6#include "dfu/dfu_def.hpp"
17 using JumpCallback = void (*)(
void*);
18 static constexpr uint32_t kSealMagic = 0x4C414553u;
26 uint32_t magic = kSealMagic;
27 uint32_t image_size = 0u;
29 uint32_t crc32_inv = 0u;
42 size_t seal_offset, JumpCallback jump_to_app,
43 void* jump_app_ctx =
nullptr,
bool autorun =
true)
83 image_.launch_requested =
false;
88 DfuBootloaderBackend(
const DfuBootloaderBackend&) =
delete;
89 DfuBootloaderBackend& operator=(
const DfuBootloaderBackend&) =
delete;
97 caps.can_download =
true;
98 caps.can_upload =
true;
99 caps.manifestation_tolerant =
false;
100 caps.will_detach =
false;
101 caps.detach_timeout_ms = 0u;
105 caps.transfer_size = 0xFFFFu;
124 ResetTransferState();
125 image_.launch_requested =
false;
135 ResetTransferState();
136 image_.launch_requested =
false;
139 DFUStatusCode DfuDownload(uint8_t alt, uint16_t block_num,
ConstRawData data,
140 uint32_t& poll_timeout_ms)
142 poll_timeout_ms = 0u;
146 return DFUStatusCode::ERR_TARGET;
150 return DFUStatusCode::ERR_USBR;
155 return DFUStatusCode::ERR_VENDOR;
157 if (HasPendingWrite() || HasPendingManifest())
159 return DFUStatusCode::ERR_NOTDONE;
162 if ((block_num == 0u) &&
171 ResetTransferState();
178 return DFUStatusCode::ERR_ADDRESS;
180 StartDownloadSession();
182 else if (block_num !=
download_.expected_block_num)
184 return DFUStatusCode::ERR_ADDRESS;
187 const size_t offset =
download_.received_bytes;
188 const size_t payload_limit = PayloadLimit();
189 if (offset + data.
size_ < offset || (offset + data.
size_) > payload_limit)
191 return DFUStatusCode::ERR_ADDRESS;
197 write_.block_num = block_num;
199 download_.last_status = DFUStatusCode::OK;
200 download_.next_poll_timeout_ms = ComputeWritePollTimeout(offset, data.
size_);
201 poll_timeout_ms =
download_.next_poll_timeout_ms;
202 return DFUStatusCode::OK;
205 DFUStatusCode DfuGetDownloadStatus(uint8_t alt,
bool& busy, uint32_t& poll_timeout_ms)
210 poll_timeout_ms = 0u;
211 return DFUStatusCode::ERR_TARGET;
213 busy = HasPendingWrite();
214 poll_timeout_ms = busy ?
download_.next_poll_timeout_ms : 0u;
218 size_t DfuUpload(uint8_t alt, uint16_t block_num, RawData data, DFUStatusCode& status,
219 uint32_t& poll_timeout_ms)
221 poll_timeout_ms = 0u;
222 status = DFUStatusCode::OK;
226 status = DFUStatusCode::ERR_TARGET;
229 if (data.addr_ ==
nullptr || data.size_ == 0u)
231 status = DFUStatusCode::ERR_USBR;
237 upload_.session_started =
true;
239 upload_.expected_block_num = 1u;
240 size_t image_size = 0u;
243 image_size =
image_.stored_size;
245 else if (!ProbeStoredImage(&image_size))
249 upload_.image_size = image_size;
252 status = DFUStatusCode::ERR_FIRMWARE;
256 else if (!
upload_.session_started || block_num !=
upload_.expected_block_num)
258 status = DFUStatusCode::ERR_ADDRESS;
268 if (read_size > data.size_)
270 read_size = data.size_;
273 {reinterpret_cast<uint8_t*>(data.addr_), read_size}) !=
ErrorCode::OK)
275 status = DFUStatusCode::ERR_FIRMWARE;
280 upload_.expected_block_num =
static_cast<uint16_t
>(block_num + 1u);
289 poll_timeout_ms = 0u;
293 return DFUStatusCode::ERR_TARGET;
295 if (!
download_.session_started ||
download_.received_bytes == 0u || HasPendingWrite())
297 return DFUStatusCode::ERR_NOTDONE;
300 manifest_.last_status = DFUStatusCode::OK;
301 poll_timeout_ms =
manifest_.poll_timeout_ms;
302 return DFUStatusCode::OK;
313 poll_timeout_ms = 0u;
314 return DFUStatusCode::ERR_TARGET;
316 busy = HasPendingManifest();
317 poll_timeout_ms = busy ?
manifest_.poll_timeout_ms : 0u;
329 ProcessPendingWrite();
334 ProcessPendingManifest();
338 bool TryRequestRunApp()
346 size_t image_size = 0u;
347 image_.ready = ProbeStoredImage(&image_size);
352 image_.launch_requested =
true;
358 void DfuCommitManifestWaitReset(uint8_t alt)
366 image_.launch_requested =
true;
370 bool TryConsumeAppLaunch(uint32_t)
376 image_.launch_requested =
false;
384 bool HasPendingWork()
const {
return HasPendingWrite() || HasPendingManifest(); }
386 bool HasValidImage()
const {
return image_.ready; }
387 size_t ImageSize()
const {
return image_.stored_size; }
392 size_t PayloadLimit()
const
403 void StartDownloadSession()
405 ResetTransferState();
413 image_.launch_requested =
false;
416 void ResetTransferState()
428 bool HasPendingWrite()
const {
return write_.pending; }
430 bool HasPendingManifest()
const {
return manifest_.pending; }
436 uint32_t ComputeWritePollTimeout(
size_t offset,
size_t len)
const
457 void ProcessPendingWrite()
461 download_.last_status = DFUStatusCode::ERR_ERASE;
468 download_.last_status = DFUStatusCode::ERR_PROG;
474 download_.expected_block_num =
static_cast<uint16_t
>(
write_.block_num + 1u);
475 download_.last_status = DFUStatusCode::OK;
481 void ProcessPendingManifest()
483 const size_t payload_limit = PayloadLimit();
486 manifest_.last_status = DFUStatusCode::ERR_ADDRESS;
492 if (!ComputeImageCrc32(
download_.received_bytes, crc32))
494 manifest_.last_status = DFUStatusCode::ERR_VERIFY;
498 if (!WriteSeal(
download_.received_bytes, crc32))
500 manifest_.last_status = DFUStatusCode::ERR_VERIFY;
507 image_.launch_requested =
false;
508 manifest_.last_status = DFUStatusCode::OK;
512 upload_.session_started =
false;
514 upload_.expected_block_num = 0u;
521 bool ComputeImageCrc32(
size_t image_size, uint32_t& crc32_out)
527 uint32_t crc = 0xFFFFFFFFu;
529 while (offset < image_size)
531 size_t chunk = image_size - offset;
541 size_t remain = chunk;
542 while (remain-- > 0u)
554 bool ReadSeal(SealRecord& seal)
564 bool WriteSeal(
size_t image_size, uint32_t crc32)
572 seal->magic = kSealMagic;
573 seal->image_size =
static_cast<uint32_t
>(image_size);
575 seal->crc32_inv = ~crc32;
589 bool ProbeStoredImage(
size_t* out_image_size)
591 SealRecord seal = {};
596 if (seal.magic != kSealMagic)
600 if ((seal.crc32 ^ seal.crc32_inv) != 0xFFFFFFFFu)
604 const size_t image_size =
static_cast<size_t>(seal.image_size);
605 if (image_size == 0u || image_size > PayloadLimit())
609 uint32_t actual_crc = 0u;
610 if (!ComputeImageCrc32(image_size, actual_crc))
614 if (actual_crc != seal.crc32)
618 if (out_image_size !=
nullptr)
620 *out_image_size = image_size;
629 bool EnsureBlocksErased(
size_t offset,
size_t len)
643 for (
size_t block = first_block; block <= last_block; ++block)
665 bool launch_requested =
false;
667 size_t stored_size = 0u;
675 bool session_started =
false;
676 size_t received_bytes = 0u;
677 uint16_t expected_block_num = 0u;
678 uint32_t next_poll_timeout_ms = 0u;
679 DFUStatusCode last_status = DFUStatusCode::OK;
689 uint16_t block_num = 0u;
690 bool pending =
false;
698 bool pending =
false;
699 uint32_t poll_timeout_ms = 50u;
700 DFUStatusCode last_status = DFUStatusCode::OK;
708 bool session_started =
false;
710 uint16_t expected_block_num = 0u;
711 size_t image_size = 0u;
741template <
typename Backend,
size_t MAX_TRANSFER_SIZE = 4096u>
744 static_assert(MAX_TRANSFER_SIZE > 0u,
"DFU transfer size must be non-zero.");
745 static_assert(MAX_TRANSFER_SIZE <= 0xFFFFu,
746 "DFU transfer size must fit in wTransferSize.");
748 static constexpr uint8_t kInterfaceClass = 0xFEu;
749 static constexpr uint8_t kInterfaceSubClass = 0x01u;
750 static constexpr uint8_t kInterfaceProtocol = 0x02u;
751 static constexpr uint16_t kDfuVersion = 0x0110u;
753 static constexpr uint8_t kAttrCanDownload = 0x01u;
754 static constexpr uint8_t kAttrCanUpload = 0x02u;
755 static constexpr uint8_t kAttrManifestationTolerant = 0x04u;
756 static constexpr uint8_t kAttrWillDetach = 0x08u;
767 uint8_t bDescriptorType = 0x21;
768 uint8_t bmAttributes = 0;
769 uint16_t wDetachTimeOut = 0;
770 uint16_t wTransferSize = 0;
771 uint16_t bcdDFUVersion = kDfuVersion;
780 uint8_t bwPollTimeout[3] = {0, 0, 0};
784 void SetPollTimeout(uint32_t timeout_ms)
786 bwPollTimeout[0] =
static_cast<uint8_t
>(timeout_ms & 0xFFu);
787 bwPollTimeout[1] =
static_cast<uint8_t
>((timeout_ms >> 8) & 0xFFu);
788 bwPollTimeout[2] =
static_cast<uint8_t
>((timeout_ms >> 16) & 0xFFu);
799 static_cast<uint8_t
>(DescriptorType::INTERFACE),
812 "DFU functional descriptor size mismatch.");
813 static_assert(
sizeof(
StatusResponse) == 6,
"DFU status response size mismatch.");
816 static constexpr const char* DEFAULT_INTERFACE_STRING =
"XRUSB DFU";
836 Backend& backend,
const char* interface_string = DEFAULT_INTERFACE_STRING,
837 const char* webusb_landing_page_url =
nullptr,
838 uint8_t webusb_vendor_code = LibXR::USB::WebUsb::WEBUSB_VENDOR_CODE_DEFAULT)
850 interface_num_ = start_itf_num;
851 current_alt_setting_ = 0u;
854 if (
caps_.transfer_size == 0u ||
caps_.transfer_size > MAX_TRANSFER_SIZE)
856 caps_.transfer_size =
static_cast<uint16_t
>(MAX_TRANSFER_SIZE);
869 ResetProtocolState();
870 auto ec =
backend_.DfuSetAlternate(current_alt_setting_);
888 backend_.DfuAbort(current_alt_setting_);
891 ResetProtocolState();
907 if (itf != interface_num_)
915 if (
state_ == DFUState::DFU_DNBUSY ||
state_ == DFUState::DFU_MANIFEST ||
916 state_ == DFUState::DFU_MANIFEST_WAIT_RESET)
923 auto ec =
backend_.DfuSetAlternate(alt);
929 backend_.DfuAbort(current_alt_setting_);
930 current_alt_setting_ = alt;
937 if (itf != interface_num_)
941 alt = current_alt_setting_;
948 const uint8_t desc_type =
static_cast<uint8_t
>((wValue >> 8) & 0xFFu);
949 if (desc_type !=
desc_block_.func_desc.bDescriptorType)
954 out_data = {
reinterpret_cast<const uint8_t*
>(&
desc_block_.func_desc),
966 if ((wIndex & 0xFFu) != interface_num_)
971 switch (
static_cast<DFURequest
>(bRequest))
973 case DFURequest::DETACH:
974 return HandleDetach(result);
976 case DFURequest::DNLOAD:
977 return HandleDnload(wValue, wLength, result);
979 case DFURequest::UPLOAD:
980 return HandleUpload(wValue, wLength, result);
982 case DFURequest::GETSTATUS:
983 return HandleGetStatus(result);
985 case DFURequest::CLRSTATUS:
986 return HandleClearStatus(result);
988 case DFURequest::GETSTATE:
989 return HandleGetState(result);
991 case DFURequest::ABORT:
992 return HandleAbort(result);
995 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1001 const auto request =
static_cast<DFURequest
>(bRequest);
1004 if (request != DFURequest::DNLOAD)
1017 uint32_t poll_timeout_ms = 0u;
1023 if (status == DFUStatusCode::OK)
1025 state_ = DFUState::DFU_DNLOAD_SYNC;
1031 EnterErrorState(status);
1038 if (
static_cast<DFURequest
>(bRequest) != DFURequest::GETSTATUS)
1042 if (
state_ == DFUState::DFU_MANIFEST_WAIT_RESET)
1048 backend_.DfuCommitManifestWaitReset(current_alt_setting_);
1053 static constexpr uint8_t BuildAttributeBitmap(
const DFUCapabilities& caps)
1055 return static_cast<uint8_t
>(
1056 (caps.can_download ? kAttrCanDownload : 0u) |
1057 (caps.can_upload ? kAttrCanUpload : 0u) |
1058 (caps.manifestation_tolerant ? kAttrManifestationTolerant : 0u) |
1059 (caps.will_detach ? kAttrWillDetach : 0u));
1062 ErrorCode HandleDetach(ControlTransferResult&)
1066 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1069 ErrorCode HandleDnload(uint16_t block_num, uint16_t wLength,
1070 ControlTransferResult& result)
1072 if (!
caps_.can_download)
1074 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1076 if (!(
state_ == DFUState::DFU_IDLE ||
state_ == DFUState::DFU_DNLOAD_IDLE))
1078 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1080 if (wLength >
caps_.transfer_size)
1082 return ProtocolStall(DFUStatusCode::ERR_USBR);
1095 EnterErrorState(DFUStatusCode::ERR_NOTDONE);
1099 state_ = DFUState::DFU_MANIFEST_SYNC;
1103 result.SendStatusInZLP() =
true;
1113 ErrorCode HandleUpload(uint16_t block_num, uint16_t wLength,
1114 ControlTransferResult& result)
1116 if (!
caps_.can_upload)
1118 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1120 if (!(
state_ == DFUState::DFU_IDLE ||
state_ == DFUState::DFU_UPLOAD_IDLE))
1122 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1126 return ProtocolStall(DFUStatusCode::ERR_USBR);
1129 size_t req_size = wLength;
1130 if (req_size >
caps_.transfer_size)
1132 req_size =
caps_.transfer_size;
1135 DFUStatusCode op_status = DFUStatusCode::OK;
1136 uint32_t poll_timeout_ms = 0u;
1137 const size_t read_size =
1139 op_status, poll_timeout_ms);
1142 if (op_status != DFUStatusCode::OK)
1144 return ProtocolStall(op_status);
1146 if (read_size > req_size)
1148 return ProtocolStall(DFUStatusCode::ERR_USBR);
1152 state_ = (read_size < req_size) ? DFUState::DFU_IDLE : DFUState::DFU_UPLOAD_IDLE;
1157 ErrorCode HandleGetStatus(ControlTransferResult& result)
1159 AdvanceStateForStatusRead();
1169 ErrorCode HandleClearStatus(ControlTransferResult& result)
1171 if (
state_ != DFUState::DFU_ERROR)
1173 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1175 backend_.DfuClearStatus(current_alt_setting_);
1177 result.SendStatusInZLP() =
true;
1181 ErrorCode HandleGetState(ControlTransferResult& result)
1188 ErrorCode HandleAbort(ControlTransferResult& result)
1192 case DFUState::DFU_IDLE:
1193 case DFUState::DFU_DNLOAD_SYNC:
1194 case DFUState::DFU_DNLOAD_IDLE:
1195 case DFUState::DFU_UPLOAD_IDLE:
1196 case DFUState::DFU_MANIFEST_SYNC:
1197 backend_.DfuAbort(current_alt_setting_);
1199 result.SendStatusInZLP() =
true;
1203 return ProtocolStall(DFUStatusCode::ERR_STALLEDPKT);
1207 void AdvanceStateForStatusRead()
1213 case DFUState::DFU_DNLOAD_SYNC:
1214 RefreshDownloadStatus();
1217 case DFUState::DFU_MANIFEST_SYNC:
1219 if (
status_ != DFUStatusCode::OK)
1221 state_ = DFUState::DFU_ERROR;
1225 uint32_t poll_timeout_ms = 0u;
1226 auto manifest_status =
1227 backend_.DfuManifest(current_alt_setting_, poll_timeout_ms);
1229 if (manifest_status == DFUStatusCode::OK)
1232 state_ = DFUState::DFU_MANIFEST;
1236 EnterErrorState(manifest_status);
1241 case DFUState::DFU_DNBUSY:
1242 RefreshDownloadStatus();
1245 case DFUState::DFU_MANIFEST:
1246 RefreshManifestStatus();
1254 void RefreshDownloadStatus()
1256 if (
status_ != DFUStatusCode::OK)
1258 state_ = DFUState::DFU_ERROR;
1263 uint32_t poll_timeout_ms = 0u;
1264 const auto download_status =
1265 backend_.DfuGetDownloadStatus(current_alt_setting_, busy, poll_timeout_ms);
1267 if (download_status != DFUStatusCode::OK)
1269 EnterErrorState(download_status);
1277 state_ = busy ? DFUState::DFU_DNBUSY : DFUState::DFU_DNLOAD_IDLE;
1280 void RefreshManifestStatus()
1282 if (
status_ != DFUStatusCode::OK)
1284 state_ = DFUState::DFU_ERROR;
1289 uint32_t poll_timeout_ms = 0u;
1290 const auto manifest_status =
1291 backend_.DfuGetManifestStatus(current_alt_setting_, busy, poll_timeout_ms);
1293 if (manifest_status != DFUStatusCode::OK)
1295 EnterErrorState(manifest_status);
1301 state_ = DFUState::DFU_MANIFEST;
1308 state_ =
caps_.manifestation_tolerant ? DFUState::DFU_IDLE
1309 : DFUState::DFU_MANIFEST_WAIT_RESET;
1312 void ResetProtocolState()
1321 current_alt_setting_ = 0u;
1326 void ClearErrorState()
1329 state_ = DFUState::DFU_IDLE;
1333 void EnterErrorState(DFUStatusCode status)
1340 state_ = DFUState::DFU_ERROR;
1344 ErrorCode ProtocolStall(DFUStatusCode status)
1346 EnterErrorState(status);
1373 using JumpCallback = DfuBootloaderBackend::JumpCallback;
1376 size_t seal_offset, JumpCallback jump_to_app,
1377 void* jump_app_ctx =
nullptr,
bool autorun =
true)
1378 : backend_(flash, image_base, image_limit, seal_offset, jump_to_app, jump_app_ctx,
1380 image_base_(image_base),
1381 image_limit_(image_limit),
1382 seal_offset_(seal_offset)
1387 size_t image_base_ = 0u;
1388 size_t image_limit_ = 0u;
1389 size_t seal_offset_ = 0u;
1396template <
size_t MAX_TRANSFER_SIZE = 4096u>
1398 public DFUClass<DfuBootloaderBackend, MAX_TRANSFER_SIZE>
1404 using JumpCallback = DfuBootloaderBackend::JumpCallback;
1405 static constexpr uint8_t kVendorRequestRunApp = 0x5Au;
1408 Flash& flash,
size_t image_base,
size_t image_limit,
size_t seal_offset,
1409 JumpCallback jump_to_app,
void* jump_app_ctx =
nullptr,
bool autorun =
true,
1410 const char* interface_string = Base::DEFAULT_INTERFACE_STRING,
1411 const char* webusb_landing_page_url =
nullptr,
1412 uint8_t webusb_vendor_code = LibXR::USB::WebUsb::WEBUSB_VENDOR_CODE_DEFAULT)
1413 :
Storage(flash, image_base, image_limit, seal_offset, jump_to_app, jump_app_ctx,
1415 Base(Storage::backend_, interface_string, webusb_landing_page_url,
1422 void Process() { Storage::backend_.Process(); }
1423 bool RequestRunApp() {
return Storage::backend_.TryRequestRunApp(); }
1425 bool TryConsumeAppLaunch(uint32_t now_ms)
1427 return Storage::backend_.TryConsumeAppLaunch(now_ms);
1430 bool HasPendingWork()
const {
return Storage::backend_.HasPendingWork(); }
1431 bool HasValidImage()
const {
return Storage::backend_.HasValidImage(); }
1432 size_t ImageSize()
const {
return Storage::backend_.ImageSize(); }
1433 size_t ImageBase()
const {
return Storage::image_base_; }
1434 size_t ImageLimit()
const {
return Storage::image_limit_; }
1435 size_t SealOffset()
const {
return Storage::seal_offset_; }
1442 if (bRequest != kVendorRequestRunApp)
1446 if (wLength != 0u || wValue != 0u)
1450 if (Storage::backend_.HasPendingWork())
1456 if (!Storage::backend_.TryRequestRunApp())
1462 result.SendStatusInZLP() =
true;
1467using DfuBootloaderClass = DfuBootloaderClassT<4096u>;
static bool inited_
查找表是否已初始化 / Whether the lookup table is initialized
static uint32_t tab_[256]
CRC32 查找表 / CRC32 lookup table.
static void GenerateTable()
生成 CRC32 查找表 / Generates the CRC32 lookup table
常量原始数据封装类。 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).
Abstract base class representing a flash memory interface. 抽象基类,表示闪存接口。
virtual ErrorCode Erase(size_t offset, size_t size)=0
Erases a section of the flash memory. 擦除闪存的指定区域。
virtual ErrorCode Write(size_t offset, ConstRawData data)=0
Writes data to the flash memory. 向闪存写入数据。
virtual ErrorCode Read(size_t offset, RawData data)
Reads data from the flash memory. 从闪存中读取数据。
size_t MinEraseSize() const
Returns the minimum erasable block size in bytes. 获取最小可擦除块大小(字节)。
原始数据封装类。 A class for encapsulating raw data.
void SetData(RawData data)
设置内部数据缓存 / Set internal data cache
通用 DFU 前端:实现标准 DFU 状态机,backend 只负责存储细节 Generic DFU frontend: implements the standard DFU state machin...
ErrorCode SetAltSetting(uint8_t itf, uint8_t alt) override
可选:设置接口备用设置 / Optional: set interface alternate setting
bool HasIAD() override
是否包含 IAD / Whether an IAD is used
ErrorCode OnClassData(bool, uint8_t bRequest, LibXR::ConstRawData &data) override
处理 Class request 数据阶段 / Handle class request data stage
ErrorCode WriteDeviceDescriptor(DeviceDescriptor &header) override
可选:覆盖设备描述符字段 / Optional: override device descriptor fields
DFUState state_
DFU 状态 / DFU state.
size_t GetInterfaceCount() override
接口数量 / Number of interfaces contributed
void UnbindEndpoints(EndpointPool &, bool) override
解绑端点资源 / Unbind endpoint resources
uint32_t poll_timeout_ms_
当前轮询超时 / Current poll timeout
uint8_t transfer_buffer_[MAX_TRANSFER_SIZE]
EP0 传输缓冲 / EP0 transfer buffer.
DFUClass(Backend &backend, 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)
Backend 需要满足的接口契约 / Backend contract requirements.
DFUStatusCode status_
DFU 状态码 / DFU status code.
ErrorCode OnGetDescriptor(bool, uint8_t, uint16_t wValue, uint16_t, ConstRawData &out_data) override
处理标准请求 GET_DESCRIPTOR(类特定描述符) Handle standard GET_DESCRIPTOR request (class-specific descriptors).
uint16_t pending_block_num_
待提交 block 编号 / Pending block number
void BindEndpoints(EndpointPool &, uint8_t start_itf_num, bool) override
绑定端点资源 / Bind endpoint resources
size_t GetMaxConfigSize() override
最大配置描述符占用 / Maximum bytes required in configuration descriptor
uint16_t pending_dnload_length_
待提交 DNLOAD 长度 / Pending DNLOAD length
uint8_t state_response_
GETSTATE 缓冲字节 / GETSTATE byte buffer.
DescriptorBlock desc_block_
描述符缓存 / Descriptor cache
ErrorCode GetAltSetting(uint8_t itf, uint8_t &alt) override
可选:获取接口备用设置 / Optional: get interface alternate setting
void OnClassInDataStatusComplete(bool, uint8_t bRequest) override
类请求的 IN 数据阶段在 STATUS OUT 完成后回调 Called after the STATUS OUT completes for a Class IN data request.
Backend & backend_
后端实现 / Backend implementation
bool download_started_
是否已有有效下载数据 / Whether payload has started
StatusResponse status_response_
GETSTATUS 缓冲区 / GETSTATUS buffer.
DFUCapabilities caps_
能力集缓存 / Capability cache
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)
uint8_t GetInterfaceStringIndex(size_t local_interface_index) const
返回已分配的接口字符串索引 Return the assigned USB string index for a local interface.
USB描述符基类 USB descriptor base class.
Data data_
设备描述符数据实例 / Internal data instance
@ APPLICATION_SPECIFIC
应用专用类 / Application Specific
Bootloader DFU 的通用后端:围绕 Flash 基类实现 download/upload/manifest Generic bootloader DFU backend built arou...
uint8_t * erased_blocks_
每块擦除标记 / Per-block erase marks
uint8_t crc_buffer_[256]
CRC 分块缓冲 / CRC chunk buffer.
size_t erase_block_count_
受管块数量 / Number of tracked erase blocks
DFUStatusCode DfuGetManifestStatus(uint8_t alt, bool &busy, uint32_t &poll_timeout_ms)
查询 manifest 异步状态 / Query manifest async status
DownloadState download_
Download 状态 / Download state.
size_t transfer_size_
单次 DFU 传输上限 / Per-transfer DFU limit
uint8_t * seal_storage_
seal 暂存区 / Seal scratch buffer
void DfuClearStatus(uint8_t)
清除 DFU 错误态 / Clear the DFU error state
Flash & flash_
底层 flash 设备 / Underlying flash device
size_t seal_offset_
seal 相对镜像区偏移 / Seal offset inside image region
size_t erase_block_size_
最小擦除粒度 / Minimum erase granularity
size_t image_size_limit_
镜像区总边界 / Image region limit
WriteState write_
写入步骤状态 / Write-step state
UploadState upload_
Upload 状态 / Upload state.
ManifestState manifest_
Manifest 状态 / Manifest state.
bool autorun_
manifest 后是否自动请求运行 / Autorun after manifest
void * jump_app_ctx_
跳转上下文 / Jump callback context
uint8_t * write_buffer_
下载块暂存区 / Download chunk buffer
ImageState image_
镜像级状态 / Image-level state
DFUStatusCode DfuManifest(uint8_t alt, uint32_t &poll_timeout_ms)
启动 manifest 阶段 / Start the manifest stage
size_t seal_storage_size_
seal 暂存大小 / Seal scratch size
JumpCallback jump_to_app_
跳 app 回调 / App jump callback
DFUCapabilities GetDfuCapabilities() const
报告 DFU 能力集 / Report DFU capabilities
size_t image_offset_
镜像区起始偏移 / Image base offset
void DfuAbort(uint8_t)
放弃当前协议会话 / Abort the current protocol session
把 backend 与前端 DFUClass 组装在一起的存储基类 Storage base that assembles the backend and the DFU frontend class.
面向单镜像 bootloader 区的 DFU 类 Bootloader DFU class for a single image region.
ErrorCode OnVendorRequest(bool, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t, typename Base::ControlTransferResult &result) override
处理 Vendor request(Setup stage)/ Handle vendor request (Setup stage)
DFU 单接口类公共基类 / Common base for single-interface DFU classes.
USB端点池类 / USB endpoint pool class.
@ INIT_ERR
初始化错误 | Initialization error
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
接口描述符(9 字节)/ Interface descriptor (9 bytes)
uint8_t iInterface
接口字符串索引 / Interface string index
uint8_t bAlternateSetting
备用设置号 / Alternate setting
uint8_t bInterfaceNumber
接口号 / Interface number
DFU 功能能力集合 / DFU functional capability set.
Bootloader DFU 的接口描述符块 / Bootloader DFU descriptor block.
DFU Functional Descriptor(固件模式) DFU Functional Descriptor for firmware mode.
GETSTATUS 返回包 / GETSTATUS response payload.
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
ClassID bDeviceClass
设备类代码 / Device class code
uint8_t bDeviceSubClass
设备子类代码 / Device subclass code
uint8_t bDeviceProtocol
协议代码 / Protocol code
Download 会话状态 / Download session state.
镜像级状态:独立于一次具体的 DFU 传输会话 Image-level state kept outside any single DFU transfer session.
Manifest 会话状态 / Manifest session state.
seal 区固定记录 / Fixed record stored in the seal region
Upload 会话状态 / Upload session state.
延迟写入步骤状态 / Deferred write-step state