summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2017-09-12 15:47:31 +0200
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-12-16 00:56:16 +0000
commit011fa8f2ab69d66240e2f5450d52e51b55236568 (patch)
tree5a455a1ec7703a75d207c940330bf242147f2345
parent3bb8b0e0db724c6998ef68a591c15440d0861e90 (diff)
downloadchrome-ec-011fa8f2ab69d66240e2f5450d52e51b55236568.tar.gz
Add WebUSB descriptor support
The WebUSB specification defines a specific Platform Descriptor in the Binary Object Store: https://wicg.github.io/webusb/#webusb-platform-capability-descriptor This descriptor provides a special 'Landing page' URL to the host browser and associated privileges for it. Bump the USB version for BOS descriptors to 2.1 to be compatible with Chrome implementation. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BUG=none BRANCH=twinkie TEST=manual: on Twinkie (chip/stm32) and HG proto2 (chip/g), enumerate WebUSB descriptors with lsusb and connect to a WebUSB page in Chrome R61+. Change-Id: I7211ab554f4a6c156c1e8e79a3d9f0d6644217c6 Reviewed-on: https://chromium-review.googlesource.com/664813 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> (cherry picked from commit 77f011206c87a7a3e8cd93d3635c6c4f0ea3e32d) Reviewed-on: https://chromium-review.googlesource.com/828415 Commit-Queue: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--chip/g/usb.c18
-rw-r--r--chip/stm32/usb.c59
-rw-r--r--common/build.mk1
-rw-r--r--common/webusb_desc.c46
-rw-r--r--include/config.h12
-rw-r--r--include/usb_descriptor.h48
6 files changed, 163 insertions, 21 deletions
diff --git a/chip/g/usb.c b/chip/g/usb.c
index ea791fa15a..00b1e8df8c 100644
--- a/chip/g/usb.c
+++ b/chip/g/usb.c
@@ -186,8 +186,8 @@ static void showregs(void)
/* Standard USB stuff */
#ifdef CONFIG_USB_BOS
-/* v2.01 (vs 2.00) BOS Descriptor provided */
-#define USB_DEV_BCDUSB 0x0201
+/* v2.10 (vs 2.00) BOS Descriptor provided */
+#define USB_DEV_BCDUSB 0x0210
#else
#define USB_DEV_BCDUSB 0x0200
#endif
@@ -822,6 +822,20 @@ static void handle_setup(enum table_case tc)
print_later(" iface returned %d", bytes, 0, 0, 0, 0);
}
} else {
+#ifdef CONFIG_WEBUSB_URL
+ if (data_phase_in &&
+ ((req->bmRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR)) {
+ if (req->bRequest == 0x01 &&
+ req->wIndex == WEBUSB_REQ_GET_URL) {
+ bytes = *(uint8_t *)webusb_url;
+ bytes = MIN(req->wLength, bytes);
+ if (load_in_fifo(webusb_url, bytes) < 0)
+ bytes = -1;
+ } else {
+ report_error(-1);
+ }
+ } else
+#endif
/* Something we need to add support for? */
report_error(-1);
}
diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c
index 2afab3f415..a179461af5 100644
--- a/chip/stm32/usb.c
+++ b/chip/stm32/usb.c
@@ -112,6 +112,29 @@ void usb_read_setup_packet(usb_uint *buffer, struct usb_setup_packet *packet)
packet->wLength = buffer[3];
}
+static void ep0_send_descriptor(const uint8_t *desc, int len,
+ uint16_t fixup_size)
+{
+ /* do not send more than what the host asked for */
+ len = MIN(ep0_buf_rx[3], len);
+ /*
+ * if we cannot transmit everything at once,
+ * keep the remainder for the next IN packet
+ */
+ if (len >= USB_MAX_PACKET_SIZE) {
+ desc_left = len - USB_MAX_PACKET_SIZE;
+ desc_ptr = desc + USB_MAX_PACKET_SIZE;
+ len = USB_MAX_PACKET_SIZE;
+ }
+ memcpy_to_usbram(EP0_BUF_TX_SRAM_ADDR, desc, len);
+ if (fixup_size) /* set the real descriptor size */
+ ep0_buf_tx[1] = fixup_size;
+ btable_ep[0].tx_count = len;
+ /* send the null OUT transaction if the transfer is complete */
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID,
+ desc_left ? 0 : EP_STATUS_OUT);
+}
+
/* Requests on the control endpoint (aka EP0) */
static void ep0_rx(void)
{
@@ -135,6 +158,21 @@ static void ep0_rx(void)
return;
}
}
+ /* vendor specific request */
+ if ((req & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
+#ifdef CONFIG_WEBUSB_URL
+ uint8_t b_req = req >> 8; /* bRequest in the transfer */
+ uint16_t idx = ep0_buf_rx[2]; /* wIndex in the transfer */
+
+ if (b_req == 0x01 && idx == WEBUSB_REQ_GET_URL) {
+ int len = *(uint8_t *)webusb_url;
+
+ ep0_send_descriptor(webusb_url, len, 0);
+ return;
+ }
+#endif
+ goto unknown_req;
+ }
/* TODO check setup bit ? */
if (req == (USB_DIR_IN | (USB_REQ_GET_DESCRIPTOR << 8))) {
@@ -176,25 +214,8 @@ static void ep0_rx(void)
default: /* unhandled descriptor */
goto unknown_req;
}
- /* do not send more than what the host asked for */
- len = MIN(ep0_buf_rx[3], len);
- /*
- * if we cannot transmit everything at once,
- * keep the remainder for the next IN packet
- */
- if (len >= USB_MAX_PACKET_SIZE) {
- desc_left = len - USB_MAX_PACKET_SIZE;
- desc_ptr = desc + USB_MAX_PACKET_SIZE;
- len = USB_MAX_PACKET_SIZE;
- }
- memcpy_to_usbram(EP0_BUF_TX_SRAM_ADDR, desc, len);
- if (type == USB_DT_CONFIGURATION)
- /* set the real descriptor size */
- ep0_buf_tx[1] = USB_DESC_SIZE;
- btable_ep[0].tx_count = len;
- STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID,
- desc_left ? 0 : EP_STATUS_OUT);
- /* send the null OUT transaction if the transfer is complete */
+ ep0_send_descriptor(desc, len, type == USB_DT_CONFIGURATION ?
+ USB_DESC_SIZE : 0);
} else if (req == (USB_DIR_IN | (USB_REQ_GET_STATUS << 8))) {
uint16_t zero = 0;
/* Get status */
diff --git a/common/build.mk b/common/build.mk
index ef41886133..ae48325949 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -107,6 +107,7 @@ common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o
common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o
common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o
common-$(CONFIG_VSTORE)+=vstore.o
+common-$(CONFIG_WEBUSB_URL)+=webusb_desc.o
common-$(CONFIG_WIRELESS)+=wireless.o
common-$(HAS_TASK_CHIPSET)+=chipset.o
common-$(HAS_TASK_CONSOLE)+=console.o console_output.o uart_buffering.o
diff --git a/common/webusb_desc.c b/common/webusb_desc.c
new file mode 100644
index 0000000000..41d39006e0
--- /dev/null
+++ b/common/webusb_desc.c
@@ -0,0 +1,46 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/* WebUSB platform descriptor */
+
+#include "common.h"
+#include "usb_descriptor.h"
+#include "util.h"
+
+#ifndef CONFIG_USB_BOS
+#error "CONFIG_USB_BOS must be defined to use WebUSB descriptor"
+#endif
+
+const void *webusb_url = USB_URL_DESC(HTTPS, CONFIG_WEBUSB_URL);
+
+/*
+ * Platform Descriptor in the device Binary Object Store
+ * as defined by USB 3.1 spec chapter 9.6.2.
+ */
+static struct {
+ struct usb_bos_hdr_descriptor bos;
+ struct usb_platform_descriptor platform;
+} bos_desc = {
+ .bos = {
+ .bLength = USB_DT_BOS_SIZE,
+ .bDescriptorType = USB_DT_BOS,
+ .wTotalLength = (USB_DT_BOS_SIZE + USB_DT_PLATFORM_SIZE),
+ .bNumDeviceCaps = 1, /* platform caps */
+ },
+ .platform = {
+ .bLength = USB_DT_PLATFORM_SIZE,
+ .bDescriptorType = USB_DT_DEVICE_CAPABILITY,
+ .bDevCapabilityType = USB_DC_DTYPE_PLATFORM,
+ .bReserved = 0,
+ .PlatformCapUUID = USB_PLAT_CAP_WEBUSB,
+ .bcdVersion = 0x0100,
+ .bVendorCode = 0x01,
+ .iLandingPage = 1,
+ },
+};
+
+const struct bos_context bos_ctx = {
+ .descp = (void *)&bos_desc,
+ .size = sizeof(bos_desc),
+};
diff --git a/include/config.h b/include/config.h
index 7206555113..4a7b82ab45 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2537,6 +2537,18 @@
#define CONFIG_AUX_TIMER_PERIOD_MS (CONFIG_WATCHDOG_PERIOD_MS - 500)
/*****************************************************************************/
+/* WebUSB config */
+
+/*
+ * Enable the WebUSB support and define its URL.
+ * Export a WebUSB Platform Descriptor in the Binary Object Store descriptor.
+ * The WebUSB landing page URL is equal to 'CONFIG_WEBUSB_URL' plus the
+ * https:// prefix.
+ * This requires CONFIG_USB_BOS.
+ */
+#undef CONFIG_WEBUSB_URL
+
+/*****************************************************************************/
/*
* Support controlling power to WiFi, WWAN (3G/LTE), and/or bluetooth modules.
diff --git a/include/usb_descriptor.h b/include/usb_descriptor.h
index 0493f4f558..24d5676cfc 100644
--- a/include/usb_descriptor.h
+++ b/include/usb_descriptor.h
@@ -89,6 +89,24 @@ struct usb_contid_caps_descriptor {
#define USB_DC_DTYPE_BILLBOARD 0x0d
/* RESERVED 0x00, 0xOe - 0xff */
+/* Platform descriptor */
+struct usb_platform_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType; /* USB_DT_DEVICE_CAPABILITY */
+ uint8_t bDevCapabilityType; /* USB_DC_DTYPE_PLATFORM */
+ uint8_t bReserved; /* SBZ */
+ uint8_t PlatformCapUUID[16]; /* USB_PLAT_CAP_xxx */
+ uint16_t bcdVersion; /* 0x0100 */
+ uint8_t bVendorCode;
+ uint8_t iLandingPage;
+} __packed;
+#define USB_DT_PLATFORM_SIZE 24
+
+/* Platform Capability UUIDs */
+#define USB_PLAT_CAP_WEBUSB /*{3408b638-09a9-47a0-8bfd-a0768815b665}*/ \
+ {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \
+ 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65}
+
/* Qualifier Descriptor */
struct usb_qualifier_descriptor {
uint8_t bLength;
@@ -225,6 +243,35 @@ struct usb_endpoint_descriptor {
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
+/* WebUSB URL descriptors */
+#define WEBUSB_REQ_GET_URL 0x02
+#define USB_DT_WEBUSB_URL 0x03
+
+#define USB_URL_SCHEME_HTTP 0x00
+#define USB_URL_SCHEME_HTTPS 0x01
+#define USB_URL_SCHEME_NONE 0xff
+
+/*
+ * URL descriptor helper.
+ * (similar to string descriptor but UTF-8 instead of UTF-16)
+ */
+#define USB_URL_DESC(scheme, str) \
+ (const void *)&(const struct { \
+ uint8_t _len; \
+ uint8_t _type; \
+ uint8_t _scheme; \
+ char _data[sizeof(str)]; \
+ }) { \
+ /* Total size of the descriptor is : \
+ * size of the UTF-8 text plus the len/type fields \
+ * minus the string 0-termination \
+ */ \
+ sizeof(str) + 3 - 1, \
+ USB_DT_WEBUSB_URL, \
+ USB_URL_SCHEME_##scheme, \
+ str \
+ }
+
/* Setup Packet */
struct usb_setup_packet {
uint8_t bmRequestType;
@@ -290,5 +337,6 @@ extern const uint8_t usb_string_desc[];
/* USB string descriptor with the firmware version */
extern const void * const usb_fw_version;
extern const struct bos_context bos_ctx;
+extern const void *webusb_url;
#endif /* __CROS_EC_USB_DESCRIPTOR_H */