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 里面

12input_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 }
View Code

 

 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 }
View Code

 

 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 }
View Code

 

查看设备在系统中对应的节点信息(包括设备名称ID对应的handler等),例如usb鼠标对应的节点信息如下:

鼠标对应的事件驱动为mouse1 和event3,因为它和两个事件驱动匹配成功;

Event 节点里面存放的数据都是没有经过处理的原始数据流,通过命令$cat  event3可以看到鼠标输入的数据,但是mouse 节点里面的数据是经过处理的有结构的数据,直接对应鼠标点击或滑动的具体坐标,应用程序可以直接读取使用,可以通过命令$cat  mouse1可以看到鼠标输入的数据

 

 

posted on 2015-12-22 18:11  图灵之梦  阅读(1889)  评论(0编辑  收藏  举报