< Asynchronous Transfer Mode (ATM) | Winsock2 Supported Protocols Main | Bluetooth Device Query Example >


 

 

Winsock 2: Other Supported Protocols 4 Part 11

 

 

What do we have in this chapter 4 part 11?

  1. Bluetooth

  2. Stack

  3. Windows CE SDK vs Win32 Platform SDK

  4. Discovering Bluetooth Devices Using Winsock

  5. Bluetooth Device Query Program Example

 

Bluetooth

 

Bluetooth is an industry-standard protocol that enables wireless connectivity for computers, handheld devices, mobile phones, and other devices. In normal applications it already surpassed the infrared technology. Bluetooth is designed for use by C/C++ programmers and some Bluetooth features are available with Windows Sockets.

Microsoft Bluetooth supports begin with Windows XP with Service Pack 1 (SP1). Support for Bluetooth 2.1 is offered via the latest Windows Vista Feature Pack for Wireless. The header file associated with this update is available at Microsoft Connect via the Windows Vista Feature Pack for Wireless Developers Supplement download.

 

Stack

 

A diagram of the Bluetooth stack is shown in Figure 4-2. The lower three layers - Baseband, Link Manager Protocol, and the first Host Controller Interface (HCI) layer, are implemented in the Bluetooth hardware. The layers above the hardware and below the application are provided by Windows CE, although it’s possible for third parties to extend the Bluetooth stack by providing additional profiles above the HCI layer.

Applications interact with the Bluetooth stack through one of two interfaces. The preferred method is for applications to use the Winsock API to access the Bluetooth stack. Just as with IrDA, applications use standard Winsock functions to open sockets associated with the Bluetooth stack. Control is accomplished through various WSAxxx() functions. Data transfer is accomplished through the standard socket send and recv functions.

 

Bluetooth: A diagram of the Bluetooth stack on Windows CE

 

Figure 4-2 A diagram of the Bluetooth stack on Windows CE

 

Winsock support for Bluetooth depends on the Winsock stack installed on the device. If the system has Winsock 2.0 installed, such as Windows Mobile devices, Bluetooth functionality is accessed directly through Winsock calls such as setsockopt(). For systems with Winsock 1.1 installed, the Bluetooth stack needs to be configured through a dedicated Bluetooth API. For example, to query the current mode of an asynchronous connection, an application can use the dedicated function BthGetCurrentMode() or, if Winsock 2.0 is on the system, a call to getsockopt() with the option name SO_BTH_GET_MODE.

The other way applications can work with Bluetooth is through virtual serial ports. With this method, applications load a Bluetooth-dedicated serial driver. Control of the stack is accomplished through DeviceIoControl() calls to the COM driver. Calling WriteFile() and ReadFile() to write and read the COM port sends and receives data across the Bluetooth connection.

 

Windows CE SDK vs Win32 Platform SDK

 

In the programming part of the bluetooth, normally are based on the two bluetooth stacks: Microsoft and Widcomm/Broadcom. Program created based on the Microsoft stack cannot be run on the Widcomm/Broadcom. In simple word, there isn't a single method which works on all stacks. Most notebook and IPAQ range of products for example, use Widcomm/Broadcom stack. Widcomm provide their own SDK for their bluetooth stack and you can download the widcomm SDK from their website for bluetooth programming. Some OEMs have chosen not to use the Microsoft bluetooth stack. This means the examples created based on the Microsoft stack will not operate on those devices.

The winsock APIs only work with the Microsoft stack and there are Windows CE SDK and Win32 Platform SDK for bluetooth programming. The Bluetooth APIs exposed on a Windows CE/Windows Mobile device has a slightly different design. With some features not exposed and others exposed differently. The header files and libraries used also different except winsock.h/winsock2.h (ws2_32.lib). In this chapter we will try to demonstrate code samples from both Windows CE SDK and Win32 Platform SDK. It is better for you to choose one SDK and not mix both SDKs in one program. For desktop bluetooth application development, of course to choose the Win32 Platform SDK.

 

