]> sigrok.org Git - libsigrok.git/blame - src/hardware/kingst-la2016/api.c
kingst-la2016: reduce scope of a few more declarations
[libsigrok.git] / src / hardware / kingst-la2016 / api.c
CommitLineData
f2cd2deb
FS
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2020 Florian Schmidt <schmidt_florian@gmx.de>
5 * Copyright (C) 2013 Marcus Comstedt <marcus@mc.pp.se>
6 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
7 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
96dc954e
GS
23/*
24 * This driver implementation initially was derived from the
25 * src/hardware/saleae-logic16/ source code.
26 */
f2cd2deb
FS
27
28#include <config.h>
a7740b06 29
a7740b06 30#include <libsigrok/libsigrok.h>
f2cd2deb 31#include <string.h>
a7740b06 32
f2cd2deb
FS
33#include "libsigrok-internal.h"
34#include "protocol.h"
35
36static const uint32_t scanopts[] = {
37 SR_CONF_CONN,
38};
39
40static const uint32_t drvopts[] = {
41 SR_CONF_LOGIC_ANALYZER,
42};
43
44static const uint32_t devopts[] = {
45 /* TODO: SR_CONF_CONTINUOUS, */
46 SR_CONF_CONN | SR_CONF_GET,
47 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
a38f0f5e
GS
48 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
49 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
f2cd2deb
FS
50 SR_CONF_VOLTAGE_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
51 SR_CONF_LOGIC_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
52 SR_CONF_LOGIC_THRESHOLD_CUSTOM | SR_CONF_GET | SR_CONF_SET,
53 SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
54 SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
55};
56
57static const int32_t trigger_matches[] = {
58 SR_TRIGGER_ZERO,
59 SR_TRIGGER_ONE,
60 SR_TRIGGER_RISING,
61 SR_TRIGGER_FALLING,
62};
63
d466f61c 64static const char *channel_names_logic[] = {
da25c287
GS
65 "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7",
66 "CH8", "CH9", "CH10", "CH11", "CH12", "CH13", "CH14", "CH15",
d466f61c
GS
67 "CH16", "CH17", "CH18", "CH19", "CH20", "CH21", "CH22", "CH23",
68 "CH24", "CH25", "CH26", "CH27", "CH28", "CH29", "CH30", "CH31",
f2cd2deb
FS
69};
70
ea436ba7 71/*
330853ba 72 * The hardware uses a 100/200/500MHz base clock (model dependent) and
ea436ba7
GS
73 * a 16bit divider (common across all models). The range from 10kHz to
74 * 100/200/500MHz should be applicable to all devices. High rates may
75 * suffer from coarse resolution (e.g. in the "500MHz div 2" case) and
330853ba
GS
76 * may not provide the desired 1/2/5 steps. Fortunately this exclusively
77 * affects the 500MHz model where 250MHz is used instead of 200MHz and
78 * the 166MHz and 125MHz rates are not presented to users. Deep memory
79 * of these models and hardware compression reduce the necessity to let
80 * users pick from a huge list of possible rates.
81 *
ea436ba7
GS
82 */
83
330853ba
GS
84static const uint64_t rates_500mhz[] = {
85 SR_KHZ(10),
86 SR_KHZ(20),
87 SR_KHZ(50),
88 SR_KHZ(100),
89 SR_KHZ(200),
90 SR_KHZ(500),
91 SR_MHZ(1),
92 SR_MHZ(2),
93 SR_MHZ(5),
94 SR_MHZ(10),
95 SR_MHZ(20),
96 SR_MHZ(50),
97 SR_MHZ(100),
98 SR_MHZ(250),
99 SR_MHZ(500),
100};
101
102static const uint64_t rates_200mhz[] = {
ea436ba7 103 SR_KHZ(10),
f2cd2deb
FS
104 SR_KHZ(20),
105 SR_KHZ(50),
106 SR_KHZ(100),
107 SR_KHZ(200),
108 SR_KHZ(500),
109 SR_MHZ(1),
110 SR_MHZ(2),
f2cd2deb 111 SR_MHZ(5),
f2cd2deb
FS
112 SR_MHZ(10),
113 SR_MHZ(20),
114 SR_MHZ(50),
115 SR_MHZ(100),
116 SR_MHZ(200),
117};
118
330853ba 119static const uint64_t rates_100mhz[] = {
ea436ba7 120 SR_KHZ(10),
8b172e78
KG
121 SR_KHZ(20),
122 SR_KHZ(50),
123 SR_KHZ(100),
124 SR_KHZ(200),
125 SR_KHZ(500),
126 SR_MHZ(1),
127 SR_MHZ(2),
8b172e78 128 SR_MHZ(5),
8b172e78
KG
129 SR_MHZ(10),
130 SR_MHZ(20),
131 SR_MHZ(50),
132 SR_MHZ(100),
133};
134
f2cd2deb
FS
135static const float logic_threshold_value[] = {
136 1.58,
137 2.5,
138 1.165,
139 1.5,
140 1.25,
141 0.9,
142 0.75,
143 0.60,
144 0.45,
145};
146
147static const char *logic_threshold[] = {
148 "TTL 5V",
149 "CMOS 5V",
150 "CMOS 3.3V",
151 "CMOS 3.0V",
152 "CMOS 2.5V",
153 "CMOS 1.8V",
154 "CMOS 1.5V",
155 "CMOS 1.2V",
156 "CMOS 0.9V",
157 "USER",
158};
159
da2cb50d 160#define LOGIC_THRESHOLD_IDX_USER (ARRAY_SIZE(logic_threshold) - 1)
f2cd2deb 161
d466f61c
GS
162/* Convenience. Release an allocated devc from error paths. */
163static void kingst_la2016_free_devc(struct dev_context *devc)
164{
165 if (!devc)
166 return;
167 g_free(devc->mcu_firmware);
168 g_free(devc->fpga_bitstream);
169 g_free(devc);
170}
171
172/* Convenience. Release an allocated sdi from error paths. */
173static void kingst_la2016_free_sdi(struct sr_dev_inst *sdi)
174{
175 if (!sdi)
176 return;
177 g_free(sdi->vendor);
178 g_free(sdi->model);
179 g_free(sdi->version);
180 g_free(sdi->serial_num);
181 g_free(sdi->connection_id);
182 sr_usb_dev_inst_free(sdi->conn);
183 kingst_la2016_free_devc(sdi->priv);
184}
185
186/* Convenience. Open a USB device (including claiming an interface). */
187static int la2016_open_usb(struct sr_usb_dev_inst *usb,
188 libusb_device *dev, gboolean show_message)
189{
190 int ret;
191
192 ret = libusb_open(dev, &usb->devhdl);
193 if (ret != 0) {
194 if (show_message) {
195 sr_err("Cannot open device: %s.",
196 libusb_error_name(ret));
197 }
198 return SR_ERR_IO;
199 }
200
201 if (usb->address == 0xff) {
202 /*
203 * First encounter after firmware upload.
204 * Grab current address after enumeration.
205 */
206 usb->address = libusb_get_device_address(dev);
207 }
208
209 ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE);
210 if (ret == LIBUSB_ERROR_BUSY) {
211 sr_err("Cannot claim USB interface. Another program or driver using it?");
212 return SR_ERR_IO;
213 } else if (ret == LIBUSB_ERROR_NO_DEVICE) {
214 sr_err("Device has been disconnected.");
215 return SR_ERR_IO;
216 } else if (ret != 0) {
217 sr_err("Cannot claim USB interface: %s.",
218 libusb_error_name(ret));
219 return SR_ERR_IO;
220 }
221
222 return SR_OK;
223}
224
225/* Convenience. Close an opened USB device (and release the interface). */
226static void la2016_close_usb(struct sr_usb_dev_inst *usb)
227{
228
229 if (!usb)
230 return;
231
232 if (usb->devhdl) {
233 libusb_release_interface(usb->devhdl, USB_INTERFACE);
234 libusb_close(usb->devhdl);
235 usb->devhdl = NULL;
236 }
237}
238
239/* Communicate to an USB device to identify the Kingst LA model. */
240static int la2016_identify_read(struct sr_dev_inst *sdi,
241 struct sr_usb_dev_inst *usb, libusb_device *dev,
242 gboolean show_message)
243{
244 int ret;
245
246 ret = la2016_open_usb(usb, dev, show_message);
247 if (ret != SR_OK) {
248 if (show_message)
249 sr_err("Cannot communicate to MCU firmware.");
250 return ret;
251 }
6d53e949
GS
252
253 /*
254 * Also complete the hardware configuration (FPGA bitstream)
255 * when MCU firmware communication became operational. Either
256 * failure is considered fatal when probing for the device.
257 */
d466f61c 258 ret = la2016_identify_device(sdi, show_message);
6d53e949
GS
259 if (ret == SR_OK) {
260 ret = la2016_init_hardware(sdi);
261 }
262
d466f61c
GS
263 la2016_close_usb(usb);
264
265 return ret;
266}
267
268/* Find given conn_id in another USB enum. Identify Kingst LA model. */
269static int la2016_identify_enum(struct sr_dev_inst *sdi)
270{
271 struct sr_dev_driver *di;
272 struct drv_context *drvc;
273 struct sr_context *ctx;
274 libusb_device **devlist, *dev;
275 struct libusb_device_descriptor des;
276 int ret, id_ret;
277 size_t device_count, dev_idx;
278 char conn_id[64];
279
280 di = sdi->driver;
281 drvc = di->context;
282 ctx = drvc->sr_ctx;;
283
284 ret = libusb_get_device_list(ctx->libusb_ctx, &devlist);
285 if (ret < 0)
286 return SR_ERR_IO;
287 device_count = ret;
288 if (!device_count)
289 return SR_ERR_IO;
290 id_ret = SR_ERR_IO;
291 for (dev_idx = 0; dev_idx < device_count; dev_idx++) {
292 dev = devlist[dev_idx];
293 libusb_get_device_descriptor(dev, &des);
294 if (des.idVendor != LA2016_VID || des.idProduct != LA2016_PID)
295 continue;
296 if (des.iProduct != LA2016_IPRODUCT_INDEX)
297 continue;
298 ret = usb_get_port_path(dev, conn_id, sizeof(conn_id));
299 if (ret < 0)
300 continue;
301 if (strcmp(sdi->connection_id, conn_id) != 0)
302 continue;
303 id_ret = la2016_identify_read(sdi, sdi->conn, dev, FALSE);
304 break;
305 }
306 libusb_free_device_list(devlist, 1);
307
308 return id_ret;
309}
310
311/* Wait for a device to re-appear after firmware upload. */
312static int la2016_identify_wait(struct sr_dev_inst *sdi)
313{
314 struct dev_context *devc;
315 uint64_t reset_done, now, elapsed_ms;
316 int ret;
317
318 devc = sdi->priv;
319
320 sr_info("Waiting for device to reset after firmware upload.");
321 now = g_get_monotonic_time();
322 reset_done = devc->fw_uploaded + RENUM_GONE_DELAY_MS * 1000;
323 if (now < reset_done)
324 g_usleep(reset_done - now);
325 do {
326 now = g_get_monotonic_time();
327 elapsed_ms = (now - devc->fw_uploaded) / 1000;
328 sr_spew("Waited %" PRIu64 "ms.", elapsed_ms);
329 ret = la2016_identify_enum(sdi);
330 if (ret == SR_OK) {
331 devc->fw_uploaded = 0;
332 break;
333 }
334 g_usleep(RENUM_POLL_INTERVAL_MS * 1000);
335 } while (elapsed_ms < RENUM_CHECK_PERIOD_MS);
336 if (ret != SR_OK) {
337 sr_err("Device failed to re-enumerate.");
338 return ret;
339 }
340 sr_info("Device came back after %" PRIi64 "ms.", elapsed_ms);
341
342 return SR_OK;
343}
344
345/*
346 * Open given conn_id from another USB enum. Used by dev_open(). Similar
347 * to, and should be kept in sync with la2016_identify_enum().
348 */
349static int la2016_open_enum(struct sr_dev_inst *sdi)
350{
351 struct sr_dev_driver *di;
352 struct drv_context *drvc;
353 struct sr_context *ctx;
354 libusb_device **devlist, *dev;
355 struct libusb_device_descriptor des;
356 int ret, open_ret;
357 size_t device_count, dev_idx;
358 char conn_id[64];
359
360 di = sdi->driver;
361 drvc = di->context;
362 ctx = drvc->sr_ctx;;
363
364 ret = libusb_get_device_list(ctx->libusb_ctx, &devlist);
365 if (ret < 0)
366 return SR_ERR_IO;
367 device_count = ret;
368 if (!device_count)
369 return SR_ERR_IO;
370 open_ret = SR_ERR_IO;
371 for (dev_idx = 0; dev_idx < device_count; dev_idx++) {
372 dev = devlist[dev_idx];
373 libusb_get_device_descriptor(dev, &des);
374 if (des.idVendor != LA2016_VID || des.idProduct != LA2016_PID)
375 continue;
376 if (des.iProduct != LA2016_IPRODUCT_INDEX)
377 continue;
378 ret = usb_get_port_path(dev, conn_id, sizeof(conn_id));
379 if (ret < 0)
380 continue;
381 if (strcmp(sdi->connection_id, conn_id) != 0)
382 continue;
383 open_ret = la2016_open_usb(sdi->conn, dev, TRUE);
384 break;
385 }
386 libusb_free_device_list(devlist, 1);
387
388 return open_ret;
389}
390
f2cd2deb
FS
391static GSList *scan(struct sr_dev_driver *di, GSList *options)
392{
393 struct drv_context *drvc;
520a20e9 394 struct sr_context *ctx;
f2cd2deb
FS
395 struct dev_context *devc;
396 struct sr_dev_inst *sdi;
397 struct sr_usb_dev_inst *usb;
398 struct sr_config *src;
399 GSList *l;
d466f61c 400 GSList *devices, *found_devices, *renum_devices;
f2cd2deb
FS
401 GSList *conn_devices;
402 struct libusb_device_descriptor des;
520a20e9
GS
403 libusb_device **devlist, *dev;
404 size_t dev_count, dev_idx, ch_idx;
405 uint8_t bus, addr;
d466f61c 406 uint16_t pid;
f2cd2deb 407 const char *conn;
520a20e9 408 char conn_id[64];
520a20e9 409 int ret;
d466f61c 410 size_t ch_off, ch_max;
f2cd2deb
FS
411
412 drvc = di->context;
520a20e9 413 ctx = drvc->sr_ctx;;
f2cd2deb
FS
414
415 conn = NULL;
d466f61c 416 conn_devices = NULL;
f2cd2deb
FS
417 for (l = options; l; l = l->next) {
418 src = l->data;
419 switch (src->key) {
420 case SR_CONF_CONN:
421 conn = g_variant_get_string(src->data, NULL);
422 break;
423 }
424 }
425 if (conn)
520a20e9 426 conn_devices = sr_usb_find(ctx->libusb_ctx, conn);
d466f61c
GS
427 if (conn && !conn_devices) {
428 sr_err("Cannot find the specified connection '%s'.", conn);
429 return NULL;
430 }
f2cd2deb 431
d466f61c
GS
432 /*
433 * Find all LA2016 devices, optionally upload firmware to them.
434 * Defer completion of sdi/devc creation until all (selected)
435 * devices were found in a usable state, and their models got
436 * identified which affect their feature set. It appears that
437 * we cannot communicate to the device within the same USB enum
438 * cycle, needs another USB enumeration after firmware upload.
439 */
f2cd2deb 440 devices = NULL;
d466f61c
GS
441 found_devices = NULL;
442 renum_devices = NULL;
520a20e9
GS
443 ret = libusb_get_device_list(ctx->libusb_ctx, &devlist);
444 if (ret < 0) {
445 sr_err("Cannot get device list: %s.", libusb_error_name(ret));
446 return devices;
447 }
448 dev_count = ret;
449 for (dev_idx = 0; dev_idx < dev_count; dev_idx++) {
450 dev = devlist[dev_idx];
451 bus = libusb_get_bus_number(dev);
452 addr = libusb_get_device_address(dev);
d466f61c
GS
453
454 /* Filter by connection when externally specified. */
455 for (l = conn_devices; l; l = l->next) {
456 usb = l->data;
457 if (usb->bus == bus && usb->address == addr)
458 break;
459 }
460 if (conn_devices && !l) {
461 sr_spew("Bus %hhu, addr %hhu do not match specified filter.",
462 bus, addr);
463 continue;
f2cd2deb
FS
464 }
465
d466f61c 466 /* Check USB VID:PID. Get the connection string. */
520a20e9 467 libusb_get_device_descriptor(dev, &des);
d466f61c
GS
468 if (des.idVendor != LA2016_VID || des.idProduct != LA2016_PID)
469 continue;
470 pid = des.idProduct;
520a20e9
GS
471 ret = usb_get_port_path(dev, conn_id, sizeof(conn_id));
472 if (ret < 0)
f2cd2deb 473 continue;
d466f61c
GS
474 sr_dbg("USB enum found %04x:%04x at path %s, %d.%d.",
475 des.idVendor, des.idProduct, conn_id, bus, addr);
476 usb = sr_usb_dev_inst_new(bus, addr, NULL);
f2cd2deb 477
520a20e9 478 sdi = g_malloc0(sizeof(*sdi));
d466f61c 479 sdi->driver = di;
f2cd2deb 480 sdi->status = SR_ST_INITIALIZING;
d466f61c 481 sdi->inst_type = SR_INST_USB;
520a20e9 482 sdi->connection_id = g_strdup(conn_id);
d466f61c 483 sdi->conn = usb;
f2cd2deb 484
d466f61c
GS
485 devc = g_malloc0(sizeof(*devc));
486 sdi->priv = devc;
f2cd2deb 487
d466f61c
GS
488 /*
489 * Load MCU firmware if it is currently missing. Which
490 * makes the device disappear and renumerate in USB.
491 * We need to come back another time to communicate to
492 * this device.
493 */
494 devc->fw_uploaded = 0;
495 if (des.iProduct != LA2016_IPRODUCT_INDEX) {
496 sr_info("Uploading MCU firmware to '%s'.", conn_id);
497 ret = la2016_upload_firmware(sdi, ctx, dev, pid);
520a20e9 498 if (ret != SR_OK) {
91f73872 499 sr_err("MCU firmware upload failed.");
d466f61c 500 kingst_la2016_free_sdi(sdi);
f2cd2deb
FS
501 continue;
502 }
d466f61c
GS
503 devc->fw_uploaded = g_get_monotonic_time();
504 usb->address = 0xff;
505 renum_devices = g_slist_append(renum_devices, sdi);
506 continue;
f2cd2deb
FS
507 }
508
d466f61c
GS
509 /*
510 * Communicate to the MCU firmware to access EEPROM data
511 * which lets us identify the device type. Then stop, to
512 * share remaining sdi/devc creation with those devices
513 * which had their MCU firmware uploaded above and which
514 * get revisited later.
515 */
516 ret = la2016_identify_read(sdi, usb, dev, TRUE);
517 if (ret != SR_OK || !devc->model) {
518 sr_err("Unknown or unsupported device type.");
519 kingst_la2016_free_sdi(sdi);
520 continue;
521 }
522 found_devices = g_slist_append(found_devices, sdi);
523 }
524 libusb_free_device_list(devlist, 1);
525 g_slist_free_full(conn_devices, sr_usb_dev_inst_free_cb);
f2cd2deb 526
d466f61c
GS
527 /*
528 * Wait for devices to re-appear after firmware upload. Append
529 * the yet unidentified device to the list of found devices, or
530 * release the previously allocated sdi/devc.
531 */
532 for (l = renum_devices; l; l = l->next) {
533 sdi = l->data;
534 devc = sdi->priv;
535 ret = la2016_identify_wait(sdi);
536 if (ret != SR_OK || !devc->model) {
537 sr_dbg("Skipping unusable '%s'.", sdi->connection_id);
538 kingst_la2016_free_sdi(sdi);
539 continue;
520a20e9 540 }
d466f61c
GS
541 found_devices = g_slist_append(found_devices, sdi);
542 }
543 g_slist_free(renum_devices);
f2cd2deb 544
d466f61c
GS
545 /*
546 * All found devices got identified, their type is known here.
547 * Complete the sdi/devc creation. Assign default settings
548 * because the vendor firmware would not let us read back the
549 * previously written configuration.
550 */
551 for (l = found_devices; l; l = l->next) {
552 sdi = l->data;
553 devc = sdi->priv;
554
555 sdi->vendor = g_strdup("Kingst");
556 sdi->model = g_strdup(devc->model->name);
557 ch_off = 0;
558
559 /* Create the logic channels. */
560 ch_max = ARRAY_SIZE(channel_names_logic);
561 if (ch_max > devc->model->channel_count)
562 ch_max = devc->model->channel_count;
563 for (ch_idx = 0; ch_idx < ch_max; ch_idx++) {
564 sr_channel_new(sdi, ch_off,
565 SR_CHANNEL_LOGIC, TRUE,
566 channel_names_logic[ch_idx]);
567 ch_off++;
568 }
f2cd2deb 569
08a49848
GS
570 /*
571 * Ideally we'd get the previous configuration from the
572 * hardware, but this device is write-only. So we have
573 * to assign a fixed set of initial configuration values.
574 */
a38f0f5e 575 sr_sw_limits_init(&devc->sw_limits);
d8fbfcd9
GS
576 devc->sw_limits.limit_samples = 0;
577 devc->capture_ratio = 50;
578 devc->cur_samplerate = devc->model->samplerate;
f2cd2deb
FS
579 devc->threshold_voltage_idx = 0;
580 devc->threshold_voltage = logic_threshold_value[devc->threshold_voltage_idx];
08a49848
GS
581 if (ARRAY_SIZE(devc->pwm_setting) >= 1) {
582 devc->pwm_setting[0].enabled = FALSE;
583 devc->pwm_setting[0].freq = SR_KHZ(1);
584 devc->pwm_setting[0].duty = 50;
585 }
586 if (ARRAY_SIZE(devc->pwm_setting) >= 2) {
587 devc->pwm_setting[1].enabled = FALSE;
588 devc->pwm_setting[1].freq = SR_KHZ(100);
589 devc->pwm_setting[1].duty = 50;
590 }
f2cd2deb
FS
591
592 sdi->status = SR_ST_INACTIVE;
d466f61c 593 devices = g_slist_append(devices, sdi);
f2cd2deb 594 }
d466f61c 595 g_slist_free(found_devices);
f2cd2deb
FS
596
597 return std_scan_complete(di, devices);
598}
599
f2cd2deb
FS
600static int dev_open(struct sr_dev_inst *sdi)
601{
08a49848 602 struct dev_context *devc;
f2cd2deb 603 int ret;
08a49848
GS
604 size_t ch;
605
606 devc = sdi->priv;
f2cd2deb 607
d466f61c 608 ret = la2016_open_enum(sdi);
f2cd2deb 609 if (ret != SR_OK) {
91f73872 610 sr_err("Cannot open device.");
520a20e9 611 return ret;
f2cd2deb
FS
612 }
613
08a49848
GS
614 /* Send most recent PWM configuration to the device. */
615 for (ch = 0; ch < ARRAY_SIZE(devc->pwm_setting); ch++) {
616 ret = la2016_write_pwm_config(sdi, ch);
617 if (ret != SR_OK)
618 return ret;
6d53e949
GS
619 }
620
f2cd2deb
FS
621 return SR_OK;
622}
623
624static int dev_close(struct sr_dev_inst *sdi)
625{
626 struct sr_usb_dev_inst *usb;
627
628 usb = sdi->conn;
629
630 if (!usb->devhdl)
631 return SR_ERR_BUG;
632
6d53e949 633 la2016_deinit_hardware(sdi);
f2cd2deb
FS
634
635 sr_info("Closing device on %d.%d (logical) / %s (physical) interface %d.",
636 usb->bus, usb->address, sdi->connection_id, USB_INTERFACE);
d466f61c 637 la2016_close_usb(sdi->conn);
f2cd2deb
FS
638
639 return SR_OK;
640}
641
955ab604
GS
642static int config_get(uint32_t key, GVariant **data,
643 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
f2cd2deb
FS
644{
645 struct dev_context *devc;
646 struct sr_usb_dev_inst *usb;
647 double rounded;
da2cb50d 648 const char *label;
f2cd2deb
FS
649
650 (void)cg;
651
652 if (!sdi)
653 return SR_ERR_ARG;
654 devc = sdi->priv;
655
656 switch (key) {
657 case SR_CONF_CONN:
658 if (!sdi->conn)
659 return SR_ERR_ARG;
660 usb = sdi->conn;
96dc954e
GS
661 if (usb->address == 0xff) {
662 /*
663 * Device still needs to re-enumerate after firmware
664 * upload, so we don't know its (future) address.
665 */
f2cd2deb 666 return SR_ERR;
955ab604 667 }
f2cd2deb
FS
668 *data = g_variant_new_printf("%d.%d", usb->bus, usb->address);
669 break;
670 case SR_CONF_SAMPLERATE:
671 *data = g_variant_new_uint64(devc->cur_samplerate);
672 break;
673 case SR_CONF_LIMIT_SAMPLES:
a38f0f5e
GS
674 case SR_CONF_LIMIT_MSEC:
675 return sr_sw_limits_config_get(&devc->sw_limits, key, data);
f2cd2deb
FS
676 case SR_CONF_CAPTURE_RATIO:
677 *data = g_variant_new_uint64(devc->capture_ratio);
678 break;
679 case SR_CONF_VOLTAGE_THRESHOLD:
680 rounded = (int)(devc->threshold_voltage / 0.1) * 0.1;
681 *data = std_gvar_tuple_double(rounded, rounded + 0.1);
682 return SR_OK;
683 case SR_CONF_LOGIC_THRESHOLD:
da2cb50d
GS
684 label = logic_threshold[devc->threshold_voltage_idx];
685 *data = g_variant_new_string(label);
f2cd2deb
FS
686 break;
687 case SR_CONF_LOGIC_THRESHOLD_CUSTOM:
688 *data = g_variant_new_double(devc->threshold_voltage);
689 break;
955ab604 690
f2cd2deb
FS
691 default:
692 return SR_ERR_NA;
693 }
694
695 return SR_OK;
696}
697
955ab604
GS
698static int config_set(uint32_t key, GVariant *data,
699 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
f2cd2deb
FS
700{
701 struct dev_context *devc;
702 double low, high;
703 int idx;
704
705 (void)cg;
706
707 devc = sdi->priv;
708
709 switch (key) {
710 case SR_CONF_SAMPLERATE:
711 devc->cur_samplerate = g_variant_get_uint64(data);
712 break;
713 case SR_CONF_LIMIT_SAMPLES:
a38f0f5e
GS
714 case SR_CONF_LIMIT_MSEC:
715 return sr_sw_limits_config_set(&devc->sw_limits, key, data);
f2cd2deb
FS
716 case SR_CONF_CAPTURE_RATIO:
717 devc->capture_ratio = g_variant_get_uint64(data);
718 break;
719 case SR_CONF_VOLTAGE_THRESHOLD:
720 g_variant_get(data, "(dd)", &low, &high);
721 devc->threshold_voltage = (low + high) / 2.0;
da2cb50d 722 devc->threshold_voltage_idx = LOGIC_THRESHOLD_IDX_USER;
f2cd2deb
FS
723 break;
724 case SR_CONF_LOGIC_THRESHOLD: {
411ad77c
GS
725 idx = std_str_idx(data, ARRAY_AND_SIZE(logic_threshold));
726 if (idx < 0)
f2cd2deb 727 return SR_ERR_ARG;
da2cb50d 728 if (idx != LOGIC_THRESHOLD_IDX_USER) {
f2cd2deb
FS
729 devc->threshold_voltage = logic_threshold_value[idx];
730 }
731 devc->threshold_voltage_idx = idx;
732 break;
733 }
734 case SR_CONF_LOGIC_THRESHOLD_CUSTOM:
735 devc->threshold_voltage = g_variant_get_double(data);
736 break;
737 default:
738 return SR_ERR_NA;
739 }
740
741 return SR_OK;
742}
743
955ab604
GS
744static int config_list(uint32_t key, GVariant **data,
745 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
f2cd2deb 746{
8b172e78
KG
747 struct dev_context *devc;
748
a38f0f5e
GS
749 devc = sdi ? sdi->priv : NULL;
750
f2cd2deb
FS
751 switch (key) {
752 case SR_CONF_SCAN_OPTIONS:
753 case SR_CONF_DEVICE_OPTIONS:
411ad77c
GS
754 return STD_CONFIG_LIST(key, data, sdi, cg,
755 scanopts, drvopts, devopts);
f2cd2deb 756 case SR_CONF_SAMPLERATE:
fb28e72d
MW
757 if (!sdi)
758 return SR_ERR_ARG;
d466f61c 759 if (devc->model->samplerate == SR_MHZ(500))
330853ba 760 *data = std_gvar_samplerates(ARRAY_AND_SIZE(rates_500mhz));
d466f61c 761 else if (devc->model->samplerate == SR_MHZ(200))
330853ba
GS
762 *data = std_gvar_samplerates(ARRAY_AND_SIZE(rates_200mhz));
763 else
764 *data = std_gvar_samplerates(ARRAY_AND_SIZE(rates_100mhz));
f2cd2deb
FS
765 break;
766 case SR_CONF_LIMIT_SAMPLES:
d8fbfcd9 767 *data = std_gvar_tuple_u64(0, LA2016_NUM_SAMPLES_MAX);
f2cd2deb
FS
768 break;
769 case SR_CONF_VOLTAGE_THRESHOLD:
770 *data = std_gvar_min_max_step_thresholds(
771 LA2016_THR_VOLTAGE_MIN,
772 LA2016_THR_VOLTAGE_MAX, 0.1);
773 break;
774 case SR_CONF_TRIGGER_MATCH:
775 *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
776 break;
777 case SR_CONF_LOGIC_THRESHOLD:
da2cb50d 778 *data = g_variant_new_strv(ARRAY_AND_SIZE(logic_threshold));
f2cd2deb
FS
779 break;
780 default:
781 return SR_ERR_NA;
782 }
783
784 return SR_OK;
785}
786
f2cd2deb
FS
787static int dev_acquisition_start(const struct sr_dev_inst *sdi)
788{
789 struct sr_dev_driver *di;
790 struct drv_context *drvc;
520a20e9 791 struct sr_context *ctx;
f2cd2deb
FS
792 struct dev_context *devc;
793 int ret;
794
795 di = sdi->driver;
796 drvc = di->context;
520a20e9 797 ctx = drvc->sr_ctx;;
f2cd2deb
FS
798 devc = sdi->priv;
799
a38f0f5e
GS
800 if (!devc->feed_queue) {
801 devc->feed_queue = feed_queue_logic_alloc(sdi,
802 LA2016_CONVBUFFER_SIZE, sizeof(uint16_t));
803 if (!devc->feed_queue) {
804 sr_err("Cannot allocate buffer for session feed.");
805 return SR_ERR_MALLOC;
806 }
f2cd2deb
FS
807 }
808
a38f0f5e
GS
809 sr_sw_limits_acquisition_start(&devc->sw_limits);
810
411ad77c
GS
811 ret = la2016_setup_acquisition(sdi);
812 if (ret != SR_OK) {
a38f0f5e
GS
813 feed_queue_logic_free(devc->feed_queue);
814 devc->feed_queue = NULL;
f2cd2deb
FS
815 return ret;
816 }
817
411ad77c
GS
818 ret = la2016_start_acquisition(sdi);
819 if (ret != SR_OK) {
3ebc1cb2 820 la2016_abort_acquisition(sdi);
a38f0f5e
GS
821 feed_queue_logic_free(devc->feed_queue);
822 devc->feed_queue = NULL;
f2cd2deb
FS
823 return ret;
824 }
825
cf057ac4 826 devc->completion_seen = FALSE;
520a20e9 827 usb_source_add(sdi->session, ctx, 50,
388438e4 828 la2016_receive_data, (void *)sdi);
f2cd2deb
FS
829
830 std_session_send_df_header(sdi);
831
832 return SR_OK;
833}
834
835static int dev_acquisition_stop(struct sr_dev_inst *sdi)
836{
837 int ret;
838
839 ret = la2016_abort_acquisition(sdi);
f2cd2deb
FS
840
841 return ret;
842}
843
844static struct sr_dev_driver kingst_la2016_driver_info = {
845 .name = "kingst-la2016",
846 .longname = "Kingst LA2016",
847 .api_version = 1,
848 .init = std_init,
849 .cleanup = std_cleanup,
850 .scan = scan,
851 .dev_list = std_dev_list,
852 .dev_clear = std_dev_clear,
853 .config_get = config_get,
854 .config_set = config_set,
855 .config_list = config_list,
856 .dev_open = dev_open,
857 .dev_close = dev_close,
858 .dev_acquisition_start = dev_acquisition_start,
859 .dev_acquisition_stop = dev_acquisition_stop,
860 .context = NULL,
861};
862SR_REGISTER_DEV_DRIVER(kingst_la2016_driver_info);