summaryrefslogtreecommitdiff
path: root/hw/usb
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-03-24 12:35:26 +0100
committerPeter Wu <peter@lekensteyn.nl>2014-03-24 12:35:26 +0100
commit4215730f0ac21c625effe50ba14fbf050dc991a8 (patch)
treec0c44b81ce2acdd4f7197243293febf3cfdb6acf /hw/usb
parent7249fb7b3ac3e05b604228314a48ad5703506c1d (diff)
downloadqemu-4215730f0ac21c625effe50ba14fbf050dc991a8.tar.gz
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 <peter@lekensteyn.nl>
Diffstat (limited to 'hw/usb')
-rw-r--r--hw/usb/hid-logitech-dj.c10
-rw-r--r--hw/usb/hid-logitech-dj.h3
-rw-r--r--hw/usb/hid-logitech-hidpp20.c41
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) {