April 24, 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 »

Few General Words

The previous article, "Experiencing This Mysterious Bluetooth Stack Programming," gave you a very brief overview of the Widcomm BT stack and how to manage it from your own applications. Now, you switch to yet another implementation of Bluetooth stack, this time from Microsoft as a part of the Windows Mobile OS SDK. It follows the common Microsoft C-style paradigm and is quite different from, for example, the Widcomm stack. In this article, you will repeat those typical operations you might be needing to use in many cases (as in BT devices enumeration and so forth) as you did for the Widcomm stack. Code snippets here and there throughout the article should provide you a good basis for your own experiments.

Enumerating Bluetooth Devices

If you look at the SDK headers, you will see a few files related to Bluetooth. What you are interested in right now is located in winsock2.h. Here, you may find client-level APIs to the BT stack. For enumeration purposes, you will use the following functions:

WSALookupServiceBegin
WSALookupServiceNext
WSALookupServiceEnd

Seeing a "WSA" prefix in the API declarations above, you might bet it has to deal with sockets somehow. Yes, that's correct. Here, you'll get a good mix of sockets with virtual RFComm channels. Saying all this, the actual programming may be even simpler than for the Widcomm stack, but it really depends on your requirements.

All right, let me start with device enumeration. A scheme here is quite typical for many enumerating operations you can perform with other media, such as, for example, files:

  • Open enumeration
  • Loop through with 'Next' function
  • Close enumeration

In practice you have to do the following steps, as in this code snippet:

struct BtInfo
{
   CString m_sName;
   BT_ADDR m_btAddr;
};

typedef CArray<BtInfo,BtInfo&> CBtInfoArray;

int DiscoverBtDevList(CBtInfoArray& arrBtInfo)
{
   BOOL           bRes = FALSE;
   int            iResult = 0;
   LPWSAQUERYSET  pwsaResults;
   DWORD          dwSize = 0;
   WSAQUERYSET    wsaq;
   HANDLE         hLookup = 0;

   memset (&wsaq, 0, sizeof(wsaq));
   wsaq.dwSize      = sizeof(wsaq);
   wsaq.dwNameSpace = NS_BTH;
   wsaq.lpcsaBuffer = NULL;

   // initialize searching procedure
   iResult = WSALookupServiceBegin(&wsaq,
      LUP_CONTAINERS,
      &hLookup);

   if (iResult != 0)
   {
      iResult = WSAGetLastError();
      return iResult;
   }

   union {
      // returned struct can be quite large
      CHAR buf[5000];
      // properly align buffer to BT_ADDR requirements
      SOCKADDR_BTH  __unused;
   };

   for (;;)
   {
      pwsaResults = (LPWSAQUERYSET) buf;

      dwSize  = sizeof(buf);

      memset(pwsaResults,0,sizeof(WSAQUERYSET));
      pwsaResults->dwSize = sizeof(WSAQUERYSET);
      // namespace MUST be NS_BTH for bluetooth queries
      pwsaResults->dwNameSpace = NS_BTH;
      pwsaResults->lpBlob = NULL;

      // iterate through all found devices, returning name and address
      iResult = WSALookupServiceNext (hLookup,
         LUP_RETURN_NAME | LUP_RETURN_ADDR,
         &dwSize,
         pwsaResults);

      if (iResult != 0)
      {
         iResult = WSAGetLastError();
         if (iResult != WSA_E_NO_MORE)
         {
            TCHAR tszErr[32];
            iResult = WSAGetLastError();
            _sntprintf(tszErr, 32, _T("Socket Error: %d"), iResult);
            AfxMessageBox(tszErr, MB_OK);
         }
         break;
      }

      // collect name and address
      if (pwsaResults->lpszServiceInstanceName)
      {
         BtInfo btInfo;
         btInfo.m_sName = pwsaResults->lpszServiceInstanceName;
         memcpy(&(btInfo.m_btAddr),pwsaResults->
                lpcsaBuffer,sizeof(BT_ADDR));
         arrBtInfo.Add(btInfo);
      }
      Sleep(100);
   }

   WSALookupServiceEnd(hLookup);

   return iResult;
}

As you can see, there is nothing complex except few magical words and passes. The latter, I will discuss right here. First, you want to look up all containers in NS_BTH namespace. Second, you don't want to get back any additional information about neither local nor remote addresses. Thus wsaq variable setup and call to WSALookupServiceBegin start the race.

The next stage is a simple iteration through obtained results until you get an error WSA_E_NO_MORE after calling WSALookupServiceNext. You can control which data you want to get via parameters of that function. Our snippet requests a name and BT address. For simplicity, you use MFC's CArray here, but you may return the result as you want to—for example, looking up only for specific device and so forth.





Page 1 of 3



Comment and Contribute

 


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

 

 


Sitemap | Contact Us

Rocket Fuel