1 /* 2 * HID driver for Saitek devices. 3 * 4 * PS1000 (USB gamepad): 5 * Fixes the HID report descriptor by removing a non-existent axis and 6 * clearing the constant bit on the input reports for buttons and d-pad. 7 * (This module is based on "hid-ortek".) 8 * Copyright (c) 2012 Andreas Hübner 9 * 10 * R.A.T.7, M.M.O.7 (USB gaming mice): 11 * Fixes the mode button which cycles through three constantly pressed 12 * buttons. All three press events are mapped to one button and the 13 * missing release event is generated immediately. 14 * 15 */ 16 17 /* 18 * This program is free software; you can redistribute it and/or modify it 19 * under the terms of the GNU General Public License as published by the Free 20 * Software Foundation; either version 2 of the License, or (at your option) 21 * any later version. 22 */ 23 24 #include <linux/device.h> 25 #include <linux/hid.h> 26 #include <linux/module.h> 27 #include <linux/kernel.h> 28 29 #include "hid-ids.h" 30 31 #define SAITEK_FIX_PS1000 0x0001 32 #define SAITEK_RELEASE_MODE_RAT7 0x0002 33 #define SAITEK_RELEASE_MODE_MMO7 0x0004 34 35 struct saitek_sc { 36 unsigned long quirks; 37 int mode; 38 }; 39 40 static int saitek_probe(struct hid_device *hdev, 41 const struct hid_device_id *id) 42 { 43 unsigned long quirks = id->driver_data; 44 struct saitek_sc *ssc; 45 int ret; 46 47 ssc = devm_kzalloc(&hdev->dev, sizeof(*ssc), GFP_KERNEL); 48 if (ssc == NULL) { 49 hid_err(hdev, "can't alloc saitek descriptor\n"); 50 return -ENOMEM; 51 } 52 53 ssc->quirks = quirks; 54 ssc->mode = -1; 55 56 hid_set_drvdata(hdev, ssc); 57 58 ret = hid_parse(hdev); 59 if (ret) { 60 hid_err(hdev, "parse failed\n"); 61 return ret; 62 } 63 64 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 65 if (ret) { 66 hid_err(hdev, "hw start failed\n"); 67 return ret; 68 } 69 70 return 0; 71 } 72 73 static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, 74 unsigned int *rsize) 75 { 76 struct saitek_sc *ssc = hid_get_drvdata(hdev); 77 78 if ((ssc->quirks & SAITEK_FIX_PS1000) && *rsize == 137 && 79 rdesc[20] == 0x09 && rdesc[21] == 0x33 && 80 rdesc[94] == 0x81 && rdesc[95] == 0x03 && 81 rdesc[110] == 0x81 && rdesc[111] == 0x03) { 82 83 hid_info(hdev, "Fixing up Saitek PS1000 report descriptor\n"); 84 85 /* convert spurious axis to a "noop" Logical Minimum (0) */ 86 rdesc[20] = 0x15; 87 rdesc[21] = 0x00; 88 89 /* clear constant bit on buttons and d-pad */ 90 rdesc[95] = 0x02; 91 rdesc[111] = 0x02; 92 93 } 94 return rdesc; 95 } 96 97 static int saitek_raw_event(struct hid_device *hdev, 98 struct hid_report *report, u8 *raw_data, int size) 99 { 100 struct saitek_sc *ssc = hid_get_drvdata(hdev); 101 102 if (ssc->quirks & SAITEK_RELEASE_MODE_RAT7 && size == 7) { 103 /* R.A.T.7 uses bits 13, 14, 15 for the mode */ 104 int mode = -1; 105 if (raw_data[1] & 0x01) 106 mode = 0; 107 else if (raw_data[1] & 0x02) 108 mode = 1; 109 else if (raw_data[1] & 0x04) 110 mode = 2; 111 112 /* clear mode bits */ 113 raw_data[1] &= ~0x07; 114 115 if (mode != ssc->mode) { 116 hid_dbg(hdev, "entered mode %d\n", mode); 117 if (ssc->mode != -1) { 118 /* use bit 13 as the mode button */ 119 raw_data[1] |= 0x04; 120 } 121 ssc->mode = mode; 122 } 123 } else if (ssc->quirks & SAITEK_RELEASE_MODE_MMO7 && size == 8) { 124 125 /* M.M.O.7 uses bits 8, 22, 23 for the mode */ 126 int mode = -1; 127 if (raw_data[1] & 0x80) 128 mode = 0; 129 else if (raw_data[2] & 0x01) 130 mode = 1; 131 else if (raw_data[2] & 0x02) 132 mode = 2; 133 134 /* clear mode bits */ 135 raw_data[1] &= ~0x80; 136 raw_data[2] &= ~0x03; 137 138 if (mode != ssc->mode) { 139 hid_dbg(hdev, "entered mode %d\n", mode); 140 if (ssc->mode != -1) { 141 /* use bit 8 as the mode button, bits 22 142 * and 23 do not represent buttons 143 * according to the HID report descriptor 144 */ 145 raw_data[1] |= 0x80; 146 } 147 ssc->mode = mode; 148 } 149 } 150 151 return 0; 152 } 153 154 static int saitek_event(struct hid_device *hdev, struct hid_field *field, 155 struct hid_usage *usage, __s32 value) 156 { 157 struct saitek_sc *ssc = hid_get_drvdata(hdev); 158 struct input_dev *input = field->hidinput->input; 159 160 if (usage->type == EV_KEY && value && 161 (((ssc->quirks & SAITEK_RELEASE_MODE_RAT7) && 162 usage->code - BTN_MOUSE == 10) || 163 ((ssc->quirks & SAITEK_RELEASE_MODE_MMO7) && 164 usage->code - BTN_MOUSE == 15))) { 165 166 input_report_key(input, usage->code, 1); 167 168 /* report missing release event */ 169 input_report_key(input, usage->code, 0); 170 171 return 1; 172 } 173 174 return 0; 175 } 176 177 static const struct hid_device_id saitek_devices[] = { 178 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000), 179 .driver_data = SAITEK_FIX_PS1000 }, 180 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), 181 .driver_data = SAITEK_RELEASE_MODE_RAT7 }, 182 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7), 183 .driver_data = SAITEK_RELEASE_MODE_MMO7 }, 184 { } 185 }; 186 187 MODULE_DEVICE_TABLE(hid, saitek_devices); 188 189 static struct hid_driver saitek_driver = { 190 .name = "saitek", 191 .id_table = saitek_devices, 192 .probe = saitek_probe, 193 .report_fixup = saitek_report_fixup, 194 .raw_event = saitek_raw_event, 195 .event = saitek_event, 196 }; 197 module_hid_driver(saitek_driver); 198 199 MODULE_LICENSE("GPL"); 200