Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  HID driver for Saitek devices.
0004  *
0005  *  PS1000 (USB gamepad):
0006  *  Fixes the HID report descriptor by removing a non-existent axis and
0007  *  clearing the constant bit on the input reports for buttons and d-pad.
0008  *  (This module is based on "hid-ortek".)
0009  *  Copyright (c) 2012 Andreas Hübner
0010  *
0011  *  R.A.T.7, R.A.T.9, M.M.O.7 (USB gaming mice):
0012  *  Fixes the mode button which cycles through three constantly pressed
0013  *  buttons. All three press events are mapped to one button and the
0014  *  missing release event is generated immediately.
0015  */
0016 
0017 /*
0018  */
0019 
0020 #include <linux/device.h>
0021 #include <linux/hid.h>
0022 #include <linux/module.h>
0023 #include <linux/kernel.h>
0024 
0025 #include "hid-ids.h"
0026 
0027 #define SAITEK_FIX_PS1000   0x0001
0028 #define SAITEK_RELEASE_MODE_RAT7    0x0002
0029 #define SAITEK_RELEASE_MODE_MMO7    0x0004
0030 
0031 struct saitek_sc {
0032     unsigned long quirks;
0033     int mode;
0034 };
0035 
0036 static int saitek_probe(struct hid_device *hdev,
0037         const struct hid_device_id *id)
0038 {
0039     unsigned long quirks = id->driver_data;
0040     struct saitek_sc *ssc;
0041     int ret;
0042 
0043     ssc = devm_kzalloc(&hdev->dev, sizeof(*ssc), GFP_KERNEL);
0044     if (ssc == NULL) {
0045         hid_err(hdev, "can't alloc saitek descriptor\n");
0046         return -ENOMEM;
0047     }
0048 
0049     ssc->quirks = quirks;
0050     ssc->mode = -1;
0051 
0052     hid_set_drvdata(hdev, ssc);
0053 
0054     ret = hid_parse(hdev);
0055     if (ret) {
0056         hid_err(hdev, "parse failed\n");
0057         return ret;
0058     }
0059 
0060     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0061     if (ret) {
0062         hid_err(hdev, "hw start failed\n");
0063         return ret;
0064     }
0065 
0066     return 0;
0067 }
0068 
0069 static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0070         unsigned int *rsize)
0071 {
0072     struct saitek_sc *ssc = hid_get_drvdata(hdev);
0073 
0074     if ((ssc->quirks & SAITEK_FIX_PS1000) && *rsize == 137 &&
0075             rdesc[20] == 0x09 && rdesc[21] == 0x33 &&
0076             rdesc[94] == 0x81 && rdesc[95] == 0x03 &&
0077             rdesc[110] == 0x81 && rdesc[111] == 0x03) {
0078 
0079         hid_info(hdev, "Fixing up Saitek PS1000 report descriptor\n");
0080 
0081         /* convert spurious axis to a "noop" Logical Minimum (0) */
0082         rdesc[20] = 0x15;
0083         rdesc[21] = 0x00;
0084 
0085         /* clear constant bit on buttons and d-pad */
0086         rdesc[95] = 0x02;
0087         rdesc[111] = 0x02;
0088 
0089     }
0090     return rdesc;
0091 }
0092 
0093 static int saitek_raw_event(struct hid_device *hdev,
0094         struct hid_report *report, u8 *raw_data, int size)
0095 {
0096     struct saitek_sc *ssc = hid_get_drvdata(hdev);
0097 
0098     if (ssc->quirks & SAITEK_RELEASE_MODE_RAT7 && size == 7) {
0099         /* R.A.T.7 uses bits 13, 14, 15 for the mode */
0100         int mode = -1;
0101         if (raw_data[1] & 0x01)
0102             mode = 0;
0103         else if (raw_data[1] & 0x02)
0104             mode = 1;
0105         else if (raw_data[1] & 0x04)
0106             mode = 2;
0107 
0108         /* clear mode bits */
0109         raw_data[1] &= ~0x07;
0110 
0111         if (mode != ssc->mode) {
0112             hid_dbg(hdev, "entered mode %d\n", mode);
0113             if (ssc->mode != -1) {
0114                 /* use bit 13 as the mode button */
0115                 raw_data[1] |= 0x04;
0116             }
0117             ssc->mode = mode;
0118         }
0119     } else if (ssc->quirks & SAITEK_RELEASE_MODE_MMO7 && size == 8) {
0120 
0121         /* M.M.O.7 uses bits 8, 22, 23 for the mode */
0122         int mode = -1;
0123         if (raw_data[1] & 0x80)
0124             mode = 0;
0125         else if (raw_data[2] & 0x01)
0126             mode = 1;
0127         else if (raw_data[2] & 0x02)
0128             mode = 2;
0129 
0130         /* clear mode bits */
0131         raw_data[1] &= ~0x80;
0132         raw_data[2] &= ~0x03;
0133 
0134         if (mode != ssc->mode) {
0135             hid_dbg(hdev, "entered mode %d\n", mode);
0136             if (ssc->mode != -1) {
0137                 /* use bit 8 as the mode button, bits 22
0138                  * and 23 do not represent buttons
0139                  * according to the HID report descriptor
0140                  */
0141                 raw_data[1] |= 0x80;
0142             }
0143             ssc->mode = mode;
0144         }
0145     }
0146 
0147     return 0;
0148 }
0149 
0150 static int saitek_event(struct hid_device *hdev, struct hid_field *field,
0151         struct hid_usage *usage, __s32 value)
0152 {
0153     struct saitek_sc *ssc = hid_get_drvdata(hdev);
0154     struct input_dev *input = field->hidinput->input;
0155 
0156     if (usage->type == EV_KEY && value &&
0157             (((ssc->quirks & SAITEK_RELEASE_MODE_RAT7) &&
0158               usage->code - BTN_MOUSE == 10) ||
0159             ((ssc->quirks & SAITEK_RELEASE_MODE_MMO7) &&
0160              usage->code - BTN_MOUSE == 15))) {
0161 
0162         input_report_key(input, usage->code, 1);
0163 
0164         /* report missing release event */
0165         input_report_key(input, usage->code, 0);
0166 
0167         return 1;
0168     }
0169 
0170     return 0;
0171 }
0172 
0173 static const struct hid_device_id saitek_devices[] = {
0174     { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000),
0175         .driver_data = SAITEK_FIX_PS1000 },
0176     { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5),
0177         .driver_data = SAITEK_RELEASE_MODE_RAT7 },
0178     { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD),
0179         .driver_data = SAITEK_RELEASE_MODE_RAT7 },
0180     { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7),
0181         .driver_data = SAITEK_RELEASE_MODE_RAT7 },
0182     { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_CONTAGION),
0183         .driver_data = SAITEK_RELEASE_MODE_RAT7 },
0184     { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT9),
0185         .driver_data = SAITEK_RELEASE_MODE_RAT7 },
0186     { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9),
0187         .driver_data = SAITEK_RELEASE_MODE_RAT7 },
0188     { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7),
0189         .driver_data = SAITEK_RELEASE_MODE_MMO7 },
0190     { }
0191 };
0192 
0193 MODULE_DEVICE_TABLE(hid, saitek_devices);
0194 
0195 static struct hid_driver saitek_driver = {
0196     .name = "saitek",
0197     .id_table = saitek_devices,
0198     .probe = saitek_probe,
0199     .report_fixup = saitek_report_fixup,
0200     .raw_event = saitek_raw_event,
0201     .event = saitek_event,
0202 };
0203 module_hid_driver(saitek_driver);
0204 
0205 MODULE_LICENSE("GPL");