[arm驱动]input system 子系统的驱动编写

简介:

更多可参考 

Linux输入子系统分析

input 子系统架构总结

1、定义一个static struct input_dev结构体

static struct input_dev *mybutton_dev;


2、初始化时分配input_dev结构体

mybutton_dev = input_allocate_device();//分配 input_dev

/*能产生的事件类型
1. #define EV_SYN     0x00   /*表示设备支持所有的事件*/
2. #define EV_KEY     0x01  /*键盘或者按键,表示一个键码*/
3. #define EV_REL     0x02  /*鼠标设备,表示一个相对的光标位置结果*/
4. #define EV_ABS     0x03  /*手写板产生的值,其是一个绝对整数值*/
5. #define EV_MSC     0x04  /*其他类型*/
6. #define EV_LED     0x11   /*LED 灯设备*/
7. #define EV_SND     0x12  /*蜂鸣器,输入声音*/
8. #define EV_REP     0x14   /*允许重复按键类型*/
9. #define EV_PWR     0x16   /*电源管理事件*/
*/

set_bit(EV_KEY, mybutton_dev->evbit);
set_bit(EV_REP, mybutton_dev->evbit);


//设置支持的按键值
set_bit(KEY_L, mybutton_dev->keybit);
set_bit(KEY_S, mybutton_dev->keybit);
set_bit(KEY_ENTER, mybutton_dev->keybit);
error = input_register_device(mybutton_dev);//注册驱动



3、//输入子系统的事件handle函数
static void inputsystemtimer_handle(unsigned long data){
struct pin_desc * pino_desc = irq_pd;
unsigned int pinval;
if (!pino_desc)
return;
pinval = s3c2410_gpio_getpin(pino_desc->pin);
if (pinval)
{
/* 松开 : 最后一个参数: 0-松开, 1-按下 */
input_report_key(mybutton_dev, pino_desc->key_val,  0);
//貌似必须这样,如果val填pinval会一直报告事件
//貌似必须这样,如果val填inb(pino_desc->pin) & 1会一直报告事件有延迟
 input_sync(mybutton_dev);
}
else
{
/* 按下 */
input_report_key(mybutton_dev, pino_desc->key_val, 1);//必须填1
   input_sync(mybutton_dev);
}
   printk("press button is %s\n", pino_desc->name);
}


4、//注销驱动
input_unregister_device(mybutton_dev);//注销驱动
input_free_device(mybutton_dev);


完整实例:按键的输入子系统

#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 <linux/gpio_keys.h>
#include <asm/gpio.h>
#include <asm/irq.h>
#include <asm/io.h>
static struct input_dev *mybutton_dev;
static struct timer_list mybutton_timer;
struct pin_desc *irq_pd;
struct pin_desc{
    int irq;
    char *name;
    unsigned int pin;
    unsigned int key_val;
};
struct pin_desc pins_desc[3] = {
    {IRQ_EINT0,  "S2", S3C2410_GPF0,   KEY_L},
    {IRQ_EINT2,  "S3", S3C2410_GPF2,   KEY_S},
    {IRQ_EINT11, "S4", S3C2410_GPG3,   KEY_ENTER},
};
static irqreturn_t irq_handle(int irq, void *dev__id){
    irq_pd = (struct pin_desc *)dev__id;
    mod_timer(&mybutton_timer, jiffies+HZ/100);
    return IRQ_HANDLED;//返回IRQ_HANDLED表示中断已经处理
}
static void inputsystemtimer_handle(unsigned long data){
    struct pin_desc * pino_desc = irq_pd;
    unsigned int pinval;
                                        
    if (!pino_desc)
        return;
                                        
    pinval = s3c2410_gpio_getpin(pino_desc->pin);
                                        
    if (pinval)
    {
        /* 松开 : 最后一个参数: 0-松开, 1-按下 */
        input_report_key(mybutton_dev, pino_desc->key_val,  0);
    input_sync(mybutton_dev);
    }
    else
    {
        /* 按下 */
        input_report_key(mybutton_dev, pino_desc->key_val, 1);
    input_sync(mybutton_dev);
    }
    printk("press button is %s\n", pino_desc->name);
}
static int inputsystem_init(void){
    int i = 0;
    int error;
    init_timer(&mybutton_timer);
    mybutton_timer.function = inputsystemtimer_handle;
    add_timer(&mybutton_timer);
                                        
    mybutton_dev = input_allocate_device();
    if(! mybutton_dev){
    printk(KERN_ERR "allocate failed!\n");
    error = -ENOMEM;
    goto err_free_irq;
    }
                                        
    mybutton_dev->name = "buttonKeyboard";
    mybutton_dev->phys = "gpio-keys/input0";
    mybutton_dev->id.version = 0x0100;
                                        
    set_bit(EV_KEY, mybutton_dev->evbit);
    set_bit(EV_REP, mybutton_dev->evbit);
                                        
    set_bit(KEY_L, mybutton_dev->keybit);
    set_bit(KEY_S, mybutton_dev->keybit);
    set_bit(KEY_ENTER, mybutton_dev->keybit);
    error = input_register_device(mybutton_dev);
    if(error){
    printk(KERN_ERR"input regsiter error\n");
    goto err_free_dev;
    }
        for(i = 0; i < 3; i ++)
    request_irq(pins_desc[i].irq, irq_handle, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);
    return 0;
    err_free_irq:
        for(i = 0; i < 3; i ++)free_irq(pins_desc[i].irq, &pins_desc[i]);
    err_free_dev:
        input_free_device(mybutton_dev);
    return error;
}
static void inputsystem_exit(void){
    int i = 0;
    input_unregister_device(mybutton_dev);//注销驱动
    input_free_device(mybutton_dev);
    del_timer(&mybutton_timer);
    for(i = 0; i < 3; i ++)free_irq(pins_desc[i].irq, &pins_desc[i]);
                                        
}
module_init(inputsystem_init);
module_exit(inputsystem_exit);
MODULE_LICENSE("GPL");



   测试程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <linux/input.h>
int main(void)
{
   int fd;
   int key_value,i=0,count;
   struct input_event ev_key;
   fd = open("/dev/event1", 666);
   if (fd < 0)
  {
    printf("can't open device buttons!\n");
    exit(1);
  }
  for (;;)
  {
    count = read(fd,&ev_key,sizeof(struct input_event));
    for(i=0; i<(int)count/sizeof(struct input_event); i++){
        printf("%d\n", ev_key.type);
        if(EV_KEY==ev_key.type)
          printf("type:%d,code:%d,value:%d\n", ev_key.type,ev_key.code,ev_key.value);
                               
         }
        if(EV_SYN==ev_key.type)
          printf("syn event\n\n");
  }
  printf("app close fd\n");
   close(fd);
   return 0;
}
本文转自lilin9105 51CTO博客,原文链接:http://blog.51cto.com/7071976/1406092,如需转载请自行联系原作者
相关文章
|
7月前
|
缓存 C++
基于ARM-contexA9-蜂鸣器pwm驱动开发
基于ARM-contexA9-蜂鸣器pwm驱动开发
50 0
|
7月前
基于ARM-contexA9蜂鸣器驱动开发
基于ARM-contexA9蜂鸣器驱动开发
43 0