Registering a Bluetooth Service (Windows Embedded CE 6.0)

1/6/2010

To publish a Bluetooth service record, the application must register the service. Windows Embedded CE ships a tool, Bthnscreate that you can use to generate a blob that represents the SDP record. You can then register the record by using the standard Winsock function, WSASetService (Bluetooth).

Before you register a Bluetooth service, you must have the following information:

  • You have a record file that contains the SDP data. SDP data must be placed within a SEQUENCE...END block. Each block contains a series of [type] [value] pairs. The following code example shows a sample record file.
    ;  Simple data file
    1    SEQUENCE
         ; Sequences contain one or more elements.
         UUID16 30000
         UUID32 4000000
         UUID128 12345678-ABCD-AF12-8800-12345678EF12
         END
    119  UINT16  19
    
    For more information about the elements of a record file, see Windows Embedded CE topic SDP Search and Record Generator Sample.

    For more sample record files, see .rec files located in the %_WINCEROOT%\Public\Common\Sdk\Samples\Bluetooth\Bthnscreate directory.
  • You have the Bthnscreate executable in the release directory on your device. If not, then build this tool by using the source code for Bthnscreate.
Ee495837.note(en-US,WinEmbedded.60).gifNote:
This procedure does not include error handling for code clarity.

The Bthnscreate sample that ships with Windows Embedded CE, contains source code for creating and searching SDP records.

For more information about this sample, see Windows Embedded CE topic SDP Search and Record Generator Sample.

