From: Gabor Juhos Date: Mon, 7 Apr 2008 19:54:44 +0000 (+0000) Subject: [kernel] add a polled GPIO buttons input driver X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;h=f905ced306847ad79348e0489ef1a56f25cc65e3 [kernel] add a polled GPIO buttons input driver SVN-Revision: 10766 --- diff --git a/package/kernel/modules/other.mk b/package/kernel/modules/other.mk index 03d2f0de6d..921cebf4cf 100644 --- a/package/kernel/modules/other.mk +++ b/package/kernel/modules/other.mk @@ -497,6 +497,40 @@ endef $(eval $(call KernelPackage,input-evdev)) +define KernelPackage/input-polldev + SUBMENU:=$(OTHER_MENU) + TITLE:=Polled Input device support + DEPENDS:=+kmod-input-core @LINUX_2_6 + KCONFIG:=CONFIG_INPUT_POLLDEV + FILES:=$(LINUX_DIR)/drivers/input/input-polldev.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,61,input-polldev) +endef + +define KernelPackage/input-polldev/description + Kernel module for support of polled input devices +endef + +$(eval $(call KernelPackage,input-polldev)) + + +define KernelPackage/input-gpio-buttons + SUBMENU:=$(OTHER_MENU) + TITLE:=Polled GPIO buttons input device + DEPENDS:=+kmod-input-polldev @LINUX_2_6 + KCONFIG:= \ + CONFIG_INPUT_GPIO_BUTTONS \ + CONFIG_INPUT_MISC=y + FILES:=$(LINUX_DIR)/drivers/input/misc/gpio_buttons.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,62,gpio_buttons) +endef + +define KernelPackage/input-gpio-buttons/description + Kernel module for support polled GPIO buttons input device +endef + +$(eval $(call KernelPackage,input-gpio-buttons)) + + define KernelPackage/mmc-spi SUBMENU:=$(OTHER_MENU) TITLE:=MMC/SD over SPI Support diff --git a/target/linux/generic-2.6/files/drivers/input/misc/gpio_buttons.c b/target/linux/generic-2.6/files/drivers/input/misc/gpio_buttons.c new file mode 100644 index 0000000000..0d219ff7cb --- /dev/null +++ b/target/linux/generic-2.6/files/drivers/input/misc/gpio_buttons.c @@ -0,0 +1,206 @@ +/* + * Driver for buttons on GPIO lines not capable of generating interrupts + * + * Copyright (C) 2007,2008 Gabor Juhos + * + * This file was based on: /drivers/input/misc/cobalt_btns.c + * Copyright (C) 2007 Yoichi Yuasa + * + * also was based on: /drivers/input/keyboard/gpio_keys.c + * Copyright 2005 Phil Blundell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#define DRV_NAME "gpio-buttons" +#define DRV_VERSION "0.1.0" +#define PFX DRV_NAME ": " + +struct gpio_buttons_dev { + struct input_polled_dev *poll_dev; + struct gpio_buttons_platform_data *pdata; +}; + +static void gpio_buttons_poll(struct input_polled_dev *dev) +{ + struct gpio_buttons_dev *bdev = dev->private; + struct gpio_buttons_platform_data *pdata = bdev->pdata; + struct input_dev *input = dev->input; + int i; + + for (i = 0; i < bdev->pdata->nbuttons; i++) { + struct gpio_button *button = &pdata->buttons[i]; + unsigned int type = button->type ?: EV_KEY; + int state; + + state = gpio_get_value(button->gpio) ? 1 : 0; + state ^= button->active_low; + + if (state) { + button->count++; + } else { + if (button->count >= button->threshold) { + input_event(input, type, button->code, 1); + input_sync(input); + } + button->count = 0; + } + + if (button->count == button->threshold) { + input_event(input, type, button->code, 0); + input_sync(input); + } + } +} + +static int __devinit gpio_buttons_probe(struct platform_device *pdev) +{ + struct gpio_buttons_platform_data *pdata = pdev->dev.platform_data; + struct gpio_buttons_dev *bdev; + struct input_polled_dev *poll_dev; + struct input_dev *input; + int error, i; + + + if (!pdata) + return -ENXIO; + + bdev = kzalloc(sizeof(*bdev), GFP_KERNEL); + if (!bdev) { + pr_err(DRV_NAME "no memory for device\n"); + return -ENOMEM; + } + + poll_dev = input_allocate_polled_device(); + if (!poll_dev) { + pr_err(DRV_NAME "no memory for polled device\n"); + error = -ENOMEM; + goto err_free_bdev; + } + + poll_dev->private = bdev; + poll_dev->poll = gpio_buttons_poll; + poll_dev->poll_interval = pdata->poll_interval; + + input = poll_dev->input; + + input->evbit[0] = BIT_MASK(EV_KEY); + input->name = pdev->name; + input->phys = "gpio-buttons/input0"; + input->dev.parent = &pdev->dev; + + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0100; + + for (i = 0; i < pdata->nbuttons; i++) { + struct gpio_button *button = &pdata->buttons[i]; + unsigned int gpio = button->gpio; + unsigned int type = button->type ?: EV_KEY; + + error = gpio_request(gpio, button->desc ? + button->desc : DRV_NAME); + if (error) { + pr_err(PFX "unable to claim gpio %u, error %d\n", + gpio, error); + goto err_free_gpio; + } + + error = gpio_direction_input(gpio); + if (error) { + pr_err(PFX "unable to set direction on gpio %u, " + "error %d\n", gpio, error); + goto err_free_gpio; + } + + input_set_capability(input, type, button->code); + button->count = 0; + } + + bdev->poll_dev = poll_dev; + bdev->pdata = pdata; + platform_set_drvdata(pdev, bdev); + + error = input_register_polled_device(poll_dev); + if (error) { + pr_err(PFX "unable to register polled device, error %d\n", + error); + goto err_free_gpio; + } + + return 0; + +err_free_gpio: + for (i = i - 1; i >= 0; i--) + gpio_free(pdata->buttons[i].gpio); + + input_free_polled_device(poll_dev); + +err_free_bdev: + kfree(bdev); +err: + platform_set_drvdata(pdev, NULL); + return error; +} + +static int __devexit gpio_buttons_remove(struct platform_device *pdev) +{ + struct gpio_buttons_dev *bdev = platform_get_drvdata(pdev); + struct gpio_buttons_platform_data *pdata = bdev->pdata; + int i; + + input_unregister_polled_device(bdev->poll_dev); + + for (i = 0; i < pdata->nbuttons; i++) + gpio_free(pdata->buttons[i].gpio); + + input_free_polled_device(bdev->poll_dev); + + kfree(bdev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver gpio_buttons_driver = { + .probe = gpio_buttons_probe, + .remove = __devexit_p(gpio_buttons_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init gpio_buttons_init(void) +{ + pr_info(DRV_NAME " driver version " DRV_VERSION "\n"); + return platform_driver_register(&gpio_buttons_driver); +} + +static void __exit gpio_buttons_exit(void) +{ + platform_driver_unregister(&gpio_buttons_driver); +} + +module_init(gpio_buttons_init); +module_exit(gpio_buttons_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("Polled buttons driver for CPU GPIOs"); + diff --git a/target/linux/generic-2.6/files/include/linux/gpio_buttons.h b/target/linux/generic-2.6/files/include/linux/gpio_buttons.h new file mode 100644 index 0000000000..f5e6297258 --- /dev/null +++ b/target/linux/generic-2.6/files/include/linux/gpio_buttons.h @@ -0,0 +1,35 @@ +/* + * Definitions for the GPIO buttons interface driver + * + * Copyright (C) 2007,2008 Gabor Juhos + * + * This file was based on: /include/linux/gpio_keys.h + * The original gpio_keys.h seems not to have a license. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef _GPIO_BUTTONS_H_ +#define _GPIO_BUTTONS_H_ + +struct gpio_button { + int gpio; /* GPIO line number */ + int active_low; + char *desc; /* button description */ + int type; /* input event type (EV_KEY, EV_SW) */ + int code; /* input event code (KEY_*, SW_*) */ + int count; + int threshold; /* count threshold */ +}; + +struct gpio_buttons_platform_data { + struct gpio_button *buttons; + int nbuttons; /* number of buttons */ + int poll_interval; /* polling interval */ +}; + +#endif /* _GPIO_BUTTONS_H_ */ + diff --git a/target/linux/generic-2.6/patches-2.6.22/410-gpio_buttons.patch b/target/linux/generic-2.6/patches-2.6.22/410-gpio_buttons.patch new file mode 100644 index 0000000000..8e215f99d7 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.22/410-gpio_buttons.patch @@ -0,0 +1,30 @@ +--- linux-2.6.22.orig/drivers/input/misc/Kconfig 2007-08-21 06:33:06.000000000 +0200 ++++ linux-2.6.22/drivers/input/misc/Kconfig 2007-10-08 10:57:23.000000000 +0200 +@@ -178,4 +178,20 @@ + Say Y here if you want to support the built-in real time clock + of the HP SDC controller. + ++config INPUT_GPIO_BUTTONS ++ tristate "Polled GPIO buttons interface" ++ depends on GENERIC_GPIO ++ select INPUT_POLLDEV ++ help ++ This driver implements support for buttons connected ++ to GPIO pins of various CPUs (and some other chips). ++ ++ Say Y here if your device has buttons connected ++ directly to such GPIO pins. Your board-specific ++ setup logic must also provide a platform device, ++ with configuration data saying which GPIOs are used. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called gpio-buttons. ++ + endif +--- linux-2.6.22.4.orig/drivers/input/misc/Makefile 2007-08-21 06:33:06.000000000 +0200 ++++ linux-2.6.22.4/drivers/input/misc/Makefile 2007-10-08 10:50:12.000000000 +0200 +@@ -18,3 +18,4 @@ + obj-$(CONFIG_INPUT_YEALINK) += yealink.o + obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o + obj-$(CONFIG_INPUT_UINPUT) += uinput.o ++obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o diff --git a/target/linux/generic-2.6/patches-2.6.23/410-gpio_buttons.patch b/target/linux/generic-2.6/patches-2.6.23/410-gpio_buttons.patch new file mode 100644 index 0000000000..6de5d7040c --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.23/410-gpio_buttons.patch @@ -0,0 +1,30 @@ +--- linux-2.6.23.orig/drivers/input/misc/Kconfig 2007-08-21 06:33:06.000000000 +0200 ++++ linux-2.6.23/drivers/input/misc/Kconfig 2007-10-08 10:57:23.000000000 +0200 +@@ -178,4 +178,20 @@ + Say Y here if you want to support the built-in real time clock + of the HP SDC controller. + ++config INPUT_GPIO_BUTTONS ++ tristate "Polled GPIO buttons interface" ++ depends on GENERIC_GPIO ++ select INPUT_POLLDEV ++ help ++ This driver implements support for buttons connected ++ to GPIO pins of various CPUs (and some other chips). ++ ++ Say Y here if your device has buttons connected ++ directly to such GPIO pins. Your board-specific ++ setup logic must also provide a platform device, ++ with configuration data saying which GPIOs are used. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called gpio-buttons. ++ + endif +--- linux-2.6.23.orig/drivers/input/misc/Makefile 2007-08-21 06:33:06.000000000 +0200 ++++ linux-2.6.23/drivers/input/misc/Makefile 2007-10-08 10:50:12.000000000 +0200 +@@ -18,3 +18,4 @@ + obj-$(CONFIG_INPUT_YEALINK) += yealink.o + obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o + obj-$(CONFIG_INPUT_UINPUT) += uinput.o ++obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o diff --git a/target/linux/generic-2.6/patches-2.6.24/410-gpio_buttons.patch b/target/linux/generic-2.6/patches-2.6.24/410-gpio_buttons.patch new file mode 100644 index 0000000000..03957152af --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.24/410-gpio_buttons.patch @@ -0,0 +1,30 @@ +--- linux-2.6.24.2.orig/drivers/input/misc/Kconfig 2007-08-21 06:33:06.000000000 +0200 ++++ linux-2.6.24.2/drivers/input/misc/Kconfig 2007-10-08 10:57:23.000000000 +0200 +@@ -178,4 +178,20 @@ + Say Y here if you want to support the built-in real time clock + of the HP SDC controller. + ++config INPUT_GPIO_BUTTONS ++ tristate "Polled GPIO buttons interface" ++ depends on GENERIC_GPIO ++ select INPUT_POLLDEV ++ help ++ This driver implements support for buttons connected ++ to GPIO pins of various CPUs (and some other chips). ++ ++ Say Y here if your device has buttons connected ++ directly to such GPIO pins. Your board-specific ++ setup logic must also provide a platform device, ++ with configuration data saying which GPIOs are used. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called gpio-buttons. ++ + endif +--- linux-2.6.24.2.orig/drivers/input/misc/Makefile 2007-08-21 06:33:06.000000000 +0200 ++++ linux-2.6.24.2/drivers/input/misc/Makefile 2007-10-08 10:50:12.000000000 +0200 +@@ -18,3 +18,4 @@ + obj-$(CONFIG_INPUT_YEALINK) += yealink.o + obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o + obj-$(CONFIG_INPUT_UINPUT) += uinput.o ++obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o