[PATCH 2/4] HID: winwing: make the LED set and lighting controller model-dependent
From: René Onier
Date: Wed Sep 30 2026 - 16:23:12 EST
The driver hardcodes the three LEDs of the Orion 2 throttle base and the
lighting controller they are addressed to. Other WinWing devices speaking
this protocol carry a different LED set on a different controller, so
move both to the per-device data and select them once at init time.
Turn has_grip15 into a quirk mask at the same time, so that a model can
be described by more than one bit.
No functional change: the Orion 2 keeps its three LEDs on device 0x60,
family 0xbe, and the same button mapping.
Signed-off-by: René Onier <f3nr1l@xxxxxx>
---
drivers/hid/hid-winwing.c | 52 ++++++++++++++++++++++++++-------------
1 file changed, 35 insertions(+), 17 deletions(-)
diff --git a/drivers/hid/hid-winwing.c b/drivers/hid/hid-winwing.c
index a9bf81c19f..9ec0d2cf53 100644
--- a/drivers/hid/hid-winwing.c
+++ b/drivers/hid/hid-winwing.c
@@ -40,6 +40,9 @@
#define WINWING_RUMBLE_LEFT_DEVICE 0x01
#define WINWING_RUMBLE_RIGHT_DEVICE 0x03
+/* Grip with a rumble motor and more than 32 buttons */
+#define WINWING_GRIP15 BIT(0)
+
struct winwing_led {
struct led_classdev cdev;
struct hid_device *hdev;
@@ -52,7 +55,7 @@ struct winwing_led_info {
const char *led_name;
};
-static const struct winwing_led_info led_info[3] = {
+static const struct winwing_led_info orion2_led_info[] = {
{ 0, 255, "backlight" },
{ 1, 1, "a-a" },
{ 2, 1, "a-g" },
@@ -67,7 +70,13 @@ struct winwing_drv_data {
struct ff_rumble_effect rumble;
int rumble_left;
int rumble_right;
- int has_grip15;
+ unsigned long quirks;
+
+ /* Lighting controller and LED set of this model */
+ unsigned int num_leds;
+ __u8 led_device;
+ __u8 led_family;
+
struct winwing_led leds[];
};
@@ -104,7 +113,7 @@ static int winwing_led_write(struct led_classdev *cdev,
mutex_lock(&data->lights_lock);
ret = winwing_send_set_ledx(led->hdev, data->report_lights,
- ORION2_LIGHT_DEVICE, ORION2_LIGHT_FAMILY,
+ data->led_device, data->led_family,
led->number, br);
mutex_unlock(&data->lights_lock);
@@ -115,10 +124,11 @@ static int winwing_led_write(struct led_classdev *cdev,
static int winwing_init_led(struct hid_device *hdev,
struct input_dev *input)
{
+ const struct winwing_led_info *table;
struct winwing_drv_data *data;
struct winwing_led *led;
- int ret;
- int i;
+ int ret = 0;
+ unsigned int i;
data = hid_get_drvdata(hdev);
@@ -130,8 +140,13 @@ static int winwing_init_led(struct hid_device *hdev,
if (!data->report_lights)
return -ENOMEM;
- for (i = 0; i < 3; i += 1) {
- const struct winwing_led_info *info = &led_info[i];
+ table = orion2_led_info;
+ data->num_leds = ARRAY_SIZE(orion2_led_info);
+ data->led_device = ORION2_LIGHT_DEVICE;
+ data->led_family = ORION2_LIGHT_FAMILY;
+
+ for (i = 0; i < data->num_leds; i += 1) {
+ const struct winwing_led_info *info = &table[i];
led = &data->leds[i];
led->hdev = hdev;
@@ -155,7 +170,7 @@ static int winwing_init_led(struct hid_device *hdev,
return ret;
}
-static int winwing_map_button(int button, int has_grip15)
+static int winwing_map_button(int button, int map_more_buttons)
{
if (button < 1)
return KEY_RESERVED;
@@ -179,7 +194,7 @@ static int winwing_map_button(int button, int has_grip15)
return (button - 65) + BTN_TRIGGER_HAPPY17;
}
- if (!has_grip15) {
+ if (!map_more_buttons) {
/*
* Not mapping numbers [33 .. 64] which
* are not assigned to any real buttons
@@ -232,7 +247,7 @@ static int winwing_input_mapping(struct hid_device *hdev,
/* Button numbers start with 1 */
button = usage->hid & HID_USAGE;
- code = winwing_map_button(button, data->has_grip15);
+ code = winwing_map_button(button, data->quirks & WINWING_GRIP15);
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
@@ -368,7 +383,7 @@ static int winwing_probe(struct hid_device *hdev,
return -ENOMEM;
data->hdev = hdev;
- data->has_grip15 = id->driver_data;
+ data->quirks = id->driver_data;
hid_set_drvdata(hdev, data);
mutex_init(&data->lights_lock);
@@ -414,18 +429,21 @@ static int winwing_input_configured(struct hid_device *hdev,
if (ret)
hid_err(hdev, "led init failed\n");
- if (data->has_grip15)
+ if (data->quirks & WINWING_GRIP15)
winwing_init_ff(hdev, hidinput);
return ret;
}
-/* Set driver_data to 1 for grips with rumble motor and more than 32 buttons */
static const struct hid_device_id winwing_devices[] = {
- { HID_USB_DEVICE(0x4098, 0xbd65), .driver_data = 1 }, /* TGRIP-15E */
- { HID_USB_DEVICE(0x4098, 0xbd64), .driver_data = 1 }, /* TGRIP-15EX */
- { HID_USB_DEVICE(0x4098, 0xbe68), .driver_data = 0 }, /* TGRIP-16EX */
- { HID_USB_DEVICE(0x4098, 0xbe62), .driver_data = 0 }, /* TGRIP-18 */
+ { HID_USB_DEVICE(0x4098, 0xbd65), /* TGRIP-15E */
+ .driver_data = WINWING_GRIP15 },
+ { HID_USB_DEVICE(0x4098, 0xbd64), /* TGRIP-15EX */
+ .driver_data = WINWING_GRIP15 },
+ { HID_USB_DEVICE(0x4098, 0xbe68), /* TGRIP-16EX */
+ .driver_data = 0 },
+ { HID_USB_DEVICE(0x4098, 0xbe62), /* TGRIP-18 */
+ .driver_data = 0 },
{}
};
--
2.55.0