usb触摸屏研究

主要分析以下文件

一、文件介绍

drivers/input/touchscreen/usbtouchscreen.c

drivers/hid/hid-multitouch.c

drivers/hid/hid-input.c

drivers/hid/hid-core.c

driver/hid/usbhid/hid-core.c

drivers/input/touchscreen/usbtouchscreen.c经过打印Log这个文件没起作用,probe也没执行,貌似里面的代码都是单点触摸的

drivers/hid/hid-multitouch.c 多点usb触摸屏驱动,触点上报信息在这里面,

drivers/hid/hid-core.c注册hid类bus

driver/hid/usbhid/hid-core.c usb驱动,这个驱动在probe里面发现usb设备,收集相关信息并调用drivers/hid/hid-core.c提供的函数注册hid设备。

hid-generic.c这个函数没有probe函数,hid类的probe通常使用总线提供的probe来进行匹配。

hid-generic.c只能识别单点触摸屏,如果是多点触摸屏hid_have_special_driver在这个数组里面加入匹配的vid,pid,然后在hid-multitouch.c加入对应的驱动处理,例如之前的博客:https://blog.csdn.net/jlgcumt/article/details/106719391

打印log发现,usb触摸屏会通知配置两个驱动hid-generic和hid-multitouch,一个设备难道会同时match多个驱动吗?

hid-multitouch 0003:2A94:526D.0003: input,hidraw0: USB HID v1.11 Device [G2Touch Multi-Touch by G2TSP] on usb-xhci-hcd.0.auto-1.1.4/input0

hid-generic 0003:2A94:526D.0004: hiddev0,hidraw1: USB HID v1.11 Device [G2Touch Multi-Touch by G2TSP] on usb-xhci-hcd.0.auto-1.1.4/input1

 

二、流程分析

static struct hid_driver mt_driver = {

.name = "hid-multitouch",

.id_table = mt_devices,

.probe = mt_probe,       //这个函数是在hid-core.c里面的probe函数调用的,跟Linux里面的驱动模型匹配调用的还                                                           不一样

.remove = mt_remove,

.input_mapping = mt_input_mapping, //这几个函数会在hid-core.c的hidinput_connect里面调用,hidinput_connect的定义在

                                                              // hid-input.c里面

.input_mapped = mt_input_mapped,

.input_configured = mt_input_configured,

.feature_mapping = mt_feature_mapping,

.usage_table = mt_grabbed_usages,

.event = mt_event,

.report = mt_report,

#ifdef CONFIG_PM

.reset_resume = mt_reset_resume,

.resume = mt_resume,

#endif

};

module_hid_driver(mt_driver);

下面结构体函数使用地方在linux/hid.h 

static struct hid_ll_driver usb_hid_driver = {
    .parse = usbhid_parse,
    .start = usbhid_start,
    .stop = usbhid_stop,
    .open = usbhid_open,
    .close = usbhid_close,
    .power = usbhid_power,
    .request = usbhid_request,
    .wait = usbhid_wait_io,
    .raw_request = usbhid_raw_request,
    .output_report = usbhid_output_report,
    .idle = usbhid_idle,
};

 

三、下面这段来源于网络

传输驱动程序通常使用以下步骤向HID core注册新设备:
 struct hid_device *hid;
 int ret;

 hid = hid_allocate_device();
 if (IS_ERR(hid)) {
  ret = PTR_ERR(hid);
  goto err_<...>;
 }

 strlcpy(hid->name, <device-name-src>, 127);
 strlcpy(hid->phys, <device-phys-src>, 63);
 strlcpy(hid->uniq, <device-uniq-src>, 63);

 hid->ll_driver = &custom_ll_driver;
 hid->bus = <device-bus>;
 hid->vendor = <device-vendor>;
 hid->product = <device-product>;
 hid->version = <device-version>;
 hid->country = <device-country>;
 hid->dev.parent = <pointer-to-parent-device>;
 hid->driver_data = <transport-driver-data-field>;

 ret = hid_add_device(hid);
 if (ret)
  goto err_<...>;

