Skip to content

Commit d43ae84

Browse files
Ivan GorinovJiri Kosina
authored andcommitted
HID: winwing: Improve Orion2 throttle support
Add support for Orion2 throttle configurations with more than 32 buttons on the grip handle (this means the device reports more than 80 buttons). Map additional button codes to KEY_MACRO1 .. KEY_MACRO28. Make the module simpler, removing report descriptor fixup. [jkosina@suse.com: fix changelog] Signed-off-by: Ivan Gorinov <linux-kernel@altimeter.info> Signed-off-by: Jiri Kosina <jkosina@suse.com>
1 parent 54ba6d9 commit d43ae84

2 files changed

Lines changed: 107 additions & 66 deletions

File tree

drivers/hid/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,8 @@ config HID_WINWING
13181318
help
13191319
Support for WinWing Orion2 throttle base with the following grips:
13201320

1321+
* TGRIP-15E
1322+
* TGRIP-15EX
13211323
* TGRIP-16EX
13221324
* TGRIP-18
13231325

drivers/hid/hid-winwing.c

Lines changed: 105 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct winwing_drv_data {
3737
struct hid_device *hdev;
3838
__u8 *report_buf;
3939
struct mutex lock;
40+
int map_more_buttons;
4041
unsigned int num_leds;
4142
struct winwing_led leds[];
4243
};
@@ -81,12 +82,10 @@ static int winwing_init_led(struct hid_device *hdev,
8182
int ret;
8283
int i;
8384

84-
size_t data_size = struct_size(data, leds, 3);
85-
86-
data = devm_kzalloc(&hdev->dev, data_size, GFP_KERNEL);
85+
data = hid_get_drvdata(hdev);
8786

8887
if (!data)
89-
return -ENOMEM;
88+
return -EINVAL;
9089

9190
data->report_buf = devm_kmalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL);
9291

@@ -106,6 +105,7 @@ static int winwing_init_led(struct hid_device *hdev,
106105
"%s::%s",
107106
dev_name(&input->dev),
108107
info->led_name);
108+
109109
if (!led->cdev.name)
110110
return -ENOMEM;
111111

@@ -114,14 +114,98 @@ static int winwing_init_led(struct hid_device *hdev,
114114
return ret;
115115
}
116116

117-
hid_set_drvdata(hdev, data);
118-
119117
return ret;
120118
}
121119

