输入子系统带来的好处: 

统一了物理形态各异的相似的输入设备的处理功能。例如,各种鼠标,不论是PS/2、USB,还是蓝牙,都做同样的处理; 

简单的事件接口; 

简化了驱动程序  

input_dev结构体来描述input设备。驱动的 核心工作是向系统 报告按键,触摸屏,鼠标等 输入事件(event,用 input_event描述),驱动中不再需要关心文件操作接口,驱动报告的事件经过inputcore和eventhardler,最终到达用户空间 ​​​


驱动实现:

①分配input结构,并用set_bit()告诉input子系统需要报告那些事件,

②注册输入设备

③在有按键按下/抬起、或触摸屏被触摸/抬起/滑动等发生时(用中断或查询抓捕事件发生),用report_xxx()报告发生的事件及对应的键值/坐标状态


主要事件包括:

EV_KEY(案件事件),

EV_REL(相对值,比如光标移动,是相对最后一次位置的偏移),

EV_ABS(绝对值,比如触摸屏坐标)


  1. 常见典型事件
  2. EV_RST 0x00 Reset
  3. EV_KEY 0x01 按键
  4. EV_REL 0x02 相对坐标
  5. EV_ABS 0x03 绝对坐标
  6. EV_MSC 0x04 其它
  7. EV_LED 0x11 LED
  8. EV_SND 0x12 声音
  9. EV_REP 0x14 Repeat
  10. EV_FF 0x15 力反馈


报告EV_KEY,EV_REL,EV_ABS的函数分别是


  1. void input_report_key(struct input_dev *dev, unsigned int code, int value)
  2. (struct input_dev *dev, unsigned int code, int value)
  3. (struct input_dev *dev, unsigned int code, int value)


input_sync()用于事件同步,告诉事件接收者驱动已经发出了一个完整的报告。比如触摸屏案件事件


  1. void input_report_abs(input_dev,ABS_X,x);
  2. (input_dev,ABS_Y,y);
  3. (input_dev,ABS_PRESSURE,pres);//压力
  4. (input_dev);


注册,注销函数


  1. void input_register_device(struct input_dev *dev)
  2. (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. }