Bluetooth and WSALookupServiceBegin for Service Discovery
To discover the existence of a particular service on a Bluetooth server, clients use the WSALookupServiceBegin, WSALookupServiceNext, and WSALookupServiceEnd functions. Queries can be performed for local and remote addresses, but connections can only be established with remote addresses. Service handles discovered during this operation cannot be used to delete the service via WSASetService. Loopback is not supported by RFCOMM.
Two basic types of service discovery queries can be performed:
- Queries for one or more services on the local device
- Queries for one or more services on a specified peer device
The WSALookupServiceBegin function receives a WSAQUERYSET structure in its lpqsRestrictions parameter. WSALookupServiceBegin performs a client query based on the set of search restrictions that the WSAQUERYSET contains. Bluetooth clients must specify the restrictions, listed in the following table, in the WSAQUERYSET structure when using the WSALookupServiceBegin function to query for services.
WSAQUERYSET member | Restriction |
---|---|
dwSize | Set to sizeof(WSAQUERYSET). |
lpServiceClassId | Set to the most specific Bluetooth UUID that can be used to determine the scope of the query. For example, setting lpServiceClassId to the UUID of the L2CAP protocol results in all L2CAP services returned, essentially enumerating all SD records on the target. Setting the UUID to a specific service, however, returns only the instances of that service. |
dwNameSpace | Set to NS_BTH. |
dwNumberOfCsAddrs | Set to 0. |
lpszContext | Set to the Bluetooth Device Address with which to establish an SDP connection to perform the query of services. This member must be a string that is converted by using the WSAAddressToString function. If the local radio address is supplied, the local SDP records are searched. |
Other members | All other members of the WSAQUERYSET structure are ignored. |
The SDP connection to the remote device does not remain active after the WSALookupServiceBegin function completes a service query; the connection is terminated before WSALookupServiceBegin returns. Applications that require the SDP connection to remain active after a service query completes should specify the service class UUID to which to connect by using the serviceClassId member of the SOCKADDR_BTH structure when issuing the Windows Sockets connect function call.
The flags, listed in the following table, are used in the dwControlFlags parameter of the WSALookupServiceBegin and WSALookupServiceNext functions to control the query results. The LUP_CONTAINERS and LUP_FLUSHCACHE flags are used by the WSALookupServiceBegin function; the rest of the flags are used in calls to the WSALookupServiceNext function.
Flag | Result |
---|---|
LUP_CONTAINERS | Must not be set. |
LUP_FLUSHCACHE | Applications should generally specify LUP_FLUSHCACHE. This flag instructs the system to ignore any cached information and establish an over-the-air SDP connection to the specified device to perform the SDP search. This non-cached operation may take several seconds (whereas a cached search returns quickly). Bluetooth currently does not proactively cache SDP records from nearby devices, nor does it currently aggressively cache previous queries. Therefore, applications should anticipate that queries may return no results (with an error code of WSASERVICE_NOT_FOUND) if LUP_FLUSHCACHE is not specified. The cached data that is available by using the Windows Sockets interface may be enhanced in the future. |
LUP_RES_SERVICE | Return information about the local Bluetooth address. This flag has an effect only if LUP_RETURN_ADDR is also specified. |
LUP_RETURN_NAME | Return the display name of the service in the lpszServiceInstanceName member of the WSAQUERYSET structure for each call to the WSALookupServiceNext function. |
LUP_RETURN_TYPE | Return the service class ID in the lpServiceClassId member of the WSAQUERYSET structure. Note: Use of this flag is only applicable to the WSALookupServiceBegin function. This value is always zero for WSALookupServiceNext. |
LUP_RETURN_ADDR | Return an address in the lpcsaBuffer member to be used with connect function calls. The returned address contains the port number. |
LUP_RETURN_BLOB | Return the matching SD records in the lpBlob member, formatted according to the Bluetooth SDP record specification. |
LUP_RETURN_ALL | Return all of the above flags' information. |
LUP_RETURN_COMMENT | Return the service description in the lpszComment member of the WSAQUERYSET structure for each call to the WSALookupServiceNext function. |
LUP_FLUSHPREVIOUS | Skip the next available record, and return the record that follows it. |
Advanced Service Queries
The query operations that are described in the previous section can be used to return all results from a single GUID, which should be sufficient for most applications. An advanced query enables an application to create a more specific query; it provides the capability to match UUIDs and attributes in returned information.
To perform an advanced query for services, Bluetooth clients must specify the following restrictions in the WSAQUERYSET structure that is passed into the lpqsRestrictions parameter.
WSAQUERYSET member | Restriction |
---|---|
dwSize | Set to sizeof(WSAQUERYSET). |
lpszContext | Set to the Bluetooth Device Address with which to establish an SDP connection to perform the query of services. This member must be a string that is converted by using the WSAAddressToString function. If the local radio address is supplied, the local SDP records are searched. |
lpBlob.pBlobData | Pointer to a BTH_QUERY_SERVICE structure that contains all parameters that limit the results of the query. |
dwNameSpace | Set to NS_BTH. |
Other members | All other members of the WSAQUERYSET structure are ignored. |
The following flags are passed in the dwControlFlags parameter of WSALookupServiceBegin to control the results of an advanced query.
Flag | Result |
---|---|
LUP_CONTAINERS | Must not be set. |
LUP_FLUSHCACHE | Applications should generally specify LUP_FLUSHCACHE. This flag instructs the system to ignore any cached information and establish an over-the-air SDP connection to the specified device to perform the SDP search. This non-cached operation may take several seconds (whereas a cached search returns quickly). Bluetooth does not proactively cache SDP records from nearby devices, nor does it aggressively cache previous queries. Therefore applications should expect that queries may frequently return no results (WSASERVICE_NOT_FOUND) if LUP_FLUSHCACHE is not specified. The cached data that is available by using the Windows Sockets interface may be enhanced in the future. |
LUP_RES_SERVICE | Return information for the local Bluetooth Address. Setting this flag has an effect only if LUP_RETURN_ADDRR is also specified. |
LUP_RETURN_NAME | Return the display name of the service. This flag is ignored for SDP_SERVICE_SEARCH_REQUEST. |
LUP_RETURN_TYPE | Return the service class ID. This flag is ignored for SDP_SERVICE_SEARCH_REQUEST. |
LUP_RETURN_ADDR | Return an address in the lpcsaBuffer member to be used with connect function calls. The returned address contains the port number. This flag is ignored for SDP_SERVICE_SEARCH_REQUEST. |
LUP_RETURN_BLOB | Return the matching SD records in a format that conforms to the Bluetooth SDP record specification. For SDP_SERVICE_SEARCH_REQUEST, the result in lpBlob for the subsequent call to WSALookupServiceNext is an array of Bluetooth SDP handles. For SDP_SERVICE_ATTRIBUTE_REQUEST and SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST, the result for each subsequent call to WSALookupServiceNext is a binary Bluetooth SDP record whose attributes are restricted to those specified by the pRange member of the query. This flag is required for SDP_SERVICE_SEARCH_REQUEST. |
LUP_RETURN_COMMENT | Return the service description in the lpszComment member of the WSAQUERYSET structure for each call to the WSALookupServiceNext function. |
LUP_FLUSHPREVIOUS | Skip the next available record, and return the record that follows it. |
On input, lpBlob->pBlobData points to a BTH_QUERY_SERVICE structure that contains the values listed in the following table.
Note
The initial search request must be able to fit into one L2CAP packet. The response, however, may be broken into many L2CAP packets.
Member | Value |
---|---|
type | Type of search to perform. This value can be one of SDP_SERVICE_SEARCH_REQUEST, SDP_SERVICE_ATTRIBUTE_REQUEST, or SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST. Each search type is associated with an underlying search mechanism that is defined by the Bluetooth SDP specification. Each return results in the form described by the WSAQUERYSET structure that is defined earlier in this (Advanced Service Queries) section. |
serviceHandle | Used for attribute searches. This value specifies the service handle with which to query the attributes in the pRange member. |
uuids | Used for service and serviceAttribute searches. This value specifies the UUIDs that a record must contain to match the search. If less than MAX_UUIDS_IN_QUERY UUIDs are to be queried, this value sets the SdpQueryUuid element that immediately follows the last valid UUID to all zeros. |
numRange | Used for attribute and serviceAttribute searches. This value specifies the number of elements in pRange. |
pRange | Used for attribute and serviceAttribute searches. This value specifies the attribute values to retrieve for any matching records. |
After each successful call to the WSALookupServiceNext function, lpBlob->pBlobData points to a block of data that contains the values listed in the following table.
Value | Description |
---|---|
SDP_SERVICE_SEARCH_REQUEST | An array of SDP record handles that is identical to the ServiceRecordHandleList defined by Bluetooth 1.1 SDP 4.5.2. The number of SDP handles that is returned is calculated by (lpBlob->cbSize)/sizeof(ULONG). All results are returned in a single call to the WSALookupServiceNext function. |
SDP_SERVICE_ATTRIBUTE_REQUEST or SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST | A binary Bluetooth SDP record. For SDP_SERVICE_ATTRIBUTE_REQUEST, all results are returned in a single call to the WSALookupServiceNext function. |
Note
If the lpBlob member is not specified during input for a service query, a service and attribute search is performed for the service specified in the lpServiceClassId member on attributes from 0 through 0xFFFF.