libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
dev_core.cpp
1#include "dev_core.hpp"
2
3#include <cstdint>
4
5#include "core.hpp"
6#include "device_composition.hpp"
7#include "libxr_mem.hpp"
8#include "libxr_type.hpp"
9
10using namespace LibXR::USB;
11
13 EndpointPool& ep_pool, USBSpec spec, Speed speed,
14 DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid, uint16_t bcd,
15 const std::initializer_list<const DescriptorStrings::LanguagePack*>& lang_list,
16 const std::initializer_list<const std::initializer_list<ConfigDescriptorItem*>>&
17 configs,
18 ConstRawData uid)
19 : composition_(ep_pool, lang_list, configs, uid),
20 device_desc_(spec, packet_size, vid, pid, bcd, composition_.GetConfigNum()),
21 endpoint_({ep_pool, nullptr, nullptr, {}, {}}),
22 state_({false,
23 speed,
24 Context::UNKNOWN,
25 Context::UNKNOWN,
26 {nullptr, 0},
27 {nullptr, 0},
28 0xff,
29 nullptr,
30 false})
31{
32 ASSERT(IsValidUSBCombination(spec, speed, packet_size));
33
34 endpoint_.ep0_in_cb =
35 LibXR::Callback<LibXR::ConstRawData&>::Create(OnEP0InCompleteStatic, this);
36
37 endpoint_.ep0_out_cb =
38 LibXR::Callback<LibXR::ConstRawData&>::Create(OnEP0OutCompleteStatic, this);
39}
40
41void DeviceCore::OnEP0OutCompleteStatic(bool in_isr, DeviceCore* self,
43{
44 self->OnEP0OutComplete(in_isr, data);
45}
46
47void DeviceCore::OnEP0InCompleteStatic(bool in_isr, DeviceCore* self,
49{
50 self->OnEP0InComplete(in_isr, data);
51}
52
53bool DeviceCore::IsValidUSBCombination(USBSpec spec, Speed speed,
55{
56 const uint8_t SIZE = static_cast<uint8_t>(packet_size);
57
58 switch (speed)
59 {
60 case Speed::LOW:
61 // USB 1.0/1.1 可允许 LOW,包长必须为 8
62 // USB 1.0/1.1 allows LOW speed; EP0 max packet size must be 8.
63 return (spec == USBSpec::USB_1_0 || spec == USBSpec::USB_1_1) && SIZE == 8;
64
65 case Speed::FULL:
66 // USB 1.x/2.0 均可运行在 FULL
67 // USB 1.x/2.0 can run at FULL speed.
68 if (!(spec >= USBSpec::USB_1_0 && spec <= USBSpec::USB_2_1))
69 {
70 return false;
71 }
72 return SIZE == 8 || SIZE == 16 || SIZE == 32 || SIZE == 64;
73
74 case Speed::HIGH:
75 // 只有 USB 2.0+ 才能跑 HIGH,包长必须是 64
76 // Only USB 2.0+ supports HIGH speed; EP0 max packet size must be 64.
77 if (spec < USBSpec::USB_2_0)
78 {
79 return false;
80 }
81 return SIZE == 64;
82
83 case Speed::SUPER: // NOLINT
84 case Speed::SUPER_PLUS:
85 return false;
86
87 default:
88 return false;
89 }
90}
91
92void DeviceCore::ReadZLP(Context context)
93{
94 state_.out0 = context;
95 endpoint_.out0->TransferZLP();
96}
97
98void DeviceCore::WriteZLP(Context context)
99{
100 state_.in0 = context;
101 endpoint_.in0->TransferZLP();
102}
103
104void DeviceCore::ResetControlTransferState()
105{
106 // USB reset / 重枚举会重建 DeviceCore,但软件侧前一笔控制传输
107 // 不一定已经自然清干净。这里必须把 EP0 软状态全部清零,
108 // 否则下一轮 DFU DNLOAD 可能继承陈旧状态,只在“第二次传输”时才坏。
109 // USB reset / re-enumeration can rebuild DeviceCore while a previous control
110 // transfer is still partially remembered in software. If these fields leak
111 // across sessions, the next DFU DNLOAD may fail only on the second run.
112 state_.in0 = Context::UNKNOWN;
113 state_.out0 = Context::UNKNOWN;
114 state_.write_remain = {nullptr, 0};
115 state_.read_remain = {nullptr, 0};
116 state_.pending_addr = 0xFF;
117 state_.out0_buffer = nullptr;
118 state_.need_write_zlp = false;
119 state_.status_out_armed = false;
120}
121
122void DeviceCore::Init(bool in_isr)
123{
124 endpoint_.in0 = endpoint_.pool.GetEndpoint0In();
125 endpoint_.out0 = endpoint_.pool.GetEndpoint0Out();
126
127 endpoint_.in0->Configure({Endpoint::Direction::IN, Endpoint::Type::CONTROL, 64});
128 endpoint_.out0->Configure({Endpoint::Direction::OUT, Endpoint::Type::CONTROL, 64});
129
130 endpoint_.in0->SetOnTransferCompleteCallback(endpoint_.ep0_in_cb);
131 endpoint_.out0->SetOnTransferCompleteCallback(endpoint_.ep0_out_cb);
132
133 ResetControlTransferState();
134 composition_.Init(in_isr);
135
136 state_.inited = true;
137}
138
139void DeviceCore::Deinit(bool in_isr)
140{
141 state_.inited = false;
142 composition_.Deinit(in_isr);
143 endpoint_.in0->Close();
144 endpoint_.out0->Close();
145 ResetControlTransferState();
146 ResetClassRequestState();
147}
148
149void DeviceCore::ResetClassRequestState()
150{
151 class_req_.write = false;
152 class_req_.read = false;
153 class_req_.class_in_data_status_pending = false;
154 class_req_.class_ptr = nullptr;
155 class_req_.b_request = 0u;
156 class_req_.data = {nullptr, 0};
157}
158
159void DeviceCore::OnEP0OutComplete(bool in_isr, LibXR::ConstRawData& data)
160{
161 if (!state_.inited)
162 {
163 return;
164 }
165 const bool STATUS_OUT_DONE = state_.status_out_armed &&
166 class_req_.class_in_data_status_pending &&
167 endpoint_.in0->GetState() != Endpoint::State::BUSY;
168 auto status = this->state_.out0;
169 state_.out0 = Context::UNKNOWN;
170
171 switch (status)
172 {
173 case Context::ZLP:
174 // 主机中断 IN 操作后,重新配置控制端点
175 // Re-configure control endpoint after host aborts IN transfer.
176 state_.status_out_armed = false;
177 if (endpoint_.in0->GetState() == Endpoint::State::BUSY)
178 {
179 endpoint_.in0->Close();
180 endpoint_.in0->Configure({Endpoint::Direction::IN, Endpoint::Type::CONTROL, 64});
181 state_.in0 = Context::ZLP;
182 state_.write_remain = {nullptr, 0};
183 }
184 // fall through
186 state_.status_out_armed = false;
187 if (STATUS_OUT_DONE && class_req_.class_ptr != nullptr)
188 {
189 class_req_.class_ptr->OnClassInDataStatusComplete(in_isr, class_req_.b_request);
190 ResetClassRequestState();
191 }
192 break;
193
195 if (data.size_ > 0)
196 {
197 LibXR::Memory::FastCopy(state_.out0_buffer, data.addr_, data.size_);
198 }
199
200 if (state_.read_remain.size_ > 0)
201 {
202 state_.out0_buffer += data.size_;
203 DevReadEP0Data(state_.read_remain, endpoint_.out0->MaxTransferSize());
204 }
205 else if (class_req_.read)
206 {
207 class_req_.read = false;
208 class_req_.class_ptr->OnClassData(in_isr, class_req_.b_request, class_req_.data);
209 ResetClassRequestState();
210 WriteZLP();
211 }
212 else
213 {
214 WriteZLP();
215 }
216 break;
217
218 default:
219 StallControlEndpoint();
220 break;
221 }
222}
223
224void DeviceCore::OnEP0InComplete(bool in_isr, LibXR::ConstRawData& data)
225{
226 if (!state_.inited)
227 {
228 return;
229 }
230 UNUSED(in_isr);
231 UNUSED(data);
232
233 auto status = state_.in0;
234
235 state_.in0 = Context::UNKNOWN;
236
237 switch (status)
238 {
239 case Context::ZLP:
240 break;
241
243 if (state_.pending_addr != 0xFF)
244 {
245 SetAddress(state_.pending_addr, Context::STATUS_IN_COMPLETE);
246 state_.pending_addr = 0xFF;
247 }
248 break;
249
250 case Context::DATA_IN:
251 if (state_.write_remain.size_ > 0)
252 {
253 DevWriteEP0Data(state_.write_remain, endpoint_.in0->MaxTransferSize());
254 }
255 else if (state_.need_write_zlp)
256 {
257 state_.need_write_zlp = false;
258 ArmStatusOutIfNeeded();
259 WriteZLP();
260 }
261 else if (class_req_.write)
262 {
263 class_req_.write = false;
264 class_req_.class_ptr->OnClassData(in_isr, class_req_.b_request, data);
265 if (!class_req_.class_in_data_status_pending)
266 {
267 ResetClassRequestState();
268 }
269 }
270 break;
271
272 default:
273 StallControlEndpoint();
274 break;
275 }
276}
277
278void DeviceCore::DevWriteEP0Data(LibXR::ConstRawData data, size_t packet_max_length,
279 size_t request_size, bool early_read_zlp)
280{
281 state_.in0 = Context::DATA_IN;
282
283 const bool FIRST_CHUNK = (state_.write_remain.size_ == 0);
284 const size_t PAYLOAD_TOTAL_SIZE = data.size_;
285 const size_t HOST_REQUEST_SIZE = (request_size > 0) ? request_size : PAYLOAD_TOTAL_SIZE;
286 size_t transfer_total_size = PAYLOAD_TOTAL_SIZE;
287
288 if (FIRST_CHUNK)
289 {
290 state_.status_out_armed = false;
291 }
292
293 // 限制最大传输长度
294 // Clamp max transfer length.
295 if (request_size > 0 && request_size < data.size_)
296 {
297 data.size_ = request_size;
298 transfer_total_size = request_size;
299 }
300
301 // `need_write_zlp` 依据主机可见的完整 control-IN 总长度推导,
302 // 而不是依据当前拆分后的单个分片长度。
303 // `need_write_zlp` is derived from the full control-IN payload length visible to the
304 // host, not from the current split chunk.
305 if (FIRST_CHUNK)
306 {
307 state_.need_write_zlp = (HOST_REQUEST_SIZE > transfer_total_size) &&
308 ((transfer_total_size % endpoint_.in0->MaxPacketSize()) == 0);
309 }
310
311 if (data.size_ == 0 || data.size_ > 0xFFFF)
312 {
313 // 数据长度为 0,直接 STALL(协议层面不允许)
314 // If length is 0, STALL directly (not allowed by protocol).
315 StallControlEndpoint();
316 return;
317 }
318
319 // 判断是否需要拆包或发送 ZLP
320 // Determine whether to split packets or send ZLP.
321 bool has_more = data.size_ > packet_max_length;
322
323 // 拆分数据包
324 // Split packets.
325 if (has_more)
326 {
327 state_.write_remain = {
328 reinterpret_cast<const uint8_t*>(data.addr_) + packet_max_length,
329 data.size_ - packet_max_length};
330 data.size_ = packet_max_length;
331 }
332 else
333 {
334 state_.write_remain = {nullptr, 0};
335 // 对单缓冲/软件补挂 STATUS OUT 的控制器,最后一个 IN 包发出前必须先挂好
336 // STATUS OUT,否则主机可能在我们收到 IN 完成回调前就发出零长度 OUT,导致
337 // 枚举阶段直接丢掉状态包。
338 if (!state_.need_write_zlp && !state_.status_out_armed)
339 {
340 ArmStatusOutIfNeeded();
341 }
342 }
343
344 auto buffer = endpoint_.in0->GetBuffer();
345 ASSERT(buffer.size_ >= data.size_);
347
348 if (early_read_zlp && !state_.status_out_armed)
349 {
350 ArmStatusOutIfNeeded();
351 }
352
353 endpoint_.in0->Transfer(data.size_);
354}
355
356void DeviceCore::ArmStatusOutIfNeeded()
357{
358 if (!state_.status_out_armed)
359 {
360 ReadZLP();
361 state_.status_out_armed = true;
362 }
363}
364
365void DeviceCore::DevReadEP0Data(LibXR::RawData data, size_t packet_max_length)
366{
367 state_.out0 = Context::DATA_OUT;
368
369 // 限制最大接收长度
370 // Validate/clamp max receive length.
371 if (data.size_ == 0 || data.size_ > 0xFFFF)
372 {
373 StallControlEndpoint();
374 return;
375 }
376
377 // 数据长度 <= 一个包长,直接收一次即可
378 // If length <= one packet, receive once.
379 if (data.size_ <= packet_max_length)
380 {
381 state_.read_remain = {nullptr, 0}; // 标记本次已收完 / Mark as completed
382 }
383 else
384 {
385 // 数据需要多包接收
386 // Multi-packet receive.
387 state_.read_remain = {reinterpret_cast<uint8_t*>(data.addr_) + packet_max_length,
388 data.size_ - packet_max_length};
389 data.size_ = packet_max_length;
390 }
391
392 state_.out0_buffer = reinterpret_cast<uint8_t*>(data.addr_);
393 endpoint_.out0->Transfer(data.size_);
394}
395
396void DeviceCore::OnSetupPacket(bool in_isr, const SetupPacket* setup)
397{
398 if (!state_.inited)
399 {
400 return;
401 }
402 ResetClassRequestState();
403
404 RequestDirection direction =
405 static_cast<RequestDirection>(setup->bmRequestType & REQ_DIRECTION_MASK);
406 RequestType type = static_cast<RequestType>(setup->bmRequestType & REQ_TYPE_MASK);
407 Recipient recipient = static_cast<Recipient>(setup->bmRequestType & REQ_RECIPIENT_MASK);
408
409 if (endpoint_.in0->IsStalled())
410 {
411 endpoint_.in0->ClearStall();
412 }
413
414 if (endpoint_.out0->IsStalled())
415 {
416 endpoint_.out0->ClearStall();
417 }
418
420
421 switch (type)
422 {
423 case RequestType::STANDARD:
424 ans = ProcessStandardRequest(in_isr, setup, direction, recipient);
425 break;
426 case RequestType::CLASS:
427 ans = ProcessClassRequest(in_isr, setup, direction, recipient);
428 break;
429 case RequestType::VENDOR:
430 ans = ProcessVendorRequest(in_isr, setup, direction, recipient);
431 break;
432 default:
434 break;
435 }
436
437 if (ans != LibXR::ErrorCode::OK)
438 {
439 StallControlEndpoint();
440 }
441}
442
443LibXR::ErrorCode DeviceCore::ProcessStandardRequest(bool in_isr,
444 const SetupPacket*& setup,
445 RequestDirection direction,
446 Recipient recipient)
447{
448 UNUSED(in_isr);
449 UNUSED(direction);
450 UNUSED(recipient);
451
452 // 根据 recipient 处理不同目标的请求。
453 // Handle requests for different recipients.
454 StandardRequest req = static_cast<StandardRequest>(setup->bRequest);
455
457
458 switch (req)
459 {
460 case StandardRequest::GET_STATUS:
461 // 设备 / 接口 / 端点的状态请求。
462 // GET_STATUS for device/interface/endpoint.
463 ans = RespondWithStatus(setup, recipient);
464 break;
465
466 case StandardRequest::CLEAR_FEATURE:
467 // 解除某个特性(如端点 HALT)。
468 // Clear a feature (e.g., endpoint HALT).
469 ans = ClearFeature(setup, recipient);
470 break;
471
472 case StandardRequest::SET_FEATURE:
473 // 设置特性(如 Remote Wakeup / 端点 STALL)。
474 // Set a feature (e.g., remote wakeup/endpoint STALL).
475 ans = ApplyFeature(setup, recipient);
476 break;
477
478 case StandardRequest::SET_ADDRESS:
479 // 设置 USB 地址,status 阶段后生效。
480 // Set USB address; takes effect after status stage.
481 ans = PrepareAddressChange(setup->wValue);
482 break;
483
484 case StandardRequest::GET_DESCRIPTOR:
485 // 返回设备 / 配置 / 字符串等描述符。
486 // Return device/config/string descriptors.
487 ans = SendDescriptor(in_isr, setup, recipient);
488 break;
489
490 case StandardRequest::SET_DESCRIPTOR:
491 // TODO: 很少用,可选实现
492 // TODO: rarely used; optional implementation.
493 break;
494
495 case StandardRequest::GET_CONFIGURATION:
496 // 返回当前配置。
497 // Return current configuration.
498 ans = SendConfiguration();
499 break;
500
501 case StandardRequest::SET_CONFIGURATION:
502 // 设置当前配置(切换 config 描述符索引)。
503 // Set current configuration (switch configuration index).
504 ans = SwitchConfiguration(setup->wValue, in_isr);
505 break;
506
507 case StandardRequest::GET_INTERFACE:
508 {
509 if (recipient != Recipient::INTERFACE)
510 {
512 break;
513 }
514
515 uint8_t interface_index = static_cast<uint8_t>(setup->wIndex & 0xFF);
516
517 uint8_t alt = 0;
518 auto* item = composition_.FindClassByInterfaceNumber(interface_index);
519
520 if (item != nullptr)
521 {
522 item->GetAltSetting(interface_index, alt);
523 }
524 else
525 {
527 break;
528 }
529
530 DevWriteEP0Data(LibXR::ConstRawData(&alt, 1), endpoint_.in0->MaxTransferSize(), 1);
532 }
533
534 case StandardRequest::SET_INTERFACE:
535 {
536 if (recipient != Recipient::INTERFACE)
537 {
539 break;
540 }
541
542 uint8_t interface_index = static_cast<uint8_t>(setup->wIndex & 0xFF);
543 uint8_t alt_setting = static_cast<uint8_t>(setup->wValue);
544
545 auto* item = composition_.FindClassByInterfaceNumber(interface_index);
546 if (item == nullptr)
547 {
549 break;
550 }
551
552 ans = item->SetAltSetting(interface_index, alt_setting);
553 if (ans == LibXR::ErrorCode::OK)
554 {
555 WriteZLP();
556 }
557 break;
558 }
559
560 case StandardRequest::SYNCH_FRAME:
561 // TODO: 一般仅用于同步端点
562 // TODO: typically used for isochronous endpoint sync.
564 break;
565
566 default:
567 // 未知请求,直接 STALL
568 // Unknown request; STALL.
570 break;
571 }
572
573 return ans;
574}
575
576LibXR::ErrorCode DeviceCore::RespondWithStatus(const SetupPacket* setup,
577 Recipient recipient)
578{
579 if (setup->wLength != 2)
580 {
582 }
583
584 uint16_t status = 0;
585 switch (recipient)
586 {
587 case Recipient::DEVICE:
588 status = composition_.GetDeviceStatus();
589 break;
590
591 case Recipient::INTERFACE:
592 status = 0x0000;
593 break;
594
595 case Recipient::ENDPOINT:
596 {
597 uint8_t ep_addr = setup->wIndex & 0xFF;
598 Endpoint* ep = nullptr;
599 endpoint_.pool.FindEndpoint(ep_addr, ep);
600
601 if (ep == nullptr)
602 {
604 }
605
607 {
608 status = 0x0001;
609 }
610 break;
611 }
612
613 default:
615 }
616
617 LibXR::ConstRawData data(&status, 2);
618 DevWriteEP0Data(data, endpoint_.in0->MaxTransferSize(), setup->wLength);
619
621}
622
623LibXR::ErrorCode DeviceCore::ClearFeature(const SetupPacket* setup, Recipient recipient)
624{
625 switch (recipient)
626 {
627 case Recipient::ENDPOINT:
628 {
629 // 只允许清除 ENDPOINT_HALT 特性(wValue==0)
630 // Only ENDPOINT_HALT (wValue==0) is allowed.
631 if (setup->wValue == 0) // 0 = ENDPOINT_HALT
632 {
633 uint8_t ep_addr =
634 setup->wIndex & 0xFF; // 端点号(低 7 位=EP 号, 高位=方向)/ Endpoint address
635 Endpoint* ep = nullptr;
636 endpoint_.pool.FindEndpoint(ep_addr, ep);
637 if (ep)
638 {
639 auto ans = ep->ClearStall();
640 if (ans != LibXR::ErrorCode::OK)
641 {
642 return ans;
643 }
644 WriteZLP(); // 状态阶段:回复 ZLP / Status stage: send ZLP
645 }
646 else
647 {
649 }
650 }
651 else
652 {
654 }
655 break;
656 }
657
658 case Recipient::DEVICE:
659 // 可选:处理 Remote Wakeup 等设备级特性
660 // Optional: device-level feature handling (e.g., remote wakeup).
661 if (setup->wValue == 1) // 1 = DEVICE_REMOTE_WAKEUP
662 {
664 WriteZLP();
665 }
666 else
667 {
669 }
670 break;
671
672 default:
674 }
675
677}
678
679LibXR::ErrorCode DeviceCore::ApplyFeature(const SetupPacket* setup, Recipient recipient)
680{
681 switch (recipient)
682 {
683 case Recipient::ENDPOINT:
684 {
685 if (setup->wValue == 0) // 0 = ENDPOINT_HALT
686 {
687 uint8_t ep_addr = setup->wIndex & 0xFF;
688 Endpoint* ep = nullptr;
689 endpoint_.pool.FindEndpoint(ep_addr, ep);
690 if (ep)
691 {
692 auto ans = ep->Stall();
693 if (ans != LibXR::ErrorCode::OK)
694 {
695 return ans;
696 }
697 WriteZLP(); // 状态阶段回复 ZLP / Status stage: send ZLP
698 }
699 else
700 {
702 }
703 }
704 else
705 {
707 }
708 break;
709 }
710
711 case Recipient::DEVICE:
712 if (setup->wValue == 1) // 1 = DEVICE_REMOTE_WAKEUP
713 {
715 WriteZLP();
716 }
717 else
718 {
720 }
721 break;
722
723 default:
725 }
726
728}
729
730LibXR::ErrorCode DeviceCore::SendDescriptor(bool in_isr, const SetupPacket* setup,
731 Recipient recipient)
732{
733 uint8_t desc_type = (setup->wValue >> 8) & 0xFF;
734 uint8_t desc_idx = (setup->wValue) & 0xFF;
735 ConstRawData data = {nullptr, 0};
736
737 bool early_read_zlp = false;
738
739 switch (desc_type)
740 {
741 case 0x01: // DEVICE
743 // 覆盖设备描述符(非 IAD 时可用)
744 // Override device descriptor (available when not using IAD).
746 early_read_zlp = true;
747 break;
748
749 case 0x02: // CONFIGURATION
750 {
752 if (ec != LibXR::ErrorCode::OK)
753 {
754 return ec;
755 }
757 break;
758 }
759
760 case 0x03: // STRING
761 {
762 uint8_t string_idx = desc_idx;
763 uint16_t lang = setup->wIndex;
764 auto ec = composition_.GetStringDescriptor(string_idx, lang, data);
765 if (ec != LibXR::ErrorCode::OK)
766 {
767 return ec;
768 }
769 break;
770 }
771
772 // BOS (0x0F)
773 case 0x0F: // BOS
774 {
776 early_read_zlp = true;
777 break;
778 }
779
780 case 0x06: // Device Qualifier
781 case 0x07: // Other Speed Configurations
783
784 default:
785 {
786 uint8_t intf_num = 0;
787
788 if (recipient == Recipient::INTERFACE)
789 {
790 intf_num = setup->wIndex & 0xFF;
791 }
792 else
793 {
795 }
796
797 auto* item = composition_.FindClassByInterfaceNumber(intf_num);
798 if (item && item->OnGetDescriptor(in_isr, setup->bRequest, setup->wValue,
800 {
801 break;
802 }
804 }
805 }
806
807 DevWriteEP0Data(data, endpoint_.in0->MaxTransferSize(), setup->wLength, early_read_zlp);
809}
810
811LibXR::ErrorCode DeviceCore::PrepareAddressChange(uint16_t address)
812{
813 state_.pending_addr = static_cast<uint8_t>(address & 0x7F);
814
815 const LibXR::ErrorCode pre_status = SetAddress(address, Context::SETUP_BEFORE_STATUS);
818 return (pre_status != LibXR::ErrorCode::OK) ? pre_status : armed;
819}
820
821LibXR::ErrorCode DeviceCore::SwitchConfiguration(uint16_t value, bool in_isr)
822{
823 if (composition_.SwitchConfig(value, in_isr) != LibXR::ErrorCode::OK)
824 {
826 }
827
828 // ACK status 阶段
829 // ACK status stage.
830 WriteZLP();
831
833}
834
835LibXR::ErrorCode DeviceCore::SendConfiguration()
836{
837 uint8_t cfg = composition_.GetCurrentConfig();
838 LibXR::ConstRawData data(&cfg, 1);
839 DevWriteEP0Data(data, endpoint_.in0->MaxTransferSize(), 1);
840
842}
843
844void DeviceCore::StallControlEndpoint()
845{
846 endpoint_.pool.GetEndpoint0Out()->Stall();
847 endpoint_.pool.GetEndpoint0In()->Stall();
848}
849
850void DeviceCore::ClearControlEndpointStall()
851{
852 endpoint_.pool.GetEndpoint0Out()->ClearStall();
853 endpoint_.pool.GetEndpoint0In()->ClearStall();
854}
855
856LibXR::ErrorCode DeviceCore::ProcessClassRequest(bool in_isr, const SetupPacket* setup,
857 RequestDirection /*direction*/,
858 Recipient recipient)
859{
860 // 只处理 Class 请求(bmRequestType bits[6:5] == 01)。
861 // Only handle Class requests (bmRequestType bits[6:5] == 01).
862 if ((setup->bmRequestType & 0x60) != 0x20)
863 {
865 }
866
867 DeviceClass* item = nullptr;
868
869 switch (recipient)
870 {
871 case Recipient::INTERFACE:
872 {
873 // 低字节 = 接口号。
874 // Low byte = interface number.
875 uint8_t if_num = static_cast<uint8_t>(setup->wIndex & 0xFF);
877 break;
878 }
879 case Recipient::ENDPOINT:
880 {
881 // 低字节 = 端点地址(含 0x80 方向位)。
882 // Low byte = endpoint address (including 0x80 direction bit).
883 uint8_t ep_addr = static_cast<uint8_t>(setup->wIndex & 0xFF);
885 break;
886 }
887 default:
888 // Device / Other 一般不在这里处理。
889 // Device/Other is typically not handled here.
891 }
892
893 if (!item)
894 {
896 }
897
899 auto ec = item->OnClassRequest(in_isr, setup->bRequest, setup->wValue, setup->wLength,
900 setup->wIndex, result);
901 if (ec != LibXR::ErrorCode::OK)
902 {
903 return ec;
904 }
905
906 // 不允许同时提供读写缓冲
907 // Do not allow both read and write buffers simultaneously.
908 const bool HAS_READ_BUF = (result.read_data.size_ > 0);
909 const bool HAS_WRITE_BUF = (result.write_data.size_ > 0);
910 if (HAS_READ_BUF && HAS_WRITE_BUF)
911 {
913 }
914
915 // Host->Device(OUT):从主机读数据进 read_data
916 // Host->Device (OUT): read host data into read_data.
917 if (HAS_READ_BUF)
918 {
919 if (setup->wLength == 0 || result.read_data.size_ < setup->wLength)
920 {
922 }
923
924 class_req_.read = true;
925 class_req_.write = false;
926 class_req_.class_in_data_status_pending = false;
927 class_req_.class_ptr = item;
928 class_req_.b_request = setup->bRequest;
929 class_req_.data = result.read_data;
930
931 DevReadEP0Data(result.read_data, endpoint_.in0->MaxTransferSize());
933 }
934
935 // Device->Host(IN):从 write_data 发数据给主机
936 // Device->Host (IN): send write_data to host.
937 if (HAS_WRITE_BUF)
938 {
939 if (setup->wLength == 0)
940 {
942 }
943
944 class_req_.write = true;
945 class_req_.read = false;
946 class_req_.class_in_data_status_pending = true;
947 class_req_.class_ptr = item;
948 class_req_.b_request = setup->bRequest;
949 class_req_.data = result.write_data;
950
951 // Class IN 传输需要主机请求的 wLength,
952 // 这样 EP0 才能判断当 payload 短于请求值、但又恰好整除 bMaxPacketSize0 时,
953 // 是否还需要补一个结束 ZLP(例如 DFU UPLOAD 尾包)。
954 // Class IN transfers need the host-requested wLength so EP0 can decide
955 // whether a terminating ZLP is required when the payload is shorter than
956 // the request but still an exact multiple of bMaxPacketSize0.
957 DevWriteEP0Data(result.write_data, endpoint_.in0->MaxTransferSize(), setup->wLength);
959 }
960
961 // 无数据阶段:按类的意愿发送/接收 ZLP(如果有)
962 // No data stage: send/receive ZLP as requested by class (if any).
963 if (result.read_zlp)
964 {
965 ReadZLP();
967 }
968 if (result.write_zlp)
969 {
970 WriteZLP();
972 }
973
975}
976
977LibXR::ErrorCode DeviceCore::ProcessVendorRequest(bool in_isr, const SetupPacket*& setup,
978 RequestDirection /*direction*/,
979 Recipient recipient)
980{
981 // 只处理 Vendor 请求(bmRequestType bits[6:5] == 10)
982 // Only handle Vendor requests (bmRequestType bits[6:5] == 10).
983 if ((setup->bmRequestType & 0x60) != 0x40)
984 {
986 }
987
988 // 先交给 BOS capabilities 尝试处理(WinUSB / WebUSB / ContainerID 等)。
989 // First, try BOS capabilities (WinUSB / WebUSB / ContainerID, etc.).
990 {
991 BosVendorResult bos_ret{};
992 auto bec = composition_.ProcessBosVendorRequest(in_isr, setup, bos_ret);
993 if (bec == LibXR::ErrorCode::OK && bos_ret.handled)
994 {
995 if (bos_ret.in_data.addr_ != nullptr && bos_ret.in_data.size_ > 0)
996 {
997 if (setup->wLength == 0)
998 {
1000 }
1001
1002 DevWriteEP0Data(bos_ret.in_data, endpoint_.in0->MaxTransferSize(), setup->wLength,
1003 bos_ret.early_read_zlp);
1004 return LibXR::ErrorCode::OK;
1005 }
1006
1007 if (bos_ret.write_zlp)
1008 {
1009 WriteZLP();
1010 return LibXR::ErrorCode::OK;
1011 }
1012
1013 // handled 但既没有 in_data 也没有 write_zlp:默认 ACK
1014 // handled but no in_data and no write_zlp: default ACK.
1015 WriteZLP();
1016 return LibXR::ErrorCode::OK;
1017 }
1018
1019 // bec != OK:匹配但错误,直接返回让上层 STALL
1020 // bec != OK: matched but failed; return to upper layer to STALL.
1022 {
1023 return bec;
1024 }
1025 }
1026
1027 DeviceClass* item = nullptr;
1028
1029 switch (recipient)
1030 {
1031 case Recipient::INTERFACE:
1032 {
1033 uint8_t if_num = static_cast<uint8_t>(setup->wIndex & 0xFF);
1035 break;
1036 }
1037 case Recipient::ENDPOINT:
1038 {
1039 uint8_t ep_addr = static_cast<uint8_t>(setup->wIndex & 0xFF);
1041 break;
1042 }
1043 default:
1044 // 先不处理 DEVICE/OTHER 级别的 Vendor 请求
1045 // 暂不处理 DEVICE / OTHER 级别的 Vendor 请求。
1046 // Do not handle DEVICE / OTHER vendor requests for now.
1048 }
1049
1050 if (!item)
1051 {
1053 }
1054
1056 auto ec = item->OnVendorRequest(in_isr, setup->bRequest, setup->wValue, setup->wLength,
1057 setup->wIndex, result);
1058 if (ec != LibXR::ErrorCode::OK)
1059 {
1060 return ec;
1061 }
1062
1063 const bool HAS_READ_BUF = (result.read_data.size_ > 0);
1064 const bool HAS_WRITE_BUF = (result.write_data.size_ > 0);
1065
1066 if (HAS_READ_BUF && HAS_WRITE_BUF)
1067 {
1069 }
1070
1071 // Host -> Device(OUT)路径:从主机读数据进 read_data。
1072 // Host->Device (OUT): read host data into read_data.
1073 if (HAS_READ_BUF)
1074 {
1075 if (setup->wLength == 0 || result.read_data.size_ < setup->wLength)
1076 {
1078 }
1079
1080 class_req_.read = true;
1081 class_req_.write = false;
1082 class_req_.class_in_data_status_pending = false;
1083 class_req_.class_ptr = item;
1084 class_req_.b_request = setup->bRequest;
1085 class_req_.data = result.read_data;
1086
1087 DevReadEP0Data(result.read_data, endpoint_.in0->MaxTransferSize());
1088 return LibXR::ErrorCode::OK;
1089 }
1090
1091 // Device -> Host(IN)路径:从 write_data 发数据给主机。
1092 // Device->Host (IN): send write_data to host.
1093 if (HAS_WRITE_BUF)
1094 {
1095 if (setup->wLength == 0)
1096 {
1098 }
1099
1100 class_req_.write = true;
1101 class_req_.read = false;
1102 class_req_.class_in_data_status_pending = false;
1103 class_req_.class_ptr = item;
1104 class_req_.b_request = setup->bRequest;
1105 class_req_.data = result.write_data;
1106
1107 DevWriteEP0Data(result.write_data, endpoint_.in0->MaxTransferSize(), setup->wLength);
1108 return LibXR::ErrorCode::OK;
1109 }
1110
1111 // 无数据阶段,只需要 ZLP 的情况
1112 // No data stage; ZLP only.
1113 if (result.read_zlp)
1114 {
1115 ReadZLP();
1116 return LibXR::ErrorCode::OK;
1117 }
1118 if (result.write_zlp)
1119 {
1120 WriteZLP();
1121 return LibXR::ErrorCode::OK;
1122 }
1123
1124 return LibXR::ErrorCode::OK;
1125}
1126
1127Speed DeviceCore::GetSpeed() const { return state_.speed; }
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:159
常量原始数据封装类。 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:5
原始数据封装类。 A class for encapsulating raw data.
virtual ErrorCode SetAltSetting(uint8_t itf, uint8_t alt)
可选:设置接口备用设置 / Optional: set interface alternate setting
Definition desc_cfg.hpp:134
USB 设备类接口基类 / USB device class interface base.
virtual ErrorCode OnClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, ControlTransferResult &result)
处理 Class-specific 请求(Setup stage)/ Handle class-specific request (Setup stage)
virtual ErrorCode OnVendorRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, ControlTransferResult &result)
处理 Vendor request(Setup stage)/ Handle vendor request (Setup stage)
void Deinit(bool in_isr)
释放当前 configuration 的运行态资源 Release runtime resources for the active configuration.
ErrorCode TryOverrideDeviceDescriptor(DeviceDescriptor &descriptor)
用当前配置覆盖 device descriptor 的类字段 Try to override device-descriptor class fields from the current config...
RawData GetConfigDescriptor() const
获取当前 configuration 描述符缓存 Get the current configuration descriptor cache.
ErrorCode SwitchConfig(size_t index, bool in_isr)
切换到指定 configuration value Switch to the given configuration value.
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 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
size_t GetCurrentConfig() const
当前 configuration value / Current configuration value
ErrorCode BuildConfigDescriptor()
生成当前 configuration 描述符缓存 Build the current configuration descriptor cache.
USB 设备协议栈核心:EP0 控制传输、描述符、配置、标准/类/厂商请求 USB device core: EP0 control transfer, descriptors,...
Definition dev_core.hpp:22
virtual void Deinit(bool in_isr)
反初始化 / Deinitialize
Definition dev_core.cpp:139
virtual void EnableRemoteWakeup()
启用远程唤醒 / Enable remote wakeup
Definition dev_core.hpp:114
ConstRawData data
数据阶段数据 / Data stage payload
Definition dev_core.hpp:213
@ SETUP_BEFORE_STATUS
Setup handled, before STATUS IN ZLP is armed.
Definition dev_core.hpp:33
@ STATUS_IN_ARMED
STATUS IN ZLP armed, but not yet completed.
Definition dev_core.hpp:34
@ STATUS_IN_COMPLETE
IN status stage completed.
Definition dev_core.hpp:38
@ DATA_OUT
OUT data stage / OUT data stage.
Definition dev_core.hpp:35
@ STATUS_OUT
OUT status stage / OUT status stage.
Definition dev_core.hpp:36
@ DATA_IN
IN data stage / IN data stage.
Definition dev_core.hpp:37
@ ZLP
ZLP stage marker / ZLP stage marker.
Definition dev_core.hpp:39
@ UNKNOWN
未知 / Unknown
Definition dev_core.hpp:32
virtual void Init(bool in_isr)
初始化 / Initialize
Definition dev_core.cpp:122
DeviceDescriptor device_desc_
设备描述符 / Device descriptor
Definition dev_core.hpp:177
Speed GetSpeed() const
获取设备速度 / Get device speed
DeviceComposition composition_
USB 组合管理器 / USB composition manager.
Definition dev_core.hpp:176
virtual void DisableRemoteWakeup()
禁用远程唤醒 / Disable remote wakeup
Definition dev_core.hpp:119
DeviceCore(EndpointPool &ep_pool, USBSpec spec, Speed speed, DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid, uint16_t bcd, const std::initializer_list< const DescriptorStrings::LanguagePack * > &lang_list, const std::initializer_list< const std::initializer_list< ConfigDescriptorItem * > > &configs, ConstRawData uid={nullptr, 0})
构造函数 / Constructor
Definition dev_core.cpp:12
Speed speed
设备速度 / Device speed
Definition dev_core.hpp:192
void OnSetupPacket(bool in_isr, const SetupPacket *setup)
处理 Setup 包 / Handle Setup packet
Definition dev_core.cpp:396
virtual ErrorCode SetAddress(uint8_t address, Context state)=0
设置设备地址(由子类实现) Set device address (implemented by derived class).
PacketSize0
控制端点0最大包长度枚举 Packet size for endpoint 0 (bMaxPacketSize0)
Definition desc_dev.hpp:75
RawData GetData()
获取设备描述符的原始数据指针及长度 Get the raw device descriptor data pointer and length
Definition desc_dev.cpp:24
USB 端点基类 / USB Endpoint base class.
Definition ep.hpp:24
virtual ErrorCode Stall()=0
置 STALL / Stall endpoint
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
virtual ErrorCode ClearStall()=0
清除 STALL / Clear stall
@ CONTROL
控制端点 / Control
@ STALLED
停止/挂起 / Stalled
State GetState() const
获取端点状态 / Get endpoint state
Definition ep.hpp:208
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
ErrorCode
定义错误码枚举
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
Vendor 请求处理结果(EP0 控制传输) Vendor request handling result for EP0 control transfers.
Definition bos.hpp:45
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
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
uint16_t wValue
参数字段,含请求相关值 / Value field (e.g., descriptor type/index)
Definition core.hpp:62
uint8_t bRequest
请求码 / Request code (e.g., GET_DESCRIPTOR)
Definition core.hpp:60