]>
Commit | Line | Data |
---|---|---|
a8e913c4 JL |
1 | /* |
2 | * This file is part of the libsigrok project. | |
3 | * | |
4 | * Copyright (C) 2017 Jan Luebbe <jluebbe@lasnet.de> | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 3 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include <config.h> | |
ca7d19b5 | 21 | #include <string.h> |
a8e913c4 JL |
22 | #include "protocol.h" |
23 | ||
ca7d19b5 JL |
24 | #define COMMAND_START_CAPTURE 0x01 |
25 | #define COMMAND_STOP_CAPTURE 0x02 | |
26 | #define COMMAND_READ_EEPROM 0x07 | |
27 | #define COMMAND_WRITE_REG 0x80 | |
28 | #define COMMAND_READ_REG 0x81 | |
29 | #define COMMAND_WRITE_I2C 0x87 | |
30 | #define COMMAND_READ_I2C 0x88 | |
31 | #define COMMAND_WAKE_I2C 0x89 | |
32 | #define COMMAND_READ_FW_VER 0x8b | |
33 | ||
34 | #define REG_LED_RED 0x0f | |
35 | #define REG_LED_GREEN 0x10 | |
36 | #define REG_LED_BLUE 0x11 | |
37 | ||
38 | static void iterate_lfsr(const struct sr_dev_inst *sdi) | |
39 | { | |
40 | struct dev_context *devc = sdi->priv; | |
41 | uint32_t lfsr = devc->lfsr; | |
42 | int i, max; | |
43 | ||
44 | max = (lfsr & 0x1f) + 34; | |
45 | for (i = 0; i <= max; i++) { | |
46 | lfsr = (lfsr >> 1) | \ | |
47 | ((lfsr ^ \ | |
48 | (lfsr >> 1) ^ \ | |
49 | (lfsr >> 21) ^ \ | |
50 | (lfsr >> 31) \ | |
51 | ) << 31); | |
52 | } | |
53 | sr_dbg("Iterate 0x%08x -> 0x%08x", devc->lfsr, lfsr); | |
54 | devc->lfsr = lfsr; | |
55 | } | |
56 | ||
57 | static void encrypt(const struct sr_dev_inst *sdi, const uint8_t *in, uint8_t *out, uint8_t len) | |
58 | { | |
59 | struct dev_context *devc = sdi->priv; | |
60 | uint32_t lfsr = devc->lfsr; | |
61 | uint8_t value, mask; | |
62 | int i; | |
63 | ||
64 | for (i = 0; i < len; i++) { | |
65 | value = in[i]; | |
66 | mask = lfsr >> (i%4*8); | |
67 | if (i == 0) | |
68 | value = (value & 0x28) | ((value ^ mask) & ~0x28); | |
69 | else | |
70 | value = value ^ mask; | |
71 | out[i] = value; | |
72 | } | |
73 | iterate_lfsr(sdi); | |
74 | } | |
75 | ||
76 | static void decrypt(const struct sr_dev_inst *sdi, uint8_t *data, uint8_t len) | |
77 | { | |
78 | struct dev_context *devc = sdi->priv; | |
79 | uint32_t lfsr = devc->lfsr; | |
80 | int i; | |
81 | ||
82 | for (i = 0; i < len; i++) { | |
83 | data[i] ^= (lfsr >> (i%4*8)); | |
84 | } | |
85 | iterate_lfsr(sdi); | |
86 | } | |
87 | ||
88 | static int transact(const struct sr_dev_inst *sdi, | |
89 | const uint8_t *req, uint8_t req_len, | |
90 | uint8_t *rsp, uint8_t rsp_len) | |
91 | { | |
92 | struct sr_usb_dev_inst *usb = sdi->conn; | |
93 | uint8_t *req_enc; | |
94 | uint8_t rsp_dummy[1] = {}; | |
95 | int ret, xfer; | |
96 | ||
97 | if (req_len < 2 || req_len > 64 || rsp_len > 128 || | |
98 | !req || (rsp_len > 0 && !rsp)) | |
99 | return SR_ERR_ARG; | |
100 | ||
101 | req_enc = g_malloc(req_len); | |
102 | encrypt(sdi, req, req_enc, req_len); | |
103 | ||
104 | ret = libusb_bulk_transfer(usb->devhdl, 1, req_enc, req_len, &xfer, 1000); | |
105 | if (ret != 0) { | |
106 | sr_dbg("Failed to send request 0x%02x: %s.", | |
107 | req[1], libusb_error_name(ret)); | |
108 | return SR_ERR; | |
109 | } | |
110 | if (xfer != req_len) { | |
111 | sr_dbg("Failed to send request 0x%02x: incorrect length " | |
112 | "%d != %d.", req[1], xfer, req_len); | |
113 | return SR_ERR; | |
114 | } | |
115 | ||
116 | if (req[0] == 0x20) { // reseed | |
117 | return SR_OK; | |
118 | } else if (rsp_len == 0) { | |
119 | rsp = rsp_dummy; | |
120 | rsp_len = sizeof(rsp_dummy); | |
121 | } | |
122 | ||
123 | ret = libusb_bulk_transfer(usb->devhdl, 0x80 | 1, rsp, rsp_len, | |
124 | &xfer, 1000); | |
125 | if (ret != 0) { | |
126 | sr_dbg("Failed to receive response to request 0x%02x: %s.", | |
127 | req[1], libusb_error_name(ret)); | |
128 | return SR_ERR; | |
129 | } | |
130 | if (xfer != rsp_len) { | |
131 | sr_dbg("Failed to receive response to request 0x%02x: " | |
132 | "incorrect length %d != %d.", req[1], xfer, rsp_len); | |
133 | return SR_ERR; | |
134 | } | |
135 | ||
136 | decrypt(sdi, rsp, rsp_len); | |
137 | ||
138 | return SR_OK; | |
139 | } | |
140 | ||
141 | static int reseed(const struct sr_dev_inst *sdi) | |
142 | { | |
143 | struct dev_context *devc = sdi->priv; | |
144 | uint8_t req[] = {0x20, 0x24, 0x4b, 0x35, 0x8e}; | |
145 | ||
146 | devc->lfsr = 0; | |
147 | return transact(sdi, req, sizeof(req), NULL, 0); | |
148 | } | |
149 | ||
150 | static int write_regs(const struct sr_dev_inst *sdi, uint8_t (*regs)[2], uint8_t cnt) | |
151 | { | |
152 | uint8_t req[64]; | |
153 | int i; | |
154 | ||
155 | if (cnt < 1 || cnt > 30) | |
156 | return SR_ERR_ARG; | |
157 | ||
158 | req[0] = 0x00; | |
159 | req[1] = COMMAND_WRITE_REG; | |
160 | req[2] = cnt; | |
161 | ||
162 | for (i = 0; i < cnt; i++) { | |
163 | req[3 + 2 * i] = regs[i][0]; | |
164 | req[4 + 2 * i] = regs[i][1]; | |
165 | } | |
166 | ||
167 | return transact(sdi, req, 3 + 2*cnt, NULL, 0); | |
168 | } | |
169 | ||
170 | static int write_reg(const struct sr_dev_inst *sdi, | |
171 | uint8_t address, uint8_t value) | |
172 | { | |
173 | uint8_t regs[2] = {address, value}; | |
174 | ||
175 | return write_regs(sdi, ®s, 1); | |
176 | } | |
177 | ||
178 | static int get_firmware_version(const struct sr_dev_inst *sdi) | |
a8e913c4 | 179 | { |
ca7d19b5 JL |
180 | uint8_t req[2] = {0x00, COMMAND_READ_FW_VER}; |
181 | uint8_t rsp[128] = {}; | |
182 | int ret; | |
183 | ||
184 | ret = transact(sdi, req, sizeof(req), rsp, sizeof(rsp)); | |
185 | if (ret == SR_OK) { | |
186 | rsp[63] = 0; | |
187 | sr_dbg("fw-version: %s", rsp); | |
188 | } | |
189 | ||
190 | return ret; | |
191 | } | |
a8e913c4 | 192 | |
ca7d19b5 JL |
193 | static int read_i2c(const struct sr_dev_inst *sdi, uint8_t *data, uint8_t len) |
194 | { | |
195 | uint8_t req[5]; | |
196 | uint8_t rsp[1+128]; | |
197 | int ret; | |
a8e913c4 | 198 | |
ca7d19b5 JL |
199 | if (len < 1 || len > 128 || !data) |
200 | return SR_ERR_ARG; | |
a8e913c4 | 201 | |
ca7d19b5 JL |
202 | req[0] = 0x00; |
203 | req[1] = COMMAND_READ_I2C; | |
204 | req[2] = 0xc0; // fixed address | |
205 | req[3] = len; | |
206 | req[4] = 0; // len msb? | |
a8e913c4 | 207 | |
ca7d19b5 JL |
208 | ret = transact(sdi, req, sizeof(req), rsp, 1 + len); |
209 | if (ret != SR_OK) { | |
210 | return ret; | |
211 | } | |
212 | if (rsp[0] != 0x02) { | |
213 | sr_dbg("Failed to do I2C read (0x%02x).", rsp[0]); | |
214 | return SR_ERR; | |
a8e913c4 JL |
215 | } |
216 | ||
ca7d19b5 JL |
217 | memcpy(data, rsp+1, len); |
218 | return SR_OK; | |
219 | } | |
220 | ||
221 | static int write_i2c(const struct sr_dev_inst *sdi, const uint8_t *data, uint8_t len) | |
222 | { | |
223 | uint8_t req[5 + 128]; | |
224 | uint8_t rsp[1]; | |
225 | int ret; | |
226 | ||
227 | if (len < 1 || len > 128 || !data) | |
228 | return SR_ERR_ARG; | |
229 | ||
230 | req[0] = 0x00; | |
231 | req[1] = COMMAND_WRITE_I2C; | |
232 | req[2] = 0xc0; // fixed address | |
233 | req[3] = len; | |
234 | req[4] = 0; // len msb? | |
235 | memcpy(req + 5, data, len); | |
236 | ||
237 | ret = transact(sdi, req, 5 + len, rsp, sizeof(rsp)); | |
238 | if (ret != SR_OK) { | |
239 | return ret; | |
240 | } | |
241 | if (rsp[0] != 0x02) { | |
242 | sr_dbg("Failed to do I2C write (0x%02x).", rsp[0]); | |
243 | return SR_ERR; | |
244 | } | |
245 | ||
246 | return SR_OK; | |
247 | } | |
248 | ||
249 | static int wake_i2c(const struct sr_dev_inst *sdi) | |
250 | { | |
251 | uint8_t req[] = {0x00, COMMAND_WAKE_I2C}; | |
252 | uint8_t rsp[1] = {}; | |
253 | uint8_t i2c_rsp[1+1+2] = {}; | |
254 | int ret; | |
255 | ||
256 | ret = transact(sdi, req, sizeof(req), rsp, sizeof(rsp)); | |
257 | if (ret != SR_OK) { | |
258 | return ret; | |
259 | } | |
260 | if (rsp[0] != 0x00) { | |
261 | sr_dbg("Failed to do I2C wake trigger (0x%02x).", rsp[0]); | |
262 | return SR_ERR; | |
263 | } | |
264 | ||
265 | ret = read_i2c(sdi, i2c_rsp, sizeof(i2c_rsp)); | |
266 | if (ret != SR_OK) { | |
267 | return ret; | |
268 | } | |
269 | if (i2c_rsp[1] != 0x11) { | |
270 | sr_dbg("Failed to do I2C wake read (0x%02x).", i2c_rsp[0]); | |
271 | return SR_ERR; | |
272 | } | |
273 | ||
274 | return SR_OK; | |
275 | } | |
276 | ||
277 | static int crypto_random(const struct sr_dev_inst *sdi, uint8_t *data) | |
278 | { | |
279 | uint8_t i2c_req[8] = {0x03, 0x07, 0x1b, 0x00, 0x00, 0x00, 0x24, 0xcd}; | |
280 | uint8_t i2c_rsp[1+32+2] = {}; | |
281 | int ret; | |
282 | ||
283 | ret = write_i2c(sdi, i2c_req, sizeof(i2c_req)); | |
284 | if (ret != SR_OK) { | |
285 | return ret; | |
286 | } | |
287 | ||
288 | g_usleep(100000); // TODO: poll instead | |
289 | ||
290 | ret = read_i2c(sdi, i2c_rsp, sizeof(i2c_rsp)); | |
291 | if (ret != SR_OK) { | |
292 | return ret; | |
293 | } | |
294 | ||
295 | if (data) { | |
296 | memcpy(data, i2c_rsp+1, 32); | |
297 | } | |
298 | ||
299 | return SR_OK; | |
300 | } | |
301 | ||
302 | static int crypto_nonce(const struct sr_dev_inst *sdi, uint8_t *data) | |
303 | { | |
304 | uint8_t i2c_req[6+20+2] = {0x03, 0x1b, 0x16, 0x00, 0x00, 0x00}; | |
305 | uint8_t i2c_rsp[1+32+2] = {}; | |
306 | int ret; | |
307 | ||
308 | // CRC | |
309 | i2c_req[26] = 0x7d; | |
310 | i2c_req[27] = 0xe0; | |
311 | ||
312 | ret = write_i2c(sdi, i2c_req, sizeof(i2c_req)); | |
313 | if (ret != SR_OK) { | |
314 | return ret; | |
315 | } | |
316 | ||
317 | g_usleep(100000); // TODO: poll instead | |
318 | ||
319 | ret = read_i2c(sdi, i2c_rsp, sizeof(i2c_rsp)); | |
320 | if (ret != SR_OK) { | |
321 | return ret; | |
322 | } | |
323 | ||
324 | if (data) { | |
325 | memcpy(data, i2c_rsp+1, 32); | |
326 | } | |
327 | ||
328 | return SR_OK; | |
329 | } | |
330 | ||
331 | static int crypto_sign(const struct sr_dev_inst *sdi, uint8_t *data, uint8_t *crc) | |
332 | { | |
333 | uint8_t i2c_req[8] = {0x03, 0x07, 0x41, 0x80, 0x00, 0x00, 0x28, 0x05}; | |
334 | uint8_t i2c_rsp[1+64+2] = {}; | |
335 | int ret; | |
336 | ||
337 | ret = write_i2c(sdi, i2c_req, sizeof(i2c_req)); | |
338 | if (ret != SR_OK) { | |
339 | return ret; | |
340 | } | |
341 | ||
342 | g_usleep(100000); // TODO: poll instead | |
343 | ||
344 | ret = read_i2c(sdi, i2c_rsp, sizeof(i2c_rsp)); | |
345 | if (ret != SR_OK) { | |
346 | return ret; | |
347 | } | |
348 | ||
349 | memcpy(data, i2c_rsp+1, 64); | |
350 | memcpy(crc, i2c_rsp+1+64, 2); | |
351 | ||
352 | return SR_OK; | |
353 | } | |
354 | ||
355 | static int authenticate(const struct sr_dev_inst *sdi) | |
356 | { | |
357 | struct dev_context *devc = sdi->priv; | |
358 | uint8_t random[32] = {}; | |
359 | uint8_t nonce[32] = {}; | |
360 | uint8_t sig[64] = {}; | |
361 | uint8_t sig_crc[64] = {}; | |
362 | uint32_t lfsr; | |
363 | int i, ret; | |
364 | ||
365 | ret = wake_i2c(sdi); | |
366 | if (ret != SR_OK) | |
367 | return ret; | |
368 | ||
369 | ret = crypto_random(sdi, random); | |
370 | if (ret != SR_OK) | |
371 | return ret; | |
372 | sr_dbg("random: 0x%02x 0x%02x 0x%02x 0x%02x", random[0], random[1], random[2], random[3]); | |
373 | ||
374 | ret = crypto_nonce(sdi, nonce); | |
375 | if (ret != SR_OK) | |
376 | return ret; | |
377 | sr_dbg("nonce: 0x%02x 0x%02x 0x%02x 0x%02x", nonce[0], nonce[1], nonce[2], nonce[3]); | |
378 | ||
379 | ret = crypto_nonce(sdi, nonce); | |
380 | if (ret != SR_OK) | |
381 | return ret; | |
382 | sr_dbg("nonce: 0x%02x 0x%02x 0x%02x 0x%02x", nonce[0], nonce[1], nonce[2], nonce[3]); | |
383 | ||
384 | ret = crypto_sign(sdi, sig, sig_crc); | |
385 | if (ret != SR_OK) | |
386 | return ret; | |
387 | sr_dbg("sig: 0x%02x 0x%02x 0x%02x 0x%02x", sig[0], sig[1], sig[2], sig[3]); | |
388 | sr_dbg("sig crc: 0x%02x 0x%02x", sig_crc[0], sig_crc[1]); | |
389 | ||
390 | lfsr = 0; | |
391 | for (i = 0; i < 28; i++) | |
392 | lfsr ^= nonce[i] << (8*(i%4)); | |
393 | lfsr ^= sig_crc[0] | sig_crc[1] << 8; | |
394 | ||
395 | sr_dbg("Authenticate 0x%08x -> 0x%08x", devc->lfsr, lfsr); | |
396 | devc->lfsr = lfsr; | |
397 | ||
398 | return SR_OK; | |
399 | } | |
400 | ||
401 | static int set_led(const struct sr_dev_inst *sdi, uint8_t r, uint8_t g, uint8_t b) | |
402 | { | |
403 | uint8_t regs[][2] = { | |
404 | {REG_LED_RED, r}, | |
405 | {REG_LED_GREEN, g}, | |
406 | {REG_LED_BLUE, b}, | |
407 | }; | |
408 | ||
409 | authenticate(sdi); | |
410 | ||
411 | return write_regs(sdi, regs, G_N_ELEMENTS(regs)); | |
412 | } | |
413 | ||
414 | static int configure_channels(const struct sr_dev_inst *sdi) | |
415 | { | |
416 | struct dev_context *devc = sdi->priv; | |
417 | const struct sr_channel *c; | |
418 | const GSList *l; | |
419 | uint16_t mask; | |
420 | ||
421 | devc->dig_channel_cnt = 0; | |
422 | devc->dig_channel_mask = 0; | |
423 | for (l = sdi->channels; l; l = l->next) { | |
424 | c = l->data; | |
425 | if (!c->enabled) | |
426 | continue; | |
427 | ||
428 | mask = 1 << c->index; | |
429 | devc->dig_channel_masks[devc->dig_channel_cnt++] = mask; | |
430 | devc->dig_channel_mask |= mask; | |
431 | ||
432 | } | |
433 | sr_dbg("%d channels enabled (0x%04x)", | |
434 | devc->dig_channel_cnt, | |
435 | devc->dig_channel_mask); | |
436 | ||
437 | return SR_OK; | |
438 | } | |
439 | ||
b6189f7c | 440 | SR_PRIV int saleae_logic_pro_init(const struct sr_dev_inst *sdi) |
ca7d19b5 JL |
441 | { |
442 | reseed(sdi); | |
443 | get_firmware_version(sdi); | |
444 | /* setting the LED doesn't work yet */ | |
445 | /* set_led(sdi, 0x00, 0x00, 0xff); */ | |
446 | ||
447 | return SR_OK; | |
448 | } | |
449 | ||
b6189f7c | 450 | SR_PRIV int saleae_logic_pro_prepare(const struct sr_dev_inst *sdi) |
ca7d19b5 JL |
451 | { |
452 | struct dev_context *devc = sdi->priv; | |
453 | uint8_t regs_unknown[][2] = { | |
454 | {0x03, 0x0f}, | |
455 | {0x04, 0x00}, | |
456 | {0x05, 0x00}, | |
457 | }; | |
458 | uint8_t regs_config[][2] = { | |
459 | {0x00, 0x00}, | |
460 | {0x08, 0x00}, /* analog channel mask (LSB) */ | |
461 | {0x09, 0x00}, /* analog channel mask (MSB) */ | |
462 | {0x06, 0x01}, /* digital channel mask (LSB) */ | |
463 | {0x07, 0x00}, /* digital channel mask (MSB) */ | |
464 | {0x0a, 0x00}, /* analog sample rate? */ | |
465 | {0x0b, 0x64}, /* digital sample rate? */ | |
466 | {0x0c, 0x00}, | |
467 | {0x0d, 0x00}, /* analog mux rate? */ | |
468 | {0x0e, 0x01}, /* digital mux rate? */ | |
469 | {0x12, 0x04}, | |
470 | {0x13, 0x00}, | |
471 | {0x14, 0xff}, /* pre-divider? */ | |
472 | }; | |
473 | uint8_t start_req[] = {0x00, 0x01}; | |
474 | uint8_t start_rsp[2] = {}; | |
475 | ||
476 | configure_channels(sdi); | |
477 | ||
478 | /* digital channel mask and muxing */ | |
479 | regs_config[3][1] = devc->dig_channel_mask; | |
480 | regs_config[4][1] = devc->dig_channel_mask >> 8; | |
481 | regs_config[9][1] = devc->dig_channel_cnt; | |
482 | ||
483 | /* samplerate */ | |
484 | switch (devc->dig_samplerate) { | |
485 | case SR_MHZ(1): | |
486 | regs_config[6][1] = 0x64; | |
487 | break; | |
488 | case SR_MHZ(2): | |
489 | regs_config[6][1] = 0x32; | |
490 | break; | |
491 | case SR_KHZ(2500): | |
492 | regs_config[6][1] = 0x28; | |
493 | break; | |
494 | case SR_MHZ(10): | |
495 | regs_config[6][1] = 0x0a; | |
496 | break; | |
497 | case SR_MHZ(25): | |
498 | regs_config[6][1] = 0x04; | |
499 | regs_config[12][1] = 0x80; | |
500 | break; | |
501 | case SR_MHZ(50): | |
502 | regs_config[6][1] = 0x02; | |
503 | regs_config[12][1] = 0x40; | |
504 | break; | |
505 | default: | |
506 | return SR_ERR_ARG; | |
507 | } | |
508 | ||
509 | authenticate(sdi); | |
510 | ||
511 | write_reg(sdi, 0x15, 0x03); | |
512 | write_regs(sdi, regs_unknown, G_N_ELEMENTS(regs_unknown)); | |
513 | write_regs(sdi, regs_config, G_N_ELEMENTS(regs_config)); | |
514 | ||
515 | transact(sdi, start_req, sizeof(start_req), start_rsp, sizeof(start_rsp)); | |
516 | ||
517 | return SR_OK; | |
518 | } | |
519 | ||
b6189f7c | 520 | SR_PRIV int saleae_logic_pro_start(const struct sr_dev_inst *sdi) |
ca7d19b5 JL |
521 | { |
522 | struct dev_context *devc = sdi->priv; | |
523 | ||
524 | devc->conv_size = 0; | |
525 | devc->batch_index = 0; | |
526 | ||
527 | write_reg(sdi, 0x00, 0x01); | |
528 | ||
529 | return SR_OK; | |
530 | } | |
531 | ||
b6189f7c | 532 | SR_PRIV int saleae_logic_pro_stop(const struct sr_dev_inst *sdi) |
ca7d19b5 JL |
533 | { |
534 | uint8_t stop_req[] = {0x00, 0x02}; | |
535 | uint8_t stop_rsp[2] = {}; | |
536 | ||
537 | write_reg(sdi, 0x00, 0x00); | |
538 | transact(sdi, stop_req, sizeof(stop_req), stop_rsp, sizeof(stop_rsp)); | |
539 | ||
540 | return SR_OK; | |
541 | } | |
542 | ||
b6189f7c | 543 | static void saleae_logic_pro_send_data(const struct sr_dev_inst *sdi, |
ca7d19b5 JL |
544 | void *data, size_t length, size_t unitsize) |
545 | { | |
546 | const struct sr_datafeed_logic logic = { | |
547 | .length = length, | |
548 | .unitsize = unitsize, | |
549 | .data = data | |
550 | }; | |
551 | ||
552 | const struct sr_datafeed_packet packet = { | |
553 | .type = SR_DF_LOGIC, | |
554 | .payload = &logic | |
555 | }; | |
556 | ||
557 | sr_session_send(sdi, &packet); | |
558 | } | |
559 | ||
560 | /* | |
561 | * One batch from the device consists of 32 samples per active digital channel. | |
562 | * This stream of batches is packed into USB packets with 16384 bytes each. | |
563 | */ | |
b6189f7c | 564 | static void saleae_logic_pro_convert_data(const struct sr_dev_inst *sdi, |
ca7d19b5 JL |
565 | const uint32_t *src, size_t srccnt) |
566 | { | |
567 | struct dev_context *devc = sdi->priv; | |
568 | uint8_t *dst = devc->conv_buffer; | |
569 | uint32_t samples; | |
570 | uint16_t channel_mask; | |
571 | unsigned int sample_index, batch_index; | |
572 | uint16_t *dst_batch; | |
573 | ||
574 | /* copy partial batch to the beginning */ | |
575 | memcpy(dst, dst+devc->conv_size, CONV_BATCH_SIZE); | |
576 | /* reset converted size */ | |
577 | devc->conv_size = 0; | |
578 | ||
579 | batch_index = devc->batch_index; | |
580 | while (srccnt--) { | |
581 | samples = *src++; | |
582 | dst_batch = (uint16_t*)dst; | |
583 | ||
584 | /* first index of the batch */ | |
585 | if (batch_index == 0) | |
586 | memset(dst, 0, CONV_BATCH_SIZE); | |
587 | ||
588 | /* convert one channel */ | |
589 | channel_mask = devc->dig_channel_masks[batch_index]; | |
590 | for (sample_index = 0; sample_index <= 31; sample_index++) | |
591 | if ((samples >> (31-sample_index)) & 1) | |
592 | dst_batch[sample_index] |= channel_mask; | |
593 | ||
594 | /* last index of the batch */ | |
595 | if (++batch_index == devc->dig_channel_cnt) { | |
596 | devc->conv_size += CONV_BATCH_SIZE; | |
597 | batch_index = 0; | |
598 | dst += CONV_BATCH_SIZE; | |
599 | } | |
600 | } | |
601 | devc->batch_index = batch_index; | |
602 | } | |
603 | ||
b6189f7c | 604 | SR_PRIV void LIBUSB_CALL saleae_logic_pro_receive_data(struct libusb_transfer *transfer) |
ca7d19b5 JL |
605 | { |
606 | const struct sr_dev_inst *sdi = transfer->user_data; | |
607 | struct dev_context *devc = sdi->priv; | |
608 | int ret; | |
609 | ||
610 | switch (transfer->status) { | |
611 | case LIBUSB_TRANSFER_NO_DEVICE: | |
612 | sr_dbg("FIXME no device"); | |
613 | return; | |
614 | case LIBUSB_TRANSFER_COMPLETED: | |
615 | case LIBUSB_TRANSFER_TIMED_OUT: /* We may have received some data though. */ | |
616 | break; | |
617 | default: | |
618 | // FIXME | |
619 | return; | |
620 | } | |
621 | ||
b6189f7c UH |
622 | saleae_logic_pro_convert_data(sdi, (uint32_t*)transfer->buffer, 16*1024/4); |
623 | saleae_logic_pro_send_data(sdi, devc->conv_buffer, devc->conv_size, 2); | |
ca7d19b5 JL |
624 | |
625 | if ((ret = libusb_submit_transfer(transfer)) != LIBUSB_SUCCESS) | |
626 | sr_dbg("FIXME resubmit failed"); | |
a8e913c4 | 627 | } |