summaryrefslogtreecommitdiff
path: root/chip/stm32/usb_hid.c
diff options
context:
space:
mode:
authorWei-Han Chen <stimim@google.com>2018-07-06 15:04:41 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-08-31 11:19:46 -0700
commit83ee439d07468b4e4a196b81da665c06f3c779a1 (patch)
tree74dc69b0ce2b8918d109d969b56f818fc4b63cf7 /chip/stm32/usb_hid.c
parentb9841cfcdf7404c868ea9967217cf750820b9491 (diff)
downloadchrome-ec-83ee439d07468b4e4a196b81da665c06f3c779a1.tar.gz
stm32: usb_hid: refactor to support `Get_Report` request
`Get_Report` request is required by USB HID standard. BRANCH=none BUG=b:70482333 TEST=manual on device Signed-off-by: Wei-Han Chen <stimim@chromium.org> Change-Id: I1543f019676259beb161db3195364998987ea529 Reviewed-on: https://chromium-review.googlesource.com/1188171 Commit-Ready: Wei-Han Chen <stimim@chromium.org> Tested-by: Wei-Han Chen <stimim@chromium.org> Reviewed-by: Wei-Han Chen <stimim@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Diffstat (limited to 'chip/stm32/usb_hid.c')
-rw-r--r--chip/stm32/usb_hid.c73
1 files changed, 55 insertions, 18 deletions
diff --git a/chip/stm32/usb_hid.c b/chip/stm32/usb_hid.c
index 873d80009a..043c4f8082 100644
--- a/chip/stm32/usb_hid.c
+++ b/chip/stm32/usb_hid.c
@@ -64,10 +64,41 @@ void hid_reset(int ep, usb_uint *hid_ep_tx_buf, int tx_len,
static int report_left;
static const uint8_t *report_ptr;
+/*
+ * Send report through ep0_buf_tx.
+ *
+ * If report size is greater than USB packet size (64 bytes), rest of the
+ * reports will be saved in `report_ptr` and `report_left`, so we can call this
+ * function again to send the remain parts.
+ *
+ * @return 0 if entire report is sent, 1 if there are remaining data.
+ */
+static int send_report(usb_uint *ep0_buf_tx,
+ const uint8_t *report,
+ int report_size)
+{
+ int packet_size = MIN(report_size, USB_MAX_PACKET_SIZE);
+
+ memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
+ report, packet_size);
+ btable_ep[0].tx_count = packet_size;
+ /* report_left != 0 if report doesn't fit in 1 packet. */
+ report_left = report_size - packet_size;
+ report_ptr = report + packet_size;
+
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID,
+ report_left ? 0 : EP_STATUS_OUT);
+
+ return report_left ? 1 : 0;
+}
+
int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx,
- const uint8_t *report_desc, int report_size,
- const struct usb_hid_descriptor *hid_desc)
+ const struct usb_hid_config_t *config)
{
+ const uint8_t *report_desc = config->report_desc;
+ int report_size = config->report_size;
+ const struct usb_hid_descriptor *hid_desc = config->hid_desc;
+
if (!ep0_buf_rx) {
/*
* Continue previous transfer. We ignore report_desc/size here,
@@ -89,22 +120,8 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx,
(USB_REQ_GET_DESCRIPTOR << 8))) {
if (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 doesn't fit in 1 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 = report_size;
- STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID,
- report_left ? 0 : EP_STATUS_OUT);
- return report_left ? 1 : 0;
+ return send_report(ep0_buf_tx, report_desc,
+ MIN(ep0_buf_rx[3], report_size));
} else if (ep0_buf_rx[1] == (USB_HID_DT_HID << 8)) {
/* Setup : HID specific : Get HID descriptor */
memcpy_to_usbram_ep0_patch(hid_desc, sizeof(*hid_desc));
@@ -113,6 +130,26 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx,
EP_STATUS_OUT);
return 0;
}
+ } else if (ep0_buf_rx[0] == (USB_DIR_IN |
+ USB_RECIP_INTERFACE |
+ USB_TYPE_CLASS |
+ (USB_HID_REQ_GET_REPORT << 8))) {
+ const uint8_t report_type = (ep0_buf_rx[1] >> 8) & 0xFF;
+ const uint8_t report_id = ep0_buf_rx[1] & 0xFF;
+ int retval;
+
+ report_left = ep0_buf_rx[3];
+ if (!config->get_report) /* not supported */
+ return -1;
+
+ retval = config->get_report(report_id,
+ report_type,
+ &report_ptr,
+ &report_left);
+ if (retval)
+ return retval;
+
+ return send_report(ep0_buf_tx, report_ptr, report_left);
}
return -1;