OpenKODE Core extension: KD_ATX_bluetooth


NameATX_bluetooth
Name stringsKD_ATX_bluetooth
ContributorsTim Renouf
ContactsAntix Labs
StatusImplemented by Antix Labs
Version6
Number9
Dependencies Requires OpenKODE Core 1.0 and the ATX_socktype extension. This extension is written based on the wording of the OpenKODE Core 1.0 specification and version 2 of the ATX_socktype extension.

1. Overview

This OpenKODE Core extension provides a new socket type and address family for Bluetooth communications, together with functions and events to perform device and service discovery.

Only SDP (Service Discovery Protocol) and RFCOMM are supported in this extension. It would be straightforward to draft a further extension to add L2CAP.

It is possible for an implementation to conform to this extension specification without actually implementing Bluetooth communications, as long as the constants and types are present and each function returns the applicable “not implemented” error code as specified.

1.1. General issues

ISSUE: Might we want a function to get the local device's device class?

ISSUE: Do we want a function for doing service discovery over all visible devices? JSR-82 lets you do this, and I'm told Windows does for some stacks, but I don't think all stacks let you do it. The options seem to be (1) we don't support it, (2) we support it but make it optional so the function returns an error if the underlying stack doesn't support it, or (3) we support it and fake it up if the underlying stack doesn't do it. (3) seems a bit heavyweight to me. I suggest going for (1) for now.

2. Header file

When this extension is present, its facilities are accessed by including its header file:

#include <KD/ATX_bluetooth.h>

3. New socket type: 20.4. Bluetooth

This new section is added after 20.3 TCP and UDP in the Network sockets chapter as modified by the ATX_socktype extension.

An OpenKODE Core implementation may optionally support Bluetooth RFCOMM sockets.

3.1. 20.4.1. KDUuidATX

The type KDUuidATX represents an up to 128-bit universally unique identifier (UUID), as used in Bluetooth, most notably as a service ID.

typedef struct KDUuidATX {
    KDuint32 i1, i2, i3, i4;
} KDUuidATX;

The declaration is such that it can be initialized with a list of four 32-bit integers all enclosed in braces, for example:

KDUuidATX uuid = { 0, 0, 0, 0xabcd }; /* UUID of 0xabcd */

The first integer is the most significant. The correspondence between the fields here, the fields in a Windows GUID and the fields in the canonical text representation of a UUID is as follows:

KDUuidATX fieldWindows GUID fieldCanonical UUID field
KDuint32 i1Data1first_field
KDuint32 i2(Data2 << 16) | Data3(second_field << 16) | third_field
KDuint32 i3(Data4[0] << 24) | (Data4[1] << 16) | (Data4[2] << 8) | Data4[3]fourth_field >> 32
KDuint32 i4(Data4[4] << 24) | (Data4[5] << 16) | (Data4[6] << 8) | Data4[7]fourth_field & 0xffffffff

Thus, for example, a UUID of 12345678-9abc-def0-fedc-ba9876543210, which would be created in a Java UUID initializer as follows:

UUID u = new UUID(0x123456789abcdef0L, 0xfedcba9876543210L);

or in a Windows GUID initializer as follows:

GUID u = { 0x12345678, 0x9abc, 0xdef0, "\xfe\xdc\xba\x98\x76\x54\x32\x10" };

is initialized in an OpenKODE UUID as follows:

KDUuidATX u = { 0x12345678, 0x9abcdef0, 0xfedcba98, 0x76543210 };

The layout of the bytes in memory in an OpenKODE KDUuidATX depends on the endianness of the target platform, and in either case is different to the layout used by Windows.

ISSUE: Is this right? It needs checking.

ISSUE: Is this how we want to represent a UUID? We could instead use the Java way (two 64-bit ints) or the Linux libuuid way (16 8-bit ints) or the Windows way. The representation in memory does not matter that much as long as it is properly specified; I think what matters is how the programmer initializes a UUID.

