< Bluetooth Device Query Example | Winsock2 Supported Protocols Main | Querying Bluetooth Device Example >
What do we have in this chapter 4 part 13?
|
Querying Service Capability on Remote Bluetooth Devices
An application can query for services on a remote Bluetooth device by using the following standard Winsock programming elements:
1. WSAQUERYSET structure. 2. WSALookupServiceBegin() function. 3. WSALookupServiceNext() function. 4. WSALookupServiceEnd() function.
Before you query service capability on remote Bluetooth devices, you must have the address of the remote Bluetooth device information to query, as a BT_ADDR type, which is defined in Ws2bth.h as:
typedef ULONGLONG bt_addr, *pbt_addr, BT_ADDR, *PBT_ADDR;
To perform a service query on a remote Bluetooth device:
1. To prepare the caller application by providing Winsock-related data such as version and implementation details. This data can be retrieved by calling the WSAStartup function as the following example shows.
WSADATA wsd; WSAStartup (MAKEWORD(2,2), &wsd);
2. Specify the search parameters by configuring the WSAQUERYSET structure. The following code example shows the values in this structure.
WSAQUERYSET wsaq; memset (&wsaq, 0, sizeof(wsaq)); wsaq.dwSize = sizeof(wsaq); wsaq.dwNameSpace = NS_BTH; wsaq.lpBlob = &blob; wsaq.lpcsaBuffer = &csai;
Restrict the search to Bluetooth queries by setting the dwNameSpace member to NS_BTH. |
3. To initiate the search process, call the WSALookupServiceBegin() function. Specify the search criteria by passing the WSAQUERYSET variable, created in step 1, in the pQuerySet parameter. The following code example show how to call WSALookupServiceBegin().
int iRet = WSALookupServiceBegin (&wsaq, 0, &hLookup);
Pass zero (0) in the dwFlags parameter to perform a service query on the remote device. WSALookupServiceBegin() returns a handle in the hLookup parameter. Passing LUP_CONTAINERS in the dwFlags parameter, sets up WSALookupServiceBegin() to perform a device inquiry.
4. To retrieve data about the services found on the remote device, call the WSALookupServiceNext() function by using the handle returned by WSALookupServiceBegin() as shown in the following code example.
CHAR buf[5000];
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
DWORD dwSize = sizeof(buf);
memset(pwsaResults,0,sizeof(WSAQUERYSET));
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->lpBlob = NULL;
iRet = WSALookupServiceNext (hLookup, 0, &dwSize, pwsaResults);
WSALookupServiceNext() returns a pointer to WSAQUERYSET that references the service data in the lpBlob member. This member points to a BLOB (Windows Sockets) structure, which contains the binary data that is returned by WSALookupServiceNext() all at once. Windows Embedded CE provides COM interfaces that you can use to parse service data.
5. To terminate the service discovery process, call the WSALookupServiceEnd() function. This function releases the lookup handle created by WSALookupServiceBegin(). The following code example shows how to call WSALookupServiceEnd().
WSALookupServiceEnd(hLookup);
6. To terminate the use of Winsock services, call the WSACleanup() function. There must be a call to WSACleanup() for every successful call to WSAStartup() made by an application.
The following code example shows queries a remote Bluetooth device for the supported services. The remote device is specified by passing a pointer to the address of the device stored in the in a BT_ADDR type, as defined in Ws2bth.h:
Add the following source code.
// Link to ws2_32.lib
#include <winsock2.h>
#include <Ws2bth.h>
// Link to Bthprops.lib
#include <BluetoothAPIs.h>
#include <stdio.h>
// callback for BluetoothSdpEnumAttributes()
BOOL __stdcall callback(ULONG uAttribId, LPBYTE pValueStream, ULONG cbStreamSize, LPVOID pvParam)
{
SDP_ELEMENT_DATA element;
// Just a verification, uncomment to see the output!!!
//printf("Callback() uAttribId: %ul\n", uAttribId);
//printf("Callback() pValueStream: %d\n ", pValueStream);
//printf("Callback() cbStreamSize: %ul\n ", cbStreamSize);
if (BluetoothSdpGetElementData(pValueStream, cbStreamSize, &element) != ERROR_SUCCESS)
{
// Just a verification
// printf("BluetoothSdpGetElementData() failed with error code %ld\n", WSAGetLastError());
return FALSE;
}
else
{
// Just a verification
// printf("BluetoothSdpGetElementData() is OK!\n");
return TRUE;
}
}
int main(int argc, char** argv)
{
WSADATA m_data;
SOCKET s;
WSAPROTOCOL_INFO protocolInfo;
int protocolInfoSize;
WSAQUERYSET querySet, *pResults, querySet2;
HANDLE hLookup, hLookup2;
int result;
static int i;
BYTE buffer[1000];
BYTE buffer1[2000];
DWORD bufferLength, flags, addressSize, bufferLength1;
CSADDR_INFO *pCSAddr;
BTH_DEVICE_INFO *pDeviceInfo;
char addressAsString[2000];
BLOB *pBlob;
GUID protocol;
// Load the winsock2 library
if (WSAStartup(MAKEWORD(2,2), &m_data) == 0)
{
printf("WSAStartup() should be fine!\n");
// Create a blutooth socket
s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (s == INVALID_SOCKET)
{
printf("Failed to get bluetooth socket with error code %ld\n", WSAGetLastError());
return 1;
}
else
printf("socket() is OK!\n");
protocolInfoSize = sizeof(protocolInfo);
// Get the bluetooth device info using getsockopt()
if (getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, (char*)&protocolInfo, &protocolInfoSize) != 0)
{
printf("getsockopt(SO_PROTOCOL_INFO) failed with error code %ld\n", WSAGetLastError());
return 1;
}
else
printf("getsockopt(SO_PROTOCOL_INFO) is OK!\n");
// Query set criteria
memset(&querySet, 0, sizeof(querySet));
querySet.dwSize = sizeof(querySet);
querySet.dwNameSpace = NS_BTH;
// Set the flags for query
flags = LUP_RETURN_NAME | LUP_CONTAINERS | LUP_RETURN_ADDR | LUP_FLUSHCACHE |
LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE;
// Start a device in range query...
result = WSALookupServiceBegin(&querySet, flags, &hLookup);
// If OK
if (result == 0)
{
printf(" WSALookupServiceBegin() is OK!\n");
i = 0;
while (result == 0)
{
bufferLength = sizeof(buffer);
pResults = (WSAQUERYSET *)&buffer;
// Next query...
result = WSALookupServiceNext(hLookup, flags, &bufferLength, pResults);
if (result != 0)
{
printf(" WSALookupServiceNext() failed with error code %ld\n", WSAGetLastError());
}
else
{
// Get the device info, name, address etc
printf(" WSALookupServiceNext() is OK!\n");
printf(" The service instance name is %S\n", pResults->lpszServiceInstanceName);
pCSAddr = (CSADDR_INFO *)pResults->lpcsaBuffer;
pDeviceInfo = (BTH_DEVICE_INFO *)pResults->lpBlob;
memset(&querySet2, 0, sizeof(querySet2));
querySet2.dwSize = sizeof(querySet2);
protocol = L2CAP_PROTOCOL_UUID;
querySet2.lpServiceClassId = &protocol;
querySet2.dwNameSpace = NS_BTH;
addressSize = sizeof(addressAsString);
// Print the local bluetooth device address...
if (WSAAddressToString(pCSAddr->LocalAddr.lpSockaddr, pCSAddr->LocalAddr.iSockaddrLength,
&protocolInfo, (LPWSTR)addressAsString, &addressSize) == 0)
{
printf(" WSAAddressToString() for local address is fine!\n");
printf(" The local address: %S\n", addressAsString);
}
else
printf(" WSAAddressToString() for local address failed with error code %ld\n", WSAGetLastError());
addressSize = sizeof(addressAsString);
// Print the remote bluetooth device address...
if (WSAAddressToString(pCSAddr->RemoteAddr.lpSockaddr, pCSAddr->RemoteAddr.iSockaddrLength,
&protocolInfo, (LPWSTR)addressAsString, &addressSize) == 0)
{
printf(" WSAAddressToString() for remote address is fine!\n");
printf(" The remote device address: %S\n", addressAsString);
}
else
printf(" WSAAddressToString() for remote address failed with error code %ld\n", WSAGetLastError());
// Prepare for service query set
querySet2.lpszContext = (LPWSTR)addressAsString;
flags = LUP_FLUSHCACHE |LUP_RETURN_NAME | LUP_RETURN_TYPE |
LUP_RETURN_ADDR | LUP_RETURN_BLOB | LUP_RETURN_COMMENT;
// Start service query
result = WSALookupServiceBegin(&querySet2, flags, &hLookup2);
if (result == 0)
{
printf(" WSALookupServiceBegin() is OK!\n");
while (result == 0)
{
bufferLength1 = sizeof(buffer1);
pResults = (WSAQUERYSET *)&buffer1;
// Next service query
result = WSALookupServiceNext(hLookup2, flags, &bufferLength1, pResults);
if(result == 0)
{
// Populate the service info
printf(" WSALookupServiceNext() is OK!\n");
printf(" WSALookupServiceNext() - service instance name: %S\n",
pResults->lpszServiceInstanceName);
printf(" WSALookupServiceNext() - comment (if any): %s\n", pResults->lpszComment);
pCSAddr = (CSADDR_INFO *)pResults->lpcsaBuffer;
// Extract the sdp info
if (pResults->lpBlob)
{
pBlob = (BLOB*)pResults->lpBlob;
if (!BluetoothSdpEnumAttributes(pBlob->pBlobData, pBlob->cbSize, callback, 0))
{
printf("BluetoothSdpEnumAttributes() failed with error code %ld\n", WSAGetLastError());
}
else
{
printf("BluetoothSdpEnumAttributes() #%d is OK!\n", i++);
}
}
}
else
{
printf(" WSALookupServiceNext() failed with error code %ld\n", WSAGetLastError());
printf(" Error code = 11011 ~ WSA_E_NO_MORE ~ No more device!\n");
}
}
// Close the handle to service query
if(WSALookupServiceEnd(hLookup2) == 0)
printf("WSALookupServiceEnd(hLookup2) is fine!\n", WSAGetLastError());
else
printf("WSALookupServiceEnd(hLookup2) failed with error code %ld\n");
}
else
printf("WSALookupServiceBegin() failed with error code %ld\n", WSAGetLastError());
}
}
// Close handle to the device query
if(WSALookupServiceEnd(hLookup) == 0)
printf("WSALookupServiceEnd(hLookup) is fine!\n", WSAGetLastError());
else
printf("WSALookupServiceEnd(hLookup) failed with error code %ld\n");
}
else
{
printf("WSALookupServiceBegin() failed with error code %ld\n", WSAGetLastError());
}// end WSALookupServiceBegin()
// Cleanup the winsock library startup
if(WSACleanup() == 0)
printf("WSACleanup() pretty fine!\n");
else
printf("WSACleanup() failed with error code %ld\n", WSAGetLastError());
} // end WSAStartup()
return 0;
}
Build and run the project. The following screenshot shows a sample output.
----------------------------------------------------------------------------------
The following sample output is the full version of the previous screenshot.
WSAStartup() should be fine!
socket() is OK!
getsockopt(SO_PROTOCOL_INFO) is OK!
WSALookupServiceBegin() is OK!
WSALookupServiceNext() is OK!
The service instance name is nazuri
WSAAddressToString() for local address is fine!
The local address: (00:11:67:55:8F:69)
WSAAddressToString() for remote address is fine!
The remote device address: (00:1D:D9:EA:24:D8)
WSALookupServiceBegin() is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Bluetooth Serial Port
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #0 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Network Access
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #1 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Network Access
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #2 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Dial-up Networking
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #3 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: PIM Item Transfer
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #4 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: File Transfer
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #5 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Fax
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #6 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: PIM Synchronization
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #7 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Sync Command Service
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #8 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Headset
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #9 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Stereo Audio
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #10 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name:
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #11 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Audio Source
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #12 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Bluetooth Imaging
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #13 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Audio Gateway
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #14 is OK!
WSALookupServiceNext() is OK!
WSALookupServiceNext() - service instance name: Audio Gateway
WSALookupServiceNext() - comment (if any):
BluetoothSdpEnumAttributes() #15 is OK!
WSALookupServiceNext() failed with error code 10110
Error code = 11011 ~ WSA_E_NO_MORE ~ No more device!
WSALookupServiceEnd(hLookup2) is fine!
WSALookupServiceEnd(hLookup) is fine!
WSACleanup() pretty fine!
Press any key to continue . . .
< Bluetooth Device Query Example | Winsock2 Supported Protocols Main | Querying Bluetooth Device Example >