Skip to content

Commit 4ea4ed2

Browse files
committed
Merge tag 'for-linus-2023110101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - fixes for crashes detected by CONFIG_KUNIT_ALL_TESTS in hid-uclogic driver (Jinjie Ruan) - HID selftests fixes and improvements (Benjamin Tissoires) - probe error handling path fixes in hid-nvidia-shield driver (Christophe JAILLET) - cleanup of LED handling in hid-nintendo (Martino Fontana) - big cleanup of logitech-hidpp probe code (Hans de Goede) - Suspend/Resume fix for USB Thinkpad Compact Keyboard (Jamie Lentin) - firmware detection improvement for Lenovo cptkbd (Mikhail Khvainitski) - IRQ shutdown and workqueue initialization fixes for hid-cp2112 driver (Danny Kaehn) - #ifdef CONFIG_PM removal from HID code (Thomas Weißschuh) - other assorted device-ID additions and quirks * tag 'for-linus-2023110101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (31 commits) HID: Add quirk for Dell Pro Wireless Keyboard and Mouse KM5221W HID: logitech-hidpp: Stop IO before calling hid_connect() HID: logitech-hidpp: Drop HIDPP_QUIRK_UNIFYING HID: logitech-hidpp: Drop delayed_work_cb() HID: logitech-hidpp: Fix connect event race HID: logitech-hidpp: Remove unused connected param from *_connect() HID: logitech-hidpp: Remove connected check for non-unifying devices HID: logitech-hidpp: Add hidpp_non_unifying_init() helper HID: logitech-hidpp: Move hidpp_overwrite_name() to before connect check HID: logitech-hidpp: Move g920_get_config() to just before hidpp_ff_init() HID: logitech-hidpp: Remove wtp_get_config() call from probe() HID: logitech-hidpp: Move get_wireless_feature_index() check to hidpp_connect_event() HID: logitech-hidpp: Revert "Don't restart communication if not necessary" HID: logitech-hidpp: Don't restart IO, instead defer hid_connect() only HID: rmi: remove #ifdef CONFIG_PM HID: multitouch: remove #ifdef CONFIG_PM HID: usbhid: remove #ifdef CONFIG_PM HID: core: remove #ifdef CONFIG_PM from hid_driver hid: lenovo: Resend all settings on reset_resume for compact keyboards HID: uclogic: Fix a work->entry not empty bug in __queue_work() ...
2 parents 27beb3c + 1372e73 commit 4ea4ed2

File tree

16 files changed

+352
-254
lines changed

16 files changed

+352
-254
lines changed

drivers/hid/hid-cp2112.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,8 +1151,6 @@ static unsigned int cp2112_gpio_irq_startup(struct irq_data *d)
11511151
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
11521152
struct cp2112_device *dev = gpiochip_get_data(gc);
11531153

1154-
INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
1155-
11561154
if (!dev->gpio_poll) {
11571155
dev->gpio_poll = true;
11581156
schedule_delayed_work(&dev->gpio_poll_worker, 0);
@@ -1168,7 +1166,11 @@ static void cp2112_gpio_irq_shutdown(struct irq_data *d)
11681166
struct cp2112_device *dev = gpiochip_get_data(gc);
11691167

11701168
cp2112_gpio_irq_mask(d);
1171-
cancel_delayed_work_sync(&dev->gpio_poll_worker);
1169+
1170+
if (!dev->irq_mask) {
1171+
dev->gpio_poll = false;
1172+
cancel_delayed_work_sync(&dev->gpio_poll_worker);
1173+
}
11721174
}
11731175

11741176
static int cp2112_gpio_irq_type(struct irq_data *d, unsigned int type)
@@ -1307,6 +1309,8 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
13071309
girq->handler = handle_simple_irq;
13081310
girq->threaded = true;
13091311

1312+
INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
1313+
13101314
ret = gpiochip_add_data(&dev->gc, dev);
13111315
if (ret < 0) {
13121316
hid_err(hdev, "error registering gpio chip\n");

drivers/hid/hid-ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@
366366

367367
#define USB_VENDOR_ID_DELL 0x413c
368368
#define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE 0x301a
369+
#define USB_DEVICE_ID_DELL_PRO_WIRELESS_KM5221W 0x4503
369370

370371
#define USB_VENDOR_ID_DELORME 0x1163
371372
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100

drivers/hid/hid-lenovo.c

Lines changed: 79 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@ struct lenovo_drvdata {
5151
int select_right;
5252
int sensitivity;
5353
int press_speed;
54-
u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
54+
/* 0: Up
55+
* 1: Down (undecided)
56+
* 2: Scrolling
57+
* 3: Patched firmware, disable workaround
58+
*/
59+
u8 middlebutton_state;
5560
bool fn_lock;
5661
};
5762

@@ -521,6 +526,19 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev)
521526
int ret;
522527
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
523528