To register a Bluetooth service by using Winsock
  1. To retrieve the binary service data, run bthnscreate.exe from the command prompt on your target Bluetooth device. Use the -record option and specify the record file as an argument to the tool. Type the following command:

    bthnscreate -record <record filename>
    

    Bthnscreate generates an SDP record in raw binary format. The following example shows the output for the sample record file, ftp.rec.

    const int cSdpRecord = 0x00000043
    BYTE rgbSdpRecord[] = {
      0x35, 0x41, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 
      0x11, 0x06, 0x09, 0x00, 0x04, 0x35, 0x11, 0x35, 
      0x03, 0x19, 0x01, 0x00, 0x35, 0x05, 0x19, 0x00, 
      0x03, 0x08, 0x0a, 0x35, 0x03, 0x19, 0x00, 0x08, 
      0x09, 0x00, 0x06, 0x35, 0x09, 0x09, 0x65, 0x6e, 
      0x09, 0x00, 0x6a, 0x09, 0x01, 0x00, 0x09, 0x00, 
      0x09, 0x35, 0x08, 0x35, 0x06, 0x19, 0x11, 0x06, 
      0x09, 0x01, 0x00, 0x09, 0x01, 0x00, 0x25, 0x03, 
      0x46, 0x54, 0x50
    };
    
  2. Prepare the caller application by providing Winsock-related data such as the 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);
    
  3. Define the SDP record size, the server channel offset, and create an array to store the binary SDP data returned by the Bthnscreate tool in step 1.

    1. Define the SDP record size SDP_RECORD_SIZE and set the record size returned in step 1. The following example code shows how to define the record size.
      #define SDP_RECORD_SIZE 0x00000043
      
    2. Identify the byte that represents the channel in the record file, and define the server channel offset as the index of this byte in the array. For example, for the sample ftp.rec, the offset is 32. The following example code defines the server offset.
      #define SDP_CHANNEL_OFFSET 32
      
    3. Declare a BYTE array, rgbSdpRecord and initialize it with the output values generated by Bthnscreate as the following example shows.
      static const BYTE rgbSdpRecord[] = {
        0x35, 0x41, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 
        0x11, 0x06, 0x09, 0x00, 0x04, 0x35, 0x11, 0x35, 
        0x03, 0x19, 0x01, 0x00, 0x35, 0x05, 0x19, 0x00, 
        0x03, 0x08, 0x0a, 0x35, 0x03, 0x19, 0x00, 0x08, 
      //Server offset.
        0x09, 0x00, 0x06, 0x35, 0x09, 0x09, 0x65, 0x6e, 
        0x09, 0x00, 0x6a, 0x09, 0x01, 0x00, 0x09, 0x00, 
        0x09, 0x35, 0x08, 0x35, 0x06, 0x19, 0x11, 0x06, 
        0x09, 0x01, 0x00, 0x09, 0x01, 0x00, 0x25, 0x03, 
        0x46, 0x54, 0x50
      };
      
  4. To store information about the service record, create and configure a BLOB (Windows Sockets) structure as the following example code shows.

    struct {
      BTHNS_SETBLOB   b;
      unsigned char   uca[SDP_RECORD_SIZE];
    } bigBlob;
    ULONG ulSdpVersion = BTH_SDP_VERSION;
    bigBlob.b.pRecordHandle   = &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 blob;
    blob.cbSize    = sizeof(BTHNS_SETBLOB) + SDP_RECORD_SIZE - 1;
    blob.pBlobData = (PBYTE) &bigBlob;
    

    In the preceding example, the structure bigblob declares a BTHNS_SETBLOB variable that stores the service record and information about the record such as the SDP version and size of the record.

    For BTHNS_SETBLOB, set the following members:

    • pRecordHandle: Set to the address of a ULONG variable that contains the record handle. For new records, this handle should be set to zero (0). During registration, SDP assigns a value to this handle and returns it in an out parameter for WSASetService.
    • ulRecordLength: Set to SDP_RECORD_SIZE as defined in step 2.
    • pSdpVersion: Set to the address of a ULONG variable that is assigned the value, BTH_SDP_VERSION, that defines the SDP version and is declared in the header file bthapi.h.
    • pRecord: Points to the buffer that contains the contents of the BYTE array rgbSdpRecord as defined in step 2.

    The variable, blob, declared as BLOB type, references bigblob variable and specifies the total size for the record and data.

  5. Create a WSAQUERYSET (Bluetooth) and configure it to register a new Bluetooth service by setting the dwNameSpace to NS_BTH. Specify the service to register by setting the lpBlob to the address of the BLOB variable created in step 3.

    The following example code shows how to set this variable.

    WSAQUERYSET Service;
    memset (&Service, 0, sizeof(Service));
    Service.dwSize = sizeof(Service);
    Service.lpBlob = &blob;
    Service.dwNameSpace = NS_BTH;
    
  6. To register the new Bluetooth service, call the WSASetService (Bluetooth) function by specifying the service to register in the lpqsRegInfo parameter and passing the RNRSERVICE_REGISTER flag in the essoperation parameter.

    The following example code shows how to call WSASetService.

    int iRet = BthNsSetService (&Service, RNRSERVICE_REGISTER,0);
    
  7. To terminate the use of Winsock services, call the WSACleanup function. Call WSACleanup for every successful call to WSAStartup made by an application.

    //------------------------------------------------------------------------
    // Function: BT_SetService
    // Purpose: Registers a new SDP record
    // Note: This function does not include a call to WSAStartup or WSACleanup 
    //       as described in the procedure.
    //       This sample has not been tested and is not intended for production use.
    //------------------------------------------------------------------------
    bool BT_SetService()
    {
       ULONG recordHandle = 0;
       #define SDP_RECORD_SIZE   0x0000004f
    
       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
       };
       struct 
       {
          BTHNS_SETBLOB   b;
          unsigned char   uca[SDP_RECORD_SIZE];
       } bigBlob;
       ULONG ulSdpVersion = BTH_SDP_VERSION;
       bigBlob.b.pRecordHandle   = &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 blob;
       blob.cbSize    = sizeof(BTHNS_SETBLOB) + SDP_RECORD_SIZE - 1;
       blob.pBlobData = (PBYTE) &bigBlob;
    
       WSAQUERYSET Service;
       memset (&Service, 0, sizeof(Service));
       Service.dwSize = sizeof(Service);
       Service.lpBlob = &blob;
       Service.dwNameSpace = NS_BTH;
    
       if (WSASetService(&Service,RNRSERVICE_REGISTER,0) == SOCKET_ERROR)
          return false;
       else
          return true;
    }
    

Community Additions

ADD
Show: