Re: [RFC] HID:hid-lg4ff: Delay to allow wheels to center after plug-in

2016-10-27 Thread Simon Wood
On Wed, October 26, 2016 11:00 am, Dmitry Torokhov wrote:
>
> Yeah, if device happens to be plugged at boot time it will wait that
> long before even getting to mount rootfs if driver is built into the
> kernel.

Not a case I had considered... that would probably be bad. I'll look at
coding up a work queue as Elias had suggested.

>
> This is also interesting way to say "msleep(8000)".

I'm a copy/paste guy, this was from the delay we have in hid-lg.c probe,
if one way or another is better I'll use that,
Simon



Re: [RFC] HID:hid-lg4ff: Delay to allow wheels to center after plug-in

2016-10-27 Thread Simon Wood
On Wed, October 26, 2016 11:00 am, Dmitry Torokhov wrote:
>
> Yeah, if device happens to be plugged at boot time it will wait that
> long before even getting to mount rootfs if driver is built into the
> kernel.

Not a case I had considered... that would probably be bad. I'll look at
coding up a work queue as Elias had suggested.

>
> This is also interesting way to say "msleep(8000)".

I'm a copy/paste guy, this was from the delay we have in hid-lg.c probe,
if one way or another is better I'll use that,
Simon



[RFC] HID:hid-lg4ff: Delay to allow wheels to center after plug-in

2016-10-25 Thread Simon Wood
A number of wheels (G27/etc) do a little full right/full left 'dance'
when first plugged in. This patch inserts a delay so that this 'dance'
is completed before we disable (set to zero) the autocenter spring.

A side benefit is that the DFGT was confused without the delay, and is
now correctly being set to 900' rotation mode.

Side Effect - and the reason I am sending as RFC. This 8s delay seems
to have an effect on other wheels connected at the same time.

With 3 wheels on a hub, and then the hub connected to PC. The wheel
on the right in video below waits for G27 to complete this 8s, before
it will do it's 'dance' and register with the system.

https://www.youtube.com/watch?v=xCVpCw_yGgA

I don't know if this is a problem, or if someone here has suggestions
on a better way to implement the delay...
---
 drivers/hid/hid-lg4ff.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index af3a8ec..3eee920 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -1248,6 +1248,8 @@ int lg4ff_init(struct hid_device *hid)
/* Check if autocentering is available and
 * set the centering force to zero by default */
if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+   wait_queue_head_t wait;
+
/* Formula Force EX expects different autocentering command */
if ((bcdDevice >> 8) == LG4FF_FFEX_REV_MAJ &&
(bcdDevice & 0xff) == LG4FF_FFEX_REV_MIN)
@@ -1255,6 +1257,14 @@ int lg4ff_init(struct hid_device *hid)
else
dev->ff->set_autocenter = lg4ff_set_autocenter_default;
 
+   /* insert a 8s delay to allow DFGT/G25/G27/G29 wheels to return 
to center position*/
+   if (lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_DFGT_WHEEL ||
+   lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_G25_WHEEL ||
+   lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_G27_WHEEL ||
+   lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) {
+   init_waitqueue_head ();
+   wait_event_interruptible_timeout(wait, 0, 
msecs_to_jiffies(8000));
+   }
dev->ff->set_autocenter(dev, 0);
}
 
-- 
2.7.4



[RFC] HID:hid-lg4ff: Delay to allow wheels to center after plug-in

2016-10-25 Thread Simon Wood
A number of wheels (G27/etc) do a little full right/full left 'dance'
when first plugged in. This patch inserts a delay so that this 'dance'
is completed before we disable (set to zero) the autocenter spring.

A side benefit is that the DFGT was confused without the delay, and is
now correctly being set to 900' rotation mode.

Side Effect - and the reason I am sending as RFC. This 8s delay seems
to have an effect on other wheels connected at the same time.

With 3 wheels on a hub, and then the hub connected to PC. The wheel
on the right in video below waits for G27 to complete this 8s, before
it will do it's 'dance' and register with the system.

https://www.youtube.com/watch?v=xCVpCw_yGgA

I don't know if this is a problem, or if someone here has suggestions
on a better way to implement the delay...
---
 drivers/hid/hid-lg4ff.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index af3a8ec..3eee920 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -1248,6 +1248,8 @@ int lg4ff_init(struct hid_device *hid)
/* Check if autocentering is available and
 * set the centering force to zero by default */
if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+   wait_queue_head_t wait;
+
/* Formula Force EX expects different autocentering command */
if ((bcdDevice >> 8) == LG4FF_FFEX_REV_MAJ &&
(bcdDevice & 0xff) == LG4FF_FFEX_REV_MIN)
@@ -1255,6 +1257,14 @@ int lg4ff_init(struct hid_device *hid)
else
dev->ff->set_autocenter = lg4ff_set_autocenter_default;
 
+   /* insert a 8s delay to allow DFGT/G25/G27/G29 wheels to return 
to center position*/
+   if (lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_DFGT_WHEEL ||
+   lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_G25_WHEEL ||
+   lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_G27_WHEEL ||
+   lg4ff_devices[i].product_id == 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) {
+   init_waitqueue_head ();
+   wait_event_interruptible_timeout(wait, 0, 
msecs_to_jiffies(8000));
+   }
dev->ff->set_autocenter(dev, 0);
}
 
-- 
2.7.4



[Patch-V2 5/6] HID:hid-logitech: Improve Wingman Formula Force GP support

2016-09-18 Thread Simon Wood
Move ForceFeedback support for the Formula Force GP into hid-lgff4
and re-write HID descriptor, thus allowing combined pedals or not
as user desires.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg.c| 59 -
 drivers/hid/hid-lg4ff.c |  2 ++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index ffcf4f1..76f644d 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -49,6 +49,7 @@
 #define FV_RDESC_ORIG_SIZE 130
 #define MOMO_RDESC_ORIG_SIZE   87
 #define MOMO2_RDESC_ORIG_SIZE  87
+#define FFG_RDESC_ORIG_SIZE85
 
 /* Fixed report descriptors for Logitech Driving Force (and Pro)
  * wheel controllers
@@ -334,6 +335,52 @@ static __u8 momo2_rdesc_fixed[] = {
 0xC0/*  End Collection  */
 };
 
+static __u8 ffg_rdesc_fixed[] = {
+0x05, 0x01, /*  Usage Page (Desktop),   */
+0x09, 0x04, /*  Usage (Joystik),*/
+0xA1, 0x01, /*  Collection (Application),   */
+0xA1, 0x02, /*  Collection (Logical),   */
+0x95, 0x01, /*  Report Count (1),   */
+0x75, 0x0A, /*  Report Size (10),   */
+0x15, 0x00, /*  Logical Minimum (0),*/
+0x26, 0xFF, 0x03,   /*  Logical Maximum (1023), */
+0x35, 0x00, /*  Physical Minimum (0),   */
+0x46, 0xFF, 0x03,   /*  Physical Maximum (1023),*/
+0x09, 0x30, /*  Usage (X),  */
+0x81, 0x02, /*  Input (Variable),   */
+0x95, 0x06, /*  Report Count (6),   */
+0x75, 0x01, /*  Report Size (1),*/
+0x25, 0x01, /*  Logical Maximum (1),*/
+0x45, 0x01, /*  Physical Maximum (1),   */
+0x05, 0x09, /*  Usage Page (Button),*/
+0x19, 0x01, /*  Usage Minimum (01h),*/
+0x29, 0x06, /*  Usage Maximum (06h),*/
+0x81, 0x02, /*  Input (Variable),   */
+0x95, 0x01, /*  Report Count (1),   */
+0x75, 0x08, /*  Report Size (8),*/
+0x26, 0xFF, 0x00,   /*  Logical Maximum (255),  */
+0x46, 0xFF, 0x00,   /*  Physical Maximum (255), */
+0x06, 0x00, 0xFF,   /*  Usage Page (FF00h), */
+0x09, 0x01, /*  Usage (01h),*/
+0x81, 0x02, /*  Input (Variable),   */
+0x05, 0x01, /*  Usage Page (Desktop),   */
+0x81, 0x01, /*  Input (Constant),   */
+0x09, 0x31, /*  Usage (Y),  */
+0x81, 0x02, /*  Input (Variable),   */
+0x09, 0x32, /*  Usage (Z),  */
+0x81, 0x02, /*  Input (Variable),   */
+0x06, 0x00, 0xFF,   /*  Usage Page (FF00h), */
+0x09, 0x01, /*  Usage (01h),*/
+0x81, 0x02, /*  Input (Variable),   */
+0xC0,   /*  End Collection, */
+0xA1, 0x02, /*  Collection (Logical),   */
+0x09, 0x02, /*  Usage (02h),*/
+0x95, 0x07, /*  Report Count (7),   */
+0x91, 0x02, /*  Output (Variable),  */
+0xC0,   /*  End Collection, */
+0xC0/*  End Collection  */
+};
+
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
  * above the logical maximum described in descriptor. This extends
@@ -361,6 +408,15 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
 
switch (hdev->product) {
 
+   case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
+   if (*rsize == FFG_RDESC_ORIG_SIZE) {
+   hid_info(hdev,
+   "fixing up Logitech Wingman Formula Force GP 
report descriptor\n");
+   rdesc = ffg_rdesc_fixed;
+   *rsize = sizeof(ffg_rdesc_fixed);
+   }
+   break;
+
/* Several wheels report as this id when operating in emulation mode. */
case USB_DEVICE_ID_LOGITECH_WHEEL:
if (*rsize == DF_RDESC_ORIG_SIZE) {
@@ -608,6 +664,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct 
hid_input *hi,
usage->code == ABS_RZ)) {
switch (hdev->product) {
case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
case USB_DEVICE_ID_LOGITECH_WHEEL:
case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
@

[Patch-V2 6/6] HID:hid-logitech: Documentation updates/corrections

2016-09-18 Thread Simon Wood
Signed-off-by: Simon Wood <si...@mungewell.org>
---
 .../ABI/testing/sysfs-driver-hid-logitech-lg4ff|  6 ++
 drivers/hid/Kconfig| 23 +-
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index 9cd7c5a..305dffd 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -35,6 +35,12 @@ Description: Displays a set of alternate modes supported by 
a wheel. Each
  DF-EX <*> G25 <-> G27
  DF-EX <*> G27
 
+   G29:
+ DF-EX <*> DFP <-> G25 <-> G27 <-> G29
+ DF-EX <*> G25 <-> G27 <-> G29
+ DF-EX <*> G27 <-> G29
+ DF-EX <*> G29
+
DFGT:
  DF-EX <*> DFP <-> DFGT
  DF-EX <*> DFGT
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 78ac481..5227d8a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -457,8 +457,6 @@ config LOGITECH_FF
  - Logitech WingMan Cordless RumblePad
  - Logitech WingMan Cordless RumblePad 2
  - Logitech WingMan Force 3D
- - Logitech Formula Force EX
- - Logitech WingMan Formula Force GP
 
  and if you want to enable force feedback for them.
  Note: if you say N here, this device will still be supported, but 
without
@@ -488,15 +486,22 @@ config LOGIWHEELS_FF
select INPUT_FF_MEMLESS
default LOGITECH_FF
help
- Say Y here if you want to enable force feedback and range setting
+ Say Y here if you want to enable force feedback and range setting(*)
  support for following Logitech wheels:
+ - Logitech G25 (*)
+ - Logitech G27 (*)
+ - Logitech G29 (*)
  - Logitech Driving Force
- - Logitech Driving Force Pro
- - Logitech Driving Force GT
- - Logitech G25
- - Logitech G27
- - Logitech MOMO/MOMO 2
- - Logitech Formula Force EX
+ - Logitech Driving Force Pro (*)
+ - Logitech Driving Force GT (*)
+ - Logitech Driving Force EX/RX
+ - Logitech Driving Force Wireless
+ - Logitech Speed Force Wireless
+ - Logitech MOMO Force
+ - Logitech MOMO Racing Force
+ - Logitech Formula Force GP
+ - Logitech Formula Force EX/RX
+ - Logitech Wingman Formula Force GP
 
 config HID_MAGICMOUSE
tristate "Apple Magic Mouse/Trackpad multi-touch support"
-- 
2.7.4



[Patch-V2 5/6] HID:hid-logitech: Improve Wingman Formula Force GP support

2016-09-18 Thread Simon Wood
Move ForceFeedback support for the Formula Force GP into hid-lgff4
and re-write HID descriptor, thus allowing combined pedals or not
as user desires.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg.c| 59 -
 drivers/hid/hid-lg4ff.c |  2 ++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index ffcf4f1..76f644d 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -49,6 +49,7 @@
 #define FV_RDESC_ORIG_SIZE 130
 #define MOMO_RDESC_ORIG_SIZE   87
 #define MOMO2_RDESC_ORIG_SIZE  87
+#define FFG_RDESC_ORIG_SIZE85
 
 /* Fixed report descriptors for Logitech Driving Force (and Pro)
  * wheel controllers
@@ -334,6 +335,52 @@ static __u8 momo2_rdesc_fixed[] = {
 0xC0/*  End Collection  */
 };
 
+static __u8 ffg_rdesc_fixed[] = {
+0x05, 0x01, /*  Usage Page (Desktop),   */
+0x09, 0x04, /*  Usage (Joystik),*/
+0xA1, 0x01, /*  Collection (Application),   */
+0xA1, 0x02, /*  Collection (Logical),   */
+0x95, 0x01, /*  Report Count (1),   */
+0x75, 0x0A, /*  Report Size (10),   */
+0x15, 0x00, /*  Logical Minimum (0),*/
+0x26, 0xFF, 0x03,   /*  Logical Maximum (1023), */
+0x35, 0x00, /*  Physical Minimum (0),   */
+0x46, 0xFF, 0x03,   /*  Physical Maximum (1023),*/
+0x09, 0x30, /*  Usage (X),  */
+0x81, 0x02, /*  Input (Variable),   */
+0x95, 0x06, /*  Report Count (6),   */
+0x75, 0x01, /*  Report Size (1),*/
+0x25, 0x01, /*  Logical Maximum (1),*/
+0x45, 0x01, /*  Physical Maximum (1),   */
+0x05, 0x09, /*  Usage Page (Button),*/
+0x19, 0x01, /*  Usage Minimum (01h),*/
+0x29, 0x06, /*  Usage Maximum (06h),*/
+0x81, 0x02, /*  Input (Variable),   */
+0x95, 0x01, /*  Report Count (1),   */
+0x75, 0x08, /*  Report Size (8),*/
+0x26, 0xFF, 0x00,   /*  Logical Maximum (255),  */
+0x46, 0xFF, 0x00,   /*  Physical Maximum (255), */
+0x06, 0x00, 0xFF,   /*  Usage Page (FF00h), */
+0x09, 0x01, /*  Usage (01h),*/
+0x81, 0x02, /*  Input (Variable),   */
+0x05, 0x01, /*  Usage Page (Desktop),   */
+0x81, 0x01, /*  Input (Constant),   */
+0x09, 0x31, /*  Usage (Y),  */
+0x81, 0x02, /*  Input (Variable),   */
+0x09, 0x32, /*  Usage (Z),  */
+0x81, 0x02, /*  Input (Variable),   */
+0x06, 0x00, 0xFF,   /*  Usage Page (FF00h), */
+0x09, 0x01, /*  Usage (01h),*/
+0x81, 0x02, /*  Input (Variable),   */
+0xC0,   /*  End Collection, */
+0xA1, 0x02, /*  Collection (Logical),   */
+0x09, 0x02, /*  Usage (02h),*/
+0x95, 0x07, /*  Report Count (7),   */
+0x91, 0x02, /*  Output (Variable),  */
+0xC0,   /*  End Collection, */
+0xC0/*  End Collection  */
+};
+
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
  * above the logical maximum described in descriptor. This extends
@@ -361,6 +408,15 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
 
switch (hdev->product) {
 
+   case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
+   if (*rsize == FFG_RDESC_ORIG_SIZE) {
+   hid_info(hdev,
+   "fixing up Logitech Wingman Formula Force GP 
report descriptor\n");
+   rdesc = ffg_rdesc_fixed;
+   *rsize = sizeof(ffg_rdesc_fixed);
+   }
+   break;
+
/* Several wheels report as this id when operating in emulation mode. */
case USB_DEVICE_ID_LOGITECH_WHEEL:
if (*rsize == DF_RDESC_ORIG_SIZE) {
@@ -608,6 +664,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct 
hid_input *hi,
usage->code == ABS_RZ)) {
switch (hdev->product) {
case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
case USB_DEVICE_ID_LOGITECH_WHEEL:
case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
@@ -807,7 +864,7 @@ 

[Patch-V2 6/6] HID:hid-logitech: Documentation updates/corrections

2016-09-18 Thread Simon Wood
Signed-off-by: Simon Wood 
---
 .../ABI/testing/sysfs-driver-hid-logitech-lg4ff|  6 ++
 drivers/hid/Kconfig| 23 +-
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index 9cd7c5a..305dffd 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -35,6 +35,12 @@ Description: Displays a set of alternate modes supported by 
a wheel. Each
  DF-EX <*> G25 <-> G27
  DF-EX <*> G27
 
+   G29:
+ DF-EX <*> DFP <-> G25 <-> G27 <-> G29
+ DF-EX <*> G25 <-> G27 <-> G29
+ DF-EX <*> G27 <-> G29
+ DF-EX <*> G29
+
DFGT:
  DF-EX <*> DFP <-> DFGT
  DF-EX <*> DFGT
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 78ac481..5227d8a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -457,8 +457,6 @@ config LOGITECH_FF
  - Logitech WingMan Cordless RumblePad
  - Logitech WingMan Cordless RumblePad 2
  - Logitech WingMan Force 3D
- - Logitech Formula Force EX
- - Logitech WingMan Formula Force GP
 
  and if you want to enable force feedback for them.
  Note: if you say N here, this device will still be supported, but 
without
@@ -488,15 +486,22 @@ config LOGIWHEELS_FF
select INPUT_FF_MEMLESS
default LOGITECH_FF
help
- Say Y here if you want to enable force feedback and range setting
+ Say Y here if you want to enable force feedback and range setting(*)
  support for following Logitech wheels:
+ - Logitech G25 (*)
+ - Logitech G27 (*)
+ - Logitech G29 (*)
  - Logitech Driving Force
- - Logitech Driving Force Pro
- - Logitech Driving Force GT
- - Logitech G25
- - Logitech G27
- - Logitech MOMO/MOMO 2
- - Logitech Formula Force EX
+ - Logitech Driving Force Pro (*)
+ - Logitech Driving Force GT (*)
+ - Logitech Driving Force EX/RX
+ - Logitech Driving Force Wireless
+ - Logitech Speed Force Wireless
+ - Logitech MOMO Force
+ - Logitech MOMO Racing Force
+ - Logitech Formula Force GP
+ - Logitech Formula Force EX/RX
+ - Logitech Wingman Formula Force GP
 
 config HID_MAGICMOUSE
tristate "Apple Magic Mouse/Trackpad multi-touch support"
-- 
2.7.4



[Patch-V2 4/6] HID:hid-logitech: Rewrite of descriptor for all DF wheels

2016-09-18 Thread Simon Wood
Rewrite the HID descriptor for _all_ Driving Force wheels (real
or emulated) so that they can report separate Accelerator and
Brake axis.

If the user wants a combined accel/brake axis, they can use the
'combined pedals' feature.

$ echo 1 > /sys/bus/hid/devices//combine_pedals

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg.c | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 06f8a5e..ffcf4f1 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -343,8 +343,6 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
unsigned int *rsize)
 {
struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
-   struct usb_device_descriptor *udesc;
-   __u16 bcdDevice, rev_maj, rev_min;
 
if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 
&&
rdesc[84] == 0x8c && rdesc[85] == 0x02) {
@@ -365,18 +363,7 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
 
/* Several wheels report as this id when operating in emulation mode. */
case USB_DEVICE_ID_LOGITECH_WHEEL:
-   udesc = &(hid_to_usb_dev(hdev)->descriptor);
-   if (!udesc) {
-   hid_err(hdev, "NULL USB device descriptor\n");
-   break;
-   }
-   bcdDevice = le16_to_cpu(udesc->bcdDevice);
-   rev_maj = bcdDevice >> 8;
-   rev_min = bcdDevice & 0xff;
-
-   /* Update the report descriptor for only the Driving Force 
wheel */
-   if (rev_maj == 1 && rev_min == 2 &&
-   *rsize == DF_RDESC_ORIG_SIZE) {
+   if (*rsize == DF_RDESC_ORIG_SIZE) {
hid_info(hdev,
"fixing up Logitech Driving Force report 
descriptor\n");
rdesc = df_rdesc_fixed;
-- 
2.7.4



[Patch-V2 4/6] HID:hid-logitech: Rewrite of descriptor for all DF wheels

2016-09-18 Thread Simon Wood
Rewrite the HID descriptor for _all_ Driving Force wheels (real
or emulated) so that they can report separate Accelerator and
Brake axis.

If the user wants a combined accel/brake axis, they can use the
'combined pedals' feature.

$ echo 1 > /sys/bus/hid/devices//combine_pedals

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg.c | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 06f8a5e..ffcf4f1 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -343,8 +343,6 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
unsigned int *rsize)
 {
struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
-   struct usb_device_descriptor *udesc;
-   __u16 bcdDevice, rev_maj, rev_min;
 
if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 
&&
rdesc[84] == 0x8c && rdesc[85] == 0x02) {
@@ -365,18 +363,7 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
 
/* Several wheels report as this id when operating in emulation mode. */
case USB_DEVICE_ID_LOGITECH_WHEEL:
-   udesc = &(hid_to_usb_dev(hdev)->descriptor);
-   if (!udesc) {
-   hid_err(hdev, "NULL USB device descriptor\n");
-   break;
-   }
-   bcdDevice = le16_to_cpu(udesc->bcdDevice);
-   rev_maj = bcdDevice >> 8;
-   rev_min = bcdDevice & 0xff;
-
-   /* Update the report descriptor for only the Driving Force 
wheel */
-   if (rev_maj == 1 && rev_min == 2 &&
-   *rsize == DF_RDESC_ORIG_SIZE) {
+   if (*rsize == DF_RDESC_ORIG_SIZE) {
hid_info(hdev,
"fixing up Logitech Driving Force report 
descriptor\n");
rdesc = df_rdesc_fixed;
-- 
2.7.4



[Patch-V2 2/6] HID:hid-logitech: Add combined pedal support Logitech wheels

2016-09-18 Thread Simon Wood
Add support for reporting a combined accelerator/brake axis for wheels
which contain combined data in their HID stream.

This includes DF, MOMO, MOMO2 and DFP.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg.c| 12 
 drivers/hid/hid-lg4ff.c | 32 
 drivers/hid/hid-lg4ff.h |  4 
 3 files changed, 48 insertions(+)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index feb2be7..06f8a5e 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -657,6 +657,17 @@ static int lg_event(struct hid_device *hdev, struct 
hid_field *field,
return 0;
 }
 
+static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size)
+{
+   struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
+
+   if (drv_data->quirks & LG_FF4)
+   return lg4ff_raw_event(hdev, report, rd, size, drv_data);
+
+   return 0;
+}
+
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
@@ -830,6 +841,7 @@ static struct hid_driver lg_driver = {
.input_mapping = lg_input_mapping,
.input_mapped = lg_input_mapped,
.event = lg_event,
+   .raw_event = lg_raw_event,
.probe = lg_probe,
.remove = lg_remove,
 };
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index ca31ce4..79d34c2 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -329,6 +329,38 @@ int lg4ff_adjust_input_event(struct hid_device *hid, 
struct hid_field *field,
}
 }
 
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data)
+{
+   struct lg4ff_device_entry *entry = drv_data->device_props;
+
+   if (!entry)
+   return 0;
+
+   /* adjust HID report present combined pedals data */
+   if (entry->wdata.combine) {
+   switch (entry->wdata.product_id) {
+   case USB_DEVICE_ID_LOGITECH_WHEEL:
+   rd[5] = rd[3];
+   rd[6] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+   rd[4] = rd[3];
+   rd[5] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+   rd[5] = rd[4];
+   rd[6] = 0x7F;
+   return 1;
+   default:
+   return 0;
+   }
+   }
+
+   return 0;
+}
+
 static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const 
struct lg4ff_wheel *wheel,
  const struct lg4ff_multimode_wheel 
*mmode_wheel,
  const u16 real_product_id)
diff --git a/drivers/hid/hid-lg4ff.h b/drivers/hid/hid-lg4ff.h
index 66201af..de1f350 100644
--- a/drivers/hid/hid-lg4ff.h
+++ b/drivers/hid/hid-lg4ff.h
@@ -6,11 +6,15 @@ extern int lg4ff_no_autoswitch; /* From hid-lg.c */
 
 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
 struct hid_usage *usage, s32 value, struct 
lg_drv_data *drv_data);
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data);
 int lg4ff_init(struct hid_device *hdev);
 int lg4ff_deinit(struct hid_device *hdev);
 #else
 static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
   struct hid_usage *usage, s32 value, 
struct lg_drv_data *drv_data) { return 0; }
+static inline int lg4ff_raw_event(struct hid_device *hdev, struct hid_report 
*report,
+   u8 *rd, int size, struct lg_drv_data *drv_data) { return 0; }
 static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
 static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
 #endif
-- 
2.7.4



[Patch-V2 2/6] HID:hid-logitech: Add combined pedal support Logitech wheels

2016-09-18 Thread Simon Wood
Add support for reporting a combined accelerator/brake axis for wheels
which contain combined data in their HID stream.

This includes DF, MOMO, MOMO2 and DFP.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg.c| 12 
 drivers/hid/hid-lg4ff.c | 32 
 drivers/hid/hid-lg4ff.h |  4 
 3 files changed, 48 insertions(+)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index feb2be7..06f8a5e 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -657,6 +657,17 @@ static int lg_event(struct hid_device *hdev, struct 
hid_field *field,
return 0;
 }
 
+static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size)
+{
+   struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
+
+   if (drv_data->quirks & LG_FF4)
+   return lg4ff_raw_event(hdev, report, rd, size, drv_data);
+
+   return 0;
+}
+
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
@@ -830,6 +841,7 @@ static struct hid_driver lg_driver = {
.input_mapping = lg_input_mapping,
.input_mapped = lg_input_mapped,
.event = lg_event,
+   .raw_event = lg_raw_event,
.probe = lg_probe,
.remove = lg_remove,
 };
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index ca31ce4..79d34c2 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -329,6 +329,38 @@ int lg4ff_adjust_input_event(struct hid_device *hid, 
struct hid_field *field,
}
 }
 
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data)
+{
+   struct lg4ff_device_entry *entry = drv_data->device_props;
+
+   if (!entry)
+   return 0;
+
+   /* adjust HID report present combined pedals data */
+   if (entry->wdata.combine) {
+   switch (entry->wdata.product_id) {
+   case USB_DEVICE_ID_LOGITECH_WHEEL:
+   rd[5] = rd[3];
+   rd[6] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+   rd[4] = rd[3];
+   rd[5] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+   rd[5] = rd[4];
+   rd[6] = 0x7F;
+   return 1;
+   default:
+   return 0;
+   }
+   }
+
+   return 0;
+}
+
 static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const 
struct lg4ff_wheel *wheel,
  const struct lg4ff_multimode_wheel 
*mmode_wheel,
  const u16 real_product_id)
