radio_tool 0.2.1
Loading...
Searching...
No Matches
h8sx.cpp
1
18#include <radio_tool/h8sx/h8sx.hpp>
19
20#include <algorithm>
21#include <chrono>
22#include <cstring>
23#include <exception>
24#include <thread>
25
26#if defined(_MSC_VER)
27#define bswap32(x) _byteswap_ulong((x))
28#else
29#define bswap32(x) __builtin_bswap32((x))
30#endif
31
32using namespace radio_tool::h8sx;
33
34auto H8SX::IdentifyDevice() const -> std::string
35{
36 int err = 0;
37 int transferred = 0, received = 0;
38 uint8_t buf[BUF_SIZE];
39
40 // First command 0x55 -> Begin inquiry phase
41 uint8_t cmd = static_cast<uint8_t>(H8SXCmd::BEGIN_INQUIRY);
42 err = libusb_bulk_transfer(device,
43 BULK_EP_OUT,
44 &cmd,
45 1,
46 &transferred,
47 0);
48 CHECK_ERR("cannot begin inquiry phase!");
49
50 // Expected response 0xE6 <- (ACK)
51 err = libusb_bulk_transfer(device,
52 BULK_EP_IN,
53 buf,
54 sizeof(buf),
55 &received,
56 0);
57 CHECK_ERR("I/O error!");
58 if (buf[0] != 0xE6)
59 err = -1;
60 CHECK_ERR("wrong response from radio!");
61
62 // Second command 0x20 -> Supported Device Inquiry
63 cmd = static_cast<uint8_t>(H8SXCmd::DEVICE_INQUIRY);
64 err = libusb_bulk_transfer(device,
65 BULK_EP_OUT,
66 &cmd,
67 1,
68 &transferred,
69 0);
70 CHECK_ERR("I/O error!");
71
72 // Expected response <- Supported Device Response
73 err = libusb_bulk_transfer(device,
74 BULK_EP_IN,
75 buf,
76 sizeof(buf),
77 &received,
78 0);
79 // Checksum
80 err = libusb_bulk_transfer(device,
81 BULK_EP_IN,
82 buf,
83 1,
84 &received,
85 0);
86 CHECK_ERR("error in device selection!");
87 auto dir = (struct dev_inq_hdr_t *)buf;
88 // TODO: Validate checksum
89 buf[sizeof(struct dev_inq_hdr_t) + dir->nchar] = '\0';
90
91 // Return device identifier
92 std::ostringstream dev_str;
93 dev_str << dir->code[0]
94 << dir->code[1]
95 << dir->code[2]
96 << dir->code[3]
97 << "-"
98 << buf + sizeof(struct dev_inq_hdr_t);
99 return dev_str.str();
100}
101
102auto H8SX::Download(const std::vector<uint8_t> &data) const -> void
103{
104 int err = 0;
105 int transferred = 0, received = 0;
106 uint8_t buf[BUF_SIZE];
107
108 InitDownload();
109
110 // 128-Byte Programming 0x50 ->
111 struct prog_chunk_t c = {};
112 uint8_t cmd = static_cast<uint8_t>(H8SXCmd::PROGRAM_128B);
113 uint32_t bin_sum = 0;
114 for (std::vector<uint8_t>::size_type i = 0; i < data.size() / 1024; i++)
115 {
116 c.addr = bswap32(i * 1024);
117 std::copy(data.begin() + i * 1024, data.begin() + (i + 1) * 1024, c.data);
118 bin_sum += Checksum((uint8_t *)&(c.data), 1024);
119 c.sum = Checksum((uint8_t *)&c, sizeof(c) - 1);
120 err = libusb_bulk_transfer(device,
121 BULK_EP_OUT,
122 (uint8_t *)&c,
123 sizeof(c),
124 &transferred,
125 0);
126 CHECK_ERR("error during programming!");
127 // Expected response 0x06 <- (ACK)
128 err = libusb_bulk_transfer(device,
129 BULK_EP_IN,
130 buf,
131 sizeof(buf),
132 &received,
133 0);
134 CHECK_ERR("error during programming!");
135 if (buf[0] != 0x06)
136 err = -1;
137 CHECK_ERR("error during programming!");
138 }
139
140 // Send 1024 and then last 6
141
142 // Stop Programming Operation
143 struct prog_end_t e = {};
144 err = libusb_bulk_transfer(device,
145 BULK_EP_OUT,
146 (uint8_t *)&e,
147 sizeof(e),
148 &transferred,
149 0);
150 CHECK_ERR("error during programming stop!");
151 // Expected response 0x06 <- (ACK)
152 err = libusb_bulk_transfer(device,
153 BULK_EP_IN,
154 buf,
155 sizeof(buf),
156 &received,
157 0);
158 CHECK_ERR("error during programming stop!");
159 if (buf[0] != 0x06)
160 err = -1;
161 CHECK_ERR("error during programming stop!");
162
163 // User MAT Sum Check 0x4B ->
164 cmd = static_cast<uint8_t>(H8SXCmd::USER_MAT_CHECKSUM);
165 err = libusb_bulk_transfer(device,
166 BULK_EP_OUT,
167 &cmd,
168 1,
169 &transferred,
170 0);
171 CHECK_ERR("error during user MAT sum check!");
172 err = libusb_bulk_transfer(device,
173 BULK_EP_IN,
174 buf,
175 sizeof(buf),
176 &received,
177 0);
178 CHECK_ERR("error during user MAT sum check!");
179 struct sum_chk_t *chk = (struct sum_chk_t *)buf;
180 if (chk->cmd != 0x5B &&
181 chk->size != 4 &&
182 chk->sum != Checksum((uint8_t *)chk, sizeof(struct sum_chk_t) - 1) &&
183 bswap32(chk->chk) != bin_sum)
184 err = -1;
185 CHECK_ERR("error during user MAT sum check!");
186}
187
188auto H8SX::InitDownload() const -> void
189{
190 int err = 0;
191 int transferred = 0, received = 0;
192 uint8_t buf[BUF_SIZE];
193 uint8_t sum = 0;
194
195 // Select device to flash
196 struct dev_sel_t sel = {0};
197 sel.cmd = static_cast<uint8_t>(H8SXCmd::DEVICE_SELECT);
198 sel.size = 4;
199 for (int i = 0; i < 4; i++)
200 sel.code[i] = dir->code[i];
201 sel.sum = Checksum((uint8_t *)&sel, sizeof(sel) - 1);
202 err = libusb_bulk_transfer(device,
203 BULK_EP_OUT,
204 (uint8_t *)&sel,
205 sizeof(sel),
206 &transferred,
207 0);
208 CHECK_ERR("error in device selection!");
209 // Expected response 0x06 <- (ACK)
210 err = libusb_bulk_transfer(device,
211 BULK_EP_IN,
212 buf,
213 sizeof(buf),
214 &received,
215 0);
216 CHECK_ERR("error in device selection!");
217 if (buf[0] != 0x06)
218 err = -1;
219 CHECK_ERR("error in device selection!");
220
221 // 0x21 -> Clock Mode Inquiry
222 uint8_t cmd = static_cast<uint8_t>(H8SXCmd::CLOCK_MODE_INQUIRY);
223 err = libusb_bulk_transfer(device,
224 BULK_EP_OUT,
225 &cmd,
226 1,
227 &transferred,
228 0);
229 CHECK_ERR("error during clock mode inquiry!");
230 err = libusb_bulk_transfer(device,
231 BULK_EP_IN,
232 (uint8_t *)&buf,
233 sizeof(buf),
234 &received,
235 0);
236 CHECK_ERR("error during clock mode inquiry!");
237 // Checksum
238 err = libusb_bulk_transfer(device,
239 BULK_EP_IN,
240 &sum,
241 1,
242 &received,
243 0);
244
245 // 0x11 -> Clock Mode Selection
246 uint8_t csel[] = {0x11, 0x01, 0x01, 0xed};
247 err = libusb_bulk_transfer(device,
248 BULK_EP_OUT,
249 (uint8_t *)&csel,
250 sizeof(csel),
251 &transferred,
252 0);
253 CHECK_ERR("error during clock mode selection!");
254 // Expected response 0x06 <- (ACK)
255 err = libusb_bulk_transfer(device,
256 BULK_EP_IN,
257 buf,
258 sizeof(buf),
259 &received,
260 0);
261 CHECK_ERR("error in clock mode selection!");
262 if (buf[0] != 0x06)
263 err = -1;
264 CHECK_ERR("error in clock mode selection!");
265
266 // 0x27 -> Programming Unit Inquiry
267 cmd = static_cast<uint8_t>(H8SXCmd::PROG_UNIT_INQUIRY);
268 err = libusb_bulk_transfer(device,
269 BULK_EP_OUT,
270 &cmd,
271 1,
272 &transferred,
273 0);
274 CHECK_ERR("error during programming mode inquiry!");
275 err = libusb_bulk_transfer(device,
276 BULK_EP_IN,
277 (uint8_t *)&buf,
278 sizeof(buf),
279 &received,
280 0);
281 CHECK_ERR("error during programming mode inquiry!");
282 // Checksum
283 err = libusb_bulk_transfer(device,
284 BULK_EP_IN,
285 &sum,
286 1,
287 &received,
288 0);
289
290 // 0x3F -> New Bit-Rate Selection
291 uint8_t bsel[] = {0x3f, 0x07, 0x04, 0x80, 0x06, 0x40,
292 0x02, 0x01, 0x01, 0xec};
293 err = libusb_bulk_transfer(device,
294 BULK_EP_OUT,
295 (uint8_t *)&bsel,
296 sizeof(bsel),
297 &transferred,
298 0);
299 CHECK_ERR("error during bit rate selection!");
300 // Expected response 0x06 <- (ACK)
301 err = libusb_bulk_transfer(device,
302 BULK_EP_IN,
303 buf,
304 sizeof(buf),
305 &received,
306 0);
307 CHECK_ERR("error during bit rate selection!");
308 if (buf[0] != 0x06)
309 err = -1;
310 CHECK_ERR("error during bit rate selection!");
311 // Bit rate confirmation 0x06 ->
312 cmd = 0x06;
313 err = libusb_bulk_transfer(device,
314 BULK_EP_OUT,
315 &cmd,
316 1,
317 &transferred,
318 0);
319 CHECK_ERR("error during bit rate confirmation!");
320 // Expected response 0x06 <- (ACK)
321 err = libusb_bulk_transfer(device,
322 BULK_EP_IN,
323 buf,
324 sizeof(buf),
325 &received,
326 0);
327 CHECK_ERR("error during bit rate confirmation!");
328 if (buf[0] != 0x06)
329 err = -1;
330 CHECK_ERR("error during bit rate confirmation!");
331
332 // Transition to Programming/Erasing State 0x40 ->
333 cmd = static_cast<uint8_t>(H8SXCmd::BEGIN_PROGRAMMING);
334 err = libusb_bulk_transfer(device,
335 BULK_EP_OUT,
336 &cmd,
337 1,
338 &transferred,
339 0);
340 CHECK_ERR("error during transition to programming state!");
341 // Expected response 0x06 <- (ACK)
342 err = libusb_bulk_transfer(device,
343 BULK_EP_IN,
344 buf,
345 sizeof(buf),
346 &received,
347 0);
348 CHECK_ERR("error during transition to programming state!");
349 if (buf[0] != 0x06)
350 err = -1;
351 CHECK_ERR("error during transition to programming state!");
352
353 // User MAT Programming Selection 0x43 ->
354 cmd = static_cast<uint8_t>(H8SXCmd::USER_MAT_SELECT);
355 err = libusb_bulk_transfer(device,
356 BULK_EP_OUT,
357 &cmd,
358 1,
359 &transferred,
360 0);
361 CHECK_ERR("error during user MAT programming selection!");
362 // Expected response 0x06 <- (ACK)
363 err = libusb_bulk_transfer(device,
364 BULK_EP_IN,
365 buf,
366 sizeof(buf),
367 &received,
368 0);
369 CHECK_ERR("error during user MAT programming selection!");
370 if (buf[0] != 0x06)
371 err = -1;
372 CHECK_ERR("error during user MAT programming selection!");
373}
374
375auto H8SX::Init() const -> void
376{
377 int err = 0;
378
379 // Reset device
380 err = libusb_reset_device(device);
381 CHECK_ERR("cannot reset device!");
382
383 // Unset auto kernel detach
384 err = libusb_set_auto_detach_kernel_driver(device, 0);
385 CHECK_ERR("cannot unset auto-detach!");
386
387 // Detach kernel interface
388 if (libusb_kernel_driver_active(device, 0))
389 {
390 err = libusb_detach_kernel_driver(device, 0);
391 CHECK_ERR("cannot detach kernel!");
392 }
393
394 // Set configuration
395 err = libusb_set_configuration(device, 1);
396 CHECK_ERR("cannot set configuration!");
397
398 // Claim device
399 err = libusb_claim_interface(device, 0);
400 CHECK_ERR("cannot claim interface!");
401}
402
403auto H8SX::CheckDevice() const -> void
404{
405 if (this->device == nullptr)
406 throw std::runtime_error("Device is not opened");
407}
408
409auto H8SX::Checksum(const uint8_t *data, size_t len) const -> uint8_t
410{
411 uint8_t sum = 0;
412 for (size_t i = 0; i < len; i++)
413 {
414 sum += data[i];
415 }
416 sum = ~sum;
417 sum++;
418 return sum;
419}
auto InitDownload() const -> void
Definition: h8sx.cpp:188