radio_tool 0.2.1
Loading...
Searching...
No Matches
dfu.hpp
1
18#pragma once
19
20#include <stdint.h>
21#include <vector>
22#include <string>
23#include <sstream>
24#include <iomanip>
25#include <iostream>
26
27#include <libusb-1.0/libusb.h>
28
30{
31 enum class DFURequest : uint8_t
32 {
36 DETACH = 0x00,
37
42 DNLOAD = 0x01,
43
48 UPLOAD = 0x02,
49
55 GETSTATUS = 0x03,
56
60 CLRSTATUS = 0x04,
61
66 GETSTATE = 5,
67
72 ABORT = 6
73 };
74
75 enum class DFUState : uint8_t
76 {
77 IDLE = 0x00,
78 DETACH = 0x01,
79 DFU_IDLE = 0x02,
80 DFU_DOWNLOAD_SYNC = 0x03,
81 DFU_DOWNLOAD_BUSY = 0x04,
82 DFU_DOWNLOAD_IDLE = 0x05,
83 DFU_MANIFEST_SYNC = 0x06,
84 DFU_MANIFEST = 0x07,
85 DFU_MANIFEST_WAIT_RESET = 0x08,
86 DFU_UPLOAD_IDLE = 0x09,
87 DFU_ERROR = 0x0a,
88 DFU_UPLOAD_SYNC = 0x91,
89 DFU_UPLOAD_BUSY = 0x92
90 };
91
92 enum class DFUStatus : uint8_t
93 {
94 OK = 0x00,
95 errTARGET = 0x01,
96 errFILE = 0x02,
97 errWRITE = 0x03,
98 errERASE = 0x04,
99 errCHECK_ERASE = 0x05,
100 errPROG = 0x06,
101 errVERIFY = 0x07,
102 errADDRESS = 0x08,
103 errNOTDONE = 0x09,
104 errFIRMWARE = 0x0a,
105 errVENDOR = 0x0b,
106 errUSBR = 0x0c,
107 errPOR = 0x0d,
108 errUNKNOWN = 0x0e,
109 errSTALLEDPKT = 0x0f,
110 };
111
112 static auto ToString(DFUStatus s)
113 {
114 switch (s)
115 {
116 case DFUStatus::OK:
117 return "OK";
118 case DFUStatus::errTARGET:
119 return "errTARGET";
120 case DFUStatus::errFILE:
121 return "errFILE";
122 case DFUStatus::errWRITE:
123 return "errWRITE";
124 case DFUStatus::errERASE:
125 return "errERASE";
126 case DFUStatus::errCHECK_ERASE:
127 return "errCHECK_ERASE";
128 case DFUStatus::errPROG:
129 return "errPROG";
130 case DFUStatus::errVERIFY:
131 return "errVERIFY";
132 case DFUStatus::errADDRESS:
133 return "errADDRESS";
134 case DFUStatus::errNOTDONE:
135 return "errNOTDONE";
136 case DFUStatus::errFIRMWARE:
137 return "errFIRMWARE";
138 case DFUStatus::errVENDOR:
139 return "errVENDOR";
140 case DFUStatus::errUSBR:
141 return "errUSBR";
142 case DFUStatus::errPOR:
143 return "errPOR";
144 case DFUStatus::errUNKNOWN:
145 return "errUNKNOWN";
146 case DFUStatus::errSTALLEDPKT:
147 return "errSTALLEDPKT";
148 }
149 return "**UKNOWN**";
150 };
151
152 static auto ToString(DFUState s)
153 {
154 switch (s)
155 {
156 case DFUState::IDLE:
157 return "IDLE";
158 case DFUState::DETACH:
159 return "DETACH";
160 case DFUState::DFU_IDLE:
161 return "DFU_IDLE";
162 case DFUState::DFU_DOWNLOAD_SYNC:
163 return "DFU_DOWNLOAD_SYNC";
164 case DFUState::DFU_DOWNLOAD_BUSY:
165 return "DFU_DOWNLOAD_BUSY";
166 case DFUState::DFU_DOWNLOAD_IDLE:
167 return "DFU_DOWNLOAD_IDLE";
168 case DFUState::DFU_MANIFEST_SYNC:
169 return "DFU_MANIFEST_SYNC";
170 case DFUState::DFU_MANIFEST:
171 return "DFU_MANIFEST";
172 case DFUState::DFU_MANIFEST_WAIT_RESET:
173 return "DFU_MANIFEST_WAIT_RESET";
174 case DFUState::DFU_UPLOAD_IDLE:
175 return "DFU_UPLOAD_IDLE";
176 case DFUState::DFU_ERROR:
177 return "DFU_ERROR";
178 case DFUState::DFU_UPLOAD_SYNC:
179 return "DFU_UPLOAD_SYNC";
180 case DFUState::DFU_UPLOAD_BUSY:
181 return "DFU_UPLOAD_BUSY";
182 }
183 return "**UKNOWN**";
184 };
185
187 {
188 public:
189 DFUStatusReport(const DFUStatus &status, const uint32_t &timeout, const DFUState &state, const uint8_t &discarded)
190 : status(status), timeout(timeout), state(state), discarded(discarded)
191 {
192 //std::cerr << ToString() << std::endl;
193 }
194
195 const DFUStatus status;
196 const uint32_t timeout;
197 const DFUState state;
198 const uint8_t discarded;
199
200 static auto Parse(const uint8_t data[6]) -> const DFUStatusReport
201 {
202 return DFUStatusReport(
203 static_cast<DFUStatus>((int)data[0]),
204 (((data[1] << 8) | data[2]) << 8) | data[3],
205 static_cast<DFUState>((int)data[4]),
206 (int)data[5]);
207 }
208
209 static auto Empty() -> const DFUStatusReport
210 {
211 return DFUStatusReport();
212 }
213
214 auto ToString() const -> std::string
215 {
216 std::stringstream out;
217 out << "Status: " << radio_tool::dfu::ToString(status) << ", "
218 << "Timeout: 0x" << std::setfill('0') << std::setw(2) << std::hex << timeout << ", "
219 << "State: " << radio_tool::dfu::ToString(state) << ", "
220 << "Discarded: 0x" << std::setfill('0') << std::setw(2) << std::hex << discarded;
221 return out.str();
222 }
223
224 private:
226 : status(DFUStatus::errUNKNOWN), timeout(0), state(DFUState::DFU_ERROR), discarded(0)
227 {
228 }
229 };
230
231 class DFU
232 {
233 public:
234 DFU(libusb_device_handle *device)
235 : timeout(5000), device(device) {}
236
237 auto SetAddress(const uint32_t &) const -> void;
238 auto Erase(const uint32_t &) const -> void;
239 auto Download(const std::vector<uint8_t> &, const uint16_t &wValue = 0) const -> void;
240 auto Upload(const uint16_t &, const uint8_t &wValue = 0) const -> std::vector<uint8_t>;
241
242 auto Get() const -> std::vector<uint8_t>;
243 auto ReadUnprotected() const -> void;
244
245 auto GetState() const -> DFUState;
246 auto GetStatus() const -> const DFUStatusReport;
247 auto Abort() const -> void;
248 auto Detach() const -> void;
249
250 private:
251 libusb_context *usb_ctx;
252 auto GetDeviceString(const libusb_device_descriptor &, libusb_device_handle *) const -> std::wstring;
253
254 protected:
255 const uint16_t timeout;
256 libusb_device_handle *device;
257
258 auto CheckDevice() const -> void;
259
263 auto InitDownload() const -> void;
264
268 auto InitUpload() const -> void;
269 };
270} // namespace radio_tool::dfu
auto InitUpload() const -> void
Definition: dfu.cpp:177
auto InitDownload() const -> void
Definition: dfu.cpp:157