diff --git a/drivers/hid/hid-lg4ff.h b/drivers/hid/hid-lg4ff.h
index 66201af..de1f350 100644
--- a/drivers/hid/hid-lg4ff.h
+++ b/drivers/hid/hid-lg4ff.h
@@ -6,11 +6,15 @@ extern int lg4ff_no_autoswitch; /* From hid-lg.c */
 
 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
 struct hid_usage *usage, s32 value, struct 
lg_drv_data *drv_data);
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data);
 int lg4ff_init(struct hid_device *hdev);
 int lg4ff_deinit(struct hid_device *hdev);
 #else
 static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
   struct hid_usage *usage, s32 value, 
struct lg_drv_data *drv_data) { return 0; }
+static inline int lg4ff_raw_event(struct hid_device *hdev, struct hid_report 
*report,
+   u8 *rd, int size, struct lg_drv_data *drv_data) { return 0; }
 static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
 static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
 #endif
-- 
2.7.4



[Patch-V2 3/6] HID:hid-logitech: Compute combined pedals value

2016-09-18 Thread Simon Wood
Add support for computing a combined accelerator/brake axis for wheels
which don't contain combined data in their HID stream.

This includes DFGT, G25, G27, G29 and Wii-Wheel.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg4ff.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 79d34c2..cc5c9ebd 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -332,6 +332,7 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
 int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *rd, int size, struct lg_drv_data *drv_data)
 {
+   int offset;
struct lg4ff_device_entry *entry = drv_data->device_props;
 
if (!entry)
@@ -353,9 +354,25 @@ int lg4ff_raw_event(struct hid_device *hdev, struct 
hid_report *report,
rd[5] = rd[4];
rd[6] = 0x7F;
return 1;
+   case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+   offset = 5;
+   break;
+   case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+   offset = 6;
+   break;
+   case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
+   offset = 3;
+   break;
default:
return 0;
}
+
+   /* Compute a combined axis when wheel does not supply it */
+   rd[offset] = (0xFF + rd[offset] - rd[offset+1]) >> 1;
+   rd[offset+1] = 0x7F;
+   return 1;
}
 
return 0;
-- 
2.7.4



[Patch-V2 3/6] HID:hid-logitech: Compute combined pedals value

2016-09-18 Thread Simon Wood
Add support for computing a combined accelerator/brake axis for wheels
which don't contain combined data in their HID stream.

This includes DFGT, G25, G27, G29 and Wii-Wheel.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg4ff.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 79d34c2..cc5c9ebd 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -332,6 +332,7 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
 int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *rd, int size, struct lg_drv_data *drv_data)
 {
+   int offset;
struct lg4ff_device_entry *entry = drv_data->device_props;
 
if (!entry)
@@ -353,9 +354,25 @@ int lg4ff_raw_event(struct hid_device *hdev, struct 
hid_report *report,
rd[5] = rd[4];
rd[6] = 0x7F;
return 1;
+   case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+   offset = 5;
+   break;
+   case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+   offset = 6;
+   break;
+   case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
+   offset = 3;
+   break;
default:
return 0;
}
+
+   /* Compute a combined axis when wheel does not supply it */
+   rd[offset] = (0xFF + rd[offset] - rd[offset+1]) >> 1;
+   rd[offset+1] = 0x7F;
+   return 1;
}
 
return 0;
-- 
2.7.4



[Patch-V2 1/6] HID:hid-logitech: Introduce control for combined pedals feature

2016-09-18 Thread Simon Wood
Introduce a dev_attr which can be used to combine the accelerator
and brake pedals into a single axis. This is useful for older games
which can not handle seperate accelerator and brake.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 .../ABI/testing/sysfs-driver-hid-logitech-lg4ff|  9 
 drivers/hid/hid-lg4ff.c| 58 ++
 2 files changed, 67 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index db197a8..9cd7c5a 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -50,3 +50,12 @@ Description: Displays the real model of the wheel regardless 
of any
alternate mode the wheel might be switched to.
It is a read-only value.
This entry is not created for devices that have only one mode.
+
+What:  /sys/bus/hid/drivers/logitech//combine_pedals
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Simon Wood <si...@mungewell.org>
+Description:   Controls whether a combined value of accelerator and brake is
+   reported on the Y axis of the controller. Useful for older games
+   which can do not work with separate accelerator/brake axis.
+   Off ('0') by default, enabled by setting '1'.
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index af3a8ec..ca31ce4 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -75,6 +75,7 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 
range);
 
 struct lg4ff_wheel_data {
const u32 product_id;
+   u16 combine;
u16 range;
const u16 min_range;
const u16 max_range;
@@ -345,6 +346,7 @@ static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * 
const wdata, const s
{
struct lg4ff_wheel_data t_wdata =  { .product_id = 
wheel->product_id,
 .real_product_id = 
real_product_id,
+.combine = 0,
 .min_range = 
wheel->min_range,
 .max_range = 
wheel->max_range,
 .set_range = 
wheel->set_range,
@@ -885,6 +887,58 @@ static ssize_t lg4ff_alternate_modes_store(struct device 
*dev, struct device_att
 }
 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
 
+static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   size_t count;
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return 0;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return 0;
+   }
+
+   count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine);
+   return count;
+}
+
+static ssize_t lg4ff_combine_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   u16 combine = simple_strtoul(buf, NULL, 10);
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return -EINVAL;
+   }
+
+   if (combine > 1)
+   combine = 1;
+
+   entry->wdata.combine = combine;
+   return count;
+}
+static DEVICE_ATTR(combine_pedals, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_combine_show, lg4ff_combine_store);
+
 /* Export the currently set range of the wheel */
 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute 
*attr,
char *buf)
@@ -1259,6 +1313,9 @@ int lg4ff_init(struct hid_device *hid)
}
 
/* Create sysfs interface */
+   error = device_create_file(>dev, _attr_combine_pedals);
+   if (error)
+   hid_warn(hid, "Unable to create sysfs interface for 
\"combine\", errno %d\n", error);
error = device_create_file(>dev, _attr_ra

[Patch-V2 1/6] HID:hid-logitech: Introduce control for combined pedals feature

2016-09-18 Thread Simon Wood
Introduce a dev_attr which can be used to combine the accelerator
and brake pedals into a single axis. This is useful for older games
which can not handle seperate accelerator and brake.

Signed-off-by: Simon Wood 
---
 .../ABI/testing/sysfs-driver-hid-logitech-lg4ff|  9 
 drivers/hid/hid-lg4ff.c| 58 ++
 2 files changed, 67 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index db197a8..9cd7c5a 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -50,3 +50,12 @@ Description: Displays the real model of the wheel regardless 
of any
alternate mode the wheel might be switched to.
It is a read-only value.
This entry is not created for devices that have only one mode.
+
+What:  /sys/bus/hid/drivers/logitech//combine_pedals
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Simon Wood 
+Description:   Controls whether a combined value of accelerator and brake is
+   reported on the Y axis of the controller. Useful for older games
+   which can do not work with separate accelerator/brake axis.
+   Off ('0') by default, enabled by setting '1'.
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index af3a8ec..ca31ce4 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -75,6 +75,7 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 
range);
 
 struct lg4ff_wheel_data {
const u32 product_id;
+   u16 combine;
u16 range;
const u16 min_range;
const u16 max_range;
@@ -345,6 +346,7 @@ static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * 
const wdata, const s
{
struct lg4ff_wheel_data t_wdata =  { .product_id = 
wheel->product_id,
 .real_product_id = 
real_product_id,
+.combine = 0,
 .min_range = 
wheel->min_range,
 .max_range = 
wheel->max_range,
 .set_range = 
wheel->set_range,
@@ -885,6 +887,58 @@ static ssize_t lg4ff_alternate_modes_store(struct device 
*dev, struct device_att
 }
 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
 
+static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   size_t count;
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return 0;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return 0;
+   }
+
+   count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine);
+   return count;
+}
+
+static ssize_t lg4ff_combine_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   u16 combine = simple_strtoul(buf, NULL, 10);
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return -EINVAL;
+   }
+
+   if (combine > 1)
+   combine = 1;
+
+   entry->wdata.combine = combine;
+   return count;
+}
+static DEVICE_ATTR(combine_pedals, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_combine_show, lg4ff_combine_store);
+
 /* Export the currently set range of the wheel */
 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute 
*attr,
char *buf)
@@ -1259,6 +1313,9 @@ int lg4ff_init(struct hid_device *hid)
}
 
/* Create sysfs interface */
+   error = device_create_file(>dev, _attr_combine_pedals);
+   if (error)
+   hid_warn(hid, "Unable to create sysfs interface for 
\"combine\", errno %d\n", error);
error = device_create_file(>dev, _attr_range);
if (error)
hid_war

Re: [PATCH 4/5] HID:hid-logitech: Rewrite of descriptor for all DF wheels

2016-09-14 Thread Simon Wood
On Fri, September 9, 2016 7:34 pm, kbuild test robot wrote:
> All warnings (new ones prefixed by >>):
>
>
> drivers/hid/hid-lg.c: In function 'lg_report_fixup':
>
>>> drivers/hid/hid-lg.c:347:28: warning: unused variable 'rev_min'
>>> [-Wunused-variable]
>>>
> __u16 bcdDevice, rev_maj, rev_min;
> ^
>
>>> drivers/hid/hid-lg.c:347:19: warning: unused variable 'rev_maj'
>>> [-Wunused-variable]
>>>
> __u16 bcdDevice, rev_maj, rev_min;
> ^
>
>>> drivers/hid/hid-lg.c:347:8: warning: unused variable 'bcdDevice'
>>> [-Wunused-variable]
>>>
> __u16 bcdDevice, rev_maj, rev_min;
> ^
>
>>> drivers/hid/hid-lg.c:346:32: warning: unused variable 'udesc'
>>> [-Wunused-variable]
>>>
> struct usb_device_descriptor *udesc; ^

Hi all,
No other comments from the rest of the patch set (so far), so I'll send a
V2 patch set to cover these towards the end of the week.

Also have better support for the "Wingman Forumula Force GT" to include,
as I picked one up cheap on Kijiji.
Simon.



Re: [PATCH 4/5] HID:hid-logitech: Rewrite of descriptor for all DF wheels

2016-09-14 Thread Simon Wood
On Fri, September 9, 2016 7:34 pm, kbuild test robot wrote:
> All warnings (new ones prefixed by >>):
>
>
> drivers/hid/hid-lg.c: In function 'lg_report_fixup':
>
>>> drivers/hid/hid-lg.c:347:28: warning: unused variable 'rev_min'
>>> [-Wunused-variable]
>>>
> __u16 bcdDevice, rev_maj, rev_min;
> ^
>
>>> drivers/hid/hid-lg.c:347:19: warning: unused variable 'rev_maj'
>>> [-Wunused-variable]
>>>
> __u16 bcdDevice, rev_maj, rev_min;
> ^
>
>>> drivers/hid/hid-lg.c:347:8: warning: unused variable 'bcdDevice'
>>> [-Wunused-variable]
>>>
> __u16 bcdDevice, rev_maj, rev_min;
> ^
>
>>> drivers/hid/hid-lg.c:346:32: warning: unused variable 'udesc'
>>> [-Wunused-variable]
>>>
> struct usb_device_descriptor *udesc; ^

Hi all,
No other comments from the rest of the patch set (so far), so I'll send a
V2 patch set to cover these towards the end of the week.

Also have better support for the "Wingman Forumula Force GT" to include,
as I picked one up cheap on Kijiji.
Simon.



[PATCH 5/5] HID:hid-logitech: Documentation updates/corrections

2016-09-09 Thread Simon Wood
Signed-off-by: Simon Wood <si...@mungewell.org>
---
 Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff | 6 ++
 drivers/hid/Kconfig   | 6 +++---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index 69fb890..36e4d68 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -35,6 +35,12 @@ Description: Displays a set of alternate modes supported by 
a wheel. Each
  DF-EX <*> G25 <-> G27
  DF-EX <*> G27
 
+   G29:
+ DF-EX <*> DFP <-> G25 <-> G27 <-> G29
+ DF-EX <*> G25 <-> G27 <-> G29
+ DF-EX <*> G27 <-> G29
+ DF-EX <*> G29
+
DFGT:
  DF-EX <*> DFP <-> DFGT
  DF-EX <*> DFGT
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 78ac481..bebf89c0 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -457,8 +457,6 @@ config LOGITECH_FF
  - Logitech WingMan Cordless RumblePad
  - Logitech WingMan Cordless RumblePad 2
  - Logitech WingMan Force 3D
- - Logitech Formula Force EX
- - Logitech WingMan Formula Force GP
 
  and if you want to enable force feedback for them.
  Note: if you say N here, this device will still be supported, but 
without
@@ -491,12 +489,14 @@ config LOGIWHEELS_FF
  Say Y here if you want to enable force feedback and range setting
  support for following Logitech wheels:
  - Logitech Driving Force
+ - Logitech Driving Force EX
  - Logitech Driving Force Pro
  - Logitech Driving Force GT
  - Logitech G25
  - Logitech G27
+ - Logitech G29
  - Logitech MOMO/MOMO 2
- - Logitech Formula Force EX
+ - Logitech Formula Force EX/FX/GP
 
 config HID_MAGICMOUSE
tristate "Apple Magic Mouse/Trackpad multi-touch support"
-- 
2.7.4



[PATCH 4/5] HID:hid-logitech: Rewrite of descriptor for all DF wheels

2016-09-09 Thread Simon Wood
Rewrite the HID descriptor for _all_ Driving Force wheels (real
or emulated) so that they can report separate Accelerator and
Brake axis.

If the user wants a combined accel/brake axis, they can use the
'combined pedals' feature.

$ echo 1 > /sys/bus/hid/devices//combine_pedals

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg.c | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 06f8a5e..53429c6 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -365,18 +365,7 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
 
/* Several wheels report as this id when operating in emulation mode. */
case USB_DEVICE_ID_LOGITECH_WHEEL:
-   udesc = &(hid_to_usb_dev(hdev)->descriptor);
-   if (!udesc) {
-   hid_err(hdev, "NULL USB device descriptor\n");
-   break;
-   }
-   bcdDevice = le16_to_cpu(udesc->bcdDevice);
-   rev_maj = bcdDevice >> 8;
-   rev_min = bcdDevice & 0xff;
-
-   /* Update the report descriptor for only the Driving Force 
wheel */
-   if (rev_maj == 1 && rev_min == 2 &&
-   *rsize == DF_RDESC_ORIG_SIZE) {
+   if (*rsize == DF_RDESC_ORIG_SIZE) {
hid_info(hdev,
"fixing up Logitech Driving Force report 
descriptor\n");
rdesc = df_rdesc_fixed;
-- 
2.7.4



[PATCH 5/5] HID:hid-logitech: Documentation updates/corrections

2016-09-09 Thread Simon Wood
Signed-off-by: Simon Wood 
---
 Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff | 6 ++
 drivers/hid/Kconfig   | 6 +++---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index 69fb890..36e4d68 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -35,6 +35,12 @@ Description: Displays a set of alternate modes supported by 
a wheel. Each
  DF-EX <*> G25 <-> G27
  DF-EX <*> G27
 
+   G29:
+ DF-EX <*> DFP <-> G25 <-> G27 <-> G29
+ DF-EX <*> G25 <-> G27 <-> G29
+ DF-EX <*> G27 <-> G29
+ DF-EX <*> G29
+
DFGT:
  DF-EX <*> DFP <-> DFGT
  DF-EX <*> DFGT
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 78ac481..bebf89c0 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -457,8 +457,6 @@ config LOGITECH_FF
  - Logitech WingMan Cordless RumblePad
  - Logitech WingMan Cordless RumblePad 2
  - Logitech WingMan Force 3D
- - Logitech Formula Force EX
- - Logitech WingMan Formula Force GP
 
  and if you want to enable force feedback for them.
  Note: if you say N here, this device will still be supported, but 
without
@@ -491,12 +489,14 @@ config LOGIWHEELS_FF
  Say Y here if you want to enable force feedback and range setting
  support for following Logitech wheels:
  - Logitech Driving Force
+ - Logitech Driving Force EX
  - Logitech Driving Force Pro
  - Logitech Driving Force GT
  - Logitech G25
  - Logitech G27
+ - Logitech G29
  - Logitech MOMO/MOMO 2
- - Logitech Formula Force EX
+ - Logitech Formula Force EX/FX/GP
 
 config HID_MAGICMOUSE
tristate "Apple Magic Mouse/Trackpad multi-touch support"
-- 
2.7.4



[PATCH 4/5] HID:hid-logitech: Rewrite of descriptor for all DF wheels

2016-09-09 Thread Simon Wood
Rewrite the HID descriptor for _all_ Driving Force wheels (real
or emulated) so that they can report separate Accelerator and
Brake axis.

If the user wants a combined accel/brake axis, they can use the
'combined pedals' feature.

$ echo 1 > /sys/bus/hid/devices//combine_pedals

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg.c | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 06f8a5e..53429c6 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -365,18 +365,7 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 
*rdesc,
 
/* Several wheels report as this id when operating in emulation mode. */
case USB_DEVICE_ID_LOGITECH_WHEEL:
-   udesc = &(hid_to_usb_dev(hdev)->descriptor);
-   if (!udesc) {
-   hid_err(hdev, "NULL USB device descriptor\n");
-   break;
-   }
-   bcdDevice = le16_to_cpu(udesc->bcdDevice);
-   rev_maj = bcdDevice >> 8;
-   rev_min = bcdDevice & 0xff;
-
-   /* Update the report descriptor for only the Driving Force 
wheel */
-   if (rev_maj == 1 && rev_min == 2 &&
-   *rsize == DF_RDESC_ORIG_SIZE) {
+   if (*rsize == DF_RDESC_ORIG_SIZE) {
hid_info(hdev,
"fixing up Logitech Driving Force report 
descriptor\n");
rdesc = df_rdesc_fixed;
-- 
2.7.4



[PATCH 2/5] HID:hid-logitech: Add combined pedal support Logitech wheels

2016-09-09 Thread Simon Wood
Add support for reporting a combined accelerator/brake axis for wheels
which contain combined data in their HID stream.

This includes DF, MOMO, MOMO2 and DFP.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg.c| 12 
 drivers/hid/hid-lg4ff.c | 32 
 drivers/hid/hid-lg4ff.h |  4 
 3 files changed, 48 insertions(+)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index feb2be7..06f8a5e 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -657,6 +657,17 @@ static int lg_event(struct hid_device *hdev, struct 
hid_field *field,
return 0;
 }
 
+static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size)
+{
+   struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
+
+   if (drv_data->quirks & LG_FF4)
+   return lg4ff_raw_event(hdev, report, rd, size, drv_data);
+
+   return 0;
+}
+
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
@@ -830,6 +841,7 @@ static struct hid_driver lg_driver = {
.input_mapping = lg_input_mapping,
.input_mapped = lg_input_mapped,
.event = lg_event,
+   .raw_event = lg_raw_event,
.probe = lg_probe,
.remove = lg_remove,
 };
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index ca31ce4..79d34c2 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -329,6 +329,38 @@ int lg4ff_adjust_input_event(struct hid_device *hid, 
struct hid_field *field,
}
 }
 
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data)
+{
+   struct lg4ff_device_entry *entry = drv_data->device_props;
+
+   if (!entry)
+   return 0;
+
+   /* adjust HID report present combined pedals data */
+   if (entry->wdata.combine) {
+   switch (entry->wdata.product_id) {
+   case USB_DEVICE_ID_LOGITECH_WHEEL:
+   rd[5] = rd[3];
+   rd[6] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+   rd[4] = rd[3];
+   rd[5] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+   rd[5] = rd[4];
+   rd[6] = 0x7F;
+   return 1;
+   default:
+   return 0;
+   }
+   }
+
+   return 0;
+}
+
 static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const 
struct lg4ff_wheel *wheel,
  const struct lg4ff_multimode_wheel 
*mmode_wheel,
  const u16 real_product_id)
diff --git a/drivers/hid/hid-lg4ff.h b/drivers/hid/hid-lg4ff.h
index 66201af..de1f350 100644
--- a/drivers/hid/hid-lg4ff.h
+++ b/drivers/hid/hid-lg4ff.h
@@ -6,11 +6,15 @@ extern int lg4ff_no_autoswitch; /* From hid-lg.c */
 
 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
 struct hid_usage *usage, s32 value, struct 
lg_drv_data *drv_data);
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data);
 int lg4ff_init(struct hid_device *hdev);
 int lg4ff_deinit(struct hid_device *hdev);
 #else
 static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
   struct hid_usage *usage, s32 value, 
struct lg_drv_data *drv_data) { return 0; }
+static inline int lg4ff_raw_event(struct hid_device *hdev, struct hid_report 
*report,
+   u8 *rd, int size, struct lg_drv_data *drv_data) { return 0; }
 static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
 static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
 #endif
-- 
2.7.4



[PATCH 2/5] HID:hid-logitech: Add combined pedal support Logitech wheels

2016-09-09 Thread Simon Wood
Add support for reporting a combined accelerator/brake axis for wheels
which contain combined data in their HID stream.

This includes DF, MOMO, MOMO2 and DFP.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg.c| 12 
 drivers/hid/hid-lg4ff.c | 32 
 drivers/hid/hid-lg4ff.h |  4 
 3 files changed, 48 insertions(+)

diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index feb2be7..06f8a5e 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -657,6 +657,17 @@ static int lg_event(struct hid_device *hdev, struct 
hid_field *field,
return 0;
 }
 
