summaryrefslogtreecommitdiff
path: root/drivers/input/misc
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-01-20 14:01:31 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-01-20 14:01:31 -0300
commitb4b7ff4b08e691656c9d77c758fc355833128ac0 (patch)
tree82fcb00e6b918026dc9f2d1f05ed8eee83874cc0 /drivers/input/misc
parent35acfa0fc609f2a2cd95cef4a6a9c3a5c38f1778 (diff)
Linux-libre 4.4-gnupck-4.4-gnu
Diffstat (limited to 'drivers/input/misc')
-rw-r--r--drivers/input/misc/Kconfig12
-rw-r--r--drivers/input/misc/ad714x-i2c.c10
-rw-r--r--drivers/input/misc/ad714x-spi.c11
-rw-r--r--drivers/input/misc/ad714x.c214
-rw-r--r--drivers/input/misc/ad714x.h1
-rw-r--r--drivers/input/misc/adxl34x-spi.c1
-rw-r--r--drivers/input/misc/arizona-haptics.c3
-rw-r--r--drivers/input/misc/bma150.c2
-rw-r--r--drivers/input/misc/da9063_onkey.c137
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c52
-rw-r--r--drivers/input/misc/kxtj9.c3
-rw-r--r--drivers/input/misc/rotary_encoder.c129
-rw-r--r--drivers/input/misc/sparcspkr.c18
-rw-r--r--drivers/input/misc/uinput.c158
-rw-r--r--drivers/input/misc/xen-kbdfront.c10
15 files changed, 483 insertions, 278 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 906dd1b25..d6d16fa78 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -94,11 +94,11 @@ config INPUT_BMA150
module will be called bma150.
config INPUT_E3X0_BUTTON
- tristate "NI Ettus Research USRP E3x0 Button support."
+ tristate "NI Ettus Research USRP E3xx Button support."
default n
help
Say Y here to enable support for the NI Ettus Research
- USRP E3x0 Button.
+ USRP E3xx Button.
To compile this driver as a module, choose M here: the
module will be called e3x0_button.
@@ -599,11 +599,11 @@ config INPUT_DA9055_ONKEY
will be called da9055_onkey.
config INPUT_DA9063_ONKEY
- tristate "Dialog DA9063 OnKey"
- depends on MFD_DA9063
+ tristate "Dialog DA9062/63 OnKey"
+ depends on MFD_DA9063 || MFD_DA9062
help
- Support the ONKEY of Dialog DA9063 Power Management IC as an
- input device reporting power button statue.
+ Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs
+ as an input device capable of reporting the power button status.
To compile this driver as a module, choose M here: the module
will be called da9063_onkey.
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index 189bdc8e9..2f047738b 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -85,15 +85,6 @@ static int ad714x_i2c_probe(struct i2c_client *client,
return 0;
}
-static int ad714x_i2c_remove(struct i2c_client *client)
-{
- struct ad714x_chip *chip = i2c_get_clientdata(client);
-
- ad714x_remove(chip);
-
- return 0;
-}
-
static const struct i2c_device_id ad714x_id[] = {
{ "ad7142_captouch", 0 },
{ "ad7143_captouch", 0 },
@@ -110,7 +101,6 @@ static struct i2c_driver ad714x_i2c_driver = {
.pm = &ad714x_i2c_pm,
},
.probe = ad714x_i2c_probe,
- .remove = ad714x_i2c_remove,
.id_table = ad714x_id,
};
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
index a79e50b58..aac910326 100644
--- a/drivers/input/misc/ad714x-spi.c
+++ b/drivers/input/misc/ad714x-spi.c
@@ -101,23 +101,12 @@ static int ad714x_spi_probe(struct spi_device *spi)
return 0;
}
-static int ad714x_spi_remove(struct spi_device *spi)
-{
- struct ad714x_chip *chip = spi_get_drvdata(spi);
-
- ad714x_remove(chip);
-
- return 0;
-}
-
static struct spi_driver ad714x_spi_driver = {
.driver = {
.name = "ad714x_captouch",
- .owner = THIS_MODULE,
.pm = &ad714x_spi_pm,
},
.probe = ad714x_spi_probe,
- .remove = ad714x_spi_remove,
};
module_spi_driver(ad714x_spi_driver);
diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c
index 7a61e9ee6..84b51dd51 100644
--- a/drivers/input/misc/ad714x.c
+++ b/drivers/input/misc/ad714x.c
@@ -960,13 +960,12 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
return IRQ_HANDLED;
}
-#define MAX_DEVICE_NUM 8
struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
ad714x_read_t read, ad714x_write_t write)
{
- int i, alloc_idx;
+ int i;
int error;
- struct input_dev *input[MAX_DEVICE_NUM];
+ struct input_dev *input;
struct ad714x_platform_data *plat_data = dev_get_platdata(dev);
struct ad714x_chip *ad714x;
@@ -982,25 +981,25 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
if (irq <= 0) {
dev_err(dev, "IRQ not configured!\n");
error = -EINVAL;
- goto err_out;
+ return ERR_PTR(error);
}
if (dev_get_platdata(dev) == NULL) {
dev_err(dev, "platform data for ad714x doesn't exist\n");
error = -EINVAL;
- goto err_out;
+ return ERR_PTR(error);
}
- ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) +
- sizeof(*sd_drv) * plat_data->slider_num +
- sizeof(*wl_drv) * plat_data->wheel_num +
- sizeof(*tp_drv) * plat_data->touchpad_num +
- sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL);
+ ad714x = devm_kzalloc(dev, sizeof(*ad714x) + sizeof(*ad714x->sw) +
+ sizeof(*sd_drv) * plat_data->slider_num +
+ sizeof(*wl_drv) * plat_data->wheel_num +
+ sizeof(*tp_drv) * plat_data->touchpad_num +
+ sizeof(*bt_drv) * plat_data->button_num,
+ GFP_KERNEL);
if (!ad714x) {
error = -ENOMEM;
- goto err_out;
+ return ERR_PTR(error);
}
-
ad714x->hw = plat_data;
drv_mem = ad714x + 1;
@@ -1022,47 +1021,40 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
error = ad714x_hw_detect(ad714x);
if (error)
- goto err_free_mem;
+ return ERR_PTR(error);
/* initialize and request sw/hw resources */
ad714x_hw_init(ad714x);
mutex_init(&ad714x->mutex);
- /*
- * Allocate and register AD714X input device
- */
- alloc_idx = 0;
-
/* a slider uses one input_dev instance */
if (ad714x->hw->slider_num > 0) {
struct ad714x_slider_plat *sd_plat = ad714x->hw->slider;
for (i = 0; i < ad714x->hw->slider_num; i++) {
- sd_drv[i].input = input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
- error = -ENOMEM;
- goto err_free_dev;
- }
-
- __set_bit(EV_ABS, input[alloc_idx]->evbit);
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
- __set_bit(ABS_X, input[alloc_idx]->absbit);
- __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
- input_set_abs_params(input[alloc_idx],
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return ERR_PTR(-ENOMEM);
+
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(ABS_X, input->absbit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ input_set_abs_params(input,
ABS_X, 0, sd_plat->max_coord, 0, 0);
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_slider";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_slider";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
+ return ERR_PTR(error);
- alloc_idx++;
+ sd_drv[i].input = input;
}
}
@@ -1071,30 +1063,28 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel;
for (i = 0; i < ad714x->hw->wheel_num; i++) {
- wl_drv[i].input = input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
- error = -ENOMEM;
- goto err_free_dev;
- }
-
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
- __set_bit(EV_ABS, input[alloc_idx]->evbit);
- __set_bit(ABS_WHEEL, input[alloc_idx]->absbit);
- __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
- input_set_abs_params(input[alloc_idx],
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return ERR_PTR(-ENOMEM);
+
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(ABS_WHEEL, input->absbit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ input_set_abs_params(input,
ABS_WHEEL, 0, wl_plat->max_coord, 0, 0);
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_wheel";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_wheel";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
+ return ERR_PTR(error);
- alloc_idx++;
+ wl_drv[i].input = input;
}
}
@@ -1103,33 +1093,31 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad;
for (i = 0; i < ad714x->hw->touchpad_num; i++) {
- tp_drv[i].input = input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
- error = -ENOMEM;
- goto err_free_dev;
- }
-
- __set_bit(EV_ABS, input[alloc_idx]->evbit);
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
- __set_bit(ABS_X, input[alloc_idx]->absbit);
- __set_bit(ABS_Y, input[alloc_idx]->absbit);
- __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
- input_set_abs_params(input[alloc_idx],
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return ERR_PTR(-ENOMEM);
+
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(ABS_X, input->absbit);
+ __set_bit(ABS_Y, input->absbit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ input_set_abs_params(input,
ABS_X, 0, tp_plat->x_max_coord, 0, 0);
- input_set_abs_params(input[alloc_idx],
+ input_set_abs_params(input,
ABS_Y, 0, tp_plat->y_max_coord, 0, 0);
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_pad";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_pad";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
+ return ERR_PTR(error);
- alloc_idx++;
+ tp_drv[i].input = input;
}
}
@@ -1137,82 +1125,44 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
if (ad714x->hw->button_num > 0) {
struct ad714x_button_plat *bt_plat = ad714x->hw->button;
- input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
+ input = devm_input_allocate_device(dev);
+ if (!input) {
error = -ENOMEM;
- goto err_free_dev;
+ return ERR_PTR(error);
}
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
+ __set_bit(EV_KEY, input->evbit);
for (i = 0; i < ad714x->hw->button_num; i++) {
- bt_drv[i].input = input[alloc_idx];
- __set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit);
+ bt_drv[i].input = input;
+ __set_bit(bt_plat[i].keycode, input->keybit);
}
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_button";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_button";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
-
- alloc_idx++;
+ return ERR_PTR(error);
}
irqflags = plat_data->irqflags ?: IRQF_TRIGGER_FALLING;
irqflags |= IRQF_ONESHOT;
- error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread,
- irqflags, "ad714x_captouch", ad714x);
+ error = devm_request_threaded_irq(dev, ad714x->irq, NULL,
+ ad714x_interrupt_thread,
+ irqflags, "ad714x_captouch", ad714x);
if (error) {
dev_err(dev, "can't allocate irq %d\n", ad714x->irq);
- goto err_unreg_dev;
+ return ERR_PTR(error);
}
return ad714x;
-
- err_free_dev:
- dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx);
- input_free_device(input[alloc_idx]);
- err_unreg_dev:
- while (--alloc_idx >= 0)
- input_unregister_device(input[alloc_idx]);
- err_free_mem:
- kfree(ad714x);
- err_out:
- return ERR_PTR(error);
}
EXPORT_SYMBOL(ad714x_probe);
-void ad714x_remove(struct ad714x_chip *ad714x)
-{
- struct ad714x_platform_data *hw = ad714x->hw;
- struct ad714x_driver_data *sw = ad714x->sw;
- int i;
-
- free_irq(ad714x->irq, ad714x);
-
- /* unregister and free all input devices */
-
- for (i = 0; i < hw->slider_num; i++)
- input_unregister_device(sw->slider[i].input);
-
- for (i = 0; i < hw->wheel_num; i++)
- input_unregister_device(sw->wheel[i].input);
-
- for (i = 0; i < hw->touchpad_num; i++)
- input_unregister_device(sw->touchpad[i].input);
-
- if (hw->button_num)
- input_unregister_device(sw->button[0].input);
-
- kfree(ad714x);
-}
-EXPORT_SYMBOL(ad714x_remove);
-
#ifdef CONFIG_PM
int ad714x_disable(struct ad714x_chip *ad714x)
{
diff --git a/drivers/input/misc/ad714x.h b/drivers/input/misc/ad714x.h
index 3c85455aa..5d65d303b 100644
--- a/drivers/input/misc/ad714x.h
+++ b/drivers/input/misc/ad714x.h
@@ -50,6 +50,5 @@ int ad714x_disable(struct ad714x_chip *ad714x);
int ad714x_enable(struct ad714x_chip *ad714x);
struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
ad714x_read_t read, ad714x_write_t write);
-void ad714x_remove(struct ad714x_chip *ad714x);
#endif
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
index da6e76b58..3ec03ad88 100644
--- a/drivers/input/misc/adxl34x-spi.c
+++ b/drivers/input/misc/adxl34x-spi.c
@@ -120,7 +120,6 @@ static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
static struct spi_driver adxl34x_driver = {
.driver = {
.name = "adxl34x",
- .owner = THIS_MODULE,
.pm = &adxl34x_spi_pm,
},
.probe = adxl34x_spi_probe,
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
index 4bf678541..d5994a745 100644
--- a/drivers/input/misc/arizona-haptics.c
+++ b/drivers/input/misc/arizona-haptics.c
@@ -97,8 +97,7 @@ static void arizona_haptics_work(struct work_struct *work)
ret = regmap_update_bits(arizona->regmap,
ARIZONA_HAPTICS_CONTROL_1,
- ARIZONA_HAP_CTRL_MASK,
- 1 << ARIZONA_HAP_CTRL_SHIFT);
+ ARIZONA_HAP_CTRL_MASK, 0);
if (ret != 0) {
dev_err(arizona->dev, "Failed to stop haptics: %d\n",
ret);
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index 1d0e61d7c..b0d445390 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -147,7 +147,7 @@ struct bma150_data {
* are stated and verified by Bosch Sensortec where they are configured
* to provide a generic sensitivity performance.
*/
-static struct bma150_cfg default_cfg = {
+static const struct bma150_cfg default_cfg = {
.any_motion_int = 1,
.hg_int = 1,
.lg_int = 1,
diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index f577585ef..bb863e062 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -1,5 +1,5 @@
/*
- * OnKey device driver for DA9063
+ * OnKey device driver for DA9063 and DA9062 PMICs
* Copyright (C) 2015 Dialog Semiconductor Ltd.
*
* This program is free software; you can redistribute it and/or
@@ -24,36 +24,96 @@
#include <linux/mfd/da9063/core.h>
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
+#include <linux/mfd/da9062/core.h>
+#include <linux/mfd/da9062/registers.h>
+
+struct da906x_chip_config {
+ /* REGS */
+ int onkey_status;
+ int onkey_pwr_signalling;
+ int onkey_fault_log;
+ int onkey_shutdown;
+ /* MASKS */
+ int onkey_nonkey_mask;
+ int onkey_nonkey_lock_mask;
+ int onkey_key_reset_mask;
+ int onkey_shutdown_mask;
+ /* NAMES */
+ const char *name;
+};
struct da9063_onkey {
- struct da9063 *hw;
struct delayed_work work;
struct input_dev *input;
struct device *dev;
+ struct regmap *regmap;
+ const struct da906x_chip_config *config;
+ char phys[32];
bool key_power;
};
+static const struct da906x_chip_config da9063_regs = {
+ /* REGS */
+ .onkey_status = DA9063_REG_STATUS_A,
+ .onkey_pwr_signalling = DA9063_REG_CONTROL_B,
+ .onkey_fault_log = DA9063_REG_FAULT_LOG,
+ .onkey_shutdown = DA9063_REG_CONTROL_F,
+ /* MASKS */
+ .onkey_nonkey_mask = DA9063_NONKEY,
+ .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK,
+ .onkey_key_reset_mask = DA9063_KEY_RESET,
+ .onkey_shutdown_mask = DA9063_SHUTDOWN,
+ /* NAMES */
+ .name = DA9063_DRVNAME_ONKEY,
+};
+
+static const struct da906x_chip_config da9062_regs = {
+ /* REGS */
+ .onkey_status = DA9062AA_STATUS_A,
+ .onkey_pwr_signalling = DA9062AA_CONTROL_B,
+ .onkey_fault_log = DA9062AA_FAULT_LOG,
+ .onkey_shutdown = DA9062AA_CONTROL_F,
+ /* MASKS */
+ .onkey_nonkey_mask = DA9062AA_NONKEY_MASK,
+ .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK,
+ .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK,
+ .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK,
+ /* NAMES */
+ .name = "da9062-onkey",
+};
+
+static const struct of_device_id da9063_compatible_reg_id_table[] = {
+ { .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
+ { .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
+ { },
+};
+
static void da9063_poll_on(struct work_struct *work)
{
- struct da9063_onkey *onkey = container_of(work, struct da9063_onkey,
- work.work);
+ struct da9063_onkey *onkey = container_of(work,
+ struct da9063_onkey,
+ work.work);
+ const struct da906x_chip_config *config = onkey->config;
unsigned int val;
int fault_log = 0;
bool poll = true;
int error;
/* Poll to see when the pin is released */
- error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
+ error = regmap_read(onkey->regmap,
+ config->onkey_status,
+ &val);
if (error) {
dev_err(onkey->dev,
"Failed to read ON status: %d\n", error);
goto err_poll;
}
- if (!(val & DA9063_NONKEY)) {
- error = regmap_update_bits(onkey->hw->regmap,
- DA9063_REG_CONTROL_B,
- DA9063_NONKEY_LOCK, 0);
+ if (!(val & config->onkey_nonkey_mask)) {
+ error = regmap_update_bits(onkey->regmap,
+ config->onkey_pwr_signalling,
+ config->onkey_nonkey_lock_mask,
+ 0);
if (error) {
dev_err(onkey->dev,
"Failed to reset the Key Delay %d\n", error);
@@ -70,15 +130,16 @@ static void da9063_poll_on(struct work_struct *work)
* If the fault log KEY_RESET is detected, then clear it
* and shut down the system.
*/
- error = regmap_read(onkey->hw->regmap,
- DA9063_REG_FAULT_LOG, &fault_log);
+ error = regmap_read(onkey->regmap,
+ config->onkey_fault_log,
+ &fault_log);
if (error) {
dev_warn(&onkey->input->dev,
"Cannot read FAULT_LOG: %d\n", error);
- } else if (fault_log & DA9063_KEY_RESET) {
- error = regmap_write(onkey->hw->regmap,
- DA9063_REG_FAULT_LOG,
- DA9063_KEY_RESET);
+ } else if (fault_log & config->onkey_key_reset_mask) {
+ error = regmap_write(onkey->regmap,
+ config->onkey_fault_log,
+ config->onkey_key_reset_mask);
if (error) {
dev_warn(&onkey->input->dev,
"Cannot reset KEY_RESET fault log: %d\n",
@@ -88,10 +149,10 @@ static void da9063_poll_on(struct work_struct *work)
* and then send shutdown command
*/
dev_dbg(&onkey->input->dev,
- "Sending SHUTDOWN to DA9063 ...\n");
- error = regmap_write(onkey->hw->regmap,
- DA9063_REG_CONTROL_F,
- DA9063_SHUTDOWN);
+ "Sending SHUTDOWN to DA9063 ...\n");
+ error = regmap_write(onkey->regmap,
+ config->onkey_shutdown,
+ config->onkey_shutdown_mask);
if (error)
dev_err(&onkey->input->dev,
"Cannot SHUTDOWN DA9063: %d\n",
@@ -107,21 +168,24 @@ err_poll:
static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
{
struct da9063_onkey *onkey = data;
+ const struct da906x_chip_config *config = onkey->config;
unsigned int val;
int error;
- error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
- if (onkey->key_power && !error && (val & DA9063_NONKEY)) {
+ error = regmap_read(onkey->regmap,
+ config->onkey_status,
+ &val);
+ if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) {
input_report_key(onkey->input, KEY_POWER, 1);
input_sync(onkey->input);
schedule_delayed_work(&onkey->work, 0);
- dev_dbg(onkey->dev, "KEY_POWER pressed.\n");
+ dev_dbg(onkey->dev, "KEY_POWER long press.\n");
} else {
- input_report_key(onkey->input, KEY_SLEEP, 1);
+ input_report_key(onkey->input, KEY_POWER, 1);
input_sync(onkey->input);
- input_report_key(onkey->input, KEY_SLEEP, 0);
+ input_report_key(onkey->input, KEY_POWER, 0);
input_sync(onkey->input);
- dev_dbg(onkey->dev, "KEY_SLEEP pressed.\n");
+ dev_dbg(onkey->dev, "KEY_POWER short press.\n");
}
return IRQ_HANDLED;
@@ -139,9 +203,15 @@ static int da9063_onkey_probe(struct platform_device *pdev)
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_pdata *pdata = dev_get_platdata(da9063->dev);
struct da9063_onkey *onkey;
+ const struct of_device_id *match;
int irq;
int error;
+ match = of_match_node(da9063_compatible_reg_id_table,
+ pdev->dev.of_node);
+ if (!match)
+ return -ENXIO;
+
onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
GFP_KERNEL);
if (!onkey) {
@@ -149,8 +219,14 @@ static int da9063_onkey_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ onkey->config = match->data;
onkey->dev = &pdev->dev;
- onkey->hw = da9063;
+
+ onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!onkey->regmap) {
+ dev_err(&pdev->dev, "Parent regmap unavailable.\n");
+ return -ENXIO;
+ }
if (pdata)
onkey->key_power = pdata->key_power;
@@ -165,8 +241,10 @@ static int da9063_onkey_probe(struct platform_device *pdev)
return -ENOMEM;
}
- onkey->input->name = DA9063_DRVNAME_ONKEY;
- onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0";
+ onkey->input->name = onkey->config->name;
+ snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
+ onkey->config->name);
+ onkey->input->phys = onkey->phys;
onkey->input->dev.parent = &pdev->dev;
if (onkey->key_power)
@@ -216,11 +294,12 @@ static struct platform_driver da9063_onkey_driver = {
.probe = da9063_onkey_probe,
.driver = {
.name = DA9063_DRVNAME_ONKEY,
+ .of_match_table = da9063_compatible_reg_id_table,
},
};
module_platform_driver(da9063_onkey_driver);
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
-MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063");
+MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 45e0e3e55..1c8c56efc 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -198,7 +198,7 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
/* Read the i8042 real-time clock */
-static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_rt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
unsigned int days;
@@ -209,15 +209,15 @@ static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
days = (unsigned int)(raw >> 24) & 0xffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100) + days * 86400;
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (tenms / 100) + (time64_t)days * 86400;
return 0;
}
/* Read the i8042 fast handshake timer */
-static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
+static inline int hp_sdc_rtc_read_fhs(struct timespec64 *res) {
int64_t raw;
unsigned int tenms;
@@ -226,15 +226,15 @@ static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
tenms = (unsigned int)raw & 0xffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 match timer (a.k.a. alarm) */
-static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_mt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
@@ -243,15 +243,15 @@ static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 delay timer */
-static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_dt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
@@ -260,15 +260,15 @@ static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 cycle timer (a.k.a. periodic) */
-static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
+static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
@@ -277,8 +277,8 @@ static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
@@ -433,7 +433,7 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
#define YN(bit) ("no")
#define NY(bit) ("yes")
struct rtc_time tm;
- struct timeval tv;
+ struct timespec64 tv;
memset(&tm, 0, sizeof(struct rtc_time));
@@ -452,36 +452,36 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
if (hp_sdc_rtc_read_rt(&tv)) {
seq_puts(m, "i8042 rtc\t: READ FAILED!\n");
} else {
- seq_printf(m, "i8042 rtc\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "i8042 rtc\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_fhs(&tv)) {
seq_puts(m, "handshake\t: READ FAILED!\n");
} else {
- seq_printf(m, "handshake\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "handshake\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_mt(&tv)) {
seq_puts(m, "alarm\t\t: READ FAILED!\n");
} else {
- seq_printf(m, "alarm\t\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "alarm\t\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_dt(&tv)) {
seq_puts(m, "delay\t\t: READ FAILED!\n");
} else {
- seq_printf(m, "delay\t\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "delay\t\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_ct(&tv)) {
seq_puts(m, "periodic\t: READ FAILED!\n");
} else {
- seq_printf(m, "periodic\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "periodic\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
seq_printf(m,
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index e058d7112..efaffcc57 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -635,7 +635,6 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
struct input_dev *input_dev = tj9->input_dev;
- int retval = 0;
mutex_lock(&input_dev->mutex);
@@ -643,7 +642,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
kxtj9_enable(tj9);
mutex_unlock(&input_dev->mutex);
- return retval;
+ return 0;
}
static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index f27f81ee8..8aee71986 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -26,6 +26,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
+#include <linux/pm.h>
#define DRV_NAME "rotary-encoder"
@@ -142,6 +143,55 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
+{
+ struct rotary_encoder *encoder = dev_id;
+ unsigned char sum;
+ int state;
+
+ state = rotary_encoder_get_state(encoder->pdata);
+
+ /*
+ * We encode the previous and the current state using a byte.
+ * The previous state in the MSB nibble, the current state in the LSB
+ * nibble. Then use a table to decide the direction of the turn.
+ */
+ sum = (encoder->last_stable << 4) + state;
+ switch (sum) {
+ case 0x31:
+ case 0x10:
+ case 0x02:
+ case 0x23:
+ encoder->dir = 0; /* clockwise */
+ break;
+
+ case 0x13:
+ case 0x01:
+ case 0x20:
+ case 0x32:
+ encoder->dir = 1; /* counter-clockwise */
+ break;
+
+ default:
+ /*
+ * Ignore all other values. This covers the case when the
+ * state didn't change (a spurious interrupt) and the
+ * cases where the state changed by two steps, making it
+ * impossible to tell the direction.
+ *
+ * In either case, don't report any event and save the
+ * state for later.
+ */
+ goto out;
+ }
+
+ rotary_encoder_report_event(encoder);
+
+out:
+ encoder->last_stable = state;
+ return IRQ_HANDLED;
+}
+
#ifdef CONFIG_OF
static const struct of_device_id rotary_encoder_of_match[] = {
{ .compatible = "rotary-encoder", },
@@ -156,6 +206,7 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic
struct device_node *np = dev->of_node;
struct rotary_encoder_platform_data *pdata;
enum of_gpio_flags flags;
+ int error;
if (!of_id || !np)
return NULL;
@@ -174,12 +225,27 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic
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);
+ pdata->relative_axis =
+ of_property_read_bool(np, "rotary-encoder,relative-axis");
+ pdata->rollover = of_property_read_bool(np, "rotary-encoder,rollover");
+
+ error = of_property_read_u32(np, "rotary-encoder,steps-per-period",
+ &pdata->steps_per_period);
+ if (error) {
+ /*
+ * The 'half-period' property has been deprecated, you must use
+ * 'steps-per-period' and set an appropriate value, but we still
+ * need to parse it to maintain compatibility.
+ */
+ if (of_property_read_bool(np, "rotary-encoder,half-period")) {
+ pdata->steps_per_period = 2;
+ } else {
+ /* Fallback to one step per period behavior */
+ pdata->steps_per_period = 1;
+ }
+ }
+
+ pdata->wakeup_source = of_property_read_bool(np, "wakeup-source");
return pdata;
}
@@ -250,12 +316,23 @@ static int rotary_encoder_probe(struct platform_device *pdev)
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) {
+ switch (pdata->steps_per_period) {
+ case 4:
+ handler = &rotary_encoder_quarter_period_irq;
+ encoder->last_stable = rotary_encoder_get_state(pdata);
+ break;
+ case 2:
handler = &rotary_encoder_half_period_irq;
encoder->last_stable = rotary_encoder_get_state(pdata);
- } else {
+ break;
+ case 1:
handler = &rotary_encoder_irq;
+ break;
+ default:
+ dev_err(dev, "'%d' is not a valid steps-per-period value\n",
+ pdata->steps_per_period);
+ err = -EINVAL;
+ goto exit_free_gpio_b;
}
err = request_irq(encoder->irq_a, handler,
@@ -280,6 +357,8 @@ static int rotary_encoder_probe(struct platform_device *pdev)
goto exit_free_irq_b;
}
+ device_init_wakeup(&pdev->dev, pdata->wakeup_source);
+
platform_set_drvdata(pdev, encoder);
return 0;
@@ -306,6 +385,8 @@ static int rotary_encoder_remove(struct platform_device *pdev)
struct rotary_encoder *encoder = platform_get_drvdata(pdev);
const struct rotary_encoder_platform_data *pdata = encoder->pdata;
+ device_init_wakeup(&pdev->dev, false);
+
free_irq(encoder->irq_a, encoder);
free_irq(encoder->irq_b, encoder);
gpio_free(pdata->gpio_a);
@@ -320,11 +401,41 @@ static int rotary_encoder_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int rotary_encoder_suspend(struct device *dev)
+{
+ struct rotary_encoder *encoder = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(encoder->irq_a);
+ enable_irq_wake(encoder->irq_b);
+ }
+
+ return 0;
+}
+
+static int rotary_encoder_resume(struct device *dev)
+{
+ struct rotary_encoder *encoder = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(encoder->irq_a);
+ disable_irq_wake(encoder->irq_b);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops,
+ rotary_encoder_suspend, rotary_encoder_resume);
+
static struct platform_driver rotary_encoder_driver = {
.probe = rotary_encoder_probe,
.remove = rotary_encoder_remove,
.driver = {
.name = DRV_NAME,
+ .pm = &rotary_encoder_pm_ops,
.of_match_table = of_match_ptr(rotary_encoder_of_match),
}
};
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 6f997aa49..4a5afc7fe 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -345,23 +345,19 @@ static struct platform_driver grover_beep_driver = {
.shutdown = sparcspkr_shutdown,
};
+static struct platform_driver * const drivers[] = {
+ &bbc_beep_driver,
+ &grover_beep_driver,
+};
+
static int __init sparcspkr_init(void)
{
- int err = platform_driver_register(&bbc_beep_driver);
-
- if (!err) {
- err = platform_driver_register(&grover_beep_driver);
- if (err)
- platform_driver_unregister(&bbc_beep_driver);
- }
-
- return err;
+ return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
static void __exit sparcspkr_exit(void)
{
- platform_driver_unregister(&bbc_beep_driver);
- platform_driver_unregister(&grover_beep_driver);
+ platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
}
module_init(sparcspkr_init);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 5adbcedcb..4eb9e4d94 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -256,13 +256,29 @@ static void uinput_destroy_device(struct uinput_device *udev)
static int uinput_create_device(struct uinput_device *udev)
{
struct input_dev *dev = udev->dev;
- int error;
+ int error, nslot;
if (udev->state != UIST_SETUP_COMPLETE) {
printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
return -EINVAL;
}
+ if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+ nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+ error = input_mt_init_slots(dev, nslot, 0);
+ if (error)
+ goto fail1;
+ } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+ input_set_events_per_packet(dev, 60);
+ }
+
+ if (test_bit(EV_FF, dev->evbit) && !udev->ff_effects_max) {
+ printk(KERN_DEBUG "%s: ff_effects_max should be non-zero when FF_BIT is set\n",
+ UINPUT_NAME);
+ error = -EINVAL;
+ goto fail1;
+ }
+
if (udev->ff_effects_max) {
error = input_ff_create(dev, udev->ff_effects_max);
if (error)
@@ -308,10 +324,35 @@ static int uinput_open(struct inode *inode, struct file *file)
return 0;
}
+static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
+ const struct input_absinfo *abs)
+{
+ int min, max;
+
+ min = abs->minimum;
+ max = abs->maximum;
+
+ if ((min != 0 || max != 0) && max <= min) {
+ printk(KERN_DEBUG
+ "%s: invalid abs[%02x] min:%d max:%d\n",
+ UINPUT_NAME, code, min, max);
+ return -EINVAL;
+ }
+
+ if (abs->flat > max - min) {
+ printk(KERN_DEBUG
+ "%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n",
+ UINPUT_NAME, code, abs->flat, min, max);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int uinput_validate_absbits(struct input_dev *dev)
{
unsigned int cnt;
- int nslot;
+ int error;
if (!test_bit(EV_ABS, dev->evbit))
return 0;
@@ -321,38 +362,12 @@ static int uinput_validate_absbits(struct input_dev *dev)
*/
for_each_set_bit(cnt, dev->absbit, ABS_CNT) {
- int min, max;
-
- min = input_abs_get_min(dev, cnt);
- max = input_abs_get_max(dev, cnt);
-
- if ((min != 0 || max != 0) && max <= min) {
- printk(KERN_DEBUG
- "%s: invalid abs[%02x] min:%d max:%d\n",
- UINPUT_NAME, cnt,
- input_abs_get_min(dev, cnt),
- input_abs_get_max(dev, cnt));
+ if (!dev->absinfo)
return -EINVAL;
- }
- if (input_abs_get_flat(dev, cnt) >
- input_abs_get_max(dev, cnt) - input_abs_get_min(dev, cnt)) {
- printk(KERN_DEBUG
- "%s: abs_flat #%02x out of range: %d "
- "(min:%d/max:%d)\n",
- UINPUT_NAME, cnt,
- input_abs_get_flat(dev, cnt),
- input_abs_get_min(dev, cnt),
- input_abs_get_max(dev, cnt));
- return -EINVAL;
- }
- }
-
- if (test_bit(ABS_MT_SLOT, dev->absbit)) {
- nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
- input_mt_init_slots(dev, nslot, 0);
- } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
- input_set_events_per_packet(dev, 60);
+ error = uinput_validate_absinfo(dev, cnt, &dev->absinfo[cnt]);
+ if (error)
+ return error;
}
return 0;
@@ -370,8 +385,71 @@ 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_dev_setup(struct uinput_device *udev,
+ struct uinput_setup __user *arg)
+{
+ struct uinput_setup setup;
+ struct input_dev *dev;
+
+ if (udev->state == UIST_CREATED)
+ return -EINVAL;
+
+ if (copy_from_user(&setup, arg, sizeof(setup)))
+ return -EFAULT;
+
+ if (!setup.name[0])
+ return -EINVAL;
+
+ dev = udev->dev;
+ dev->id = setup.id;
+ udev->ff_effects_max = setup.ff_effects_max;
+
+ kfree(dev->name);
+ dev->name = kstrndup(setup.name, UINPUT_MAX_NAME_SIZE, GFP_KERNEL);
+ if (!dev->name)
+ return -ENOMEM;
+
+ udev->state = UIST_SETUP_COMPLETE;
+ return 0;
+}
+
+static int uinput_abs_setup(struct uinput_device *udev,
+ struct uinput_setup __user *arg, size_t size)
+{
+ struct uinput_abs_setup setup = {};
+ struct input_dev *dev;
+ int error;
+
+ if (size > sizeof(setup))
+ return -E2BIG;
+
+ if (udev->state == UIST_CREATED)
+ return -EINVAL;
+
+ if (copy_from_user(&setup, arg, size))
+ return -EFAULT;
+
+ if (setup.code > ABS_MAX)
+ return -ERANGE;
+
+ dev = udev->dev;
+
+ error = uinput_validate_absinfo(dev, setup.code, &setup.absinfo);
+ if (error)
+ return error;
+
+ input_alloc_absinfo(dev);
+ if (!dev->absinfo)
+ return -ENOMEM;
+
+ set_bit(setup.code, dev->absbit);
+ dev->absinfo[setup.code] = setup.absinfo;
+ return 0;
+}
+
+/* legacy setup via write() */
+static int uinput_setup_device_legacy(struct uinput_device *udev,
+ const char __user *buffer, size_t count)
{
struct uinput_user_dev *user_dev;
struct input_dev *dev;
@@ -474,7 +552,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer,
retval = udev->state == UIST_CREATED ?
uinput_inject_events(udev, buffer, count) :
- uinput_setup_device(udev, buffer, count);
+ uinput_setup_device_legacy(udev, buffer, count);
mutex_unlock(&udev->mutex);
@@ -735,6 +813,12 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
uinput_destroy_device(udev);
goto out;
+ case UI_DEV_SETUP:
+ retval = uinput_dev_setup(udev, p);
+ goto out;
+
+ /* UI_ABS_SETUP is handled in the variable size ioctls */
+
case UI_SET_EVBIT:
retval = uinput_set_bit(arg, evbit, EV_MAX);
goto out;
@@ -879,6 +963,10 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
name = dev_name(&udev->dev->dev);
retval = uinput_str_to_user(p, name, size);
goto out;
+
+ case UI_ABS_SETUP & ~IOCSIZE_MASK:
+ retval = uinput_abs_setup(udev, p, size);
+ goto out;
}
retval = -EINVAL;
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index 23d054953..0a9ad2cfb 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -129,8 +129,14 @@ static int xenkbd_probe(struct xenbus_device *dev,
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
abs = 0;
- if (abs)
- xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
+ if (abs) {
+ ret = xenbus_printf(XBT_NIL, dev->nodename,
+ "request-abs-pointer", "1");
+ if (ret) {
+ pr_warning("xenkbd: can't request abs-pointer");
+ abs = 0;
+ }
+ }
/* keyboard */
kbd = input_allocate_device();