3.2. 20.4.2. Bluetooth socket type and address

The socket type constants for use in kdSocketCreate are:

#define KD_SOCK_RFCOMM_ATX 169

An RFCOMM socket is connection based, reliable and stream oriented.

RFCOMM has an address family of KD_AF_BLUETOOTH_ATX:

#define KD_AF_BLUETOOTH_ATX 170

It contributes the sbtrcATX field (of type KDSockaddrAfBtrcATX) to the KDSockaddr data union:

typedef struct KDBdAddrATX {
    KDuint8 b[6];
} KDBdAddrATX;
typedef struct KDSockaddrAfBtrcATX {
    KDBdAddrATX bdaddr;
    KDuint8 channel;
} KDSockaddrAfBtrcATX;

For a KDSockaddr addr where addr.family is KD_AF_BLUETOOTH_ATX and a RFCOMM address is required, the fields are set as follows:

addr.data.sbtrcATX.bdaddr

Bluetooth device address

addr.data.sbtrcATX.channel

RFCOMM channel number

Once a Bluetooth RFCOMM socket is bound, the Bluetooth device address of the local Bluetooth device it uses can be retrieved using kdSocketGetName.

ISSUE: Recall we defined KDSockaddr to have a union instead of the POSIX-style multiple structs where the first element is always the address family. The trouble with that is that a new socket type needs to add a new struct member to the union in <KD/kd.h>, breaking the model that an extension has everything in its own header file. In this case that probably doesn't matter; I don't see how a third party can add a new socket type to an existing OpenKODE implementation.

WG note

BlueZ (the Bluetooth API on Linux) has the slightly odd feature that there are two Bluetooth socket types for RFCOMM and L2CAP, but only one address family. In IP this works, since TCP, UDP and IP all use the same address format (IP address and port), but RFCOMM and L2CAP have slightly different address formats (RFCOMM is bdaddr and channel, L2CAP is bdaddr and psm) and hence different sockaddr struct types. I have copied that here.

3.3. 20.4.3. Overview of using Bluetooth sockets

Connecting to an RFCOMM service on a remote device

The steps to setting up communication with a service on a remote device are typically as follows:

  • Use kdBtInquireDevicesATX to start an inquiry to find nearby devices. This inquiry is asynchronous; the function returns immediately and then each device found is returned in a KD_EVENT_BT_DEVICE_DISCOVERED_ATX event, which gives the Bluetooth device address (KDBdAddrATX) of the remote device, plus the device class (computer, phone, printer, etc).

    The inquiry can be cancelled using kdBtCancelInquireDevicesATX.

  • To determine the user-friendly name of a particular remote Bluetooth device for presenting to the user, use kdBtGetFriendlyName. This initiates an asynchronous query to the remote device; the function returns immediately and the result is returned in a KD_EVENT_BT_DEVICE_NAME_ATX event, which gives either a failure indication or the name.

    The query can be cancelled using kdBtCancelGetFriendlyName.

  • Use kdBtSearchServicesATX to initiate a request to a particular remote device to return information on all services it has matching any of an array of service IDs. This function is asynchronous; it returns immediately and any matching service found is returned in a KD_EVENT_BT_SERVICE_DISCOVERED_ATX event, which gives the values of all the requested attributes in a KDBtServiceRecordATX struct.

    The search can be cancelled using kdBtCancelSearchServicesATX.

  • Set up a KDSockaddr struct with the address information of the remote end in the data union’s sbtrcATX member. bdaddr is the remote Bluetooth device address, as given in the KD_EVENT_BT_DEVICE_DISCOVERED_ATX event. channel is the service’s channel number, retrieved from the KDBtServiceRecordATX * service record using kdBtServiceRecordGetRfcommChannelATX. Note that the KDBtServiceRecordATX * service record handle has the same lifetime as the event it arrived in, that is until the event callback returns or the next time the thread calls kdWaitEvent.

  • Use kdSocketCreate to create the socket with socket type KD_SOCK_RFCOMM_ATX.

  • Use kdBtSetSockOptATX to specify that the client wants authentication and/or encryption.

  • Connect to the service on the remote device using kdSocketConnect, using the KDSockaddr set up above. As with TCP, the function initiates an asynchronous connect attempt and returns immediately. The result of the connect attempt arrives in a KD_EVENT_SOCKET_CONNECT_COMPLETE event.

  • Send and receive data using the same events and functions as for a TCP socket, and close the socket in the same way.

