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 	0x11, WEBUSB_DESC_TYPE_URL, WEBUSB_URL_PREFIX_HTTP,
61 	'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', ':', '8', '0', '0', '0'
62 };
63 
webusb_to_host_cb(const struct usbd_context * const ctx,const struct usb_setup_packet * const setup,struct net_buf * const buf)64 static int webusb_to_host_cb(const struct usbd_context *const ctx,
65 			     const struct usb_setup_packet *const setup,
66 			     struct net_buf *const buf)
67 {
68 	LOG_INF("Vendor callback to host");
69 
70 	if (setup->wIndex == WEBUSB_REQ_GET_URL) {
71 		uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue);
72 
73 		if (index != SAMPLE_WEBUSB_LANDING_PAGE) {
74 			return -ENOTSUP;
75 		}
76 
77 		LOG_INF("Get URL request, index %u", index);
78 		net_buf_add_mem(buf, &webusb_origin_url,
79 				MIN(net_buf_tailroom(buf), sizeof(webusb_origin_url)));
80 
81 		return 0;
82 	}
83 
84 	return -ENOTSUP;
85 }
86 
87 USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_webusb, sizeof(bos_cap_webusb), &bos_cap_webusb,
88 			  SAMPLE_WEBUSB_VENDOR_CODE, webusb_to_host_cb, NULL);
89 
90 #endif /* ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H */
91