120+
static int winwing_map_button(int button, int map_more_buttons)
121+
{
122+
if (button < 1)
123+
return KEY_RESERVED;
124+
125+
if (button > 112)
126+
return KEY_RESERVED;
127+
128+
if (button <= 16) {
129+
/*
130+
* Grip buttons [1 .. 16] are mapped to
131+
* key codes BTN_TRIGGER .. BTN_DEAD
132+
*/
133+
return (button - 1) + BTN_JOYSTICK;
134+
}
135+
136+
if (button >= 65) {
137+
/*
138+
* Base buttons [65 .. 112] are mapped to
139+
* key codes BTN_TRIGGER_HAPPY17 .. KEY_MAX
140+
*/
141+
return (button - 65) + BTN_TRIGGER_HAPPY17;
142+
}
143+
144+
if (!map_more_buttons) {
145+
/*
146+
* Not mapping numbers [33 .. 64] which
147+
* are not assigned to any real buttons
148+
*/
149+
if (button >= 33)
150+
return KEY_RESERVED;
151+
/*
152+
* Grip buttons [17 .. 32] are mapped to
153+
* BTN_TRIGGER_HAPPY1 .. BTN_TRIGGER_HAPPY16
154+
*/
155+
return (button - 17) + BTN_TRIGGER_HAPPY1;
156+
}
157+
158+
if (button >= 49) {
159+
/*
160+
* Grip buttons [49 .. 64] are mapped to
161+
* BTN_TRIGGER_HAPPY1 .. BTN_TRIGGER_HAPPY16
162+
*/
163+
return (button - 49) + BTN_TRIGGER_HAPPY1;
164+
}
165+
166+
/*
167+
* Grip buttons [17 .. 44] are mapped to
168+
* key codes KEY_MACRO1 .. KEY_MACRO28;
169+
* also mapping numbers [45 .. 48] which
170+
* are not assigned to any real buttons.
171+
*/
172+
return (button - 17) + KEY_MACRO1;
173+
}
174+
175+
static int winwing_input_mapping(struct hid_device *hdev,
176+
struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
177+
unsigned long **bit, int *max)
178+
{
179+
struct winwing_drv_data *data;
180+
int code = KEY_RESERVED;
181+
int button = 0;
182+
183+
data = hid_get_drvdata(hdev);
184+
185+
if (!data)
186+
return -EINVAL;
187+
188+
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
189+
return 0;
190+
191+
if (field->application != HID_GD_JOYSTICK)
192+
return 0;
193+
194+
/* Button numbers start with 1 */
195+
button = usage->hid & HID_USAGE;
196+
197+
code = winwing_map_button(button, data->map_more_buttons);
198+
199+
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
200+
201+
return 1;
202+
}
203+
122204
static int winwing_probe(struct hid_device *hdev,
123205
const struct hid_device_id *id)
124206
{
207+
struct winwing_drv_data *data;
208+
size_t data_size = struct_size(data, leds, 3);
125209
int ret;
126210

127211
ret = hid_parse(hdev);
@@ -130,6 +214,15 @@ static int winwing_probe(struct hid_device *hdev,
130214
return ret;
131215
}
132216

217+
data = devm_kzalloc(&hdev->dev, data_size, GFP_KERNEL);
218+
219+
if (!data)
220+
return -ENOMEM;
221+
222+
data->map_more_buttons = id->driver_data;
223+
224+
hid_set_drvdata(hdev, data);
225+
133226
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
134227
if (ret) {
135228
hid_err(hdev, "hw start failed\n");
@@ -152,64 +245,11 @@ static int winwing_input_configured(struct hid_device *hdev,
152245
return ret;
153246
}
154247

155-
static const __u8 original_rdesc_buttons[] = {
156-
0x05, 0x09, 0x19, 0x01, 0x29, 0x6F,
157-
0x15, 0x00, 0x25, 0x01, 0x35, 0x00,
158-
0x45, 0x01, 0x75, 0x01, 0x95, 0x6F,
159-
0x81, 0x02, 0x75, 0x01, 0x95, 0x01,
160-
0x81, 0x01
161-
};
162-
163-
/*
164-
* HID report descriptor shows 111 buttons, which exceeds maximum
165-
* number of buttons (80) supported by Linux kernel HID subsystem.
166-
*
167-
* This module skips numbers 32-63, unused on some throttle grips.
168-
*/
169-
170-
static const __u8 *winwing_report_fixup(struct hid_device *hdev, __u8 *rdesc,
171-
unsigned int *rsize)
172-
{
173-
int sig_length = sizeof(original_rdesc_buttons);
174-
int unused_button_numbers = 32;
175-
176-
if (*rsize < 34)
177-
return rdesc;
178-
179-
if (memcmp(rdesc + 8, original_rdesc_buttons, sig_length) == 0) {
180-
181-
/* Usage Maximum */
182-
rdesc[13] -= unused_button_numbers;
183-
184-
/* Report Count for buttons */
185-
rdesc[25] -= unused_button_numbers;
186-
187-
/* Report Count for padding [HID1_11, 6.2.2.9] */
188-
rdesc[31] += unused_button_numbers;
189-
190-
hid_info(hdev, "winwing descriptor fixed\n");
191-
}
192-
193-
return rdesc;
194-
}
195-
196-
static int winwing_raw_event(struct hid_device *hdev,
197-
struct hid_report *report, u8 *raw_data, int size)
198-
{
199-
if (size >= 15) {
200-
/* Skip buttons 32 .. 63 */
201-
memmove(raw_data + 5, raw_data + 9, 6);
202-
203-
/* Clear the padding */
204-
memset(raw_data + 11, 0, 4);
205-
}
206-
207-
return 0;
208-
}
209-
210248
static const struct hid_device_id winwing_devices[] = {
211-
{ HID_USB_DEVICE(0x4098, 0xbe62) }, /* TGRIP-18 */
212-
{ HID_USB_DEVICE(0x4098, 0xbe68) }, /* TGRIP-16EX */
249+
{ HID_USB_DEVICE(0x4098, 0xbd65), .driver_data = 1 }, /* TGRIP-15E */
250+
{ HID_USB_DEVICE(0x4098, 0xbd64), .driver_data = 1 }, /* TGRIP-15EX */
251+
{ HID_USB_DEVICE(0x4098, 0xbe68), .driver_data = 0 }, /* TGRIP-16EX */
252+
{ HID_USB_DEVICE(0x4098, 0xbe62), .driver_data = 0 }, /* TGRIP-18 */
213253
{}
214254
};
215255

@@ -218,10 +258,9 @@ MODULE_DEVICE_TABLE(hid, winwing_devices);
218258
static struct hid_driver winwing_driver = {
219259
.name = "winwing",
220260
.id_table = winwing_devices,
221-
.probe = winwing_probe,
222261
.input_configured = winwing_input_configured,
223-
.report_fixup = winwing_report_fixup,
224-
.raw_event = winwing_raw_event,
262+
.input_mapping = winwing_input_mapping,
263+
.probe = winwing_probe,
225264
};
226265
module_hid_driver(winwing_driver);
227266

0 commit comments

Comments
 (0)