| /* drivers/input/misc/gpio_output.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/kernel.h> |
| #include <linux/gpio.h> |
| #include <linux/gpio_event.h> |
| |
| int gpio_event_output_event( |
| struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, |
| void **data, unsigned int dev, unsigned int type, |
| unsigned int code, int value) |
| { |
| int i; |
| struct gpio_event_output_info *oi; |
| oi = container_of(info, struct gpio_event_output_info, info); |
| if (type != oi->type) |
| return 0; |
| if (!(oi->flags & GPIOEDF_ACTIVE_HIGH)) |
| value = !value; |
| for (i = 0; i < oi->keymap_size; i++) |
| if (dev == oi->keymap[i].dev && code == oi->keymap[i].code) |
| gpio_set_value(oi->keymap[i].gpio, value); |
| return 0; |
| } |
| |
| int gpio_event_output_func( |
| struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, |
| void **data, int func) |
| { |
| int ret; |
| int i; |
| struct gpio_event_output_info *oi; |
| oi = container_of(info, struct gpio_event_output_info, info); |
| |
| if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) |
| return 0; |
| |
| if (func == GPIO_EVENT_FUNC_INIT) { |
| int output_level = !(oi->flags & GPIOEDF_ACTIVE_HIGH); |
| |
| for (i = 0; i < oi->keymap_size; i++) { |
| int dev = oi->keymap[i].dev; |
| if (dev >= input_devs->count) { |
| pr_err("gpio_event_output_func: bad device " |
| "index %d >= %d for key code %d\n", |
| dev, input_devs->count, |
| oi->keymap[i].code); |
| ret = -EINVAL; |
| goto err_bad_keymap; |
| } |
| input_set_capability(input_devs->dev[dev], oi->type, |
| oi->keymap[i].code); |
| } |
| |
| for (i = 0; i < oi->keymap_size; i++) { |
| ret = gpio_request(oi->keymap[i].gpio, |
| "gpio_event_output"); |
| if (ret) { |
| pr_err("gpio_event_output_func: gpio_request " |
| "failed for %d\n", oi->keymap[i].gpio); |
| goto err_gpio_request_failed; |
| } |
| ret = gpio_direction_output(oi->keymap[i].gpio, |
| output_level); |
| if (ret) { |
| pr_err("gpio_event_output_func: " |
| "gpio_direction_output failed for %d\n", |
| oi->keymap[i].gpio); |
| goto err_gpio_direction_output_failed; |
| } |
| } |
| return 0; |
| } |
| |
| ret = 0; |
| for (i = oi->keymap_size - 1; i >= 0; i--) { |
| err_gpio_direction_output_failed: |
| gpio_free(oi->keymap[i].gpio); |
| err_gpio_request_failed: |
| ; |
| } |
| err_bad_keymap: |
| return ret; |
| } |
| |