Wince蓝牙虚拟串口通信(server & client)

微软官网文章标题:Creating a Connection to a Remote Device Using a Virtual COM Port

很多内容参照此文章http://blog.csdn.net/jdcb2001/article/details/819550。

创建一个虚拟的服务端或客户端串口来接收或者发起RFCOMM连接。

在两个设备间建立连接之前,必须先知道以下信息:
Ø         要连接的蓝牙设备的地址,以BT_ADDR类型存储(用于客户端端口)
Ø         RFCOMM 通道编号(1到31)
Ø         要分配给蓝牙操作的串口编号(0到9)

(一)创建虚拟端口

1.       通过配置PORTEMUPortParams结构体来设置虚拟串口的属性。这个结构体储存了诸如通道和地址等蓝牙详细信息。
(1)对于服务器端口,像下面的示例一样设置PORTEMUPortParams的成员。
PORTEMUPortParams pp;
memset (&pp, 0, sizeof(pp));
pp.flocal = TRUE;
pp.channel = channel & 0xff;
上面的示例中将flocal设为TRUE,使得服务器串口端口能接收传入的连接。服务器通道设置为channel的值。
注意: 为了消除冲突,建议在选择服务器通道时将channel设置为RFCOMM_CHANNEL_MULTIPLE(0xfe),让RFCOMM使用下一个
可用的 通道。
(2)对于客户端端口,设置PORTEMUPortParams中的devicechanneluiportflags
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层初始化一个远程的链接。
其中最重要的是channel值,必须和服务器的通道一致。
很多文档说到:如果不知道服务器通道,客户端可以在uuidService成员中指定服务器的UUID。在这种条件下,SDP查询将自动
执行 并返回目标通道编号,但是我自己没有查到 uuidService 如何指定,但是找到如何查询到服务器使用的channel
以下代码为客服端如何确定channel ,请参照微软官网
Creating a Connection to a Remote Device Using Winsock
BOOL ConfirmBthChannel(BT_ADDR ullAddr, int& iChannel)
{
	BOOL   bRetValue = FALSE;
	SOCKET uSocket   = INVALID_SOCKET;

	SOCKADDR_BTH stSockBth = {0};
        WSADATA      stWsaData = {0};    

        if ( ERROR_SUCCESS == WSAStartup(MAKEWORD(2,2), &stWsaData) )
       {
                uSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
		if ( uSocket != INVALID_SOCKET )
		{
			memset (&stSockBth, 0, sizeof(stSockBth));
			stSockBth.btAddr = ullAddr; 
			stSockBth.addressFamily = AF_BT;
			
			for (iChannel = 1; iChannel < 32; iChannel++)
			{
				stSockBth.port = iChannel & 0xff;
				if (connect (uSocket, (SOCKADDR *)&stSockBth, sizeof(stSockBth))) 
				{
					continue;
				}
				else
				{
					break;
				}
			}
			closesocket (uSocket);
			WSACleanup();

			if (iChannel < 32)
			{
				bRetValue = TRUE;
			}
		}
		else
		{
			WSACleanup();
		}
    <span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return bRetValue;
}


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所使用,而不能与ReadFileWriteFile一起使用。
一旦串口创建好了,它就等价于一个真实的串口,能调用同样的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.         使用RegisterDeviceCreateFile创建一个虚拟串口 。
3. 3. 通过使用IOCTL来确定分配的RFCOMM通道。
      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
       }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值