linux驱动模型<输入子系统>

      在linux中提供一种输入子系统的驱动模型,其主要是实现在input.c中。

      在输入子系统这套模型中,他把驱动分层分类。首先分为上下两层,上层为input.c 。下层为驱动的实现,下层分为两部分,一部分为drive部分,主要实现和硬件无关的代码,一本分为device部分,这部分就是与硬件相关的代码。

 

    Image007

在内核代码中drive部分已经为我们写好了,你也可以自己写,我一般用的是evdev.c这个文件里面的代码。我们所要做的就是编写device里面的代码。这样就可以减轻程序员的编写负担。免得每次写驱动程序都要编写与硬件无关的程序。

下面看我写的device部分的代码:  

 

  1 #include <linux/module.h>
  2 #include <linux/version.h>
  3 
  4 #include <linux/init.h>
  5 #include <linux/fs.h>
  6 #include <linux/interrupt.h>
  7 #include <linux/irq.h>
  8 #include <linux/sched.h>
  9 #include <linux/pm.h>
 10 #include <linux/sysctl.h>
 11 #include <linux/proc_fs.h>
 12 #include <linux/delay.h>
 13 #include <linux/platform_device.h>
 14 #include <linux/input.h>
 15 #include <linux/irq.h>
 16 
 17 #include <asm/gpio.h>
 18 #include <asm/io.h>
 19 #include <asm/arch/regs-gpio.h>
 20 
//////////////这里声明了一个结构体指针  为构建整套系统所必须的
21 static struct input_dev *buttons_dev; 22 //////////////定义了一个时钟的结构体,程序里面关键是为了防抖
23 static struct timer_list buttons_timer; 24
////////////////////////// 25 static struct pin_desc *irq_pd; 26
/////////////////这个结构体存储了一些必要的数据 27 struct pin_desc{ 28 int irq; 29 char *name; 30 unsigned int pin; 31 unsigned int key_val; 32 }; 33 34 struct pin_desc pins_desc[4] = { 35 {IRQ_EINT8, "K1", S3C2410_GPG0, KEY_L}, 36 {IRQ_EINT11, "K2", S3C2410_GPG3, KEY_S}, 37 {IRQ_EINT13, "K3", S3C2410_GPG5, KEY_ENTER}, 38 {IRQ_EINT14, "K4", S3C2410_GPG6, KEY_LEFTSHIFT}, 39 }; 40 /////////中断处理函数 里面主要是设置定时器的时钟 用来防抖
41 static irqreturn_t buttons_irq(int irq, void *dev_id) 42 { 43 irq_pd = (struct pin_desc *) dev_id; 44 mod_timer(&buttons_timer, jiffies+HZ/100); 45 return IRQ_RETVAL(IRQ_HANDLED); 46 } 47 //////////此函数为定时器函数 定时的时间到了后这个函数被执行 主要用于检测按键被按下 然后上报事件
48 static void buttons_timer_function(unsigned long data) 49 { 50 struct pin_desc * pindesc = irq_pd; 51 52 unsigned int pinval; 53 54 if (!pindesc) 55 return; 56 57 pinval = s3c2410_gpio_getpin(pindesc->pin); 58 59 if (pinval) 60 { 61 /* 松开 : 最后一个参数: 0-松开, 1-按下 */ 62 input_event(buttons_dev, EV_KEY, pindesc->key_val, 0); 63 input_sync(buttons_dev); 64 } 65 else 66 { 67 /* 按下 */ 68 input_event(buttons_dev, EV_KEY, pindesc->key_val, 1); 69 input_sync(buttons_dev); 70 } 71 72 return ; 73 } 74 75
//////////各种初始化 关于input_dev结构体的分配 和赋值什么的 这个关键是要看input.c里面的内容
76 static int buttons_init(void) 77 { 78 int i; 79 /* 1.分配一个imput_dev结构体*/ 80 buttons_dev = input_allocate_device(); 81 82 /*2. 设置*/ 83 84 /*2.1 能产生哪类事件*/ 85 set_bit(EV_KEY, buttons_dev->evbit); 86 set_bit(EV_REP, buttons_dev->evbit); 87 88 /*2.2 能够产生哪些事件*/ 89 set_bit(KEY_L, buttons_dev->keybit); 90 set_bit(KEY_S, buttons_dev->keybit); 91 set_bit(KEY_ENTER, buttons_dev->keybit); 92 set_bit(KEY_LEFTSHIFT, buttons_dev->keybit); 93 94 /*3. 注册*/ 95 input_register_device(buttons_dev); 96 97 /*4. 硬件相关的操作*/ 98 init_timer(&buttons_timer); 99 buttons_timer.function = buttons_timer_function; 100 add_timer(&buttons_timer); 101 102 for(i = 0; i < 4; i++) 103 { 104 request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]); 105 } 106 107 return 0; 108 109 } 110 ///////////这个函数就是各种卸载啦
111 static void buttons_exit(void) 112 { 113 int i; 114 for (i = 0; i < 4; i++) 115 { 116 free_irq(pins_desc[i].irq, &pins_desc[i]); 117 } 118 119 del_timer(&buttons_timer); 120 input_unregister_device(buttons_dev); 121 input_free_device(buttons_dev); 122 123 return ; 124 } 125 126 module_init(buttons_init); 127 module_exit(buttons_exit); 128 MODULE_LICENSE("GPL");

 

以上的程序没有什么太大的难点,但是细细研究还是有很多东西值得我们去研究的。

我们研究的只是device这部分的代码,要深入的理解还是要看内核源码啊。

 

                                  

posted @ 2013-10-07 15:20  pslzym  阅读(399)  评论(0编辑  收藏  举报