keys-input.c
/*
* linux-3.10.27
* arm-linux-gcc-4.5.1
*
* @ keys driver (input subsystem)
* @ ref : gpio_keys.c (drivers\input\keyboard)
*/
#include <linux/module.h>
#include <linux/init.h> /* module_init, ... */
#include <linux/kernel.h> /* everything */
#include <linux/cdev.h> /* cdev_init, ... */
#include <linux/fs.h> /* file_operations, */
#include <linux/device.h> /* class_create,... */
#include <linux/platform_device.h>
#include <linux/slab.h> /* kmalloc, ... */
#include <asm/io.h> /* ioremap,... */
#include <linux/uaccess.h> /* copy_from_user, ... */
#include <linux/irq.h> /* IRQ_EINT(x), ... */
#include <linux/gpio.h>
#include <linux/interrupt.h> /* irq_request(),IRQF_xxx, ... */
#include <linux/input.h>
/*
* GPIO OF KEY FOR SMART210
* K1 - GPH2-0 - EXINT16
* K2 - GPH2-1 - EXINT17
* K3 - GPH2-2 - EXINT18
* K4 - GPH2-3 - EXINT19
* K5 - GPH3-0 - EXINT24
* K6 - GPH3-1 - EXINT25
* K7 - GPH3-2 - EXINT26
* K8 - GPH3-3 - EXINT27
*
* LOW MEANS PRESSED
*
*/
struct keys_data
{
unsigned int pin;
unsigned int irq;
unsigned char key_val;
char *name;
};
static const struct keys_data keys_res[] =
{
{S5PV210_GPH2(0), IRQ_EINT(16),KEY_L, "K1"},
{S5PV210_GPH2(1), IRQ_EINT(17),KEY_S, "K2"},
{S5PV210_GPH2(2), IRQ_EINT(18),KEY_P, "K3"},
{S5PV210_GPH2(3), IRQ_EINT(19),KEY_W, "K4"},
{S5PV210_GPH3(0), IRQ_EINT(24),KEY_T, "K5"},
{S5PV210_GPH3(1), IRQ_EINT(25),KEY_D, "K6"},
{S5PV210_GPH3(2), IRQ_EINT(26),KEY_C, "K7"},
{S5PV210_GPH3(3), IRQ_EINT(27),KEY_ENTER, "K8"},
};
static struct input_dev *keys_dev;
static struct keys_data *pdata;
static struct timer_list keys_timer;
irqreturn_t mykeys_handler(int irq, void *dev_id)
{
pdata = (struct keys_data *)dev_id;
//pr_info("%s pressed.\n", pdata->name);
mod_timer(&keys_timer, jiffies+HZ/100);
return IRQ_RETVAL(IRQ_HANDLED);
}
static void keys_timer_function(unsigned long data)
{
unsigned int pinval;
pinval = gpio_get_value(pdata->pin);
if (pinval){
/* unpressed */
input_event(keys_dev, EV_KEY, pdata->key_val, 0);
input_sync(keys_dev);
}
else {
/* pressed */
input_event(keys_dev, EV_KEY, pdata->key_val, 1);
input_sync(keys_dev);
}
}
static int keys_input_init(void)
{
int ret ,i = 0;
int irq;
pr_info("%s called.\n", __func__);
keys_dev = input_allocate_device();
if (!keys_dev){
return -ENOMEM;
}
keys_dev->name = "mykeys";
keys_dev->id.bustype = BUS_HOST;
keys_dev->id.vendor = 0x0001;
keys_dev->id.product = 0x0001;
keys_dev->id.version = 0x0100;
set_bit(EV_KEY, keys_dev->evbit);
set_bit(EV_REP, keys_dev->evbit);
set_bit(KEY_L, keys_dev->keybit);
set_bit(KEY_S, keys_dev->keybit);
set_bit(KEY_P, keys_dev->keybit);
set_bit(KEY_W, keys_dev->keybit);
set_bit(KEY_T, keys_dev->keybit);
set_bit(KEY_D, keys_dev->keybit);
set_bit(KEY_C, keys_dev->keybit);
set_bit(KEY_ENTER, keys_dev->keybit);
ret = input_register_device(keys_dev);
if (ret){
input_free_device(keys_dev);
return ret;
}
init_timer(&keys_timer);
keys_timer.function = keys_timer_function;
add_timer(&keys_timer);
//gpio_to_irq(unsigned gpio)
for (i = 0; i < 8; i++){
//irq = gpio_to_irq(keys_res[i].pin);
if(request_irq(keys_res[i].irq, mykeys_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
keys_res[i].name, (void *)&keys_res[i]))
break;
}
return 0;
}
static void keys_input_exit(void)
{
int i = 0;
pr_info("%s called.\n", __func__);
for (i = 7; i >= 0 ; i--){
free_irq(keys_res[i].irq, (void *)&keys_res[i]);
}
del_timer(&keys_timer);
input_unregister_device(keys_dev);
input_free_device(keys_dev);
}
module_init(keys_input_init);
module_exit(keys_input_exit);
MODULE_LICENSE("GPL");