hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/hid/hid-logitech-hidpp.c
....@@ -828,8 +828,7 @@
828828 if (ret)
829829 return ret;
830830
831
- snprintf(hdev->uniq, sizeof(hdev->uniq), "%04x-%4phD",
832
- hdev->product, &serial);
831
+ snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
833832 dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq);
834833
835834 name = hidpp_unifying_get_name(hidpp);
....@@ -919,6 +918,54 @@
919918 print_version:
920919 hid_info(hidpp->hid_dev, "HID++ %u.%u device connected.\n",
921920 hidpp->protocol_major, hidpp->protocol_minor);
921
+ return 0;
922
+}
923
+
924
+/* -------------------------------------------------------------------------- */
925
+/* 0x0003: Device Information */
926
+/* -------------------------------------------------------------------------- */
927
+
928
+#define HIDPP_PAGE_DEVICE_INFORMATION 0x0003
929
+
930
+#define CMD_GET_DEVICE_INFO 0x00
931
+
932
+static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial)
933
+{
934
+ struct hidpp_report response;
935
+ u8 feature_type;
936
+ u8 feature_index;
937
+ int ret;
938
+
939
+ ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_DEVICE_INFORMATION,
940
+ &feature_index,
941
+ &feature_type);
942
+ if (ret)
943
+ return ret;
944
+
945
+ ret = hidpp_send_fap_command_sync(hidpp, feature_index,
946
+ CMD_GET_DEVICE_INFO,
947
+ NULL, 0, &response);
948
+ if (ret)
949
+ return ret;
950
+
951
+ /* See hidpp_unifying_get_serial() */
952
+ *serial = *((u32 *)&response.rap.params[1]);
953
+ return 0;
954
+}
955
+
956
+static int hidpp_serial_init(struct hidpp_device *hidpp)
957
+{
958
+ struct hid_device *hdev = hidpp->hid_dev;
959
+ u32 serial;
960
+ int ret;
961
+
962
+ ret = hidpp_get_serial(hidpp, &serial);
963
+ if (ret)
964
+ return ret;
965
+
966
+ snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
967
+ dbg_hid("HID++ DeviceInformation: Got serial: %s\n", hdev->uniq);
968
+
922969 return 0;
923970 }
924971
....@@ -3763,6 +3810,7 @@
37633810 bool connected;
37643811 unsigned int connect_mask = HID_CONNECT_DEFAULT;
37653812 struct hidpp_ff_private_data data;
3813
+ bool will_restart = false;
37663814
37673815 /* report_fixup needs drvdata to be set before we call hid_parse */
37683816 hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL);
....@@ -3818,6 +3866,10 @@
38183866 return ret;
38193867 }
38203868
3869
+ if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT ||
3870
+ hidpp->quirks & HIDPP_QUIRK_UNIFYING)
3871
+ will_restart = true;
3872
+
38213873 INIT_WORK(&hidpp->work, delayed_work_cb);
38223874 mutex_init(&hidpp->send_mutex);
38233875 init_waitqueue_head(&hidpp->wait);
....@@ -3832,7 +3884,7 @@
38323884 * Plain USB connections need to actually call start and open
38333885 * on the transport driver to allow incoming data.
38343886 */
3835
- ret = hid_hw_start(hdev, 0);
3887
+ ret = hid_hw_start(hdev, will_restart ? 0 : connect_mask);
38363888 if (ret) {
38373889 hid_err(hdev, "hw start failed\n");
38383890 goto hid_hw_start_fail;
....@@ -3850,6 +3902,8 @@
38503902
38513903 if (hidpp->quirks & HIDPP_QUIRK_UNIFYING)
38523904 hidpp_unifying_init(hidpp);
3905
+ else if (hid_is_usb(hidpp->hid_dev))
3906
+ hidpp_serial_init(hidpp);
38533907
38543908 connected = hidpp_root_get_protocol_version(hidpp) == 0;
38553909 atomic_set(&hidpp->connected, connected);
....@@ -3869,6 +3923,7 @@
38693923 hidpp->wireless_feature_index = 0;
38703924 else if (ret)
38713925 goto hid_hw_init_fail;
3926
+ ret = 0;
38723927 }
38733928
38743929 if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
....@@ -3883,19 +3938,21 @@
38833938
38843939 hidpp_connect_event(hidpp);
38853940
3886
- /* Reset the HID node state */
3887
- hid_device_io_stop(hdev);
3888
- hid_hw_close(hdev);
3889
- hid_hw_stop(hdev);
3941
+ if (will_restart) {
3942
+ /* Reset the HID node state */
3943
+ hid_device_io_stop(hdev);
3944
+ hid_hw_close(hdev);
3945
+ hid_hw_stop(hdev);
38903946
3891
- if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
3892
- connect_mask &= ~HID_CONNECT_HIDINPUT;
3947
+ if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
3948
+ connect_mask &= ~HID_CONNECT_HIDINPUT;
38933949
3894
- /* Now export the actual inputs and hidraw nodes to the world */
3895
- ret = hid_hw_start(hdev, connect_mask);
3896
- if (ret) {
3897
- hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
3898
- goto hid_hw_start_fail;
3950
+ /* Now export the actual inputs and hidraw nodes to the world */
3951
+ ret = hid_hw_start(hdev, connect_mask);
3952
+ if (ret) {
3953
+ hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
3954
+ goto hid_hw_start_fail;
3955
+ }
38993956 }
39003957
39013958 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
....@@ -3952,7 +4009,7 @@
39524009 { /* wireless touchpad T651 */
39534010 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
39544011 USB_DEVICE_ID_LOGITECH_T651),
3955
- .driver_data = HIDPP_QUIRK_CLASS_WTP },
4012
+ .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT },
39564013 { /* Mouse Logitech Anywhere MX */
39574014 LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
39584015 { /* Mouse Logitech Cube */