你可以利用Microsoft Windows CE的串口模拟器在两个蓝牙设备间建立连接。串口模拟器处于蓝牙协议栈的顶层,在虚拟串口的基础上提供连接RFCOMM的通路。它没有暴露栈的接口,而是提供了一个API层来向远程蓝牙设备开放连接。
Microsoft® Windows® CE
的蓝牙实现允许你建立一个piconet。按照蓝牙规范,一个主设备可以同时与7个从设备连接。要了解更多关于piconet的信息,请参见Official Bluetooth Wireless Info Web site上的蓝牙核心规范。
当准备好蓝牙栈中的这一层时,就可以创建一个虚拟的服务端或客户端串口来接受或者发起RFCOMM连接。
在你在两个设备间建立连接之前,你必须先知道以下信息:
Ø
要连接得蓝牙设备的地址,以BT_ADDR类型存储(用于客户端端口)
Ø
RFCOMM
通道编号(1到31)
Ø
要分配给蓝牙操作的串口编号(0到9)
创建虚拟串口
1.
通过配置PORTEMUPortParams结构体来设置虚拟串口的属性。这个结构体储存了诸如通道和地址等蓝牙详细信息。
对于服务器端口,像下面的示例一样设置PORTEMUPortParams的成员。
PORTEMUPortParams pp;
memset (&pp, 0, sizeof(pp));
pp.flocal = TRUE;
pp.channel = channel & 0xff;
上面的示例中将flocal设为TRUE,使得服务器串口端口能接受传入的连接。服务器通道设置为channel的值。
注意
为了消除冲突,建议你在选择服务器通道时将channel设置为RFCOMM_CHANNEL_MULTIPLE(0xfe),让RFCOMM使用下一个可用的通道。
对于客户端端口,设置PORTEMUPortParams中的device、channel和uiportflags。
PORTEMUPortParams pp;
memset (&pp, 0, sizeof(pp));
pp.device = ba;
pp.channel = channel & 0xff;
pp.uiportflags = RFCOMM_PORT_FLAGS_REMOTE_DCB;
在上面的示例中,device赋值成一个存有远程设备地址的BT_ADDR型变量,将uiportflags设置为RFCOMM_PORT_FLAGS_REMOTE_DCB通过RFCOMM层初始化一个远程的链接。
如果不知道服务器通道,客户端可以在uuidService成员中指定服务器的UUID。在这种条件下,SDP查询将自动执行并返回目标通道编号。
2.
通过条用
RegisterDevice
函数来注册设备,如下例所示。
HANDLE h = RegisterDevice (L"COM", index, L"btd.dll", (DWORD)&pp);
上述示例将端口类型定义为COM,端口号、设备驱动DLL名称如参数所示。同时也在dwInfo参数位置传入在第一步创建的PORTEMUPortParams结构体的地址。RegisterDevice将虚拟串口注册到蓝牙协议栈上。
3.
创建一个字符串来储存串口的端口名称,如下例所示,你必须在名称后添加一个冒号。
WCHAR szComPort[30];
wsprintf (szComPort, L"COM%d:", index);
4.
通过调用
CreateFile
函数来打开串口。
HANDLE hCommPort = CreateFile (szComPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
对于客户端端口,只有在the device is open with read or write access by using CreateFile时才能建立物理连接,当第一个具有读或写权限的句柄关闭的时候服务器和客户端的端口的物理连接都将中止。
每个创建的虚拟串口最多能识别4个打开的句柄,每个句柄都维持其自身的连接和掩码。如果打开文件时的掩码是0,那么这个句柄就只能被WaitCommEvent所使用,而不能与ReadFile和WriteFile一起使用。
一旦串口创建好了,它就等价于一个真实的串口,能调用同样的API来操作它。
删除现有的虚拟串口
1.
调用
CloseHandle
函数,将
CreateFile
返回的句柄传给它,如下所示。
CloseHandle (hCommPort);
2.
要注销设备,调用
DeregisterDevice
函数并将
RegisterDevice
函数返回的句柄传给它,如下所示。
DeregisterDevice (h);
在端口模拟中使用“自动通道绑定”
1.
将PORTEMUPortParams中的channel 设置为RFCOMM_CHANNEL_MULTIPLE。
PORTEMUPortParams pp;
memset (&pp, 0, sizeof(pp));
pp.channel = RFCOMM_CHANNEL_MULTIPLE;
2.
使用RegisterDevice和CreateFile创建一个虚拟串口 。
3.
通过使用IOCTL来确定分配的RFCOMM通道。IOCTL_BLUETOOTH_GET_RFCOMM_CHANNEL.
DWORD port = 0;
DWORD dwSizeOut = 0;
HANDLE hFile;
if (!DeviceIoControl (hFile, IOCTL_BLUETOOTH_GET_RFCOMM_CHANNEL, NULL, 0, &port, sizeof(port), &dwSizeOut, NULL))
{
// Perform error handling
}