diff options
author | Linus Torvalds | 2012-10-02 17:16:10 -0700 |
---|---|---|
committer | Linus Torvalds | 2012-10-02 17:16:10 -0700 |
commit | fc47912d9cda50ae6bd9ca30e97e8c03de5b7b60 (patch) | |
tree | d7da6ce3b23c1524e681ee33aa6e21d3c0586108 | |
parent | 06fe918e9f177dc2a0592b0ad40a6ce4920b2033 (diff) | |
parent | dde3ada3d0069855eeb353707b2b0f946191cfd6 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
"A few drivers were updated with device tree bindings and others got a
few small cleanups and fixes."
Fix trivial conflict in drivers/input/keyboard/omap-keypad.c due to
changes clashing with a whitespace cleanup.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (28 commits)
Input: wacom - mark Intuos5 pad as in-prox when touching buttons
Input: synaptics - adjust threshold for treating position values as negative
Input: hgpk - use %*ph to dump small buffer
Input: gpio_keys_polled - fix dt pdata->nbuttons
Input: Add KD[GS]KBDIACRUC ioctls to the compatible list
Input: omap-keypad - fixed formatting
Input: tegra - move platform data header
Input: wacom - add support for EMR on Cintiq 24HD touch
Input: s3c2410_ts - make s3c_ts_pmops const
Input: samsung-keypad - use of_get_child_count() helper
Input: samsung-keypad - use of_match_ptr()
Input: uinput - fix formatting
Input: uinput - specify exact bit sizes on userspace APIs
Input: uinput - mark failed submission requests as free
Input: uinput - fix race that can block nonblocking read
Input: uinput - return -EINVAL when read buffer size is too small
Input: uinput - take event lock when fetching events from buffer
Input: get rid of MATCH_BIT() macro
Input: rotary-encoder - add DT bindings
Input: rotary-encoder - constify platform data pointers
...
24 files changed, 610 insertions, 287 deletions
diff --git a/Documentation/devicetree/bindings/input/gpio-keys-polled.txt b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt new file mode 100644 index 000000000000..313abefa37cc --- /dev/null +++ b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt @@ -0,0 +1,38 @@ +Device-Tree bindings for input/gpio_keys_polled.c keyboard driver + +Required properties: + - compatible = "gpio-keys-polled"; + - poll-interval: Poll interval time in milliseconds + +Optional properties: + - autorepeat: Boolean, Enable auto repeat feature of Linux input + subsystem. + +Each button (key) is represented as a sub-node of "gpio-keys-polled": +Subnode properties: + + - gpios: OF device-tree gpio specification. + - label: Descriptive name of the key. + - linux,code: Keycode to emit. + +Optional subnode-properties: + - linux,input-type: Specify event type this button/key generates. + If not specified defaults to <1> == EV_KEY. + - debounce-interval: Debouncing interval time in milliseconds. + If not specified defaults to 5. + - gpio-key,wakeup: Boolean, button can wake-up the system. + +Example nodes: + + gpio_keys_polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + autorepeat; + button@21 { + label = "GPIO Key UP"; + linux,code = <103>; + gpios = <&gpio1 0 1>; + }; + ... diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt new file mode 100644 index 000000000000..331549593ed5 --- /dev/null +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt @@ -0,0 +1,36 @@ +Rotary encoder DT bindings + +Required properties: +- gpios: a spec for two GPIOs to be used + +Optional properties: +- linux,axis: the input subsystem axis to map to this rotary encoder. + Defaults to 0 (ABS_X / REL_X) +- rotary-encoder,steps: Number of steps in a full turnaround of the + encoder. Only relevant for absolute axis. Defaults to 24 which is a + typical value for such devices. +- rotary-encoder,relative-axis: register a relative axis rather than an + absolute one. Relative axis will only generate +1/-1 events on the input + device, hence no steps need to be passed. +- rotary-encoder,rollover: Automatic rollove when the rotary value becomes + greater than the specified steps or smaller than 0. For absolute axis only. +- rotary-encoder,half-period: Makes the driver work on half-period mode. + +See Documentation/input/rotary-encoder.txt for more information. + +Example: + + rotary@0 { + compatible = "rotary-encoder"; + gpios = <&gpio 19 1>, <&gpio 20 0>; /* GPIO19 is inverted */ + linux,axis = <0>; /* REL_X */ + rotary-encoder,relative-axis; + }; + + rotary@1 { + compatible = "rotary-encoder"; + gpios = <&gpio 21 0>, <&gpio 22 0>; + linux,axis = <1>; /* ABS_Y */ + rotary-encoder,steps = <24>; + rotary-encoder,rollover; + }; diff --git a/drivers/input/apm-power.c b/drivers/input/apm-power.c index e90ee3d30613..650177a3c858 100644 --- a/drivers/input/apm-power.c +++ b/drivers/input/apm-power.c @@ -33,7 +33,7 @@ static void system_power_event(unsigned int keycode) } static void apmpower_event(struct input_handle *handle, unsigned int type, - unsigned int code, int value) + unsigned int code, int value) { /* only react on key down events */ if (value != 1) diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 480eb9d9876a..f50f6dd92274 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -138,8 +138,8 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, if (effect->id == -1) { for (id = 0; id < ff->max_effects; id++) - if (!ff->effect_owners[id]) - break; + if (!ff->effect_owners[id]) + break; if (id >= ff->max_effects) { ret = -ENOSPC; diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index b107922514fb..74c0d8c6002a 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -72,12 +72,14 @@ static const struct ff_envelope *get_envelope(const struct ff_effect *effect) static const struct ff_envelope empty_envelope; switch (effect->type) { - case FF_PERIODIC: - return &effect->u.periodic.envelope; - case FF_CONSTANT: - return &effect->u.constant.envelope; - default: - return &empty_envelope; + case FF_PERIODIC: + return &effect->u.periodic.envelope; + + case FF_CONSTANT: + return &effect->u.constant.envelope; + + default: + return &empty_envelope; } } diff --git a/drivers/input/input.c b/drivers/input/input.c index 5244f3d05b12..ace3f7c4226d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -918,18 +918,10 @@ int input_set_keycode(struct input_dev *dev, } EXPORT_SYMBOL(input_set_keycode); -#define MATCH_BIT(bit, max) \ - for (i = 0; i < BITS_TO_LONGS(max); i++) \ - if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \ - break; \ - if (i != BITS_TO_LONGS(max)) \ - continue; - static const struct input_device_id *input_match_device(struct input_handler *handler, struct input_dev *dev) { const struct input_device_id *id; - int i; for (id = handler->id_table; id->flags || id->driver_info; id++) { @@ -949,15 +941,32 @@ static const struct input_device_id *input_match_device(struct input_handler *ha if (id->version != dev->id.version) continue; - MATCH_BIT(evbit, EV_MAX); - MATCH_BIT(keybit, KEY_MAX); - MATCH_BIT(relbit, REL_MAX); - MATCH_BIT(absbit, ABS_MAX); - MATCH_BIT(mscbit, MSC_MAX); - MATCH_BIT(ledbit, LED_MAX); - MATCH_BIT(sndbit, SND_MAX); - MATCH_BIT(ffbit, FF_MAX); - MATCH_BIT(swbit, SW_MAX); + if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX)) + continue; + + if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX)) + continue; + + if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX)) + continue; + + if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX)) + continue; + + if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX)) + continue; + + if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX)) + continue; + + if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX)) + continue; + + if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX)) + continue; + + if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX)) + continue; if (!handler->match || handler->match(handler, dev)) return id; diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 26043cc6a016..78f323ea1e4b 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -711,7 +711,7 @@ static long joydev_ioctl(struct file *file, case JS_SET_ALL: retval = copy_from_user(&joydev->glue, argp, - sizeof(joydev->glue)) ? -EFAULT: 0; + sizeof(joydev->glue)) ? -EFAULT : 0; break; case JS_GET_ALL: diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index cbb1add43d5e..6a68041c261d 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -43,11 +43,9 @@ struct gpio_button_data { }; struct gpio_keys_drvdata { + const struct gpio_keys_platform_data *pdata; struct input_dev *input; struct mutex disable_lock; - unsigned int n_buttons; - int (*enable)(struct device *dev); - void (*disable)(struct device *dev); struct gpio_button_data data[0]; }; @@ -171,7 +169,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, if (!bits) return -ENOMEM; - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->type != type) @@ -219,7 +217,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, goto out; /* First validate */ - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->type != type) @@ -234,7 +232,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, mutex_lock(&ddata->disable_lock); - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->type != type) @@ -346,6 +344,9 @@ static void gpio_keys_gpio_work_func(struct work_struct *work) container_of(work, struct gpio_button_data, work); gpio_keys_gpio_report_event(bdata); + + if (bdata->button->wakeup) + pm_relax(bdata->input->dev.parent); } static void gpio_keys_gpio_timer(unsigned long _data) @@ -361,6 +362,8 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) BUG_ON(irq != bdata->irq); + if (bdata->button->wakeup) + pm_stay_awake(bdata->input->dev.parent); if (bdata->timer_debounce) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(bdata->timer_debounce)); @@ -397,6 +400,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) spin_lock_irqsave(&bdata->lock, flags); if (!bdata->key_pressed) { + if (bdata->button->wakeup) + pm_wakeup_event(bdata->input->dev.parent, 0); + input_event(input, EV_KEY, button->code, 1); input_sync(input); @@ -523,56 +529,64 @@ fail: static int gpio_keys_open(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); + const struct gpio_keys_platform_data *pdata = ddata->pdata; - return ddata->enable ? ddata->enable(input->dev.parent) : 0; + return pdata->enable ? pdata->enable(input->dev.parent) : 0; } static void gpio_keys_close(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); + const struct gpio_keys_platform_data *pdata = ddata->pdata; - if (ddata->disable) - ddata->disable(input->dev.parent); + if (pdata->disable) + pdata->disable(input->dev.parent); } /* * Handlers for alternative sources of platform_data */ + #ifdef CONFIG_OF /* * Translate OpenFirmware node properties into platform_data */ -static int gpio_keys_get_devtree_pdata(struct device *dev, - struct gpio_keys_platform_data *pdata) +static struct gpio_keys_platform_data * __devinit +gpio_keys_get_devtree_pdata(struct device *dev) { struct device_node *node, *pp; + struct gpio_keys_platform_data *pdata; + struct gpio_keys_button *button; + int error; + int nbuttons; int i; - struct gpio_keys_button *buttons; - u32 reg; node = dev->of_node; - if (node == NULL) - return -ENODEV; - - memset(pdata, 0, sizeof *pdata); + if (!node) { + error = -ENODEV; + goto err_out; + } - pdata->rep = !!of_get_property(node, "autorepeat", NULL); + nbuttons = of_get_child_count(node); + if (nbuttons == 0) { + error = -ENODEV; + goto err_out; + } - /* First count the subnodes */ - pp = NULL; - while ((pp = of_get_next_child(node, pp))) - pdata->nbuttons++; + pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), + GFP_KERNEL); + if (!pdata) { + error = -ENOMEM; + goto err_out; + } - if (pdata->nbuttons == 0) - return -ENODEV; + pdata->buttons = (struct gpio_keys_button *)(pdata + 1); + pdata->nbuttons = nbuttons; - buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL); - if (!buttons) - return -ENOMEM; + pdata->rep = !!of_get_property(node, "autorepeat", NULL); - pp = NULL; i = 0; - while ((pp = of_get_next_child(node, pp))) { + for_each_child_of_node(node, pp) { enum of_gpio_flags flags; if (!of_find_property(pp, "gpios", NULL)) { @@ -580,39 +594,42 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, dev_warn(dev, "Found button without gpios\n"); continue; } - buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags); - buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW; - if (of_property_read_u32(pp, "linux,code", ®)) { - dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio); - goto out_fail; - } - buttons[i].code = reg; + button = &pdata->buttons[i++]; - buttons[i].desc = of_get_property(pp, "label", NULL); + button->gpio = of_get_gpio_flags(pp, 0, &flags); + button->active_low = flags & OF_GPIO_ACTIVE_LOW; - if (of_property_read_u32(pp, "linux,input-type", ®) == 0) - buttons[i].type = reg; - else - buttons[i].type = EV_KEY; + if (of_property_read_u32(pp, "linux,code", &button->code)) { + dev_err(dev, "Button without keycode: 0x%x\n", + button->gpio); + error = -EINVAL; + goto err_free_pdata; + } - buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + button->desc = of_get_property(pp, "label", NULL); - if (of_property_read_u32(pp, "debounce-interval", ®) == 0) - buttons[i].debounce_interval = reg; - else - buttons[i].debounce_interval = 5; + if (of_property_read_u32(pp, "linux,input-type", &button->type)) + button->type = EV_KEY; - i++; + button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + + if (of_property_read_u32(pp, "debounce-interval", + &button->debounce_interval)) + button->debounce_interval = 5; } - pdata->buttons = buttons; + if (pdata->nbuttons == 0) { + error = -EINVAL; + goto err_free_pdata; + } - return 0; + return pdata; -out_fail: - kfree(buttons); - return -ENODEV; +err_free_pdata: + kfree(pdata); +err_out: + return ERR_PTR(error); } static struct of_device_id gpio_keys_of_match[] = { @@ -623,14 +640,12 @@ MODULE_DEVICE_TABLE(of, gpio_keys_of_match); #else -static int gpio_keys_get_devtree_pdata(struct device *dev, - struct gpio_keys_platform_data *altp) +static inline struct gpio_keys_platform_data * +gpio_keys_get_devtree_pdata(struct device *dev) { - return -ENODEV; + return ERR_PTR(-ENODEV); } -#define gpio_keys_of_match NULL - #endif static void gpio_remove_key(struct gpio_button_data *bdata) @@ -645,19 +660,17 @@ static void gpio_remove_key(struct gpio_button_data *bdata) static int __devinit gpio_keys_probe(struct platform_device *pdev) { - const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; - struct gpio_keys_drvdata *ddata; struct device *dev = &pdev->dev; - struct gpio_keys_platform_data alt_pdata; + const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); + struct gpio_keys_drvdata *ddata; struct input_dev *input; int i, error; int wakeup = 0; if (!pdata) { - error = gpio_keys_get_devtree_pdata(dev, &alt_pdata); - if (error) - return error; - pdata = &alt_pdata; + pdata = gpio_keys_get_devtree_pdata(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); } ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + @@ -670,10 +683,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) goto fail1; } + ddata->pdata = pdata; ddata->input = input; - ddata->n_buttons = pdata->nbuttons; - ddata->enable = pdata->enable; - ddata->disable = pdata->disable; mutex_init(&ddata->disable_lock); platform_set_drvdata(pdev, ddata); @@ -742,9 +753,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail1: input_free_device(input); kfree(ddata); - /* If we have no platform_data, we allocated buttons dynamically. */ - if (!pdev->dev.platform_data) - kfree(pdata->buttons); + /* If we have no platform data, we allocated pdata dynamically. */ + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); return error; } @@ -759,18 +770,14 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); - for (i = 0; i < ddata->n_buttons; i++) + for (i = 0; i < ddata->pdata->nbuttons; i++) gpio_remove_key(&ddata->data[i]); input_unregister_device(input); - /* - * If we had no platform_data, we allocated buttons dynamically, and - * must free them here. ddata->data[0].button is the pointer to the - * beginning of the allocated array. - */ - if (!pdev->dev.platform_data) - kfree(ddata->data[0].button); + /* If we have no platform data, we allocated pdata dynamically. */ + if (!dev_get_platdata(&pdev->dev)) + kfree(ddata->pdata); kfree(ddata); @@ -784,7 +791,7 @@ static int gpio_keys_suspend(struct device *dev) int i; if (device_may_wakeup(dev)) { - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) enable_irq_wake(bdata->irq); @@ -799,7 +806,7 @@ static int gpio_keys_resume(struct device *dev) struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); int i; - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup && device_may_wakeup(dev)) disable_irq_wake(bdata->irq); @@ -822,7 +829,7 @@ static struct platform_driver gpio_keys_device_driver = { .name = "gpio-keys", .owner = THIS_MODULE, .pm = &gpio_keys_pm_ops, - .of_match_table = gpio_keys_of_match, + .of_match_table = of_match_ptr(gpio_keys_of_match), } }; diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 20c8ab172214..f2142de789e7 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -25,6 +25,8 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> #define DRV_NAME "gpio-keys-polled" @@ -38,7 +40,7 @@ struct gpio_keys_button_data { struct gpio_keys_polled_dev { struct input_polled_dev *poll_dev; struct device *dev; - struct gpio_keys_platform_data *pdata; + const struct gpio_keys_platform_data *pdata; struct gpio_keys_button_data data[0]; }; @@ -67,11 +69,11 @@ static void gpio_keys_polled_check_state(struct input_dev *input, static void gpio_keys_polled_poll(struct input_polled_dev *dev) { struct gpio_keys_polled_dev *bdev = dev->private; - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; struct input_dev *input = dev->input; int i; - for (i = 0; i < bdev->pdata->nbuttons; i++) { + for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button_data *bdata = &bdev->data[i]; if (bdata->count < bdata->threshold) @@ -85,7 +87,7 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev) static void gpio_keys_polled_open(struct input_polled_dev *dev) { struct gpio_keys_polled_dev *bdev = dev->private; - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; if (pdata->enable) pdata->enable(bdev->dev); @@ -94,31 +96,139 @@ static void gpio_keys_polled_open(struct input_polled_dev *dev) static void gpio_keys_polled_close(struct input_polled_dev *dev) { struct gpio_keys_polled_dev *bdev = dev->private; - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; if (pdata->disable) pdata->disable(bdev->dev); } +#ifdef CONFIG_OF +static struct gpio_keys_platform_data * __devinit +gpio_keys_polled_get_devtree_pdata(struct device *dev) +{ + struct device_node *node, *pp; + struct gpio_keys_platform_data *pdata; + struct gpio_keys_button *button; + int error; + int nbuttons; + int i; + + node = dev->of_node; + if (!node) + return NULL; + + nbuttons = of_get_child_count(node); + if (nbuttons == 0) + return NULL; + + pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), + GFP_KERNEL); + if (!pdata) { + error = -ENOMEM; + goto err_out; + } + + pdata->buttons = (struct gpio_keys_button *)(pdata + 1); + pdata->nbuttons = nbuttons; + + pdata->rep = !!of_get_property(node, "autorepeat", NULL); + of_property_read_u32(node, "poll-interval", &pdata->poll_interval); + + i = 0; + for_each_child_of_node(node, pp) { + enum of_gpio_flags flags; + + if (!of_find_property(pp, "gpios", NULL)) { + pdata->nbuttons--; + dev_warn(dev, "Found button without gpios\n"); + continue; + } + + button = &pdata->buttons[i++]; + + button->gpio = of_get_gpio_flags(pp, 0, &flags); + button->active_low = flags & OF_GPIO_ACTIVE_LOW; + + if (of_property_read_u32(pp, "linux,code", &button->code)) { + dev_err(dev, "Button without keycode: 0x%x\n", + button->gpio); + error = -EINVAL; + goto err_free_pdata; + } + + button->desc = of_get_property(pp, "label", NULL); + + if (of_property_read_u32(pp, "linux,input-type", &button->type)) + button->type = EV_KEY; + + button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + + if (of_property_read_u32(pp, "debounce-interval", + &button->debounce_interval)) + button->debounce_interval = 5; + } + + if (pdata->nbuttons == 0) { + error = -EINVAL; + goto err_free_pdata; + } + + return pdata; + +err_free_pdata: + kfree(pdata); +err_out: + return ERR_PTR(error); +} + +static struct of_device_id gpio_keys_polled_of_match[] = { + { .compatible = "gpio-keys-polled", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match); + +#else + +static inline struct gpio_keys_platform_data * +gpio_keys_polled_get_devtree_pdata(struct device *dev) +{ + return NULL; +} +#endif + static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) { - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; + const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); struct gpio_keys_polled_dev *bdev; struct input_polled_dev *poll_dev; struct input_dev *input; int error; int i; - if (!pdata || !pdata->poll_interval) - return -EINVAL; + if (!pdata) { + pdata = gpio_keys_polled_get_devtree_pdata(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + if (!pdata) { + dev_err(dev, "missing platform data\n"); + return -EINVAL; + } + } + + if (!pdata->poll_interval) { + dev_err(dev, "missing poll_interval value\n"); + error = -EINVAL; + goto err_free_pdata; + } bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + pdata->nbuttons * sizeof(struct gpio_keys_button_data), GFP_KERNEL); if (!bdev) { dev_err(dev, "no memory for private data\n"); - return -ENOMEM; + error = -ENOMEM; + goto err_free_pdata; } poll_dev = input_allocate_polled_device(); @@ -197,7 +307,7 @@ static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) /* report initial state of the buttons */ for (i = 0; i < pdata->nbuttons; i++) gpio_keys_polled_check_state(input, &pdata->buttons[i], - &bdev->data[i]); + &bdev->data[i]); return 0; @@ -209,15 +319,20 @@ err_free_gpio: err_free_bdev: kfree(bdev); - platform_set_drvdata(pdev, NULL); + +err_free_pdata: + /* If we have no platform_data, we allocated pdata dynamically. */ + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + return error; } static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) { struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev); - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; int i; input_unregister_polled_device(bdev->poll_dev); @@ -227,6 +342,13 @@ static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) input_free_polled_device(bdev->poll_dev); + /* + * If we had no platform_data, we allocated pdata dynamically and + * must free it here. + */ + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + kfree(bdev); platform_set_drvdata(pdev, NULL); @@ -239,6 +361,7 @@ static struct platform_driver gpio_keys_polled_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpio_keys_polled_of_match), }, }; module_platform_driver(gpio_keys_polled_driver); diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 6d6b1427ae12..4a5fcc8026f5 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -179,7 +179,7 @@ static void omap_kp_tasklet(unsigned long data) memcpy(keypad_state, new_state, sizeof(keypad_state)); if (key_down) { - int delay = HZ / 20; + int delay = HZ / 20; /* some key is pressed - keep irq disabled and use timer * to poll the keypad */ if (spurious) @@ -346,9 +346,9 @@ err4: err3: device_remove_file(&pdev->dev, &dev_attr_enable); err2: - for (i = row_idx - 1; i >=0; i--) + for (i = row_idx - 1; i >= 0; i--) gpio_free(row_gpios[i]); - for (i = col_idx - 1; i >=0; i--) + for (i = col_idx - 1; i >= 0; i--) gpio_free(col_gpios[i]); kfree(omap_kp); diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index a061ba603a29..277e26dc910e 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -256,7 +256,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( struct matrix_keymap_data *keymap_data; uint32_t *keymap, num_rows = 0, num_cols = 0; struct device_node *np = dev->of_node, *key_np; - unsigned int key_count = 0; + unsigned int key_count; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -280,9 +280,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( } pdata->keymap_data = keymap_data; - for_each_child_of_node(np, key_np) - key_count++; - + key_count = of_get_child_count(np); keymap_data->keymap_size = key_count; keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); if (!keymap) { @@ -662,8 +660,6 @@ static const struct of_device_id samsung_keypad_dt_match[] = { {}, }; MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match); -#else -#define samsung_keypad_dt_match NULL #endif static struct platform_device_id samsung_keypad_driver_ids[] = { @@ -684,7 +680,7 @@ static struct platform_driver samsung_keypad_driver = { .driver = { .name = "samsung-keypad", .owner = THIS_MODULE, - .of_match_table = samsung_keypad_dt_match, + .of_match_table = of_match_ptr(samsung_keypad_dt_match), .pm = &samsung_keypad_pm_ops, }, .id_table = samsung_keypad_driver_ids, diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 2c1c9ed1bd9f..5faaf2553e33 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -29,8 +29,8 @@ #include <linux/of.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/input/tegra_kbc.h> #include <mach/clk.h> -#include <mach/kbc.h> #define KBC_MAX_DEBOUNCE_CNT 0x3ffu diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index f07f784198b9..99a49e4968d2 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -24,12 +24,14 @@ #include <linux/gpio.h> #include <linux/rotary_encoder.h> #include <linux/slab.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> #define DRV_NAME "rotary-encoder" struct rotary_encoder { struct input_dev *input; - struct rotary_encoder_platform_data *pdata; + const struct rotary_encoder_platform_data *pdata; unsigned int axis; unsigned int pos; @@ -43,7 +45,7 @@ struct rotary_encoder { char last_stable; }; -static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) +static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata) { int a = !!gpio_get_value(pdata->gpio_a); int b = !!gpio_get_value(pdata->gpio_b); @@ -56,7 +58,7 @@ static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) static void rotary_encoder_report_event(struct rotary_encoder *encoder) { - struct rotary_encoder_platform_data *pdata = encoder->pdata; + const struct rotary_encoder_platform_data *pdata = encoder->pdata; if (pdata->relative_axis) { input_report_rel(encoder->input, @@ -140,36 +142,89 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) return IRQ_HANDLED; } +#ifdef CONFIG_OF +static struct of_device_id rotary_encoder_of_match[] = { + { .compatible = "rotary-encoder", }, + { }, +}; +MODULE_DEVICE_TABLE(of, rotary_encoder_of_match); + +static struct rotary_encoder_platform_data * __devinit +rotary_encoder_parse_dt(struct device *dev) +{ + const struct of_device_id *of_id = + of_match_device(rotary_encoder_of_match, dev); + struct device_node *np = dev->of_node; + struct rotary_encoder_platform_data *pdata; + enum of_gpio_flags flags; + + if (!of_id || !np) + return NULL; + + pdata = kzalloc(sizeof(struct rotary_encoder_platform_data), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + of_property_read_u32(np, "rotary-encoder,steps", &pdata->steps); + of_property_read_u32(np, "linux,axis", &pdata->axis); + + pdata->gpio_a = of_get_gpio_flags(np, 0, &flags); + pdata->inverted_a = flags & OF_GPIO_ACTIVE_LOW; + + pdata->gpio_b = of_get_gpio_flags(np, 1, &flags); + pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW; + + pdata->relative_axis = !!of_get_property(np, + "rotary-encoder,relative-axis", NULL); + pdata->rollover = !!of_get_property(np, + "rotary-encoder,rollover", NULL); + pdata->half_period = !!of_get_property(np, + "rotary-encoder,half-period", NULL); + + return pdata; +} +#else +static inline struct rotary_encoder_platform_data * +rotary_encoder_parse_dt(struct device *dev) +{ + return NULL; +} +#endif + static int __devinit rotary_encoder_probe(struct platform_device *pdev) { - struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev); struct rotary_encoder *encoder; struct input_dev *input; irq_handler_t handler; int err; if (!pdata) { - dev_err(&pdev->dev, "missing platform data\n"); - return -ENOENT; + pdata = rotary_encoder_parse_dt(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + + if (!pdata) { + dev_err(dev, "missing platform data\n"); + return -EINVAL; + } } encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); input = input_allocate_device(); if (!encoder || !input) { - dev_err(&pdev->dev, "failed to allocate memory for device\n"); err = -ENOMEM; goto exit_free_mem; } encoder->input = input; encoder->pdata = pdata; - encoder->irq_a = gpio_to_irq(pdata->gpio_a); - encoder->irq_b = gpio_to_irq(pdata->gpio_b); - /* create and register the input driver */ input->name = pdev->name; input->id.bustype = BUS_HOST; - input->dev.parent = &pdev->dev; + input->dev.parent = dev; if (pdata->relative_axis) { input->evbit[0] = BIT_MASK(EV_REL); @@ -180,40 +235,21 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) pdata->axis, 0, pdata->steps, 0, 1); } - err = input_register_device(input); - if (err) { - dev_err(&pdev->dev, "failed to register input device\n"); - goto exit_free_mem; - } - /* request the GPIOs */ - err = gpio_request(pdata->gpio_a, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "unable to request GPIO %d\n", - pdata->gpio_a); - goto exit_unregister_input; - } - - err = gpio_direction_input(pdata->gpio_a); + err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev)); if (err) { - dev_err(&pdev->dev, "unable to set GPIO %d for input\n", - pdata->gpio_a); - goto exit_unregister_input; + dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a); + goto exit_free_mem; } - err = gpio_request(pdata->gpio_b, DRV_NAME); + err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev)); if (err) { - dev_err(&pdev->dev, "unable to request GPIO %d\n", - pdata->gpio_b); + dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b); goto exit_free_gpio_a; } - err = gpio_direction_input(pdata->gpio_b); - if (err) { - dev_err(&pdev->dev, "unable to set GPIO %d for input\n", - pdata->gpio_b); - goto exit_free_gpio_a; - } + encoder->irq_a = gpio_to_irq(pdata->gpio_a); + encoder->irq_b = gpio_to_irq(pdata->gpio_b); /* request the IRQs */ if (pdata->half_period) { @@ -227,8 +263,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DRV_NAME, encoder); if (err) { - dev_err(&pdev->dev, "unable to request IRQ %d\n", - encoder->irq_a); + dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a); goto exit_free_gpio_b; } @@ -236,43 +271,55 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DRV_NAME, encoder); if (err) { - dev_err(&pdev->dev, "unable to request IRQ %d\n", - encoder->irq_b); + dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b); goto exit_free_irq_a; } + err = input_register_device(input); + if (err) { + dev_err(dev, "failed to register input device\n"); + goto exit_free_irq_b; + } + platform_set_drvdata(pdev, encoder); return 0; +exit_free_irq_b: + free_irq(encoder->irq_b, encoder); exit_free_irq_a: free_irq(encoder->irq_a, encoder); exit_free_gpio_b: gpio_free(pdata->gpio_b); exit_free_gpio_a: gpio_free(pdata->gpio_a); -exit_unregister_input: - input_unregister_device(input); - input = NULL; /* so we don't try to free it */ exit_free_mem: input_free_device(input); kfree(encoder); + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + return err; } static int __devexit rotary_encoder_remove(struct platform_device *pdev) { struct rotary_encoder *encoder = platform_get_drvdata(pdev); - struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; + const struct rotary_encoder_platform_data *pdata = encoder->pdata; free_irq(encoder->irq_a, encoder); free_irq(encoder->irq_b, encoder); gpio_free(pdata->gpio_a); gpio_free(pdata->gpio_b); + input_unregister_device(encoder->input); - platform_set_drvdata(pdev, NULL); kfree(encoder); + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + + platform_set_drvdata(pdev, NULL); + return 0; } @@ -282,6 +329,7 @@ static struct platform_driver rotary_encoder_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rotary_encoder_of_match), } }; module_platform_driver(rotary_encoder_driver); diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index 38e4b507b94c..b3dd96d6448b 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -42,6 +42,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS); if (!err) { + pm_wakeup_event(pwr->dev.parent, 0); input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); input_sync(pwr); } else { diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 6b1797503e34..a0a4bbaef02c 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -40,7 +40,8 @@ #include <linux/input/mt.h> #include "../input-compat.h" -static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +static int uinput_dev_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) { struct uinput_device *udev = input_get_drvdata(dev); @@ -56,10 +57,11 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i } /* Atomically allocate an ID for the given request. Returns 0 on success. */ -static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request) +static bool uinput_request_alloc_id(struct uinput_device *udev, + struct uinput_request *request) { - int id; - int err = -1; + unsigned int id; + bool reserved = false; spin_lock(&udev->requests_lock); @@ -67,32 +69,35 @@ static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_req if (!udev->requests[id]) { request->id = id; udev->requests[id] = request; - err = 0; + reserved = true; break; } } spin_unlock(&udev->requests_lock); - return err; + return reserved; } -static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id) +static struct uinput_request *uinput_request_find(struct uinput_device *udev, + unsigned int id) { /* Find an input request, by ID. Returns NULL if the ID isn't valid. */ - if (id >= UINPUT_NUM_REQUESTS || id < 0) + if (id >= UINPUT_NUM_REQUESTS) return NULL; return udev->requests[id]; } -static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct uinput_request *request) +static int uinput_request_reserve_slot(struct uinput_device *udev, + struct uinput_request *request) { /* Allocate slot. If none are available right away, wait. */ return wait_event_interruptible(udev->requests_waitq, - !uinput_request_alloc_id(udev, request)); + uinput_request_alloc_id(udev, request)); } -static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request) +static void uinput_request_done(struct uinput_device *udev, + struct uinput_request *request) { /* Mark slot as available */ udev->requests[request->id] = NULL; @@ -101,14 +106,11 @@ static void uinput_request_done(struct uinput_device *udev, struct uinput_reques complete(&request->done); } -static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request) +static int uinput_request_send(struct uinput_device *udev, + struct uinput_request *request) { int retval; - retval = uinput_request_reserve_slot(udev, request); - if (retval) - return retval; - retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; @@ -118,7 +120,12 @@ static int uinput_request_submit(struct uinput_device *udev, struct uinput_reque goto out; } - /* Tell our userspace app about this new request by queueing an input event */ + init_completion(&request->done); + + /* + * Tell our userspace application about this new request + * by queueing an input event. + */ uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id); out: @@ -126,8 +133,27 @@ static int uinput_request_submit(struct uinput_device *udev, struct uinput_reque return retval; } +static int uinput_request_submit(struct uinput_device *udev, + struct uinput_request *request) +{ + int error; + + error = uinput_request_reserve_slot(udev, request); + if (error) + return error; + + error = uinput_request_send(udev, request); + if (error) { + uinput_request_done(udev, request); + return error; + } + + wait_for_completion(&request->done); + return request->retval; +} + /* - * Fail all ouitstanding requests so handlers don't wait for the userspace + * Fail all outstanding requests so handlers don't wait for the userspace * to finish processing them. */ static void uinput_flush_requests(struct uinput_device *udev) @@ -163,11 +189,12 @@ static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value) return uinput_dev_event(dev, EV_FF, effect_id, value); } -static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) +static int uinput_dev_upload_effect(struct input_dev *dev, + struct ff_effect *effect, + struct ff_effect *old) { struct uinput_device *udev = input_get_drvdata(dev); struct uinput_request request; - int retval; /* * uinput driver does not currently support periodic effects with @@ -180,42 +207,25 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff effect->u.periodic.waveform == FF_CUSTOM) return -EINVAL; - request.id = -1; - init_completion(&request.done); request.code = UI_FF_UPLOAD; request.u.upload.effect = effect; request.u.upload.old = old; - retval = uinput_request_submit(udev, &request); - if (!retval) { - wait_for_completion(&request.done); - retval = request.retval; - } - - return retval; + return uinput_request_submit(udev, &request); } static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) { struct uinput_device *udev = input_get_drvdata(dev); struct uinput_request request; - int retval; if (!test_bit(EV_FF, dev->evbit)) return -ENOSYS; - request.id = -1; - init_completion(&request.done); request.code = UI_FF_ERASE; request.u.effect_id = effect_id; - retval = uinput_request_submit(udev, &request); - if (!retval) { - wait_for_completion(&request.done); - retval = request.retval; - } - - return retval; + return uinput_request_submit(udev, &request); } static void uinput_destroy_device(struct uinput_device *udev) @@ -347,7 +357,8 @@ static int uinput_allocate_device(struct uinput_device *udev) return 0; } -static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count) +static int uinput_setup_device(struct uinput_device *udev, + const char __user *buffer, size_t count) { struct uinput_user_dev *user_dev; struct input_dev *dev; @@ -419,7 +430,8 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu return retval; } -static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char __user *buffer, size_t count) +static ssize_t uinput_inject_event(struct uinput_device *udev, + const char __user *buffer, size_t count) { struct input_event ev; @@ -434,11 +446,15 @@ static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char return input_event_size(); } -static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) +static ssize_t uinput_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { struct uinput_device *udev = file->private_data; int retval; + if (count == 0) + return 0; + retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; @@ -452,42 +468,74 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t return retval; } -static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) +static bool uinput_fetch_next_event(struct uinput_device *udev, + struct input_event *event) { - struct uinput_device *udev = file->private_data; - int retval = 0; + bool have_event; - if (udev->state != UIST_CREATED) - return -ENODEV; + spin_lock_irq(&udev->dev->event_lock); - if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK)) - return -EAGAIN; + have_event = udev->head != udev->tail; + if (have_event) { + *event = udev->buff[udev->tail]; + udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE; + } - retval = wait_event_interruptible(udev->waitq, - udev->head != udev->tail || udev->state != UIST_CREATED); - if (retval) - return retval; + spin_unlock_irq(&udev->dev->event_lock); - retval = mutex_lock_interruptible(&udev->mutex); - if (retval) - return retval; + return have_event; +} - if (udev->state != UIST_CREATED) { - retval = -ENODEV; - goto out; - } +static ssize_t uinput_events_to_user(struct uinput_device *udev, + char __user *buffer, size_t count) +{ + struct input_event event; + size_t read = 0; - while (udev->head != udev->tail && retval + input_event_size() <= count) { - if (input_event_to_user(buffer + retval, &udev->buff[udev->tail])) { - retval = -EFAULT; - goto out; - } - udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE; - retval += input_event_size(); + while (read + input_event_size() <= count && + uinput_fetch_next_event(udev, &event)) { + + if (input_event_to_user(buffer + read, &event)) + return -EFAULT; + + read += input_event_size(); } - out: - mutex_unlock(&udev->mutex); + return read; +} + +static ssize_t uinput_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct uinput_device *udev = file->private_data; + ssize_t retval; + + if (count != 0 && count < input_event_size()) + return -EINVAL; + + do { + retval = mutex_lock_interruptible(&udev->mutex); + if (retval) + return retval; + + if (udev->state != UIST_CREATED) + retval = -ENODEV; + else if (udev->head == udev->tail && + (file->f_flags & O_NONBLOCK)) + retval = -EAGAIN; + else + retval = uinput_events_to_user(udev, buffer, count); + + mutex_unlock(&udev->mutex); + + if (retval || count == 0) + break; + + if (!(file->f_flags & O_NONBLOCK)) + retval = wait_event_interruptible(udev->waitq, + udev->head != udev->tail || + udev->state != UIST_CREATED); + } while (retval == 0); return retval; } @@ -516,8 +564,8 @@ static int uinput_release(struct inode *inode, struct file *file) #ifdef CONFIG_COMPAT struct uinput_ff_upload_compat { - int request_id; - int retval; + __u32 request_id; + __s32 retval; struct ff_effect_compat effect; struct ff_effect_compat old; }; @@ -703,7 +751,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, break; req = uinput_request_find(udev, ff_up.request_id); - if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) { + if (!req || req->code != UI_FF_UPLOAD || + !req->u.upload.effect) { retval = -EINVAL; break; } @@ -786,7 +835,8 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_COMPAT -static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long uinput_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) { return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg)); } @@ -831,4 +881,3 @@ MODULE_VERSION("0.3"); module_init(uinput_init); module_exit(uinput_exit); - diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 575f880727fe..62be888e83d0 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -334,11 +334,8 @@ static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet) if (!valid) psmouse_dbg(psmouse, - "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n", - priv->mode, pktcnt, - psmouse->packet[0], psmouse->packet[1], - psmouse->packet[2], psmouse->packet[3], - psmouse->packet[4], psmouse->packet[5]); + "bad data, mode %d (%d) %*ph\n", + priv->mode, pktcnt, 6, psmouse->packet); return valid; } @@ -1030,7 +1027,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) return -EIO; } - psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]); + psmouse_dbg(psmouse, "ID: %*ph\n", 3, param); /* HGPK signature: 0x67, 0x00, 0x<model> */ if (param[0] != 0x67 || param[1] != 0x00) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 37033ade79d3..12d12ca3fee0 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -53,14 +53,19 @@ #define ABS_POS_BITS 13 /* - * Any position values from the hardware above the following limits are - * treated as "wrapped around negative" values that have been truncated to - * the 13-bit reporting range of the hardware. These are just reasonable - * guesses and can be adjusted if hardware is found that operates outside - * of these parameters. + * These values should represent the absolute maximum value that will + * be reported for a positive position value. Some Synaptics firmware + * uses this value to indicate a finger near the edge of the touchpad + * whose precise position cannot be determined. + * + * At least one touchpad is known to report positions in excess of this + * value which are actually negative values truncated to the 13-bit + * reporting range. These values have never been observed to be lower + * than 8184 (i.e. -8), so we treat all values greater than 8176 as + * negative and any other value as positive. */ -#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2) -#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2) +#define X_MAX_POSITIVE 8176 +#define Y_MAX_POSITIVE 8176 /***************************************************************************** * Stuff we need even when we do not want native Synaptics support @@ -604,11 +609,21 @@ static int synaptics_parse_hw_state(const unsigned char buf[], hw->right = (buf[0] & 0x02) ? 1 : 0; } - /* Convert wrap-around values to negative */ + /* + * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE + * is used by some firmware to indicate a finger at the edge of + * the touchpad whose precise position cannot be determined, so + * convert these values to the maximum axis value. + */ if (hw->x > X_MAX_POSITIVE) hw->x -= 1 << ABS_POS_BITS; + else if (hw->x == X_MAX_POSITIVE) + hw->x = XMAX; + if (hw->y > Y_MAX_POSITIVE) hw->y -= 1 << ABS_POS_BITS; + else if (hw->y == Y_MAX_POSITIVE) + hw->y = YMAX; return 0; } diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 0110b5a3a167..964e43d81e29 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -551,17 +551,16 @@ static int mousedev_open(struct inode *inode, struct file *file) return -ENODEV; error = mutex_lock_interruptible(&mousedev_table_mutex); - if (error) { + if (error) return error; - } + mousedev = mousedev_table[i]; if (mousedev) get_device(&mousedev->dev); mutex_unlock(&mousedev_table_mutex); - if (!mousedev) { + if (!mousedev) return -ENODEV; - } client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); if (!client) { @@ -1088,7 +1087,7 @@ static int __init mousedev_init(void) #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX error = misc_register(&psaux_mouse); if (error) - pr_warning("could not register psaux device, error: %d\n", + pr_warn("could not register psaux device, error: %d\n", error); else psaux_registered = 1; diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 75fb040a3435..a70aa555bbff 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -180,11 +180,11 @@ int sparse_keymap_setup(struct input_dev *dev, for (e = keymap; e->type != KE_END; e++) map_size++; - map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL); + map = kcalloc(map_size, sizeof(struct key_entry), GFP_KERNEL); if (!map) return -ENOMEM; - memcpy(map, keymap, map_size * sizeof (struct key_entry)); + memcpy(map, keymap, map_size * sizeof(struct key_entry)); for (i = 0; i < map_size; i++) { entry = &map[i]; diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 2a81ce375f75..08b462b6c0d8 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -606,7 +606,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_WHEEL, 0); } - if (data[2] | (data[3] & 0x01) | data[4]) { + if (data[2] | (data[3] & 0x01) | data[4] | data[5]) { input_report_key(input, wacom->tool[1], 1); input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); } else { diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index df9e816d55e4..549fa29548f8 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -406,7 +406,7 @@ static int s3c2410ts_resume(struct device *dev) return 0; } -static struct dev_pm_ops s3c_ts_pmops = { +static const struct dev_pm_ops s3c_ts_pmops = { .suspend = s3c2410ts_suspend, .resume = s3c2410ts_resume, }; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 59f8db4a39a7..9c03a3ae898f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -903,6 +903,8 @@ COMPATIBLE_IOCTL(KDGKBSENT) COMPATIBLE_IOCTL(KDSKBSENT) COMPATIBLE_IOCTL(KDGKBDIACR) COMPATIBLE_IOCTL(KDSKBDIACR) +COMPATIBLE_IOCTL(KDGKBDIACRUC) +COMPATIBLE_IOCTL(KDSKBDIACRUC) COMPATIBLE_IOCTL(KDKBDREP) COMPATIBLE_IOCTL(KDGKBLED) COMPATIBLE_IOCTL(KDGETLED) diff --git a/arch/arm/mach-tegra/include/mach/kbc.h b/include/linux/input/tegra_kbc.h index a13025612939..a13025612939 100644 --- a/arch/arm/mach-tegra/include/mach/kbc.h +++ b/include/linux/input/tegra_kbc.h diff --git a/include/linux/uinput.h b/include/linux/uinput.h index 2aa2881b0df9..c454bbe39ee7 100644 --- a/include/linux/uinput.h +++ b/include/linux/uinput.h @@ -32,6 +32,7 @@ * - first public version */ +#include <linux/types.h> #include <linux/input.h> #define UINPUT_VERSION 3 @@ -44,14 +45,14 @@ enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED }; struct uinput_request { - int id; - int code; /* UI_FF_UPLOAD, UI_FF_ERASE */ + unsigned int id; + unsigned int code; /* UI_FF_UPLOAD, UI_FF_ERASE */ int retval; struct completion done; union { - int effect_id; + unsigned int effect_id; struct { struct ff_effect *effect; struct ff_effect *old; @@ -77,16 +78,16 @@ struct uinput_device { #endif /* __KERNEL__ */ struct uinput_ff_upload { - int request_id; - int retval; + __u32 request_id; + __s32 retval; struct ff_effect effect; struct ff_effect old; }; struct uinput_ff_erase { - int request_id; - int retval; - int effect_id; + __u32 request_id; + __s32 retval; + __u32 effect_id; }; /* ioctl */ @@ -166,11 +167,11 @@ struct uinput_ff_erase { struct uinput_user_dev { char name[UINPUT_MAX_NAME_SIZE]; struct input_id id; - int ff_effects_max; - int absmax[ABS_CNT]; - int absmin[ABS_CNT]; - int absfuzz[ABS_CNT]; - int absflat[ABS_CNT]; + __u32 ff_effects_max; + __s32 absmax[ABS_CNT]; + __s32 absmin[ABS_CNT]; + __s32 absfuzz[ABS_CNT]; + __s32 absflat[ABS_CNT]; }; #endif /* __UINPUT_H_ */ |