#include
#include
#include
#include
#include
#include
#include
#include
#include
#define OK210_KBD "ok210kbd"
#define OK210_KBD_NUM (5)
#define KBD_NONE (0xff)
#define KBD_UP (0)
#define KBD_DOWN (1)
typedef struct _ok210_key{
unsigned int gpio;/*对应gpio口*/
unsigned int irq;/*对应中断*/
int n_key;/*键值*/
}ok210_key;
struct ok210_kbd{
ok210_key keys[OK210_KBD_NUM];
struct timer_list key_timer; /*按键去抖定时器*/
unsigned int key_status; /*按键状态*/
struct input_dev *input;
};
static void ok210_init_kbd_data(struct ok210_kbd *p_kbd)
{
printk("ok210_init_kbd_data p_kbd=%x\n", (unsigned int)p_kbd);
p_kbd->keys[0].gpio = s5pv210_GPH0(3);
p_kbd->keys[1].gpio = S5Pv210_GPH0(4);
p_kbd->keys[2].gpio = S5PV210_GPH0(5);
p_kbd->keys[3].gpio = S5PV210_GPH0(6);
p_kbd->keys[4].gpio = S5PV210_GPH0(7);
p_kbd->keys[0].irq = IRQ_EINT3;
p_kbd->keys[1].irq = IRQ_EINT4;
p_kbd->keys[2].irq = IRQ_EINT5;
p_kbd->keys[3].irq = IRQ_EINT6;
p_kbd->keys[4].irq = IRQ_EINT7;
p_kbd->keys[0].n_key = KEY_0;
p_kbd->keys[1].n_key = KEY_1;
p_kbd->keys[2].n_key = KEY_2;
p_kbd->keys[3].n_key = KEY_3;
p_kbd->keys[4].n_key = KEY_4;
}
struct ok210_kbd *p_ok210_kbd;
struct ok210_kbd *get_kbd(void)
{
return p_ok210_kbd;
}
void set_kbd(struct ok210_kbd *p_kbd)
{
p_ok210_kbd = p_kbd;
}
static irqreturn_t ok210_kbd_handler(int irq, void *p_date)
{
unsigned int n_key = 0;
struct ok210_kbd *p_kbd = p_date;
unsigned int key_state = 0;
int i;
for(i = 0; i < OK210_KBD_NUM; i++)
{
if( irq == p_kbd->keys[i].irq )
{
key_state = gpio_get_value(p_kbd->keys[i].gpio);
n_key = p_kbd->keys[i].n_key;
break;
}
}
printk("ok210_kbd_handler n_key=%d, key_state=%d\n", n_key, key_state);
input_report_key(p_kbd->input, n_key, !key_state);/*1表示按下*/
input_sync(p_kbd->input);
return IRQ_HANDLED;
}
static void kbd_free_irqs(void)
{
int i;
struct ok210_kbd *p_kbd = get_kbd();
for(i = 0; i < OK210_KBD_NUM; i++)
free_irq(p_kbd->keys[i].irq, p_kbd);
}
static int kbd_req_irqs(void)
{
int n_ret;
int i;
struct ok210_kbd *p_kbd = get_kbd();
for(i = 0; i < OK210_KBD_NUM; i++)
{
n_ret = request_irq(p_kbd->keys[i].irq, ok210_kbd_handler, IRQ_TYPE_EDGE_BOTH, OK210_KBD, p_kbd);
if(n_ret)
{
printk("%d: could not register interrupt\n", p_kbd->keys[i].irq);
goto fail;
}
}
return n_ret;
fail:
/*因为上面申请失败的那个没有成功,所以也不要释放*/
for(i--; i >= 0; i--)
{
disable_irq(p_kbd->keys[i].irq);
free_irq(p_kbd->keys[i].irq, p_kbd);
}
return n_ret;
}
static int __devinit ok210_keys_probe(struct platform_device *pdev)
{
int err = -ENOMEM;
struct ok210_kbd *p_ok210_keys = NULL;
struct input_dev *input_dev = NULL;
printk("ok210_keys_probe entry!\n");
p_ok210_keys = kmalloc(sizeof(struct ok210_kbd), GFP_KERNEL);
if( !p_ok210_keys )
{
printk("ok210_keys_probe kmalloc error!\n");
return err;
}
ok210_init_kbd_data(p_ok210_keys);
input_dev = input_allocate_device();
if (!input_dev)
{
printk("ok210_keys_probe input_allocate_device error!\n");
goto fail;
}
p_ok210_keys->input = input_dev;
platform_set_drvdata(pdev, p_ok210_keys);
input_dev->name = pdev->name;
input_dev->phys = OK210_KBD"/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(KEY_0, input_dev->keybit);
__set_bit(KEY_1, input_dev->keybit);
__set_bit(KEY_2, input_dev->keybit);
__set_bit(KEY_3, input_dev->keybit);
__set_bit(KEY_5, input_dev->keybit);
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
err = input_register_device(input_dev);
if( err )
{
printk("ok210_keys_probe input_register_device error!\n");
goto fail_allocate;
}
set_kbd(p_ok210_keys);
err = kbd_req_irqs();
if( err )
{
printk("ok210_keys_probe kbd_req_irqs error!\n");
goto fail_register;
}
return 0;
fail_register:
input_unregister_device(input_dev);
goto fail;
fail_allocate:
input_free_device(input_dev);
fail:
kfree(p_ok210_keys);
return err;
}
static int __devexit ok210_keys_remove(struct platform_device *pdev)
{
struct ok210_kbd *p_ok210_keys = platform_get_drvdata(pdev);
kbd_free_irqs();
input_unregister_device(p_ok210_keys->input);
kfree(p_ok210_keys);
return 0;
}
static void ok210_keys_release(struct device *dev)
{
dev = dev;
}
static struct platform_driver ok210_keys_device_driver = {
.probe = ok210_keys_probe,
.remove = __devexit_p(ok210_keys_remove),
.driver = {
.name = OK210_KBD,
.owner = THIS_MODULE,
}
};
static struct platform_device ok210_device_kbd = {
.name = OK210_KBD,
.id = -1,
.dev = {
.release = ok210_keys_release,
}
};
static int __init ok210_keys_init(void)
{
int n_ret;
printk("ok210_keys_init\n");
n_ret = platform_driver_register(&ok210_keys_device_driver);
if( n_ret )
return n_ret;
n_ret = platform_device_register(&ok210_device_kbd);
if( n_ret )
goto fail;
return n_ret;
fail:
platform_driver_unregister(&ok210_keys_device_driver);
return n_ret;
}
static void __exit ok210_keys_exit(void)
{
printk("ok210_keys_exit\n");
platform_device_unregister(&ok210_device_kbd);
platform_driver_unregister(&ok210_keys_device_driver);
}
module_init(ok210_keys_init);
module_exit(ok210_keys_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("gjianw217@163.com");
MODULE_DESCRIPTION("ok210 keyboard input events driver");