Linux input子系统学习总结(三)----Input设备驱动
Input 设备驱动 ---操作硬件获取硬件寄存器中设备输入的数据,并把数据交给核心层;
一 、设备驱动的注册步骤:
1、分配一个struct input_dev :
struct input_dev *input_dev;
2、 初始化 input_dev 这个结构体 :
3、 注册这个input_dev 设备:
Input_register_device(dev);
4、 在input设备发生输入操作时,提交所发生的事件及键值、坐标等信息:
Input_report_abs()///报告X,y的坐标值
Input_report_key()///报告触摸屏的状态,是否被按下
Input_sync () ///表示提交一个完整的报告,这样linux内核就知道哪几个数据组合起来代表一个事件
二、Linux 中输入事件的类型:
EV_SYN 0X00 同步事件
EV_KEY 0X01 按键事件
EV_REL 0X02 相对坐标
EV_ABS 0X03 绝对坐标
....
三、关键程序片段(以USB鼠标为例:drivers\hid\usbhid\usbmouse.c)
1、 module_usb_driver(usb_mouse_driver);///系统启动时注册usb_mouse_driver (在usb架构中实现)
2、 usb_mouse_probe (设备初始化,usbmouse 属于usb设备,匹配成功后注册input设备)
3、 input_register_device(mouse->dev); 注册设备驱动
4、 input_attach_handler(dev, handler);///遍历所有的input_handler,并与 dev 进行匹配
usbmouse除了可以和evdev_handler 匹配成功,还和mousedev_handler 匹配成功,所以会分别调用evdev_handler的connect 函数创建event 节点和 mousedev_handler 的connect创建mouse节点
5、 input_match_device(handler, dev);///---->handler 和 device 进行真正的匹配(通过id_table 进行匹配)
6、 handler->connect(handler, dev, id);///匹配成功调用handler的connect 函数
7、 evdev_connect()///将创建 event(0、1、2…)节点
8、 mousedev_connect()///将创建 mouse(0、1、2…)节点
9、 mousedev_create()
10、cdev_init(&mousedev->cdev, &mousedev_fops);
11、usb_mouse_irq()///最终的数据在中断里面获取到,并保存到mouse –>data 里面
12、input_report_key\ input_report_rel\ input_sync ///报告按键信息
13、input_event
14、input_handle_event(dev, type, code, value)
15、input_pass_values(dev, dev->vals, dev->num_vals);
16 、input_to_handler(handle, vals, count);
17、handler->event(handle, v->type, v->code, v->value);
1 static struct usb_driver usb_mouse_driver = { 2 .name = "usbmouse", 3 .probe = usb_mouse_probe,///当有新的usbmouse加入时,系统会进行匹配,匹配成功后则调用probe函数,完成设备的初始化 4 .disconnect = usb_mouse_disconnect, 5 .id_table = usb_mouse_id_table, 6 }; 7 8 module_usb_driver(usb_mouse_driver);///系统启动时注册usb_mouse_driver
1 static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) 2 { 3 struct usb_device *dev = interface_to_usbdev(intf); 4 struct usb_host_interface *interface; 5 struct usb_endpoint_descriptor *endpoint; 6 struct usb_mouse *mouse; 7 struct input_dev *input_dev; 8 int pipe, maxp; 9 int error = -ENOMEM; 10 11 interface = intf->cur_altsetting; 12 13 if (interface->desc.bNumEndpoints != 1) 14 return -ENODEV; 15 16 endpoint = &interface->endpoint[0].desc; 17 if (!usb_endpoint_is_int_in(endpoint)) 18 return -ENODEV; 19 20 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 21 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 22 23 mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); 24 input_dev = input_allocate_device(); 25 if (!mouse || !input_dev) 26 goto fail1; 27 28 mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma); 29 if (!mouse->data) 30 goto fail1; 31 32 mouse->irq = usb_alloc_urb(0, GFP_KERNEL); 33 if (!mouse->irq) 34 goto fail2; 35 36 mouse->usbdev = dev; 37 mouse->dev = input_dev; 38 39 if (dev->manufacturer) 40 strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); 41 42 if (dev->product) { 43 if (dev->manufacturer) 44 strlcat(mouse->name, " ", sizeof(mouse->name)); 45 strlcat(mouse->name, dev->product, sizeof(mouse->name)); 46 } 47 48 if (!strlen(mouse->name)) 49 snprintf(mouse->name, sizeof(mouse->name), 50 "USB HIDBP Mouse %04x:%04x", 51 le16_to_cpu(dev->descriptor.idVendor), 52 le16_to_cpu(dev->descriptor.idProduct)); 53 54 usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); 55 strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); 56 57 input_dev->name = mouse->name; 58 input_dev->phys = mouse->phys; 59 usb_to_input_id(dev, &input_dev->id); 60 input_dev->dev.parent = &intf->dev; 61 62 ////evbit 关于设备支持事件类型的 bitmap 63 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); ///BIT_MASK 找到参数值所在的 bit位 64 input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | ///鼠标支持左键、右键、中键三个按键 65 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); 66 input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); ///REL_X REL_Y 表示鼠标的位置信息 67 input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) | ///在已有按键的基础上加上一个边键和一个而外的键 68 BIT_MASK(BTN_EXTRA); 69 input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);///给相对事件加上滚轮的事件 70 71 input_set_drvdata(input_dev, mouse); 72 73 input_dev->open = usb_mouse_open; 74 input_dev->close = usb_mouse_close; 75 76 usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, 77 (maxp > 8 ? 8 : maxp), 78 usb_mouse_irq, mouse, endpoint->bInterval); 79 mouse->irq->transfer_dma = mouse->data_dma; 80 mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 81 82 error = input_register_device(mouse->dev); 83 if (error) 84 goto fail3; 85 86 usb_set_intfdata(intf, mouse); 87 return 0; 88 89 fail3: 90 usb_free_urb(mouse->irq); 91 fail2: 92 usb_free_coherent(dev, 8, mouse->data, mouse->data_dma); 93 fail1: 94 input_free_device(input_dev); 95 kfree(mouse); 96 return error; 97 }
1 int input_register_device(struct input_dev *dev) 2 { 3 struct input_devres *devres = NULL; 4 struct input_handler *handler; 5 unsigned int packet_size; 6 const char *path; 7 int error; 8 9 if (dev->devres_managed) { 10 devres = devres_alloc(devm_input_device_unregister, 11 sizeof(struct input_devres), GFP_KERNEL); 12 if (!devres) 13 return -ENOMEM; 14 15 devres->input = dev; 16 } 17 18 /* Every input device generates EV_SYN/SYN_REPORT events. */ 19 __set_bit(EV_SYN, dev->evbit); 20 21 /* KEY_RESERVED is not supposed to be transmitted to userspace. */ 22 __clear_bit(KEY_RESERVED, dev->keybit); 23 24 /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ 25 input_cleanse_bitmasks(dev); 26 27 packet_size = input_estimate_events_per_packet(dev); 28 if (dev->hint_events_per_packet < packet_size) 29 dev->hint_events_per_packet = packet_size; 30 31 dev->max_vals = dev->hint_events_per_packet + 2; 32 dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); 33 if (!dev->vals) { 34 error = -ENOMEM; 35 goto err_devres_free; 36 } 37 38 /* 39 * If delay and period are pre-set by the driver, then autorepeating 40 * is handled by the driver itself and we don't do it in input.c. 41 */ 42 if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) { 43 dev->timer.data = (long) dev; 44 dev->timer.function = input_repeat_key; 45 dev->rep[REP_DELAY] = 250; 46 dev->rep[REP_PERIOD] = 33; 47 } 48 49 if (!dev->getkeycode) 50 dev->getkeycode = input_default_getkeycode; 51 52 if (!dev->setkeycode) 53 dev->setkeycode = input_default_setkeycode; 54 55 error = device_add(&dev->dev); 56 if (error) 57 goto err_free_vals; 58 59 path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); 60 pr_info("%s as %s\n", 61 dev->name ? dev->name : "Unspecified device", 62 path ? path : "N/A"); 63 kfree(path); 64 65 error = mutex_lock_interruptible(&input_mutex); 66 if (error) 67 goto err_device_del; 68 69 list_add_tail(&dev->node, &input_dev_list); 70 71 list_for_each_entry(handler, &input_handler_list, node) 72 input_attach_handler(dev, handler);////遍历所有的input_handler,并与 dev 进行匹配 73 74 input_wakeup_procfs_readers(); 75 76 mutex_unlock(&input_mutex); 77 78 if (dev->devres_managed) { 79 dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n", 80 __func__, dev_name(&dev->dev)); 81 devres_add(dev->dev.parent, devres); 82 } 83 return 0; 84 85 err_device_del: 86 device_del(&dev->dev); 87 err_free_vals: 88 kfree(dev->vals); 89 dev->vals = NULL; 90 err_devres_free: 91 devres_free(devres); 92 return error; 93 }
1 static int input_attach_handler(struct input_dev *dev, struct input_handler *handler) 2 { 3 const struct input_device_id *id; 4 int error; 5 6 id = input_match_device(handler, dev);////---->handler 和 device 进行真正的匹配 7 if (!id) 8 return -ENODEV; 9 10 error = handler->connect(handler, dev, id);///如果返回id不为空就执行handler 的 connect ---> 调用 evdev.c 的 connect 函数 11 if (error && error != -ENODEV) 12 pr_err("failed to attach handler %s to device %s, error: %d\n", 13 handler->name, kobject_name(&dev->dev.kobj), error); 14 15 return error; 16 }
查看设备在系统中对应的节点信息(包括设备名称ID对应的handler等),例如usb鼠标对应的节点信息如下:
鼠标对应的事件驱动为mouse1 和event3,因为它和两个事件驱动匹配成功;
Event 节点里面存放的数据都是没有经过处理的原始数据流,通过命令$cat event3可以看到鼠标输入的数据,但是mouse 节点里面的数据是经过处理的有结构的数据,直接对应鼠标点击或滑动的具体坐标,应用程序可以直接读取使用,可以通过命令$cat mouse1可以看到鼠标输入的数据