123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /* drivers/input/misc/gpio_event.c
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/module.h>
- #include <linux/input.h>
- #include <linux/gpio_event.h>
- #include <linux/hrtimer.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- struct gpio_event {
- struct gpio_event_input_devs *input_devs;
- const struct gpio_event_platform_data *info;
- void *state[0];
- };
- static int gpio_input_event(
- struct input_dev *dev, unsigned int type, unsigned int code, int value)
- {
- int i;
- int devnr;
- int ret = 0;
- int tmp_ret;
- struct gpio_event_info **ii;
- struct gpio_event *ip = input_get_drvdata(dev);
- for (devnr = 0; devnr < ip->input_devs->count; devnr++)
- if (ip->input_devs->dev[devnr] == dev)
- break;
- if (devnr == ip->input_devs->count) {
- pr_err("gpio_input_event: unknown device %p\n", dev);
- return -EIO;
- }
- for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
- if ((*ii)->event) {
- tmp_ret = (*ii)->event(ip->input_devs, *ii,
- &ip->state[i],
- devnr, type, code, value);
- if (tmp_ret)
- ret = tmp_ret;
- }
- }
- return ret;
- }
- static int gpio_event_call_all_func(struct gpio_event *ip, int func)
- {
- int i;
- int ret;
- struct gpio_event_info **ii;
- if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) {
- ii = ip->info->info;
- for (i = 0; i < ip->info->info_count; i++, ii++) {
- if ((*ii)->func == NULL) {
- ret = -ENODEV;
- pr_err("gpio_event_probe: Incomplete pdata, "
- "no function\n");
- goto err_no_func;
- }
- if (func == GPIO_EVENT_FUNC_RESUME && (*ii)->no_suspend)
- continue;
- ret = (*ii)->func(ip->input_devs, *ii, &ip->state[i],
- func);
- if (ret) {
- pr_err("gpio_event_probe: function failed\n");
- goto err_func_failed;
- }
- }
- return 0;
- }
- ret = 0;
- i = ip->info->info_count;
- ii = ip->info->info + i;
- while (i > 0) {
- i--;
- ii--;
- if ((func & ~1) == GPIO_EVENT_FUNC_SUSPEND && (*ii)->no_suspend)
- continue;
- (*ii)->func(ip->input_devs, *ii, &ip->state[i], func & ~1);
- err_func_failed:
- err_no_func:
- ;
- }
- return ret;
- }
- static void __maybe_unused gpio_event_suspend(struct gpio_event *ip)
- {
- gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND);
- if (ip->info->power)
- ip->info->power(ip->info, 0);
- }
- static void __maybe_unused gpio_event_resume(struct gpio_event *ip)
- {
- if (ip->info->power)
- ip->info->power(ip->info, 1);
- gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME);
- }
- static int gpio_event_probe(struct platform_device *pdev)
- {
- int err;
- struct gpio_event *ip;
- struct gpio_event_platform_data *event_info;
- int dev_count = 1;
- int i;
- int registered = 0;
- event_info = pdev->dev.platform_data;
- if (event_info == NULL) {
- pr_err("gpio_event_probe: No pdata\n");
- return -ENODEV;
- }
- if ((!event_info->name && !event_info->names[0]) ||
- !event_info->info || !event_info->info_count) {
- pr_err("gpio_event_probe: Incomplete pdata\n");
- return -ENODEV;
- }
- if (!event_info->name)
- while (event_info->names[dev_count])
- dev_count++;
- ip = kzalloc(sizeof(*ip) +
- sizeof(ip->state[0]) * event_info->info_count +
- sizeof(*ip->input_devs) +
- sizeof(ip->input_devs->dev[0]) * dev_count, GFP_KERNEL);
- if (ip == NULL) {
- err = -ENOMEM;
- pr_err("gpio_event_probe: Failed to allocate private data\n");
- goto err_kp_alloc_failed;
- }
- ip->input_devs = (void*)&ip->state[event_info->info_count];
- platform_set_drvdata(pdev, ip);
- for (i = 0; i < dev_count; i++) {
- struct input_dev *input_dev = input_allocate_device();
- if (input_dev == NULL) {
- err = -ENOMEM;
- pr_err("gpio_event_probe: "
- "Failed to allocate input device\n");
- goto err_input_dev_alloc_failed;
- }
- input_set_drvdata(input_dev, ip);
- input_dev->name = event_info->name ?
- event_info->name : event_info->names[i];
- input_dev->event = gpio_input_event;
- ip->input_devs->dev[i] = input_dev;
- }
- ip->input_devs->count = dev_count;
- ip->info = event_info;
- if (event_info->power)
- ip->info->power(ip->info, 1);
- err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
- if (err)
- goto err_call_all_func_failed;
- for (i = 0; i < dev_count; i++) {
- err = input_register_device(ip->input_devs->dev[i]);
- if (err) {
- pr_err("gpio_event_probe: Unable to register %s "
- "input device\n", ip->input_devs->dev[i]->name);
- goto err_input_register_device_failed;
- }
- registered++;
- }
- return 0;
- err_input_register_device_failed:
- gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
- err_call_all_func_failed:
- if (event_info->power)
- ip->info->power(ip->info, 0);
- for (i = 0; i < registered; i++)
- input_unregister_device(ip->input_devs->dev[i]);
- for (i = dev_count - 1; i >= registered; i--) {
- input_free_device(ip->input_devs->dev[i]);
- err_input_dev_alloc_failed:
- ;
- }
- kfree(ip);
- err_kp_alloc_failed:
- return err;
- }
- static int gpio_event_remove(struct platform_device *pdev)
- {
- struct gpio_event *ip = platform_get_drvdata(pdev);
- int i;
- gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
- if (ip->info->power)
- ip->info->power(ip->info, 0);
- for (i = 0; i < ip->input_devs->count; i++)
- input_unregister_device(ip->input_devs->dev[i]);
- kfree(ip);
- return 0;
- }
- static struct platform_driver gpio_event_driver = {
- .probe = gpio_event_probe,
- .remove = gpio_event_remove,
- .driver = {
- .name = GPIO_EVENT_DEV_NAME,
- },
- };
- static int __devinit gpio_event_init(void)
- {
- return platform_driver_register(&gpio_event_driver);
- }
- static void __exit gpio_event_exit(void)
- {
- platform_driver_unregister(&gpio_event_driver);
- }
- module_init(gpio_event_init);
- module_exit(gpio_event_exit);
- MODULE_DESCRIPTION("GPIO Event Driver");
- MODULE_LICENSE("GPL");
|