+static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size)
+{
+   struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
+
+   if (drv_data->quirks & LG_FF4)
+   return lg4ff_raw_event(hdev, report, rd, size, drv_data);
+
+   return 0;
+}
+
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
@@ -830,6 +841,7 @@ static struct hid_driver lg_driver = {
.input_mapping = lg_input_mapping,
.input_mapped = lg_input_mapped,
.event = lg_event,
+   .raw_event = lg_raw_event,
.probe = lg_probe,
.remove = lg_remove,
 };
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index ca31ce4..79d34c2 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -329,6 +329,38 @@ int lg4ff_adjust_input_event(struct hid_device *hid, 
struct hid_field *field,
}
 }
 
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data)
+{
+   struct lg4ff_device_entry *entry = drv_data->device_props;
+
+   if (!entry)
+   return 0;
+
+   /* adjust HID report present combined pedals data */
+   if (entry->wdata.combine) {
+   switch (entry->wdata.product_id) {
+   case USB_DEVICE_ID_LOGITECH_WHEEL:
+   rd[5] = rd[3];
+   rd[6] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+   rd[4] = rd[3];
+   rd[5] = 0x7F;
+   return 1;
+   case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+   rd[5] = rd[4];
+   rd[6] = 0x7F;
+   return 1;
+   default:
+   return 0;
+   }
+   }
+
+   return 0;
+}
+
 static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const 
struct lg4ff_wheel *wheel,
  const struct lg4ff_multimode_wheel 
*mmode_wheel,
  const u16 real_product_id)
diff --git a/drivers/hid/hid-lg4ff.h b/drivers/hid/hid-lg4ff.h
index 66201af..de1f350 100644
--- a/drivers/hid/hid-lg4ff.h
+++ b/drivers/hid/hid-lg4ff.h
@@ -6,11 +6,15 @@ extern int lg4ff_no_autoswitch; /* From hid-lg.c */
 
 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
 struct hid_usage *usage, s32 value, struct 
lg_drv_data *drv_data);
+int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
+   u8 *rd, int size, struct lg_drv_data *drv_data);
 int lg4ff_init(struct hid_device *hdev);
 int lg4ff_deinit(struct hid_device *hdev);
 #else
 static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
   struct hid_usage *usage, s32 value, 
struct lg_drv_data *drv_data) { return 0; }
+static inline int lg4ff_raw_event(struct hid_device *hdev, struct hid_report 
*report,
+   u8 *rd, int size, struct lg_drv_data *drv_data) { return 0; }
 static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
 static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
 #endif
-- 
2.7.4



[PATCH 3/5] HID:hid-logitech: Compute combined pedals if not supplied

2016-09-09 Thread Simon Wood
Add support for computing a combined accelerator/brake axis for wheels
which don't contain combined data in their HID stream.

This includes DFGT, G25, G27, G29 and Wii-Wheel.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg4ff.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 79d34c2..cc5c9ebd 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -332,6 +332,7 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
 int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *rd, int size, struct lg_drv_data *drv_data)
 {
+   int offset;
struct lg4ff_device_entry *entry = drv_data->device_props;
 
if (!entry)
@@ -353,9 +354,25 @@ int lg4ff_raw_event(struct hid_device *hdev, struct 
hid_report *report,
rd[5] = rd[4];
rd[6] = 0x7F;
return 1;
+   case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+   offset = 5;
+   break;
+   case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+   offset = 6;
+   break;
+   case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
+   offset = 3;
+   break;
default:
return 0;
}
+
+   /* Compute a combined axis when wheel does not supply it */
+   rd[offset] = (0xFF + rd[offset] - rd[offset+1]) >> 1;
+   rd[offset+1] = 0x7F;
+   return 1;
}
 
return 0;
-- 
2.7.4



[PATCH 1/5] HID:hid-logitech: Introduce dev_attr for combined pedals feature

2016-09-09 Thread Simon Wood
Introduce a dev_attr which can be used to combine the accelerator
and brake pedals into a single axis. This is useful for older games
which can not handle separate accelerator and brake.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 .../ABI/testing/sysfs-driver-hid-logitech-lg4ff|  9 
 drivers/hid/hid-lg4ff.c| 58 ++
 2 files changed, 67 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index db197a8..69fb890 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -50,3 +50,12 @@ Description: Displays the real model of the wheel regardless 
of any
alternate mode the wheel might be switched to.
It is a read-only value.
This entry is not created for devices that have only one mode.
+
+What:  /sys/bus/hid/drivers/logitech//combine_pedals
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Simon Wood <si...@mungewell.org>
+Description:   Controls whether a combined value of accelerator and brake is
+   reported on the Y axis of the controller. Useful for older games
+   which can do not work with separate accelerator/brake axis.
+   Off ('0') by default, enabled by setting '1'.
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index af3a8ec..ca31ce4 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -75,6 +75,7 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 
range);
 
 struct lg4ff_wheel_data {
const u32 product_id;
+   u16 combine;
u16 range;
const u16 min_range;
const u16 max_range;
@@ -345,6 +346,7 @@ static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * 
const wdata, const s
{
struct lg4ff_wheel_data t_wdata =  { .product_id = 
wheel->product_id,
 .real_product_id = 
real_product_id,
+.combine = 0,
 .min_range = 
wheel->min_range,
 .max_range = 
wheel->max_range,
 .set_range = 
wheel->set_range,
@@ -885,6 +887,58 @@ static ssize_t lg4ff_alternate_modes_store(struct device 
*dev, struct device_att
 }
 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
 
+static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   size_t count;
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return 0;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return 0;
+   }
+
+   count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine);
+   return count;
+}
+
+static ssize_t lg4ff_combine_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   u16 combine = simple_strtoul(buf, NULL, 10);
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return -EINVAL;
+   }
+
+   if (combine > 1)
+   combine = 1;
+
+   entry->wdata.combine = combine;
+   return count;
+}
+static DEVICE_ATTR(combine_pedals, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_combine_show, lg4ff_combine_store);
+
 /* Export the currently set range of the wheel */
 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute 
*attr,
char *buf)
@@ -1259,6 +1313,9 @@ int lg4ff_init(struct hid_device *hid)
}
 
/* Create sysfs interface */
+   error = device_create_file(>dev, _attr_combine_pedals);
+   if (error)
+   hid_warn(hid, "Unable to create sysfs interface for 
\"combine\", errno %d\n", error);
error = device_create_file(>dev, _attr_ra

[PATCH 1/5] HID:hid-logitech: Introduce dev_attr for combined pedals feature

2016-09-09 Thread Simon Wood
Introduce a dev_attr which can be used to combine the accelerator
and brake pedals into a single axis. This is useful for older games
which can not handle separate accelerator and brake.

Signed-off-by: Simon Wood 
---
 .../ABI/testing/sysfs-driver-hid-logitech-lg4ff|  9 
 drivers/hid/hid-lg4ff.c| 58 ++
 2 files changed, 67 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff 
b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index db197a8..69fb890 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -50,3 +50,12 @@ Description: Displays the real model of the wheel regardless 
of any
alternate mode the wheel might be switched to.
It is a read-only value.
This entry is not created for devices that have only one mode.
+
+What:  /sys/bus/hid/drivers/logitech//combine_pedals
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Simon Wood 
+Description:   Controls whether a combined value of accelerator and brake is
+   reported on the Y axis of the controller. Useful for older games
+   which can do not work with separate accelerator/brake axis.
+   Off ('0') by default, enabled by setting '1'.
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index af3a8ec..ca31ce4 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -75,6 +75,7 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 
range);
 
 struct lg4ff_wheel_data {
const u32 product_id;
+   u16 combine;
u16 range;
const u16 min_range;
const u16 max_range;
@@ -345,6 +346,7 @@ static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * 
const wdata, const s
{
struct lg4ff_wheel_data t_wdata =  { .product_id = 
wheel->product_id,
 .real_product_id = 
real_product_id,
+.combine = 0,
 .min_range = 
wheel->min_range,
 .max_range = 
wheel->max_range,
 .set_range = 
wheel->set_range,
@@ -885,6 +887,58 @@ static ssize_t lg4ff_alternate_modes_store(struct device 
*dev, struct device_att
 }
 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
 
+static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   size_t count;
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return 0;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return 0;
+   }
+
+   count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine);
+   return count;
+}
+
+static ssize_t lg4ff_combine_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct lg4ff_device_entry *entry;
+   struct lg_drv_data *drv_data;
+   u16 combine = simple_strtoul(buf, NULL, 10);
+
+   drv_data = hid_get_drvdata(hid);
+   if (!drv_data) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   entry = drv_data->device_props;
+   if (!entry) {
+   hid_err(hid, "Device properties not found!\n");
+   return -EINVAL;
+   }
+
+   if (combine > 1)
+   combine = 1;
+
+   entry->wdata.combine = combine;
+   return count;
+}
+static DEVICE_ATTR(combine_pedals, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
S_IROTH, lg4ff_combine_show, lg4ff_combine_store);
+
 /* Export the currently set range of the wheel */
 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute 
*attr,
char *buf)
@@ -1259,6 +1313,9 @@ int lg4ff_init(struct hid_device *hid)
}
 
/* Create sysfs interface */
+   error = device_create_file(>dev, _attr_combine_pedals);
+   if (error)
+   hid_warn(hid, "Unable to create sysfs interface for 
\"combine\", errno %d\n", error);
error = device_create_file(>dev, _attr_range);
if (error)
hid_war

[PATCH 3/5] HID:hid-logitech: Compute combined pedals if not supplied

2016-09-09 Thread Simon Wood
Add support for computing a combined accelerator/brake axis for wheels
which don't contain combined data in their HID stream.

This includes DFGT, G25, G27, G29 and Wii-Wheel.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg4ff.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 79d34c2..cc5c9ebd 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -332,6 +332,7 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct 
hid_field *field,
 int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *rd, int size, struct lg_drv_data *drv_data)
 {
+   int offset;
struct lg4ff_device_entry *entry = drv_data->device_props;
 
if (!entry)
@@ -353,9 +354,25 @@ int lg4ff_raw_event(struct hid_device *hdev, struct 
hid_report *report,
rd[5] = rd[4];
rd[6] = 0x7F;
return 1;
+   case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+   offset = 5;
+   break;
+   case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+   case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+   offset = 6;
+   break;
+   case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
+   offset = 3;
+   break;
default:
return 0;
}
+
+   /* Compute a combined axis when wheel does not supply it */
+   rd[offset] = (0xFF + rd[offset] - rd[offset+1]) >> 1;
+   rd[offset+1] = 0x7F;
+   return 1;
}
 
return 0;
-- 
2.7.4



Re: RFC: Backport HID-logitech to 3.10?

2016-09-02 Thread Simon Wood
On Fri, September 2, 2016 3:32 am, Benjamin Tissoires wrote:
> On Thu, Sep 1, 2016 at 2:56 AM, Simon Wood <si...@mungewell.org> wrote:
>> After copying the HEAD 'hid-lg.[ch]' and 'hid-lg4ff.[ch]' from 4.7,
>> there is a minimal patch (example attached) required to get the build
>> working.
>
> Don't you need hid-logitech-hidpp too?

Hi Benjamin,
Nope, the 'hid-logitech-hidpp.ko' driver is separate and (for wheels) only
has support for the G920 wheel. Other Logitech wheels are handled by
'hid-logitech.ko'.

> Not sure I understand exactly what you want from us here.

A puppy. ;-)

> The stable rules are detailed in
> Documentation/stable_kernel_rules.txt. And unfortunately, I don't
> think adding these patches will be acceptable for upstream 3.10.

After reading through these I would agree with you, that this is a
nice-to-have not a need-to-have. So, the patch is here if anyone wants to
use it personally or for a distribution.

Thank you for your comments,
Simon.



Re: RFC: Backport HID-logitech to 3.10?

2016-09-02 Thread Simon Wood
On Fri, September 2, 2016 3:32 am, Benjamin Tissoires wrote:
> On Thu, Sep 1, 2016 at 2:56 AM, Simon Wood  wrote:
>> After copying the HEAD 'hid-lg.[ch]' and 'hid-lg4ff.[ch]' from 4.7,
>> there is a minimal patch (example attached) required to get the build
>> working.
>
> Don't you need hid-logitech-hidpp too?

Hi Benjamin,
Nope, the 'hid-logitech-hidpp.ko' driver is separate and (for wheels) only
has support for the G920 wheel. Other Logitech wheels are handled by
'hid-logitech.ko'.

> Not sure I understand exactly what you want from us here.

A puppy. ;-)

> The stable rules are detailed in
> Documentation/stable_kernel_rules.txt. And unfortunately, I don't
> think adding these patches will be acceptable for upstream 3.10.

After reading through these I would agree with you, that this is a
nice-to-have not a need-to-have. So, the patch is here if anyone wants to
use it personally or for a distribution.

Thank you for your comments,
Simon.



RFC: Backport HID-logitech to 3.10?

2016-08-31 Thread Simon Wood
Hi all,
I received a question regarding back-porting the support for the G29
racing wheel to 3.10 (Android in particular), and after some collaborative
work we determined that changes between 3.10 and 4.7 are actually pretty
minimal and self contained.

After copying the HEAD 'hid-lg.[ch]' and 'hid-lg4ff.[ch]' from 4.7, there
is a minimal patch (example attached) required to get the build working.


My question to the list would be how this would/could be implemented, and
how the process works as 3.10 moves through the mainline patches to reach
current HEAD.

Any hints that anyone has would be appreciated.
Simon.

0002-HID-hid-logitech-backported-from-v4.7-to-v3.10.102.patch
Description: Binary data


RFC: Backport HID-logitech to 3.10?

2016-08-31 Thread Simon Wood
Hi all,
I received a question regarding back-porting the support for the G29
racing wheel to 3.10 (Android in particular), and after some collaborative
work we determined that changes between 3.10 and 4.7 are actually pretty
minimal and self contained.

After copying the HEAD 'hid-lg.[ch]' and 'hid-lg4ff.[ch]' from 4.7, there
is a minimal patch (example attached) required to get the build working.


My question to the list would be how this would/could be implemented, and
how the process works as 3.10 moves through the mainline patches to reach
current HEAD.

Any hints that anyone has would be appreciated.
Simon.

0002-HID-hid-logitech-backported-from-v4.7-to-v3.10.102.patch
Description: Binary data


Re: [PATCH-V2 1/1] HID: Force feedback support for the Logitech G920

2016-01-26 Thread Simon Wood
On Sun, January 10, 2016 4:25 pm, Edwin Velds wrote:
> This patch implements force feedback support for the Logitech
> G920 Driving Force Racing Wheel. It is a generic implementation
> of feature 0x8123 of the Logitech HID++ protocol and should be usable for
> any future devices that implement this feature.

Apologies for being slow on this (something to do with changing jobs and
accomodation ;-).

Doesn't patch cleanly on Linus' HEAD due to:
--
commit d8ce9bf5551bfea431893bdd0a943f24a5170828
Author: Geliang Tang 
Date:   Sun Dec 27 17:25:20 2015 +0800

HID: move to_hid_device() to hid.h
--

A couple of white space issues:
--
ERROR: trailing whitespace
#114: FILE: drivers/hid/hid-logitech-hidpp.c:867:
+static const u8 HIDPP_FF_CONDITION_CMDS[] = { $

ERROR: trailing whitespace
#121: FILE: drivers/hid/hid-logitech-hidpp.c:874:
+static const char *HIDPP_FF_CONDITION_NAMES[] = { $
--

Note: The wheel _DOES_NOT_ auto switch to Logitech/HID mode (it is stuck
in XBox since the xpad changes where not included). Michal has an
alternative approach documented here:
--
Create a file named "046d:c261" in "/etc/usb_modeswitch.d" with the
following content:

# Logitech G920 Racing Wheel
DefaultVendor=046d
DefaultProduct=c261
MessageEndpoint=01
ResponseEndpoint=01
TargetClass=0x03
MessageContent="0f00010142"

Then run "usb_modeswitch -c /etc/modeswitch.d/046d:c291" as root and
watch the magic happen:)
--

Apart from these few minor points, but seems to work OK - tested against
G920 with older firmware.

Tested-by: Simon Wood 




Re: [PATCH-V2 1/1] HID: Force feedback support for the Logitech G920

2016-01-26 Thread Simon Wood
On Sun, January 10, 2016 4:25 pm, Edwin Velds wrote:
> This patch implements force feedback support for the Logitech
> G920 Driving Force Racing Wheel. It is a generic implementation
> of feature 0x8123 of the Logitech HID++ protocol and should be usable for
> any future devices that implement this feature.

Apologies for being slow on this (something to do with changing jobs and
accomodation ;-).

Doesn't patch cleanly on Linus' HEAD due to:
--
commit d8ce9bf5551bfea431893bdd0a943f24a5170828
Author: Geliang Tang <geliangt...@163.com>
Date:   Sun Dec 27 17:25:20 2015 +0800

HID: move to_hid_device() to hid.h
--

A couple of white space issues:
--
ERROR: trailing whitespace
#114: FILE: drivers/hid/hid-logitech-hidpp.c:867:
+static const u8 HIDPP_FF_CONDITION_CMDS[] = { $

ERROR: trailing whitespace
#121: FILE: drivers/hid/hid-logitech-hidpp.c:874:
+static const char *HIDPP_FF_CONDITION_NAMES[] = { $
--

Note: The wheel _DOES_NOT_ auto switch to Logitech/HID mode (it is stuck
in XBox since the xpad changes where not included). Michal has an
alternative approach documented here:
--
Create a file named "046d:c261" in "/etc/usb_modeswitch.d" with the
following content:

# Logitech G920 Racing Wheel
DefaultVendor=046d
DefaultProduct=c261
MessageEndpoint=01
ResponseEndpoint=01
TargetClass=0x03
MessageContent="0f00010142"

Then run "usb_modeswitch -c /etc/modeswitch.d/046d:c291" as root and
watch the magic happen:)
--

Apart from these few minor points, but seems to work OK - tested against
G920 with older firmware.

Tested-by: Simon Wood <si...@mungewell.org>




Re: [Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2016-01-06 Thread Simon Wood
On Wed, January 6, 2016 6:47 pm, Dmitry Torokhov wrote:

> It is wrong. Aside form the fact that IMO xpad.c is the wrong place for
> this code to be in, why are we waiting for the input device to be opened by
> userspace before we do the switch instead of doing it immediately?

The 'send magic' might be better in a probe() call, but I don't believe
that it requires userspace interaction as it stands. The wheel will
disconnect almost immediately without me doing anything other than plug it
in.
--
Jan  6 21:18:50 speedster kernel: [  439.604037] usb 5-1: new full-speed
USB device number 2 using uhci_hcd
Jan  6 21:18:50 speedster kernel: [  439.791153] usb 5-1: New USB device
found, idVendor=046d, idProduct=c261
Jan  6 21:18:50 speedster kernel: [  439.791160] usb 5-1: New USB device
strings: Mfr=1, Product=2, SerialNumber=3
Jan  6 21:18:50 speedster kernel: [  439.791164] usb 5-1: Product: G920
Driving Force Racing Wheel for Xbox One
Jan  6 21:18:50 speedster kernel: [  439.791167] usb 5-1: Manufacturer:
Logitech
Jan  6 21:18:50 speedster kernel: [  439.791170] usb 5-1: SerialNumber:
5d1d5129cebe
Jan  6 21:18:50 speedster mtp-probe: checking bus 5, device 2:
"/sys/devices/pci:00/:00:1d.3/usb5/5-1"
Jan  6 21:18:50 speedster mtp-probe: bus: 5, device: 2 was not an MTP device
Jan  6 21:18:51 speedster kernel: [  440.815191] input: Logitech G920
Driving Force Racing Wheel as
/devices/pci:00/:00:1d.3/usb5/5-1/5-1:1.0/input/input4
Jan  6 21:18:51 speedster kernel: [  440.815310] usbcore: registered new
interface driver xpad
Jan  6 21:18:52 speedster kernel: [  441.340093] usb 5-1: USB disconnect,
device number 2
Jan  6 21:18:52 speedster kernel: [  442.052037] usb 5-1: new full-speed
USB device number 3 using uhci_hcd
Jan  6 21:18:52 speedster kernel: [  442.239129] usb 5-1: New USB device
found, idVendor=046d, idProduct=c262
Jan  6 21:18:52 speedster kernel: [  442.239136] usb 5-1: New USB device
strings: Mfr=1, Product=2, SerialNumber=3
Jan  6 21:18:52 speedster kernel: [  442.239139] usb 5-1: Product: G920
Driving Force Racing Wheel for Xbox One
Jan  6 21:18:52 speedster kernel: [  442.239142] usb 5-1: Manufacturer:
Logitech
Jan  6 21:18:52 speedster kernel: [  442.239145] usb 5-1: SerialNumber:
5d1d5129cebe
Jan  6 21:18:52 speedster mtp-probe: checking bus 5, device 3:
"/sys/devices/pci:00/:00:1d.3/usb5/5-1"
Jan  6 21:18:52 speedster mtp-probe: bus: 5, device: 3 was not an MTP device
Jan  6 21:18:52 speedster kernel: [  442.267248] input: Logitech G920
Driving Force Racing Wheel for Xbox One as
/devices/pci:00/:00:1d.3/usb5/5-1/5-1:1.0/0003:046D:C262.0002/input/input5
Jan  6 21:18:52 speedster kernel: [  442.267510] logitech-hidpp-device
0003:046D:C262.0002: input,hiddev0,hidraw1: USB HID v1.11 Joystick
[Logitech G920 Driving Force Racing Wheel for Xbox One] on
usb-:00:1d.3-1/input0
Jan  6 21:18:53 speedster kernel: [  442.322160] logitech-hidpp-device
0003:046D:C262.0002: HID++ 4.2 device connected.
--

I also did a quick check with the 'send magic' disabled. Xpad creates the
js0 and populates buttons, but pressing buttons/turning wheel does not
result in any change in js0.

I don't disagree to it being a seperate module, but don't have the time to
implement/test at the moment. If some else does that would be good, can we
make sure that the kconfig/makefile stuff uses same/sensible HID_CONFIGs?
Simon


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2016-01-06 Thread Simon Wood
On Wed, January 6, 2016 6:47 pm, Dmitry Torokhov wrote:

> It is wrong. Aside form the fact that IMO xpad.c is the wrong place for
> this code to be in, why are we waiting for the input device to be opened by
> userspace before we do the switch instead of doing it immediately?

The 'send magic' might be better in a probe() call, but I don't believe
that it requires userspace interaction as it stands. The wheel will
disconnect almost immediately without me doing anything other than plug it
in.
--
Jan  6 21:18:50 speedster kernel: [  439.604037] usb 5-1: new full-speed
USB device number 2 using uhci_hcd
Jan  6 21:18:50 speedster kernel: [  439.791153] usb 5-1: New USB device
found, idVendor=046d, idProduct=c261
Jan  6 21:18:50 speedster kernel: [  439.791160] usb 5-1: New USB device
strings: Mfr=1, Product=2, SerialNumber=3
Jan  6 21:18:50 speedster kernel: [  439.791164] usb 5-1: Product: G920
Driving Force Racing Wheel for Xbox One
Jan  6 21:18:50 speedster kernel: [  439.791167] usb 5-1: Manufacturer:
Logitech
Jan  6 21:18:50 speedster kernel: [  439.791170] usb 5-1: SerialNumber:
5d1d5129cebe
Jan  6 21:18:50 speedster mtp-probe: checking bus 5, device 2:
"/sys/devices/pci:00/:00:1d.3/usb5/5-1"
Jan  6 21:18:50 speedster mtp-probe: bus: 5, device: 2 was not an MTP device
Jan  6 21:18:51 speedster kernel: [  440.815191] input: Logitech G920
Driving Force Racing Wheel as
/devices/pci:00/:00:1d.3/usb5/5-1/5-1:1.0/input/input4
Jan  6 21:18:51 speedster kernel: [  440.815310] usbcore: registered new
interface driver xpad
Jan  6 21:18:52 speedster kernel: [  441.340093] usb 5-1: USB disconnect,
device number 2
Jan  6 21:18:52 speedster kernel: [  442.052037] usb 5-1: new full-speed
USB device number 3 using uhci_hcd
Jan  6 21:18:52 speedster kernel: [  442.239129] usb 5-1: New USB device
found, idVendor=046d, idProduct=c262
Jan  6 21:18:52 speedster kernel: [  442.239136] usb 5-1: New USB device
strings: Mfr=1, Product=2, SerialNumber=3
Jan  6 21:18:52 speedster kernel: [  442.239139] usb 5-1: Product: G920
Driving Force Racing Wheel for Xbox One
Jan  6 21:18:52 speedster kernel: [  442.239142] usb 5-1: Manufacturer:
Logitech
Jan  6 21:18:52 speedster kernel: [  442.239145] usb 5-1: SerialNumber:
5d1d5129cebe
Jan  6 21:18:52 speedster mtp-probe: checking bus 5, device 3:
"/sys/devices/pci:00/:00:1d.3/usb5/5-1"
Jan  6 21:18:52 speedster mtp-probe: bus: 5, device: 3 was not an MTP device
Jan  6 21:18:52 speedster kernel: [  442.267248] input: Logitech G920
Driving Force Racing Wheel for Xbox One as
/devices/pci:00/:00:1d.3/usb5/5-1/5-1:1.0/0003:046D:C262.0002/input/input5
Jan  6 21:18:52 speedster kernel: [  442.267510] logitech-hidpp-device
0003:046D:C262.0002: input,hiddev0,hidraw1: USB HID v1.11 Joystick
[Logitech G920 Driving Force Racing Wheel for Xbox One] on
usb-:00:1d.3-1/input0
Jan  6 21:18:53 speedster kernel: [  442.322160] logitech-hidpp-device
0003:046D:C262.0002: HID++ 4.2 device connected.
--

I also did a quick check with the 'send magic' disabled. Xpad creates the
js0 and populates buttons, but pressing buttons/turning wheel does not
result in any change in js0.

I don't disagree to it being a seperate module, but don't have the time to
implement/test at the moment. If some else does that would be good, can we
make sure that the kconfig/makefile stuff uses same/sensible HID_CONFIGs?
Simon


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 1/6] INPUT: xpad: switch Logitech G920 Wheel into HID mode

2015-11-19 Thread Simon Wood
When plugged in the Logitech G920 wheel starts with USBID 046d:c261
and behaviors as a vendor specific class. If a 'magic' byte sequence
is sent the wheel will detach and reconnect as a HID device with the
USBID 046d:c262.

Signed-off-by: Simon Wood 
---
 drivers/input/joystick/xpad.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index fd4100d..338a3a4 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -93,6 +93,7 @@
 #define MAP_STICKS_TO_NULL (1 << 2)
 #define DANCEPAD_MAP_CONFIG(MAP_DPAD_TO_BUTTONS |  \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
+#define SWITCH_G920_TO_HID_MODE(1 << 3)
 
 #define XTYPE_XBOX0
 #define XTYPE_XBOX360 1
@@ -134,6 +135,7 @@ static const struct xpad_device {
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
+   { 0x046d, 0xc261, "Logitech G920 Driving Force Racing Wheel", 
SWITCH_G920_TO_HID_MODE, XTYPE_XBOXONE },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX 
},
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
@@ -299,6 +301,7 @@ static struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x045e),/* Microsoft X-Box 360 
controllers */
XPAD_XBOXONE_VENDOR(0x045e),/* Microsoft X-Box One 
controllers */
XPAD_XBOX360_VENDOR(0x046d),/* Logitech X-Box 360 style 
controllers */
+   XPAD_XBOXONE_VENDOR(0x046d),/* Logitech X-Box One style 
controllers */
XPAD_XBOX360_VENDOR(0x0738),/* Mad Catz X-Box 360 
controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOX360_VENDOR(0x0e6f),/* 0x0e6f X-Box 360 controllers 
*/
@@ -1048,6 +1051,19 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
 
+   /* Logitect G920 wheel starts in XBOX mode, but is reconfigured to be 
HID  */
+   /* device with USBID of 046D:C262. Wheel will detach when 'magic' is 
sent. */
+   if (xpad->mapping & SWITCH_G920_TO_HID_MODE) {
+   xpad->odata[0] = 0x0F;
+   xpad->odata[1] = 0x00;
+   xpad->odata[2] = 0x01;
+   xpad->odata[3] = 0x01;
+   xpad->odata[4] = 0x42;
+   xpad->irq_out->transfer_buffer_length = 5;
+
+   return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+   }
+
if (xpad->xtype == XTYPE_XBOXONE) {
/* Xbox one controller needs to be initialized. */
xpad->odata[0] = 0x05;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech G920

2015-11-19 Thread Simon Wood
This patch adds basic support for the Logitech G920 wheel when in HID
mode. This wheel 'speaks' the HID++ protocol, and therefor is driven
with hid-logitech-hidpp.

At this stage the driver only shows that it can communicate with the
wheel by outputting the name discovered over HID++.

The normal HID functions work to give input functionality using
joystick/event interface.

Note: in 'hidpp_probe()' we have to start the hardware to get packets
flowing, the same might apply in future for other devices which don't
use the unifying protocol.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-core.c   |  1 +
 drivers/hid/hid-ids.h|  1 +
 drivers/hid/hid-logitech-hidpp.c | 71 +++-
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c6f7a69..190260c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1902,6 +1902,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ac1feea..269e758 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -619,6 +619,7 @@
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2  0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_20xc219
 #define USB_DEVICE_ID_LOGITECH_G29_WHEEL   0xc24f
+#define USB_DEVICE_ID_LOGITECH_G920_WHEEL  0xc262
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940  0xc287
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 0f53dc8..98b8f09 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -49,11 +49,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
 #define HIDPP_QUIRK_CLASS_K400 BIT(2)
+#define HIDPP_QUIRK_CLASS_G920 BIT(3)
 
 /* bits 2..20 are reserved for classes */
 #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS   BIT(22)
 #define HIDPP_QUIRK_NO_HIDINPUTBIT(23)
+#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS   BIT(24)
 
 #define HIDPP_QUIRK_DELAYED_INIT   (HIDPP_QUIRK_NO_HIDINPUT | \
 HIDPP_QUIRK_CONNECT_EVENTS)
@@ -146,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device 
*hidpp_dev);
 static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
 {
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
int fields_count, ret;
 
+   hidpp = hid_get_drvdata(hdev);
+
switch (hidpp_report->report_id) {
case REPORT_ID_HIDPP_SHORT:
fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -168,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
 */
hidpp_report->device_index = 0xff;
 
-   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
-   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
-   HID_REQ_SET_REPORT);
+   if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
+   ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, 
fields_count);
+   } else {
+   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
+   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
+   HID_REQ_SET_REPORT);
+   }
 
