summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/gpio-mouse.txt32
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/exc3000.txt27
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/goodix.txt3
-rw-r--r--drivers/input/ff-memless.c8
-rw-r--r--drivers/input/input.c11
-rw-r--r--drivers/input/keyboard/bf54x-keys.c7
-rw-r--r--drivers/input/keyboard/gpio_keys.c7
-rw-r--r--drivers/input/keyboard/imx_keypad.c8
-rw-r--r--drivers/input/keyboard/locomokbd.c7
-rw-r--r--drivers/input/keyboard/omap-keypad.c6
-rw-r--r--drivers/input/keyboard/snvs_pwrkey.c7
-rw-r--r--drivers/input/keyboard/tegra-kbc.c6
-rw-r--r--drivers/input/misc/adxl34x.c2
-rw-r--r--drivers/input/misc/uinput.c305
-rw-r--r--drivers/input/mouse/alps.c8
-rw-r--r--drivers/input/mouse/byd.c10
-rw-r--r--drivers/input/mouse/elan_i2c_core.c11
-rw-r--r--drivers/input/mouse/gpio_mouse.c206
-rw-r--r--drivers/input/rmi4/rmi_f54.c2
-rw-r--r--drivers/input/serio/hil_mlc.c4
-rw-r--r--drivers/input/serio/hp_sdc.c5
-rw-r--r--drivers/input/serio/ps2-gpio.c1
-rw-r--r--drivers/input/serio/sa1111ps2.c69
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ad7877.c6
-rw-r--r--drivers/input/touchscreen/ad7879.c19
-rw-r--r--drivers/input/touchscreen/atmel-wm97xx.c10
-rw-r--r--drivers/input/touchscreen/cyttsp4_core.c59
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c173
-rw-r--r--drivers/input/touchscreen/elants_i2c.c19
-rw-r--r--drivers/input/touchscreen/exc3000.c223
-rw-r--r--drivers/input/touchscreen/goodix.c125
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c17
-rw-r--r--drivers/input/touchscreen/mxs-lradc-ts.c2
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c18
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c17
-rw-r--r--drivers/input/touchscreen/stmfts.c4
-rw-r--r--drivers/input/touchscreen/tsc200x-core.c6
-rw-r--r--drivers/input/touchscreen/w90p910_ts.c7
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c10
-rw-r--r--drivers/media/pci/ttpci/av7110.h2
-rw-r--r--drivers/media/pci/ttpci/av7110_ir.c56
-rw-r--r--include/linux/gpio_mouse.h61
-rw-r--r--include/linux/uinput.h81
45 files changed, 980 insertions, 700 deletions
diff --git a/Documentation/devicetree/bindings/input/gpio-mouse.txt b/Documentation/devicetree/bindings/input/gpio-mouse.txt
new file mode 100644
index 000000000000..519510a11af9
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/gpio-mouse.txt
@@ -0,0 +1,32 @@
+Device-Tree bindings for GPIO attached mice
+
+This simply uses standard GPIO handles to define a simple mouse connected
+to 5-7 GPIO lines.
+
+Required properties:
+ - compatible: must be "gpio-mouse"
+ - scan-interval-ms: The scanning interval in milliseconds
+ - up-gpios: GPIO line phandle to the line indicating "up"
+ - down-gpios: GPIO line phandle to the line indicating "down"
+ - left-gpios: GPIO line phandle to the line indicating "left"
+ - right-gpios: GPIO line phandle to the line indicating "right"
+
+Optional properties:
+ - button-left-gpios: GPIO line handle to the left mouse button
+ - button-middle-gpios: GPIO line handle to the middle mouse button
+ - button-right-gpios: GPIO line handle to the right mouse button
+Example:
+
+#include <dt-bindings/gpio/gpio.h>
+
+gpio-mouse {
+ compatible = "gpio-mouse";
+ scan-interval-ms = <50>;
+ up-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+ down-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+ left-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+ right-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+ button-left-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+ button-middle-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+ button-right-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/exc3000.txt b/Documentation/devicetree/bindings/input/touchscreen/exc3000.txt
new file mode 100644
index 000000000000..1dcff4a43eaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/exc3000.txt
@@ -0,0 +1,27 @@
+* EETI EXC3000 Multiple Touch Controller
+
+Required properties:
+- compatible: must be "eeti,exc3000"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: touch controller interrupt
+- touchscreen-size-x: See touchscreen.txt
+- touchscreen-size-y: See touchscreen.txt
+
+Optional properties:
+- touchscreen-inverted-x: See touchscreen.txt
+- touchscreen-inverted-y: See touchscreen.txt
+- touchscreen-swapped-x-y: See touchscreen.txt
+
+Example:
+
+ touchscreen@2a {
+ compatible = "eeti,exc3000";
+ reg = <0x2a>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
+ touchscreen-inverted-x;
+ touchscreen-swapped-x-y;
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt
index c98757a69110..0c369d8ebcab 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt
@@ -2,7 +2,8 @@ Device tree bindings for Goodix GT9xx series touchscreen controller
Required properties:
- - compatible : Should be "goodix,gt911"
+ - compatible : Should be "goodix,gt1151"
+ or "goodix,gt911"
or "goodix,gt9110"
or "goodix,gt912"
or "goodix,gt927"
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index fcc6c3368182..2743ed4656e4 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -412,10 +412,10 @@ static void ml_play_effects(struct ml_device *ml)
ml_schedule_timer(ml);
}
-static void ml_effect_timer(unsigned long timer_data)
+static void ml_effect_timer(struct timer_list *t)
{
- struct input_dev *dev = (struct input_dev *)timer_data;
- struct ml_device *ml = dev->ff->private;
+ struct ml_device *ml = from_timer(ml, t, timer);
+ struct input_dev *dev = ml->dev;
unsigned long flags;
pr_debug("timer: updating effects\n");
@@ -526,7 +526,7 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
ml->private = data;
ml->play_effect = play_effect;
ml->gain = 0xffff;
- setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev);
+ timer_setup(&ml->timer, ml_effect_timer, 0);
set_bit(FF_GAIN, dev->ffbit);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 762bfb9487dc..44916ef4a424 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -76,7 +76,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code)
{
if (test_bit(EV_REP, dev->evbit) &&
dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
- dev->timer.data) {
+ dev->timer.function) {
dev->repeat_key = code;
mod_timer(&dev->timer,
jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
@@ -179,9 +179,9 @@ static void input_pass_event(struct input_dev *dev,
* dev->event_lock here to avoid racing with input_event
* which may cause keys get "stuck".
*/
-static void input_repeat_key(unsigned long data)
+static void input_repeat_key(struct timer_list *t)
{
- struct input_dev *dev = (void *) data;
+ struct input_dev *dev = from_timer(dev, t, timer);
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
@@ -1784,7 +1784,7 @@ struct input_dev *input_allocate_device(void)
device_initialize(&dev->dev);
mutex_init(&dev->mutex);
spin_lock_init(&dev->event_lock);
- init_timer(&dev->timer);
+ timer_setup(&dev->timer, NULL, 0);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
@@ -2047,8 +2047,7 @@ static void devm_input_device_unregister(struct device *dev, void *res)
*/
void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
{
- dev->timer.data = (unsigned long) dev;
- dev->timer.function = input_repeat_key;
+ dev->timer.function = (TIMER_FUNC_TYPE)input_repeat_key;
dev->rep[REP_DELAY] = delay;
dev->rep[REP_PERIOD] = period;
}
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
index 39bcbc38997f..8a07a426f88e 100644
--- a/drivers/input/keyboard/bf54x-keys.c
+++ b/drivers/input/keyboard/bf54x-keys.c
@@ -127,10 +127,9 @@ static inline void bfin_kpad_clear_irq(void)
bfin_write_KPAD_ROWCOL(0xFFFF);
}
-static void bfin_kpad_timer(unsigned long data)
+static void bfin_kpad_timer(struct timer_list *t)
{
- struct platform_device *pdev = (struct platform_device *) data;
- struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+ struct bf54x_kpad *bf54x_kpad = from_timer(bf54x_kpad, t, timer);
if (bfin_kpad_get_keypressed(bf54x_kpad)) {
/* Try again later */
@@ -298,7 +297,7 @@ static int bfin_kpad_probe(struct platform_device *pdev)
/* Init Keypad Key Up/Release test timer */
- setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev);
+ timer_setup(&bf54x_kpad->timer, bfin_kpad_timer, 0);
bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE));
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index e9f0ebf3267a..87e613dc33b8 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -419,9 +419,9 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void gpio_keys_irq_timer(unsigned long _data)
+static void gpio_keys_irq_timer(struct timer_list *t)
{
- struct gpio_button_data *bdata = (struct gpio_button_data *)_data;
+ struct gpio_button_data *bdata = from_timer(bdata, t, release_timer);
struct input_dev *input = bdata->input;
unsigned long flags;
@@ -582,8 +582,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
bdata->release_delay = button->debounce_interval;
- setup_timer(&bdata->release_timer,
- gpio_keys_irq_timer, (unsigned long)bdata);
+ timer_setup(&bdata->release_timer, gpio_keys_irq_timer, 0);
isr = gpio_keys_irq_isr;
irqflags = 0;
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 2165f3dd328b..25d61d8d4fc4 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -184,9 +184,9 @@ static void imx_keypad_fire_events(struct imx_keypad *keypad,
/*
* imx_keypad_check_for_events is the timer handler.
*/
-static void imx_keypad_check_for_events(unsigned long data)
+static void imx_keypad_check_for_events(struct timer_list *t)
{
- struct imx_keypad *keypad = (struct imx_keypad *) data;
+ struct imx_keypad *keypad = from_timer(keypad, t, check_matrix_timer);
unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS];
unsigned short reg_val;
bool state_changed, is_zero_matrix;
@@ -456,8 +456,8 @@ static int imx_keypad_probe(struct platform_device *pdev)
keypad->irq = irq;
keypad->stable_count = 0;
- setup_timer(&keypad->check_matrix_timer,
- imx_keypad_check_for_events, (unsigned long) keypad);
+ timer_setup(&keypad->check_matrix_timer,
+ imx_keypad_check_for_events, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 0d74312d5b02..30d610758595 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -210,9 +210,9 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
/*
* LoCoMo timer checking for released keys
*/
-static void locomokbd_timer_callback(unsigned long data)
+static void locomokbd_timer_callback(struct timer_list *t)
{
- struct locomokbd *locomokbd = (struct locomokbd *) data;
+ struct locomokbd *locomokbd = from_timer(locomokbd, t, timer);
locomokbd_scankeyboard(locomokbd);
}
@@ -264,8 +264,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
spin_lock_init(&locomokbd->lock);
- setup_timer(&locomokbd->timer, locomokbd_timer_callback,
- (unsigned long)locomokbd);
+ timer_setup(&locomokbd->timer, locomokbd_timer_callback, 0);
locomokbd->suspend_jiffies = jiffies;
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 146b26f665f6..7bd107910a6e 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -41,7 +41,7 @@
#undef NEW_BOARD_LEARNING_MODE
static void omap_kp_tasklet(unsigned long);
-static void omap_kp_timer(unsigned long);
+static void omap_kp_timer(struct timer_list *);
static unsigned char keypad_state[8];
static DEFINE_MUTEX(kp_enable_mutex);
@@ -74,7 +74,7 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void omap_kp_timer(unsigned long data)
+static void omap_kp_timer(struct timer_list *unused)
{
tasklet_schedule(&kp_tasklet);
}
@@ -233,7 +233,7 @@ static int omap_kp_probe(struct platform_device *pdev)
col_idx = 0;
row_idx = 0;
- setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
+ timer_setup(&omap_kp->timer, omap_kp_timer, 0);
/* get the irq and init timer*/
kp_tasklet.data = (unsigned long) omap_kp;
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 7544888c4749..53c768b95939 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -45,9 +45,9 @@ struct pwrkey_drv_data {
struct input_dev *input;
};
-static void imx_imx_snvs_check_for_events(unsigned long data)
+static void imx_imx_snvs_check_for_events(struct timer_list *t)
{
- struct pwrkey_drv_data *pdata = (struct pwrkey_drv_data *) data;
+ struct pwrkey_drv_data *pdata = from_timer(pdata, t, check_timer);
struct input_dev *input = pdata->input;
u32 state;
@@ -134,8 +134,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
/* clear the unexpected interrupt before driver ready */
regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
- setup_timer(&pdata->check_timer,
- imx_imx_snvs_check_for_events, (unsigned long) pdata);
+ timer_setup(&pdata->check_timer, imx_imx_snvs_check_for_events, 0);
input = devm_input_allocate_device(&pdev->dev);
if (!input) {
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index edc1385ca00b..875205f445b5 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -251,9 +251,9 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable)
writel(val, kbc->mmio + KBC_CONTROL_0);
}
-static void tegra_kbc_keypress_timer(unsigned long data)
+static void tegra_kbc_keypress_timer(struct timer_list *t)
{
- struct tegra_kbc *kbc = (struct tegra_kbc *)data;
+ struct tegra_kbc *kbc = from_timer(kbc, t, timer);
unsigned long flags;
u32 val;
unsigned int i;
@@ -655,7 +655,7 @@ static int tegra_kbc_probe(struct platform_device *pdev)
return -ENOMEM;
}
- setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc);
+ timer_setup(&kbc->timer, tegra_kbc_keypress_timer, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
kbc->mmio = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c
index 2b2d02f408bb..a3e79bf5a04b 100644
--- a/drivers/input/misc/adxl34x.c
+++ b/drivers/input/misc/adxl34x.c
@@ -796,7 +796,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
if (pdata->watermark) {
ac->int_mask |= WATERMARK;
- if (!FIFO_MODE(pdata->fifo_mode))
+ if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS)
ac->pdata.fifo_mode |= FIFO_STREAM;
} else {
ac->int_mask |= DATA_READY;
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 443151de90c6..7b41aad7ec27 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -31,6 +31,7 @@
* 0.1 20/06/2002
* - first public version
*/
+#include <uapi/linux/uinput.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -38,10 +39,47 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
-#include <linux/uinput.h>
#include <linux/input/mt.h>
#include "../input-compat.h"
+#define UINPUT_NAME "uinput"
+#define UINPUT_BUFFER_SIZE 16
+#define UINPUT_NUM_REQUESTS 16
+
+enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
+
+struct uinput_request {
+ unsigned int id;
+ unsigned int code; /* UI_FF_UPLOAD, UI_FF_ERASE */
+
+ int retval;
+ struct completion done;
+
+ union {
+ unsigned int effect_id;
+ struct {
+ struct ff_effect *effect;
+ struct ff_effect *old;
+ } upload;
+ } u;
+};
+
+struct uinput_device {
+ struct input_dev *dev;
+ struct mutex mutex;
+ enum uinput_state state;
+ wait_queue_head_t waitq;
+ unsigned char ready;
+ unsigned char head;
+ unsigned char tail;
+ struct input_event buff[UINPUT_BUFFER_SIZE];
+ unsigned int ff_effects_max;
+
+ struct uinput_request *requests[UINPUT_NUM_REQUESTS];
+ wait_queue_head_t requests_waitq;
+ spinlock_t requests_lock;
+};
+
static int uinput_dev_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
@@ -149,7 +187,11 @@ static int uinput_request_submit(struct uinput_device *udev,
if (retval)
goto out;
- wait_for_completion(&request->done);
+ if (!wait_for_completion_timeout(&request->done, 30 * HZ)) {
+ retval = -ETIMEDOUT;
+ goto out;
+ }
+
retval = request->retval;
out:
@@ -320,6 +362,10 @@ static int uinput_create_device(struct uinput_device *udev)
dev->flush = uinput_dev_flush;
}
+ dev->event = uinput_dev_event;
+
+ input_set_drvdata(udev->dev, udev);
+
error = input_register_device(udev->dev);
if (error)
goto fail2;
@@ -402,18 +448,6 @@ static int uinput_validate_absbits(struct input_dev *dev)
return 0;
}
-static int uinput_allocate_device(struct uinput_device *udev)
-{
- udev->dev = input_allocate_device();
- if (!udev->dev)
- return -ENOMEM;
-
- udev->dev->event = uinput_dev_event;
- input_set_drvdata(udev->dev, udev);
-
- return 0;
-}
-
static int uinput_dev_setup(struct uinput_device *udev,
struct uinput_setup __user *arg)
{
@@ -489,9 +523,9 @@ static int uinput_setup_device_legacy(struct uinput_device *udev,
return -EINVAL;
if (!udev->dev) {
- retval = uinput_allocate_device(udev);
- if (retval)
- return retval;
+ udev->dev = input_allocate_device();
+ if (!udev->dev)
+ return -ENOMEM;
}
dev = udev->dev;
@@ -822,162 +856,161 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
return retval;
if (!udev->dev) {
- retval = uinput_allocate_device(udev);
- if (retval)
- goto out;
+ udev->dev = input_allocate_device();
+ if (!udev->dev)
+ return -ENOMEM;
}
switch (cmd) {
- case UI_GET_VERSION:
- if (put_user(UINPUT_VERSION,
- (unsigned int __user *)p))
- retval = -EFAULT;
- goto out;
+ case UI_GET_VERSION:
+ if (put_user(UINPUT_VERSION, (unsigned int __user *)p))
+ retval = -EFAULT;
+ goto out;
- case UI_DEV_CREATE:
- retval = uinput_create_device(udev);
- goto out;
+ case UI_DEV_CREATE:
+ retval = uinput_create_device(udev);
+ goto out;
- case UI_DEV_DESTROY:
- uinput_destroy_device(udev);
- goto out;
+ case UI_DEV_DESTROY:
+ uinput_destroy_device(udev);
+ goto out;
- case UI_DEV_SETUP:
- retval = uinput_dev_setup(udev, p);
- goto out;
+ case UI_DEV_SETUP:
+ retval = uinput_dev_setup(udev, p);
+ goto out;
- /* UI_ABS_SETUP is handled in the variable size ioctls */
+ /* UI_ABS_SETUP is handled in the variable size ioctls */
- case UI_SET_EVBIT:
- retval = uinput_set_bit(arg, evbit, EV_MAX);
- goto out;
+ case UI_SET_EVBIT:
+ retval = uinput_set_bit(arg, evbit, EV_MAX);
+ goto out;
- case UI_SET_KEYBIT:
- retval = uinput_set_bit(arg, keybit, KEY_MAX);
- goto out;
+ case UI_SET_KEYBIT:
+ retval = uinput_set_bit(arg, keybit, KEY_MAX);
+ goto out;
- case UI_SET_RELBIT:
- retval = uinput_set_bit(arg, relbit, REL_MAX);
- goto out;
+ case UI_SET_RELBIT:
+ retval = uinput_set_bit(arg, relbit, REL_MAX);
+ goto out;
- case UI_SET_ABSBIT:
- retval = uinput_set_bit(arg, absbit, ABS_MAX);
- goto out;
+ case UI_SET_ABSBIT:
+ retval = uinput_set_bit(arg, absbit, ABS_MAX);
+ goto out;
- case UI_SET_MSCBIT:
- retval = uinput_set_bit(arg, mscbit, MSC_MAX);
- goto out;
+ case UI_SET_MSCBIT:
+ retval = uinput_set_bit(arg, mscbit, MSC_MAX);
+ goto out;
- case UI_SET_LEDBIT:
- retval = uinput_set_bit(arg, ledbit, LED_MAX);
- goto out;
+ case UI_SET_LEDBIT:
+ retval = uinput_set_bit(arg, ledbit, LED_MAX);
+ goto out;
+
+ case UI_SET_SNDBIT:
+ retval = uinput_set_bit(arg, sndbit, SND_MAX);
+ goto out;
- case UI_SET_SNDBIT:
- retval = uinput_set_bit(arg, sndbit, SND_MAX);
+ case UI_SET_FFBIT:
+ retval = uinput_set_bit(arg, ffbit, FF_MAX);
+ goto out;
+
+ case UI_SET_SWBIT:
+ retval = uinput_set_bit(arg, swbit, SW_MAX);
+ goto out;
+
+ case UI_SET_PROPBIT:
+ retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
+ goto out;
+
+ case UI_SET_PHYS:
+ if (udev->state == UIST_CREATED) {
+ retval = -EINVAL;
goto out;
+ }
- case UI_SET_FFBIT:
- retval = uinput_set_bit(arg, ffbit, FF_MAX);
+ phys = strndup_user(p, 1024);
+ if (IS_ERR(phys)) {
+ retval = PTR_ERR(phys);
goto out;
+ }
+
+ kfree(udev->dev->phys);
+ udev->dev->phys = phys;
+ goto out;
- case UI_SET_SWBIT:
- retval = uinput_set_bit(arg, swbit, SW_MAX);
+ case UI_BEGIN_FF_UPLOAD:
+ retval = uinput_ff_upload_from_user(p, &ff_up);
+ if (retval)
goto out;
- case UI_SET_PROPBIT:
- retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
+ req = uinput_request_find(udev, ff_up.request_id);
+ if (!req || req->code != UI_FF_UPLOAD ||
+ !req->u.upload.effect) {
+ retval = -EINVAL;
goto out;
+ }
- case UI_SET_PHYS:
- if (udev->state == UIST_CREATED) {
- retval = -EINVAL;
- goto out;
- }
+ ff_up.retval = 0;
+ ff_up.effect = *req->u.upload.effect;
+ if (req->u.upload.old)
+ ff_up.old = *req->u.upload.old;
+ else
+ memset(&ff_up.old, 0, sizeof(struct ff_effect));
- phys = strndup_user(p, 1024);
- if (IS_ERR(phys)) {
- retval = PTR_ERR(phys);
- goto out;
- }
+ retval = uinput_ff_upload_to_user(p, &ff_up);
+ goto out;
- kfree(udev->dev->phys);
- udev->dev->phys = phys;
+ case UI_BEGIN_FF_ERASE:
+ if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
+ retval = -EFAULT;
goto out;
+ }
- case UI_BEGIN_FF_UPLOAD:
- retval = uinput_ff_upload_from_user(p, &ff_up);
- if (retval)
- goto out;
-
- req = uinput_request_find(udev, ff_up.request_id);
- if (!req || req->code != UI_FF_UPLOAD ||
- !req->u.upload.effect) {
- retval = -EINVAL;
- goto out;
- }
-
- ff_up.retval = 0;
- ff_up.effect = *req->u.upload.effect;
- if (req->u.upload.old)
- ff_up.old = *req->u.upload.old;
- else
- memset(&ff_up.old, 0, sizeof(struct ff_effect));
-
- retval = uinput_ff_upload_to_user(p, &ff_up);
+ req = uinput_request_find(udev, ff_erase.request_id);
+ if (!req || req->code != UI_FF_ERASE) {
+ retval = -EINVAL;
goto out;
+ }
- case UI_BEGIN_FF_ERASE:
- if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
- retval = -EFAULT;
- goto out;
- }
-
- req = uinput_request_find(udev, ff_erase.request_id);
- if (!req || req->code != UI_FF_ERASE) {
- retval = -EINVAL;
- goto out;
- }
-
- ff_erase.retval = 0;
- ff_erase.effect_id = req->u.effect_id;
- if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
- retval = -EFAULT;
- goto out;
- }
-
+ ff_erase.retval = 0;
+ ff_erase.effect_id = req->u.effect_id;
+ if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
+ retval = -EFAULT;
goto out;
+ }
- case UI_END_FF_UPLOAD:
- retval = uinput_ff_upload_from_user(p, &ff_up);
- if (retval)
- goto out;
+ goto out;
- req = uinput_request_find(udev, ff_up.request_id);
- if (!req || req->code != UI_FF_UPLOAD ||
- !req->u.upload.effect) {
- retval = -EINVAL;
- goto out;
- }
+ case UI_END_FF_UPLOAD:
+ retval = uinput_ff_upload_from_user(p, &ff_up);
+ if (retval)
+ goto out;
- req->retval = ff_up.retval;
- complete(&req->done);
+ req = uinput_request_find(udev, ff_up.request_id);
+ if (!req || req->code != UI_FF_UPLOAD ||
+ !req->u.upload.effect) {
+ retval = -EINVAL;
goto out;
+ }
- case UI_END_FF_ERASE:
- if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
- retval = -EFAULT;
- goto out;
- }
+ req->retval = ff_up.retval;
+ complete(&req->done);
+ goto out;
- req = uinput_request_find(udev, ff_erase.request_id);
- if (!req || req->code != UI_FF_ERASE) {
- retval = -EINVAL;
- goto out;
- }
+ case UI_END_FF_ERASE:
+ if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
+ retval = -EFAULT;
+ goto out;
+ }
- req->retval = ff_erase.retval;
- complete(&req->done);
+ req = uinput_request_find(udev, ff_erase.request_id);
+ if (!req || req->code != UI_FF_ERASE) {
+ retval = -EINVAL;
goto out;
+ }
+
+ req->retval = ff_erase.retval;
+ complete(&req->done);
+ goto out;
}
size = _IOC_SIZE(cmd);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 850b00e3ad8e..579b899add26 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1587,10 +1587,10 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
return PSMOUSE_GOOD_DATA;
}
-static void alps_flush_packet(unsigned long data)
+static void alps_flush_packet(struct timer_list *t)
{
- struct psmouse *psmouse = (struct psmouse *)data;
- struct alps_data *priv = psmouse->private;
+ struct alps_data *priv = from_timer(priv, t, timer);
+ struct psmouse *psmouse = priv->psmouse;
serio_pause_rx(psmouse->ps2dev.serio);
@@ -2702,7 +2702,7 @@ static int alps_set_protocol(struct psmouse *psmouse,
{
psmouse->private = priv;
- setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
+ timer_setup(&priv->timer, alps_flush_packet, 0);
priv->proto_version = protocol->version;
priv->byte0 = protocol->byte0;
diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c
index b64b81599f7e..f2aabf7f906f 100644
--- a/drivers/input/mouse/byd.c
+++ b/drivers/input/mouse/byd.c
@@ -227,6 +227,7 @@
struct byd_data {
struct timer_list timer;
+ struct psmouse *psmouse;
s32 abs_x;
s32 abs_y;
typeof(jiffies) last_touch_time;
@@ -251,10 +252,10 @@ static void byd_report_input(struct psmouse *psmouse)
input_sync(dev);
}
-static void byd_clear_touch(unsigned long data)
+static void byd_clear_touch(struct timer_list *t)
{
- struct psmouse *psmouse = (struct psmouse *)data;
- struct byd_data *priv = psmouse->private;
+ struct byd_data *priv = from_timer(priv, t, timer);
+ struct psmouse *psmouse = priv->psmouse;
serio_pause_rx(psmouse->ps2dev.serio);
priv->touch = false;
@@ -478,7 +479,8 @@ int byd_init(struct psmouse *psmouse)
if (!priv)
return -ENOMEM;
- setup_timer(&priv->timer, byd_clear_touch, (unsigned long) psmouse);
+ priv->psmouse = psmouse;
+ timer_setup(&priv->timer, byd_clear_touch, 0);
psmouse->private = priv;
psmouse->disconnect = byd_disconnect;
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 6d6b092e2da9..2690a8223841 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
@@ -1141,10 +1142,13 @@ static int elan_probe(struct i2c_client *client,
return error;
/*
- * Systems using device tree should set up interrupt via DTS,
- * the rest will use the default falling edge interrupts.
+ * Platform code (ACPI, DTS) should normally set up interrupt
+ * for us, but in case it did not let's fall back to using falling
+ * edge to be compatible with older Chromebooks.
*/
- irqflags = dev->of_node ? 0 : IRQF_TRIGGER_FALLING;
+ irqflags = irq_get_trigger_type(client->irq);
+ if (!irqflags)
+ irqflags = IRQF_TRIGGER_FALLING;
error = devm_request_threaded_irq(dev, client->irq, NULL, elan_isr,
irqflags | IRQF_ONESHOT,
@@ -1255,7 +1259,6 @@ static const struct acpi_device_id elan_acpi_id[] = {
{ "ELAN0602", 0 },
{ "ELAN0605", 0 },
{ "ELAN0608", 0 },
- { "ELAN0605", 0 },
{ "ELAN0609", 0 },
{ "ELAN060B", 0 },
{ "ELAN0611", 0 },
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
index ced07391304b..a26d8be6f795 100644
--- a/drivers/input/mouse/gpio_mouse.c
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -2,6 +2,7 @@
* Driver for simulating a mouse on GPIO lines.
*
* Copyright (C) 2007 Atmel Corporation
+ * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -11,9 +12,35 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
-#include <linux/gpio.h>
-#include <linux/gpio_mouse.h>
-
+#include <linux/gpio/consumer.h>
+#include <linux/property.h>
+#include <linux/of.h>
+
+/**
+ * struct gpio_mouse
+ * @scan_ms: the scan interval in milliseconds.
+ * @up: GPIO line for up value.
+ * @down: GPIO line for down value.
+ * @left: GPIO line for left value.
+ * @right: GPIO line for right value.
+ * @bleft: GPIO line for left button.
+ * @bmiddle: GPIO line for middle button.
+ * @bright: GPIO line for right button.
+ *
+ * This struct must be added to the platform_device in the board code.
+ * It is used by the gpio_mouse driver to setup GPIO lines and to
+ * calculate mouse movement.
+ */
+struct gpio_mouse {
+ u32 scan_ms;
+ struct gpio_desc *up;
+ struct gpio_desc *down;
+ struct gpio_desc *left;
+ struct gpio_desc *right;
+ struct gpio_desc *bleft;
+ struct gpio_desc *bmiddle;
+ struct gpio_desc *bright;
+};
/*
* Timer function which is run every scan_ms ms when the device is opened.
@@ -21,24 +48,22 @@
*/
static void gpio_mouse_scan(struct input_polled_dev *dev)
{
- struct gpio_mouse_platform_data *gpio = dev->private;
+ struct gpio_mouse *gpio = dev->private;
struct input_dev *input = dev->input;
int x, y;
- if (gpio->bleft >= 0)
+ if (gpio->bleft)
input_report_key(input, BTN_LEFT,
- gpio_get_value(gpio->bleft) ^ gpio->polarity);
- if (gpio->bmiddle >= 0)
+ gpiod_get_value(gpio->bleft));
+ if (gpio->bmiddle)
input_report_key(input, BTN_MIDDLE,
- gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
- if (gpio->bright >= 0)
+ gpiod_get_value(gpio->bmiddle));
+ if (gpio->bright)
input_report_key(input, BTN_RIGHT,
- gpio_get_value(gpio->bright) ^ gpio->polarity);
+ gpiod_get_value(gpio->bright));
- x = (gpio_get_value(gpio->right) ^ gpio->polarity)
- - (gpio_get_value(gpio->left) ^ gpio->polarity);
- y = (gpio_get_value(gpio->down) ^ gpio->polarity)
- - (gpio_get_value(gpio->up) ^ gpio->polarity);
+ x = gpiod_get_value(gpio->right) - gpiod_get_value(gpio->left);
+ y = gpiod_get_value(gpio->down) - gpiod_get_value(gpio->up);
input_report_rel(input, REL_X, x);
input_report_rel(input, REL_Y, y);
@@ -47,65 +72,61 @@ static void gpio_mouse_scan(struct input_polled_dev *dev)
static int gpio_mouse_probe(struct platform_device *pdev)
{
- struct gpio_mouse_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct device *dev = &pdev->dev;
+ struct gpio_mouse *gmouse;
struct input_polled_dev *input_poll;
struct input_dev *input;
- int pin, i;
- int error;
-
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data\n");
- error = -ENXIO;
- goto out;
- }
-
- if (pdata->scan_ms < 0) {
- dev_err(&pdev->dev, "invalid scan time\n");
- error = -EINVAL;
- goto out;
- }
-
- for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
- pin = pdata->pins[i];
-
- if (pin < 0) {
-
- if (i <= GPIO_MOUSE_PIN_RIGHT) {
- /* Mouse direction is required. */
- dev_err(&pdev->dev,
- "missing GPIO for directions\n");
- error = -EINVAL;
- goto out_free_gpios;
- }
-
- if (i == GPIO_MOUSE_PIN_BLEFT)
- dev_dbg(&pdev->dev, "no left button defined\n");
-
- } else {
- error = gpio_request(pin, "gpio_mouse");
- if (error) {
- dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
- pin, i);
- goto out_free_gpios;
- }
-
- gpio_direction_input(pin);
- }
+ int ret;
+
+ gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL);
+ if (!gmouse)
+ return -ENOMEM;
+
+ /* Assign some default scanning time */
+ ret = device_property_read_u32(dev, "scan-interval-ms",
+ &gmouse->scan_ms);
+ if (ret || gmouse->scan_ms == 0) {
+ dev_warn(dev, "invalid scan time, set to 50 ms\n");
+ gmouse->scan_ms = 50;
}
- input_poll = input_allocate_polled_device();
+ gmouse->up = devm_gpiod_get(dev, "up", GPIOD_IN);
+ if (IS_ERR(gmouse->up))
+ return PTR_ERR(gmouse->up);
+ gmouse->down = devm_gpiod_get(dev, "down", GPIOD_IN);
+ if (IS_ERR(gmouse->down))
+ return PTR_ERR(gmouse->down);
+ gmouse->left = devm_gpiod_get(dev, "left", GPIOD_IN);
+ if (IS_ERR(gmouse->left))
+ return PTR_ERR(gmouse->left);
+ gmouse->right = devm_gpiod_get(dev, "right", GPIOD_IN);
+ if (IS_ERR(gmouse->right))
+ return PTR_ERR(gmouse->right);
+
+ gmouse->bleft = devm_gpiod_get_optional(dev, "button-left", GPIOD_IN);
+ if (IS_ERR(gmouse->bleft))
+ return PTR_ERR(gmouse->bleft);
+ gmouse->bmiddle = devm_gpiod_get_optional(dev, "button-middle",
+ GPIOD_IN);
+ if (IS_ERR(gmouse->bmiddle))
+ return PTR_ERR(gmouse->bmiddle);
+ gmouse->bright = devm_gpiod_get_optional(dev, "button-right",
+ GPIOD_IN);
+ if (IS_ERR(gmouse->bright))
+ return PTR_ERR(gmouse->bright);
+
+ input_poll = devm_input_allocate_polled_device(dev);
if (!input_poll) {
- dev_err(&pdev->dev, "not enough memory for input device\n");
- error = -ENOMEM;
- goto out_free_gpios;
+ dev_err(dev, "not enough memory for input device\n");
+ return -ENOMEM;
}
platform_set_drvdata(pdev, input_poll);
/* set input-polldev handlers */
- input_poll->private = pdata;
+ input_poll->private = gmouse;
input_poll->poll = gpio_mouse_scan;
- input_poll->poll_interval = pdata->scan_ms;
+ input_poll->poll_interval = gmouse->scan_ms;
input = input_poll->input;
input->name = pdev->name;
@@ -114,63 +135,39 @@ static int gpio_mouse_probe(struct platform_device *pdev)
input_set_capability(input, EV_REL, REL_X);
input_set_capability(input, EV_REL, REL_Y);
- if (pdata->bleft >= 0)
+ if (gmouse->bleft)
input_set_capability(input, EV_KEY, BTN_LEFT);
- if (pdata->bmiddle >= 0)
+ if (gmouse->bmiddle)
input_set_capability(input, EV_KEY, BTN_MIDDLE);
- if (pdata->bright >= 0)
+ if (gmouse->bright)
input_set_capability(input, EV_KEY, BTN_RIGHT);
- error = input_register_polled_device(input_poll);
- if (error) {
- dev_err(&pdev->dev, "could not register input device\n");
- goto out_free_polldev;
+ ret = input_register_polled_device(input_poll);
+ if (ret) {
+ dev_err(dev, "could not register input device\n");
+ return ret;
}
- dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
- pdata->scan_ms,
- pdata->bleft < 0 ? "" : "left ",
- pdata->bmiddle < 0 ? "" : "middle ",
- pdata->bright < 0 ? "" : "right");
+ dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n",
+ gmouse->scan_ms,
+ gmouse->bleft ? "" : "left ",
+ gmouse->bmiddle ? "" : "middle ",
+ gmouse->bright ? "" : "right");
return 0;
-
- out_free_polldev:
- input_free_polled_device(input_poll);
-
- out_free_gpios:
- while (--i >= 0) {
- pin = pdata->pins[i];
- if (pin)
- gpio_free(pin);
- }
- out:
- return error;
}
-static int gpio_mouse_remove(struct platform_device *pdev)
-{
- struct input_polled_dev *input = platform_get_drvdata(pdev);
- struct gpio_mouse_platform_data *pdata = input->private;
- int pin, i;
-
- input_unregister_polled_device(input);
- input_free_polled_device(input);
-
- for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
- pin = pdata->pins[i];
- if (pin >= 0)
- gpio_free(pin);
- }
-
- return 0;
-}
+static const struct of_device_id gpio_mouse_of_match[] = {
+ { .compatible = "gpio-mouse", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, gpio_mouse_of_match);
static struct platform_driver gpio_mouse_device_driver = {
.probe = gpio_mouse_probe,
- .remove = gpio_mouse_remove,
.driver = {
.name = "gpio_mouse",
+ .of_match_table = gpio_mouse_of_match,
}
};
module_platform_driver(gpio_mouse_device_driver);
@@ -179,4 +176,3 @@ MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("GPIO mouse driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
-
diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c
index f5206e2c767e..5343f2c08f15 100644
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -73,7 +73,7 @@ enum rmi_f54_report_type {
F54_MAX_REPORT_TYPE,
};
-const char *rmi_f54_report_type_names[] = {
+static const char * const rmi_f54_report_type_names[] = {
[F54_REPORT_NONE] = "Unknown",
[F54_8BIT_IMAGE] = "Normalized 8-Bit Image",
[F54_16BIT_IMAGE] = "Normalized 16-Bit Image",
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 65605e4ef3cf..d66d01c5373b 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -784,7 +784,7 @@ static void hil_mlcs_process(unsigned long unused)
/************************* Keepalive timer task *********************/
-static void hil_mlcs_timer(unsigned long data)
+static void hil_mlcs_timer(struct timer_list *unused)
{
hil_mlcs_probe = 1;
tasklet_schedule(&hil_mlcs_tasklet);
@@ -998,7 +998,7 @@ int hil_mlc_unregister(hil_mlc *mlc)
static int __init hil_mlc_init(void)
{
- setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0);
+ timer_setup(&hil_mlcs_kicker, &hil_mlcs_timer, 0);
mod_timer(&hil_mlcs_kicker, jiffies + HZ);
tasklet_enable(&hil_mlcs_tasklet);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 8eef6849d066..1d7c7d81a5ef 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -794,7 +794,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
/************************* Keepalive timer task *********************/
-static void hp_sdc_kicker(unsigned long data)
+static void hp_sdc_kicker(struct timer_list *unused)
{
tasklet_schedule(&hp_sdc.task);
/* Re-insert the periodic task. */
@@ -909,9 +909,8 @@ static int __init hp_sdc_init(void)
down(&s_sync); /* Wait for t_sync to complete */
/* Create the keepalive task */
- init_timer(&hp_sdc.kicker);
+ timer_setup(&hp_sdc.kicker, hp_sdc_kicker, 0);
hp_sdc.kicker.expires = jiffies + HZ;
- hp_sdc.kicker.function = &hp_sdc_kicker;
add_timer(&hp_sdc.kicker);
hp_sdc.dev_err = 0;
diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c
index b50e3817f3c4..c62cceb97bb1 100644
--- a/drivers/input/serio/ps2-gpio.c
+++ b/drivers/input/serio/ps2-gpio.c
@@ -366,6 +366,7 @@ static int ps2_gpio_probe(struct platform_device *pdev)
gpiod_cansleep(drvdata->gpio_clk)) {
dev_err(dev, "GPIO data or clk are connected via slow bus\n");
error = -EINVAL;
+ goto err_free_serio;
}
drvdata->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index b3e688911fd9..f9e5c793f4f0 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -47,6 +47,8 @@ struct ps2if {
struct serio *io;
struct sa1111_dev *dev;
void __iomem *base;
+ int rx_irq;
+ int tx_irq;
unsigned int open;
spinlock_t lock;
unsigned int head;
@@ -64,22 +66,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id)
struct ps2if *ps2if = dev_id;
unsigned int scancode, flag, status;
- status = sa1111_readl(ps2if->base + PS2STAT);
+ status = readl_relaxed(ps2if->base + PS2STAT);
while (status & PS2STAT_RXF) {
if (status & PS2STAT_STP)
- sa1111_writel(PS2STAT_STP, ps2if->base + PS2STAT);
+ writel_relaxed(PS2STAT_STP, ps2if->base + PS2STAT);
flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
(status & PS2STAT_RXP ? 0 : SERIO_PARITY);
- scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff;
+ scancode = readl_relaxed(ps2if->base + PS2DATA) & 0xff;
if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY;
serio_interrupt(ps2if->io, scancode, flag);
- status = sa1111_readl(ps2if->base + PS2STAT);
+ status = readl_relaxed(ps2if->base + PS2STAT);
}
return IRQ_HANDLED;
@@ -94,12 +96,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
unsigned int status;
spin_lock(&ps2if->lock);
- status = sa1111_readl(ps2if->base + PS2STAT);
+ status = readl_relaxed(ps2if->base + PS2STAT);
if (ps2if->head == ps2if->tail) {
disable_irq_nosync(irq);
/* done */
} else if (status & PS2STAT_TXE) {
- sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA);
+ writel_relaxed(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA);
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
}
spin_unlock(&ps2if->lock);
@@ -122,11 +124,11 @@ static int ps2_write(struct serio *io, unsigned char val)
/*
* If the TX register is empty, we can go straight out.
*/
- if (sa1111_readl(ps2if->base + PS2STAT) & PS2STAT_TXE) {
- sa1111_writel(val, ps2if->base + PS2DATA);
+ if (readl_relaxed(ps2if->base + PS2STAT) & PS2STAT_TXE) {
+ writel_relaxed(val, ps2if->base + PS2DATA);
} else {
if (ps2if->head == ps2if->tail)
- enable_irq(ps2if->dev->irq[1]);
+ enable_irq(ps2if->tx_irq);
head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
if (head != ps2if->tail) {
ps2if->buf[ps2if->head] = val;
@@ -147,30 +149,30 @@ static int ps2_open(struct serio *io)
if (ret)
return ret;
- ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
+ ret = request_irq(ps2if->rx_irq, ps2_rxint, 0,
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
if (ret) {
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
- ps2if->dev->irq[0], ret);
+ ps2if->rx_irq, ret);
sa1111_disable_device(ps2if->dev);
return ret;
}
- ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0,
+ ret = request_irq(ps2if->tx_irq, ps2_txint, 0,
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
if (ret) {
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
- ps2if->dev->irq[1], ret);
- free_irq(ps2if->dev->irq[0], ps2if);
+ ps2if->tx_irq, ret);
+ free_irq(ps2if->rx_irq, ps2if);
sa1111_disable_device(ps2if->dev);
return ret;
}
ps2if->open = 1;
- enable_irq_wake(ps2if->dev->irq[0]);
+ enable_irq_wake(ps2if->rx_irq);
- sa1111_writel(PS2CR_ENA, ps2if->base + PS2CR);
+ writel_relaxed(PS2CR_ENA, ps2if->base + PS2CR);
return 0;
}
@@ -178,14 +180,14 @@ static void ps2_close(struct serio *io)
{
struct ps2if *ps2if = io->port_data;
- sa1111_writel(0, ps2if->base + PS2CR);
+ writel_relaxed(0, ps2if->base + PS2CR);
- disable_irq_wake(ps2if->dev->irq[0]);
+ disable_irq_wake(ps2if->rx_irq);
ps2if->open = 0;
- free_irq(ps2if->dev->irq[1], ps2if);
- free_irq(ps2if->dev->irq[0], ps2if);
+ free_irq(ps2if->tx_irq, ps2if);
+ free_irq(ps2if->rx_irq, ps2if);
sa1111_disable_device(ps2if->dev);
}
@@ -198,7 +200,7 @@ static void ps2_clear_input(struct ps2if *ps2if)
int maxread = 100;
while (maxread--) {
- if ((sa1111_readl(ps2if->base + PS2DATA) & 0xff) == 0xff)
+ if ((readl_relaxed(ps2if->base + PS2DATA) & 0xff) == 0xff)
break;
}
}
@@ -208,11 +210,11 @@ static unsigned int ps2_test_one(struct ps2if *ps2if,
{
unsigned int val;
- sa1111_writel(PS2CR_ENA | mask, ps2if->base + PS2CR);
+ writel_relaxed(PS2CR_ENA | mask, ps2if->base + PS2CR);
- udelay(2);
+ udelay(10);
- val = sa1111_readl(ps2if->base + PS2STAT);
+ val = readl_relaxed(ps2if->base + PS2STAT);
return val & (PS2STAT_KBC | PS2STAT_KBD);
}
@@ -243,7 +245,7 @@ static int ps2_test(struct ps2if *ps2if)
ret = -ENODEV;
}
- sa1111_writel(0, ps2if->base + PS2CR);
+ writel_relaxed(0, ps2if->base + PS2CR);
return ret;
}
@@ -264,7 +266,6 @@ static int ps2_probe(struct sa1111_dev *dev)
goto free;
}
-
serio->id.type = SERIO_8042;
serio->write = ps2_write;
serio->open = ps2_open;
@@ -279,6 +280,18 @@ static int ps2_probe(struct sa1111_dev *dev)
spin_lock_init(&ps2if->lock);
+ ps2if->rx_irq = sa1111_get_irq(dev, 0);
+ if (ps2if->rx_irq <= 0) {
+ ret = ps2if->rx_irq ? : -ENXIO;
+ goto free;
+ }
+
+ ps2if->tx_irq = sa1111_get_irq(dev, 1);
+ if (ps2if->tx_irq <= 0) {
+ ret = ps2if->tx_irq ? : -ENXIO;
+ goto free;
+ }
+
/*
* Request the physical region for this PS2 port.
*/
@@ -297,8 +310,8 @@ static int ps2_probe(struct sa1111_dev *dev)
sa1111_enable_device(ps2if->dev);
/* Incoming clock is 8MHz */
- sa1111_writel(0, ps2if->base + PS2CLKDIV);
- sa1111_writel(127, ps2if->base + PS2PRECNT);
+ writel_relaxed(0, ps2if->base + PS2CLKDIV);
+ writel_relaxed(127, ps2if->base + PS2PRECNT);
/*
* Flush any pending input.
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 64b30fe273fd..26a66bc7b2df 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -316,6 +316,16 @@ config TOUCHSCREEN_EGALAX_SERIAL
To compile this driver as a module, choose M here: the
module will be called egalax_ts_serial.
+config TOUCHSCREEN_EXC3000
+ tristate "EETI EXC3000 multi-touch panel support"
+ depends on I2C
+ help
+ Say Y here to enable support for I2C connected EETI
+ EXC3000 multi-touch panels.
+
+ To compile this driver as a module, choose M here: the
+ module will be called exc3000.
+
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
@@ -949,7 +959,7 @@ config TOUCHSCREEN_USB_NEXIO
config TOUCHSCREEN_USB_EASYTOUCH
default y
- bool "EasyTouch USB Touch controller device support" if EMBEDDED
+ bool "EasyTouch USB Touch controller device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
help
Say Y here if you have an EasyTouch USB Touch controller.
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 850c1562555a..2fa458088e3b 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
+obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 9c250ae780d9..0381c7809d1b 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -385,9 +385,9 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts)
input_sync(input_dev);
}
-static void ad7877_timer(unsigned long handle)
+static void ad7877_timer(struct timer_list *t)
{
- struct ad7877 *ts = (void *)handle;
+ struct ad7877 *ts = from_timer(ts, t, timer);
unsigned long flags;
spin_lock_irqsave(&ts->lock, flags);
@@ -718,7 +718,7 @@ static int ad7877_probe(struct spi_device *spi)
ts->spi = spi;
ts->input = input_dev;
- setup_timer(&ts->timer, ad7877_timer, (unsigned long) ts);
+ timer_setup(&ts->timer, ad7877_timer, 0);
mutex_init(&ts->mutex);
spin_lock_init(&ts->lock);
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 196028c45210..6bad23ee47a1 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -237,9 +237,9 @@ static void ad7879_ts_event_release(struct ad7879 *ts)
input_sync(input_dev);
}
-static void ad7879_timer(unsigned long handle)
+static void ad7879_timer(struct timer_list *t)
{
- struct ad7879 *ts = (void *)handle;
+ struct ad7879 *ts = from_timer(ts, t, timer);
ad7879_ts_event_release(ts);
}
@@ -524,13 +524,6 @@ static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts)
return 0;
}
-static void ad7879_cleanup_sysfs(void *_ts)
-{
- struct ad7879 *ts = _ts;
-
- sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group);
-}
-
int ad7879_probe(struct device *dev, struct regmap *regmap,
int irq, u16 bustype, u8 devid)
{
@@ -577,7 +570,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
ts->irq = irq;
ts->regmap = regmap;
- setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts);
+ timer_setup(&ts->timer, ad7879_timer, 0);
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
input_dev->name = "AD7879 Touchscreen";
@@ -658,11 +651,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
__ad7879_disable(ts);
- err = sysfs_create_group(&dev->kobj, &ad7879_attr_group);
- if (err)
- return err;
-
- err = devm_add_action_or_reset(dev, ad7879_cleanup_sysfs, ts);
+ err = devm_device_add_group(dev, &ad7879_attr_group);
if (err)
return err;
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c
index 8cf0b2be2df4..9140a43cfe20 100644
--- a/drivers/input/touchscreen/atmel-wm97xx.c
+++ b/drivers/input/touchscreen/atmel-wm97xx.c
@@ -208,9 +208,12 @@ static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm)
}
}
-static void atmel_wm97xx_pen_timer(unsigned long data)
+static void atmel_wm97xx_pen_timer(struct timer_list *t)
{
- atmel_wm97xx_acc_pen_up((struct wm97xx *)data);
+ struct atmel_wm97xx *atmel_wm97xx = from_timer(atmel_wm97xx, t,
+ pen_timer);
+
+ atmel_wm97xx_acc_pen_up(atmel_wm97xx->wm);
}
static int atmel_wm97xx_acc_startup(struct wm97xx *wm)
@@ -348,8 +351,7 @@ static int __init atmel_wm97xx_probe(struct platform_device *pdev)
atmel_wm97xx->gpio_pen = atmel_gpio_line;
atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen);
- setup_timer(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer,
- (unsigned long)wm);
+ timer_setup(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, 0);
ret = request_irq(atmel_wm97xx->ac97c_irq,
atmel_wm97xx_channel_b_interrupt,
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c
index beaf61ce775b..727c3232517c 100644
--- a/drivers/input/touchscreen/cyttsp4_core.c
+++ b/drivers/input/touchscreen/cyttsp4_core.c
@@ -201,13 +201,21 @@ static int cyttsp4_si_get_cydata(struct cyttsp4 *cd)
void *p;
int rc;
+ if (si->si_ofs.test_ofs <= si->si_ofs.cydata_ofs) {
+ dev_err(cd->dev,
+ "%s: invalid offset test_ofs: %zu, cydata_ofs: %zu\n",
+ __func__, si->si_ofs.test_ofs, si->si_ofs.cydata_ofs);
+ return -EINVAL;
+ }
+
si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs;
dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__,
si->si_ofs.cydata_size);
p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL);
if (p == NULL) {
- dev_err(cd->dev, "%s: fail alloc cydata memory\n", __func__);
+ dev_err(cd->dev, "%s: failed to allocate cydata memory\n",
+ __func__);
return -ENOMEM;
}
si->si_ptrs.cydata = p;
@@ -270,11 +278,19 @@ static int cyttsp4_si_get_test_data(struct cyttsp4 *cd)
void *p;
int rc;
+ if (si->si_ofs.pcfg_ofs <= si->si_ofs.test_ofs) {
+ dev_err(cd->dev,
+ "%s: invalid offset pcfg_ofs: %zu, test_ofs: %zu\n",
+ __func__, si->si_ofs.pcfg_ofs, si->si_ofs.test_ofs);
+ return -EINVAL;
+ }
+
si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs;
p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL);
if (p == NULL) {
- dev_err(cd->dev, "%s: fail alloc test memory\n", __func__);
+ dev_err(cd->dev, "%s: failed to allocate test memory\n",
+ __func__);
return -ENOMEM;
}
si->si_ptrs.test = p;
@@ -321,14 +337,20 @@ static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd)
void *p;
int rc;
+ if (si->si_ofs.opcfg_ofs <= si->si_ofs.pcfg_ofs) {
+ dev_err(cd->dev,
+ "%s: invalid offset opcfg_ofs: %zu, pcfg_ofs: %zu\n",
+ __func__, si->si_ofs.opcfg_ofs, si->si_ofs.pcfg_ofs);
+ return -EINVAL;
+ }
+
si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs;
p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL);
if (p == NULL) {
- rc = -ENOMEM;
- dev_err(cd->dev, "%s: fail alloc pcfg memory r=%d\n",
- __func__, rc);
- return rc;
+ dev_err(cd->dev, "%s: failed to allocate pcfg memory\n",
+ __func__);
+ return -ENOMEM;
}
si->si_ptrs.pcfg = p;
@@ -367,13 +389,20 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
void *p;
int rc;
+ if (si->si_ofs.ddata_ofs <= si->si_ofs.opcfg_ofs) {
+ dev_err(cd->dev,
+ "%s: invalid offset ddata_ofs: %zu, opcfg_ofs: %zu\n",
+ __func__, si->si_ofs.ddata_ofs, si->si_ofs.opcfg_ofs);
+ return -EINVAL;
+ }
+
si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs;
p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL);
if (p == NULL) {
- dev_err(cd->dev, "%s: fail alloc opcfg memory\n", __func__);
- rc = -ENOMEM;
- goto cyttsp4_si_get_opcfg_data_exit;
+ dev_err(cd->dev, "%s: failed to allocate opcfg memory\n",
+ __func__);
+ return -ENOMEM;
}
si->si_ptrs.opcfg = p;
@@ -382,7 +411,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
if (rc < 0) {
dev_err(cd->dev, "%s: fail read opcfg data r=%d\n",
__func__, rc);
- goto cyttsp4_si_get_opcfg_data_exit;
+ return rc;
}
si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs;
si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs;
@@ -447,8 +476,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg,
si->si_ofs.opcfg_size, "sysinfo_opcfg_data");
-cyttsp4_si_get_opcfg_data_exit:
- return rc;
+ return 0;
}
static int cyttsp4_si_get_ddata(struct cyttsp4 *cd)
@@ -1237,9 +1265,9 @@ static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd)
del_timer_sync(&cd->watchdog_timer);
}
-static void cyttsp4_watchdog_timer(unsigned long handle)
+static void cyttsp4_watchdog_timer(struct timer_list *t)
{
- struct cyttsp4 *cd = (struct cyttsp4 *)handle;
+ struct cyttsp4 *cd = from_timer(cd, t, watchdog_timer);
dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__);
@@ -2074,8 +2102,7 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
}
/* Setup watchdog timer */
- setup_timer(&cd->watchdog_timer, cyttsp4_watchdog_timer,
- (unsigned long)cd);
+ timer_setup(&cd->watchdog_timer, cyttsp4_watchdog_timer, 0);
/*
* call startup directly to ensure that the device
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 5bf63f76ddda..c53a3d7239e7 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -70,8 +70,10 @@
#define EDT_RAW_DATA_DELAY 1000 /* usec */
enum edt_ver {
- M06,
- M09,
+ EDT_M06,
+ EDT_M09,
+ EDT_M12,
+ GENERIC_FT,
};
struct edt_reg_addr {
@@ -179,14 +181,16 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
int error;
switch (tsdata->version) {
- case M06:
+ case EDT_M06:
cmd = 0xf9; /* tell the controller to send touch data */
offset = 5; /* where the actual touch data starts */
tplen = 4; /* data comes in so called frames */
crclen = 1; /* length of the crc data */
break;
- case M09:
+ case EDT_M09:
+ case EDT_M12:
+ case GENERIC_FT:
cmd = 0x0;
offset = 3;
tplen = 6;
@@ -209,8 +213,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
goto out;
}
- /* M09 does not send header or CRC */
- if (tsdata->version == M06) {
+ /* M09/M12 does not send header or CRC */
+ if (tsdata->version == EDT_M06) {
if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||
rdbuf[2] != datalen) {
dev_err_ratelimited(dev,
@@ -233,7 +237,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
continue;
/* M06 sometimes sends bogus coordinates in TOUCH_DOWN */
- if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN)
+ if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN)
continue;
x = ((buf[0] << 8) | buf[1]) & 0x0fff;
@@ -264,14 +268,16 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
u8 wrbuf[4];
switch (tsdata->version) {
- case M06:
+ case EDT_M06:
wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
wrbuf[2] = value;
wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
return edt_ft5x06_ts_readwrite(tsdata->client, 4,
wrbuf, 0, NULL);
- case M09:
+ case EDT_M09:
+ case EDT_M12:
+ case GENERIC_FT:
wrbuf[0] = addr;
wrbuf[1] = value;
@@ -290,7 +296,7 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
int error;
switch (tsdata->version) {
- case M06:
+ case EDT_M06:
wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
@@ -309,7 +315,9 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
}
break;
- case M09:
+ case EDT_M09:
+ case EDT_M12:
+ case GENERIC_FT:
wrbuf[0] = addr;
error = edt_ft5x06_ts_readwrite(tsdata->client, 1,
wrbuf, 1, rdbuf);
@@ -368,11 +376,13 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
}
switch (tsdata->version) {
- case M06:
+ case EDT_M06:
addr = attr->addr_m06;
break;
- case M09:
+ case EDT_M09:
+ case EDT_M12:
+ case GENERIC_FT:
addr = attr->addr_m09;
break;
@@ -437,11 +447,13 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
}
switch (tsdata->version) {
- case M06:
+ case EDT_M06:
addr = attr->addr_m06;
break;
- case M09:
+ case EDT_M09:
+ case EDT_M12:
+ case GENERIC_FT:
addr = attr->addr_m09;
break;
@@ -466,14 +478,18 @@ out:
return error ?: count;
}
+/* m06, m09: range 0-31, m12: range 0-5 */
static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN,
M09_REGISTER_GAIN, 0, 31);
+/* m06, m09: range 0-31, m12: range 0-16 */
static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET,
M09_REGISTER_OFFSET, 0, 31);
+/* m06: range 20 to 80, m09: range 0 to 30, m12: range 1 to 255... */
static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
- M09_REGISTER_THRESHOLD, 0, 80);
+ M09_REGISTER_THRESHOLD, 0, 255);
+/* m06: range 3 to 14, m12: (0x64: 100Hz) */
static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
- NO_REGISTER, 3, 14);
+ NO_REGISTER, 0, 255);
static struct attribute *edt_ft5x06_attrs[] = {
&edt_ft5x06_attr_gain.dattr.attr,
@@ -508,7 +524,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
}
/* mode register is 0x3c when in the work mode */
- if (tsdata->version == M09)
+ if (tsdata->version != EDT_M06)
goto m09_out;
error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
@@ -545,7 +561,7 @@ err_out:
return error;
m09_out:
- dev_err(&client->dev, "No factory mode support for M09\n");
+ dev_err(&client->dev, "No factory mode support for M09/M12/GENERIC_FT\n");
return -EINVAL;
}
@@ -770,16 +786,17 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
* to have garbage in there
*/
memset(rdbuf, 0, sizeof(rdbuf));
- error = edt_ft5x06_ts_readwrite(client, 1, "\xbb",
+ error = edt_ft5x06_ts_readwrite(client, 1, "\xBB",
EDT_NAME_LEN - 1, rdbuf);
if (error)
return error;
- /* if we find something consistent, stay with that assumption
- * at least M09 won't send 3 bytes here
+ /* Probe content for something consistent.
+ * M06 starts with a response byte, M12 gives the data directly.
+ * M09/Generic does not provide model number information.
*/
- if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
- tsdata->version = M06;
+ if (!strncasecmp(rdbuf + 1, "EP0", 3)) {
+ tsdata->version = EDT_M06;
/* remove last '$' end marker */
rdbuf[EDT_NAME_LEN - 1] = '\0';
@@ -792,9 +809,31 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
*p++ = '\0';
strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN);
strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
+ } else if (!strncasecmp(rdbuf, "EP0", 3)) {
+ tsdata->version = EDT_M12;
+
+ /* remove last '$' end marker */
+ rdbuf[EDT_NAME_LEN - 2] = '\0';
+ if (rdbuf[EDT_NAME_LEN - 3] == '$')
+ rdbuf[EDT_NAME_LEN - 3] = '\0';
+
+ /* look for Model/Version separator */
+ p = strchr(rdbuf, '*');
+ if (p)
+ *p++ = '\0';
+ strlcpy(model_name, rdbuf, EDT_NAME_LEN);
+ strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
} else {
- /* since there are only two versions around (M06, M09) */
- tsdata->version = M09;
+ /* If it is not an EDT M06/M12 touchscreen, then the model
+ * detection is a bit hairy. The different ft5x06
+ * firmares around don't reliably implement the
+ * identification registers. Well, we'll take a shot.
+ *
+ * The main difference between generic focaltec based
+ * touches and EDT M09 is that we know how to retrieve
+ * the max coordinates for the latter.
+ */
+ tsdata->version = GENERIC_FT;
error = edt_ft5x06_ts_readwrite(client, 1, "\xA6",
2, rdbuf);
@@ -808,8 +847,34 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
if (error)
return error;
- snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09",
- rdbuf[0] >> 4, rdbuf[0] & 0x0F);
+ /* This "model identification" is not exact. Unfortunately
+ * not all firmwares for the ft5x06 put useful values in
+ * the identification registers.
+ */
+ switch (rdbuf[0]) {
+ case 0x35: /* EDT EP0350M09 */
+ case 0x43: /* EDT EP0430M09 */
+ case 0x50: /* EDT EP0500M09 */
+ case 0x57: /* EDT EP0570M09 */
+ case 0x70: /* EDT EP0700M09 */
+ tsdata->version = EDT_M09;
+ snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09",
+ rdbuf[0] >> 4, rdbuf[0] & 0x0F);
+ break;
+ case 0xa1: /* EDT EP1010ML00 */
+ tsdata->version = EDT_M09;
+ snprintf(model_name, EDT_NAME_LEN, "EP%i%i0ML00",
+ rdbuf[0] >> 4, rdbuf[0] & 0x0F);
+ break;
+ case 0x5a: /* Solomon Goldentek Display */
+ snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0");
+ break;
+ default:
+ snprintf(model_name, EDT_NAME_LEN,
+ "generic ft5x06 (%02x)",
+ rdbuf[0]);
+ break;
+ }
}
return 0;
@@ -853,8 +918,17 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
if (reg_addr->reg_report_rate != NO_REGISTER)
tsdata->report_rate = edt_ft5x06_register_read(tsdata,
reg_addr->reg_report_rate);
- tsdata->num_x = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_x);
- tsdata->num_y = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_y);
+ if (tsdata->version == EDT_M06 ||
+ tsdata->version == EDT_M09 ||
+ tsdata->version == EDT_M12) {
+ tsdata->num_x = edt_ft5x06_register_read(tsdata,
+ reg_addr->reg_num_x);
+ tsdata->num_y = edt_ft5x06_register_read(tsdata,
+ reg_addr->reg_num_y);
+ } else {
+ tsdata->num_x = -1;
+ tsdata->num_y = -1;
+ }
}
static void
@@ -863,7 +937,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
switch (tsdata->version) {
- case M06:
+ case EDT_M06:
reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD;
reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE;
reg_addr->reg_gain = WORK_REGISTER_GAIN;
@@ -872,7 +946,8 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
reg_addr->reg_num_y = WORK_REGISTER_NUM_Y;
break;
- case M09:
+ case EDT_M09:
+ case EDT_M12:
reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
reg_addr->reg_report_rate = NO_REGISTER;
reg_addr->reg_gain = M09_REGISTER_GAIN;
@@ -880,6 +955,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
reg_addr->reg_num_x = M09_REGISTER_NUM_X;
reg_addr->reg_num_y = M09_REGISTER_NUM_Y;
break;
+
+ case GENERIC_FT:
+ /* this is a guesswork */
+ reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
+ reg_addr->reg_gain = M09_REGISTER_GAIN;
+ reg_addr->reg_offset = M09_REGISTER_OFFSET;
+ break;
}
}
@@ -969,10 +1051,20 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
input->id.bustype = BUS_I2C;
input->dev.parent = &client->dev;
- input_set_abs_params(input, ABS_MT_POSITION_X,
- 0, tsdata->num_x * 64 - 1, 0, 0);
- input_set_abs_params(input, ABS_MT_POSITION_Y,
- 0, tsdata->num_y * 64 - 1, 0, 0);
+ if (tsdata->version == EDT_M06 ||
+ tsdata->version == EDT_M09 ||
+ tsdata->version == EDT_M12) {
+ input_set_abs_params(input, ABS_MT_POSITION_X,
+ 0, tsdata->num_x * 64 - 1, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y,
+ 0, tsdata->num_y * 64 - 1, 0, 0);
+ } else {
+ /* Unknown maximum values. Specify via devicetree */
+ input_set_abs_params(input, ABS_MT_POSITION_X,
+ 0, 65535, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y,
+ 0, 65535, 0, 0);
+ }
touchscreen_parse_properties(input, true, &tsdata->prop);
@@ -998,13 +1090,13 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
return error;
}
- error = sysfs_create_group(&client->dev.kobj, &edt_ft5x06_attr_group);
+ error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group);
if (error)
return error;
error = input_register_device(input);
if (error)
- goto err_remove_attrs;
+ return error;
edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev));
device_init_wakeup(&client->dev, 1);
@@ -1016,10 +1108,6 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
tsdata->reset_gpio ? desc_to_gpio(tsdata->reset_gpio) : -1);
return 0;
-
-err_remove_attrs:
- sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group);
- return error;
}
static int edt_ft5x06_ts_remove(struct i2c_client *client)
@@ -1027,7 +1115,6 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client)
struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
edt_ft5x06_ts_teardown_debugfs(tsdata);
- sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group);
return 0;
}
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 0f4cda7282a2..e102d7764bc2 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -1070,13 +1070,6 @@ static const struct attribute_group elants_attribute_group = {
.attrs = elants_attributes,
};
-static void elants_i2c_remove_sysfs_group(void *_data)
-{
- struct elants_data *ts = _data;
-
- sysfs_remove_group(&ts->client->dev.kobj, &elants_attribute_group);
-}
-
static int elants_i2c_power_on(struct elants_data *ts)
{
int error;
@@ -1289,23 +1282,13 @@ static int elants_i2c_probe(struct i2c_client *client,
if (!client->dev.of_node)
device_init_wakeup(&client->dev, true);
- error = sysfs_create_group(&client->dev.kobj, &elants_attribute_group);
+ error = devm_device_add_group(&client->dev, &elants_attribute_group);
if (error) {
dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
error);
return error;
}
- error = devm_add_action(&client->dev,
- elants_i2c_remove_sysfs_group, ts);
- if (error) {
- elants_i2c_remove_sysfs_group(ts);
- dev_err(&client->dev,
- "Failed to add sysfs cleanup action: %d\n",
- error);
- return error;
- }
-
return 0;
}
diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c
new file mode 100644
index 000000000000..37437a53cd1a
--- /dev/null
+++ b/drivers/input/touchscreen/exc3000.c
@@ -0,0 +1,223 @@
+/*
+ * Driver for I2C connected EETI EXC3000 multiple touch controller
+ *
+ * Copyright (C) 2017 Ahmet Inan <inan@distec.de>
+ *
+ * minimal implementation based on egalax_ts.c and egalax_i2c.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/timer.h>
+#include <asm/unaligned.h>
+
+#define EXC3000_NUM_SLOTS 10
+#define EXC3000_SLOTS_PER_FRAME 5
+#define EXC3000_LEN_FRAME 66
+#define EXC3000_LEN_POINT 10
+#define EXC3000_MT_EVENT 6
+#define EXC3000_TIMEOUT_MS 100
+
+struct exc3000_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct touchscreen_properties prop;
+ struct timer_list timer;
+ u8 buf[2 * EXC3000_LEN_FRAME];
+};
+
+static void exc3000_report_slots(struct input_dev *input,
+ struct touchscreen_properties *prop,
+ const u8 *buf, int num)
+{
+ for (; num--; buf += EXC3000_LEN_POINT) {
+ if (buf[0] & BIT(0)) {
+ input_mt_slot(input, buf[1]);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+ touchscreen_report_pos(input, prop,
+ get_unaligned_le16(buf + 2),
+ get_unaligned_le16(buf + 4),
+ true);
+ }
+ }
+}
+
+static void exc3000_timer(struct timer_list *t)
+{
+ struct exc3000_data *data = from_timer(data, t, timer);
+
+ input_mt_sync_frame(data->input);
+ input_sync(data->input);
+}
+
+static int exc3000_read_frame(struct i2c_client *client, u8 *buf)
+{
+ int ret;
+
+ ret = i2c_master_send(client, "'", 2);
+ if (ret < 0)
+ return ret;
+
+ if (ret != 2)
+ return -EIO;
+
+ ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME);
+ if (ret < 0)
+ return ret;
+
+ if (ret != EXC3000_LEN_FRAME)
+ return -EIO;
+
+ if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME ||
+ buf[2] != EXC3000_MT_EVENT)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int exc3000_read_data(struct i2c_client *client,
+ u8 *buf, int *n_slots)
+{
+ int error;
+
+ error = exc3000_read_frame(client, buf);
+ if (error)
+ return error;
+
+ *n_slots = buf[3];
+ if (!*n_slots || *n_slots > EXC3000_NUM_SLOTS)
+ return -EINVAL;
+
+ if (*n_slots > EXC3000_SLOTS_PER_FRAME) {
+ /* Read 2nd frame to get the rest of the contacts. */
+ error = exc3000_read_frame(client, buf + EXC3000_LEN_FRAME);
+ if (error)
+ return error;
+
+ /* 2nd chunk must have number of contacts set to 0. */
+ if (buf[EXC3000_LEN_FRAME + 3] != 0)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
+{
+ struct exc3000_data *data = dev_id;
+ struct input_dev *input = data->input;
+ u8 *buf = data->buf;
+ int slots, total_slots;
+ int error;
+
+ error = exc3000_read_data(data->client, buf, &total_slots);
+ if (error) {
+ /* Schedule a timer to release "stuck" contacts */
+ mod_timer(&data->timer,
+ jiffies + msecs_to_jiffies(EXC3000_TIMEOUT_MS));
+ goto out;
+ }
+
+ /*
+ * We read full state successfully, no contacts will be "stuck".
+ */
+ del_timer_sync(&data->timer);
+
+ while (total_slots > 0) {
+ slots = min(total_slots, EXC3000_SLOTS_PER_FRAME);
+ exc3000_report_slots(input, &data->prop, buf + 4, slots);
+ total_slots -= slots;
+ buf += EXC3000_LEN_FRAME;
+ }
+
+ input_mt_sync_frame(input);
+ input_sync(input);
+
+out:
+ return IRQ_HANDLED;
+}
+
+static int exc3000_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct exc3000_data *data;
+ struct input_dev *input;
+ int error;
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->client = client;
+ timer_setup(&data->timer, exc3000_timer, 0);
+
+ input = devm_input_allocate_device(&client->dev);
+ if (!input)
+ return -ENOMEM;
+
+ data->input = input;
+
+ input->name = "EETI EXC3000 Touch Screen";
+ input->id.bustype = BUS_I2C;
+
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, 4095, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
+ touchscreen_parse_properties(input, true, &data->prop);
+
+ error = input_mt_init_slots(input, EXC3000_NUM_SLOTS,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ if (error)
+ return error;
+
+ error = input_register_device(input);
+ if (error)
+ return error;
+
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, exc3000_interrupt, IRQF_ONESHOT,
+ client->name, data);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static const struct i2c_device_id exc3000_id[] = {
+ { "exc3000", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, exc3000_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id exc3000_of_match[] = {
+ { .compatible = "eeti,exc3000" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, exc3000_of_match);
+#endif
+
+static struct i2c_driver exc3000_driver = {
+ .driver = {
+ .name = "exc3000",
+ .of_match_table = of_match_ptr(exc3000_of_match),
+ },
+ .id_table = exc3000_id,
+ .probe = exc3000_probe,
+};
+
+module_i2c_driver(exc3000_driver);
+
+MODULE_AUTHOR("Ahmet Inan <inan@distec.de>");
+MODULE_DESCRIPTION("I2C connected EETI EXC3000 multiple touch controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index b3bbad7d2282..69d0b8cbc71f 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -31,9 +31,18 @@
#include <linux/of.h>
#include <asm/unaligned.h>
+struct goodix_ts_data;
+
+struct goodix_chip_data {
+ u16 config_addr;
+ int config_len;
+ int (*check_config)(struct goodix_ts_data *, const struct firmware *);
+};
+
struct goodix_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
+ const struct goodix_chip_data *chip;
int abs_x_max;
int abs_y_max;
bool swapped_x_y;
@@ -41,7 +50,6 @@ struct goodix_ts_data {
bool inverted_y;
unsigned int max_touch_num;
unsigned int int_trigger_type;
- int cfg_len;
struct gpio_desc *gpiod_int;
struct gpio_desc *gpiod_rst;
u16 id;
@@ -69,7 +77,8 @@ struct goodix_ts_data {
#define GOODIX_CMD_SCREEN_OFF 0x05
#define GOODIX_READ_COOR_ADDR 0x814E
-#define GOODIX_REG_CONFIG_DATA 0x8047
+#define GOODIX_GT1X_REG_CONFIG_DATA 0x8050
+#define GOODIX_GT9X_REG_CONFIG_DATA 0x8047
#define GOODIX_REG_ID 0x8140
#define GOODIX_BUFFER_STATUS_READY BIT(7)
@@ -79,6 +88,35 @@ struct goodix_ts_data {
#define MAX_CONTACTS_LOC 5
#define TRIGGER_LOC 6
+static int goodix_check_cfg_8(struct goodix_ts_data *ts,
+ const struct firmware *cfg);
+static int goodix_check_cfg_16(struct goodix_ts_data *ts,
+ const struct firmware *cfg);
+
+static const struct goodix_chip_data gt1x_chip_data = {
+ .config_addr = GOODIX_GT1X_REG_CONFIG_DATA,
+ .config_len = GOODIX_CONFIG_MAX_LENGTH,
+ .check_config = goodix_check_cfg_16,
+};
+
+static const struct goodix_chip_data gt911_chip_data = {
+ .config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
+ .config_len = GOODIX_CONFIG_911_LENGTH,
+ .check_config = goodix_check_cfg_8,
+};
+
+static const struct goodix_chip_data gt967_chip_data = {
+ .config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
+ .config_len = GOODIX_CONFIG_967_LENGTH,
+ .check_config = goodix_check_cfg_8,
+};
+
+static const struct goodix_chip_data gt9x_chip_data = {
+ .config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
+ .config_len = GOODIX_CONFIG_MAX_LENGTH,
+ .check_config = goodix_check_cfg_8,
+};
+
static const unsigned long goodix_irq_flags[] = {
IRQ_TYPE_EDGE_RISING,
IRQ_TYPE_EDGE_FALLING,
@@ -177,22 +215,25 @@ static int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value)
return goodix_i2c_write(client, reg, &value, sizeof(value));
}
-static int goodix_get_cfg_len(u16 id)
+static const struct goodix_chip_data *goodix_get_chip_data(u16 id)
{
switch (id) {
+ case 1151:
+ return &gt1x_chip_data;
+
case 911:
case 9271:
case 9110:
case 927:
case 928:
- return GOODIX_CONFIG_911_LENGTH;
+ return &gt911_chip_data;
case 912:
case 967:
- return GOODIX_CONFIG_967_LENGTH;
+ return &gt967_chip_data;
default:
- return GOODIX_CONFIG_MAX_LENGTH;
+ return &gt9x_chip_data;
}
}
@@ -332,25 +373,12 @@ static int goodix_request_irq(struct goodix_ts_data *ts)
ts->irq_flags, ts->client->name, ts);
}
-/**
- * goodix_check_cfg - Checks if config fw is valid
- *
- * @ts: goodix_ts_data pointer
- * @cfg: firmware config data
- */
-static int goodix_check_cfg(struct goodix_ts_data *ts,
- const struct firmware *cfg)
+static int goodix_check_cfg_8(struct goodix_ts_data *ts,
+ const struct firmware *cfg)
{
- int i, raw_cfg_len;
+ int i, raw_cfg_len = cfg->size - 2;
u8 check_sum = 0;
- if (cfg->size > GOODIX_CONFIG_MAX_LENGTH) {
- dev_err(&ts->client->dev,
- "The length of the config fw is not correct");
- return -EINVAL;
- }
-
- raw_cfg_len = cfg->size - 2;
for (i = 0; i < raw_cfg_len; i++)
check_sum += cfg->data[i];
check_sum = (~check_sum) + 1;
@@ -369,6 +397,48 @@ static int goodix_check_cfg(struct goodix_ts_data *ts,
return 0;
}
+static int goodix_check_cfg_16(struct goodix_ts_data *ts,
+ const struct firmware *cfg)
+{
+ int i, raw_cfg_len = cfg->size - 3;
+ u16 check_sum = 0;
+
+ for (i = 0; i < raw_cfg_len; i += 2)
+ check_sum += get_unaligned_be16(&cfg->data[i]);
+ check_sum = (~check_sum) + 1;
+ if (check_sum != get_unaligned_be16(&cfg->data[raw_cfg_len])) {
+ dev_err(&ts->client->dev,
+ "The checksum of the config fw is not correct");
+ return -EINVAL;
+ }
+
+ if (cfg->data[raw_cfg_len + 2] != 1) {
+ dev_err(&ts->client->dev,
+ "Config fw must have Config_Fresh register set");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * goodix_check_cfg - Checks if config fw is valid
+ *
+ * @ts: goodix_ts_data pointer
+ * @cfg: firmware config data
+ */
+static int goodix_check_cfg(struct goodix_ts_data *ts,
+ const struct firmware *cfg)
+{
+ if (cfg->size > GOODIX_CONFIG_MAX_LENGTH) {
+ dev_err(&ts->client->dev,
+ "The length of the config fw is not correct");
+ return -EINVAL;
+ }
+
+ return ts->chip->check_config(ts, cfg);
+}
+
/**
* goodix_send_cfg - Write fw config to device
*
@@ -384,7 +454,7 @@ static int goodix_send_cfg(struct goodix_ts_data *ts,
if (error)
return error;
- error = goodix_i2c_write(ts->client, GOODIX_REG_CONFIG_DATA, cfg->data,
+ error = goodix_i2c_write(ts->client, ts->chip->config_addr, cfg->data,
cfg->size);
if (error) {
dev_err(&ts->client->dev, "Failed to write config data: %d",
@@ -511,8 +581,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
u8 config[GOODIX_CONFIG_MAX_LENGTH];
int error;
- error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA,
- config, ts->cfg_len);
+ error = goodix_i2c_read(ts->client, ts->chip->config_addr,
+ config, ts->chip->config_len);
if (error) {
dev_warn(&ts->client->dev,
"Error reading config (%d), using defaults\n",
@@ -592,7 +662,7 @@ static int goodix_i2c_test(struct i2c_client *client)
u8 test;
while (retry++ < 2) {
- error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA,
+ error = goodix_i2c_read(client, GOODIX_REG_ID,
&test, 1);
if (!error)
return 0;
@@ -762,7 +832,7 @@ static int goodix_ts_probe(struct i2c_client *client,
return error;
}
- ts->cfg_len = goodix_get_cfg_len(ts->id);
+ ts->chip = goodix_get_chip_data(ts->id);
if (ts->gpiod_int && ts->gpiod_rst) {
/* update device config */
@@ -891,6 +961,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
#ifdef CONFIG_OF
static const struct of_device_id goodix_of_match[] = {
+ { .compatible = "goodix,gt1151" },
{ .compatible = "goodix,gt911" },
{ .compatible = "goodix,gt9110" },
{ .compatible = "goodix,gt912" },
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 05108c2fea93..6892f0e28918 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1433,13 +1433,6 @@ static const struct attribute_group mip4_attr_group = {
.attrs = mip4_attrs,
};
-static void mip4_sysfs_remove(void *_data)
-{
- struct mip4_ts *ts = _data;
-
- sysfs_remove_group(&ts->client->dev.kobj, &mip4_attr_group);
-}
-
static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct mip4_ts *ts;
@@ -1535,21 +1528,13 @@ static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
return error;
}
- error = sysfs_create_group(&client->dev.kobj, &mip4_attr_group);
+ error = devm_device_add_group(&client->dev, &mip4_attr_group);
if (error) {
dev_err(&client->dev,
"Failed to create sysfs attribute group: %d\n", error);
return error;
}
- error = devm_add_action(&client->dev, mip4_sysfs_remove, ts);
- if (error) {
- mip4_sysfs_remove(ts);
- dev_err(&client->dev,
- "Failed to install sysfs remoce action: %d\n", error);
- return error;
- }
-
return 0;
}
diff --git a/drivers/input/touchscreen/mxs-lradc-ts.c b/drivers/input/touchscreen/mxs-lradc-ts.c
index 3707e927f770..c850b517854e 100644
--- a/drivers/input/touchscreen/mxs-lradc-ts.c
+++ b/drivers/input/touchscreen/mxs-lradc-ts.c
@@ -584,7 +584,7 @@ static void mxs_lradc_ts_hw_init(struct mxs_lradc_ts *ts)
static int mxs_lradc_ts_register(struct mxs_lradc_ts *ts)
{
- struct input_dev *input = ts->ts_input;
+ struct input_dev *input;
struct device *dev = ts->dev;
input = devm_input_allocate_device(dev);
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 4f1d3fd5d412..100538d64fff 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -943,13 +943,6 @@ static const struct attribute_group raydium_i2c_attribute_group = {
.attrs = raydium_i2c_attributes,
};
-static void raydium_i2c_remove_sysfs_group(void *_data)
-{
- struct raydium_data *ts = _data;
-
- sysfs_remove_group(&ts->client->dev.kobj, &raydium_i2c_attribute_group);
-}
-
static int raydium_i2c_power_on(struct raydium_data *ts)
{
int error;
@@ -1120,7 +1113,7 @@ static int raydium_i2c_probe(struct i2c_client *client,
return error;
}
- error = sysfs_create_group(&client->dev.kobj,
+ error = devm_device_add_group(&client->dev,
&raydium_i2c_attribute_group);
if (error) {
dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
@@ -1128,15 +1121,6 @@ static int raydium_i2c_probe(struct i2c_client *client,
return error;
}
- error = devm_add_action(&client->dev,
- raydium_i2c_remove_sysfs_group, ts);
- if (error) {
- raydium_i2c_remove_sysfs_group(ts);
- dev_err(&client->dev,
- "Failed to add sysfs cleanup action: %d\n", error);
- return error;
- }
-
return 0;
}
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index eeaf6ff03597..bda0500c9b57 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -1103,13 +1103,6 @@ static void rohm_ts_close(struct input_dev *input_dev)
ts->initialized = false;
}
-static void rohm_ts_remove_sysfs_group(void *_dev)
-{
- struct device *dev = _dev;
-
- sysfs_remove_group(&dev->kobj, &rohm_ts_attr_group);
-}
-
static int rohm_bu21023_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -1180,20 +1173,12 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client,
return error;
}
- error = sysfs_create_group(&dev->kobj, &rohm_ts_attr_group);
+ error = devm_device_add_group(dev, &rohm_ts_attr_group);
if (error) {
dev_err(dev, "failed to create sysfs group: %d\n", error);
return error;
}
- error = devm_add_action(dev, rohm_ts_remove_sysfs_group, dev);
- if (error) {
- rohm_ts_remove_sysfs_group(dev);
- dev_err(dev, "Failed to add sysfs cleanup action: %d\n",
- error);
- return error;
- }
-
return error;
}
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 8c6c6178ec12..c12d01899939 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -725,8 +725,7 @@ static int stmfts_probe(struct i2c_client *client,
}
}
- err = sysfs_create_group(&sdata->client->dev.kobj,
- &stmfts_attribute_group);
+ err = devm_device_add_group(&client->dev, &stmfts_attribute_group);
if (err)
return err;
@@ -738,7 +737,6 @@ static int stmfts_probe(struct i2c_client *client,
static int stmfts_remove(struct i2c_client *client)
{
pm_runtime_disable(&client->dev);
- sysfs_remove_group(&client->dev.kobj, &stmfts_attribute_group);
return 0;
}
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
index 88ea5e1b72ae..542db26d7fd0 100644
--- a/drivers/input/touchscreen/tsc200x-core.c
+++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -202,9 +202,9 @@ out:
return IRQ_HANDLED;
}
-static void tsc200x_penup_timer(unsigned long data)
+static void tsc200x_penup_timer(struct timer_list *t)
{
- struct tsc200x *ts = (struct tsc200x *)data;
+ struct tsc200x *ts = from_timer(ts, t, penup_timer);
unsigned long flags;
spin_lock_irqsave(&ts->lock, flags);
@@ -506,7 +506,7 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
mutex_init(&ts->mutex);
spin_lock_init(&ts->lock);
- setup_timer(&ts->penup_timer, tsc200x_penup_timer, (unsigned long)ts);
+ timer_setup(&ts->penup_timer, tsc200x_penup_timer, 0);
INIT_DELAYED_WORK(&ts->esd_work, tsc200x_esd_work);
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
index da6004e97753..638c1d78ca3a 100644
--- a/drivers/input/touchscreen/w90p910_ts.c
+++ b/drivers/input/touchscreen/w90p910_ts.c
@@ -146,9 +146,9 @@ static irqreturn_t w90p910_ts_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void w90p910_check_pen_up(unsigned long data)
+static void w90p910_check_pen_up(struct timer_list *t)
{
- struct w90p910_ts *w90p910_ts = (struct w90p910_ts *) data;
+ struct w90p910_ts *w90p910_ts = from_timer(w90p910_ts, t, timer);
unsigned long flags;
spin_lock_irqsave(&w90p910_ts->lock, flags);
@@ -232,8 +232,7 @@ static int w90x900ts_probe(struct platform_device *pdev)
w90p910_ts->input = input_dev;
w90p910_ts->state = TS_IDLE;
spin_lock_init(&w90p910_ts->lock);
- setup_timer(&w90p910_ts->timer, w90p910_check_pen_up,
- (unsigned long)w90p910_ts);
+ timer_setup(&w90p910_ts->timer, w90p910_check_pen_up, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c
index a9132603ab34..d351efd18f89 100644
--- a/drivers/input/touchscreen/wdt87xx_i2c.c
+++ b/drivers/input/touchscreen/wdt87xx_i2c.c
@@ -1106,7 +1106,7 @@ static int wdt87xx_ts_probe(struct i2c_client *client,
return error;
}
- error = sysfs_create_group(&client->dev.kobj, &wdt87xx_attr_group);
+ error = devm_device_add_group(&client->dev, &wdt87xx_attr_group);
if (error) {
dev_err(&client->dev, "create sysfs failed: %d\n", error);
return error;
@@ -1115,13 +1115,6 @@ static int wdt87xx_ts_probe(struct i2c_client *client,
return 0;
}
-static int wdt87xx_ts_remove(struct i2c_client *client)
-{
- sysfs_remove_group(&client->dev.kobj, &wdt87xx_attr_group);
-
- return 0;
-}
-
static int __maybe_unused wdt87xx_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1179,7 +1172,6 @@ MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id);
static struct i2c_driver wdt87xx_driver = {
.probe = wdt87xx_ts_probe,
- .remove = wdt87xx_ts_remove,
.id_table = wdt87xx_dev_id,
.driver = {
.name = WDT87XX_NAME,
diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h
index cd09fd6e6548..cbb150d6cbb1 100644
--- a/drivers/media/pci/ttpci/av7110.h
+++ b/drivers/media/pci/ttpci/av7110.h
@@ -94,7 +94,7 @@ struct infrared {
u8 inversion;
u16 last_key;
u16 last_toggle;
- u8 delay_timer_finished;
+ bool keypressed;
};
diff --git a/drivers/media/pci/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c
index ca05198de2c2..ee414803e6b5 100644
--- a/drivers/media/pci/ttpci/av7110_ir.c
+++ b/drivers/media/pci/ttpci/av7110_ir.c
@@ -84,15 +84,16 @@ static u16 default_key_map [256] = {
/* key-up timer */
-static void av7110_emit_keyup(unsigned long parm)
+static void av7110_emit_keyup(struct timer_list *t)
{
- struct infrared *ir = (struct infrared *) parm;
+ struct infrared *ir = from_timer(ir, t, keyup_timer);
- if (!ir || !test_bit(ir->last_key, ir->input_dev->key))
+ if (!ir || !ir->keypressed)
return;
input_report_key(ir->input_dev, ir->last_key, 0);
input_sync(ir->input_dev);
+ ir->keypressed = false;
}
@@ -152,29 +153,18 @@ static void av7110_emit_key(unsigned long parm)
return;
}
- if (timer_pending(&ir->keyup_timer)) {
- del_timer(&ir->keyup_timer);
- if (ir->last_key != keycode || toggle != ir->last_toggle) {
- ir->delay_timer_finished = 0;
- input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
- input_event(ir->input_dev, EV_KEY, keycode, 1);
- input_sync(ir->input_dev);
- } else if (ir->delay_timer_finished) {
- input_event(ir->input_dev, EV_KEY, keycode, 2);
- input_sync(ir->input_dev);
- }
- } else {
- ir->delay_timer_finished = 0;
- input_event(ir->input_dev, EV_KEY, keycode, 1);
- input_sync(ir->input_dev);
- }
+ if (ir->keypressed &&
+ (ir->last_key != keycode || toggle != ir->last_toggle))
+ input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
+ input_event(ir->input_dev, EV_KEY, keycode, 1);
+ input_sync(ir->input_dev);
+
+ ir->keypressed = true;
ir->last_key = keycode;
ir->last_toggle = toggle;
- ir->keyup_timer.expires = jiffies + UP_TIMEOUT;
- add_timer(&ir->keyup_timer);
-
+ mod_timer(&ir->keyup_timer, jiffies + UP_TIMEOUT);
}
@@ -204,16 +194,6 @@ static void input_register_keys(struct infrared *ir)
ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);
}
-
-/* called by the input driver after rep[REP_DELAY] ms */
-static void input_repeat_key(unsigned long parm)
-{
- struct infrared *ir = (struct infrared *) parm;
-
- ir->delay_timer_finished = 1;
-}
-
-
/* check for configuration changes */
int av7110_check_ir_config(struct av7110 *av7110, int force)
{
@@ -333,8 +313,7 @@ int av7110_ir_init(struct av7110 *av7110)
av_list[av_cnt++] = av7110;
av7110_check_ir_config(av7110, true);
- setup_timer(&av7110->ir.keyup_timer, av7110_emit_keyup,
- (unsigned long)&av7110->ir);
+ timer_setup(&av7110->ir.keyup_timer, av7110_emit_keyup, 0);
input_dev = input_allocate_device();
if (!input_dev)
@@ -365,8 +344,13 @@ int av7110_ir_init(struct av7110 *av7110)
input_free_device(input_dev);
return err;
}
- input_dev->timer.function = input_repeat_key;
- input_dev->timer.data = (unsigned long) &av7110->ir;
+
+ /*
+ * Input core's default autorepeat is 33 cps with 250 msec
+ * delay, let's adjust to numbers more suitable for remote
+ * control.
+ */
+ input_enable_softrepeat(input_dev, 250, 125);
if (av_cnt == 1) {
e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops);
diff --git a/include/linux/gpio_mouse.h b/include/linux/gpio_mouse.h
deleted file mode 100644
index 44ed7aa14d85..000000000000
--- a/include/linux/gpio_mouse.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Driver for simulating a mouse on GPIO lines.
- *
- * Copyright (C) 2007 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _GPIO_MOUSE_H
-#define _GPIO_MOUSE_H
-
-#define GPIO_MOUSE_POLARITY_ACT_HIGH 0x00
-#define GPIO_MOUSE_POLARITY_ACT_LOW 0x01
-
-#define GPIO_MOUSE_PIN_UP 0
-#define GPIO_MOUSE_PIN_DOWN 1
-#define GPIO_MOUSE_PIN_LEFT 2
-#define GPIO_MOUSE_PIN_RIGHT 3
-#define GPIO_MOUSE_PIN_BLEFT 4
-#define GPIO_MOUSE_PIN_BMIDDLE 5
-#define GPIO_MOUSE_PIN_BRIGHT 6
-#define GPIO_MOUSE_PIN_MAX 7
-
-/**
- * struct gpio_mouse_platform_data
- * @scan_ms: integer in ms specifying the scan periode.
- * @polarity: Pin polarity, active high or low.
- * @up: GPIO line for up value.
- * @down: GPIO line for down value.
- * @left: GPIO line for left value.
- * @right: GPIO line for right value.
- * @bleft: GPIO line for left button.
- * @bmiddle: GPIO line for middle button.
- * @bright: GPIO line for right button.
- *
- * This struct must be added to the platform_device in the board code.
- * It is used by the gpio_mouse driver to setup GPIO lines and to
- * calculate mouse movement.
- */
-struct gpio_mouse_platform_data {
- int scan_ms;
- int polarity;
-
- union {
- struct {
- int up;
- int down;
- int left;
- int right;
-
- int bleft;
- int bmiddle;
- int bright;
- };
- int pins[GPIO_MOUSE_PIN_MAX];
- };
-};
-
-#endif /* _GPIO_MOUSE_H */
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
deleted file mode 100644
index 75de43da2301..000000000000
--- a/include/linux/uinput.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * User level driver support for input subsystem
- *
- * Heavily based on evdev.c by Vojtech Pavlik
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
- *
- * Changes/Revisions:
- * 0.5 08/13/2015 (David Herrmann <dh.herrmann@gmail.com> &
- * Benjamin Tissoires <benjamin.tissoires@redhat.com>)
- * - add UI_DEV_SETUP ioctl
- * - add UI_ABS_SETUP ioctl
- * - add UI_GET_VERSION ioctl
- * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
- * - add UI_GET_SYSNAME ioctl
- * 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
- * - update ff support for the changes in kernel interface
- * - add UINPUT_VERSION
- * 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
- * - added force feedback support
- * - added UI_SET_PHYS
- * 0.1 20/06/2002
- * - first public version
- */
-#ifndef __UINPUT_H_
-#define __UINPUT_H_
-
-#include <uapi/linux/uinput.h>
-
-#define UINPUT_NAME "uinput"
-#define UINPUT_BUFFER_SIZE 16
-#define UINPUT_NUM_REQUESTS 16
-
-enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
-
-struct uinput_request {
- unsigned int id;
- unsigned int code; /* UI_FF_UPLOAD, UI_FF_ERASE */
-
- int retval;
- struct completion done;
-
- union {
- unsigned int effect_id;
- struct {
- struct ff_effect *effect;
- struct ff_effect *old;
- } upload;
- } u;
-};
-
-struct uinput_device {
- struct input_dev *dev;
- struct mutex mutex;
- enum uinput_state state;
- wait_queue_head_t waitq;
- unsigned char ready;
- unsigned char head;
- unsigned char tail;
- struct input_event buff[UINPUT_BUFFER_SIZE];
- unsigned int ff_effects_max;
-
- struct uinput_request *requests[UINPUT_NUM_REQUESTS];
- wait_queue_head_t requests_waitq;
- spinlock_t requests_lock;
-};
-#endif /* __UINPUT_H_ */