summaryrefslogtreecommitdiff
path: root/hw/usb/hid-logitech-dj.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/hid-logitech-dj.c')
-rw-r--r--hw/usb/hid-logitech-dj.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/hw/usb/hid-logitech-dj.c b/hw/usb/hid-logitech-dj.c
index 77e7f20202..dddc5027f4 100644
--- a/hw/usb/hid-logitech-dj.c
+++ b/hw/usb/hid-logitech-dj.c
@@ -38,6 +38,12 @@ enum {
DJ_LONG = 0x21, /* 32 bytes */
};
+/* helpers to handle the HID++ register queries */
+#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))
+
/* returns the expected length of the report or 0 if invalid */
static unsigned msg_report_length(HidppMsg *msg)
{
@@ -149,7 +155,46 @@ static bool hidpp_process_receiver_report(USBLtunifyState *s, HidppMsg *msg)
hidpp_queue_error(s, msg, HIDPP_ERR_INVALID_SUBID);
}
} else if (msg->report_id == HIDPP_SHORT || msg->report_id == HIDPP_LONG) {
- /* TODO: handle requests */
+ LHidReceiver *rcvr = &s->receiver;
+ HidppMsgShort *ms = &msg->hidpp_s;
+ unsigned req = (ms->report_id << 16) | (ms->sub_id << 8) | ms->address;
+
+ switch (req) {
+ case GET_REG(0x00): /* Enable HID++ notifs */
+ ms->value[0] = ms->value[2] = 0;
+ ms->value[1] = rcvr->reporting_flags;
+ hidpp_queue_output_report(s, msg);
+ break;
+ case SET_REG(0x00): /* Enable HID++ notifs */
+ rcvr->reporting_flags = ms->value[1];
+ rcvr->reporting_flags &= REPORTING_FLAG_RECV_MASK;
+ memset(ms->value, 0, 3);
+ hidpp_queue_output_report(s, msg);
+ break;
+ case GET_REG(0x02): /* Connection State */
+ memset(ms->value, 0, 3);
+ for (i = 0; i < MAX_DEVICES; i++) {
+ if (s->devices[i].info.device_type) {
+ ms->value[1]++;
+ }
+ }
+ hidpp_queue_output_report(s, msg);
+ break;
+ default:
+ /* unknown request, return error */
+ switch (req & ~0xFF) {
+ case SET_REG(0):
+ case GET_REG(0):
+ case SET_LONG_REG(0):
+ case GET_LONG_REG(0):
+ /* register request unsatisfied */
+ hidpp_queue_error(s, msg, HIDPP_ERR_INVALID_ADDRESS);
+ break;
+ default:
+ /* invalid report ID and command SubID combination */
+ hidpp_queue_error(s, msg, HIDPP_ERR_INVALID_SUBID);
+ }
+ }
} else {
/* DJ_LONG is unhandled */
return false;