Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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