diff options
| author | Paul Sbarra <sbarra.paul@gmail.com> | 2013-02-17 12:53:13 -0500 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2013-02-19 07:50:10 -0500 |
| commit | 54bfe3f0dab2b2f0ac629690f187537d95adeb4f (patch) | |
| tree | d6d03915a5763f7061e9882e0941eca49612692d | |
| parent | cf5425bfcd6909f9831a00bc06ccb9a5b163766a (diff) | |
HID: logitech: add report descriptor for Driving Force wheel
This is the original report descriptor as reported by lsusb -vd 046d:c294.
Signed-off-by: Paul Sbarra <sbarra.paul@gmail.com>
Signed-off-by: Simon Wood <simon@mungewell.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
| -rw-r--r-- | drivers/hid/hid-lg.c | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index a2f8e88b9fa2..6daa1927bf69 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
| @@ -21,8 +21,10 @@ | |||
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/random.h> | 22 | #include <linux/random.h> |
| 23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
| 24 | #include <linux/usb.h> | ||
| 24 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
| 25 | 26 | ||
| 27 | #include "usbhid/usbhid.h" | ||
| 26 | #include "hid-ids.h" | 28 | #include "hid-ids.h" |
| 27 | #include "hid-lg.h" | 29 | #include "hid-lg.h" |
| 28 | 30 | ||
| @@ -40,17 +42,83 @@ | |||
| 40 | #define LG_FF3 0x1000 | 42 | #define LG_FF3 0x1000 |
| 41 | #define LG_FF4 0x2000 | 43 | #define LG_FF4 0x2000 |
| 42 | 44 | ||
| 43 | /* Size of the original descriptor of the Driving Force Pro wheel */ | 45 | /* Size of the original descriptors of the Driving Force (and Pro) wheels */ |
| 46 | #define DF_RDESC_ORIG_SIZE 130 | ||
| 44 | #define DFP_RDESC_ORIG_SIZE 97 | 47 | #define DFP_RDESC_ORIG_SIZE 97 |
| 45 | 48 | ||
| 46 | /* Fixed report descriptor for Logitech Driving Force Pro wheel controller | 49 | /* Fixed report descriptors for Logitech Driving Force (and Pro) |
| 50 | * wheel controllers | ||
| 47 | * | 51 | * |
| 48 | * The original descriptor hides the separate throttle and brake axes in | 52 | * The original descriptors hide the separate throttle and brake axes in |
| 49 | * a custom vendor usage page, providing only a combined value as | 53 | * a custom vendor usage page, providing only a combined value as |
| 50 | * GenericDesktop.Y. | 54 | * GenericDesktop.Y. |
| 51 | * This descriptor removes the combined Y axis and instead reports | 55 | * These descriptors remove the combined Y axis and instead report |
| 52 | * separate throttle (Y) and brake (RZ). | 56 | * separate throttle (Y) and brake (RZ). |
| 53 | */ | 57 | */ |
| 58 | static __u8 df_rdesc_fixed[] = { | ||
| 59 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 60 | 0x09, 0x04, /* Usage (Joystik), */ | ||
| 61 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 62 | 0xA1, 0x02, /* Collection (Logical), */ | ||
| 63 | 0x95, 0x01, /* Report Count (1), */ | ||
| 64 | 0x75, 0x0A, /* Report Size (10), */ | ||
| 65 | 0x14, /* Logical Minimum (0), */ | ||
| 66 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 67 | 0x34, /* Physical Minimum (0), */ | ||
| 68 | 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ | ||
| 69 | 0x09, 0x30, /* Usage (X), */ | ||
| 70 | 0x81, 0x02, /* Input (Variable), */ | ||
| 71 | 0x95, 0x0C, /* Report Count (12), */ | ||
| 72 | 0x75, 0x01, /* Report Size (1), */ | ||
| 73 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 74 | 0x45, 0x01, /* Physical Maximum (1), */ | ||
| 75 | 0x05, 0x09, /* Usage (Buttons), */ | ||
| 76 | 0x19, 0x01, /* Usage Minimum (1), */ | ||
| 77 | 0x29, 0x0c, /* Usage Maximum (12), */ | ||
| 78 | 0x81, 0x02, /* Input (Variable), */ | ||
| 79 | 0x95, 0x02, /* Report Count (2), */ | ||
| 80 | 0x06, 0x00, 0xFF, /* Usage Page (Vendor: 65280), */ | ||
| 81 | 0x09, 0x01, /* Usage (?: 1), */ | ||
| 82 | 0x81, 0x02, /* Input (Variable), */ | ||
| 83 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 84 | 0x09, 0x31, /* Usage (Y), */ | ||
| 85 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
| 86 | 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ | ||
| 87 | 0x95, 0x01, /* Report Count (1), */ | ||
| 88 | 0x75, 0x08, /* Report Size (8), */ | ||
| 89 | 0x81, 0x02, /* Input (Variable), */ | ||
| 90 | 0x25, 0x07, /* Logical Maximum (7), */ | ||
| 91 | 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ | ||
| 92 | 0x75, 0x04, /* Report Size (4), */ | ||
| 93 | 0x65, 0x14, /* Unit (Degrees), */ | ||
| 94 | 0x09, 0x39, /* Usage (Hat Switch), */ | ||
| 95 | 0x81, 0x42, /* Input (Variable, Null State), */ | ||
| 96 | 0x75, 0x01, /* Report Size (1), */ | ||
| 97 | 0x95, 0x04, /* Report Count (4), */ | ||
| 98 | 0x65, 0x00, /* Unit (none), */ | ||
| 99 | 0x06, 0x00, 0xFF, /* Usage Page (Vendor: 65280), */ | ||
| 100 | 0x09, 0x01, /* Usage (?: 1), */ | ||
| 101 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 102 | 0x45, 0x01, /* Physical Maximum (1), */ | ||
| 103 | 0x81, 0x02, /* Input (Variable), */ | ||
| 104 | 0x95, 0x02, /* Report Count (2), */ | ||
| 105 | 0x75, 0x08, /* Report Size (8), */ | ||
| 106 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
| 107 | 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ | ||
| 108 | 0x09, 0x02, /* Usage (?: 2), */ | ||
| 109 | 0x81, 0x02, /* Input (Variable), */ | ||
| 110 | 0xC0, /* End Collection, */ | ||
| 111 | 0xA1, 0x02, /* Collection (Logical), */ | ||
| 112 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
| 113 | 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ | ||
| 114 | 0x95, 0x07, /* Report Count (7), */ | ||
| 115 | 0x75, 0x08, /* Report Size (8), */ | ||
| 116 | 0x09, 0x03, /* Usage (?: 3), */ | ||
| 117 | 0x91, 0x02, /* Output (Variable), */ | ||
| 118 | 0xC0, /* End Collection, */ | ||
| 119 | 0xC0 /* End Collection */ | ||
| 120 | }; | ||
| 121 | |||
| 54 | static __u8 dfp_rdesc_fixed[] = { | 122 | static __u8 dfp_rdesc_fixed[] = { |
| 55 | 0x05, 0x01, /* Usage Page (Desktop), */ | 123 | 0x05, 0x01, /* Usage Page (Desktop), */ |
| 56 | 0x09, 0x04, /* Usage (Joystik), */ | 124 | 0x09, 0x04, /* Usage (Joystik), */ |
| @@ -99,7 +167,6 @@ static __u8 dfp_rdesc_fixed[] = { | |||
| 99 | 0xC0 /* End Collection */ | 167 | 0xC0 /* End Collection */ |
| 100 | }; | 168 | }; |
| 101 | 169 | ||
| 102 | |||
| 103 | /* | 170 | /* |
| 104 | * Certain Logitech keyboards send in report #3 keys which are far | 171 | * Certain Logitech keyboards send in report #3 keys which are far |
| 105 | * above the logical maximum described in descriptor. This extends | 172 | * above the logical maximum described in descriptor. This extends |
| @@ -109,6 +176,8 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 109 | unsigned int *rsize) | 176 | unsigned int *rsize) |
| 110 | { | 177 | { |
| 111 | struct lg_drv_data *drv_data = hid_get_drvdata(hdev); | 178 | struct lg_drv_data *drv_data = hid_get_drvdata(hdev); |
| 179 | struct usb_device_descriptor *udesc; | ||
| 180 | __u16 bcdDevice, rev_maj, rev_min; | ||
| 112 | 181 | ||
| 113 | if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && | 182 | if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && |
| 114 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { | 183 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { |
| @@ -135,6 +204,28 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 135 | } | 204 | } |
| 136 | 205 | ||
| 137 | switch (hdev->product) { | 206 | switch (hdev->product) { |
| 207 | |||
| 208 | /* Several wheels report as this id when operating in emulation mode. */ | ||
| 209 | case USB_DEVICE_ID_LOGITECH_WHEEL: | ||
| 210 | udesc = &(hid_to_usb_dev(hdev)->descriptor); | ||
| 211 | if (!udesc) { | ||
| 212 | hid_err(hdev, "NULL USB device descriptor\n"); | ||
| 213 | break; | ||
| 214 | } | ||
| 215 | bcdDevice = le16_to_cpu(udesc->bcdDevice); | ||
| 216 | rev_maj = bcdDevice >> 8; | ||
| 217 | rev_min = bcdDevice & 0xff; | ||
| 218 | |||
| 219 | /* Update the report descriptor for only the Driving Force wheel */ | ||
| 220 | if (rev_maj == 1 && rev_min == 2 && | ||
| 221 | *rsize == DF_RDESC_ORIG_SIZE) { | ||
| 222 | hid_info(hdev, | ||
| 223 | "fixing up Logitech Driving Force report descriptor\n"); | ||
| 224 | rdesc = df_rdesc_fixed; | ||
| 225 | *rsize = sizeof(df_rdesc_fixed); | ||
| 226 | } | ||
| 227 | break; | ||
| 228 | |||
| 138 | case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: | 229 | case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: |
| 139 | if (*rsize == DFP_RDESC_ORIG_SIZE) { | 230 | if (*rsize == DFP_RDESC_ORIG_SIZE) { |
| 140 | hid_info(hdev, | 231 | hid_info(hdev, |