Providing an RFCOMM service

The steps to providing a service for remote devices to connect to are typically as follows:

  • Create the socket using kdSocketCreate with a socket type of KD_SOCK_RFCOMM_ATX.

  • Use kdBtSetSockOptATX to specify that the server requires authentication, encryption and/or authorization.

  • Bind the socket to any channel on a local Bluetooth adapter using kdSocketBind, using a KDSockaddr struct typically set up with a Bluetooth address of “any” and a channel number of “any”.

  • Use kdSocketGetName to get the local Bluetooth device address and channel number of the socket that kdSocketBind set.

  • Register the service.

    • Create a KDBtServiceRecordATX for the RFCOMM service using kdBtServiceRecordCreateRfcommATX. As well as setting the service ID and the channel number, it also allows the setting of whether authentication, encryption or authorization is required.

      ISSUE: This API does not provide a way to modify the service record (adding more attributes) before registering it, or to create a new empty one. I don't believe we have a use case for doing that. Functions to do this could be added here, or in a future extension.

    • Register the service record using kdBtRegisterServiceATX.

    • Free the service record using kdBtServiceRecordFreeATX.

  • Use kdSocketListen to start listening for remote connections to this service. This can return an error if the socket was set up for authentication, encryption or authorization but the platform cannot fulfill that, either because it does not implement it, or for example a user preference has disabled it globally.

  • As usual for a listening socket, when a KD_EVENT_SOCKET_INCOMING event arrives, use kdSocketAccept to create a new socket for the connection to the remote device.

  • Send and receive data using the same events and functions as for a TCP socket, and close the socket in the same way.

4. New functions in section 20 Network sockets

4.1. kdBtInquireDevicesATX

Start an inquiry for remote Bluetooth devices.

Synopsis

typedef struct KDBtLocalDeviceATX KDBtLocalDeviceATX;
KDint kdBtInquireDevicesATX(KDBtLocalDeviceATX * localdevice,
 KDint  access,
 void * eventuserptr);

Description

This function retrieves local contactable Bluetooth devices, giving an event for each one, either by performing an inquiry, or by reading the platform’s list of cached remote devices or “pre-known” devices.

localdevice specifies the local Bluetooth device to use. KD_NULL means the default local device; this is currently the only valid setting.

access determines how the list of Bluetooth devices is determined. Currently only one value is supported:

KD_BT_GIAC_ATX
#define KD_BT_GIAC_ATX 0x9e8b33

Perform a general/unlimited inquiry for remote Bluetooth devices.

ISSUE: KD_BT_LIAC_ATX has been removed as it looks like it is not supported on Windows. Is there any call for having it as an optional feature?

The inquiry is asynchronous; the function returns immediately and, after a successful return, each device found and a terminating record (or an error indication) are notified in a KD_EVENT_BT_DEVICE_DISCOVERED_ATX event. The event user pointer in that event will be the value of this function’s eventuserptr parameter.

Once successfully initiated, the inquiry can be cancelled using kdBtCancelInquireDevicesATX.

If localdevice is not KD_NULL, undefined behavior results.

Return value

On immediate failure, the function returns -1 and stores one of the error codes below into the error indicator returned by kdGetError. In particular, if the implementation does not support Bluetooth at all, the function fails with error KD_ENOSYS. Otherwise, the function returns 0 to indicate that it has successfully initiated the inquiry.

