Soumyajyotii Ssarkar <[email protected]> writes:
> Build on top of the simple mouse HID report descriptor with an enhanced
> version
> that supports report IDs and feature reports for high resolution mouse
> wheel control. As per the documentation structure.
>
> Check:
> https://download.microsoft.com/download/b/d/1/bd1f7ef4-7d72-419e-bc5c-9f79ad7bb66e/wheel.docx
>
> Changes:
> - Increase HID descriptor length from 52 to 144 bytes
> - Add report IDs (0x01 input, 0x02 feature)
> - Implement feature reports for wheel/pan resolution multipliers
> - Add AC Pan (horizontal scroll) usage
> - Increase endpoint packet size from 4 to 6 bytes for pan byte
>
> This enables guests to configure resolution multipliers (+-1, +-4, +-8, +-16)
> to control scroll acceleration and precision.
>
> Signed-off-by: Soumyajyotii Ssarkar <[email protected]>
> ---
> hw/usb/dev-hid.c | 126 +++++++++++++++++++++++++++++++++++------------
> 1 file changed, 95 insertions(+), 31 deletions(-)
>
> diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
> index ae19d60203..49e23c2319 100644
> --- a/hw/usb/dev-hid.c
> +++ b/hw/usb/dev-hid.c
> @@ -93,7 +93,7 @@ static const USBDescIface desc_iface_mouse = {
> 0x00, /* u8 country_code */
> 0x01, /* u8 num_descriptors */
> USB_DT_REPORT, /* u8 type: Report */
> - 52, 0, /* u16 len */
> + 144, 0, /* u16 len */
Is this effectively just sizeof(qemu_mouse_hid_report_descriptor)? Could
we use that instead of hard coding constants in the descriptor? Are
there a limited number of sizes or are these a flexible stream of bytes?
> },
> },
> },
> @@ -101,7 +101,7 @@ static const USBDescIface desc_iface_mouse = {
> {
> .bEndpointAddress = USB_DIR_IN | 0x01,
> .bmAttributes = USB_ENDPOINT_XFER_INT,
> - .wMaxPacketSize = 4,
> + .wMaxPacketSize = 6,
> .bInterval = 0x0a,
> },
> },
> @@ -124,7 +124,7 @@ static const USBDescIface desc_iface_mouse2 = {
> 0x00, /* u8 country_code */
> 0x01, /* u8 num_descriptors */
> USB_DT_REPORT, /* u8 type: Report */
> - 52, 0, /* u16 len */
> + 144, 0, /* u16 len */
> },
> },
> },
> @@ -132,7 +132,7 @@ static const USBDescIface desc_iface_mouse2 = {
> {
> .bEndpointAddress = USB_DIR_IN | 0x01,
> .bmAttributes = USB_ENDPOINT_XFER_INT,
> - .wMaxPacketSize = 4,
> + .wMaxPacketSize = 6,
> .bInterval = 7, /* 2 ^ (8-1) * 125 usecs = 8 ms */
> },
> },
> @@ -454,33 +454,97 @@ static const USBDesc desc_keyboard2 = {
> };
>
> static const uint8_t qemu_mouse_hid_report_descriptor[] = {
> - 0x05, 0x01, /* Usage Page (Generic Desktop) */
> - 0x09, 0x02, /* Usage (Mouse) */
> - 0xa1, 0x01, /* Collection (Application) */
> - 0x09, 0x01, /* Usage (Pointer) */
> - 0xa1, 0x00, /* Collection (Physical) */
> - 0x05, 0x09, /* Usage Page (Button) */
> - 0x19, 0x01, /* Usage Minimum (1) */
> - 0x29, 0x05, /* Usage Maximum (5) */
> - 0x15, 0x00, /* Logical Minimum (0) */
> - 0x25, 0x01, /* Logical Maximum (1) */
> - 0x95, 0x05, /* Report Count (5) */
> - 0x75, 0x01, /* Report Size (1) */
> - 0x81, 0x02, /* Input (Data, Variable, Absolute) */
> - 0x95, 0x01, /* Report Count (1) */
> - 0x75, 0x03, /* Report Size (3) */
> - 0x81, 0x01, /* Input (Constant) */
> - 0x05, 0x01, /* Usage Page (Generic Desktop) */
> - 0x09, 0x30, /* Usage (X) */
> - 0x09, 0x31, /* Usage (Y) */
> - 0x09, 0x38, /* Usage (Wheel) */
> - 0x15, 0x81, /* Logical Minimum (-0x7f) */
> - 0x25, 0x7f, /* Logical Maximum (0x7f) */
> - 0x75, 0x08, /* Report Size (8) */
> - 0x95, 0x03, /* Report Count (3) */
> - 0x81, 0x06, /* Input (Data, Variable, Relative) */
> - 0xc0, /* End Collection */
> - 0xc0, /* End Collection */
> + 0x05, 0x01, /* Usage Page (Generic Desktop) */
> + 0x09, 0x02, /* Usage (Mouse) */
> + 0xA1, 0x01, /* Collection (Application) */
> +
> + 0x09, 0x02, /* Usage (Mouse) */
> + 0xA1, 0x02, /* Collection (Logical) */
> +
> + 0x85, 0x01, /* Report ID (0x01) */
> + 0x09, 0x01, /* Usage (Pointer) */
> + 0xA1, 0x00, /* Collection (Physical) */
> +
> + 0x05, 0x09, /* Usage Page (Button) */
> + 0x19, 0x01, /* Usage Minimum (1) */
> + 0x29, 0x05, /* Usage Maximum (5) */
> + 0x15, 0x00, /* Logical Minimum (0) */
> + 0x25, 0x01, /* Logical Maximum (1) */
> + 0x95, 0x05, /* Report Count (5) */
> + 0x75, 0x01, /* Report Size (1) */
> + 0x81, 0x02, /* Input (Data,Var,Abs) */
> +
> + 0x95, 0x01, /* Report Count (1) */
> + 0x75, 0x03, /* Report Size (3) */
> + 0x81, 0x01, /* Input (Const) */
> +
> + 0x05, 0x01, /* Usage Page (Generic Desktop) */
> + 0x09, 0x30, /* Usage (X) */
> + 0x09, 0x31, /* Usage (Y) */
> + 0x95, 0x02, /* Report Count (2) */
> + 0x75, 0x08, /* Report Size (8) */
> + 0x15, 0x81, /* Logical Minimum (-127) */
> + 0x25, 0x7F, /* Logical Maximum (127) */
> + 0x81, 0x06, /* Input (Data,Var,Rel) */
> +
> + /* Vertical wheel logical collection */
> + 0xA1, 0x02, /* Collection (Logical) */
> +
> + 0x85, 0x02, /* Report ID (0x02) */
> + 0x09, 0x48, /* Usage (Resolution Multiplier) */
> + 0x15, 0x00, /* Logical Minimum (0) */
> + 0x25, 0x01, /* Logical Maximum (1) */
> + 0x35, 0x01, /* Physical Minimum (1) */
> + 0x45, 0x04, /* Physical Maximum (4) */
> + 0x75, 0x02, /* Report Size (2) */
> + 0x95, 0x01, /* Report Count (1) */
> + 0xB1, 0x02, /* Feature (Data,Var,Abs) */
> +
> + 0x85, 0x01, /* Report ID (0x01) */
> + 0x09, 0x38, /* Usage (Wheel) */
> + 0x35, 0x00, /* Physical Minimum (0) */
> + 0x45, 0x00, /* Physical Maximum (0) */
> + 0x15, 0x81, /* Logical Minimum (-0x7f) */
> + 0x25, 0x7F, /* Logical Maximum (0x7f) */
> + 0x75, 0x08, /* Report Size (8) */
> + 0x95, 0x01, /* Report Count (1) */
> + 0x81, 0x06, /* Input (Data,Var,Rel) */
> +
> + 0xC0, /* End Collection */
> +
> + /* Horizontal wheel logical collection */
> + 0xA1, 0x02, /* Collection (Logical) */
> +
> + 0x85, 0x02, /* Report ID (0x02) */
> + 0x09, 0x48, /* Usage (Resolution Multiplier) */
> + 0x15, 0x00, /* Logical Minimum (0) */
> + 0x25, 0x01, /* Logical Maximum (1) */
> + 0x35, 0x01, /* Physical Minimum (1) */
> + 0x45, 0x04, /* Physical Maximum (4) */
> + 0x75, 0x02, /* Report Size (2) */
> + 0x95, 0x01, /* Report Count (1) */
> + 0xB1, 0x02, /* Feature (Data,Var,Abs) */
> +
> + 0x35, 0x00, /* Physical Minimum (0) */
> + 0x45, 0x00, /* Physical Maximum (0) */
> + 0x75, 0x04, /* Report Size (4) */
> + 0x95, 0x01, /* Report Count (1) */
> + 0xB1, 0x01, /* Feature (Const) */
> +
> + 0x85, 0x01, /* Report ID (0x01) */
> + 0x05, 0x0C, /* Usage Page (Consumer Devices) */
> + 0x0A, 0x38, 0x02, /* Usage (AC Pan) */
> + 0x15, 0x81, /* Logical Minimum (-0x7f) */
> + 0x25, 0x7F, /* Logical Maximum (0x7f) */
> + 0x75, 0x08, /* Report Size (8) */
> + 0x95, 0x01, /* Report Count (1) */
> + 0x81, 0x06, /* Input (Data,Var,Rel) */
> +
> + 0xC0, /* End Collection */
> +
> + 0xC0, /* End Collection (Physical) */
> + 0xC0, /* End Collection (Logical) */
> + 0xC0 /* End Collection (Application) */
> };
>
> static const uint8_t qemu_tablet_hid_report_descriptor[] = {
--
Alex Bennée
Virtualisation Tech Lead @ Linaro