输入子系统由驱动层、输入子系统核心、事件处理层三部分组成。一个输入事件,如鼠标移动、键盘按下等通过Driver->Inputcore->Event handler->userspace的顺序到达用户控件的应用程序。

其中核心层提供一些设备层与事件层公用的函数,比如说注册函数、反注册函数、事件到来的处理函数等等;事件层其实在Linux内核里面已经帮我们写好了很多有关的事件;而设备层就跟我们新添加到输入系统的具体设备相关了。这里以JZ2440开发板上的4个按键作为输入子系统的按键:它定义的功能分别为:KEY_L、KEY_S、KEY_ENTER、KEY_LEFTSHIFT。这几个值是在include\linux\input.h中被定义的。

button_drv.c文件:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> 
#include <asm/uaccess.h>
#include <linux/device.h>/
#include <asm/arch/regs-gpio.h>
#include <linux/irq.h>
#include <asm-arm/irq.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <asm-generic/errno-base.h>
#include <linux/input.h>

struct pin_desc
{
  char * name;            //名称
  unsigned int pin;       //管脚定义
  unsigned int irq;       //中断号
  unsigned int key_val;   //按键值
};

static struct pin_desc pins_desc[4] = 
{
  {"S1",S3C2410_GPF0,IRQ_EINT0,KEY_L},
  {"S2",S3C2410_GPF2,IRQ_EINT2,KEY_S},
  {"S3",S3C2410_GPG3,IRQ_EINT11,KEY_ENTER},
  {"S4",S3C2410_GPG11,IRQ_EINT19,KEY_LEFTSHIFT}
};

static struct pin_desc *pinss_desc=NULL;

static struct timer_list timer_button;                //新建一个定时器

static struct input_dev *buttons_input;               //新建一个输入子系统的设备层结构

static irqreturn_t buttons_irq(int irq, void *dev_id)
{
  pinss_desc = (struct pin_desc *)dev_id;            //取得哪个按键被按下的状态
  mod_timer(&inputbuttons_timer, jiffies+HZ/100);    //10ms之后调用定时器处理函数
  return IRQ_HANDLED;
}

static void timer_button_timeout(unsigned long a)
{
  unsigned int pin_val;

  if(pinss_desc==NULL)
    return;
  else
  {
    pin_val = s3c2410_gpio_getpin(pinss_desc->pin);

    if(pin_val)
    {
      input_event(buttons_input,EV_KEY, pinss_desc->key_val, 0);
    }
    else
    {
      input_event(buttons_input,EV_KEY, pinss_desc->key_val, 1);
    }
  }
}

static int button_drv_init(void)
{
  unsigned char i;
  int ret;
  buttons_input = input_allocate_device();        //分配input_dev结构体
  if (!buttons_input)
    return -ENOMEM;

  set_bit(EV_KEY, buttons_input->evbit);          //按键事件
  set_bit(EV_REP, buttons_input->evbit);          //重复事件类型
  set_bit(KEY_L, buttons_input->keybit);
  set_bit(KEY_S, buttons_input->keybit);
  set_bit(KEY_ENTER, buttons_input->keybit);
  set_bit(KEY_LEFTSHIFT, buttons_input->keybit);

  input_register_device(buttons_input);           //注册设备驱动

  init_timer(&timer_button);
  inputbuttons_timer.expires = 0;
  inputbuttons_timer.function = timer_button_timeout;
  add_timer(&timer_button);
                                                                                                                                     //注意这里没有创建设备类和设备文件(设备节点)

                                                              //因为输入子系统的设备文件本来就存在为/dev/event0
  for(i=0;i<4;i++)
  {
    ret = request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, (void * )&pins_desc[i]);
    if(ret)
    {
      printk("open failed %d\n",i);
      return -(i+1);
    }
  }
  return 0;
}

static void button_drv_exit(void)
{
  unsigned char i;

  input_unregister_device(buttons_input);
  input_free_device(buttons_input);
  del_timer(&timer_button);

  for(i=0;i<4;i++)
  {
    free_irq(pins_desc[i].irq, (void * )&pins_desc[i]);
  }
}

module_init(seven_drv_init);
module_exit(seven_drv_exit);

MODULE_LICENSE("GPL");

Makefile文件:

obj-m += button_drv.o

KERN_DIR = /work/system/linux-2.6.22.6

all:
make -C $(KERN_DIR) M=`pwd` modules 
clean:
rm -rf *.o *.ko *.order *.symvers *.mod.c

button_app.c文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>

static int fd;

int main(int argc, char **argv)
{
  char* filename = argv[1];
  int oflags, ret=0;
  unsigned char key_val[16];

  fd = open(filename, O_RDWR);//打开设备文件,阻塞方式打开
  if (fd < 0)
  {
    printf("error, can't open %s\n", filename);
    return 0;
  }
  while(1)
  {
    ret = read(fd, key_val, 16);
    printf("ret: %d, code: %02d, value: %d \n", ret, key_val[10], key_val[12]);
  }
  return 0;
}

app_read->evdev_read->kbtab_irq->input_report_key->input_event->evdev_event->evdev_read

