3using namespace LibXR::USB;
8 const std::initializer_list<const DescriptorStrings::LanguagePack *> &lang_list,
9 const std::initializer_list<
const std::initializer_list<ConfigDescriptorItem *>>
11 : config_desc_(ep_pool, configs),
12 device_desc_(spec, packet_size, vid, pid, bcd, config_desc_.GetConfigNum()),
14 endpoint_({ep_pool,
nullptr,
nullptr, {}, {}}),
15 state_({
false, speed, Context::UNKNOW, Context::UNKNOW, 0xFF,
nullptr,
false})
17 ASSERT(IsValidUSBCombination(spec, speed, packet_size));
22 endpoint_.ep0_out_cb =
41 const uint8_t SIZE =
static_cast<uint8_t
>(packet_size);
47 return (spec == USBSpec::USB_1_0 || spec == USBSpec::USB_1_1) && SIZE == 8;
51 if (!(spec >= USBSpec::USB_1_0 && spec <= USBSpec::USB_2_1))
55 return SIZE == 8 || SIZE == 16 || SIZE == 32 || SIZE == 64;
59 if (spec < USBSpec::USB_2_0)
66 case Speed::SUPER_PLUS:
76 state_.out0 = context;
77 endpoint_.out0->TransferZLP();
83 endpoint_.in0->TransferZLP();
88 endpoint_.in0 = endpoint_.pool.GetEndpoint0In();
89 endpoint_.out0 = endpoint_.pool.GetEndpoint0Out();
94 endpoint_.in0->SetOnTransferCompleteCallback(endpoint_.ep0_in_cb);
95 endpoint_.out0->SetOnTransferCompleteCallback(endpoint_.ep0_out_cb);
104 state_.inited =
false;
106 endpoint_.in0->Close();
107 endpoint_.out0->Close();
116 auto status = this->state_.out0;
130 if (state_.read_remain.size_ > 0)
132 state_.out0_buffer += data.
size_;
133 DevReadEP0Data(state_.read_remain, endpoint_.out0->MaxTransferSize());
135 else if (class_req_.read)
137 class_req_.read =
false;
138 class_req_.class_ptr->OnClassData(in_isr, class_req_.b_request, data);
161 auto status = state_.in0;
170 if (state_.pending_addr != 0xFF)
173 state_.pending_addr = 0xFF;
177 if (state_.write_remain.size_ > 0)
179 DevWriteEP0Data(state_.write_remain, endpoint_.in0->MaxTransferSize());
181 else if (state_.need_write_zlp)
183 state_.need_write_zlp =
false;
187 else if (class_req_.write)
189 class_req_.write =
false;
190 class_req_.class_ptr->OnClassData(in_isr, class_req_.b_request, data);
205 if (request_size > 0 && request_size < data.
size_)
207 data.
size_ = request_size;
218 bool has_more = data.
size_ > packet_max_length;
223 state_.write_remain = {
224 reinterpret_cast<const uint8_t *
>(data.
addr_) + packet_max_length,
225 data.
size_ - packet_max_length};
226 data.
size_ = packet_max_length;
227 state_.need_write_zlp =
false;
231 state_.write_remain = {
nullptr, 0};
232 state_.need_write_zlp = data.
size_ % endpoint_.in0->MaxPacketSize() == 0;
235 auto buffer = endpoint_.in0->GetBuffer();
236 ASSERT(buffer.size_ >= data.
size_);
240 if (!has_more && !state_.need_write_zlp)
245 endpoint_.in0->Transfer(data.
size_);
260 if (data.
size_ <= packet_max_length)
262 state_.read_remain = {
nullptr, 0};
267 state_.read_remain = {
reinterpret_cast<uint8_t *
>(data.
addr_) + packet_max_length,
268 data.
size_ - packet_max_length};
269 data.
size_ = packet_max_length;
272 state_.out0_buffer =
reinterpret_cast<uint8_t *
>(data.
addr_);
273 endpoint_.out0->Transfer(data.
size_);
282 RequestDirection direction =
283 static_cast<RequestDirection
>(setup->
bmRequestType & REQ_DIRECTION_MASK);
284 RequestType type =
static_cast<RequestType
>(setup->
bmRequestType & REQ_TYPE_MASK);
285 Recipient recipient =
static_cast<Recipient
>(setup->
bmRequestType & REQ_RECIPIENT_MASK);
287 if (endpoint_.in0->IsStalled())
289 endpoint_.in0->ClearStall();
292 if (endpoint_.out0->IsStalled())
294 endpoint_.out0->ClearStall();
297 ErrorCode ans = ErrorCode::OK;
301 case RequestType::STANDARD:
304 case RequestType::CLASS:
307 case RequestType::VENDOR:
311 ans = ErrorCode::ARG_ERR;
315 if (ans != ErrorCode::OK)
322 RequestDirection direction,
329 StandardRequest req =
static_cast<StandardRequest
>(setup->
bRequest);
331 ErrorCode ans = ErrorCode::OK;
335 case StandardRequest::GET_STATUS:
339 case StandardRequest::CLEAR_FEATURE:
343 case StandardRequest::SET_FEATURE:
347 case StandardRequest::SET_ADDRESS:
351 case StandardRequest::GET_DESCRIPTOR:
355 case StandardRequest::SET_DESCRIPTOR:
358 case StandardRequest::GET_CONFIGURATION:
362 case StandardRequest::SET_CONFIGURATION:
366 case StandardRequest::GET_INTERFACE:
368 if (recipient != Recipient::INTERFACE)
370 ans = ErrorCode::ARG_ERR;
374 uint8_t interface_index =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
381 item->GetAltSetting(interface_index, alt);
385 ans = ErrorCode::NOT_FOUND;
391 return ErrorCode::OK;
393 case StandardRequest::SET_INTERFACE:
395 if (recipient != Recipient::INTERFACE)
397 ans = ErrorCode::ARG_ERR;
401 uint8_t interface_index =
static_cast<uint8_t
>(setup->
wIndex & 0xFF);
402 uint8_t alt_setting =
static_cast<uint8_t
>(setup->
wValue);
407 ans = ErrorCode::NOT_FOUND;
414 case StandardRequest::SYNCH_FRAME:
416 ans = ErrorCode::NOT_SUPPORT;
420 ans = ErrorCode::ARG_ERR;
430 return ErrorCode::ARG_ERR;
436 case Recipient::DEVICE:
439 case Recipient::INTERFACE:
442 case Recipient::ENDPOINT:
444 uint8_t ep_addr = setup->
wIndex & 0xFF;
446 endpoint_.pool.FindEndpoint(ep_addr, ep);
450 return ErrorCode::NOT_FOUND;
460 return ErrorCode::ARG_ERR;
466 return ErrorCode::OK;
473 case Recipient::ENDPOINT:
478 uint8_t ep_addr = setup->
wIndex & 0xFF;
481 endpoint_.pool.FindEndpoint(ep_addr, ep);
490 return ErrorCode::NOT_FOUND;
495 return ErrorCode::ARG_ERR;
499 case Recipient::DEVICE:
508 return ErrorCode::ARG_ERR;
512 return ErrorCode::ARG_ERR;
515 return ErrorCode::OK;
522 case Recipient::ENDPOINT:
526 uint8_t ep_addr = setup->
wIndex & 0xFF;
529 endpoint_.pool.FindEndpoint(ep_addr, ep);
538 return ErrorCode::NOT_FOUND;
543 return ErrorCode::ARG_ERR;
547 case Recipient::DEVICE:
555 return ErrorCode::ARG_ERR;
559 return ErrorCode::ARG_ERR;
562 return ErrorCode::OK;
568 uint8_t desc_type = (setup->
wValue >> 8) & 0xFF;
569 uint8_t desc_idx = (setup->
wValue) & 0xFF;
586 uint8_t string_idx = desc_idx;
587 uint16_t lang = setup->
wIndex;
596 if (ec != ErrorCode::OK)
607 return ErrorCode::NOT_SUPPORT;
610 uint8_t intf_num = 0;
612 if (recipient == Recipient::INTERFACE)
614 intf_num = setup->
wIndex & 0xFF;
618 return ErrorCode::ARG_ERR;
623 if (item && item->OnGetDescriptor(in_isr, setup->
bRequest, setup->
wValue,
624 setup->
wLength, data) == ErrorCode::OK)
630 return ErrorCode::ARG_ERR;
637 return ErrorCode::OK;
642 state_.pending_addr =
static_cast<uint8_t
>(address & 0x7F);
653 return ErrorCode::NOT_SUPPORT;
658 return ErrorCode::NOT_FOUND;
663 return ErrorCode::OK;
672 return ErrorCode::OK;
677 endpoint_.pool.GetEndpoint0Out()->Stall();
678 endpoint_.pool.GetEndpoint0In()->Stall();
683 endpoint_.pool.GetEndpoint0Out()->ClearStall();
684 endpoint_.pool.GetEndpoint0In()->ClearStall();
688 RequestDirection direction, Recipient recipient)
692 if (recipient != Recipient::INTERFACE)
694 return ErrorCode::NOT_SUPPORT;
697 uint8_t intf_num = setup->
wIndex & 0xFF;
703 return ErrorCode::NOT_FOUND;
711 if (ans != ErrorCode::OK)
718 class_req_.read =
true;
719 class_req_.class_ptr = item;
720 class_req_.b_request = setup->
bRequest;
725 class_req_.write =
true;
726 class_req_.class_ptr = item;
727 class_req_.b_request = setup->
bRequest;
739 return ErrorCode::OK;
743 RequestDirection direction,
752 return ErrorCode::NOT_SUPPORT;
static Callback Create(FunType fun, ArgType arg)
创建一个新的回调对象,并绑定回调函数和参数。 Creates a new callback instance, binding a function and an 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.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
bool IsComposite() const
判断是否为复合设备(composite device) Check if this is a composite device
RawData GetData() const
获取拼接好的配置描述符数据 Get the generated configuration descriptor data
uint16_t GetDeviceStatus() const
获取当前设备状态 / Get the current device status
void AssignEndpoints()
分配端点并分配总缓冲区 Assign endpoints and allocate the total config descriptor buffer
ErrorCode OverrideDeviceDescriptor(DeviceDescriptor &descriptor)
覆盖设备描述符(非IAD时可用) Override the device descriptor (can be used when not using IAD)
void ReleaseEndpoints()
释放所有功能项占用的端点资源 Release all endpoints/resources allocated by function blocks
ErrorCode Generate()
生成完整的配置描述符(自动拼接 header 和所有功能项数据) Generate and assemble the full configuration descriptor (header + al...
size_t GetCurrentConfig() const
获取当前配置值 / Get the current configuration value
ConfigDescriptorItem * GetItemByInterfaceNum(size_t index) const
获取指定接口的配置项 / Get the configuration item by interface number
virtual ErrorCode SetAltSetting(uint8_t itf, uint8_t alt)
设置接口的备用设置 Set the alternate setting of an interface
ErrorCode GenerateString(Index index, uint16_t lang)
生成指定语言和索引的字符串描述符 Generate USB string descriptor for given language and string index
RawData GetData()
获取当前构建好的字符串描述符数据 Get the descriptor buffer
RawData GetLangIDData()
获取语言ID描述符内容 Get LangID descriptor data
Index
描述符字符串索引 / USB descriptor string index
USB 设备类接口基类,所有自定义 USB 类(如 HID、CDC、MSC)都需派生自本类。 USB device class base interface, all custom device cla...
USB 设备协议栈核心类,负责端点 0 控制传输及配置、描述符、标准请求处理等。 USB device protocol stack core class. Handles EP0 control tr...
ErrorCode SwitchConfiguration(uint16_t value)
切换配置 / Switch USB configuration
virtual void EnableRemoteWakeup()
启用远程唤醒功能(SetFeature: DEVICE_REMOTE_WAKEUP) Enable remote wakeup (via SetFeature)
ConfigDescriptor config_desc_
配置描述符 / Config descriptor
static void OnEP0OutCompleteStatic(bool in_isr, DeviceCore *self, LibXR::ConstRawData &data)
EP0 OUT 端点传输完成回调(静态) EP0 OUT endpoint transfer complete (static)
ErrorCode PrepareAddressChange(uint16_t address)
预设地址变更 / Prepare address change
ErrorCode RespondWithStatus(const SetupPacket *setup, Recipient recipient)
返回状态响应 / Respond with status stage
ErrorCode ProcessStandardRequest(bool in_isr, const SetupPacket *&setup, RequestDirection direction, Recipient recipient)
处理标准请求 Process standard USB requests
static bool IsValidUSBCombination(USBSpec spec, Speed speed, DeviceDescriptor::PacketSize0 packet_size)
检查 USB 组合是否合法 / Check if USB combination is valid
Context
控制传输状态枚举 / Control transfer context enum
@ SETUP
SETUP 阶段 / Setup stage.
@ STATUS_IN
状态 IN 阶段 / Status in stage
@ DATA_OUT
数据 OUT 阶段 / Data out stage
@ STATUS_OUT
状态 OUT 阶段 / Status out stage
@ DATA_IN
数据 IN 阶段 / Data in stage
@ ZLP
0 长度包 / Zero-length packet
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)
构造函数 / Constructor
void ReadZLP(Context context=Context::ZLP)
接收 0 长度包 / Receive zero-length packet (ZLP)
ErrorCode ProcessVendorRequest(bool in_isr, const SetupPacket *&setup, RequestDirection direction, Recipient recipient)
处理厂商请求 / Process vendor-specific request
DeviceDescriptor device_desc_
设备描述符 / Device descriptor
virtual void Deinit()
反初始化 USB 设备 / Deinitialize USB device
void OnEP0InComplete(bool in_isr, LibXR::ConstRawData &data)
EP0 IN 端点传输完成回调 / EP0 IN endpoint transfer complete.
Speed GetSpeed() const
获取当前 USB 速度 / Get current USB speed
void WriteZLP(Context context=Context::ZLP)
发送 0 长度包 / Send zero-length packet (ZLP)
void OnEP0OutComplete(bool in_isr, LibXR::ConstRawData &data)
EP0 OUT 端点传输完成回调 / EP0 OUT endpoint transfer complete.
void DevReadEP0Data(LibXR::RawData data, size_t packet_max_length)
接收主机发送的 EP0 数据包 Receive data packet from host via EP0
virtual void DisableRemoteWakeup()
禁用远程唤醒功能(ClearFeature: DEVICE_REMOTE_WAKEUP) Disable remote wakeup (via ClearFeature)
static void OnEP0InCompleteStatic(bool in_isr, DeviceCore *self, LibXR::ConstRawData &data)
EP0 IN 端点传输完成回调(静态) EP0 IN endpoint transfer complete (static)
ErrorCode ClearFeature(const SetupPacket *setup, Recipient recipient)
清除功能特性 / Clear USB feature
ErrorCode SendDescriptor(bool in_isr, const SetupPacket *setup, Recipient recipient)
发送描述符 / Send USB descriptor
ErrorCode ApplyFeature(const SetupPacket *setup, Recipient recipient)
启用功能特性 / Apply USB feature
Speed speed
当前速度 / Current speed
DescriptorStrings strings_
字符串描述符管理 / String descriptors
ErrorCode ProcessClassRequest(bool in_isr, const SetupPacket *setup, RequestDirection direction, Recipient recipient)
处理类请求 / Process class-specific request
void OnSetupPacket(bool in_isr, const SetupPacket *setup)
处理主机发送的 SETUP 包 Handle USB setup packet from host
ErrorCode SendConfiguration()
发送配置响应 / Send configuration
virtual void Init()
初始化 USB 设备 / Initialize USB device
void StallControlEndpoint()
设置控制端点为 STALL / Stall control endpoint
void ClearControlEndpointStall()
清除控制端点 STALL / Clear control endpoint stall
virtual ErrorCode SetAddress(uint8_t address, Context state)=0
设置设备地址(必须由子类实现) Set device address (must be implemented by subclass)
void DevWriteEP0Data(LibXR::ConstRawData data, size_t packet_max_length, size_t request_size=0)
向主机发送 EP0 数据包 Send data packet to host via EP0
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
停止端点传输 Stop endpoint transfer
@ OUT
输出方向 / OUT direction
virtual ErrorCode ClearStall()=0
清除端点停止状态 Clear endpoint stop status
State GetState() const
获取端点状态 Get endpoint state
USB端点池类 / USB endpoint pool class.
控制请求结果结构体 / Structure for control transfer results
RawData read_data
设备返回给主机的数据 / Data to read (to host)
bool write_zlp
写操作是否需要发送 0 长度包 / Send ZLP after write
ConstRawData write_data
主机写入设备的数据 / Data to write (from host)
bool read_zlp
读操作是否需要发送 0 长度包 / Send ZLP after read
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)