Monday, July 30, 2007

Bluetooth Service Publishing

The code for my forthcoming article on Microsoft Bluetooth Stack inquiry and discovery (remember, inquiry is for devices and discovery is for services) is ready. Apart from inquiring the available devices, it also discovers the existing services and lists the SDP record contents.

After being able to find a device with the service you want to consume, you can connect to that device using Windows Sockets. The reverse process involves publishing a service for other devices to consume and to serve requests using WS. Unfortunately the SDK has no means (nor explanation) on how to create an SDP record. Platform Builder users have the BTHNSCREATE sample to play with, but what about us, mere SDK users? Looks like Microsoft thinks this is something that should only concern people designing new Windows CE or Windows Mobile devices. I sincerely hope not and I'd rather think this is a design oversight. Why would I need such a thing?

Well, one of my plans is to provide P2P support for my products. If you look around the newsgroups you will see lots of people asking for an SDF-only synchronization package. This will require that two SDF files can "talk" to one another. I already support having a PC talk to an SDF file on a device, but what about having one device talk to another? A year ago I actually achieved this using WiFi, but this is not the correct protocol for ad-hoc P2P scenarios - Bluetooth is better. So if I want to support this scenario, I must publish a new Bluetooth service. Yes, of course I could use emulated COM ports and the code already supports serial communications. But I want the real thing: a dedicated service with its own GUID.

So how am I going to circumvent this? Most likely I will use Doug Boling's solution: use a templated SDP record and fill in the gaps (not nice, I know). What really bugs me is that the Widcomm stack makes it so much easier to publish a new service...

7 comments:

Smartymobile said...

Looks great if you need some help dont doubt!

ARNavPoch said...

Hi João Paulo,
There is some doc in the Mobile 6 SDK under:
'Windows Mobile Features (Native)'->'Networking - Wireless'->'Bluetooth'->'Bluetooth Application Development'->'Registering a Bluetooth Service'
cheers,
AR

João Paulo Figueira said...

Do you mean this link (http://msdn2.microsoft.com/en-us/library/aa916271.aspx)? It references the dreaded and missing BthNsCreate...

ARNavPoch said...

Yes it is the matching MSDN link.
The -not so difficult to tanslate- C# code from http://go.microsoft.com/?linkid=2913250 referenced in http://msdn2.microsoft.com/fr-fr/embedded/Aa714533.aspx may replace the missing BthNsCreate utility.
See GenerateSDPRecord(Guid serviceGuid, int channel) in 'Windows Embedded Source Tools'\BluetoothService.cs

BTW I have some WTL usage suggestions about your PPCDN article. Don't know if you are interested about.
cheers,
AR

João Paulo Figueira said...

Your WTL comments are most welcome! The code is just a sample and I used it to have a first go at WTL 8.0 on Windows Mobile and I loved it.

ARNavPoch said...

Hi João Paulo,

1 I compiled and ran (in Debug mode only) the sample on a WM2005 Smartphone device without problem. Noticed that the device search sometimes fails without apparent reason... 2.3 may be useful :)

2 WTL usage
2.1 The CMsBtDiscoveryView::PreTranslateMessage member sucks computing time without benefit. I suggest removal of the class from the project: in MsBtDiscoveryFrame.h change to
CTreeViewCtrl m_view;
and in MsBtDiscoveryFrame.cpp
BOOL CMsBtDiscoveryFrame:: PreTranslateMessage(MSG* pMsg)
{
return CFrameWindowImpl <CMsBtDiscoveryFrame> ::PreTranslateMessage(pMsg));
}
2.2 Your
MSG_WM_INITMENUPOPUP(OnInitMenuPopup)handler prevents the CUpdateUI chained message map to work. You might
a) remove the CUpdateUI inheritance in your frame class( not suggested)
b) use it by removing this member and it's message map entry, adding
UPDATE_ELEMENT(ID_MENU_DISCOVER, UPDUI_MENUPOPUP)
in the UPDATE_UI_MAP
and changing in CMsBtDiscoveryFrame.cpp to
BOOL CMsBtDiscoveryFrame:: OnIdle()
{
UIEnable(ID_MENU_DISCOVER, m_hSelItem && m_view.GetItemData(m_hSelItem));
return FALSE;
}
2.3 You could add a wait cursor during device inquiry:
// MsBtDiscoveryFrame.cpp : implementation of the CMsBtDiscoveryFrame class
//...
#include "stdafx.h"
#include <atlctrlx.h>
//...
LRESULT CMsBtDiscoveryFrame::OnInquire(...)
{
CWaitCursor wc;
//...

I am glad you love WTL. So do I!
cheers,
AR

Marcelo/Porks said...

Hi!

I've got the sample in VS2005 C# that you posted at
February 25, 2007

http://nativemobile.
blogspot.com/
2007_02_01_archive.html


The project compiles and I try to run at an iPAQ (With WIDCOMM Stack), but I have a little problem.

Your code have some dllimport (to access the bluetooth functions at wcbts.dll and msbts.dll)...
When your code invoke the functions of msbts.dll it works fine. But when the functions of wcbts.dll are invoked an exception appear saying that couldn't find the wcbts.dll (yes, I put the msbts.dll and wcbts.dll at the device's windows directory and at the program's directory too - \program file\enumerate)

The first function that is called is "Primeworks.Bluetooth.
Widcomm.WidcommStack.Version" to determine if the device have the MS or WIDCOMM Bluetooth Stack.

public static int Version
{
get
{
try
{
return WidcommAPI.WidcommStackPresent();
}
catch
{
return 0;
}
}
}


At this point an Exception occurs because can't find the wcbts.dll and so your code thinks that the device have the MS Bluetooth Stack.

I know that my English is very poor. But I think that you can understand the problem. Or not?

Excuse-me and Thanks!