linux/drivers/staging/dream/gpio_event.c
<<
>>
Prefs
   1/* drivers/input/misc/gpio_event.c
   2 *
   3 * Copyright (C) 2007 Google, Inc.
   4 *
   5 * This software is licensed under the terms of the GNU General Public
   6 * License version 2, as published by the Free Software Foundation, and
   7 * may be copied, distributed, and modified under those terms.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 */
  15
  16#include <linux/earlysuspend.h>
  17#include <linux/module.h>
  18#include <linux/input.h>
  19#include <linux/gpio_event.h>
  20#include <linux/hrtimer.h>
  21#include <linux/platform_device.h>
  22
  23struct gpio_event {
  24        struct input_dev *input_dev;
  25        const struct gpio_event_platform_data *info;
  26        struct early_suspend early_suspend;
  27        void *state[0];
  28};
  29
  30static int gpio_input_event(
  31        struct input_dev *dev, unsigned int type, unsigned int code, int value)
  32{
  33        int i;
  34        int ret = 0;
  35        int tmp_ret;
  36        struct gpio_event_info **ii;
  37        struct gpio_event *ip = input_get_drvdata(dev);
  38
  39        for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
  40                if ((*ii)->event) {
  41                        tmp_ret = (*ii)->event(ip->input_dev, *ii,
  42                                        &ip->state[i], type, code, value);
  43                        if (tmp_ret)
  44                                ret = tmp_ret;
  45                }
  46        }
  47        return ret;
  48}
  49
  50static int gpio_event_call_all_func(struct gpio_event *ip, int func)
  51{
  52        int i;
  53        int ret;
  54        struct gpio_event_info **ii;
  55
  56        if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) {
  57                ii = ip->info->info;
  58                for (i = 0; i < ip->info->info_count; i++, ii++) {
  59                        if ((*ii)->func == NULL) {
  60                                ret = -ENODEV;
  61                                pr_err("gpio_event_probe: Incomplete pdata, "
  62                                        "no function\n");
  63                                goto err_no_func;
  64                        }
  65                        ret = (*ii)->func(ip->input_dev, *ii, &ip->state[i],
  66                                          func);
  67                        if (ret) {
  68                                pr_err("gpio_event_probe: function failed\n");
  69                                goto err_func_failed;
  70                        }
  71                }
  72                return 0;
  73        }
  74
  75        ret = 0;
  76        i = ip->info->info_count;
  77        ii = ip->info->info + i;
  78        while (i > 0) {
  79                i--;
  80                ii--;
  81                (*ii)->func(ip->input_dev, *ii, &ip->state[i], func & ~1);
  82err_func_failed:
  83err_no_func:
  84                ;
  85        }
  86        return ret;
  87}
  88
  89#ifdef CONFIG_HAS_EARLYSUSPEND
  90void gpio_event_suspend(struct early_suspend *h)
  91{
  92        struct gpio_event *ip;
  93        ip = container_of(h, struct gpio_event, early_suspend);
  94        gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND);
  95        ip->info->power(ip->info, 0);
  96}
  97
  98void gpio_event_resume(struct early_suspend *h)
  99{
 100        struct gpio_event *ip;
 101        ip = container_of(h, struct gpio_event, early_suspend);
 102        ip->info->power(ip->info, 1);
 103        gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME);
 104}
 105#endif
 106
 107static int __init gpio_event_probe(struct platform_device *pdev)
 108{
 109        int err;
 110        struct gpio_event *ip;
 111        struct input_dev *input_dev;
 112        struct gpio_event_platform_data *event_info;
 113
 114        event_info = pdev->dev.platform_data;
 115        if (event_info == NULL) {
 116                pr_err("gpio_event_probe: No pdata\n");
 117                return -ENODEV;
 118        }
 119        if (event_info->name == NULL ||
 120           event_info->info == NULL ||
 121           event_info->info_count == 0) {
 122                pr_err("gpio_event_probe: Incomplete pdata\n");
 123                return -ENODEV;
 124        }
 125        ip = kzalloc(sizeof(*ip) +
 126                     sizeof(ip->state[0]) * event_info->info_count, GFP_KERNEL);
 127        if (ip == NULL) {
 128                err = -ENOMEM;
 129                pr_err("gpio_event_probe: Failed to allocate private data\n");
 130                goto err_kp_alloc_failed;
 131        }
 132        platform_set_drvdata(pdev, ip);
 133
 134        input_dev = input_allocate_device();
 135        if (input_dev == NULL) {
 136                err = -ENOMEM;
 137                pr_err("gpio_event_probe: Failed to allocate input device\n");
 138                goto err_input_dev_alloc_failed;
 139        }
 140        input_set_drvdata(input_dev, ip);
 141        ip->input_dev = input_dev;
 142        ip->info = event_info;
 143        if (event_info->power) {
 144#ifdef CONFIG_HAS_EARLYSUSPEND
 145                ip->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
 146                ip->early_suspend.suspend = gpio_event_suspend;
 147                ip->early_suspend.resume = gpio_event_resume;
 148                register_early_suspend(&ip->early_suspend);
 149#endif
 150                ip->info->power(ip->info, 1);
 151        }
 152
 153        input_dev->name = ip->info->name;
 154        input_dev->event = gpio_input_event;
 155
 156        err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
 157        if (err)
 158                goto err_call_all_func_failed;
 159
 160        err = input_register_device(input_dev);
 161        if (err) {
 162                pr_err("gpio_event_probe: Unable to register %s input device\n",
 163                        input_dev->name);
 164                goto err_input_register_device_failed;
 165        }
 166
 167        return 0;
 168
 169err_input_register_device_failed:
 170        gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
 171err_call_all_func_failed:
 172        if (event_info->power) {
 173#ifdef CONFIG_HAS_EARLYSUSPEND
 174                unregister_early_suspend(&ip->early_suspend);
 175#endif
 176                ip->info->power(ip->info, 0);
 177        }
 178        input_free_device(input_dev);
 179err_input_dev_alloc_failed:
 180        kfree(ip);
 181err_kp_alloc_failed:
 182        return err;
 183}
 184
 185static int gpio_event_remove(struct platform_device *pdev)
 186{
 187        struct gpio_event *ip = platform_get_drvdata(pdev);
 188
 189        gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
 190        if (ip->info->power) {
 191#ifdef CONFIG_HAS_EARLYSUSPEND
 192                unregister_early_suspend(&ip->early_suspend);
 193#endif
 194                ip->info->power(ip->info, 0);
 195        }
 196        input_unregister_device(ip->input_dev);
 197        kfree(ip);
 198        return 0;
 199}
 200
 201static struct platform_driver gpio_event_driver = {
 202        .probe          = gpio_event_probe,
 203        .remove         = gpio_event_remove,
 204        .driver         = {
 205                .name   = GPIO_EVENT_DEV_NAME,
 206        },
 207};
 208
 209static int __devinit gpio_event_init(void)
 210{
 211        return platform_driver_register(&gpio_event_driver);
 212}
 213
 214static void __exit gpio_event_exit(void)
 215{
 216        platform_driver_unregister(&gpio_event_driver);
 217}
 218
 219module_init(gpio_event_init);
 220module_exit(gpio_event_exit);
 221
 222MODULE_DESCRIPTION("GPIO Event Driver");
 223MODULE_LICENSE("GPL");
 224
 225