首页 > 系统服务 > 详细

2linux输入子系统-按键驱动程序

时间:2019-08-28 16:53:58      阅读:87      评论:0      收藏:0      [点我收藏+]

1实验目的和内容

实验目的:(1)通过实验,了解在linux输入子系统框架中编写输入设备驱动程序的步骤;

2)体会与之前章节讲的编写驱动的方法之间的差异。

实验内容:在linux输入子系统中编写按键驱动程序,按键S2S3S4S5按下时,代表 "L"、"S"、"ENTER"、"LEFTSHIFT"等操作功能。

2知识回顾

前面章节讲到的自己编写驱动的方法,主要包含以下步骤:

  1. 定义file_operation结构体,实现openreadwrite等接口函数;
  2. 调用register_chrdev函数注册设备;
  3. 定义入口函数;
  4. 定义出口函数。

上一章节分析的输入子系统的结构,共分为三层:Input driver、InputCore、EventHandler。其中Input driver层实现对硬件设备的读写访问,中断设置,并将硬件产生的事件转换为InputCore层定义的规范提交给EventHandler。因此,是本节编写驱动程序时需要重点实现的部分。InputCore层,也就是我们的drivers/input/input.c文件,内核已经提供了完整的代码程序,不用再做修改。EventHandler层主要是用于支持输入设备与用户空间之间的交互,linux内核已经自带了一部分事件处理器,可支持大部分的输入设备,例如:Evdev.c、mousedev.c等。其中Evdev.c中的evdev_handler的id_table:evdev_ids定义如下:

技术分享图片

可以支持所有的输入设备。所以本节实验也不需要对EventHandler层的代码再做任何修改。那么接下来将重点放到Input driver层。

3实验原理简介

Input driver设备驱动层是与硬件紧密相关的,其主要工作:向InputCore报告同步、按键等事件,让驱动事件经由inputcore和Eventhandler到达用户空间。

input_dev结构体

  1. struct?input_dev?{??
  2. ?? ?
  3. ????void?*private;??
  4. ?? ?
  5. ????const?char?*name;??//输入设备的名称
  6. ????const?char?*phys;??//输入设备节点的名称
  7. ????const?char?*uniq;? //输入设备的唯一ID号,类似于mac地址?
  8. ????struct?input_id?id;?//?输入设备的唯一标识,用于和eventhandler层进行匹配
  9. ?? ?
  10. ????unsigned?long?evbit[NBITS(EV_MAX)];??//设备支持的事件类型
  11. ????unsigned?long?keybit[NBITS(KEY_MAX)];??//设备支持的按键类型
  12. ????unsigned?long?relbit[NBITS(REL_MAX)];??//可产生的相对位移事件
  13. ????unsigned?long?absbit[NBITS(ABS_MAX)];??
  14. ????unsigned?long?mscbit[NBITS(MSC_MAX)];??
  15. ????unsigned?long?ledbit[NBITS(LED_MAX)];??
  16. ????unsigned?long?sndbit[NBITS(SND_MAX)];??
  17. ????unsigned?long?ffbit[NBITS(FF_MAX)];??
  18. ????unsigned?long?swbit[NBITS(SW_MAX)];??
  19. ?? ?
  20. ????unsigned?int?keycodemax;??
  21. ????unsigned?int?keycodesize;??
  22. ????void?*keycode;??
  23. ????????......??
  24. ?? ?
  25. ????struct?list_head????h_list;??
  26. ????struct?list_head????node;??
  27. };??

驱动层的主要函数接口如下表:

接口

功能

struct input_dev *input_allocate_device(void)

为一个新的输入设备申请空间

static inline void set_bit(int nr, volatile void * addr)

设置设备支持哪些事件

eg: set_bit(EV_KEY, buttons_dev->evbit);

int input_register_device(struct input_dev *dev)

注册输入设备

void input_unregister_device(struct input_dev *dev)

卸载输入设备

void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

报告新的输入事件

dev:要上报的输入设备

type:上报的事件类型

code:上报的事件code

value:上报的事件值

static inline void input_sync(struct input_dev *dev)

报告同步事件,通知InputCore层子系统input_event报告结束

结合上述函数接口,我们需要在驱动层完成如下工作:分配、设置、注册一个结构体,并完成硬件相关的操作。

按照驱动的要求,定义模块的入口函数和出口函数。

技术分享图片

