June 23, 2018
Hot Topics:

Get Familiar: Microsoft Bluetooth Stack on Windows Mobile

  • October 27, 2006
  • By Alex Gusev
  • Send Email »
  • More Articles »

Detecting RFComm Channel

Once you have detected a device and grabbed its address, you can connect to it via WinSock. The first steps are quite common for any other networking code except some BT-specific settings:

if(WSAStartup(MAKEWORD(1,1), &wsd))
   return FALSE;

// Create a Bluetooth socket
if(btSocket == INVALID_SOCKET)
   //report an error
   return FALSE;

// Setup the socket address
memset (&sockAddr, 0, sizeof(sockAddr));
sockAddr.addressFamily = AF_BTH;
// m_btAddr was obtained earlier via device enumeration
sockAddr.btAddr = m_btAddr;
int nResult = connect(btSocket, (SOCKADDR*)&sockAddr,

As you see, there is nothing unusual in the above snippet except for the address family, the socket address itself, and the given protocol. The most interesting question here is what should be a port value to connect to? To answer this question, you need to determine the RFComm channel associated with SPP service because in this sample you want to use BTHPROTO_RFCOMM. In case of BTHPROTO_L2CAP, you will be required to set up the appropriate stuff too. But here, you will focus on RFComm for it is supported in Widcomm stack as well.

Now, you get to the problem of RFComm channel detection. You will find everything required to perform this task in bthapi.h. There are a number of COM interfaces responsible for various Bluetooth operations. You will be interested in SDP. Having said this, you should call

CoUninitialize ();

somewhere in the code.

To obtain a RFComm channel associated with SPP service from given device, you need to run a query similar to the one that you used for device enumeration, but this time with more restrictions:

int DetectRFCommChannel(BT_ADDR *pbBtAddr)
   int iResult = 0;

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

   RBlob.type                   = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
   RBlob.numRange               = 1;
   RBlob.pRange[0].minAttribute = SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST;
   RBlob.pRange[0].maxAttribute = SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST;
   RBlob.uuids[0].uuidType      = SDP_ST_UUID16;
   RBlob.uuids[0].u.uuid16      = SerialPortServiceClassID_UUID16;

   BLOB blob;
   blob.cbSize    = sizeof(RBlob);
   blob.pBlobData = (BYTE *)&RBlob;

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

   *(BT_ADDR *)(&sa.btAddr) = *pbBtAddr;
   sa.addressFamily = AF_BT;

   CSADDR_INFO      csai;
   memset (&csai, 0, sizeof(csai));
   csai.RemoteAddr.lpSockaddr = (sockaddr *)&sa;
   csai.RemoteAddr.iSockaddrLength = sizeof(sa);

   WSAQUERYSET      wsaq;
   memset (&wsaq, 0, sizeof(wsaq));
   wsaq.dwSize      = sizeof(wsaq);
   wsaq.dwNameSpace = NS_BTH;
   wsaq.lpBlob      = &blob;
   wsaq.lpcsaBuffer = &csai;

   HANDLE hLookup;
   int iRet = WSALookupServiceBegin (&wsaq, 0, &hLookup);
   if (ERROR_SUCCESS == iRet)
      CHAR buf[5000];
      LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
      DWORD dwSize  = sizeof(buf);

      pwsaResults->dwSize      = sizeof(WSAQUERYSET);
      pwsaResults->dwNameSpace = NS_BTH;
      pwsaResults->lpBlob      = NULL;

      iRet = WSALookupServiceNext (hLookup, 0, &dwSize, pwsaResults);
      if (iRet == ERROR_SUCCESS)
         unsigned char cChannel = 0;
         if (ERROR_SUCCESS == FindRFCOMMChannel(
                              iResult = cChannel;


   return iResult;

An important difference from previous query is that you have specified the previously found BT address and service. All above structures are documented in MSDN, so you can consult it for more detailed information.

Page 2 of 3

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

By submitting your information, you agree that developer.com may send you developer offers via email, phone and text message, as well as email offers about other products and services that developer believes may be of interest to you. developer will process your information in accordance with the Quinstreet Privacy Policy.


We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.
Thanks for your registration, follow us on our social networks to keep up-to-date