嵌入式linux驱动-输入子系统笔记

来源:互联网 发布:霓虹灯效果图制作软件 编辑:程序博客网 时间:2024/04/30 21:40

一、开发环境

1、内核:Linux 2.6.22.6;

2、JZ2440

3、ubuntu 9.10


二、过程

1、分配input_dev结构体

   使用input_allocate_device函数,如:

先定义一个input_dev 结构体类型变量:static struct input_dev *key_dev;

使用input_allocate_device函数分配key_dev=input_allocate_device();

2、设置input_dev

 input_dev结构体成员有:

struct input_dev {  
    const char *name;  
    const char *phys;  
    const char *uniq;  
    struct input_id id;  
  
    unsigned long evbit[NBITS(EV_MAX)];   // 表示能产生哪类事件  
    unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键  
    unsigned long relbit[NBITS(REL_MAX)]; // 表示能产生哪些相对位移事件, x,y,滚轮  
    unsigned long absbit[NBITS(ABS_MAX)]; // 表示能产生哪些绝对位移事件, x,y  
    unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];  
    unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];  
    unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];  
    unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];  
    ...  
 }

先设置哪类操作,再设置这类操作的哪些事件,如

/* 2.1 设置按键能产生哪类事件 */ 

set_bit(EV_KEY,key_dev->evbit);//EV_KEY表示按键操作
set_bit(EV_REP,key_dev->evbit);//EV_REP表示按键重复操作  
/* 2.2 设置能产生这类操作的哪些事件 */  

set_bit(KEY_L,key_dev->keybit);//KEY_L表示按了L键
set_bit(KEY_S,key_dev->keybit);//KEY_S表示按了S键
set_bit(KEY_ENTER,key_dev->keybit);//ENTER表示按了ENTER键
set_bit(KEY_LEFTSHIFT,key_dev->keybit);//KEY_LEFTSHIFT表示按了左边的SHIFT键

另外:

input.h里有以下类

#define EV_SYN          0x00    //同步类  
#define EV_KEY          0x01    //按键类  
#define EV_REL          0x02    //相对位移类  
#define EV_ABS          0x03    //绝对位移类  
#define EV_MSC          0x04      
#define EV_SW           0x05  
#define EV_LED          0x11  
#define EV_SND          0x12    //声音类  
#define EV_REP          0x14    //重复类  
#define EV_FF           0x15  
#define EV_PWR          0x16  
#define EV_FF_STATUS        0x17  
#define EV_MAX          0x1f  
#define EV_CNT          (EV_MAX+1) 

3、注册

使用input_register_device(struct input_dev *dev)函数来注册,如:input_register_device(key_dev);

4、硬件相关操作

具体应用具体写了。比如本实验中使用到定时器,初始化定时器,使用按键注册中断等。

5、程序

#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/sched.h>#include <linux/pm.h>#include <linux/sysctl.h>#include <linux/proc_fs.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/input.h>#include <linux/irq.h>#include <asm/gpio.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>struct key_desc{int irq;char *name;unsignedint pin;unsignedint key_val;};struct key_desc key_desc[4]={{IRQ_EINT0,"s2",S3C2410_GPF0,KEY_L},{IRQ_EINT2,"s3",S3C2410_GPF2,KEY_S},{IRQ_EINT11,"s4",S3C2410_GPG3,KEY_ENTER},{IRQ_EINT19,"s5",S3C2410_GPG11,KEY_LEFTSHIFT},};static struct input_dev *key_dev;static struct key_desc *irq_tmp;static struct timer_list key_timer;static irqreturn_t key_irq(int irq, void *dev_id){   // printk("key_irq!irq=%d \n",irq);irq_tmp=(struct key_desc*)dev_id;mod_timer(&key_timer, jiffies + HZ/100);return IRQ_RETVAL(IRQ_HANDLED);}static void key_timer_func(unsigned long __data){struct key_desc * keysdesc=irq_tmp;unsigned int keyval;//printk("key_timer_func! \n");if (!keysdesc){//printk("keysdesc\n");return;}keyval=s3c2410_gpio_getpin(keysdesc->pin);if(keyval){//松开input_event(key_dev,EV_KEY,keysdesc->key_val,0);input_sync(key_dev);//printk("input_event0! \n");}else{//按下input_event(key_dev,EV_KEY,keysdesc->key_val,1);input_sync(key_dev);//printk("input_event1! \n");}}static int  key_init(void){int i;printk("key_init! \n");//分配一个input_dev结构体key_dev=input_allocate_device();//设置set_bit(EV_KEY,key_dev->evbit);set_bit(EV_REP,key_dev->evbit);set_bit(KEY_L,key_dev->keybit);set_bit(KEY_S,key_dev->keybit);set_bit(KEY_ENTER,key_dev->keybit);set_bit(KEY_LEFTSHIFT,key_dev->keybit);//注册input_register_device(key_dev);//硬件相关操作//定时器初始化init_timer(&key_timer);key_timer.function = key_timer_func;add_timer(&key_timer);for(i=0;i<4;i++){request_irq(key_desc[i].irq,key_irq ,IRQT_BOTHEDGE,key_desc[i].name,&key_desc[i]);}return 0;}static void key_exit(void){int i;printk("key_exit! \n");for(i=0;i<4;i++){free_irq(key_desc[i].irq,&key_desc[i]);}del_timer(&key_timer);input_unregister_device(key_dev);input_free_device(key_dev);}module_init(key_init);module_exit(key_exit);MODULE_LICENSE("GPL");

三、架构相关

1、驱动中按键松开、按下时调用input_event()函数把keysdesc->key_val即结构体

struct key_desc key_desc[4]={
{IRQ_EINT0,"s1",S3C2410_GPF0,KEY_L},
{IRQ_EINT2,"s2",S3C2410_GPF2,KEY_S},
{IRQ_EINT11,"s3",S3C2410_GPG3,KEY_ENTER},
{IRQ_EINT19,"s4",S3C2410_GPG11,KEY_LEFTSHIFT},
};

中的KEY_L,KEY_S,KEY_ENTER,KEY_LEFTSHIFT,传递给内核。

input_event()函数中有:

list_for_each_entry(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle, type, code, value);


实现了从input_dev到input_handle到input_handler的调用。即从硬件层到两者的连接层到驱动层的调用。我们写的程序调用input_event()函数,input_event中通过dev->h_list找到input_handle,input_handle通过其成员handler找到event。

2、韦分层框架截图


四、命令

hexdump /dev/event1 hex显示/dev/event1

exec 0</dev/tty1 标准输入改为tty1

五、问题

1、加载模块后,没有event,如下

# ls -l /dev/event*
ls: /dev/event*: No such file or directory

解决:配置内核时选上Device Drivers->Input device support->Event interface && Event debugging。下载新内核到板子上。再重新make下编写的输入子系统。

加载子系统后,结果如下

六、结果






0 0
原创粉丝点击