Skip to content

Commit eacdef8

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.19/winwing' into for-linus
- WinWing Orion2 throttle support improvement (Ivan Gorinov)
2 parents d6f4941 + d43ae84 commit eacdef8

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
@@ -1319,6 +1319,8 @@ config HID_WINWING
13191319
help
13201320
Support for WinWing Orion2 throttle base with the following grips:
13211321

1322+
* TGRIP-15E
1323+
* TGRIP-15EX
13221324
* TGRIP-16EX
13231325
* TGRIP-18
13241326

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)