驅動程式之驅動程式之_1_字元裝置_9_輸入子系統_2_執行個體
本文中input_handler層使用evdev,在input_dev層編寫按鍵執行個體
基本流程:
1、編寫入口函數,配置設定、設定、注冊input_dev結構體,并且完成硬體初始化
2、編寫出口函數,完成與入口函數相反的操作
3、聲明、定義硬體相關結構體和定時器
4、編寫按鍵中斷服務程式
5、編寫定時器中斷服務程式,定時時間為10ms,用于消抖
6、添加相關頭檔案
附上完整代碼
#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>
/* 結構體的聲明和定義 */
typedef struct{
unsigned char *pucDevName;
int dwIrq;
unsigned long dwIrqFlags;
unsigned int dwPin;
unsigned int dwVal;
}buttons_desc, *pbuttons_desc;
buttons_desc g_tButtonsDesc[4] =
{
{"S2",IRQ_EINT0, IRQT_BOTHEDGE,S3C2410_GPF0 ,KEY_L},
{"S3",IRQ_EINT2, IRQT_BOTHEDGE,S3C2410_GPF2 ,KEY_S},
{"S4",IRQ_EINT11,IRQT_BOTHEDGE,S3C2410_GPG3 ,KEY_ENTER},
{"S5",IRQ_EINT19,IRQT_BOTHEDGE,S3C2410_GPG11,KEY_LEFTSHIFT},
};
static struct input_dev *g_ptButtonsDev;
static struct timer_list g_tButtonsTimer;
static pbuttons_desc g_ptButtonsDescSelect;
/* 定時器中斷服務程式 */
static void buttons_timer_isr(unsigned long data)
{
pbuttons_desc g_ptButtonsDescTmp = g_ptButtonsDescSelect;
if(!g_ptButtonsDescTmp)
return ;
if(s3c2410_gpio_getpin(g_ptButtonsDescTmp->dwPin)) //松開
{
input_event(g_ptButtonsDev,EV_KEY,g_ptButtonsDescTmp->dwVal,0);
input_sync(g_ptButtonsDev);
}
else
{
input_event(g_ptButtonsDev,EV_KEY,g_ptButtonsDescTmp->dwVal,1);
input_sync(g_ptButtonsDev);
}
}
/* 按鍵中斷服務程式 */
static irqreturn_t buttons_isr(int irq, void *dev_id)
{
g_ptButtonsDescSelect = (pbuttons_desc)dev_id;
mod_timer(&g_tButtonsTimer, jiffies + HZ / 100);
return IRQ_RETVAL(IRQ_HANDLED);
}
/* 入口函數 */
static int input_init(void)
{
int i;
int iError;
/* 配置設定設定注冊結構體 */
g_ptButtonsDev = input_allocate_device();
set_bit(EV_KEY, g_ptButtonsDev->evbit);
set_bit(EV_REP, g_ptButtonsDev->evbit);
set_bit(KEY_L, g_ptButtonsDev->keybit);
set_bit(KEY_S, g_ptButtonsDev->keybit);
set_bit(KEY_LEFTSHIFT,g_ptButtonsDev->keybit);
set_bit(KEY_ENTER, g_ptButtonsDev->keybit);
input_register_device(g_ptButtonsDev);
/* 建立定時器并設定其中斷服務程式 */
init_timer(&g_tButtonsTimer);
g_tButtonsTimer.function = buttons_timer_isr;
add_timer(&g_tButtonsTimer);
/* 設定按鍵中斷 */
for(i = 0;i < 4;i++)
iError = request_irq(g_tButtonsDesc[i].dwIrq,buttons_isr,g_tButtonsDesc[i].dwIrqFlags,
g_tButtonsDesc[i].pucDevName,&g_tButtonsDesc[i]);
return 0;
}
/* 出口函數 */
static void input_exit(void)
{
int i;
/* 關閉按鍵中斷 */
for(i = 0;i < 4;i++)
free_irq(g_tButtonsDesc[i].dwIrq,&g_tButtonsDesc[i]);
/* 銷毀定時器 */
del_timer(&g_tButtonsTimer);
/* 銷毀結構體 */
input_unregister_device(g_ptButtonsDev);
}
module_init(input_init);
module_exit(input_exit);
MODULE_LICENSE("GPL");
測試方法:
cat /dev/event*
加載驅動裝置,再次cat /dev/event*,會多出一個event
1、hexdump /dev/event1(event1是加載驅動裝置後新出現的event,根據實際情況修改),按下按鍵會回顯按鍵事件的時間、鍵值碼、類型等資訊
2、cat /dev/tty1,按下字母按鍵,再按下回車按鍵,會回顯字母資訊,由于使能了REP事件,是以按鍵長按有效
3、exec 0</dev/tty1,按下’l’,‘s’,再按下"enter",這時不僅回顯資訊,并且按鍵傳入控制台,效果相當于鍵盤輸入"ls"