1 /*
2 * Copyright (c) 2016-2019 Intel Corporation
3 * Copyright (c) 2023-2024 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #ifndef ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H
9 #define ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H
10
11 /*
12 * WebUSB platform capability and WebUSB URL descriptor.
13 * See https://wicg.github.io/webusb for reference.
14 */
15
16 #define WEBUSB_REQ_GET_URL 0x02U
17 #define WEBUSB_DESC_TYPE_URL 0x03U
18 #define WEBUSB_URL_PREFIX_HTTP 0x00U
19 #define WEBUSB_URL_PREFIX_HTTPS 0x01U
20
21 #define SAMPLE_WEBUSB_VENDOR_CODE 0x01U
22 #define SAMPLE_WEBUSB_LANDING_PAGE 0x01U
23
24 struct usb_bos_webusb_desc {
25 struct usb_bos_platform_descriptor platform;
26 struct usb_bos_capability_webusb cap;
27 } __packed;
28
29 static const struct usb_bos_webusb_desc bos_cap_webusb = {
30 /* WebUSB Platform Capability Descriptor:
31 * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
32 */
33 .platform = {
34 .bLength = sizeof(struct usb_bos_platform_descriptor)
35 + sizeof(struct usb_bos_capability_webusb),
36 .bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
37 .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM,
38 .bReserved = 0,
39 /* WebUSB Platform Capability UUID
40 * 3408b638-09a9-47a0-8bfd-a0768815b665
41 */
42 .PlatformCapabilityUUID = {
43 0x38, 0xB6, 0x08, 0x34,
44 0xA9, 0x09,
45 0xA0, 0x47,
46 0x8B, 0xFD,
47 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
48 },
49 },
50 .cap = {
51 .bcdVersion = sys_cpu_to_le16(0x0100),
52 .bVendorCode = SAMPLE_WEBUSB_VENDOR_CODE,
53 .iLandingPage = SAMPLE_WEBUSB_LANDING_PAGE
54 }
55 };
56
57 /* WebUSB URL Descriptor, see https://wicg.github.io/webusb/#webusb-descriptors */
58 static const uint8_t webusb_origin_url[] = {
59 /* bLength, bDescriptorType, bScheme, UTF-8 encoded URL */
60 0x24, WEBUSB_DESC_TYPE_URL, WEBUSB_URL_PREFIX_HTTPS,
61 'w', 'w', 'w', '.',
62 'z', 'e', 'p', 'h', 'y', 'r', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.',
63 'o', 'r', 'g', '/',
64 };
65
webusb_to_host_cb(const struct usbd_context * const ctx,const struct usb_setup_packet * const setup,struct net_buf * const buf)66 static int webusb_to_host_cb(const struct usbd_context *const ctx,
67 const struct usb_setup_packet *const setup,
68 struct net_buf *const buf)
69 {
70 LOG_INF("Vendor callback to host");
71
72 if (setup->wIndex == WEBUSB_REQ_GET_URL) {
73 uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue);
74
75 if (index != SAMPLE_WEBUSB_LANDING_PAGE) {
76 return -ENOTSUP;
77 }
78
79 LOG_INF("Get URL request, index %u", index);
80 net_buf_add_mem(buf, &webusb_origin_url,
81 MIN(net_buf_tailroom(buf), sizeof(webusb_origin_url)));
82
83 return 0;
84 }
85
86 return -ENOTSUP;
87 }
88
89 USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_webusb, sizeof(bos_cap_webusb), &bos_cap_webusb,
90 SAMPLE_WEBUSB_VENDOR_CODE, webusb_to_host_cb, NULL);
91
92 #endif /* ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H */
93