return ret == fields_count ? 0 : -1;
 }
@@ -1430,10 +1439,12 @@ static void hidpp_overwrite_name(struct hid_device 
*hdev, bool use_unifying)
else
name = hidpp_get_device_name(hidpp);
 
-   if (!name)
+   if (!name) {
hid_err(hdev, "unable to retrieve the name of the device");
-   else
+   } else {
+   dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+   }
 
kfree(name);
 }
@@ -1596,6 +1607,25 @@ static int hidpp_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
goto hid_parse_fail;

[Patch-V3 5/6] HID: Add vendor specific usage pages for Logitech G920

2015-11-19 Thread Simon Wood
The Logitech G920 uses a couple of vendor specific usage pages,
which results in incorrect number of axis/buttons being detected.

This patch adds these pages to the 'ignore' list.

Reported-by: Elias Vanderstuyft 
Signed-off-by: Simon Wood 
---
 drivers/hid/hid-input.c | 4 
 include/linux/hid.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 2ba6bf6..f4eeb6b 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -960,6 +960,10 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
goto ignore;
 
case HID_UP_LOGIVENDOR:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR2:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR3:
goto ignore;
 
case HID_UP_PID:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 251a1d3..a6d7a3f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -168,6 +168,8 @@ struct hid_item {
 #define HID_UP_MSVENDOR0xff00
 #define HID_UP_CUSTOM  0x00ff
 #define HID_UP_LOGIVENDOR  0xffbc
+#define HID_UP_LOGIVENDOR2   0xff09
+#define HID_UP_LOGIVENDOR3   0xff43
 #define HID_UP_LNVENDOR0xffa0
 #define HID_UP_SENSOR  0x0020
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-19 Thread Simon Wood
Ensure that the G920 is not given the default deadzones.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index fc553e3..f2a4811 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1441,6 +1441,25 @@ static int hidpp_input_mapping(struct hid_device *hdev, 
struct hid_input *hi,
return 0;
 }
 
+static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+   struct hid_field *field, struct hid_usage *usage,
+   unsigned long **bit, int *max)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+   /* Ensure that Logitech G920 is not given a default fuzz/flat value */
+   if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+   if (usage->type == EV_ABS && (usage->code == ABS_X ||
+   usage->code == ABS_Y || usage->code == ABS_Z ||
+   usage->code == ABS_RZ)) {
+   field->application = HID_GD_MULTIAXIS;
+   }
+   }
+
+   return 0;
+}
+
+
 static void hidpp_populate_input(struct hidpp_device *hidpp,
struct input_dev *input, bool origin_is_hid_core)
 {
@@ -1875,6 +1894,7 @@ static struct hid_driver hidpp_driver = {
.raw_event = hidpp_raw_event,
.input_configured = hidpp_input_configured,
.input_mapping = hidpp_input_mapping,
+   .input_mapped = hidpp_input_mapped,
 };
 
 module_hid_driver(hidpp_driver);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech G920

2015-11-19 Thread Simon Wood
The G920 can adjust the amount of 'turn' it permits, this patch adds
a sysfs file 'range' to control this.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 140 ++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 98b8f09..fc553e3 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1295,6 +1295,133 @@ static int k400_connect(struct hid_device *hdev, bool 
connected)
return k400_disable_tap_to_click(hidpp);
 }
 
+/* - */
+/* Logitech G920 Driving Force Racing Wheel for Xbox One */
+/* - */
+
+#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
+
+/* Using session ID = 1 */
+#define CMD_G920_FORCE_GET_APERTURE0x51
+#define CMD_G920_FORCE_SET_APERTURE0x61
+
+struct g920_private_data {
+   u8 force_feature;
+   u16 range;
+};
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static ssize_t g920_range_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
+}
+
+static ssize_t g920_range_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+   struct hidpp_report response;
+   u8 params[2];
+   int ret;
+   u16 range = simple_strtoul(buf, NULL, 10);
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   if (range < 180)
+   range = 180;
+   else if (range > 900)
+   range = 900;
+
+   params[0] = range >> 8;
+   params[1] = range & 0x00FF;
+
+   ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
+   CMD_G920_FORCE_SET_APERTURE, params, 2, );
+   if (ret)
+   return ret;
+
+   pdata->range = range;
+   return count;
+}
+
+static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, 
g920_range_show, g920_range_store);
+
+static int g920_allocate(struct hid_device *hdev)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+   struct g920_private_data *pdata;
+
+   pdata = devm_kzalloc(>dev, sizeof(struct g920_private_data),
+   GFP_KERNEL);
+   if (!pdata)
+   return -ENOMEM;
+
+   hidpp->private_data = pdata;
+
+   return 0;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp)
+{
+   struct g920_private_data *pdata = hidpp->private_data;
+   struct hidpp_report response;
+   u8 feature_type;
+   u8 feature_index;
+   int ret;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hidpp->hid_dev, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   /* Find feature and store for later use */
+   ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
+   _index, _type);
+   if (ret)
+   return ret;
+
+   pdata->force_feature = feature_index;
+
+   /* Read current Range */
+   ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+   CMD_G920_FORCE_GET_APERTURE, NULL, 0, );
+   if (ret > 0) {
+   hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+   __func__, ret);
+   return -EPROTO;
+   }
+   if (ret)
+   return ret;
+
+   pdata->range = get_unaligned_be16([0]);
+
+   /* Create sysfs interface */
+   ret = device_create_file(&(hidpp->hid_dev->dev), _attr_range);
+   if (ret)
+   hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for 
\"range\", errno %d\n", ret);
+
+   return 0;
+}
+
 /* -- 
*/
 /* Generic HID++ devices  
*/
 /* -

[Patch-V3 2/6] HID: hid-logitech-hidpp: Add support for very long packets

2015-11-19 Thread Simon Wood
Patch add support for the 'very long' HID++ packets, which are
64 bytes in length.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 59 
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5fd9786..0f53dc8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -40,9 +40,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
 
 #define REPORT_ID_HIDPP_SHORT  0x10
 #define REPORT_ID_HIDPP_LONG   0x11
+#define REPORT_ID_HIDPP_VERY_LONG  0x12
 
 #define HIDPP_REPORT_SHORT_LENGTH  7
 #define HIDPP_REPORT_LONG_LENGTH   20
+#define HIDPP_REPORT_VERY_LONG_LENGTH  64
 
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
@@ -81,13 +83,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 struct fap {
u8 feature_index;
u8 funcindex_clientid;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct rap {
u8 sub_id;
u8 reg_address;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct hidpp_report {
@@ -153,6 +155,9 @@ static int __hidpp_send_report(struct hid_device *hdev,
case REPORT_ID_HIDPP_LONG:
fields_count = HIDPP_REPORT_LONG_LENGTH;
break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   fields_count = HIDPP_REPORT_VERY_LONG_LENGTH;
+   break;
default:
return -ENODEV;
}
@@ -217,8 +222,9 @@ static int hidpp_send_message_sync(struct hidpp_device 
*hidpp,
goto exit;
}
 
-   if (response->report_id == REPORT_ID_HIDPP_LONG &&
-   response->fap.feature_index == HIDPP20_ERROR) {
+   if ((response->report_id == REPORT_ID_HIDPP_LONG ||
+   response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
+   response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
goto exit;
@@ -243,7 +249,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device 
*hidpp,
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
if (!message)
return -ENOMEM;
-   message->report_id = REPORT_ID_HIDPP_LONG;
+
+   if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4))
+   message->report_id = REPORT_ID_HIDPP_VERY_LONG;
+   else
+   message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid;
memcpy(>fap.params, params, param_count);
@@ -258,13 +268,23 @@ static int hidpp_send_rap_command_sync(struct 
hidpp_device *hidpp_dev,
struct hidpp_report *response)
 {
struct hidpp_report *message;
-   int ret;
+   int ret, max_count;
 
-   if ((report_id != REPORT_ID_HIDPP_SHORT) &&
-   (report_id != REPORT_ID_HIDPP_LONG))
+   switch (report_id) {
+   case REPORT_ID_HIDPP_SHORT:
+   max_count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
+   max_count = HIDPP_REPORT_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   default:
return -EINVAL;
+   }
 
-   if (param_count > sizeof(message->rap.params))
+   if (param_count > max_count)
return -EINVAL;
 
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
@@ -508,10 +528,19 @@ static int hidpp_devicenametype_get_device_name(struct 
hidpp_device *hidpp,
if (ret)
return ret;
 
-   if (response.report_id == REPORT_ID_HIDPP_LONG)
+   switch (response.report_id) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
count = HIDPP_REPORT_LONG_LENGTH - 4;
-   else
+   break;
+   case REPORT_ID_HIDPP_SHORT:
count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   default:
+   return -EPROTO;
+   }
 
if (len_buf < count)
count = len_buf;
@@ -1347,6 +1376,14 @@ static int hidpp_raw_event(struct hid_device *hdev, 
struct hid_report *report,
 
/* Generic HID++ processing. */
switch (data[0]) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   if (size != HIDPP_REPORT_VERY_LONG_L

[Patch-V3 0/6] HID: Support for the Logitech G920 Wheel

2015-11-19 Thread Simon Wood
Patch-V3 tweaked as per Benjamin's and Dmitry's requests.

This series of patches provide input support for the Logitech G920 gaming wheel.

This wheel is internally different from the other Logitech wheels; when first 
connected it is in X-Box mode and can instructed to switch to HID with a 'magic 
command' (1st patch). Once the wheel reconnects in HID mode it can communicate 
with the HID++ protocol, but using a 'very long' packet size (2nd patch).

Basic input operation is possible with adustment of the 'range' (the amount 
that 
the wheel turns) controlled via the '/sys' interface, same concept as the 
G25/G27/etc.

We also discovered that wheel uses some vendor specific pages, which confuse 
the 
HID system resulting in lots of additional axis reported. This is prevented by 
ignoring these pages (5th patch, thank you Elias).

The future... as the internals of the wheel are considerably more 'capable' we 
are working on implementing Force Feedback using the forth-coming KLGD system.

Simon Wood (6):
  INPUT: xpad: switch Logitech G920 Wheel into HID mode
  HID: hid-logitech-hidpp: Add support for very long packets
  HID: hid-logitech-hidpp: Add basic support for Logitech G920
  HID: hid-logitech-hidpp: Add range sysfs for Logitech G920
  HID: Add vendor specific usage pages for Logitech G920
  HID: hid-logitech-hidpp: G920 remove deadzones

 drivers/hid/hid-core.c   |   1 +
 drivers/hid/hid-ids.h|   1 +
 drivers/hid/hid-input.c  |   4 +
 drivers/hid/hid-logitech-hidpp.c | 288 +++
 drivers/input/joystick/xpad.c|  16 +++
 include/linux/hid.h  |   2 +
 6 files changed, 285 insertions(+), 27 deletions(-)

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2015-11-19 Thread Simon Wood
On Thu, November 19, 2015 11:31 am, Dmitry Torokhov wrote:
> On Thu, Nov 19, 2015 at 02:50:51PM +0100, Jiri Kosina wrote:
>
>> On Thu, 12 Nov 2015, Simon Wood wrote:
>>
>>
>>> When plugged in the Logitech G920 wheel starts with USBID 046d:c261
>>> and behaviors as a vendor specific class. If a 'magic' byte sequence is
>>> sent the wheel will detach and reconnect as a HID device with the
>>> USBID 046d:c262.
>>>
>>>
>>> Signed-off-by: Simon Wood 
>>>
>>
>> Adding Dmitry to CC.
>>
>>
>> Dmitry, I am planning to take this through my tree together with the
>> rest of the actual HID support for that device if you Ack this.
>
> Hmm, I have an incoming series for xbox that night clash with this... If
> you'll put it in a clean branch off 4.3 I'd pull it and then get more
> changes on top.
>
> Can we also change the subject as it is not about adding a minimal
> support. Something like "Input: xpad - switch Logitech G920 Wheel into HID
> mode"

Will spin a 'v3' with this and Benjamin's suggestion.

Cheers,
Simon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2015-11-19 Thread Simon Wood
On Thu, November 19, 2015 11:31 am, Dmitry Torokhov wrote:
> On Thu, Nov 19, 2015 at 02:50:51PM +0100, Jiri Kosina wrote:
>
>> On Thu, 12 Nov 2015, Simon Wood wrote:
>>
>>
>>> When plugged in the Logitech G920 wheel starts with USBID 046d:c261
>>> and behaviors as a vendor specific class. If a 'magic' byte sequence is
>>> sent the wheel will detach and reconnect as a HID device with the
>>> USBID 046d:c262.
>>>
>>>
>>> Signed-off-by: Simon Wood <si...@mungewell.org>
>>>
>>
>> Adding Dmitry to CC.
>>
>>
>> Dmitry, I am planning to take this through my tree together with the
>> rest of the actual HID support for that device if you Ack this.
>
> Hmm, I have an incoming series for xbox that night clash with this... If
> you'll put it in a clean branch off 4.3 I'd pull it and then get more
> changes on top.
>
> Can we also change the subject as it is not about adding a minimal
> support. Something like "Input: xpad - switch Logitech G920 Wheel into HID
> mode"

Will spin a 'v3' with this and Benjamin's suggestion.

Cheers,
Simon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech G920

2015-11-19 Thread Simon Wood
This patch adds basic support for the Logitech G920 wheel when in HID
mode. This wheel 'speaks' the HID++ protocol, and therefor is driven
with hid-logitech-hidpp.

At this stage the driver only shows that it can communicate with the
wheel by outputting the name discovered over HID++.

The normal HID functions work to give input functionality using
joystick/event interface.

Note: in 'hidpp_probe()' we have to start the hardware to get packets
flowing, the same might apply in future for other devices which don't
use the unifying protocol.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-core.c   |  1 +
 drivers/hid/hid-ids.h|  1 +
 drivers/hid/hid-logitech-hidpp.c | 71 +++-
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c6f7a69..190260c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1902,6 +1902,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ac1feea..269e758 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -619,6 +619,7 @@
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2  0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_20xc219
 #define USB_DEVICE_ID_LOGITECH_G29_WHEEL   0xc24f
+#define USB_DEVICE_ID_LOGITECH_G920_WHEEL  0xc262
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940  0xc287
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 0f53dc8..98b8f09 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -49,11 +49,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
 #define HIDPP_QUIRK_CLASS_K400 BIT(2)
+#define HIDPP_QUIRK_CLASS_G920 BIT(3)
 
 /* bits 2..20 are reserved for classes */
 #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS   BIT(22)
 #define HIDPP_QUIRK_NO_HIDINPUTBIT(23)
+#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS   BIT(24)
 
 #define HIDPP_QUIRK_DELAYED_INIT   (HIDPP_QUIRK_NO_HIDINPUT | \
 HIDPP_QUIRK_CONNECT_EVENTS)
@@ -146,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device 
*hidpp_dev);
 static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
 {
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
int fields_count, ret;
 
+   hidpp = hid_get_drvdata(hdev);
+
switch (hidpp_report->report_id) {
case REPORT_ID_HIDPP_SHORT:
fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -168,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
 */
hidpp_report->device_index = 0xff;
 
-   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
-   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
-   HID_REQ_SET_REPORT);
+   if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
+   ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, 
fields_count);
+   } else {
+   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
+   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
+   HID_REQ_SET_REPORT);
+   }
 
return ret == fields_count ? 0 : -1;
 }
@@ -1430,10 +1439,12 @@ static void hidpp_overwrite_name(struct hid_device 
*hdev, bool use_unifying)
else
name = hidpp_get_device_name(hidpp);
 
-   if (!name)
+   if (!name) {
hid_err(hdev, "unable to retrieve the name of the device");
-   else
+   } else {
+   dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+   }
 
kfree(name);
 }
@@ -1596,6 +1607,25 @@ static int hidpp_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
 

[Patch-V3 5/6] HID: Add vendor specific usage pages for Logitech G920

2015-11-19 Thread Simon Wood
The Logitech G920 uses a couple of vendor specific usage pages,
which results in incorrect number of axis/buttons being detected.

This patch adds these pages to the 'ignore' list.

Reported-by: Elias Vanderstuyft <elias@gmail.com>
Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-input.c | 4 
 include/linux/hid.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 2ba6bf6..f4eeb6b 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -960,6 +960,10 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
goto ignore;
 
case HID_UP_LOGIVENDOR:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR2:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR3:
goto ignore;
 
case HID_UP_PID:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 251a1d3..a6d7a3f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -168,6 +168,8 @@ struct hid_item {
 #define HID_UP_MSVENDOR0xff00
 #define HID_UP_CUSTOM  0x00ff
 #define HID_UP_LOGIVENDOR  0xffbc
+#define HID_UP_LOGIVENDOR2   0xff09
+#define HID_UP_LOGIVENDOR3   0xff43
 #define HID_UP_LNVENDOR0xffa0
 #define HID_UP_SENSOR  0x0020
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech G920

2015-11-19 Thread Simon Wood
The G920 can adjust the amount of 'turn' it permits, this patch adds
a sysfs file 'range' to control this.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 140 ++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 98b8f09..fc553e3 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1295,6 +1295,133 @@ static int k400_connect(struct hid_device *hdev, bool 
connected)
return k400_disable_tap_to_click(hidpp);
 }
 
+/* - */
+/* Logitech G920 Driving Force Racing Wheel for Xbox One */
+/* - */
+
+#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
+
+/* Using session ID = 1 */
+#define CMD_G920_FORCE_GET_APERTURE0x51
+#define CMD_G920_FORCE_SET_APERTURE0x61
+
+struct g920_private_data {
+   u8 force_feature;
+   u16 range;
+};
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static ssize_t g920_range_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
+}
+
+static ssize_t g920_range_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+   struct hidpp_report response;
+   u8 params[2];
+   int ret;
+   u16 range = simple_strtoul(buf, NULL, 10);
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   if (range < 180)
+   range = 180;
+   else if (range > 900)
+   range = 900;
+
+   params[0] = range >> 8;
+   params[1] = range & 0x00FF;
+
+   ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
+   CMD_G920_FORCE_SET_APERTURE, params, 2, );
+   if (ret)
+   return ret;
+
+   pdata->range = range;
+   return count;
+}
+
+static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, 
g920_range_show, g920_range_store);
+
+static int g920_allocate(struct hid_device *hdev)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+   struct g920_private_data *pdata;
+
+   pdata = devm_kzalloc(>dev, sizeof(struct g920_private_data),
+   GFP_KERNEL);
+   if (!pdata)
+   return -ENOMEM;
+
+   hidpp->private_data = pdata;
+
+   return 0;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp)
+{
+   struct g920_private_data *pdata = hidpp->private_data;
+   struct hidpp_report response;
+   u8 feature_type;
+   u8 feature_index;
+   int ret;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hidpp->hid_dev, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   /* Find feature and store for later use */
+   ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
+   _index, _type);
+   if (ret)
+   return ret;
+
+   pdata->force_feature = feature_index;
+
+   /* Read current Range */
+   ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+   CMD_G920_FORCE_GET_APERTURE, NULL, 0, );
+   if (ret > 0) {
+   hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+   __func__, ret);
+   return -EPROTO;
+   }
+   if (ret)
+   return ret;
+
+   pdata->range = get_unaligned_be16([0]);
+
+   /* Create sysfs interface */
+   ret = device_create_file(&(hidpp->hid_dev->dev), _attr_range);
+   if (ret)
+   hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for 
\"range\", errno %d\n", ret);
+
+   return 0;
+}
+
 /* -- 
*/
 /* Generic HID++ devices  
*/
 /* --

[Patch-V3 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-19 Thread Simon Wood
Ensure that the G920 is not given the default deadzones.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index fc553e3..f2a4811 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1441,6 +1441,25 @@ static int hidpp_input_mapping(struct hid_device *hdev, 
struct hid_input *hi,
return 0;
 }
 
+static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+   struct hid_field *field, struct hid_usage *usage,
+   unsigned long **bit, int *max)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+   /* Ensure that Logitech G920 is not given a default fuzz/flat value */
+   if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+   if (usage->type == EV_ABS && (usage->code == ABS_X ||
+   usage->code == ABS_Y || usage->code == ABS_Z ||
+   usage->code == ABS_RZ)) {
+   field->application = HID_GD_MULTIAXIS;
+   }
+   }
+
+   return 0;
+}
+
+
 static void hidpp_populate_input(struct hidpp_device *hidpp,
struct input_dev *input, bool origin_is_hid_core)
 {
@@ -1875,6 +1894,7 @@ static struct hid_driver hidpp_driver = {
.raw_event = hidpp_raw_event,
.input_configured = hidpp_input_configured,
.input_mapping = hidpp_input_mapping,
+   .input_mapped = hidpp_input_mapped,
 };
 
 module_hid_driver(hidpp_driver);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 1/6] INPUT: xpad: switch Logitech G920 Wheel into HID mode

