Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: gembird: add new driver to fix Gembird JPD-DualForce 2

This gamepad advertise 5 absolute axis while 4 are actually used.
The second Z axis shows some garbage, so it has to be ignored by HID.
The first Z axis and the Rz one are actually Rx and Ry. Remap them.

We could also just remap and ignore the axis in .input_mapping(). I
went ahead with .report_fixup() first, so here it is.

Reported-by: Orivej Desh <orivej@gmx.fr>
Tested-by: Orivej Desh <orivej@gmx.fr>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Benjamin Tissoires and committed by
Jiri Kosina
931830aa 7a834ba5

+127
+6
drivers/hid/Kconfig
··· 251 251 ---help--- 252 252 Support for Ezkey BTC 8193 keyboard. 253 253 254 + config HID_GEMBIRD 255 + tristate "Gembird Joypad" 256 + depends on HID 257 + ---help--- 258 + Support for Gembird JPD-DualForce 2. 259 + 254 260 config HID_HOLTEK 255 261 tristate "Holtek HID devices" 256 262 depends on USB_HID
+1
drivers/hid/Makefile
··· 36 36 obj-$(CONFIG_HID_ELECOM) += hid-elecom.o 37 37 obj-$(CONFIG_HID_ELO) += hid-elo.o 38 38 obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o 39 + obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o 39 40 obj-$(CONFIG_HID_GT683R) += hid-gt683r.o 40 41 obj-$(CONFIG_HID_GYRATION) += hid-gyration.o 41 42 obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
+1
drivers/hid/hid-core.c
··· 1823 1823 { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, 1824 1824 { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, 1825 1825 { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, 1826 + { HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) }, 1826 1827 { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, 1827 1828 { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, 1828 1829 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+116
drivers/hid/hid-gembird.c
··· 1 + /* 2 + * HID driver for Gembird Joypad, "PC Game Controller" 3 + * 4 + * Copyright (c) 2015 Red Hat, Inc 5 + * Copyright (c) 2015 Benjamin Tissoires 6 + */ 7 + 8 + /* 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License as published by the Free 11 + * Software Foundation; either version 2 of the License, or (at your option) 12 + * any later version. 13 + */ 14 + 15 + #include <linux/device.h> 16 + #include <linux/hid.h> 17 + #include <linux/module.h> 18 + 19 + #include "hid-ids.h" 20 + 21 + #define GEMBIRD_START_FAULTY_RDESC 8 22 + 23 + static const __u8 gembird_jpd_faulty_rdesc[] = { 24 + 0x75, 0x08, /* Report Size (8) */ 25 + 0x95, 0x05, /* Report Count (5) */ 26 + 0x15, 0x00, /* Logical Minimum (0) */ 27 + 0x26, 0xff, 0x00, /* Logical Maximum (255) */ 28 + 0x35, 0x00, /* Physical Minimum (0) */ 29 + 0x46, 0xff, 0x00, /* Physical Maximum (255) */ 30 + 0x09, 0x30, /* Usage (X) */ 31 + 0x09, 0x31, /* Usage (Y) */ 32 + 0x09, 0x32, /* Usage (Z) */ 33 + 0x09, 0x32, /* Usage (Z) */ 34 + 0x09, 0x35, /* Usage (Rz) */ 35 + 0x81, 0x02, /* Input (Data,Var,Abs) */ 36 + }; 37 + 38 + /* 39 + * we fix the report descriptor by: 40 + * - marking the first Z axis as constant (so it is ignored by HID) 41 + * - assign the original second Z to Rx 42 + * - assign the original Rz to Ry 43 + */ 44 + static const __u8 gembird_jpd_fixed_rdesc[] = { 45 + 0x75, 0x08, /* Report Size (8) */ 46 + 0x95, 0x02, /* Report Count (2) */ 47 + 0x15, 0x00, /* Logical Minimum (0) */ 48 + 0x26, 0xff, 0x00, /* Logical Maximum (255) */ 49 + 0x35, 0x00, /* Physical Minimum (0) */ 50 + 0x46, 0xff, 0x00, /* Physical Maximum (255) */ 51 + 0x09, 0x30, /* Usage (X) */ 52 + 0x09, 0x31, /* Usage (Y) */ 53 + 0x81, 0x02, /* Input (Data,Var,Abs) */ 54 + 0x95, 0x01, /* Report Count (1) */ 55 + 0x09, 0x32, /* Usage (Z) */ 56 + 0x81, 0x01, /* Input (Cnst,Arr,Abs) */ 57 + 0x95, 0x02, /* Report Count (2) */ 58 + 0x09, 0x33, /* Usage (Rx) */ 59 + 0x09, 0x34, /* Usage (Ry) */ 60 + 0x81, 0x02, /* Input (Data,Var,Abs) */ 61 + }; 62 + 63 + static __u8 *gembird_report_fixup(struct hid_device *hdev, __u8 *rdesc, 64 + unsigned int *rsize) 65 + { 66 + __u8 *new_rdesc; 67 + /* delta_size is > 0 */ 68 + size_t delta_size = sizeof(gembird_jpd_fixed_rdesc) - 69 + sizeof(gembird_jpd_faulty_rdesc); 70 + size_t new_size = *rsize + delta_size; 71 + 72 + if (*rsize >= 31 && !memcmp(&rdesc[GEMBIRD_START_FAULTY_RDESC], 73 + gembird_jpd_faulty_rdesc, 74 + sizeof(gembird_jpd_faulty_rdesc))) { 75 + new_rdesc = devm_kzalloc(&hdev->dev, new_size, GFP_KERNEL); 76 + if (new_rdesc == NULL) 77 + return rdesc; 78 + 79 + dev_info(&hdev->dev, 80 + "fixing Gembird JPD-DualForce 2 report descriptor.\n"); 81 + 82 + /* start by copying the end of the rdesc */ 83 + memcpy(new_rdesc + delta_size, rdesc, *rsize); 84 + 85 + /* add the correct beginning */ 86 + memcpy(new_rdesc, rdesc, GEMBIRD_START_FAULTY_RDESC); 87 + 88 + /* replace the faulty part with the fixed one */ 89 + memcpy(new_rdesc + GEMBIRD_START_FAULTY_RDESC, 90 + gembird_jpd_fixed_rdesc, 91 + sizeof(gembird_jpd_fixed_rdesc)); 92 + 93 + *rsize = new_size; 94 + rdesc = new_rdesc; 95 + } 96 + 97 + return rdesc; 98 + } 99 + 100 + static const struct hid_device_id gembird_devices[] = { 101 + { HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, 102 + USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) }, 103 + { } 104 + }; 105 + MODULE_DEVICE_TABLE(hid, gembird_devices); 106 + 107 + static struct hid_driver gembird_driver = { 108 + .name = "gembird", 109 + .id_table = gembird_devices, 110 + .report_fixup = gembird_report_fixup, 111 + }; 112 + module_hid_driver(gembird_driver); 113 + 114 + MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); 115 + MODULE_DESCRIPTION("HID Gembird joypad driver"); 116 + MODULE_LICENSE("GPL");
+3
drivers/hid/hid-ids.h
··· 358 358 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 359 359 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 360 360 361 + #define USB_VENDOR_ID_GEMBIRD 0x11ff 362 + #define USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2 0x3331 363 + 361 364 #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc 362 365 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 363 366 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100