Error codes

KD_EBUSY

The inquiry cannot be started due to other Bluetooth operations being performed.

KD_EINVAL

access has an unrecognized value

KD_EIO

General I/O error.

KD_ENOMEM

Not enough space.

KD_ENOSYS

Bluetooth not supported at all.

Rationale

The KD_BT_GIAC_ATX value is set by the Bluetooth standard. The Bluetooth standard also has KD_BT_LIAC_ATX, which is not included here as it is not universally supported by Bluetooth stacks. Other values in the range 0x9e8b00 to 0x9e8b3f may be allocated to access codes in future Bluetooth standards.

ISSUE: I was considering adding the functionality of JSR-82's retrieveDevices into this function by defining two extra values access to get the locally cached devices and to get the pre-known devices. However, I am told that the Broadcom Bluetooth stack on Windows cannot do either of these.

ISSUE: It has been suggested that we allow DIAC. I'm not yet quite sure what that does.

4.2. kdBtCancelInquireDevicesATX

Selectively cancel ongoing kdBtInquireDevicesATX operations.

Synopsis

void kdBtCancelInquireDevicesATX(void * eventuserptr);

Description

This function cancels any outstanding device inquiry operations initiated by calls in this same thread to kdBtInquireDevicesATX whose eventuserptr values match the eventuserptr supplied to this function. If this function’s eventuserptr is KD_NULL, then all outstanding device inquiry operations initiated by calls in this same thread are cancelled. Cancelling a kdBtInquireDevicesATX includes removing any pending events it generated.

The function does nothing and succeeds if eventuserptr does not match any outstanding lookup operation.

4.3. kdBtGetFriendlyNameATX

Get the user-friendly name of a Bluetooth device.

Synopsis

KDint kdBtGetFriendlyNameATX(KDBtLocalDeviceATX * localdevice,
 const KDBdAddrATX * bdaddr,
 void * eventuserptr);

Description

This function gets the user-friendly name of a Bluetooth device, either a local one or a remote one.

localdevice specifies the local Bluetooth device to use. KD_NULL means the default local device; this is currently the only valid setting.

To get the name of the local Bluetooth device specified by localdevice, set bdaddr to KD_NULL. To get the name of a remote Bluetooth device, set bdaddr to point to a KDBdAddrATX struct giving its Bluetooth device address, as given in a KD_EVENT_BT_DEVICE_DISCOVERED_ATX event.

The query is asynchronous, even for a local Bluetooth device; the function returns immediately and, after a successful return, the name is returned in a KD_EVENT_BT_NAME_ATX event. The event user pointer in that event will be the value of this function’s eventuserptr parameter.

Once successfully initiated, the operation can be cancelled using kdBtCancelGetFriendlyNameATX.

If localdevice is not KD_NULL, or bdaddr is not KD_NULL and does not point to a readable KDBdAddrATX struct, then undefined behavior results.

Return value

On immediate failure, the function returns -1 and stores one of the error codes below into the error indicator returned by kdGetError. In particular, if the implementation does not support Bluetooth at all, the function fails with error KD_ENOSYS. Otherwise, the function returns 0 to indicate that it has successfully initiated the query.

Error codes

KD_EBUSY

The query cannot be started due to other Bluetooth operations being performed. This error never occurs when bdaddr is KD_NULL (for a local name query).

KD_EIO

General I/O error.

KD_ENOMEM

Not enough space.

KD_ENOSYS

Bluetooth not supported at all.

4.4. kdBtCancelGetFriendlyNameATX

Selectively cancel ongoing kdBtGetFriendlyNameATX operations.

Synopsis

void kdBtCancelGetFriendlyNameATX(void * eventuserptr);

Description

