libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
LibXR::USB::DeviceComposition Class Reference

USB 组合管理器:class 列表、字符串、BOS、配置切换 USB composition manager: class list, strings, BOS, and configuration switching. More...

#include <device_composition.hpp>

Public Member Functions

 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.
 
 DeviceComposition (const DeviceComposition &)=delete
 
DeviceComposition & operator= (const DeviceComposition &)=delete
 
 DeviceComposition (DeviceComposition &&)=delete
 
DeviceComposition & operator= (DeviceComposition &&)=delete
 
void Init (bool in_isr)
 初始化当前 configuration 的运行态资源 Initialize runtime resources for the active configuration.
 
void Deinit (bool in_isr)
 释放当前 configuration 的运行态资源 Release runtime resources for the active configuration.
 
ErrorCode SwitchConfig (size_t index, bool in_isr)
 切换到指定 configuration value Switch to the given configuration value.
 
ErrorCode BuildConfigDescriptor ()
 生成当前 configuration 描述符缓存 Build the current configuration descriptor cache.
 
RawData GetConfigDescriptor () const
 获取当前 configuration 描述符缓存 Get the current configuration descriptor cache.
 
ConstRawData GetBosDescriptor ()
 获取当前 BOS 描述符缓存 / Get the current BOS descriptor cache
 
ErrorCode ProcessBosVendorRequest (bool in_isr, const SetupPacket *setup, BosVendorResult &result)
 分发 BOS vendor request / Dispatch BOS vendor requests
 
ErrorCode GetStringDescriptor (uint8_t string_index, uint16_t lang, ConstRawData &data)
 获取字符串描述符(含 interface string) Get a string descriptor, including runtime-generated interface strings.
 
bool IsComposite () const
 是否为复合设备 / Whether this is a composite device
 
ErrorCode TryOverrideDeviceDescriptor (DeviceDescriptor &descriptor)
 用当前配置覆盖 device descriptor 的类字段 Try to override device-descriptor class fields from the current configuration.
 
size_t GetConfigNum () const
 配置数量 / Number of configurations
 
size_t GetCurrentConfig () const
 当前 configuration value / Current configuration value
 
uint16_t GetDeviceStatus () const
 设备 GET_STATUS 返回值 / Device-level GET_STATUS value
 
DeviceClass * FindClassByInterfaceNumber (size_t index) const
 按接口号查找所属 class Find the owning class by interface number.
 
DeviceClass * FindClassByEndpointAddress (uint8_t addr) const
 按端点地址查找所属 class Find the owning class by endpoint address.
 

Detailed Description

USB 组合管理器:class 列表、字符串、BOS、配置切换 USB composition manager: class list, strings, BOS, and configuration switching.

Definition at line 20 of file device_composition.hpp.

Constructor & Destructor Documentation

◆ DeviceComposition()

DeviceComposition::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.

负责把 class/config/string/BOS 相关静态信息整理成 DeviceCore 可直接使用的形态。 This flattens class/config/string/BOS metadata into the shape consumed by DeviceCore.

Definition at line 345 of file device_composition.cpp.

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;
395 if (interface_string_count_ > 0)
396 {
397 interface_strings_ = new const char*[interface_string_count_];
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
402 RegisterInterfaceStrings();
403}
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
static size_t CalcMaxConfigSize(const std::initializer_list< const std::initializer_list< ConfigDescriptorItem * > > &configs)
计算所有 configuration 中需要的最大缓冲区大小 Calculate the maximum buffer size required across all configurations.
Definition desc_cfg.cpp:55
USB 配置项基类(功能块)/ USB configuration item base (functional block)
Definition desc_cfg.hpp:36
USB 设备类接口基类 / USB device class interface base.

Member Function Documentation

◆ BuildConfigDescriptor()

LibXR::ErrorCode DeviceComposition::BuildConfigDescriptor ( )

生成当前 configuration 描述符缓存 Build the current configuration descriptor cache.

Definition at line 454 of file device_composition.cpp.

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),
464 i_configuration_);
465}
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

◆ Deinit()

void DeviceComposition::Deinit ( bool in_isr)

释放当前 configuration 的运行态资源 Release runtime resources for the active configuration.

Definition at line 421 of file device_composition.cpp.

422{
423 UnbindEndpoints(in_isr);
424 configured_ = false;
425 current_cfg_ = 0;
426}

◆ FindClassByEndpointAddress()

DeviceClass * DeviceComposition::FindClassByEndpointAddress ( uint8_t addr) const
nodiscard

按端点地址查找所属 class Find the owning class by endpoint address.

Definition at line 573 of file device_composition.cpp.

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}

◆ FindClassByInterfaceNumber()

