Android BLE为例分析内核UHID

一、Android BLE HID 大致框架

开局一张图,文章全靠编:

以 Android BLE 架构简单分析下 UHID 机制,图中①②不探索,毕竟 bluedroid 这个东西也不是很快就能分析透彻的。

二、分析开始

在Android连接中蓝牙设备后,会向内核 UHID 发送 creat 消息,中间的桥梁是 /dev/uhid 节点。

UHID驱动会调用到 uhid_dev_create 来初始化bus、vendor、product等信息,并拷贝 report 报文(这个东西很重要,用来描述BLE设备都支持什么操作,例如:INPUT)

进而调用到 uhid_dev_create2 ,期间会 alloc hid 设备,并在最后利用工作队列中将 hid device 注册到 hid bus 当中。

有了 device,和对应driver匹配之后才能有后戏,那么它来了 hid_generic ,ANY_BUS、ANY_ID,来吧,它是个 device 就能匹配。

熟悉的总线设备驱动模型,那么之后将调用 bus 的 probe 回调,它是 hid_device_probe ,插入一段简短的代码凑字。

 1 static int hid_device_probe(struct device *dev)
 2 {
 3     struct hid_driver *hdrv = to_hid_driver(dev->driver);
 4     struct hid_device *hdev = to_hid_device(dev);
 5     ...
 6     if (!hdev->driver) {
 7         id = hid_match_device(hdev, hdrv);
 8         if (id == NULL) {
 9             ret = -ENODEV;
10             goto unlock;
11         }
12 
13         hdev->driver = hdrv;
14         if (hdrv->probe) {
15             ret = hdrv->probe(hdev, id);
16         } else { /* default probe */
17             ret = hid_open_report(hdev);
18             if (!ret)
19                 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
20         }
21         if (ret) {
22             hid_close_report(hdev);
23             hdev->driver = NULL;
24         }
25     }
26     ...  
27 }

 hid_open_report 用来解析我们前面说的比较重要的那个 report 报文,适配 HID 设备的所有 capability,它也会检查 report 是否完成通过 COLLECTION 与 END_COLLECTION 的匹配,检查不通过后就没有下方了。

 hid_hw_start 是创建给 Android 传送信息的 event 通道,

 1 int hid_hw_start(struct hid_device *hdev, unsigned int connect_mask)
 2 {
 3     int error;
 4 
 5     error = hdev->ll_driver->start(hdev);
 6     if (error)
 7         return error;
 8 
 9     if (connect_mask) {
10         error = hid_connect(hdev, connect_mask);
11         if (error) {
12             hdev->ll_driver->stop(hdev);
13             return error;
14         }
15     }
16 
17     return 0;
18 }

这里的 ll_driver 指的是 uhid_hid_driver ,ll_driver 会发回 UHID_START 消息通知内核已准备好。hid 是真正的主角,在其内部注册了 input_device 和 hidraw 字符设备,至此所有的准备工作已就绪。

创建 OK,内核会有类似这样的打印:

1 [ 0000.0000] input: BLE Remote as /devices/virtual/misc/uhid/0006:0095:0001.0006/input/input9
2 [ 0000.0000] hid-generic 0006:0095:0001.0006: input,hidraw3: BLUETOOTH HID v1.11 Device [BLE Remote] on

那再来看看 Bluedroid 是怎么将解析后的数据信息发到 event 的。

Bluedroid 中会调用 bta_hh_co_write 通过 UHID_INPUT 来向内核发送 HID 信息,进而内核调用到 uhid_dev_input 来将上层发过来的 HID 信息写入到 event 节点和 hidraw 节点,具体细节暂不做深入分析。

原文地址:https://www.cnblogs.com/GyForever1004/p/13755377.html