This function cancels any outstanding friendly name retrieving operations initiated by calls in this same thread to kdBtGetFriendlyNameATX whose eventuserptr values match the eventuserptr supplied to this function. If this function’s eventuserptr is KD_NULL, then all outstanding friendly name retrieving operations initiated by calls in this same thread are cancelled. Cancelling a kdBtGetFriendlyNameATX includes removing any pending events it generated.

The function does nothing and succeeds if eventuserptr does not match any outstanding friendly name retrieving operation.

4.5. kdBtSearchServicesATX

Search services on a remote Bluetooth device.

Synopsis

KDint kdBtSearchServicesATX(KDBtLocalDeviceATX * localdevice,
 const KDBdAddrATX * bdaddr,
 const KDint32 * attrset,
 const KDUuidATX * uuidset,
 void * eventuserptr);

Description

This function searches for services matching any of a set of service UUIDs on a particular remote Bluetooth device.

localdevice specifies the local Bluetooth device to use. KD_NULL means the default local device; this is currently the only valid setting.

bdaddr points to a KDBdAddrATX struct giving the Bluetooth device address of the remote device to search, as given in a KD_EVENT_BT_DEVICE_DISCOVERED_ATX event.

attrset is a placeholder for a possible future extension to allow the caller to specify the set of attributes to return with each found service. Currently, attrset must be KD_NULL.

uuidset points to an array of UUIDs (each of type KDUuidATX), terminated by zero, giving the list of service IDs to search for.

The search is asynchronous; the function returns immediately and, after a successful return, each service found and a terminating record (or an error indication) are notified in a KD_EVENT_BT_SERVICE_DISCOVERED_ATX event. The event user pointer in that event will be the value of this function’s eventuserptr parameter.

Once successfully initiated, the inquiry can be cancelled using kdBtCancelSearchServicesATX.

If localdevice is not KD_NULL, or bdaddr does not point to a readable KDBdAddrATX struct, or attrset is not KD_NULL, or uuidset does not point to a readable array of type KDUuidATX terminated by zero, then undefined behavior results.

Return value

On immediate failure, the function returns -1 and stores one of the error codes below into the error indicator returned by kdGetError. In particular, if the implementation does not support Bluetooth at all, the function fails with error KD_ENOSYS. Otherwise, the function returns 0 to indicate that it has successfully initiated the query.

Error codes

KD_EBUSY

The query cannot be started due to other Bluetooth operations being performed.

KD_EIO

General I/O error.

KD_ENOMEM

Not enough space.

KD_ENOSYS

Bluetooth not supported at all.

4.6. kdBtCancelSearchServicesATX

Cancel an outstanding Bluetooth service search.

Synopsis

void kdBtCancelSearchServicesATX(void * eventuserptr);

Description

This function cancels any outstanding service search operations initiated by calls in this same thread to kdBtSearchServicesATX whose eventuserptr values match the eventuserptr supplied to this function. If this function’s eventuserptr is KD_NULL, then all outstanding service search operations initiated by calls in this same thread are cancelled. Cancelling a kdBtSearchServicesATX includes removing any pending events it generated.

The function does nothing and succeeds if eventuserptr does not match any outstanding search operation.

4.7. kdBtServiceRecordGetRfcommChannelATX

Get the RFCOMM channel from a Bluetooth service record.

Synopsis

typedef struct KDBtServiceRecordATX KDBtServiceRecordATX;
KDint kdBtServiceRecordGetRfcommChannelATX(KDBtServiceRecordATX * servicerecord);

Description

Given a KDBtServiceRecordATX * service record handle (created with a service record creation function or obtained from a KD_EVENT_BT_SERVICE_DISCOVERED_ATX event), this function retrieves the RFCOMM channel number if any.

If servicerecord is not a valid KDBtServiceRecordATX * service record handle, then undefined behavior results.

Return value

On success, the function returns the RFCOMM channel number, an integer in the range 0..31. On failure it returns -1 and stores one of the error codes below into the error indicator returned by kdGetError.

Error codes

KD_ENOENT

