diff mbox series

[19/28] HID: logitech-hidpp: create a name based on the type if non available

Message ID 20190330112418.15042-20-hdegoede@redhat.com (mailing list archive)
State Superseded
Delegated to: Jiri Kosina
Headers show
Series HID: logitech: Handling of non DJ receivers in hid-logitech-dj | expand

Commit Message

Hans de Goede March 30, 2019, 11:24 a.m. UTC
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Some low cost devices don't even have a name (nor a serial) registered
in the receiver. In those case, create a better name that "Logitech
USB Receiver" or even "Logitech  " if we try to get their name.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/hid-logitech-hidpp.c | 55 ++++++++++++++++++++++++++++++--
 1 file changed, 52 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index b950a44157a2..887af6068985 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -717,9 +717,28 @@  static int hidpp10_battery_event(struct hidpp_device *hidpp, u8 *data, int size)
 }
 
 #define HIDPP_REG_PAIRING_INFORMATION			0xB5
+#define HIDPP_PAIRING_INFORMATION			0x20
 #define HIDPP_EXTENDED_PAIRING				0x30
 #define HIDPP_DEVICE_NAME				0x40
 
+static int hidpp_unifying_get_type(struct hidpp_device *hidpp_dev)
+{
+	struct hidpp_report response;
+	int ret;
+	u8 params[1] = { HIDPP_PAIRING_INFORMATION };
+
+	ret = hidpp_send_rap_command_sync(hidpp_dev,
+					  REPORT_ID_HIDPP_SHORT,
+					  HIDPP_GET_LONG_REGISTER,
+					  HIDPP_REG_PAIRING_INFORMATION,
+					  params, 1, &response);
+	if (ret)
+		return ret;
+
+	return response.rap.params[7];
+
+}
+
 static char *hidpp_unifying_get_name(struct hidpp_device *hidpp_dev)
 {
 	struct hidpp_report response;
@@ -741,6 +760,9 @@  static char *hidpp_unifying_get_name(struct hidpp_device *hidpp_dev)
 	if (2 + len > sizeof(response.rap.params))
 		return NULL;
 
+	if (len < 4) /* logitech devices are usually at least Xddd */
+		return 0;
+
 	name = kzalloc(len + 1, GFP_KERNEL);
 	if (!name)
 		return NULL;
@@ -778,7 +800,7 @@  static int hidpp_unifying_get_serial(struct hidpp_device *hidpp, u32 *serial)
 static int hidpp_unifying_init(struct hidpp_device *hidpp)
 {
 	struct hid_device *hdev = hidpp->hid_dev;
-	const char *name;
+	const char *name = NULL;
 	u32 serial;
 	int ret;
 
@@ -791,8 +813,35 @@  static int hidpp_unifying_init(struct hidpp_device *hidpp)
 	dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq);
 
 	name = hidpp_unifying_get_name(hidpp);
-	if (!name)
-		return -EIO;
+	if (!name) {
+		ret = hidpp_unifying_get_type(hidpp);
+		if (ret < 0)
+			return ret;
+
+		switch (ret) {
+		case 0x01:
+			name = "Logitech Wireless Keyboard";
+			break;
+		case 0x02:
+			name = "Logitech Wireless Mouse";
+			break;
+		case 0x03:
+			name = "Logitech Wireless Numpad";
+			break;
+		case 0x04:
+			name = "Logitech Wireless Presenter";
+			break;
+		case 0x08:
+			name = "Logitech Wireless Trackball";
+			break;
+		case 0x09:
+			name = "Logitech Wireless Touchpad";
+			break;
+		}
+		if (name)
+			snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+		return 0;
+	}
 
 	snprintf(hdev->name, sizeof(hdev->name), "%s", name);
 	dbg_hid("HID++ Unifying: Got name: %s\n", name);