July 25, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

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:

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

// Create a Bluetooth socket
SOCKET btSocket = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if(btSocket == INVALID_SOCKET)
{
   //report an error
   return FALSE;
}

// Setup the socket address
SOCKADDR_BTH sockAddr;
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,
                      sizeof(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

...
CoInitializeEx (0, COINIT_MULTITHREADED);
...
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;

   BTHNS_RESTRICTIONBLOB RBlob;
   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;

   SOCKADDR_BTH   sa;
   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);

      memset(pwsaResults,0,sizeof(WSAQUERYSET));
      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(
                              pwsaResults->lpBlob->pBlobData,
                              pwsaResults->lpBlob->cbSize,
                              &cChannel))
                              iResult = cChannel;
      }

      WSALookupServiceEnd(hLookup);
   }

   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.

 

 


Sitemap | Contact Us

Rocket Fuel