zoukankan      html  css  js  c++  java
  • 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 节点,具体细节暂不做深入分析。

  • 相关阅读:
    Mysql分布式事务
    Mysql锁
    Mysql事务隔离级别
    java 资源监控
    Mysql子查询
    javaWeb四大域对象
    KVM 迁移
    KVM 虚拟化
    网络基础
    系统简单启动过程
  • 原文地址:https://www.cnblogs.com/GyForever1004/p/13755377.html
Copyright © 2011-2022 走看看