summaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-10 23:24:10 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-10 23:24:10 -0700
commit597473720f4dc69749542bfcfed4a927a43d935e (patch)
tree711bf773910fb93d1dd9120c633adc807685e0d8 /drivers/input
parentf0dd687815f9546860fc3ac4379d55da045942c9 (diff)
parent593fdd4fb44ef2cbf4ec53ec2c6eb60eb079bb4c (diff)
Merge branch 'next' into for-linus
Prepare input updates for 5.3 merge window.
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/joydev.c24
-rw-r--r--drivers/input/joystick/iforce/Kconfig8
-rw-r--r--drivers/input/joystick/iforce/Makefile7
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c18
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c178
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c215
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c161
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c192
-rw-r--r--drivers/input/joystick/iforce/iforce.h55
-rw-r--r--drivers/input/keyboard/davinci_keyscan.c4
-rw-r--r--drivers/input/keyboard/gpio_keys.c6
-rw-r--r--drivers/input/keyboard/gpio_keys_polled.c10
-rw-r--r--drivers/input/keyboard/imx_keypad.c4
-rw-r--r--drivers/input/keyboard/tca8418_keypad.c3
-rw-r--r--drivers/input/misc/Kconfig20
-rw-r--r--drivers/input/misc/Makefile3
-rw-r--r--drivers/input/misc/da9063_onkey.c22
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c8
-rw-r--r--drivers/input/misc/max77650-onkey.c122
-rw-r--r--drivers/input/misc/stpmic1_onkey.c198
-rw-r--r--drivers/input/mouse/elan_i2c_core.c122
-rw-r--r--drivers/input/mouse/elantech.c322
-rw-r--r--drivers/input/mouse/elantech.h8
-rw-r--r--drivers/input/rmi4/rmi_f12.c6
-rw-r--r--drivers/input/serio/gscps2.c4
-rw-r--r--drivers/input/serio/hp_sdc.c4
-rw-r--r--drivers/input/serio/olpc_apsp.c14
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c20
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c18
-rw-r--r--drivers/input/touchscreen/eeti_ts.c71
-rw-r--r--drivers/input/touchscreen/imx6ul_tsc.c8
-rw-r--r--drivers/input/touchscreen/iqs5xx.c2
-rw-r--r--drivers/input/touchscreen/raspberrypi-ts.c4
-rw-r--r--drivers/input/touchscreen/stmpe-ts.c66
34 files changed, 1138 insertions, 789 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 4c1e427dfabb..319c641edb93 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -812,6 +812,7 @@ static bool joydev_dev_is_blacklisted(struct input_dev *dev)
static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)
{
DECLARE_BITMAP(jd_scratch, KEY_CNT);
+ bool ev_match = false;
BUILD_BUG_ON(ABS_CNT > KEY_CNT || EV_CNT > KEY_CNT);
@@ -830,17 +831,36 @@ static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)
* considered to be an absolute mouse if the following is
* true:
*
- * 1) Event types are exactly EV_ABS, EV_KEY and EV_SYN.
+ * 1) Event types are exactly
+ * EV_ABS, EV_KEY and EV_SYN
+ * or
+ * EV_ABS, EV_KEY, EV_SYN and EV_MSC
+ * or
+ * EV_ABS, EV_KEY, EV_SYN, EV_MSC and EV_REL.
* 2) Absolute events are exactly ABS_X and ABS_Y.
* 3) Keys are exactly BTN_LEFT, BTN_RIGHT and BTN_MIDDLE.
* 4) Device is not on "Amiga" bus.
*/
bitmap_zero(jd_scratch, EV_CNT);
+ /* VMware VMMouse, HP ILO2 */
__set_bit(EV_ABS, jd_scratch);
__set_bit(EV_KEY, jd_scratch);
__set_bit(EV_SYN, jd_scratch);
- if (!bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ if (bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ ev_match = true;
+
+ /* HP ILO2, AMI BMC firmware */
+ __set_bit(EV_MSC, jd_scratch);
+ if (bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ ev_match = true;
+
+ /* VMware Virtual USB Mouse, QEMU USB Tablet, ATEN BMC firmware */
+ __set_bit(EV_REL, jd_scratch);
+ if (bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ ev_match = true;
+
+ if (!ev_match)
return false;
bitmap_zero(jd_scratch, ABS_CNT);
diff --git a/drivers/input/joystick/iforce/Kconfig b/drivers/input/joystick/iforce/Kconfig
index ab4dbcbcbf50..55f6ae1da6b0 100644
--- a/drivers/input/joystick/iforce/Kconfig
+++ b/drivers/input/joystick/iforce/Kconfig
@@ -13,15 +13,15 @@ config JOYSTICK_IFORCE
module will be called iforce.
config JOYSTICK_IFORCE_USB
- bool "I-Force USB joysticks and wheels"
- depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || USB=y) && USB
+ tristate "I-Force USB joysticks and wheels"
+ depends on JOYSTICK_IFORCE && USB
help
Say Y here if you have an I-Force joystick or steering wheel
connected to your USB port.
config JOYSTICK_IFORCE_232
- bool "I-Force Serial joysticks and wheels"
- depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || SERIO=y) && SERIO
+ tristate "I-Force Serial joysticks and wheels"
+ depends on JOYSTICK_IFORCE && SERIO
help
Say Y here if you have an I-Force joystick or steering wheel
connected to your serial (COM) port.
diff --git a/drivers/input/joystick/iforce/Makefile b/drivers/input/joystick/iforce/Makefile
index bc5bda22f15e..414075019a4f 100644
--- a/drivers/input/joystick/iforce/Makefile
+++ b/drivers/input/joystick/iforce/Makefile
@@ -4,8 +4,7 @@
# By Johann Deneux <johann.deneux@gmail.com>
#
-obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o
-
+obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o
iforce-y := iforce-ff.o iforce-main.o iforce-packets.o
-iforce-$(CONFIG_JOYSTICK_IFORCE_232) += iforce-serio.o
-iforce-$(CONFIG_JOYSTICK_IFORCE_USB) += iforce-usb.o
+obj-$(CONFIG_JOYSTICK_IFORCE_232) += iforce-serio.o
+obj-$(CONFIG_JOYSTICK_IFORCE_USB) += iforce-usb.o
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 3536d5f5ad18..56973dd97fd6 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -384,12 +384,12 @@ int iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, stru
}
switch (effect->u.periodic.waveform) {
- case FF_SQUARE: wave_code = 0x20; break;
- case FF_TRIANGLE: wave_code = 0x21; break;
- case FF_SINE: wave_code = 0x22; break;
- case FF_SAW_UP: wave_code = 0x23; break;
- case FF_SAW_DOWN: wave_code = 0x24; break;
- default: wave_code = 0x20; break;
+ case FF_SQUARE: wave_code = 0x20; break;
+ case FF_TRIANGLE: wave_code = 0x21; break;
+ case FF_SINE: wave_code = 0x22; break;
+ case FF_SAW_UP: wave_code = 0x23; break;
+ case FF_SAW_DOWN: wave_code = 0x24; break;
+ default: wave_code = 0x20; break;
}
if (!old || need_core(old, effect)) {
@@ -488,9 +488,9 @@ int iforce_upload_condition(struct iforce *iforce, struct ff_effect *effect, str
int core_err = 0;
switch (effect->type) {
- case FF_SPRING: type = 0x40; break;
- case FF_DAMPER: type = 0x41; break;
- default: return -1;
+ case FF_SPRING: type = 0x40; break;
+ case FF_DAMPER: type = 0x41; break;
+ default: return -1;
}
if (!old || need_condition_modifier(iforce, old, effect)) {
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 58d5cfe46526..40eb65bfd57e 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -21,10 +21,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <asm/unaligned.h>
#include "iforce.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
-MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
+MODULE_DESCRIPTION("Core I-Force joysticks and wheels driver");
MODULE_LICENSE("GPL");
static signed short btn_joystick[] =
@@ -67,6 +68,7 @@ static struct iforce_device iforce_device[] = {
{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce },
+ { 0x06a3, 0xff04, "Saitek R440 Force Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce },
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
@@ -132,22 +134,21 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect,
* Upload the effect
*/
switch (effect->type) {
+ case FF_PERIODIC:
+ ret = iforce_upload_periodic(iforce, effect, old);
+ break;
- case FF_PERIODIC:
- ret = iforce_upload_periodic(iforce, effect, old);
- break;
-
- case FF_CONSTANT:
- ret = iforce_upload_constant(iforce, effect, old);
- break;
+ case FF_CONSTANT:
+ ret = iforce_upload_constant(iforce, effect, old);
+ break;
- case FF_SPRING:
- case FF_DAMPER:
- ret = iforce_upload_condition(iforce, effect, old);
- break;
+ case FF_SPRING:
+ case FF_DAMPER:
+ ret = iforce_upload_condition(iforce, effect, old);
+ break;
- default:
- return -EINVAL;
+ default:
+ return -EINVAL;
}
if (ret == 0) {
@@ -185,15 +186,7 @@ static int iforce_open(struct input_dev *dev)
{
struct iforce *iforce = input_get_drvdata(dev);
- switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
- iforce->irq->dev = iforce->usbdev;
- if (usb_submit_urb(iforce->irq, GFP_KERNEL))
- return -EIO;
- break;
-#endif
- }
+ iforce->xport_ops->start_io(iforce);
if (test_bit(EV_FF, dev->evbit)) {
/* Enable force feedback */
@@ -226,27 +219,17 @@ static void iforce_close(struct input_dev *dev)
!test_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags));
}
- switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
- usb_kill_urb(iforce->irq);
- usb_kill_urb(iforce->out);
- usb_kill_urb(iforce->ctrl);
- break;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- case IFORCE_232:
- //TODO: Wait for the last packets to be sent
- break;
-#endif
- }
+ iforce->xport_ops->stop_io(iforce);
}
-int iforce_init_device(struct iforce *iforce)
+int iforce_init_device(struct device *parent, u16 bustype,
+ struct iforce *iforce)
{
struct input_dev *input_dev;
struct ff_device *ff;
- unsigned char c[] = "CEOV";
+ u8 c[] = "CEOV";
+ u8 buf[IFORCE_MAX_LENGTH];
+ size_t len;
int i, error;
int ff_effects = 0;
@@ -264,20 +247,8 @@ int iforce_init_device(struct iforce *iforce)
* Input device fields.
*/
- switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
- input_dev->id.bustype = BUS_USB;
- input_dev->dev.parent = &iforce->usbdev->dev;
- break;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- case IFORCE_232:
- input_dev->id.bustype = BUS_RS232;
- input_dev->dev.parent = &iforce->serio->dev;
- break;
-#endif
- }
+ input_dev->id.bustype = bustype;
+ input_dev->dev.parent = parent;
input_set_drvdata(input_dev, iforce);
@@ -302,7 +273,7 @@ int iforce_init_device(struct iforce *iforce)
*/
for (i = 0; i < 20; i++)
- if (!iforce_get_id_packet(iforce, "O"))
+ if (!iforce_get_id_packet(iforce, 'O', buf, &len))
break;
if (i == 20) { /* 5 seconds */
@@ -316,23 +287,23 @@ int iforce_init_device(struct iforce *iforce)
* Get device info.
*/
- if (!iforce_get_id_packet(iforce, "M"))
- input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'M', buf, &len) || len < 3)
+ input_dev->id.vendor = get_unaligned_le16(buf + 1);
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet M\n");
- if (!iforce_get_id_packet(iforce, "P"))
- input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'P', buf, &len) || len < 3)
+ input_dev->id.product = get_unaligned_le16(buf + 1);
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet P\n");
- if (!iforce_get_id_packet(iforce, "B"))
- iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'B', buf, &len) || len < 3)
+ iforce->device_memory.end = get_unaligned_le16(buf + 1);
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet B\n");
- if (!iforce_get_id_packet(iforce, "N"))
- ff_effects = iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'N', buf, &len) || len < 2)
+ ff_effects = buf[1];
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet N\n");
@@ -348,8 +319,9 @@ int iforce_init_device(struct iforce *iforce)
*/
for (i = 0; c[i]; i++)
- if (!iforce_get_id_packet(iforce, c + i))
- iforce_dump_packet(iforce, "info", iforce->ecmd, iforce->edata);
+ if (!iforce_get_id_packet(iforce, c[i], buf, &len))
+ iforce_dump_packet(iforce, "info",
+ (FF_CMD_QUERY & 0xff00) | len, buf);
/*
* Disable spring, enable force feedback.
@@ -383,34 +355,29 @@ int iforce_init_device(struct iforce *iforce)
signed short t = iforce->type->abs[i];
switch (t) {
+ case ABS_X:
+ case ABS_Y:
+ case ABS_WHEEL:
+ input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
+ set_bit(t, input_dev->ffbit);
+ break;
- case ABS_X:
- case ABS_Y:
- case ABS_WHEEL:
-
- input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
- set_bit(t, input_dev->ffbit);
- break;
-
- case ABS_THROTTLE:
- case ABS_GAS:
- case ABS_BRAKE:
-
- input_set_abs_params(input_dev, t, 0, 255, 0, 0);
- break;
-
- case ABS_RUDDER:
-
- input_set_abs_params(input_dev, t, -128, 127, 0, 0);
- break;
+ case ABS_THROTTLE:
+ case ABS_GAS:
+ case ABS_BRAKE:
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
+ break;
- case ABS_HAT0X:
- case ABS_HAT0Y:
- case ABS_HAT1X:
- case ABS_HAT1Y:
+ case ABS_RUDDER:
+ input_set_abs_params(input_dev, t, -128, 127, 0, 0);
+ break;
- input_set_abs_params(input_dev, t, -1, 1, 0, 0);
- break;
+ case ABS_HAT0X:
+ case ABS_HAT0Y:
+ case ABS_HAT1X:
+ case ABS_HAT1Y:
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+ break;
}
}
@@ -443,35 +410,4 @@ int iforce_init_device(struct iforce *iforce)
fail: input_free_device(input_dev);
return error;
}
-
-static int __init iforce_init(void)
-{
- int err = 0;
-
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- err = usb_register(&iforce_usb_driver);
- if (err)
- return err;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- err = serio_register_driver(&iforce_serio_drv);
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- if (err)
- usb_deregister(&iforce_usb_driver);
-#endif
-#endif
- return err;
-}
-
-static void __exit iforce_exit(void)
-{
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- usb_deregister(&iforce_usb_driver);
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- serio_unregister_driver(&iforce_serio_drv);
-#endif
-}
-
-module_init(iforce_init);
-module_exit(iforce_exit);
+EXPORT_SYMBOL(iforce_init_device);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index c10169f4554e..76c4475740ab 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -21,6 +21,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <asm/unaligned.h>
#include "iforce.h"
static struct {
@@ -91,27 +92,12 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
/*
* If necessary, start the transmission
*/
- switch (iforce->bus) {
+ if (empty)
+ iforce->xport_ops->xmit(iforce);
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- case IFORCE_232:
- if (empty)
- iforce_serial_xmit(iforce);
- break;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
-
- if (iforce->usbdev && empty &&
- !test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
-
- iforce_usb_xmit(iforce);
- }
- break;
-#endif
- }
return 0;
}
+EXPORT_SYMBOL(iforce_send_packet);
/* Start or stop an effect */
int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value)
@@ -145,157 +131,96 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
return -1;
}
-void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
+static void iforce_report_hats_buttons(struct iforce *iforce, u8 *data)
{
struct input_dev *dev = iforce->dev;
int i;
- static int being_used = 0;
- if (being_used)
- dev_warn(&iforce->dev->dev,
- "re-entrant call to iforce_process %d\n", being_used);
- being_used++;
-
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- if (HI(iforce->expect_packet) == HI(cmd)) {
- iforce->expect_packet = 0;
- iforce->ecmd = cmd;
- memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
- }
-#endif
- wake_up(&iforce->wait);
+ input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
+ input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
- if (!iforce->type) {
- being_used--;
- return;
- }
-
- switch (HI(cmd)) {
-
- case 0x01: /* joystick position data */
- case 0x03: /* wheel position data */
- if (HI(cmd) == 1) {
- input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
- input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
- input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
- if (LO(cmd) >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
- input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
- } else {
- input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0]));
- input_report_abs(dev, ABS_GAS, 255 - data[2]);
- input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
- }
+ for (i = 0; iforce->type->btn[i] >= 0; i++)
+ input_report_key(dev, iforce->type->btn[i],
+ data[(i >> 3) + 5] & (1 << (i & 7)));
- input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
- input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
-
- for (i = 0; iforce->type->btn[i] >= 0; i++)
- input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7)));
-
- /* If there are untouched bits left, interpret them as the second hat */
- if (i <= 8) {
- int btns = data[6];
- if (test_bit(ABS_HAT1X, dev->absbit)) {
- if (btns & 8) input_report_abs(dev, ABS_HAT1X, -1);
- else if (btns & 2) input_report_abs(dev, ABS_HAT1X, 1);
- else input_report_abs(dev, ABS_HAT1X, 0);
- }
- if (test_bit(ABS_HAT1Y, dev->absbit)) {
- if (btns & 1) input_report_abs(dev, ABS_HAT1Y, -1);
- else if (btns & 4) input_report_abs(dev, ABS_HAT1Y, 1);
- else input_report_abs(dev, ABS_HAT1Y, 0);
- }
- }
+ /* If there are untouched bits left, interpret them as the second hat */
+ if (i <= 8) {
+ u8 btns = data[6];
- input_sync(dev);
-
- break;
-
- case 0x02: /* status report */
- input_report_key(dev, BTN_DEAD, data[0] & 0x02);
- input_sync(dev);
+ if (test_bit(ABS_HAT1X, dev->absbit)) {
+ if (btns & BIT(3))
+ input_report_abs(dev, ABS_HAT1X, -1);
+ else if (btns & BIT(1))
+ input_report_abs(dev, ABS_HAT1X, 1);
+ else
+ input_report_abs(dev, ABS_HAT1X, 0);
+ }
- /* 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);
- }
- } 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);
- }
- if (LO(cmd) > 3) {
- int j;
- for (j = 3; j < LO(cmd); j += 2)
- mark_core_as_ready(iforce, data[j] | (data[j+1]<<8));
- }
- break;
+ if (test_bit(ABS_HAT1Y, dev->absbit)) {
+ if (btns & BIT(0))
+ input_report_abs(dev, ABS_HAT1Y, -1);
+ else if (btns & BIT(2))
+ input_report_abs(dev, ABS_HAT1Y, 1);
+ else
+ input_report_abs(dev, ABS_HAT1Y, 0);
+ }
}
- being_used--;
}
-int iforce_get_id_packet(struct iforce *iforce, char *packet)
+void iforce_process_packet(struct iforce *iforce,
+ u8 packet_id, u8 *data, size_t len)
{
- switch (iforce->bus) {
+ struct input_dev *dev = iforce->dev;
+ int i, j;
- case IFORCE_USB: {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- int status;
+ switch (packet_id) {
- iforce->cr.bRequest = packet[0];
- iforce->ctrl->dev = iforce->usbdev;
+ case 0x01: /* joystick position data */
+ input_report_abs(dev, ABS_X,
+ (__s16) get_unaligned_le16(data));
+ input_report_abs(dev, ABS_Y,
+ (__s16) get_unaligned_le16(data + 2));
+ input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
- status = usb_submit_urb(iforce->ctrl, GFP_KERNEL);
- if (status) {
- dev_err(&iforce->intf->dev,
- "usb_submit_urb failed %d\n", status);
- return -1;
- }
+ if (len >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
+ input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
- wait_event_interruptible_timeout(iforce->wait,
- iforce->ctrl->status != -EINPROGRESS, HZ);
+ iforce_report_hats_buttons(iforce, data);
- if (iforce->ctrl->status) {
- dev_dbg(&iforce->intf->dev,
- "iforce->ctrl->status = %d\n",
- iforce->ctrl->status);
- usb_unlink_urb(iforce->ctrl);
- return -1;
- }
-#else
- printk(KERN_DEBUG "iforce_get_id_packet: iforce->bus = USB!\n");
-#endif
- }
+ input_sync(dev);
break;
- case IFORCE_232:
+ case 0x03: /* wheel position data */
+ input_report_abs(dev, ABS_WHEEL,
+ (__s16) get_unaligned_le16(data));
+ input_report_abs(dev, ABS_GAS, 255 - data[2]);
+ input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- iforce->expect_packet = FF_CMD_QUERY;
- iforce_send_packet(iforce, FF_CMD_QUERY, packet);
+ iforce_report_hats_buttons(iforce, data);
- wait_event_interruptible_timeout(iforce->wait,
- !iforce->expect_packet, HZ);
+ input_sync(dev);
+ break;
+
+ case 0x02: /* status report */
+ input_report_key(dev, BTN_DEAD, data[0] & 0x02);
+ input_sync(dev);
- if (iforce->expect_packet) {
- iforce->expect_packet = 0;
- return -1;
+ /* 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);
+ }
+ } 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
- dev_err(&iforce->dev->dev,
- "iforce_get_id_packet: iforce->bus = SERIO!\n");
-#endif
- break;
- default:
- dev_err(&iforce->dev->dev,
- "iforce_get_id_packet: iforce->bus = %d\n",
- iforce->bus);
+ for (j = 3; j < len; j += 2)
+ mark_core_as_ready(iforce, get_unaligned_le16(data + j));
+
break;
}
-
- return -(iforce->edata[0] != packet[0]);
}
-
+EXPORT_SYMBOL(iforce_process_packet);
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index f4ba4a751fe0..e7692a38591e 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -21,10 +21,26 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/serio.h>
#include "iforce.h"
-void iforce_serial_xmit(struct iforce *iforce)
+struct iforce_serio {
+ struct iforce iforce;
+
+ struct serio *serio;
+ int idx, pkt, len, id;
+ u8 csum;
+ u8 expect_packet;
+ u8 cmd_response[IFORCE_MAX_LENGTH];
+ u8 cmd_response_len;
+ u8 data_in[IFORCE_MAX_LENGTH];
+};
+
+static void iforce_serio_xmit(struct iforce *iforce)
{
+ struct iforce_serio *iforce_serio = container_of(iforce,
+ struct iforce_serio,
+ iforce);
unsigned char cs;
int i;
unsigned long flags;
@@ -45,19 +61,20 @@ again:
cs = 0x2b;
- serio_write(iforce->serio, 0x2b);
+ serio_write(iforce_serio->serio, 0x2b);
- serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
+ serio_write(iforce_serio->serio, iforce->xmit.buf[iforce->xmit.tail]);
cs ^= iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
- serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
+ serio_write(iforce_serio->serio,
+ iforce->xmit.buf[iforce->xmit.tail]);
cs ^= iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
}
- serio_write(iforce->serio, cs);
+ serio_write(iforce_serio->serio, cs);
if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
goto again;
@@ -67,54 +84,118 @@ again:
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
}
+static int iforce_serio_get_id(struct iforce *iforce, u8 id,
+ u8 *response_data, size_t *response_len)
+{
+ struct iforce_serio *iforce_serio = container_of(iforce,
+ struct iforce_serio,
+ iforce);
+
+ iforce_serio->expect_packet = HI(FF_CMD_QUERY);
+ iforce_serio->cmd_response_len = 0;
+
+ iforce_send_packet(iforce, FF_CMD_QUERY, &id);
+
+ wait_event_interruptible_timeout(iforce->wait,
+ !iforce_serio->expect_packet, HZ);
+
+ if (iforce_serio->expect_packet) {
+ iforce_serio->expect_packet = 0;
+ return -ETIMEDOUT;
+ }
+
+ if (iforce_serio->cmd_response[0] != id)
+ return -EIO;
+
+ memcpy(response_data, iforce_serio->cmd_response,
+ iforce_serio->cmd_response_len);
+ *response_len = iforce_serio->cmd_response_len;
+
+ return 0;
+}
+
+static int iforce_serio_start_io(struct iforce *iforce)
+{
+ /* No special handling required */
+ return 0;
+}
+
+static void iforce_serio_stop_io(struct iforce *iforce)
+{
+ //TODO: Wait for the last packets to be sent
+}
+
+static const struct iforce_xport_ops iforce_serio_xport_ops = {
+ .xmit = iforce_serio_xmit,
+ .get_id = iforce_serio_get_id,
+ .start_io = iforce_serio_start_io,
+ .stop_io = iforce_serio_stop_io,
+};
+
static void iforce_serio_write_wakeup(struct serio *serio)
{
struct iforce *iforce = serio_get_drvdata(serio);
- iforce_serial_xmit(iforce);
+ iforce_serio_xmit(iforce);
}
static irqreturn_t iforce_serio_irq(struct serio *serio,
- unsigned char data, unsigned int flags)
+ unsigned char data, unsigned int flags)
{
- struct iforce *iforce = serio_get_drvdata(serio);
+ struct iforce_serio *iforce_serio = serio_get_drvdata(serio);
+ struct iforce *iforce = &iforce_serio->iforce;
- if (!iforce->pkt) {
+ if (!iforce_serio->pkt) {
if (data == 0x2b)
- iforce->pkt = 1;
+ iforce_serio->pkt = 1;
goto out;
}
- if (!iforce->id) {
+ if (!iforce_serio->id) {
if (data > 3 && data != 0xff)
- iforce->pkt = 0;
+ iforce_serio->pkt = 0;
else
- iforce->id = data;
+ iforce_serio->id = data;
goto out;