文章目录
-
- 一、内核中通用hid触摸驱动
- 二、probe过程剖析
-
- (1)hid_parse()函数
- (2)hid_hw_start()函数
- (3)hid_connect()函数
- 三、hid-multitouch.c应用场景
一、内核中通用hid触摸驱动
在linux内核中,为HID触摸面板实现了一个通用的驱动程序,位于/drivers/hid/hid-multitouch.c文件中。hid触摸驱动是以struct hid_driver
实现,首先定义一个描述hid触摸驱动的结构mt_driver
:
static struct hid_driver mt_driver = {
.name = "hid-multitouch",
.id_table = mt_devices,
.probe = mt_probe,
.remove = mt_remove,
.input_mapping = mt_input_mapping,
.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,
.suspend = pm_ptr(mt_suspend),
.reset_resume = pm_ptr(mt_reset_resume),
.resume = pm_ptr(mt_resume),
};
并实现了struct hid_driver
结构中关键的函数。接着使用module_hdi_driver()
将该驱动以模块方式构建:
module_hid_driver(mt_driver);
mt_devices
是一个truct hid_device_id
类型的数组,定义了hid备的设备参数,这些参数根据不同的厂家进行划分,划分的准则符合USB-HID协议,例如(
static const struct hid_device_id mt_devices[] = {
/* 3M panels */
{
.driver_data = MT_CLS_3M,
MT_USB_DEVICE(USB_VENDOR_ID_3M,
USB_DEVICE_ID_3M1968) },
{
.driver_data = MT_CLS_3M,
MT_USB_DEVICE(USB_VENDOR_ID_3M,
USB_DEVICE_ID_3M2256) },
{
.driver_data = MT_CLS_3M,
MT_USB_DEVICE(USB_VENDOR_ID_3M,
USB_DEVICE_ID_3M3266) },
/* Anton devices */
{
.driver_data = MT_CLS_EXPORT_ALL_INPUTS,
MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
USB_DEVICE_ID_ANTON_TOUCH_PAD) },
/* Asus T101HA */
{
.driver_data = MT_CLS_WIN_8_DISABLE_WAKEUP,
HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T101HA_KEYBOARD) },
/* 省略大量内容 */
}
上述元素实则是填充struct hid_device_id
的各个元素,HID_DEVICE
宏包装对.bus、.group、.vendor、.product
赋值操作:
在mt_devices
数组中,直接使用HID_DEVICE
以及衍生宏为其各个字段赋值。
二、probe过程剖析
从struct hid_driver mt_driver
可以知道mt_drvier的.probe
为mt_probe()
:
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret, i;
struct mt_device *td;
const struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
for (i = 0; mt_classes[i].name ; i++) {
if (id->driver_data == mt_classes[i].name) {
mtclass = &(mt_classes[i]);
break;
}
}
td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
if (!td) {
dev_err(&hdev->dev, "cannot allocate multitouch data\n");
return -ENOMEM;
}
td->hdev = hdev;
td->mtclass = *mtclass;
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
hid_set_drvdata(hdev,