DeviceClass * DeviceComposition::FindClassByInterfaceNumber ( size_t index) const
nodiscard

按接口号查找所属 class Find the owning class by interface number.

Definition at line 541 of file device_composition.cpp.

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}

◆ GetBosDescriptor()

ConstRawData DeviceComposition::GetBosDescriptor ( )
nodiscard

获取当前 BOS 描述符缓存 / Get the current BOS descriptor cache

Definition at line 469 of file device_composition.cpp.

469{ return bos_.GetBosDescriptor(); }
ConstRawData GetBosDescriptor()
构建 BOS 描述符(BOS 头 + 能力块) Build BOS descriptor (header + blocks).
Definition bos.hpp:158

◆ GetConfigDescriptor()

RawData DeviceComposition::GetConfigDescriptor ( ) const
nodiscard

获取当前 configuration 描述符缓存 Get the current configuration descriptor cache.

Definition at line 467 of file device_composition.cpp.

467{ return config_desc_.GetData(); }
RawData GetData() const
获取配置描述符数据 / Get configuration descriptor data
Definition desc_cfg.cpp:111

◆ GetConfigNum()

size_t DeviceComposition::GetConfigNum ( ) const
nodiscard

配置数量 / Number of configurations

Definition at line 528 of file device_composition.cpp.

528{ return config_num_; }

◆ GetCurrentConfig()

size_t DeviceComposition::GetCurrentConfig ( ) const
nodiscard

当前 configuration value / Current configuration value

Definition at line 530 of file device_composition.cpp.

531{
532 return configured_ ? static_cast<size_t>(current_cfg_ + 1u) : 0u;
533}

◆ GetDeviceStatus()

uint16_t DeviceComposition::GetDeviceStatus ( ) const
nodiscard

设备 GET_STATUS 返回值 / Device-level GET_STATUS value

Definition at line 535 of file device_composition.cpp.

536{
537 return ((bm_attributes_ & CFG_SELF_POWERED) ? 0x01 : 0x00) |
538 ((bm_attributes_ & CFG_REMOTE_WAKEUP) ? 0x02 : 0x00);
539}

◆ GetStringDescriptor()

LibXR::ErrorCode DeviceComposition::GetStringDescriptor ( uint8_t string_index,
uint16_t lang,
ConstRawData & data )

获取字符串描述符(含 interface string) Get a string descriptor, including runtime-generated interface strings.

Definition at line 478 of file device_composition.cpp.

480{
481 if (string_index == 0)
482 {
483 data = ConstRawData(strings_.GetLangIDData());
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}
只读原始数据视图 / Immutable raw data view
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
@ NOT_FOUND
未找到 / Not found
@ OK
操作成功 / Operation successful

◆ Init()

void DeviceComposition::Init ( bool in_isr)

初始化当前 configuration 的运行态资源 Initialize runtime resources for the active configuration.

Definition at line 412 of file device_composition.cpp.

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);
418 RebuildBosCache();
419}

◆ IsComposite()

bool DeviceComposition::IsComposite ( ) const
nodiscard

是否为复合设备 / Whether this is a composite device

Definition at line 509 of file device_composition.cpp.

509{ return composite_; }

◆ ProcessBosVendorRequest()

LibXR::ErrorCode DeviceComposition::ProcessBosVendorRequest ( bool in_isr,
const SetupPacket * setup,
BosVendorResult & result )

分发 BOS vendor request / Dispatch BOS vendor requests

Definition at line 471 of file device_composition.cpp.

474{
475 return bos_.ProcessVendorRequest(in_isr, setup, result);
476}
ErrorCode ProcessVendorRequest(bool in_isr, const SetupPacket *setup, BosVendorResult &result)
Vendor 请求分发 / Vendor request dispatch.
Definition bos.hpp:234

◆ SwitchConfig()

LibXR::ErrorCode DeviceComposition::SwitchConfig ( size_t index,
bool in_isr )

切换到指定 configuration value Switch to the given configuration value.

Definition at line 428 of file device_composition.cpp.

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;
440 RebuildBosCache();
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);
450 RebuildBosCache();
452}

◆ TryOverrideDeviceDescriptor()

LibXR::ErrorCode DeviceComposition::TryOverrideDeviceDescriptor ( DeviceDescriptor & descriptor)

用当前配置覆盖 device descriptor 的类字段 Try to override device-descriptor class fields from the current configuration.

Definition at line 511 of file device_composition.cpp.

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}
virtual ErrorCode WriteDeviceDescriptor(DeviceDescriptor &header)
可选:覆盖设备描述符字段 / Optional: override device descriptor fields
Definition desc_cfg.hpp:122
@ NOT_SUPPORT
不支持 / Not supported

The documentation for this class was generated from the following files: