diff options
Diffstat (limited to 'chip/stm32/usb_hid.c')
-rw-r--r-- | chip/stm32/usb_hid.c | 49 |
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; } |