编写入口函数buttons_init

  1. int?buttons_init(void)??
  2. {??
  3. ????int?i,?error;??
  4. ?????? ?
  5. ????/*?1、分配一个input_dev空间*/??
  6. ????buttons_dev?=?input_allocate_device();??
  7. ????if?(!buttons_dev)??
  8. ????????return?-ENOMEM;??
  9. ?????? ?
  10. ????/*?2、设置input_dev结构体?*/??
  11. ????/*?2.1buttons_dev可以产生按键类的事件?*/??
  12. ????set_bit(EV_KEY,?buttons_dev->evbit);??
  13. ????set_bit(EV_REP,?buttons_dev->evbit);??
  14. ?????? ?
  15. ????/*?2.2?能产生按键类事件中的哪一类事件:L?S?ENTER?LEFTSHIFT?*/??
  16. ????set_bit(KEY_L,?????????buttons_dev->keybit);??
  17. ????set_bit(KEY_S,?????????buttons_dev->keybit);??
  18. ????set_bit(KEY_ENTER,?????buttons_dev->keybit);??
  19. ????set_bit(KEY_LEFTSHIFT,?buttons_dev->keybit);??
  20. ?????? ?
  21. ????/*?3、注册buttons_dev?*/?????
  22. ????error?=?input_register_device(buttons_dev);??
  23. ????if?(error)?{??
  24. ????????printk(KERN_ERR?"Unable?to?register?buttons_dev\n");??
  25. ????????goto?fail;??
  26. ????}??
  27. ?? ?
  28. ????/*?4、硬件相关的配置?*/??
  29. ????init_timer(&button_timer);??
  30. ????button_timer.function?=?button_timer_func;??
  31. ????add_timer(&button_timer);??
  32. ?????? ?
  33. ????for(i=0;?i<4;?i++)??
  34. ????{??
  35. ????????request_irq(pins_desc[i].irq,?buttons_irq,?IRQT_BOTHEDGE,???
  36. ????????????????????pins_desc[i].devname,?&pins_desc[i]);??
  37. ????}??
  38. ?????? ?
  39. ????return?0;??
  40. ????fail:??
  41. ????????for(i=0;?i<4;?i++)??
  42. ????????????free_irq(pins_desc[i].irq,?&pins_desc[i]);??
  43. ????????input_free_device(buttons_dev);??
  44. }??
    1. 6行,为按键输入设备buttons_dev申请空间;
    2. 12行,设置buttons_dev支持按键事件;
    3. 16~19行,设置4个物理按键对应的按键事件,S2S3S4S5分别对应"L"、"S"、"ENTER"、"LEFTSHIFT"事件;
    4. 调用input_register_device函数注册buttons_dev设备;
    5. 29~31行,关于定时器的设置,用于按键消抖处理;
    6. 33~37行,关于中断的注册,采用中断的方式检测按键,为了简化程序,定义一个pins_desc[4]结构体数组用于管理按键相关的信息,其定义如下:

      技术分享图片

    7. 40行,一些错误处理。

出口函数代码如下:

  1. static?void?buttons_exit(void)??
  2. {??
  3. ????int?i;??
  4. ????for(i=0;?i<4;?i++)??
  5. ????????free_irq(pins_desc[i].irq,?&pins_desc[i]);??
  6. ????del_timer(&button_timer);??
  7. ????input_unregister_device(buttons_dev);??
  8. ????input_free_device(buttons_dev);??
  9. }??

驱动层检测到按键时,需要向上层发送按键事件。这里在定时器中断服务函数中,调用input_event函数发送对应的按键事件,codevalue,再调用input_sync函数结束报告。

  1. void?button_timer_func(unsigned?long?arg)??
  2. {??
  3. ????struct?pin_desc?*?pindesc?=?irq_pd;??
  4. ????unsigned?int?pinval?;??
  5. ?????? ?
  6. ????if(pindesc)??
  7. ????{??
  8. ????????pinval?=?s3c2410_gpio_getpin(pindesc->pin);??
  9. ?????????? ?
  10. ????????if(pinval)/*?最后一个参数?松开:0??按下:1?*/??
  11. ????????{??
  12. ????????????input_event(buttons_dev,?EV_KEY,?pindesc->key_val,?0);??
  13. ????????????input_sync(buttons_dev);??
  14. ????????}??
  15. ????????else??
  16. ????????{??
  17. ????????????input_event(buttons_dev,?EV_KEY,?pindesc->key_val,?1);??
  18. ????????????input_sync(buttons_dev);??
  19. ????????}??
  20. ????}??
  21. }??

至此,基于输入子系统的按键驱动程序就已编写结束。

4实验验证

将编写的驱动代码进行编译、挂载。通过ls -l /dev/event*命令,可以查看到已经挂载的驱动设备/dev/event1

技术分享图片

方法一

使用hexdump /dev/event1命令,查看/dev/event1的十六进制编码。

技术分享图片

这里我们需要查看这些数据都表示些什么含义?

首先找到evdev_read函数,该函数中通过evdev_event_to_user函数将input_event事件发送至用户空间,其中input_event结构体定义如下:

技术分享图片

对应到显示的数据的含义如图所示。

技术分享图片

从读出的16进制数据显示,说明按键驱动可以正常工作。

方法二

若未使用QT,可执行cat /dev/tty1命令,再按下按键时,就会输出对应的按键值。

技术分享图片

若在执行exec 0</dev/tty1命令,将/dev/tty1设置为标准输入,此时就可通过按键输入ls命令,并在终端上显示执行结果。

技术分享图片

2linux输入子系统-按键驱动程序

原文:https://www.cnblogs.com/beijiqie1104/p/11424982.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!