科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件用C#开发.NET CF 蓝牙通信模块

用C#开发.NET CF 蓝牙通信模块

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在Windows Mobile软件开发中.Net正扮演着日益重要的角色。

作者:lornshrimp 来源:blog 2007年11月22日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
四. 监听服务

  监听服务调用的是非托管API WSASetService,其原型是

INT WSASetService(

LPWSAQUERYSET lpqsRegInfo,

WSAESETSERVICEOP essoperation,

DWORD dwControlFlags

);

  可以看到关键也是第一个参数,lpqsRegInfo,这也是一个struct,我们的包装方法与前面的发现设备采用的方法类似,做蓝牙通信时要注意其成员要如下设置:

lpqsRegInfo dwSize sizeof(WSAQUERYSET)
  lpszServiceInstanceName Not supported on Windows CE. Set to 0.
  lpServiceClassId Not supported on Windows CE. Set to 0.
  dwNameSpace NS_BTH.
  dwNumberOfCsAddrs Not supported on Windows CE. Set to 0.
  IpcsaBuffer Not supported on Windows CE. Set to 0.
  lpBlob Points to a BTHNS_SETBLOB structure, containing information about the service to be added.
  *
All other WSAQUERYSET fields are ignored.

  五. 连接

  我们知道,IrDA中连接远程服务是使用方法System.Net.Sockets.IrDAClient类中的Connect方法。而这个方法又是调用的Socket类中的Connect方法。而Socket类是一个比较抽象的类,它并不绑定某个具体的地址族、SocketType和protocolType,所以在实例化的时候,需要指定这三个参数。我们也知道,在IrDA中,这三个参数分别是AddressFamily.Irda, SocketType.Stream,和ProtocolType.IP,那么在蓝牙中这三个参数分别是什么呢?我们好像找不到。

  且慢,真是这样吗?

  我们知道在.net中,这三个参数都是枚举值,而枚举在默认情况下,你可以认为就是int值的替代表现。

  我们该如何知道这三个参数到底是什么呢?

  还是先看Socket类的Connect方法。

  我们查查有关资料,可以知道这个方法实际上是调用的一个非托管函数:

[DllImport("mscoree", EntryPoint="@339")]

public static extern int connect(int s, byte[] name, int namelen);

  也就是非托管的Socket API。

  我们看Windows CE 4.2的SDK,可以看到,在使用蓝牙进行连接的时候,需要使用WinSock扩展。我们还可以看到,在使用蓝牙进行连接的时候,三个参数分别应当是AF_BTH、SOCK_STREAM和BTHPROTO_RFCOMM,至于这三个参数分别代表什么,我们就要查看相关的头文件了。

  我们找到ws2bth.h头文件,可以看到AF_BTH代表十进制数32,而BTHPROTO_RFCOMM代表十六进制数0x0003,恰好和ProtocolType.Ggp代表的数值是一致的。所以,我们在实例化Socket时是这么写的:

new Socket((AddressFamily) 0x20, SocketType.Stream, ProtocolType.Ggp);

  Socket实例化出来了,其他的当然就都好说了,这里不再赘述。

  六. 蓝牙的安全设置

  蓝牙比红外多了安全方面的设置,所以就需要多一些代码来处理这些。具体也就不多说了,其实也就是一些非托管代码的包装调用,这些API在Btdrt.dll中:

  获取配对码请求:

[DllImport("Btdrt.dll", SetLastError=true)]

public static extern int BthGetPINRequest(byte[] pba);

  设置配对码:

[DllImport("btdrt.dll", SetLastError=true)]

public static extern int BthSetPIN(byte[] pba, int cPinLength, byte[] ppin);

  比较麻烦点的是配对,总共有三步操作:

  首先是创建ACL连接:

[DllImport("Btdrt.dll", SetLastError=true)]

public static extern int BthCreateACLConnection(byte[] pbt, ref ushort phandle);

  然后是配对码验证:

[DllImport("Btdrt.dll", SetLastError=true)]

public static extern int BthAuthenticate(byte[] pbt);

  然后一定要关闭连接:

[DllImport("Btdrt.dll", SetLastError=true)]

public static extern int BthCloseConnection(ushort handle);

  七. 设置蓝牙无线电状态

  我们知道,蓝牙无线电有打开、关闭、可发现三种状态,那么我们如何实现编程控制呢?

  我想这个一定大家都知道了,因为网上有很多关于这个的文章

  先写一个枚举:

public enum RadioMode
{
 Connectable = 1,
 Discoverable = 2,
 PowerOff = 0
}

  然后写一个函数调用非托管代码即可:

[DllImport("BthUtil.dll", SetLastError=true)]

public static extern int BthSetMode(RadioMode dwMode);

  获取无线电状态的话就用下面的函数:

[DllImport("BthUtil.dll", SetLastError=true)]

public static extern int BthGetMode(ref RadioMode dwMode);

  八. 已知的问题

  可能是因为蓝牙控制软件还没有实现标准化或者还是其他的问题,我们发现根据Windows CE 4.2 SDK 使用Winsock 扩展做的蓝牙开发有一个问题,而且不论是本文中所述的托管代码还是其他的非托管代码,只要是用的这种思路用Winsock 2做的开发都会存在这样一个问题,那就是不是在所有的Windows Mobile设备上都能正常运行。经过我的测试,我发现在很多使用另行开发的蓝牙控制软件的设备上,如联想ET560、华硕MyPAL A730上都无法运行,而在没有另行开发蓝牙控制软件的设备上是可以正常运行的,我不知道这是什么原因,初步推测可能是厂商另行开发的蓝牙控制软件屏蔽了微软的API的缘故,到底是不是这样,还得请高人指点。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章