Client


Widcomm/Broadcom produces different SDKs for their different platforms, but the PDF documentation files in the the various SDKs looks very similar, so I printed the Windows CE/WM version and worked from that.  Recently however I was reading from the Win32 version and found this statement:

“An additional implication of this guideline is that derived functions must not call back into the stack with another SDK API.  Any SDK API that must be called as a result of a callback from the stack must be executed from the application main thread, not the callback execution context.”

So in a Widcomm-callback handler we shouldn’t call back into the stack. 😦  In the current code we do that — for instance when we have get pending data to send, and that stack sends us a ‘finished sending’ event, we call Write from there.  Maybe its this that causes the “gets stuck sending” problem

Anyway I’ve got some work in process to enable this, being tracked by bug 25410.

 I intend just to

  1. Mark threads with a flag noting whether they’re from a Widcomm callback or not.
  2. Any time I make a call back into the stack, check that flag, and if set force the call onto another thread, e.g. via a Delegate.BeginInvoke/EndInvoke pair.

Other much more complex mechanisms are available, e.g. one I tried earlier was to action all Widcomm-callbacks on a new thread, but that was very slow.

Note however that the documentation says “from the application main thread”.  As a library, we can’t know the application’s main thread.  We could though create a single thread and pass all calls to the Widcomm API via it, but is that really required??  It would make things much more complex…

On the Widcomm stack if you call connect on two (or more) BluetoothClients in close succession the the latter connect might fail with NotSupportedException(“Currently support only one concurrent Service Lookup operation.”).  This occurs because Widcomm supports only one SDP lookup at a time, which seems very restrictive.  This situation is of course much more likely to happen if the first device is not in range, in that case the Widcomm SDP lookup takes thirty seconds to timeout and return failure.  This also affects BluetoothDeviceInfo.GetServiceRecords which uses the same service lookup infrastructure.  I has some people asking how they can workaround this.

So there’s multiple ways we can think of handling this:

  1. Do nothing
    Hope that multiple connects will be rare, or the caller will have to retry a connect later if it fails due to this.
  2. Serialise the SDP lookups internally
    Rather than having the caller ensure there’s only one outstanding connect we could internally keep a queue of SDP lookup requests and carry them out as each completes.  The problem with this is that the delay for the queued items could quickly increase if one or more of the target devices are not in range, and then the developer/user will get confused as to why the connects are taking an age to complete.
  3. Find some way to detect if a device is not in range before starting the SDP query
    There are two functions available on later versions of the stack:  CBtIf::IsRemoteDeviceConnected and CBtIf::IsRemoteDevicePresent, they’re present on BTW in 5.0.1.300 and  5.0.1.1000 respectively, and on WCE on 1.7.1.2700 (both).  If they work well we could use these before calling the SDP lookup and thus allow multiple operations…
    We firstly want the results to be correct; in particular that we don’t get false negatives — that is that they don’t report the device as not in range if SDP lookup would find it in range.  Secondly we need these methods to be reasonably fast[2].  And ideally that they can be called for multiple targets at the same time!  Of the last two we need at least one to be the case; if they are quick but can’t be used concurrently we can serialise them if they can only be called for one device at a time.

The last is obviously the best solution, we could even combine it with number 2 if required if they are reasonably quick.

Unfortunately I don’t have a device that supports these functions[2].  So I need your feedback.  I’ve implemented support for these methods in the code in the repository.  They’re accessible at the top level in WidcommPlaying.FindIfPresentOrConnected.  I’ve created one test option WidcommIsPresentConnected in the ConsoleMenuTesting/DeviceMenuTesting programs to test this, which calls the above function once.  We’ll need more to test the concurrent behaviour.

____

[1] The  WCE/Windows Mobile version of the stack seems to support one SDP lookup per remote device.  That’s much more useful than the restriction on Win32.  However it doesn’t seem worth complicating the code to support the two different restrictions when its more likely that multiple connects would be used on the Win32 where they aren’t supported.

[2]I expect that IsRemoteDeviceConnected will be fast, it should only be a lookup in the stack state to see whether there’s a connection to the specified device.  I wonder how long IsRemoteDevicePresent will take to timeout if the specified device is not present however…

[3] I have an iPAQ with 1.7.1.1424 and a desktop dongle with version 3.0.1.912.  Can someone recommend me a desktop dongle that comes with a recent Widcomm version?  Or how I can find a cheap PPC with a later stack version.

FindIfPresentOrConnectedFindIfPresentOrConnected