Discovering Bluetooth Devices Using Winsock

 

An application can create a query for discovering remote Bluetooth devices within range, by using the following standard Winsock programming elements:

 

  1. WSAQUERYSET structure.
  2. WSALookupServiceBegin() function.
  3. WSALookupServiceNext() function.
  4. WSALookupServiceEnd() function.

 

The sample that ships with Windows Embedded CE contains source code for discovering Bluetooth devices by using Winsock. To perform device discovery and retrieve the address of a remote Bluetooth device:

 

 

1.      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(1,0), &wsd);

 

2.      Create and initialize a WSAQUERYSET variable to specify search parameters. Set the dwNameSpace member to NS_BTH to restrict the query to Bluetooth devices. The following code example shows the values to set in WSAQUERYSET.

 

WSAQUERYSET wsaq;

ZeroMemory(&wsaq, sizeof(wsaq));

wsaq.dwSize = sizeof(wsaq);

wsaq.dwNameSpace = NS_BTH;

wsaq.lpcsaBuffer = NULL;

 

3.      To start an inquiry, call the WSALookupServiceBegin() function. The following code example shows how to call WSALookupServiceBegin() to perform a device inquiry by passing the WSAQUERYSET variable, created in step 1.

 

int iRet = WSALookupServiceBegin (&wsaq, LUP_CONTAINERS, &hLookup);

 

In the preceding example, LUP_CONTAINERS is passed in the dwFlags parameter. This enables Service Discovery Protocol (SDP) to search for other Bluetooth devices within range. Passing zero (0) in the dwFlags parameter performs a service search. The WSALookupServiceBegin() function returns a handle in the hLookup parameter.

 

4.      To enumerate devices that were scanned in the previous call to WSALookupServiceBegin(), call the WSALookupServiceNext() function. This function returns a pointer to a buffer that stores the result set in a WSAQUERYSET structure.

 

a.             Configure a WSAQUERYSET structure to store device data returned by WSALookupServiceNext(). The following code shows how to configure this structure.

 

CHAR buf[4096];

LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;

ZeroMemory(pwsaResults, sizeof(WSAQUERYSET));

pwsaResults->dwSize = sizeof(WSAQUERYSET);

pwsaResults->dwNameSpace = NS_BTH;

pwsaResults->lpBlob = NULL;

 

b.             Call WSALookupServiceNext() by passing the handle returned by WSALookupServiceBegin() in the hLookUp parameter. To improve performance, the call to WSALookupServiceBegin() returns only the addresses of the devices, and these addresses are stored in memory. To retrieve the name and address of the device, pass LUP_RETURN_NAME | LUP_RETURN_ADDR in the dwFlags parameter. The following code shows how to call WSALookupServiceNext().

 

DWORD dwSize  = sizeof(buf);

int iRet = WSALookupServiceNext (hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &dwSize, pwsaResults)

 

5.      To enumerate the devices, the caller application can loop through the list of devices, by calling WSALookupServiceNext() repetitively.

6.      To terminate the device discovery process, call the WSALookupServiceEnd() function. This function releases the lookup handle created by WSALookupServiceBegin(). The following code shows how to call WSALookupServiceEnd().

 

WSALookupServiceEnd(hLookup);

 

7.      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.

 

Bluetooth Device Query Program Example

 

The following code example performs a device inquiry displays the device name in a console. Create a new empty Win32 console mode application and add the project/solution name.

 

----------------------------------------------------------------

Bluetooth Device Query Program Example: Creating a new empty Win32 console mode application and adding the project/solution name

 

Add the following source code.

 

// Note: These header files used are from the

// Windows SDKs v6.0A. The Windows CE header files

// are different though some of the file names might be similar

// and this is 'tally' with the VS project type. In full version VS

// there is a project template for Windows CE which is SmartDevice.

// Choosing the SmartDevice project template will 'bind' the project

// to the appropriate header files and library

 

// Link to ws2_32.lib

#include <winsock2.h>

