hid-dr.c (9338B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Force feedback support for DragonRise Inc. game controllers 4 * 5 * From what I have gathered, these devices are mass produced in China and are 6 * distributed under several vendors. They often share the same design as 7 * the original PlayStation DualShock controller. 8 * 9 * 0079:0006 "DragonRise Inc. Generic USB Joystick " 10 * - tested with a Tesun USB-703 game controller. 11 * 12 * Copyright (c) 2009 Richard Walmsley <richwalm@gmail.com> 13 */ 14 15/* 16 */ 17 18#include <linux/input.h> 19#include <linux/slab.h> 20#include <linux/hid.h> 21#include <linux/module.h> 22 23#include "hid-ids.h" 24 25#ifdef CONFIG_DRAGONRISE_FF 26 27struct drff_device { 28 struct hid_report *report; 29}; 30 31static int drff_play(struct input_dev *dev, void *data, 32 struct ff_effect *effect) 33{ 34 struct hid_device *hid = input_get_drvdata(dev); 35 struct drff_device *drff = data; 36 int strong, weak; 37 38 strong = effect->u.rumble.strong_magnitude; 39 weak = effect->u.rumble.weak_magnitude; 40 41 dbg_hid("called with 0x%04x 0x%04x", strong, weak); 42 43 if (strong || weak) { 44 strong = strong * 0xff / 0xffff; 45 weak = weak * 0xff / 0xffff; 46 47 /* While reverse engineering this device, I found that when 48 this value is set, it causes the strong rumble to function 49 at a near maximum speed, so we'll bypass it. */ 50 if (weak == 0x0a) 51 weak = 0x0b; 52 53 drff->report->field[0]->value[0] = 0x51; 54 drff->report->field[0]->value[1] = 0x00; 55 drff->report->field[0]->value[2] = weak; 56 drff->report->field[0]->value[4] = strong; 57 hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); 58 59 drff->report->field[0]->value[0] = 0xfa; 60 drff->report->field[0]->value[1] = 0xfe; 61 } else { 62 drff->report->field[0]->value[0] = 0xf3; 63 drff->report->field[0]->value[1] = 0x00; 64 } 65 66 drff->report->field[0]->value[2] = 0x00; 67 drff->report->field[0]->value[4] = 0x00; 68 dbg_hid("running with 0x%02x 0x%02x", strong, weak); 69 hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); 70 71 return 0; 72} 73 74static int drff_init(struct hid_device *hid) 75{ 76 struct drff_device *drff; 77 struct hid_report *report; 78 struct hid_input *hidinput; 79 struct list_head *report_list = 80 &hid->report_enum[HID_OUTPUT_REPORT].report_list; 81 struct input_dev *dev; 82 int error; 83 84 if (list_empty(&hid->inputs)) { 85 hid_err(hid, "no inputs found\n"); 86 return -ENODEV; 87 } 88 hidinput = list_first_entry(&hid->inputs, struct hid_input, list); 89 dev = hidinput->input; 90 91 if (list_empty(report_list)) { 92 hid_err(hid, "no output reports found\n"); 93 return -ENODEV; 94 } 95 96 report = list_first_entry(report_list, struct hid_report, list); 97 if (report->maxfield < 1) { 98 hid_err(hid, "no fields in the report\n"); 99 return -ENODEV; 100 } 101 102 if (report->field[0]->report_count < 7) { 103 hid_err(hid, "not enough values in the field\n"); 104 return -ENODEV; 105 } 106 107 drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL); 108 if (!drff) 109 return -ENOMEM; 110 111 set_bit(FF_RUMBLE, dev->ffbit); 112 113 error = input_ff_create_memless(dev, drff, drff_play); 114 if (error) { 115 kfree(drff); 116 return error; 117 } 118 119 drff->report = report; 120 drff->report->field[0]->value[0] = 0xf3; 121 drff->report->field[0]->value[1] = 0x00; 122 drff->report->field[0]->value[2] = 0x00; 123 drff->report->field[0]->value[3] = 0x00; 124 drff->report->field[0]->value[4] = 0x00; 125 drff->report->field[0]->value[5] = 0x00; 126 drff->report->field[0]->value[6] = 0x00; 127 hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); 128 129 hid_info(hid, "Force Feedback for DragonRise Inc. " 130 "game controllers by Richard Walmsley <richwalm@gmail.com>\n"); 131 132 return 0; 133} 134#else 135static inline int drff_init(struct hid_device *hid) 136{ 137 return 0; 138} 139#endif 140 141/* 142 * The original descriptor of joystick with PID 0x0011, represented by DVTech PC 143 * JS19. It seems both copied from another device and a result of confusion 144 * either about the specification or about the program used to create the 145 * descriptor. In any case, it's a wonder it works on Windows. 146 * 147 * Usage Page (Desktop), ; Generic desktop controls (01h) 148 * Usage (Joystick), ; Joystick (04h, application collection) 149 * Collection (Application), 150 * Collection (Logical), 151 * Report Size (8), 152 * Report Count (5), 153 * Logical Minimum (0), 154 * Logical Maximum (255), 155 * Physical Minimum (0), 156 * Physical Maximum (255), 157 * Usage (X), ; X (30h, dynamic value) 158 * Usage (X), ; X (30h, dynamic value) 159 * Usage (X), ; X (30h, dynamic value) 160 * Usage (X), ; X (30h, dynamic value) 161 * Usage (Y), ; Y (31h, dynamic value) 162 * Input (Variable), 163 * Report Size (4), 164 * Report Count (1), 165 * Logical Maximum (7), 166 * Physical Maximum (315), 167 * Unit (Degrees), 168 * Usage (00h), 169 * Input (Variable, Null State), 170 * Unit, 171 * Report Size (1), 172 * Report Count (10), 173 * Logical Maximum (1), 174 * Physical Maximum (1), 175 * Usage Page (Button), ; Button (09h) 176 * Usage Minimum (01h), 177 * Usage Maximum (0Ah), 178 * Input (Variable), 179 * Usage Page (FF00h), ; FF00h, vendor-defined 180 * Report Size (1), 181 * Report Count (10), 182 * Logical Maximum (1), 183 * Physical Maximum (1), 184 * Usage (01h), 185 * Input (Variable), 186 * End Collection, 187 * Collection (Logical), 188 * Report Size (8), 189 * Report Count (4), 190 * Physical Maximum (255), 191 * Logical Maximum (255), 192 * Usage (02h), 193 * Output (Variable), 194 * End Collection, 195 * End Collection 196 */ 197 198/* Size of the original descriptor of the PID 0x0011 joystick */ 199#define PID0011_RDESC_ORIG_SIZE 101 200 201/* Fixed report descriptor for PID 0x011 joystick */ 202static __u8 pid0011_rdesc_fixed[] = { 203 0x05, 0x01, /* Usage Page (Desktop), */ 204 0x09, 0x04, /* Usage (Joystick), */ 205 0xA1, 0x01, /* Collection (Application), */ 206 0xA1, 0x02, /* Collection (Logical), */ 207 0x14, /* Logical Minimum (0), */ 208 0x75, 0x08, /* Report Size (8), */ 209 0x95, 0x03, /* Report Count (3), */ 210 0x81, 0x01, /* Input (Constant), */ 211 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 212 0x95, 0x02, /* Report Count (2), */ 213 0x09, 0x30, /* Usage (X), */ 214 0x09, 0x31, /* Usage (Y), */ 215 0x81, 0x02, /* Input (Variable), */ 216 0x75, 0x01, /* Report Size (1), */ 217 0x95, 0x04, /* Report Count (4), */ 218 0x81, 0x01, /* Input (Constant), */ 219 0x25, 0x01, /* Logical Maximum (1), */ 220 0x95, 0x0A, /* Report Count (10), */ 221 0x05, 0x09, /* Usage Page (Button), */ 222 0x19, 0x01, /* Usage Minimum (01h), */ 223 0x29, 0x0A, /* Usage Maximum (0Ah), */ 224 0x81, 0x02, /* Input (Variable), */ 225 0x95, 0x0A, /* Report Count (10), */ 226 0x81, 0x01, /* Input (Constant), */ 227 0xC0, /* End Collection, */ 228 0xC0 /* End Collection */ 229}; 230 231static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, 232 unsigned int *rsize) 233{ 234 switch (hdev->product) { 235 case 0x0011: 236 if (*rsize == PID0011_RDESC_ORIG_SIZE) { 237 rdesc = pid0011_rdesc_fixed; 238 *rsize = sizeof(pid0011_rdesc_fixed); 239 } 240 break; 241 } 242 return rdesc; 243} 244 245#define map_abs(c) hid_map_usage(hi, usage, bit, max, EV_ABS, (c)) 246#define map_rel(c) hid_map_usage(hi, usage, bit, max, EV_REL, (c)) 247 248static int dr_input_mapping(struct hid_device *hdev, struct hid_input *hi, 249 struct hid_field *field, struct hid_usage *usage, 250 unsigned long **bit, int *max) 251{ 252 switch (usage->hid) { 253 /* 254 * revert to the old hid-input behavior where axes 255 * can be randomly assigned when hid->usage is reused. 256 */ 257 case HID_GD_X: case HID_GD_Y: case HID_GD_Z: 258 case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: 259 if (field->flags & HID_MAIN_ITEM_RELATIVE) 260 map_rel(usage->hid & 0xf); 261 else 262 map_abs(usage->hid & 0xf); 263 return 1; 264 } 265 266 return 0; 267} 268 269static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) 270{ 271 int ret; 272 273 dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe..."); 274 275 ret = hid_parse(hdev); 276 if (ret) { 277 hid_err(hdev, "parse failed\n"); 278 goto err; 279 } 280 281 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); 282 if (ret) { 283 hid_err(hdev, "hw start failed\n"); 284 goto err; 285 } 286 287 switch (hdev->product) { 288 case 0x0006: 289 ret = drff_init(hdev); 290 if (ret) { 291 dev_err(&hdev->dev, "force feedback init failed\n"); 292 hid_hw_stop(hdev); 293 goto err; 294 } 295 break; 296 } 297 298 return 0; 299err: 300 return ret; 301} 302 303static const struct hid_device_id dr_devices[] = { 304 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, 305 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011), }, 306 { } 307}; 308MODULE_DEVICE_TABLE(hid, dr_devices); 309 310static struct hid_driver dr_driver = { 311 .name = "dragonrise", 312 .id_table = dr_devices, 313 .report_fixup = dr_report_fixup, 314 .probe = dr_probe, 315 .input_mapping = dr_input_mapping, 316}; 317module_hid_driver(dr_driver); 318 319MODULE_LICENSE("GPL");