Bluetooth between phone and PC
I’ve spent the last two days pulling out my hair, trying to get an application on my PC talking to my Bluetooth phone. If you have an inbuilt aversion of using Java for PC apps (like I do), there is preciously little documentation about this. Benhui shows how to do this particular thing between two Java applications (one running on the phone, and one on the PC). But if you don’t want to use Java on the PC, you’re pretty much stuck using sockets, and there is little documentation example material out there on the net.
So this is where this blog item comes in. I’m going to tell you how I did it, and share my source code.
This code uses the Microsoft Bluetooth Stack Socket API. You require WinXP SP2 for this, or — reputedly — WinXP SP1 with the Bluetooth stack downloaded and installed separately. Linux uses a completely different stack, obviously, with BlueZ and Affix being the most popular. These stacks also have socket APIs, so you may find the code presented here useful, but remember that this code is specifically for Windows.
On your PC, you will need some constants and structs from the MS Bluetooth SDK. I implemented these in Delphi, but you can use them equally well in any language.
I did this in Delphi so that’s the language these definitions will be in. You should be able to translate them easily into your programming language of choice:
// Bluetooth address family
AF_BTH: Integer = 32;
// Bluetooth SPP protocol
BTHPROTO_RFCOMM: Integer = $0003;
// Bluetooth service namespace
NS_BTH: Integer = 16;
// Bluetooth address struct
PSockAddrBth = ^TSockAddrBth;
_SOCKADDR_BTH = packed
record
addressFamily: U_SHORT;
btAddr: Int64;
serviceClassId: System.TGUID;
port: ULONG;
end;
TSockAddrBth = _SOCKADDR_BTH;
For Delphi, you’ll also need a copy of the winsock2 headers, because we require theWSASetService call, which is not available in the winsock header that is shipped with Delphi. You can find it via Google.
The (simplified) code goes like this:
// ———— Variables ———————–
var
s,t : TSocket;
sa, ta : TSockAddrBth;
sasize, tasize : Integer;
ca : CSAddr_Info;
qs : TWSAQuerySetA;
// ———— Code ————————-
// Create Bluetooth socket
s := socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if s = INVALID_SOCKET then RaiseLastOsError;
// Bind to listening address
sa.addressFamily := AF_BTH; // Address family
sa.btAddr := 0; // Address not set
sa.serviceClassId := NullGuid; // NullGuid is simply a GUID with all zeroes
sa.port := ULONG(-1); // Let OS select port
if bind(s, PSockAddr(@sa), sizeof(sa)) = SOCKET_ERROR then RaiseLastOsError;
// Get the bound name back, required for WSASetService
sasize := sizeof(sa);
if getsockname(s, @sa, sasize) = SOCKET_ERROR then RaiseLastOsError;
// We need to register this socket with WSASetService, so that it can be
// discovered by other Bluetooth devices. Filling
FillChar(ca, sizeof(ca), 0);
ca.LocalAddr.lpSockaddr := @sa;
ca.LocalAddr.iSockaddrLength := sizeof(sa);
ca.iSocketType := SOCK_STREAM;
ca.iProtocol := BTHPROTO_RFCOMM;
// Set service record
FillChar(qs, sizeof(qs), 0);
qs.dwSize := sizeof(qs);
qs.lpszServiceInstanceName := 'My service';
qs.lpServiceClassId := @MyGuid; // MyGuid is an application-specific GUID
qs.lpszComment := 'This is a test service';
qs.dwNameSpace := NS_BTH;
qs.dwNumberOfCsAddrs := 1;
qs.lpcsaBuffer := @ca;
// Register service
if WSASetService(@qs, RNRSERVICE_REGISTER, 0) = SOCKET_ERROR then RaiseLastOsError;
// Set-up is complete. You can now use the other socket functions,
// listen(), accept(), recv() and send() as usual.
On the mobile phone, you will need to write a J2ME application that uses the JSR-82 API, which is a standardized Java API for Bluetooth. To write the application, you will need to install 250MB’s worth of Java SDK (the J2SE SDK and J2ME SDK). I based my application on the BluetoothDemo application that is included with the J2ME.
Key points:
- Use the same GUID as MyGuid used above, as the only GUID in the UUID list when specifying a device search. You don’t need to use the attribute set used in the example.
- Make sure you are not connected to some other device (such as the Nokia PC Suite) when doing a device discovery — otherwise it won’t work.
If everything goes well, you should be able to discover the socket you just created (provided you have set your computer to discoverable in the Bluetooth settings), and connect to it. After that, you can exchange application-specific data in the same way as a regular socket/stream connection.
This post does not cover using Bluetooth standards, such as the OBEX protocol. I might post something about that when I figure it out, but since it doesn’t interest me very much at the moment, don’t count on it anytime soon.
Tags: bluetooth, delphi, java, mobile phone, Programming
This entry was posted on Monday, July 25th, 2005 at 4:45 pm and is filed under Programming. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.