summaryrefslogtreecommitdiff
path: root/chip/stm32/usb_hid.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/stm32/usb_hid.c')
-rw-r--r--chip/stm32/usb_hid.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/chip/stm32/usb_hid.c b/chip/stm32/usb_hid.c
index b316585e77..79668ad0de 100644
--- a/chip/stm32/usb_hid.c
+++ b/chip/stm32/usb_hid.c
@@ -40,23 +40,54 @@ void hid_reset(int ep, usb_uint *hid_ep_buf, int len)
(0 << 12) /* RX Disabled */;
}
+/*
+ * Keep track of state in case we need to be called multiple times,
+ * if the report length is bigger than 64 bytes.
+ */
+static int report_left;
+static const uint8_t *report_ptr;
+
int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx,
const uint8_t *report_desc, int report_size)
{
- if ((ep0_buf_rx[0] == (USB_DIR_IN | USB_RECIP_INTERFACE |
+ if (!ep0_buf_rx) {
+ /*
+ * Continue previous transfer. We ignore report_desc/size here,
+ * which is fine as only one GET_DESCRIPTOR command comes at a
+ * time.
+ */
+ if (report_left == 0)
+ return -1;
+ report_size = MIN(USB_MAX_PACKET_SIZE, report_left);
+ memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
+ report_ptr, report_size);
+ btable_ep[0].tx_count = report_size;
+ report_left -= report_size;
+ report_ptr += report_size;
+ STM32_TOGGLE_EP(0, EP_TX_MASK, EP_TX_VALID,
+ report_left ? 0 : EP_STATUS_OUT);
+ return report_left ? 1 : 0;
+ } else if ((ep0_buf_rx[0] == (USB_DIR_IN | USB_RECIP_INTERFACE |
(USB_REQ_GET_DESCRIPTOR << 8))) &&
(ep0_buf_rx[1] == (USB_HID_DT_REPORT << 8))) {
/* Setup : HID specific : Get Report descriptor */
+ report_size = MIN(ep0_buf_rx[3], report_size);
+
+ if (report_size > USB_MAX_PACKET_SIZE) {
+ /* Report descriptor does not fit in one packet. */
+ report_left = report_size - USB_MAX_PACKET_SIZE;
+ report_ptr = report_desc + USB_MAX_PACKET_SIZE;
+ report_size = USB_MAX_PACKET_SIZE;
+ } else {
+ report_left = 0;
+ }
memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
- report_desc,
- report_size);
- btable_ep[0].tx_count = MIN(ep0_buf_rx[3], report_size);
+ report_desc, report_size);
+ btable_ep[0].tx_count = report_size;
STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID,
- EP_STATUS_OUT);
- CPRINTF("RPT %04x[l %04x]\n", STM32_USB_EP(0),
- ep0_buf_rx[3]);
- return 0;
+ report_left ? 0 : EP_STATUS_OUT);
+ return report_left ? 1 : 0;
}
- return 1;
+ return -1;
}