* [PATCH RESEND] HID: winwing: Enable rumble effects
@ 2026-02-11 5:31 Ivan Gorinov
2026-02-12 5:31 ` Dan Carpenter
0 siblings, 1 reply; 2+ messages in thread
From: Ivan Gorinov @ 2026-02-11 5:31 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, linux-kernel
Enable rumble motor control on TGRIP-15E and TGRIP-15EX throttle grips
by sending haptic feedback commands (EV_FF events) to the input device.
Signed-off-by: Ivan Gorinov <linux-kernel@altimeter.info>
---
drivers/hid/hid-winwing.c | 193 +++++++++++++++++++++++++++++++++++---
1 file changed, 179 insertions(+), 14 deletions(-)
diff --git a/drivers/hid/hid-winwing.c b/drivers/hid/hid-winwing.c
index ab65dc12d1e0..031590ffd383 100644
--- a/drivers/hid/hid-winwing.c
+++ b/drivers/hid/hid-winwing.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#define MAX_REPORT 16
@@ -35,10 +36,14 @@ static const struct winwing_led_info led_info[3] = {
struct winwing_drv_data {
struct hid_device *hdev;
- __u8 *report_buf;
- struct mutex lock;
- int map_more_buttons;
- unsigned int num_leds;
+ struct mutex lights_lock;
+ __u8 *report_lights;
+ __u8 *report_rumble;
+ struct work_struct rumble_work;
+ struct ff_rumble_effect rumble;
+ int rumble_left;
+ int rumble_right;
+ int has_grip15;
struct winwing_led leds[];
};
@@ -47,10 +52,10 @@ static int winwing_led_write(struct led_classdev *cdev,
{
struct winwing_led *led = (struct winwing_led *) cdev;
struct winwing_drv_data *data = hid_get_drvdata(led->hdev);
- __u8 *buf = data->report_buf;
+ __u8 *buf = data->report_lights;
int ret;
- mutex_lock(&data->lock);
+ mutex_lock(&data->lights_lock);
buf[0] = 0x02;
buf[1] = 0x60;
@@ -69,7 +74,7 @@ static int winwing_led_write(struct led_classdev *cdev,
ret = hid_hw_output_report(led->hdev, buf, 14);
- mutex_unlock(&data->lock);
+ mutex_unlock(&data->lights_lock);
return ret;
}
@@ -87,9 +92,9 @@ static int winwing_init_led(struct hid_device *hdev,
if (!data)
return -EINVAL;
- data->report_buf = devm_kmalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL);
+ data->report_lights = devm_kzalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL);
- if (!data->report_buf)
+ if (!data->report_lights)
return -ENOMEM;
for (i = 0; i < 3; i += 1) {
@@ -117,7 +122,7 @@ static int winwing_init_led(struct hid_device *hdev,
return ret;
}
-static int winwing_map_button(int button, int map_more_buttons)
+static int winwing_map_button(int button, int has_grip15)
{
if (button < 1)
return KEY_RESERVED;
@@ -141,7 +146,7 @@ static int winwing_map_button(int button, int map_more_buttons)
return (button - 65) + BTN_TRIGGER_HAPPY17;
}
- if (!map_more_buttons) {
+ if (!has_grip15) {
/*
* Not mapping numbers [33 .. 64] which
* are not assigned to any real buttons
@@ -194,13 +199,150 @@ 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->map_more_buttons);
+ code = winwing_map_button(button, data->has_grip15);
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
return 1;
}
+/*
+ * If x ≤ 0, return 0;
+ * if x is in [1 .. 65535], return a value in [1 .. 255]
+ */
+static inline int convert_magnitude(int x)
+{
+ if (x < 1)
+ return 0;
+
+ return ((x * 255) >> 16) + 1;
+}
+
+static int winwing_haptic_rumble(struct winwing_drv_data *data)
+{
+ __u8 *buf;
+ __u8 m;
+
+ if (!data)
+ return -EINVAL;
+
+ buf = data->report_rumble;
+
+ if (!buf)
+ return -EINVAL;
+
+ if (!data->hdev) {
+ hid_err(data->hdev, "data->hdev == NULL\n");
+ return -EINVAL;
+ }
+
+ if (!data->hdev->ll_driver) {
+ hid_err(data->hdev, "data->hdev->ll_driver == NULL\n");
+ return -EINVAL;
+ }
+
+ m = convert_magnitude(data->rumble.strong_magnitude);
+ if (m != data->rumble_left) {
+ int ret;
+
+ buf[0] = 0x02;
+ buf[1] = 0x01;
+ buf[2] = 0xbf;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x03;
+ buf[6] = 0x49;
+ buf[7] = 0x00;
+ buf[8] = m;
+ buf[9] = 0x00;
+ buf[10] = 0;
+ buf[11] = 0;
+ buf[12] = 0;
+ buf[13] = 0;
+
+ ret = hid_hw_output_report(data->hdev, buf, 14);
+ if (ret < 0) {
+ hid_err(data->hdev, "error %d (%*ph)\n", ret, 14, buf);
+ return ret;
+ }
+ data->rumble_left = m;
+ }
+
+ m = convert_magnitude(data->rumble.weak_magnitude);
+ if (m != data->rumble_right) {
+ int ret;
+
+ buf[0] = 0x02;
+ buf[1] = 0x03;
+ buf[2] = 0xbf;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x03;
+ buf[6] = 0x49;
+ buf[7] = 0x00;
+ buf[8] = m;
+ buf[9] = 0x00;
+ buf[10] = 0;
+ buf[11] = 0;
+ buf[12] = 0;
+ buf[13] = 0;
+
+ ret = hid_hw_output_report(data->hdev, buf, 14);
+ if (ret < 0) {
+ hid_err(data->hdev, "error %d (%*ph)\n", ret, 14, buf);
+ return ret;
+ }
+ data->rumble_right = m;
+ }
+
+ return 0;
+}
+
+
+static void winwing_haptic_rumble_cb(struct work_struct *work)
+{
+ struct winwing_drv_data *data;
+
+ data = container_of(work, struct winwing_drv_data, rumble_work);
+
+ if (data)
+ winwing_haptic_rumble(data);
+}
+
+static int winwing_play_effect(struct input_dev *dev, void *context,
+ struct ff_effect *effect)
+{
+ struct winwing_drv_data *data = (struct winwing_drv_data *) context;
+
+ if (effect->type != FF_RUMBLE)
+ return 0;
+
+ if (!data)
+ return -EINVAL;
+
+ data->rumble = effect->u.rumble;
+
+ return schedule_work(&data->rumble_work);
+}
+
+static int winwing_init_ff(struct hid_device *hdev, struct hid_input *hidinput)
+{
+ struct winwing_drv_data *data;
+
+ data = (struct winwing_drv_data *) hid_get_drvdata(hdev);
+ data->report_rumble = devm_kzalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL);
+ data->rumble_left = -1;
+ data->rumble_right = -1;
+
+ input_set_capability(hidinput->input, EV_FF, FF_RUMBLE);
+
+ if (!data)
+ return -EINVAL;
+
+ return input_ff_create_memless(hidinput->input, data,
+ winwing_play_effect);
+}
+
static int winwing_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
@@ -219,10 +361,12 @@ static int winwing_probe(struct hid_device *hdev,
if (!data)
return -ENOMEM;
- data->map_more_buttons = id->driver_data;
-
+ data->hdev = hdev;
+ data->has_grip15 = id->driver_data;
hid_set_drvdata(hdev, data);
+ INIT_WORK(&data->rumble_work, winwing_haptic_rumble_cb);
+
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "hw start failed\n");
@@ -232,19 +376,39 @@ static int winwing_probe(struct hid_device *hdev,
return 0;
}
+static void winwing_remove(struct hid_device *hdev)
+{
+ struct winwing_drv_data *data;
+
+ data = (struct winwing_drv_data *) hid_get_drvdata(hdev);
+
+ if (data)
+ cancel_work_sync(&data->rumble_work);
+
+ hid_hw_close(hdev);
+ hid_hw_stop(hdev);
+}
+
static int winwing_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
+ struct winwing_drv_data *data;
int ret;
+ data = (struct winwing_drv_data *) hid_get_drvdata(hdev);
+
ret = winwing_init_led(hdev, hidinput->input);
if (ret)
hid_err(hdev, "led init failed\n");
+ if (data->has_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 */
@@ -261,6 +425,7 @@ static struct hid_driver winwing_driver = {
.input_configured = winwing_input_configured,
.input_mapping = winwing_input_mapping,
.probe = winwing_probe,
+ .remove = winwing_remove,
};
module_hid_driver(winwing_driver);
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH RESEND] HID: winwing: Enable rumble effects
2026-02-11 5:31 [PATCH RESEND] HID: winwing: Enable rumble effects Ivan Gorinov
@ 2026-02-12 5:31 ` Dan Carpenter
0 siblings, 0 replies; 2+ messages in thread
From: Dan Carpenter @ 2026-02-12 5:31 UTC (permalink / raw)
To: oe-kbuild, Ivan Gorinov, Jiri Kosina
Cc: lkp, oe-kbuild-all, linux-input, linux-kernel
Hi Ivan,
kernel test robot noticed the following build warnings:
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Ivan-Gorinov/HID-winwing-Enable-rumble-effects/20260211-133322
base: https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link: https://lore.kernel.org/r/20260211053116.GA20357%40altimeter-info
patch subject: [PATCH RESEND] HID: winwing: Enable rumble effects
config: parisc-randconfig-r071-20260211 (https://download.01.org/0day-ci/archive/20260212/202602120209.xYKh9QQp-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0
smatch version: v0.5.0-8994-gd50c5a4c
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202602120209.xYKh9QQp-lkp@intel.com/
smatch warnings:
drivers/hid/hid-winwing.c:235 winwing_haptic_rumble() warn: address of NULL pointer 'data->hdev'
drivers/hid/hid-winwing.c:308 winwing_haptic_rumble_cb() warn: can 'data' even be NULL?
drivers/hid/hid-winwing.c:339 winwing_init_ff() warn: variable dereferenced before check 'data' (see line 333)
vim +235 drivers/hid/hid-winwing.c
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 221 static int winwing_haptic_rumble(struct winwing_drv_data *data)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 222 {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 223 __u8 *buf;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 224 __u8 m;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 225
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 226 if (!data)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 227 return -EINVAL;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 228
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 229 buf = data->report_rumble;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 230
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 231 if (!buf)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 232 return -EINVAL;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 233
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 234 if (!data->hdev) {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 @235 hid_err(data->hdev, "data->hdev == NULL\n");
^^^^^^^^^^
This doesn't end up getting dereferenced because of dev_err() magic
but passing a NULL here is pointless.
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 236 return -EINVAL;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 237 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 238
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 239 if (!data->hdev->ll_driver) {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 240 hid_err(data->hdev, "data->hdev->ll_driver == NULL\n");
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 241 return -EINVAL;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 242 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 243
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 244 m = convert_magnitude(data->rumble.strong_magnitude);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 245 if (m != data->rumble_left) {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 246 int ret;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 247
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 248 buf[0] = 0x02;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 249 buf[1] = 0x01;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 250 buf[2] = 0xbf;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 251 buf[3] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 252 buf[4] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 253 buf[5] = 0x03;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 254 buf[6] = 0x49;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 255 buf[7] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 256 buf[8] = m;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 257 buf[9] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 258 buf[10] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 259 buf[11] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 260 buf[12] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 261 buf[13] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 262
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 263 ret = hid_hw_output_report(data->hdev, buf, 14);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 264 if (ret < 0) {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 265 hid_err(data->hdev, "error %d (%*ph)\n", ret, 14, buf);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 266 return ret;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 267 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 268 data->rumble_left = m;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 269 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 270
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 271 m = convert_magnitude(data->rumble.weak_magnitude);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 272 if (m != data->rumble_right) {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 273 int ret;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 274
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 275 buf[0] = 0x02;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 276 buf[1] = 0x03;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 277 buf[2] = 0xbf;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 278 buf[3] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 279 buf[4] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 280 buf[5] = 0x03;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 281 buf[6] = 0x49;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 282 buf[7] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 283 buf[8] = m;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 284 buf[9] = 0x00;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 285 buf[10] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 286 buf[11] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 287 buf[12] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 288 buf[13] = 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 289
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 290 ret = hid_hw_output_report(data->hdev, buf, 14);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 291 if (ret < 0) {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 292 hid_err(data->hdev, "error %d (%*ph)\n", ret, 14, buf);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 293 return ret;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 294 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 295 data->rumble_right = m;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 296 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 297
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 298 return 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 299 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 300
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 301
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 302 static void winwing_haptic_rumble_cb(struct work_struct *work)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 303 {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 304 struct winwing_drv_data *data;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 305
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 306 data = container_of(work, struct winwing_drv_data, rumble_work);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 307
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 @308 if (data)
"data" can't be NULL. It's work minus an offset.
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 309 winwing_haptic_rumble(data);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 310 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 311
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 312 static int winwing_play_effect(struct input_dev *dev, void *context,
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 313 struct ff_effect *effect)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 314 {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 315 struct winwing_drv_data *data = (struct winwing_drv_data *) context;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 316
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 317 if (effect->type != FF_RUMBLE)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 318 return 0;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 319
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 320 if (!data)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 321 return -EINVAL;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 322
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 323 data->rumble = effect->u.rumble;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 324
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 325 return schedule_work(&data->rumble_work);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 326 }
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 327
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 328 static int winwing_init_ff(struct hid_device *hdev, struct hid_input *hidinput)
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 329 {
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 330 struct winwing_drv_data *data;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 331
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 332 data = (struct winwing_drv_data *) hid_get_drvdata(hdev);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 @333 data->report_rumble = devm_kzalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 334 data->rumble_left = -1;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 335 data->rumble_right = -1;
^^^^^^^^^^^^^^^^^^
Dereferences here.
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 336
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 337 input_set_capability(hidinput->input, EV_FF, FF_RUMBLE);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 338
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 @339 if (!data)
^^^^^^
Checked too late.
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 340 return -EINVAL;
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 341
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 342 return input_ff_create_memless(hidinput->input, data,
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 343 winwing_play_effect);
c4c97b07cd09c03 Ivan Gorinov 2026-02-11 344 }
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-02-12 5:31 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-11 5:31 [PATCH RESEND] HID: winwing: Enable rumble effects Ivan Gorinov
2026-02-12 5:31 ` Dan Carpenter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox