3#include "dfu/dfu_def.hpp"
14 using JumpCallback = void (*)(
void*);
15 static constexpr const char* DEFAULT_INTERFACE_STRING =
"XRUSB DFU RT";
16 static constexpr uint8_t ATTR_WILL_DETACH = 0x08u;
23 JumpCallback jump_to_bootloader,
void* jump_ctx =
nullptr,
24 uint16_t detach_timeout_ms = 50u,
25 const char* interface_string = DEFAULT_INTERFACE_STRING,
26 const char* webusb_landing_page_url =
nullptr,
27 uint8_t webusb_vendor_code = LibXR::USB::WebUsb::WEBUSB_VENDOR_CODE_DEFAULT)
29 webusb_vendor_code, DEFAULT_WINUSB_DEVICE_INTERFACE_GUID,
30 DEFAULT_WINUSB_VENDOR_CODE, WinUsbMsOs20Scope::FUNCTION),
31 jump_to_bootloader_(jump_to_bootloader),
33 default_detach_timeout_ms_(detach_timeout_ms)
48 if (
static_cast<int32_t
>(now_ms - detach_deadline_ms_) < 0)
53 detach_pending_ =
false;
54 if (jump_to_bootloader_ !=
nullptr)
56 jump_to_bootloader_(jump_ctx_);
69 uint8_t bDescriptorType = 0x21;
70 uint8_t bmAttributes = 0u;
71 uint16_t wDetachTimeOut = 0;
72 uint16_t wTransferSize = 0;
73 uint16_t bcdDFUVersion = 0x0110u;
81 uint8_t bStatus =
static_cast<uint8_t
>(DFUStatusCode::OK);
82 uint8_t bwPollTimeout[3] = {0, 0, 0};
83 uint8_t bState =
static_cast<uint8_t
>(DFUState::APP_IDLE);
86 void SetPollTimeout(uint32_t timeout_ms)
88 bwPollTimeout[0] =
static_cast<uint8_t
>(timeout_ms & 0xFFu);
89 bwPollTimeout[1] =
static_cast<uint8_t
>((timeout_ms >> 8) & 0xFFu);
90 bwPollTimeout[2] =
static_cast<uint8_t
>((timeout_ms >> 16) & 0xFFu);
101 9,
static_cast<uint8_t
>(DescriptorType::INTERFACE), 0, 0, 0, 0xFEu, 0x01u, 0x01u,
112 interface_num_ = start_itf_num;
113 UpdateWinUsbFunctionInterface(interface_num_);
114 current_alt_setting_ = 0u;
115 detach_pending_ =
false;
116 detach_timeout_ms_ = default_detach_timeout_ms_;
117 state_ = DFUState::APP_IDLE;
120 desc_block_.func_desc.bmAttributes =
121 (jump_to_bootloader_ !=
nullptr) ? ATTR_WILL_DETACH : 0u;
122 desc_block_.func_desc.wDetachTimeOut =
123 (jump_to_bootloader_ !=
nullptr) ? detach_timeout_ms_ : 0u;
124 desc_block_.func_desc.wTransferSize = 0u;
125 SetData(
RawData{
reinterpret_cast<uint8_t*
>(&desc_block_),
sizeof(desc_block_)});
133 detach_pending_ =
false;
134 state_ = DFUState::APP_IDLE;
144 if (itf != interface_num_)
152 current_alt_setting_ = alt;
158 if (itf != interface_num_)
162 alt = current_alt_setting_;
169 const uint8_t desc_type =
static_cast<uint8_t
>((wValue >> 8) & 0xFFu);
170 if (desc_type != desc_block_.func_desc.bDescriptorType)
175 out_data = {
reinterpret_cast<const uint8_t*
>(&desc_block_.func_desc),
176 sizeof(desc_block_.func_desc)};
187 if ((wIndex & 0xFFu) != interface_num_)
192 switch (
static_cast<DFURequest
>(bRequest))
194 case DFURequest::DETACH:
199 if (jump_to_bootloader_ ==
nullptr)
203 if (wLength != 0u || state_ != DFUState::APP_IDLE)
207 detach_timeout_ms_ = (wValue == 0u) ? default_detach_timeout_ms_ : wValue;
210 detach_pending_ =
true;
211 state_ = DFUState::APP_DETACH;
212 desc_block_.func_desc.wDetachTimeOut = detach_timeout_ms_;
213 result.SendStatusInZLP() =
true;
216 case DFURequest::GETSTATUS:
220 status_response_.bStatus =
static_cast<uint8_t
>(DFUStatusCode::OK);
221 status_response_.bState =
static_cast<uint8_t
>(state_);
224 const uint32_t now_ms =
226 const uint32_t remain_ms =
227 (
static_cast<int32_t
>(detach_deadline_ms_ - now_ms) > 0)
228 ? (detach_deadline_ms_ - now_ms)
230 status_response_.SetPollTimeout(remain_ms);
234 status_response_.SetPollTimeout(0u);
236 result.InData() = {
reinterpret_cast<const uint8_t*
>(&status_response_),
237 sizeof(status_response_)};
240 case DFURequest::GETSTATE:
241 state_response_ =
static_cast<uint8_t
>(state_);
242 result.InData() = {&state_response_,
sizeof(state_response_)};
251 DescriptorBlock desc_block_ = {};
252 StatusResponse status_response_ = {};
253 JumpCallback jump_to_bootloader_ =
nullptr;
254 void* jump_ctx_ =
nullptr;
255 uint8_t state_response_ = 0u;
256 bool detach_pending_ =
false;
257 uint16_t default_detach_timeout_ms_ =
259 uint16_t detach_timeout_ms_ = 50u;
260 uint32_t detach_deadline_ms_ = 0u;
261 DFUState state_ = DFUState::APP_IDLE;
只读原始数据视图 / Immutable raw data view
可写原始数据视图 / Mutable raw data view
static MillisecondTimestamp GetMilliseconds()
获取当前时间的毫秒级时间戳。 Gets the current timestamp in milliseconds.
void SetData(RawData data)
设置内部数据缓存 / Set internal data cache
uint8_t GetInterfaceStringIndex(size_t local_interface_index) const
返回已分配的接口字符串索引 Return the assigned USB string index for a local interface.
DFU 单接口类公共基类 / Common base for single-interface DFU classes.
Runtime DFU 类:只负责 DETACH 后跳转 bootloader Runtime DFU class: only handles DETACH and later jumps to boo...
ErrorCode SetAltSetting(uint8_t itf, uint8_t alt) override
可选:设置接口备用设置 / Optional: set interface alternate setting
LIBXR_PACKED_END void BindEndpoints(EndpointPool &, uint8_t start_itf_num, bool) override
绑定端点资源 / Bind endpoint resources
DfuRuntimeClass(JumpCallback jump_to_bootloader, void *jump_ctx=nullptr, uint16_t detach_timeout_ms=50u, const char *interface_string=DEFAULT_INTERFACE_STRING, const char *webusb_landing_page_url=nullptr, uint8_t webusb_vendor_code=LibXR::USB::WebUsb::WEBUSB_VENDOR_CODE_DEFAULT)
构造 Runtime DFU 类 Construct the runtime DFU class.
size_t GetMaxConfigSize() override
最大配置描述符占用 / Maximum bytes required in configuration descriptor
void UnbindEndpoints(EndpointPool &, bool) override
解绑端点资源 / Unbind endpoint resources
size_t GetInterfaceCount() override
接口数量 / Number of interfaces contributed
ErrorCode OnClassRequest(bool, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, ControlTransferResult &result) override
处理 Class-specific 请求(Setup stage)/ Handle class-specific request (Setup stage)
ErrorCode OnGetDescriptor(bool, uint8_t, uint16_t wValue, uint16_t, ConstRawData &out_data) override
处理标准请求 GET_DESCRIPTOR(类特定描述符) Handle standard GET_DESCRIPTOR request (class-specific descriptors).
ErrorCode GetAltSetting(uint8_t itf, uint8_t &alt) override
可选:获取接口备用设置 / Optional: get interface alternate setting
bool HasIAD() override
是否包含 IAD / Whether an IAD is used
USB端点池类 / USB endpoint pool class.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ INIT_ERR
初始化错误 / Initialization error
@ NOT_FOUND
未找到 / Not found
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
接口描述符(9 字节)/ Interface descriptor (9 bytes)
uint8_t iInterface
接口字符串索引 / Interface string index
uint8_t bInterfaceNumber
接口号 / Interface number
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
Runtime DFU 的接口描述符块 Runtime DFU descriptor block.
DFU Functional Descriptor(Runtime 变体) DFU Functional Descriptor for the runtime variant.
GETSTATUS 返回包 / GETSTATUS response payload.