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