From f7f3651e0887f536a6854dfcae0c21fc5463b733 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 24 Jul 2018 17:18:27 -0700 Subject: Input: iforce - remove "being used" silliness The kernel is supposed to handle multiple devices, static flags in packet handling code will never work. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index c10169f4554e..91893c751524 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -149,12 +149,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *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)) { @@ -165,10 +159,8 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) #endif wake_up(&iforce->wait); - if (!iforce->type) { - being_used--; + if (!iforce->type) return; - } switch (HI(cmd)) { @@ -233,7 +225,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) } break; } - being_used--; } int iforce_get_id_packet(struct iforce *iforce, char *packet) -- cgit v1.2.3 From 38d107690df7f0826adb5b53f4e87676859ff0a6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 26 Jul 2018 17:36:36 -0700 Subject: Input: iforce - introduce transport ops In order to tease apart the driver into core and transport modules, let's introduce transport operations and make "xmit" the very first one such operation. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 20 ++------------------ drivers/input/joystick/iforce/iforce-serio.c | 9 +++++++-- drivers/input/joystick/iforce/iforce-usb.c | 15 +++++++++++++-- drivers/input/joystick/iforce/iforce.h | 13 +++++++------ 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 91893c751524..b8ca9bdfdef8 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -91,25 +91,9 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data) /* * If necessary, start the transmission */ - switch (iforce->bus) { - -#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 (empty) + iforce->xport_ops->xmit(iforce); - if (iforce->usbdev && empty && - !test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) { - - iforce_usb_xmit(iforce); - } - break; -#endif - } return 0; } diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index f4ba4a751fe0..c9469209f994 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -23,7 +23,7 @@ #include "iforce.h" -void iforce_serial_xmit(struct iforce *iforce) +static void iforce_serio_xmit(struct iforce *iforce) { unsigned char cs; int i; @@ -67,11 +67,15 @@ again: spin_unlock_irqrestore(&iforce->xmit_lock, flags); } +static const struct iforce_xport_ops iforce_serio_xport_ops = { + .xmit = iforce_serio_xmit, +}; + 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, @@ -129,6 +133,7 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) if (!iforce) return -ENOMEM; + iforce->xport_ops = &iforce_serio_xport_ops; iforce->bus = IFORCE_232; iforce->serio = serio; diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 78073259c9a1..d4f7f34db9a0 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -23,7 +23,7 @@ #include "iforce.h" -void iforce_usb_xmit(struct iforce *iforce) +static void __iforce_usb_xmit(struct iforce *iforce) { int n, c; unsigned long flags; @@ -69,6 +69,16 @@ void iforce_usb_xmit(struct iforce *iforce) spin_unlock_irqrestore(&iforce->xmit_lock, flags); } +static void iforce_usb_xmit(struct iforce *iforce) +{ + if (!test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) + __iforce_usb_xmit(iforce); +} + +static const struct iforce_xport_ops iforce_usb_xport_ops = { + .xmit = iforce_usb_xmit, +}; + static void iforce_usb_irq(struct urb *urb) { struct iforce *iforce = urb->context; @@ -113,7 +123,7 @@ static void iforce_usb_out(struct urb *urb) return; } - iforce_usb_xmit(iforce); + __iforce_usb_xmit(iforce); wake_up(&iforce->wait); } @@ -155,6 +165,7 @@ static int iforce_usb_probe(struct usb_interface *intf, if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) goto fail; + iforce->xport_ops = &iforce_usb_xport_ops; iforce->bus = IFORCE_USB; iforce->usbdev = dev; iforce->intf = intf; diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index 0e9d01f8bcb6..2fea3be751ed 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -93,9 +93,16 @@ struct iforce_device { signed short *ff; }; +struct iforce; + +struct iforce_xport_ops { + void (*xmit)(struct iforce *iforce); +}; + struct iforce { struct input_dev *dev; /* Input device interface */ struct iforce_device *type; + const struct iforce_xport_ops *xport_ops; int bus; unsigned char data[IFORCE_MAX_LENGTH]; @@ -141,12 +148,6 @@ struct iforce { /* Public functions */ -/* iforce-serio.c */ -void iforce_serial_xmit(struct iforce *iforce); - -/* iforce-usb.c */ -void iforce_usb_xmit(struct iforce *iforce); - /* iforce-main.c */ int iforce_init_device(struct iforce *iforce); -- cgit v1.2.3 From 2a1433ff08a1b23e3003483ee2883d327f78db9e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 26 Jul 2018 17:49:34 -0700 Subject: Input: iforce - move get_id to the transport operations To avoid #ifdef-ing out parts of the code and having conditionals in normal control flow, let's define "get_id" transport method and move implementation into respective transport modules. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 64 -------------------------- drivers/input/joystick/iforce/iforce-serio.c | 17 +++++++ drivers/input/joystick/iforce/iforce-usb.c | 29 ++++++++++++ drivers/input/joystick/iforce/iforce.h | 6 ++- 4 files changed, 51 insertions(+), 65 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index b8ca9bdfdef8..e677562efc9a 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -210,67 +210,3 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) break; } } - -int iforce_get_id_packet(struct iforce *iforce, char *packet) -{ - switch (iforce->bus) { - - case IFORCE_USB: { -#ifdef CONFIG_JOYSTICK_IFORCE_USB - int status; - - iforce->cr.bRequest = packet[0]; - iforce->ctrl->dev = iforce->usbdev; - - status = usb_submit_urb(iforce->ctrl, GFP_KERNEL); - if (status) { - dev_err(&iforce->intf->dev, - "usb_submit_urb failed %d\n", status); - return -1; - } - - wait_event_interruptible_timeout(iforce->wait, - iforce->ctrl->status != -EINPROGRESS, HZ); - - 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 - } - break; - - case IFORCE_232: - -#ifdef CONFIG_JOYSTICK_IFORCE_232 - iforce->expect_packet = FF_CMD_QUERY; - iforce_send_packet(iforce, FF_CMD_QUERY, packet); - - wait_event_interruptible_timeout(iforce->wait, - !iforce->expect_packet, HZ); - - if (iforce->expect_packet) { - iforce->expect_packet = 0; - return -1; - } -#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); - break; - } - - return -(iforce->edata[0] != packet[0]); -} - diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index c9469209f994..fa45ce425d47 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -67,8 +67,25 @@ again: spin_unlock_irqrestore(&iforce->xmit_lock, flags); } +static int iforce_serio_get_id(struct iforce *iforce, u8 *packet) +{ + iforce->expect_packet = FF_CMD_QUERY; + iforce_send_packet(iforce, FF_CMD_QUERY, packet); + + wait_event_interruptible_timeout(iforce->wait, + !iforce->expect_packet, HZ); + + if (iforce->expect_packet) { + iforce->expect_packet = 0; + return -EIO; + } + + return -(iforce->edata[0] != packet[0]); +} + static const struct iforce_xport_ops iforce_serio_xport_ops = { .xmit = iforce_serio_xmit, + .get_id = iforce_serio_get_id, }; static void iforce_serio_write_wakeup(struct serio *serio) diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index d4f7f34db9a0..f7eeaad92602 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -75,8 +75,37 @@ static void iforce_usb_xmit(struct iforce *iforce) __iforce_usb_xmit(iforce); } +static int iforce_usb_get_id(struct iforce *iforce, u8 *packet) +{ + int status; + + iforce->cr.bRequest = packet[0]; + iforce->ctrl->dev = iforce->usbdev; + + status = usb_submit_urb(iforce->ctrl, GFP_KERNEL); + if (status) { + dev_err(&iforce->intf->dev, + "usb_submit_urb failed %d\n", status); + return -EIO; + } + + wait_event_interruptible_timeout(iforce->wait, + iforce->ctrl->status != -EINPROGRESS, HZ); + + if (iforce->ctrl->status) { + dev_dbg(&iforce->intf->dev, + "iforce->ctrl->status = %d\n", + iforce->ctrl->status); + usb_unlink_urb(iforce->ctrl); + return -EIO; + } + + return -(iforce->edata[0] != packet[0]); +} + static const struct iforce_xport_ops iforce_usb_xport_ops = { .xmit = iforce_usb_xmit, + .get_id = iforce_usb_get_id, }; static void iforce_usb_irq(struct urb *urb) diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index 2fea3be751ed..f6636230be31 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -97,6 +97,7 @@ struct iforce; struct iforce_xport_ops { void (*xmit)(struct iforce *iforce); + int (*get_id)(struct iforce *iforce, u8* id); }; struct iforce { @@ -146,6 +147,10 @@ struct iforce { /* Encode a time value */ #define TIME_SCALE(a) (a) +static inline int iforce_get_id_packet(struct iforce *iforce, u8* id) +{ + return iforce->xport_ops->get_id(iforce, id); +} /* Public functions */ /* iforce-main.c */ @@ -156,7 +161,6 @@ int iforce_control_playback(struct iforce*, u16 id, unsigned int); void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data); int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data); void iforce_dump_packet(struct iforce *iforce, char *msg, u16 cmd, unsigned char *data); -int iforce_get_id_packet(struct iforce *iforce, char *packet); /* iforce-ff.c */ int iforce_upload_periodic(struct iforce *, struct ff_effect *, struct ff_effect *); -- cgit v1.2.3 From 9381758466f9939d84f6f70097c8883da9639379 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 3 Aug 2018 15:23:40 -0700 Subject: Input: iforce - move command completion handling to serio code Continue teasing apart protocol-specific bits from core into transport modules. This time move RS232-specific command completion handling from core to iforce-serio module. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 7 ------- drivers/input/joystick/iforce/iforce-serio.c | 12 +++++++++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index e677562efc9a..8a9a152bb595 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -134,13 +134,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) struct input_dev *dev = iforce->dev; int i; -#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); if (!iforce->type) diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index fa45ce425d47..eca2f6eca7f0 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -130,7 +130,17 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, } if (iforce->idx == iforce->len) { - iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data); + u16 cmd = (iforce->id << 8) | iforce->idx; + + /* Handle command completion */ + if (HI(iforce->expect_packet) == HI(cmd)) { + iforce->expect_packet = 0; + iforce->ecmd = cmd; + memcpy(iforce->edata, iforce->data, IFORCE_MAX_LENGTH); + } + + iforce_process_packet(iforce, cmd, iforce->data); + iforce->pkt = 0; iforce->id = 0; iforce->len = 0; -- cgit v1.2.3 From 05ca38283afa5ad11de88395cf0b28c192766bc1 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 3 Aug 2018 15:26:00 -0700 Subject: Input: iforce - introduce start and stop io transport ops Add start_io() and stop_io() transport methods so that core does not have to know the details. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 25 ++----------------------- drivers/input/joystick/iforce/iforce-serio.c | 13 +++++++++++++ drivers/input/joystick/iforce/iforce-usb.c | 17 +++++++++++++++++ drivers/input/joystick/iforce/iforce.h | 2 ++ 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 58d5cfe46526..4401ca4a4c38 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -185,15 +185,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,20 +218,7 @@ 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) diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index eca2f6eca7f0..afc7521b430d 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -83,9 +83,22 @@ static int iforce_serio_get_id(struct iforce *iforce, u8 *packet) return -(iforce->edata[0] != packet[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) diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index f7eeaad92602..10b583b5fc82 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -103,9 +103,26 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 *packet) return -(iforce->edata[0] != packet[0]); } +static int iforce_usb_start_io(struct iforce *iforce) +{ + if (usb_submit_urb(iforce->irq, GFP_KERNEL)) + return -EIO; + + return 0; +} + +static void iforce_usb_stop_io(struct iforce *iforce) +{ + usb_kill_urb(iforce->irq); + usb_kill_urb(iforce->out); + usb_kill_urb(iforce->ctrl); +} + static const struct iforce_xport_ops iforce_usb_xport_ops = { .xmit = iforce_usb_xmit, .get_id = iforce_usb_get_id, + .start_io = iforce_usb_start_io, + .stop_io = iforce_usb_stop_io, }; static void iforce_usb_irq(struct urb *urb) diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index f6636230be31..c020d61eccf2 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -98,6 +98,8 @@ struct iforce; struct iforce_xport_ops { void (*xmit)(struct iforce *iforce); int (*get_id)(struct iforce *iforce, u8* id); + int (*start_io)(struct iforce *iforce); + void (*stop_io)(struct iforce *iforce); }; struct iforce { -- cgit v1.2.3 From 501025df2e774ea840276e08d2a0aead606ffa52 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 3 Aug 2018 15:34:41 -0700 Subject: Input: iforce - add bus type and parent arguments to iforce_init_device() Note that the parent device for the USB-connected controllers is now USB interface instead of USB device. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 19 ++++--------------- drivers/input/joystick/iforce/iforce-serio.c | 2 +- drivers/input/joystick/iforce/iforce-usb.c | 2 +- drivers/input/joystick/iforce/iforce.h | 3 ++- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 4401ca4a4c38..894769d03df3 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -221,7 +221,8 @@ static void iforce_close(struct input_dev *dev) 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; @@ -243,20 +244,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); diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index afc7521b430d..b5dea273f98e 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -183,7 +183,7 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) if (err) goto fail1; - err = iforce_init_device(iforce); + err = iforce_init_device(&serio->dev, BUS_RS232, iforce); if (err) goto fail2; diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 10b583b5fc82..824df4273774 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -229,7 +229,7 @@ static int iforce_usb_probe(struct usb_interface *intf, usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0), (void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce); - err = iforce_init_device(iforce); + err = iforce_init_device(&intf->dev, BUS_USB, iforce); if (err) goto fail; diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index c020d61eccf2..3ee9245a415b 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -156,7 +156,8 @@ static inline int iforce_get_id_packet(struct iforce *iforce, u8* id) /* Public functions */ /* iforce-main.c */ -int iforce_init_device(struct iforce *iforce); +int iforce_init_device(struct device *parent, u16 bustype, + struct iforce *iforce); /* iforce-packets.c */ int iforce_control_playback(struct iforce*, u16 id, unsigned int); -- cgit v1.2.3 From 81fd43132684605b21600fa5e27f23034e18dfd3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 3 Aug 2018 16:27:45 -0700 Subject: Input: iforce - move transport data into transport modules This moves transport-specific data from main iforce structure into transport modules. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-serio.c | 96 ++++++++++++------- drivers/input/joystick/iforce/iforce-usb.c | 138 ++++++++++++++++----------- drivers/input/joystick/iforce/iforce.h | 14 +-- 3 files changed, 144 insertions(+), 104 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index b5dea273f98e..6ff1bbeeb494 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -23,8 +23,20 @@ #include "iforce.h" +struct iforce_serio { + struct iforce iforce; + + struct serio *serio; + int idx, pkt, len, id; + u8 csum; + u8 expect_packet; +}; + 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 +57,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; @@ -69,14 +82,18 @@ again: static int iforce_serio_get_id(struct iforce *iforce, u8 *packet) { - iforce->expect_packet = FF_CMD_QUERY; + struct iforce_serio *iforce_serio = container_of(iforce, + struct iforce_serio, + iforce); + + iforce_serio->expect_packet = HI(FF_CMD_QUERY); iforce_send_packet(iforce, FF_CMD_QUERY, packet); wait_event_interruptible_timeout(iforce->wait, - !iforce->expect_packet, HZ); + !iforce_serio->expect_packet, HZ); - if (iforce->expect_packet) { - iforce->expect_packet = 0; + if (iforce_serio->expect_packet) { + iforce_serio->expect_packet = 0; return -EIO; } @@ -111,54 +128,56 @@ static void iforce_serio_write_wakeup(struct serio *serio) static irqreturn_t iforce_serio_irq(struct serio *serio, 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; } - if (!iforce->len) { + if (!iforce_serio->len) { if (data > IFORCE_MAX_LENGTH) { - iforce->pkt = 0; - iforce->id = 0; + iforce_serio->pkt = 0; + iforce_serio->id = 0; } else { - iforce->len = data; + iforce_serio->len = data; } goto out; } - if (iforce->idx < iforce->len) { - iforce->csum += iforce->data[iforce->idx++] = data; + if (iforce_serio->idx < iforce_serio->len) { + iforce->data[iforce_serio->idx++] = data; + iforce_serio->csum += data; goto out; } - if (iforce->idx == iforce->len) { - u16 cmd = (iforce->id << 8) | iforce->idx; + if (iforce_serio->idx == iforce_serio->len) { + u16 cmd = (iforce_serio->id << 8) | iforce_serio->idx; /* Handle command completion */ - if (HI(iforce->expect_packet) == HI(cmd)) { - iforce->expect_packet = 0; + if (iforce_serio->expect_packet == iforce_serio->id) { + iforce_serio->expect_packet = 0; iforce->ecmd = cmd; memcpy(iforce->edata, iforce->data, IFORCE_MAX_LENGTH); } iforce_process_packet(iforce, cmd, iforce->data); - iforce->pkt = 0; - iforce->id = 0; - iforce->len = 0; - iforce->idx = 0; - iforce->csum = 0; + iforce_serio->pkt = 0; + iforce_serio->id = 0; + iforce_serio->len = 0; + iforce_serio->idx = 0; + iforce_serio->csum = 0; } out: return IRQ_HANDLED; @@ -166,18 +185,21 @@ out: static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) { + struct iforce_serio *iforce_serio; struct iforce *iforce; int err; - iforce = kzalloc(sizeof(struct iforce), GFP_KERNEL); - if (!iforce) + iforce_serio = kzalloc(sizeof(*iforce_serio), GFP_KERNEL); + if (!iforce_serio) return -ENOMEM; + iforce = &iforce_serio->iforce; + iforce->xport_ops = &iforce_serio_xport_ops; iforce->bus = IFORCE_232; - iforce->serio = serio; - serio_set_drvdata(serio, iforce); + iforce_serio->serio = serio; + serio_set_drvdata(serio, iforce_serio); err = serio_open(serio, drv); if (err) @@ -191,18 +213,18 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) fail2: serio_close(serio); fail1: serio_set_drvdata(serio, NULL); - kfree(iforce); + kfree(iforce_serio); return err; } static void iforce_serio_disconnect(struct serio *serio) { - struct iforce *iforce = serio_get_drvdata(serio); + struct iforce_serio *iforce_serio = serio_get_drvdata(serio); - input_unregister_device(iforce->dev); + input_unregister_device(iforce_serio->iforce.dev); serio_close(serio); serio_set_drvdata(serio, NULL); - kfree(iforce); + kfree(iforce_serio); } static const struct serio_device_id iforce_serio_ids[] = { diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 824df4273774..d4e7a24922cd 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -23,8 +23,19 @@ #include "iforce.h" +struct iforce_usb { + struct iforce iforce; + + struct usb_device *usbdev; + struct usb_interface *intf; + struct urb *irq, *out, *ctrl; + struct usb_ctrlrequest cr; +}; + static void __iforce_usb_xmit(struct iforce *iforce) { + struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, + iforce); int n, c; unsigned long flags; @@ -36,31 +47,32 @@ static void __iforce_usb_xmit(struct iforce *iforce) return; } - ((char *)iforce->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail]; + ((char *)iforce_usb->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); n = iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); - iforce->out->transfer_buffer_length = n + 1; - iforce->out->dev = iforce->usbdev; + iforce_usb->out->transfer_buffer_length = n + 1; + iforce_usb->out->dev = iforce_usb->usbdev; /* Copy rest of data then */ c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE); if (n < c) c=n; - memcpy(iforce->out->transfer_buffer + 1, + memcpy(iforce_usb->out->transfer_buffer + 1, &iforce->xmit.buf[iforce->xmit.tail], c); if (n != c) { - memcpy(iforce->out->transfer_buffer + 1 + c, + memcpy(iforce_usb->out->transfer_buffer + 1 + c, &iforce->xmit.buf[0], n-c); } XMIT_INC(iforce->xmit.tail, n); - if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) { + if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) { clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); - dev_warn(&iforce->intf->dev, "usb_submit_urb failed %d\n", n); + dev_warn(&iforce_usb->intf->dev, + "usb_submit_urb failed %d\n", n); } /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended. @@ -77,26 +89,28 @@ static void iforce_usb_xmit(struct iforce *iforce) static int iforce_usb_get_id(struct iforce *iforce, u8 *packet) { + struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, + iforce); int status; - iforce->cr.bRequest = packet[0]; - iforce->ctrl->dev = iforce->usbdev; + iforce_usb->cr.bRequest = packet[0]; + iforce_usb->ctrl->dev = iforce_usb->usbdev; - status = usb_submit_urb(iforce->ctrl, GFP_KERNEL); + status = usb_submit_urb(iforce_usb->ctrl, GFP_KERNEL); if (status) { - dev_err(&iforce->intf->dev, + dev_err(&iforce_usb->intf->dev, "usb_submit_urb failed %d\n", status); return -EIO; } wait_event_interruptible_timeout(iforce->wait, - iforce->ctrl->status != -EINPROGRESS, HZ); + iforce_usb->ctrl->status != -EINPROGRESS, HZ); - if (iforce->ctrl->status) { - dev_dbg(&iforce->intf->dev, + if (iforce_usb->ctrl->status) { + dev_dbg(&iforce_usb->intf->dev, "iforce->ctrl->status = %d\n", - iforce->ctrl->status); - usb_unlink_urb(iforce->ctrl); + iforce_usb->ctrl->status); + usb_unlink_urb(iforce_usb->ctrl); return -EIO; } @@ -105,7 +119,10 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 *packet) static int iforce_usb_start_io(struct iforce *iforce) { - if (usb_submit_urb(iforce->irq, GFP_KERNEL)) + struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, + iforce); + + if (usb_submit_urb(iforce_usb->irq, GFP_KERNEL)) return -EIO; return 0; @@ -113,9 +130,12 @@ static int iforce_usb_start_io(struct iforce *iforce) static void iforce_usb_stop_io(struct iforce *iforce) { - usb_kill_urb(iforce->irq); - usb_kill_urb(iforce->out); - usb_kill_urb(iforce->ctrl); + struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, + iforce); + + usb_kill_urb(iforce_usb->irq); + usb_kill_urb(iforce_usb->out); + usb_kill_urb(iforce_usb->ctrl); } static const struct iforce_xport_ops iforce_usb_xport_ops = { @@ -127,8 +147,9 @@ static const struct iforce_xport_ops iforce_usb_xport_ops = { static void iforce_usb_irq(struct urb *urb) { - struct iforce *iforce = urb->context; - struct device *dev = &iforce->intf->dev; + struct iforce_usb *iforce_usb = urb->context; + struct iforce *iforce = &iforce_usb->iforce; + struct device *dev = &iforce_usb->intf->dev; int status; switch (urb->status) { @@ -152,7 +173,7 @@ static void iforce_usb_irq(struct urb *urb) (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1); exit: - status = usb_submit_urb (urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, status); @@ -160,11 +181,12 @@ exit: static void iforce_usb_out(struct urb *urb) { - struct iforce *iforce = urb->context; + struct iforce_usb *iforce_usb = urb->context; + struct iforce *iforce = &iforce_usb->iforce; if (urb->status) { clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); - dev_dbg(&iforce->intf->dev, "urb->status %d, exiting\n", + dev_dbg(&iforce_usb->intf->dev, "urb->status %d, exiting\n", urb->status); return; } @@ -176,8 +198,12 @@ static void iforce_usb_out(struct urb *urb) static void iforce_usb_ctrl(struct urb *urb) { - struct iforce *iforce = urb->context; - if (urb->status) return; + struct iforce_usb *iforce_usb = urb->context; + struct iforce *iforce = &iforce_usb->iforce; + + if (urb->status) + return; + iforce->ecmd = 0xff00 | urb->actual_length; wake_up(&iforce->wait); } @@ -188,6 +214,7 @@ static int iforce_usb_probe(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *epirq, *epout; + struct iforce_usb *iforce_usb; struct iforce *iforce; int err = -ENOMEM; @@ -199,49 +226,52 @@ static int iforce_usb_probe(struct usb_interface *intf, epirq = &interface->endpoint[0].desc; epout = &interface->endpoint[1].desc; - if (!(iforce = kzalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) + if (!(iforce_usb = kzalloc(sizeof(*iforce_usb) + 32, GFP_KERNEL))) goto fail; - if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL))) + if (!(iforce_usb->irq = usb_alloc_urb(0, GFP_KERNEL))) goto fail; - if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL))) + if (!(iforce_usb->out = usb_alloc_urb(0, GFP_KERNEL))) goto fail; - if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) + if (!(iforce_usb->ctrl = usb_alloc_urb(0, GFP_KERNEL))) goto fail; + iforce = &iforce_usb->iforce; + iforce->xport_ops = &iforce_usb_xport_ops; iforce->bus = IFORCE_USB; - iforce->usbdev = dev; - iforce->intf = intf; - iforce->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE; - iforce->cr.wIndex = 0; - iforce->cr.wLength = cpu_to_le16(16); + iforce_usb->usbdev = dev; + iforce_usb->intf = intf; + + iforce_usb->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE; + iforce_usb->cr.wIndex = 0; + iforce_usb->cr.wLength = cpu_to_le16(16); - usb_fill_int_urb(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress), - iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval); + usb_fill_int_urb(iforce_usb->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress), + iforce->data, 16, iforce_usb_irq, iforce_usb, epirq->bInterval); - usb_fill_int_urb(iforce->out, dev, usb_sndintpipe(dev, epout->bEndpointAddress), - iforce + 1, 32, iforce_usb_out, iforce, epout->bInterval); + usb_fill_int_urb(iforce_usb->out, dev, usb_sndintpipe(dev, epout->bEndpointAddress), + iforce_usb + 1, 32, iforce_usb_out, iforce_usb, epout->bInterval); - usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0), - (void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce); + usb_fill_control_urb(iforce_usb->ctrl, dev, usb_rcvctrlpipe(dev, 0), + (void*) &iforce_usb->cr, iforce->edata, 16, iforce_usb_ctrl, iforce_usb); err = iforce_init_device(&intf->dev, BUS_USB, iforce); if (err) goto fail; - usb_set_intfdata(intf, iforce); + usb_set_intfdata(intf, iforce_usb); return 0; fail: - if (iforce) { - usb_free_urb(iforce->irq); - usb_free_urb(iforce->out); - usb_free_urb(iforce->ctrl); - kfree(iforce); + if (iforce_usb) { + usb_free_urb(iforce_usb->irq); + usb_free_urb(iforce_usb->out); + usb_free_urb(iforce_usb->ctrl); + kfree(iforce_usb); } return err; @@ -249,17 +279,17 @@ fail: static void iforce_usb_disconnect(struct usb_interface *intf) { - struct iforce *iforce = usb_get_intfdata(intf); + struct iforce_usb *iforce_usb = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); - input_unregister_device(iforce->dev); + input_unregister_device(iforce_usb->iforce.dev); - usb_free_urb(iforce->irq); - usb_free_urb(iforce->out); - usb_free_urb(iforce->ctrl); + usb_free_urb(iforce_usb->irq); + usb_free_urb(iforce_usb->out); + usb_free_urb(iforce_usb->ctrl); - kfree(iforce); + kfree(iforce_usb); } static const struct usb_device_id iforce_usb_ids[] = { diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index 3ee9245a415b..d9712c48ba74 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -111,19 +111,7 @@ struct iforce { unsigned char data[IFORCE_MAX_LENGTH]; unsigned char edata[IFORCE_MAX_LENGTH]; u16 ecmd; - u16 expect_packet; - -#ifdef CONFIG_JOYSTICK_IFORCE_232 - struct serio *serio; /* RS232 transfer */ - int idx, pkt, len, id; - unsigned char csum; -#endif -#ifdef CONFIG_JOYSTICK_IFORCE_USB - struct usb_device *usbdev; /* USB transfer */ - struct usb_interface *intf; - struct urb *irq, *out, *ctrl; - struct usb_ctrlrequest cr; -#endif + spinlock_t xmit_lock; /* Buffer used for asynchronous sending of bytes to the device */ struct circ_buf xmit; -- cgit v1.2.3 From 4f99de6d9d57d29b10f132490034aa21b7ba184f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 24 Jul 2018 17:32:24 -0700 Subject: Input: iforce - split into core and transport modules Now that we have moved enough transport details into separate source files we can change them into transport modules so that they are only loaded when needed. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/Kconfig | 8 +++--- drivers/input/joystick/iforce/Makefile | 7 +++--- drivers/input/joystick/iforce/iforce-main.c | 35 ++------------------------ drivers/input/joystick/iforce/iforce-packets.c | 2 ++ drivers/input/joystick/iforce/iforce-serio.c | 7 ++++++ drivers/input/joystick/iforce/iforce-usb.c | 7 ++++++ drivers/input/joystick/iforce/iforce.h | 2 -- 7 files changed, 25 insertions(+), 43 deletions(-) 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 # -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-main.c b/drivers/input/joystick/iforce/iforce-main.c index 894769d03df3..3a0698327c42 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -24,7 +24,7 @@ #include "iforce.h" MODULE_AUTHOR("Vojtech Pavlik , Johann Deneux "); -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[] = @@ -411,35 +411,4 @@ int iforce_init_device(struct device *parent, u16 bustype, 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 8a9a152bb595..70db273e5045 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -96,6 +96,7 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data) return 0; } +EXPORT_SYMBOL(iforce_send_packet); /* Start or stop an effect */ int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value) @@ -203,3 +204,4 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) break; } } +EXPORT_SYMBOL(iforce_process_packet); diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 6ff1bbeeb494..6c6411fbdc32 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -21,6 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "iforce.h" struct iforce_serio { @@ -250,3 +251,9 @@ struct serio_driver iforce_serio_drv = { .connect = iforce_serio_connect, .disconnect = iforce_serio_disconnect, }; + +module_serio_driver(iforce_serio_drv); + +MODULE_AUTHOR("Vojtech Pavlik , Johann Deneux "); +MODULE_DESCRIPTION("RS232 I-Force joysticks and wheels driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index d4e7a24922cd..9d635f01cf19 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -21,6 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "iforce.h" struct iforce_usb { @@ -316,3 +317,9 @@ struct usb_driver iforce_usb_driver = { .disconnect = iforce_usb_disconnect, .id_table = iforce_usb_ids, }; + +module_usb_driver(iforce_usb_driver); + +MODULE_AUTHOR("Vojtech Pavlik , Johann Deneux "); +MODULE_DESCRIPTION("USB I-Force joysticks and wheels driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index d9712c48ba74..3e3df83b9d77 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include -- cgit v1.2.3 From 4873586278258453bed94ffc04bfdc439197e86b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 9 Aug 2018 16:08:15 -0700 Subject: Input: iforce - use DMA-safe buffer when getting IDs from USB When working with USB devices we need to use DMA-safe buffers, and iforce->edata is not one. Let's rework the code to allocate temporary buffer (iforce_get_id() is called only during initialization so there is no reason to have permanent buffer) and use it. While at it, let's utilize usb_control_msg() API which simplifies code. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-usb.c | 68 ++++++++++-------------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 9d635f01cf19..cefaa1c5abc7 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -29,8 +29,7 @@ struct iforce_usb { struct usb_device *usbdev; struct usb_interface *intf; - struct urb *irq, *out, *ctrl; - struct usb_ctrlrequest cr; + struct urb *irq, *out; }; static void __iforce_usb_xmit(struct iforce *iforce) @@ -92,30 +91,32 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 *packet) { struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, iforce); + u8 *buf; int status; - iforce_usb->cr.bRequest = packet[0]; - iforce_usb->ctrl->dev = iforce_usb->usbdev; - - status = usb_submit_urb(iforce_usb->ctrl, GFP_KERNEL); - if (status) { + buf = kmalloc(IFORCE_MAX_LENGTH, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + status = usb_control_msg(iforce_usb->usbdev, + usb_rcvctrlpipe(iforce_usb->usbdev, 0), + packet[0], + USB_TYPE_VENDOR | USB_DIR_IN | + USB_RECIP_INTERFACE, + 0, 0, buf, IFORCE_MAX_LENGTH, HZ); + if (status < 0) { dev_err(&iforce_usb->intf->dev, - "usb_submit_urb failed %d\n", status); - return -EIO; - } - - wait_event_interruptible_timeout(iforce->wait, - iforce_usb->ctrl->status != -EINPROGRESS, HZ); - - if (iforce_usb->ctrl->status) { - dev_dbg(&iforce_usb->intf->dev, - "iforce->ctrl->status = %d\n", - iforce_usb->ctrl->status); - usb_unlink_urb(iforce_usb->ctrl); - return -EIO; + "usb_submit_urb failed: %d\n", status); + } else if (buf[0] != packet[0]) { + status = -EIO; + } else { + iforce->ecmd = 0xff00 | status; + memcpy(iforce->edata, buf, status); + status = 0; } - return -(iforce->edata[0] != packet[0]); + kfree(buf); + return status; } static int iforce_usb_start_io(struct iforce *iforce) @@ -136,7 +137,6 @@ static void iforce_usb_stop_io(struct iforce *iforce) usb_kill_urb(iforce_usb->irq); usb_kill_urb(iforce_usb->out); - usb_kill_urb(iforce_usb->ctrl); } static const struct iforce_xport_ops iforce_usb_xport_ops = { @@ -197,18 +197,6 @@ static void iforce_usb_out(struct urb *urb) wake_up(&iforce->wait); } -static void iforce_usb_ctrl(struct urb *urb) -{ - struct iforce_usb *iforce_usb = urb->context; - struct iforce *iforce = &iforce_usb->iforce; - - if (urb->status) - return; - - iforce->ecmd = 0xff00 | urb->actual_length; - wake_up(&iforce->wait); -} - static int iforce_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -236,9 +224,6 @@ static int iforce_usb_probe(struct usb_interface *intf, if (!(iforce_usb->out = usb_alloc_urb(0, GFP_KERNEL))) goto fail; - if (!(iforce_usb->ctrl = usb_alloc_urb(0, GFP_KERNEL))) - goto fail; - iforce = &iforce_usb->iforce; iforce->xport_ops = &iforce_usb_xport_ops; @@ -247,19 +232,12 @@ static int iforce_usb_probe(struct usb_interface *intf, iforce_usb->usbdev = dev; iforce_usb->intf = intf; - iforce_usb->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE; - iforce_usb->cr.wIndex = 0; - iforce_usb->cr.wLength = cpu_to_le16(16); - usb_fill_int_urb(iforce_usb->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress), iforce->data, 16, iforce_usb_irq, iforce_usb, epirq->bInterval); usb_fill_int_urb(iforce_usb->out, dev, usb_sndintpipe(dev, epout->bEndpointAddress), iforce_usb + 1, 32, iforce_usb_out, iforce_usb, epout->bInterval); - usb_fill_control_urb(iforce_usb->ctrl, dev, usb_rcvctrlpipe(dev, 0), - (void*) &iforce_usb->cr, iforce->edata, 16, iforce_usb_ctrl, iforce_usb); - err = iforce_init_device(&intf->dev, BUS_USB, iforce); if (err) goto fail; @@ -271,7 +249,6 @@ fail: if (iforce_usb) { usb_free_urb(iforce_usb->irq); usb_free_urb(iforce_usb->out); - usb_free_urb(iforce_usb->ctrl); kfree(iforce_usb); } @@ -288,7 +265,6 @@ static void iforce_usb_disconnect(struct usb_interface *intf) usb_free_urb(iforce_usb->irq); usb_free_urb(iforce_usb->out); - usb_free_urb(iforce_usb->ctrl); kfree(iforce_usb); } -- cgit v1.2.3 From 43e61fc77fd1b1ee6c7e4989809e1d6b3fb65ad9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 9 Aug 2018 17:40:39 -0700 Subject: Input: iforce - update formatting of switch statements According to our coding style case labels in switch statements should be aligned with the switch keyword. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-ff.c | 18 ++-- drivers/input/joystick/iforce/iforce-main.c | 70 +++++++--------- drivers/input/joystick/iforce/iforce-packets.c | 112 +++++++++++++------------ 3 files changed, 100 insertions(+), 100 deletions(-) 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 3a0698327c42..9964aa8b3cdc 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -132,22 +132,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) { @@ -351,34 +350,29 @@ int iforce_init_device(struct device *parent, u16 bustype, 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; } } diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 70db273e5045..7aba2966454a 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -142,66 +142,72 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) 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]); - } + 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]); + } - 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); - } + 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); + } + } - input_sync(dev); + input_sync(dev); - break; + break; - case 0x02: /* status report */ - input_report_key(dev, BTN_DEAD, data[0] & 0x02); - input_sync(dev); + case 0x02: /* status report */ + input_report_key(dev, BTN_DEAD, data[0] & 0x02); + input_sync(dev); - /* 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); + /* 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 (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; + } 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; } } EXPORT_SYMBOL(iforce_process_packet); -- cgit v1.2.3 From 8a25e05890f155406171e8cb256177275bbf387f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 9 Aug 2018 17:41:40 -0700 Subject: Input: iforce - factor out hat handling when parsing packets This makes code clearer a bit. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 101 ++++++++++++++----------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 7aba2966454a..ffd1dd65deb8 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -130,11 +130,47 @@ 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; + 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) { + u8 btns = data[6]; + + 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); + } + + 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); + } + } +} + +void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) +{ + struct input_dev *dev = iforce->dev; + int i, j; + wake_up(&iforce->wait); if (!iforce->type) @@ -143,48 +179,26 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) 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]); - } + 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]); - 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 (LO(cmd) >= 8 && test_bit(ABS_RUDDER ,dev->absbit)) + input_report_abs(dev, ABS_RUDDER, (__s8)data[7]); + + iforce_report_hats_buttons(iforce, data); input_sync(dev); + break; + case 0x03: /* wheel position data */ + 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]); + + iforce_report_hats_buttons(iforce, data); + + input_sync(dev); break; case 0x02: /* status report */ @@ -202,11 +216,10 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) /* 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)); - } + + for (j = 3; j < LO(cmd); j += 2) + mark_core_as_ready(iforce, data[j] | (data[j + 1] << 8)); + break; } } -- cgit v1.2.3 From d3cc100069f945a392d6cde5ea326bb686418193 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 9 Aug 2018 17:50:39 -0700 Subject: Input: iforce - do not combine arguments for iforce_process_packet() Current code combines packet type and data length into single argument to iforce_process_packet() and then has to untangle it. It is much clearer to simply use separate arguments. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 9 +++++---- drivers/input/joystick/iforce/iforce-serio.c | 8 ++++---- drivers/input/joystick/iforce/iforce-usb.c | 4 ++-- drivers/input/joystick/iforce/iforce.h | 3 ++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index ffd1dd65deb8..35b7a5206977 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -166,7 +166,8 @@ static void iforce_report_hats_buttons(struct iforce *iforce, u8 *data) } } -void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) +void iforce_process_packet(struct iforce *iforce, + u8 packet_id, u8 *data, size_t len) { struct input_dev *dev = iforce->dev; int i, j; @@ -176,14 +177,14 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) if (!iforce->type) return; - switch (HI(cmd)) { + switch (packet_id) { case 0x01: /* joystick position data */ 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)) + if (len >= 8 && test_bit(ABS_RUDDER ,dev->absbit)) input_report_abs(dev, ABS_RUDDER, (__s8)data[7]); iforce_report_hats_buttons(iforce, data); @@ -217,7 +218,7 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) input_report_ff_status(dev, i, FF_STATUS_STOPPED); } - for (j = 3; j < LO(cmd); j += 2) + for (j = 3; j < len; j += 2) mark_core_as_ready(iforce, data[j] | (data[j + 1] << 8)); break; diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 6c6411fbdc32..f8bf7d2aa59f 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -163,16 +163,16 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, } if (iforce_serio->idx == iforce_serio->len) { - u16 cmd = (iforce_serio->id << 8) | iforce_serio->idx; - /* Handle command completion */ if (iforce_serio->expect_packet == iforce_serio->id) { iforce_serio->expect_packet = 0; - iforce->ecmd = cmd; + iforce->ecmd = (iforce_serio->id << 8) | + iforce_serio->idx; memcpy(iforce->edata, iforce->data, IFORCE_MAX_LENGTH); } - iforce_process_packet(iforce, cmd, iforce->data); + iforce_process_packet(iforce, iforce_serio->id, + iforce->data, iforce_serio->len); iforce_serio->pkt = 0; iforce_serio->id = 0; diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index cefaa1c5abc7..b3743fde2a3a 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -170,8 +170,8 @@ static void iforce_usb_irq(struct urb *urb) goto exit; } - iforce_process_packet(iforce, - (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1); + iforce_process_packet(iforce, iforce->data[0], + iforce->data + 1, urb->actual_length - 1); exit: status = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index 3e3df83b9d77..ce3c6aead8b6 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -147,7 +147,8 @@ int iforce_init_device(struct device *parent, u16 bustype, /* iforce-packets.c */ int iforce_control_playback(struct iforce*, u16 id, unsigned int); -void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data); +void iforce_process_packet(struct iforce *iforce, + u8 packet_id, u8 *data, size_t len); int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data); void iforce_dump_packet(struct iforce *iforce, char *msg, u16 cmd, unsigned char *data); -- cgit v1.2.3 From 2880dcf9cfc28a3803aee4c964743adbb66b0f1a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 10 Aug 2018 10:21:13 -0700 Subject: Input: iforce - signal command completion from transport code Signalling command completion from iforce_process_packet() does not make sense, as not all transport use the same data path for both commands and motion data form the device, that is why USB code already has to signal command completion iforce_usb_out(). Let's move signalling completion into individual transport modules. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 2 -- drivers/input/joystick/iforce/iforce-serio.c | 9 ++++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 35b7a5206977..c0a665961c23 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -172,8 +172,6 @@ void iforce_process_packet(struct iforce *iforce, struct input_dev *dev = iforce->dev; int i, j; - wake_up(&iforce->wait); - if (!iforce->type) return; diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index f8bf7d2aa59f..0dd95d145e85 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -169,10 +169,13 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, iforce->ecmd = (iforce_serio->id << 8) | iforce_serio->idx; memcpy(iforce->edata, iforce->data, IFORCE_MAX_LENGTH); - } - iforce_process_packet(iforce, iforce_serio->id, - iforce->data, iforce_serio->len); + /* Signal that command is done */ + wake_up(&iforce->wait); + } else { + iforce_process_packet(iforce, iforce_serio->id, + iforce->data, iforce_serio->len); + } iforce_serio->pkt = 0; iforce_serio->id = 0; -- cgit v1.2.3 From 633354d1910262f2a3262797572ff72da461379e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 10 Aug 2018 10:34:13 -0700 Subject: Input: iforce - only call iforce_process_packet() if initialized It is excessive to check if device is fully initialized in iforce_process_packet(), as for USB-conected devices we do not start collecting reports until the device is fully initialized. Let's change serio transport code to not call iforce_process_packet() until device initialization is done. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 3 --- drivers/input/joystick/iforce/iforce-serio.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index c0a665961c23..976ec1c7cf15 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -172,9 +172,6 @@ void iforce_process_packet(struct iforce *iforce, struct input_dev *dev = iforce->dev; int i, j; - if (!iforce->type) - return; - switch (packet_id) { case 0x01: /* joystick position data */ diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 0dd95d145e85..8d7eba9c9f0e 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -172,7 +172,7 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, /* Signal that command is done */ wake_up(&iforce->wait); - } else { + } else if (likely(iforce->type)) { iforce_process_packet(iforce, iforce_serio->id, iforce->data, iforce_serio->len); } -- cgit v1.2.3 From 6ac0aec6b0a651d64eef759fddf17d9145b51033 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 9 Aug 2018 17:28:35 -0700 Subject: Input: iforce - allow callers supply data buffer when fetching device IDs We want to move buffer handling into transport layers as the properties of buffers (DMA-safety, alignment, etc) are different for different transports. To allow this, let's allow caller to specify their own buffers for the results of iforce_get_id_packet() and let transport drivers to figure what buffers they need to use for transfers. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 27 +++++++++++++++------------ drivers/input/joystick/iforce/iforce-serio.c | 28 ++++++++++++++++++++-------- drivers/input/joystick/iforce/iforce-usb.c | 11 ++++++----- drivers/input/joystick/iforce/iforce.h | 11 ++++++----- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 9964aa8b3cdc..5cb3e80f4e0d 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -225,7 +225,9 @@ int iforce_init_device(struct device *parent, u16 bustype, { 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; @@ -269,7 +271,7 @@ int iforce_init_device(struct device *parent, u16 bustype, */ 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 */ @@ -283,23 +285,23 @@ int iforce_init_device(struct device *parent, u16 bustype, * 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 = (buf[2] << 8) | 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 = (buf[2] << 8) | 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 = (buf[2] << 8) | 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"); @@ -315,8 +317,9 @@ int iforce_init_device(struct device *parent, u16 bustype, */ 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. diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 8d7eba9c9f0e..be44aed551f7 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -31,6 +31,8 @@ struct iforce_serio { int idx, pkt, len, id; u8 csum; u8 expect_packet; + u8 cmd_response[IFORCE_MAX_LENGTH]; + u8 cmd_response_len; }; static void iforce_serio_xmit(struct iforce *iforce) @@ -81,24 +83,34 @@ again: spin_unlock_irqrestore(&iforce->xmit_lock, flags); } -static int iforce_serio_get_id(struct iforce *iforce, u8 *packet) +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_send_packet(iforce, FF_CMD_QUERY, packet); + 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 -EIO; + return -ETIMEDOUT; } - return -(iforce->edata[0] != packet[0]); + 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) @@ -127,7 +139,7 @@ static void iforce_serio_write_wakeup(struct serio *serio) } static irqreturn_t iforce_serio_irq(struct serio *serio, - unsigned char data, unsigned int flags) + unsigned char data, unsigned int flags) { struct iforce_serio *iforce_serio = serio_get_drvdata(serio); struct iforce *iforce = &iforce_serio->iforce; @@ -166,9 +178,9 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, /* Handle command completion */ if (iforce_serio->expect_packet == iforce_serio->id) { iforce_serio->expect_packet = 0; - iforce->ecmd = (iforce_serio->id << 8) | - iforce_serio->idx; - memcpy(iforce->edata, iforce->data, IFORCE_MAX_LENGTH); + memcpy(iforce_serio->cmd_response, iforce->data, + IFORCE_MAX_LENGTH); + iforce_serio->cmd_response_len = iforce_serio->len; /* Signal that command is done */ wake_up(&iforce->wait); diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index b3743fde2a3a..68155c4de412 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -87,7 +87,8 @@ static void iforce_usb_xmit(struct iforce *iforce) __iforce_usb_xmit(iforce); } -static int iforce_usb_get_id(struct iforce *iforce, u8 *packet) +static int iforce_usb_get_id(struct iforce *iforce, u8 id, + u8 *response_data, size_t *response_len) { struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, iforce); @@ -100,18 +101,18 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 *packet) status = usb_control_msg(iforce_usb->usbdev, usb_rcvctrlpipe(iforce_usb->usbdev, 0), - packet[0], + id, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE, 0, 0, buf, IFORCE_MAX_LENGTH, HZ); if (status < 0) { dev_err(&iforce_usb->intf->dev, "usb_submit_urb failed: %d\n", status); - } else if (buf[0] != packet[0]) { + } else if (buf[0] != id) { status = -EIO; } else { - iforce->ecmd = 0xff00 | status; - memcpy(iforce->edata, buf, status); + memcpy(response_data, buf, status); + *response_len = status; status = 0; } diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index ce3c6aead8b6..68558c594e54 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -95,7 +95,8 @@ struct iforce; struct iforce_xport_ops { void (*xmit)(struct iforce *iforce); - int (*get_id)(struct iforce *iforce, u8* id); + int (*get_id)(struct iforce *iforce, u8 id, + u8 *response_data, size_t *response_len); int (*start_io)(struct iforce *iforce); void (*stop_io)(struct iforce *iforce); }; @@ -107,8 +108,6 @@ struct iforce { int bus; unsigned char data[IFORCE_MAX_LENGTH]; - unsigned char edata[IFORCE_MAX_LENGTH]; - u16 ecmd; spinlock_t xmit_lock; /* Buffer used for asynchronous sending of bytes to the device */ @@ -135,9 +134,11 @@ struct iforce { /* Encode a time value */ #define TIME_SCALE(a) (a) -static inline int iforce_get_id_packet(struct iforce *iforce, u8* id) +static inline int iforce_get_id_packet(struct iforce *iforce, u8 id, + u8 *response_data, size_t *response_len) { - return iforce->xport_ops->get_id(iforce, id); + return iforce->xport_ops->get_id(iforce, id, + response_data, response_len); } /* Public functions */ -- cgit v1.2.3 From dfad2b17935d70d7dc3830c4986344b3f2669c62 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 10 Aug 2018 13:44:52 -0700 Subject: Input: iforce - use DMA-safe buffores for USB transfers USB transport has to use cache line-aligned buffers for transfers to avoid DMA issues; serio doe snot have such restrictions. Let's move "data_in" buffer from main driver structure into transport modules and make sure USB requirements are respected. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-serio.c | 10 ++++++---- drivers/input/joystick/iforce/iforce-usb.c | 28 +++++++++++++++++++--------- drivers/input/joystick/iforce/iforce.h | 2 -- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index be44aed551f7..c73d988cbc92 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -33,6 +33,7 @@ struct iforce_serio { 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) @@ -169,7 +170,7 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, } if (iforce_serio->idx < iforce_serio->len) { - iforce->data[iforce_serio->idx++] = data; + iforce_serio->data_in[iforce_serio->idx++] = data; iforce_serio->csum += data; goto out; } @@ -178,15 +179,16 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, /* Handle command completion */ if (iforce_serio->expect_packet == iforce_serio->id) { iforce_serio->expect_packet = 0; - memcpy(iforce_serio->cmd_response, iforce->data, - IFORCE_MAX_LENGTH); + memcpy(iforce_serio->cmd_response, + iforce_serio->data_in, IFORCE_MAX_LENGTH); iforce_serio->cmd_response_len = iforce_serio->len; /* Signal that command is done */ wake_up(&iforce->wait); } else if (likely(iforce->type)) { iforce_process_packet(iforce, iforce_serio->id, - iforce->data, iforce_serio->len); + iforce_serio->data_in, + iforce_serio->len); } iforce_serio->pkt = 0; diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 68155c4de412..d85258b50be2 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -30,6 +30,9 @@ struct iforce_usb { struct usb_device *usbdev; struct usb_interface *intf; struct urb *irq, *out; + + u8 data_in[IFORCE_MAX_LENGTH] ____cacheline_aligned; + u8 data_out[IFORCE_MAX_LENGTH] ____cacheline_aligned; }; static void __iforce_usb_xmit(struct iforce *iforce) @@ -171,8 +174,8 @@ static void iforce_usb_irq(struct urb *urb) goto exit; } - iforce_process_packet(iforce, iforce->data[0], - iforce->data + 1, urb->actual_length - 1); + iforce_process_packet(iforce, iforce_usb->data_in[0], + iforce_usb->data_in + 1, urb->actual_length - 1); exit: status = usb_submit_urb(urb, GFP_ATOMIC); @@ -216,13 +219,16 @@ static int iforce_usb_probe(struct usb_interface *intf, epirq = &interface->endpoint[0].desc; epout = &interface->endpoint[1].desc; - if (!(iforce_usb = kzalloc(sizeof(*iforce_usb) + 32, GFP_KERNEL))) + iforce_usb = kzalloc(sizeof(*iforce_usb), GFP_KERNEL); + if (!iforce_usb) goto fail; - if (!(iforce_usb->irq = usb_alloc_urb(0, GFP_KERNEL))) + iforce_usb->irq = usb_alloc_urb(0, GFP_KERNEL); + if (!iforce_usb->irq) goto fail; - if (!(iforce_usb->out = usb_alloc_urb(0, GFP_KERNEL))) + iforce_usb->out = usb_alloc_urb(0, GFP_KERNEL); + if (!iforce_usb->out) goto fail; iforce = &iforce_usb->iforce; @@ -233,11 +239,15 @@ static int iforce_usb_probe(struct usb_interface *intf, iforce_usb->usbdev = dev; iforce_usb->intf = intf; - usb_fill_int_urb(iforce_usb->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress), - iforce->data, 16, iforce_usb_irq, iforce_usb, epirq->bInterval); + usb_fill_int_urb(iforce_usb->irq, dev, + usb_rcvintpipe(dev, epirq->bEndpointAddress), + iforce_usb->data_in, sizeof(iforce_usb->data_in), + iforce_usb_irq, iforce_usb, epirq->bInterval); - usb_fill_int_urb(iforce_usb->out, dev, usb_sndintpipe(dev, epout->bEndpointAddress), - iforce_usb + 1, 32, iforce_usb_out, iforce_usb, epout->bInterval); + usb_fill_int_urb(iforce_usb->out, dev, + usb_sndintpipe(dev, epout->bEndpointAddress), + iforce_usb->data_out, sizeof(iforce_usb->data_out), + iforce_usb_out, iforce_usb, epout->bInterval); err = iforce_init_device(&intf->dev, BUS_USB, iforce); if (err) diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index 68558c594e54..180de7a3f3a1 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -107,8 +107,6 @@ struct iforce { const struct iforce_xport_ops *xport_ops; int bus; - unsigned char data[IFORCE_MAX_LENGTH]; - spinlock_t xmit_lock; /* Buffer used for asynchronous sending of bytes to the device */ struct circ_buf xmit; -- cgit v1.2.3 From 2178db65cd9c81c790cbf7504e90650750c3b467 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 10 Aug 2018 13:48:16 -0700 Subject: Input: iforce - drop bus type from iforce structure It is not needed anymore as behavior is controlled by the transport operations set up for given device. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-serio.c | 1 - drivers/input/joystick/iforce/iforce-usb.c | 1 - drivers/input/joystick/iforce/iforce.h | 5 ----- 3 files changed, 7 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index c73d988cbc92..277522d0f324 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -214,7 +214,6 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) iforce = &iforce_serio->iforce; iforce->xport_ops = &iforce_serio_xport_ops; - iforce->bus = IFORCE_232; iforce_serio->serio = serio; serio_set_drvdata(serio, iforce_serio); diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index d85258b50be2..ae2dd5b5a416 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -234,7 +234,6 @@ static int iforce_usb_probe(struct usb_interface *intf, iforce = &iforce_usb->iforce; iforce->xport_ops = &iforce_usb_xport_ops; - iforce->bus = IFORCE_USB; iforce_usb->usbdev = dev; iforce_usb->intf = intf; diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index 180de7a3f3a1..3e91cc381488 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -38,10 +38,6 @@ #define IFORCE_MAX_LENGTH 16 -/* iforce::bus */ -#define IFORCE_232 1 -#define IFORCE_USB 2 - #define IFORCE_EFFECTS_MAX 32 /* Each force feedback effect is made of one core effect, which can be @@ -105,7 +101,6 @@ struct iforce { struct input_dev *dev; /* Input device interface */ struct iforce_device *type; const struct iforce_xport_ops *xport_ops; - int bus; spinlock_t xmit_lock; /* Buffer used for asynchronous sending of bytes to the device */ -- cgit v1.2.3 From 8624dfd10a3bb3ea3d8a959e17f8951f1b03d68d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 10 Aug 2018 13:52:31 -0700 Subject: Input: iforce - drop couple of temps from transport code Transport initialization code now deals mostly with transport-specific data, so we can drop couple of temporary variables. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-serio.c | 7 ++----- drivers/input/joystick/iforce/iforce-usb.c | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 277522d0f324..e7692a38591e 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -204,16 +204,13 @@ out: static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) { struct iforce_serio *iforce_serio; - struct iforce *iforce; int err; iforce_serio = kzalloc(sizeof(*iforce_serio), GFP_KERNEL); if (!iforce_serio) return -ENOMEM; - iforce = &iforce_serio->iforce; - - iforce->xport_ops = &iforce_serio_xport_ops; + iforce_serio->iforce.xport_ops = &iforce_serio_xport_ops; iforce_serio->serio = serio; serio_set_drvdata(serio, iforce_serio); @@ -222,7 +219,7 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) if (err) goto fail1; - err = iforce_init_device(&serio->dev, BUS_RS232, iforce); + err = iforce_init_device(&serio->dev, BUS_RS232, &iforce_serio->iforce); if (err) goto fail2; diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index ae2dd5b5a416..a1e670781441 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -208,7 +208,6 @@ static int iforce_usb_probe(struct usb_interface *intf, struct usb_host_interface *interface; struct usb_endpoint_descriptor *epirq, *epout; struct iforce_usb *iforce_usb; - struct iforce *iforce; int err = -ENOMEM; interface = intf->cur_altsetting; @@ -231,9 +230,7 @@ static int iforce_usb_probe(struct usb_interface *intf, if (!iforce_usb->out) goto fail; - iforce = &iforce_usb->iforce; - - iforce->xport_ops = &iforce_usb_xport_ops; + iforce_usb->iforce.xport_ops = &iforce_usb_xport_ops; iforce_usb->usbdev = dev; iforce_usb->intf = intf; @@ -248,7 +245,7 @@ static int iforce_usb_probe(struct usb_interface *intf, iforce_usb->data_out, sizeof(iforce_usb->data_out), iforce_usb_out, iforce_usb, epout->bInterval); - err = iforce_init_device(&intf->dev, BUS_USB, iforce); + err = iforce_init_device(&intf->dev, BUS_USB, &iforce_usb->iforce); if (err) goto fail; -- cgit v1.2.3 From 21ae38f8558511450a33fb3873bfcd6b8f1e0922 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 10 Aug 2018 13:54:02 -0700 Subject: Input: iforce - use unaligned accessors, where appropriate Instead of open-coding conversion from/to little-endian, let's use proper accessors. Tested-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 7 ++++--- drivers/input/joystick/iforce/iforce-packets.c | 12 ++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 5cb3e80f4e0d..d696b0b653b6 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -21,6 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "iforce.h" MODULE_AUTHOR("Vojtech Pavlik , Johann Deneux "); @@ -286,17 +287,17 @@ int iforce_init_device(struct device *parent, u16 bustype, */ if (!iforce_get_id_packet(iforce, 'M', buf, &len) || len < 3) - input_dev->id.vendor = (buf[2] << 8) | buf[1]; + 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', buf, &len) || len < 3) - input_dev->id.product = (buf[2] << 8) | buf[1]; + 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', buf, &len) || len < 3) - iforce->device_memory.end = (buf[2] << 8) | buf[1]; + iforce->device_memory.end = get_unaligned_le16(buf + 1); else dev_warn(&iforce->dev->dev, "Device does not respond to id packet B\n"); diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 976ec1c7cf15..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 #include "iforce.h" static struct { @@ -175,8 +176,10 @@ void iforce_process_packet(struct iforce *iforce, switch (packet_id) { case 0x01: /* joystick position data */ - 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_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]); if (len >= 8 && test_bit(ABS_RUDDER ,dev->absbit)) @@ -188,7 +191,8 @@ void iforce_process_packet(struct iforce *iforce, break; case 0x03: /* wheel position data */ - input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0])); + 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]); @@ -214,7 +218,7 @@ void iforce_process_packet(struct iforce *iforce, } for (j = 3; j < len; j += 2) - mark_core_as_ready(iforce, data[j] | (data[j + 1] << 8)); + mark_core_as_ready(iforce, get_unaligned_le16(data + j)); break; } -- cgit v1.2.3 From 11518370b332c0eeaaccef1f5de7877747893f1f Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Tue, 18 Jun 2019 17:22:14 -0700 Subject: Input: iforce - add the Saitek R440 Force Wheel This is added based on the fact that this is an iforce-based device and that the Windows driver for the R440 works for the Logitech WingMan Formula Force after replacing the device/vendor IDs. Signed-off-by: Tim Schumacher Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 1 + drivers/input/joystick/iforce/iforce-usb.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index d696b0b653b6..40eb65bfd57e 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -68,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 }, //? diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index a1e670781441..75a2b0ea37b4 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -285,6 +285,7 @@ static const struct usb_device_id iforce_usb_ids[] = { { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */ { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ + { USB_DEVICE(0x06a3, 0xff04) }, /* Saitek R440 Force Wheel */ { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0003) }, /* Guillemot Jet Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ -- cgit v1.2.3