The service record is for a service that is not exposed over RFCOMM.

Rationale

ISSUE: This extension provides only this function, and no general way of retrieving attributes from the service record. Is that required?

4.8. kdBtServiceRecordFreeATX

Free a Bluetooth service record.

Synopsis

void kdBtServiceRecordFreeATX(KDBtServiceRecordATX * servicerecord);

Description

This function frees the KDBtServiceRecordATX * Bluetooth service record handle servicerecord that was created by a service record creation function. servicerecord ceases to be a valid service record handle.

If servicerecord is not a valid service record handle created by a service record creation function, then undefined behavior results.

4.9. kdBtServiceRecordCreateRfcommATX

Create a Bluetooth service record for an RFCOMM service.

Synopsis

KDBtServiceRecordATX *kdBtServiceRecordCreateRfcommATX(const KDUuidATX * uuid,
 KDint  channel);

Description

This function creates and returns a KDBtServiceRecordATX * service record handle representing an RFCOMM service whose ID is the UUID pointed to by uuid and whose channel number is channel.

If uuid does not point to a readable KDUuidATX location, then undefined behavior results.

Return value

On success, the function returns the created KDBtServiceRecordATX * service record handle. On failure, it returns KD_NULL and stores one of the error codes below into the error indicator returned by kdGetError. In particular, if the implementation does not support Bluetooth at all, the function fails with error KD_ENOSYS.

Error codes

KD_EINVAL

The channel number is not valid.

KD_ENOMEM

Not enough space.

KD_ENOSYS

Bluetooth not supported at all.

4.10. kdBtRegisterServiceATX

Register a Bluetooth service.

Synopsis

KDint kdBtRegisterServiceATX(KDBtLocalDeviceATX * localdevice,
 KDBtServiceRecordATX * servicerecord);

Description

This function registers the service described by servicerecord.

localdevice specifies the local Bluetooth device to use. KD_NULL means the default local device; this is currently the only valid setting.

If localdevice is not KD_NULL, or servicerecord is not a valid KDBtServiceRecordATX * service record handle, then undefined behavior results.

Return value

On success, the function returns 0. On failure, it returns -1 and stores one of the error codes below into the error indicator returned by kdGetError.

Error codes

KD_ENOMEM

Not enough space.

4.11. kdBtSocketSetFlagsATX

Set Bluetooth socket flags for authentication, encryption and/or authorization.

Synopsis

KDint kdBtSocketSetFlagsATX(KDSocket * socket,
 KDuint  flags);

Description

This function sets the value of the flags word for a Bluetooth socket. The flag bits indicate whether the caller requires authentication, encryption and/or authorization on the connection.

flags is 0 or more of the following values bitwise ORed together.

#define KD_BTFLAG_AUTHENTICATE 1
#define KD_BTFLAG_ENCRYPT 2
#define KD_BTFLAG_AUTHORIZE 4
  • KD_BTFLAG_AUTHENTICATE: the remote device will be authenticated. Setting this bit to 0 does not necessarily force authentication to be disabled; it may be enabled anyway because one of the two bits below is set, or because some other application has a connection to the same remote device and has demanded authentication.

  • KD_BTFLAG_ENCRYPT: the connection will be encrypted (which forces authentication, even if disabled in this bitmap). Setting this bit to 0 does not necessarily force encryption to be disabled; it may be enabled anyway because some other application has a connection to the same remote device and has demanded encryption.

  • KD_BTFLAG_AUTHORIZE: the connection requires authorization (which forces authentication, even if disabled in this bitmap). This flag is used only in a server socket; it is ignored in a client socket.

If any other bit in flags is set, then it is undefined whether the function succeeds or fails or appears to succeed in a way that further operations on the socket do not work as expected. If socket is not a valid Bluetooth socket handle, then undefined behavior results.

Return value

On success, the function returns 0. On failure, it returns -1 and stores one of the error codes below into the error indicator returned by kdGetError.

