summaryrefslogtreecommitdiff
path: root/hw/usb/dev-unifying.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/dev-unifying.c')
-rw-r--r--hw/usb/dev-unifying.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/hw/usb/dev-unifying.c b/hw/usb/dev-unifying.c
index 218a654833..36ffdb3f55 100644
--- a/hw/usb/dev-unifying.c
+++ b/hw/usb/dev-unifying.c
@@ -485,31 +485,60 @@ data_ready:
usb_dump_complete(s->usb_dump_state, p);
}
-static void usb_ltunify_handle_datain_hid(USBDevice *dev, USBPacket *p)
+int usb_ltunify_poll_hid(HIDState *hs, uint8_t *buf, size_t bufsz)
{
- USBLtunifyState *s = (USBLtunifyState *) dev;
- uint8_t ifnum = p->ep->nr == 1 ? IFACE_KBD : IFACE_MSE;
- HIDState *hs = &s->hid[ifnum];
- uint8_t buf[p->iov.size];
int len = 0;
+ assert(hs != NULL);
if (hs->kind == HID_MOUSE) {
/* start accepting pointer events if not already */
hid_pointer_activate(hs);
}
if (!hid_has_events(hs)) {
- p->status = USB_RET_NAK;
- return;
+ return 0;
}
hid_set_next_idle(hs);
assert(hs->kind == HID_MOUSE || hs->kind == HID_KEYBOARD);
if (hs->kind == HID_MOUSE) {
- len = hid_pointer_poll(hs, buf, p->iov.size);
+ uint8_t pbuf[4]; /* buttons, x, y, wheel */
+ uint8_t lbuf[7];
+
+ hid_pointer_poll(hs, pbuf, sizeof(pbuf));
+ /* buttons (16 bits) */
+ lbuf[0] = pbuf[0];
+ lbuf[1] = 0;
+ /* X, Y (12 bits each) */
+ lbuf[2] = pbuf[1];
+ lbuf[3] = ((int8_t) pbuf[1] & 0xf00) >> 8; /* (ff)fe -> 0f */
+ lbuf[3] |= ((int8_t) pbuf[2] & 0xf00) >> 4; /* (ff)fe -> f0 */
+ lbuf[4] = pbuf[2];
+ /* wheel, consumer (8 bit each) */
+ lbuf[5] = pbuf[3];
+ lbuf[6] = 0;
+ len = MIN(len, bufsz);
+ memcpy(buf, lbuf, len);
} else if (hs->kind == HID_KEYBOARD) {
- len = hid_keyboard_poll(hs, buf, p->iov.size);
+ len = hid_keyboard_poll(hs, buf, bufsz);
+ }
+
+ return len;
+}
+
+static void usb_ltunify_handle_datain_hid(USBDevice *dev, USBPacket *p)
+{
+ USBLtunifyState *s = (USBLtunifyState *) dev;
+ uint8_t ifnum = p->ep->nr == 1 ? IFACE_KBD : IFACE_MSE;
+ HIDState *hs = &s->hid[ifnum];
+ uint8_t buf[p->iov.size];
+ int len;
+
+ len = usb_ltunify_poll_hid(hs, buf, sizeof(buf));
+ if (len <= 0) {
+ p->status = USB_RET_NAK;
+ return;
}
usb_dump_complete_data(s->usb_dump_state, p, buf, len);