libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
webusb.hpp
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <cstring>
6
7#include "libxr_mem.hpp"
8#include "libxr_type.hpp"
9#include "usb/core/bos.hpp"
10#include "usb/core/core.hpp"
11
12namespace LibXR::USB::WebUsb
13{
14
15// ---- WebUSB constants ----
16
17static constexpr uint16_t WEBUSB_REQUEST_GET_URL = 0x0002u;
18static constexpr uint8_t WEBUSB_VENDOR_CODE_DEFAULT = 0x01u;
19static constexpr uint8_t WEBUSB_URL_DESCRIPTOR_TYPE = 0x03u;
20static constexpr uint8_t WEBUSB_URL_SCHEME_HTTP = 0x00u;
21static constexpr uint8_t WEBUSB_URL_SCHEME_HTTPS = 0x01u;
22static constexpr uint8_t WEBUSB_LANDING_PAGE_INDEX = 0x01u;
23
24// WebUSB platform capability UUID: 3408b638-09a9-47a0-8bfd-a0768815b665
25static constexpr uint8_t WEBUSB_PLATFORM_CAPABILITY_UUID[16] = {
26 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,
27 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
28};
29
30LIBXR_PACKED_BEGIN
31
36{
37 uint8_t bLength = 0x18u;
38 uint8_t bDescriptorType = 0x10u;
39 uint8_t bDevCapabilityType = 0x05u;
40 uint8_t bReserved = 0x00u;
41 uint8_t PlatformCapabilityUUID[16] = {};
42 uint16_t bcdVersion = 0x0100u;
43 uint8_t bVendorCode = WEBUSB_VENDOR_CODE_DEFAULT;
44 uint8_t iLandingPage = 0u;
45};
46LIBXR_PACKED_END
47
48static_assert(sizeof(WebUsbPlatformCapability) == 24,
49 "WebUSB platform capability size mismatch.");
50
60{
61 public:
66 explicit WebUsbBosCapability(const char* landing_page_url = nullptr,
67 uint8_t vendor_code = WEBUSB_VENDOR_CODE_DEFAULT)
68 : vendor_code_(vendor_code)
69 {
70 url_descriptor_.addr_ = url_descriptor_storage_;
71 LibXR::Memory::FastCopy(platform_cap_.PlatformCapabilityUUID,
72 WEBUSB_PLATFORM_CAPABILITY_UUID,
73 sizeof(WEBUSB_PLATFORM_CAPABILITY_UUID));
74 platform_cap_.bVendorCode = vendor_code_;
75 const bool landing_page_ok = SetLandingPageUrl(landing_page_url);
76 ASSERT(landing_page_ok);
77 }
78
80 WebUsbBosCapability& operator=(const WebUsbBosCapability&) = delete;
81
85 bool Enabled() const { return enabled_; }
86
91 void SetVendorCode(uint8_t vendor_code)
92 {
93 vendor_code_ = vendor_code;
94 platform_cap_.bVendorCode = vendor_code_;
95 }
96
105 bool SetLandingPageUrl(const char* landing_page_url)
106 {
107 url_descriptor_.size_ = 0u;
108
109 if (landing_page_url == nullptr || landing_page_url[0] == '\0')
110 {
111 enabled_ = false;
112 platform_cap_.iLandingPage = 0u;
113 return true;
114 }
115
116 uint8_t scheme = WEBUSB_URL_SCHEME_HTTPS;
117 const char* url_body = nullptr;
118 if (!ParseLandingPageUrl(landing_page_url, scheme, url_body))
119 {
120 enabled_ = false;
121 platform_cap_.iLandingPage = 0u;
122 return false;
123 }
124
125 const size_t URL_BODY_LEN = std::strlen(url_body);
126 if (URL_BODY_LEN == 0u || URL_BODY_LEN > 252u)
127 {
128 // URL descriptor 的总长度由 1 字节表示,且包含前 3 字节头部。
129 // The URL descriptor length is stored in one byte and includes the
130 // 3-byte header.
131 enabled_ = false;
132 platform_cap_.iLandingPage = 0u;
133 return false;
134 }
135
136 url_descriptor_storage_[0] = static_cast<uint8_t>(URL_BODY_LEN + 3u);
137 url_descriptor_storage_[1] = WEBUSB_URL_DESCRIPTOR_TYPE;
138 url_descriptor_storage_[2] = scheme;
139 LibXR::Memory::FastCopy(url_descriptor_storage_ + 3u, url_body, URL_BODY_LEN);
140
141 url_descriptor_.size_ = URL_BODY_LEN + 3u;
142 enabled_ = true;
143 platform_cap_.iLandingPage = WEBUSB_LANDING_PAGE_INDEX;
144 return true;
145 }
146
151 {
152 if (!enabled_)
153 {
154 return {nullptr, 0};
155 }
156 return {reinterpret_cast<const uint8_t*>(&platform_cap_), sizeof(platform_cap_)};
157 }
158
164 LibXR::USB::BosVendorResult& result) override
165 {
166 if (!enabled_)
167 {
169 }
170 if (setup == nullptr)
171 {
172 return ErrorCode::ARG_ERR;
173 }
174
175 const uint8_t BM = setup->bmRequestType;
176
177 if ((BM & 0x60u) != 0x40u)
178 {
180 }
181 if ((BM & 0x1Fu) != 0x00u)
182 {
184 }
185 if ((BM & 0x80u) == 0u)
186 {
188 }
189 if (setup->bRequest != vendor_code_ || setup->wIndex != WEBUSB_REQUEST_GET_URL)
190 {
192 }
193 if ((setup->wValue & 0xFFu) != WEBUSB_LANDING_PAGE_INDEX || setup->wLength == 0u)
194 {
195 return ErrorCode::ARG_ERR;
196 }
197
198 result.handled = true;
199 result.in_data = {reinterpret_cast<const uint8_t*>(url_descriptor_.addr_),
200 url_descriptor_.size_};
201 result.write_zlp = false;
202 result.early_read_zlp = true;
203 return ErrorCode::OK;
204 }
205
206 private:
211 static bool ParseLandingPageUrl(const char* input, uint8_t& scheme, const char*& body)
212 {
213 static constexpr const char HTTPS_PREFIX[] = "https://";
214 static constexpr const char HTTP_PREFIX[] = "http://";
215
216 if (std::strncmp(input, HTTPS_PREFIX, sizeof(HTTPS_PREFIX) - 1u) == 0)
217 {
218 scheme = WEBUSB_URL_SCHEME_HTTPS;
219 body = input + sizeof(HTTPS_PREFIX) - 1u;
220 return true;
221 }
222 if (std::strncmp(input, HTTP_PREFIX, sizeof(HTTP_PREFIX) - 1u) == 0)
223 {
224 scheme = WEBUSB_URL_SCHEME_HTTP;
225 body = input + sizeof(HTTP_PREFIX) - 1u;
226 return true;
227 }
228
229 return false;
230 }
231
232 uint8_t vendor_code_ = WEBUSB_VENDOR_CODE_DEFAULT;
233 bool enabled_ = false;
234 uint8_t url_descriptor_storage_[255] =
235 {};
236 RawData url_descriptor_{nullptr, 0};
237 WebUsbPlatformCapability platform_cap_{};
238};
239
240} // namespace LibXR::USB::WebUsb
只读原始数据视图 / Immutable raw data view
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
BOS 能力接口 / BOS capability interface.
Definition bos.hpp:57
WebUSB BOS 能力包装器 / WebUSB BOS capability wrapper.
Definition webusb.hpp:60
ErrorCode OnVendorRequest(bool, const SetupPacket *setup, LibXR::USB::BosVendorResult &result) override
处理 WebUSB GET_URL vendor request Handle the WebUSB GET_URL vendor request.
Definition webusb.hpp:163
bool Enabled() const
当前是否启用 WebUSB / Whether WebUSB is currently enabled
Definition webusb.hpp:85
void SetVendorCode(uint8_t vendor_code)
更新 GET_URL 使用的 vendor code Update the vendor code used by GET_URL.
Definition webusb.hpp:91
WebUsbBosCapability(const char *landing_page_url=nullptr, uint8_t vendor_code=WEBUSB_VENDOR_CODE_DEFAULT)
构造能力对象,并可选缓存 landing page URL Construct the capability and optionally cache the landing-page URL.
Definition webusb.hpp:66
bool SetLandingPageUrl(const char *landing_page_url)
解析并缓存 landing page URL Parse and cache the landing-page URL.
Definition webusb.hpp:105
ConstRawData GetCapabilityDescriptor() const override
获取 BOS capability 描述符 / Get the BOS capability descriptor
Definition webusb.hpp:150
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
Vendor 请求处理结果(EP0 控制传输) Vendor request handling result for EP0 control transfers.
Definition bos.hpp:45
bool handled
已处理该请求 / Request consumed by capability
Definition bos.hpp:46
ConstRawData in_data
IN 数据阶段返回数据 / IN data stage payload.
Definition bos.hpp:47
bool write_zlp
状态阶段发送 ZLP / Send ZLP at status stage
Definition bos.hpp:48
bool early_read_zlp
提前准备 OUT 以适配主机短读 / Arm OUT early for short-read tolerance
Definition bos.hpp:49
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)
Definition core.hpp:59
uint16_t wIndex
对象索引,如接口号或端点号 / Index (e.g., interface or endpoint)
Definition core.hpp:65
uint16_t wLength
数据阶段长度 / Number of bytes in data stage
Definition core.hpp:66
uint16_t wValue
参数字段,含请求相关值 / Value field (e.g., descriptor type/index)
Definition core.hpp:64
uint8_t bRequest
请求码 / Request code (e.g., GET_DESCRIPTOR)
Definition core.hpp:62
WebUSB BOS 平台能力描述符 / WebUSB BOS platform capability descriptor.
Definition webusb.hpp:36