Error codes

KD_EIO

General I/O error.

KD_ENOMEM

Not enough space.

Rationale

ISSUE: I decided not to introduce a general kdSetSockOptATX, since we don't have any use cases outside these Bluetooth flags.

ISSUE: There is no flag to force switch to master mode. Do we need it?

4.12. kdBtSetDiscoverableATX

Set the discoverable mode of the device.

Synopsis

KDint kdBtSetDiscoverableATX(KDBtLocalDeviceATX * localdevice,
 KDuint  mode);

Description

This function sets the discoverable mode of the local Bluetooth device localdevice. Setting localdevice to KD_NULL means the default local device; this is currently the only valid setting.

mode is the discovery mode to set the local device to, one of:

KD_BT_GIAC_ATX

General discoverable mode.

KD_BT_NOT_DISCOVERABLE_ATX
#define KD_BT_NOT_DISCOVERABLE_ATX 0
            

Non-discoverable mode.

If localdevice is not KD_NULL, then undefined behavior results.

Return value

On success, the function returns 0. On failure, it returns -1 and stores one of the error codes below into the error indicator returned by kdGetError.

Error codes

KD_EINVAL

mode has an unrecognized value.

KD_EIO

General I/O error.

KD_ENOMEM

Not enough space.

KD_ENOSYS

Bluetooth not supported at all.

Rationale

The Bluetooth standard also has KD_BT_LIAC_ATX for "limited discoverable mode". It is not included in this OpenKODE extension as it is not universally supported.

ISSUE: Should we have it as an optional feature?

5. New events

5.1. KD_EVENT_BT_DEVICE_DISCOVERED_ATX

kdBtInquireDevicesATX has found a device or has completed event.

Synopsis

#define KD_EVENT_BT_DEVICE_DISCOVERED_ATX 171

Description

This event is generated when an inquiry initiated by a call to kdBtInquireDevicesATX is complete, either successfully or with an error, or has found a device. An inquiry generates zero or more events each with a single remote device, then a final event indicating that the inquiry has completed or that an error occurred.

The event’s userptr field is set to the value supplied in the eventuserptr parameter to kdBtInquireDevicesATX. The event is sent to the queue for the thread that initiated the inquiry by calling that function.

The event data (below) has a result field that points to a KDBtRemoteDeviceInfoATX struct, defined as follows:

typedef struct KDBtRemoteDeviceInfoATX {
    KDBdAddrATX bdaddr;
    KDuint8 deviceclass[3];
} KDBtRemoteDeviceInfoATX;

In this struct, bdaddr is the Bluetooth device address of the remote device, and deviceclass gives the device class.

ISSUE: deviceclass is supposed to be the same as the analogous field in BlueZ, but I haven't worked out what its definition is yet.

The event data is in the event->data.btdeviceATX element of the event’s data union, which has the following type:

typedef struct KDEventBtDeviceATX {
    KDint32 error;
    const struct KDBtRemoteDeviceInfoATX *result;
} KDEventBtDeviceATX;

For an event containing a discovered device, error is 0 and result points to a KDBtRemoteDeviceInfoATX struct as defined above. The lifetime of the struct is the same as the lifetime of the event struct, that is until the event callback returns or the thread next calls kdWaitEvent.

A final event with error 0 and result KD_NULL indicates that the inquiry has completed.

If an error occurs, the final event has result KD_NULL and error set to one of the error codes listed in kdBtInquireDevicesATX.

Rationale

kdNameLookup delivering possibly multiple KD_EVENT_NAME_LOOKUP_COMPLETE events and kdBtInquireDevicesATX delivering possibly multiple KD_EVENT_BT_DEVICE_DISCOVERED_ATX events have slightly different semantics in the way the events are delivered. For KD_EVENT_NAME_LOOKUP_COMPLETE, each address found for the name is delivered in an event, and the final one is specially marked. In contract, for KD_EVENT_BT_DEVICE_DISCOVERED_ATX, each device discovered is delivered in an event, and then there is a final terminating event with no device. This difference is needed because a Bluetooth device inquiry can find no devices without there being an error.

