1.

蓝牙模块在系统进入睡眠的时候,如果对蓝牙模块下电(也即被GPG2输出低电平),那么唤醒后蓝牙驱动不能正常工作,此时用WINCE系统控制面板下自动的蓝牙应用程序搜索蓝牙设备的时候,提示:“Bluetooth硬件错误 10050(控制器不存在)”,这种情况下,除非重启,否则蓝牙驱动不能正常工作。

 

 

2.

增加串口调试信息,在睡眠时系统对蓝牙模块下电的情况下,唤醒后蓝牙驱动部分输出串口信息如下:

kandi HCI_CloseConnection() 1111
<CloseConnection> Done. kandi HCI_CloseConnection() 33333
DllMain() detach---><CloseConnection> Done. <CloseConnection> Done. ~BcspCommunication()---><CloseConnection> Done. <CloseConnection> Done.

可以看出唤醒后蓝牙驱动显示调用bt\hci_bcsp.cpp文件下HCI_CloseConnection函数,然后以DLL_PROCESS_DETACH这个参数调用DllMain函数,如果要执行这些动作,也应该是在进入睡眠前应该先被调用的。说明在对蓝牙模块驱动之前,应该对蓝牙模块先卸掉或是停止WINCE自带的蓝牙协议栈(体现),然后再唤醒的时候,应该要加载或是开启蓝牙协议栈(应该理解为初始化蓝牙协议栈可能更为合适)。

 

这里有几点需要说明:

⑴ HCI_CloseConnection函数

此函数主要功能是关闭蓝牙协议栈和HCI(host controller interface)传输之间的连接,调用这个函数将会解锁读和写,硬件未初始化,释放所有资源空间包括缓冲区。如果驱动在DLL中,当函数返回时会被卸载。

 

⑵HCI_OpenConnection()

此函数主要功能是在蓝牙协议栈中的HCI层和蓝牙硬件建立连接,返回成功代表传输启动,这种情况发生时,栈会调用HCI_ReadHciParamerters函数。这个函数是用来开启硬件,初始化硬件,和硬件建立连接。返回true代表成功建立连接。这是个阻塞函数。

 

⑶蓝牙协议栈对应的组件

android蓝牙休眠 蓝牙里面的电池休眠_android蓝牙休眠

图1 蓝牙协议栈对应的组件

⑷蓝牙传输文件需要OBEX组件

android蓝牙休眠 蓝牙里面的电池休眠_初始化_02


图2 蓝牙传输文件需要的组件

3.

根据上面的分析,那么如何停止蓝牙服务和开启蓝牙服务,上网百度,功夫不负有心人,正在陷入困境的时候,找到了解决这个问题的办法,就是分别已IOCTL_SERVICE_STOP和IOCTL_SERVICE_START为控制码来调用DeviceIoControl函数,具体代码见drivers\cmc\CmcPDD.cpp下的BTDEnable函数,这就是卸载和加载蓝牙协议栈服务的控制代码:

android蓝牙休眠 蓝牙里面的电池休眠_android蓝牙休眠_03


图3 控制蓝牙协议栈服务

找到了解决这个问题的办法,那么在睡眠之间在哪里关闭蓝牙协议栈的服务呢?在唤醒的过程中,又该在哪里加载蓝牙协议栈的服务呢?经过不断尝试和测试,总结出来的原则就是:在睡眠之前,应尽快卸载蓝牙协议栈服务,而在唤醒过程,应靠后一点再加载蓝牙协议栈的服务之后,而且不适合在xxx_PowerDown和xxx_PowerUp函数中卸载或是加载,因为这种类型的函数,对于睡眠过程是比较接近处理器进入睡眠的;对于唤醒过程,也比较接近处理器刚唤醒时的动作。为了便于管理和控制通信模块,我们增加了cmc驱动,我们选在CMC_IOControl函数中处理,如下所示:

android蓝牙休眠 蓝牙里面的电池休眠_协议栈_04


图4 CMC_IOControl函数控制蓝牙协议栈服务加载和卸载