2015-11-19 Thread Simon Wood
When plugged in the Logitech G920 wheel starts with USBID 046d:c261
and behaviors as a vendor specific class. If a 'magic' byte sequence
is sent the wheel will detach and reconnect as a HID device with the
USBID 046d:c262.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/input/joystick/xpad.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index fd4100d..338a3a4 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -93,6 +93,7 @@
 #define MAP_STICKS_TO_NULL (1 << 2)
 #define DANCEPAD_MAP_CONFIG(MAP_DPAD_TO_BUTTONS |  \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
+#define SWITCH_G920_TO_HID_MODE(1 << 3)
 
 #define XTYPE_XBOX0
 #define XTYPE_XBOX360 1
@@ -134,6 +135,7 @@ static const struct xpad_device {
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
+   { 0x046d, 0xc261, "Logitech G920 Driving Force Racing Wheel", 
SWITCH_G920_TO_HID_MODE, XTYPE_XBOXONE },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX 
},
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
@@ -299,6 +301,7 @@ static struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x045e),/* Microsoft X-Box 360 
controllers */
XPAD_XBOXONE_VENDOR(0x045e),/* Microsoft X-Box One 
controllers */
XPAD_XBOX360_VENDOR(0x046d),/* Logitech X-Box 360 style 
controllers */
+   XPAD_XBOXONE_VENDOR(0x046d),/* Logitech X-Box One style 
controllers */
XPAD_XBOX360_VENDOR(0x0738),/* Mad Catz X-Box 360 
controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOX360_VENDOR(0x0e6f),/* 0x0e6f X-Box 360 controllers 
*/
@@ -1048,6 +1051,19 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
 
+   /* Logitect G920 wheel starts in XBOX mode, but is reconfigured to be 
HID  */
+   /* device with USBID of 046D:C262. Wheel will detach when 'magic' is 
sent. */
+   if (xpad->mapping & SWITCH_G920_TO_HID_MODE) {
+   xpad->odata[0] = 0x0F;
+   xpad->odata[1] = 0x00;
+   xpad->odata[2] = 0x01;
+   xpad->odata[3] = 0x01;
+   xpad->odata[4] = 0x42;
+   xpad->irq_out->transfer_buffer_length = 5;
+
+   return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+   }
+
if (xpad->xtype == XTYPE_XBOXONE) {
/* Xbox one controller needs to be initialized. */
xpad->odata[0] = 0x05;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V3 2/6] HID: hid-logitech-hidpp: Add support for very long packets

2015-11-19 Thread Simon Wood
Patch add support for the 'very long' HID++ packets, which are
64 bytes in length.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 59 
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5fd9786..0f53dc8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -40,9 +40,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
 
 #define REPORT_ID_HIDPP_SHORT  0x10
 #define REPORT_ID_HIDPP_LONG   0x11
+#define REPORT_ID_HIDPP_VERY_LONG  0x12
 
 #define HIDPP_REPORT_SHORT_LENGTH  7
 #define HIDPP_REPORT_LONG_LENGTH   20
+#define HIDPP_REPORT_VERY_LONG_LENGTH  64
 
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
@@ -81,13 +83,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 struct fap {
u8 feature_index;
u8 funcindex_clientid;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct rap {
u8 sub_id;
u8 reg_address;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct hidpp_report {
@@ -153,6 +155,9 @@ static int __hidpp_send_report(struct hid_device *hdev,
case REPORT_ID_HIDPP_LONG:
fields_count = HIDPP_REPORT_LONG_LENGTH;
break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   fields_count = HIDPP_REPORT_VERY_LONG_LENGTH;
+   break;
default:
return -ENODEV;
}
@@ -217,8 +222,9 @@ static int hidpp_send_message_sync(struct hidpp_device 
*hidpp,
goto exit;
}
 
-   if (response->report_id == REPORT_ID_HIDPP_LONG &&
-   response->fap.feature_index == HIDPP20_ERROR) {
+   if ((response->report_id == REPORT_ID_HIDPP_LONG ||
+   response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
+   response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
goto exit;
@@ -243,7 +249,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device 
*hidpp,
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
if (!message)
return -ENOMEM;
-   message->report_id = REPORT_ID_HIDPP_LONG;
+
+   if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4))
+   message->report_id = REPORT_ID_HIDPP_VERY_LONG;
+   else
+   message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid;
memcpy(>fap.params, params, param_count);
@@ -258,13 +268,23 @@ static int hidpp_send_rap_command_sync(struct 
hidpp_device *hidpp_dev,
struct hidpp_report *response)
 {
struct hidpp_report *message;
-   int ret;
+   int ret, max_count;
 
-   if ((report_id != REPORT_ID_HIDPP_SHORT) &&
-   (report_id != REPORT_ID_HIDPP_LONG))
+   switch (report_id) {
+   case REPORT_ID_HIDPP_SHORT:
+   max_count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
+   max_count = HIDPP_REPORT_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   default:
return -EINVAL;
+   }
 
-   if (param_count > sizeof(message->rap.params))
+   if (param_count > max_count)
return -EINVAL;
 
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
@@ -508,10 +528,19 @@ static int hidpp_devicenametype_get_device_name(struct 
hidpp_device *hidpp,
if (ret)
return ret;
 
-   if (response.report_id == REPORT_ID_HIDPP_LONG)
+   switch (response.report_id) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
count = HIDPP_REPORT_LONG_LENGTH - 4;
-   else
+   break;
+   case REPORT_ID_HIDPP_SHORT:
count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   default:
+   return -EPROTO;
+   }
 
if (len_buf < count)
count = len_buf;
@@ -1347,6 +1376,14 @@ static int hidpp_raw_event(struct hid_device *hdev, 
struct hid_report *report,
 
/* Generic HID++ processing. */
switch (data[0]) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   if (size != HIDPP_REP

[Patch-V3 0/6] HID: Support for the Logitech G920 Wheel

2015-11-19 Thread Simon Wood
Patch-V3 tweaked as per Benjamin's and Dmitry's requests.

This series of patches provide input support for the Logitech G920 gaming wheel.

This wheel is internally different from the other Logitech wheels; when first 
connected it is in X-Box mode and can instructed to switch to HID with a 'magic 
command' (1st patch). Once the wheel reconnects in HID mode it can communicate 
with the HID++ protocol, but using a 'very long' packet size (2nd patch).

Basic input operation is possible with adustment of the 'range' (the amount 
that 
the wheel turns) controlled via the '/sys' interface, same concept as the 
G25/G27/etc.

We also discovered that wheel uses some vendor specific pages, which confuse 
the 
HID system resulting in lots of additional axis reported. This is prevented by 
ignoring these pages (5th patch, thank you Elias).

The future... as the internals of the wheel are considerably more 'capable' we 
are working on implementing Force Feedback using the forth-coming KLGD system.

Simon Wood (6):
  INPUT: xpad: switch Logitech G920 Wheel into HID mode
  HID: hid-logitech-hidpp: Add support for very long packets
  HID: hid-logitech-hidpp: Add basic support for Logitech G920
  HID: hid-logitech-hidpp: Add range sysfs for Logitech G920
  HID: Add vendor specific usage pages for Logitech G920
  HID: hid-logitech-hidpp: G920 remove deadzones

 drivers/hid/hid-core.c   |   1 +
 drivers/hid/hid-ids.h|   1 +
 drivers/hid/hid-input.c  |   4 +
 drivers/hid/hid-logitech-hidpp.c | 288 +++
 drivers/input/joystick/xpad.c|  16 +++
 include/linux/hid.h  |   2 +
 6 files changed, 285 insertions(+), 27 deletions(-)

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Depmod issues with libcfs on 4.4 HEAD

2015-11-13 Thread Simon Wood
Hi James,
I am still seeing problems with libcfs whilst building a Ubuntu kernel
from 4.4 HEAD (0e976064256523ca604bd82048ae0e3402ce2467, as per pull last
night 12th Nov).
--
  INSTALL
/home/simon/linux-git/debian/linux-image-4.3.0-g920+/lib/firmware/4.3.0-g920+/cpia2/stv0672_vp4.bin
  INSTALL
/home/simon/linux-git/debian/linux-image-4.3.0-g920+/lib/firmware/4.3.0-g920+/yam/1200.bin
  INSTALL
/home/simon/linux-git/debian/linux-image-4.3.0-g920+/lib/firmware/4.3.0-g920+/yam/9600.bin
  DEPMOD  4.3.0-g920+
depmod: ERROR: Found 2 modules in dependency cycles!
depmod: ERROR: Cycle detected: lnet -> libcfs -> lnet
--

Previously you suggested that there was a fix:
https://lkml.org/lkml/2015/11/9/702

Can you please point me at it as it's not included yet (apparently) and I
haven't been able to track it down.

Cheers,
Simon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Depmod issues with libcfs on 4.4 HEAD

2015-11-13 Thread Simon Wood
Hi James,
I am still seeing problems with libcfs whilst building a Ubuntu kernel
from 4.4 HEAD (0e976064256523ca604bd82048ae0e3402ce2467, as per pull last
night 12th Nov).
--
  INSTALL
/home/simon/linux-git/debian/linux-image-4.3.0-g920+/lib/firmware/4.3.0-g920+/cpia2/stv0672_vp4.bin
  INSTALL
/home/simon/linux-git/debian/linux-image-4.3.0-g920+/lib/firmware/4.3.0-g920+/yam/1200.bin
  INSTALL
/home/simon/linux-git/debian/linux-image-4.3.0-g920+/lib/firmware/4.3.0-g920+/yam/9600.bin
  DEPMOD  4.3.0-g920+
depmod: ERROR: Found 2 modules in dependency cycles!
depmod: ERROR: Cycle detected: lnet -> libcfs -> lnet
--

Previously you suggested that there was a fix:
https://lkml.org/lkml/2015/11/9/702

Can you please point me at it as it's not included yet (apparently) and I
haven't been able to track it down.

Cheers,
Simon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 2/6] HID: hid-logitech-hidpp: Add support for very long packets

2015-11-12 Thread Simon Wood
Patch add support for the 'very long' HID++ packets, which are
64 bytes in length.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 59 
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5fd9786..0f53dc8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -40,9 +40,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
 
 #define REPORT_ID_HIDPP_SHORT  0x10
 #define REPORT_ID_HIDPP_LONG   0x11
+#define REPORT_ID_HIDPP_VERY_LONG  0x12
 
 #define HIDPP_REPORT_SHORT_LENGTH  7
 #define HIDPP_REPORT_LONG_LENGTH   20
+#define HIDPP_REPORT_VERY_LONG_LENGTH  64
 
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
@@ -81,13 +83,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 struct fap {
u8 feature_index;
u8 funcindex_clientid;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct rap {
u8 sub_id;
u8 reg_address;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct hidpp_report {
@@ -153,6 +155,9 @@ static int __hidpp_send_report(struct hid_device *hdev,
case REPORT_ID_HIDPP_LONG:
fields_count = HIDPP_REPORT_LONG_LENGTH;
break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   fields_count = HIDPP_REPORT_VERY_LONG_LENGTH;
+   break;
default:
return -ENODEV;
}
@@ -217,8 +222,9 @@ static int hidpp_send_message_sync(struct hidpp_device 
*hidpp,
goto exit;
}
 
-   if (response->report_id == REPORT_ID_HIDPP_LONG &&
-   response->fap.feature_index == HIDPP20_ERROR) {
+   if ((response->report_id == REPORT_ID_HIDPP_LONG ||
+   response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
+   response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
goto exit;
@@ -243,7 +249,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device 
*hidpp,
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
if (!message)
return -ENOMEM;
-   message->report_id = REPORT_ID_HIDPP_LONG;
+
+   if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4))
+   message->report_id = REPORT_ID_HIDPP_VERY_LONG;
+   else
+   message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid;
memcpy(>fap.params, params, param_count);
@@ -258,13 +268,23 @@ static int hidpp_send_rap_command_sync(struct 
hidpp_device *hidpp_dev,
struct hidpp_report *response)
 {
struct hidpp_report *message;
-   int ret;
+   int ret, max_count;
 
-   if ((report_id != REPORT_ID_HIDPP_SHORT) &&
-   (report_id != REPORT_ID_HIDPP_LONG))
+   switch (report_id) {
+   case REPORT_ID_HIDPP_SHORT:
+   max_count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
+   max_count = HIDPP_REPORT_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   default:
return -EINVAL;
+   }
 
-   if (param_count > sizeof(message->rap.params))
+   if (param_count > max_count)
return -EINVAL;
 
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
@@ -508,10 +528,19 @@ static int hidpp_devicenametype_get_device_name(struct 
hidpp_device *hidpp,
if (ret)
return ret;
 
-   if (response.report_id == REPORT_ID_HIDPP_LONG)
+   switch (response.report_id) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
count = HIDPP_REPORT_LONG_LENGTH - 4;
-   else
+   break;
+   case REPORT_ID_HIDPP_SHORT:
count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   default:
+   return -EPROTO;
+   }
 
if (len_buf < count)
count = len_buf;
@@ -1347,6 +1376,14 @@ static int hidpp_raw_event(struct hid_device *hdev, 
struct hid_report *report,
 
/* Generic HID++ processing. */
switch (data[0]) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   if (size != HIDPP_REPORT_VERY_LONG_L

Re: [Patch-V2 0/6] HID: Support for the Logitech G920 Wheel

2015-11-12 Thread Simon Wood
> Note: These patches are applied to Jiri's 'for-next' tree to work with
> the other HID++ changes already queued for 4.4.

Whoops, left this note in by mistake. These patches are against 4.4 HEAD.
Simon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-12 Thread Simon Wood
Ensure that the G920 is not given the default deadzones.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 80ebd1c..e235f3d 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1441,6 +1441,25 @@ static int hidpp_input_mapping(struct hid_device *hdev, 
struct hid_input *hi,
return 0;
 }
 
+static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+   struct hid_field *field, struct hid_usage *usage,
+   unsigned long **bit, int *max)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+   /* Ensure that Logitech G920 is not given a default fuzz/flat value */
+   if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+   if (usage->type == EV_ABS && (usage->code == ABS_X ||
+   usage->code == ABS_Y || usage->code == ABS_Z ||
+   usage->code == ABS_RZ)) {
+   field->application = HID_GD_MULTIAXIS;
+   }
+   }
+
+   return 0;
+}
+
+
 static void hidpp_populate_input(struct hidpp_device *hidpp,
struct input_dev *input, bool origin_is_hid_core)
 {
@@ -1875,6 +1894,7 @@ static struct hid_driver hidpp_driver = {
.raw_event = hidpp_raw_event,
.input_configured = hidpp_input_configured,
.input_mapping = hidpp_input_mapping,
+   .input_mapped = hidpp_input_mapped,
 };
 
 module_hid_driver(hidpp_driver);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech G920

2015-11-12 Thread Simon Wood
The G920 can adjust the amount of 'turn' it permits, this patch adds
a sysfs file 'range' to control this.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 140 ++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 699a486..80ebd1c 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1295,6 +1295,133 @@ static int k400_connect(struct hid_device *hdev, bool 
connected)
return k400_disable_tap_to_click(hidpp);
 }
 
+/* - */
+/* Logitech G920 Driving Force Racing Wheel for Xbox One */
+/* - */
+
+#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
+
+/* Using session ID = 1 */
+#define CMD_G920_FORCE_GET_APERTURE0x51
+#define CMD_G920_FORCE_SET_APERTURE0x61
+
+struct g920_private_data {
+   u8 force_feature;
+   u16 range;
+};
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static ssize_t g920_range_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
+}
+
+static ssize_t g920_range_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+   struct hidpp_report response;
+   u8 params[2];
+   int ret;
+   u16 range = simple_strtoul(buf, NULL, 10);
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   if (range < 180)
+   range = 180;
+   else if (range > 900)
+   range = 900;
+
+   params[0] = range >> 8;
+   params[1] = range & 0x00FF;
+
+   ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
+   CMD_G920_FORCE_SET_APERTURE, params, 2, );
+   if (ret)
+   return ret;
+
+   pdata->range = range;
+   return count;
+}
+
+static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, 
g920_range_show, g920_range_store);
+
+static int g920_allocate(struct hid_device *hdev)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+   struct g920_private_data *pdata;
+
+   pdata = devm_kzalloc(>dev, sizeof(struct g920_private_data),
+   GFP_KERNEL);
+   if (!pdata)
+   return -ENOMEM;
+
+   hidpp->private_data = pdata;
+
+   return 0;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp)
+{
+   struct g920_private_data *pdata = hidpp->private_data;
+   struct hidpp_report response;
+   u8 feature_type;
+   u8 feature_index;
+   int ret;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hidpp->hid_dev, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   /* Find feature and store for later use */
+   ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
+   _index, _type);
+   if (ret)
+   return ret;
+
+   pdata->force_feature = feature_index;
+
+   /* Read current Range */
+   ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+   CMD_G920_FORCE_GET_APERTURE, NULL, 0, );
+   if (ret > 0) {
+   hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+   __func__, ret);
+   return -EPROTO;
+   }
+   if (ret)
+   return ret;
+
+   pdata->range = get_unaligned_be16([0]);
+
+   /* Create sysfs interface */
+   ret = device_create_file(&(hidpp->hid_dev->dev), _attr_range);
+   if (ret)
+   hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for 
\"range\", errno %d\n", ret);
+
+   return 0;
+}
+
 /* -- 
*/
 /* Generic HID++ devices  
*/
 /* -

[Patch-V2 5/6] HID: Add vendor specific usage pages for Logitech G920

2015-11-12 Thread Simon Wood
The Logitech G920 uses a couple of vendor specific usage pages,
which results in incorrect number of axis/buttons being detected.

This patch adds these pages to the 'ignore' list.

Reported-by: Elias Vanderstuyft 
Signed-off-by: Simon Wood 
---
 drivers/hid/hid-input.c | 4 
 include/linux/hid.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 2ba6bf6..f4eeb6b 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -960,6 +960,10 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
goto ignore;
 
case HID_UP_LOGIVENDOR:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR2:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR3:
goto ignore;
 
case HID_UP_PID:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 251a1d3..a6d7a3f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -168,6 +168,8 @@ struct hid_item {
 #define HID_UP_MSVENDOR0xff00
 #define HID_UP_CUSTOM  0x00ff
 #define HID_UP_LOGIVENDOR  0xffbc
+#define HID_UP_LOGIVENDOR2   0xff09
+#define HID_UP_LOGIVENDOR3   0xff43
 #define HID_UP_LNVENDOR0xffa0
 #define HID_UP_SENSOR  0x0020
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech G920

2015-11-12 Thread Simon Wood
This patch adds basic support for the Logitech G920 wheel when in HID
mode. This wheel 'speaks' the HID++ protocol, and therefor is driven
with hid-logitech-hidpp.

At this stage the driver only shows that it can communicate with the
wheel by outputting the name discovered over HID++.

The normal HID functions work to give input functionality using
joystick/event interface.

Note: in 'hidpp_probe()' we have to start the hardware to get packets
flowing, the same might apply in future for other devices which don't
use the unifying protocol.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-core.c   |  1 +
 drivers/hid/hid-ids.h|  1 +
 drivers/hid/hid-logitech-hidpp.c | 71 +++-
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c6f7a69..190260c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1902,6 +1902,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ac1feea..269e758 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -619,6 +619,7 @@
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2  0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_20xc219
 #define USB_DEVICE_ID_LOGITECH_G29_WHEEL   0xc24f
+#define USB_DEVICE_ID_LOGITECH_G920_WHEEL  0xc262
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940  0xc287
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 0f53dc8..699a486 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -49,11 +49,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
 #define HIDPP_QUIRK_CLASS_K400 BIT(2)
+#define HIDPP_QUIRK_CLASS_G920 BIT(3)
 
 /* bits 2..20 are reserved for classes */
 #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS   BIT(22)
 #define HIDPP_QUIRK_NO_HIDINPUTBIT(23)
+#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS   BIT(24)
 
 #define HIDPP_QUIRK_DELAYED_INIT   (HIDPP_QUIRK_NO_HIDINPUT | \
 HIDPP_QUIRK_CONNECT_EVENTS)
@@ -146,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device 
*hidpp_dev);
 static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
 {
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
int fields_count, ret;
 
+   hidpp = hid_get_drvdata(hdev);
+
switch (hidpp_report->report_id) {
case REPORT_ID_HIDPP_SHORT:
fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -168,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
 */
hidpp_report->device_index = 0xff;
 
-   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
-   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
-   HID_REQ_SET_REPORT);
+   if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
+   ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, 
fields_count);
+   } else {
+   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
+   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
+   HID_REQ_SET_REPORT);
+   }
 
return ret == fields_count ? 0 : -1;
 }
@@ -1430,10 +1439,12 @@ static void hidpp_overwrite_name(struct hid_device 
*hdev, bool use_unifying)
else
name = hidpp_get_device_name(hidpp);
 
-   if (!name)
+   if (!name) {
hid_err(hdev, "unable to retrieve the name of the device");
-   else
+   } else {
+   dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+   }
 
kfree(name);
 }
@@ -1596,6 +1607,25 @@ static int hidpp_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
got

[Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2015-11-12 Thread Simon Wood
When plugged in the Logitech G920 wheel starts with USBID 046d:c261
and behaviors as a vendor specific class. If a 'magic' byte sequence
is sent the wheel will detach and reconnect as a HID device with the
USBID 046d:c262.

Signed-off-by: Simon Wood 
---
 drivers/input/joystick/xpad.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index fd4100d..338a3a4 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -93,6 +93,7 @@
 #define MAP_STICKS_TO_NULL (1 << 2)
 #define DANCEPAD_MAP_CONFIG(MAP_DPAD_TO_BUTTONS |  \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
+#define SWITCH_G920_TO_HID_MODE(1 << 3)
 
 #define XTYPE_XBOX0
 #define XTYPE_XBOX360 1
@@ -134,6 +135,7 @@ static const struct xpad_device {
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
+   { 0x046d, 0xc261, "Logitech G920 Driving Force Racing Wheel", 
SWITCH_G920_TO_HID_MODE, XTYPE_XBOXONE },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX 
},
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
@@ -299,6 +301,7 @@ static struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x045e),/* Microsoft X-Box 360 
controllers */
XPAD_XBOXONE_VENDOR(0x045e),/* Microsoft X-Box One 
controllers */
XPAD_XBOX360_VENDOR(0x046d),/* Logitech X-Box 360 style 
controllers */
+   XPAD_XBOXONE_VENDOR(0x046d),/* Logitech X-Box One style 
controllers */
XPAD_XBOX360_VENDOR(0x0738),/* Mad Catz X-Box 360 
controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOX360_VENDOR(0x0e6f),/* 0x0e6f X-Box 360 controllers 
*/
@@ -1048,6 +1051,19 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
 
