libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
winusb_msos20.hpp
1#pragma once
2#include <cstddef>
3#include <cstdint>
4#include <cstring>
5
6#include "libxr_type.hpp"
7#include "usb/core/bos.hpp"
8#include "usb/core/core.hpp"
9
10namespace LibXR::USB::WinUsbMsOs20
11{
12
13// ---- constants ----
14
15// wIndex values for vendor request
16static constexpr uint16_t MSOS20_DESCRIPTOR_INDEX = 0x0007;
17static constexpr uint16_t MSOS20_SET_ALT_ENUMERATION = 0x0008;
18
19// MS OS 2.0 descriptor types
20static constexpr uint16_t MS_OS_20_SET_HEADER_DESCRIPTOR = 0x0000;
21static constexpr uint16_t MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x0001;
22static constexpr uint16_t MS_OS_20_SUBSET_HEADER_FUNCTION = 0x0002;
23static constexpr uint16_t MS_OS_20_FEATURE_COMPATIBLE_ID = 0x0003;
24static constexpr uint16_t MS_OS_20_FEATURE_REG_PROPERTY = 0x0004;
25
26// Registry property data type
27static constexpr uint16_t REG_MULTI_SZ = 0x0007;
28
29// MS OS 2.0 platform capability UUID: D8DD60DF-4589-4CC7-9CD2-659D9E648A9F
30static constexpr uint8_t MSOS20_PLATFORM_CAPABILITY_UUID[16] = {
31 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C,
32 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
33};
34
35// "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" + UTF-16 NUL
36static constexpr uint16_t GUID_CHARS_WITH_BRACES = 38;
37static constexpr uint16_t GUID_STR_UTF16_BYTES = (GUID_CHARS_WITH_BRACES + 1) * 2; // 78
38
39// "DeviceInterfaceGUIDs" (UTF-16LE) + NUL terminator
40static constexpr uint8_t PROP_NAME_DEVICE_INTERFACE_GUIDS_UTF16[] = {
41 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00,
42 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00,
43 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00};
44static constexpr uint16_t PROP_NAME_DEVICE_INTERFACE_GUIDS_BYTES =
45 static_cast<uint16_t>(sizeof(PROP_NAME_DEVICE_INTERFACE_GUIDS_UTF16));
46
47#pragma pack(push, 1)
48
49// ---- MS OS 2.0 basic blocks ----
50
51// 9.22.1 MS OS 2.0 descriptor set header
53{
54 uint16_t wLength = 0x000A;
55 uint16_t wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR;
56 uint32_t dwWindowsVersion = 0x06030000; // 0x06030000 = Win 8.1
57 uint16_t wTotalLength = 0; // sizeof(whole set)
58};
59
60// 9.22.2 Configuration subset header
62{
63 uint16_t wLength = 0x0008;
64 uint16_t wDescriptorType = MS_OS_20_SUBSET_HEADER_CONFIGURATION;
65 uint8_t bConfigurationValue = 0;
66 uint8_t bReserved = 0;
67 uint16_t wTotalLength = 0; // sizeof(this cfg subset)
68};
69
70// 9.22.3 Function subset header
72{
73 uint16_t wLength = 0x0008;
74 uint16_t wDescriptorType = MS_OS_20_SUBSET_HEADER_FUNCTION;
75 uint8_t bFirstInterface = 0;
76 uint8_t bReserved = 0;
77 uint16_t wTotalLength = 0; // sizeof(this function subset)
78};
79
80// 9.22.4 Compatible ID descriptor
82{
83 uint16_t wLength = 0x0014;
84 uint16_t wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID;
85
86 // "WINUSB" + padding NULs
87 uint8_t CompatibleID[8] = {'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00};
88
89 // Optional; usually all zeros
90 uint8_t SubCompatibleID[8] = {0};
91};
92
93// 9.22.5 Registry property descriptor header (common part)
95{
96 uint16_t wLength = 0; // sizeof(whole reg property feature)
97 uint16_t wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY;
98 uint16_t wPropertyDataType = 0; // e.g. REG_MULTI_SZ
99 uint16_t wPropertyNameLength = 0;
100};
101
102// ---- MS OS 2.0 Platform Capability (BOS Device Capability) ----
103//
104// Exposed via BOS Platform Capability. Host can query the MS OS 2.0 descriptor
105// set using a vendor request with matching bMS_VendorCode and wIndex=0x0007.
107{
108 uint8_t bLength = 0x1C;
109 uint8_t bDescriptorType = 0x10; // DEVICE_CAPABILITY
110 uint8_t bDevCapabilityType = 0x05; // PLATFORM
111 uint8_t bReserved = 0x00;
112
113 uint8_t PlatformCapabilityUUID[16] = {
114 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C,
115 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
116 };
117
118 uint32_t dwWindowsVersion = 0x06030000; // Win 8.1+
119 uint16_t wMSOSDescriptorSetTotalLength = 0; // sizeof(MS OS 2.0 set)
120 uint8_t bMS_VendorCode = 0x20; // vendor request bRequest
121 uint8_t bAltEnumCode = 0x00; // optional, often 0
122};
123
124#pragma pack(pop)
125
126// ---- sanity checks ----
127static_assert(sizeof(MsOs20SetHeader) == 10, "SetHeader size mismatch");
128static_assert(sizeof(MsOs20SubsetHeaderConfiguration) == 8, "CfgHeader size mismatch");
129static_assert(sizeof(MsOs20SubsetHeaderFunction) == 8, "FuncHeader size mismatch");
130static_assert(sizeof(MsOs20FeatureCompatibleId) == 20, "CompatibleId size mismatch");
131static_assert(sizeof(MsOs20PlatformCapability) == 28, "PlatformCapability size mismatch");
132
133// ---- helpers ----
134
135// Initialize MsOs20PlatformCapability with given descriptor-set length / vendor code /
136// version.
137inline void init_msos20_platform_capability(MsOs20PlatformCapability& cap,
138 uint16_t msos_descriptor_set_total_length,
139 uint8_t vendor_code = 0x20,
140 uint32_t windows_version = 0x06030000)
141{
143 Memory::FastCopy(cap.PlatformCapabilityUUID, MSOS20_PLATFORM_CAPABILITY_UUID,
144 sizeof(MSOS20_PLATFORM_CAPABILITY_UUID));
145 cap.dwWindowsVersion = windows_version;
146 cap.wMSOSDescriptorSetTotalLength = msos_descriptor_set_total_length;
147 cap.bMS_VendorCode = vendor_code;
148 cap.bAltEnumCode = 0x00;
149}
150
151// ---- BOS capability wrapper ----
152//
153// Purpose:
154// - Register a BOS Platform Capability (MS OS 2.0) to BosManager.
155// - Handle vendor requests:
156// - wIndex=0x0007 (IN): return MS OS 2.0 descriptor set.
157// - wIndex=0x0008 (OUT): Set Alt Enumeration (usually no data stage).
159{
160 public:
161 explicit MsOs20BosCapability(LibXR::ConstRawData descriptor_set,
162 uint8_t vendor_code = 0x20,
163 uint32_t windows_version = 0x06030000)
164 : descriptor_set_(descriptor_set),
165 vendor_code_(vendor_code),
166 windows_version_(windows_version)
167 {
168 RefreshPlatformCap();
169 }
170
171 void SetDescriptorSet(LibXR::ConstRawData descriptor_set)
172 {
173 descriptor_set_ = descriptor_set;
174 RefreshPlatformCap();
175 }
176
177 void SetVendorCode(uint8_t vendor_code)
178 {
179 vendor_code_ = vendor_code;
180 platform_cap_.bMS_VendorCode = vendor_code_;
181 }
182
184 {
185 return LibXR::ConstRawData(&platform_cap_, sizeof(platform_cap_));
186 }
187
188 ErrorCode OnVendorRequest(bool /*in_isr*/, const SetupPacket* setup,
189 LibXR::USB::BosVendorResult& result) override
190 {
191 if (setup == nullptr)
192 {
193 return ErrorCode::ARG_ERR;
194 }
195
196 const uint8_t BM = setup->bmRequestType;
197
198 // type must be Vendor (bits[6:5] == 10)
199 if ((BM & 0x60) != 0x40)
200 {
201 return ErrorCode::NOT_SUPPORT;
202 }
203
204 // recipient must be Device (bits[4:0] == 00000)
205 if ((BM & 0x1F) != 0x00)
206 {
207 return ErrorCode::NOT_SUPPORT;
208 }
209
210 // vendor code must match
211 if (setup->bRequest != vendor_code_)
212 {
213 return ErrorCode::NOT_SUPPORT;
214 }
215
216 // wIndex == 0x0007: MS OS 2.0 descriptor set (Vendor IN)
217 if (setup->wIndex == MSOS20_DESCRIPTOR_INDEX)
218 {
219 // direction must be IN
220 if ((BM & 0x80) == 0)
221 {
222 return ErrorCode::NOT_SUPPORT;
223 }
224
225 if (descriptor_set_.addr_ == nullptr || descriptor_set_.size_ == 0 ||
226 descriptor_set_.size_ > 0xFFFF)
227 {
228 return ErrorCode::ARG_ERR;
229 }
230
231 // Host wLength==0 is meaningless here; reject.
232 if (setup->wLength == 0)
233 {
234 return ErrorCode::NOT_SUPPORT;
235 }
236
237 result.handled = true;
238 result.in_data = descriptor_set_; // USB stack truncates by wLength
239 result.write_zlp = false;
240 result.early_read_zlp = true;
241 return ErrorCode::OK;
242 }
243
244 // wIndex == 0x0008: Set Alt Enumeration (Vendor OUT, usually wLength==0)
245 if (setup->wIndex == MSOS20_SET_ALT_ENUMERATION)
246 {
247 // direction should be OUT
248 if ((BM & 0x80) != 0)
249 {
250 // Strict behavior: reject IN.
251 return ErrorCode::NOT_SUPPORT;
252 }
253
254 // Usually no data stage. If wLength != 0, we still ACK to keep flow smooth.
255 if (setup->wLength != 0)
256 {
257 // no-op
258 }
259
260 result.handled = true;
261 result.in_data = {nullptr, 0};
262 result.write_zlp = true; // complete status stage
263 result.early_read_zlp = true;
264 return ErrorCode::OK;
265 }
266
267 return ErrorCode::NOT_SUPPORT;
268 }
269
270 private:
271 void RefreshPlatformCap()
272 {
273 // Keep Platform Capability synchronized with descriptor set length / vendor code.
274 platform_cap_ = MsOs20PlatformCapability{};
275 Memory::FastCopy(platform_cap_.PlatformCapabilityUUID,
276 MSOS20_PLATFORM_CAPABILITY_UUID,
277 sizeof(MSOS20_PLATFORM_CAPABILITY_UUID));
278 platform_cap_.dwWindowsVersion = windows_version_;
279 platform_cap_.bMS_VendorCode = vendor_code_;
280 platform_cap_.bAltEnumCode = 0x00;
281
282 if (descriptor_set_.size_ <= 0xFFFF)
283 {
284 platform_cap_.wMSOSDescriptorSetTotalLength =
285 static_cast<uint16_t>(descriptor_set_.size_);
286 }
287 else
288 {
289 platform_cap_.wMSOSDescriptorSetTotalLength = 0;
290 }
291 }
292
293 // Cached MS OS 2.0 descriptor set bytes.
294 LibXR::ConstRawData descriptor_set_{nullptr, 0};
295
296 // Vendor request bRequest code used for MS OS 2.0 query.
297 uint8_t vendor_code_ = 0x20;
298
299 // Windows version field in Platform Capability.
300 uint32_t windows_version_ = 0x06030000;
301
302 // BOS Platform Capability descriptor block.
303 MsOs20PlatformCapability platform_cap_{};
304};
305
306} // namespace LibXR::USB::WinUsbMsOs20
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:3
BOS 能力接口 / BOS capability interface.
Definition bos.hpp:56
ErrorCode OnVendorRequest(bool, const SetupPacket *setup, LibXR::USB::BosVendorResult &result) override
处理该能力相关 Vendor 请求 / Handle vendor request for this capability
LibXR::ConstRawData GetCapabilityDescriptor() const override
返回能力块(不含 BOS 头) Return capability block (without BOS header).
Vendor 请求处理结果(EP0 控制传输) Vendor request handling result for EP0 control transfers.
Definition bos.hpp:44
bool handled
已处理该请求 / Request consumed by capability
Definition bos.hpp:45
ConstRawData in_data
IN 数据阶段返回数据 / IN data stage payload.
Definition bos.hpp:46
bool write_zlp
状态阶段发送 ZLP / Send ZLP at status stage
Definition bos.hpp:47
bool early_read_zlp
提前准备 OUT 以适配主机短读 / Arm OUT early for short-read tolerance
Definition bos.hpp:48
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
uint8_t bRequest
请求码 / Request code (e.g., GET_DESCRIPTOR)
Definition core.hpp:60