From patchwork Wed Nov 11 10:36:08 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 59308 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nABAeTAv029380 for ; Wed, 11 Nov 2009 10:40:30 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756712AbZKKKkY (ORCPT ); Wed, 11 Nov 2009 05:40:24 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755694AbZKKKkY (ORCPT ); Wed, 11 Nov 2009 05:40:24 -0500 Received: from smtp.nokia.com ([192.100.105.134]:20400 "EHLO mgw-mx09.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755853AbZKKKkX (ORCPT ); Wed, 11 Nov 2009 05:40:23 -0500 Received: from esebh106.NOE.Nokia.com (esebh106.ntc.nokia.com [172.21.138.213]) by mgw-mx09.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nABAeMEf004442; Wed, 11 Nov 2009 04:40:27 -0600 Received: from esebh102.NOE.Nokia.com ([172.21.138.183]) by esebh106.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 11 Nov 2009 12:40:25 +0200 Received: from mgw-sa02.ext.nokia.com ([147.243.1.48]) by esebh102.NOE.Nokia.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Wed, 11 Nov 2009 12:40:25 +0200 Received: from localhost.localdomain (esdhcp04137.research.nokia.com [172.21.41.37]) by mgw-sa02.ext.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nABAeLew017341; Wed, 11 Nov 2009 12:40:23 +0200 From: Mika Westerberg To: dmitry.torokhov@gmail.com Cc: linux-input@vger.kernel.org Subject: [RFC PATCH 2/2] Input: gpio-keys: implemented support for enabling/disabling gpios Date: Wed, 11 Nov 2009 12:36:08 +0200 Message-Id: <9b012ed801479acf5d4cbdf29292fdfc937d5e07.1257931659.git.ext-mika.1.westerberg@nokia.com> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: References: <1257929573.21596.960.camel@localhost> In-Reply-To: References: X-OriginalArrivalTime: 11 Nov 2009 10:40:25.0321 (UTC) FILETIME=[60A36D90:01CA62BB] X-Nokia-AV: Clean Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 8941a8b..d9b492e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -30,10 +30,12 @@ struct gpio_button_data { struct input_dev *input; struct timer_list timer; struct work_struct work; + u8 state; /* event state */ }; struct gpio_keys_drvdata { struct input_dev *input; + struct gpio_keys_platform_data *pdata; struct gpio_button_data data[0]; }; @@ -73,6 +75,69 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static int gpio_keys_get_event_state(struct input_dev *dev, + struct input_event_state *st) +{ + const struct gpio_keys_drvdata *ddata = input_get_drvdata(dev); + const struct gpio_keys_platform_data *pdata = ddata->pdata; + int i; + + for (i = 0; i < pdata->nbuttons; i++) { + const struct gpio_keys_button *button = &pdata->buttons[i]; + const struct gpio_button_data *bdata = &ddata->data[i]; + + if (button->code == st->code && button->type == st->type) { + st->state = bdata->state; + return 0; + } + } + return -EINVAL; +} + +/* + * This function is used to enable/disable hardware interrupts from + * GPIO lines that are aggregated into single gpio-keys input device. + */ +static int gpio_keys_set_event_state(struct input_dev *dev, + const struct input_event_state *st) +{ + struct gpio_keys_drvdata *ddata = input_get_drvdata(dev); + struct gpio_keys_platform_data *pdata = ddata->pdata; + int i; + + for (i = 0; i < pdata->nbuttons; i++) { + struct gpio_keys_button *button = &pdata->buttons[i]; + struct gpio_button_data *bdata = &ddata->data[i]; + + if (button->code == st->code && button->type == st->type) { + switch (st->state) { + case EVENT_STATE_DISABLE: + if (bdata->state == EVENT_STATE_ENABLE) { + bdata->state = EVENT_STATE_DISABLE; + /* + * Disable physical irq line. This is + * enough also for keeping device from + * waking up during sleep so no need + * to change wakeup flags for this irq. + */ + disable_irq(gpio_to_irq(button->gpio)); + } + break; + case EVENT_STATE_ENABLE: + if (bdata->state == EVENT_STATE_DISABLE) { + bdata->state = EVENT_STATE_ENABLE; + enable_irq(gpio_to_irq(button->gpio)); + } + break; + default: + return -EINVAL; + } + return 0; + } + } + return -EINVAL; +} + static int __devinit gpio_keys_setup_key(struct device *dev, struct gpio_button_data *bdata, struct gpio_keys_button *button) @@ -154,11 +219,19 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) input->id.product = 0x0001; input->id.version = 0x0100; + /* + * We support setting/getting event state ioctl. + */ + input->get_event_state = gpio_keys_get_event_state; + input->set_event_state = gpio_keys_set_event_state; + input_set_drvdata(input, ddata); + /* Enable auto repeat feature of Linux input subsystem */ if (pdata->rep) __set_bit(EV_REP, input->evbit); ddata->input = input; + ddata->pdata = pdata; for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; @@ -167,6 +240,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) bdata->input = input; bdata->button = button; + bdata->state = EVENT_STATE_ENABLE; /* enabled by default */ error = gpio_keys_setup_key(dev, bdata, button); if (error) @@ -200,6 +274,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); fail1: + input_set_drvdata(input, NULL); input_free_device(input); kfree(ddata);