529+
/*
530+
* Tell the keyboard a driver understands it, and turn F7, F9, F11 into
531+
* regular keys
532+
*/
533+
ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
534+
if (ret)
535+
hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
536+
537+
/* Switch middle button to native mode */
538+
ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
539+
if (ret)
540+
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
541+
524542
ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
525543
if (ret)
526544
hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
@@ -668,31 +686,48 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
668686
{
669687
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
670688

671-
/* "wheel" scroll events */
672-
if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
673-
usage->code == REL_HWHEEL)) {
674-
/* Scroll events disable middle-click event */
675-
cptkbd_data->middlebutton_state = 2;
676-
return 0;
677-
}
689+
if (cptkbd_data->middlebutton_state != 3) {
690+
/* REL_X and REL_Y events during middle button pressed
691+
* are only possible on patched, bug-free firmware
692+
* so set middlebutton_state to 3
693+
* to never apply workaround anymore
694+
*/
695+
if (cptkbd_data->middlebutton_state == 1 &&
696+
usage->type == EV_REL &&
697+
(usage->code == REL_X || usage->code == REL_Y)) {
698+
cptkbd_data->middlebutton_state = 3;
699+
/* send middle button press which was hold before */
700+
input_event(field->hidinput->input,
701+
EV_KEY, BTN_MIDDLE, 1);
702+
input_sync(field->hidinput->input);
703+
}
704+
705+
/* "wheel" scroll events */
706+
if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
707+
usage->code == REL_HWHEEL)) {
708+
/* Scroll events disable middle-click event */
709+
cptkbd_data->middlebutton_state = 2;
710+
return 0;
711+
}
678712

679-
/* Middle click events */
680-
if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
681-
if (value == 1) {
682-
cptkbd_data->middlebutton_state = 1;
683-
} else if (value == 0) {
684-
if (cptkbd_data->middlebutton_state == 1) {
685-
/* No scrolling inbetween, send middle-click */
686-
input_event(field->hidinput->input,
687-
EV_KEY, BTN_MIDDLE, 1);
688-
input_sync(field->hidinput->input);
689-
input_event(field->hidinput->input,
690-
EV_KEY, BTN_MIDDLE, 0);
691-
input_sync(field->hidinput->input);
713+
/* Middle click events */
714+
if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
715+
if (value == 1) {
716+
cptkbd_data->middlebutton_state = 1;
717+
} else if (value == 0) {
718+
if (cptkbd_data->middlebutton_state == 1) {
719+
/* No scrolling inbetween, send middle-click */
720+
input_event(field->hidinput->input,
721+
EV_KEY, BTN_MIDDLE, 1);
722+
input_sync(field->hidinput->input);
723+
input_event(field->hidinput->input,
724+
EV_KEY, BTN_MIDDLE, 0);
725+
input_sync(field->hidinput->input);
726+
}
727+
cptkbd_data->middlebutton_state = 0;
692728
}
693-
cptkbd_data->middlebutton_state = 0;
729+
return 1;
694730
}
695-
return 1;
696731
}
697732

698733
if (usage->type == EV_KEY && usage->code == KEY_FN_ESC && value == 1) {
@@ -1126,22 +1161,6 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
11261161
}
11271162
hid_set_drvdata(hdev, cptkbd_data);
11281163

1129-
/*
1130-
* Tell the keyboard a driver understands it, and turn F7, F9, F11 into
1131-
* regular keys (Compact only)
1132-
*/
1133-
if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD ||
1134-
hdev->product == USB_DEVICE_ID_LENOVO_CBTKBD) {
1135-
ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
1136-
if (ret)
1137-
hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
1138-
}
1139-
1140-
/* Switch middle button to native mode */
1141-
ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
1142-
if (ret)
1143-
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
1144-
11451164
/* Set keyboard settings to known state */
11461165
cptkbd_data->middlebutton_state = 0;
11471166
cptkbd_data->fn_lock = true;
@@ -1264,6 +1283,24 @@ static int lenovo_probe(struct hid_device *hdev,
12641283
return ret;
12651284
}
12661285

1286+
#ifdef CONFIG_PM
1287+
static int lenovo_reset_resume(struct hid_device *hdev)
1288+
{
1289+
switch (hdev->product) {
1290+
case USB_DEVICE_ID_LENOVO_CUSBKBD:
1291+
case USB_DEVICE_ID_LENOVO_TPIIUSBKBD:
1292+
if (hdev->type == HID_TYPE_USBMOUSE)
1293+
lenovo_features_set_cptkbd(hdev);
1294+
1295+
break;
1296+
default:
1297+
break;
1298+
}
1299+
1300+
return 0;
1301+
}
1302+
#endif
1303+
12671304
static void lenovo_remove_tpkbd(struct hid_device *hdev)
12681305
{
12691306
struct lenovo_drvdata *data_pointer = hid_get_drvdata(hdev);
@@ -1380,6 +1417,9 @@ static struct hid_driver lenovo_driver = {
13801417
.raw_event = lenovo_raw_event,
13811418
.event = lenovo_event,
13821419
.report_fixup = lenovo_report_fixup,
1420+
#ifdef CONFIG_PM
1421+
.reset_resume = lenovo_reset_resume,
1422+
#endif
13831423
};
13841424
module_hid_driver(lenovo_driver);
13851425

0 commit comments

Comments
 (0)