Irqreturn

前面程序存在的问题

1)按键缓冲区的问题 kbuf[100]  r_pos  w_pos

2)按键值的问题    drive    说明文档

3)连续按键的问题

-------------------------------

input子系统

对于这些只有输入没有输出的设备,该类设备驱动程序中有很多可以公用的代码(缓冲区,连续按键,)

Input子系统解决的问题就是把这些抽象出来的代码帮我们实现好了直接可以使用了。

input子系统的核心模块

Drivers/input/inputC

要想使用内核提供的这些公共代码,我们所要完成的驱动程序就是要遵循一定得框架。

1)分配一个输入设备  struct input_dev

 Input_allocate_device

2)设置该输入设备 input_dev

3)注册输入设备

input_register_device(....)

4)报告事件

  Input_event(...)

5)注销输入设备

 Input_unregister_device

6)释放输入设备

 Input_free_device(...)

BSS段、数据段、代码段

可执行程序包括BSS段、数据段、代码段(也称文本段)。

BSSBlock Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。特点是:可读写的,在程序执行之前BSS段会自动清0。所以,未初始的全局变量在程序执行之前已经成0了。

在采用段式内存管理的架构中,数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

代码段(code segment / text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许自修改程序。

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

 

 

------------------------------------------------

Gpio_to_irq

定时器 struct timer_list

spacer.gif

spacer.gif

spacer.gif

spacer.gif

 

 

Ls /dev/event*

 

hexdump /dev/event3

作用:显示设备信息

spacer.gif

序列号     时间值 s    us   事件类型type   事件值code     value   

 

 

 

ls /proc/bus/input

----------------------------------------------------

用户控件open/dev/event0

Input.c

      中的input_fops.open

      {

          .owner =

          .open=

       }

       取得input_dev匹配的handler中的操作函数集合

      New_fops =fops_get(handler->fops)

      把该设备对应的操作函数集合有input重定向为handler中的操作函数集合

       File->f_op=new_fops

       New_fops->open(inode,file);//evdev_open

 

用户空间read

 Sys_readread_write.c

     Vfs_read

File->f_op->read //evdev_read

{

         判断是否要阻塞

       

         Input_event_to_user

}

Input_register_device

List_add_tail()input_dev_list

List_for_each_entry 遍历下

在调用input_attach_handler看看能不能匹配

Match

 

Handler->connecthandler_dev

Event_connect

分配次设备号,创建设备节点的事

查看自己的input

Cat /proc/bus/input/devices

 

什么情况唤醒被阻塞的进程,代码的执行流程

 

 

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/cdev.h>

#include <linux/device.h>

#include <linux/interrupt.h>

#include <linux/stat.h>

#include <linux/slab.h>

 

//#include <linux/unicore.h>

 

#include <linux/gpio.h>

#include <linux/moduleparam.h>

#include <linux/kdev_t.h>

#include <linux/delay.h>

#include <linux/wait.h>

#include <linux/sched.h>

#include <linux/input.h>

 

 

#include <mach/gpio-exynos4.h>

 

#include <asm/gpio.h>

#include <asm/io.h>

 

#include <plat/gpio-cfg.h>

 

MODULE_LICENSE("Dual BSD/GPL");

/*声明是开源的,没有内核版本限制*/

MODULE_AUTHOR("songmao");

/*声明作者*/

#define Base_Address 0x11000000

 

 

struct pins_decs

{

    int irq;

unsigned int pin;

char * name;

unsigned int value;

     

};

 

struct timer_list pin_timer;

 

struct pins_decs pindecs[]={

{IRQ_EINT10,EXYNOS4_GPX1(2),"my_firstPin",KEY_UP},

};

 

volatile struct pins_decs *irq_pd=NULL;

 

 

static struct input_dev *my_input =NULL;

 

volatile unsigned int __iomem *gph0_base=NULL;

static irqreturn_t inputs_handler (int irq,void *dev_id)

{

      irq_pd=(volatile struct pins_decs *) dev_id;

 

  mod_timer(&pin_timer,jiffies+HZ/100);

  

  return IRQ_HANDLED;

}

 

static void pin_timer_function(unsigned int data)

{

     unsigned int pinval = 0;

 struct pins_decs *pinsdecs = (volatile struct pins_decs *)irq_pd;

 

 unsigned int con_tmp =0;

 

 volatile unsigned int __iomem *gph0_con = gph0_base;

 volatile unsigned int __iomem *gph0_dat= gph0_base+1;

 volatile unsigned int __iomem *gph0_pud= gph0_base+2;

 if(!pinsdecs)

 return 0;

 

 con_tmp = *gph0_con;

 

 *gph0_con &= ~(0x0f << 4);

 

 pinval = *gph0_dat&(0x01 << 1);

 

 *gph0_con = con_tmp;

 

 if(pinval)

 {

        input_event(my_input,EV_KEY,pindecs[0].value,0);

   input_event(my_input,EV_SYN,0,0);

 }

 else{

       input_event(my_input,EV_KEY,pindecs[0].value,1);

   input_event(my_input,EV_SYN,0,0);

 }

 

}

 

static int __init init_myinput(void)

{

   int ret =0;

   gph0_base = ioremap( Base_Address + 0x0C20,12);

   

   my_input=input_allocate_device();

   if(my_input==NULL)

   {

        printk(KERN_ERR "Myinput:Failure to input_allocate_device");

 

 goto fail_input_allocate_device;

   }

   set_bit(EV_KEY,my_input->evbit);

   set_bit(EV_SYN,my_input->evbit);

   set_bit(KEY_UP,my_input->keybit);

 

   my_input->name="myf_input";

 

   ret= input_register_device(my_input);

   if(ret!=0){

        printk(KERN_ERR"Myinput:Failure to input_register_device");

 goto fail_input_register_device;

     }

    ret=request_irq(pindecs[0].irq,inputs_handler,IRQF_TRIGGER_RISING|IRQF_TRIGGER_PROBE,

                pindecs[0].name,pindecs);

if(ret<0){

  printk(KERN_ERR"Myinput:Failure to request_irq");

  goto fail_request_irq;

}

   init_timer(&pin_timer);

   pin_timer.function=pin_timer_function;

   add_timer(&pin_timer);

   

   return 0;

fail_input_allocate_device:

 

   iounmap(gph0_base);

fail_request_irq:

input_unregister_device(&my_input);

fail_input_register_device:

   input_free_device(&my_input);

   return -ENOANO;

}

static void __exit exit_myinput (void)

{

     del_timer(&pin_timer);

 input_unregister_device(&my_input);

 input_free_device(&my_input);

     iounmap(gph0_base);

}

module(init_myinput);

module(exit_myinput);