#include <ws2bth.h>

#include <BluetoothAPIs.h>

#include <stdio.h>

 

#define MAX_NAME 248

typedef ULONGLONG bt_addr, *pbt_addr, BT_ADDR, *PBT_ADDR;

 

union {

            // Storage for returned struct

            CHAR buf[5000];

            // properly align buffer to BT_ADDR requirements

            SOCKADDR_BTH _Unused_;

} butuh;

 

//------------------------------------------------------------------------

// Function: FindingBtDevices

// Purpose: Performs a device inquiry displays the device name in a console

//------------------------------------------------------------------------

BOOL FindingBtDevices()

{

            WSAQUERYSET wsaq;

            HANDLE hLookup;

            LPWSAQUERYSET pwsaResults;

            DWORD dwSize;

            BOOL bHaveName;

            BT_ADDR btAddr;

            DWORD dwNameSpace;

           

            pwsaResults = (LPWSAQUERYSET) butuh.buf;

            dwSize  = sizeof(butuh.buf);

           

            ZeroMemory(&wsaq, sizeof(wsaq));

            wsaq.dwSize = sizeof(wsaq);

            // namespace MUST be NS_BTH for bluetooth queries

            wsaq.dwNameSpace = NS_BTH;

            wsaq.lpcsaBuffer = NULL;

 

            printf("\n");

            // initialize searching procedure

            if (WSALookupServiceBegin(&wsaq, LUP_CONTAINERS, &hLookup) == SOCKET_ERROR)

            {

                        printf("WSALookupServiceBegin() failed %d\r\n", WSAGetLastError());

                        return FALSE;

            }

            else

                        printf("WSALookupServiceBegin() pretty damn OK!\n");

 

            ZeroMemory(pwsaResults, sizeof(WSAQUERYSET));

            pwsaResults->dwSize = sizeof(WSAQUERYSET);

            pwsaResults->dwNameSpace = NS_BTH;

            pwsaResults->lpBlob = NULL;

 

            // iterate through all found devices, returning name and address

            while (WSALookupServiceNext(hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &dwSize, pwsaResults) == 0)

            {

                        btAddr = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;

                        // Verify the returned name

                        bHaveName = (pwsaResults->lpszServiceInstanceName) && *(pwsaResults->lpszServiceInstanceName);

 

                        dwNameSpace = pwsaResults->dwNameSpace;

                        // print name and address

                        wprintf (L"Name\tNAP Address\tSAP Address\tName Space\n");

                        wprintf (L"%s\t0X%04X\t\t0X%08X\t0X%0X\n", pwsaResults->lpszServiceInstanceName, GET_NAP(btAddr), GET_SAP(btAddr),

                                    dwNameSpace);

            }

 

            if(WSALookupServiceEnd(hLookup) == 0)

                        printf("WSALookupServiceEnd(hLookup) is OK!\n");

            else

                        printf("WSALookupServiceEnd(hLookup) failed with error code %ld\n",WSAGetLastError());

            return TRUE;

}

 

 

int main(int argc, char **argv)

{

            WSADATA wsd;

            BOOL retVal;

           

            if(WSAStartup(MAKEWORD(2,2), &wsd) != 0)

                        printf("WSAStartup() failed with error code %ld\n", WSAGetLastError());

            else

                        printf("WSAStartup() is OK!\n");

 

            retVal = FindingBtDevices();

 

            if(FindingBtDevices() == FALSE)

                        printf("\nNo bulutooth device in range found!\n");

            else

                        printf("\nWell, found some bluetooth devices around!\n");

 

            if(WSACleanup() == 0)

                        printf("WSACleanup() is OK!\n");

            else

                        printf("WSACleanup() failed with error code %ld\n", WSAGetLastError());

            return 0;

}

 

Build and run the project. The following is a sample output screenshot.

 

Bluetooth Device Query Program Example: A sample program output

 

 

 


< Asynchronous Transfer Mode (ATM) | Winsock2 Supported Protocols Main | Bluetooth Device Query Example >