input子系統

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);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章