]> sigrok.org Git - libsigrok.git/blame - hardware/fx2lafw/fx2lafw.c
fx2lafw: Made fx2lafw profiles const
[libsigrok.git] / hardware / fx2lafw / fx2lafw.c
CommitLineData
f302a082
JH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
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 <stdio.h>
21#include <stdlib.h>
8b35f474 22#include <inttypes.h>
187b3582
JH
23#include <glib.h>
24#include <libusb.h>
f302a082
JH
25#include "config.h"
26#include "sigrok.h"
27#include "sigrok-internal.h"
28#include "fx2lafw.h"
f6582cd7 29#include "command.h"
f302a082 30
4679d14d 31static const struct fx2lafw_profile supported_fx2[] = {
17b6c75a
JH
32 /* CWAV USBee AX
33 * EE Electronics ESLA201A
34 */
187b3582
JH
35 { 0x08a9, 0x0014, "CWAV", "USBee AX", NULL, 8 },
36 { 0, 0, 0, 0, 0, 0 }
37};
38
8b35f474
JH
39static int fx2lafw_capabilities[] = {
40 SR_HWCAP_LOGIC_ANALYZER,
41 SR_HWCAP_SAMPLERATE,
42
43 /* These are really implemented in the driver, not the hardware. */
44 SR_HWCAP_LIMIT_SAMPLES,
45 SR_HWCAP_CONTINUOUS,
772a0e61 46 0,
8b35f474
JH
47};
48
49static const char *fx2lafw_probe_names[] = {
50 "D0",
51 "D1",
52 "D2",
53 "D3",
54 "D4",
55 "D5",
56 "D6",
57 "D7",
772a0e61 58 NULL,
8b35f474
JH
59};
60
61static uint64_t fx2lafw_supported_samplerates[] = {
62 SR_MHZ(1),
63 SR_MHZ(2),
64 SR_MHZ(3),
65 SR_MHZ(4),
66 SR_MHZ(6),
67 SR_MHZ(8),
68 SR_MHZ(12),
69 SR_MHZ(16),
772a0e61 70 SR_MHZ(24),
8b35f474
JH
71};
72
73static struct sr_samplerates fx2lafw_samplerates = {
74 SR_MHZ(1),
75 SR_MHZ(24),
76 SR_HZ(0),
772a0e61 77 fx2lafw_supported_samplerates,
8b35f474
JH
78};
79
cac0bbaa 80static GSList *dev_insts = NULL;
187b3582
JH
81static libusb_context *usb_context = NULL;
82
f92994fd 83static int hw_dev_config_set(int dev_index, int hwcap, void *value);
1f9813eb 84static int hw_dev_acquisition_stop(int dev_index, void *session_dev_id);
610dbb70 85
b1eeb67e
JH
86/**
87 * Check the USB configuration to determine if this is an fx2lafw device.
88 *
f9a69557
UH
89 * @return TRUE if the device's configuration profile match fx2lafw
90 * configuration, FALSE otherwise.
b1eeb67e 91 */
f9a69557 92static gboolean check_conf_profile(libusb_device *dev)
b1eeb67e
JH
93{
94 struct libusb_device_descriptor des;
95 struct libusb_config_descriptor *conf_dsc = NULL;
96 const struct libusb_interface_descriptor *intf_dsc;
f9a69557 97 gboolean ret = FALSE;
b1eeb67e
JH
98
99 while (!ret) {
100 /* Assume it's not a Saleae Logic unless proven wrong. */
101 ret = 0;
102
103 if (libusb_get_device_descriptor(dev, &des) != 0)
104 break;
105
106 if (des.bNumConfigurations != 1)
107 /* Need exactly 1 configuration. */
108 break;
109
110 if (libusb_get_config_descriptor(dev, 0, &conf_dsc) != 0)
111 break;
112
113 if (conf_dsc->bNumInterfaces != 1)
114 /* Need exactly 1 interface. */
115 break;
116
117 if (conf_dsc->interface[0].num_altsetting != 1)
118 /* Need just one alternate setting. */
119 break;
120
121 intf_dsc = &(conf_dsc->interface[0].altsetting[0]);
9031ce63
JH
122 if (intf_dsc->bNumEndpoints != 2)
123 /* Need exactly 2 end points. */
b1eeb67e
JH
124 break;
125
126 if ((intf_dsc->endpoint[0].bEndpointAddress & 0x8f) !=
9031ce63
JH
127 (2 | LIBUSB_ENDPOINT_IN)) // 0x82
128 /* The first endpoint should be 2 (inbound). */
b1eeb67e
JH
129 break;
130
131 /* TODO: Check the debug channel... */
132
133 /* If we made it here, it must be an fx2lafw. */
f9a69557 134 ret = TRUE;
b1eeb67e
JH
135 }
136
137 if (conf_dsc)
138 libusb_free_config_descriptor(conf_dsc);
139
140 return ret;
141}
142
43125c69
JH
143static int fx2lafw_open_dev(int dev_index)
144{
145 libusb_device **devlist;
146 struct libusb_device_descriptor des;
147 struct sr_dev_inst *sdi;
772a0e61 148 struct context *ctx;
43125c69
JH
149 int err, skip, i;
150
151 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
152 return SR_ERR;
153 ctx = sdi->priv;
154
155 if (sdi->status == SR_ST_ACTIVE)
156 /* already in use */
157 return SR_ERR;
158
159 skip = 0;
160 libusb_get_device_list(usb_context, &devlist);
161 for (i = 0; devlist[i]; i++) {
162 if ((err = libusb_get_device_descriptor(devlist[i], &des))) {
163 sr_err("fx2lafw: failed to get device descriptor: %d", err);
164 continue;
165 }
166
74fcfb80
JH
167 if (des.idVendor != ctx->profile->vid
168 || des.idProduct != ctx->profile->pid)
43125c69
JH
169 continue;
170
171 if (sdi->status == SR_ST_INITIALIZING) {
172 if (skip != dev_index) {
173 /* Skip devices of this type that aren't the one we want. */
174 skip += 1;
175 continue;
176 }
177 } else if (sdi->status == SR_ST_INACTIVE) {
178 /*
179 * This device is fully enumerated, so we need to find
180 * this device by vendor, product, bus and address.
181 */
182 if (libusb_get_bus_number(devlist[i]) != ctx->usb->bus
183 || libusb_get_device_address(devlist[i]) != ctx->usb->address)
184 /* this is not the one */
185 continue;
186 }
187
188 if (!(err = libusb_open(devlist[i], &ctx->usb->devhdl))) {
189 if (ctx->usb->address == 0xff)
190 /*
191 * first time we touch this device after firmware upload,
192 * so we don't know the address yet.
193 */
194 ctx->usb->address = libusb_get_device_address(devlist[i]);
195
196 sdi->status = SR_ST_ACTIVE;
197 sr_info("fx2lafw: opened device %d on %d.%d interface %d",
198 sdi->index, ctx->usb->bus,
199 ctx->usb->address, USB_INTERFACE);
200 } else {
201 sr_err("fx2lafw: failed to open device: %d", err);
202 }
203
204 /* if we made it here, we handled the device one way or another */
205 break;
206 }
207 libusb_free_device_list(devlist, 1);
208
209 if (sdi->status != SR_ST_ACTIVE)
210 return SR_ERR;
211
212 return SR_OK;
213}
214
f1898235
JH
215static void close_dev(struct sr_dev_inst *sdi)
216{
772a0e61 217 struct context *ctx;
f1898235
JH
218
219 ctx = sdi->priv;
220
221 if (ctx->usb->devhdl == NULL)
222 return;
223
224 sr_info("fx2lafw: closing device %d on %d.%d interface %d", sdi->index,
225 ctx->usb->bus, ctx->usb->address, USB_INTERFACE);
226 libusb_release_interface(ctx->usb->devhdl, USB_INTERFACE);
227 libusb_close(ctx->usb->devhdl);
228 ctx->usb->devhdl = NULL;
229 sdi->status = SR_ST_INACTIVE;
230}
231
772a0e61 232static struct context *fx2lafw_device_new(void)
187b3582 233{
772a0e61 234 struct context *ctx;
187b3582 235
772a0e61
UH
236 if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
237 sr_err("fx2lafw: %s: ctx malloc failed", __func__);
187b3582
JH
238 return NULL;
239 }
240
772a0e61 241 return ctx;
187b3582 242}
f302a082
JH
243
244/*
245 * API callbacks
246 */
247
248static int hw_init(const char *deviceinfo)
249{
187b3582
JH
250 struct sr_dev_inst *sdi;
251 struct libusb_device_descriptor des;
4679d14d 252 const struct fx2lafw_profile *fx2lafw_prof;
772a0e61 253 struct context *ctx;
187b3582
JH
254 libusb_device **devlist;
255 int err;
256 int devcnt = 0;
257 int i, j;
258
259 /* Avoid compiler warnings. */
f302a082 260 (void)deviceinfo;
187b3582
JH
261
262 if (libusb_init(&usb_context) != 0) {
263 sr_warn("Failed to initialize USB.");
264 return 0;
265 }
266
267 /* Find all fx2lafw compatible devices and upload firware to all of them. */
268 libusb_get_device_list(usb_context, &devlist);
269 for (i = 0; devlist[i]; i++) {
270
271 if ((err = libusb_get_device_descriptor(
272 devlist[i], &des)) != 0) {
273 sr_warn("failed to get device descriptor: %d", err);
274 continue;
275 }
276
277 fx2lafw_prof = NULL;
278 for (j = 0; supported_fx2[j].vid; j++) {
279 if (des.idVendor == supported_fx2[j].vid &&
280 des.idProduct == supported_fx2[j].pid) {
281 fx2lafw_prof = &supported_fx2[j];
282 }
283 }
284
285 /* Skip if the device was not found */
286 if(!fx2lafw_prof)
287 continue;
288
289 sdi = sr_dev_inst_new(devcnt, SR_ST_INITIALIZING,
290 fx2lafw_prof->vendor, fx2lafw_prof->model,
291 fx2lafw_prof->model_version);
292 if(!sdi)
293 return 0;
294
90282c82
JH
295 ctx = fx2lafw_device_new();
296 ctx->profile = fx2lafw_prof;
297 sdi->priv = ctx;
be4b99e8 298 dev_insts = g_slist_append(dev_insts, sdi);
187b3582 299
b1eeb67e
JH
300 if (check_conf_profile(devlist[i])) {
301 /* Already has the firmware, so fix the new address. */
302 sr_dbg("fx2lafw: Found a fx2lafw device.");
303 sdi->status = SR_ST_INACTIVE;
304 ctx->usb = sr_usb_dev_inst_new
305 (libusb_get_bus_number(devlist[i]),
306 libusb_get_device_address(devlist[i]), NULL);
307 } else {
308 if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION, FIRMWARE) == SR_OK)
309 /* Remember when the firmware on this device was updated */
310 g_get_current_time(&ctx->fw_updated);
311 else
312 sr_err("fx2lafw: firmware upload failed for "
313 "device %d", devcnt);
314 ctx->usb = sr_usb_dev_inst_new
315 (libusb_get_bus_number(devlist[i]), 0xff, NULL);
316 }
317
187b3582
JH
318 devcnt++;
319 }
320 libusb_free_device_list(devlist, 1);
321
322 return devcnt;
f302a082
JH
323}
324
772a0e61 325static int hw_dev_open(int dev_index)
f302a082 326{
43125c69
JH
327 GTimeVal cur_time;
328 struct sr_dev_inst *sdi;
772a0e61 329 struct context *ctx;
43125c69
JH
330 int timediff, err;
331
772a0e61 332 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
43125c69
JH
333 return SR_ERR;
334 ctx = sdi->priv;
335
336 /*
337 * if the firmware was recently uploaded, wait up to MAX_RENUM_DELAY ms
338 * for the FX2 to renumerate
339 */
340 err = 0;
341 if (GTV_TO_MSEC(ctx->fw_updated) > 0) {
342 sr_info("fx2lafw: waiting for device to reset");
343 /* takes at least 300ms for the FX2 to be gone from the USB bus */
344 g_usleep(300 * 1000);
345 timediff = 0;
346 while (timediff < MAX_RENUM_DELAY) {
772a0e61 347 if ((err = fx2lafw_open_dev(dev_index)) == SR_OK)
43125c69
JH
348 break;
349 g_usleep(100 * 1000);
350 g_get_current_time(&cur_time);
351 timediff = GTV_TO_MSEC(cur_time) - GTV_TO_MSEC(ctx->fw_updated);
352 }
353 sr_info("fx2lafw: device came back after %d ms", timediff);
354 } else {
772a0e61 355 err = fx2lafw_open_dev(dev_index);
43125c69
JH
356 }
357
358 if (err != SR_OK) {
359 sr_err("fx2lafw: unable to open device");
360 return SR_ERR;
361 }
362 ctx = sdi->priv;
363
364 err = libusb_claim_interface(ctx->usb->devhdl, USB_INTERFACE);
365 if (err != 0) {
366 sr_err("fx2lafw: Unable to claim interface: %d", err);
367 return SR_ERR;
368 }
369
f92994fd
JH
370 if (ctx->cur_samplerate == 0) {
371 /* Samplerate hasn't been set; default to the slowest one. */
372 if (hw_dev_config_set(dev_index, SR_HWCAP_SAMPLERATE,
373 &fx2lafw_supported_samplerates[0]) == SR_ERR)
374 return SR_ERR;
375 }
376
f302a082
JH
377 return SR_OK;
378}
379
f1898235 380static int hw_dev_close(int dev_index)
f302a082 381{
f1898235
JH
382 struct sr_dev_inst *sdi;
383
384 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
385 sr_err("fx2lafw: %s: sdi was NULL", __func__);
0abee507 386 return SR_ERR_BUG;
f1898235
JH
387 }
388
389 /* TODO */
390 close_dev(sdi);
391
f302a082
JH
392 return SR_OK;
393}
394
395static int hw_cleanup(void)
396{
187b3582
JH
397 GSList *l;
398 struct sr_dev_inst *sdi;
772a0e61 399 struct context *ctx;
62bc70e4 400 int ret = SR_OK;
187b3582 401
62bc70e4
JH
402 for(l = dev_insts; l; l = l->next) {
403 if (!(sdi = l->data)) {
404 /* Log error, but continue cleaning up the rest. */
405 sr_err("fx2lafw: %s: sdi was NULL, continuing", __func__);
406 ret = SR_ERR_BUG;
407 continue;
408 }
409 if (!(ctx = sdi->priv)) {
410 /* Log error, but continue cleaning up the rest. */
411 sr_err("fx2lafw: %s: sdi->priv was NULL, continuing",
412 __func__);
413 ret = SR_ERR_BUG;
414 continue;
415 }
416 close_dev(sdi);
187b3582
JH
417 sdi = l->data;
418 sr_dev_inst_free(sdi);
419 }
420
62bc70e4
JH
421 g_slist_free(dev_insts);
422 dev_insts = NULL;
187b3582
JH
423
424 if(usb_context)
425 libusb_exit(usb_context);
426 usb_context = NULL;
427
62bc70e4 428 return ret;
f302a082
JH
429}
430
772a0e61 431static void *hw_dev_info_get(int dev_index, int dev_info_id)
f302a082 432{
8b35f474 433 struct sr_dev_inst *sdi;
772a0e61 434 struct context *ctx;
8b35f474 435
772a0e61 436 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
8b35f474 437 return NULL;
cdfdd711 438 ctx = sdi->priv;
8b35f474 439
772a0e61 440 switch (dev_info_id) {
8b35f474
JH
441 case SR_DI_INST:
442 return sdi;
443 case SR_DI_NUM_PROBES:
cdfdd711 444 return GINT_TO_POINTER(ctx->profile->num_probes);
8b35f474
JH
445 case SR_DI_PROBE_NAMES:
446 return fx2lafw_probe_names;
447 case SR_DI_SAMPLERATES:
448 return &fx2lafw_samplerates;
449 case SR_DI_TRIGGER_TYPES:
450 return TRIGGER_TYPES;
e3186647
JH
451 case SR_DI_CUR_SAMPLERATE:
452 return &ctx->cur_samplerate;
8b35f474
JH
453 }
454
f302a082
JH
455 return NULL;
456}
457
772a0e61 458static int hw_dev_status_get(int dev_index)
f302a082 459{
aae2fed6 460 const struct sr_dev_inst *const sdi =
772a0e61 461 sr_dev_inst_get(dev_insts, dev_index);
aae2fed6
JH
462
463 if (!sdi)
464 return SR_ST_NOT_FOUND;
465
466 return sdi->status;
f302a082
JH
467}
468
469static int *hw_hwcap_get_all(void)
470{
8b35f474 471 return fx2lafw_capabilities;
f302a082
JH
472}
473
7cb621d4 474static int hw_dev_config_set(int dev_index, int hwcap, void *value)
f302a082 475{
7cb621d4 476 struct sr_dev_inst *sdi;
772a0e61 477 struct context *ctx;
7cb621d4
JH
478 int ret;
479
480 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
481 return SR_ERR;
482 ctx = sdi->priv;
483
e3186647
JH
484 if (hwcap == SR_HWCAP_SAMPLERATE) {
485 ctx->cur_samplerate = *(uint64_t *)value;
486 ret = SR_OK;
487 } else if (hwcap == SR_HWCAP_PROBECONFIG) {
488 ret = SR_OK;
489 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
7cb621d4
JH
490 ctx->limit_samples = *(uint64_t *)value;
491 ret = SR_OK;
492 } else {
493 ret = SR_ERR;
494 }
495
496 return ret;
f302a082
JH
497}
498
1f9813eb 499static int receive_data(int fd, int revents, void *cb_data)
610dbb70
JH
500{
501 struct timeval tv;
502
503 /* Avoid compiler warnings. */
504 (void)fd;
505 (void)revents;
1f9813eb 506 (void)cb_data;
610dbb70
JH
507
508 tv.tv_sec = tv.tv_usec = 0;
509 libusb_handle_events_timeout(usb_context, &tv);
510
511 return TRUE;
512}
513
2e526f4a
JH
514static void abort_acquisition(struct context *ctx)
515{
516 struct sr_datafeed_packet packet;
517
518 packet.type = SR_DF_END;
519 sr_session_send(ctx->session_dev_id, &packet);
520
521 ctx->num_samples = -1;
522
523 /* TODO: Need to cancel and free any queued up transfers. */
524}
525
610dbb70
JH
526static void receive_transfer(struct libusb_transfer *transfer)
527{
528 /* TODO: These statics have to move to the ctx struct. */
610dbb70
JH
529 static int empty_transfer_count = 0;
530 struct sr_datafeed_packet packet;
531 struct sr_datafeed_logic logic;
2e526f4a 532 struct context *ctx = transfer->user_data;
610dbb70
JH
533 int cur_buflen;
534 unsigned char *cur_buf, *new_buf;
535
610dbb70
JH
536 /*
537 * If acquisition has already ended, just free any queued up
538 * transfer that come in.
539 */
2e526f4a 540 if (ctx->num_samples == -1) {
610dbb70
JH
541 if (transfer)
542 libusb_free_transfer(transfer);
543 return;
544 }
545
546 sr_info("fx2lafw: receive_transfer(): status %d received %d bytes",
547 transfer->status, transfer->actual_length);
548
549 /* Save incoming transfer before reusing the transfer struct. */
550 cur_buf = transfer->buffer;
551 cur_buflen = transfer->actual_length;
552 ctx = transfer->user_data;
553
554 /* Fire off a new request. */
555 if (!(new_buf = g_try_malloc(4096))) {
556 sr_err("fx2lafw: %s: new_buf malloc failed", __func__);
557 return; /* TODO: SR_ERR_MALLOC */
558 }
559
560 transfer->buffer = new_buf;
561 transfer->length = 4096;
562 if (libusb_submit_transfer(transfer) != 0) {
563 /* TODO: Stop session? */
564 /* TODO: Better error message. */
565 sr_err("fx2lafw: %s: libusb_submit_transfer error", __func__);
566 }
567
568 if (cur_buflen == 0) {
569 empty_transfer_count++;
570 if (empty_transfer_count > MAX_EMPTY_TRANSFERS) {
571 /*
572 * The FX2 gave up. End the acquisition, the frontend
573 * will work out that the samplecount is short.
574 */
2e526f4a 575 abort_acquisition(ctx);
610dbb70
JH
576 }
577 return;
578 } else {
579 empty_transfer_count = 0;
580 }
581
582 /* Send the incoming transfer to the session bus. */
583 packet.type = SR_DF_LOGIC;
584 packet.payload = &logic;
585 logic.length = cur_buflen;
586 logic.unitsize = 1;
587 logic.data = cur_buf;
3cd3a20b 588 sr_session_send(ctx->session_dev_id, &packet);
610dbb70
JH
589 g_free(cur_buf);
590
2e526f4a 591 ctx->num_samples += cur_buflen;
610dbb70 592 if (ctx->limit_samples &&
2e526f4a
JH
593 (unsigned int) ctx->num_samples > ctx->limit_samples) {
594 abort_acquisition(ctx);
610dbb70
JH
595 }
596}
597
3cd3a20b 598static int hw_dev_acquisition_start(int dev_index, void *cb_data)
f302a082 599{
610dbb70
JH
600 struct sr_dev_inst *sdi;
601 struct sr_datafeed_packet *packet;
602 struct sr_datafeed_header *header;
772a0e61 603 struct context *ctx;
610dbb70
JH
604 struct libusb_transfer *transfer;
605 const struct libusb_pollfd **lupfd;
f6582cd7 606 int err, size, i;
610dbb70
JH
607 unsigned char *buf;
608
609 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
610 return SR_ERR;
611 ctx = sdi->priv;
3cd3a20b 612 ctx->session_dev_id = cb_data;
2e526f4a 613 ctx->num_samples = 0;
610dbb70
JH
614
615 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
616 sr_err("fx2lafw: %s: packet malloc failed", __func__);
617 return SR_ERR_MALLOC;
618 }
619
620 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
621 sr_err("fx2lafw: %s: header malloc failed", __func__);
622 return SR_ERR_MALLOC;
623 }
624
625 /* Start with 2K transfer, subsequently increased to 4K. */
626 size = 2048;
627 for (i = 0; i < NUM_SIMUL_TRANSFERS; i++) {
628 if (!(buf = g_try_malloc(size))) {
629 sr_err("fx2lafw: %s: buf malloc failed", __func__);
630 return SR_ERR_MALLOC;
631 }
632 transfer = libusb_alloc_transfer(0);
633 libusb_fill_bulk_transfer(transfer, ctx->usb->devhdl,
634 2 | LIBUSB_ENDPOINT_IN, buf, size,
635 receive_transfer, ctx, 40);
636 if (libusb_submit_transfer(transfer) != 0) {
637 /* TODO: Free them all. */
638 libusb_free_transfer(transfer);
639 g_free(buf);
640 return SR_ERR;
641 }
642 size = 4096;
643 }
644
645 lupfd = libusb_get_pollfds(usb_context);
646 for (i = 0; lupfd[i]; i++)
647 sr_source_add(lupfd[i]->fd, lupfd[i]->events,
648 40, receive_data, NULL);
649 free(lupfd); /* NOT g_free()! */
650
651 packet->type = SR_DF_HEADER;
652 packet->payload = header;
653 header->feed_version = 1;
654 gettimeofday(&header->starttime, NULL);
e3186647 655 header->samplerate = ctx->cur_samplerate;
610dbb70 656 header->num_logic_probes = ctx->profile->num_probes;
c8f2c9dd 657 sr_session_send(cb_data, packet);
610dbb70
JH
658 g_free(header);
659 g_free(packet);
660
017375d1
JH
661 if ((err = command_start_acquisition (ctx->usb->devhdl,
662 ctx->cur_samplerate)) != SR_OK) {
663 return err;
664 }
665
f302a082
JH
666 return SR_OK;
667}
668
3cd3a20b 669/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
c8f2c9dd 670static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
f302a082 671{
2e526f4a 672 struct sr_dev_inst *sdi;
5da93902 673
2e526f4a
JH
674 /* unused parameter */
675 (void)cb_data;
5da93902 676
2e526f4a
JH
677 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
678 return SR_ERR;
679
680 abort_acquisition(sdi->priv);
5da93902 681
f302a082
JH
682 return SR_OK;
683}
684
c09f0b57 685SR_PRIV struct sr_dev_driver fx2lafw_driver_info = {
f302a082
JH
686 .name = "fx2lafw",
687 .longname = "fx2lafw",
688 .api_version = 1,
689 .init = hw_init,
690 .cleanup = hw_cleanup,
691 .dev_open = hw_dev_open,
692 .dev_close = hw_dev_close,
693 .dev_info_get = hw_dev_info_get,
694 .dev_status_get = hw_dev_status_get,
695 .hwcap_get_all = hw_hwcap_get_all,
696 .dev_config_set = hw_dev_config_set,
697 .dev_acquisition_start = hw_dev_acquisition_start,
698 .dev_acquisition_stop = hw_dev_acquisition_stop,
699};