< Bluetooth Service & SDP Record | Winsock2 Supported Protocols Main | Bluetooth & Socket Options >


 

 

Winsock 2: Other Supported Protocols 4 Part 16

 

 

What do we have in this chapter 4 part 16?

  1. Registering a Bluetooth Service Program Example

  2. Winsock Extensions

  3. Winsock Function Extensions

  4. Bluetooth and socket

  5. Bluetooth and bind

  6. Bluetooth and connect

  7. Bluetooth and accept

  8. Bluetooth and listen, select, and closesocket

  9. Bluetooth and accept

  10. Bluetooth and read or write operations

  11. Bluetooth and shutdown

 

Registering a Bluetooth Service Program Example

 

The following example shows a complete code snippet. Create a new empty Win32 console mode application and add the project/solution name.

 

Registering a Bluetooth Service Steps and Example: Create a new empty Win32 console mode application and add the project/solution name.

 

Add the following source code.

 

#include <stdio.h>

// Link to ws2_32.lib

#include <winsock2.h>

#include <ws2bth.h>

#include <BluetoothAPIs.h>

 

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

// Function: BT_SetService

// Purpose: Registers a new SDP record

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

#define SDP_RECORD_SIZE   0x0000004f

#define SDP_CHANNEL_OFFSET 32

 

struct

{

            BTHNS_SETBLOB   b;

            unsigned char   uca[SDP_RECORD_SIZE];

} bigBlob;

 

BOOL BT_SetService()

{

   ULONG recordHandle = 0;

   ULONG ulSdpVersion = BTH_SDP_VERSION;

   BLOB blob;

   WSAQUERYSET Service;

 

   // Bluetooth device profile record sample

   BYTE rgbSdpRecord[] = {

         0x35, 0x4d, 0x09, 0x00, 0x01, 0x35, 0x11, 0x1c,

         0x29, 0xf9, 0xc0, 0xfd, 0xbb, 0x6e, 0x47, 0x97,

         0x9f, 0xa9, 0x3e, 0xc9, 0xa8, 0x54, 0x29, 0x0c,

         0x09, 0x00, 0x04, 0x35, 0x0c, 0x35, 0x03, 0x19,

         0x01, 0x00, 0x35, 0x05, 0x19, 0x00, 0x03, 0x08,

         0x1a, 0x09, 0x00, 0x06, 0x35, 0x09, 0x09, 0x65,

         0x6e, 0x09, 0x00, 0x6a, 0x09, 0x01, 0x00, 0x09,

         0x00, 0x09, 0x35, 0x08, 0x35, 0x06, 0x19, 0x11,

         0x05, 0x09, 0x01, 0x00, 0x09, 0x01, 0x00, 0x25,

         0x06, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c

   };

 

   bigBlob.b.pRecordHandle   = (HANDLE *)&recordHandle;

   bigBlob.b.pSdpVersion     = &ulSdpVersion;

   // bigBlob.b.fSecurity       = 0;

   // bigBlob.b.fOptions        = 0;

   bigBlob.b.ulRecordLength  = SDP_RECORD_SIZE;

   memcpy (bigBlob.b.pRecord, rgbSdpRecord, SDP_RECORD_SIZE);

 

   blob.cbSize    = sizeof(BTHNS_SETBLOB) + SDP_RECORD_SIZE - 1;

   blob.pBlobData = (PBYTE) &bigBlob;

 

   memset (&Service, 0, sizeof(Service));

   Service.dwSize = sizeof(Service);

   Service.lpBlob = &blob;

   Service.dwNameSpace = NS_BTH;

 

   if (WSASetService(&Service,RNRSERVICE_REGISTER,0) == SOCKET_ERROR)

   {

      printf("WSASetService() failed with error code %d\n", WSAGetLastError ());

      return FALSE;

   }

   else

   {

       printf("WSASetService() is working!\n");

       return TRUE;

   }

}

 

int main(int argc, char **argv)

