libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
device_composition.cpp
1#include "device_composition.hpp"
2
3#include <cstddef>
4#include <cstdint>
5
6namespace
7{
8using LibXR::USB::BOS_HEADER_SIZE;
10using LibXR::USB::CFG_REMOTE_WAKEUP;
11using LibXR::USB::CFG_SELF_POWERED;
13using LibXR::USB::DESCRIPTOR_TYPE_DEVICE_CAPABILITY;
15using LibXR::USB::DEV_CAPABILITY_TYPE_USB20EXT;
17
18struct InterfaceStringLayout
19{
20 size_t count = 0;
21 size_t max_len = 0;
22};
23
24// 在 class 去重前,先统计原始配置项数量。
25// Count the raw number of config items before unique-class deduplication.
26static size_t calc_total_item_num(
27 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
28 configs)
29{
30 // 这里先统计原始 item 数量;最终唯一 class 表会在构造函数里去重。
31 // Count raw items first; the final unique-class table is deduplicated in the
32 // constructor.
33 size_t total = 0;
34 for (const auto& group : configs)
35 {
36 total += group.size();
37 }
38 return total;
39}
40
41// 构造期唯一 class 表很小,线性查重已经足够。
42// The constructor-time unique-class table is tiny, so a linear contains check is
43// sufficient.
44static bool contains_class(DeviceClass* const* list, size_t count,
45 const DeviceClass* item)
46{
47 for (size_t i = 0; i < count; ++i)
48 {
49 if (list[i] == item)
50 {
51 return true;
52 }
53 }
54 return false;
55}
56
57// 计算 UTF-8 接口字符串转换成 UTF-16LE 后的有效载荷长度。
58// Compute the UTF-16LE payload size produced from a UTF-8 interface string.
59static size_t calc_utf16le_len_runtime(const char* input)
60{
61 if (input == nullptr)
62 {
63 return 0;
64 }
65
66 size_t len = 0;
67 for (size_t i = 0; input[i];)
68 {
69 unsigned char c = static_cast<unsigned char>(input[i]);
70 if (c < 0x80)
71 {
72 len += 2;
73 i += 1;
74 }
75 else if ((c & 0xE0) == 0xC0)
76 {
77 len += 2;
78 i += 2;
79 }
80 else if ((c & 0xF0) == 0xE0)
81 {
82 len += 2;
83 i += 3;
84 }
85 else
86 {
87 i += 4;
88 }
89 }
90 return len;
91}
92
93// Convert a UTF-8 interface string into UTF-16LE for USB string descriptors.
94// Unsupported code points are skipped in the same conservative way as before.
95// 把 UTF-8 接口字符串转换成 USB 字符串描述符使用的 UTF-16LE;
96// 不支持的码点保持原先的保守跳过策略。
97static void to_utf16le(const char* str, uint8_t* buffer)
98{
99 size_t len = 0;
100 const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
101
102 while (*s)
103 {
104 uint32_t codepoint = 0;
105
106 if (*s < 0x80)
107 {
108 codepoint = *s++;
109 }
110 else if ((*s & 0xE0) == 0xC0)
111 {
112 codepoint = (*s & 0x1F) << 6;
113 s++;
114 codepoint |= (*s & 0x3F);
115 s++;
116 }
117 else if ((*s & 0xF0) == 0xE0)
118 {
119 codepoint = (*s & 0x0F) << 12;
120 s++;
121 codepoint |= (*s & 0x3F) << 6;
122 s++;
123 codepoint |= (*s & 0x3F);
124 s++;
125 }
126 else if ((*s & 0xF8) == 0xF0)
127 {
128 s++;
129 if (*s)
130 {
131 s++;
132 }
133 if (*s)
134 {
135 s++;
136 }
137 if (*s)
138 {
139 s++;
140 }
141 continue;
142 }
143 else
144 {
145 s++;
146 continue;
147 }
148
149 buffer[len++] = codepoint & 0xFF;
150 buffer[len++] = (codepoint >> 8) & 0xFF;
151 }
152}
153
154// 预先算出接口字符串总数,以及运行时生成描述符所需的最大缓冲区。
155// Pre-compute the interface-string count and the largest runtime descriptor
156// buffer needed.
157static InterfaceStringLayout calc_interface_string_layout(DeviceClass* const* classes,
158 size_t class_count)
159{
160 // 接口字符串描述符在运行时生成,但其源字符串指针和最大 UTF-16LE
161 // 空间可在构造期一次算清。
162 // Interface strings are generated at runtime, but their source pointers and
163 // maximum UTF-16LE descriptor size can be fixed up front during construction.
164 InterfaceStringLayout layout{};
165 for (size_t class_index = 0; class_index < class_count; ++class_index)
166 {
167 auto* device_class = classes[class_index];
168 if (device_class == nullptr)
169 {
170 continue;
171 }
172
173 const size_t interface_num = device_class->GetInterfaceCount();
174 for (size_t i = 0; i < interface_num; ++i)
175 {
176 const char* str = device_class->GetInterfaceString(i);
177 if (str == nullptr || str[0] == '\0')
178 {
179 continue;
180 }
181
182 ++layout.count;
183 const size_t utf16_len = calc_utf16le_len_runtime(str);
184 if (utf16_len > layout.max_len)
185 {
186 layout.max_len = utf16_len;
187 }
188 }
189 }
190 return layout;
191}
192
193// A configuration is treated as composite if it exposes multiple items or any IAD.
194// 一个 configuration 只要有多个 item,或包含任意 IAD,就按复合设备处理。
195static bool config_contains_iad(const std::initializer_list<ConfigDescriptorItem*>& group)
196{
197 for (auto* item : group)
198 {
199 if (item != nullptr && item->HasIAD())
200 {
201 return true;
202 }
203 }
204 return false;
205}
206
207static bool is_composite_config(const std::initializer_list<ConfigDescriptorItem*>& group)
208{
209 return (group.size() > 1) || config_contains_iad(group);
210}
211
212// 只有“单 class、单接口、无 IAD”的简单形态,
213// 才允许覆盖 device descriptor 的类字段。
214// Device-descriptor override is only valid for the simple
215// "single class, single interface, no IAD" shape.
216static bool is_device_descriptor_override_eligible(ConfigDescriptorItem* const* items,
217 size_t item_num)
218{
219 if (item_num != 1)
220 {
221 return false;
222 }
223
224 auto* item = items[0];
225 if (item == nullptr)
226 {
227 return false;
228 }
229
230 if (item->HasIAD())
231 {
232 return false;
233 }
234
235 return (item->GetInterfaceCount() == 1);
236}
237
238static bool is_composite_device(
239 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
240 configs)
241{
242 for (const auto& group : configs)
243 {
244 if (is_composite_config(group))
245 {
246 return true;
247 }
248 }
249 return false;
250}
251
252// 统计所有 configuration 中 BOS capability 数量的最大值,
253// 这样 BosManager 的暂存空间只需分配一次。
254// Count the worst-case BOS capability count among all configurations so the
255// BosManager scratch storage can be allocated once.
256static size_t calc_bos_capability_num_max(
257 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
258 configs)
259{
260 size_t max_num = 0;
261 for (const auto& group : configs)
262 {
263 size_t num = 0;
264 for (auto* item : group)
265 {
266 if (item == nullptr)
267 {
268 continue;
269 }
270 num += item->GetBosCapabilityCount();
271 }
272 if (num > max_num)
273 {
274 max_num = num;
275 }
276 }
277 return max_num;
278}
279
280// 统计所有 configuration 中 BOS 描述符尺寸的最大值;
281// 若没有类提供 USB 2.0 Extension capability,则为自动补上的那项预留空间。
282// Count the worst-case BOS descriptor size among all configurations.
283// If no class provides a USB 2.0 Extension capability, reserve space for the
284// auto-added one.
285static size_t calc_bos_descriptor_size_max(
286 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
287 configs)
288{
289 static constexpr size_t usb2_ext_size = 7;
290
291 size_t max_total = BOS_HEADER_SIZE;
292 for (const auto& group : configs)
293 {
294 size_t cap_bytes = 0;
295 bool has_usb2_ext = false;
296
297 for (auto* item : group)
298 {
299 if (item == nullptr)
300 {
301 continue;
302 }
303
304 const size_t capability_num = item->GetBosCapabilityCount();
305 for (size_t i = 0; i < capability_num; ++i)
306 {
307 BosCapability* cap = item->GetBosCapability(i);
308 if (cap == nullptr)
309 {
310 continue;
311 }
312
313 auto blk = cap->GetCapabilityDescriptor();
314 ASSERT(blk.addr_ != nullptr);
315 ASSERT(blk.size_ >= 3);
316
317 cap_bytes += blk.size_;
318
319 const uint8_t* p = reinterpret_cast<const uint8_t*>(blk.addr_);
320 if (p[1] == DESCRIPTOR_TYPE_DEVICE_CAPABILITY &&
321 p[2] == DEV_CAPABILITY_TYPE_USB20EXT)
322 {
323 has_usb2_ext = true;
324 }
325 }
326 }
327
328 const size_t total = BOS_HEADER_SIZE + cap_bytes + (has_usb2_ext ? 0 : usb2_ext_size);
329 if (total > max_total)
330 {
331 max_total = total;
332 }
333 }
334
335 ASSERT(max_total <= 0xFFFF);
336 return max_total;
337}
338
339} // namespace
340
341using namespace LibXR::USB;
343using LibXR::RawData;
344
346 EndpointPool& endpoint_pool,
347 const std::initializer_list<const DescriptorStrings::LanguagePack*>& lang_list,
348 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
349 configs,
350 ConstRawData uid, uint8_t bmAttributes, uint8_t bMaxPower)
351 : endpoint_pool_(endpoint_pool),
352 bm_attributes_(bmAttributes),
353 composite_(is_composite_device(configs)),
354 config_num_(configs.size()),
355 items_(new ConfigItems[config_num_]),
356 classes_(new DeviceClass*[calc_total_item_num(configs)]),
357 strings_(lang_list, reinterpret_cast<const uint8_t*>(uid.addr_), uid.size_),
358 bos_(calc_bos_descriptor_size_max(configs), calc_bos_capability_num_max(configs)),
359 config_desc_(ConfigDescriptor::CalcMaxConfigSize(configs), bmAttributes, bMaxPower)
360{
361 ASSERT(config_num_ > 0);
362
363 // 将所有配置项整理成:
364 // 1) 每个 configuration 自己的 item 表
365 // 2) 一份用于字符串注册的唯一 class 表
366 // Flatten every configuration item into:
367 // 1) per-config item tables for descriptor building / binding
368 // 2) one unique class table for string registration
369 size_t config_index = 0;
370 for (const auto& cfg_group : configs)
371 {
372 items_[config_index].item_num = cfg_group.size();
373 items_[config_index].items = new ConfigDescriptorItem*[cfg_group.size()];
374
375 size_t item_index = 0;
376 for (auto* item : cfg_group)
377 {
378 items_[config_index].items[item_index++] = item;
379 auto* device_class = static_cast<DeviceClass*>(item);
380 if (device_class != nullptr &&
381 !contains_class(classes_, class_count_, device_class))
382 {
383 classes_[class_count_++] = device_class;
384 }
385 }
386
387 ++config_index;
388 }
389
390 // 初始化阶段一次性算出接口字符串容量和最大描述符空间。
391 // Pre-compute interface-string storage once during initialization.
392 const auto interface_string_layout =
393 calc_interface_string_layout(classes_, class_count_);
394 interface_string_count_ = interface_string_layout.count;
396 {
398 interface_string_buffer_.addr_ = new uint8_t[interface_string_layout.max_len + 2];
399 interface_string_buffer_.size_ = interface_string_layout.max_len + 2;
400 }
401
403}
404
411
412void DeviceComposition::Init(bool in_isr)
413{
414 // Init 先绑定端点,再按当前激活配置重建 BOS 视图。
415 // Init binds endpoints first, then rebuilds the BOS view for the active configuration.
416 configured_ = false;
417 BindEndpoints(in_isr);
419}
420
422{
423 UnbindEndpoints(in_isr);
424 configured_ = false;
425 current_cfg_ = 0;
426}
427
429{
430 if (index > config_num_)
431 {
433 }
434
435 if (index == 0)
436 {
437 UnbindEndpoints(in_isr);
438 configured_ = false;
439 current_cfg_ = 0;
442 }
443
444 // USB configuration value 从 1 开始,而 current_cfg_ 内部保存的是从 0 开始的槽位。
445 // USB configuration values are 1-based, while current_cfg_ stores a 0-based slot index.
446 UnbindEndpoints(in_isr);
447 current_cfg_ = static_cast<uint8_t>(index - 1);
448 configured_ = true;
449 BindEndpoints(in_isr);
452}
453
455{
456 // ConfigDescriptor 只构建当前激活的 configuration;
457 // current_cfg_ 同时决定 item 表和对外可见的 bConfigurationValue。
458 // ConfigDescriptor builds the active configuration only;
459 // current_cfg_ supplies both the item table and the externally visible
460 // bConfigurationValue.
461 const auto& config = CurrentConfigItems();
462 return config_desc_.BuildConfigDescriptor(config.items, config.item_num,
463 static_cast<uint8_t>(current_cfg_ + 1),
465}
466
468
470
472 const SetupPacket* setup,
473 BosVendorResult& result)
474{
475 return bos_.ProcessVendorRequest(in_isr, setup, result);
476}
477
479 uint16_t lang, ConstRawData& data)
480{
481 if (string_index == 0)
482 {
485 }
486
487 if (string_index > static_cast<uint8_t>(DescriptorStrings::Index::SERIAL_NUMBER_STRING))
488 {
489 // 接口字符串与内建字符串集合共用同一套语言号校验。
490 // Interface strings share the same language gate as the built-in string set.
491 if (!strings_.HasLanguage(lang))
492 {
494 }
495 return GenerateInterfaceString(string_index, data);
496 }
497
498 auto ec =
499 strings_.GenerateString(static_cast<DescriptorStrings::Index>(string_index), lang);
500 if (ec != LibXR::ErrorCode::OK)
501 {
502 return ec;
503 }
504
505 data = ConstRawData(strings_.GetData());
507}
508
510
512 DeviceDescriptor& descriptor)
513{
514 if (config_num_ != 1)
515 {
517 }
518
519 const auto config = items_[0];
520 if (!is_device_descriptor_override_eligible(config.items, config.item_num))
521 {
523 }
524
525 return config.items[0]->WriteDeviceDescriptor(descriptor);
526}
527
529
531{
532 return configured_ ? static_cast<size_t>(current_cfg_ + 1u) : 0u;
533}
534
536{
537 return ((bm_attributes_ & CFG_SELF_POWERED) ? 0x01 : 0x00) |
538 ((bm_attributes_ & CFG_REMOTE_WAKEUP) ? 0x02 : 0x00);
539}
540
542{
543 if (!configured_)
544 {
545 return nullptr;
546 }
547
548 const auto& config = CurrentConfigItems();
549
550 // 每个 item 都声明自己占用的接口数量;
551 // 沿扁平表前进,直到目标接口落入某个 item 的区间。
552 // Each item reports how many interfaces it occupies; walk the flattened list
553 // until the requested interface falls into one item's local range.
554 int interface_index = -1;
555 for (size_t i = 0; i < config.item_num; ++i)
556 {
557 auto* item = config.items[i];
558 if (item == nullptr)
559 {
560 continue;
561 }
562
563 interface_index += static_cast<int>(item->GetInterfaceCount());
564 if (interface_index >= static_cast<int>(index))
565 {
566 return static_cast<DeviceClass*>(item);
567 }
568 }
569
570 return nullptr;
571}
572
574{
575 if (!configured_)
576 {
577 return nullptr;
578 }
579
580 const auto& config = CurrentConfigItems();
581
582 for (size_t i = 0; i < config.item_num; ++i)
583 {
584 auto* item = config.items[i];
585 if (item == nullptr)
586 {
587 continue;
588 }
589
590 if (item->OwnsEndpoint(addr))
591 {
592 return static_cast<DeviceClass*>(item);
593 }
594 }
595
596 return nullptr;
597}
598
600{
601 if (ep_assigned_)
602 {
603 return;
604 }
605 ep_assigned_ = true;
606
607 const auto& config = CurrentConfigItems();
608
609 // start_itf tracks the configuration-global interface number assigned to each class.
610 // start_itf 记录 configuration 级别的全局接口号分配游标。
611 size_t start_itf = 0;
612 for (size_t i = 0; i < config.item_num; ++i)
613 {
614 auto* item = config.items[i];
615 if (item == nullptr)
616 {
617 continue;
618 }
619
620 item->BindEndpoints(endpoint_pool_, static_cast<uint8_t>(start_itf), in_isr);
621 start_itf += item->GetInterfaceCount();
622 }
623}
624
626{
627 if (!ep_assigned_)
628 {
629 return;
630 }
631 ep_assigned_ = false;
632
633 // Unbind 走的仍是当前激活 item 表,但这里不再需要重新分配接口号。
634 // Unbind walks the same active item table, but no interface renumbering is needed here.
635 const auto& config = CurrentConfigItems();
636 for (size_t i = 0; i < config.item_num; ++i)
637 {
638 auto* item = config.items[i];
639 if (item == nullptr)
640 {
641 continue;
642 }
643
644 item->UnbindEndpoints(endpoint_pool_, in_isr);
645 }
646}
647
649{
650 // BOS capability 只从当前激活的 configuration 收集。
651 // BOS capabilities are collected from the active configuration only.
653 const auto& config = CurrentConfigItems();
654 for (size_t i = 0; i < config.item_num; ++i)
655 {
656 auto* item = config.items[i];
657 if (item == nullptr)
658 {
659 continue;
660 }
661
662 const size_t capability_num = item->GetBosCapabilityCount();
663 for (size_t j = 0; j < capability_num; ++j)
664 {
665 auto* cap = item->GetBosCapability(j);
666 if (cap != nullptr)
667 {
668 bos_.AddCapability(cap);
669 }
670 }
671 }
672
673 (void)bos_.GetBosDescriptor();
674}
675
677 ConstRawData& data)
678{
679 // 接口字符串位于内建 manufacturer/product/serial 之后的索引区间。
680 // Interface strings live after the built-in manufacturer/product/serial range.
681 const size_t base_index =
683 if (string_index <= base_index)
684 {
686 }
687
688 const size_t extra_index = static_cast<size_t>(string_index - base_index - 1u);
689 if (extra_index >= interface_string_count_ || interface_string_buffer_.addr_ == nullptr)
690 {
692 }
693
694 uint8_t* buffer = reinterpret_cast<uint8_t*>(interface_string_buffer_.addr_);
695 const char* str = interface_strings_[extra_index];
696 const size_t utf16_len = calc_utf16le_len_runtime(str);
697 ASSERT(utf16_len + 2 <= 255);
698
699 // USB 字符串描述符格式:[bLength][bDescriptorType=0x03][UTF-16LE payload...]
700 // USB string descriptor layout: [bLength][bDescriptorType=0x03][UTF-16LE payload...]
701 buffer[1] = 0x03;
702 buffer[0] = static_cast<uint8_t>(utf16_len + 2);
703 to_utf16le(str, buffer + 2);
706}
707
709{
711 {
712 return;
713 }
714
715 // USB 字符串索引 1..3 保留给厂商/产品/序列号。
716 // USB string indices 1..3 are reserved for manufacturer/product/serial.
717 uint8_t next_index =
718 static_cast<uint8_t>(DescriptorStrings::Index::SERIAL_NUMBER_STRING) + 1u;
719 size_t registered_count = 0u;
720
721 for (size_t class_index = 0; class_index < class_count_; ++class_index)
722 {
723 auto* device_class = classes_[class_index];
724 if (device_class == nullptr)
725 {
726 continue;
727 }
728
729 const size_t interface_num = device_class->GetInterfaceCount();
730 device_class->SetInterfaceStringBaseIndex(0u);
731 bool class_has_string = false;
732
733 for (size_t i = 0; i < interface_num; ++i)
734 {
735 const char* str = device_class->GetInterfaceString(i);
736 if (str == nullptr || str[0] == '\0')
737 {
738 continue;
739 }
740
741 // 这里保留一张扁平源字符串表,
742 // 这样 DeviceCore 之后按索引取接口字符串时,不必再重新遍历全部 class。
743 // 保留一张扁平源字符串表,
744 // 这样 DeviceCore 之后可以按索引重新生成任意接口字符串,而不必重扫全部 class。
745 // Keep a flat source-string table so DeviceCore can later regenerate any
746 // interface string by index without re-scanning all classes.
747 ASSERT(registered_count < interface_string_count_);
748 if (!class_has_string)
749 {
750 device_class->SetInterfaceStringBaseIndex(next_index);
751 class_has_string = true;
752 }
753 interface_strings_[registered_count++] = str;
754 ++next_index;
755 }
756 }
757
758 ASSERT(registered_count == interface_string_count_);
759}
常量原始数据封装类。 A class for encapsulating constant raw data.
原始数据封装类。 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
virtual ConstRawData GetCapabilityDescriptor() const =0
返回能力块(不含 BOS 头) Return capability block (without BOS header).
bool AddCapability(BosCapability *cap)
添加能力 / Add capability
Definition bos.hpp:142
ConstRawData GetBosDescriptor()
构建 BOS 描述符(BOS 头 + 能力块) Build BOS descriptor (header + blocks).
Definition bos.hpp:158
void ClearCapabilities()
清空已注册能力 / Clear registered capabilities
Definition bos.hpp:134
ErrorCode ProcessVendorRequest(bool in_isr, const SetupPacket *setup, BosVendorResult &result)
Vendor 请求分发 / Vendor request dispatch.
Definition bos.hpp:234
配置描述符字节构造器 Configuration descriptor byte builder.
Definition desc_cfg.hpp:209
RawData GetData() const
获取配置描述符数据 / Get configuration descriptor data
Definition desc_cfg.cpp:111
ErrorCode BuildConfigDescriptor(ConfigDescriptorItem *const *items, size_t item_num, uint8_t configuration_value, uint8_t i_configuration=0)
构建指定 configuration 的描述符 Build the descriptor for the specified configuration.
Definition desc_cfg.cpp:62
USB 配置项基类(功能块)/ USB configuration item base (functional block)
Definition desc_cfg.hpp:36
virtual size_t GetInterfaceCount()=0
接口数量 / Number of interfaces contributed
virtual void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool in_isr)=0
绑定端点资源 / Bind endpoint resources
virtual bool HasIAD()=0
是否包含 IAD / Whether an IAD is used
virtual ErrorCode WriteDeviceDescriptor(DeviceDescriptor &header)
可选:覆盖设备描述符字段 / Optional: override device descriptor fields
Definition desc_cfg.hpp:122
virtual void UnbindEndpoints(EndpointPool &endpoint_pool, bool in_isr)=0
解绑端点资源 / Unbind endpoint resources
virtual bool OwnsEndpoint(uint8_t ep_addr) const
可选:端点归属判定 / Optional: endpoint ownership
Definition desc_cfg.hpp:158
字符串描述符管理器 / USB string descriptor manager
Definition desc_str.hpp:15
bool HasLanguage(uint16_t lang) const
检查是否注册了指定语言 / Check whether the given language is registered
Definition desc_str.cpp:151
RawData GetData()
获取当前构建好的字符串描述符数据 Get the descriptor buffer
Definition desc_str.cpp:139
RawData GetLangIDData()
获取语言ID描述符内容 Get LangID descriptor data
Definition desc_str.cpp:146
Index
描述符字符串索引 / USB descriptor string index
Definition desc_str.hpp:21
@ SERIAL_NUMBER_STRING
序列号字符串索引 / Serial number string
ErrorCode GenerateString(Index index, uint16_t lang)
生成指定语言和索引的字符串描述符 Generate USB string descriptor for given language and string index
Definition desc_str.cpp:58
USB 设备类接口基类 / USB device class interface base.
BosCapability * GetBosCapability(size_t index) override
返回指定 BOS capability Return the BOS capability at the given index.
size_t GetBosCapabilityCount() override
返回本类提供的 BOS capability 数量 Return the number of BOS capabilities exposed by this class.
size_t class_count_
唯一 class 数量 / Unique class count
void Deinit(bool in_isr)
释放当前 configuration 的运行态资源 Release runtime resources for the active configuration.
const ConfigItems & CurrentConfigItems() const
获取当前激活 configuration 的扁平 item 表 Get the flattened item table of the active configuration.
void RegisterInterfaceStrings()
为所有 class 分配并登记 interface string 索引 Allocate and register interface-string indices for all classes.
bool ep_assigned_
端点是否已绑定 / Whether endpoints are assigned
ConfigItems * items_
配置项集合 / Configuration item set
DeviceClass ** classes_
唯一 class 表 / Unique class table
ErrorCode TryOverrideDeviceDescriptor(DeviceDescriptor &descriptor)
用当前配置覆盖 device descriptor 的类字段 Try to override device-descriptor class fields from the current config...
uint8_t i_configuration_
配置字符串索引 / Configuration string index
const bool composite_
是否为复合设备 / Whether composite device
RawData GetConfigDescriptor() const
获取当前 configuration 描述符缓存 Get the current configuration descriptor cache.
bool configured_
是否已进入非 0 配置态 / Whether a non-zero config is active
const size_t config_num_
配置数量 / Configuration count
uint8_t bm_attributes_
配置属性 / bmAttributes
const char ** interface_strings_
接口字符串源表 / Interface string source table
EndpointPool & endpoint_pool_
端点池引用 / Endpoint pool reference
DescriptorStrings strings_
字符串描述符管理 / String descriptor manager
BosManager bos_
BOS 聚合管理 / BOS aggregation manager.
RawData interface_string_buffer_
临时字符串描述符缓冲区 / Temp interface string descriptor buffer
ErrorCode SwitchConfig(size_t index, bool in_isr)
切换到指定 configuration value Switch to the given configuration value.
void BindEndpoints(bool in_isr)
绑定当前配置的全部端点 / Bind all endpoints for the active configuration
uint8_t current_cfg_
当前配置索引 / Current configuration index
DeviceComposition(EndpointPool &endpoint_pool, const std::initializer_list< const DescriptorStrings::LanguagePack * > &lang_list, const std::initializer_list< const std::initializer_list< ConfigDescriptorItem * > > &configs, ConstRawData uid={nullptr, 0}, uint8_t bmAttributes=CFG_BUS_POWERED, uint8_t bMaxPower=50)
构造 USB 组合管理器 Construct the USB composition manager.
DeviceClass * FindClassByInterfaceNumber(size_t index) const
按接口号查找所属 class Find the owning class by interface number.
uint16_t GetDeviceStatus() const
设备 GET_STATUS 返回值 / Device-level GET_STATUS value
ErrorCode GetStringDescriptor(uint8_t string_index, uint16_t lang, ConstRawData &data)
获取字符串描述符(含 interface string) Get a string descriptor, including runtime-generated interface strings.
DeviceClass * FindClassByEndpointAddress(uint8_t addr) const
按端点地址查找所属 class Find the owning class by endpoint address.
void RebuildBosCache()
按当前配置重建 BOS capability 缓存 Rebuild the BOS capability cache from the active configuration.
size_t GetConfigNum() const
配置数量 / Number of configurations
void UnbindEndpoints(bool in_isr)
解绑当前配置的全部端点 / Unbind all endpoints for the active configuration
void Init(bool in_isr)
初始化当前 configuration 的运行态资源 Initialize runtime resources for the active configuration.
ErrorCode ProcessBosVendorRequest(bool in_isr, const SetupPacket *setup, BosVendorResult &result)
分发 BOS vendor request / Dispatch BOS vendor requests
ConstRawData GetBosDescriptor()
获取当前 BOS 描述符缓存 / Get the current BOS descriptor cache
bool IsComposite() const
是否为复合设备 / Whether this is a composite device
size_t interface_string_count_
接口字符串总数量 / Total interface string count
size_t GetCurrentConfig() const
当前 configuration value / Current configuration value
ErrorCode BuildConfigDescriptor()
生成当前 configuration 描述符缓存 Build the current configuration descriptor cache.
ConfigDescriptor config_desc_
配置描述符构造器 / Configuration descriptor builder
ErrorCode GenerateInterfaceString(uint8_t string_index, ConstRawData &data)
运行时生成 interface string 描述符 Generate one interface-string descriptor at runtime.
USB描述符基类 USB descriptor base class.
Definition desc_dev.hpp:40
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
ErrorCode
定义错误码枚举
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
Vendor 请求处理结果(EP0 控制传输) Vendor request handling result for EP0 control transfers.
Definition bos.hpp:45
单个 configuration 的扁平 item 表 Flattened item table for one configuration.
ConfigDescriptorItem ** items
配置项指针表 / Item pointer table
size_t item_num
配置项数量 / Item count
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)
Definition core.hpp:57