linux 按键驱动简单实例

本章将介绍Linux输入子系统的驱动开发。Linux的输入子系统不仅支持鼠标、键盘等常规输入设备,而且还支持蜂鸣器、触摸屏等设备。本章将对Linux输入子系统进行详细的分析。

输入子系统大致实现方法:

   底层驱动层(input_dev)-----<通过结构体input_handle关联>-----输入事件处理层类接口(input_handler)-----<输入核心层input.c>-----应用层

17.1  input子系统入门

输入子系统又叫input子系统。其构建非常灵活,只需要调用一些简单的函数,就可以将一个输入设备的功能呈现给应用程序。本节将从一个实例开始,介绍编写输入子系统驱动程序的方法。

17.1.1  简单的实例

本节将讲述一个简单的输入设备驱动实例。这个输入设备只有一个按键,按键被连接到一条中断线上,当按键被按下时,将产生一个中断,内核将检测到这个中断,并对其进行处理。该实例的代码如下:

01  #include <asm/irq.h>

02  #include <asm/io.h>

03  static struct input_dev *button_dev;    /*输入设备结构体*/ 

04  static irqreturn_t button_interrupt(int irq, void *dummy)                                                       /*中断处理函数*/  

05  { 

06      input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);      
                                                                     /*向输入子系统报告产生按键事件*/  

07      input_sync(button_dev);             /*通知接收者,一个报告发送完毕*/  
08      return IRQ_HANDLED; 

09  } 

10  static int __init button_init(void) /*加载函数*/ 

11  {  

12      int error;  

13      if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL))                                           /*申请中断处理函数*/ 

14      { 

15          /*申请失败,则打印出错信息*/

16          printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_  
irq); 

17          return -EBUSY;  
18      }  

19      button_dev = input_allocate_device();   /*分配一个设备结构体*/  

20      if (!button_dev)                        /*判断分配是否成功*/ 

21      {  

22          printk(KERN_ERR "button.c: Not enough memory\n");  

23          error = -ENOMEM;  

24          goto err_free_irq;  

25      } 

 26      button_dev->evbit[0] = BIT_MASK(EV_KEY);    /*设置按键信息*/ 

 27      button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);  

28      error = input_register_device(button_dev);  /*注册一个输入设备*/ 

 29      if (error)  

30      { 

 31          printk(KERN_ERR "button.c: Failed to register device\n"); 

 32          goto err_free_dev;  

33      } 

 34      return 0; 

 35      err_free_dev:                               /*以下是错误处理*/ 

36          input_free_device(button_dev);  

37      err_free_irq:  

38          free_irq(BUTTON_IRQ, button_interrupt);  

39      return error; 

40  }  

41  static void __exit button_exit(void)            /*卸载函数*/

42  {  

43      input_unregister_device(button_dev);        /*注销按键设备*/  

44      free_irq(BUTTON_IRQ, button_interrupt); /*释放按键占用的中断线*/ 

45  } 

 46  module_init(button_init);  

47  module_exit(button_exit); 

这个实例程序代码比较简单,在初始化函数button_init()中注册了一个中断处理函数,然后调用input_allocate_device()函数分配了一个input_dev结构体,并调用input_register_device()函数对其进行了注册。在中断处理函数button_interrupt()中,实例将接收到的按键信息上报给input子系统。从而通过input子系统,向用户态程序提供按键输入信息。

本实例采用了中断方式,除了中断相关的代码外,实例中包含了一些input子系统提供的函数,现对其中一些重要的函数进行分析。

第19行的input_allocate_device()函数在内存中为输入设备结构体分配一个空间,并对其主要的成员进行了初始化。驱动开发人员为了更深入的了解input子系统,应该对其代码有一点的认识,该函数的代码如下:

  1. struct input_dev *input_allocate_device(void)  
  2. {  
  3.     struct input_dev *dev;  
  4.     dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);              
    /*分配一个input_dev结构体,并初始化为0*/  
  5.     if (dev) {  
  6.         dev->dev.type = &input_dev_type;        /*初始化设备的类型*/  
  7.         dev->dev.class = &input_class;          /*设置为输入设备类*/  
  8.         device_initialize(&dev->dev);           /*初始化device结构*/  
  9.         mutex_init(&dev->mutex);                /*初始化互斥锁*/  
  10.         spin_lock_init(&dev->event_lock);       /*初始化事件自旋锁*/  
  11.         INIT_LIST_HEAD(&dev->h_list);           /*初始化链表*/  
  12.         INIT_LIST_HEAD(&dev->node);             /*初始化链表*/  
  13.         __module_get(THIS_MODULE);              /*模块引用技术加1*/  
  14.     }  
  15.     return dev;  

该函数返回一个指向input_dev类型的指针,该结构体是一个输入设备结构体,包含了输入设备的一些相关信息,如设备支持的按键码、设备的名称、设备支持的事件等。在本章用到这个结构体时,将对其进行详细介绍。此处将注意力集中在实例中的函数上。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值