6#include "device_composition.hpp"
7#include "libxr_mem.hpp"
8#include "libxr_type.hpp"
10using namespace LibXR::USB;
15 const std::initializer_list<const DescriptorStrings::LanguagePack*>& lang_list,
16 const std::initializer_list<
const std::initializer_list<ConfigDescriptorItem*>>&
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, {}, {}}),
32 ASSERT(IsValidUSBCombination(spec, speed, packet_size));
37 endpoint_.ep0_out_cb =
41void DeviceCore::OnEP0OutCompleteStatic(
bool in_isr,
DeviceCore* self,
44 self->OnEP0OutComplete(in_isr,
data);
47void DeviceCore::OnEP0InCompleteStatic(
bool in_isr,
DeviceCore* self,
50 self->OnEP0InComplete(in_isr,
data);
53bool DeviceCore::IsValidUSBCombination(USBSpec spec, Speed speed,
56 const uint8_t SIZE =
static_cast<uint8_t
>(packet_size);
63 return (spec == USBSpec::USB_1_0 || spec == USBSpec::USB_1_1) && SIZE == 8;
68 if (!(spec >= USBSpec::USB_1_0 && spec <= USBSpec::USB_2_1))
72 return SIZE == 8 || SIZE == 16 || SIZE == 32 || SIZE == 64;
77 if (spec < USBSpec::USB_2_0)
84 case Speed::SUPER_PLUS:
92void DeviceCore::ReadZLP(Context context)
94 state_.out0 = context;
95 endpoint_.out0->TransferZLP();
98void DeviceCore::WriteZLP(Context context)
100 state_.in0 = context;
101 endpoint_.in0->TransferZLP();
104void DeviceCore::ResetControlTransferState()
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;
124 endpoint_.in0 = endpoint_.pool.GetEndpoint0In();
125 endpoint_.out0 = endpoint_.pool.GetEndpoint0Out();
130 endpoint_.in0->SetOnTransferCompleteCallback(endpoint_.ep0_in_cb);
131 endpoint_.out0->SetOnTransferCompleteCallback(endpoint_.ep0_out_cb);
133 ResetControlTransferState();
136 state_.inited =
true;
141 state_.inited =
false;
143 endpoint_.in0->Close();
144 endpoint_.out0->Close();
145 ResetControlTransferState();
146 ResetClassRequestState();
149void DeviceCore::ResetClassRequestState()
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};
165 const bool STATUS_OUT_DONE = state_.status_out_armed &&
166 class_req_.class_in_data_status_pending &&
168 auto status = this->state_.out0;
176 state_.status_out_armed =
false;
179 endpoint_.in0->Close();
182 state_.write_remain = {
nullptr, 0};
186 state_.status_out_armed =
false;
187 if (STATUS_OUT_DONE && class_req_.class_ptr !=
nullptr)
189 class_req_.class_ptr->OnClassInDataStatusComplete(in_isr, class_req_.b_request);
190 ResetClassRequestState();
200 if (state_.read_remain.size_ > 0)
203 DevReadEP0Data(state_.read_remain, endpoint_.out0->MaxTransferSize());
205 else if (class_req_.read)
207 class_req_.read =
false;
208 class_req_.class_ptr->OnClassData(in_isr, class_req_.b_request, class_req_.data);
209 ResetClassRequestState();
219 StallControlEndpoint();
233 auto status = state_.in0;
243 if (state_.pending_addr != 0xFF)
246 state_.pending_addr = 0xFF;
251 if (state_.write_remain.size_ > 0)
253 DevWriteEP0Data(state_.write_remain, endpoint_.in0->MaxTransferSize());
255 else if (state_.need_write_zlp)
257 state_.need_write_zlp =
false;
258 ArmStatusOutIfNeeded();
261 else if (class_req_.write)
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)
267 ResetClassRequestState();
273 StallControlEndpoint();
279 size_t request_size,
bool early_read_zlp)
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;
290 state_.status_out_armed =
false;
295 if (request_size > 0 && request_size <
data.
size_)
298 transfer_total_size = request_size;
307 state_.need_write_zlp = (HOST_REQUEST_SIZE > transfer_total_size) &&
308 ((transfer_total_size % endpoint_.in0->MaxPacketSize()) == 0);
315 StallControlEndpoint();
321 bool has_more =
data.
size_ > packet_max_length;
327 state_.write_remain = {
328 reinterpret_cast<const uint8_t*
>(
data.
addr_) + packet_max_length,
334 state_.write_remain = {
nullptr, 0};
338 if (!state_.need_write_zlp && !state_.status_out_armed)
340 ArmStatusOutIfNeeded();
344 auto buffer = endpoint_.in0->GetBuffer();
348 if (early_read_zlp && !state_.status_out_armed)
350 ArmStatusOutIfNeeded();
356void DeviceCore::ArmStatusOutIfNeeded()
358 if (!state_.status_out_armed)
361 state_.status_out_armed =
true;
365void DeviceCore::DevReadEP0Data(
LibXR::RawData data,
size_t packet_max_length)
373 StallControlEndpoint();
381 state_.read_remain = {
nullptr, 0};
387 state_.read_remain = {
reinterpret_cast<uint8_t*
>(
data.
addr_) + packet_max_length,
392 state_.out0_buffer =
reinterpret_cast<uint8_t*
>(
data.
addr_);
402 ResetClassRequestState();
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);
409 if (endpoint_.in0->IsStalled())
411 endpoint_.in0->ClearStall();
414 if (endpoint_.out0->IsStalled())
416 endpoint_.out0->ClearStall();
423 case RequestType::STANDARD:
424 ans = ProcessStandardRequest(in_isr, setup, direction, recipient);
426 case RequestType::CLASS:
427 ans = ProcessClassRequest(in_isr, setup, direction, recipient);
429 case RequestType::VENDOR:
430 ans = ProcessVendorRequest(in_isr, setup, direction, recipient);
439 StallControlEndpoint();
445 RequestDirection direction,
454 StandardRequest req =
static_cast<StandardRequest
>(setup->
bRequest);
460 case StandardRequest::GET_STATUS:
463 ans = RespondWithStatus(setup, recipient);
466 case StandardRequest::CLEAR_FEATURE:
469 ans = ClearFeature(setup, recipient);
472 case StandardRequest::SET_FEATURE:
475 ans = ApplyFeature(setup, recipient);
478 case StandardRequest::SET_ADDRESS:
481 ans = PrepareAddressChange(setup->
wValue);
484 case StandardRequest::GET_DESCRIPTOR:
487 ans = SendDescriptor(in_isr, setup, recipient);
490 case StandardRequest::SET_DESCRIPTOR:
495 case StandardRequest::GET_CONFIGURATION:
498 ans = SendConfiguration();
501 case StandardRequest::SET_CONFIGURATION:
504 ans = SwitchConfiguration(setup->
wValue, in_isr);
507 case StandardRequest::GET_INTERFACE:
509 if (recipient != Recipient::INTERFACE)
515 uint8_t interface_index =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
522 item->GetAltSetting(interface_index, alt);
534 case StandardRequest::SET_INTERFACE:
536 if (recipient != Recipient::INTERFACE)
542 uint8_t interface_index =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
543 uint8_t alt_setting =
static_cast<uint8_t
>(setup->
wValue);
560 case StandardRequest::SYNCH_FRAME:
587 case Recipient::DEVICE:
591 case Recipient::INTERFACE:
595 case Recipient::ENDPOINT:
597 uint8_t ep_addr = setup->
wIndex & 0xFF;
599 endpoint_.pool.FindEndpoint(ep_addr, ep);
618 DevWriteEP0Data(
data, endpoint_.in0->MaxTransferSize(), setup->
wLength);
627 case Recipient::ENDPOINT:
636 endpoint_.pool.FindEndpoint(ep_addr, ep);
658 case Recipient::DEVICE:
683 case Recipient::ENDPOINT:
687 uint8_t ep_addr = setup->
wIndex & 0xFF;
689 endpoint_.pool.FindEndpoint(ep_addr, ep);
692 auto ans = ep->
Stall();
711 case Recipient::DEVICE:
733 uint8_t desc_type = (setup->
wValue >> 8) & 0xFF;
734 uint8_t desc_idx = (setup->
wValue) & 0xFF;
737 bool early_read_zlp =
false;
746 early_read_zlp =
true;
762 uint8_t string_idx = desc_idx;
763 uint16_t lang = setup->
wIndex;
776 early_read_zlp =
true;
786 uint8_t intf_num = 0;
788 if (recipient == Recipient::INTERFACE)
790 intf_num = setup->
wIndex & 0xFF;
798 if (item && item->OnGetDescriptor(in_isr, setup->
bRequest, setup->
wValue,
807 DevWriteEP0Data(
data, endpoint_.in0->MaxTransferSize(), setup->
wLength, early_read_zlp);
813 state_.pending_addr =
static_cast<uint8_t
>(address & 0x7F);
821LibXR::ErrorCode DeviceCore::SwitchConfiguration(uint16_t value,
bool in_isr)
839 DevWriteEP0Data(
data, endpoint_.in0->MaxTransferSize(), 1);
844void DeviceCore::StallControlEndpoint()
846 endpoint_.pool.GetEndpoint0Out()->Stall();
847 endpoint_.pool.GetEndpoint0In()->Stall();
850void DeviceCore::ClearControlEndpointStall()
852 endpoint_.pool.GetEndpoint0Out()->ClearStall();
853 endpoint_.pool.GetEndpoint0In()->ClearStall();
871 case Recipient::INTERFACE:
875 uint8_t if_num =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
879 case Recipient::ENDPOINT:
883 uint8_t ep_addr =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
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)
919 if (setup->
wLength == 0 || result.read_data.size_ < setup->
wLength)
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;
931 DevReadEP0Data(result.read_data, endpoint_.in0->MaxTransferSize());
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;
957 DevWriteEP0Data(result.write_data, endpoint_.in0->MaxTransferSize(), setup->
wLength);
968 if (result.write_zlp)
995 if (bos_ret.in_data.addr_ !=
nullptr && bos_ret.in_data.size_ > 0)
1002 DevWriteEP0Data(bos_ret.in_data, endpoint_.in0->MaxTransferSize(), setup->
wLength,
1003 bos_ret.early_read_zlp);
1007 if (bos_ret.write_zlp)
1031 case Recipient::INTERFACE:
1033 uint8_t if_num =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
1037 case Recipient::ENDPOINT:
1039 uint8_t ep_addr =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
1063 const bool HAS_READ_BUF = (result.read_data.size_ > 0);
1064 const bool HAS_WRITE_BUF = (result.write_data.size_ > 0);
1066 if (HAS_READ_BUF && HAS_WRITE_BUF)
1075 if (setup->
wLength == 0 || result.read_data.size_ < setup->
wLength)
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;
1087 DevReadEP0Data(result.read_data, endpoint_.in0->MaxTransferSize());
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;
1107 DevWriteEP0Data(result.write_data, endpoint_.in0->MaxTransferSize(), setup->
wLength);
1113 if (result.read_zlp)
1118 if (result.write_zlp)
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
常量原始数据封装类。 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
原始数据封装类。 A class for encapsulating raw data.
virtual ErrorCode SetAltSetting(uint8_t itf, uint8_t alt)
可选:设置接口备用设置 / Optional: set interface alternate setting
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,...
virtual void Deinit(bool in_isr)
反初始化 / Deinitialize
virtual void EnableRemoteWakeup()
启用远程唤醒 / Enable remote wakeup
ConstRawData data
数据阶段数据 / Data stage payload
@ SETUP_BEFORE_STATUS
Setup handled, before STATUS IN ZLP is armed.
@ STATUS_IN_ARMED
STATUS IN ZLP armed, but not yet completed.
@ STATUS_IN_COMPLETE
IN status stage completed.
@ DATA_OUT
OUT data stage / OUT data stage.
@ STATUS_OUT
OUT status stage / OUT status stage.
@ DATA_IN
IN data stage / IN data stage.
@ ZLP
ZLP stage marker / ZLP stage marker.
virtual void Init(bool in_isr)
初始化 / Initialize
DeviceDescriptor device_desc_
设备描述符 / Device descriptor
Speed GetSpeed() const
获取设备速度 / Get device speed
DeviceComposition composition_
USB 组合管理器 / USB composition manager.
virtual void DisableRemoteWakeup()
禁用远程唤醒 / Disable remote wakeup
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
Speed speed
设备速度 / Device speed
void OnSetupPacket(bool in_isr, const SetupPacket *setup)
处理 Setup 包 / Handle Setup packet
virtual ErrorCode SetAddress(uint8_t address, Context state)=0
设置设备地址(由子类实现) Set device address (implemented by derived class).
PacketSize0
控制端点0最大包长度枚举 Packet size for endpoint 0 (bMaxPacketSize0)
RawData GetData()
获取设备描述符的原始数据指针及长度 Get the raw device descriptor data pointer and length
USB 端点基类 / USB Endpoint base class.
virtual ErrorCode Stall()=0
置 STALL / Stall endpoint
@ OUT
输出方向 / OUT direction
virtual ErrorCode ClearStall()=0
清除 STALL / Clear stall
State GetState() const
获取端点状态 / Get endpoint state
USB端点池类 / USB endpoint pool class.
@ 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.
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)
uint16_t wIndex
对象索引,如接口号或端点号 / Index (e.g., interface or endpoint)
uint16_t wLength
数据阶段长度 / Number of bytes in data stage
uint16_t wValue
参数字段,含请求相关值 / Value field (e.g., descriptor type/index)
uint8_t bRequest
请求码 / Request code (e.g., GET_DESCRIPTOR)