]> sigrok.org Git - libsigrok.git/blame - hardware/asix-sigma/asix-sigma.c
demo: Cosmetics, constify.
[libsigrok.git] / hardware / asix-sigma / asix-sigma.c
CommitLineData
28a35d8a
HE
1/*
2 * This file is part of the sigrok project.
3 *
911f1834
UH
4 * Copyright (C) 2010 Håvard Espeland <gus@ping.uio.no>,
5 * Copyright (C) 2010 Martin Stensgård <mastensg@ping.uio.no>
6 * Copyright (C) 2010 Carl Henrik Lunde <chlunde@ping.uio.no>
28a35d8a
HE
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
911f1834
UH
22/*
23 * ASIX Sigma Logic Analyzer Driver
24 */
25
28a35d8a
HE
26#include <ftdi.h>
27#include <string.h>
28#include <zlib.h>
fefa1800 29#include <sigrok.h>
28a35d8a
HE
30#include "asix-sigma.h"
31
32#define USB_VENDOR 0xa600
33#define USB_PRODUCT 0xa000
34#define USB_DESCRIPTION "ASIX SIGMA"
35#define USB_VENDOR_NAME "ASIX"
36#define USB_MODEL_NAME "SIGMA"
37#define USB_MODEL_VERSION ""
ee492173 38#define TRIGGER_TYPES "rf10"
28a35d8a
HE
39
40static GSList *device_instances = NULL;
41
42// XXX These should be per device
43static struct ftdi_context ftdic;
f78898e9 44static uint64_t cur_samplerate = 0;
28a35d8a
HE
45static uint32_t limit_msec = 0;
46static struct timeval start_tv;
f6564c8d 47static int cur_firmware = -1;
f78898e9
HE
48static int num_probes = 0;
49static int samples_per_event = 0;
57bbf56b 50static int capture_ratio = 50;
c53d793f 51static struct sigma_trigger trigger;
6aac7737 52static struct sigma_state sigma;
ee492173 53
28a35d8a 54static uint64_t supported_samplerates[] = {
ed09fd07 55 KHZ(200),
edca2c5c 56 KHZ(250),
ed09fd07 57 KHZ(500),
edca2c5c 58 MHZ(1),
ed09fd07 59 MHZ(5),
edca2c5c
HE
60 MHZ(10),
61 MHZ(25),
e8397563
HE
62 MHZ(50),
63 MHZ(100),
28a35d8a
HE
64 MHZ(200),
65 0,
66};
67
68static struct samplerates samplerates = {
ed09fd07 69 KHZ(200),
28a35d8a
HE
70 MHZ(200),
71 0,
72 supported_samplerates,
73};
74
75static int capabilities[] = {
76 HWCAP_LOGIC_ANALYZER,
77 HWCAP_SAMPLERATE,
57bbf56b
HE
78 HWCAP_CAPTURE_RATIO,
79 HWCAP_PROBECONFIG,
28a35d8a 80
28a35d8a
HE
81 HWCAP_LIMIT_MSEC,
82 0,
83};
84
fefa1800
UH
85/* Force the FPGA to reboot. */
86static uint8_t suicide[] = {
87 0x84, 0x84, 0x88, 0x84, 0x88, 0x84, 0x88, 0x84,
88};
89
90/* Prepare to upload firmware (FPGA specific). */
91static uint8_t init[] = {
92 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
93};
94
95/* Initialize the logic analyzer mode. */
96static uint8_t logic_mode_start[] = {
97 0x00, 0x40, 0x0f, 0x25, 0x35, 0x40,
98 0x2a, 0x3a, 0x40, 0x03, 0x20, 0x38,
99};
100
eec5275e 101static const char *firmware_files[] = {
a8116d76
HE
102 "asix-sigma-50.fw", /* 50 MHz, supports 8 bit fractions */
103 "asix-sigma-100.fw", /* 100 MHz */
104 "asix-sigma-200.fw", /* 200 MHz */
ed09fd07 105 "asix-sigma-50sync.fw", /* Synchronous clock from pin */
a8116d76 106 "asix-sigma-phasor.fw", /* Frequency counter */
f6564c8d
HE
107};
108
6aac7737
HE
109static void hw_stop_acquisition(int device_index, gpointer session_device_id);
110
9ddb2a12 111static int sigma_read(void *buf, size_t size)
28a35d8a
HE
112{
113 int ret;
fefa1800
UH
114
115 ret = ftdi_read_data(&ftdic, (unsigned char *)buf, size);
28a35d8a
HE
116 if (ret < 0) {
117 g_warning("ftdi_read_data failed: %s",
fefa1800 118 ftdi_get_error_string(&ftdic));
28a35d8a
HE
119 }
120
121 return ret;
122}
123
fefa1800 124static int sigma_write(void *buf, size_t size)
28a35d8a
HE
125{
126 int ret;
fefa1800
UH
127
128 ret = ftdi_write_data(&ftdic, (unsigned char *)buf, size);
28a35d8a
HE
129 if (ret < 0) {
130 g_warning("ftdi_write_data failed: %s",
fefa1800
UH
131 ftdi_get_error_string(&ftdic));
132 } else if ((size_t) ret != size) {
28a35d8a
HE
133 g_warning("ftdi_write_data did not complete write\n");
134 }
135
136 return ret;
137}
138
139static int sigma_write_register(uint8_t reg, uint8_t *data, size_t len)
140{
141 size_t i;
142 uint8_t buf[len + 2];
143 int idx = 0;
144
145 buf[idx++] = REG_ADDR_LOW | (reg & 0xf);
146 buf[idx++] = REG_ADDR_HIGH | (reg >> 4);
147
fefa1800 148 for (i = 0; i < len; ++i) {
28a35d8a
HE
149 buf[idx++] = REG_DATA_LOW | (data[i] & 0xf);
150 buf[idx++] = REG_DATA_HIGH_WRITE | (data[i] >> 4);
151 }
152
153 return sigma_write(buf, idx);
154}
155
156static int sigma_set_register(uint8_t reg, uint8_t value)
157{
158 return sigma_write_register(reg, &value, 1);
159}
160
161static int sigma_read_register(uint8_t reg, uint8_t *data, size_t len)
162{
163 uint8_t buf[3];
fefa1800 164
28a35d8a
HE
165 buf[0] = REG_ADDR_LOW | (reg & 0xf);
166 buf[1] = REG_ADDR_HIGH | (reg >> 4);
28a35d8a
HE
167 buf[2] = REG_READ_ADDR;
168
169 sigma_write(buf, sizeof(buf));
170
171 return sigma_read(data, len);
172}
173
174static uint8_t sigma_get_register(uint8_t reg)
175{
176 uint8_t value;
fefa1800 177
28a35d8a
HE
178 if (1 != sigma_read_register(reg, &value, 1)) {
179 g_warning("Sigma_get_register: 1 byte expected");
180 return 0;
181 }
182
183 return value;
184}
185
186static int sigma_read_pos(uint32_t *stoppos, uint32_t *triggerpos)
187{
188 uint8_t buf[] = {
189 REG_ADDR_LOW | READ_TRIGGER_POS_LOW,
190
191 REG_READ_ADDR | NEXT_REG,
192 REG_READ_ADDR | NEXT_REG,
193 REG_READ_ADDR | NEXT_REG,
194 REG_READ_ADDR | NEXT_REG,
195 REG_READ_ADDR | NEXT_REG,
196 REG_READ_ADDR | NEXT_REG,
197 };
28a35d8a
HE
198 uint8_t result[6];
199
200 sigma_write(buf, sizeof(buf));
201
202 sigma_read(result, sizeof(result));
203
204 *triggerpos = result[0] | (result[1] << 8) | (result[2] << 16);
205 *stoppos = result[3] | (result[4] << 8) | (result[5] << 16);
206
57bbf56b
HE
207 /* Not really sure why this must be done, but according to spec. */
208 if ((--*stoppos & 0x1ff) == 0x1ff)
209 stoppos -= 64;
210
211 if ((*--triggerpos & 0x1ff) == 0x1ff)
212 triggerpos -= 64;
213
28a35d8a
HE
214 return 1;
215}
216
217static int sigma_read_dram(uint16_t startchunk, size_t numchunks, uint8_t *data)
218{
219 size_t i;
220 uint8_t buf[4096];
221 int idx = 0;
222
fefa1800 223 /* Send the startchunk. Index start with 1. */
28a35d8a
HE
224 buf[0] = startchunk >> 8;
225 buf[1] = startchunk & 0xff;
226 sigma_write_register(WRITE_MEMROW, buf, 2);
227
fefa1800 228 /* Read the DRAM. */
28a35d8a
HE
229 buf[idx++] = REG_DRAM_BLOCK;
230 buf[idx++] = REG_DRAM_WAIT_ACK;
231
232 for (i = 0; i < numchunks; ++i) {
fefa1800
UH
233 /* Alternate bit to copy from DRAM to cache. */
234 if (i != (numchunks - 1))
235 buf[idx++] = REG_DRAM_BLOCK | (((i + 1) % 2) << 4);
28a35d8a
HE
236
237 buf[idx++] = REG_DRAM_BLOCK_DATA | ((i % 2) << 4);
238
fefa1800 239 if (i != (numchunks - 1))
28a35d8a
HE
240 buf[idx++] = REG_DRAM_WAIT_ACK;
241 }
242
243 sigma_write(buf, idx);
244
245 return sigma_read(data, numchunks * CHUNK_SIZE);
246}
247
4ae1f451 248/* Upload trigger look-up tables to Sigma. */
ee492173
HE
249static int sigma_write_trigger_lut(struct triggerlut *lut)
250{
251 int i;
252 uint8_t tmp[2];
253 uint16_t bit;
254
255 /* Transpose the table and send to Sigma. */
256 for (i = 0; i < 16; ++i) {
257 bit = 1 << i;
258
259 tmp[0] = tmp[1] = 0;
260
261 if (lut->m2d[0] & bit)
262 tmp[0] |= 0x01;
263 if (lut->m2d[1] & bit)
264 tmp[0] |= 0x02;
265 if (lut->m2d[2] & bit)
266 tmp[0] |= 0x04;
267 if (lut->m2d[3] & bit)
268 tmp[0] |= 0x08;
269
270 if (lut->m3 & bit)
271 tmp[0] |= 0x10;
272 if (lut->m3s & bit)
273 tmp[0] |= 0x20;
274 if (lut->m4 & bit)
275 tmp[0] |= 0x40;
276
277 if (lut->m0d[0] & bit)
278 tmp[1] |= 0x01;
279 if (lut->m0d[1] & bit)
280 tmp[1] |= 0x02;
281 if (lut->m0d[2] & bit)
282 tmp[1] |= 0x04;
283 if (lut->m0d[3] & bit)
284 tmp[1] |= 0x08;
285
286 if (lut->m1d[0] & bit)
287 tmp[1] |= 0x10;
288 if (lut->m1d[1] & bit)
289 tmp[1] |= 0x20;
290 if (lut->m1d[2] & bit)
291 tmp[1] |= 0x40;
292 if (lut->m1d[3] & bit)
293 tmp[1] |= 0x80;
294
295 sigma_write_register(WRITE_TRIGGER_SELECT0, tmp, sizeof(tmp));
296 sigma_set_register(WRITE_TRIGGER_SELECT1, 0x30 | i);
297 }
298
299 /* Send the parameters */
300 sigma_write_register(WRITE_TRIGGER_SELECT0, (uint8_t *) &lut->params,
301 sizeof(lut->params));
302
303 return SIGROK_OK;
304}
305
fefa1800 306/* Generate the bitbang stream for programming the FPGA. */
28a35d8a 307static int bin2bitbang(const char *filename,
fefa1800 308 unsigned char **buf, size_t *buf_size)
28a35d8a 309{
fefa1800 310 FILE *f;
28a35d8a
HE
311 long file_size;
312 unsigned long offset = 0;
313 unsigned char *p;
314 uint8_t *compressed_buf, *firmware;
315 uLongf csize, fwsize;
316 const int buffer_size = 65536;
317 size_t i;
fefa1800
UH
318 int c, ret, bit, v;
319 uint32_t imm = 0x3f6df2ab;
28a35d8a 320
fefa1800 321 f = fopen(filename, "r");
28a35d8a
HE
322 if (!f) {
323 g_warning("fopen(\"%s\", \"r\")", filename);
324 return -1;
325 }
326
327 if (-1 == fseek(f, 0, SEEK_END)) {
328 g_warning("fseek on %s failed", filename);
329 fclose(f);
330 return -1;
331 }
332
333 file_size = ftell(f);
334
335 fseek(f, 0, SEEK_SET);
336
28a35d8a
HE
337 compressed_buf = g_malloc(file_size);
338 firmware = g_malloc(buffer_size);
339
340 if (!compressed_buf || !firmware) {
341 g_warning("Error allocating buffers");
342 return -1;
343 }
344
28a35d8a
HE
345 csize = 0;
346 while ((c = getc(f)) != EOF) {
347 imm = (imm + 0xa853753) % 177 + (imm * 0x8034052);
348 compressed_buf[csize++] = c ^ imm;
349 }
350 fclose(f);
351
352 fwsize = buffer_size;
353 ret = uncompress(firmware, &fwsize, compressed_buf, csize);
354 if (ret < 0) {
355 g_free(compressed_buf);
356 g_free(firmware);
357 g_warning("Could not unpack Sigma firmware. (Error %d)\n", ret);
358 return -1;
359 }
360
361 g_free(compressed_buf);
362
363 *buf_size = fwsize * 2 * 8;
364
fefa1800 365 *buf = p = (unsigned char *)g_malloc(*buf_size);
28a35d8a
HE
366
367 if (!p) {
368 g_warning("Error allocating buffers");
369 return -1;
370 }
371
372 for (i = 0; i < fwsize; ++i) {
28a35d8a 373 for (bit = 7; bit >= 0; --bit) {
fefa1800 374 v = firmware[i] & 1 << bit ? 0x40 : 0x00;
28a35d8a
HE
375 p[offset++] = v | 0x01;
376 p[offset++] = v;
377 }
378 }
379
380 g_free(firmware);
381
382 if (offset != *buf_size) {
383 g_free(*buf);
384 g_warning("Error reading firmware %s "
fefa1800
UH
385 "offset=%ld, file_size=%ld, buf_size=%zd\n",
386 filename, offset, file_size, *buf_size);
28a35d8a
HE
387
388 return -1;
389 }
390
391 return 0;
392}
393
394static int hw_init(char *deviceinfo)
395{
396 struct sigrok_device_instance *sdi;
397
398 deviceinfo = deviceinfo;
399
400 ftdi_init(&ftdic);
401
fefa1800
UH
402 /* Look for SIGMAs. */
403 if (ftdi_usb_open_desc(&ftdic, USB_VENDOR, USB_PRODUCT,
404 USB_DESCRIPTION, NULL) < 0)
28a35d8a
HE
405 return 0;
406
fefa1800 407 /* Register SIGMA device. */
28a35d8a
HE
408 sdi = sigrok_device_instance_new(0, ST_INITIALIZING,
409 USB_VENDOR_NAME, USB_MODEL_NAME, USB_MODEL_VERSION);
410 if (!sdi)
411 return 0;
412
413 device_instances = g_slist_append(device_instances, sdi);
414
fefa1800 415 /* We will open the device again when we need it. */
28a35d8a
HE
416 ftdi_usb_close(&ftdic);
417
418 return 1;
419}
420
f6564c8d 421static int upload_firmware(int firmware_idx)
28a35d8a
HE
422{
423 int ret;
424 unsigned char *buf;
425 unsigned char pins;
426 size_t buf_size;
28a35d8a 427 unsigned char result[32];
e8397563 428 char firmware_path[128];
28a35d8a 429
fefa1800 430 /* Make sure it's an ASIX SIGMA. */
28a35d8a
HE
431 if ((ret = ftdi_usb_open_desc(&ftdic,
432 USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) {
28a35d8a 433 g_warning("ftdi_usb_open failed: %s",
fefa1800 434 ftdi_get_error_string(&ftdic));
28a35d8a
HE
435 return 0;
436 }
437
438 if ((ret = ftdi_set_bitmode(&ftdic, 0xdf, BITMODE_BITBANG)) < 0) {
439 g_warning("ftdi_set_bitmode failed: %s",
fefa1800 440 ftdi_get_error_string(&ftdic));
28a35d8a
HE
441 return 0;
442 }
443
fefa1800 444 /* Four times the speed of sigmalogan - Works well. */
28a35d8a
HE
445 if ((ret = ftdi_set_baudrate(&ftdic, 750000)) < 0) {
446 g_warning("ftdi_set_baudrate failed: %s",
fefa1800 447 ftdi_get_error_string(&ftdic));
28a35d8a
HE
448 return 0;
449 }
450
fefa1800 451 /* Force the FPGA to reboot. */
28a35d8a
HE
452 sigma_write(suicide, sizeof(suicide));
453 sigma_write(suicide, sizeof(suicide));
454 sigma_write(suicide, sizeof(suicide));
455 sigma_write(suicide, sizeof(suicide));
456
fefa1800 457 /* Prepare to upload firmware (FPGA specific). */
28a35d8a
HE
458 sigma_write(init, sizeof(init));
459
460 ftdi_usb_purge_buffers(&ftdic);
461
fefa1800 462 /* Wait until the FPGA asserts INIT_B. */
28a35d8a
HE
463 while (1) {
464 ret = sigma_read(result, 1);
465 if (result[0] & 0x20)
466 break;
467 }
468
9ddb2a12 469 /* Prepare firmware. */
e8397563 470 snprintf(firmware_path, sizeof(firmware_path), "%s/%s", FIRMWARE_DIR,
f6564c8d
HE
471 firmware_files[firmware_idx]);
472
e8397563 473 if (-1 == bin2bitbang(firmware_path, &buf, &buf_size)) {
28a35d8a 474 g_warning("An error occured while reading the firmware: %s",
e8397563 475 firmware_path);
28a35d8a
HE
476 return SIGROK_ERR;
477 }
478
fefa1800 479 /* Upload firmare. */
28a35d8a
HE
480 sigma_write(buf, buf_size);
481
482 g_free(buf);
483
484 if ((ret = ftdi_set_bitmode(&ftdic, 0x00, BITMODE_RESET)) < 0) {
9ddb2a12 485 g_warning("ftdi_set_bitmode failed: %s",
fefa1800 486 ftdi_get_error_string(&ftdic));
28a35d8a
HE
487 return SIGROK_ERR;
488 }
489
490 ftdi_usb_purge_buffers(&ftdic);
491
fefa1800 492 /* Discard garbage. */
28a35d8a
HE
493 while (1 == sigma_read(&pins, 1))
494 ;
495
fefa1800 496 /* Initialize the logic analyzer mode. */
28a35d8a
HE
497 sigma_write(logic_mode_start, sizeof(logic_mode_start));
498
fefa1800 499 /* Expect a 3 byte reply. */
28a35d8a
HE
500 ret = sigma_read(result, 3);
501 if (ret != 3 ||
502 result[0] != 0xa6 || result[1] != 0x55 || result[2] != 0xaa) {
fefa1800 503 g_warning("Configuration failed. Invalid reply received.");
28a35d8a
HE
504 return SIGROK_ERR;
505 }
506
f6564c8d
HE
507 cur_firmware = firmware_idx;
508
509 return SIGROK_OK;
510}
511
512static int hw_opendev(int device_index)
513{
514 struct sigrok_device_instance *sdi;
515 int ret;
516
9ddb2a12 517 /* Make sure it's an ASIX SIGMA. */
f6564c8d
HE
518 if ((ret = ftdi_usb_open_desc(&ftdic,
519 USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) {
520
521 g_warning("ftdi_usb_open failed: %s",
522 ftdi_get_error_string(&ftdic));
523
524 return 0;
525 }
28a35d8a
HE
526
527 if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
528 return SIGROK_ERR;
529
530 sdi->status = ST_ACTIVE;
531
f6564c8d
HE
532 return SIGROK_OK;
533}
534
6aac7737
HE
535static int set_samplerate(struct sigrok_device_instance *sdi,
536 uint64_t samplerate)
f6564c8d 537{
e8397563 538 int i, ret;
f6564c8d
HE
539
540 sdi = sdi;
541
542 for (i = 0; supported_samplerates[i]; i++) {
543 if (supported_samplerates[i] == samplerate)
544 break;
545 }
546 if (supported_samplerates[i] == 0)
547 return SIGROK_ERR_SAMPLERATE;
548
e8397563
HE
549 if (samplerate <= MHZ(50)) {
550 ret = upload_firmware(0);
f78898e9 551 num_probes = 16;
e8397563 552 }
f78898e9 553 if (samplerate == MHZ(100)) {
e8397563 554 ret = upload_firmware(1);
f78898e9
HE
555 num_probes = 8;
556 }
557 else if (samplerate == MHZ(200)) {
e8397563 558 ret = upload_firmware(2);
f78898e9
HE
559 num_probes = 4;
560 }
f6564c8d 561
e8397563 562 cur_samplerate = samplerate;
f78898e9 563 samples_per_event = 16 / num_probes;
6aac7737 564 sigma.state = SIGMA_IDLE;
f6564c8d 565
28a35d8a
HE
566 g_message("Firmware uploaded");
567
e8397563 568 return ret;
28a35d8a
HE
569}
570
c53d793f
HE
571/*
572 * In 100 and 200 MHz mode, only a single pin rising/falling can be
573 * set as trigger. In other modes, two rising/falling triggers can be set,
574 * in addition to value/mask trigger for any number of probes.
575 *
576 * The Sigma supports complex triggers using boolean expressions, but this
577 * has not been implemented yet.
578 */
57bbf56b
HE
579static int configure_probes(GSList *probes)
580{
581 struct probe *probe;
582 GSList *l;
583 int trigger_set = 0;
a42aec7f 584 int probebit;
57bbf56b 585
c53d793f 586 memset(&trigger, 0, sizeof(struct sigma_trigger));
eec5275e 587
57bbf56b
HE
588 for (l = probes; l; l = l->next) {
589 probe = (struct probe *)l->data;
a42aec7f 590 probebit = 1 << (probe->index - 1);
57bbf56b
HE
591
592 if (!probe->enabled || !probe->trigger)
593 continue;
594
ee492173 595 if (cur_samplerate >= MHZ(100)) {
c53d793f 596 /* Fast trigger support. */
ee492173 597 if (trigger_set) {
6aac7737
HE
598 g_warning("Asix Sigma only supports a single "
599 "pin trigger in 100 and 200 "
600 "MHz mode.");
ee492173
HE
601 return SIGROK_ERR;
602 }
603 if (probe->trigger[0] == 'f')
a42aec7f 604 trigger.fallingmask |= probebit;
ee492173 605 else if (probe->trigger[0] == 'r')
a42aec7f 606 trigger.risingmask |= probebit;
ee492173
HE
607 else {
608 g_warning("Asix Sigma only supports "
609 "rising/falling trigger in 100 "
610 "and 200 MHz mode.");
611 return SIGROK_ERR;
612 }
57bbf56b 613
c53d793f 614 ++trigger_set;
ee492173 615 } else {
c53d793f
HE
616 /* Simple trigger support (event). */
617 if (probe->trigger[0] == '1') {
a42aec7f
HE
618 trigger.simplevalue |= probebit;
619 trigger.simplemask |= probebit;
c53d793f
HE
620 }
621 else if (probe->trigger[0] == '0') {
a42aec7f
HE
622 trigger.simplevalue &= ~probebit;
623 trigger.simplemask |= probebit;
c53d793f
HE
624 }
625 else if (probe->trigger[0] == 'f') {
a42aec7f 626 trigger.fallingmask |= probebit;
c53d793f
HE
627 ++trigger_set;
628 }
629 else if (probe->trigger[0] == 'r') {
a42aec7f 630 trigger.risingmask |= probebit;
c53d793f
HE
631 ++trigger_set;
632 }
ee492173 633
c53d793f
HE
634 if (trigger_set > 2) {
635 g_warning("Asix Sigma only supports 2 rising/"
636 "falling triggers.");
ee492173
HE
637 return SIGROK_ERR;
638 }
ee492173 639 }
57bbf56b
HE
640 }
641
642 return SIGROK_OK;
643}
644
28a35d8a
HE
645static void hw_closedev(int device_index)
646{
647 device_index = device_index;
648
649 ftdi_usb_close(&ftdic);
650}
651
28a35d8a
HE
652static void hw_cleanup(void)
653{
654}
655
28a35d8a
HE
656static void *hw_get_device_info(int device_index, int device_info_id)
657{
658 struct sigrok_device_instance *sdi;
659 void *info = NULL;
660
661 if (!(sdi = get_sigrok_device_instance(device_instances, device_index))) {
662 fprintf(stderr, "It's NULL.\n");
663 return NULL;
664 }
665
666 switch (device_info_id) {
667 case DI_INSTANCE:
668 info = sdi;
669 break;
670 case DI_NUM_PROBES:
edca2c5c 671 info = GINT_TO_POINTER(16);
28a35d8a
HE
672 break;
673 case DI_SAMPLERATES:
674 info = &samplerates;
675 break;
676 case DI_TRIGGER_TYPES:
57bbf56b 677 info = (char *)TRIGGER_TYPES;
28a35d8a
HE
678 break;
679 case DI_CUR_SAMPLERATE:
680 info = &cur_samplerate;
681 break;
682 }
683
684 return info;
685}
686
28a35d8a
HE
687static int hw_get_status(int device_index)
688{
689 struct sigrok_device_instance *sdi;
690
691 sdi = get_sigrok_device_instance(device_instances, device_index);
692 if (sdi)
693 return sdi->status;
694 else
695 return ST_NOT_FOUND;
696}
697
28a35d8a
HE
698static int *hw_get_capabilities(void)
699{
700 return capabilities;
701}
702
703static int hw_set_configuration(int device_index, int capability, void *value)
704{
705 struct sigrok_device_instance *sdi;
706 int ret;
f6564c8d 707
28a35d8a
HE
708 if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
709 return SIGROK_ERR;
710
711 if (capability == HWCAP_SAMPLERATE) {
f6564c8d 712 ret = set_samplerate(sdi, *(uint64_t*) value);
28a35d8a 713 } else if (capability == HWCAP_PROBECONFIG) {
57bbf56b 714 ret = configure_probes(value);
28a35d8a
HE
715 } else if (capability == HWCAP_LIMIT_MSEC) {
716 limit_msec = strtoull(value, NULL, 10);
717 ret = SIGROK_OK;
57bbf56b
HE
718 } else if (capability == HWCAP_CAPTURE_RATIO) {
719 capture_ratio = strtoull(value, NULL, 10);
720 ret = SIGROK_OK;
721 } else if (capability == HWCAP_PROBECONFIG) {
722 ret = configure_probes((GSList *) value);
28a35d8a
HE
723 } else {
724 ret = SIGROK_ERR;
725 }
726
727 return ret;
728}
729
36b1c8e6
HE
730/* Software trigger to determine exact trigger position. */
731static int get_trigger_offset(uint16_t *samples, uint16_t last_sample,
732 struct sigma_trigger *t)
733{
734 int i;
735
736 for (i = 0; i < 8; ++i) {
737 if (i > 0)
738 last_sample = samples[i-1];
739
740 /* Simple triggers. */
741 if ((samples[i] & t->simplemask) != t->simplevalue)
742 continue;
743
744 /* Rising edge. */
745 if ((last_sample & t->risingmask) != 0 || (samples[i] &
746 t->risingmask) != t->risingmask)
747 continue;
748
749 /* Falling edge. */
bdfc7a89
HE
750 if ((last_sample & t->fallingmask) != t->fallingmask ||
751 (samples[i] & t->fallingmask) != 0)
36b1c8e6
HE
752 continue;
753
754 break;
755 }
756
757 /* If we did not match, return original trigger pos. */
758 return i & 0x7;
759}
760
28a35d8a 761/*
fefa1800
UH
762 * Decode chunk of 1024 bytes, 64 clusters, 7 events per cluster.
763 * Each event is 20ns apart, and can contain multiple samples.
f78898e9
HE
764 *
765 * For 200 MHz, events contain 4 samples for each channel, spread 5 ns apart.
766 * For 100 MHz, events contain 2 samples for each channel, spread 10 ns apart.
767 * For 50 MHz and below, events contain one sample for each channel,
768 * spread 20 ns apart.
28a35d8a
HE
769 */
770static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
57bbf56b 771 uint16_t *lastsample, int triggerpos, void *user_data)
28a35d8a 772{
fefa1800 773 uint16_t tsdiff, ts;
f78898e9 774 uint16_t samples[65536 * samples_per_event];
28a35d8a 775 struct datafeed_packet packet;
f78898e9 776 int i, j, k, l, numpad, tosend;
fefa1800 777 size_t n = 0, sent = 0;
f78898e9 778 int clustersize = EVENTS_PER_CLUSTER * samples_per_event;
fefa1800 779 uint16_t *event;
f78898e9 780 uint16_t cur_sample;
57bbf56b 781 int triggerts = -1;
ee492173 782
4ae1f451 783 /* Check if trigger is in this chunk. */
ee492173
HE
784 if (triggerpos != -1) {
785 if (cur_samplerate <= MHZ(50))
36b1c8e6 786 triggerpos -= EVENTS_PER_CLUSTER - 1;
ee492173
HE
787
788 if (triggerpos < 0)
789 triggerpos = 0;
57bbf56b 790
ee492173
HE
791 /* Find in which cluster the trigger occured. */
792 triggerts = triggerpos / 7;
793 }
28a35d8a 794
eec5275e 795 /* For each ts. */
28a35d8a 796 for (i = 0; i < 64; ++i) {
fefa1800 797 ts = *(uint16_t *) &buf[i * 16];
28a35d8a
HE
798 tsdiff = ts - *lastts;
799 *lastts = ts;
800
fefa1800
UH
801 /* Pad last sample up to current point. */
802 numpad = tsdiff * samples_per_event - clustersize;
28a35d8a 803 if (numpad > 0) {
f78898e9
HE
804 for (j = 0; j < numpad; ++j)
805 samples[j] = *lastsample;
806
807 n = numpad;
28a35d8a
HE
808 }
809
57bbf56b
HE
810 /* Send samples between previous and this timestamp to sigrok. */
811 sent = 0;
812 while (sent < n) {
813 tosend = MIN(2048, n - sent);
814
4c046c6b 815 packet.type = DF_LOGIC;
57bbf56b 816 packet.length = tosend * sizeof(uint16_t);
4c046c6b 817 packet.unitsize = 2;
57bbf56b
HE
818 packet.payload = samples + sent;
819 session_bus(user_data, &packet);
28a35d8a 820
57bbf56b
HE
821 sent += tosend;
822 }
823 n = 0;
824
825 event = (uint16_t *) &buf[i * 16 + 2];
f78898e9
HE
826 cur_sample = 0;
827
828 /* For each event in cluster. */
28a35d8a 829 for (j = 0; j < 7; ++j) {
f78898e9
HE
830
831 /* For each sample in event. */
28a35d8a 832 for (k = 0; k < samples_per_event; ++k) {
f78898e9
HE
833 cur_sample = 0;
834
835 /* For each probe. */
836 for (l = 0; l < num_probes; ++l)
edca2c5c
HE
837 cur_sample |= (!!(event[j] & (1 << (l *
838 samples_per_event + k))))
839 << l;
f78898e9
HE
840
841 samples[n++] = cur_sample;
28a35d8a
HE
842 }
843 }
844
eec5275e 845 /* Send data up to trigger point (if triggered). */
fefa1800 846 sent = 0;
57bbf56b
HE
847 if (i == triggerts) {
848 /*
36b1c8e6
HE
849 * Trigger is not always accurate to sample because of
850 * pipeline delay. However, it always triggers before
851 * the actual event. We therefore look at the next
852 * samples to pinpoint the exact position of the trigger.
57bbf56b 853 */
bdfc7a89
HE
854 tosend = get_trigger_offset(samples, *lastsample,
855 &trigger);
57bbf56b
HE
856
857 if (tosend > 0) {
4c046c6b 858 packet.type = DF_LOGIC;
57bbf56b 859 packet.length = tosend * sizeof(uint16_t);
4c046c6b 860 packet.unitsize = 2;
57bbf56b
HE
861 packet.payload = samples;
862 session_bus(user_data, &packet);
863
864 sent += tosend;
865 }
28a35d8a 866
57bbf56b
HE
867 packet.type = DF_TRIGGER;
868 packet.length = 0;
869 packet.payload = 0;
28a35d8a 870 session_bus(user_data, &packet);
28a35d8a 871 }
57bbf56b 872
eec5275e 873 /* Send rest of the chunk to sigrok. */
57bbf56b
HE
874 tosend = n - sent;
875
4c046c6b 876 packet.type = DF_LOGIC;
57bbf56b 877 packet.length = tosend * sizeof(uint16_t);
4c046c6b 878 packet.unitsize = 2;
57bbf56b
HE
879 packet.payload = samples + sent;
880 session_bus(user_data, &packet);
ee492173
HE
881
882 *lastsample = samples[n - 1];
28a35d8a
HE
883 }
884
f78898e9 885 return SIGROK_OK;
28a35d8a
HE
886}
887
888static int receive_data(int fd, int revents, void *user_data)
889{
890 struct datafeed_packet packet;
28a35d8a
HE
891 const int chunks_per_read = 32;
892 unsigned char buf[chunks_per_read * CHUNK_SIZE];
6aac7737
HE
893 int bufsz, numchunks, i, newchunks;
894 uint32_t running_msec;
28a35d8a 895 struct timeval tv;
28a35d8a
HE
896
897 fd = fd;
898 revents = revents;
899
6aac7737 900 numchunks = sigma.stoppos / 512;
28a35d8a 901
6aac7737 902 if (sigma.state == SIGMA_IDLE)
28a35d8a
HE
903 return FALSE;
904
6aac7737 905 if (sigma.state == SIGMA_CAPTURE) {
28a35d8a 906
6aac7737
HE
907 /* Check if the timer has expired, or memory is full. */
908 gettimeofday(&tv, 0);
909 running_msec = (tv.tv_sec - start_tv.tv_sec) * 1000 +
910 (tv.tv_usec - start_tv.tv_usec) / 1000;
28a35d8a 911
6aac7737
HE
912 if (running_msec < limit_msec && numchunks < 32767)
913 return FALSE;
28a35d8a 914
6aac7737
HE
915 hw_stop_acquisition(-1, user_data);
916
917 return FALSE;
918
919 } else if (sigma.state == SIGMA_DOWNLOAD) {
920 if (sigma.chunks_downloaded >= numchunks) {
921 /* End of samples. */
922 packet.type = DF_END;
923 packet.length = 0;
924 session_bus(user_data, &packet);
925
926 sigma.state = SIGMA_IDLE;
f78898e9 927
6aac7737
HE
928 return TRUE;
929 }
930
931 newchunks = MIN(chunks_per_read,
932 numchunks - sigma.chunks_downloaded);
28a35d8a
HE
933
934 g_message("Downloading sample data: %.0f %%",
6aac7737 935 100.0 * sigma.chunks_downloaded / numchunks);
28a35d8a 936
6aac7737
HE
937 bufsz = sigma_read_dram(sigma.chunks_downloaded,
938 newchunks, buf);
28a35d8a 939
fefa1800 940 /* Find first ts. */
6aac7737
HE
941 if (sigma.chunks_downloaded == 0) {
942 sigma.lastts = *(uint16_t *) buf - 1;
943 sigma.lastsample = 0;
944 }
28a35d8a 945
fefa1800 946 /* Decode chunks and send them to sigrok. */
28a35d8a 947 for (i = 0; i < newchunks; ++i) {
6aac7737 948 if (sigma.chunks_downloaded + i == sigma.triggerchunk)
57bbf56b 949 decode_chunk_ts(buf + (i * CHUNK_SIZE),
6aac7737
HE
950 &sigma.lastts, &sigma.lastsample,
951 sigma.triggerpos & 0x1ff,
952 user_data);
57bbf56b
HE
953 else
954 decode_chunk_ts(buf + (i * CHUNK_SIZE),
6aac7737 955 &sigma.lastts, &sigma.lastsample,
57bbf56b 956 -1, user_data);
28a35d8a
HE
957 }
958
6aac7737 959 sigma.chunks_downloaded += newchunks;
28a35d8a
HE
960 }
961
28a35d8a
HE
962 return TRUE;
963}
964
c53d793f
HE
965/* Build a LUT entry used by the trigger functions. */
966static void build_lut_entry(uint16_t value, uint16_t mask, uint16_t *entry)
ee492173
HE
967{
968 int i, j, k, bit;
969
f758d074 970 /* For each quad probe. */
ee492173 971 for (i = 0; i < 4; ++i) {
c53d793f 972 entry[i] = 0xffff;
ee492173 973
f758d074 974 /* For each bit in LUT. */
ee492173
HE
975 for (j = 0; j < 16; ++j)
976
f758d074 977 /* For each probe in quad. */
ee492173
HE
978 for (k = 0; k < 4; ++k) {
979 bit = 1 << (i * 4 + k);
980
c53d793f
HE
981 /* Set bit in entry */
982 if ((mask & bit) &&
983 ((!(value & bit)) !=
4ae1f451 984 (!(j & (1 << k)))))
c53d793f 985 entry[i] &= ~(1 << j);
ee492173
HE
986 }
987 }
c53d793f 988}
ee492173 989
c53d793f
HE
990/* Add a logical function to LUT mask. */
991static void add_trigger_function(enum triggerop oper, enum triggerfunc func,
992 int index, int neg, uint16_t *mask)
993{
994 int i, j;
995 int x[2][2], tmp, a, b, aset, bset, rset;
996
997 memset(x, 0, 4 * sizeof(int));
998
999 /* Trigger detect condition. */
1000 switch (oper) {
1001 case OP_LEVEL:
1002 x[0][1] = 1;
1003 x[1][1] = 1;
1004 break;
1005 case OP_NOT:
1006 x[0][0] = 1;
1007 x[1][0] = 1;
1008 break;
1009 case OP_RISE:
1010 x[0][1] = 1;
1011 break;
1012 case OP_FALL:
1013 x[1][0] = 1;
1014 break;
1015 case OP_RISEFALL:
1016 x[0][1] = 1;
1017 x[1][0] = 1;
1018 break;
1019 case OP_NOTRISE:
1020 x[1][1] = 1;
1021 x[0][0] = 1;
1022 x[1][0] = 1;
1023 break;
1024 case OP_NOTFALL:
1025 x[1][1] = 1;
1026 x[0][0] = 1;
1027 x[0][1] = 1;
1028 break;
1029 case OP_NOTRISEFALL:
1030 x[1][1] = 1;
1031 x[0][0] = 1;
1032 break;
1033 }
1034
1035 /* Transpose if neg is set. */
1036 if (neg) {
1037 for (i = 0; i < 2; ++i)
1038 for (j = 0; j < 2; ++j) {
1039 tmp = x[i][j];
1040 x[i][j] = x[1-i][1-j];
1041 x[1-i][1-j] = tmp;
1042 }
1043 }
1044
1045 /* Update mask with function. */
1046 for (i = 0; i < 16; ++i) {
1047 a = (i >> (2 * index + 0)) & 1;
1048 b = (i >> (2 * index + 1)) & 1;
1049
1050 aset = (*mask >> i) & 1;
1051 bset = x[b][a];
1052
1053 if (func == FUNC_AND || func == FUNC_NAND)
1054 rset = aset & bset;
1055 else if (func == FUNC_OR || func == FUNC_NOR)
1056 rset = aset | bset;
1057 else if (func == FUNC_XOR || func == FUNC_NXOR)
1058 rset = aset ^ bset;
1059
1060 if (func == FUNC_NAND || func == FUNC_NOR || func == FUNC_NXOR)
1061 rset = !rset;
1062
1063 *mask &= ~(1 << i);
1064
1065 if (rset)
1066 *mask |= 1 << i;
1067 }
1068}
1069
1070/*
1071 * Build trigger LUTs used by 50 MHz and lower sample rates for supporting
1072 * simple pin change and state triggers. Only two transitions (rise/fall) can be
1073 * set at any time, but a full mask and value can be set (0/1).
1074 */
1075static int build_basic_trigger(struct triggerlut *lut)
1076{
1077 int i,j;
4ae1f451 1078 uint16_t masks[2] = { 0, 0 };
c53d793f
HE
1079
1080 memset(lut, 0, sizeof(struct triggerlut));
1081
1082 /* Contant for simple triggers. */
1083 lut->m4 = 0xa000;
1084
1085 /* Value/mask trigger support. */
1086 build_lut_entry(trigger.simplevalue, trigger.simplemask, lut->m2d);
1087
1088 /* Rise/fall trigger support. */
1089 for (i = 0, j = 0; i < 16; ++i) {
1090 if (trigger.risingmask & (1 << i) ||
1091 trigger.fallingmask & (1 << i))
1092 masks[j++] = 1 << i;
1093 }
1094
1095 build_lut_entry(masks[0], masks[0], lut->m0d);
1096 build_lut_entry(masks[1], masks[1], lut->m1d);
1097
1098 /* Add glue logic */
1099 if (masks[0] || masks[1]) {
1100 /* Transition trigger. */
1101 if (masks[0] & trigger.risingmask)
1102 add_trigger_function(OP_RISE, FUNC_OR, 0, 0, &lut->m3);
1103 if (masks[0] & trigger.fallingmask)
1104 add_trigger_function(OP_FALL, FUNC_OR, 0, 0, &lut->m3);
1105 if (masks[1] & trigger.risingmask)
1106 add_trigger_function(OP_RISE, FUNC_OR, 1, 0, &lut->m3);
1107 if (masks[1] & trigger.fallingmask)
1108 add_trigger_function(OP_FALL, FUNC_OR, 1, 0, &lut->m3);
1109 } else {
1110 /* Only value/mask trigger. */
1111 lut->m3 = 0xffff;
1112 }
ee492173 1113
c53d793f 1114 /* Triggertype: event. */
ee492173
HE
1115 lut->params.selres = 3;
1116
1117 return SIGROK_OK;
1118}
1119
28a35d8a
HE
1120static int hw_start_acquisition(int device_index, gpointer session_device_id)
1121{
1122 struct sigrok_device_instance *sdi;
1123 struct datafeed_packet packet;
1124 struct datafeed_header header;
9ddb2a12
UH
1125 struct clockselect_50 clockselect;
1126 int frac;
57bbf56b
HE
1127 uint8_t triggerselect;
1128 struct triggerinout triggerinout_conf;
ee492173 1129 struct triggerlut lut;
a42aec7f 1130 int triggerpin;
28a35d8a
HE
1131
1132 session_device_id = session_device_id;
1133
1134 if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
1135 return SIGROK_ERR;
1136
1137 device_index = device_index;
1138
ed09fd07 1139 /* If the samplerate has not been set, default to 50 MHz. */
9ddb2a12 1140 if (cur_firmware == -1)
ed09fd07 1141 set_samplerate(sdi, MHZ(50));
e8397563 1142
eec5275e 1143 /* Enter trigger programming mode. */
28a35d8a
HE
1144 sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20);
1145
eec5275e 1146 /* 100 and 200 MHz mode. */
57bbf56b
HE
1147 if (cur_samplerate >= MHZ(100)) {
1148 sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81);
1149
a42aec7f
HE
1150 /* Find which pin to trigger on from mask. */
1151 for (triggerpin = 0; triggerpin < 8; ++triggerpin)
1152 if ((trigger.risingmask | trigger.fallingmask) &
1153 (1 << triggerpin))
1154 break;
1155
1156 /* Set trigger pin and light LED on trigger. */
1157 triggerselect = (1 << LEDSEL1) | (triggerpin & 0x7);
1158
1159 /* Default rising edge. */
1160 if (trigger.fallingmask)
1161 triggerselect |= 1 << 3;
57bbf56b 1162
eec5275e 1163 /* All other modes. */
57bbf56b 1164 } else if (cur_samplerate <= MHZ(50)) {
ee492173
HE
1165 build_basic_trigger(&lut);
1166
1167 sigma_write_trigger_lut(&lut);
57bbf56b
HE
1168
1169 triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0);
1170 }
1171
eec5275e 1172 /* Setup trigger in and out pins to default values. */
57bbf56b
HE
1173 memset(&triggerinout_conf, 0, sizeof(struct triggerinout));
1174 triggerinout_conf.trgout_bytrigger = 1;
1175 triggerinout_conf.trgout_enable = 1;
1176
28a35d8a 1177 sigma_write_register(WRITE_TRIGGER_OPTION,
57bbf56b
HE
1178 (uint8_t *) &triggerinout_conf,
1179 sizeof(struct triggerinout));
28a35d8a 1180
eec5275e 1181 /* Go back to normal mode. */
57bbf56b 1182 sigma_set_register(WRITE_TRIGGER_SELECT1, triggerselect);
28a35d8a 1183
edca2c5c
HE
1184 /* Set clock select register. */
1185 if (cur_samplerate == MHZ(200))
1186 /* Enable 4 probes. */
1187 sigma_set_register(WRITE_CLOCK_SELECT, 0xf0);
1188 else if (cur_samplerate == MHZ(100))
1189 /* Enable 8 probes. */
1190 sigma_set_register(WRITE_CLOCK_SELECT, 0x00);
1191 else {
1192 /*
9ddb2a12 1193 * 50 MHz mode (or fraction thereof). Any fraction down to
eec5275e 1194 * 50 MHz / 256 can be used, but is not supported by sigrok API.
edca2c5c 1195 */
9ddb2a12 1196 frac = MHZ(50) / cur_samplerate - 1;
edca2c5c 1197
9ddb2a12
UH
1198 clockselect.async = 0;
1199 clockselect.fraction = frac;
1200 clockselect.disabled_probes = 0;
edca2c5c
HE
1201
1202 sigma_write_register(WRITE_CLOCK_SELECT,
9ddb2a12
UH
1203 (uint8_t *) &clockselect,
1204 sizeof(clockselect));
edca2c5c
HE
1205 }
1206
fefa1800 1207 /* Setup maximum post trigger time. */
11fc8d9d 1208 sigma_set_register(WRITE_POST_TRIGGER, (capture_ratio * 255) / 100);
28a35d8a 1209
eec5275e 1210 /* Start acqusition. */
28a35d8a
HE
1211 gettimeofday(&start_tv, 0);
1212 sigma_set_register(WRITE_MODE, 0x0d);
1213
28a35d8a
HE
1214 /* Send header packet to the session bus. */
1215 packet.type = DF_HEADER;
1216 packet.length = sizeof(struct datafeed_header);
1217 packet.payload = &header;
1218 header.feed_version = 1;
1219 gettimeofday(&header.starttime, NULL);
1220 header.samplerate = cur_samplerate;
1221 header.protocol_id = PROTO_RAW;
c2616fb9
DR
1222 header.num_logic_probes = num_probes;
1223 header.num_analog_probes = 0;
28a35d8a
HE
1224 session_bus(session_device_id, &packet);
1225
57bbf56b
HE
1226 /* Add capture source. */
1227 source_add(0, G_IO_IN, 10, receive_data, session_device_id);
1228
6aac7737
HE
1229 sigma.state = SIGMA_CAPTURE;
1230
28a35d8a
HE
1231 return SIGROK_OK;
1232}
1233
28a35d8a
HE
1234static void hw_stop_acquisition(int device_index, gpointer session_device_id)
1235{
6aac7737
HE
1236 uint8_t modestatus;
1237
28a35d8a
HE
1238 device_index = device_index;
1239 session_device_id = session_device_id;
1240
fefa1800 1241 /* Stop acquisition. */
28a35d8a
HE
1242 sigma_set_register(WRITE_MODE, 0x11);
1243
6aac7737
HE
1244 /* Set SDRAM Read Enable. */
1245 sigma_set_register(WRITE_MODE, 0x02);
1246
1247 /* Get the current position. */
1248 sigma_read_pos(&sigma.stoppos, &sigma.triggerpos);
1249
1250 /* Check if trigger has fired. */
1251 modestatus = sigma_get_register(READ_MODE);
1252 if (modestatus & 0x20) {
1253 sigma.triggerchunk = sigma.triggerpos / 512;
1254
1255 } else
1256 sigma.triggerchunk = -1;
1257
1258 sigma.chunks_downloaded = 0;
1259
1260 sigma.state = SIGMA_DOWNLOAD;
28a35d8a
HE
1261}
1262
28a35d8a
HE
1263struct device_plugin asix_sigma_plugin_info = {
1264 "asix-sigma",
1265 1,
1266 hw_init,
1267 hw_cleanup,
28a35d8a
HE
1268 hw_opendev,
1269 hw_closedev,
1270 hw_get_device_info,
1271 hw_get_status,
1272 hw_get_capabilities,
1273 hw_set_configuration,
1274 hw_start_acquisition,
9ddb2a12 1275 hw_stop_acquisition,
28a35d8a 1276};