应用层      事件层        设备层        核心层               核心层          事件层          事件层

应用函数最终会通过事件层的evdev_event调用evdev_read

而在linux中evdev_event结构体共16字节,所以app中的read函数也应该读取16字节

编译生成button_drv.ko和button_app文件,运行./button_app /dev/event0

Linux 驱动——Button8(输入子系统)的更多相关文章

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

    在linux中提供一种输入子系统的驱动模型,其主要是实现在input.c中. 在输入子系统这套模型中,他把驱动分层分类.首先分为上下两层,上层为input.c .下层为驱动的实现,下层分为两部分,一部 ...

  2. Linux驱动之输入子系统简析

    输入子系统由驱动层.输入子系统核心.事件处理层三部分组成.一个输入事件,如鼠标移动.键盘按下等通过Driver->Inputcore->Event handler->userspac ...

  3. Linux 驱动框架---input子系统框架

    前面从具体(Linux 驱动框架---input子系统)的工作过程学习了Linux的input子系统相关的架构知识,但是前面的学习比较实际缺少总结,所以今天就来总结一下输入子系统的架构分层,站到远处来 ...

  4. Linux 驱动框架---input子系统

    input 子系统也是作为内核的一个字符设备模块存在的,所以他也是字符设备自然也会有字符设备的文件接口.input子系统的注册过程主要分为两步,先注册了一个input class然后再注册一个字符设备 ...

  5. ARM Linux内核Input输入子系统浅解

    --以触摸屏驱动为例 第一章.了解linux input子系统         Linux输入设备总类繁杂,常见的包括有按键.键盘.触摸屏.鼠标.摇杆等等,他们本身就是字符设备,而linux内核将这些 ...

  6. Linux驱动之一个简单的输入子系统程序编写

    的在Linux驱动之输入子系统简析已经分析过了输入子系统的构成,它是由设备层.核心层.事件层共同组成的.其中核心层提供一些设备层与事件层公用的函数,比如说注册函数.反注册函数.事件到来的处理函数等等: ...

  7. Linux输入子系统 转载

    NQian 记录成长~ 首页 新随笔 联系 订阅 管理 随笔 - 305  文章 - 0  评论 - 254 12.Linux之输入子系统分析(详解)   在此节之前,我们学的都是简单的字符驱动,涉及 ...

  8. Linux驱动之触摸屏程序编写

    本篇博客分以下几部分讲解 1.介绍电阻式触摸屏的原理 2.介绍触摸屏驱动的框架(输入子系统) 3.介绍程序用到的结构体 4.介绍程序用到的函数 5.编写程序 6.测试程序 1.介绍电阻式触摸屏的原理 ...

  9. linux 输入子系统之电阻式触摸屏驱动

    一.输入子系统情景回忆ING...... 在Linux中,输入子系统是由输入子系统设备驱动层.输入子系统核心层(Input Core)和输入子系统事件处理层(Event Handler)组成.其中设备 ...

随机推荐

  1. XV Open Cup named after E.V. Pankratiev. GP of Siberia-Swimming

    给出两个点,找到过这两个点的等角螺线,并求出中间的螺线长 $c = \frac{b}{a}$ $p = a \times c^{\frac{\theta}{angle}}$ 对弧线积分 #includ ...

  2. h5页面避免两个页面反复跳转死循环

    项目中经常会碰到在一个页面加判断之后跳转另一个页面,并且无法返回,来回跳转,死循环,遇到这种情况可以在跳转时使用location,replace,关闭之前页面,与location.href 两者的不同 ...

  3. elasticSearch安装 Kibana安装 Sense安装

    安装最新版本,安装6.*版本 先提示一个重要的事情,kibana新版本不需要安装Sense, 官方的是老版的Kibana才需要,我们现在用devTool http://localhost:5601/a ...

  4. node项目运行报错

    Cannot find module 'webpack/bin/config-optimist' 在项目里面运行npm i webpack-dev-server Cannot find module ...

  5. WebService调用SSAS教程

    WebService调用SSAS教程 一.创建SSAS项目 使用SQL Server Business Intelligence Development Studio新建Analysis Servic ...

  6. 小程序数据绑定点赞效果切换(交流QQ群:604788754)

    如果对本例有更好的意见和建议,希望给予留言或是加群跟群主联系,交流学习. WXML: <block wx:for="{{nums}}" wx:for-index='idx' ...

  7. DOM4j 修改和删除

    XML文件 <?xml version="1.0" encoding="UTF-8"?> <contactList> <conta ...

  8. spoj Ae2b

    题解: 设最后为x1+t1k+t2n,y1+t3k+t4n 显然t1,t4或t2,t3同余(mod 2) 然后exgcd一下 代码: #include<bits/stdc++.h> #de ...

  9. nginx常用模块

    Nginx模块介绍 核心模块:core module 标准模块:stand modules HTTP modules: Standard HTTP modules Optional HTTP modu ...

  10. Python 的第一个小程序

    F盘   新建文本文档 hello.txt 内容为: print("hello world! hello 2018!"); 打开CMD cd c:\                 ...