From 4215730f0ac21c625effe50ba14fbf050dc991a8 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Mon, 24 Mar 2014 12:35:26 +0100 Subject: unifying: impl HID++ 2.0 DeviceName, adjust device info Set K800 to use HID++ 1.0; add a device_name field to store long device names for HID++ 2.0 devices. The device types constants are slightly different between HID++ 1.0 and HID++ 2.0, two constants are not implemented (and those will probably never be implemented). Signed-off-by: Peter Wu --- hw/usb/hid-logitech-dj.c | 10 ++++++++-- hw/usb/hid-logitech-dj.h | 3 ++- hw/usb/hid-logitech-hidpp20.c | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/hw/usb/hid-logitech-dj.c b/hw/usb/hid-logitech-dj.c index 196b430c43..59bdc7f65c 100644 --- a/hw/usb/hid-logitech-dj.c +++ b/hw/usb/hid-logitech-dj.c @@ -583,13 +583,16 @@ static void hidpp_init_device(USBLtunifyState *s, int device_index, int devtype) hd->info.device_type = devtype; hd->info.protocol_type = PROTO_UNIFYING; + hd->info.protocol_version = 0x0200; /* HID++ 2.0 */ switch (devtype) { case DEVTYPE_KEYBOARD: + hd->info.protocol_version = 0x0100; /* override: HID++ 1.0 */ hd->hid = &s->hid[IFACE_KBD]; hd->info.report_types = 0x1a; /* Keyboard, Consumer Control, System Control */ hd->info.wireless_pid = 0x2010; hd->info.serial = 0x4b657973; memcpy(hd->info.name, "K800", 4); + /* hd->info.device_name N/A for HID++ 1.0 */ hd->report_interval = 20; break; case DEVTYPE_MOUSE: @@ -598,6 +601,7 @@ static void hidpp_init_device(USBLtunifyState *s, int device_index, int devtype) hd->info.wireless_pid = 0x4013; hd->info.serial = 0x52617473; memcpy(hd->info.name, "M525", 4); + hd->info.device_name = "WirelessMouse M525"; hd->report_interval = 8; break; case DEVTYPE_TOUCHPAD: @@ -607,11 +611,13 @@ static void hidpp_init_device(USBLtunifyState *s, int device_index, int devtype) hd->info.wireless_pid = 0x4026; hd->info.serial = 0x4f4f4f48; memcpy(hd->info.name, "T650", 4); + hd->info.device_name = "Rechargeable Touchpad T650"; hd->report_interval = 8; break; } - hidpp20_init_features(hd); - hd->info.protocol_version = 0x0200; /* HID++ 2.0 */ + if (hd->info.protocol_version >= 0x0200) { + hidpp20_init_features(hd); + } hd->mode = LTUNIFY_MODE_HID; hd->powered_on = true; } diff --git a/hw/usb/hid-logitech-dj.h b/hw/usb/hid-logitech-dj.h index 3e7fab9fa1..6a29b6639e 100644 --- a/hw/usb/hid-logitech-dj.h +++ b/hw/usb/hid-logitech-dj.h @@ -193,7 +193,8 @@ typedef struct { uint16_t protocol_version; /* HID++ protocol version */ uint16_t wireless_pid; uint32_t serial; - char name[15]; + char name[15]; /* short name for receiver */ + const char *device_name; /* long device name for HID++ 2.0 */ uint8_t usability_info; /* bits 0..3 power switch location */ uint32_t report_types; /* supported report types (e.g. mouse) */ diff --git a/hw/usb/hid-logitech-hidpp20.c b/hw/usb/hid-logitech-hidpp20.c index eb15ab1c96..3c664cc089 100644 --- a/hw/usb/hid-logitech-hidpp20.c +++ b/hw/usb/hid-logitech-hidpp20.c @@ -146,10 +146,51 @@ static HIDPP20_FEATURE(feat_devicefwversion) } } +/* returns the HID++ 2.0 Device Type constant for a device */ +static uint8_t hidpp20_get_device_type(LHidDevice *hd) +{ + static const uint8_t device_types_map[0x10] = { + [DEVTYPE_KEYBOARD] = 0, + [DEVTYPE_MOUSE] = 3, + [DEVTYPE_NUMPAD] = 2, + [DEVTYPE_PRESENTER] = 6, + [DEVTYPE_TRACKBALL] = 5, + [DEVTYPE_TOUCHPAD] = 4, + // Not handled: RemoteControl (1) Receiver (7) + }; + + assert(hd->info.device_type < ARRAY_SIZE(device_types_map)); + return device_types_map[hd->info.device_type]; +} + +static HIDPP20_FEATURE(feat_devicename) +{ + switch (fn) { + case 0: /* nameLength = GetCount() */ + params[0] = strlen(hd->info.device_name); + return 1; + case 1: /* DeviceName = GetDeviceName(CharIndex) */ + if (params[0] > strlen(hd->info.device_name)) { + return -HIDPP20_ERR_CODE_OUTOFRANGE; + } + const char *name = hd->info.device_name + params[0]; + /* always include trailing 0 such that the param len > 0 (non-void) */ + unsigned len = MIN(sizeof(msg->params), strlen(name) + 1); + memcpy(params, name, len); + return len; + case 2: /* DeviceType, deviceInterface(s) = GetDeviceType() */ + params[0] = hidpp20_get_device_type(hd); + return 1; + default: + return -HIDPP20_ERR_CODE_INVALID_FUNCTION_ID; + } +} + /* root feature not included! */ static const HidppFeature features_m525[] = { { 0x0001, 0, feat_featureset }, { 0x0003, 0, feat_devicefwversion }, + { 0x0005, 0, feat_devicename }, }; void hidpp20_init_features(LHidDevice *hd) { -- cgit v1.2.1