summaryrefslogtreecommitdiff
path: root/hw/usb/hid-logitech-dj.h
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-03-18 21:21:51 +0100
committerPeter Wu <peter@lekensteyn.nl>2014-03-18 21:21:51 +0100
commit3a5922cc11f73269bfcd762997efc2c029a3b585 (patch)
tree04f129f72b655e1976b0a9456a17b4f93fe9fe7c /hw/usb/hid-logitech-dj.h
parent0bb8d924cbcd02069eb64893a2c2d48a20631866 (diff)
downloadqemu-3a5922cc11f73269bfcd762997efc2c029a3b585.tar.gz
unifying: WIP for HID++ support
Error queue is implemented, possible receiver and device properties are filled in (in the header). Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'hw/usb/hid-logitech-dj.h')
-rw-r--r--hw/usb/hid-logitech-dj.h176
1 files changed, 174 insertions, 2 deletions
diff --git a/hw/usb/hid-logitech-dj.h b/hw/usb/hid-logitech-dj.h
index 4269457354..36b2c31e2e 100644
--- a/hw/usb/hid-logitech-dj.h
+++ b/hw/usb/hid-logitech-dj.h
@@ -1,5 +1,5 @@
/*
- * Logitech Unifying recever emulation (DJ mode).
+ * Logitech Unifying receiver emulation (HID++ protocol).
*
* Copyright (c) 2014 Peter Wu <peter@lekensteyn.nl>
*
@@ -24,13 +24,163 @@
#ifndef HID_LOGITECH_DJ_H
#define HID_LOGITECH_DJ_H
+/* HID requests ((bmRequestType << 8) | bRequest) */
+#define HID_GET_REPORT 0xa101
+#define HID_GET_IDLE 0xa102
+#define HID_GET_PROTOCOL 0xa103
+/* 0x04-0x08 Reserved */
+#define HID_SET_REPORT 0x2109
+#define HID_SET_IDLE 0x210a
+#define HID_SET_PROTOCOL 0x210b
+
+
/* interface numbers (also used for array indices) */
enum {
IFACE_KBD, /* keyboard */
IFACE_MSE, /* mouse; multimedia, power, media center buttons */
- IFACE_DJ, /* DJ mode */
+ IFACE_HIDPP, /* HID++, DJ */
+};
+
+#define MAX_DEVICES 6
+
+
+/* report formats */
+typedef struct {
+ uint8_t report_id;
+ uint8_t device_index;
+ uint8_t sub_id;
+ uint8_t address;
+ uint8_t value[3];
+} HidppMsgShort;
+
+typedef struct {
+ uint8_t report_id;
+ uint8_t device_index;
+ uint8_t sub_id;
+ uint8_t address;
+ uint8_t value[16];
+} HidppMsgLong;
+
+typedef struct {
+ uint8_t report_id;
+ uint8_t device_index;
+ uint8_t report_type;
+ uint8_t payload[12];
+} DjMsgShort;
+
+typedef struct {
+ uint8_t report_id;
+ uint8_t device_index;
+ uint8_t report_type;
+ uint8_t payload[29];
+} DjMsgLong;
+
+/* generic HID++ or DJ report */
+typedef struct {
+ union {
+ struct {
+ uint8_t report_id;
+ uint8_t device_index;
+ };
+ HidppMsgShort hidpp_s;
+ HidppMsgLong hidpp_l;
+ DjMsgShort dj_s;
+ DjMsgLong dj_l;
+ };
+} HidppMsg;
+
+/* information to generate an error output report */
+typedef struct {
+ uint8_t device_index;
+ uint8_t sub_id;
+ uint8_t address;
+#define HIDPP_ERR_SUCCESS 0x00
+#define HIDPP_ERR_INVALID_SUBID 0x01
+#define HIDPP_ERR_INVALID_ADDRESS 0x02
+#define HIDPP_ERR_INVALID_VALUE 0x03
+#define HIDPP_ERR_CONNECT_FAIL 0x04
+#define HIDPP_ERR_TOO_MANY_DEVICES 0x05
+#define HIDPP_ERR_ALREADY_EXISTS 0x06
+#define HIDPP_ERR_BUSY 0x07
+#define HIDPP_ERR_UNKNOWN_DEVICE 0x08
+#define HIDPP_ERR_RESOURCE_ERROR 0x09
+#define HIDPP_ERR_REQUEST_UNAVAILABLE 0x0A
+#define HIDPP_ERR_INVALID_PARAM_VALUE 0x0B
+#define HIDPP_ERR_WRONG_PIN_CODE 0x0C
+ uint8_t error;
+} HidppError;
+
+
+/* device and receiver info */
+struct firmware_version {
+ uint8_t fw_major;
+ uint8_t fw_minor;
+ uint16_t fw_build;
+ /* boot loader */
+ uint8_t bl_major;
+ uint8_t bl_minor;
};
+typedef struct {
+ const struct {
+ uint32_t serial;
+ struct firmware_version version;
+ } info; /* static information */
+
+#define REPORTING_FLAG_WIRELESS_NOTIFS 0
+#define REPORTING_FLAG_SOFTWARE_PRESENT (1 << 3)
+ int reporting_flags;
+ uint8_t activity_counter[MAX_DEVICES];
+ /* TODO: pairing lock open or closed (+ timeout) */
+ /* TODO: connected devices */
+ /* TODO: device firmware upgrade things? */
+} LHidReceiver;
+
+typedef struct {
+ const struct {
+ enum {
+ DEVTYPE_KEYBOARD = 1,
+ DEVTYPE_MOUSE,
+ DEVTYPE_NUMPAD,
+ DEVTYPE_PRESENTER,
+ /* 0x05..0x07 Reserved for future */
+ DEVTYPE_TRACKBALL = 8,
+ DEVTYPE_TOUCHPAD,
+ /* 0x0A..0x0F Reserved */
+ } device_type;
+ enum {
+ PROTO_UNIFYING = 4,
+ } protocol_type;
+ struct firmware_version version;
+ uint16_t protocol_version; /* HID++ protocol version */
+ uint16_t wireless_pid;
+ uint32_t serial;
+ const char name[15];
+ uint8_t usability_info; /* bits 0..3 power switch location */
+ /* TODO: feature set */
+ /* TODO: special mouse and key button mappings */
+ } info; /* static information */
+
+ bool powered_on;
+ uint8_t report_interval;
+#define REPORTING_FLAG_BATTERY_STATUS (1 << 4)
+ int reporting_flags;
+
+ /* TODO: status (device seen or not, encrypted link) */
+ struct {
+ uint8_t level;
+ enum {
+ BAT_STS_CHARGING,
+ /* TODO: charging, discharging, etc. */
+ } status;
+ } battery;
+} LHidDevice;
+
+/* helper macros for handling the report and error queue */
+#define LQUEUE_SIZE(q) ARRAY_SIZE((q).reports)
+#define LQUEUE_WRAP(q, val) ((val) & (LQUEUE_SIZE((q)) - 1u))
+#define LQUEUE_INCR(q, var) ((var) = LQUEUE_WRAP((q), (var) + 1))
+
typedef struct USBLtunifyState {
USBDevice dev;
USBEndpoint *intr[3]; /* interfaces (keyboard, mouse, DJ) */
@@ -40,6 +190,28 @@ typedef struct USBLtunifyState {
LTUNIFY_MODE_DJ = 2
} mode;
HIDState hid[2]; /* HID devices (keyboard, mouse) */
+
+ /* queue for HID++ requests and responses */
+ struct {
+ HidppMsg reports[16];
+ unsigned head;
+ unsigned n;
+ } queue;
+ /* receiver error queue (to be send): drop if full */
+ struct {
+ HidppMsgShort reports[2];
+ unsigned head;
+ unsigned n;
+ } error_queue;
+ LHidReceiver receiver;
+ LHidDevice devices[MAX_DEVICES];
} USBLtunifyState;
+
+/* handle control packets for interface 3 (HID++ / DJ) */
+void usb_ltunify_handle_control_hidpp(USBDevice *dev, USBPacket *p,
+ int request, int value, int index, int length, uint8_t *data);
+
+/* handle control packets for interface 3 (HID++ / DJ) */
+void usb_ltunify_handle_datain_hidpp(USBDevice *dev, USBPacket *p);
#endif