Issues

ISSUE: Like KDSockaddr, the event struct has the problem that adding a new event data struct in an extension requires a change to KD/kd.h. Thus a third party extension (which only has control over its own extension header file) cannot add a new event data struct. That is not an issue for this Bluetooth extension, as a third party extension cannot add a new socket type anyway.

5.2. KD_EVENT_BT_NAME_ATX

kdBtGetFriendlyNameATX complete event.

Synopsis

#define KD_EVENT_BT_NAME_ATX 172

Description

This event is generated when a name query initiated by a successful call to kdBtGetFriendlyNameATX completes, either successfully or with an error.

The event’s userptr field is set to the value supplied in the eventuserptr parameter to kdBtGetFriendlyNameATX.

The event data is in the event->data.btnameATX element of the event’s data union, which has the following type:

typedef struct KDEventBtNameATX {
    KDint32 error;
    const KDchar *result;
} KDEventBtNameATX;

For an event indicating successful completion, error is 0 and result points to a null-terminated string giving the requested friendly name. The lifetime of the string is the same as the lifetime of the event, that is until the event callback returns or the thread next calls kdWaitEvent.

If an error occurs, the final event has result KD_NULL and error set to one of the error codes listed in kdBtGetFriendlyNameATX.

5.3. KD_EVENT_BT_SERVICE_DISCOVERED_ATX

kdBtSearchServicesATX has found a service or has completed event.

Synopsis

#define KD_EVENT_BT_SERVICE_DISCOVERED_ATX 173

Description

This event is generated when a service search initiated by a call to kdBtSearchServicesATX is complete, either successfully or with an error, or has found a service. A search generates zero or more events each with a single service record, then a final event indicating that the search has completed or that an error occurred.

The event’s userptr field is set to the value supplied in the eventuserptr parameter to kdBtSearchServicesATX. The event is sent to the queue for the thread that initiated the search by calling that function.

The event data is in the event->data.btserviceATX element of the event’s data union, which has the following type:

typedef struct KDEventBtServiceATX {
    KDint32 error;
    struct KDBtServiceRecordATX *result;
} KDEventBtServiceATX;

For an event containing a discovered service, error is 0 and result is a KDBtServiceRecordATX * handle. The lifetime of the handle is the same as the lifetime of the event struct, that is until the event callback returns or the thread next calls kdWaitEvent.

A final event with error 0 and result KD_NULL indicates that the search has completed.

If an error occurs, the final event has result KD_NULL and error set to one of the error codes listed in kdBtSearchServicesATX.

6. Revision history

6.1. Version 6, 2009-02-04

  • Added kdBtCancelGetFriendlyNameATX. Added missing 'L' on constant in example of Java UUID initialization.

6.2. Version 5, 2009-01-22

  • Made kdBtInquireDevicesATX consistently plural.

  • Fixed a couple of typos in type/constant names.

6.3. Version 4, 2008-11-17

  • Various fixes to sample header file: Added missing KDBdAddrATX declaration. Moved KDBtServiceRecordATX declaration before its first use.

6.4. Version 3, 2008-11-12

  • Removed KD_BT_LIAC_ATX, and added issues on whether we want to support it as an optional feature.

  • Added Java UUID example.

  • Removed flags parameter from kdBtServiceRecordCreateRfcommATX.

6.5. Version 2, 2008-10-27

  • Explained how a UUID is represented. Added an issue on whether we want to do it like that, and an issue that the explanation needs checking.

  • Changed class field of KDBtRemoteDeviceInfoATX to deviceclass. Noted that it is meant to be the same as the analogous field in BlueZ, but I haven't worked out what that is yet.

6.6. Version 1, 2008-10-16

  • First draft.