From f169eef99246893b01faf088629d79336f37e605 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 19 Mar 2014 23:04:10 +0100 Subject: unifying: fix long reg read, implement reg b5 read Signed-off-by: Peter Wu --- hw/usb/hid-logitech-dj.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file 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 */ -- cgit v1.2.1