summaryrefslogtreecommitdiff
path: root/chip/stm32
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
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')
-rw-r--r--chip/stm32/usb_hid.c73
-rw-r--r--chip/stm32/usb_hid_hw.h26
-rw-r--r--chip/stm32/usb_hid_keyboard.c21
-rw-r--r--chip/stm32/usb_hid_touchpad.c18
4 files changed, 104 insertions, 34 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;
diff --git a/chip/stm32/usb_hid_hw.h b/chip/stm32/usb_hid_hw.h
index 0133a0a16b..d4d5ac3ca9 100644
--- a/chip/stm32/usb_hid_hw.h
+++ b/chip/stm32/usb_hid_hw.h
@@ -8,12 +8,34 @@
#ifndef __CROS_EC_USB_HID_HW_H
#define __CROS_EC_USB_HID_HW_H
+#include <common.h>
+
+struct usb_hid_config_t {
+ const uint8_t *report_desc;
+ int report_size;
+ const struct usb_hid_descriptor *hid_desc;
+
+ /*
+ * Handle USB HID Get_Report request, can be NULL if not supported.
+ *
+ * @param report_id: ID of the report being requested
+ * @param report_type: 0x1 (INPUT) / 0x2 (OUTPUT) / 0x3 (FEATURE)
+ * @param buffer_ptr: handler should set it to the pointer of buffer to
+ * return.
+ * @param buffer_size: handler should set it to the size of returned
+ * buffer.
+ */
+ int (*get_report)(uint8_t report_id,
+ uint8_t report_type,
+ const uint8_t **buffer_ptr,
+ int *buffer_size);
+};
+
/* internal callbacks for HID class drivers */
void hid_tx(int ep);
void hid_reset(int ep, usb_uint *hid_ep_tx_buf, int tx_len,
usb_uint *hid_ep_rx_buf, int rx_len);
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 *hid_config);
#endif
diff --git a/chip/stm32/usb_hid_keyboard.c b/chip/stm32/usb_hid_keyboard.c
index 566be2440f..11cc42974c 100644
--- a/chip/stm32/usb_hid_keyboard.c
+++ b/chip/stm32/usb_hid_keyboard.c
@@ -422,22 +422,18 @@ USB_DECLARE_EP(USB_EP_HID_KEYBOARD, hid_keyboard_tx,
#endif
hid_keyboard_event);
+static struct usb_hid_config_t hid_config_kb = {
+ .report_desc = report_desc,
+ .report_size = sizeof(report_desc),
+ .hid_desc = &hid_desc_kb,
+};
+
static int hid_keyboard_iface_request(usb_uint *ep0_buf_rx,
usb_uint *ep0_buf_tx)
{
int ret;
- const uint8_t *desc = report_desc;
- uint32_t size = sizeof(report_desc);
-
-#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT
- if (board_has_keyboard_backlight()) {
- desc = report_desc_with_backlight;
- size = sizeof(report_desc_with_backlight);
- }
-#endif
- ret = hid_iface_request(ep0_buf_rx, ep0_buf_tx,
- desc, size, &hid_desc_kb);
+ ret = hid_iface_request(ep0_buf_rx, ep0_buf_tx, &hid_config_kb);
if (ret >= 0)
return ret;
@@ -644,6 +640,9 @@ void clear_typematic_key(void)
void usb_hid_keyboard_init(void)
{
if (board_has_keyboard_backlight()) {
+ hid_config_kb.report_desc = report_desc_with_backlight;
+ hid_config_kb.report_size = sizeof(report_desc_with_backlight);
+
set_descriptor_patch(USB_DESC_KEYBOARD_BACKLIGHT,
&hid_desc_kb.desc[0].wDescriptorLength,
sizeof(report_desc_with_backlight));
diff --git a/chip/stm32/usb_hid_touchpad.c b/chip/stm32/usb_hid_touchpad.c
index ebb8bd9ef4..6a658ce66d 100644
--- a/chip/stm32/usb_hid_touchpad.c
+++ b/chip/stm32/usb_hid_touchpad.c
@@ -324,11 +324,23 @@ static void hid_touchpad_event(enum usb_ep_event evt)
USB_DECLARE_EP(USB_EP_HID_TOUCHPAD, hid_touchpad_tx, hid_touchpad_tx,
hid_touchpad_event);
+static int get_report(uint8_t report_id, uint8_t report_type,
+ const uint8_t **buffer_ptr,
+ int *buffer_size)
+{
+ return -1;
+}
+
+static const struct usb_hid_config_t hid_config_tp = {
+ .report_desc = report_desc,
+ .report_size = sizeof(report_desc),
+ .hid_desc = &hid_desc_tp,
+ .get_report = get_report,
+};
+
static int hid_touchpad_iface_request(usb_uint *ep0_buf_rx,
usb_uint *ep0_buf_tx)
{
- return hid_iface_request(ep0_buf_rx, ep0_buf_tx,
- report_desc, sizeof(report_desc),
- &hid_desc_tp);
+ return hid_iface_request(ep0_buf_rx, ep0_buf_tx, &hid_config_tp);
}
USB_DECLARE_IFACE(USB_IFACE_HID_TOUCHPAD, hid_touchpad_iface_request)