{

            WSADATA wsd;

            BOOL RetVal;

 

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

            {

                        printf("Unable to load Winsock! Error code is %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("WSAStartup() is OK, Winsock lib loaded!\n");

 

            RetVal = BT_SetService();

 

            printf("The return value is: %d\n", RetVal);

 

            if(WSACleanup() == 0)

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

            else

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

            return 0;

}

 

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

 

Registering a Bluetooth Service Steps and Example: A sample of program output

 

Winsock Extensions

 

Using Bluetooth through Winsock interfaces is common to all socket-based programming. The server creates the socket, binds it to a given RFCOMM channel, exports the SDP record advertising this channel, and then listens for incoming connections. The following code example shows how this is done.

 

SOCKET s = socket(...);

bind(s, ...);

listen(s, ...);

for(; ;)

{

   SOCKET s2= accept(s, ...);

   recv(...);

   send(...);

}

 

The client then creates the socket, connects it to the server using a known server channel obtained from the SDP query or a UUID of the target service, and then starts sending and receiving requests. The following code snippet demonstrates how this is done.

 

SOCKET s = socket(...);

connect(s, ...);

send(s, ...);        // send request

recv(s, ...);        // get response

closesocket(s);    // done

 

Winsock Function Extensions

 

To establish a Bluetooth connection using the Winsock interface, use the following extensions:

 

1.      socket()

2.      bind()

3.      getsockname()

4.      getpeername()

5.      connect()

6.      accept()

7.      getsockopt()

8.      setsockopt()

 

Bluetooth and socket

 

The socket() function creates a socket for incoming or outgoing connections. This function is actually a Winsock function. However, the information that is presented in it is specific to Bluetooth. The syntax is:

 

SOCKET socket(int af, int type, int protocol);

 

 To create a socket using Bluetooth, use the following settings:

 

1.      The af parameter of the socket function is always set to AF_BTH for Bluetooth sockets.

2.      The type parameter of the socket function is always SOCK_STREAM; SOCK_DGRAM sockets are not supported by Bluetooth.

3.      For the protocol parameter, BTHPROTO_RFCOMM is the supported protocol.

 

The following example code shows how to use socket to create a Bluetooth socket.

 

SOCKET s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);

 

 

Bluetooth and bind

 

Bluetooth uses the bind function to bind to a socket. To bind a Bluetooth socket, call the bind function using the SOCKADDR_BTH structure. The syntax is:

 

int bind(SOCKET s, const struct sockaddr FAR* name, int namelen);

 

To bind a Bluetooth socket use the SOCKADDR_BTH structure with the following settings:

 

name.addressFamily = AF_BTH;

name.btAddr = 0;

name.serviceClassId = NULL_GUID;

name.port = number of service channel, 0 or BT_PORT_ANY;

 

On client applications, the port member must be zero to enable an appropriate local endpoint to be assigned. On server applications, the port member must be a valid port number or BT_PORT_ANY; ports automatically assigned using BT_PORT_ANY may be queried subsequently with a call to the getsockname() function. The valid range for requesting a specific RFCOMM port is 1 through 30. Server channels are global resource, and only 30 server channels are available for RFCOMM on any Bluetooth device, which must be shared by all Windows Sockets that belong to the Bluetooth address family. If no server channel is available, or if the specified server channel is already reserved, the bind() call fails. Upon successful return from bind(), the server channel is reserved until the socket is closed. You can use the getsockname() function to retrieve the channel number for SDP registration. Applications should use auto-allocation for the server channel.

The bind() function does not automatically advertise the server application using the Bluetooth SDP; applications must call the WSASetService() function to be found by remote Bluetooth applications. If the port is 0, the port will be allocated automatically. Remember that server channels are a global resource and there are a total of 31 server channels available for RFCOMM on any Bluetooth device for all applications to share (both Winsock and virtual COM ports).

If there is no available server channel, or the specified server channel is already reserved by another application, the call will fail.

It is recommended that an application always use auto-allocation for a server channel, unless a fixed server channel is specified by a future Bluetooth profile specification. Currently, there are no profiles that fix channel numbers. The following example code shows how to use auto-allocation for a server channel.

 

SOCKADDR_BTH sab;

memset (&sab, 0, sizeof(sab));

sab.addressFamily = AF_BTH;

// auto-allocate server channel

sab.port = 0;

 

Bluetooth and connect

 

This function establishes a connection to a specified socket. This function is actually a Winsock function. However, the information that is presented in it is specific to Bluetooth. The syntax is:

 

int connect(SOCKET s, const struct sockaddr FAR* name, int namelen);

 

If no error occurs, this function returns zero. If an error occurs, it returns SOCKET_ERROR, and a specific error code can be retrieved by calling WSAGetLastError().

Use this function to connect to a target device. Socket s must be created as a Bluetooth socket. The parameter name must specify the target Bluetooth device. If name.port is 0, then name.serviceClassId should contain the UUID of an RFCOMM-based service. Winsock performs an SDP call to find out the server channel number. The following example code shows how to use the connect() function to connect to a target device.

 

SOCKET s;

SOCKADDR_BTH sab;

 

s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);