一旦hid_add_device()被调用,HID core可以使用custom_ll_driver中提供的回调。

注销设备:

 hid_destroy_device(hid);

一旦hid_destory_device()返回,HID core将不可以再使用任何驱动回调。

hid_ll_driver operations
-----------------------------

有效的HID回调:
 - int (*start) (struct hid_device *hdev)
    HID驱动程序想要使用设备,就会调用。传输驱动程序可以选择在此回调中设置其设备。 然而,一般来说,设备在传输驱动程序将其注册到HID核心之前已经建立,因此这主要仅用于USB HID。

 - void (*stop) (struct hid_device *hdev)
    一旦使用完一个设备,就从HID设备驱动程序调用,传输驱动程序可以释放任何缓冲区并将设备取消初始化。但是,如果在设备上加载了另一个HID设备驱动程序,则可能再次调用->start().
   
 - int (*open) (struct hid_device *hdev)
如果对数据reports感兴趣,就从HID设备驱动程序调用。
通常,当用户空间没有打开任何输入API / etc时,设备驱动程序是
 对设备数据和传输驱动程序不感兴趣,可以将设备置于睡眠状态。
但是,一旦 - > open()被调用,传输驱动程序必须准备好进行I / O。
->open()是为每一个要打开HID设备的客户端嵌套调用。
 - void (*close) (struct hid_device *hdev)
    在->open()之后在HID设备驱动调用,它们将不再对设备reports感兴趣,(通常是用户空间关闭驱动程序的任何输入设备)。传输驱动可以将设备置于睡眠状态并终止所有I/O.

 - int (*parse) (struct hid_device *hdev)
   在->start()之后调用,传输驱动必须从设备读取HID report描述符,并通过  hid_parse_report()告知HID core。

 - int (*power) (struct hid_device *hdev, int level)
    HID core调用给PM提示。
 
 - void (*request) (struct hid_device *hdev, struct hid_report *report,
                    int reqtype)
在ctrl通道发送一个HID请求,“report”包含应发送的报告和“reqtype”请求类型, 请求类型可以是HID_REQ_SET_REPORT或HID_REQ_GET_REPORT.这个回调是可选的。 如果没有提供,HID core将按照HID规范组装原始报告,并通过 - > raw_request()回调发送它。

 - int (*wait) (struct hid_device *hdev)
    在再次调用->request()之前有HID core调用,如果一次只允许一个请求,传输驱动程序可以使用它来等待任何待处理的请求完成。

 - int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
                       __u8 *buf, size_t count, unsigned char rtype,
                       int reqtype)
    与 - > request()相同,但以报告为原始缓冲区。该请求应同步。传输驱动程序不能使用 - > wait()来完成这些请求。 此请求是强制性的,并且如果缺少,HID core将拒绝该设备。

 - int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
    通过intr通道发送原始输出报告。由一些需要高吞吐量的HID设备驱动程序用于内部通道的传出请求。 这不能导致SET_REPORT调用! 这必须在内部通道上实现为异步输出报告!

 - int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
   执行SET / GET_IDLE请求。

Data Path
--------------

传输驱动负责从I/O设备读取数据。它们必须自己处理与I/O有关的状态跟踪。HID core不实现协议握手或其它管理命令,这些命令由给定的HID传输规范来执行。
从设备读取的每个原始数据包都必须通过HID core进行hid_input_report().必须指定通道类型(intr或ctrl)并报告类型(输入/输出/功能)。在正常情况下,只有输入报告通过此API提供。

还必须通过API提供对GET_REPORT请求的响应->request()。对->raw_request()的响应是同步的,必须被传输驱动程序拦截,而不会传递给hid_input_report()。对SET_REPORT请求的确认不是HID core所关心的。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值