summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/usb/hid-logitech-dj.c44
-rw-r--r--hw/usb/hid-logitech-dj.h31
2 files changed, 67 insertions, 8 deletions
diff --git a/hw/usb/hid-logitech-dj.c b/hw/usb/hid-logitech-dj.c
index a035bc533d..caa0383bc9 100644
--- a/hw/usb/hid-logitech-dj.c
+++ b/hw/usb/hid-logitech-dj.c
@@ -379,14 +379,56 @@ static void hidpp_process_device_hidpp10(USBLtunifyState *s, HidppMsg *msg)
}
}
+
+/* HID++ 2.0 */
+static void hidpp20_queue_error(USBLtunifyState *s, Hidpp20Msg *func, uint8_t err)
+{
+ Hidpp20Msg error_report = {
+ .report_id = func->report_id,
+ .device_index = func->device_index,
+ .feat_index = 0xFF,
+ .func = func->func,
+ .params = { err }
+ };
+
+ hidpp_queue_output_report(s, (HidppMsg *) &error_report);
+}
+
+/* called for HID++ 2.0 reports targeted at devices */
+static void hidpp_process_device_hidpp20(USBLtunifyState *s, HidppMsg *msg)
+{
+ LHidDevice *hd = &s->devices[msg->device_index - 1];
+ Hidpp20Msg *func = (Hidpp20Msg *) msg;
+ uint8_t fn = func->func >> 4;
+
+ if (func->feat_index == 0) { /* IRoot */
+ if (fn == 1) { /* GetProtocolVersion */
+ func->params_s[0] = (uint8_t) (hd->info.protocol_version >> 8);
+ func->params_s[1] = (uint8_t) hd->info.protocol_version;
+ hidpp_queue_output_report(s, msg);
+ } else {
+ hidpp20_queue_error(s, func, HIDPP20_ERR_CODE_INVALID_FUNCTION_ID);
+ }
+ return;
+ }
+ /* TODO: implement features and more functions */
+}
+
+
static void hidpp_process_input_report(USBLtunifyState *s, HidppMsg msg)
{
/* receiver reports are processed earlier, elsewhere */
assert(msg.device_index != 0xFF);
if (hidpp_device_available(s, msg.device_index)) {
+ LHidDevice *hd = &s->devices[msg.device_index - 1];
+
if (msg.report_id == HIDPP_SHORT || msg.report_id == HIDPP_LONG) {
- hidpp_process_device_hidpp10(s, &msg);
+ if (hd->info.protocol_version >= 0x0200) {
+ hidpp_process_device_hidpp20(s, &msg);
+ } else {
+ hidpp_process_device_hidpp10(s, &msg);
+ }
}
} else {
hidpp_queue_error(s, &msg, HIDPP_ERR_RESOURCE_ERROR);
diff --git a/hw/usb/hid-logitech-dj.h b/hw/usb/hid-logitech-dj.h
index 04a31c95a3..6a2ca18413 100644
--- a/hw/usb/hid-logitech-dj.h
+++ b/hw/usb/hid-logitech-dj.h
@@ -73,6 +73,18 @@ typedef struct {
typedef struct {
uint8_t report_id;
+ const uint8_t device_index;
+ const uint8_t feat_index;
+ const uint8_t func; /* function/ASE ID | sw ID */
+ union {
+ uint8_t params[16];
+ uint8_t params_s[3];
+ };
+} Hidpp20Msg;
+
+
+typedef struct {
+ uint8_t report_id;
uint8_t device_index;
uint8_t report_type;
uint8_t payload[12];
@@ -99,11 +111,7 @@ typedef struct {
};
} HidppMsg;
-/* information to generate an error output report */
-typedef struct {
- uint8_t device_index;
- uint8_t sub_id;
- uint8_t address;
+/* HID++ 1.0 error codes */
#define HIDPP_ERR_SUCCESS 0x00
#define HIDPP_ERR_INVALID_SUBID 0x01
#define HIDPP_ERR_INVALID_ADDRESS 0x02
@@ -117,8 +125,17 @@ typedef struct {
#define HIDPP_ERR_REQUEST_UNAVAILABLE 0x0A
#define HIDPP_ERR_INVALID_PARAM_VALUE 0x0B
#define HIDPP_ERR_WRONG_PIN_CODE 0x0C
- uint8_t error;
-} HidppError;
+/* HID++ 2.0 error codes */
+#define HIDPP20_ERR_CODE_NOERROR 0x00
+#define HIDPP20_ERR_CODE_UNKNOWN 0x01
+#define HIDPP20_ERR_CODE_INVALIDARGUMENT 0x02
+#define HIDPP20_ERR_CODE_OUTOFRANGE 0x03
+#define HIDPP20_ERR_CODE_HWERROR 0x04
+#define HIDPP20_ERR_CODE_LOGITECH_INTERNAL 0x05
+#define HIDPP20_ERR_CODE_INVALID_FEATURE_INDEX 0x06
+#define HIDPP20_ERR_CODE_INVALID_FUNCTION_ID 0x07
+#define HIDPP20_ERR_CODE_BUSY 0x08
+#define HIDPP20_ERR_CODE_UNSUPPORTED 0x09
/* device and receiver info */