if (s == INVALID_SOCKET)

{

            wprintf (L"Could not create socket: error %d\n", WSAGetLastError());

            return;

}

 

memset (&sab, 0, sizeof(sab));

sab.addressFamily = AF_BTH;

sab.serviceClassId = FaxServiceClass_UUID;

sab.btAddr = target_bluetooth_device;

 

if (0 != connect (s, &sab, sizeof(sab))

{

            wprintf (L"Could not connect socket: error %d\n", WSAGetLastError());

            return;

}

 

The RFCOMM supports only one connection for a particular server channel between two devices. Which means that if application A on device X is connected to server P on device Y, application B on device X will not be able to connect to the same server on device Y. However, device Y will be able to accept an incoming connection on the same server channel from a different device, as well as an incoming connection from device X to a different server channel.

 

Bluetooth and accept

 

This function permits an incoming connection attempt on a socket. This function is actually a Winsock function. However, the information that is presented in it is specific to Bluetooth. The syntax is:

 

SOCKET accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

 

If no error occurs, this function returns a value of type SOCKET that is a descriptor for the new socket. This returned value is a handle for the socket on which the actual connection is made.

The integer referred to by addrlen initially contains the amount of space pointed to by addr. On return, it will contain the actual length in bytes of the address returned.

If an error occurs, a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by calling WSAGetLastError().

The Bluetooth server application calls accept() to wait for the incoming connection. The addr must point to the SOCKADDR_BTH structure, and *addrlen must be sizeof(SOCKADDR_BTH). This structure receives the address of the connecting client. The following example code shows how to use accept.

 

SOCKET s, s2;

SOCKADDR_BTH sab, sab2;

int ilen;

 

SOCKET s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);

if (s == INVALID_SOCKET)

{

            wprintf (L"Socket creation failed, error %d\n", WSAGetLastError ());

            return;

}

 

memset (&sab, 0, sizeof(sab));

sab.addressFamily  = AF_BTH;

 

if (0 != bind (s, (SOCKADDR *) &sab, sizeof(sab)))

{

            wprintf (L"Socket bind, error %d\n", WSAGetLastError ());

            closesocket (s);

            return;

}

 

listen (s, 5);

for ( ; ; )

{

            ilen = sizeof(sab2);

            s2 = accept (s, &sab2, &ilen);

           

            if (s2 == INVALID_SOCKET)

            {

                        wprintf (L"Socket bind, error %d\n", WSAGetLastError ());

                        break;

            }

            wprintf (L"Connection came from %04x%08x to channel %d\n",

                        GET_NAP(sab2.btAddr), GET_SAP(sab2.btAddr), sab2.port);

           

            SpinConnectionThreadsOnSocket(s2);

}

closesocket (s);

return;

 

Bluetooth and listen, select, and closesocket

 

Bluetooth uses the listen(), select(), and closesocket() functions without any modification from standard Windows Sockets programming. As with Windows Sockets, the closesocket() function frees resources associated with the socket.

When calling the listen() function, it is strongly recommended that a low value is used for the backlog parameter (typically 2 to 4), since only a few client connections are accepted. This reduces the system resources that are allocated for use by the listening socket.

 

Bluetooth and accept

 

Bluetooth uses the accept() function to enable incoming connection attempts on a socket. The BTH_ADDR of the client application is obtained by reading the Bluetooth transport-specific section of the returned sockaddr structure. Use of the accept() function with Bluetooth has the following format:

 

  1. The addr parameter of the accept() function is an optional pointer to a buffer that receives the address of the connecting entity, as known to the communications layer. A pointer to a SOCKADDR_BTH structure with the remote Bluetooth device address is returned.
  2. The addrlen parameter of the accept() function is an optional pointer to an integer that contains the length, in bytes, of addr. The integer must be greater or equal to the value of sizeof (SOCKADDR_BTH).

 

Bluetooth and read or write operations

 

Bluetooth is capable of performing all read and write operations available with Windows Sockets that are currently supported with other address families.

 

Bluetooth and shutdown

 

Bluetooth uses the shutdown() function to disconnect from the remote radio. Bluetooth does not have protocol-level support for the same graceful closes or half-closes that TCP/IP provides.

 

 

 


< Bluetooth Service & SDP Record | Winsock2 Supported Protocols Main | Bluetooth & Socket Options >