06day01input_driver

  1 /*
  2 输入子系统:
  3 把按键的驱动,添加到输入子系统中,可以通过按键来输入对应的字符
  4 
  5 内核中  include/linux/input.h 
  6 驱动中主要填充 input_dev 这个结构体
  7 name 名称  phys  uniq  input_id  设置对应的节点信息
  8 
  9 
 10 */
 11 #include <linux/module.h>
 12 #include <linux/init.h>
 13 #include <linux/kernel.h>
 14 
 15 #include <linux/input.h>
 16 #include <linux/bitops.h>
 17 #include <linux/interrupt.h> //request_irq
 18 #include <mach/irqs.h> //IRQ_EINT
 19 #include <linux/gpio.h>  //gpio_request
 20 #include <mach/gpio.h>  //EXYNOS4_GPX3
 21 /*
 22 用四个按键模拟键盘  把案件值 直接输出标准输出
 23 
 24 可以将开发板上的系统当前终端输入重定向为标准输入
 25 
 26 exec 0 < /dev/tty1
 27 */
 28 
 29 
 30 #define DEVNAME "ldm"
 31 
 32 //
 33 struct ldm_info
 34 {
 35     struct input_dev * pdev;
 36 };
 37 
 38 struct ldm_info ldm;
 39 
 40 struct  key_info
 41 {
 42     char * name;
 43     int code;
 44     int irqno;
 45     int gpio_num;
 46 };
 47 
 48 //l s enter   backspace
 49 struct key_info keyinfo[] = {
 50     {"KEY_L", KEY_L, IRQ_EINT(26), EXYNOS4_GPX3(2)},
 51     {"KEY_S", KEY_S, IRQ_EINT(27), EXYNOS4_GPX3(3)},
 52     {"KEY_ENTER", KEY_ENTER, IRQ_EINT(28), EXYNOS4_GPX3(4)},
 53     {"KEY_BACKSPACE", KEY_BACKSPACE, IRQ_EINT(29), EXYNOS4_GPX3(5)},  
 54 };
 55 
 56 //中断处理函数
 57 static irqreturn_t key_handler(int irqno, void * arg)
 58 {
 59     struct key_info *key = (struct key_info *)arg;
 60     //产生了中断,在合适时候,发送input_event事件
 61 
 62     int key_stat = gpio_get_value(key->gpio_num);
 63 
 64     //发送事件  发送按键的按键值 和 按键的状态
 65     input_report_key(ldm.pdev,  key->code,  !key_stat);
 66     //发送结束事件
 67     input_sync(ldm.pdev);
 68 
 69     return IRQ_HANDLED;
 70 }
 71 
 72 static int test_init(void)
 73 {
 74     int ret = 0;
 75     int i = 0;
 76     int j = 0;
 77     printk("%s:%s:%d
", __FILE__, __FUNCTION__, __LINE__);
 78 
 79     //1.创建input_dev 的对象  input_allocate_device();
 80     //如果仅仅申请了空间,没有注册 即调用input_allocate_device
 81     //那么需要调用input_free_device 函数来释放空间
 82     //一旦注册成功,则不需要调用input_free_device来释放空间
 83     ldm.pdev = input_allocate_device();
 84     if(!ldm.pdev) {
 85         printk("input_allocate_device  failed
");
 86         ret = -ENOMEM;
 87         goto err_input_allocate_device;
 88     }
 89 
 90     //2.填充input_dev 这个结构体
 91     ////////////相关的信息/////////////////////////
 92     ldm.pdev->name = "my test input device";
 93     ldm.pdev->phys = "key";
 94     ldm.pdev->uniq = "candle";
 95     ldm.pdev->id.bustype = 0x1234;
 96     ldm.pdev->id.vendor = 0x2222;
 97     ldm.pdev->id.product =  0xabcd;
 98     ldm.pdev->id.version =  0x3433;
 99     ///////////////////////////////////////////////////////
100 
101     //这个设备支持哪些事件?
102     //本设备支持的事件的类型,通过set_bit函数来指定位置
103     //所有的位置,都可以通过宏来设置
104     set_bit(EV_KEY,   ldm.pdev->evbit); //支持按键类型的事件
105     set_bit(EV_REP, ldm.pdev->evbit);//支持连发
106 
107     //针对不同的事件,处理什么样的数据?
108     //eint26~29   GPX3_2 ~5
109     //这个设备支持的按键的键值
110     
111     for(i=0; i< ARRAY_SIZE(keyinfo);i++) {
112         set_bit(keyinfo[i].code, ldm.pdev->keybit);
113     }
114 
115     //注册设备对象
116     ret = input_register_device(ldm.pdev);
117     if(ret < 0) {
118         printk("input_register_device  failed
");
119         goto  err_input_register_device;
120     }
121 
122     //注册中断,按下和抬起的时候都要去触发
123     for(i=0;i < ARRAY_SIZE(keyinfo);i++) {
124         ret = request_irq(keyinfo[i].irqno, key_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, DEVNAME, keyinfo + i );
125         if(ret < 0) {
126             printk("request_irq  failed
");
127             goto err_request_irq;
128         }
129     }
130 
131     //注册GPIO管脚
132     //int j = 0;
133     for(j=0; j < ARRAY_SIZE(keyinfo);j++) {
134         ret = gpio_request(keyinfo[j].gpio_num, keyinfo[j].name);
135         if(ret < 0) {
136             printk("gpio_request  failed
");
137             goto err_gpio_request;
138         }
139     }
140 
141 
142     return 0;
143 
144 err_gpio_request:
145     for(j = j - 1;j>=0;j--) {
146         gpio_free(keyinfo[j].gpio_num);
147     }
148 err_request_irq:
149     for(i=i-1;i>=0;i--) {
150         free_irq(keyinfo[i].irqno, keyinfo + i); 
151         //把之前注册成功的中断号释放掉
152     }
153     input_unregister_device(ldm.pdev);
154     return ret;
155 err_input_register_device:
156     input_free_device(ldm.pdev);
157 err_input_allocate_device:
158     return ret;
159 }
160 
161 static  void test_exit(void)
162 {
163     int i = ARRAY_SIZE(keyinfo);
164     printk("%s:%s:%d
", __FILE__, __FUNCTION__, __LINE__);
165     
166 
167     for(i=i-1; i>=0;i--) {
168         gpio_free(keyinfo[i].gpio_num);
169         free_irq(keyinfo[i].irqno, keyinfo + i);
170     }
171 
172     input_unregister_device(ldm.pdev);
173 }
174 
175 
176 module_init(test_init);
177 module_exit(test_exit);
178 MODULE_LICENSE("GPL");
原文地址:https://www.cnblogs.com/baoshulin/p/6477030.html