Programmatically searching for nearby Bluetooth devices in Windows Mobile from C#

As part of my plan to write a location-based reminder app using Bluetooth devices, I need a way to know what bluetooth devices are near me.

I’ve not done any Bluetooth development before, so I’ve had to learn a few new bits and pieces tonight.

Decision 1 – Which SDK?

It turns out that there is more than one type of Bluetooth radio used in Windows Mobile phones. And the SDKs that lets you programmatically interact with the bluetooth stack are specific to certain radios. There seem to be only a few big players here. A lot of Windows Mobile devices use the Microsoft Bluetooth stack, and Microsoft provide an API for them. The other big chunk of devices are supported by a Widcomm Bluetooth SDK. I also found references in a couple of forum posts about a third, smaller, provider – although I can’t find them now. (Why don’t I make better notes as I go along?!)

My Windows Mobile devices both support the Microsoft Bluetooth stack, so I’m gonna go with that for now. I did download the Widcomm SDK and start playing with it a bit, but I think I’ll leave that for another day.

Decision 2 – To discover, or not to discover…

I have a couple of options:

Search for all local Bluetooth devices with a discoverable device ID

PROS:

  • The devices don’t need to be registered / paired with my phone.

CONS:

  • Not everyone leaves their Bluetooth devices in a ‘discoverable’ mode.
  • You can’t do this easily in a background, notification-based way. You’re limited to polling at regular intervals – which is never a particularly elegant (or battery-efficient!) programming paradigm.

.

Register for connect and disconnect notifications from paired devices

PROS:

  • Bluetooth devices you search for don’t need to be discoverable.
  • You don’t need to poll – you can just register for notifications then sit back and wait to be called when a device comes into range

CONS:

  • You need to pair with every device – adding hassle and overhead for users. Would people worry about trust issues?

I guess an ideal solution would be to write an app which can do both. For now, I’ll start with the Discovery approach.

Decision 3 – Implementation time!

As I’ve already started my app in C#, I started by looking for a C# API. There isn’t one. (Well, there are some third-party libraries kicking about… 32feet.NET seems to be popular from what I’ve read. But where’s the fun in that? 🙂 )

There is a C++ API to do it with Winsock commands which is well-documented with a sample and walkthrough on MSDN. I had a go at writing some P/Invoke code to port the sample to C# – using P/Invoke to call each of the WSAStartup, WSALookupServiceBegin, WSALookupServiceNext, WSALookupServiceEnd, WSACleanup functions in turn from C# code.

I thought it was easy enough to write, but I can’t seem to get it working. It compiles fine, but I’m obviously not creating the C# equivalent of the WSAQUERYSET structure correctly, because calls to WSALookupServiceBegin keep getting WSA_INVALID_HANDLE error codes.

I’ve tried a bunch of different approaches, but it just isn’t working. I’m guessing it’s something I’m doing wrong marshalling the strings in the structure.

So on to Plan B – give up trying to write it in C#, write the whole thing in a C++ function, and compile it into a DLL which I can P/Invoke from C#. Then I don’t need to muck about P/Invoking the individual Winsock calls and structures.

I’ve done that now, and it seems to be working okay.

If anyone thinks it might be useful, the DLL is available here. You can use it from C# like this:

[DllImport("bLADEBluetoothLib.dll",
  EntryPoint = "discoverbluetoothdevices",
  CharSet = CharSet.Unicode,
  SetLastError = true)]
private static extern int DiscoverBluetoothDevices(String deviceList);

[DllImport("Ws2.dll", 
  SetLastError = true)]
private extern static Int32 WSAGetLastError();

public static string[] GetDiscoverableDevices()
{
  // prepare a 500 character buffer for the DLL to return 
  //  the result in
  String deviceList = new String(' ', 500);

  // get a comma-separated list of 
  // discoverable Bluetooth devices
  // 
  // the number of devices is returned
  int nbrDevices = DiscoverBluetoothDevices(deviceList);

  if (nbrDevices >= 0)
  {
    return deviceList.ToString().Split(new char[] { ',' });
  }
  else
  {
    // if the DLL encounters an error in one of the WinSock
    //  functions it uses, it returns -1
    // 
    // you can then use WSAGetLastError to find the source
    //  of the error
    MessageBox.Show(nbrDevices.ToString() + 
            " (reason: " + WSAGetLastError() + ")");
    return new string[0];
  }
}

It’s still very rough around the edges, so stuff like tidying and error-handling needs to be sorted. I’ve not written C++ for P/Invoking before, so as a first attempt, there are almost certainly a few mistakes in my approach. But so far… it seems to work.

The location-based reminder app is starting to take shape. 🙂

Tags: , , , , , , ,

11 Responses to “Programmatically searching for nearby Bluetooth devices in Windows Mobile from C#”

  1. […] dale lane fan of all things mobile, father of small girls, IBM code monkey, youth charity trustee… « Programmatically searching for nearby Bluetooth devices in Windows Mobile from C# […]

  2. tamberg says:

    You might want to download Peter Foot’s excellent InTheHand.Net.Bluetooth.dll (from http://inthehand.com/ e.g. http://inthehand.com/files/folders/releases/entry801.aspx) which supports the Microsoft stack on .NET Compact Framework.

    Regards,
    tamberg

  3. dale says:

    hi tamberg

    Thanks for the comment. You’ll see in my original post that I do actually link to the 32feet.NET library, as – although I’ve not tried it – I came across some positive comments about it in forums and blog posts.

    But, like I wrote at the time, where’s the fun in using someone elses code? 😉

  4. […] wrote on Sunday about writing Bluetooth code for Windows Mobile for a location-based reminder app I hacked […]

  5. karthikeyan durai M says:

    Sir
    The Bluetooth device how to search the other devices and how communicate other devices. why the Bluetooth device communicate one device at a time.
    Just improve my knowledge

  6. Reelix says:

    Hello!

    Attempting to download DLL returns a 404 🙁

    Don’t suppose you would mind mailing me when (if?) the DLL ever comes back to life? 🙂

    Thanks alot!

    – Reelix

  7. dale says:

    @Reelix – Ah, sorry about that. My web host have changed their settings and no longer let me host DLL files… I’ve put it in a zip file, as it looks like they still allow zip files. Hope that helps. Sorry about that!

    http://dalelane.co.uk/files/bLADEBluetoothLib.zip

  8. Eric says:

    Does this work with devices that have a Broadcom Stack?

  9. dale says:

    Eric – I don’t know, sorry.

  10. Jason says:

    Hi,

    I get the error below when trying to use your dll in windows7

    —————————
    Project1.exe – Bad Image
    —————————
    C:\Users\xx\blutooth_research\bLADEBlutooth\bLADEBluetoothLib\bLADEBluetoothLib.dll is either not designed to run on Windows or it contains an error. Try installing the program again using the original installation media or contact your system administrator or the software vendor for support.
    —————————
    OK
    —————————

    Regards

  11. dale says:

    Hi Jason – When you say you’re trying to use the DLL in Windows 7, do you mean Windows Phone 7?