Irqreturn
前面程序存在的問題
1)按鍵緩衝區的問題 kbuf[100] r_pos w_pos
2)按鍵值的問題 drive 說明文檔
3)連續按鍵的問題
-------------------------------
input子系統
對於這些只有輸入沒有輸出的設備,該類設備驅動程序中有很多可以公用的代碼(緩衝區,連續按鍵,)
Input子系統解決的問題就是把這些抽象出來的代碼幫我們實現好了直接可以使用了。
input子系統的核心模塊
Drivers/input/input。C
要想使用內核提供的這些公共代碼,我們所要完成的驅動程序就是要遵循一定得框架。
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段、數據段、代碼段(也稱文本段)。
BSS(Block Started by Symbol)通常是指用來存放程序中未初始化的全局變量和靜態變量的一塊內存區域。特點是:可讀寫的,在程序執行之前BSS段會自動清0。所以,未初始的全局變量在程序執行之前已經成0了。
在採用段式內存管理的架構中,數據段(data segment)通常是指用來存放程序中已初始化的全局變量的一塊內存區域。數據段屬於靜態內存分配。
代碼段(code segment / text segment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀, 某些架構也允許代碼段爲可寫,即允許自修改程序。
堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)。
棧又稱堆棧, 是用戶存放程序臨時創建的局部變量,也就是說我們函數括弧“{}”中定義的變量(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值也會被存放回棧中。由於棧的先進後出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。
------------------------------------------------
Gpio_to_irq
定時器 struct timer_list
Ls /dev/event*
hexdump /dev/event3
作用:顯示設備信息
序列號 時間值 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_read(read_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->connect(handler_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);