]> sigrok.org Git - libsigrok.git/blob - hardware/chronovu-la8/chronovu-la8.c
98a732846812a99665c0265b784109f46996601c
[libsigrok.git] / hardware / chronovu-la8 / chronovu-la8.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.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 2 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, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <ftdi.h>
22 #include <sigrok.h>
23 #include <sigrok-internal.h>
24
25 #define USB_VENDOR_ID                   0x0403
26 #define USB_PRODUCT_ID                  0x6001
27 #define USB_DESCRIPTION                 "ChronoVu LA8"
28 #define USB_VENDOR_NAME                 "ChronoVu"
29 #define USB_MODEL_NAME                  "LA8"
30 #define USB_MODEL_VERSION               ""
31
32 #define NUM_PROBES                      8
33 #define TRIGGER_TYPES                   "01"
34 #define SDRAM_SIZE                      (8 * 1024 * 1024)
35 #define MIN_NUM_SAMPLES                 1
36
37 static GSList *device_instances = NULL;
38
39 struct la8 {
40         /** FTDI device context (used by libftdi). */
41         struct ftdi_context *ftdic;
42
43         /** The currently configured samplerate of the device. */
44         uint64_t cur_samplerate;
45
46         /** The current sampling limit (in ms). */
47         uint64_t limit_msec;
48
49         /** The current sampling limit (in number of samples). */
50         uint64_t limit_samples;
51
52         /** The number of probes. */
53         int num_probes;
54
55         /** TODO */
56         gpointer session_id;
57
58         /**
59          * An 8MB buffer containing the (mangled) samples from the device.
60          * Format: Pretty mangled-up (due to hardware reasons), see code.
61          */
62         uint8_t *mangled_buf;
63
64         /**
65          * An 8MB buffer where we'll store the de-mangled samples.
66          * Format: Each sample is 1 byte, MSB is channel 7, LSB is channel 0.
67          */
68         uint8_t *final_buf;
69
70         /**
71          * Trigger pattern (MSB = channel 7, LSB = channel 0).
72          * A 1 bit matches a high signal, 0 matches a low signal on a probe.
73          * Only low/high triggers (but not e.g. rising/falling) are supported.
74          */
75         uint8_t trigger_pattern;
76
77         /**
78          * Trigger mask (MSB = channel 7, LSB = channel 0).
79          * A 1 bit means "must match trigger_pattern", 0 means "don't care".
80          */
81         uint8_t trigger_mask;
82
83         /** Time (in seconds) before the trigger times out. */
84         uint64_t trigger_timeout;
85
86         /** TODO */
87         time_t done;
88
89         /** Counter/index for the data block (0..2047) to be read. */
90         int block_counter;
91
92         /** The divcount value (determines the sample period) for the LA8. */
93         uint8_t divcount;
94 };
95
96 /* This will be initialized via hw_get_device_info()/SR_DI_SAMPLERATES. */
97 static uint64_t supported_samplerates[255 + 1] = { 0 };
98
99 /*
100  * Min: 1 sample per 0.01us -> sample time is 0.084s, samplerate 100MHz
101  * Max: 1 sample per 2.55us -> sample time is 21.391s, samplerate 392.15kHz
102  */
103 static struct sr_samplerates samplerates = {
104         .low  = 0,
105         .high = 0,
106         .step = 0,
107         .list = supported_samplerates,
108 };
109
110 /* Note: Continuous sampling is not supported by the hardware. */
111 static int capabilities[] = {
112         SR_HWCAP_LOGIC_ANALYZER,
113         SR_HWCAP_SAMPLERATE,
114         SR_HWCAP_LIMIT_MSEC, /* TODO: Not yet implemented. */
115         SR_HWCAP_LIMIT_SAMPLES, /* TODO: Not yet implemented. */
116         0,
117 };
118
119 /* Function prototypes. */
120 static int la8_close_usb_reset_sequencer(struct la8 *la8);
121 static void hw_stop_acquisition(int device_index, gpointer session_device_id);
122 static int la8_reset(struct la8 *la8);
123
124 static void fill_supported_samplerates_if_needed(void)
125 {
126         int i;
127
128         /* Do nothing if supported_samplerates[] is already filled. */
129         if (supported_samplerates[0] != 0)
130                 return;
131
132         /* Fill supported_samplerates[] with the proper values. */
133         for (i = 0; i < 255; i++)
134                 supported_samplerates[254 - i] = SR_MHZ(100) / (i + 1);
135         supported_samplerates[255] = 0;
136 }
137
138 /**
139  * Check if the given samplerate is supported by the LA8 hardware.
140  *
141  * @param samplerate The samplerate (in Hz) to check.
142  * @return 1 if the samplerate is supported/valid, 0 otherwise.
143  */
144 static int is_valid_samplerate(uint64_t samplerate)
145 {
146         int i;
147
148         fill_supported_samplerates_if_needed();
149
150         for (i = 0; i < 255; i++) {
151                 if (supported_samplerates[i] == samplerate)
152                         return 1;
153         }
154
155         sr_warn("la8: %s: invalid samplerate (%" PRIu64 "Hz)",
156                 __func__, samplerate);
157
158         return 0;
159 }
160
161 /**
162  * Convert a samplerate (in Hz) to the 'divcount' value the LA8 wants.
163  *
164  * LA8 hardware: sample period = (divcount + 1) * 10ns.
165  * Min. value for divcount: 0x00 (10ns sample period, 100MHz samplerate).
166  * Max. value for divcount: 0xfe (2550ns sample period, 392.15kHz samplerate).
167  *
168  * @param samplerate The samplerate in Hz.
169  * @return The divcount value as needed by the hardware, or 0xff upon errors.
170  */
171 static uint8_t samplerate_to_divcount(uint64_t samplerate)
172 {
173         if (samplerate == 0) {
174                 sr_warn("la8: %s: samplerate was 0", __func__);
175                 return 0xff;
176         }
177
178         if (!is_valid_samplerate(samplerate)) {
179                 sr_warn("la8: %s: can't get divcount, samplerate invalid",
180                         __func__);
181                 return 0xff;
182         }
183
184         return (SR_MHZ(100) / samplerate) - 1;
185 }
186
187 /**
188  * Write data of a certain length to the LA8's FTDI device.
189  *
190  * @param la8 The LA8 struct containing private per-device-instance data.
191  * @param buf The buffer containing the data to write.
192  * @param size The number of bytes to write.
193  * @return The number of bytes written, or a negative value upon errors.
194  */
195 static int la8_write(struct la8 *la8, uint8_t *buf, int size)
196 {
197         int bytes_written;
198
199         if (!la8) {
200                 sr_warn("la8: %s: la8 was NULL", __func__);
201                 return SR_ERR_ARG;
202         }
203
204         if (!la8->ftdic) {
205                 sr_warn("la8: %s: la8->ftdic was NULL", __func__);
206                 return SR_ERR_ARG;
207         }
208
209         if (!buf) {
210                 sr_warn("la8: %s: buf was NULL", __func__);
211                 return SR_ERR_ARG;
212         }
213
214         if (size < 0) {
215                 sr_warn("la8: %s: size was < 0", __func__);
216                 return SR_ERR_ARG;
217         }
218
219         bytes_written = ftdi_write_data(la8->ftdic, buf, size);
220
221         if (bytes_written < 0) {
222                 sr_warn("la8: %s: ftdi_write_data: (%d) %s", __func__,
223                         bytes_written, ftdi_get_error_string(la8->ftdic));
224                 (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
225         } else if (bytes_written != size) {
226                 sr_warn("la8: %s: bytes to write: %d, bytes written: %d",
227                         __func__, size, bytes_written);
228                 (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
229         }
230
231         return bytes_written;
232 }
233
234 /**
235  * Read a certain amount of bytes from the LA8's FTDI device.
236  *
237  * @param la8 The LA8 struct containing private per-device-instance data.
238  * @param buf The buffer where the received data will be stored.
239  * @param size The number of bytes to read.
240  * @return The number of bytes read, or a negative value upon errors.
241  */
242 static int la8_read(struct la8 *la8, uint8_t *buf, int size)
243 {
244         int bytes_read;
245
246         if (!la8) {
247                 sr_warn("la8: %s: la8 was NULL", __func__);
248                 return SR_ERR_ARG;
249         }
250
251         if (!la8->ftdic) {
252                 sr_warn("la8: %s: la8->ftdic was NULL", __func__);
253                 return SR_ERR_ARG;
254         }
255
256         if (!buf) {
257                 sr_warn("la8: %s: buf was NULL", __func__);
258                 return SR_ERR_ARG;
259         }
260
261         if (size <= 0) {
262                 sr_warn("la8: %s: size was <= 0", __func__);
263                 return SR_ERR_ARG;
264         }
265
266         bytes_read = ftdi_read_data(la8->ftdic, buf, size);
267
268         if (bytes_read < 0) {
269                 sr_warn("la8: %s: ftdi_read_data: (%d) %s", __func__,
270                         bytes_read, ftdi_get_error_string(la8->ftdic));
271         } else if (bytes_read != size) {
272                 // sr_warn("la8: %s: bytes to read: %d, bytes read: %d",
273                 //      __func__, size, bytes_read);
274         }
275
276         return bytes_read;
277 }
278
279 static int la8_close(struct la8 *la8)
280 {
281         int ret;
282
283         if (!la8) {
284                 sr_warn("la8: %s: la8 was NULL", __func__);
285                 return SR_ERR_ARG;
286         }
287
288         if (!la8->ftdic) {
289                 sr_warn("la8: %s: la8->ftdic was NULL", __func__);
290                 return SR_ERR_ARG;
291         }
292
293         if ((ret = ftdi_usb_close(la8->ftdic)) < 0) {
294                 sr_warn("la8: %s: ftdi_usb_close: (%d) %s",
295                         __func__, ret, ftdi_get_error_string(la8->ftdic));
296         }
297
298         return ret;
299 }
300
301 /**
302  * Close the ChronoVu LA8 USB port and reset the LA8 sequencer logic.
303  *
304  * @param la8 The LA8 struct containing private per-device-instance data.
305  * @return SR_OK upon success, SR_ERR upon failure.
306  */
307 static int la8_close_usb_reset_sequencer(struct la8 *la8)
308 {
309         /* Magic sequence of bytes for resetting the LA8 sequencer logic. */
310         uint8_t buf[8] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
311         int ret;
312
313         sr_dbg("la8: entering %s", __func__);
314
315         if (!la8) {
316                 sr_warn("la8: %s: la8 was NULL", __func__);
317                 return SR_ERR_ARG;
318         }
319
320         if (!la8->ftdic) {
321                 sr_warn("la8: %s: la8->ftdic was NULL", __func__);
322                 return SR_ERR_ARG;
323         }
324
325         if (la8->ftdic->usb_dev) {
326                 /* Reset the LA8 sequencer logic, then wait 100ms. */
327                 sr_dbg("la8: resetting sequencer logic");
328                 (void) la8_write(la8, buf, 8); /* Ignore errors. */
329                 g_usleep(100 * 1000);
330
331                 /* Purge FTDI buffers, then reset and close the FTDI device. */
332                 sr_dbg("la8: purging buffers, resetting+closing FTDI device");
333
334                 /* Log errors, but ignore them (i.e., don't abort). */
335                 if ((ret = ftdi_usb_purge_buffers(la8->ftdic)) < 0)
336                         sr_warn("la8: %s: ftdi_usb_purge_buffers: (%d) %s",
337                             __func__, ret, ftdi_get_error_string(la8->ftdic));
338                 if ((ret = ftdi_usb_reset(la8->ftdic)) < 0)
339                         sr_warn("la8: %s: ftdi_usb_reset: (%d) %s", __func__,
340                                 ret, ftdi_get_error_string(la8->ftdic));
341                 if ((ret = ftdi_usb_close(la8->ftdic)) < 0)
342                         sr_warn("la8: %s: ftdi_usb_close: (%d) %s", __func__,
343                                 ret, ftdi_get_error_string(la8->ftdic));
344         } else {
345                 sr_dbg("la8: %s: usb_dev was NULL, nothing to do", __func__);
346         }
347
348         ftdi_free(la8->ftdic); /* Returns void. */
349         la8->ftdic = NULL;
350
351         return SR_OK;
352 }
353
354 /**
355  * Reset the ChronoVu LA8.
356  *
357  * The LA8 must be reset after a failed read/write operation or upon timeouts.
358  *
359  * @param la8 The LA8 struct containing private per-device-instance data.
360  * @return SR_OK upon success, SR_ERR upon failure.
361  */
362 static int la8_reset(struct la8 *la8)
363 {
364         uint8_t buf[4096];
365         time_t done, now;
366         int bytes_read;
367
368         if (!la8) {
369                 sr_warn("la8: %s: la8 was NULL", __func__);
370                 return SR_ERR_ARG;
371         }
372
373         if (!la8->ftdic) {
374                 sr_warn("la8: %s: la8->ftdic was NULL", __func__);
375                 return SR_ERR_ARG;
376         }
377
378         sr_dbg("la8: resetting the device");
379
380         /*
381          * Purge pending read data from the FTDI hardware FIFO until
382          * no more data is left, or a timeout occurs (after 20s).
383          */
384         done = 20 + time(NULL);
385         do {
386                 /* TODO: Ignore errors? Check for < 0 at least! */
387                 bytes_read = la8_read(la8, (uint8_t *)&buf, 4096);
388                 now = time(NULL);
389         } while ((done > now) && (bytes_read > 0));
390
391         /* Reset the LA8 sequencer logic and close the USB port. */
392         (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
393
394         sr_dbg("la8: device reset finished");
395
396         return SR_OK;
397 }
398
399 static int hw_init(const char *deviceinfo)
400 {
401         int ret;
402         struct sr_device_instance *sdi;
403         struct la8 *la8;
404
405         sr_dbg("la8: entering %s", __func__);
406
407         /* Avoid compiler errors. */
408         deviceinfo = deviceinfo;
409
410         /* Allocate memory for our private driver context. */
411         if (!(la8 = malloc(sizeof(struct la8)))) {
412                 sr_warn("la8: %s: struct la8 malloc failed", __func__);
413                 ret = SR_ERR_MALLOC;
414                 goto err_free_nothing;
415         }
416
417         /* Set some sane defaults. */
418         la8->ftdic = NULL;
419         la8->cur_samplerate = SR_MHZ(100); /* 100MHz == max. samplerate */
420         la8->limit_msec = 0;
421         la8->limit_samples = 0;
422         la8->num_probes = NUM_PROBES;
423         la8->session_id = NULL;
424         la8->mangled_buf = NULL;
425         la8->final_buf = NULL;
426         la8->trigger_pattern = 0x00; /* Value irrelevant, see trigger_mask. */
427         la8->trigger_mask = 0x00; /* All probes are "don't care". */
428         la8->trigger_timeout = 10; /* Default to 10s trigger timeout. */
429         la8->done = 0;
430         la8->block_counter = 0;
431         la8->divcount = 0; /* 10ns sample period == 100MHz samplerate */
432
433         /* Allocate memory for the raw (mangled) data from the LA8. */
434         if (!(la8->mangled_buf = malloc(SDRAM_SIZE))) {
435                 sr_warn("la8: %s: mangled_buf malloc failed", __func__);
436                 ret = SR_ERR_MALLOC;
437                 goto err_free_la8;
438         }
439
440         /* Allocate memory where we'll store the de-mangled data. */
441         if (!(la8->final_buf = malloc(SDRAM_SIZE))) {
442                 sr_warn("la8: %s: final_buf malloc failed", __func__);
443                 ret = SR_ERR_MALLOC;
444                 goto err_free_mangled_buf;
445         }
446
447         /* Allocate memory for the FTDI context (ftdic) and initialize it. */
448         if (!(la8->ftdic = ftdi_new())) {
449                 sr_warn("la8: %s: ftdi_new failed", __func__);
450                 ret = SR_ERR; /* TODO: More specific error? */
451                 goto err_free_final_buf;
452         }
453
454         /* Check for the device and temporarily open it. */
455         if ((ret = ftdi_usb_open_desc(la8->ftdic, USB_VENDOR_ID,
456                         USB_PRODUCT_ID, USB_DESCRIPTION, NULL)) < 0) {
457                 sr_warn("la8: %s: ftdi_usb_open_desc: (%d) %s",
458                         __func__, ret, ftdi_get_error_string(la8->ftdic));
459                 (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
460                 ret = SR_ERR; /* TODO: More specific error? */
461                 goto err_free_ftdic;
462         }
463         sr_dbg("la8: found device");
464
465         /* Register the device with libsigrok. */
466         sdi = sr_device_instance_new(0, SR_ST_INITIALIZING,
467                         USB_VENDOR_NAME, USB_MODEL_NAME, USB_MODEL_VERSION);
468         if (!sdi) {
469                 sr_warn("la8: %s: sr_device_instance_new failed", __func__);
470                 ret = SR_ERR; /* TODO: More specific error? */
471                 goto err_close_ftdic;
472         }
473
474         sdi->priv = la8;
475
476         device_instances = g_slist_append(device_instances, sdi);
477
478         sr_dbg("la8: %s finished successfully", __func__);
479
480         /* Close device. We'll reopen it again when we need it. */
481         (void) la8_close(la8); /* Log, but ignore errors. */
482
483         // return SR_OK; /* TODO */
484         return 1;
485
486 err_close_ftdic:
487         (void) la8_close(la8); /* Log, but ignore errors. */
488 err_free_ftdic:
489         free(la8->ftdic);
490 err_free_final_buf:
491         free(la8->final_buf);
492 err_free_mangled_buf:
493         free(la8->mangled_buf);
494 err_free_la8:
495         free(la8);
496 err_free_nothing:
497         // return ret; /* TODO */
498         return 0;
499 }
500
501 static int hw_opendev(int device_index)
502 {
503         int ret;
504         struct sr_device_instance *sdi;
505         struct la8 *la8;
506
507         if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
508                 sr_warn("la8: %s: sdi was NULL", __func__);
509                 return SR_ERR; /* TODO: SR_ERR_ARG? */
510         }
511
512         if (!(la8 = sdi->priv)) {
513                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
514                 return SR_ERR; /* TODO: SR_ERR_ARG? */
515         }
516
517         sr_dbg("la8: opening device");
518
519         /* Open the device. */
520         if ((ret = ftdi_usb_open_desc(la8->ftdic, USB_VENDOR_ID,
521                         USB_PRODUCT_ID, USB_DESCRIPTION, NULL)) < 0) {
522                 sr_warn("la8: %s: ftdi_usb_open_desc: (%d) %s",
523                         __func__, ret, ftdi_get_error_string(la8->ftdic));
524                 (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
525                 return SR_ERR;
526         }
527         sr_dbg("la8: device opened successfully");
528
529         /* Purge RX/TX buffers in the FTDI chip. */
530         if ((ret = ftdi_usb_purge_buffers(la8->ftdic)) < 0) {
531                 sr_warn("la8: %s: ftdi_usb_purge_buffers: (%d) %s",
532                         __func__, ret, ftdi_get_error_string(la8->ftdic));
533                 (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
534                 goto err_opendev_close_ftdic;
535         }
536         sr_dbg("la8: FTDI buffers purged successfully");
537
538         /* Enable flow control in the FTDI chip. */
539         if ((ret = ftdi_setflowctrl(la8->ftdic, SIO_RTS_CTS_HS)) < 0) {
540                 sr_warn("la8: %s: ftdi_setflowcontrol: (%d) %s",
541                         __func__, ret, ftdi_get_error_string(la8->ftdic));
542                 (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
543                 goto err_opendev_close_ftdic;
544         }
545         sr_dbg("la8: FTDI flow control enabled successfully");
546
547         /* Wait 100ms. */
548         g_usleep(100 * 1000);
549
550         sdi->status = SR_ST_ACTIVE;
551
552         return SR_OK;
553
554 err_opendev_close_ftdic:
555         (void) la8_close(la8); /* Log, but ignore errors. */
556         return SR_ERR;
557 }
558
559 static int set_samplerate(struct sr_device_instance *sdi, uint64_t samplerate)
560 {
561         struct la8 *la8;
562
563         if (!sdi) {
564                 sr_warn("la8: %s: sdi was NULL", __func__);
565                 return SR_ERR_ARG;
566         }
567
568         if (!(la8 = sdi->priv)) {
569                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
570                 return SR_ERR_ARG;
571         }
572
573         sr_dbg("la8: setting samplerate");
574
575         fill_supported_samplerates_if_needed();
576
577         /* Check if this is a samplerate supported by the hardware. */
578         if (!is_valid_samplerate(samplerate))
579                 return SR_ERR;
580
581         /* Set the new samplerate. */
582         la8->cur_samplerate = samplerate;
583
584         sr_dbg("la8: samplerate set to %" PRIu64 "Hz", la8->cur_samplerate);
585
586         return SR_OK;
587 }
588
589 static void hw_closedev(int device_index)
590 {
591         struct sr_device_instance *sdi;
592         struct la8 *la8;
593
594         if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
595                 sr_warn("la8: %s: sdi was NULL", __func__);
596                 return;
597         }
598
599         if (!(la8 = sdi->priv)) {
600                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
601                 return;
602         }
603
604         sr_dbg("la8: closing device");
605
606         if (sdi->status == SR_ST_ACTIVE) {
607                 sr_dbg("la8: %s: status ACTIVE, closing device", __func__);
608                 /* TODO: Handle or ignore errors here? */
609                 (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
610         } else {
611                 sr_dbg("la8: %s: status not ACTIVE, nothing to do", __func__);
612         }
613
614         sdi->status = SR_ST_INACTIVE;
615
616         sr_dbg("la8: %s: freeing sample buffers", __func__);
617         free(la8->mangled_buf);
618         free(la8->final_buf);
619 }
620
621 static void hw_cleanup(void)
622 {
623         GSList *l;
624         struct sr_device_instance *sdi;
625
626         sr_dbg("la8: entering %s", __func__);
627
628         /* Properly close all devices. */
629         for (l = device_instances; l; l = l->next) {
630                 if ((sdi = l->data) == NULL) {
631                         sr_warn("la8: %s: sdi was NULL", __func__);
632                         continue;
633                 }
634                 if (sdi->priv != NULL)
635                         free(sdi->priv);
636                 else
637                         sr_warn("la8: %s: sdi->priv was NULL", __func__);
638                 sr_device_instance_free(sdi); /* Returns void. */
639         }
640         g_slist_free(device_instances); /* Returns void. */
641         device_instances = NULL;
642 }
643
644 static void *hw_get_device_info(int device_index, int device_info_id)
645 {
646         struct sr_device_instance *sdi;
647         struct la8 *la8;
648         void *info;
649
650         sr_dbg("la8: entering %s", __func__);
651
652         if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
653                 sr_warn("la8: %s: sdi was NULL", __func__);
654                 return NULL;
655         }
656
657         if (!(la8 = sdi->priv)) {
658                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
659                 return NULL;
660         }
661
662         switch (device_info_id) {
663         case SR_DI_INSTANCE:
664                 info = sdi;
665                 break;
666         case SR_DI_NUM_PROBES:
667                 info = GINT_TO_POINTER(NUM_PROBES);
668                 break;
669         case SR_DI_SAMPLERATES:
670                 fill_supported_samplerates_if_needed();
671                 info = &samplerates;
672                 break;
673         case SR_DI_TRIGGER_TYPES:
674                 info = (char *)TRIGGER_TYPES;
675                 break;
676         case SR_DI_CUR_SAMPLERATE:
677                 info = &la8->cur_samplerate;
678                 break;
679         default:
680                 /* Unknown device info ID, return NULL. */
681                 sr_warn("la8: %s: Unknown device info ID", __func__);
682                 info = NULL;
683                 break;
684         }
685
686         return info;
687 }
688
689 static int hw_get_status(int device_index)
690 {
691         struct sr_device_instance *sdi;
692
693         if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
694                 sr_warn("la8: %s: sdi was NULL, device not found", __func__);
695                 return SR_ST_NOT_FOUND;
696         }
697
698         sr_dbg("la8: %s: returning status %d", __func__, sdi->status);
699
700         return sdi->status;
701 }
702
703 static int *hw_get_capabilities(void)
704 {
705         sr_dbg("la8: entering %s", __func__);
706
707         return capabilities;
708 }
709
710 static int hw_set_configuration(int device_index, int capability, void *value)
711 {
712         struct sr_device_instance *sdi;
713         struct la8 *la8;
714
715         sr_dbg("la8: entering %s", __func__);
716
717         if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
718                 sr_warn("la8: %s: sdi was NULL", __func__);
719                 return SR_ERR; /* TODO: SR_ERR_ARG? */
720         }
721
722         if (!(la8 = sdi->priv)) {
723                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
724                 return SR_ERR; /* TODO: SR_ERR_ARG? */
725         }
726
727         switch (capability) {
728         case SR_HWCAP_SAMPLERATE:
729                 if (set_samplerate(sdi, *(uint64_t *)value) == SR_ERR)
730                         return SR_ERR;
731                 sr_dbg("la8: SAMPLERATE = %" PRIu64, la8->cur_samplerate);
732                 break;
733         case SR_HWCAP_PROBECONFIG:
734                 /* Nothing to do, but this entry must exist. Fix this. */
735                 /* TODO? */
736                 sr_dbg("la8: %s: SR_HWCAP_PROBECONFIG called", __func__);
737                 return SR_OK;
738                 break;
739         case SR_HWCAP_LIMIT_MSEC:
740                 if (*(uint64_t *)value == 0) {
741                         sr_warn("la8: %s: LIMIT_MSEC can't be 0", __func__);
742                         return SR_ERR;
743                 }
744                 la8->limit_msec = *(uint64_t *)value;
745                 sr_dbg("la8: LIMIT_MSEC = %" PRIu64, la8->limit_msec);
746                 break;
747         case SR_HWCAP_LIMIT_SAMPLES:
748                 if (*(uint64_t *)value < MIN_NUM_SAMPLES) {
749                         sr_warn("la8: %s: LIMIT_SAMPLES too small", __func__);
750                         return SR_ERR;
751                 }
752                 la8->limit_samples = *(uint64_t *)value;
753                 sr_dbg("la8: LIMIT_SAMPLES = %" PRIu64, la8->limit_samples);
754                 break;
755         default:
756                 /* Unknown capability, return SR_ERR. */
757                 sr_warn("la8: %s: Unknown capability", __func__);
758                 return SR_ERR;
759                 break;
760         }
761
762         return SR_OK;
763 }
764
765 /**
766  * Get a block of 4096 bytes of data from the LA8.
767  *
768  * @param la8 The LA8 struct containing private per-device-instance data.
769  * @return SR_OK upon success, or SR_ERR upon errors.
770  */
771 static int la8_read_block(struct la8 *la8)
772 {
773         int i, byte_offset, m, mi, p, index, bytes_read;
774         time_t now;
775
776         if (!la8) {
777                 sr_warn("la8: %s: la8 was NULL", __func__);
778                 return SR_ERR_ARG;
779         }
780
781         if (!la8->ftdic) {
782                 sr_warn("la8: %s: la8->ftdic was NULL", __func__);
783                 return SR_ERR_ARG;
784         }
785
786         // sr_dbg("la8: %s: reading block %d", __func__, la8->block_counter);
787
788         bytes_read = la8_read(la8, la8->mangled_buf, 4096);
789
790         /* If first block read got 0 bytes, retry until success or timeout. */
791         if ((bytes_read == 0) && (la8->block_counter == 0)) {
792                 do {
793                         // sr_dbg("la8: %s: reading block 0 again", __func__);
794                         bytes_read = la8_read(la8, la8->mangled_buf, 4096);
795                         /* TODO: How to handle read errors here? */
796                         now = time(NULL);
797                 } while ((la8->done > now) && (bytes_read == 0));
798         }
799
800         /* Check if block read was successful or a timeout occured. */
801         if (bytes_read != 4096) {
802                 sr_warn("la8: %s: trigger timed out", __func__);
803                 (void) la8_reset(la8); /* Ignore errors. */
804                 return SR_ERR;
805         }
806
807         /* De-mangle the data. */
808         // sr_dbg("la8: de-mangling samples of block %d", la8->block_counter);
809         byte_offset = la8->block_counter * 4096;
810         m = byte_offset / (1024 * 1024);
811         mi = m * (1024 * 1024);
812         for (i = 0; i < 4096; i++) {
813                 p = i & (1 << 0);
814                 index = m * 2 + (((byte_offset + i) - mi) / 2) * 16;
815                 index += (la8->divcount == 0) ? p : (1 - p);
816                 la8->final_buf[index] = la8->mangled_buf[i];
817         }
818
819         return SR_OK;
820 }
821
822 static int receive_data(int fd, int revents, void *user_data)
823 {
824         int i, ret;
825         struct sr_device_instance *sdi;
826         struct sr_datafeed_packet packet;
827         struct la8 *la8;
828
829         /* Avoid compiler errors. */
830         fd = fd;
831         revents = revents;
832
833         if (!(sdi = user_data)) {
834                 sr_warn("la8: %s: user_data was NULL", __func__);
835                 return FALSE;
836         }
837
838         if (!(la8 = sdi->priv)) {
839                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
840                 return FALSE;
841         }
842
843         /* Get one block of data (4096 bytes). */
844         if ((ret = la8_read_block(la8)) < 0) {
845                 sr_warn("la8: %s: la8_read_block error: %d", __func__, ret);
846                 return FALSE;
847         }
848
849         /* We need to get exactly 2048 blocks (i.e. 8MB) of data. */
850         if (la8->block_counter != 2047) {
851                 la8->block_counter++;
852                 return TRUE;
853         }
854
855         sr_dbg("la8: sampling finished, sending data to session bus now");
856
857         /* All data was received and demangled, send it to the session bus. */
858         for (i = 0; i < 2048; i++) {
859                 /* Send a 4096 byte SR_DF_LOGIC packet to the session bus. */
860                 // sr_dbg("la8: %s: sending SR_DF_LOGIC packet", __func__);
861                 packet.type = SR_DF_LOGIC;
862                 packet.length = 4096;
863                 packet.unitsize = 1;
864                 packet.payload = la8->final_buf + (i * 4096);
865                 sr_session_bus(la8->session_id, &packet);
866         }
867
868         hw_stop_acquisition(sdi->index, user_data);
869
870         // return FALSE; /* FIXME? */
871         return TRUE;
872 }
873
874 static int hw_start_acquisition(int device_index, gpointer session_device_id)
875 {
876         struct sr_device_instance *sdi;
877         struct la8 *la8;
878         struct sr_datafeed_packet packet;
879         struct sr_datafeed_header header;
880         uint8_t buf[4];
881         int bytes_written;
882
883         sr_dbg("la8: entering %s", __func__);
884
885         if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
886                 sr_warn("la8: %s: sdi was NULL", __func__);
887                 return SR_ERR; /* TODO: SR_ERR_ARG? */
888         }
889
890         if (!(la8 = sdi->priv)) {
891                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
892                 return SR_ERR; /* TODO: SR_ERR_ARG? */
893         }
894
895         if (!la8->ftdic) {
896                 sr_warn("la8: %s: la8->ftdic was NULL", __func__);
897                 return SR_ERR_ARG;
898         }
899
900         la8->divcount = samplerate_to_divcount(la8->cur_samplerate);
901         if (la8->divcount == 0xff) {
902                 sr_warn("la8: %s: invalid divcount/samplerate", __func__);
903                 return SR_ERR;
904         }
905
906         /* Fill acquisition parameters into buf[]. */
907         buf[0] = la8->divcount;
908         buf[1] = 0xff; /* This byte must always be 0xff. */
909         buf[2] = la8->trigger_pattern;
910         buf[3] = la8->trigger_mask;
911
912         /* Start acquisition. */
913         bytes_written = la8_write(la8, buf, 4);
914
915         if (bytes_written < 0) {
916                 sr_warn("la8: acquisition failed to start");
917                 return SR_ERR;
918         } else if (bytes_written != 4) {
919                 sr_warn("la8: acquisition failed to start");
920                 return SR_ERR; /* TODO: Other error and return code? */
921         }
922
923         sr_dbg("la8: acquisition started successfully");
924
925         la8->session_id = session_device_id;
926
927         /* Send header packet to the session bus. */
928         sr_dbg("la8: %s: sending SR_DF_HEADER", __func__);
929         packet.type = SR_DF_HEADER;
930         packet.length = sizeof(struct sr_datafeed_header);
931         packet.unitsize = 0;
932         packet.payload = &header;
933         header.feed_version = 1;
934         gettimeofday(&header.starttime, NULL);
935         header.samplerate = la8->cur_samplerate;
936         header.protocol_id = SR_PROTO_RAW;
937         header.num_logic_probes = la8->num_probes;
938         header.num_analog_probes = 0;
939         sr_session_bus(session_device_id, &packet);
940
941         /* Time when we should be done (for detecting trigger timeouts). */
942         la8->done = (la8->divcount + 1) * 0.08388608 + time(NULL)
943                         + la8->trigger_timeout;
944         la8->block_counter = 0;
945
946         /* Hook up a dummy handler to receive data from the LA8. */
947         sr_source_add(-1, G_IO_IN, 0, receive_data, sdi);
948
949         return SR_OK;
950 }
951
952 static void hw_stop_acquisition(int device_index, gpointer session_device_id)
953 {
954         struct sr_device_instance *sdi;
955         struct la8 *la8;
956         struct sr_datafeed_packet packet;
957
958         sr_dbg("la8: stopping acquisition");
959
960         if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
961                 sr_warn("la8: %s: sdi was NULL", __func__);
962                 return;
963         }
964
965         if (!(la8 = sdi->priv)) {
966                 sr_warn("la8: %s: sdi->priv was NULL", __func__);
967                 return;
968         }
969
970         /* Reset the LA8 sequencer and close the device. */
971         (void) la8_close_usb_reset_sequencer(la8); /* Ignore errors. */
972
973         /* Send end packet to the session bus. */
974         sr_dbg("la8: %s: sending SR_DF_END", __func__);
975         packet.type = SR_DF_END;
976         packet.length = 0;
977         packet.unitsize = 0;
978         packet.payload = NULL;
979         sr_session_bus(session_device_id, &packet);
980 }
981
982 struct sr_device_plugin chronovu_la8_plugin_info = {
983         .name = "chronovu-la8",
984         .longname = "ChronoVu LA8",
985         .api_version = 1,
986         .init = hw_init,
987         .cleanup = hw_cleanup,
988         .open = hw_opendev,
989         .close = hw_closedev,
990         .get_device_info = hw_get_device_info,
991         .get_status = hw_get_status,
992         .get_capabilities = hw_get_capabilities,
993         .set_configuration = hw_set_configuration,
994         .start_acquisition = hw_start_acquisition,
995         .stop_acquisition = hw_stop_acquisition,
996 };