/**
* Driver for keys on GPIO using input-subsystem way
*/
Driver Test:
----------------------------------------------------------driver---------------------------------------------------------------
#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>
#define DRIVER_NAME "czinputsubsys_keys"
static struct input_dev *czinput_dev;
//tips: why no static?
struct czkey_desc {
unsigned char * name;
int irq;
int pin;
int code;
};
//gpio_to_irq(S3C2410_GPF1) is wrong!
static struct czkey_desc aczkey_desc[4] = {
{"L", IRQ_EINT1, S3C2410_GPF1, KEY_L},
{"S", IRQ_EINT4, S3C2410_GPF4, KEY_S},
{"ENTER", IRQ_EINT2, S3C2410_GPF2, KEY_ENTER},
{"LEFTSHIFT", IRQ_EINT0, S3C2410_GPF0, KEY_LEFTSHIFT},
};
static irqreturn_t czinputsubsys_keys_isr(int irq, void *dev_id)
{
printk("driver:czinputsubsys_keys_isr in\n");
struct czkey_desc *pczkey_desc = (struct czkey_desc *)dev_id;
int state = (gpio_get_value(pczkey_desc->pin) ? 1 : 0);
// input_event(czinput_dev, czinput_dev->evbit[0], pczkey_desc->code, state);
if(state){
input_event(czinput_dev, EV_KEY, pczkey_desc->code, 1);//untest 2013.01.15
printk("driver:czinputsubsys_keys_isr key state:%d\n",state);
}
else
{
input_event(czinput_dev, EV_KEY, pczkey_desc->code, 0);//untest 2013.01.15
printk("driver:czinputsubsys_keys_isr key state:%d\n",state);
}
input_sync(czinput_dev);
return IRQ_HANDLED;
}
static int czinputsubsys_keys_init(void)
{
printk("driver:czinputsubsys_key_init in\n");
int error;
int i ;
czinput_dev = input_allocate_device();
if (!czinput_dev){
printk(KERN_ERR "Cannot request keypad device\n");
return -ENOMEM;}
else
printk("Can request keypad device\n");
//czinput_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
//czinput_dev->keybit[0] = BIT(KEY_L) | BIT(KEY_S) | BIT(KEY_ENTER) | BIT(KEY_LEFTSHIFT);
//czinput_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
set_bit(EV_KEY, czinput_dev->evbit);//untest 2013.01.15
set_bit(KEY_ENTER, czinput_dev->keybit);
set_bit(KEY_L, czinput_dev->keybit);
set_bit(KEY_S, czinput_dev->keybit);
set_bit(KEY_LEFTSHIFT, czinput_dev->keybit);
czinput_dev->name = DRIVER_NAME;
//czinput_dev->phys = "gpio-keys/input0";
//czinput_dev->dev.parent = &pdev->dev;
//czinput_dev->id.bustype = BUS_HOST;
//czinput_dev->id.vendor = 0x0001;
//czinput_dev->id.product = 0x0001;
//czinput_dev->id.version = 0x0100;
error = input_register_device(czinput_dev);
if (error)
printk(KERN_ERR "Unable to register gpio-keys input device\n");
else
printk(KERN_ERR "able to register gpio-keys input device\n");
//for(i=0;i<4;i++)
// set_irq_type(aczkey_desc[i].irq, IRQ_TYPE_EDGE_BOTH);
//tips: about KERN_ERR?; about IRQF_SAMPLE_RANDOM
//tips: about IRQT_BOTHEDGE is the right way
for(i=0;i<4;i++){
error = request_irq(aczkey_desc[i].irq, czinputsubsys_keys_isr, IRQT_BOTHEDGE,
aczkey_desc[i].name,&aczkey_desc[i]);
if (error)
printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",aczkey_desc[i].irq, error);
else
printk("gpio-keys: able to claim irq %d\n",aczkey_desc[i].irq);
}
return 0;
}
static void czinputsubsys_keys_exit(void)
{
printk("driver:czinputsubsys_key_exit in\n");
int i;
for(i=0;i<4;i++)
free_irq(aczkey_desc[i].irq, &aczkey_desc[i]);
input_unregister_device(czinput_dev);
return;
}
module_init(czinputsubsys_keys_init);
module_exit(czinputsubsys_keys_exit);
MODULE_AUTHOR("chaozang(cz) <zangchao.cn@gmail.com>, copy frm teacher:weidongshan,thanks so much!");
MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
MODULE_LICENSE("GPL");
----------------------------------------------------test commands----------------------------------------------------------
# exec 0</dev/tty1
-------------------------------------------------
Contact: zangchao.cn@gmail.com