根據韋東山視頻講解,和自己理解總結的:
1.分配一個input_dev結構體,
2.設置input_dev。
3.註冊input_dev結構體。
4.硬件相關的操作。
/*參考/keyboard/corgikbd.c*/
static int __init corgikbd_init(void)
{
return platform_driver_register(&corgikbd_driver);
}
static struct platform_driver corgikbd_driver = {
.probe = corgikbd_probe,
.remove = __devexit_p(corgikbd_remove),
.suspend = corgikbd_suspend,
.resume = corgikbd_resume,
.driver = {
.name = "corgi-keyboard",
.owner = THIS_MODULE,
},
};
static int __devinit corgikbd_probe(struct platform_device *pdev)
{
struct corgikbd *corgikbd;
struct input_dev *input_dev;
int i, err = -ENOMEM;
corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
/*1.分配一個input_dev結構*/
input_dev = input_allocate_device();
if (!corgikbd || !input_dev)
goto fail;
platform_set_drvdata(pdev, corgikbd);
corgikbd->input = input_dev;
spin_lock_init(&corgikbd->lock);
/* Init Keyboard rescan timer */
init_timer(&corgikbd->timer);
corgikbd->timer.function = corgikbd_timer_callback;
corgikbd->timer.data = (unsigned long) corgikbd;
/* Init Hinge Timer */
init_timer(&corgikbd->htimer);
corgikbd->htimer.function = corgikbd_hinge_timer;
corgikbd->htimer.data = (unsigned long) corgikbd;
corgikbd->suspend_jiffies=jiffies;
(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
input_dev->name = "Corgi Keyboard";
input_dev->phys = "corgikbd/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &pdev->dev;
/*2.設置input_dev*/
/*2.1設置能產生哪些事件 Event types
*EV_KEY 定義爲#define EV_KEY 0x01
*能產生按鍵類事件
*EV_REP 重複,當按下,不松時能產生多個值
*/
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
input_dev->keycode = corgikbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
/*2.2設置能產生這類事件的哪些事件*/
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
set_bit(corgikbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
set_bit(SW_LID, input_dev->swbit);
set_bit(SW_TABLET_MODE, input_dev->swbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
/*3.註冊 input_dev */
err = input_register_device(corgikbd->input);
if (err)
goto fail;
mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
/*4.硬件相關的操作*/
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
/*註冊中斷*/
if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i),corgikbd_interrupt,
IRQF_DISABLED | IRQF_TRIGGER_RISING,"corgikbd",corgikbd))
printk(KERN_WARNING "corgikbd:Can't get IRQ:%d!\n",i);
}
/* Set Strobe lines as outputs - set high */
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i)|GPIO_OUT|GPIO_DFLT_HIGH);
/* Setup the headphone jack as an input */
pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
return 0;
fail: input_free_device(input_dev);
kfree(corgikbd);
return err;
}
下面我們自己下符合輸入子服務系統的程序
/*引腳描述結構體*/
struct pin_dec{
int irq;
char *name;
unsigned int pin;
unsigned int key_val;
};
/*定義的按鍵的四個引腳描述結構體數組*/
struct pin_dec pins_desc[4] = {
{IRQ_EINT1,"s1",S3C2410_GPF1, KEY_L},
{IRQ_EINT4,"s2",S3C2410_GPF4, KEY_S},
{IRQ_EINT2,"s3",S3C2410_GPF2, KEY_ENTER},
{IRQ_EINT0,"s4",S3C2410_GPF0, KEY_LEFTSHIFT},
};
/*定義一個定時器*/
static struct timer_list buttons_timer;
/*入口函數*/
static int buttons_init(void)
{
int i;
/*1.分配一個input_dev結構體*/
buttons_dev = input_allocate_device();
/*2.設置*/
/*2.1能產生的哪類事件*/
buttons_dev->evbit = BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);
/*2.2能產生這類操作裏的哪些事件*/
__set_bit(KEY_L,buttons_dev->keybit);
__set_bit(KEY_S,buttons_dev->keybit);
__set_bit(KEY_ENTER,buttons_dev->keybit);
__set_bit(KEY_LEFTSHIFT,buttons_dev->keybit);
/*3.註冊*/
input_register_device(buttons_dev);
/*4.硬件相關的操作*/
init_timer(&buttons_timer); /*初始化定時器*/
/*指定定時器中斷的處理函數*/
buttons_timer.function = buttons_timer_function;
/*增加一個定時器*/
add_timer(&buttons_timer);
for(i=0;i<4;i++){
/*註冊中斷*/
request_irq(pins_desc[i].irq,buttons_irq,IRQ_TYPE_EDGE_BOTH,pins_desc[i].name,
&pins_desc[i]);
}
return 0;
}
static irqreturn_t buttons_irq(int irq, void *dev_id){
/*10ms後啓動定時器,消抖*/
irq_pd = (struct pin_dec*)dev_id;
/*修改定時器*/
mod_timer(&buttons_timer,jiffies+HZ/100);
return IRQ_RETVAL(IRQ_HANDLED);
}
/*定時器的處理函數*/
static void buttons_timer_function(unsigned long data)
{
struct pin_dec*pindesc = irq_pd;
unsigned int pinval;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if(pinval){
/*上報事件*/
/*也可以用input_report_key(buttons_dev,pindesc->key_val,0)*/
/*鬆開時*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,0);
input_sync(buttons_dev);
}
else
{
/*按下時*/
/*也可以用input_report_key(buttons_dev,pindesc->key_val,1)*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,1);
input_sync(buttons_dev);
}
}
/*出口函數*/
static void buttons_exit(void)
{
int i;
for(i=0;i<4;i++){
/*釋放中斷*/
free_irq(pins_desc[i].irq,&pins_desc[i]);
}
/*吊銷定時器*/
del_timer(&buttons_timer);
/*註銷註冊的buttons_dev*/
input_unregister_device(buttons_dev);
/*釋放掉buttons_dev佔用的內存*/
input_free_device(buttons_dev);
}