Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103066
  • 博文数量: 31
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 12
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-26 17:44
文章分类
文章存档

2015年(31)

我的朋友

分类: LINUX

2015-11-01 19:00:50

原文地址:Linux输入子系统 作者:leon_yu

输入子系统是对多种不同类别的输入设备(如键盘、鼠标、跟踪球、操作杆、触摸屏、加速计和手写板)进行统一处理(inputcore)的驱动程序。

输入子系统带来的好处: 
统一了物理形态各异的相似的输入设备的处理功能。例如,各种鼠标,不论是PS/2、USB,还是蓝牙,都做同样的处理; 
②提供了给用户应用程序的简单的事件接口; 
③抽取出了输入驱动程序的通用部分,也简化了驱动程序   

在Linux内核中用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. void input_report_rel(struct input_dev *dev, unsigned int code, int value)
  3. void input_report_abs(struct input_dev *dev, unsigned int code, int value)

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

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

注册,注销函数

  1. void input_register_device(struct input_dev *dev)
  2. void input_unregister_device(struct input_dev *dev)

下面摘录自手头案例的部分代码(按键板输入,IIC接口)

  1. #define JG616L_I2C_ADDR    (0xc>>1)
  2. static struct jg616l_chip *g_jg616l_chip;
  3. struct key_val {
  4.     unsigned int usVal;
  5.     unsigned int ucKey;
  6. };

  7. static struct key_val gstKey[] = {
  8.     {0x02, KEY_1},
  9.     {0x03, KEY_2},
  10.     {0x04, KEY_3},
  11.     {0x05, KEY_4},
  12.     {0x06, KEY_5},
  13.     {0x07, KEY_6},
  14.     {0x08, KEY_7},
  15.     {0x09, KEY_8},
  16.     {0x0a, KEY_9},
  17.     {0x01, KEY_ESC},
  18.     {0x0b, KEY_0},
  19.     {0x1c, KEY_ENTER},
  20.     {0x1e, KEY_A},        //F1
  21.     {0x30, KEY_B},        //F2
  22.     {0x2e, KEY_C},        //F3
  23. };

  24. static void scan_max7349_key(unsigned long data)
  25. {
  26.     unsigned char ucVal, ucVal1, ucLoop, ucData[4];
  27.     struct i2c_client *client;

  28.     struct jg616l_chip *stMaxChip;
  29.     unsigned short usVal = 0, usGpio = 0;
  30.     stMaxChip = g_jg616l_chip;

  31.     int i = 0;
  32.     i2c_read_reg(gstI2cHandle, &usVal);//从I2C器件读到按键值,要是IO案件的话,要做消抖处理
  33.     if (0 == usVal)
  34.         return;
  35.     if (0x1ff >= usVal) {
  36.         for (i = 0; i < ARRAY_SIZE(gstKey); i++) {
  37.             if (usVal == gstKey[i].usVal) {
  38.                 input_report_key(stMaxChip->key_input,gstKey[i].ucKey, 1);
  39.                 input_sync(stMaxChip->key_input);//提交一个完整的input事件
  40.                 return;
  41.             }
  42.         }
  43.     }
  44. }

  45. static irqreturn_t jg616l_irq(int irq, void *handle)
  46. {
  47.     unsigned char ucData;
  48.     struct i2c_client *client;
  49.     unsigned long ulFlag;
  50.     struct jg616l_chip *stMaxChip = handle;

  51.     schedule_work(&stMaxChip->work);//中断函数里,启动scan_max7349_key函数

  52.     return IRQ_HANDLED;
  53. }

  54. static int jg616l_probe(struct i2c_client *client)
  55. {
  56.     struct input_dev *key_input;
  57.     int err = 0;
  58.     struct jg616l_chip *stMaxChip;
  59.     u32 key_val;

  60.     stMaxChip = kzalloc(sizeof(struct jg616l_chip), GFP_KERNEL);
  61.     if (NULL == stMaxChip) {
  62.         printk("Can't malloc memony!\r\n");
  63.         return -ENOMEM;
  64.     }

  65.     INIT_WORK(&stMaxChip->work, scan_max7349_key, NULL);
  66.     key_input = kzalloc(sizeof(struct input_dev), GFP_KERNEL);//分配input结构体

  67.     if (!key_input) {
  68.         printk("key input devices err!\r\n");
  69.         return -ENOMEM;
  70.     }
  71.     stMaxChip->key_input = key_input;
  72.      set_bit(EV_KEY,key_input->evbit);//向input注册事件类型

  73.     for (ucLoop = 0; ucLoop < ARRAY_SIZE(gstKey); ucLoop++) {
  74.         __set_bit(gstKey[ucLoop].ucKey, key_input->keybit);//注册按键值
  75.     }
  76.     //申请中断
  77.     if (request_irq(stMaxChip->jg616l_irq, jg616l_irq, 0, key_input->name,stMaxChip)) {
  78.         printk("request irq failed!\r\n");
  79.         err = -EBUSY;
  80.         free_irq(stMaxChip->jg616l_irq, stMaxChip);
  81.         goto err_free_irq;
  82.     }

  83.     input_register_device(key_input);//注册input设备

  84.     return err;
  85. err_free_irq:

  86.     kfree(stMaxChip->key_input);
  87.     kfree(stMaxChip);
  88.     return err;
  89. }

  90. static int jg616l_remove(struct i2c_client *client)
  91. {
  92.     struct jg616l_chip *stMaxChip;

  93.     input_unregister_device(stMaxChip->key_input);//注销input设备,释放相关资源
  94.     free_irq(stMaxChip->jg616l_irq, stMaxChip);
  95.     kfree(stMaxChip->key_input);
  96.     
  97.     return 0;
  98. }

阅读(1538) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~