I’ve added support for Secure Simple Pairing (SSP) for Windows 7 and Vista SP2 using the Microsoft stack.  When a Windows 7/etc PC has a Bluetooth version 2.1 dongle (radio/controller) attached and a version 2.1 device is to be atempts to authenticate then one of the new SSP authentication methods will be used.  Previously we had support only for the original Bluetooth PIN authentication method and thus BluetoothWin32Authentication would ignore SSP authentication attempts.  It aims to supports all the authentication methods, although I’ve managed to test only the NumericalComparison/JustWorks methods, and not Passkey, PasskeyNotification and OutOfBand methods.

From the BluetoothWin32Authentication class documentation:

[…] the callback includes a parameter of type BluetoothWin32AuthenticationEventArgs. Various authentication methods are available in Bluetooth version 2.1 and later. Which one is being used is indicated by the AuthenticationMethod property. If it is Legacy then the callback method should set the Pin property.

For the other authentication methods e.g. NumericComparison or OutOfBand the callback method should use one or more of the other properties and methods e.g. NumberOrPasskeyAsString, NumberOrPasskey, Confirm, ResponseNumberOrPasskey, ConfirmOob etc.

For more information see the class documentation and the user guide (

Let me have your feedback.

No changes to BluetoothSecurity.PairRequest nor BluetoothWin32Authentication.New(BluetoothAddress,String).  Those will be considered in the future based on your feedback.  This also affects BluetoothClient.SetPin etc.

UPDATED: Renamed to NumberOrPasskey from  NumberOrPasscode etc

The Microsoft Bluetooth stack on both desktop Windows and WM/CE uses sockets for RFCOMM communications, and they use socket options for both setting parameters and getting information.  We use two of the options to implement the BluetoothClient and BluetoothListener Authenticate and Encrypt properties, and another on WM/CE for the SetPin method.

As these options are present only on the Microsoft platforms and even vary between the two platforms they aren’t very useful for production use, but they can be useful for diagnostics etc.  We recently had a question in the forums and I knocked up a bit of code to run through all the options we’ve seen in MSDN and see what values they return.  The code to run through all the known option is in our code repository at codeplex in the XxxMenuTesting suite of apps (Forms-/Device-/ConsoleMenuTesting) and uses reflection to get the list of options.  I won’t reproduce that here due to its complexity, but a sample simple(!) call would be:

    System.Net.Sockets.Socket sock = ... ...;
    System.Net.Sockets.SocketOptionName option;
    option = BluetoothSocketOptionName.GetMtu;
    option = BluetoothSocketOptionName.XPMtu;
    var v = sock.GetSocketOption(BluetoothSocketOptionLevel.RFComm, option);
    var i = (int)v;
    console.WriteLine("Option MTU value: {0}=0x{0:X}", i);

Firstly the result from a WM device, when connected to Widcomm on Windows XP. We get fifteen successes there.

---- TryAllMsftSocketOptions ----
Option:             Authenticate           1 : error:  (10042)
Option:           XPAuthenticate  0x80000001 : error:  (10042)
Option:                  Encrypt           2 : error:  (10042)
Option:                   SetPin           3 : error:  (10042)
Option:                  SetLink           4 : error:  (10042)
Option:                  GetLink           5 : error:  (10022)
Option:                    XPMtu  0x80000007 : error:  (10042)
Option:                   SetMtu           6 : error:  (10042)
Option:                   GetMtu           7 : value: 127=0x7F
Option:             XPMtuMaximum  0x80000008 : error:  (10042)
Option:            SetMtuMaximum           8 : error:  (10042)
Option:            GetMtuMaximum           9 : value: 32767=0x7FFF
Option:             XPMtuMinimum  0x8000000A : error:  (10042)
Option:            SetMtuMinimum          10 : error:  (10042)
Option:            GetMtuMinimum          11 : value: 23=0x17
Option:              SetXOnLimit          12 : error:  (10042)
Option:              GetXOnLimit          13 : value: 800=0x320
Option:             SetXOffLimit          14 : error:  (10042)
Option:             GetXOffLimit          15 : value: 200=0xC8
Option:            SetSendBuffer          16 : error:  (10042)
Option:            GetSendBuffer          17 : value: 7168=0x1C00
Option:         SetReceiveBuffer          18 : error:  (10042)
Option:         GetReceiveBuffer          19 : value: 7168=0x1C00
Option:              GetV24Break          20 : error:  (10022)
Option:                   GetRls          21 : value: 0=0x0
Option:                  SendMsc          22 : error:  (10042)
Option:                  SendRls          23 : error:  (10042)
Option:              GetFlowType          24 : value: 1=0x1
Option:           SetPageTimeout          25 : error:  (10042)
Option:           GetPageTimeout          26 : value: 9472=0x2500
Option:                  SetScan          27 : error:  (10042)
Option:                  GetScan          28 : value: 3=0x3
Option:                   SetCod          29 : error:  (10042)
Option:                   GetCod          30 : value: 5898764=0x5A020C
Option:          GetLocalVersion          31 : error:  (10022)
Option:         GetRemoteVersion          32 : error:  (10022)
Option: GetAuthenticationEnabled          33 : value: 0=0x0
Option: SetAuthenticationEnabled          34 : error:  (10042)
Option:           ReadRemoteName          35 : error:  (10042)
Option:            GetLinkPolicy          36 : value: 15=0xF
Option:            SetLinkPolicy          37 : error:  (10042)
Option:            EnterHoldMode          38 : error:  (10042)
Option:           EnterSniffMode          39 : error:  (10042)
Option:            ExitSniffMode          40 : error:  (10042)
Option:            EnterParkMode          41 : error:  (10042)
Option:             ExitParkMode          42 : error:  (10042)
Option:                  GetMode          43 : value: 0=0x0
---- CLEAN EXIT ----

Secondly on Windows XP, when connected to a MSFT+WM6, we only get one successful on XP.

---- TryAllMsftSocketOptions ----
Option:             Authenticate           1 : error:  (10042 ProtocolOption)
Option:           XPAuthenticate  0x80000001 : error:  (10042 ProtocolOption)
Option:                  Encrypt           2 : error:  (10042 ProtocolOption)
Option:                   SetPin           3 : error:  (10042 ProtocolOption)
Option:                  SetLink           4 : error:  (10042 ProtocolOption)
Option:                  GetLink           5 : error:  (10042 ProtocolOption)
Option:                    XPMtu  0x80000007 : value: 666=0x29A
Option:                   SetMtu           6 : error:  (10042 ProtocolOption)
Option:                   GetMtu           7 : error:  (10042 ProtocolOption)
Option:             XPMtuMaximum  0x80000008 : error:  (10042 ProtocolOption)
Option:            SetMtuMaximum           8 : error:  (10042 ProtocolOption)
Option:            GetMtuMaximum           9 : error:  (10042 ProtocolOption)
Option:             XPMtuMinimum  0x8000000A : error:  (10042 ProtocolOption)
Option:            SetMtuMinimum          10 : error:  (10042 ProtocolOption)
Option:            GetMtuMinimum          11 : error:  (10042 ProtocolOption)
Option:              SetXOnLimit          12 : error:  (10042 ProtocolOption)
Option:              GetXOnLimit          13 : error:  (10042 ProtocolOption)
Option:             SetXOffLimit          14 : error:  (10042 ProtocolOption)
Option:             GetXOffLimit          15 : error:  (10042 ProtocolOption)
Option:            SetSendBuffer          16 : error:  (10042 ProtocolOption)
Option:            GetSendBuffer          17 : error:  (10042 ProtocolOption)
Option:         SetReceiveBuffer          18 : error:  (10042 ProtocolOption)
Option:         GetReceiveBuffer          19 : error:  (10042 ProtocolOption)
Option:              GetV24Break          20 : error:  (10042 ProtocolOption)
Option:                   GetRls          21 : error:  (10042 ProtocolOption)
Option:                  SendMsc          22 : error:  (10042 ProtocolOption)
Option:                  SendRls          23 : error:  (10042 ProtocolOption)
Option:              GetFlowType          24 : error:  (10042 ProtocolOption)
Option:           SetPageTimeout          25 : error:  (10042 ProtocolOption)
Option:           GetPageTimeout          26 : error:  (10042 ProtocolOption)
Option:                  SetScan          27 : error:  (10042 ProtocolOption)
Option:                  GetScan          28 : error:  (10042 ProtocolOption)
Option:                   SetCod          29 : error:  (10042 ProtocolOption)
Option:                   GetCod          30 : error:  (10042 ProtocolOption)
Option:          GetLocalVersion          31 : error:  (10042 ProtocolOption)
Option:         GetRemoteVersion          32 : error:  (10042 ProtocolOption)
Option: GetAuthenticationEnabled          33 : error:  (10042 ProtocolOption)
Option: SetAuthenticationEnabled          34 : error:  (10042 ProtocolOption)
Option:           ReadRemoteName          35 : error:  (10042 ProtocolOption)
Option:            GetLinkPolicy          36 : error:  (10042 ProtocolOption)
Option:            SetLinkPolicy          37 : error:  (10042 ProtocolOption)
Option:            EnterHoldMode          38 : error:  (10042 ProtocolOption)
Option:           EnterSniffMode          39 : error:  (10042 ProtocolOption)
Option:            ExitSniffMode          40 : error:  (10042 ProtocolOption)
Option:            EnterParkMode          41 : error:  (10042 ProtocolOption)
Option:             ExitParkMode          42 : error:  (10042 ProtocolOption)
Option:                  GetMode          43 : error:  (10042 ProtocolOption)
---- CLEAN EXIT ----

* WM
“setsockopt (Bluetooth)”
“getsockopt (Bluetooth)”

* Win32
“Bluetooth and Socket Options”

In the Microsoft Bluetooth API on Win32 (desktop Windows) there’s no simple way to get only the in-range-discoverable devices (as I’ve noted previously one can specify whether one wants remembered and/or unknown devices, but the ‘unknown-only’ result has had any remembered devices removed from it!)  This has prevented us from providing the DiscoverDevice(discoverableOnly=true) feature that we provide on every other platform.  We also haven’t been able to provide the ‘live’ discovery feature for in-range devices as provided through class BluetoothComponent.

I’ve recently implemented support for using the native Bluetooth events on this platform (I first implemented this code a long time ago, and see below for why I didn’t use it earlier).  So now that we have support for the events we can implement both of the features discussed above.  Briefly the events are provided through the RegisterDeviceNotifications API and the events are raised as Window Messages.  Thus we create a window on which to receive the messages, creating a new message-loop in most cases for the window, and call the API to enable the events.

Thus when ‘live’ discovery is requested via BluetoothComponent, we run a normal discovery process so that the Bluetooth hardware searches for devices, and we monitor the native events at the same time and use the resulting events to know which devices are in-range (and obviously in discoverable mode) and raise the respective BluetoothComponent events.

We also use this functionality to provided the “discoverableOnly” feature.  By monitoring the native events we make a list of all the devices that are range, and at the same time we run a discovery asking for all remembered and unknown devices — which make Windows return the union of all remembered and in-range devices — then we filter that list leaving only the devices in it that we saw ‘in-range’ events for.  Phew a lot of work for a simple thing. 😦

We should note however that this is useful only on Windows 7 (and perhaps Vista — I haven’t tested); it not useful on Windows XP.  The native events aren’t raised there correctly so we can’t use them to provide this functionality. 😦

This code is in the repository now, please test it and let me hear your feedback.  (Download the code from, build the FX2 project (only), and reference and use it with your application.  Test BluetoothClient.DiscoverDevices(discoverableOnly=true) and BluetoothComponent.DiscoverDevicesAsync(discoverableOnly=true).  One can see the native events directly with BluetoothWin32Events — currently it exposed the Radio-In-Range and Radio-Out-Of-Range event only, we don’t expose the HCI or L2CAP events etc.

Differences between Windows XP and 7

The Radio-In-Range event (on Window 7 at least) raises lots of apparently duplicate events, so we need to do some filtering to provide both functions.  On Windows XP however the native event is not useful for device discovery; when a discovery process is run we do not see Radio-In-Range events for all discoverable devices, it seems like there are no events for devices we’ve seen before.

It seem that one only reliably gets Radio-In-Range events when a connection is made to a particular remote device (e.g. for BluetoothClient.Connect or BluetoothDeviceInfo.GetServiceRecords).  So it seems that the event isn’t raised for discovered devices, but only for devices connected to.  During discovery Windows connects to the newly seen devices to then to get their Device Name — which isn’t transferred in the discovery process in earlier Bluetooth versions.  That’s why we do see events for new devices during discovery.

So that’s why this code has been “on the shelve” for a while.  When tested on Windows XP no useful events were raised.  With Windows 7 reliable events are raised during discovery so we can use it now!

As discussed previously BluetoothWin32Authentication didn’t work on Windows 7.  I have fixed it — changing it to use the new API on Windows 7 and the old API on older Win32 platforms.  See my document Bluetooth in Windows 7 for more details.

There have been questions if our library is supported on Windows 7 and to a lesser extent on Windows Vista.  I’ve completed a bank of testing and as far as I can see there are no issues with the core functionality.  I’ve tested BluetoothClient, BluetoothListener, and BluetoothSecurity and all seem to operate correctly.  This is not too unexpected as MSDN doesn’t list any changes to the main support.

MSDN does describe changes in the support for authentication, both for Windows 7 and for Windows Vista with the Feature Pack for Wirelss, and its not too unsurprising then that 32feet.NET class BluetoothWin32Authentication appears not to work on Windows 7.  At least for the two peer devices I tested with Windows XP and Windows Mobile 6.

So we need to investigate BluetoothRegisterForAuthenticationEx ( etc.  Let me know if this is affecting you.