输入子系统带来的好处:
统一了物理形态各异的相似的输入设备的处理功能。例如,各种鼠标,不论是PS/2、USB,还是蓝牙,都做同样的处理;
简单的事件接口;
简化了驱动程序
input_dev结构体来描述input设备。驱动的 核心工作是向系统 报告按键,触摸屏,鼠标等 输入事件(event,用 input_event描述),驱动中不再需要关心文件操作接口,驱动报告的事件经过inputcore和eventhardler,最终到达用户空间
驱动实现:
①分配input结构,并用set_bit()告诉input子系统需要报告那些事件,
②注册输入设备
③在有按键按下/抬起、或触摸屏被触摸/抬起/滑动等发生时(用中断或查询抓捕事件发生),用report_xxx()报告发生的事件及对应的键值/坐标状态
主要事件包括:
EV_KEY(案件事件),
EV_REL(相对值,比如光标移动,是相对最后一次位置的偏移),
EV_ABS(绝对值,比如触摸屏坐标)
- 常见典型事件
- EV_RST 0x00 Reset
- EV_KEY 0x01 按键
- EV_REL 0x02 相对坐标
- EV_ABS 0x03 绝对坐标
- EV_MSC 0x04 其它
- EV_LED 0x11 LED
- EV_SND 0x12 声音
- EV_REP 0x14 Repeat
- EV_FF 0x15 力反馈
报告EV_KEY,EV_REL,EV_ABS的函数分别是
- void input_report_key(struct input_dev *dev, unsigned int code, int value)
- (struct input_dev *dev, unsigned int code, int value)
- (struct input_dev *dev, unsigned int code, int value)
input_sync()用于事件同步,告诉事件接收者驱动已经发出了一个完整的报告。比如触摸屏案件事件
- void input_report_abs(input_dev,ABS_X,x);
- (input_dev,ABS_Y,y);
- (input_dev,ABS_PRESSURE,pres);//压力
- (input_dev);
注册,注销函数
- void input_register_device(struct input_dev *dev)
- (struct input_dev *dev)
手头案例的部分代码(按键板输入,IIC接口)
1. #define JG616L_I2C_ADDR (0xc>>1)
2. *g_jg616l_chip;
3. {
4. int usVal;
5. int ucKey;
6. };
7.
8. [] = {
9. {0x02, KEY_1},
10. {0x03, KEY_2},
11. {0x04, KEY_3},
12. {0x05, KEY_4},
13. {0x06, KEY_5},
14. {0x07, KEY_6},
15. {0x08, KEY_7},
16. {0x09, KEY_8},
17. {0x0a, KEY_9},
18. {0x01, KEY_ESC},
19. {0x0b, KEY_0},
20. {0x1c, KEY_ENTER},
21. {0x1e, KEY_A}, //F1
22. {0x30, KEY_B}, //F2
23. {0x2e, KEY_C}, //F3
24. };
25.
26. (unsigned long data)
27. {
28. , ucVal1, ucLoop, ucData[4];
29. *client;
30.
31. *stMaxChip;
32. = 0, usGpio = 0;
33. = g_jg616l_chip;
34.
35. int i = 0;
36. (gstI2cHandle, &usVal);//从I2C器件读到按键值,要是IO案件的话,要做消抖处理
37. if (0 == usVal)
38. ;
39. if (0x1ff >= usVal) {
40. for (i = 0; i < ARRAY_SIZE(gstKey); i++) {
41. if (usVal == gstKey[i].usVal) {
42. (stMaxChip->key_input,gstKey[i].ucKey, 1);
43. (stMaxChip->key_input);//提交一个完整的input事件
44. ;
45. }
46. }
47. }
48. }
49.
50. (int irq, void *handle)
51. {
52. ;
53. *client;
54. ;
55. *stMaxChip = handle;
56.
57. (&stMaxChip->work);//中断函数里,启动scan_max7349_key函数
58.
59. ;
60. }
61.
62. int jg616l_probe(struct i2c_client *client)
63. {
64. *key_input;
65. int err = 0;
66. *stMaxChip;
67. ;
68.
69. = kzalloc(sizeof(struct jg616l_chip), GFP_KERNEL);
70. if (NULL == stMaxChip) {
71. ("Can't malloc memony!\r\n");
72. -ENOMEM;
73. }
74.
75. (&stMaxChip->work, scan_max7349_key, NULL);
76. = kzalloc(sizeof(struct input_dev), GFP_KERNEL);//分配input结构体
77.
78. if (!key_input) {
79. ("key input devices err!\r\n");
80. -ENOMEM;
81. }
82. ->key_input = key_input;
83. //向input注册事件类型
84.
85. for (ucLoop = 0; ucLoop < ARRAY_SIZE(gstKey); ucLoop++) {
86. (gstKey[ucLoop].ucKey, key_input->keybit);//注册按键值
87. }
88. //申请中断
89. if (request_irq(stMaxChip->jg616l_irq, jg616l_irq, 0, key_input->name,stMaxChip)) {
90. ("request irq failed!\r\n");
91. err = -EBUSY;
92. (stMaxChip->jg616l_irq, stMaxChip);
93. ;
94. }
95.
96. (key_input);//注册input设备
97.
98. err;
99. :
100.
101. (stMaxChip->key_input);
102. (stMaxChip);
103. err;
104. }
105.
106. int jg616l_remove(struct i2c_client *client)
107. {
108. *stMaxChip;
109.
110. (stMaxChip->key_input);//注销input设备,释放相关资源
111. (stMaxChip->jg616l_irq, stMaxChip);
112. (stMaxChip->key_input);
113.
114. ;
115. }