libxr  1.0
Want to be the best embedded framework
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
30#pragma pack(push, 1)
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};
46#pragma pack(pop)
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 {
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 (void)SetLandingPageUrl(landing_page_url);
76 }
77
79 WebUsbBosCapability& operator=(const WebUsbBosCapability&) = delete;
80
84 bool Enabled() const { return enabled_; }
85
90 void SetVendorCode(uint8_t vendor_code)
91 {
92 vendor_code_ = vendor_code;
93 platform_cap_.bVendorCode = vendor_code_;
94 }
95
104 bool SetLandingPageUrl(const char* landing_page_url)
105 {
107
108 if (landing_page_url == nullptr || landing_page_url[0] == '\0')
109 {
110 enabled_ = false;
111 platform_cap_.iLandingPage = 0u;
112 return true;
113 }
114
115 uint8_t scheme = WEBUSB_URL_SCHEME_HTTPS;
116 const char* url_body = nullptr;
117 if (!ParseLandingPageUrl(landing_page_url, scheme, url_body))
118 {
119 ASSERT(false);
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 // The URL descriptor length is stored in one byte and includes the
129 // 3-byte header.
130 // URL descriptor 的总长度由 1 字节表示,且包含前 3 字节头部。
131 ASSERT(false);
132 enabled_ = false;
133 platform_cap_.iLandingPage = 0u;
134 return false;
135 }
136
137 url_descriptor_storage_[0] = static_cast<uint8_t>(URL_BODY_LEN + 3u);
138 url_descriptor_storage_[1] = WEBUSB_URL_DESCRIPTOR_TYPE;
139 url_descriptor_storage_[2] = scheme;
140 LibXR::Memory::FastCopy(url_descriptor_storage_ + 3u, url_body, URL_BODY_LEN);
141
142 url_descriptor_.size_ = URL_BODY_LEN + 3u;
143 enabled_ = true;
144 platform_cap_.iLandingPage = WEBUSB_LANDING_PAGE_INDEX;
145 return true;
146 }
147
152 {
153 if (!enabled_)
154 {
155 return {nullptr, 0};
156 }
157 return {reinterpret_cast<const uint8_t*>(&platform_cap_), sizeof(platform_cap_)};
158 }
159
165 LibXR::USB::BosVendorResult& result) override
166 {
167 if (!enabled_)
168 {
170 }
171 if (setup == nullptr)
172 {
173 return ErrorCode::ARG_ERR;
174 }
175
176 const uint8_t BM = setup->bmRequestType;
177
178 if ((BM & 0x60u) != 0x40u)
179 {
181 }
182 if ((BM & 0x1Fu) != 0x00u)
183 {
185 }
186 if ((BM & 0x80u) == 0u)
187 {
189 }
190 if (setup->bRequest != vendor_code_ || setup->wIndex != WEBUSB_REQUEST_GET_URL)
191 {
193 }
194 if ((setup->wValue & 0xFFu) != WEBUSB_LANDING_PAGE_INDEX || setup->wLength == 0u)
195 {
196 return ErrorCode::ARG_ERR;
197 }
198
199 result.handled = true;
200 result.in_data = {reinterpret_cast<const uint8_t*>(url_descriptor_.addr_),
202 result.write_zlp = false;
203 result.early_read_zlp = true;
204 return ErrorCode::OK;
205 }
206
207 private:
212 static bool ParseLandingPageUrl(const char* input, uint8_t& scheme, const char*& body)
213 {
214 static constexpr const char kHttpsPrefix[] = "https://";
215 static constexpr const char kHttpPrefix[] = "http://";
216
217 if (std::strncmp(input, kHttpsPrefix, sizeof(kHttpsPrefix) - 1u) == 0)
218 {
219 scheme = WEBUSB_URL_SCHEME_HTTPS;
220 body = input + sizeof(kHttpsPrefix) - 1u;
221 return true;
222 }
223 if (std::strncmp(input, kHttpPrefix, sizeof(kHttpPrefix) - 1u) == 0)
224 {
225 scheme = WEBUSB_URL_SCHEME_HTTP;
226 body = input + sizeof(kHttpPrefix) - 1u;
227 return true;
228 }
229
230 return false;
231 }
232
233 uint8_t vendor_code_ = WEBUSB_VENDOR_CODE_DEFAULT;
234 bool enabled_ = false;
236 {};
238 WebUsbPlatformCapability platform_cap_{};
239};
240
241} // namespace LibXR::USB::WebUsb
常量原始数据封装类。 A class for encapsulating constant raw data.
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:5
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
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:164
RawData url_descriptor_
已编码 URL 描述符 / Encoded URL descriptor
Definition webusb.hpp:237
bool Enabled() const
当前是否启用 WebUSB / Whether WebUSB is currently enabled
Definition webusb.hpp:84
static bool ParseLandingPageUrl(const char *input, uint8_t &scheme, const char *&body)
解析 URL scheme,并返回去掉前缀后的正文 Parse the URL scheme and return the prefix-stripped body.
Definition webusb.hpp:212
void SetVendorCode(uint8_t vendor_code)
更新 GET_URL 使用的 vendor code Update the vendor code used by GET_URL.
Definition webusb.hpp:90
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:104
ConstRawData GetCapabilityDescriptor() const override
获取 BOS capability 描述符 / Get the BOS capability descriptor
Definition webusb.hpp:151
uint8_t url_descriptor_storage_[255]
URL 描述符静态缓冲 / Static URL descriptor buffer.
Definition webusb.hpp:235
ErrorCode
定义错误码枚举
@ 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:57
uint16_t wIndex
对象索引,如接口号或端点号 / Index (e.g., interface or endpoint)
Definition core.hpp:63
uint16_t wLength
数据阶段长度 / Number of bytes in data stage
Definition core.hpp:64
uint16_t wValue
参数字段,含请求相关值 / Value field (e.g., descriptor type/index)
Definition core.hpp:62
uint8_t bRequest
请求码 / Request code (e.g., GET_DESCRIPTOR)
Definition core.hpp:60
WebUSB BOS 平台能力描述符 / WebUSB BOS platform capability descriptor.
Definition webusb.hpp:36