0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/device.h>
0013 #include <linux/hid.h>
0014 #include <linux/module.h>
0015
0016 #include "hid-ids.h"
0017
0018 #define GEMBIRD_START_FAULTY_RDESC 8
0019
0020 static const __u8 gembird_jpd_faulty_rdesc[] = {
0021 0x75, 0x08,
0022 0x95, 0x05,
0023 0x15, 0x00,
0024 0x26, 0xff, 0x00,
0025 0x35, 0x00,
0026 0x46, 0xff, 0x00,
0027 0x09, 0x30,
0028 0x09, 0x31,
0029 0x09, 0x32,
0030 0x09, 0x32,
0031 0x09, 0x35,
0032 0x81, 0x02,
0033 };
0034
0035
0036
0037
0038
0039
0040
0041 static const __u8 gembird_jpd_fixed_rdesc[] = {
0042 0x75, 0x08,
0043 0x95, 0x02,
0044 0x15, 0x00,
0045 0x26, 0xff, 0x00,
0046 0x35, 0x00,
0047 0x46, 0xff, 0x00,
0048 0x09, 0x30,
0049 0x09, 0x31,
0050 0x81, 0x02,
0051 0x95, 0x01,
0052 0x09, 0x32,
0053 0x81, 0x01,
0054 0x95, 0x02,
0055 0x09, 0x33,
0056 0x09, 0x34,
0057 0x81, 0x02,
0058 };
0059
0060 static __u8 *gembird_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0061 unsigned int *rsize)
0062 {
0063 __u8 *new_rdesc;
0064
0065 size_t delta_size = sizeof(gembird_jpd_fixed_rdesc) -
0066 sizeof(gembird_jpd_faulty_rdesc);
0067 size_t new_size = *rsize + delta_size;
0068
0069 if (*rsize >= 31 && !memcmp(&rdesc[GEMBIRD_START_FAULTY_RDESC],
0070 gembird_jpd_faulty_rdesc,
0071 sizeof(gembird_jpd_faulty_rdesc))) {
0072 new_rdesc = devm_kzalloc(&hdev->dev, new_size, GFP_KERNEL);
0073 if (new_rdesc == NULL)
0074 return rdesc;
0075
0076 dev_info(&hdev->dev,
0077 "fixing Gembird JPD-DualForce 2 report descriptor.\n");
0078
0079
0080 memcpy(new_rdesc + delta_size, rdesc, *rsize);
0081
0082
0083 memcpy(new_rdesc, rdesc, GEMBIRD_START_FAULTY_RDESC);
0084
0085
0086 memcpy(new_rdesc + GEMBIRD_START_FAULTY_RDESC,
0087 gembird_jpd_fixed_rdesc,
0088 sizeof(gembird_jpd_fixed_rdesc));
0089
0090 *rsize = new_size;
0091 rdesc = new_rdesc;
0092 }
0093
0094 return rdesc;
0095 }
0096
0097 static const struct hid_device_id gembird_devices[] = {
0098 { HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD,
0099 USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
0100 { }
0101 };
0102 MODULE_DEVICE_TABLE(hid, gembird_devices);
0103
0104 static struct hid_driver gembird_driver = {
0105 .name = "gembird",
0106 .id_table = gembird_devices,
0107 .report_fixup = gembird_report_fixup,
0108 };
0109 module_hid_driver(gembird_driver);
0110
0111 MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
0112 MODULE_DESCRIPTION("HID Gembird joypad driver");
0113 MODULE_LICENSE("GPL");