summaryrefslogtreecommitdiff
path: root/hw/usb
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-03-19 23:04:10 +0100
committerPeter Wu <peter@lekensteyn.nl>2014-03-19 23:04:10 +0100
commitf169eef99246893b01faf088629d79336f37e605 (patch)
tree9fc20da4a31949022709cc33e9760a58ec2a39c9 /hw/usb
parentb6f142f7f999c8453a64dbe4cfa1ef5d843b56c7 (diff)
downloadqemu-f169eef99246893b01faf088629d79336f37e605.tar.gz
unifying: fix long reg read, implement reg b5 read
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'hw/usb')
-rw-r--r--hw/usb/hid-logitech-dj.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/hw/usb/hid-logitech-dj.c b/hw/usb/hid-logitech-dj.c
index 6290a1bb39..646b63745e 100644
--- a/hw/usb/hid-logitech-dj.c
+++ b/hw/usb/hid-logitech-dj.c
@@ -42,7 +42,7 @@ enum {
#define SET_REG(reg) (0x108000 | (reg))
#define GET_REG(reg) (0x108100 | (reg))
#define SET_LONG_REG(reg) (0x118200 | (reg))
-#define GET_LONG_REG(reg) (0x118300 | (reg))
+#define GET_LONG_REG(reg) (0x108300 | (reg))
/* returns the expected length of the report or 0 if invalid */
static unsigned msg_report_length(HidppMsg *msg)
@@ -128,11 +128,12 @@ static bool hidpp_process_receiver_report(USBLtunifyState *s, HidppMsg *msg)
{
LHidDevice *hd;
int i;
- uint8_t *parms = msg->dj_s.payload;
+ uint8_t *parms;
assert(msg->device_index == 0xFF);
if (msg->report_id == DJ_SHORT) {
+ parms = msg->dj_s.payload;
/* DJ reports */
switch (msg->dj_s.report_type) {
case 0x0E: /* Keyboard LEDs */
@@ -183,6 +184,7 @@ static bool hidpp_process_receiver_report(USBLtunifyState *s, HidppMsg *msg)
HidppMsgShort *ms = &msg->hidpp_s;
HidppMsgLong *ml = &msg->hidpp_l;
unsigned req = (ms->report_id << 16) | (ms->sub_id << 8) | ms->address;
+ parms = ml->value; /* NOTE: drops address */
switch (req) {
case GET_REG(0x00): /* Enable HID++ notifs */
@@ -227,6 +229,42 @@ static bool hidpp_process_receiver_report(USBLtunifyState *s, HidppMsg *msg)
}
hidpp_queue_output_report(s, msg);
break;
+ case GET_LONG_REG(0xB5): /* Pairing information */
+ if ((parms[0] >> 4) >= 2 && (parms[0] >> 4) <= 4 &&
+ hidpp_device_available(s, 1 + (parms[0] & 0xF))) {
+ LHidDevice *hd = &s->devices[parms[0] & 0xF];
+
+ ml->report_id = HIDPP_LONG;
+ memset(parms + 1, 0, sizeof(ml->value) - 1);
+ if (parms[0] & 0x20) {
+ /* Unifying Device pairing information */
+ parms[1] = 0x42; /* Destination ID (???) */
+ parms[2] = hd->report_interval;
+ parms[3] = (uint8_t) hd->info.wireless_pid;
+ parms[4] = (uint8_t) (hd->info.wireless_pid >> 8);
+ parms[7] = hd->info.device_type;
+ } else if (parms[0] & 0x30) {
+ /* Unifying Device extended pairing info */
+ parms[1] = (uint8_t) hd->info.serial;
+ parms[2] = (uint8_t) (hd->info.serial >> 8);
+ parms[3] = (uint8_t) (hd->info.serial >> 16);
+ parms[4] = (uint8_t) (hd->info.serial >> 24);
+ parms[5] = (uint8_t) hd->info.report_types;
+ parms[6] = (uint8_t) (hd->info.report_types >> 8);
+ parms[7] = (uint8_t) (hd->info.report_types >> 16);
+ parms[8] = (uint8_t) (hd->info.report_types >> 24);
+ parms[9] = hd->info.usability_info;
+ } else if (parms[0] & 0x40) {
+ /* Unifying Device name */
+ parms[1] = strlen(hd->info.name);
+ memcpy(parms + 2, hd->info.name, parms[1]);
+ }
+ hidpp_queue_output_report(s, msg);
+ } else {
+ /* invalid command or unavailable device */
+ hidpp_queue_error(s, msg, HIDPP_ERR_INVALID_VALUE);
+ }
+ break;
default:
/* unknown request, return error */
switch (req & ~0xFF) {
@@ -432,6 +470,7 @@ static void hidpp_init_device(USBLtunifyState *s, int device_index, int devtype)
hd->info.wireless_pid = 0x2010;
hd->info.serial = 0x4b657973;
memcpy(hd->info.name, "K800", 4);
+ hd->report_interval = 20;
break;
case DEVTYPE_MOUSE:
hd->hid = &s->hid[IFACE_MSE];
@@ -439,6 +478,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->report_interval = 8;
break;
case DEVTYPE_TOUCHPAD:
/* TODO: perhaps "unpair" mouse and use this touchpad instead? */
@@ -447,6 +487,7 @@ 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->report_interval = 8;
break;
}
hd->info.protocol_version = 0x0200; /* HID++ 2.0 */