一. 开发环境
硬件: HTC3238+WM6.1
SDK: STANDARDSDK_500
二. 目标
学习winsock方式的蓝牙应用开发
三. 背景介绍
In Microsoft® Windows® CE, the primary way an application can use Bluetooth is through the Winsock interface, which exposes RFCOMM protocol. Virtual COM ports are also exposed, but this interface is designed to be enabled under existing OS services such as UNIMODEM, GPS, or terminal emulators. By using various protocols and profiles, Bluetooth can be implemented to perform the following tasks:
- Connect to a modem through a cellular phone.
- Connect to a local area network (LAN) access point.
- Enable object exchange and synchronization using the Object Exchange Protocol (OBEX).
- Use wireless headset and hands-free devices to handle calls on a cellular phone.
- Transfer data from a desktop computer to a mobile device over a wireless connection.
For more information about Bluetooth technology, see this Official Bluetooth Wireless Info Web site.
摘自:http://msdn.microsoft.com/en-us/library/ms847082.aspx
从上面的文字中可以看出在WM平台上,有两种方式可以操作蓝牙:Winsock和Virtual COM ports.这里我采用了Winsock方式.
四. 基本操作流程
1. 服务端
按MSDN上的说法,蓝牙的WINSOCK操作方式和基本的socket-based差不多.
SOCKET s = socket(...);
bind(s, ...);//绑定到一个RFCOMM通道上,exports the SDP record advertising this channellisten(s, ...);
for(; ;)
{
SOCKET s2= accept(s, ...);
SpinThreadsForConnection(s2);
}示例代码:
//Function: OpenServerConnection
//Purpose: Opens a server socket for listening. Registers the service. Creates a thread, ReadThread for reading incoming messages.
//Input: The SDP record of the service to register, size of the SDP record, channel offset in the record, pointer to the UI function that displays the messages in the UI
//Return: If error occurs, returns the appropriate WSAGetLastError, otherwise returns zero.
//注:调用语句是iRetVal=objBthUtils.OpenServerConnection(rgbSdpRecord, SDP_RECORD_SIZE, SDP_CHANNEL_OFFSET, DisplayMessage);
//rgbSdpRecord,SDP_RECORD_SIZE, SDP_CHANNEL_OFFSET是事先由bthnscreate.exe生成的,bthnscreate.exe的源码在D:/WINCE500/PUBLIC/COMMON/SDK/SAMPLES/BLUETOOTH/BTHNSCREATE,这是PB5的安装目录int BthUtils::OpenServerConnection(BYTE *rgbSdpRecord, int cSdpRecord, int iChannelOffset, void (*funcPtr)(WCHAR *))
{
int iNameLen=0;
if(m_socketServer==INVALID_SOCKET)
{
m_socketServer = socket (AF_BT, SOCK_STREAM, BTHPROTO_RFCOMM);
if (m_socketServer == INVALID_SOCKET)
{
return WSAGetLastError ();
}
SOCKADDR_BTH sa;
memset (&sa, 0, sizeof(sa));
sa.addressFamily = AF_BT;
sa.port = 0;
if (bind (m_socketServer, (SOCKADDR *)&sa, sizeof(sa)))
{
return WSAGetLastError ();
}
iNameLen = sizeof(sa);
if (getsockname(m_socketServer, (SOCKADDR *)&sa, &iNameLen))
{
return WSAGetLastError ();
}if(RegisterService(rgbSdpRecord, cSdpRecord, iChannelOffset, (UCHAR)sa.port)!=0)
return WSAGetLastError();if (listen (m_socketServer, SOMAXCONN))
{
return WSAGetLastError ();
}