Skip to content

Commit 7ad1fe0

Browse files
hadessbentiss
authored andcommitted
HID: logitech-hidpp: Don't use the USB serial for USB devices
For devices that support the 0x0003 feature (Device Information) version 4, set the serial based on the output of that feature, rather than relying on the usbhid code setting the USB serial. This should allow the serial when connected through USB to (nearly) match the one when connected through a unifying receiver. For example, on the serials on a G903 wired/wireless mouse: - Unifying: 4067-e8-ce-cd-45 - USB before patch: 017C385C3837 - USB after patch: c086-e8-ce-cd-45 Signed-off-by: Bastien Nocera <hadess@hadess.net> Link: https://lore.kernel.org/r/20230302130117.3975-1-hadess@hadess.net Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
1 parent 2653e3f commit 7ad1fe0

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

drivers/hid/hid-logitech-hidpp.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,55 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp)
947947
return 0;
948948
}
949949

950+
/* -------------------------------------------------------------------------- */
951+
/* 0x0003: Device Information */
952+
/* -------------------------------------------------------------------------- */
953+
954+
#define HIDPP_PAGE_DEVICE_INFORMATION 0x0003
955+
956+
#define CMD_GET_DEVICE_INFO 0x00
957+
958+
static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial)
959+
{
960+
struct hidpp_report response;
961+
u8 feature_type;
962+
u8 feature_index;
963+
int ret;
964+
965+
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_DEVICE_INFORMATION,
966+
&feature_index,
967+
&feature_type);
968+
if (ret)
969+
return ret;
970+
971+
ret = hidpp_send_fap_command_sync(hidpp, feature_index,
972+
CMD_GET_DEVICE_INFO,
973+
NULL, 0, &response);
974+
if (ret)
975+
return ret;
976+
977+
/* See hidpp_unifying_get_serial() */
978+
*serial = *((u32 *)&response.rap.params[1]);
979+
return 0;
980+
}
981+
982+
static int hidpp_serial_init(struct hidpp_device *hidpp)
983+
{
984+
struct hid_device *hdev = hidpp->hid_dev;
985+
u32 serial;
986+
int ret;
987+
988+
ret = hidpp_get_serial(hidpp, &serial);
989+
if (ret)
990+
return ret;
991+
992+
snprintf(hdev->uniq, sizeof(hdev->uniq), "%04x-%4phD",
993+
hdev->product, &serial);
994+
dbg_hid("HID++ DeviceInformation: Got serial: %s\n", hdev->uniq);
995+
996+
return 0;
997+
}
998+
950999
/* -------------------------------------------------------------------------- */
9511000
/* 0x0005: GetDeviceNameType */
9521001
/* -------------------------------------------------------------------------- */
@@ -4210,6 +4259,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
42104259

42114260
if (hidpp->quirks & HIDPP_QUIRK_UNIFYING)
42124261
hidpp_unifying_init(hidpp);
4262+
else if (hid_is_usb(hidpp->hid_dev))
4263+
hidpp_serial_init(hidpp);
42134264

42144265
connected = hidpp_root_get_protocol_version(hidpp) == 0;
42154266
atomic_set(&hidpp->connected, connected);

0 commit comments

Comments
 (0)