+   /* Logitect G920 wheel starts in XBOX mode, but is reconfigured to be 
HID  */
+   /* device with USBID of 046D:C262. Wheel will detach when 'magic' is 
sent. */
+   if (xpad->mapping & SWITCH_G920_TO_HID_MODE) {
+   xpad->odata[0] = 0x0F;
+   xpad->odata[1] = 0x00;
+   xpad->odata[2] = 0x01;
+   xpad->odata[3] = 0x01;
+   xpad->odata[4] = 0x42;
+   xpad->irq_out->transfer_buffer_length = 5;
+
+   return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+   }
+
if (xpad->xtype == XTYPE_XBOXONE) {
/* Xbox one controller needs to be initialized. */
xpad->odata[0] = 0x05;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 0/6] HID: Support for the Logitech G920 Wheel

2015-11-12 Thread Simon Wood
Patch-V2 tweaked as per Benjamin's requests.

This series of patches provide input support for the Logitech G920 gaming wheel.

This wheel is internally different from the other Logitech wheels; when first 
connected it is in X-Box mode and can instructed to switch to HID with a 'magic 
command' (1st patch). Once the wheel reconnects in HID mode it can communicate 
with the HID++ protocol, but using a 'very long' packet size (2nd patch).

Basic input operation is possible with adustment of the 'range' (the amount 
that 
the wheel turns) controlled via the '/sys' interface, same concept as the 
G25/G27/etc.

We also discovered that wheel uses some vendor specific pages, which confuse 
the 
HID system resulting in lots of additional axis reported. This is prevented by 
ignoring these pages (5th patch, thank you Elias).

Note: These patches are applied to Jiri's 'for-next' tree to work with the 
other 
HID++ changes already queued for 4.4.

The future... as the internals of the wheel are considerably more 'capable' we 
are working on implementing Force Feedback using the forth-coming KLGD system.

[Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920
[Patch-V2 2/6] HID: hid-logitech-hidpp: Add support for very long
[Patch-V2 3/6] HID: hid-logitech-hidpp: Add basic support for
[Patch-V2 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech
[Patch-V2 5/6] HID: Add vendor specific usage pages for Logitech G920
[Patch-V2 6/6] HID: hid-logitech-hidpp: G920 remove deadzones
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech G920

2015-11-12 Thread Simon Wood
This patch adds basic support for the Logitech G920 wheel when in HID
mode. This wheel 'speaks' the HID++ protocol, and therefor is driven
with hid-logitech-hidpp.

At this stage the driver only shows that it can communicate with the
wheel by outputting the name discovered over HID++.

The normal HID functions work to give input functionality using
joystick/event interface.

Note: in 'hidpp_probe()' we have to start the hardware to get packets
flowing, the same might apply in future for other devices which don't
use the unifying protocol.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-core.c   |  1 +
 drivers/hid/hid-ids.h|  1 +
 drivers/hid/hid-logitech-hidpp.c | 71 +++-
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c6f7a69..190260c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1902,6 +1902,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ac1feea..269e758 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -619,6 +619,7 @@
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2  0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_20xc219
 #define USB_DEVICE_ID_LOGITECH_G29_WHEEL   0xc24f
+#define USB_DEVICE_ID_LOGITECH_G920_WHEEL  0xc262
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940  0xc287
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 0f53dc8..699a486 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -49,11 +49,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
 #define HIDPP_QUIRK_CLASS_K400 BIT(2)
+#define HIDPP_QUIRK_CLASS_G920 BIT(3)
 
 /* bits 2..20 are reserved for classes */
 #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS   BIT(22)
 #define HIDPP_QUIRK_NO_HIDINPUTBIT(23)
+#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS   BIT(24)
 
 #define HIDPP_QUIRK_DELAYED_INIT   (HIDPP_QUIRK_NO_HIDINPUT | \
 HIDPP_QUIRK_CONNECT_EVENTS)
@@ -146,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device 
*hidpp_dev);
 static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
 {
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
int fields_count, ret;
 
+   hidpp = hid_get_drvdata(hdev);
+
switch (hidpp_report->report_id) {
case REPORT_ID_HIDPP_SHORT:
fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -168,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
 */
hidpp_report->device_index = 0xff;
 
-   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
-   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
-   HID_REQ_SET_REPORT);
+   if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
+   ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, 
fields_count);
+   } else {
+   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
+   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
+   HID_REQ_SET_REPORT);
+   }
 
return ret == fields_count ? 0 : -1;
 }
@@ -1430,10 +1439,12 @@ static void hidpp_overwrite_name(struct hid_device 
*hdev, bool use_unifying)
else
name = hidpp_get_device_name(hidpp);
 
-   if (!name)
+   if (!name) {
hid_err(hdev, "unable to retrieve the name of the device");
-   else
+   } else {
+   dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+   }
 
kfree(name);
 }
@@ -1596,6 +1607,25 @@ static int hidpp_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
 

[Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2015-11-12 Thread Simon Wood
When plugged in the Logitech G920 wheel starts with USBID 046d:c261
and behaviors as a vendor specific class. If a 'magic' byte sequence
is sent the wheel will detach and reconnect as a HID device with the
USBID 046d:c262.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/input/joystick/xpad.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index fd4100d..338a3a4 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -93,6 +93,7 @@
 #define MAP_STICKS_TO_NULL (1 << 2)
 #define DANCEPAD_MAP_CONFIG(MAP_DPAD_TO_BUTTONS |  \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
+#define SWITCH_G920_TO_HID_MODE(1 << 3)
 
 #define XTYPE_XBOX0
 #define XTYPE_XBOX360 1
@@ -134,6 +135,7 @@ static const struct xpad_device {
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
+   { 0x046d, 0xc261, "Logitech G920 Driving Force Racing Wheel", 
SWITCH_G920_TO_HID_MODE, XTYPE_XBOXONE },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX 
},
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
@@ -299,6 +301,7 @@ static struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x045e),/* Microsoft X-Box 360 
controllers */
XPAD_XBOXONE_VENDOR(0x045e),/* Microsoft X-Box One 
controllers */
XPAD_XBOX360_VENDOR(0x046d),/* Logitech X-Box 360 style 
controllers */
+   XPAD_XBOXONE_VENDOR(0x046d),/* Logitech X-Box One style 
controllers */
XPAD_XBOX360_VENDOR(0x0738),/* Mad Catz X-Box 360 
controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOX360_VENDOR(0x0e6f),/* 0x0e6f X-Box 360 controllers 
*/
@@ -1048,6 +1051,19 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
 
+   /* Logitect G920 wheel starts in XBOX mode, but is reconfigured to be 
HID  */
+   /* device with USBID of 046D:C262. Wheel will detach when 'magic' is 
sent. */
+   if (xpad->mapping & SWITCH_G920_TO_HID_MODE) {
+   xpad->odata[0] = 0x0F;
+   xpad->odata[1] = 0x00;
+   xpad->odata[2] = 0x01;
+   xpad->odata[3] = 0x01;
+   xpad->odata[4] = 0x42;
+   xpad->irq_out->transfer_buffer_length = 5;
+
+   return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+   }
+
if (xpad->xtype == XTYPE_XBOXONE) {
/* Xbox one controller needs to be initialized. */
xpad->odata[0] = 0x05;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 2/6] HID: hid-logitech-hidpp: Add support for very long packets

2015-11-12 Thread Simon Wood
Patch add support for the 'very long' HID++ packets, which are
64 bytes in length.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 59 
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5fd9786..0f53dc8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -40,9 +40,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
 
 #define REPORT_ID_HIDPP_SHORT  0x10
 #define REPORT_ID_HIDPP_LONG   0x11
+#define REPORT_ID_HIDPP_VERY_LONG  0x12
 
 #define HIDPP_REPORT_SHORT_LENGTH  7
 #define HIDPP_REPORT_LONG_LENGTH   20
+#define HIDPP_REPORT_VERY_LONG_LENGTH  64
 
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
@@ -81,13 +83,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 struct fap {
u8 feature_index;
u8 funcindex_clientid;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct rap {
u8 sub_id;
u8 reg_address;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct hidpp_report {
@@ -153,6 +155,9 @@ static int __hidpp_send_report(struct hid_device *hdev,
case REPORT_ID_HIDPP_LONG:
fields_count = HIDPP_REPORT_LONG_LENGTH;
break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   fields_count = HIDPP_REPORT_VERY_LONG_LENGTH;
+   break;
default:
return -ENODEV;
}
@@ -217,8 +222,9 @@ static int hidpp_send_message_sync(struct hidpp_device 
*hidpp,
goto exit;
}
 
-   if (response->report_id == REPORT_ID_HIDPP_LONG &&
-   response->fap.feature_index == HIDPP20_ERROR) {
+   if ((response->report_id == REPORT_ID_HIDPP_LONG ||
+   response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
+   response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
goto exit;
@@ -243,7 +249,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device 
*hidpp,
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
if (!message)
return -ENOMEM;
-   message->report_id = REPORT_ID_HIDPP_LONG;
+
+   if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4))
+   message->report_id = REPORT_ID_HIDPP_VERY_LONG;
+   else
+   message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid;
memcpy(>fap.params, params, param_count);
@@ -258,13 +268,23 @@ static int hidpp_send_rap_command_sync(struct 
hidpp_device *hidpp_dev,
struct hidpp_report *response)
 {
struct hidpp_report *message;
-   int ret;
+   int ret, max_count;
 
-   if ((report_id != REPORT_ID_HIDPP_SHORT) &&
-   (report_id != REPORT_ID_HIDPP_LONG))
+   switch (report_id) {
+   case REPORT_ID_HIDPP_SHORT:
+   max_count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
+   max_count = HIDPP_REPORT_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   default:
return -EINVAL;
+   }
 
-   if (param_count > sizeof(message->rap.params))
+   if (param_count > max_count)
return -EINVAL;
 
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
@@ -508,10 +528,19 @@ static int hidpp_devicenametype_get_device_name(struct 
hidpp_device *hidpp,
if (ret)
return ret;
 
-   if (response.report_id == REPORT_ID_HIDPP_LONG)
+   switch (response.report_id) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
count = HIDPP_REPORT_LONG_LENGTH - 4;
-   else
+   break;
+   case REPORT_ID_HIDPP_SHORT:
count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   default:
+   return -EPROTO;
+   }
 
if (len_buf < count)
count = len_buf;
@@ -1347,6 +1376,14 @@ static int hidpp_raw_event(struct hid_device *hdev, 
struct hid_report *report,
 
/* Generic HID++ processing. */
switch (data[0]) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   if (size != HIDPP_REP

[Patch-V2 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-12 Thread Simon Wood
Ensure that the G920 is not given the default deadzones.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 80ebd1c..e235f3d 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1441,6 +1441,25 @@ static int hidpp_input_mapping(struct hid_device *hdev, 
struct hid_input *hi,
return 0;
 }
 
+static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+   struct hid_field *field, struct hid_usage *usage,
+   unsigned long **bit, int *max)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+   /* Ensure that Logitech G920 is not given a default fuzz/flat value */
+   if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+   if (usage->type == EV_ABS && (usage->code == ABS_X ||
+   usage->code == ABS_Y || usage->code == ABS_Z ||
+   usage->code == ABS_RZ)) {
+   field->application = HID_GD_MULTIAXIS;
+   }
+   }
+
+   return 0;
+}
+
+
 static void hidpp_populate_input(struct hidpp_device *hidpp,
struct input_dev *input, bool origin_is_hid_core)
 {
@@ -1875,6 +1894,7 @@ static struct hid_driver hidpp_driver = {
.raw_event = hidpp_raw_event,
.input_configured = hidpp_input_configured,
.input_mapping = hidpp_input_mapping,
+   .input_mapped = hidpp_input_mapped,
 };
 
 module_hid_driver(hidpp_driver);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 5/6] HID: Add vendor specific usage pages for Logitech G920

2015-11-12 Thread Simon Wood
The Logitech G920 uses a couple of vendor specific usage pages,
which results in incorrect number of axis/buttons being detected.

This patch adds these pages to the 'ignore' list.

Reported-by: Elias Vanderstuyft <elias@gmail.com>
Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-input.c | 4 
 include/linux/hid.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 2ba6bf6..f4eeb6b 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -960,6 +960,10 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
goto ignore;
 
case HID_UP_LOGIVENDOR:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR2:
+   /* intentional fallback */
+   case HID_UP_LOGIVENDOR3:
goto ignore;
 
case HID_UP_PID:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 251a1d3..a6d7a3f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -168,6 +168,8 @@ struct hid_item {
 #define HID_UP_MSVENDOR0xff00
 #define HID_UP_CUSTOM  0x00ff
 #define HID_UP_LOGIVENDOR  0xffbc
+#define HID_UP_LOGIVENDOR2   0xff09
+#define HID_UP_LOGIVENDOR3   0xff43
 #define HID_UP_LNVENDOR0xffa0
 #define HID_UP_SENSOR  0x0020
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 0/6] HID: Support for the Logitech G920 Wheel

2015-11-12 Thread Simon Wood
Patch-V2 tweaked as per Benjamin's requests.

This series of patches provide input support for the Logitech G920 gaming wheel.

This wheel is internally different from the other Logitech wheels; when first 
connected it is in X-Box mode and can instructed to switch to HID with a 'magic 
command' (1st patch). Once the wheel reconnects in HID mode it can communicate 
with the HID++ protocol, but using a 'very long' packet size (2nd patch).

Basic input operation is possible with adustment of the 'range' (the amount 
that 
the wheel turns) controlled via the '/sys' interface, same concept as the 
G25/G27/etc.

We also discovered that wheel uses some vendor specific pages, which confuse 
the 
HID system resulting in lots of additional axis reported. This is prevented by 
ignoring these pages (5th patch, thank you Elias).

Note: These patches are applied to Jiri's 'for-next' tree to work with the 
other 
HID++ changes already queued for 4.4.

The future... as the internals of the wheel are considerably more 'capable' we 
are working on implementing Force Feedback using the forth-coming KLGD system.

[Patch-V2 1/6] INPUT: xpad: Add minimal support for Logitech G920
[Patch-V2 2/6] HID: hid-logitech-hidpp: Add support for very long
[Patch-V2 3/6] HID: hid-logitech-hidpp: Add basic support for
[Patch-V2 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech
[Patch-V2 5/6] HID: Add vendor specific usage pages for Logitech G920
[Patch-V2 6/6] HID: hid-logitech-hidpp: G920 remove deadzones
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Patch-V2 0/6] HID: Support for the Logitech G920 Wheel

2015-11-12 Thread Simon Wood
> Note: These patches are applied to Jiri's 'for-next' tree to work with
> the other HID++ changes already queued for 4.4.

Whoops, left this note in by mistake. These patches are against 4.4 HEAD.
Simon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch-V2 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech G920

2015-11-12 Thread Simon Wood
The G920 can adjust the amount of 'turn' it permits, this patch adds
a sysfs file 'range' to control this.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 140 ++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 699a486..80ebd1c 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1295,6 +1295,133 @@ static int k400_connect(struct hid_device *hdev, bool 
connected)
return k400_disable_tap_to_click(hidpp);
 }
 
+/* - */
+/* Logitech G920 Driving Force Racing Wheel for Xbox One */
+/* - */
+
+#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
+
+/* Using session ID = 1 */
+#define CMD_G920_FORCE_GET_APERTURE0x51
+#define CMD_G920_FORCE_SET_APERTURE0x61
+
+struct g920_private_data {
+   u8 force_feature;
+   u16 range;
+};
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static ssize_t g920_range_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
+}
+
+static ssize_t g920_range_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+   struct hidpp_report response;
+   u8 params[2];
+   int ret;
+   u16 range = simple_strtoul(buf, NULL, 10);
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   if (range < 180)
+   range = 180;
+   else if (range > 900)
+   range = 900;
+
+   params[0] = range >> 8;
+   params[1] = range & 0x00FF;
+
+   ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
+   CMD_G920_FORCE_SET_APERTURE, params, 2, );
+   if (ret)
+   return ret;
+
+   pdata->range = range;
+   return count;
+}
+
+static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, 
g920_range_show, g920_range_store);
+
+static int g920_allocate(struct hid_device *hdev)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+   struct g920_private_data *pdata;
+
+   pdata = devm_kzalloc(>dev, sizeof(struct g920_private_data),
+   GFP_KERNEL);
+   if (!pdata)
+   return -ENOMEM;
+
+   hidpp->private_data = pdata;
+
+   return 0;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp)
+{
+   struct g920_private_data *pdata = hidpp->private_data;
+   struct hidpp_report response;
+   u8 feature_type;
+   u8 feature_index;
+   int ret;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hidpp->hid_dev, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   /* Find feature and store for later use */
+   ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
+   _index, _type);
+   if (ret)
+   return ret;
+
+   pdata->force_feature = feature_index;
+
+   /* Read current Range */
+   ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+   CMD_G920_FORCE_GET_APERTURE, NULL, 0, );
+   if (ret > 0) {
+   hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+   __func__, ret);
+   return -EPROTO;
+   }
+   if (ret)
+   return ret;
+
+   pdata->range = get_unaligned_be16([0]);
+
+   /* Create sysfs interface */
+   ret = device_create_file(&(hidpp->hid_dev->dev), _attr_range);
+   if (ret)
+   hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for 
\"range\", errno %d\n", ret);
+
+   return 0;
+}
+
 /* -- 
*/
 /* Generic HID++ devices  
*/
 /* --

Re: [PATCH 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-10 Thread Simon Wood

> With this change, and the nitpicks in the other patches, the series is:
> Reviewed-by: Benjamin Tissoires 

Have Patch-V2 in progress. Other build problems stopped in last night but
trying again with new pull - hopefully they are fixed.

Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-10 Thread Simon Wood

> With this change, and the nitpicks in the other patches, the series is:
> Reviewed-by: Benjamin Tissoires 

Have Patch-V2 in progress. Other build problems stopped in last night but
trying again with new pull - hopefully they are fixed.

Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech G920

2015-11-07 Thread Simon Wood
The G920 can adjust the amount of 'turn' it permits, this patch adds
a sysfs file 'range' to control this.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 140 ++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index dbb9ff3..03e01be 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1295,6 +1295,133 @@ static int k400_connect(struct hid_device *hdev, bool 
connected)
return k400_disable_tap_to_click(hidpp);
 }
 
+/* - */
+/* Logitech G920 Driving Force Racing Wheel for Xbox One */
+/* - */
+
+#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
+
+/* Using session ID = 1 */
+#define CMD_G920_FORCE_GET_APERTURE0x51
+#define CMD_G920_FORCE_SET_APERTURE0x61
+
+struct g920_private_data {
+   u8 force_feature;
+   u16 range;
+};
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static ssize_t g920_range_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
+}
+
+static ssize_t g920_range_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+   struct hidpp_report response;
+   u8 params[2];
+   int ret;
+   u16 range = simple_strtoul(buf, NULL, 10);
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   if (range < 180)
+   range = 180;
+   else if (range > 900)
+   range = 900;
+
+   params[0] = range >> 8;
+   params[1] = range & 0x00FF;
+
+   ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
+   CMD_G920_FORCE_SET_APERTURE, params, 2, );
+   if (ret)
+   return ret;
+
+   pdata->range = range;
+   return count;
+}
+
+static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, 
g920_range_show, g920_range_store);
+
+static int g920_allocate(struct hid_device *hdev)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+   struct g920_private_data *pdata;
+
+   pdata = devm_kzalloc(>dev, sizeof(struct g920_private_data),
+   GFP_KERNEL);
+   if (!pdata)
+   return -ENOMEM;
+
+   hidpp->private_data = pdata;
+
+   return 0;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp)
+{
+   struct g920_private_data *pdata = hidpp->private_data;
+   struct hidpp_report response;
+   u8 feature_type;
+   u8 feature_index;
+   int ret;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hidpp->hid_dev, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   /* Find feature and store for later use */
+   ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
+   _index, _type);
+   if (ret)
+   return ret;
+
+   pdata->force_feature = feature_index;
+
+   /* Read current Range */
+   ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+   CMD_G920_FORCE_GET_APERTURE, NULL, 0, );
+   if (ret > 0) {
+   hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+   __func__, ret);
+   return -EPROTO;
+   }
+   if (ret)
+   return ret;
+
+   pdata->range = get_unaligned_be16([0]);
+
+   /* Create sysfs interface */
+   ret = device_create_file(&(hidpp->hid_dev->dev), _attr_range);
+   if (ret)
+   hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for 
\"range\", errno %d\n", ret);
+
+   return 0;
+}
+
 /* -- 
*/
 /* Generic HID++ devices  
*/
 /* -

[PATCH 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech G920

2015-11-07 Thread Simon Wood
This patch adds basic support for the Logitech G920 wheel when in HID
mode. This wheel 'speaks' the HID++ protocol, and therefor is driven
with hid-logitech-hidpp.

At this stage the driver only shows that it can communicate with the
wheel by outputting the name discovered over HID++.

The normal HID functions work to give input functionality using
joystick/event interface.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-core.c   |  1 +
 drivers/hid/hid-ids.h|  1 +
 drivers/hid/hid-logitech-hidpp.c | 69 +++-
 3 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bcd914a..60d564d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1896,6 +1896,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index f769208..d3500c4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -614,6 +614,7 @@
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2  0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_20xc219
 #define USB_DEVICE_ID_LOGITECH_G29_WHEEL   0xc24f
+#define USB_DEVICE_ID_LOGITECH_G920_WHEEL  0xc262
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940  0xc287
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 08e65e8..dbb9ff3 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -49,11 +49,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
 #define HIDPP_QUIRK_CLASS_K400 BIT(2)
+#define HIDPP_QUIRK_CLASS_G920 BIT(3)
 
 /* bits 2..20 are reserved for classes */
 #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS   BIT(22)
 #define HIDPP_QUIRK_NO_HIDINPUTBIT(23)
+#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS   BIT(24)
 
 #define HIDPP_QUIRK_DELAYED_INIT   (HIDPP_QUIRK_NO_HIDINPUT | \
 HIDPP_QUIRK_CONNECT_EVENTS)
@@ -146,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device 
*hidpp_dev);
 static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
 {
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
int fields_count, ret;
 
+   hidpp = hid_get_drvdata(hdev);
+
switch (hidpp_report->report_id) {
case REPORT_ID_HIDPP_SHORT:
fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -168,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
 */
hidpp_report->device_index = 0xff;
 
-   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
-   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
-   HID_REQ_SET_REPORT);
+   if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
+   ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, 
fields_count);
+   } else {
+   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
+   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
+   HID_REQ_SET_REPORT);
+   }
 
return ret == fields_count ? 0 : -1;
 }
@@ -1430,8 +1439,10 @@ static void hidpp_overwrite_name(struct hid_device 
*hdev, bool use_unifying)
 
if (!name)
hid_err(hdev, "unable to retrieve the name of the device");
-   else
+   else {
+   dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+   }
 
kfree(name);
 }
@@ -1594,6 +1605,25 @@ static int hidpp_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
goto hid_parse_fail;
}
 
+   if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+   connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+   if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+   ret = hid_hw_start(hdev, connect_mask);
+ 

[PATCH 5/6] HID: Add vendor specific usage pages for Logitech G920

2015-11-07 Thread Simon Wood
The Logitech G920 uses a couple of vendor specific usage pages,
which results in incorrect number of axis/buttons being detected.

This patch adds these pages to the 'ignore' list.

Reported-by: Elias Vanderstuyft 
Signed-off-by: Simon Wood 
---
 drivers/hid/hid-input.c | 2 +-
 include/linux/hid.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 53aeaf6..c120be5 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -959,7 +959,7 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
set_bit(EV_REP, input->evbit);
goto ignore;
 
-   case HID_UP_LOGIVENDOR:
+   case HID_UP_LOGIVENDOR: case HID_UP_LOGIVENDOR2: case 
HID_UP_LOGIVENDOR3:
goto ignore;
 
case HID_UP_PID:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index f17980d..ce1d883 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -168,6 +168,8 @@ struct hid_item {
 #define HID_UP_MSVENDOR0xff00
 #define HID_UP_CUSTOM  0x00ff
 #define HID_UP_LOGIVENDOR  0xffbc
+#define HID_UP_LOGIVENDOR2   0xff09
+#define HID_UP_LOGIVENDOR3   0xff43
 #define HID_UP_LNVENDOR0xffa0
 #define HID_UP_SENSOR  0x0020
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2015-11-07 Thread Simon Wood
When plugged in the Logitech G920 wheel starts with USBID 046d:c261
and behaviors as a vendor specific class. If a 'magic' byte sequence
is sent the wheel will detach and reconnect as a HID device with the
USBID 046d:c262.

Signed-off-by: Simon Wood 
---
 drivers/input/joystick/xpad.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f8850f9..af83f7e 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -93,6 +93,7 @@
 #define MAP_STICKS_TO_NULL (1 << 2)
 #define DANCEPAD_MAP_CONFIG(MAP_DPAD_TO_BUTTONS |  \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
+#define SWITCH_G920_TO_HID_MODE(1 << 3)
 
 #define XTYPE_XBOX0
 #define XTYPE_XBOX360 1
@@ -133,6 +134,7 @@ static const struct xpad_device {
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
+   { 0x046d, 0xc261, "Logitech G920 Driving Force Racing Wheel", 
SWITCH_G920_TO_HID_MODE, XTYPE_XBOXONE },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX 
},
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
@@ -299,6 +301,7 @@ static struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x045e),/* Microsoft X-Box 360 
controllers */
XPAD_XBOXONE_VENDOR(0x045e),/* Microsoft X-Box One 
controllers */
XPAD_XBOX360_VENDOR(0x046d),/* Logitech X-Box 360 style 
controllers */
+   XPAD_XBOXONE_VENDOR(0x046d),/* Logitech X-Box One style 
controllers */
XPAD_XBOX360_VENDOR(0x0738),/* Mad Catz X-Box 360 
controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOX360_VENDOR(0x0e6f),/* 0x0e6f X-Box 360 controllers 
*/
@@ -1021,6 +1024,19 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
 
