1、内核配置:
Device Drivers ->
input device support ->
[*] keyboards ->
[*] GPIO buttons ->
2、添加硬件信息:
修改文件 /arch/arm/mach-omap2/board-omap4panda.c
#include
第二处:
static struct gpio_keys_button pandaboard_exp_gpio_keys[] = {
{
.code = KEY_HOME, //按键码,需要预先定义
.gpio = 36, //使用的GPIO口
.active_low = 1,
.desc = "pandaboard_exp_power",
.type = EV_KEY, //类型
.wakeup = 1,
.debounce_interval = 10, //去抖
},
{
.code = KEY_PROG1,
.gpio = 32,
.active_low = 1,
.desc = "pandaboard_exp_menu",
.type = EV_KEY,
.wakeup = 1,
.debounce_interval = 10,
},
{
.code = KEY_PROG2,
.gpio = 38,
.active_low = 1,
.desc = "pandaboard_exp_back",
.type = EV_KEY,
.wakeup = 1,
.debounce_interval = 10,
},
{
.code = KEY_PROG3,
.gpio = 33,
.active_low = 1,
.desc = "pandaboard_exp_volup",
.type = EV_KEY,
.wakeup = 1,
.debounce_interval = 10,
},
{
.code = KEY_PROG4,
.gpio = 37,
.active_low = 1,
.desc = "pandaboard_exp_voldw",
.type = EV_KEY,
.wakeup = 1,
.debounce_interval = 10,
},
};
static struct gpio_keys_platform_data pandaboard_exp_gpio_keys_data = {
.buttons = pandaboard_exp_gpio_keys,
.nbuttons = ARRAY_SIZE(pandaboard_exp_gpio_keys),
};
static struct platform_device pandaboard_exp_gpio_keys_device = {
.name = "gpio-keys", //平台设备的名称
.id = -1,
.dev = {
.platform_data = &pandaboard_exp_gpio_keys_data,
},
};
static struct platform_device *panda_devices[] __initdata = {
&pandaboard_exp_gpio_keys_device, //加入到系统平台设备数组中
&wl1271_device,
&btwilink_device,
};
#include
#include
#include
#include
#include
#include
#include
#include
int main(void)
{
int key_fd;
int key_value,i=0,count;
struct input_event ev_key;
key_fd = open("/dev/event1", O_RDWR);
if (key_fd < 0) {
perror("open device keys");
exit(1);
}
while (1) {
count = read(key_fd,&ev_key,sizeof(struct input_event));
for(i=0; i<(int)count/sizeof(struct input_event); i++){
if(EV_KEY==ev_key.type)
printf("type:%d, code:%d, value:%d", ev_key.type, ev_key.code, ev_key.value);
}
}
close(key_fd);
return 0;
}
代码位置:/drivers/input/keyboard/gpio_keys.c
static int __init gpio_keys_init(void)
{
return platform_driver_register(&gpio_keys_device_driver); //注册平台驱动
}
static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe, //探测函数,在驱动找到对应的设备时执行
.remove = __devexit_p(gpio_keys_remove),
.driver = {
.name = "gpio-keys", //驱动名称 ,可以在 /sys/ 下找到
.owner = THIS_MODULE,
.pm = &gpio_keys_pm_ops, //操作函数集
.of_match_table = gpio_keys_of_match,
}
};
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; //获取平台设备的相关数据
struct gpio_keys_drvdata *ddata;
struct device *dev = &pdev->dev;
struct gpio_keys_platform_data alt_pdata;
struct input_dev *input;
int i, error;
int wakeup = 0;
if (!pdata) {
error = gpio_keys_get_devtree_pdata(dev, &alt_pdata);
if (error)
return error;
pdata = &alt_pdata;
}
ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + pdata->nbuttons * sizeof(struct gpio_button_data),GFP_KERNEL);
input = input_allocate_device(); //分配一个输入设备结构体
if (!ddata || !input) {
dev_err(dev, "failed to allocate state\n");
error = -ENOMEM;
goto fail1;
}
//对驱动结构体赋值
ddata->input = input;
ddata->n_buttons = pdata->nbuttons;
ddata->enable = pdata->enable;
ddata->disable = pdata->disable;
mutex_init(&ddata->disable_lock);
platform_set_drvdata(pdev, ddata);
input_set_drvdata(input, ddata);
//对输入设备机构体进行赋值,这些值都可以在系统启动后在 /sys/ 下找到对应项
input->name = pdata->name ? : pdev->name;
input->phys = "gpio-keys/input0";
input->dev.parent = &pdev->dev;
input->open = gpio_keys_open;
input->close = gpio_keys_close;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
// 依次对每个按键进行设置
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
unsigned int type = button->type ?: EV_KEY;
bdata->input = input;
bdata->button = button;
//设置按键,相当于初始化,主要工作是申请gpio、设置为输入、设置防抖动时间、中断申请
error = gpio_keys_setup_key(pdev, bdata, button);
if (error)
goto fail2;
if (button->wakeup)
wakeup = 1;
input_set_capability(input, type, button->code); //对输入设备进行类型和码的设置,
}
error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); //设置属性并创建接口
if (error) {
dev_err(dev, "Unable to export keys/switches, error: %d\n",error);
goto fail2;
}
error = input_register_device(input); //注册输入设备
if (error) {
dev_err(dev, "Unable to register input device, error: %d\n",error);
goto fail3;
}
/* get current state of buttons */
for (i = 0; i < pdata->nbuttons; i++) //报告事件
gpio_keys_report_event(&ddata->data[i]);
input_sync(input);
device_init_wakeup(&pdev->dev, wakeup);
return 0;
fail3:
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
fail2:
while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
if (ddata->data[i].timer_debounce)
del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio);
}
platform_set_drvdata(pdev, NULL);
fail1:
input_free_device(input);
kfree(ddata);
/* If we have no platform_data, we allocated buttons dynamically. */
if (!pdev->dev.platform_data)
kfree(pdata->buttons);
return error;
}
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
struct gpio_button_data *bdata = dev_id;
struct gpio_keys_button *button = bdata->button;
BUG_ON(irq != gpio_to_irq(button->gpio));
if (bdata->timer_debounce)
mod_timer(&bdata->timer,jiffies + msecs_to_jiffies(bdata->timer_debounce));
else
schedule_work(&bdata->work);
return IRQ_HANDLED;
}