summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-24 11:16:06 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-24 11:16:06 -0700
commite1611017870fa1582b5ff9ec0edc09542318daa6 (patch)
treefaff3dcc5bd72395f407a01922ac5366f9a76cea
parentf0e6f20cb52b14c2c441f04e21cef0c95d498cac (diff)
parent7a0e692a0381254b2f77c54dec100cd3325a6fdf (diff)
downloadlwn-e1611017870fa1582b5ff9ec0edc09542318daa6.tar.gz
lwn-e1611017870fa1582b5ff9ec0edc09542318daa6.zip
Merge tag 'input-for-v7.2-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - A new driver for Wacom W9000-series penabled touchscreens - Updates to STM FTS driver adding support for reset line and preparing the driver for STMFTS5 support - Updates to RMI4 and IMS PCU drivers hardening the code - Support for half-duplex mode restored in ADS7846 driver - Updates to driver's device_id tables to use named initializers - Removal of no longer used PCAP keys and touchscreen drivers (support for the ezx series of phones was removed in 2022) - Removal of xilinx_ps2 driver which is no longer used either - Updates to userio to allow setting up additional serio port characteristics (such as id, extra and proto) - Assorted hardening and cleanup fixes for other drivers * tag 'input-for-v7.2-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (72 commits) Input: mms114 - fix touch indexing for MMS134S and MMS136 Input: elan_i2c - prevent division by zero and arithmetic underflow Input: stop force-feedback timer when unregistering input devices Input: iforce - bound the device-reported force-feedback effect index Input: goodix - clamp the device-reported contact count Input: mms114 - reject an oversized device packet size Input: touchwin - reset the packet index on every complete packet Input: rmi4 - update formatting in F12 Input: rmi4 - propagate proper error code in F12 sensor tuning Input: rmi4 - simplify size calculations in F12 Input: rmi4 - use sizeof(*ptr) and idiomatic checks in f12 allocators Input: rmi4 - use devm_kmalloc for F12 data packet buffer Input: rmi4 - use flexible array member for IRQ masks in F12 Input: rmi4 - use unaligned access helpers in F12 Input: rmi4 - change reg_size type to u32 Input: rmi4 - refactor F12 probe function Input: rmi4 - use kzalloc_flex() for struct rmi_function Input: rmi4 - refactor function allocation and registration Input: rmi4 - use local presence map in rmi_read_register_desc() Input: rmi4 - fix limit in rmi_register_desc_has_subpacket() ...
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml4
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/wacom,w9007a-lt03.yaml73
-rw-r--r--Documentation/input/userio.rst25
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/input/ff-memless.c27
-rw-r--r--drivers/input/gameport/ns558.c46
-rw-r--r--drivers/input/input.c3
-rw-r--r--drivers/input/joystick/adafruit-seesaw.c2
-rw-r--r--drivers/input/joystick/as5011.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c18
-rw-r--r--drivers/input/joystick/qwiic-joystick.c2
-rw-r--r--drivers/input/keyboard/adp5588-keys.c4
-rw-r--r--drivers/input/keyboard/cap11xx.c14
-rw-r--r--drivers/input/keyboard/cypress-sf.c2
-rw-r--r--drivers/input/keyboard/dlink-dir685-touchkeys.c2
-rw-r--r--drivers/input/keyboard/ipaq-micro-keys.c24
-rw-r--r--drivers/input/keyboard/lm8323.c4
-rw-r--r--drivers/input/keyboard/lm8333.c2
-rw-r--r--drivers/input/keyboard/max7359_keypad.c2
-rw-r--r--drivers/input/keyboard/mpr121_touchkey.c2
-rw-r--r--drivers/input/keyboard/qt1070.c2
-rw-r--r--drivers/input/keyboard/qt2160.c2
-rw-r--r--drivers/input/keyboard/tca8418_keypad.c2
-rw-r--r--drivers/input/keyboard/tm2-touchkey.c2
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/ad714x-i2c.c10
-rw-r--r--drivers/input/misc/adxl34x-i2c.c2
-rw-r--r--drivers/input/misc/apanel.c2
-rw-r--r--drivers/input/misc/atlas_btns.c109
-rw-r--r--drivers/input/misc/atmel_captouch.c2
-rw-r--r--drivers/input/misc/bma150.c6
-rw-r--r--drivers/input/misc/cma3000_d0x_i2c.c2
-rw-r--r--drivers/input/misc/da7280.c2
-rw-r--r--drivers/input/misc/drv260x.c8
-rw-r--r--drivers/input/misc/drv2665.c2
-rw-r--r--drivers/input/misc/drv2667.c2
-rw-r--r--drivers/input/misc/ims-pcu.c131
-rw-r--r--drivers/input/misc/kxtj9.c2
-rw-r--r--drivers/input/misc/mma8450.c2
-rw-r--r--drivers/input/misc/pcap_keys.c125
-rw-r--r--drivers/input/misc/pcf8574_keypad.c2
-rw-r--r--drivers/input/misc/yealink.c9
-rw-r--r--drivers/input/mouse/cyapa.c2
-rw-r--r--drivers/input/mouse/elan_i2c_core.c38
-rw-r--r--drivers/input/mouse/synaptics_i2c.c2
-rw-r--r--drivers/input/rmi4/rmi_2d_sensor.h4
-rw-r--r--drivers/input/rmi4/rmi_bus.c34
-rw-r--r--drivers/input/rmi4/rmi_bus.h1
-rw-r--r--drivers/input/rmi4/rmi_driver.c204
-rw-r--r--drivers/input/rmi4/rmi_driver.h13
-rw-r--r--drivers/input/rmi4/rmi_f11.c2
-rw-r--r--drivers/input/rmi4/rmi_f12.c415
-rw-r--r--drivers/input/rmi4/rmi_i2c.c2
-rw-r--r--drivers/input/rmi4/rmi_smbus.c2
-rw-r--r--drivers/input/serio/Kconfig10
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/serio/apbps2.c7
-rw-r--r--drivers/input/serio/i8042-acpipnpio.h56
-rw-r--r--drivers/input/serio/userio.c34
-rw-r--r--drivers/input/serio/xilinx_ps2.c363
-rw-r--r--drivers/input/tablet/aiptek.c31
-rw-r--r--drivers/input/touchscreen/Kconfig22
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c4
-rw-r--r--drivers/input/touchscreen/ads7846.c173
-rw-r--r--drivers/input/touchscreen/ar1021_i2c.c2
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c23
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c2
-rw-r--r--drivers/input/touchscreen/bu21013_ts.c2
-rw-r--r--drivers/input/touchscreen/bu21029_ts.c2
-rw-r--r--drivers/input/touchscreen/cy8ctma140.c2
-rw-r--r--drivers/input/touchscreen/cy8ctmg110_ts.c2
-rw-r--r--drivers/input/touchscreen/cyttsp5.c2
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c2
-rw-r--r--drivers/input/touchscreen/eeti_ts.c2
-rw-r--r--drivers/input/touchscreen/egalax_ts.c2
-rw-r--r--drivers/input/touchscreen/elants_i2c.c6
-rw-r--r--drivers/input/touchscreen/exc3000.c8
-rw-r--r--drivers/input/touchscreen/goodix.c5
-rw-r--r--drivers/input/touchscreen/hideep.c2
-rw-r--r--drivers/input/touchscreen/himax_hx83112b.c4
-rw-r--r--drivers/input/touchscreen/hynitron-cst816x.c2
-rw-r--r--drivers/input/touchscreen/ili210x.c8
-rw-r--r--drivers/input/touchscreen/ilitek_ts_i2c.c2
-rw-r--r--drivers/input/touchscreen/iqs5xx.c6
-rw-r--r--drivers/input/touchscreen/max11801_ts.c2
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c2
-rw-r--r--drivers/input/touchscreen/migor_ts.c2
-rw-r--r--drivers/input/touchscreen/mms114.c26
-rw-r--r--drivers/input/touchscreen/novatek-nvt-ts.c4
-rw-r--r--drivers/input/touchscreen/pcap_ts.c252
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c4
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c4
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c2
-rw-r--r--drivers/input/touchscreen/s6sy761.c2
-rw-r--r--drivers/input/touchscreen/silead.c12
-rw-r--r--drivers/input/touchscreen/sis_i2c.c4
-rw-r--r--drivers/input/touchscreen/st1232.c4
-rw-r--r--drivers/input/touchscreen/stmfts.c162
-rw-r--r--drivers/input/touchscreen/touchwin.c15
-rw-r--r--drivers/input/touchscreen/tsc2004.c2
-rw-r--r--drivers/input/touchscreen/tsc2007_core.c8
-rw-r--r--drivers/input/touchscreen/wacom_i2c.c2
-rw-r--r--drivers/input/touchscreen/wacom_w9000.c444
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c2
-rw-r--r--drivers/input/touchscreen/zet6223.c2
-rw-r--r--drivers/input/touchscreen/zforce_ts.c2
-rw-r--r--include/linux/input.h3
-rw-r--r--include/uapi/linux/userio.h7
110 files changed, 1673 insertions, 1501 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
index 12256ae7df90..64c4f24ea3dd 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
@@ -40,6 +40,10 @@ properties:
vdd-supply:
description: Power supply
+ reset-gpios:
+ description: Reset GPIO (active-low)
+ maxItems: 1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/input/touchscreen/wacom,w9007a-lt03.yaml b/Documentation/devicetree/bindings/input/touchscreen/wacom,w9007a-lt03.yaml
new file mode 100644
index 000000000000..6d1da6a435d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/wacom,w9007a-lt03.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/wacom,w9007a-lt03.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Wacom W9000-series penabled I2C touchscreen
+
+maintainers:
+ - Hendrik Noack <hendrik-noack@gmx.de>
+
+description: |
+ The W9000-series are penabled touchscreen controllers by Wacom.
+
+ The firmware of controllers in different devices may differ. This can also
+ affect the controller's behavior.
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ enum:
+ - wacom,w9002
+ - wacom,w9007a-lt03
+ - wacom,w9007a-v1
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ vdd-supply: true
+
+ flash-mode-gpios:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ digitizer@56 {
+ compatible = "wacom,w9007a-lt03";
+ reg = <0x56>;
+ interrupt-parent = <&gpd1>;
+ interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+
+ vdd-supply = <&stylus_reg>;
+
+ flash-mode-gpios = <&gpd1 3 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpx0 1 GPIO_ACTIVE_LOW>;
+
+ touchscreen-x-mm = <216>;
+ touchscreen-y-mm = <135>;
+ touchscreen-inverted-x;
+ };
+ };
diff --git a/Documentation/input/userio.rst b/Documentation/input/userio.rst
index f780c77931fe..7aaaa629bde0 100644
--- a/Documentation/input/userio.rst
+++ b/Documentation/input/userio.rst
@@ -5,7 +5,7 @@ The userio Protocol
===================
-:Copyright: |copy| 2015 Stephen Chandler Paul <thatslyude@gmail.com>
+:Copyright: |copy| 2015 Lyude Paul <thatslyude@gmail.com>
Sponsored by Red Hat
@@ -66,8 +66,27 @@ USERIO_CMD_SET_PORT_TYPE
~~~~~~~~~~~~~~~~~~~~~~~~
Sets the type of port we're emulating, where ``data`` is the port type being
-set. Can be any of the macros from <linux/serio.h>. For example: SERIO_8042
-would set the port type to be a normal PS/2 port.
+set. Can be any of the serio type macros from <linux/serio.h>. For example:
+SERIO_8042 would set the port type to be a normal PS/2 port.
+
+USERIO_CMD_SET_PORT_PROTO
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sets the protocol of port we're emulating, where ``data`` is the protocol being
+set. Can be any of the serio proto macros from <linux/serio.h>. For example:
+SERIO_IFORCE would set the port type to be an I-Force serial joystick.
+
+USERIO_CMD_SET_PORT_ID
+~~~~~~~~~~~~~~~~~~~~~~
+
+Sets the ``id`` value on the identification of port we're emulating, where
+``data`` is the value being set.
+
+USERIO_CMD_SET_PORT_EXTRA
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sets the ``extra`` value on the identification of port we're emulating, where
+``data`` is the value being set.
USERIO_CMD_SEND_INTERRUPT
~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/MAINTAINERS b/MAINTAINERS
index 9b787bc2855f..75c6bf6699c9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28731,7 +28731,7 @@ F: sound/drivers/pcmtest.c
F: tools/testing/selftests/alsa/test-pcmtest-driver.c
VIRTUAL SERIO DEVICE DRIVER
-M: Stephen Chandler Paul <thatslyude@gmail.com>
+M: Lyude Paul <thatslyude@gmail.com>
S: Maintained
F: drivers/input/serio/userio.c
F: include/uapi/linux/userio.h
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index 937370d04928..d1fefd1dfc0d 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -484,17 +484,31 @@ static void ml_ff_destroy(struct ff_device *ff)
struct ml_device *ml = ff->private;
/*
- * Even though we stop all playing effects when tearing down
- * an input device (via input_device_flush() that calls into
- * input_ff_flush() that stops and erases all effects), we
- * do not actually stop the timer, and therefore we should
- * do it here.
+ * The timer is normally shut down in ml_ff_stop() when the device
+ * is unregistered. However, we still shut it down here as a safety
+ * net and for cases where the device was never registered (e.g.
+ * error paths during probe).
*/
- timer_delete_sync(&ml->timer);
+ timer_shutdown_sync(&ml->timer);
kfree(ml->private);
}
+static void ml_ff_stop(struct ff_device *ff)
+{
+ struct ml_device *ml = ff->private;
+
+ /*
+ * Even though we stop all playing effects when tearing down an
+ * input device (by the way of evdev calling input_flush_device()
+ * that calls into input_ff_flush() that stops and erases all
+ * effects), we do not actually shutdown the timer, and therefore
+ * we should do it here to prevent it firing after the input
+ * device is unregistered and its associated resources are freed.
+ */
+ timer_shutdown_sync(&ml->timer);
+}
+
/**
* input_ff_create_memless() - create memoryless force-feedback device
* @dev: input device supporting force-feedback
@@ -529,6 +543,7 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
ff->playback = ml_ff_playback;
ff->set_gain = ml_ff_set_gain;
ff->destroy = ml_ff_destroy;
+ ff->stop = ml_ff_stop;
/* we can emulate periodic effects with RUMBLE */
if (test_bit(FF_RUMBLE, ff->ffbit)) {
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index fdece6ec1df3..f70a96c4f1fd 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -148,29 +148,29 @@ static int ns558_isa_probe(int io)
#ifdef CONFIG_PNP
static const struct pnp_device_id pnp_devids[] = {
- { .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */
- { .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */
- { .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */
- { .id = "@P@2001", .driver_data = 0 }, /* ALS 120 */
- { .id = "ASB16fd", .driver_data = 0 }, /* AdLib NSC16 */
- { .id = "AZT3001", .driver_data = 0 }, /* AZT1008 */
- { .id = "CDC0001", .driver_data = 0 }, /* Opl3-SAx */
- { .id = "CSC0001", .driver_data = 0 }, /* CS4232 */
- { .id = "CSC000f", .driver_data = 0 }, /* CS4236 */
- { .id = "CSC0101", .driver_data = 0 }, /* CS4327 */
- { .id = "CTL7001", .driver_data = 0 }, /* SB16 */
- { .id = "CTL7002", .driver_data = 0 }, /* AWE64 */
- { .id = "CTL7005", .driver_data = 0 }, /* Vibra16 */
- { .id = "ENS2020", .driver_data = 0 }, /* SoundscapeVIVO */
- { .id = "ESS0001", .driver_data = 0 }, /* ES1869 */
- { .id = "ESS0005", .driver_data = 0 }, /* ES1878 */
- { .id = "ESS6880", .driver_data = 0 }, /* ES688 */
- { .id = "IBM0012", .driver_data = 0 }, /* CS4232 */
- { .id = "OPT0001", .driver_data = 0 }, /* OPTi Audio16 */
- { .id = "YMH0006", .driver_data = 0 }, /* Opl3-SA */
- { .id = "YMH0022", .driver_data = 0 }, /* Opl3-SAx */
- { .id = "PNPb02f", .driver_data = 0 }, /* Generic */
- { .id = "", },
+ { .id = "@P@0001" }, /* ALS 100 */
+ { .id = "@P@0020" }, /* ALS 200 */
+ { .id = "@P@1001" }, /* ALS 100+ */
+ { .id = "@P@2001" }, /* ALS 120 */
+ { .id = "ASB16fd" }, /* AdLib NSC16 */
+ { .id = "AZT3001" }, /* AZT1008 */
+ { .id = "CDC0001" }, /* Opl3-SAx */
+ { .id = "CSC0001" }, /* CS4232 */
+ { .id = "CSC000f" }, /* CS4236 */
+ { .id = "CSC0101" }, /* CS4327 */
+ { .id = "CTL7001" }, /* SB16 */
+ { .id = "CTL7002" }, /* AWE64 */
+ { .id = "CTL7005" }, /* Vibra16 */
+ { .id = "ENS2020" }, /* SoundscapeVIVO */
+ { .id = "ESS0001" }, /* ES1869 */
+ { .id = "ESS0005" }, /* ES1878 */
+ { .id = "ESS6880" }, /* ES688 */
+ { .id = "IBM0012" }, /* CS4232 */
+ { .id = "OPT0001" }, /* OPTi Audio16 */
+ { .id = "YMH0006" }, /* Opl3-SA */
+ { .id = "YMH0022" }, /* Opl3-SAx */
+ { .id = "PNPb02f" }, /* Generic */
+ { }
};
MODULE_DEVICE_TABLE(pnp, pnp_devids);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 39d9d2b1e3ca..cf6fecea79b8 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2212,6 +2212,9 @@ static void __input_unregister_device(struct input_dev *dev)
input_wakeup_procfs_readers();
}
+ if (dev->ff && dev->ff->stop)
+ dev->ff->stop(dev->ff);
+
device_del(&dev->dev);
}
diff --git a/drivers/input/joystick/adafruit-seesaw.c b/drivers/input/joystick/adafruit-seesaw.c
index c248c15b849d..5835ed1e29e1 100644
--- a/drivers/input/joystick/adafruit-seesaw.c
+++ b/drivers/input/joystick/adafruit-seesaw.c
@@ -304,7 +304,7 @@ static int seesaw_probe(struct i2c_client *client)
}
static const struct i2c_device_id seesaw_id_table[] = {
- { SEESAW_DEVICE_NAME },
+ { .name = SEESAW_DEVICE_NAME },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, seesaw_id_table);
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
index 7b4d61626898..5fca92bf9df0 100644
--- a/drivers/input/joystick/as5011.c
+++ b/drivers/input/joystick/as5011.c
@@ -337,7 +337,7 @@ static void as5011_remove(struct i2c_client *client)
}
static const struct i2c_device_id as5011_id[] = {
- { MODULE_DEVICE_ALIAS },
+ { .name = MODULE_DEVICE_ALIAS },
{ }
};
MODULE_DEVICE_TABLE(i2c, as5011_id);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index fd1cd731d781..effa76bfd8f9 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -186,14 +186,18 @@ void iforce_process_packet(struct iforce *iforce,
/* Check if an effect was just started or stopped */
i = data[1] & 0x7f;
- if (data[1] & 0x80) {
- if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
- /* Report play event */
- input_report_ff_status(dev, i, FF_STATUS_PLAYING);
+ if (i < IFORCE_EFFECTS_MAX) {
+ if (data[1] & 0x80) {
+ if (!test_and_set_bit(FF_CORE_IS_PLAYED,
+ iforce->core_effects[i].flags)) {
+ /* Report play event */
+ input_report_ff_status(dev, i, FF_STATUS_PLAYING);
+ }
+ } else if (test_and_clear_bit(FF_CORE_IS_PLAYED,
+ iforce->core_effects[i].flags)) {
+ /* Report stop event */
+ input_report_ff_status(dev, i, FF_STATUS_STOPPED);
}
- } else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
- /* Report stop event */
- input_report_ff_status(dev, i, FF_STATUS_STOPPED);
}
for (j = 3; j < len; j += 2)
diff --git a/drivers/input/joystick/qwiic-joystick.c b/drivers/input/joystick/qwiic-joystick.c
index 6f989d00d3ec..c471afc7862b 100644
--- a/drivers/input/joystick/qwiic-joystick.c
+++ b/drivers/input/joystick/qwiic-joystick.c
@@ -126,7 +126,7 @@ MODULE_DEVICE_TABLE(of, of_qwiic_match);
#endif /* CONFIG_OF */
static const struct i2c_device_id qwiic_id_table[] = {
- { KBUILD_MODNAME },
+ { .name = KBUILD_MODNAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, qwiic_id_table);
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 414fbef4abf9..8d14d0f69d4e 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -842,8 +842,8 @@ static int adp5588_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume);
static const struct i2c_device_id adp5588_id[] = {
- { "adp5588-keys" },
- { "adp5587-keys" },
+ { .name = "adp5588-keys" },
+ { .name = "adp5587-keys" },
{ }
};
MODULE_DEVICE_TABLE(i2c, adp5588_id);
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 0c17cbaa3d27..2447c1ae2166 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -651,13 +651,13 @@ static const struct of_device_id cap11xx_dt_ids[] = {
MODULE_DEVICE_TABLE(of, cap11xx_dt_ids);
static const struct i2c_device_id cap11xx_i2c_ids[] = {
- { "cap1106", (kernel_ulong_t)&cap1106_model },
- { "cap1126", (kernel_ulong_t)&cap1126_model },
- { "cap1188", (kernel_ulong_t)&cap1188_model },
- { "cap1203", (kernel_ulong_t)&cap1203_model },
- { "cap1206", (kernel_ulong_t)&cap1206_model },
- { "cap1293", (kernel_ulong_t)&cap1293_model },
- { "cap1298", (kernel_ulong_t)&cap1298_model },
+ { .name = "cap1106", .driver_data = (kernel_ulong_t)&cap1106_model },
+ { .name = "cap1126", .driver_data = (kernel_ulong_t)&cap1126_model },
+ { .name = "cap1188", .driver_data = (kernel_ulong_t)&cap1188_model },
+ { .name = "cap1203", .driver_data = (kernel_ulong_t)&cap1203_model },
+ { .name = "cap1206", .driver_data = (kernel_ulong_t)&cap1206_model },
+ { .name = "cap1293", .driver_data = (kernel_ulong_t)&cap1293_model },
+ { .name = "cap1298", .driver_data = (kernel_ulong_t)&cap1298_model },
{ }
};
MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids);
diff --git a/drivers/input/keyboard/cypress-sf.c b/drivers/input/keyboard/cypress-sf.c
index 335b72efc5aa..4b2ae07f315c 100644
--- a/drivers/input/keyboard/cypress-sf.c
+++ b/drivers/input/keyboard/cypress-sf.c
@@ -209,7 +209,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops,
cypress_sf_suspend, cypress_sf_resume);
static const struct i2c_device_id cypress_sf_id_table[] = {
- { CYPRESS_SF_DEV_NAME },
+ { .name = CYPRESS_SF_DEV_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, cypress_sf_id_table);
diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c
index 4184dd2eaeeb..bf94367f6b64 100644
--- a/drivers/input/keyboard/dlink-dir685-touchkeys.c
+++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c
@@ -128,7 +128,7 @@ static int dir685_tk_probe(struct i2c_client *client)
}
static const struct i2c_device_id dir685_tk_id[] = {
- { "dir685tk" },
+ { .name = "dir685tk" },
{ }
};
MODULE_DEVICE_TABLE(i2c, dir685_tk_id);
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index ca7ec054b1ce..ebd991de70f8 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -20,12 +20,6 @@
#include <linux/platform_device.h>
#include <linux/mfd/ipaq-micro.h>
-struct ipaq_micro_keys {
- struct ipaq_micro *micro;
- struct input_dev *input;
- u16 *codes;
-};
-
static const u16 micro_keycodes[] = {
KEY_RECORD, /* 1: Record button */
KEY_CALENDAR, /* 2: Calendar */
@@ -38,11 +32,20 @@ static const u16 micro_keycodes[] = {
KEY_DOWN, /* 9: Down */
};
+struct ipaq_micro_keys {
+ struct ipaq_micro *micro;
+ struct input_dev *input;
+ u16 codes[ARRAY_SIZE(micro_keycodes)];
+};
+
static void micro_key_receive(void *data, int len, unsigned char *msg)
{
struct ipaq_micro_keys *keys = data;
int key, down;
+ if (len < 1)
+ return;
+
down = 0x80 & msg[0];
key = 0x7f & msg[0];
@@ -54,7 +57,7 @@ static void micro_key_receive(void *data, int len, unsigned char *msg)
static void micro_key_start(struct ipaq_micro_keys *keys)
{
- guard(spinlock)(&keys->micro->lock);
+ guard(spinlock_irq)(&keys->micro->lock);
keys->micro->key = micro_key_receive;
keys->micro->key_data = keys;
@@ -62,7 +65,7 @@ static void micro_key_start(struct ipaq_micro_keys *keys)
static void micro_key_stop(struct ipaq_micro_keys *keys)
{
- guard(spinlock)(&keys->micro->lock);
+ guard(spinlock_irq)(&keys->micro->lock);
keys->micro->key = NULL;
keys->micro->key_data = NULL;
@@ -102,10 +105,7 @@ static int micro_key_probe(struct platform_device *pdev)
keys->input->keycodesize = sizeof(micro_keycodes[0]);
keys->input->keycodemax = ARRAY_SIZE(micro_keycodes);
- keys->codes = devm_kmemdup_array(&pdev->dev, micro_keycodes, keys->input->keycodemax,
- keys->input->keycodesize, GFP_KERNEL);
- if (!keys->codes)
- return -ENOMEM;
+ memcpy(keys->codes, micro_keycodes, sizeof(keys->codes));
keys->input->keycode = keys->codes;
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index e19442c6f80f..8eac63b2d304 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -259,7 +259,7 @@ static void process_keys(struct lm8323_chip *lm)
ret = lm8323_read(lm, LM8323_CMD_READ_FIFO, key_fifo, LM8323_FIFO_LEN);
if (ret < 0) {
- dev_err(&lm->client->dev, "Failed reading fifo \n");
+ dev_err(&lm->client->dev, "Failed reading fifo\n");
return;
}
key_fifo[ret] = 0;
@@ -788,7 +788,7 @@ static int lm8323_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
static const struct i2c_device_id lm8323_id[] = {
- { "lm8323" },
+ { .name = "lm8323" },
{ }
};
diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
index 384baabf9924..34be5b2e476d 100644
--- a/drivers/input/keyboard/lm8333.c
+++ b/drivers/input/keyboard/lm8333.c
@@ -194,7 +194,7 @@ static int lm8333_probe(struct i2c_client *client)
}
static const struct i2c_device_id lm8333_id[] = {
- { "lm8333" },
+ { .name = "lm8333" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm8333_id);
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index c10726b5e4d1..f8fb44bc4915 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -270,7 +270,7 @@ static int max7359_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
static const struct i2c_device_id max7359_ids[] = {
- { "max7359" },
+ { .name = "max7359" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max7359_ids);
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 47edc161ec77..a1a102855590 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -322,7 +322,7 @@ static int mpr_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
static const struct i2c_device_id mpr121_id[] = {
- { "mpr121_touchkey" },
+ { .name = "mpr121_touchkey" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mpr121_id);
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
index b255b997e279..e31cb115a954 100644
--- a/drivers/input/keyboard/qt1070.c
+++ b/drivers/input/keyboard/qt1070.c
@@ -233,7 +233,7 @@ static int qt1070_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume);
static const struct i2c_device_id qt1070_id[] = {
- { "qt1070" },
+ { .name = "qt1070" },
{ }
};
MODULE_DEVICE_TABLE(i2c, qt1070_id);
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 53f5255fd19d..e64adaca10ff 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -393,7 +393,7 @@ static int qt2160_probe(struct i2c_client *client)
}
static const struct i2c_device_id qt2160_idtable[] = {
- { "qt2160" },
+ { .name = "qt2160" },
{ }
};
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index 68c0afafee7b..eb5be644f236 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c
@@ -354,7 +354,7 @@ static int tca8418_keypad_probe(struct i2c_client *client)
}
static const struct i2c_device_id tca8418_id[] = {
- { "tca8418", 8418, },
+ { .name = "tca8418", .driver_data = 8418 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tca8418_id);
diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c
index 55d699d9037d..967bbe553c06 100644
--- a/drivers/input/keyboard/tm2-touchkey.c
+++ b/drivers/input/keyboard/tm2-touchkey.c
@@ -326,7 +326,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops,
tm2_touchkey_suspend, tm2_touchkey_resume);
static const struct i2c_device_id tm2_touchkey_id_table[] = {
- { TM2_TOUCHKEY_DEV_NAME },
+ { .name = TM2_TOUCHKEY_DEV_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 94a753fcb64f..1f6c57dba030 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -745,16 +745,6 @@ config INPUT_WM831X_ON
To compile this driver as a module, choose M here: the module
will be called wm831x_on.
-config INPUT_PCAP
- tristate "Motorola EZX PCAP misc input events"
- depends on EZX_PCAP
- help
- Say Y here if you want to use Power key and Headphone button
- on Motorola EZX phones.
-
- To compile this driver as a module, choose M here: the
- module will be called pcap_keys.
-
config INPUT_ADXL34X
tristate "Analog Devices ADXL34x Three-Axis Digital Accelerometer"
default n
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 415fc4e2918b..2281d6803fce 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -60,7 +60,6 @@ obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
obj-$(CONFIG_INPUT_MMA8450) += mma8450.o
obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o
-obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_PF1550_ONKEY) += pf1550-onkey.o
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index 2adb7a058362..c3cb561512ed 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -72,11 +72,11 @@ static int ad714x_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ad714x_id[] = {
- { "ad7142_captouch" },
- { "ad7143_captouch" },
- { "ad7147_captouch" },
- { "ad7147a_captouch" },
- { "ad7148_captouch" },
+ { .name = "ad7142_captouch" },
+ { .name = "ad7143_captouch" },
+ { .name = "ad7147_captouch" },
+ { .name = "ad7147a_captouch" },
+ { .name = "ad7148_captouch" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad714x_id);
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index 5ea0ce42a507..84665c612f3c 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -96,7 +96,7 @@ static int adxl34x_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id adxl34x_id[] = {
- { "adxl34x" },
+ { .name = "adxl34x" },
{ }
};
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c
index d43aebd785b7..3eb02a64acfb 100644
--- a/drivers/input/misc/apanel.c
+++ b/drivers/input/misc/apanel.c
@@ -192,7 +192,7 @@ static void apanel_shutdown(struct i2c_client *client)
}
static const struct i2c_device_id apanel_id[] = {
- { "fujitsu_apanel" },
+ { .name = "fujitsu_apanel" },
{ }
};
MODULE_DEVICE_TABLE(i2c, apanel_id);
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c
index 835ad45a9d65..5805a1a3bb05 100644
--- a/drivers/input/misc/atlas_btns.c
+++ b/drivers/input/misc/atlas_btns.c
@@ -15,17 +15,18 @@
#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
-#include <linux/uaccess.h>
#define ACPI_ATLAS_NAME "Atlas ACPI"
-#define ACPI_ATLAS_CLASS "Atlas"
-static unsigned short atlas_keymap[16];
-static struct input_dev *input_dev;
+struct atlas_btns {
+ struct input_dev *input_dev;
+ unsigned short keymap[16];
+};
/* button handling code */
static acpi_status acpi_atlas_button_setup(acpi_handle region_handle,
- u32 function, void *handler_context, void **return_context)
+ u32 function, void *handler_context,
+ void **return_context)
{
*return_context =
(function != ACPI_REGION_DEACTIVATE) ? handler_context : NULL;
@@ -34,33 +35,37 @@ static acpi_status acpi_atlas_button_setup(acpi_handle region_handle,
}
static acpi_status acpi_atlas_button_handler(u32 function,
- acpi_physical_address address,
- u32 bit_width, u64 *value,
- void *handler_context, void *region_context)
+ acpi_physical_address address,
+ u32 bit_width, u64 *value,
+ void *handler_context,
+ void *region_context)
{
- acpi_status status;
+ struct atlas_btns *atlas = region_context;
if (function == ACPI_WRITE) {
int code = address & 0x0f;
int key_down = !(address & 0x10);
- input_event(input_dev, EV_MSC, MSC_SCAN, code);
- input_report_key(input_dev, atlas_keymap[code], key_down);
- input_sync(input_dev);
+ input_event(atlas->input_dev, EV_MSC, MSC_SCAN, code);
+ input_report_key(atlas->input_dev, atlas->keymap[code],
+ key_down);
+ input_sync(atlas->input_dev);
- status = AE_OK;
- } else {
- pr_warn("shrugged on unexpected function: function=%x,address=%lx,value=%x\n",
- function, (unsigned long)address, (u32)*value);
- status = AE_BAD_PARAMETER;
+ return AE_OK;
}
- return status;
+ dev_warn(atlas->input_dev->dev.parent,
+ "unexpected function: function=%x,address=%lx,value=%x\n",
+ function, (unsigned long)address, (u32)*value);
+
+ return AE_BAD_PARAMETER;
}
static int atlas_acpi_button_probe(struct platform_device *pdev)
{
struct acpi_device *device;
+ struct atlas_btns *atlas;
+ struct input_dev *input_dev;
acpi_status status;
int i;
int err;
@@ -69,65 +74,62 @@ static int atlas_acpi_button_probe(struct platform_device *pdev)
if (!device)
return -ENODEV;
- input_dev = input_allocate_device();
- if (!input_dev) {
- pr_err("unable to allocate input device\n");
+ atlas = devm_kzalloc(&pdev->dev, sizeof(*atlas), GFP_KERNEL);
+ if (!atlas)
return -ENOMEM;
- }
+
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ atlas->input_dev = input_dev;
input_dev->name = "Atlas ACPI button driver";
input_dev->phys = "ASIM0000/atlas/input0";
input_dev->id.bustype = BUS_HOST;
- input_dev->keycode = atlas_keymap;
- input_dev->keycodesize = sizeof(unsigned short);
- input_dev->keycodemax = ARRAY_SIZE(atlas_keymap);
+ input_dev->keycode = atlas->keymap;
+ input_dev->keycodesize = sizeof(atlas->keymap[0]);
+ input_dev->keycodemax = ARRAY_SIZE(atlas->keymap);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
- __set_bit(EV_KEY, input_dev->evbit);
- for (i = 0; i < ARRAY_SIZE(atlas_keymap); i++) {
+ for (i = 0; i < ARRAY_SIZE(atlas->keymap); i++) {
if (i < 9) {
- atlas_keymap[i] = KEY_F1 + i;
- __set_bit(KEY_F1 + i, input_dev->keybit);
- } else
- atlas_keymap[i] = KEY_RESERVED;
+ atlas->keymap[i] = KEY_F1 + i;
+ input_set_capability(input_dev, EV_KEY, KEY_F1 + i);
+ } else {
+ atlas->keymap[i] = KEY_RESERVED;
+ }
}
err = input_register_device(input_dev);
- if (err) {
- pr_err("couldn't register input device\n");
- input_free_device(input_dev);
- return err;
- }
+ if (err)
+ return dev_err_probe(&pdev->dev, err,
+ "couldn't register input device\n");
/* hookup button handler */
status = acpi_install_address_space_handler(device->handle,
- 0x81, &acpi_atlas_button_handler,
- &acpi_atlas_button_setup, device);
- if (ACPI_FAILURE(status)) {
- pr_err("error installing addr spc handler\n");
- input_unregister_device(input_dev);
- err = -EINVAL;
- }
+ 0x81,
+ &acpi_atlas_button_handler,
+ &acpi_atlas_button_setup,
+ atlas);
+ if (ACPI_FAILURE(status))
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "error installing addr spc handler\n");
- return err;
+ return 0;
}
static void atlas_acpi_button_remove(struct platform_device *pdev)
{
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
- acpi_status status;
- status = acpi_remove_address_space_handler(device->handle,
- 0x81, &acpi_atlas_button_handler);
- if (ACPI_FAILURE(status))
- pr_err("error removing addr spc handler\n");
-
- input_unregister_device(input_dev);
+ acpi_remove_address_space_handler(device->handle, 0x81,
+ &acpi_atlas_button_handler);
}
static const struct acpi_device_id atlas_device_ids[] = {
- {"ASIM0000", 0},
- {"", 0},
+ { "ASIM0000" },
+ { "" }
};
MODULE_DEVICE_TABLE(acpi, atlas_device_ids);
@@ -144,4 +146,3 @@ module_platform_driver(atlas_acpi_driver);
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Atlas button driver");
-
diff --git a/drivers/input/misc/atmel_captouch.c b/drivers/input/misc/atmel_captouch.c
index f9744cf0ca80..fc4abea68479 100644
--- a/drivers/input/misc/atmel_captouch.c
+++ b/drivers/input/misc/atmel_captouch.c
@@ -257,7 +257,7 @@ static const struct of_device_id atmel_captouch_of_id[] = {
MODULE_DEVICE_TABLE(of, atmel_captouch_of_id);
static const struct i2c_device_id atmel_captouch_id[] = {
- { "atmel_captouch" },
+ { .name = "atmel_captouch" },
{ }
};
MODULE_DEVICE_TABLE(i2c, atmel_captouch_id);
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index 4cc2a0dcaa75..0ef282932095 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -536,9 +536,9 @@ static int __maybe_unused bma150_resume(struct device *dev)
static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
static const struct i2c_device_id bma150_id[] = {
- { "bma150" },
- { "smb380" },
- { "bma023" },
+ { .name = "bma150" },
+ { .name = "smb380" },
+ { .name = "bma023" },
{ }
};
diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
index f892c5b1e4bd..14be6d4682d0 100644
--- a/drivers/input/misc/cma3000_d0x_i2c.c
+++ b/drivers/input/misc/cma3000_d0x_i2c.c
@@ -90,7 +90,7 @@ static const struct dev_pm_ops cma3000_i2c_pm_ops = {
};
static const struct i2c_device_id cma3000_i2c_id[] = {
- { "cma3000_d01" },
+ { .name = "cma3000_d01" },
{ }
};
diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c
index e4a605c6af15..77fcf868dca2 100644
--- a/drivers/input/misc/da7280.c
+++ b/drivers/input/misc/da7280.c
@@ -1305,7 +1305,7 @@ MODULE_DEVICE_TABLE(of, da7280_of_match);
#endif
static const struct i2c_device_id da7280_i2c_id[] = {
- { "da7280", },
+ { .name = "da7280" },
{ }
};
MODULE_DEVICE_TABLE(i2c, da7280_i2c_id);
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index e2089d6ac850..6c5c4c53753b 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -630,10 +630,10 @@ static int drv260x_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume);
static const struct i2c_device_id drv260x_id[] = {
- { "drv2604" },
- { "drv2604l" },
- { "drv2605" },
- { "drv2605l" },
+ { .name = "drv2604" },
+ { .name = "drv2604l" },
+ { .name = "drv2605" },
+ { .name = "drv2605l" },
{ }
};
MODULE_DEVICE_TABLE(i2c, drv260x_id);
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index 46842cb8ddd7..4f8c1f69aa63 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -281,7 +281,7 @@ static int drv2665_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume);
static const struct i2c_device_id drv2665_id[] = {
- { "drv2665" },
+ { .name = "drv2665" },
{ }
};
MODULE_DEVICE_TABLE(i2c, drv2665_id);
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index f952a24ec595..97309984fa7c 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -458,7 +458,7 @@ static int drv2667_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
static const struct i2c_device_id drv2667_id[] = {
- { "drv2667" },
+ { .name = "drv2667" },
{ }
};
MODULE_DEVICE_TABLE(i2c, drv2667_id);
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 7a1cb9333f53..b1ff8c70877f 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -14,6 +14,7 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/usb/input.h>
#include <linux/usb/cdc.h>
@@ -406,7 +407,16 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
static void ims_pcu_report_events(struct ims_pcu *pcu)
{
- u32 data = get_unaligned_be32(&pcu->read_buf[3]);
+ u32 data;
+
+ /* 6-axis setting (1 byte) + button data + checksum */
+ if (pcu->read_pos < IMS_PCU_DATA_OFFSET + 1 + sizeof(data) + 1) {
+ dev_warn(pcu->dev, "Short buttons report: %d bytes\n",
+ pcu->read_pos);
+ return;
+ }
+
+ data = get_unaligned_be32(&pcu->read_buf[IMS_PCU_DATA_OFFSET + 1]);
ims_pcu_buttons_report(pcu, data & ~IMS_PCU_GAMEPAD_MASK);
if (pcu->gamepad)
@@ -440,7 +450,7 @@ static void ims_pcu_handle_response(struct ims_pcu *pcu)
static void ims_pcu_reset_packet(struct ims_pcu *pcu)
{
- pcu->have_stx = true;
+ pcu->have_stx = false;
pcu->have_dle = false;
pcu->read_pos = 0;
pcu->check_sum = 0;
@@ -686,11 +696,19 @@ static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu,
return error;
}
- if (expected_response && pcu->cmd_buf[2] != expected_response) {
- dev_err(pcu->dev,
- "Unexpected response from bootloader: 0x%02x, wanted 0x%02x\n",
- pcu->cmd_buf[2], expected_response);
- return -EINVAL;
+ if (expected_response) {
+ if (pcu->cmd_buf_len < 3) {
+ dev_err(pcu->dev, "Short response from bootloader: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
+ if (pcu->cmd_buf[2] != expected_response) {
+ dev_err(pcu->dev,
+ "Unexpected response from bootloader: 0x%02x, wanted 0x%02x\n",
+ pcu->cmd_buf[2], expected_response);
+ return -EINVAL;
+ }
}
return 0;
@@ -718,6 +736,12 @@ static int ims_pcu_get_info(struct ims_pcu *pcu)
return error;
}
+ if (pcu->cmd_buf_len < IMS_PCU_DATA_OFFSET + IMS_PCU_SET_INFO_SIZE + 1) {
+ dev_err(pcu->dev, "Short GET_INFO response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
memcpy(pcu->part_number,
&pcu->cmd_buf[IMS_PCU_INFO_PART_OFFSET],
sizeof(pcu->part_number));
@@ -815,6 +839,12 @@ static int ims_pcu_verify_block(struct ims_pcu *pcu,
return error;
}
+ if (pcu->cmd_buf_len < IMS_PCU_BL_DATA_OFFSET + sizeof(*fragment) + len + 1) {
+ dev_err(pcu->dev, "Short READ_APP response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
fragment = (void *)&pcu->cmd_buf[IMS_PCU_BL_DATA_OFFSET];
if (get_unaligned_le32(&fragment->addr) != addr ||
fragment->len != len) {
@@ -934,9 +964,10 @@ out:
return retval;
}
-static void ims_pcu_process_async_firmware(const struct firmware *fw,
+static void ims_pcu_process_async_firmware(const struct firmware *_fw,
void *context)
{
+ const struct firmware *fw __free(firmware) = _fw;
struct ims_pcu *pcu = context;
int error;
@@ -956,8 +987,6 @@ static void ims_pcu_process_async_firmware(const struct firmware *fw,
scoped_guard(mutex, &pcu->cmd_mutex)
ims_pcu_handle_firmware_update(pcu, fw);
- release_firmware(fw);
-
out:
complete(&pcu->async_firmware_done);
}
@@ -1009,6 +1038,10 @@ ims_pcu_backlight_get_brightness(struct led_classdev *cdev)
error);
/* Assume the LED is OFF */
brightness = LED_OFF;
+ } else if (pcu->cmd_buf_len < IMS_PCU_DATA_OFFSET + 2 + 1) {
+ dev_err(pcu->dev, "Short GET_BRIGHTNESS response: %d bytes\n",
+ pcu->cmd_buf_len);
+ brightness = LED_OFF;
} else {
brightness =
get_unaligned_le16(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET]);
@@ -1153,6 +1186,8 @@ static ssize_t ims_pcu_reset_device(struct device *dev,
dev_info(pcu->dev, "Attempting to reset device\n");
+ guard(mutex)(&pcu->cmd_mutex);
+
error = ims_pcu_execute_command(pcu, PCU_RESET, &reset_byte, 1);
if (error) {
dev_info(pcu->dev,
@@ -1249,6 +1284,9 @@ static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
struct ims_pcu *pcu = usb_get_intfdata(intf);
umode_t mode = attr->mode;
+ if (intf != pcu->ctrl_intf)
+ return 0;
+
if (pcu->bootloader_mode) {
if (attr != &dev_attr_update_firmware_status.attr &&
attr != &dev_attr_update_firmware.attr &&
@@ -1282,6 +1320,12 @@ static int ims_pcu_read_ofn_config(struct ims_pcu *pcu, u8 addr, u8 *data)
if (error)
return error;
+ if (pcu->cmd_buf_len < OFN_REG_RESULT_OFFSET + 2 + 1) {
+ dev_err(pcu->dev, "Short OFN_GET_CONFIG response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET);
if (result < 0)
return -EIO;
@@ -1302,6 +1346,12 @@ static int ims_pcu_write_ofn_config(struct ims_pcu *pcu, u8 addr, u8 data)
if (error)
return error;
+ if (pcu->cmd_buf_len < OFN_REG_RESULT_OFFSET + 2 + 1) {
+ dev_err(pcu->dev, "Short OFN_SET_CONFIG response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET);
if (result < 0)
return -EIO;
@@ -1488,6 +1538,9 @@ static umode_t ims_pcu_ofn_is_attr_visible(struct kobject *kobj,
struct ims_pcu *pcu = usb_get_intfdata(intf);
umode_t mode = attr->mode;
+ if (intf != pcu->ctrl_intf)
+ return SYSFS_GROUP_INVISIBLE;
+
/*
* PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor.
*/
@@ -1528,7 +1581,7 @@ static void ims_pcu_irq(struct urb *urb)
}
dev_dbg(pcu->dev, "%s: received %d: %*ph\n", __func__,
- urb->actual_length, urb->actual_length, pcu->urb_in_buf);
+ urb->actual_length, urb->actual_length, urb->transfer_buffer);
if (urb == pcu->urb_in)
ims_pcu_process_data(pcu, urb);
@@ -1656,8 +1709,9 @@ ims_pcu_get_cdc_union_desc(struct usb_interface *intf)
while (buflen >= sizeof(*union_desc)) {
union_desc = (struct usb_cdc_union_desc *)buf;
- if (union_desc->bLength > buflen) {
- dev_err(&intf->dev, "Too large descriptor\n");
+ if (union_desc->bLength < 2 || union_desc->bLength > buflen) {
+ dev_err(&intf->dev, "Invalid descriptor length: %d\n",
+ union_desc->bLength);
return NULL;
}
@@ -1693,7 +1747,7 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc
pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev,
union_desc->bMasterInterface0);
- if (!pcu->ctrl_intf)
+ if (pcu->ctrl_intf != intf)
return -EINVAL;
alt = pcu->ctrl_intf->cur_altsetting;
@@ -1702,6 +1756,12 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc
return -ENODEV;
pcu->ep_ctrl = &alt->endpoint[0].desc;
+ if (!usb_endpoint_is_int_in(pcu->ep_ctrl)) {
+ dev_err(pcu->dev,
+ "Control endpoint is not INTERRUPT IN\n");
+ return -EINVAL;
+ }
+
pcu->max_ctrl_size = usb_endpoint_maxp(pcu->ep_ctrl);
pcu->data_intf = usb_ifnum_to_if(pcu->udev,
@@ -1783,11 +1843,16 @@ static void ims_pcu_stop_io(struct ims_pcu *pcu)
static int ims_pcu_line_setup(struct ims_pcu *pcu)
{
struct usb_host_interface *interface = pcu->ctrl_intf->cur_altsetting;
- struct usb_cdc_line_coding *line = (void *)pcu->cmd_buf;
+ struct usb_cdc_line_coding *line __free(kfree) =
+ kmalloc(sizeof(*line), GFP_KERNEL);
int error;
- memset(line, 0, sizeof(*line));
+ if (!line)
+ return -ENOMEM;
+
line->dwDTERate = cpu_to_le32(57600);
+ line->bCharFormat = USB_CDC_1_STOP_BITS;
+ line->bParityType = USB_CDC_NO_PARITY;
line->bDataBits = 8;
error = usb_control_msg(pcu->udev, usb_sndctrlpipe(pcu->udev, 0),
@@ -1831,6 +1896,12 @@ static int ims_pcu_get_device_info(struct ims_pcu *pcu)
return error;
}
+ if (pcu->cmd_buf_len < IMS_PCU_DATA_OFFSET + 6 + 1) {
+ dev_err(pcu->dev, "Short GET_FW_VERSION response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
snprintf(pcu->fw_version, sizeof(pcu->fw_version),
"%02d%02d%02d%02d.%c%c",
pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
@@ -1843,6 +1914,12 @@ static int ims_pcu_get_device_info(struct ims_pcu *pcu)
return error;
}
+ if (pcu->cmd_buf_len < IMS_PCU_DATA_OFFSET + 6 + 1) {
+ dev_err(pcu->dev, "Short GET_BL_VERSION response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
snprintf(pcu->bl_version, sizeof(pcu->bl_version),
"%02d%02d%02d%02d.%c%c",
pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
@@ -1855,6 +1932,12 @@ static int ims_pcu_get_device_info(struct ims_pcu *pcu)
return error;
}
+ if (pcu->cmd_buf_len < IMS_PCU_DATA_OFFSET + 1 + 1) {
+ dev_err(pcu->dev, "Short RESET_REASON response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
snprintf(pcu->reset_reason, sizeof(pcu->reset_reason),
"%02x", pcu->cmd_buf[IMS_PCU_DATA_OFFSET]);
@@ -1881,6 +1964,12 @@ static int ims_pcu_identify_type(struct ims_pcu *pcu, u8 *device_id)
return error;
}
+ if (pcu->cmd_buf_len < IMS_PCU_DATA_OFFSET + 1 + 1) {
+ dev_err(pcu->dev, "Short GET_DEVICE_ID response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
*device_id = pcu->cmd_buf[IMS_PCU_DATA_OFFSET];
dev_dbg(pcu->dev, "Detected device ID: %d\n", *device_id);
@@ -1972,6 +2061,12 @@ static int ims_pcu_init_bootloader_mode(struct ims_pcu *pcu)
return error;
}
+ if (pcu->cmd_buf_len < IMS_PCU_DATA_OFFSET + 15 + 4 + 1) {
+ dev_err(pcu->dev, "Short QUERY_DEVICE response: %d bytes\n",
+ pcu->cmd_buf_len);
+ return -EIO;
+ }
+
pcu->fw_start_addr =
get_unaligned_le32(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET + 11]);
pcu->fw_end_addr =
@@ -2071,7 +2166,6 @@ err_free_mem:
static void ims_pcu_disconnect(struct usb_interface *intf)
{
struct ims_pcu *pcu = usb_get_intfdata(intf);
- struct usb_host_interface *alt = intf->cur_altsetting;
usb_set_intfdata(intf, NULL);
@@ -2079,7 +2173,7 @@ static void ims_pcu_disconnect(struct usb_interface *intf)
* See if we are dealing with control or data interface. The cleanup
* happens when we unbind primary (control) interface.
*/
- if (alt->desc.bInterfaceClass != USB_CLASS_COMM)
+ if (intf != pcu->ctrl_intf)
return;
ims_pcu_stop_io(pcu);
@@ -2090,6 +2184,7 @@ static void ims_pcu_disconnect(struct usb_interface *intf)
ims_pcu_destroy_application_mode(pcu);
ims_pcu_buffers_free(pcu);
+ usb_driver_release_interface(&ims_pcu_driver, pcu->data_intf);
kfree(pcu);
}
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index eb9788ea5215..6b3495ba5763 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -525,7 +525,7 @@ static int kxtj9_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
static const struct i2c_device_id kxtj9_id[] = {
- { NAME },
+ { .name = NAME },
{ }
};
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
index 0c661140fb88..a2888d1ff58f 100644
--- a/drivers/input/misc/mma8450.c
+++ b/drivers/input/misc/mma8450.c
@@ -200,7 +200,7 @@ static int mma8450_probe(struct i2c_client *c)
}
static const struct i2c_device_id mma8450_id[] = {
- { MMA8450_DRV_NAME },
+ { .name = MMA8450_DRV_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, mma8450_id);
diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
deleted file mode 100644
index b19899b50d0b..000000000000
--- a/drivers/input/misc/pcap_keys.c
+++ /dev/null
@@ -1,125 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Input driver for PCAP events:
- * * Power key
- * * Headphone button
- *
- * Copyright (c) 2008,2009 Ilya Petrov <ilya.muromec@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/mfd/ezx-pcap.h>
-#include <linux/slab.h>
-
-struct pcap_keys {
- struct pcap_chip *pcap;
- struct input_dev *input;
-};
-
-/* PCAP2 interrupts us on keypress */
-static irqreturn_t pcap_keys_handler(int irq, void *_pcap_keys)
-{
- struct pcap_keys *pcap_keys = _pcap_keys;
- int pirq = irq_to_pcap(pcap_keys->pcap, irq);
- u32 pstat;
-
- ezx_pcap_read(pcap_keys->pcap, PCAP_REG_PSTAT, &pstat);
- pstat &= 1 << pirq;
-
- switch (pirq) {
- case PCAP_IRQ_ONOFF:
- input_report_key(pcap_keys->input, KEY_POWER, !pstat);
- break;
- case PCAP_IRQ_MIC:
- input_report_key(pcap_keys->input, KEY_HP, !pstat);
- break;
- }
-
- input_sync(pcap_keys->input);
-
- return IRQ_HANDLED;
-}
-
-static int pcap_keys_probe(struct platform_device *pdev)
-{
- int err = -ENOMEM;
- struct pcap_keys *pcap_keys;
- struct input_dev *input_dev;
-
- pcap_keys = kmalloc_obj(*pcap_keys);
- if (!pcap_keys)
- return err;
-
- pcap_keys->pcap = dev_get_drvdata(pdev->dev.parent);
-
- input_dev = input_allocate_device();
- if (!input_dev)
- goto fail;
-
- pcap_keys->input = input_dev;
-
- platform_set_drvdata(pdev, pcap_keys);
- input_dev->name = pdev->name;
- input_dev->phys = "pcap-keys/input0";
- input_dev->id.bustype = BUS_HOST;
- input_dev->dev.parent = &pdev->dev;
-
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(KEY_POWER, input_dev->keybit);
- __set_bit(KEY_HP, input_dev->keybit);
-
- err = input_register_device(input_dev);
- if (err)
- goto fail_allocate;
-
- err = request_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF),
- pcap_keys_handler, 0, "Power key", pcap_keys);
- if (err)
- goto fail_register;
-
- err = request_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_MIC),
- pcap_keys_handler, 0, "Headphone button", pcap_keys);
- if (err)
- goto fail_pwrkey;
-
- return 0;
-
-fail_pwrkey:
- free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF), pcap_keys);
-fail_register:
- input_unregister_device(input_dev);
- goto fail;
-fail_allocate:
- input_free_device(input_dev);
-fail:
- kfree(pcap_keys);
- return err;
-}
-
-static void pcap_keys_remove(struct platform_device *pdev)
-{
- struct pcap_keys *pcap_keys = platform_get_drvdata(pdev);
-
- free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF), pcap_keys);
- free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_MIC), pcap_keys);
-
- input_unregister_device(pcap_keys->input);
- kfree(pcap_keys);
-}
-
-static struct platform_driver pcap_keys_device_driver = {
- .probe = pcap_keys_probe,
- .remove = pcap_keys_remove,
- .driver = {
- .name = "pcap-keys",
- }
-};
-module_platform_driver(pcap_keys_device_driver);
-
-MODULE_DESCRIPTION("Motorola PCAP2 input events driver");
-MODULE_AUTHOR("Ilya Petrov <ilya.muromec@gmail.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pcap_keys");
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 14fc6c6cf699..a831fcc851f7 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -189,7 +189,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(pcf8574_kp_pm_ops,
pcf8574_kp_suspend, pcf8574_kp_resume);
static const struct i2c_device_id pcf8574_kp_id[] = {
- { DRV_NAME },
+ { .name = DRV_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id);
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index 8786ed8b3565..560f895a00cd 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -22,15 +22,6 @@
* - Olivier Vandorpe, for providing the usbb2k-api.
* - Martin Diehl, for spotting my memory allocation bug.
*
- * History:
- * 20050527 henk First version, functional keyboard. Keyboard events
- * will pop-up on the ../input/eventX bus.
- * 20050531 henk Added led, LCD, dialtone and sysfs interface.
- * 20050610 henk Cleanups, make it ready for public consumption.
- * 20050630 henk Cleanups, fixes in response to comments.
- * 20050701 henk sysfs write serialisation, fix potential unload races
- * 20050801 henk Added ringtone, restructure USB
- * 20050816 henk Merge 2.6.13-rc6
*/
#include <linux/kernel.h>
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 6e0d956617a1..47000c30e4d8 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -1456,7 +1456,7 @@ static const struct dev_pm_ops cyapa_pm_ops = {
};
static const struct i2c_device_id cyapa_id_table[] = {
- { "cyapa" },
+ { .name = "cyapa" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyapa_id_table);
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 5cba02a156ce..f93dd545d66b 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -428,8 +428,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
if (error)
return error;
}
- data->width_x = data->max_x / x_traces;
- data->width_y = data->max_y / y_traces;
+
+ if (!x_traces || !y_traces) {
+ dev_warn(&client->dev,
+ "invalid trace numbers: x=%u, y=%u\n",
+ x_traces, y_traces);
+ data->width_x = 1;
+ data->width_y = 1;
+ } else {
+ data->width_x = data->max_x / x_traces;
+ data->width_y = data->max_y / y_traces;
+ }
if (device_property_read_u32(&client->dev,
"touchscreen-x-mm", &x_mm) ||
@@ -443,8 +452,16 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
data->x_res = elan_convert_resolution(hw_x_res, data->pattern);
data->y_res = elan_convert_resolution(hw_y_res, data->pattern);
} else {
- data->x_res = (data->max_x + 1) / x_mm;
- data->y_res = (data->max_y + 1) / y_mm;
+ if (unlikely(x_mm == 0 || y_mm == 0)) {
+ dev_warn(&client->dev,
+ "invalid physical dimensions: x_mm=%u, y_mm=%u\n",
+ x_mm, y_mm);
+ data->x_res = 1;
+ data->y_res = 1;
+ } else {
+ data->x_res = (data->max_x + 1) / x_mm;
+ data->y_res = (data->max_y + 1) / y_mm;
+ }
}
if (device_property_read_bool(&client->dev, "elan,clickpad"))
@@ -956,6 +973,7 @@ static void elan_report_contact(struct elan_tp_data *data, int contact_num,
if (data->report_features & ETP_FEATURE_REPORT_MK) {
unsigned int mk_x, mk_y, area_x, area_y;
+ int adj_width_x, adj_width_y;
u8 mk_data = high_precision ?
packet[ETP_MK_DATA_OFFSET + contact_num] :
finger_data[3];
@@ -967,8 +985,14 @@ static void elan_report_contact(struct elan_tp_data *data, int contact_num,
* To avoid treating large finger as palm, let's reduce
* the width x and y per trace.
*/
- area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE);
- area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE);
+
+ adj_width_x = data->width_x > ETP_FWIDTH_REDUCE ?
+ data->width_x - ETP_FWIDTH_REDUCE : 0;
+ adj_width_y = data->width_y > ETP_FWIDTH_REDUCE ?
+ data->width_y - ETP_FWIDTH_REDUCE : 0;
+
+ area_x = mk_x * adj_width_x;
+ area_y = mk_y * adj_width_y;
input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
input_report_abs(input, ABS_MT_TOUCH_MAJOR,
@@ -1407,7 +1431,7 @@ err:
static DEFINE_SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume);
static const struct i2c_device_id elan_id[] = {
- { DRIVER_NAME },
+ { .name = DRIVER_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, elan_id);
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 6f3d5c33b807..d4cf982f1263 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -607,7 +607,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
synaptics_i2c_resume);
static const struct i2c_device_id synaptics_i2c_id_table[] = {
- { "synaptics_i2c" },
+ { .name = "synaptics_i2c" },
{ }
};
MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table);
diff --git a/drivers/input/rmi4/rmi_2d_sensor.h b/drivers/input/rmi4/rmi_2d_sensor.h
index 61a99c8a7a26..f9d9c1dd5eb0 100644
--- a/drivers/input/rmi4/rmi_2d_sensor.h
+++ b/drivers/input/rmi4/rmi_2d_sensor.h
@@ -56,8 +56,8 @@ struct rmi_2d_sensor {
u16 max_y;
u8 nbr_fingers;
u8 *data_pkt;
- int pkt_size;
- int attn_size;
+ u32 pkt_size;
+ u32 attn_size;
bool topbuttonpad;
enum rmi_sensor_type sensor_type;
struct input_dev *input;
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 687cb987bc13..560c85f53327 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -237,36 +237,44 @@ static int rmi_function_remove(struct device *dev)
return 0;
}
-int rmi_register_function(struct rmi_function *fn)
+struct rmi_function *rmi_alloc_function(struct rmi_device *rmi_dev, u8 id)
{
- struct rmi_device *rmi_dev = fn->rmi_dev;
- int error;
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+ struct rmi_function *fn;
+
+ fn = kzalloc_flex(*fn, irq_mask, BITS_TO_LONGS(data->irq_count));
+ if (!fn)
+ return NULL;
device_initialize(&fn->dev);
- dev_set_name(&fn->dev, "%s.fn%02x",
- dev_name(&rmi_dev->dev), fn->fd.function_number);
+ dev_set_name(&fn->dev, "%s.fn%02x", dev_name(&rmi_dev->dev), id);
fn->dev.parent = &rmi_dev->dev;
fn->dev.type = &rmi_function_type;
fn->dev.bus = &rmi_bus_type;
+ fn->rmi_dev = rmi_dev;
+
+ return fn;
+}
+
+int rmi_register_function(struct rmi_function *fn)
+{
+ struct rmi_device *rmi_dev = fn->rmi_dev;
+ int error;
error = device_add(&fn->dev);
if (error) {
dev_err(&rmi_dev->dev,
- "Failed device_register function device %s\n",
+ "Failed to register function device %s\n",
dev_name(&fn->dev));
- goto err_put_device;
+ return error;
}
rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Registered F%02X.\n",
fn->fd.function_number);
return 0;
-
-err_put_device:
- put_device(&fn->dev);
- return error;
}
void rmi_unregister_function(struct rmi_function *fn)
@@ -455,11 +463,13 @@ static int __init rmi_bus_init(void)
if (error) {
pr_err("%s: error registering the RMI physical driver: %d\n",
__func__, error);
- goto err_unregister_bus;
+ goto err_unregister_function_handlers;
}
return 0;
+err_unregister_function_handlers:
+ rmi_unregister_function_handlers();
err_unregister_bus:
bus_unregister(&rmi_bus_type);
return error;
diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h
index d4d0d82c69aa..90122df21f74 100644
--- a/drivers/input/rmi4/rmi_bus.h
+++ b/drivers/input/rmi4/rmi_bus.h
@@ -49,6 +49,7 @@ struct rmi_function {
bool rmi_is_function_device(struct device *dev);
+struct rmi_function *rmi_alloc_function(struct rmi_device *rmi_dev, u8 id);
int __must_check rmi_register_function(struct rmi_function *);
void rmi_unregister_function(struct rmi_function *);
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index ccd9338a44db..49a59da6a841 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -22,6 +22,7 @@
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include <linux/export.h>
+#include <linux/unaligned.h>
#include "rmi_bus.h"
#include "rmi_driver.h"
@@ -182,7 +183,11 @@ void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status,
attn_data.size = size;
attn_data.data = fifo_data;
- kfifo_put(&drvdata->attn_fifo, attn_data);
+ if (!kfifo_put(&drvdata->attn_fifo, attn_data)) {
+ dev_warn_ratelimited(&rmi_dev->dev,
+ "Failed to enqueue attention data, FIFO full\n");
+ kfree(fifo_data);
+ }
}
EXPORT_SYMBOL_GPL(rmi_set_attn_data);
@@ -193,24 +198,24 @@ static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
struct rmi4_attn_data attn_data = {0};
int ret, count;
- count = kfifo_get(&drvdata->attn_fifo, &attn_data);
- if (count) {
- *(drvdata->irq_status) = attn_data.irq_status;
- drvdata->attn_data = attn_data;
- }
-
- ret = rmi_process_interrupt_requests(rmi_dev);
- if (ret)
- rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
- "Failed to process interrupt request: %d\n", ret);
+ do {
+ count = kfifo_get(&drvdata->attn_fifo, &attn_data);
+ if (count) {
+ *drvdata->irq_status = attn_data.irq_status;
+ drvdata->attn_data = attn_data;
+ }
- if (count) {
- kfree(attn_data.data);
- drvdata->attn_data.data = NULL;
- }
+ ret = rmi_process_interrupt_requests(rmi_dev);
+ if (ret)
+ rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+ "Failed to process interrupt request: %d\n",
+ ret);
- if (!kfifo_is_empty(&drvdata->attn_fifo))
- return rmi_irq_fn(irq, dev_id);
+ if (count) {
+ kfree(attn_data.data);
+ drvdata->attn_data.data = NULL;
+ }
+ } while (!kfifo_is_empty(&drvdata->attn_fifo));
return IRQ_HANDLED;
}
@@ -383,9 +388,8 @@ static int rmi_driver_set_irq_bits(struct rmi_device *rmi_dev,
__func__);
goto error_unlock;
}
- bitmap_copy(data->current_irq_mask, data->new_irq_mask,
- data->num_of_irq_regs);
+ bitmap_copy(data->current_irq_mask, data->new_irq_mask, data->irq_count);
bitmap_or(data->fn_irq_bits, data->fn_irq_bits, mask, data->irq_count);
error_unlock:
@@ -414,8 +418,8 @@ static int rmi_driver_clear_irq_bits(struct rmi_device *rmi_dev,
__func__);
goto error_unlock;
}
- bitmap_copy(data->current_irq_mask, data->new_irq_mask,
- data->num_of_irq_regs);
+
+ bitmap_copy(data->current_irq_mask, data->new_irq_mask, data->irq_count);
error_unlock:
mutex_unlock(&data->irq_mutex);
@@ -558,30 +562,75 @@ int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
return retval < 0 ? retval : 0;
}
+static int rmi_parse_register_desc_item(struct rmi_register_desc_item *item,
+ const u8 *buf, size_t size)
+{
+ unsigned int offset = 0;
+ unsigned int map_offset = 0;
+ int b;
+
+ if (offset >= size)
+ return -EIO;
+
+ item->reg_size = buf[offset++];
+ if (item->reg_size == 0) {
+ if (size - offset < 2)
+ return -EIO;
+ item->reg_size = get_unaligned_le16(&buf[offset]);
+ offset += 2;
+ }
+
+ if (item->reg_size == 0) {
+ if (size - offset < 4)
+ return -EIO;
+ item->reg_size = get_unaligned_le32(&buf[offset]);
+ offset += 4;
+ }
+
+ do {
+ if (offset >= size)
+ return -EIO;
+
+ for (b = 0; b < 7; b++) {
+ if (buf[offset] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_SUBPACKET_BITS)
+ return -EIO;
+ __set_bit(map_offset, item->subpacket_map);
+ }
+ ++map_offset;
+ }
+ } while (buf[offset++] & BIT(7));
+
+ item->num_subpackets = bitmap_weight(item->subpacket_map,
+ RMI_REG_DESC_SUBPACKET_BITS);
+
+ return offset;
+}
+
int rmi_read_register_desc(struct rmi_device *d, u16 addr,
- struct rmi_register_descriptor *rdesc)
+ struct rmi_register_descriptor *rdesc)
{
- int ret;
+ DECLARE_BITMAP(presence_map, RMI_REG_DESC_PRESENCE_BITS);
+ u8 buf[RMI_REG_DESC_PRESENCE_REGS_MAX];
u8 size_presence_reg;
- u8 buf[35];
- int presense_offset = 1;
- u8 *struct_buf;
- int reg;
- int offset = 0;
- int map_offset = 0;
+ unsigned int presence_offset;
+ unsigned int map_offset;
+ unsigned int offset;
+ unsigned int reg;
int i;
int b;
+ int ret;
/*
* The first register of the register descriptor is the size of
- * the register descriptor's presense register.
+ * the register descriptor's presence register.
*/
ret = rmi_read(d, addr, &size_presence_reg);
if (ret)
return ret;
++addr;
- if (size_presence_reg < 0 || size_presence_reg > 35)
+ if (size_presence_reg < 1 || size_presence_reg > RMI_REG_DESC_PRESENCE_REGS_MAX)
return -EIO;
memset(buf, 0, sizeof(buf));
@@ -594,25 +643,33 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
ret = rmi_read_block(d, addr, buf, size_presence_reg);
if (ret)
return ret;
- ++addr;
+ addr += size_presence_reg;
if (buf[0] == 0) {
- presense_offset = 3;
- rdesc->struct_size = buf[1] | (buf[2] << 8);
+ if (size_presence_reg < 3)
+ return -EIO;
+ presence_offset = 3;
+ rdesc->struct_size = get_unaligned_le16(&buf[1]);
} else {
+ presence_offset = 1;
rdesc->struct_size = buf[0];
}
- for (i = presense_offset; i < size_presence_reg; i++) {
+ memset(presence_map, 0, sizeof(presence_map));
+ map_offset = 0;
+ for (i = presence_offset; i < size_presence_reg; i++) {
for (b = 0; b < 8; b++) {
- if (buf[i] & (0x1 << b))
- bitmap_set(rdesc->presense_map, map_offset, 1);
+ if (buf[i] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_PRESENCE_BITS)
+ return -EIO;
+ bitmap_set(presence_map, map_offset, 1);
+ }
++map_offset;
}
}
- rdesc->num_registers = bitmap_weight(rdesc->presense_map,
- RMI_REG_DESC_PRESENSE_BITS);
+ rdesc->num_registers = bitmap_weight(presence_map,
+ RMI_REG_DESC_PRESENCE_BITS);
rdesc->registers = devm_kcalloc(&d->dev,
rdesc->num_registers,
@@ -626,7 +683,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
* I'm not using devm_kzalloc here since it will not be retained
* after exiting this function
*/
- struct_buf = kzalloc(rdesc->struct_size, GFP_KERNEL);
+ u8 *struct_buf __free(kfree) = kzalloc(rdesc->struct_size, GFP_KERNEL);
if (!struct_buf)
return -ENOMEM;
@@ -638,56 +695,32 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
*/
ret = rmi_read_block(d, addr, struct_buf, rdesc->struct_size);
if (ret)
- goto free_struct_buff;
+ return ret;
- reg = find_first_bit(rdesc->presense_map, RMI_REG_DESC_PRESENSE_BITS);
+ reg = find_first_bit(presence_map, RMI_REG_DESC_PRESENCE_BITS);
+ offset = 0;
for (i = 0; i < rdesc->num_registers; i++) {
struct rmi_register_desc_item *item = &rdesc->registers[i];
- int reg_size = struct_buf[offset];
-
- ++offset;
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8);
- offset += 2;
- }
+ int item_size;
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8) |
- (struct_buf[offset + 2] << 16) |
- (struct_buf[offset + 3] << 24);
- offset += 4;
- }
+ item_size = rmi_parse_register_desc_item(item,
+ &struct_buf[offset],
+ rdesc->struct_size - offset);
+ if (item_size < 0)
+ return item_size;
item->reg = reg;
- item->reg_size = reg_size;
-
- map_offset = 0;
-
- do {
- for (b = 0; b < 7; b++) {
- if (struct_buf[offset] & (0x1 << b))
- bitmap_set(item->subpacket_map,
- map_offset, 1);
- ++map_offset;
- }
- } while (struct_buf[offset++] & 0x80);
-
- item->num_subpackets = bitmap_weight(item->subpacket_map,
- RMI_REG_DESC_SUBPACKET_BITS);
+ offset += item_size;
rmi_dbg(RMI_DEBUG_CORE, &d->dev,
- "%s: reg: %d reg size: %ld subpackets: %d\n", __func__,
+ "%s: reg: %d reg size: %u subpackets: %d\n", __func__,
item->reg, item->reg_size, item->num_subpackets);
- reg = find_next_bit(rdesc->presense_map,
- RMI_REG_DESC_PRESENSE_BITS, reg + 1);
+ reg = find_next_bit(presence_map,
+ RMI_REG_DESC_PRESENCE_BITS, reg + 1);
}
-free_struct_buff:
- kfree(struct_buf);
- return ret;
+ return 0;
}
const struct rmi_register_desc_item *rmi_get_register_desc_item(
@@ -713,7 +746,7 @@ size_t rmi_register_desc_calc_size(struct rmi_register_descriptor *rdesc)
for (i = 0; i < rdesc->num_registers; i++) {
item = &rdesc->registers[i];
- size += item->reg_size;
+ size = size_add(size, item->reg_size);
}
return size;
}
@@ -738,7 +771,7 @@ int rmi_register_desc_calc_reg_offset(
bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
u8 subpacket)
{
- return find_next_bit(item->subpacket_map, RMI_REG_DESC_PRESENSE_BITS,
+ return find_next_bit(item->subpacket_map, RMI_REG_DESC_SUBPACKET_BITS,
subpacket) == subpacket;
}
@@ -839,9 +872,7 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
rmi_dbg(RMI_DEBUG_CORE, dev, "Initializing F%02X.\n",
pdt->function_number);
- fn = kzalloc(sizeof(struct rmi_function) +
- BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long),
- GFP_KERNEL);
+ fn = rmi_alloc_function(rmi_dev, pdt->function_number);
if (!fn) {
dev_err(dev, "Failed to allocate memory for F%02X\n",
pdt->function_number);
@@ -851,8 +882,6 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
INIT_LIST_HEAD(&fn->node);
rmi_driver_copy_pdt_to_fd(pdt, &fn->fd);
- fn->rmi_dev = rmi_dev;
-
fn->num_of_irqs = pdt->interrupt_source_count;
fn->irq_pos = *current_irq_count;
*current_irq_count += fn->num_of_irqs;
@@ -861,8 +890,10 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
set_bit(fn->irq_pos + i, fn->irq_mask);
error = rmi_register_function(fn);
- if (error)
+ if (error) {
+ put_device(&fn->dev);
return error;
+ }
if (pdt->function_number == 0x01)
data->f01_container = fn;
@@ -1133,6 +1164,7 @@ static int rmi_driver_probe(struct device *dev)
return -ENOMEM;
INIT_LIST_HEAD(&data->function_list);
+ INIT_KFIFO(data->attn_fifo);
data->rmi_dev = rmi_dev;
dev_set_drvdata(&rmi_dev->dev, data);
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index e84495caab15..abeafb77a483 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -46,16 +46,16 @@ struct pdt_entry {
u8 function_number;
};
-#define RMI_REG_DESC_PRESENSE_BITS (32 * BITS_PER_BYTE)
+#define RMI_REG_DESC_PRESENCE_BITS (32 * BITS_PER_BYTE)
+#define RMI_REG_DESC_PRESENCE_REGS_MAX (3 + RMI_REG_DESC_PRESENCE_BITS / 8)
#define RMI_REG_DESC_SUBPACKET_BITS (37 * BITS_PER_BYTE)
/* describes a single packet register */
struct rmi_register_desc_item {
+ u32 reg_size;
u16 reg;
- unsigned long reg_size;
- u8 num_subpackets;
- unsigned long subpacket_map[BITS_TO_LONGS(
- RMI_REG_DESC_SUBPACKET_BITS)];
+ u16 num_subpackets;
+ DECLARE_BITMAP(subpacket_map, RMI_REG_DESC_SUBPACKET_BITS);
};
/*
@@ -64,8 +64,7 @@ struct rmi_register_desc_item {
*/
struct rmi_register_descriptor {
unsigned long struct_size;
- unsigned long presense_map[BITS_TO_LONGS(RMI_REG_DESC_PRESENSE_BITS)];
- u8 num_registers;
+ u16 num_registers;
struct rmi_register_desc_item *registers;
};
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index 49ca9168685a..9ade74b36edb 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -1304,7 +1304,7 @@ static irqreturn_t rmi_f11_attention(int irq, void *ctx)
struct f11_data *f11 = dev_get_drvdata(&fn->dev);
u16 data_base_addr = fn->fd.data_base_addr;
int error;
- int valid_bytes = f11->sensor.pkt_size;
+ u32 valid_bytes = f11->sensor.pkt_size;
if (drvdata->attn_data.data) {
/*
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8246fe77114b..88c28089de99 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -5,6 +5,8 @@
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/rmi.h>
+#include <linux/sizes.h>
+#include <linux/unaligned.h>
#include "rmi_driver.h"
#include "rmi_2d_sensor.h"
@@ -49,7 +51,6 @@ struct f12_data {
const struct rmi_register_desc_item *data6;
u16 data6_offset;
-
/* F12 Data9 reports relative data */
const struct rmi_register_desc_item *data9;
u16 data9_offset;
@@ -57,10 +58,39 @@ struct f12_data {
const struct rmi_register_desc_item *data15;
u16 data15_offset;
- unsigned long *abs_mask;
- unsigned long *rel_mask;
+ unsigned long irq_mask[];
};
+static int rmi_f12_read_register_descs(struct rmi_function *fn,
+ struct f12_data *f12, u16 query_addr)
+{
+ struct {
+ struct rmi_register_descriptor *desc;
+ const char *name;
+ } descriptors[] = {
+ { &f12->query_reg_desc, "Query" },
+ { &f12->control_reg_desc, "Control" },
+ { &f12->data_reg_desc, "Data" },
+ };
+ struct rmi_device *rmi_dev = fn->rmi_dev;
+ int error;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(descriptors); i++) {
+ error = rmi_read_register_desc(rmi_dev, query_addr,
+ descriptors[i].desc);
+ if (error) {
+ dev_err(&fn->dev,
+ "Failed to read the %s Register Descriptor: %d\n",
+ descriptors[i].name, error);
+ return error;
+ }
+ query_addr += 3;
+ }
+
+ return 0;
+}
+
static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
{
const struct rmi_register_desc_item *item;
@@ -88,20 +118,20 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
if (item->reg_size > sizeof(buf)) {
dev_err(&fn->dev,
- "F12 control8 should be no bigger than %zd bytes, not: %ld\n",
+ "F12 control8 should be no bigger than %zd bytes, not: %u\n",
sizeof(buf), item->reg_size);
return -ENODEV;
}
- ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr + offset, buf,
- item->reg_size);
+ ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr + offset,
+ buf, item->reg_size);
if (ret)
return ret;
offset = 0;
if (rmi_register_desc_has_subpacket(item, 0)) {
- sensor->max_x = (buf[offset + 1] << 8) | buf[offset];
- sensor->max_y = (buf[offset + 3] << 8) | buf[offset + 2];
+ sensor->max_x = get_unaligned_le16(&buf[offset]);
+ sensor->max_y = get_unaligned_le16(&buf[offset + 2]);
offset += 4;
}
@@ -109,8 +139,8 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
sensor->max_x, sensor->max_y);
if (rmi_register_desc_has_subpacket(item, 1)) {
- pitch_x = (buf[offset + 1] << 8) | buf[offset];
- pitch_y = (buf[offset + 3] << 8) | buf[offset + 2];
+ pitch_x = get_unaligned_le16(&buf[offset]);
+ pitch_y = get_unaligned_le16(&buf[offset + 2]);
offset += 4;
}
@@ -132,12 +162,12 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
if (rmi_get_register_desc_item(&f12->query_reg_desc,
RMI_F12_QUERY_RESOLUTION)) {
offset = rmi_register_desc_calc_reg_offset(&f12->query_reg_desc,
- RMI_F12_QUERY_RESOLUTION);
+ RMI_F12_QUERY_RESOLUTION);
query_dpm_addr = fn->fd.query_base_addr + offset;
ret = rmi_read(fn->rmi_dev, query_dpm_addr, buf);
- if (ret < 0) {
+ if (ret) {
dev_err(&fn->dev, "Failed to read DPM value: %d\n", ret);
- return -ENODEV;
+ return ret;
}
dpm_resolution = buf[0];
@@ -164,14 +194,11 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
return 0;
}
-static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
+static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, u32 size)
{
- int i;
struct rmi_2d_sensor *sensor = &f12->sensor;
- int objects = f12->data1->num_subpackets;
-
- if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
- objects = size / F12_DATA1_BYTES_PER_OBJ;
+ u32 objects = min(f12->data1->num_subpackets, size / F12_DATA1_BYTES_PER_OBJ);
+ int i;
for (i = 0; i < objects; i++) {
struct rmi_2d_sensor_abs_object *obj = &sensor->objs[i];
@@ -196,8 +223,8 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
break;
}
- obj->x = (data1[2] << 8) | data1[1];
- obj->y = (data1[4] << 8) | data1[3];
+ obj->x = get_unaligned_le16(&data1[1]);
+ obj->y = get_unaligned_le16(&data1[3]);
obj->z = data1[5];
obj->wx = data1[6];
obj->wy = data1[7];
@@ -220,21 +247,17 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
static irqreturn_t rmi_f12_attention(int irq, void *ctx)
{
- int retval;
struct rmi_function *fn = ctx;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
struct rmi_2d_sensor *sensor = &f12->sensor;
- int valid_bytes = sensor->pkt_size;
+ u32 valid_bytes = sensor->pkt_size;
+ int retval;
if (drvdata->attn_data.data) {
- if (sensor->attn_size > drvdata->attn_data.size)
- valid_bytes = drvdata->attn_data.size;
- else
- valid_bytes = sensor->attn_size;
- memcpy(sensor->data_pkt, drvdata->attn_data.data,
- valid_bytes);
+ valid_bytes = min_t(u32, sensor->attn_size, drvdata->attn_data.size);
+ memcpy(sensor->data_pkt, drvdata->attn_data.data, valid_bytes);
drvdata->attn_data.data += valid_bytes;
drvdata->attn_data.size -= valid_bytes;
} else {
@@ -248,92 +271,100 @@ static irqreturn_t rmi_f12_attention(int irq, void *ctx)
}
if (f12->data1)
- rmi_f12_process_objects(f12,
- &sensor->data_pkt[f12->data1_offset], valid_bytes);
+ rmi_f12_process_objects(f12, &sensor->data_pkt[f12->data1_offset],
+ valid_bytes);
input_mt_sync_frame(sensor->input);
return IRQ_HANDLED;
}
-static int rmi_f12_write_control_regs(struct rmi_function *fn)
+static int rmi_f12_update_dribble(struct rmi_function *fn, struct f12_data *f12)
{
- int ret;
const struct rmi_register_desc_item *item;
struct rmi_device *rmi_dev = fn->rmi_dev;
- struct f12_data *f12 = dev_get_drvdata(&fn->dev);
- int control_size;
- char buf[3];
- u16 control_offset = 0;
u8 subpacket_offset = 0;
+ u16 control_offset;
+ u32 control_size;
+ int error;
+ u8 buf[3];
- if (f12->has_dribble
- && (f12->sensor.dribble != RMI_REG_STATE_DEFAULT)) {
- item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
- if (item) {
- control_offset = rmi_register_desc_calc_reg_offset(
- &f12->control_reg_desc, 20);
-
- /*
- * The byte containing the EnableDribble bit will be
- * in either byte 0 or byte 2 of control 20. Depending
- * on the existence of subpacket 0. If control 20 is
- * larger then 3 bytes, just read the first 3.
- */
- control_size = min(item->reg_size, 3UL);
-
- ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
- + control_offset, buf, control_size);
- if (ret)
- return ret;
-
- if (rmi_register_desc_has_subpacket(item, 0))
- subpacket_offset += 1;
-
- switch (f12->sensor.dribble) {
- case RMI_REG_STATE_OFF:
- buf[subpacket_offset] &= ~BIT(2);
- break;
- case RMI_REG_STATE_ON:
- buf[subpacket_offset] |= BIT(2);
- break;
- case RMI_REG_STATE_DEFAULT:
- default:
- break;
- }
+ item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
+ if (!item)
+ return 0;
- ret = rmi_write_block(rmi_dev,
- fn->fd.control_base_addr + control_offset,
- buf, control_size);
- if (ret)
- return ret;
- }
+ control_offset = rmi_register_desc_calc_reg_offset(&f12->control_reg_desc, 20);
+
+ /*
+ * The byte containing the EnableDribble bit will be
+ * in either byte 0 or byte 2 of control 20. Depending
+ * on the existence of subpacket 0. If control 20 is
+ * larger then 3 bytes, just read the first 3.
+ */
+ control_size = min(item->reg_size, 3U);
+
+ error = rmi_read_block(rmi_dev, fn->fd.control_base_addr + control_offset,
+ buf, control_size);
+ if (error)
+ return error;
+
+ if (rmi_register_desc_has_subpacket(item, 0))
+ subpacket_offset += 1;
+
+ switch (f12->sensor.dribble) {
+ case RMI_REG_STATE_OFF:
+ buf[subpacket_offset] &= ~BIT(2);
+ break;
+ case RMI_REG_STATE_ON:
+ buf[subpacket_offset] |= BIT(2);
+ break;
+ case RMI_REG_STATE_DEFAULT:
+ default:
+ break;
}
+ error = rmi_write_block(rmi_dev, fn->fd.control_base_addr + control_offset,
+ buf, control_size);
+ if (error)
+ return error;
+
return 0;
+}
+
+static int rmi_f12_write_control_regs(struct rmi_function *fn)
+{
+ struct f12_data *f12 = dev_get_drvdata(&fn->dev);
+ if (f12->has_dribble && f12->sensor.dribble != RMI_REG_STATE_DEFAULT)
+ return rmi_f12_update_dribble(fn, f12);
+
+ return 0;
}
static int rmi_f12_config(struct rmi_function *fn)
{
struct rmi_driver *drv = fn->rmi_dev->driver;
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
+ struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
+ int irq_mask_size = BITS_TO_LONGS(drvdata->irq_count);
+ unsigned long *abs_mask = f12->irq_mask;
+ unsigned long *rel_mask = f12->irq_mask + irq_mask_size;
struct rmi_2d_sensor *sensor;
int ret;
sensor = &f12->sensor;
if (!sensor->report_abs)
- drv->clear_irq_bits(fn->rmi_dev, f12->abs_mask);
+ drv->clear_irq_bits(fn->rmi_dev, abs_mask);
else
- drv->set_irq_bits(fn->rmi_dev, f12->abs_mask);
+ drv->set_irq_bits(fn->rmi_dev, abs_mask);
- drv->clear_irq_bits(fn->rmi_dev, f12->rel_mask);
+ drv->clear_irq_bits(fn->rmi_dev, rel_mask);
ret = rmi_f12_write_control_regs(fn);
if (ret)
dev_warn(&fn->dev,
- "Failed to write F12 control registers: %d\n", ret);
+ "Failed to write F12 control registers: %d\n", ret);
return 0;
}
@@ -349,12 +380,14 @@ static int rmi_f12_probe(struct rmi_function *fn)
struct rmi_2d_sensor *sensor;
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
- u16 data_offset = 0;
- int mask_size;
+ size_t data_offset = 0;
+ size_t pkt_size;
+ int irq_mask_size;
+ int i;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
- mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long);
+ irq_mask_size = BITS_TO_LONGS(drvdata->irq_count);
ret = rmi_read(fn->rmi_dev, query_addr, &buf);
if (ret < 0) {
@@ -370,18 +403,13 @@ static int rmi_f12_probe(struct rmi_function *fn)
return -ENODEV;
}
- f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
- GFP_KERNEL);
+ f12 = devm_kzalloc(&fn->dev, struct_size(f12, irq_mask, irq_mask_size * 2),
+ GFP_KERNEL);
if (!f12)
return -ENOMEM;
- f12->abs_mask = (unsigned long *)((char *)f12
- + sizeof(struct f12_data));
- f12->rel_mask = (unsigned long *)((char *)f12
- + sizeof(struct f12_data) + mask_size);
-
- set_bit(fn->irq_pos, f12->abs_mask);
- set_bit(fn->irq_pos + 1, f12->rel_mask);
+ set_bit(fn->irq_pos, f12->irq_mask);
+ set_bit(fn->irq_pos + 1, f12->irq_mask + irq_mask_size);
f12->has_dribble = !!(buf & BIT(3));
@@ -393,55 +421,32 @@ static int rmi_f12_probe(struct rmi_function *fn)
f12->sensor_pdata = pdata->sensor_pdata;
}
- ret = rmi_read_register_desc(rmi_dev, query_addr,
- &f12->query_reg_desc);
- if (ret) {
- dev_err(&fn->dev,
- "Failed to read the Query Register Descriptor: %d\n",
- ret);
- return ret;
- }
- query_addr += 3;
-
- ret = rmi_read_register_desc(rmi_dev, query_addr,
- &f12->control_reg_desc);
- if (ret) {
- dev_err(&fn->dev,
- "Failed to read the Control Register Descriptor: %d\n",
- ret);
- return ret;
- }
- query_addr += 3;
-
- ret = rmi_read_register_desc(rmi_dev, query_addr,
- &f12->data_reg_desc);
- if (ret) {
- dev_err(&fn->dev,
- "Failed to read the Data Register Descriptor: %d\n",
- ret);
+ ret = rmi_f12_read_register_descs(fn, f12, query_addr);
+ if (ret)
return ret;
- }
- query_addr += 3;
sensor = &f12->sensor;
sensor->fn = fn;
f12->data_addr = fn->fd.data_base_addr;
- sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+ pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+ if (pkt_size > SZ_1M) {
+ dev_err(&fn->dev, "Invalid data packet size: %zu\n", pkt_size);
+ return -EINVAL;
+ }
+ sensor->pkt_size = pkt_size;
- sensor->axis_align =
- f12->sensor_pdata.axis_align;
+ sensor->axis_align = f12->sensor_pdata.axis_align;
sensor->x_mm = f12->sensor_pdata.x_mm;
sensor->y_mm = f12->sensor_pdata.y_mm;
sensor->dribble = f12->sensor_pdata.dribble;
if (sensor->sensor_type == rmi_sensor_default)
- sensor->sensor_type =
- f12->sensor_pdata.sensor_type;
+ sensor->sensor_type = f12->sensor_pdata.sensor_type;
- rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %u\n", __func__,
sensor->pkt_size);
- sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
+ sensor->data_pkt = devm_kmalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
if (!sensor->data_pkt)
return -ENOMEM;
@@ -452,108 +457,86 @@ static int rmi_f12_probe(struct rmi_function *fn)
return ret;
/*
- * Figure out what data is contained in the data registers. HID devices
- * may have registers defined, but their data is not reported in the
- * HID attention report. Registers which are not reported in the HID
- * attention report check to see if the device is receiving data from
- * HID attention reports.
+ * Identify available data registers and calculate their offsets within
+ * the attention report. For HID devices, only Data1 and Data5 are
+ * included in the report; other registers may be described but are
+ * not transmitted in the attention packet and thus skipped here.
*/
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 0);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 1);
- if (item) {
- f12->data1 = item;
- f12->data1_offset = data_offset;
- data_offset += item->reg_size;
- sensor->nbr_fingers = item->num_subpackets;
- sensor->report_abs = 1;
- sensor->attn_size += item->reg_size;
- }
+ for (i = 0; i < 16; i++) {
+ item = rmi_get_register_desc_item(&f12->data_reg_desc, i);
+ if (!item)
+ continue;
+
+ /* HID attention reports only contain Data1 and Data5 */
+ if (drvdata->attn_data.data && i != 1 && i != 5)
+ continue;
+
+ if (data_offset > U16_MAX) {
+ dev_err(&fn->dev, "Invalid offset for data%d: %zu\n",
+ i, data_offset);
+ return -EINVAL;
+ }
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 2);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ switch (i) {
+ case 1:
+ f12->data1 = item;
+ f12->data1_offset = data_offset;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 3);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ if (item->num_subpackets > 255) {
+ dev_err(&fn->dev,
+ "Too many fingers declared: %d\n",
+ item->num_subpackets);
+ return -EINVAL;
+ }
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 4);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ sensor->nbr_fingers = item->num_subpackets;
+ sensor->report_abs = 1;
+ sensor->attn_size += item->reg_size;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 5);
- if (item) {
- f12->data5 = item;
- f12->data5_offset = data_offset;
- data_offset += item->reg_size;
- sensor->attn_size += item->reg_size;
- }
+ case 5:
+ f12->data5 = item;
+ f12->data5_offset = data_offset;
+ sensor->attn_size += item->reg_size;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 6);
- if (item && !drvdata->attn_data.data) {
- f12->data6 = item;
- f12->data6_offset = data_offset;
- data_offset += item->reg_size;
- }
+ case 6:
+ f12->data6 = item;
+ f12->data6_offset = data_offset;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 7);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ case 9:
+ f12->data9 = item;
+ f12->data9_offset = data_offset;
+ if (!sensor->report_abs)
+ sensor->report_rel = 1;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 8);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ case 15:
+ f12->data15 = item;
+ f12->data15_offset = data_offset;
+ break;
+ }
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 9);
- if (item && !drvdata->attn_data.data) {
- f12->data9 = item;
- f12->data9_offset = data_offset;
data_offset += item->reg_size;
- if (!sensor->report_abs)
- sensor->report_rel = 1;
}
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 10);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 11);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 12);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 13);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 14);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ /* allocate the in-kernel tracking buffers */
+ sensor->tracking_pos = devm_kcalloc(&fn->dev, sensor->nbr_fingers,
+ sizeof(*sensor->tracking_pos),
+ GFP_KERNEL);
+ if (!sensor->tracking_pos)
+ return -ENOMEM;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 15);
- if (item && !drvdata->attn_data.data) {
- f12->data15 = item;
- f12->data15_offset = data_offset;
- data_offset += item->reg_size;
- }
+ sensor->tracking_slots = devm_kcalloc(&fn->dev, sensor->nbr_fingers,
+ sizeof(*sensor->tracking_slots),
+ GFP_KERNEL);
+ if (!sensor->tracking_slots)
+ return -ENOMEM;
- /* allocate the in-kernel tracking buffers */
- sensor->tracking_pos = devm_kcalloc(&fn->dev,
- sensor->nbr_fingers, sizeof(struct input_mt_pos),
- GFP_KERNEL);
- sensor->tracking_slots = devm_kcalloc(&fn->dev,
- sensor->nbr_fingers, sizeof(int), GFP_KERNEL);
- sensor->objs = devm_kcalloc(&fn->dev,
- sensor->nbr_fingers,
- sizeof(struct rmi_2d_sensor_abs_object),
- GFP_KERNEL);
- if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
+ sensor->objs = devm_kcalloc(&fn->dev, sensor->nbr_fingers,
+ sizeof(*sensor->objs), GFP_KERNEL);
+ if (!sensor->objs)
return -ENOMEM;
ret = rmi_2d_sensor_configure_input(fn, sensor);
diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c
index 3c0c5fd44702..e11d0acb9b96 100644
--- a/drivers/input/rmi4/rmi_i2c.c
+++ b/drivers/input/rmi4/rmi_i2c.c
@@ -365,7 +365,7 @@ static const struct dev_pm_ops rmi_i2c_pm = {
};
static const struct i2c_device_id rmi_id[] = {
- { "rmi4_i2c" },
+ { .name = "rmi4_i2c" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rmi_id);
diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c
index f3d0b40721df..6de68c602558 100644
--- a/drivers/input/rmi4/rmi_smbus.c
+++ b/drivers/input/rmi4/rmi_smbus.c
@@ -413,7 +413,7 @@ static const struct dev_pm_ops rmi_smb_pm = {
};
static const struct i2c_device_id rmi_id[] = {
- { "rmi4_smbus" },
+ { .name = "rmi4_smbus" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rmi_id);
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 5f15a6462056..bacab1f58400 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -188,16 +188,6 @@ config SERIO_RAW
To compile this driver as a module, choose M here: the
module will be called serio_raw.
-config SERIO_XILINX_XPS_PS2
- tristate "Xilinx XPS PS/2 Controller Support"
- depends on PPC || MICROBLAZE
- help
- This driver supports XPS PS/2 IP from the Xilinx EDK on
- PowerPC platform.
-
- To compile this driver as a module, choose M here: the
- module will be called xilinx_ps2.
-
config SERIO_ALTERA_PS2
tristate "Altera UP PS/2 controller"
depends on HAS_IOMEM
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 8ab98f4aa28d..7f5137dc02e2 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -23,7 +23,6 @@ obj-$(CONFIG_SERIO_SGI_IOC3) += ioc3kbd.o
obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
obj-$(CONFIG_SERIO_RAW) += serio_raw.o
obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o
-obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o
obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o
obj-$(CONFIG_SERIO_ARC_PS2) += arc_ps2.o
obj-$(CONFIG_SERIO_APBPS2) += apbps2.o
diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c
index 0aa4ab00af35..5f21acdd4113 100644
--- a/drivers/input/serio/apbps2.c
+++ b/drivers/input/serio/apbps2.c
@@ -140,7 +140,7 @@ static int apbps2_of_probe(struct platform_device *ofdev)
}
/* Find device address */
- priv->regs = devm_platform_get_and_ioremap_resource(ofdev, 0, NULL);
+ priv->regs = devm_platform_ioremap_resource(ofdev, 0);
if (IS_ERR(priv->regs))
return PTR_ERR(priv->regs);
@@ -148,7 +148,10 @@ static int apbps2_of_probe(struct platform_device *ofdev)
iowrite32be(0, &priv->regs->ctrl);
/* IRQ */
- irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+ irq = platform_get_irq(ofdev, 0);
+ if (irq < 0)
+ return irq;
+
err = devm_request_irq(&ofdev->dev, irq, apbps2_isr,
IRQF_SHARED, "apbps2", priv);
if (err) {
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index 8ebdf4fb9030..412f82d7a303 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -1539,22 +1539,22 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
}
static const struct pnp_device_id pnp_kbd_devids[] = {
- { .id = "PNP0300", .driver_data = 0 },
- { .id = "PNP0301", .driver_data = 0 },
- { .id = "PNP0302", .driver_data = 0 },
- { .id = "PNP0303", .driver_data = 0 },
- { .id = "PNP0304", .driver_data = 0 },
- { .id = "PNP0305", .driver_data = 0 },
- { .id = "PNP0306", .driver_data = 0 },
- { .id = "PNP0309", .driver_data = 0 },
- { .id = "PNP030a", .driver_data = 0 },
- { .id = "PNP030b", .driver_data = 0 },
- { .id = "PNP0320", .driver_data = 0 },
- { .id = "PNP0343", .driver_data = 0 },
- { .id = "PNP0344", .driver_data = 0 },
- { .id = "PNP0345", .driver_data = 0 },
- { .id = "CPQA0D7", .driver_data = 0 },
- { .id = "", },
+ { .id = "PNP0300" },
+ { .id = "PNP0301" },
+ { .id = "PNP0302" },
+ { .id = "PNP0303" },
+ { .id = "PNP0304" },
+ { .id = "PNP0305" },
+ { .id = "PNP0306" },
+ { .id = "PNP0309" },
+ { .id = "PNP030a" },
+ { .id = "PNP030b" },
+ { .id = "PNP0320" },
+ { .id = "PNP0343" },
+ { .id = "PNP0344" },
+ { .id = "PNP0345" },
+ { .id = "CPQA0D7" },
+ { }
};
MODULE_DEVICE_TABLE(pnp, pnp_kbd_devids);
@@ -1569,18 +1569,18 @@ static struct pnp_driver i8042_pnp_kbd_driver = {
};
static const struct pnp_device_id pnp_aux_devids[] = {
- { .id = "AUI0200", .driver_data = 0 },
- { .id = "FJC6000", .driver_data = 0 },
- { .id = "FJC6001", .driver_data = 0 },
- { .id = "PNP0f03", .driver_data = 0 },
- { .id = "PNP0f0b", .driver_data = 0 },
- { .id = "PNP0f0e", .driver_data = 0 },
- { .id = "PNP0f12", .driver_data = 0 },
- { .id = "PNP0f13", .driver_data = 0 },
- { .id = "PNP0f19", .driver_data = 0 },
- { .id = "PNP0f1c", .driver_data = 0 },
- { .id = "SYN0801", .driver_data = 0 },
- { .id = "", },
+ { .id = "AUI0200" },
+ { .id = "FJC6000" },
+ { .id = "FJC6001" },
+ { .id = "PNP0f03" },
+ { .id = "PNP0f0b" },
+ { .id = "PNP0f0e" },
+ { .id = "PNP0f12" },
+ { .id = "PNP0f13" },
+ { .id = "PNP0f19" },
+ { .id = "PNP0f1c" },
+ { .id = "SYN0801" },
+ { },
};
MODULE_DEVICE_TABLE(pnp, pnp_aux_devids);
diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c
index 91cb7a177b2d..8c19975c84bf 100644
--- a/drivers/input/serio/userio.c
+++ b/drivers/input/serio/userio.c
@@ -1,7 +1,7 @@
/*
* userio kernel serio device emulation module
* Copyright (C) 2015 Red Hat
- * Copyright (C) 2015 Stephen Chandler Paul <thatslyude@gmail.com>
+ * Copyright (C) 2015 Lyude Paul <thatslyude@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -206,6 +206,36 @@ static int userio_execute_cmd(struct userio_device *userio,
userio->serio->id.type = cmd->data;
break;
+ case USERIO_CMD_SET_PORT_EXTRA:
+ if (userio->running) {
+ dev_warn(userio_misc.this_device,
+ "Can't change port extra on an already running userio instance\n");
+ return -EBUSY;
+ }
+
+ userio->serio->id.extra = cmd->data;
+ break;
+
+ case USERIO_CMD_SET_PORT_ID:
+ if (userio->running) {
+ dev_warn(userio_misc.this_device,
+ "Can't change port id on an already running userio instance\n");
+ return -EBUSY;
+ }
+
+ userio->serio->id.id = cmd->data;
+ break;
+
+ case USERIO_CMD_SET_PORT_PROTO:
+ if (userio->running) {
+ dev_warn(userio_misc.this_device,
+ "Can't change port proto on an already running userio instance\n");
+ return -EBUSY;
+ }
+
+ userio->serio->id.proto = cmd->data;
+ break;
+
case USERIO_CMD_SEND_INTERRUPT:
if (!userio->running) {
dev_warn(userio_misc.this_device,
@@ -278,6 +308,6 @@ module_driver(userio_misc, misc_register, misc_deregister);
MODULE_ALIAS_MISCDEV(USERIO_MINOR);
MODULE_ALIAS("devname:" USERIO_NAME);
-MODULE_AUTHOR("Stephen Chandler Paul <thatslyude@gmail.com>");
+MODULE_AUTHOR("Lyude Paul <thatslyude@gmail.com>");
MODULE_DESCRIPTION("Virtual Serio Device Support");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
deleted file mode 100644
index 411d55ca1a66..000000000000
--- a/drivers/input/serio/xilinx_ps2.c
+++ /dev/null
@@ -1,363 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Xilinx XPS PS/2 device driver
- *
- * (c) 2005 MontaVista Software, Inc.
- * (c) 2008 Xilinx, Inc.
- */
-
-
-#include <linux/module.h>
-#include <linux/serio.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/io.h>
-#include <linux/mod_devicetable.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-
-#define DRIVER_NAME "xilinx_ps2"
-
-/* Register offsets for the xps2 device */
-#define XPS2_SRST_OFFSET 0x00000000 /* Software Reset register */
-#define XPS2_STATUS_OFFSET 0x00000004 /* Status register */
-#define XPS2_RX_DATA_OFFSET 0x00000008 /* Receive Data register */
-#define XPS2_TX_DATA_OFFSET 0x0000000C /* Transmit Data register */
-#define XPS2_GIER_OFFSET 0x0000002C /* Global Interrupt Enable reg */
-#define XPS2_IPISR_OFFSET 0x00000030 /* Interrupt Status register */
-#define XPS2_IPIER_OFFSET 0x00000038 /* Interrupt Enable register */
-
-/* Reset Register Bit Definitions */
-#define XPS2_SRST_RESET 0x0000000A /* Software Reset */
-
-/* Status Register Bit Positions */
-#define XPS2_STATUS_RX_FULL 0x00000001 /* Receive Full */
-#define XPS2_STATUS_TX_FULL 0x00000002 /* Transmit Full */
-
-/*
- * Bit definitions for ISR/IER registers. Both the registers have the same bit
- * definitions and are only defined once.
- */
-#define XPS2_IPIXR_WDT_TOUT 0x00000001 /* Watchdog Timeout Interrupt */
-#define XPS2_IPIXR_TX_NOACK 0x00000002 /* Transmit No ACK Interrupt */
-#define XPS2_IPIXR_TX_ACK 0x00000004 /* Transmit ACK (Data) Interrupt */
-#define XPS2_IPIXR_RX_OVF 0x00000008 /* Receive Overflow Interrupt */
-#define XPS2_IPIXR_RX_ERR 0x00000010 /* Receive Error Interrupt */
-#define XPS2_IPIXR_RX_FULL 0x00000020 /* Receive Data Interrupt */
-
-/* Mask for all the Transmit Interrupts */
-#define XPS2_IPIXR_TX_ALL (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK)
-
-/* Mask for all the Receive Interrupts */
-#define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \
- XPS2_IPIXR_RX_FULL)
-
-/* Mask for all the Interrupts */
-#define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \
- XPS2_IPIXR_WDT_TOUT)
-
-/* Global Interrupt Enable mask */
-#define XPS2_GIER_GIE_MASK 0x80000000
-
-struct xps2data {
- int irq;
- spinlock_t lock;
- void __iomem *base_address; /* virt. address of control registers */
- unsigned int flags;
- struct serio *serio; /* serio */
- struct device *dev;
-};
-
-/************************************/
-/* XPS PS/2 data transmission calls */
-/************************************/
-
-/**
- * xps2_recv() - attempts to receive a byte from the PS/2 port.
- * @drvdata: pointer to ps2 device private data structure
- * @byte: address where the read data will be copied
- *
- * If there is any data available in the PS/2 receiver, this functions reads
- * the data, otherwise it returns error.
- */
-static int xps2_recv(struct xps2data *drvdata, u8 *byte)
-{
- u32 sr;
- int status = -1;
-
- /* If there is data available in the PS/2 receiver, read it */
- sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
- if (sr & XPS2_STATUS_RX_FULL) {
- *byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET);
- status = 0;
- }
-
- return status;
-}
-
-/*********************/
-/* Interrupt handler */
-/*********************/
-static irqreturn_t xps2_interrupt(int irq, void *dev_id)
-{
- struct xps2data *drvdata = dev_id;
- u32 intr_sr;
- u8 c;
- int status;
-
- /* Get the PS/2 interrupts and clear them */
- intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET);
- out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr);
-
- /* Check which interrupt is active */
- if (intr_sr & XPS2_IPIXR_RX_OVF)
- dev_warn(drvdata->dev, "receive overrun error\n");
-
- if (intr_sr & XPS2_IPIXR_RX_ERR)
- drvdata->flags |= SERIO_PARITY;
-
- if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT))
- drvdata->flags |= SERIO_TIMEOUT;
-
- if (intr_sr & XPS2_IPIXR_RX_FULL) {
- status = xps2_recv(drvdata, &c);
-
- /* Error, if a byte is not received */
- if (status) {
- dev_err(drvdata->dev,
- "wrong rcvd byte count (%d)\n", status);
- } else {
- serio_interrupt(drvdata->serio, c, drvdata->flags);
- drvdata->flags = 0;
- }
- }
-
- return IRQ_HANDLED;
-}
-
-/*******************/
-/* serio callbacks */
-/*******************/
-
-/**
- * sxps2_write() - sends a byte out through the PS/2 port.
- * @pserio: pointer to the serio structure of the PS/2 port
- * @c: data that needs to be written to the PS/2 port
- *
- * This function checks if the PS/2 transmitter is empty and sends a byte.
- * Otherwise it returns error. Transmission fails only when nothing is connected
- * to the PS/2 port. Thats why, we do not try to resend the data in case of a
- * failure.
- */
-static int sxps2_write(struct serio *pserio, unsigned char c)
-{
- struct xps2data *drvdata = pserio->port_data;
- u32 sr;
-
- guard(spinlock_irqsave)(&drvdata->lock);
-
- /* If the PS/2 transmitter is empty send a byte of data */
- sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
- if (sr & XPS2_STATUS_TX_FULL)
- return -EAGAIN;
-
- out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
- return 0;
-}
-
-/**
- * sxps2_open() - called when a port is opened by the higher layer.
- * @pserio: pointer to the serio structure of the PS/2 device
- *
- * This function requests irq and enables interrupts for the PS/2 device.
- */
-static int sxps2_open(struct serio *pserio)
-{
- struct xps2data *drvdata = pserio->port_data;
- int error;
- u8 c;
-
- error = request_irq(drvdata->irq, &xps2_interrupt, 0,
- DRIVER_NAME, drvdata);
- if (error) {
- dev_err(drvdata->dev,
- "Couldn't allocate interrupt %d\n", drvdata->irq);
- return error;
- }
-
- /* start reception by enabling the interrupts */
- out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK);
- out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL);
- (void)xps2_recv(drvdata, &c);
-
- return 0; /* success */
-}
-
-/**
- * sxps2_close() - frees the interrupt.
- * @pserio: pointer to the serio structure of the PS/2 device
- *
- * This function frees the irq and disables interrupts for the PS/2 device.
- */
-static void sxps2_close(struct serio *pserio)
-{
- struct xps2data *drvdata = pserio->port_data;
-
- /* Disable the PS2 interrupts */
- out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00);
- out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00);
- free_irq(drvdata->irq, drvdata);
-}
-
-/**
- * xps2_of_probe - probe method for the PS/2 device.
- * @ofdev: pointer to OF device structure
- *
- * This function probes the PS/2 device in the device tree.
- * It initializes the driver data structure and the hardware.
- * It returns 0, if the driver is bound to the PS/2 device, or a negative
- * value if there is an error.
- */
-static int xps2_of_probe(struct platform_device *ofdev)
-{
- struct resource r_mem; /* IO mem resources */
- struct xps2data *drvdata;
- struct serio *serio;
- struct device *dev = &ofdev->dev;
- resource_size_t remap_size, phys_addr;
- unsigned int irq;
- int error;
-
- dev_info(dev, "Device Tree Probing \'%pOFn\'\n", dev->of_node);
-
- /* Get iospace for the device */
- error = of_address_to_resource(dev->of_node, 0, &r_mem);
- if (error) {
- dev_err(dev, "invalid address\n");
- return error;
- }
-
- /* Get IRQ for the device */
- irq = irq_of_parse_and_map(dev->of_node, 0);
- if (!irq) {
- dev_err(dev, "no IRQ found\n");
- return -ENODEV;
- }
-
- drvdata = kzalloc_obj(*drvdata);
- serio = kzalloc_obj(*serio);
- if (!drvdata || !serio) {
- error = -ENOMEM;
- goto failed1;
- }
-
- spin_lock_init(&drvdata->lock);
- drvdata->irq = irq;
- drvdata->serio = serio;
- drvdata->dev = dev;
-
- phys_addr = r_mem.start;
- remap_size = resource_size(&r_mem);
- if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) {
- dev_err(dev, "Couldn't lock memory region at 0x%08llX\n",
- (unsigned long long)phys_addr);
- error = -EBUSY;
- goto failed1;
- }
-
- /* Fill in configuration data and add them to the list */
- drvdata->base_address = ioremap(phys_addr, remap_size);
- if (drvdata->base_address == NULL) {
- dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n",
- (unsigned long long)phys_addr);
- error = -EFAULT;
- goto failed2;
- }
-
- /* Disable all the interrupts, just in case */
- out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0);
-
- /*
- * Reset the PS2 device and abort any current transaction,
- * to make sure we have the PS2 in a good state.
- */
- out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
-
- dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n",
- (unsigned long long)phys_addr, drvdata->base_address,
- drvdata->irq);
-
- serio->id.type = SERIO_8042;
- serio->write = sxps2_write;
- serio->open = sxps2_open;
- serio->close = sxps2_close;
- serio->port_data = drvdata;
- serio->dev.parent = dev;
- snprintf(serio->name, sizeof(serio->name),
- "Xilinx XPS PS/2 at %08llX", (unsigned long long)phys_addr);
- snprintf(serio->phys, sizeof(serio->phys),
- "xilinxps2/serio at %08llX", (unsigned long long)phys_addr);
-
- serio_register_port(serio);
-
- platform_set_drvdata(ofdev, drvdata);
- return 0; /* success */
-
-failed2:
- release_mem_region(phys_addr, remap_size);
-failed1:
- kfree(serio);
- kfree(drvdata);
-
- return error;
-}
-
-/**
- * xps2_of_remove - unbinds the driver from the PS/2 device.
- * @of_dev: pointer to OF device structure
- *
- * This function is called if a device is physically removed from the system or
- * if the driver module is being unloaded. It frees any resources allocated to
- * the device.
- */
-static void xps2_of_remove(struct platform_device *of_dev)
-{
- struct xps2data *drvdata = platform_get_drvdata(of_dev);
- struct resource r_mem; /* IO mem resources */
-
- serio_unregister_port(drvdata->serio);
- iounmap(drvdata->base_address);
-
- /* Get iospace of the device */
- if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem))
- dev_err(drvdata->dev, "invalid address\n");
- else
- release_mem_region(r_mem.start, resource_size(&r_mem));
-
- kfree(drvdata);
-}
-
-/* Match table for of_platform binding */
-static const struct of_device_id xps2_of_match[] = {
- { .compatible = "xlnx,xps-ps2-1.00.a", },
- { /* end of list */ },
-};
-MODULE_DEVICE_TABLE(of, xps2_of_match);
-
-static struct platform_driver xps2_of_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .of_match_table = xps2_of_match,
- },
- .probe = xps2_of_probe,
- .remove = xps2_of_remove,
-};
-module_platform_driver(xps2_of_driver);
-
-MODULE_AUTHOR("Xilinx, Inc.");
-MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index c850b5890070..0c1acb9e6b43 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -16,37 +16,6 @@
*
* Many thanks to Oliver Kuechemann for his support.
*
- * ChangeLog:
- * v0.1 - Initial release
- * v0.2 - Hack to get around fake event 28's. (Bryan W. Headley)
- * v0.3 - Make URB dynamic (Bryan W. Headley, Jun-8-2002)
- * Released to Linux 2.4.19 and 2.5.x
- * v0.4 - Rewrote substantial portions of the code to deal with
- * corrected control sequences, timing, dynamic configuration,
- * support of 6000U - 12000U, procfs, and macro key support
- * (Jan-1-2003 - Feb-5-2003, Bryan W. Headley)
- * v1.0 - Added support for diagnostic messages, count of messages
- * received from URB - Mar-8-2003, Bryan W. Headley
- * v1.1 - added support for tablet resolution, changed DV and proximity
- * some corrections - Jun-22-2003, martin schneebacher
- * - Added support for the sysfs interface, deprecating the
- * procfs interface for 2.5.x kernel. Also added support for
- * Wheel command. Bryan W. Headley July-15-2003.
- * v1.2 - Reworked jitter timer as a kernel thread.
- * Bryan W. Headley November-28-2003/Jan-10-2004.
- * v1.3 - Repaired issue of kernel thread going nuts on single-processor
- * machines, introduced programmableDelay as a command line
- * parameter. Feb 7 2004, Bryan W. Headley.
- * v1.4 - Re-wire jitter so it does not require a thread. Courtesy of
- * Rene van Paassen. Added reporting of physical pointer device
- * (e.g., stylus, mouse in reports 2, 3, 4, 5. We don't know
- * for reports 1, 6.)
- * what physical device reports for reports 1, 6.) Also enabled
- * MOUSE and LENS tool button modes. Renamed "rubber" to "eraser".
- * Feb 20, 2004, Bryan W. Headley.
- * v1.5 - Added previousJitterable, so we don't do jitter delay when the
- * user is holding a button down for periods of time.
- *
* NOTE:
* This kernel driver is augmented by the "Aiptek" XFree86 input
* driver for your X server, as well as the Gaiptek GUI Front-end
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index aeaf9a9cbb41..9b9ae8ac3f7f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -610,6 +610,18 @@ config TOUCHSCREEN_WACOM_I2C
To compile this driver as a module, choose M here: the module
will be called wacom_i2c.
+config TOUCHSCREEN_WACOM_W9000
+ tristate "Wacom W9000-series penabled touchscreen (I2C)"
+ depends on I2C
+ help
+ Say Y here if you have a Wacom W9000-series penabled I2C touchscreen.
+ This driver supports models W9002 and W9007A.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called wacom_w9000.
+
config TOUCHSCREEN_LPC32XX
tristate "LPC32XX touchscreen controller"
depends on ARCH_LPC32XX
@@ -1178,16 +1190,6 @@ config TOUCHSCREEN_TSC2007_IIO
or ambient light monitoring), temperature and raw input
values.
-config TOUCHSCREEN_PCAP
- tristate "Motorola PCAP touchscreen"
- depends on EZX_PCAP
- help
- Say Y here if you have a Motorola EZX telephone and
- want to enable support for the built-in touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called pcap_ts.
-
config TOUCHSCREEN_RM_TS
tristate "Raydium I2C Touchscreen"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f2b002abebe8..bfd9de83389d 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -74,7 +74,6 @@ obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO) += ipaq-micro-ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
-obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o
@@ -101,6 +100,7 @@ tsc2007-$(CONFIG_TOUCHSCREEN_TSC2007_IIO) += tsc2007_iio.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_WACOM_W9000) += wacom_w9000.o
obj-$(CONFIG_TOUCHSCREEN_WDT87XX_I2C) += wdt87xx_i2c.o
obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
index e5b99312c3d9..c1ccdf86b74c 100644
--- a/drivers/input/touchscreen/ad7879-i2c.c
+++ b/drivers/input/touchscreen/ad7879-i2c.c
@@ -42,8 +42,8 @@ static int ad7879_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ad7879_id[] = {
- { "ad7879" },
- { "ad7889" },
+ { .name = "ad7879" },
+ { .name = "ad7889" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad7879_id);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 4b39f7212d35..8d6416ac283e 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -134,6 +134,9 @@ struct ads7846 {
bool disabled; /* P: lock */
bool suspended; /* P: lock */
+ int (*setup_spi_msg)(struct ads7846 *ts,
+ const struct ads7846_platform_data *pdata);
+ void (*read_state)(struct ads7846 *ts);
int (*filter)(void *data, int data_idx, int *val);
void *filter_data;
int (*get_pendown_state)(void);
@@ -325,7 +328,6 @@ struct ser_req {
u8 ref_on;
u8 command;
u8 ref_off;
- u16 scratch;
struct spi_message msg;
struct spi_transfer xfer[8];
/*
@@ -333,6 +335,7 @@ struct ser_req {
* transfer buffers to live in their own cache lines.
*/
__be16 sample ____cacheline_aligned;
+ u16 scratch;
};
struct ads7845_ser_req {
@@ -403,8 +406,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
spi_message_add_tail(&req->xfer[5], &req->msg);
/* clear the command register */
- req->scratch = 0;
- req->xfer[6].tx_buf = &req->scratch;
+ req->xfer[6].rx_buf = &req->scratch;
req->xfer[6].len = 1;
spi_message_add_tail(&req->xfer[6], &req->msg);
@@ -789,6 +791,22 @@ static int ads7846_filter(struct ads7846 *ts)
return 0;
}
+static int ads7846_filter_one(struct ads7846 *ts, unsigned int cmd_idx)
+{
+ struct ads7846_packet *packet = ts->packet;
+ struct ads7846_buf_layout *l = &packet->l[cmd_idx];
+ int action, val;
+
+ val = ads7846_get_value(&packet->rx[l->offset + l->count - 1]);
+ action = ts->filter(ts->filter_data, cmd_idx, &val);
+ if (action == ADS7846_FILTER_REPEAT)
+ return -EAGAIN;
+ else if (action != ADS7846_FILTER_OK)
+ return -EIO;
+ ads7846_set_cmd_val(ts, cmd_idx, val);
+ return 0;
+}
+
static void ads7846_wait_for_hsync(struct ads7846 *ts)
{
if (ts->wait_for_sync) {
@@ -811,6 +829,45 @@ static void ads7846_wait_for_hsync(struct ads7846 *ts)
cpu_relax();
}
+static void ads7846_halfd_read_state(struct ads7846 *ts)
+{
+ struct ads7846_packet *packet = ts->packet;
+ int msg_idx = 0;
+
+ packet->ignore = false;
+
+ while (msg_idx < ts->msg_count) {
+ int error;
+
+ ads7846_wait_for_hsync(ts);
+
+ error = spi_sync(ts->spi, &ts->msg[msg_idx]);
+ if (error) {
+ dev_err_ratelimited(&ts->spi->dev, "spi_sync --> %d\n",
+ error);
+ packet->ignore = true;
+ return;
+ }
+
+ /*
+ * Last message is power down request, no need to convert
+ * or filter the value.
+ */
+ if (msg_idx == ts->msg_count - 1)
+ break;
+
+ error = ads7846_filter_one(ts, msg_idx);
+ if (error == -EAGAIN) {
+ continue;
+ } else if (error) {
+ packet->ignore = true;
+ msg_idx = ts->msg_count - 1;
+ } else {
+ msg_idx++;
+ }
+ }
+}
+
static void ads7846_read_state(struct ads7846 *ts)
{
struct ads7846_packet *packet = ts->packet;
@@ -939,7 +996,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
while (!ts->stopped && get_pendown_state(ts)) {
/* pen is down, continue with the measurement */
- ads7846_read_state(ts);
+ ts->read_state(ts);
if (!ts->stopped)
ads7846_report_state(ts);
@@ -1026,6 +1083,102 @@ static int ads7846_setup_pendown(struct spi_device *spi,
* Set up the transfers to read touchscreen state; this assumes we
* use formula #2 for pressure, not #3.
*/
+static int ads7846_halfd_spi_msg(struct ads7846 *ts,
+ const struct ads7846_platform_data *pdata)
+{
+ struct spi_message *m = ts->msg;
+ struct spi_transfer *x = ts->xfer;
+ struct ads7846_packet *packet = ts->packet;
+ int vref = pdata->keep_vref_on;
+ unsigned int offset = 0;
+ unsigned int cmd_idx, b;
+ size_t size = 0;
+
+ if (pdata->settle_delay_usecs)
+ packet->count = 2;
+ else
+ packet->count = 1;
+
+ if (ts->model == 7846)
+ packet->cmds = 5; /* x, y, z1, z2, pwdown */
+ else
+ packet->cmds = 3; /* x, y, pwdown */
+
+ for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) {
+ struct ads7846_buf_layout *l = &packet->l[cmd_idx];
+ unsigned int max_count;
+
+ if (cmd_idx == packet->cmds - 1) {
+ cmd_idx = ADS7846_PWDOWN;
+ max_count = 1;
+ } else {
+ max_count = packet->count;
+ }
+
+ l->offset = offset;
+ offset += max_count;
+ l->count = max_count;
+ l->skip = 0;
+ size += sizeof(*packet->rx) * max_count;
+ }
+
+ /* We use two transfers per command. */
+ if (ARRAY_SIZE(ts->xfer) < offset * 2)
+ return -ENOMEM;
+
+ packet->rx = devm_kzalloc(&ts->spi->dev, size, GFP_KERNEL);
+ if (!packet->rx)
+ return -ENOMEM;
+
+ if (ts->model == 7873) {
+ /*
+ * The AD7873 is almost identical to the ADS7846
+ * keep VREF off during differential/ratiometric
+ * conversion modes.
+ */
+ ts->model = 7846;
+ vref = 0;
+ }
+
+ ts->msg_count = 0;
+
+ for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) {
+ struct ads7846_buf_layout *l = &packet->l[cmd_idx];
+ u8 cmd;
+
+ ts->msg_count++;
+ spi_message_init(m);
+ m->context = ts;
+
+ if (cmd_idx == packet->cmds - 1)
+ cmd_idx = ADS7846_PWDOWN;
+
+ cmd = ads7846_get_cmd(cmd_idx, vref);
+
+ for (b = 0; b < l->count; b++) {
+ packet->rx[l->offset + b].cmd = cmd;
+ x->tx_buf = &packet->rx[l->offset + b].cmd;
+ x->len = 1;
+ spi_message_add_tail(x, m);
+ x++;
+ x->rx_buf = &packet->rx[l->offset + b].data;
+ x->len = 2;
+ if (b < l->count - 1 && l->count > 1) {
+ x->delay.value = pdata->settle_delay_usecs;
+ x->delay.unit = SPI_DELAY_UNIT_USECS;
+ }
+ spi_message_add_tail(x, m);
+ x++;
+ }
+ m++;
+ }
+ return 0;
+}
+
+/*
+ * Set up the transfers to read touchscreen state; this assumes we
+ * use formula #2 for pressure, not #3.
+ */
static int ads7846_setup_spi_msg(struct ads7846 *ts,
const struct ads7846_platform_data *pdata)
{
@@ -1236,6 +1389,14 @@ static int ads7846_probe(struct spi_device *spi)
if (!ts)
return -ENOMEM;
+ if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) {
+ ts->setup_spi_msg = ads7846_halfd_spi_msg;
+ ts->read_state = ads7846_halfd_read_state;
+ } else {
+ ts->setup_spi_msg = ads7846_setup_spi_msg;
+ ts->read_state = ads7846_read_state;
+ }
+
packet = devm_kzalloc(dev, sizeof(struct ads7846_packet), GFP_KERNEL);
if (!packet)
return -ENOMEM;
@@ -1330,7 +1491,9 @@ static int ads7846_probe(struct spi_device *spi)
ts->core_prop.swap_x_y = true;
}
- ads7846_setup_spi_msg(ts, pdata);
+ err = ts->setup_spi_msg(ts, pdata);
+ if (err)
+ return err;
ts->reg = devm_regulator_get(dev, "vcc");
if (IS_ERR(ts->reg)) {
diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c
index 8a588202447d..aa43fc1549df 100644
--- a/drivers/input/touchscreen/ar1021_i2c.c
+++ b/drivers/input/touchscreen/ar1021_i2c.c
@@ -164,7 +164,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ar1021_i2c_pm,
ar1021_i2c_suspend, ar1021_i2c_resume);
static const struct i2c_device_id ar1021_i2c_id[] = {
- { "ar1021" },
+ { .name = "ar1021" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index f21bf2844112..2c0e5a67135b 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1397,7 +1397,8 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
{
struct device *dev = &data->client->dev;
struct mxt_object *object;
- unsigned int type, instance, size, byte_offset;
+ unsigned int type, instance, size;
+ int byte_offset;
int offset;
int ret;
int i;
@@ -2840,14 +2841,12 @@ static ssize_t mxt_object_show(struct device *dev,
int count = 0;
int i, j;
int error;
- u8 *obuf;
/* Pre-allocate buffer large enough to hold max sized object. */
- obuf = kmalloc(256, GFP_KERNEL);
+ u8 *obuf __free(kfree) = kmalloc(256, GFP_KERNEL);
if (!obuf)
return -ENOMEM;
- error = 0;
for (i = 0; i < data->info->object_num; i++) {
object = data->object_table + i;
@@ -2862,15 +2861,13 @@ static ssize_t mxt_object_show(struct device *dev,
error = __mxt_read_reg(data->client, addr, size, obuf);
if (error)
- goto done;
+ return error;
count = mxt_show_instance(buf, count, object, j, obuf);
}
}
-done:
- kfree(obuf);
- return error ?: count;
+ return count;
}
static int mxt_check_firmware_format(struct device *dev,
@@ -3420,11 +3417,11 @@ MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
#endif
static const struct i2c_device_id mxt_id[] = {
- { "qt602240_ts" },
- { "atmel_mxt_ts" },
- { "atmel_mxt_tp" },
- { "maxtouch" },
- { "mXT224" },
+ { .name = "qt602240_ts" },
+ { .name = "atmel_mxt_ts" },
+ { .name = "atmel_mxt_tp" },
+ { .name = "maxtouch" },
+ { .name = "mXT224" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mxt_id);
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 401b2264f585..6c6ebebacba9 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -618,7 +618,7 @@ static int auo_pixcir_probe(struct i2c_client *client)
}
static const struct i2c_device_id auo_pixcir_idtable[] = {
- { "auo_pixcir_ts" },
+ { .name = "auo_pixcir_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable);
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
index 6baebb7ec089..d1bdccc56fc8 100644
--- a/drivers/input/touchscreen/bu21013_ts.c
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -597,7 +597,7 @@ static int bu21013_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(bu21013_dev_pm_ops, bu21013_suspend, bu21013_resume);
static const struct i2c_device_id bu21013_id[] = {
- { DRIVER_TP },
+ { .name = DRIVER_TP },
{ }
};
MODULE_DEVICE_TABLE(i2c, bu21013_id);
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c
index 68d9cd55ceeb..339fee1622fb 100644
--- a/drivers/input/touchscreen/bu21029_ts.c
+++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -442,7 +442,7 @@ static int bu21029_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(bu21029_pm_ops, bu21029_suspend, bu21029_resume);
static const struct i2c_device_id bu21029_ids[] = {
- { DRIVER_NAME },
+ { .name = DRIVER_NAME },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, bu21029_ids);
diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c
index 2d4b6e343203..0ac48eff3376 100644
--- a/drivers/input/touchscreen/cy8ctma140.c
+++ b/drivers/input/touchscreen/cy8ctma140.c
@@ -322,7 +322,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cy8ctma140_pm,
cy8ctma140_suspend, cy8ctma140_resume);
static const struct i2c_device_id cy8ctma140_idtable[] = {
- { CY8CTMA140_NAME },
+ { .name = CY8CTMA140_NAME },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, cy8ctma140_idtable);
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index 54d6c4869eb0..33ad4f0512a0 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -267,7 +267,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cy8ctmg110_pm,
cy8ctmg110_suspend, cy8ctmg110_resume);
static const struct i2c_device_id cy8ctmg110_idtable[] = {
- { CY8CTMG110_DRIVER_NAME, 1 },
+ { .name = CY8CTMG110_DRIVER_NAME, .driver_data = 1 },
{ }
};
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
index 47f4271395a6..73c397e44da4 100644
--- a/drivers/input/touchscreen/cyttsp5.c
+++ b/drivers/input/touchscreen/cyttsp5.c
@@ -938,7 +938,7 @@ static const struct of_device_id cyttsp5_of_match[] = {
MODULE_DEVICE_TABLE(of, cyttsp5_of_match);
static const struct i2c_device_id cyttsp5_i2c_id[] = {
- { CYTTSP5_NAME },
+ { .name = CYTTSP5_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
index cb15600549cd..17524f7e944d 100644
--- a/drivers/input/touchscreen/cyttsp_i2c.c
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -103,7 +103,7 @@ static int cyttsp_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id cyttsp_i2c_id[] = {
- { CY_I2C_NAME },
+ { .name = CY_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 492e19a28a74..b12602bc368e 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -266,7 +266,7 @@ static int eeti_ts_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume);
static const struct i2c_device_id eeti_ts_id[] = {
- { "eeti_ts" },
+ { .name = "eeti_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, eeti_ts_id);
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index eb3cc2befcdf..76cf8085553f 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -219,7 +219,7 @@ static int egalax_ts_probe(struct i2c_client *client)
}
static const struct i2c_device_id egalax_ts_id[] = {
- { "egalax_ts" },
+ { .name = "egalax_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, egalax_ts_id);
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 835d91dff0a4..17175adcaebb 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -1615,9 +1615,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
elants_i2c_suspend, elants_i2c_resume);
static const struct i2c_device_id elants_i2c_id[] = {
- { DEVICE_NAME, EKTH3500 },
- { "ekth3500", EKTH3500 },
- { "ektf3624", EKTF3624 },
+ { .name = DEVICE_NAME, .driver_data = EKTH3500 },
+ { .name = "ekth3500", .driver_data = EKTH3500 },
+ { .name = "ektf3624", .driver_data = EKTF3624 },
{ }
};
MODULE_DEVICE_TABLE(i2c, elants_i2c_id);
diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c
index 78c0911ba6e2..037bb35238a3 100644
--- a/drivers/input/touchscreen/exc3000.c
+++ b/drivers/input/touchscreen/exc3000.c
@@ -432,10 +432,10 @@ static int exc3000_probe(struct i2c_client *client)
}
static const struct i2c_device_id exc3000_id[] = {
- { "exc3000", EETI_EXC3000 },
- { "exc80h60", EETI_EXC80H60 },
- { "exc80h84", EETI_EXC80H84 },
- { "exc81w32", EETI_EXC81W32 },
+ { .name = "exc3000", .driver_data = EETI_EXC3000 },
+ { .name = "exc80h60", .driver_data = EETI_EXC80H60 },
+ { .name = "exc80h84", .driver_data = EETI_EXC80H84 },
+ { .name = "exc81w32", .driver_data = EETI_EXC81W32 },
{ }
};
MODULE_DEVICE_TABLE(i2c, exc3000_id);
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index f8798d11ec03..03efc0c792c2 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -1057,7 +1057,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
}
ts->int_trigger_type = ts->config[TRIGGER_LOC] & 0x03;
- ts->max_touch_num = ts->config[MAX_CONTACTS_LOC] & 0x0f;
+ ts->max_touch_num = min(ts->config[MAX_CONTACTS_LOC] & 0x0f,
+ GOODIX_MAX_CONTACTS);
x_max = get_unaligned_le16(&ts->config[RESOLUTION_LOC]);
y_max = get_unaligned_le16(&ts->config[RESOLUTION_LOC + 2]);
@@ -1523,7 +1524,7 @@ static int goodix_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(goodix_pm_ops, goodix_suspend, goodix_resume);
static const struct i2c_device_id goodix_ts_id[] = {
- { "GDIX1001:00" },
+ { .name = "GDIX1001:00" },
{ }
};
MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index 62041bcca83d..58e00c314ace 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -1081,7 +1081,7 @@ static int hideep_probe(struct i2c_client *client)
}
static const struct i2c_device_id hideep_i2c_id[] = {
- { HIDEEP_I2C_NAME },
+ { .name = HIDEEP_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, hideep_i2c_id);
diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c
index 896a145ddb2b..0aa67dfacbad 100644
--- a/drivers/input/touchscreen/himax_hx83112b.c
+++ b/drivers/input/touchscreen/himax_hx83112b.c
@@ -406,8 +406,8 @@ static const struct himax_chip hx83112b_chip = {
};
static const struct i2c_device_id himax_ts_id[] = {
- { "hx83100a", (kernel_ulong_t)&hx83100a_chip },
- { "hx83112b", (kernel_ulong_t)&hx83112b_chip },
+ { .name = "hx83100a", .driver_data = (kernel_ulong_t)&hx83100a_chip },
+ { .name = "hx83112b", .driver_data = (kernel_ulong_t)&hx83112b_chip },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, himax_ts_id);
diff --git a/drivers/input/touchscreen/hynitron-cst816x.c b/drivers/input/touchscreen/hynitron-cst816x.c
index b64d7928e18f..47d9cd7412d1 100644
--- a/drivers/input/touchscreen/hynitron-cst816x.c
+++ b/drivers/input/touchscreen/hynitron-cst816x.c
@@ -226,7 +226,7 @@ static int cst816x_probe(struct i2c_client *client)
}
static const struct i2c_device_id cst816x_id[] = {
- { .name = "cst816s", 0 },
+ { .name = "cst816s" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cst816x_id);
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 3bf524a6ee20..66ada7ffbc80 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -1049,10 +1049,10 @@ static int ili210x_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ili210x_i2c_id[] = {
- { "ili210x", (long)&ili210x_chip },
- { "ili2117", (long)&ili211x_chip },
- { "ili2120", (long)&ili212x_chip },
- { "ili251x", (long)&ili251x_chip },
+ { .name = "ili210x", .driver_data = (long)&ili210x_chip },
+ { .name = "ili2117", .driver_data = (long)&ili211x_chip },
+ { .name = "ili2120", .driver_data = (long)&ili212x_chip },
+ { .name = "ili251x", .driver_data = (long)&ili251x_chip },
{ }
};
MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c
index 0706443792ba..3de0fbf8da38 100644
--- a/drivers/input/touchscreen/ilitek_ts_i2c.c
+++ b/drivers/input/touchscreen/ilitek_ts_i2c.c
@@ -639,7 +639,7 @@ static int ilitek_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(ilitek_pm_ops, ilitek_suspend, ilitek_resume);
static const struct i2c_device_id ilitek_ts_i2c_id[] = {
- { ILITEK_TS_NAME },
+ { .name = ILITEK_TS_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, ilitek_ts_i2c_id);
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index 587665e4e6fd..b9bbe8b3eab8 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -1049,9 +1049,9 @@ static int iqs5xx_probe(struct i2c_client *client)
}
static const struct i2c_device_id iqs5xx_id[] = {
- { "iqs550", 0 },
- { "iqs572", 1 },
- { "iqs525", 2 },
+ { .name = "iqs550" },
+ { .name = "iqs572" },
+ { .name = "iqs525" },
{ }
};
MODULE_DEVICE_TABLE(i2c, iqs5xx_id);
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index f39633fc8dc2..3996e4a61ff7 100644
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -213,7 +213,7 @@ static int max11801_ts_probe(struct i2c_client *client)
}
static const struct i2c_device_id max11801_ts_id[] = {
- { "max11801" },
+ { .name = "max11801" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max11801_ts_id);
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 10fccf4e5bb1..fd6c0ac301a2 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1536,7 +1536,7 @@ MODULE_DEVICE_TABLE(acpi, mip4_acpi_match);
#endif
static const struct i2c_device_id mip4_i2c_ids[] = {
- { MIP4_DEVICE_NAME },
+ { .name = MIP4_DEVICE_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids);
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
index 993d945dcd23..9d221e340404 100644
--- a/drivers/input/touchscreen/migor_ts.c
+++ b/drivers/input/touchscreen/migor_ts.c
@@ -211,7 +211,7 @@ static int migor_ts_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(migor_ts_pm, migor_ts_suspend, migor_ts_resume);
static const struct i2c_device_id migor_ts_id[] = {
- { "migor_ts" },
+ { .name = "migor_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, migor_ts_id);
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index af462086a65c..53ad35d61d47 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -217,7 +217,9 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
struct mms114_data *data = dev_id;
struct i2c_client *client = data->client;
struct mms114_touch touch[MMS114_MAX_TOUCH];
+ struct mms114_touch *t;
int packet_size;
+ int event_size;
int touch_size;
int index;
int error;
@@ -226,11 +228,19 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
if (packet_size <= 0)
goto out;
+ if (packet_size > sizeof(touch)) {
+ dev_err(&client->dev, "Invalid packet size %d (max %zu)\n",
+ packet_size, sizeof(touch));
+ goto out;
+ }
+
/* MMS136 has slightly different event size */
if (data->type == TYPE_MMS134S || data->type == TYPE_MMS136)
- touch_size = packet_size / MMS136_EVENT_SIZE;
+ event_size = MMS136_EVENT_SIZE;
else
- touch_size = packet_size / MMS114_EVENT_SIZE;
+ event_size = MMS114_EVENT_SIZE;
+
+ touch_size = packet_size / event_size;
error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size,
(u8 *)touch);
@@ -238,18 +248,20 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
goto out;
for (index = 0; index < touch_size; index++) {
- switch (touch[index].type) {
+ t = (struct mms114_touch *)((u8 *)touch + index * event_size);
+
+ switch (t->type) {
case MMS114_TYPE_TOUCHSCREEN:
- mms114_process_mt(data, touch + index);
+ mms114_process_mt(data, t);
break;
case MMS114_TYPE_TOUCHKEY:
- mms114_process_touchkey(data, touch + index);
+ mms114_process_touchkey(data, t);
break;
default:
dev_err(&client->dev, "Wrong touch type (%d)\n",
- touch[index].type);
+ t->type);
break;
}
}
@@ -667,7 +679,7 @@ static int mms114_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume);
static const struct i2c_device_id mms114_id[] = {
- { "mms114" },
+ { .name = "mms114" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mms114_id);
diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
index 708bfb933ddd..0f771f681952 100644
--- a/drivers/input/touchscreen/novatek-nvt-ts.c
+++ b/drivers/input/touchscreen/novatek-nvt-ts.c
@@ -326,8 +326,8 @@ static const struct of_device_id nvt_ts_of_match[] = {
MODULE_DEVICE_TABLE(of, nvt_ts_of_match);
static const struct i2c_device_id nvt_ts_i2c_id[] = {
- { "nt11205-ts", (unsigned long) &nvt_nt11205_ts_data },
- { "nt36672a-ts", (unsigned long) &nvt_nt36672a_ts_data },
+ { .name = "nt11205-ts", .driver_data = (unsigned long)&nvt_nt11205_ts_data },
+ { .name = "nt36672a-ts", .driver_data = (unsigned long)&nvt_nt36672a_ts_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, nvt_ts_i2c_id);
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
deleted file mode 100644
index 7b89eb74b9de..000000000000
--- a/drivers/input/touchscreen/pcap_ts.c
+++ /dev/null
@@ -1,252 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for Motorola PCAP2 touchscreen as found in the EZX phone platform.
- *
- * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
- * Copyright (C) 2009 Daniel Ribeiro <drwyrm@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/pm.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/mfd/ezx-pcap.h>
-
-struct pcap_ts {
- struct pcap_chip *pcap;
- struct input_dev *input;
- struct delayed_work work;
- u16 x, y;
- u16 pressure;
- u8 read_state;
-};
-
-#define SAMPLE_DELAY 20 /* msecs */
-
-#define X_AXIS_MIN 0
-#define X_AXIS_MAX 1023
-#define Y_AXIS_MAX X_AXIS_MAX
-#define Y_AXIS_MIN X_AXIS_MIN
-#define PRESSURE_MAX X_AXIS_MAX
-#define PRESSURE_MIN X_AXIS_MIN
-
-static void pcap_ts_read_xy(void *data, u16 res[2])
-{
- struct pcap_ts *pcap_ts = data;
-
- switch (pcap_ts->read_state) {
- case PCAP_ADC_TS_M_PRESSURE:
- /* pressure reading is unreliable */
- if (res[0] > PRESSURE_MIN && res[0] < PRESSURE_MAX)
- pcap_ts->pressure = res[0];
- pcap_ts->read_state = PCAP_ADC_TS_M_XY;
- schedule_delayed_work(&pcap_ts->work, 0);
- break;
- case PCAP_ADC_TS_M_XY:
- pcap_ts->y = res[0];
- pcap_ts->x = res[1];
- if (pcap_ts->x <= X_AXIS_MIN || pcap_ts->x >= X_AXIS_MAX ||
- pcap_ts->y <= Y_AXIS_MIN || pcap_ts->y >= Y_AXIS_MAX) {
- /* pen has been released */
- input_report_abs(pcap_ts->input, ABS_PRESSURE, 0);
- input_report_key(pcap_ts->input, BTN_TOUCH, 0);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
- schedule_delayed_work(&pcap_ts->work, 0);
- } else {
- /* pen is touching the screen */
- input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
- input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
- input_report_key(pcap_ts->input, BTN_TOUCH, 1);
- input_report_abs(pcap_ts->input, ABS_PRESSURE,
- pcap_ts->pressure);
-
- /* switch back to pressure read mode */
- pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
- schedule_delayed_work(&pcap_ts->work,
- msecs_to_jiffies(SAMPLE_DELAY));
- }
- input_sync(pcap_ts->input);
- break;
- default:
- dev_warn(&pcap_ts->input->dev,
- "pcap_ts: Warning, unhandled read_state %d\n",
- pcap_ts->read_state);
- break;
- }
-}
-
-static void pcap_ts_work(struct work_struct *work)
-{
- struct delayed_work *dw = to_delayed_work(work);
- struct pcap_ts *pcap_ts = container_of(dw, struct pcap_ts, work);
- u8 ch[2];
-
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
-
- if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY)
- return;
-
- /* start adc conversion */
- ch[0] = PCAP_ADC_CH_TS_X1;
- ch[1] = PCAP_ADC_CH_TS_Y1;
- pcap_adc_async(pcap_ts->pcap, PCAP_ADC_BANK_1, 0, ch,
- pcap_ts_read_xy, pcap_ts);
-}
-
-static irqreturn_t pcap_ts_event_touch(int pirq, void *data)
-{
- struct pcap_ts *pcap_ts = data;
-
- if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY) {
- pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
- schedule_delayed_work(&pcap_ts->work, 0);
- }
- return IRQ_HANDLED;
-}
-
-static int pcap_ts_open(struct input_dev *dev)
-{
- struct pcap_ts *pcap_ts = input_get_drvdata(dev);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
- schedule_delayed_work(&pcap_ts->work, 0);
-
- return 0;
-}
-
-static void pcap_ts_close(struct input_dev *dev)
-{
- struct pcap_ts *pcap_ts = input_get_drvdata(dev);
-
- cancel_delayed_work_sync(&pcap_ts->work);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_NONTS;
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
-}
-
-static int pcap_ts_probe(struct platform_device *pdev)
-{
- struct input_dev *input_dev;
- struct pcap_ts *pcap_ts;
- int err = -ENOMEM;
-
- pcap_ts = kzalloc_obj(*pcap_ts);
- if (!pcap_ts)
- return err;
-
- pcap_ts->pcap = dev_get_drvdata(pdev->dev.parent);
- platform_set_drvdata(pdev, pcap_ts);
-
- input_dev = input_allocate_device();
- if (!input_dev)
- goto fail;
-
- INIT_DELAYED_WORK(&pcap_ts->work, pcap_ts_work);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_NONTS;
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
-
- pcap_ts->input = input_dev;
- input_set_drvdata(input_dev, pcap_ts);
-
- input_dev->name = "pcap-touchscreen";
- input_dev->phys = "pcap_ts/input0";
- input_dev->id.bustype = BUS_HOST;
- input_dev->id.vendor = 0x0001;
- input_dev->id.product = 0x0002;
- input_dev->id.version = 0x0100;
- input_dev->dev.parent = &pdev->dev;
- input_dev->open = pcap_ts_open;
- input_dev->close = pcap_ts_close;
-
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN,
- PRESSURE_MAX, 0, 0);
-
- err = input_register_device(pcap_ts->input);
- if (err)
- goto fail_allocate;
-
- err = request_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS),
- pcap_ts_event_touch, 0, "Touch Screen", pcap_ts);
- if (err)
- goto fail_register;
-
- return 0;
-
-fail_register:
- input_unregister_device(input_dev);
- goto fail;
-fail_allocate:
- input_free_device(input_dev);
-fail:
- kfree(pcap_ts);
-
- return err;
-}
-
-static void pcap_ts_remove(struct platform_device *pdev)
-{
- struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
-
- free_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS), pcap_ts);
- cancel_delayed_work_sync(&pcap_ts->work);
-
- input_unregister_device(pcap_ts->input);
-
- kfree(pcap_ts);
-}
-
-#ifdef CONFIG_PM
-static int pcap_ts_suspend(struct device *dev)
-{
- struct pcap_ts *pcap_ts = dev_get_drvdata(dev);
-
- pcap_set_ts_bits(pcap_ts->pcap, PCAP_ADC_TS_REF_LOWPWR);
- return 0;
-}
-
-static int pcap_ts_resume(struct device *dev)
-{
- struct pcap_ts *pcap_ts = dev_get_drvdata(dev);
-
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
- return 0;
-}
-
-static const struct dev_pm_ops pcap_ts_pm_ops = {
- .suspend = pcap_ts_suspend,
- .resume = pcap_ts_resume,
-};
-#define PCAP_TS_PM_OPS (&pcap_ts_pm_ops)
-#else
-#define PCAP_TS_PM_OPS NULL
-#endif
-
-static struct platform_driver pcap_ts_driver = {
- .probe = pcap_ts_probe,
- .remove = pcap_ts_remove,
- .driver = {
- .name = "pcap-ts",
- .pm = PCAP_TS_PM_OPS,
- },
-};
-module_platform_driver(pcap_ts_driver);
-
-MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
-MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pcap_ts");
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index c6b3615c8775..1ca5920846df 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -580,8 +580,8 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
};
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
- { "pixcir_ts", (unsigned long) &pixcir_ts_data },
- { "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
+ { .name = "pixcir_ts", .driver_data = (unsigned long)&pixcir_ts_data },
+ { .name = "pixcir_tangoc", .driver_data = (unsigned long)&pixcir_tangoc_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index f2d33ad86fd2..0256055abcef 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -1219,8 +1219,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops,
raydium_i2c_suspend, raydium_i2c_resume);
static const struct i2c_device_id raydium_i2c_id[] = {
- { "raydium_i2c" },
- { "rm32380" },
+ { .name = "raydium_i2c" },
+ { .name = "rm32380" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, raydium_i2c_id);
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index 295d8d75ba32..a5c06b7423c0 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -1144,7 +1144,7 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id rohm_bu21023_i2c_id[] = {
- { BU21023_NAME },
+ { .name = BU21023_NAME },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, rohm_bu21023_i2c_id);
diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index e1518a75a51b..0f24a9b73063 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(of, s6sy761_of_match);
#endif
static const struct i2c_device_id s6sy761_id[] = {
- { "s6sy761" },
+ { .name = "s6sy761" },
{ }
};
MODULE_DEVICE_TABLE(i2c, s6sy761_id);
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
index 5ccc96764742..44d7141103f4 100644
--- a/drivers/input/touchscreen/silead.c
+++ b/drivers/input/touchscreen/silead.c
@@ -776,12 +776,12 @@ static int silead_ts_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(silead_ts_pm, silead_ts_suspend, silead_ts_resume);
static const struct i2c_device_id silead_ts_id[] = {
- { "gsl1680" },
- { "gsl1688" },
- { "gsl3670" },
- { "gsl3675" },
- { "gsl3692" },
- { "mssl1680" },
+ { .name = "gsl1680" },
+ { .name = "gsl1688" },
+ { .name = "gsl3670" },
+ { .name = "gsl3675" },
+ { .name = "gsl3692" },
+ { .name = "mssl1680" },
{ }
};
MODULE_DEVICE_TABLE(i2c, silead_ts_id);
diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c
index a625f2ad809d..4fa93cd31ee4 100644
--- a/drivers/input/touchscreen/sis_i2c.c
+++ b/drivers/input/touchscreen/sis_i2c.c
@@ -374,8 +374,8 @@ MODULE_DEVICE_TABLE(of, sis_ts_dt_ids);
#endif
static const struct i2c_device_id sis_ts_id[] = {
- { SIS_I2C_NAME },
- { "9200-ts" },
+ { .name = SIS_I2C_NAME },
+ { .name = "9200-ts" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, sis_ts_id);
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 9b266927b7fe..c2dcfce5003d 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -453,8 +453,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops,
st1232_ts_suspend, st1232_ts_resume);
static const struct i2c_device_id st1232_ts_id[] = {
- { ST1232_TS_NAME, (unsigned long)&st1232_chip_info },
- { ST1633_TS_NAME, (unsigned long)&st1633_chip_info },
+ { .name = ST1232_TS_NAME, .driver_data = (unsigned long)&st1232_chip_info },
+ { .name = ST1633_TS_NAME, .driver_data = (unsigned long)&st1633_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 8af87d0b6eb6..972687797f82 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -5,6 +5,7 @@
// Copyright (c) 2017 Andi Shyti <andi@etezian.org>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
@@ -69,20 +70,21 @@
#define STMFTS_MAX_FINGERS 10
#define STMFTS_DEV_NAME "stmfts"
-enum stmfts_regulators {
- STMFTS_REGULATOR_VDD,
- STMFTS_REGULATOR_AVDD,
+static const struct regulator_bulk_data stmfts_supplies[] = {
+ { .supply = "vdd" },
+ { .supply = "avdd" },
};
struct stmfts_data {
struct i2c_client *client;
struct input_dev *input;
+ struct gpio_desc *reset_gpio;
struct led_classdev led_cdev;
struct mutex mutex;
struct touchscreen_properties prop;
- struct regulator_bulk_data regulators[2];
+ struct regulator_bulk_data *supplies;
/*
* Presence of ledvdd will be used also to check
@@ -107,7 +109,7 @@ struct stmfts_data {
};
static int stmfts_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness value)
+ enum led_brightness value)
{
struct stmfts_data *sdata = container_of(led_cdev,
struct stmfts_data, led_cdev);
@@ -250,7 +252,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
switch (event[0]) {
-
case STMFTS_EV_CONTROLLER_READY:
case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY:
case STMFTS_EV_STATUS:
@@ -263,7 +264,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
}
switch (event[0] & STMFTS_MASK_EVENT_ID) {
-
case STMFTS_EV_MULTI_TOUCH_ENTER:
case STMFTS_EV_MULTI_TOUCH_MOTION:
stmfts_report_contact_event(sdata, event);
@@ -285,9 +285,9 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
case STMFTS_EV_ERROR:
dev_warn(&sdata->client->dev,
- "error code: 0x%x%x%x%x%x%x",
- event[6], event[5], event[4],
- event[3], event[2], event[1]);
+ "error code: 0x%x%x%x%x%x%x",
+ event[6], event[5], event[4],
+ event[3], event[2], event[1]);
break;
default:
@@ -404,7 +404,7 @@ static void stmfts_input_close(struct input_dev *dev)
}
static ssize_t stmfts_sysfs_chip_id(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -412,7 +412,8 @@ static ssize_t stmfts_sysfs_chip_id(struct device *dev,
}
static ssize_t stmfts_sysfs_chip_version(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -420,7 +421,7 @@ static ssize_t stmfts_sysfs_chip_version(struct device *dev,
}
static ssize_t stmfts_sysfs_fw_ver(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -428,7 +429,7 @@ static ssize_t stmfts_sysfs_fw_ver(struct device *dev,
}
static ssize_t stmfts_sysfs_config_id(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -436,7 +437,8 @@ static ssize_t stmfts_sysfs_config_id(struct device *dev,
}
static ssize_t stmfts_sysfs_config_version(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -444,7 +446,8 @@ static ssize_t stmfts_sysfs_config_version(struct device *dev,
}
static ssize_t stmfts_sysfs_read_status(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
u8 status[4];
@@ -459,7 +462,8 @@ static ssize_t stmfts_sysfs_read_status(struct device *dev,
}
static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -467,8 +471,8 @@ static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev,
}
static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
+ struct device_attribute *attr,
+ const char *buf, size_t len)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
unsigned long value;
@@ -485,8 +489,8 @@ static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
if (hover != sdata->hover_enabled) {
if (sdata->running) {
err = i2c_smbus_write_byte(sdata->client,
- value ? STMFTS_SS_HOVER_SENSE_ON :
- STMFTS_SS_HOVER_SENSE_OFF);
+ value ? STMFTS_SS_HOVER_SENSE_ON :
+ STMFTS_SS_HOVER_SENSE_OFF);
if (err)
return err;
}
@@ -518,22 +522,11 @@ static struct attribute *stmfts_sysfs_attrs[] = {
};
ATTRIBUTE_GROUPS(stmfts_sysfs);
-static int stmfts_power_on(struct stmfts_data *sdata)
+static int stmfts_read_system_info(struct stmfts_data *sdata)
{
int err;
u8 reg[8];
- err = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
- if (err)
- return err;
-
- /*
- * The datasheet does not specify the power on time, but considering
- * that the reset time is < 10ms, I sleep 20ms to be sure
- */
- msleep(20);
-
err = i2c_smbus_read_i2c_block_data(sdata->client, STMFTS_READ_INFO,
sizeof(reg), reg);
if (err < 0)
@@ -547,9 +540,21 @@ static int stmfts_power_on(struct stmfts_data *sdata)
sdata->config_id = reg[4];
sdata->config_ver = reg[5];
- enable_irq(sdata->client->irq);
+ return 0;
+}
+static void stmfts_reset(struct stmfts_data *sdata)
+{
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+ msleep(20);
+
+ gpiod_set_value_cansleep(sdata->reset_gpio, 0);
msleep(50);
+}
+
+static int stmfts_configure(struct stmfts_data *sdata)
+{
+ int err;
err = stmfts_command(sdata, STMFTS_SYSTEM_RESET);
if (err)
@@ -575,13 +580,52 @@ static int stmfts_power_on(struct stmfts_data *sdata)
if (err)
return err;
+ return 0;
+}
+
+static int stmfts_power_on(struct stmfts_data *sdata)
+{
+ int err;
+
+ err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
+ if (err)
+ return err;
+
+ /*
+ * The datasheet does not specify the power on time, but considering
+ * that the reset time is < 10ms, I sleep 20ms to be sure
+ */
+ msleep(20);
+
+ if (sdata->reset_gpio)
+ stmfts_reset(sdata);
+
+ err = stmfts_read_system_info(sdata);
+ if (err)
+ goto err_disable_regulators;
+
+ enable_irq(sdata->client->irq);
+
+ msleep(50);
+
+ err = stmfts_configure(sdata);
+ if (err)
+ goto err_disable_irq;
+
/*
* At this point no one is using the touchscreen
* and I don't really care about the return value
*/
- (void) i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
+ (void)i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
return 0;
+
+err_disable_irq:
+ disable_irq(sdata->client->irq);
+err_disable_regulators:
+ regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies), sdata->supplies);
+ return err;
}
static void stmfts_power_off(void *data)
@@ -589,8 +633,11 @@ static void stmfts_power_off(void *data)
struct stmfts_data *sdata = data;
disable_irq(sdata->client->irq);
- regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
+
+ if (sdata->reset_gpio)
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+
+ regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies), sdata->supplies);
}
static int stmfts_enable_led(struct stmfts_data *sdata)
@@ -619,6 +666,7 @@ static int stmfts_enable_led(struct stmfts_data *sdata)
static int stmfts_probe(struct i2c_client *client)
{
+ struct device *dev = &client->dev;
int err;
struct stmfts_data *sdata;
@@ -627,7 +675,7 @@ static int stmfts_probe(struct i2c_client *client)
I2C_FUNC_SMBUS_I2C_BLOCK))
return -ENODEV;
- sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL);
+ sdata = devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL);
if (!sdata)
return -ENOMEM;
@@ -637,15 +685,19 @@ static int stmfts_probe(struct i2c_client *client)
mutex_init(&sdata->mutex);
init_completion(&sdata->cmd_done);
- sdata->regulators[STMFTS_REGULATOR_VDD].supply = "vdd";
- sdata->regulators[STMFTS_REGULATOR_AVDD].supply = "avdd";
- err = devm_regulator_bulk_get(&client->dev,
- ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
+ err = devm_regulator_bulk_get_const(dev,
+ ARRAY_SIZE(stmfts_supplies),
+ stmfts_supplies,
+ &sdata->supplies);
if (err)
return err;
- sdata->input = devm_input_allocate_device(&client->dev);
+ sdata->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(sdata->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(sdata->reset_gpio),
+ "Failed to get GPIO 'reset'\n");
+
+ sdata->input = devm_input_allocate_device(dev);
if (!sdata->input)
return -ENOMEM;
@@ -664,8 +716,7 @@ static int stmfts_probe(struct i2c_client *client)
input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
- sdata->use_key = device_property_read_bool(&client->dev,
- "touch-key-connected");
+ sdata->use_key = device_property_read_bool(dev, "touch-key-connected");
if (sdata->use_key) {
input_set_capability(sdata->input, EV_KEY, KEY_MENU);
input_set_capability(sdata->input, EV_KEY, KEY_BACK);
@@ -685,20 +736,20 @@ static int stmfts_probe(struct i2c_client *client)
* interrupts. To be on the safe side it's better to not enable
* the interrupts during their request.
*/
- err = devm_request_threaded_irq(&client->dev, client->irq,
+ err = devm_request_threaded_irq(dev, client->irq,
NULL, stmfts_irq_handler,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"stmfts_irq", sdata);
if (err)
return err;
- dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n");
+ dev_dbg(dev, "initializing ST-Microelectronics FTS...\n");
err = stmfts_power_on(sdata);
if (err)
return err;
- err = devm_add_action_or_reset(&client->dev, stmfts_power_off, sdata);
+ err = devm_add_action_or_reset(dev, stmfts_power_off, sdata);
if (err)
return err;
@@ -715,13 +766,13 @@ static int stmfts_probe(struct i2c_client *client)
* without LEDs. The ledvdd regulator pointer will be
* used as a flag.
*/
- dev_warn(&client->dev, "unable to use touchkey leds\n");
+ dev_warn(dev, "unable to use touchkey leds\n");
sdata->ledvdd = NULL;
}
}
- pm_runtime_enable(&client->dev);
- device_enable_async_suspend(&client->dev);
+ pm_runtime_enable(dev);
+ device_enable_async_suspend(dev);
return 0;
}
@@ -746,9 +797,10 @@ static int stmfts_runtime_suspend(struct device *dev)
static int stmfts_runtime_resume(struct device *dev)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
+ struct i2c_client *client = sdata->client;
int ret;
- ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT);
+ ret = i2c_smbus_write_byte(client, STMFTS_SLEEP_OUT);
if (ret)
dev_err(dev, "failed to resume device: %d\n", ret);
@@ -785,7 +837,7 @@ MODULE_DEVICE_TABLE(of, stmfts_of_match);
#endif
static const struct i2c_device_id stmfts_id[] = {
- { "stmfts" },
+ { .name = "stmfts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, stmfts_id);
@@ -807,4 +859,4 @@ module_i2c_driver(stmfts_driver);
MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index 099fd88e65d8..3ed33378dfcd 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -63,12 +63,15 @@ static irqreturn_t tw_interrupt(struct serio *serio,
if (data) { /* touch */
tw->touched = 1;
tw->data[tw->idx++] = data;
- /* verify length and that the two Y's are the same */
- if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
- input_report_abs(dev, ABS_X, tw->data[0]);
- input_report_abs(dev, ABS_Y, tw->data[1]);
- input_report_key(dev, BTN_TOUCH, 1);
- input_sync(dev);
+ /* a full packet ends the accumulation, valid or not */
+ if (tw->idx == TW_LENGTH) {
+ /* report only if the two Y's are the same */
+ if (tw->data[1] == tw->data[2]) {
+ input_report_abs(dev, ABS_X, tw->data[0]);
+ input_report_abs(dev, ABS_Y, tw->data[1]);
+ input_report_key(dev, BTN_TOUCH, 1);
+ input_sync(dev);
+ }
tw->idx = 0;
}
} else if (tw->touched) { /* untouch */
diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c
index 787f2caf4f73..130aeb735b65 100644
--- a/drivers/input/touchscreen/tsc2004.c
+++ b/drivers/input/touchscreen/tsc2004.c
@@ -43,7 +43,7 @@ static int tsc2004_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tsc2004_idtable[] = {
- { "tsc2004" },
+ { .name = "tsc2004" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tsc2004_idtable);
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
index 524f14eb3da2..4a775c5df0ea 100644
--- a/drivers/input/touchscreen/tsc2007_core.c
+++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -61,10 +61,8 @@ static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc)
/* turn y+ off, x- on; we'll use formula #1 */
tc->z1 = tsc2007_xfer(tsc, READ_Z1);
- tc->z2 = tsc2007_xfer(tsc, READ_Z2);
-
- /* Prepare for next touch reading - power down ADC, enable PENIRQ */
- tsc2007_xfer(tsc, PWRDOWN);
+ /* Read Z2 and power down ADC after A/D conversion, enable PENIRQ */
+ tc->z2 = tsc2007_xfer(tsc, (TSC2007_POWER_OFF_IRQ_EN | TSC2007_MEASURE_Z2));
}
u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc)
@@ -407,7 +405,7 @@ static int tsc2007_probe(struct i2c_client *client)
}
static const struct i2c_device_id tsc2007_idtable[] = {
- { "tsc2007" },
+ { .name = "tsc2007" },
{ }
};
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index fd97a83f5664..dd7c2a8a831b 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -253,7 +253,7 @@ static int wacom_i2c_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume);
static const struct i2c_device_id wacom_i2c_id[] = {
- { "WAC_I2C_EMR" },
+ { .name = "WAC_I2C_EMR" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wacom_i2c_id);
diff --git a/drivers/input/touchscreen/wacom_w9000.c b/drivers/input/touchscreen/wacom_w9000.c
new file mode 100644
index 000000000000..4a2629a54167
--- /dev/null
+++ b/drivers/input/touchscreen/wacom_w9000.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Wacom W9000-series penabled I2C touchscreen driver
+ *
+ * Copyright (c) 2026 Hendrik Noack <hendrik-noack@gmx.de>
+ *
+ * Partially based on vendor driver:
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/lockdep.h>
+#include <linux/regulator/consumer.h>
+#include <linux/unaligned.h>
+
+/* Some chips have flaky firmware that requires many retries before responding. */
+#define CMD_QUERY_RETRIES 8
+
+/* Message length */
+#define CMD_QUERY_NUM_MAX 9
+#define MSG_COORD_NUM_MAX 12
+
+/* Commands */
+#define CMD_QUERY 0x2a
+
+struct wacom_w9000_variant {
+ const u8 cmd_query_num;
+ const u8 msg_coord_num;
+ const char *name;
+};
+
+struct wacom_w9000_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct wacom_w9000_variant *variant;
+ u16 fw_version;
+
+ struct touchscreen_properties prop;
+ u16 max_pressure;
+
+ struct regulator *regulator;
+
+ struct gpio_desc *flash_mode_gpio;
+ struct gpio_desc *reset_gpio;
+
+ unsigned int irq;
+
+ bool pen_proximity;
+};
+
+static int wacom_w9000_read(struct i2c_client *client, u8 command, u8 len, u8 *data)
+{
+ int error, res;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .buf = &command,
+ .len = sizeof(command),
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .buf = data,
+ .len = len,
+ }
+ };
+
+ res = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ if (res != ARRAY_SIZE(msg)) {
+ error = res < 0 ? res : -EIO;
+ dev_err(&client->dev, "%s: i2c transfer failed: %d (%d)\n",
+ __func__, error, res);
+ return error;
+ }
+
+ return 0;
+}
+
+static int wacom_w9000_query(struct wacom_w9000_data *wacom_data)
+{
+ struct i2c_client *client = wacom_data->client;
+ struct device *dev = &wacom_data->client->dev;
+ u8 data[CMD_QUERY_NUM_MAX];
+ int retry;
+ int error;
+
+ for (retry = 0; retry < CMD_QUERY_RETRIES; retry++) {
+ error = wacom_w9000_read(client, CMD_QUERY,
+ wacom_data->variant->cmd_query_num,
+ data);
+ if (!error && data[0] == 0x0f)
+ break;
+ }
+
+ if (error)
+ return error;
+
+ if (data[0] != 0x0f)
+ return -EIO;
+
+ dev_dbg(dev, "query: %*ph, %d\n",
+ wacom_data->variant->cmd_query_num, data, retry);
+
+ wacom_data->prop.max_x = get_unaligned_be16(&data[1]);
+ wacom_data->prop.max_y = get_unaligned_be16(&data[3]);
+ wacom_data->max_pressure = get_unaligned_be16(&data[5]);
+ wacom_data->fw_version = get_unaligned_be16(&data[7]);
+
+ dev_dbg(dev, "max_x:%d, max_y:%d, max_pressure:%d, fw:%#x\n",
+ wacom_data->prop.max_x, wacom_data->prop.max_y,
+ wacom_data->max_pressure, wacom_data->fw_version);
+
+ return 0;
+}
+
+static int wacom_w9000_power_on(struct wacom_w9000_data *wacom_data)
+{
+ int error;
+
+ lockdep_assert_held(&wacom_data->input_dev->mutex);
+
+ error = regulator_enable(wacom_data->regulator);
+ if (error) {
+ dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n", error);
+ return error;
+ }
+
+ msleep(200);
+
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 0);
+ enable_irq(wacom_data->irq);
+
+ return 0;
+}
+
+static int wacom_w9000_power_off(struct wacom_w9000_data *wacom_data)
+{
+ lockdep_assert_held(&wacom_data->input_dev->mutex);
+
+ disable_irq(wacom_data->irq);
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 1);
+ regulator_disable(wacom_data->regulator);
+
+ return 0;
+}
+
+static void wacom_w9000_coord(struct wacom_w9000_data *wacom_data)
+{
+ struct i2c_client *client = wacom_data->client;
+ struct device *dev = &wacom_data->client->dev;
+ u8 data[MSG_COORD_NUM_MAX];
+ bool touch, rubber, side_button;
+ u16 x, y, pressure;
+ u8 distance = 0;
+ int error;
+
+ error = i2c_master_recv(client, data, wacom_data->variant->msg_coord_num);
+ if (error != wacom_data->variant->msg_coord_num) {
+ if (error >= 0)
+ error = -EIO;
+ dev_err_ratelimited(dev, "%s: i2c receive failed (%d)\n", __func__, error);
+ return;
+ }
+
+ dev_dbg(dev, "data: %*ph\n", wacom_data->variant->msg_coord_num, data);
+
+ if (data[0] & BIT(7)) {
+ wacom_data->pen_proximity = true;
+
+ touch = !!(data[0] & BIT(4));
+ side_button = !!(data[0] & BIT(5));
+ rubber = !!(data[0] & BIT(6));
+
+ x = get_unaligned_be16(&data[1]);
+ y = get_unaligned_be16(&data[3]);
+ pressure = get_unaligned_be16(&data[5]);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ distance = data[7];
+
+ if (x > wacom_data->prop.max_x || y > wacom_data->prop.max_y) {
+ dev_warn_ratelimited(dev, "Coordinates out of range x=%d, y=%d\n", x, y);
+ return;
+ }
+
+ if (pressure > wacom_data->max_pressure) {
+ dev_warn_ratelimited(dev, "Pressure out of range %d\n", pressure);
+ return;
+ }
+
+ touchscreen_report_pos(wacom_data->input_dev, &wacom_data->prop, x, y, false);
+ input_report_abs(wacom_data->input_dev, ABS_PRESSURE, pressure);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ input_report_abs(wacom_data->input_dev, ABS_DISTANCE, distance);
+
+ input_report_key(wacom_data->input_dev, BTN_STYLUS, side_button);
+ input_report_key(wacom_data->input_dev, BTN_TOUCH, touch);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, !rubber);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, rubber);
+ input_sync(wacom_data->input_dev);
+ } else if (wacom_data->pen_proximity) {
+ input_report_abs(wacom_data->input_dev, ABS_PRESSURE, 0);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ input_report_abs(wacom_data->input_dev, ABS_DISTANCE, 255);
+
+ input_report_key(wacom_data->input_dev, BTN_STYLUS, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOUCH, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, 0);
+ input_sync(wacom_data->input_dev);
+
+ wacom_data->pen_proximity = false;
+ }
+}
+
+static irqreturn_t wacom_w9000_interrupt(int irq, void *dev_id)
+{
+ struct wacom_w9000_data *wacom_data = dev_id;
+
+ wacom_w9000_coord(wacom_data);
+
+ return IRQ_HANDLED;
+}
+
+static int wacom_w9000_open(struct input_dev *dev)
+{
+ struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
+
+ return wacom_w9000_power_on(wacom_data);
+}
+
+static void wacom_w9000_close(struct input_dev *dev)
+{
+ struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
+
+ wacom_w9000_power_off(wacom_data);
+}
+
+static int wacom_w9000_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct wacom_w9000_data *wacom_data;
+ struct input_dev *input_dev;
+ int error;
+ u32 val;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(dev, "i2c_check_functionality error\n");
+ return -EIO;
+ }
+
+ wacom_data = devm_kzalloc(dev, sizeof(*wacom_data), GFP_KERNEL);
+ if (!wacom_data)
+ return -ENOMEM;
+
+ wacom_data->variant = i2c_get_match_data(client);
+ if (!wacom_data->variant) {
+ dev_err(dev, "No i2c match_data available\n");
+ return -EINVAL;
+ }
+
+ if (wacom_data->variant->cmd_query_num > CMD_QUERY_NUM_MAX ||
+ wacom_data->variant->msg_coord_num > MSG_COORD_NUM_MAX) {
+ dev_err(dev, "Length of message for %s exceeds the maximum\n",
+ wacom_data->variant->name);
+ return -EINVAL;
+ }
+
+ if (wacom_data->variant->msg_coord_num < 7) {
+ dev_err(dev, "Length of coordinates message for %s too short\n",
+ wacom_data->variant->name);
+ return -EINVAL;
+ }
+
+ wacom_data->client = client;
+ wacom_data->irq = client->irq;
+ i2c_set_clientdata(client, wacom_data);
+
+ wacom_data->regulator = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(wacom_data->regulator))
+ return dev_err_probe(dev, PTR_ERR(wacom_data->regulator),
+ "Failed to get regulators\n");
+
+ wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
+ if (IS_ERR(wacom_data->flash_mode_gpio))
+ return dev_err_probe(dev, PTR_ERR(wacom_data->flash_mode_gpio),
+ "Failed to get flash-mode gpio\n");
+
+ wacom_data->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(wacom_data->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(wacom_data->reset_gpio),
+ "Failed to get reset gpio\n");
+
+ error = regulator_enable(wacom_data->regulator);
+ if (error)
+ return dev_err_probe(dev, error, "Failed to enable regulators\n");
+
+ msleep(200);
+
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 0);
+
+ error = wacom_w9000_query(wacom_data);
+
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 1);
+ regulator_disable(wacom_data->regulator);
+
+ if (error)
+ return dev_err_probe(dev, error, "Failed to query\n");
+
+ error = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
+ if (error)
+ return dev_err_probe(dev, error, "Failed to register interrupt\n");
+
+ input_dev = devm_input_allocate_device(dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ wacom_data->input_dev = input_dev;
+ input_set_drvdata(input_dev, wacom_data);
+
+ input_dev->name = wacom_data->variant->name;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->id.vendor = 0x56a;
+ input_dev->id.version = wacom_data->fw_version;
+ input_dev->open = wacom_w9000_open;
+ input_dev->close = wacom_w9000_close;
+
+ input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
+ input_set_capability(input_dev, EV_KEY, BTN_TOOL_PEN);
+ input_set_capability(input_dev, EV_KEY, BTN_TOOL_RUBBER);
+ input_set_capability(input_dev, EV_KEY, BTN_STYLUS);
+
+ input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
+
+ dev_info(dev, "%s size X%uY%u\n", wacom_data->variant->name,
+ wacom_data->prop.max_x, wacom_data->prop.max_y);
+
+ error = device_property_read_u32(dev, "touchscreen-x-mm", &val);
+ if (!error && val)
+ input_abs_set_res(input_dev, wacom_data->prop.swap_x_y ? ABS_Y : ABS_X,
+ wacom_data->prop.max_x / val);
+ error = device_property_read_u32(dev, "touchscreen-y-mm", &val);
+ if (!error && val)
+ input_abs_set_res(input_dev, wacom_data->prop.swap_x_y ? ABS_X : ABS_Y,
+ wacom_data->prop.max_y / val);
+
+ error = input_register_device(wacom_data->input_dev);
+ if (error)
+ return dev_err_probe(dev, error, "Failed to register input device\n");
+
+ return 0;
+}
+
+static int wacom_w9000_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
+
+ guard(mutex)(&wacom_data->input_dev->mutex);
+
+ if (input_device_enabled(wacom_data->input_dev))
+ return wacom_w9000_power_off(wacom_data);
+
+ return 0;
+}
+
+static int wacom_w9000_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
+
+ guard(mutex)(&wacom_data->input_dev->mutex);
+
+ if (input_device_enabled(wacom_data->input_dev))
+ return wacom_w9000_power_on(wacom_data);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(wacom_w9000_pm, wacom_w9000_suspend, wacom_w9000_resume);
+
+static const struct wacom_w9000_variant w9002 = {
+ .cmd_query_num = 9,
+ .msg_coord_num = 7,
+ .name = "Wacom W9002 Digitizer",
+};
+
+static const struct wacom_w9000_variant w9007a_lt03 = {
+ .cmd_query_num = 9,
+ .msg_coord_num = 8,
+ .name = "Wacom W9007A LT03 Digitizer",
+};
+
+static const struct wacom_w9000_variant w9007a_v1 = {
+ .cmd_query_num = 9,
+ .msg_coord_num = 12,
+ .name = "Wacom W9007A V1 Digitizer",
+};
+
+static const struct of_device_id wacom_w9000_of_match[] = {
+ { .compatible = "wacom,w9002", .data = &w9002 },
+ { .compatible = "wacom,w9007a-lt03", .data = &w9007a_lt03, },
+ { .compatible = "wacom,w9007a-v1", .data = &w9007a_v1, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);
+
+static const struct i2c_device_id wacom_w9000_id[] = {
+ { .name = "w9002", .driver_data = (kernel_ulong_t)&w9002 },
+ { .name = "w9007a-lt03", .driver_data = (kernel_ulong_t)&w9007a_lt03 },
+ { .name = "w9007a-v1", .driver_data = (kernel_ulong_t)&w9007a_v1 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wacom_w9000_id);
+
+static struct i2c_driver wacom_w9000_driver = {
+ .driver = {
+ .name = "wacom_w9000",
+ .of_match_table = wacom_w9000_of_match,
+ .pm = pm_sleep_ptr(&wacom_w9000_pm),
+ },
+ .probe = wacom_w9000_probe,
+ .id_table = wacom_w9000_id,
+};
+module_i2c_driver(wacom_w9000_driver);
+
+MODULE_AUTHOR("Hendrik Noack <hendrik-noack@gmx.de>");
+MODULE_DESCRIPTION("Wacom W9000-series penabled touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c
index bdaabb14dc8c..1af309252092 100644
--- a/drivers/input/touchscreen/wdt87xx_i2c.c
+++ b/drivers/input/touchscreen/wdt87xx_i2c.c
@@ -1140,7 +1140,7 @@ static int wdt87xx_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume);
static const struct i2c_device_id wdt87xx_dev_id[] = {
- { WDT87XX_NAME },
+ { .name = WDT87XX_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id);
diff --git a/drivers/input/touchscreen/zet6223.c b/drivers/input/touchscreen/zet6223.c
index 943634ba9cd9..a341142f3708 100644
--- a/drivers/input/touchscreen/zet6223.c
+++ b/drivers/input/touchscreen/zet6223.c
@@ -236,7 +236,7 @@ static const struct of_device_id zet6223_of_match[] = {
MODULE_DEVICE_TABLE(of, zet6223_of_match);
static const struct i2c_device_id zet6223_id[] = {
- { "zet6223" },
+ { .name = "zet6223" },
{ }
};
MODULE_DEVICE_TABLE(i2c, zet6223_id);
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index a360749fa076..4bfc9560bd6c 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -831,7 +831,7 @@ static int zforce_probe(struct i2c_client *client)
}
static const struct i2c_device_id zforce_idtable[] = {
- { "zforce-ts" },
+ { .name = "zforce-ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, zforce_idtable);
diff --git a/include/linux/input.h b/include/linux/input.h
index 06ca62328db1..3022bb730898 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -543,6 +543,8 @@ extern const struct class input_class;
* @set_autocenter: Called to auto-center device
* @destroy: called by input core when parent input device is being
* destroyed
+ * @stop: called by input core when parent input device is being
+ * unregistered
* @private: driver-specific data, will be freed automatically
* @ffbit: bitmap of force feedback capabilities truly supported by
* device (not emulated like ones in input_dev->ffbit)
@@ -571,6 +573,7 @@ struct ff_device {
void (*set_autocenter)(struct input_dev *dev, u16 magnitude);
void (*destroy)(struct ff_device *);
+ void (*stop)(struct ff_device *);
void *private;
diff --git a/include/uapi/linux/userio.h b/include/uapi/linux/userio.h
index 74c9951d2cd0..550c7465af1f 100644
--- a/include/uapi/linux/userio.h
+++ b/include/uapi/linux/userio.h
@@ -2,7 +2,7 @@
/*
* userio: virtual serio device support
* Copyright (C) 2015 Red Hat
- * Copyright (C) 2015 Lyude (Stephen Chandler Paul) <cpaul@redhat.com>
+ * Copyright (C) 2015 Lyude Paul <thatslyude@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -27,7 +27,10 @@
enum userio_cmd_type {
USERIO_CMD_REGISTER = 0,
USERIO_CMD_SET_PORT_TYPE = 1,
- USERIO_CMD_SEND_INTERRUPT = 2
+ USERIO_CMD_SEND_INTERRUPT = 2,
+ USERIO_CMD_SET_PORT_EXTRA = 3,
+ USERIO_CMD_SET_PORT_ID = 4,
+ USERIO_CMD_SET_PORT_PROTO = 5,
};
/*