+   /* Logitect G920 wheel starts in XBOX mode, but is reconfigured to be 
HID  */
+   /* device with USBID of 046D:C262. Wheel will detach when 'magic' is 
sent. */
+   if (xpad->mapping & SWITCH_G920_TO_HID_MODE) {
+   xpad->odata[0] = 0x0F;
+   xpad->odata[1] = 0x00;
+   xpad->odata[2] = 0x01;
+   xpad->odata[3] = 0x01;
+   xpad->odata[4] = 0x42;
+   xpad->irq_out->transfer_buffer_length = 5;
+
+   return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+   }
+
if (xpad->xtype == XTYPE_XBOXONE) {
/* Xbox one controller needs to be initialized. */
xpad->odata[0] = 0x05;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/6] HID: hid-logitech-hidpp: Add support for very long packets

2015-11-07 Thread Simon Wood
Patch add support for the 'very long' HID++ packets, which are
64 bytes in length.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 59 
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 452e5d5..08e65e8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -40,9 +40,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
 
 #define REPORT_ID_HIDPP_SHORT  0x10
 #define REPORT_ID_HIDPP_LONG   0x11
+#define REPORT_ID_HIDPP_VERY_LONG  0x12
 
 #define HIDPP_REPORT_SHORT_LENGTH  7
 #define HIDPP_REPORT_LONG_LENGTH   20
