1#include "device_composition.hpp"
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;
18struct InterfaceStringLayout
26static size_t calc_total_item_num(
27 const std::initializer_list<
const std::initializer_list<ConfigDescriptorItem*>>&
34 for (
const auto& group : configs)
36 total += group.size();
44static bool contains_class(
DeviceClass*
const* list,
size_t count,
47 for (
size_t i = 0; i < count; ++i)
59static size_t calc_utf16le_len_runtime(
const char* input)
67 for (
size_t i = 0; input[i];)
69 unsigned char c =
static_cast<unsigned char>(input[i]);
75 else if ((c & 0xE0) == 0xC0)
80 else if ((c & 0xF0) == 0xE0)
97static void to_utf16le(
const char* str, uint8_t* buffer)
100 const unsigned char* s =
reinterpret_cast<const unsigned char*
>(str);
104 uint32_t codepoint = 0;
110 else if ((*s & 0xE0) == 0xC0)
112 codepoint = (*s & 0x1F) << 6;
114 codepoint |= (*s & 0x3F);
117 else if ((*s & 0xF0) == 0xE0)
119 codepoint = (*s & 0x0F) << 12;
121 codepoint |= (*s & 0x3F) << 6;
123 codepoint |= (*s & 0x3F);
126 else if ((*s & 0xF8) == 0xF0)
149 buffer[len++] = codepoint & 0xFF;
150 buffer[len++] = (codepoint >> 8) & 0xFF;
157static InterfaceStringLayout calc_interface_string_layout(
DeviceClass*
const* classes,
164 InterfaceStringLayout layout{};
165 for (
size_t class_index = 0; class_index < class_count; ++class_index)
167 auto* device_class = classes[class_index];
168 if (device_class ==
nullptr)
174 for (
size_t i = 0; i < interface_num; ++i)
176 const char* str = device_class->GetInterfaceString(i);
177 if (str ==
nullptr || str[0] ==
'\0')
183 const size_t utf16_len = calc_utf16le_len_runtime(str);
184 if (utf16_len > layout.max_len)
186 layout.max_len = utf16_len;
195static bool config_contains_iad(
const std::initializer_list<ConfigDescriptorItem*>& group)
197 for (
auto* item : group)
199 if (item !=
nullptr && item->
HasIAD())
207static bool is_composite_config(
const std::initializer_list<ConfigDescriptorItem*>& group)
209 return (group.size() > 1) || config_contains_iad(group);
224 auto* item = items[0];
238static bool is_composite_device(
239 const std::initializer_list<
const std::initializer_list<ConfigDescriptorItem*>>&
242 for (
const auto& group : configs)
244 if (is_composite_config(group))
256static size_t calc_bos_capability_num_max(
257 const std::initializer_list<
const std::initializer_list<ConfigDescriptorItem*>>&
261 for (
const auto& group : configs)
264 for (
auto* item : group)
285static size_t calc_bos_descriptor_size_max(
286 const std::initializer_list<
const std::initializer_list<ConfigDescriptorItem*>>&
289 static constexpr size_t usb2_ext_size = 7;
291 size_t max_total = BOS_HEADER_SIZE;
292 for (
const auto& group : configs)
294 size_t cap_bytes = 0;
295 bool has_usb2_ext =
false;
297 for (
auto* item : group)
305 for (
size_t i = 0; i < capability_num; ++i)
314 ASSERT(blk.addr_ !=
nullptr);
315 ASSERT(blk.size_ >= 3);
317 cap_bytes += blk.size_;
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)
328 const size_t total = BOS_HEADER_SIZE + cap_bytes + (has_usb2_ext ? 0 : usb2_ext_size);
329 if (total > max_total)
335 ASSERT(max_total <= 0xFFFF);
341using namespace LibXR::USB;
347 const std::initializer_list<const DescriptorStrings::LanguagePack*>& lang_list,
348 const std::initializer_list<
const std::initializer_list<ConfigDescriptorItem*>>&
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()),
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)
369 size_t config_index = 0;
370 for (
const auto& cfg_group : configs)
375 size_t item_index = 0;
376 for (
auto* item : cfg_group)
379 auto* device_class =
static_cast<DeviceClass*
>(item);
380 if (device_class !=
nullptr &&
392 const auto interface_string_layout =
481 if (string_index == 0)
519 const auto config =
items_[0];
520 if (!is_device_descriptor_override_eligible(config.items, config.item_num))
554 int interface_index = -1;
555 for (
size_t i = 0; i < config.item_num; ++i)
557 auto* item = config.items[i];
564 if (interface_index >=
static_cast<int>(index))
582 for (
size_t i = 0; i < config.item_num; ++i)
584 auto* item = config.items[i];
611 size_t start_itf = 0;
612 for (
size_t i = 0; i < config.item_num; ++i)
614 auto* item = config.items[i];
636 for (
size_t i = 0; i < config.item_num; ++i)
638 auto* item = config.items[i];
654 for (
size_t i = 0; i < config.item_num; ++i)
656 auto* item = config.items[i];
663 for (
size_t j = 0; j < capability_num; ++j)
681 const size_t base_index =
683 if (string_index <= base_index)
688 const size_t extra_index =
static_cast<size_t>(string_index - base_index - 1u);
696 const size_t utf16_len = calc_utf16le_len_runtime(str);
697 ASSERT(utf16_len + 2 <= 255);
702 buffer[0] =
static_cast<uint8_t
>(utf16_len + 2);
703 to_utf16le(str, buffer + 2);
719 size_t registered_count = 0u;
721 for (
size_t class_index = 0; class_index <
class_count_; ++class_index)
723 auto* device_class =
classes_[class_index];
724 if (device_class ==
nullptr)
730 device_class->SetInterfaceStringBaseIndex(0u);
731 bool class_has_string =
false;
733 for (
size_t i = 0; i < interface_num; ++i)
735 const char* str = device_class->GetInterfaceString(i);
736 if (str ==
nullptr || str[0] ==
'\0')
748 if (!class_has_string)
750 device_class->SetInterfaceStringBaseIndex(next_index);
751 class_has_string =
true;
常量原始数据封装类。 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.
virtual ConstRawData GetCapabilityDescriptor() const =0
返回能力块(不含 BOS 头) Return capability block (without BOS header).
bool AddCapability(BosCapability *cap)
添加能力 / Add capability
ConstRawData GetBosDescriptor()
构建 BOS 描述符(BOS 头 + 能力块) Build BOS descriptor (header + blocks).
void ClearCapabilities()
清空已注册能力 / Clear registered capabilities
ErrorCode ProcessVendorRequest(bool in_isr, const SetupPacket *setup, BosVendorResult &result)
Vendor 请求分发 / Vendor request dispatch.
配置描述符字节构造器 Configuration descriptor byte builder.
RawData GetData() const
获取配置描述符数据 / Get configuration descriptor data
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.
USB 配置项基类(功能块)/ USB configuration item base (functional block)
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
virtual void UnbindEndpoints(EndpointPool &endpoint_pool, bool in_isr)=0
解绑端点资源 / Unbind endpoint resources
virtual bool OwnsEndpoint(uint8_t ep_addr) const
可选:端点归属判定 / Optional: endpoint ownership
字符串描述符管理器 / USB string descriptor manager
bool HasLanguage(uint16_t lang) const
检查是否注册了指定语言 / Check whether the given language is registered
RawData GetData()
获取当前构建好的字符串描述符数据 Get the descriptor buffer
RawData GetLangIDData()
获取语言ID描述符内容 Get LangID descriptor data
Index
描述符字符串索引 / USB descriptor string index
@ SERIAL_NUMBER_STRING
序列号字符串索引 / Serial number string
ErrorCode GenerateString(Index index, uint16_t lang)
生成指定语言和索引的字符串描述符 Generate USB string descriptor for given language and string index
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.
USB端点池类 / USB endpoint pool class.
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
Vendor 请求处理结果(EP0 控制传输) Vendor request handling result for EP0 control transfers.
单个 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)