libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
desc_cfg.cpp
1#include "desc_cfg.hpp"
2
3#include <cstddef>
4#include <cstdint>
5
6#include "usb/core/bos.hpp"
7
8namespace
9{
10using LibXR::USB::BOS_HEADER_SIZE;
13using LibXR::USB::DESCRIPTOR_TYPE_DEVICE_CAPABILITY;
14using LibXR::USB::DEV_CAPABILITY_TYPE_USB20EXT;
15
18static bool config_contains_iad(const std::initializer_list<ConfigDescriptorItem*>& group)
19{
20 for (auto* item : group)
21 {
22 if (item != nullptr && item->HasIAD())
23 {
24 return true;
25 }
26 }
27 return false;
28}
29
32static bool is_composite_config(const std::initializer_list<ConfigDescriptorItem*>& group)
33{
34 return (group.size() > 1) || config_contains_iad(group);
35}
36
39static bool is_device_descriptor_override_eligible(ConfigDescriptorItem* const* items,
40 size_t item_num)
41{
42 if (item_num != 1)
43 {
44 return false;
45 }
46
47 auto* item = items[0];
48 if (item == nullptr)
49 {
50 return false;
51 }
52
53 if (item->HasIAD())
54 {
55 return false;
56 }
57
58 return (item->GetInterfaceCount() == 1);
59}
60
63static size_t calc_bos_capability_num_max(
64 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
65 configs)
66{
67 size_t max_num = 0;
68 for (const auto& group : configs)
69 {
70 size_t num = 0;
71 for (auto* item : group)
72 {
73 if (item == nullptr)
74 {
75 continue;
76 }
77 num += item->GetBosCapabilityCount();
78 }
79 if (num > max_num)
80 {
81 max_num = num;
82 }
83 }
84 return max_num;
85}
86
89static size_t calc_bos_descriptor_size_max(
90 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
91 configs)
92{
93 static constexpr size_t USB2_EXT_SIZE = 7;
94
95 size_t max_total = BOS_HEADER_SIZE;
96 for (const auto& group : configs)
97 {
98 size_t cap_bytes = 0;
99 bool has_usb2_ext = false;
100
101 for (auto* item : group)
102 {
103 if (item == nullptr)
104 {
105 continue;
106 }
107
108 const size_t CAP_NUM = item->GetBosCapabilityCount();
109 for (size_t i = 0; i < CAP_NUM; ++i)
110 {
111 BosCapability* cap = item->GetBosCapability(i);
112 if (cap == nullptr)
113 {
114 continue;
115 }
116
117 auto blk = cap->GetCapabilityDescriptor();
118 ASSERT(blk.addr_ != nullptr);
119 ASSERT(blk.size_ >= 3);
120
121 cap_bytes += blk.size_;
122
123 const uint8_t* p = reinterpret_cast<const uint8_t*>(blk.addr_);
124 if (p[1] == DESCRIPTOR_TYPE_DEVICE_CAPABILITY &&
125 p[2] == DEV_CAPABILITY_TYPE_USB20EXT)
126 {
127 has_usb2_ext = true;
128 }
129 }
130 }
131
132 const size_t TOTAL = BOS_HEADER_SIZE + cap_bytes + (has_usb2_ext ? 0 : USB2_EXT_SIZE);
133 if (TOTAL > max_total)
134 {
135 max_total = TOTAL;
136 }
137 }
138
139 ASSERT(max_total <= 0xFFFF);
140 return max_total;
141}
142
143} // namespace
144
145using namespace LibXR::USB;
146
148{
151 if (CFG_NUM != 1)
152 {
153 return false;
154 }
155
156 const auto CFG = items_[0];
157 return is_device_descriptor_override_eligible(CFG.items, CFG.item_num);
158}
159
161 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
162 configs)
163{
166 for (const auto& group : configs)
167 {
168 if (is_composite_config(group))
169 {
170 return true;
171 }
172 }
173 return false;
174}
175
177
179{
183
184 ASSERT(CFG_NUM > 0);
185 ASSERT(current_cfg_ < CFG_NUM);
186
187 const auto CFG = items_[current_cfg_];
188
189 for (size_t i = 0; i < CFG.item_num; ++i)
190 {
191 auto* item = CFG.items[i];
192 if (item == nullptr)
193 {
194 continue;
195 }
196
197 const size_t CAP_NUM = item->GetBosCapabilityCount();
198 for (size_t j = 0; j < CAP_NUM; ++j)
199 {
200 auto* cap = item->GetBosCapability(j);
201 if (cap == nullptr)
202 {
203 continue;
204 }
205 AddCapability(cap);
206 }
207 }
208
209 (void)GetBosDescriptor();
210}
211
213 EndpointPool& endpoint_pool,
214 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
215 configs,
216 uint8_t bmAttributes, uint8_t bMaxPower)
217 : BosManager(calc_bos_descriptor_size_max(configs),
218 calc_bos_capability_num_max(configs)),
219 endpoint_pool_(endpoint_pool),
220 bm_attributes_(bmAttributes),
221 b_max_power_(bMaxPower),
222 COMPOSITE(IsCompositeConfig(configs)),
223 CFG_NUM(configs.size()),
224 items_(new Config[CFG_NUM])
225{
226 ASSERT(CFG_NUM > 0);
227
228 size_t max_config_size = 0;
229 size_t config_index = 0;
230
231 for (const auto& cfg_group : configs)
232 {
233 size_t config_size = sizeof(Header);
234
235 items_[config_index].item_num = cfg_group.size();
236 items_[config_index].items = new ConfigDescriptorItem*[cfg_group.size()];
237
238 size_t item_index = 0;
239 for (auto* item : cfg_group)
240 {
241 items_[config_index].items[item_index] = item;
242 if (item != nullptr)
243 {
244 config_size += item->GetMaxConfigSize();
245 }
246 ++item_index;
247 }
248
249 if (config_size > max_config_size)
250 {
251 max_config_size = config_size;
252 }
253 ++config_index;
254 }
255
256 buffer_.addr_ = new uint8_t[max_config_size];
257 buffer_.size_ = max_config_size;
258}
259
260ErrorCode ConfigDescriptor::SwitchConfig(size_t index, bool in_isr)
261{
264 if (index == 0 || index > CFG_NUM)
265 {
266 return ErrorCode::NOT_FOUND;
267 }
268
269 UnbindEndpoints(in_isr);
270 current_cfg_ = index - 1;
271 BindEndpoints(in_isr);
272 return ErrorCode::OK;
273}
274
276{
277 if (ep_assigned_)
278 {
279 return;
280 }
281 ep_assigned_ = true;
282
283 const auto CFG = items_[current_cfg_];
284
285 size_t start_itf = 0;
286 for (size_t i = 0; i < CFG.item_num; ++i)
287 {
288 auto* item = CFG.items[i];
289 if (item == nullptr)
290 {
291 continue;
292 }
293
294 item->BindEndpoints(endpoint_pool_, start_itf, in_isr);
295 start_itf += item->GetInterfaceCount();
296 }
297}
298
300{
301 if (!ep_assigned_)
302 {
303 return;
304 }
305 ep_assigned_ = false;
306
307 const auto CFG = items_[current_cfg_];
308
309 for (size_t i = 0; i < CFG.item_num; ++i)
310 {
311 auto* item = CFG.items[i];
312 if (item == nullptr)
313 {
314 continue;
315 }
316 item->UnbindEndpoints(endpoint_pool_, in_isr);
317 }
318}
319
321{
322 uint8_t* buffer = reinterpret_cast<uint8_t*>(buffer_.addr_);
323 Header* header = reinterpret_cast<Header*>(buffer);
324
326 *header = Header{};
327
328 header->bLength = 9;
329 header->bDescriptorType = 0x02;
330 header->bConfigurationValue = static_cast<uint8_t>(current_cfg_ + 1);
333 header->bMaxPower = b_max_power_;
334
335 size_t offset = sizeof(Header);
336 uint8_t total_interfaces = 0;
337
338 const auto CFG = items_[current_cfg_];
339
340 for (size_t i = 0; i < CFG.item_num; ++i)
341 {
342 auto* item = CFG.items[i];
343 if (item == nullptr)
344 {
345 continue;
346 }
347
348 auto data = item->GetData();
349 LibXR::Memory::FastCopy(&buffer[offset], data.addr_, data.size_);
350 offset += data.size_;
351
352 total_interfaces = static_cast<uint8_t>(total_interfaces + item->GetInterfaceCount());
353 }
354
355 ASSERT(offset <= 0xFFFF);
356 header->wTotalLength = static_cast<uint16_t>(offset);
357 header->bNumInterfaces = total_interfaces;
358
359 buffer_index_ = offset;
360 return ErrorCode::OK;
361}
362
364
366{
368 {
369 return ErrorCode::NOT_SUPPORT;
370 }
371
372 const auto CFG = items_[0];
373 if (CFG.item_num != 1 || CFG.items == nullptr || CFG.items[0] == nullptr)
374 {
375 return ErrorCode::NOT_SUPPORT;
376 }
377
378 return CFG.items[0]->WriteDeviceDescriptor(descriptor);
379}
380
382
383size_t ConfigDescriptor::GetConfigNum() const { return CFG_NUM; }
384
386
388{
389 return ((bm_attributes_ & CFG_SELF_POWERED) ? 0x01 : 0x00) |
390 ((bm_attributes_ & CFG_REMOTE_WAKEUP) ? 0x02 : 0x00);
391}
392
394{
396 const auto CFG = items_[current_cfg_];
397
398 int interface_index = -1;
399 for (size_t i = 0; i < CFG.item_num; ++i)
400 {
401 auto* item = CFG.items[i];
402 if (item == nullptr)
403 {
404 continue;
405 }
406
407 interface_index += static_cast<int>(item->GetInterfaceCount());
408 if (interface_index >= static_cast<int>(index))
409 {
410 return item;
411 }
412 }
413 return nullptr;
414}
415
417{
418 const auto CFG = items_[current_cfg_];
419
420 for (size_t i = 0; i < CFG.item_num; ++i)
421 {
422 auto* item = CFG.items[i];
423 if (item == nullptr)
424 {
425 continue;
426 }
427
428 if (item->OwnsEndpoint(addr))
429 {
430 return item;
431 }
432 }
433 return nullptr;
434}
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:3
原始数据封装类。 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:56
virtual ConstRawData GetCapabilityDescriptor() const =0
返回能力块(不含 BOS 头) Return capability block (without BOS header).
BOS 管理器:能力收集、BOS 描述符拼装、Vendor 请求链式分发 BOS manager: capability collection, descriptor building,...
Definition bos.hpp:116
bool AddCapability(BosCapability *cap)
添加能力 / Add capability
Definition bos.hpp:165
ConstRawData GetBosDescriptor()
构建 BOS 描述符(BOS 头 + 能力块) Build BOS descriptor (header + blocks).
Definition bos.hpp:181
void ClearCapabilities()
清空已注册能力 / Clear registered capabilities
Definition bos.hpp:153
bool IsComposite() const
是否为复合设备 / Whether composite device
Definition desc_cfg.cpp:363
RawData GetData() const
获取配置描述符数据 / Get configuration descriptor data
Definition desc_cfg.cpp:381
ConfigDescriptorItem * FindItemByInterfaceNumber(size_t index) const
按接口号查找配置项 / Find item by interface number
Definition desc_cfg.cpp:393
uint8_t i_configuration_
配置字符串索引 / Configuration string index
Definition desc_cfg.hpp:332
uint8_t bm_attributes_
配置属性 / bmAttributes
Definition desc_cfg.hpp:333
bool CanOverrideDeviceDescriptor() const
是否允许覆盖设备描述符 / Whether device descriptor override is allowed
Definition desc_cfg.cpp:147
uint16_t GetDeviceStatus() const
设备状态(GET_STATUS)/ Device status (GET_STATUS)
Definition desc_cfg.cpp:387
ErrorCode OverrideDeviceDescriptor(DeviceDescriptor &descriptor)
覆盖设备描述符 / Override device descriptor
Definition desc_cfg.cpp:365
uint8_t current_cfg_
当前配置索引 / Current configuration index
Definition desc_cfg.hpp:331
void BindEndpoints(bool in_isr)
绑定当前配置端点 / Bind endpoints for current configuration
Definition desc_cfg.cpp:275
size_t GetConfigNum() const
配置数量 / Number of configurations
Definition desc_cfg.cpp:383
bool ep_assigned_
端点是否已绑定 / Whether endpoints are assigned
Definition desc_cfg.hpp:328
ConfigDescriptorItem * FindItemByEndpointAddress(uint8_t addr) const
按端点地址查找配置项 / Find item by endpoint address
Definition desc_cfg.cpp:416
const bool COMPOSITE
是否为复合设备 / Whether composite device
Definition desc_cfg.hpp:336
size_t buffer_index_
缓冲区写入位置 / Buffer write index
Definition desc_cfg.hpp:341
ErrorCode BuildConfigDescriptor()
构建当前配置描述符 / Build current configuration descriptor
Definition desc_cfg.cpp:320
EndpointPool & endpoint_pool_
端点池引用 / Endpoint pool reference
Definition desc_cfg.hpp:330
static bool IsCompositeConfig(const std::initializer_list< const std::initializer_list< ConfigDescriptorItem * > > &configs)
Definition desc_cfg.cpp:160
uint8_t b_max_power_
最大电流(2mA 单位)/ Max power (2mA units)
Definition desc_cfg.hpp:334
const size_t CFG_NUM
配置数量 / Configuration count
Definition desc_cfg.hpp:337
ConfigDescriptor(EndpointPool &endpoint_pool, const std::initializer_list< const std::initializer_list< ConfigDescriptorItem * > > &configs, uint8_t bmAttributes=CFG_BUS_POWERED, uint8_t bMaxPower=50)
构造函数 / Constructor
Definition desc_cfg.cpp:212
void RebuildBosCache()
重建 BOS 缓存 / Rebuild BOS cache
Definition desc_cfg.cpp:178
Config * items_
配置项集合 / Configuration item set
Definition desc_cfg.hpp:338
RawData buffer_
配置描述符缓冲区 / Configuration descriptor buffer
Definition desc_cfg.hpp:340
size_t GetCurrentConfig() const
当前配置索引 / Current configuration index
Definition desc_cfg.cpp:385
ErrorCode SwitchConfig(size_t index, bool in_isr)
切换当前 configuration / Switch current configuration
Definition desc_cfg.cpp:260
void UnbindEndpoints(bool in_isr)
解绑当前配置端点 / Unbind endpoints for current configuration
Definition desc_cfg.cpp:299
USB 配置项基类(功能块)/ USB configuration item base (functional block)
Definition desc_cfg.hpp:37
RawData GetData()
获取内部数据缓存 / Get internal data cache
Definition desc_cfg.cpp:176
RawData data_
内部数据缓存 / Internal data cache
Definition desc_cfg.hpp:199
virtual ErrorCode WriteDeviceDescriptor(DeviceDescriptor &header)
可选:覆盖设备描述符字段 / Optional: override device descriptor fields
Definition desc_cfg.hpp:123
USB描述符基类 USB descriptor base class.
Definition desc_dev.hpp:40
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
单个 configuration 的配置项集合 / Item set for one configuration
Definition desc_cfg.hpp:214
size_t item_num
配置项数量 / Item count
Definition desc_cfg.hpp:216
ConfigDescriptorItem ** items
配置项指针表 / Item pointer table
Definition desc_cfg.hpp:215
配置描述符头(9 字节)/ Configuration descriptor header (9 bytes)
Definition desc_cfg.hpp:46
uint8_t bLength
描述符长度 / Descriptor length
Definition desc_cfg.hpp:47
uint8_t bmAttributes
属性位 / Attributes
Definition desc_cfg.hpp:53
uint8_t bNumInterfaces
接口数量 / Number of interfaces
Definition desc_cfg.hpp:50
uint8_t bMaxPower
最大电流(2mA 单位)/ Max power (2mA units)
Definition desc_cfg.hpp:54
uint8_t bConfigurationValue
配置值 / Configuration value
Definition desc_cfg.hpp:51
uint8_t iConfiguration
配置字符串索引 / Configuration string index
Definition desc_cfg.hpp:52
uint16_t wTotalLength
配置总长度 / Total configuration length
Definition desc_cfg.hpp:49
uint8_t bDescriptorType
描述符类型(0x02)/ Descriptor type (0x02)
Definition desc_cfg.hpp:48