+#define HIDPP_REPORT_VERY_LONG_LENGTH  64
 
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
@@ -81,13 +83,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 struct fap {
u8 feature_index;
u8 funcindex_clientid;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct rap {
u8 sub_id;
u8 reg_address;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct hidpp_report {
@@ -153,6 +155,9 @@ static int __hidpp_send_report(struct hid_device *hdev,
case REPORT_ID_HIDPP_LONG:
fields_count = HIDPP_REPORT_LONG_LENGTH;
break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   fields_count = HIDPP_REPORT_VERY_LONG_LENGTH;
+   break;
default:
return -ENODEV;
}
@@ -217,8 +222,9 @@ static int hidpp_send_message_sync(struct hidpp_device 
*hidpp,
goto exit;
}
 
-   if (response->report_id == REPORT_ID_HIDPP_LONG &&
-   response->fap.feature_index == HIDPP20_ERROR) {
+   if ((response->report_id == REPORT_ID_HIDPP_LONG ||
+   response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
+   response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
goto exit;
@@ -243,7 +249,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device 
*hidpp,
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
if (!message)
return -ENOMEM;
-   message->report_id = REPORT_ID_HIDPP_LONG;
+
+   if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4))
+   message->report_id = REPORT_ID_HIDPP_VERY_LONG;
+   else
+   message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid;
memcpy(>fap.params, params, param_count);
@@ -258,13 +268,23 @@ static int hidpp_send_rap_command_sync(struct 
hidpp_device *hidpp_dev,
struct hidpp_report *response)
 {
struct hidpp_report *message;
-   int ret;
+   int ret, max_count;
 
-   if ((report_id != REPORT_ID_HIDPP_SHORT) &&
-   (report_id != REPORT_ID_HIDPP_LONG))
+   switch (report_id) {
+   case REPORT_ID_HIDPP_SHORT:
+   max_count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
+   max_count = HIDPP_REPORT_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   default:
return -EINVAL;
+   }
 
-   if (param_count > sizeof(message->rap.params))
+   if (param_count > max_count)
return -EINVAL;
 
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
@@ -508,10 +528,19 @@ static int hidpp_devicenametype_get_device_name(struct 
hidpp_device *hidpp,
if (ret)
return ret;
 
-   if (response.report_id == REPORT_ID_HIDPP_LONG)
+   switch (response.report_id) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
count = HIDPP_REPORT_LONG_LENGTH - 4;
-   else
+   break;
+   case REPORT_ID_HIDPP_SHORT:
count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   default:
+   return -EPROTO;
+   }
 
if (len_buf < count)
count = len_buf;
@@ -1345,6 +1374,14 @@ static int hidpp_raw_event(struct hid_device *hdev, 
struct hid_report *report,
 
/* Generic HID++ processing. */
switch (data[0]) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   if (size != HIDPP_REPORT_VERY_LONG_L

[PATCH 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-07 Thread Simon Wood
Ensure that the G920 is not given the default deadzones.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-logitech-hidpp.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 03e01be..853b9c2 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1441,6 +1441,27 @@ static int hidpp_input_mapping(struct hid_device *hdev, 
struct hid_input *hi,
return 0;
 }
 
+static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+   struct hid_field *field, struct hid_usage *usage,
+   unsigned long **bit, int *max)
+{
+   /* Ensure that Logitech G920 is not given a default fuzz/flat value */
+   if (usage->type == EV_ABS && (usage->code == ABS_X ||
+   usage->code == ABS_Y || usage->code == ABS_Z ||
+   usage->code == ABS_RZ)) {
+   switch (hdev->product) {
+   case USB_DEVICE_ID_LOGITECH_G920_WHEEL:
+   field->application = HID_GD_MULTIAXIS;
+   break;
+   default:
+   break;
+   }
+   }
+
+   return 0;
+}
+
+
 static void hidpp_populate_input(struct hidpp_device *hidpp,
struct input_dev *input, bool origin_is_hid_core)
 {
@@ -1873,6 +1894,7 @@ static struct hid_driver hidpp_driver = {
.raw_event = hidpp_raw_event,
.input_configured = hidpp_input_configured,
.input_mapping = hidpp_input_mapping,
+   .input_mapped = hidpp_input_mapped,
 };
 
 module_hid_driver(hidpp_driver);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


HID: Support for the Logitech G920 wheel

2015-11-07 Thread Simon Wood
This series of patches provide input support for the Logitech G920 gaming wheel.

This wheel is internally different from the other Logitech wheels; when first 
connected it is in X-Box mode and can instructed to switch to HID with a 'magic 
command' (1st patch). Once the wheel reconnects in HID mode it can communicate 
with the HID++ protocol, but using a 'very long' packet size (2nd patch).

Basic input operation is possible with adustment of the 'range' (the amount 
that 
the wheel turns) controlled via the '/sys' interface, same concept as the 
G25/G27/etc.

We also discovered that wheel uses some vendor specific pages, which confuse 
the 
HID system resulting in lots of additional axis reported. This is prevented by 
ignoring these pages (5th patch, thank you Elias).


Note: These patches are applied to Jiri's 'for-next' tree to work with the 
other 
HID++ changes already queued for 4.4.

[PATCH 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel
[PATCH 2/6] HID: hid-logitech-hidpp: Add support for very long
[PATCH 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech
[PATCH 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech
[PATCH 5/6] HID: Add vendor specific usage pages for Logitech G920
[PATCH 6/6] HID: hid-logitech-hidpp: G920 remove deadzones


The future... as the internals of the wheel are considerably more 'capable' we 
are working on implementing Force Feedback using the forth-coming KLGD system.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 6/6] HID: hid-logitech-hidpp: G920 remove deadzones

2015-11-07 Thread Simon Wood
Ensure that the G920 is not given the default deadzones.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 03e01be..853b9c2 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1441,6 +1441,27 @@ static int hidpp_input_mapping(struct hid_device *hdev, 
struct hid_input *hi,
return 0;
 }
 
+static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+   struct hid_field *field, struct hid_usage *usage,
+   unsigned long **bit, int *max)
+{
+   /* Ensure that Logitech G920 is not given a default fuzz/flat value */
+   if (usage->type == EV_ABS && (usage->code == ABS_X ||
+   usage->code == ABS_Y || usage->code == ABS_Z ||
+   usage->code == ABS_RZ)) {
+   switch (hdev->product) {
+   case USB_DEVICE_ID_LOGITECH_G920_WHEEL:
+   field->application = HID_GD_MULTIAXIS;
+   break;
+   default:
+   break;
+   }
+   }
+
+   return 0;
+}
+
+
 static void hidpp_populate_input(struct hidpp_device *hidpp,
struct input_dev *input, bool origin_is_hid_core)
 {
@@ -1873,6 +1894,7 @@ static struct hid_driver hidpp_driver = {
.raw_event = hidpp_raw_event,
.input_configured = hidpp_input_configured,
.input_mapping = hidpp_input_mapping,
+   .input_mapped = hidpp_input_mapped,
 };
 
 module_hid_driver(hidpp_driver);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


HID: Support for the Logitech G920 wheel

2015-11-07 Thread Simon Wood
This series of patches provide input support for the Logitech G920 gaming wheel.

This wheel is internally different from the other Logitech wheels; when first 
connected it is in X-Box mode and can instructed to switch to HID with a 'magic 
command' (1st patch). Once the wheel reconnects in HID mode it can communicate 
with the HID++ protocol, but using a 'very long' packet size (2nd patch).

Basic input operation is possible with adustment of the 'range' (the amount 
that 
the wheel turns) controlled via the '/sys' interface, same concept as the 
G25/G27/etc.

We also discovered that wheel uses some vendor specific pages, which confuse 
the 
HID system resulting in lots of additional axis reported. This is prevented by 
ignoring these pages (5th patch, thank you Elias).


Note: These patches are applied to Jiri's 'for-next' tree to work with the 
other 
HID++ changes already queued for 4.4.

[PATCH 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel
[PATCH 2/6] HID: hid-logitech-hidpp: Add support for very long
[PATCH 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech
[PATCH 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech
[PATCH 5/6] HID: Add vendor specific usage pages for Logitech G920
[PATCH 6/6] HID: hid-logitech-hidpp: G920 remove deadzones


The future... as the internals of the wheel are considerably more 'capable' we 
are working on implementing Force Feedback using the forth-coming KLGD system.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/6] INPUT: xpad: Add minimal support for Logitech G920 Wheel

2015-11-07 Thread Simon Wood
When plugged in the Logitech G920 wheel starts with USBID 046d:c261
and behaviors as a vendor specific class. If a 'magic' byte sequence
is sent the wheel will detach and reconnect as a HID device with the
USBID 046d:c262.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/input/joystick/xpad.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f8850f9..af83f7e 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -93,6 +93,7 @@
 #define MAP_STICKS_TO_NULL (1 << 2)
 #define DANCEPAD_MAP_CONFIG(MAP_DPAD_TO_BUTTONS |  \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
+#define SWITCH_G920_TO_HID_MODE(1 << 3)
 
 #define XTYPE_XBOX0
 #define XTYPE_XBOX360 1
@@ -133,6 +134,7 @@ static const struct xpad_device {
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
+   { 0x046d, 0xc261, "Logitech G920 Driving Force Racing Wheel", 
SWITCH_G920_TO_HID_MODE, XTYPE_XBOXONE },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX 
},
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
@@ -299,6 +301,7 @@ static struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x045e),/* Microsoft X-Box 360 
controllers */
XPAD_XBOXONE_VENDOR(0x045e),/* Microsoft X-Box One 
controllers */
XPAD_XBOX360_VENDOR(0x046d),/* Logitech X-Box 360 style 
controllers */
+   XPAD_XBOXONE_VENDOR(0x046d),/* Logitech X-Box One style 
controllers */
XPAD_XBOX360_VENDOR(0x0738),/* Mad Catz X-Box 360 
controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOX360_VENDOR(0x0e6f),/* 0x0e6f X-Box 360 controllers 
*/
@@ -1021,6 +1024,19 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
 
+   /* Logitect G920 wheel starts in XBOX mode, but is reconfigured to be 
HID  */
+   /* device with USBID of 046D:C262. Wheel will detach when 'magic' is 
sent. */
+   if (xpad->mapping & SWITCH_G920_TO_HID_MODE) {
+   xpad->odata[0] = 0x0F;
+   xpad->odata[1] = 0x00;
+   xpad->odata[2] = 0x01;
+   xpad->odata[3] = 0x01;
+   xpad->odata[4] = 0x42;
+   xpad->irq_out->transfer_buffer_length = 5;
+
+   return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+   }
+
if (xpad->xtype == XTYPE_XBOXONE) {
/* Xbox one controller needs to be initialized. */
xpad->odata[0] = 0x05;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/6] HID: hid-logitech-hidpp: Add support for very long packets

2015-11-07 Thread Simon Wood
Patch add support for the 'very long' HID++ packets, which are
64 bytes in length.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 59 
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 452e5d5..08e65e8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -40,9 +40,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
 
 #define REPORT_ID_HIDPP_SHORT  0x10
 #define REPORT_ID_HIDPP_LONG   0x11
+#define REPORT_ID_HIDPP_VERY_LONG  0x12
 
 #define HIDPP_REPORT_SHORT_LENGTH  7
 #define HIDPP_REPORT_LONG_LENGTH   20
+#define HIDPP_REPORT_VERY_LONG_LENGTH  64
 
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
@@ -81,13 +83,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 struct fap {
u8 feature_index;
u8 funcindex_clientid;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct rap {
u8 sub_id;
u8 reg_address;
-   u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+   u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
 };
 
 struct hidpp_report {
@@ -153,6 +155,9 @@ static int __hidpp_send_report(struct hid_device *hdev,
case REPORT_ID_HIDPP_LONG:
fields_count = HIDPP_REPORT_LONG_LENGTH;
break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   fields_count = HIDPP_REPORT_VERY_LONG_LENGTH;
+   break;
default:
return -ENODEV;
}
@@ -217,8 +222,9 @@ static int hidpp_send_message_sync(struct hidpp_device 
*hidpp,
goto exit;
}
 
-   if (response->report_id == REPORT_ID_HIDPP_LONG &&
-   response->fap.feature_index == HIDPP20_ERROR) {
+   if ((response->report_id == REPORT_ID_HIDPP_LONG ||
+   response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
+   response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
goto exit;
@@ -243,7 +249,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device 
*hidpp,
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
if (!message)
return -ENOMEM;
-   message->report_id = REPORT_ID_HIDPP_LONG;
+
+   if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4))
+   message->report_id = REPORT_ID_HIDPP_VERY_LONG;
+   else
+   message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid;
memcpy(>fap.params, params, param_count);
@@ -258,13 +268,23 @@ static int hidpp_send_rap_command_sync(struct 
hidpp_device *hidpp_dev,
struct hidpp_report *response)
 {
struct hidpp_report *message;
-   int ret;
+   int ret, max_count;
 
-   if ((report_id != REPORT_ID_HIDPP_SHORT) &&
-   (report_id != REPORT_ID_HIDPP_LONG))
+   switch (report_id) {
+   case REPORT_ID_HIDPP_SHORT:
+   max_count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
+   max_count = HIDPP_REPORT_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_VERY_LONG:
+   max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   default:
return -EINVAL;
+   }
 
-   if (param_count > sizeof(message->rap.params))
+   if (param_count > max_count)
return -EINVAL;
 
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
@@ -508,10 +528,19 @@ static int hidpp_devicenametype_get_device_name(struct 
hidpp_device *hidpp,
if (ret)
return ret;
 
-   if (response.report_id == REPORT_ID_HIDPP_LONG)
+   switch (response.report_id) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+   break;
+   case REPORT_ID_HIDPP_LONG:
count = HIDPP_REPORT_LONG_LENGTH - 4;
-   else
+   break;
+   case REPORT_ID_HIDPP_SHORT:
count = HIDPP_REPORT_SHORT_LENGTH - 4;
+   break;
+   default:
+   return -EPROTO;
+   }
 
if (len_buf < count)
count = len_buf;
@@ -1345,6 +1374,14 @@ static int hidpp_raw_event(struct hid_device *hdev, 
struct hid_report *report,
 
/* Generic HID++ processing. */
switch (data[0]) {
+   case REPORT_ID_HIDPP_VERY_LONG:
+   if (size != HIDPP_REP

[PATCH 4/6] HID: hid-logitech-hidpp: Add range sysfs for Logitech G920

2015-11-07 Thread Simon Wood
The G920 can adjust the amount of 'turn' it permits, this patch adds
a sysfs file 'range' to control this.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-logitech-hidpp.c | 140 ++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index dbb9ff3..03e01be 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1295,6 +1295,133 @@ static int k400_connect(struct hid_device *hdev, bool 
connected)
return k400_disable_tap_to_click(hidpp);
 }
 
+/* - */
+/* Logitech G920 Driving Force Racing Wheel for Xbox One */
+/* - */
+
+#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
+
+/* Using session ID = 1 */
+#define CMD_G920_FORCE_GET_APERTURE0x51
+#define CMD_G920_FORCE_SET_APERTURE0x61
+
+struct g920_private_data {
+   u8 force_feature;
+   u16 range;
+};
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static ssize_t g920_range_show(struct device *dev, struct device_attribute 
*attr,
+   char *buf)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
+}
+
+static ssize_t g920_range_store(struct device *dev, struct device_attribute 
*attr,
+const char *buf, size_t count)
+{
+   struct hid_device *hid = to_hid_device(dev);
+   struct hidpp_device *hidpp = hid_get_drvdata(hid);
+   struct g920_private_data *pdata;
+   struct hidpp_report response;
+   u8 params[2];
+   int ret;
+   u16 range = simple_strtoul(buf, NULL, 10);
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hid, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   if (range < 180)
+   range = 180;
+   else if (range > 900)
+   range = 900;
+
+   params[0] = range >> 8;
+   params[1] = range & 0x00FF;
+
+   ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
+   CMD_G920_FORCE_SET_APERTURE, params, 2, );
+   if (ret)
+   return ret;
+
+   pdata->range = range;
+   return count;
+}
+
+static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, 
g920_range_show, g920_range_store);
+
+static int g920_allocate(struct hid_device *hdev)
+{
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+   struct g920_private_data *pdata;
+
+   pdata = devm_kzalloc(>dev, sizeof(struct g920_private_data),
+   GFP_KERNEL);
+   if (!pdata)
+   return -ENOMEM;
+
+   hidpp->private_data = pdata;
+
+   return 0;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp)
+{
+   struct g920_private_data *pdata = hidpp->private_data;
+   struct hidpp_report response;
+   u8 feature_type;
+   u8 feature_index;
+   int ret;
+
+   pdata = hidpp->private_data;
+   if (!pdata) {
+   hid_err(hidpp->hid_dev, "Private driver data not found!\n");
+   return -EINVAL;
+   }
+
+   /* Find feature and store for later use */
+   ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
+   _index, _type);
+   if (ret)
+   return ret;
+
+   pdata->force_feature = feature_index;
+
+   /* Read current Range */
+   ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+   CMD_G920_FORCE_GET_APERTURE, NULL, 0, );
+   if (ret > 0) {
+   hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+   __func__, ret);
+   return -EPROTO;
+   }
+   if (ret)
+   return ret;
+
+   pdata->range = get_unaligned_be16([0]);
+
+   /* Create sysfs interface */
+   ret = device_create_file(&(hidpp->hid_dev->dev), _attr_range);
+   if (ret)
+   hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for 
\"range\", errno %d\n", ret);
+
+   return 0;
+}
+
 /* -- 
*/
 /* Generic HID++ devices  
*/
 /* --

[PATCH 5/6] HID: Add vendor specific usage pages for Logitech G920

2015-11-07 Thread Simon Wood
The Logitech G920 uses a couple of vendor specific usage pages,
which results in incorrect number of axis/buttons being detected.

This patch adds these pages to the 'ignore' list.

Reported-by: Elias Vanderstuyft <elias@gmail.com>
Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-input.c | 2 +-
 include/linux/hid.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 53aeaf6..c120be5 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -959,7 +959,7 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
set_bit(EV_REP, input->evbit);
goto ignore;
 
-   case HID_UP_LOGIVENDOR:
+   case HID_UP_LOGIVENDOR: case HID_UP_LOGIVENDOR2: case 
HID_UP_LOGIVENDOR3:
goto ignore;
 
case HID_UP_PID:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index f17980d..ce1d883 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -168,6 +168,8 @@ struct hid_item {
 #define HID_UP_MSVENDOR0xff00
 #define HID_UP_CUSTOM  0x00ff
 #define HID_UP_LOGIVENDOR  0xffbc
+#define HID_UP_LOGIVENDOR2   0xff09
+#define HID_UP_LOGIVENDOR3   0xff43
 #define HID_UP_LNVENDOR0xffa0
 #define HID_UP_SENSOR  0x0020
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/6] HID: hid-logitech-hidpp: Add basic support for Logitech G920

2015-11-07 Thread Simon Wood
This patch adds basic support for the Logitech G920 wheel when in HID
mode. This wheel 'speaks' the HID++ protocol, and therefor is driven
with hid-logitech-hidpp.

At this stage the driver only shows that it can communicate with the
wheel by outputting the name discovered over HID++.

The normal HID functions work to give input functionality using
joystick/event interface.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-core.c   |  1 +
 drivers/hid/hid-ids.h|  1 +
 drivers/hid/hid-logitech-hidpp.c | 69 +++-
 3 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bcd914a..60d564d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1896,6 +1896,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index f769208..d3500c4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -614,6 +614,7 @@
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2  0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_20xc219
 #define USB_DEVICE_ID_LOGITECH_G29_WHEEL   0xc24f
+#define USB_DEVICE_ID_LOGITECH_G920_WHEEL  0xc262
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940  0xc287
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 08e65e8..dbb9ff3 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -49,11 +49,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
 #define HIDPP_QUIRK_CLASS_WTP  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560 BIT(1)
 #define HIDPP_QUIRK_CLASS_K400 BIT(2)
+#define HIDPP_QUIRK_CLASS_G920 BIT(3)
 
 /* bits 2..20 are reserved for classes */
 #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS   BIT(22)
 #define HIDPP_QUIRK_NO_HIDINPUTBIT(23)
+#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS   BIT(24)
 
 #define HIDPP_QUIRK_DELAYED_INIT   (HIDPP_QUIRK_NO_HIDINPUT | \
 HIDPP_QUIRK_CONNECT_EVENTS)
@@ -146,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device 
*hidpp_dev);
 static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
 {
+   struct hidpp_device *hidpp = hid_get_drvdata(hdev);
int fields_count, ret;
 
+   hidpp = hid_get_drvdata(hdev);
+
switch (hidpp_report->report_id) {
case REPORT_ID_HIDPP_SHORT:
fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -168,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
 */
hidpp_report->device_index = 0xff;
 
-   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
-   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
-   HID_REQ_SET_REPORT);
+   if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
+   ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, 
fields_count);
+   } else {
+   ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
+   (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
+   HID_REQ_SET_REPORT);
+   }
 
return ret == fields_count ? 0 : -1;
 }
@@ -1430,8 +1439,10 @@ static void hidpp_overwrite_name(struct hid_device 
*hdev, bool use_unifying)
 
if (!name)
hid_err(hdev, "unable to retrieve the name of the device");
-   else
+   else {
+   dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+   }
 
kfree(name);
 }
@@ -1594,6 +1605,25 @@ static int hidpp_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
goto hid_parse_fail;
}
 
+   if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+   connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+   if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+   ret = hid_hw_start(

[PATCH 1/2] HID: hid-logitech: Simplify wheel detection scheme

2015-11-02 Thread Simon Wood
Simplfy how hid-logitech driver detects the native mode of the wheel,
done by looking at the USB-ID revision and comparing bit mask.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-lg4ff.c | 70 -
 1 file changed, 28 insertions(+), 42 deletions(-)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 02cec83..b363d88 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -114,16 +114,12 @@ struct lg4ff_compat_mode_switch {
 };
 
 struct lg4ff_wheel_ident_info {
+   const u32 modes;
const u16 mask;
const u16 result;
const u16 real_product_id;
 };
 
-struct lg4ff_wheel_ident_checklist {
-   const u32 count;
-   const struct lg4ff_wheel_ident_info *models[];
-};
-
 struct lg4ff_multimode_wheel {
const u16 product_id;
const u32 alternate_modes;
@@ -174,36 +170,39 @@ static const struct lg4ff_alternate_mode 
lg4ff_alternate_modes[] = {
 
 /* Multimode wheel identificators */
 static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = {
+   LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xf000,
0x1000,
USB_DEVICE_ID_LOGITECH_DFP_WHEEL
 };
 
 static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = {
+   LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00,
0x1200,
USB_DEVICE_ID_LOGITECH_G25_WHEEL
 };
 
 static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = {
+   LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xfff0,
0x1230,
USB_DEVICE_ID_LOGITECH_G27_WHEEL
 };
 
 static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = {
+   LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00,
0x1300,
USB_DEVICE_ID_LOGITECH_DFGT_WHEEL
 };
 
 /* Multimode wheel identification checklists */
-static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = {
-   4,
-   {_dfgt_ident_info,
-_g27_ident_info,
-_g25_ident_info,
-_dfp_ident_info}
+static const struct lg4ff_wheel_ident_info *lg4ff_main_checklist[] = {
+   _dfgt_ident_info,
+   _g27_ident_info,
+   _g25_ident_info,
+   _dfp_ident_info
 };
 
 /* Compatibility mode switching commands */
@@ -1037,41 +1036,28 @@ static enum led_brightness 
lg4ff_led_get_brightness(struct led_classdev *led_cde
 
 static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 
reported_product_id, const u16 bcdDevice)
 {
-   const struct lg4ff_wheel_ident_checklist *checklist;
-   int i, from_idx, to_idx;
+   u32 current_mode;
+   int i;
 
-   switch (reported_product_id) {
-   case USB_DEVICE_ID_LOGITECH_WHEEL:
-   case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 0;
-   to_idx = checklist->count - 1;
-   break;
-   case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 0;
-   to_idx = checklist->count - 2; /* End identity check at G25 */
-   break;
-   case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 1; /* Start identity check at G27 */
-   to_idx = checklist->count - 3; /* End identity check at G27 */
-   break;
-   case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 0;
-   to_idx = checklist->count - 4; /* End identity check at DFGT */
-   break;
-   default:
-   return 0;
+   /* identify current mode from USB PID */
+   for (i = 1; i < ARRAY_SIZE(lg4ff_alternate_modes); i++) {
+   dbg_hid("Testing whether PID is %X\n", 
lg4ff_alternate_modes[i].product_id);
+   if (reported_product_id == lg4ff_alternate_modes[i].product_id)
+   break;
}
 
-   for (i = from_idx; i <= to_idx; i++) {
-   const u16 mask = checklist->models[i]->mask;
-   const u16 result = checklist->models[i]->result;
-   const u16 real_product_id = 
checklist->models[i]->real_product_id;
+   if (i == ARRAY_SIZE(lg4ff_alternate_modes))
+   return 0;
+
+   current_mode = BIT(i);
+
+   for (i = 0; i < ARRAY_SIZE(lg4ff_main_checklist); i++) {
+   const u16 mask = lg4ff_main_checklist[i]->mask;
+   const u16 result = lg4ff_main_checklist[i]->result;
+   const u16 real_product_id = 
lg4ff_main_checklist[i]->real_product_id;
 
-   if ((bcdDevice & mask) == result) {
+   if ((current_mode & lg4ff_main_checklist[i]->modes) && \
+   (bcdDevice & mask) == result) {
db

[PATCH 2/2] HID: hid-logitech: Add support for G29

2015-11-02 Thread Simon Wood
At present the G29 is mis-identified as a DFGT, this patch ensures
that the wheel is correctly detected and allows setting the LEDs and
turning range via the '/sys' interface.

This wheel can also emulate other types of Logitech wheels.

Signed-off-by: Simon Wood 
---
 drivers/hid/hid-core.c  |  1 +
 drivers/hid/hid-lg.c|  9 
 drivers/hid/hid-lg4ff.c | 57 +
 3 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 70a11ac..949d804 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1896,6 +1896,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 5332fb7..c20ac76 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -620,6 +620,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct 
hid_input *hi,
usage->code == ABS_Y || usage->code == ABS_Z ||
usage->code == ABS_RZ)) {
switch (hdev->product) {
+   case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
case USB_DEVICE_ID_LOGITECH_WHEEL:
case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
@@ -658,10 +659,18 @@ static int lg_event(struct hid_device *hdev, struct 
hid_field *field,
 
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
+   struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
+   __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
struct lg_drv_data *drv_data;
int ret;
 
+   /* Only work with the 1st interface (G29 presents multiple) */
+   if (iface_num != 0) {
+   dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
+   return -ENODEV;
+   }
+
drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
if (!drv_data) {
hid_err(hdev, "Insufficient memory, cannot allocate driver 
data\n");
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index b363d88..fbddcb3 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -45,7 +45,8 @@
 #define LG4FF_MODE_G25_IDX 3
 #define LG4FF_MODE_DFGT_IDX 4
 #define LG4FF_MODE_G27_IDX 5
-#define LG4FF_MODE_MAX_IDX 6
+#define LG4FF_MODE_G29_IDX 6
+#define LG4FF_MODE_MAX_IDX 7
 
 #define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX)
 #define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX)
@@ -53,6 +54,7 @@
 #define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX)
 #define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX)
 #define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX)
+#define LG4FF_MODE_G29 BIT(LG4FF_MODE_G29_IDX)
 
 #define LG4FF_DFEX_TAG "DF-EX"
 #define LG4FF_DFEX_NAME "Driving Force / Formula EX"
@@ -62,6 +64,8 @@
 #define LG4FF_G25_NAME "G25 Racing Wheel"
 #define LG4FF_G27_TAG "G27"
 #define LG4FF_G27_NAME "G27 Racing Wheel"
+#define LG4FF_G29_TAG "G29"
+#define LG4FF_G29_NAME "G29 Racing Wheel"
 #define LG4FF_DFGT_TAG "DFGT"
 #define LG4FF_DFGT_NAME "Driving Force GT"
 
@@ -140,6 +144,7 @@ static const struct lg4ff_wheel lg4ff_devices[] = {
{USB_DEVICE_ID_LOGITECH_G25_WHEEL,   lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,  lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G27_WHEEL,   lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
+   {USB_DEVICE_ID_LOGITECH_G29_WHEEL,   lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, 
NULL},
{USB_DEVICE_ID_LOGITECH_WII_WHEEL,   lg4ff_wheel_effects, 40, 270, NULL}
 };
@@ -157,6 +162,9 @@ static const struct lg4ff_multimode_wheel 
lg4ff_multimode_wheels[] = {
{USB_DEVICE_ID_LOGITECH_G27_WHEEL,
 LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | 
LG4FF_MODE_DFEX,
 LG4FF_G27_TAG, LG4FF_G27_NAME},
+   {USB_DEVICE_ID_LOGITECH_G29_WHEEL,
+LG4FF_MODE_NATIVE | LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | 
LG4FF_MOD

[PATCH 1/2] HID: hid-logitech: Simplify wheel detection scheme

2015-11-02 Thread Simon Wood
Simplfy how hid-logitech driver detects the native mode of the wheel,
done by looking at the USB-ID revision and comparing bit mask.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-lg4ff.c | 70 -
 1 file changed, 28 insertions(+), 42 deletions(-)

diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 02cec83..b363d88 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -114,16 +114,12 @@ struct lg4ff_compat_mode_switch {
 };
 
 struct lg4ff_wheel_ident_info {
+   const u32 modes;
const u16 mask;
const u16 result;
const u16 real_product_id;
 };
 
-struct lg4ff_wheel_ident_checklist {
-   const u32 count;
-   const struct lg4ff_wheel_ident_info *models[];
-};
-
 struct lg4ff_multimode_wheel {
const u16 product_id;
const u32 alternate_modes;
@@ -174,36 +170,39 @@ static const struct lg4ff_alternate_mode 
lg4ff_alternate_modes[] = {
 
 /* Multimode wheel identificators */
 static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = {
+   LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xf000,
0x1000,
USB_DEVICE_ID_LOGITECH_DFP_WHEEL
 };
 
 static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = {
+   LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00,
0x1200,
USB_DEVICE_ID_LOGITECH_G25_WHEEL
 };
 
 static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = {
+   LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xfff0,
0x1230,
USB_DEVICE_ID_LOGITECH_G27_WHEEL
 };
 
 static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = {
+   LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00,
0x1300,
USB_DEVICE_ID_LOGITECH_DFGT_WHEEL
 };
 
 /* Multimode wheel identification checklists */
-static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = {
-   4,
-   {_dfgt_ident_info,
-_g27_ident_info,
-_g25_ident_info,
-_dfp_ident_info}
+static const struct lg4ff_wheel_ident_info *lg4ff_main_checklist[] = {
+   _dfgt_ident_info,
+   _g27_ident_info,
+   _g25_ident_info,
+   _dfp_ident_info
 };
 
 /* Compatibility mode switching commands */
@@ -1037,41 +1036,28 @@ static enum led_brightness 
lg4ff_led_get_brightness(struct led_classdev *led_cde
 
 static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 
reported_product_id, const u16 bcdDevice)
 {
-   const struct lg4ff_wheel_ident_checklist *checklist;
-   int i, from_idx, to_idx;
+   u32 current_mode;
+   int i;
 
-   switch (reported_product_id) {
-   case USB_DEVICE_ID_LOGITECH_WHEEL:
-   case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 0;
-   to_idx = checklist->count - 1;
-   break;
-   case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 0;
-   to_idx = checklist->count - 2; /* End identity check at G25 */
-   break;
-   case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 1; /* Start identity check at G27 */
-   to_idx = checklist->count - 3; /* End identity check at G27 */
-   break;
-   case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
-   checklist = _main_checklist;
-   from_idx = 0;
-   to_idx = checklist->count - 4; /* End identity check at DFGT */
-   break;
-   default:
-   return 0;
+   /* identify current mode from USB PID */
+   for (i = 1; i < ARRAY_SIZE(lg4ff_alternate_modes); i++) {
+   dbg_hid("Testing whether PID is %X\n", 
lg4ff_alternate_modes[i].product_id);
+   if (reported_product_id == lg4ff_alternate_modes[i].product_id)
+   break;
}
 
-   for (i = from_idx; i <= to_idx; i++) {
-   const u16 mask = checklist->models[i]->mask;
-   const u16 result = checklist->models[i]->result;
-   const u16 real_product_id = 
checklist->models[i]->real_product_id;
+   if (i == ARRAY_SIZE(lg4ff_alternate_modes))
+   return 0;
+
+   current_mode = BIT(i);
+
+   for (i = 0; i < ARRAY_SIZE(lg4ff_main_checklist); i++) {
+   const u16 mask = lg4ff_main_checklist[i]->mask;
+   const u16 result = lg4ff_main_checklist[i]->result;
+   const u16 real_product_id = 
lg4ff_main_checklist[i]->real_product_id;
 
-   if ((bcdDevice & mask) == result) {
+   if ((current_mode & lg4ff_main_checklist[i]->modes) && \
+   (bcdDevice & mask) == result) {
  

[PATCH 2/2] HID: hid-logitech: Add support for G29

2015-11-02 Thread Simon Wood
At present the G29 is mis-identified as a DFGT, this patch ensures
that the wheel is correctly detected and allows setting the LEDs and
turning range via the '/sys' interface.

This wheel can also emulate other types of Logitech wheels.

Signed-off-by: Simon Wood <si...@mungewell.org>
---
 drivers/hid/hid-core.c  |  1 +
 drivers/hid/hid-lg.c|  9 
 drivers/hid/hid-lg4ff.c | 57 +
 3 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 70a11ac..949d804 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1896,6 +1896,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+   { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 
USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 5332fb7..c20ac76 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -620,6 +620,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct 
hid_input *hi,
usage->code == ABS_Y || usage->code == ABS_Z ||
usage->code == ABS_RZ)) {
switch (hdev->product) {
+   case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
case USB_DEVICE_ID_LOGITECH_WHEEL:
case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
@@ -658,10 +659,18 @@ static int lg_event(struct hid_device *hdev, struct 
hid_field *field,
 
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
+   struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
+   __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
struct lg_drv_data *drv_data;
int ret;
 
+   /* Only work with the 1st interface (G29 presents multiple) */
+   if (iface_num != 0) {
+   dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
+   return -ENODEV;
+   }
+
drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
if (!drv_data) {
hid_err(hdev, "Insufficient memory, cannot allocate driver 
data\n");
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index b363d88..fbddcb3 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -45,7 +45,8 @@
 #define LG4FF_MODE_G25_IDX 3
 #define LG4FF_MODE_DFGT_IDX 4
 #define LG4FF_MODE_G27_IDX 5
-#define LG4FF_MODE_MAX_IDX 6
+#define LG4FF_MODE_G29_IDX 6
+#define LG4FF_MODE_MAX_IDX 7
 
 #define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX)
 #define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX)
@@ -53,6 +54,7 @@
 #define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX)
 #define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX)
 #define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX)
+#define LG4FF_MODE_G29 BIT(LG4FF_MODE_G29_IDX)
 
 #define LG4FF_DFEX_TAG "DF-EX"
 #define LG4FF_DFEX_NAME "Driving Force / Formula EX"
@@ -62,6 +64,8 @@
 #define LG4FF_G25_NAME "G25 Racing Wheel"
 #define LG4FF_G27_TAG "G27"
 #define LG4FF_G27_NAME "G27 Racing Wheel"
+#define LG4FF_G29_TAG "G29"
+#define LG4FF_G29_NAME "G29 Racing Wheel"
 #define LG4FF_DFGT_TAG "DFGT"
 #define LG4FF_DFGT_NAME "Driving Force GT"
 
@@ -140,6 +144,7 @@ static const struct lg4ff_wheel lg4ff_devices[] = {
{USB_DEVICE_ID_LOGITECH_G25_WHEEL,   lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,  lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G27_WHEEL,   lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
+   {USB_DEVICE_ID_LOGITECH_G29_WHEEL,   lg4ff_wheel_effects, 40, 900, 
lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, 
NULL},
{USB_DEVICE_ID_LOGITECH_WII_WHEEL,   lg4ff_wheel_effects, 40, 270, NULL}
 };
@@ -157,6 +162,9 @@ static const struct lg4ff_multimode_wheel 
lg4ff_multimode_wheels[] = {
{USB_DEVICE_ID_LOGITECH_G27_WHEEL,
 LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | 
LG4FF_MODE_DFEX,
 LG4FF_G27_TAG, LG4FF_G27_NAME},
+   {USB_DEVICE_ID_LOGITECH_G29_WHEEL,
+LG4FF_MODE_NATIVE | LG4FF_MODE_G29 | LG4FF_MODE_G27 | 

Re: Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-30 Thread Simon Wood
On Thu, October 29, 2015 8:39 pm, Simon Wood wrote:
> On Thu, October 29, 2015 6:50 pm, Michel Dänzer wrote:
>
>
>>>> So problem (no LCD backlight) must have been introduced between
>>>> those.
>>>
>>> Well this looks like it might have something to do with it will
>>> attempt a build just before it. -- commit
>>> 4281f46ef839050d2ef60348f661eb463c21cc2e Author: Michel Dänzer
>>> 
>>> Date:   Mon Sep 28 18:16:31 2015 +0900
>>>
>>>
>>>
>>> drm/radeon: Restore LCD backlight level on resume (>= R5xx)
>>>
>>>
>>
>> Please try the patches from
>> http://lists.freedesktop.org/archives/dri-devel/2015-October/093514.html
>>
>
> Awesome sauce!
>
>
> 4281f46ef839050d2ef60348f661eb463c21cc2e + 2 patches works (backlight is
> lit).
>
> BTW my GFX is:
> 01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI]
> RV530/M56 GL [Mobility FireGL V5200]
>
>
> Patches apply cleanly to Master too, will build overnight and test first
> thing tomorrow, Simon

Confirmed the patches work with master/rc7, backlight is working!

So the big question is whether we can get these included in 4.3 final...?
Simon.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-30 Thread Simon Wood
On Thu, October 29, 2015 8:39 pm, Simon Wood wrote:
> On Thu, October 29, 2015 6:50 pm, Michel Dänzer wrote:
>
>
>>>> So problem (no LCD backlight) must have been introduced between
>>>> those.
>>>
>>> Well this looks like it might have something to do with it will
>>> attempt a build just before it. -- commit
>>> 4281f46ef839050d2ef60348f661eb463c21cc2e Author: Michel Dänzer
>>> <michel.daen...@amd.com>
>>> Date:   Mon Sep 28 18:16:31 2015 +0900
>>>
>>>
>>>
>>> drm/radeon: Restore LCD backlight level on resume (>= R5xx)
>>>
>>>
>>
>> Please try the patches from
>> http://lists.freedesktop.org/archives/dri-devel/2015-October/093514.html
>>
>
> Awesome sauce!
>
>
> 4281f46ef839050d2ef60348f661eb463c21cc2e + 2 patches works (backlight is
> lit).
>
> BTW my GFX is:
> 01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI]
> RV530/M56 GL [Mobility FireGL V5200]
>
>
> Patches apply cleanly to Master too, will build overnight and test first
> thing tomorrow, Simon

Confirmed the patches work with master/rc7, backlight is working!

So the big question is whether we can get these included in 4.3 final...?
Simon.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood
On Thu, October 29, 2015 6:50 pm, Michel Dänzer wrote:

>>> So problem (no LCD backlight) must have been introduced between
>>> those.
>>
>> Well this looks like it might have something to do with it will
>> attempt a build just before it. --
>> commit 4281f46ef839050d2ef60348f661eb463c21cc2e Author: Michel Dänzer
>> 
>> Date:   Mon Sep 28 18:16:31 2015 +0900
>>
>>
>> drm/radeon: Restore LCD backlight level on resume (>= R5xx)
>>
>
> Please try the patches from
> http://lists.freedesktop.org/archives/dri-devel/2015-October/093514.html

Awesome sauce!

4281f46ef839050d2ef60348f661eb463c21cc2e + 2 patches works (backlight is
lit).

BTW my GFX is:
01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI]
RV530/M56 GL [Mobility FireGL V5200]

Patches apply cleanly to Master too, will build overnight and test first
thing tomorrow,
Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood
On Thu, October 29, 2015 8:26 am, Simon Wood wrote:
>> 4.3.0rc6 - bad
>> 4.3.0rc7 - bad
>> 4.3.0rc2 - good
>> 4.3.0rc4 - bad (049e6dde7e57f0054fdc49102e7ef4830c698b46)
>> 4.3.0rc3 - good (9ffecb10283508260936b96022d4ee43a7798b4c)

> --
> commit 4281f46ef839050d2ef60348f661eb463c21cc2e Author: Michel Dänzer
> 
> Date:   Mon Sep 28 18:16:31 2015 +0900
>
>
> drm/radeon: Restore LCD backlight level on resume (>= R5xx)
> --

I can confirm that this is 'bad' (no backlight).

Although confusing this built labelled as rc2, despite being dated after
rc3 tag... double checking what I built.
--
simon@retrobox:~/linux-git$ git status
HEAD detached at 4281f46
--

Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood
On Thu, October 29, 2015 8:07 am, Simon Wood wrote:
>

>> Well, I can confirm that the patch stopped the Oops - but unfortunatly
>> the screen is still dark.
>>
>> Also, Oops _does_ happen with rc2 but the screens is OK with that...
>> Back
>> to looking through the logs.
>
> I couldn't see anything of note in the syslog, so attempted to bisect the
>  problem some - although building takes considerable time on this machine
>  (note 32bit).
>
>
> 4.3.0rc6 - bad
> 4.3.0rc7 - bad
> 4.3.0rc2 - good
> 4.3.0rc4 - bad (049e6dde7e57f0054fdc49102e7ef4830c698b46)
> 4.3.0rc3 - good (9ffecb10283508260936b96022d4ee43a7798b4c)
>
>
> So problem (no LCD backlight) must have been introduced between those.

Well this looks like it might have something to do with it will
attempt a build just before it.
--
commit 4281f46ef839050d2ef60348f661eb463c21cc2e
Author: Michel Dänzer 
Date:   Mon Sep 28 18:16:31 2015 +0900

drm/radeon: Restore LCD backlight level on resume (>= R5xx)
--

Cheers,
Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood

> Well, I can confirm that the patch stopped the Oops - but unfortunatly
> the screen is still dark.
>
> Also, Oops _does_ happen with rc2 but the screens is OK with that... Back
> to looking through the logs.

I couldn't see anything of note in the syslog, so attempted to bisect the
problem some - although building takes considerable time on this machine
(note 32bit).

4.3.0rc6 - bad
4.3.0rc7 - bad
4.3.0rc2 - good
4.3.0rc4 - bad (049e6dde7e57f0054fdc49102e7ef4830c698b46)
4.3.0rc3 - good (9ffecb10283508260936b96022d4ee43a7798b4c)

So problem (no LCD backlight) must have been introduced between those.
Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood

> Well, I can confirm that the patch stopped the Oops - but unfortunatly
> the screen is still dark.
>
> Also, Oops _does_ happen with rc2 but the screens is OK with that... Back
> to looking through the logs.

I couldn't see anything of note in the syslog, so attempted to bisect the
problem some - although building takes considerable time on this machine
(note 32bit).

4.3.0rc6 - bad
4.3.0rc7 - bad
4.3.0rc2 - good
4.3.0rc4 - bad (049e6dde7e57f0054fdc49102e7ef4830c698b46)
4.3.0rc3 - good (9ffecb10283508260936b96022d4ee43a7798b4c)

So problem (no LCD backlight) must have been introduced between those.
Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood
On Thu, October 29, 2015 8:07 am, Simon Wood wrote:
>

>> Well, I can confirm that the patch stopped the Oops - but unfortunatly
>> the screen is still dark.
>>
>> Also, Oops _does_ happen with rc2 but the screens is OK with that...
>> Back
>> to looking through the logs.
>
> I couldn't see anything of note in the syslog, so attempted to bisect the
>  problem some - although building takes considerable time on this machine
>  (note 32bit).
>
>
> 4.3.0rc6 - bad
> 4.3.0rc7 - bad
> 4.3.0rc2 - good
> 4.3.0rc4 - bad (049e6dde7e57f0054fdc49102e7ef4830c698b46)
> 4.3.0rc3 - good (9ffecb10283508260936b96022d4ee43a7798b4c)
>
>
> So problem (no LCD backlight) must have been introduced between those.

Well this looks like it might have something to do with it will
attempt a build just before it.
--
commit 4281f46ef839050d2ef60348f661eb463c21cc2e
Author: Michel Dänzer <michel.daen...@amd.com>
Date:   Mon Sep 28 18:16:31 2015 +0900

drm/radeon: Restore LCD backlight level on resume (>= R5xx)
--

Cheers,
Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood
On Thu, October 29, 2015 8:26 am, Simon Wood wrote:
>> 4.3.0rc6 - bad
>> 4.3.0rc7 - bad
>> 4.3.0rc2 - good
>> 4.3.0rc4 - bad (049e6dde7e57f0054fdc49102e7ef4830c698b46)
>> 4.3.0rc3 - good (9ffecb10283508260936b96022d4ee43a7798b4c)

> --
> commit 4281f46ef839050d2ef60348f661eb463c21cc2e Author: Michel Dänzer
> <michel.daen...@amd.com>
> Date:   Mon Sep 28 18:16:31 2015 +0900
>
>
> drm/radeon: Restore LCD backlight level on resume (>= R5xx)
> --

I can confirm that this is 'bad' (no backlight).

Although confusing this built labelled as rc2, despite being dated after
rc3 tag... double checking what I built.
--
simon@retrobox:~/linux-git$ git status
HEAD detached at 4281f46
--

Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Re: [Regression] 4.3.0rc4 through rc7: No LCD backlight on Thinkpad T60P

2015-10-29 Thread Simon Wood
On Thu, October 29, 2015 6:50 pm, Michel Dänzer wrote:

>>> So problem (no LCD backlight) must have been introduced between
>>> those.
>>
>> Well this looks like it might have something to do with it will
>> attempt a build just before it. --
>> commit 4281f46ef839050d2ef60348f661eb463c21cc2e Author: Michel Dänzer
>> 
>> Date:   Mon Sep 28 18:16:31 2015 +0900
>>
>>
>> drm/radeon: Restore LCD backlight level on resume (>= R5xx)
>>
>
> Please try the patches from
> http://lists.freedesktop.org/archives/dri-devel/2015-October/093514.html

Awesome sauce!

4281f46ef839050d2ef60348f661eb463c21cc2e + 2 patches works (backlight is
lit).

BTW my GFX is:
01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI]
RV530/M56 GL [Mobility FireGL V5200]

Patches apply cleanly to Master too, will build overnight and test first
thing tomorrow,
Simon

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   3   >