summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2017-11-15 15:00:12 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-12-12 03:57:19 -0800
commite3c1e2265c732d465f3df90e5ea64bd02f02234f (patch)
tree7a6db56d522a6ff448f78691ad696901792e47d8
parent2f4fd74df5af5885a24d2c1ddc9deb71dd874315 (diff)
downloadchrome-ec-e3c1e2265c732d465f3df90e5ea64bd02f02234f.tar.gz
stm32/usb: Patching framework for USB descriptors
In some cases, we want to be able to dynamically modify a few bytes in the USB descriptor (in our case, length of referenced items), but it could also be other things like flags. These 2 new functions allow to keep all the USB descriptor in flash, and modify these few bytes before writing them in the USB buffer. BRANCH=none BUG=b:37447752 TEST=Flash hammer, USB descriptors are valid. Change-Id: I8624255fa43f52a0aaa21d20e963f3974f236912 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/771057 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--chip/stm32/usb.c36
-rw-r--r--chip/stm32/usb_hid.c3
-rw-r--r--chip/stm32/usb_hw.h21
3 files changed, 57 insertions, 3 deletions
diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c
index 27ea117de5..c97c68f03c 100644
--- a/chip/stm32/usb.c
+++ b/chip/stm32/usb.c
@@ -119,6 +119,40 @@ void usb_read_setup_packet(usb_uint *buffer, struct usb_setup_packet *packet)
packet->wLength = buffer[3];
}
+struct usb_descriptor_patch {
+ const void *address;
+ uint16_t data;
+};
+
+static struct usb_descriptor_patch desc_patches[USB_DESC_PATCH_COUNT];
+
+void set_descriptor_patch(enum usb_desc_patch_type type,
+ const void *address, uint16_t data)
+{
+ desc_patches[type].address = address;
+ desc_patches[type].data = data;
+}
+
+void *memcpy_to_usbram_ep0_patch(const void *src, size_t n)
+{
+ int i;
+ void *ret;
+
+ ret = memcpy_to_usbram((void *)usb_sram_addr(ep0_buf_tx), src, n);
+
+ for (i = 0; i < USB_DESC_PATCH_COUNT; i++) {
+ unsigned int offset = desc_patches[i].address - src;
+
+ if (offset >= n)
+ continue;
+
+ memcpy_to_usbram((void *)(usb_sram_addr(ep0_buf_tx) + offset),
+ &desc_patches[i].data, sizeof(desc_patches[i].data));
+ }
+
+ return ret;
+}
+
static void ep0_send_descriptor(const uint8_t *desc, int len,
uint16_t fixup_size)
{
@@ -133,7 +167,7 @@ static void ep0_send_descriptor(const uint8_t *desc, int len,
desc_ptr = desc + USB_MAX_PACKET_SIZE;
len = USB_MAX_PACKET_SIZE;
}
- memcpy_to_usbram(EP0_BUF_TX_SRAM_ADDR, desc, len);
+ memcpy_to_usbram_ep0_patch(desc, len);
if (fixup_size) /* set the real descriptor size */
ep0_buf_tx[1] = fixup_size;
btable_ep[0].tx_count = len;
diff --git a/chip/stm32/usb_hid.c b/chip/stm32/usb_hid.c
index f24bdd5982..873d80009a 100644
--- a/chip/stm32/usb_hid.c
+++ b/chip/stm32/usb_hid.c
@@ -107,8 +107,7 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx,
return report_left ? 1 : 0;
} else if (ep0_buf_rx[1] == (USB_HID_DT_HID << 8)) {
/* Setup : HID specific : Get HID descriptor */
- memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
- hid_desc, sizeof(*hid_desc));
+ memcpy_to_usbram_ep0_patch(hid_desc, sizeof(*hid_desc));
btable_ep[0].tx_count = sizeof(*hid_desc);
STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID,
EP_STATUS_OUT);
diff --git a/chip/stm32/usb_hw.h b/chip/stm32/usb_hw.h
index 89c8e9d6f0..94734d8569 100644
--- a/chip/stm32/usb_hw.h
+++ b/chip/stm32/usb_hw.h
@@ -63,6 +63,27 @@ void usb_read_setup_packet(usb_uint *buffer, struct usb_setup_packet *packet);
void *memcpy_to_usbram(void *dest, const void *src, size_t n);
void *memcpy_from_usbram(void *dest, const void *src, size_t n);
+/*
+ * Descriptor patching support, useful to change a few values in the descriptor
+ * (typically, length or bitfields) without having to move descriptors to RAM.
+ */
+
+enum usb_desc_patch_type {
+ USB_DESC_PATCH_COUNT,
+};
+
+/*
+ * Set patch in table: replace uint16_t at address (STM32 flash) with data.
+ *
+ * The patches need to be setup before _before_ usb_init is executed (or, at
+ * least, before the first call to memcpy_to_usbram_ep0_patch).
+ */
+void set_descriptor_patch(enum usb_desc_patch_type type,
+ const void *address, uint16_t data);
+
+/* Copy to USB ram, applying patches to src as required. */
+void *memcpy_to_usbram_ep0_patch(const void *src, size_t n);
+
/* Compute the address inside dedicate SRAM for the USB controller */
#define usb_sram_addr(x) ((x - __usb_ram_start) * sizeof(uint16_t))