]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
Add implementation for SCPI over TCP.
[libsigrok.git] / hardware / rigol-ds / api.c
CommitLineData
f4816ac6
ML
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
88e429c9 5 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
bafd4890 6 * Copyright (C) 2013 Mathias Grimmberger <mgri@zaphod.sax.de>
f4816ac6
ML
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
e0b7d23c
ML
22#include <fcntl.h>
23#include <unistd.h>
24#include <stdlib.h>
25#include <string.h>
f4816ac6
ML
26#include <glib.h>
27#include "libsigrok.h"
28#include "libsigrok-internal.h"
29#include "protocol.h"
30
ca55277c
ML
31static const int32_t hwopts[] = {
32 SR_CONF_CONN,
0dc7b43e 33 SR_CONF_SERIALCOMM
ca55277c
ML
34};
35
f6a0ac9f 36static const int32_t hwcaps[] = {
1953564a 37 SR_CONF_OSCILLOSCOPE,
1953564a
BV
38 SR_CONF_TIMEBASE,
39 SR_CONF_TRIGGER_SOURCE,
40 SR_CONF_TRIGGER_SLOPE,
41 SR_CONF_HORIZ_TRIGGERPOS,
d62d7ad1 42 SR_CONF_NUM_TIMEBASE,
f48e0249
ML
43};
44
45static const int32_t analog_hwcaps[] = {
d62d7ad1 46 SR_CONF_NUM_VDIV,
f48e0249 47 SR_CONF_VDIV,
78bcc55a 48 SR_CONF_COUPLING,
babab622 49 SR_CONF_DATA_SOURCE,
e0b7d23c
ML
50};
51
f6a0ac9f 52static const uint64_t timebases[][2] = {
e0b7d23c
ML
53 /* nanoseconds */
54 { 2, 1000000000 },
55 { 5, 1000000000 },
56 { 10, 1000000000 },
57 { 20, 1000000000 },
58 { 50, 1000000000 },
59 { 100, 1000000000 },
60 { 500, 1000000000 },
61 /* microseconds */
62 { 1, 1000000 },
63 { 2, 1000000 },
64 { 5, 1000000 },
65 { 10, 1000000 },
66 { 20, 1000000 },
67 { 50, 1000000 },
68 { 100, 1000000 },
69 { 200, 1000000 },
70 { 500, 1000000 },
71 /* milliseconds */
72 { 1, 1000 },
73 { 2, 1000 },
74 { 5, 1000 },
75 { 10, 1000 },
76 { 20, 1000 },
77 { 50, 1000 },
78 { 100, 1000 },
79 { 200, 1000 },
80 { 500, 1000 },
81 /* seconds */
82 { 1, 1 },
83 { 2, 1 },
84 { 5, 1 },
85 { 10, 1 },
86 { 20, 1 },
87 { 50, 1 },
bafd4890
ML
88 { 100, 1 },
89 { 200, 1 },
90 { 500, 1 },
91 /* { 1000, 1 }, Confuses other code? */
e0b7d23c
ML
92};
93
f6a0ac9f 94static const uint64_t vdivs[][2] = {
bafd4890
ML
95 /* microvolts */
96 { 500, 1000000 },
e0b7d23c 97 /* millivolts */
bafd4890 98 { 1, 1000 },
e0b7d23c
ML
99 { 2, 1000 },
100 { 5, 1000 },
101 { 10, 1000 },
102 { 20, 1000 },
103 { 50, 1000 },
104 { 100, 1000 },
105 { 200, 1000 },
106 { 500, 1000 },
107 /* volts */
108 { 1, 1 },
109 { 2, 1 },
110 { 5, 1 },
111 { 10, 1 },
e0b7d23c
ML
112};
113
bafd4890
ML
114#define NUM_TIMEBASE ARRAY_SIZE(timebases)
115#define NUM_VDIV ARRAY_SIZE(vdivs)
116
e0b7d23c
ML
117static const char *trigger_sources[] = {
118 "CH1",
119 "CH2",
120 "EXT",
121 "AC Line",
6bb192bc
ML
122 "D0",
123 "D1",
124 "D2",
125 "D3",
126 "D4",
127 "D5",
128 "D6",
129 "D7",
130 "D8",
131 "D9",
132 "D10",
133 "D11",
134 "D12",
135 "D13",
136 "D14",
137 "D15",
e0b7d23c
ML
138};
139
140static const char *coupling[] = {
141 "AC",
142 "DC",
143 "GND",
e0b7d23c
ML
144};
145
babab622
ML
146/* Do not change the order of entries */
147static const char *data_sources[] = {
148 "Live",
149 "Memory",
150 "Segmented",
151};
152
153/*
154 * name, series, protocol flavor, min timebase, max timebase, min vdiv,
155 * digital channels, number of horizontal divs
156 */
bafd4890 157static const struct rigol_ds_model supported_models[] = {
babab622
ML
158 {"DS1052E", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, false, 12},
159 {"DS1102E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, false, 12},
160 {"DS1152E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, false, 12},
161 {"DS1052D", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, true, 12},
162 {"DS1102D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, true, 12},
163 {"DS1152D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, true, 12},
164 {"DS2072", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, false, 14},
165 {"DS2102", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, false, 14},
166 {"DS2202", RIGOL_DS2000, PROTOCOL_IEEE488_2, {2, 1000000000}, {500, 1}, {500, 1000000}, false, 14},
512bb890
BV
167};
168
3086efdd
ML
169SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
170static struct sr_dev_driver *di = &rigol_ds_driver_info;
f4816ac6 171
fa85f376 172static void clear_helper(void *priv)
f4816ac6 173{
f4816ac6 174 struct dev_context *devc;
f4816ac6 175
ba358ffd 176 devc = priv;
babab622
ML
177 g_free(devc->data);
178 g_free(devc->buffer);
fa85f376
UH
179 g_free(devc->coupling[0]);
180 g_free(devc->coupling[1]);
181 g_free(devc->trigger_source);
182 g_free(devc->trigger_slope);
ba358ffd
BV
183 g_slist_free(devc->analog_groups[0].probes);
184 g_slist_free(devc->analog_groups[1].probes);
185 g_slist_free(devc->digital_group.probes);
fa85f376 186}
f4816ac6 187
3b412e3a 188static int dev_clear(void)
fa85f376
UH
189{
190 return std_dev_clear(di, clear_helper);
f4816ac6
ML
191}
192
254dd102
BV
193static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
194{
254dd102 195 va_list args;
4d7a9a14 196 int ret;
254dd102 197
254dd102 198 va_start(args, format);
4d7a9a14 199 ret = sr_scpi_send_variadic(sdi->conn, format, args);
254dd102 200 va_end(args);
4d7a9a14
ML
201
202 if (ret != SR_OK)
254dd102
BV
203 return SR_ERR;
204
205 /* When setting a bunch of parameters in a row, the DS1052E scrambles
206 * some of them unless there is at least 100ms delay in between. */
8f35be72 207 sr_spew("delay %dms", 100);
e31d410d 208 g_usleep(100000);
254dd102
BV
209
210 return SR_OK;
211}
212
6078d2c9 213static int init(struct sr_context *sr_ctx)
f4816ac6 214{
f6beaac5 215 return std_init(sr_ctx, di, LOG_PREFIX);
f4816ac6
ML
216}
217
0dc7b43e 218static int probe_port(const char *port, const char *serialcomm, GSList **devices)
f4816ac6 219{
cc9fd2d2
BV
220 struct dev_context *devc;
221 struct sr_dev_inst *sdi;
0dc7b43e 222 const char *usbtmc_prefix = "/dev/usbtmc";
ae1bc1cc
ML
223 struct sr_scpi_dev_inst *scpi;
224 struct sr_scpi_hw_info *hw_info;
cc9fd2d2 225 struct sr_probe *probe;
f6a0ac9f 226 unsigned int i;
bafd4890 227 const struct rigol_ds_model *model = NULL;
ae1bc1cc 228 gchar *channel_name;
fb6e5ba8 229
46a743c1 230 *devices = NULL;
0dc7b43e
ML
231
232
233 if (strncmp(port, usbtmc_prefix, strlen(usbtmc_prefix)) == 0) {
234 if (!(scpi = scpi_usbtmc_dev_inst_new(port)))
235 return SR_ERR_MALLOC;
236 } else {
237 if (!(scpi = scpi_serial_dev_inst_new(port, serialcomm)))
238 return SR_ERR_MALLOC;
239 }
9bd4c956 240
ae1bc1cc
ML
241 if (sr_scpi_open(scpi) != SR_OK) {
242 sr_scpi_free(scpi);
9bd4c956 243 return SR_ERR;
ae1bc1cc 244 };
9bd4c956 245
ae1bc1cc
ML
246 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
247 sr_info("Couldn't get IDN response.");
248 sr_scpi_close(scpi);
249 sr_scpi_free(scpi);
250 return SR_ERR;
ca55277c 251 }
e0b7d23c 252
ae1bc1cc
ML
253 if (strcasecmp(hw_info->manufacturer, "Rigol Technologies")) {
254 sr_scpi_hw_info_free(hw_info);
255 sr_scpi_free(scpi);
ca55277c
ML
256 return SR_ERR_NA;
257 }
fb6e5ba8 258
ca55277c 259 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
ae1bc1cc 260 if (!strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 261 model = &supported_models[i];
ca55277c 262 break;
fb6e5ba8 263 }
ca55277c 264 }
fb6e5ba8 265
bafd4890 266 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
ae1bc1cc
ML
267 hw_info->manufacturer, hw_info->model,
268 hw_info->firmware_version))) {
269 sr_scpi_hw_info_free(hw_info);
270 sr_scpi_free(scpi);
ca55277c
ML
271 return SR_ERR_NA;
272 }
fb6e5ba8 273
ae1bc1cc
ML
274 sr_scpi_hw_info_free(hw_info);
275
276 sdi->conn = scpi;
fb6e5ba8 277
cc9fd2d2 278 sdi->driver = di;
ae1bc1cc 279 sdi->inst_type = SR_INST_SCPI;
512bb890 280
cc9fd2d2 281 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
ca55277c 282 return SR_ERR_MALLOC;
ae1bc1cc 283
cc9fd2d2 284 devc->limit_frames = 0;
bafd4890 285 devc->model = model;
512bb890 286
ca55277c 287 for (i = 0; i < 2; i++) {
3d3a601e
ML
288 channel_name = (i == 0 ? "CH1" : "CH2");
289 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name)))
ca55277c
ML
290 return SR_ERR_MALLOC;
291 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
292 devc->analog_groups[i].name = channel_name;
293 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
294 sdi->probe_groups = g_slist_append(sdi->probe_groups,
295 &devc->analog_groups[i]);
ca55277c 296 }
512bb890 297
bafd4890 298 if (devc->model->has_digital) {
ca55277c
ML
299 for (i = 0; i < 16; i++) {
300 if (!(channel_name = g_strdup_printf("D%d", i)))
301 return SR_ERR_MALLOC;
302 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
303 g_free(channel_name);
304 if (!probe)
305 return SR_ERR_MALLOC;
306 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
307 devc->digital_group.probes = g_slist_append(
308 devc->digital_group.probes, probe);
512bb890 309 }
b3916147
ML
310 devc->digital_group.name = "LA";
311 sdi->probe_groups = g_slist_append(sdi->probe_groups,
312 &devc->digital_group);
ca55277c 313 }
bafd4890
ML
314
315 for (i = 0; i < NUM_TIMEBASE; i++) {
316 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
317 devc->timebases = &timebases[i];
318 if (!memcmp(&devc->model->max_timebase, &timebases[i], sizeof(uint64_t[2])))
319 devc->num_timebases = &timebases[i] - devc->timebases + 1;
320 }
321
322 for (i = 0; i < NUM_VDIV; i++) {
323 if (!memcmp(&devc->model->min_vdiv, &vdivs[i], sizeof(uint64_t[2]))) {
6ff1394e
ML
324 devc->vdivs = &vdivs[i];
325 devc->num_vdivs = NUM_VDIV - (&vdivs[i] - &vdivs[0]);
bafd4890
ML
326 }
327 }
328
babab622
ML
329 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
330 return SR_ERR_MALLOC;
331 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
332 return SR_ERR_MALLOC;
333
334 devc->data_source = DATA_SOURCE_LIVE;
335
cc9fd2d2
BV
336 sdi->priv = devc;
337
338 *devices = g_slist_append(NULL, sdi);
512bb890 339
ca55277c
ML
340 return SR_OK;
341}
512bb890 342
6078d2c9 343static GSList *scan(GSList *options)
ca55277c
ML
344{
345 struct drv_context *drvc;
ca55277c 346 struct sr_config *src;
cc9fd2d2 347 GSList *l, *devices;
ca55277c 348 GDir *dir;
ca55277c 349 int ret;
cc9fd2d2
BV
350 const gchar *dev_name;
351 gchar *port = NULL;
0dc7b43e 352 gchar *serialcomm = NULL;
fb6e5ba8 353
ca55277c 354 drvc = di->priv;
d2e0b1fa 355
ca55277c
ML
356 for (l = options; l; l = l->next) {
357 src = l->data;
0dc7b43e
ML
358 switch (src->key) {
359 case SR_CONF_CONN:
cc9fd2d2 360 port = (char *)g_variant_get_string(src->data, NULL);
ca55277c 361 break;
0dc7b43e
ML
362 case SR_CONF_SERIALCOMM:
363 serialcomm = (char *)g_variant_get_string(src->data, NULL);
364 break;
fb6e5ba8 365 }
ca55277c 366 }
fb6e5ba8 367
46a743c1 368 devices = NULL;
cc9fd2d2 369 if (port) {
0dc7b43e
ML
370 if (probe_port(port, serialcomm, &devices) == SR_ERR_MALLOC) {
371 g_free(port);
372 if (serialcomm)
373 g_free(serialcomm);
ca55277c 374 return NULL;
0dc7b43e 375 }
ca55277c 376 } else {
da970d24
BV
377 if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
378 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
379 return NULL;
ca55277c 380 while ((dev_name = g_dir_read_name(dir))) {
cc9fd2d2 381 if (strncmp(dev_name, "usbtmc", 6))
ca55277c 382 continue;
cc9fd2d2 383 port = g_strconcat("/dev/", dev_name, NULL);
0dc7b43e 384 ret = probe_port(port, serialcomm, &devices);
cc9fd2d2 385 g_free(port);
0dc7b43e
ML
386 if (serialcomm)
387 g_free(serialcomm);
ca55277c
ML
388 if (ret == SR_ERR_MALLOC) {
389 g_dir_close(dir);
ca55277c 390 return NULL;
6bb192bc
ML
391 }
392 }
ca55277c
ML
393 g_dir_close(dir);
394 }
f4816ac6 395
46a743c1
BV
396 /* Tack a copy of the newly found devices onto the driver list. */
397 l = g_slist_copy(devices);
398 drvc->instances = g_slist_concat(drvc->instances, l);
cc9fd2d2 399
f4816ac6
ML
400 return devices;
401}
402
6078d2c9 403static GSList *dev_list(void)
f4816ac6 404{
0e94d524 405 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
406}
407
6078d2c9 408static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 409{
ae1bc1cc 410 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 411
ae1bc1cc 412 if (sr_scpi_open(scpi) < 0)
e0b7d23c 413 return SR_ERR;
e0b7d23c 414
3086efdd 415 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 416 return SR_ERR;
f4816ac6 417
46a743c1 418 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 419
f4816ac6
ML
420 return SR_OK;
421}
422
6078d2c9 423static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 424{
ae1bc1cc
ML
425 struct sr_scpi_dev_inst *scpi;
426
427 scpi = sdi->conn;
e0b7d23c 428
ae1bc1cc
ML
429 if (scpi) {
430 if (sr_scpi_close(scpi) < 0)
431 return SR_ERR;
cc9fd2d2
BV
432 sdi->status = SR_ST_INACTIVE;
433 }
f4816ac6
ML
434
435 return SR_OK;
436}
437
6078d2c9 438static int cleanup(void)
f4816ac6 439{
3b412e3a 440 return dev_clear();
f4816ac6
ML
441}
442
8f996b89
ML
443static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
444 const struct sr_probe_group *probe_group)
d62d7ad1 445{
e43fdd8d 446 struct dev_context *devc;
f48e0249 447 unsigned int i;
d62d7ad1 448
e43fdd8d
BV
449 if (!sdi || !(devc = sdi->priv))
450 return SR_ERR_ARG;
451
be60a9e4
BV
452 /* If a probe group is specified, it must be a valid one. */
453 if (probe_group) {
454 if (probe_group != &devc->analog_groups[0]
455 && probe_group != &devc->analog_groups[1]) {
456 sr_err("Invalid probe group specified.");
457 return SR_ERR;
458 }
459 }
460
d62d7ad1
BV
461 switch (id) {
462 case SR_CONF_NUM_TIMEBASE:
bafd4890 463 *data = g_variant_new_int32(devc->num_timebases);
d62d7ad1
BV
464 break;
465 case SR_CONF_NUM_VDIV:
be60a9e4
BV
466 if (!probe_group) {
467 sr_err("No probe group specified.");
468 return SR_ERR_PROBE_GROUP;
469 }
f48e0249 470 for (i = 0; i < 2; i++) {
e43fdd8d 471 if (probe_group == &devc->analog_groups[i]) {
bafd4890 472 *data = g_variant_new_int32(devc->num_vdivs);
f48e0249
ML
473 return SR_OK;
474 }
475 }
476 return SR_ERR_NA;
babab622
ML
477 case SR_CONF_DATA_SOURCE:
478 if (devc->data_source == DATA_SOURCE_LIVE)
479 *data = g_variant_new_string("Live");
480 else if (devc->data_source == DATA_SOURCE_MEMORY)
481 *data = g_variant_new_string("Memory");
482 else
483 *data = g_variant_new_string("Segmented");
484 break;
d62d7ad1 485 default:
bd6fbf62 486 return SR_ERR_NA;
d62d7ad1
BV
487 }
488
489 return SR_OK;
490}
491
8f996b89
ML
492static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
493 const struct sr_probe_group *probe_group)
f4816ac6 494{
29d957ce 495 struct dev_context *devc;
f6a0ac9f 496 uint64_t tmp_u64, p, q;
254dd102 497 double t_dbl;
f48e0249 498 unsigned int i, j;
254dd102
BV
499 int ret;
500 const char *tmp_str;
f4816ac6 501
e43fdd8d
BV
502 if (!(devc = sdi->priv))
503 return SR_ERR_ARG;
29d957ce 504
e73ffd42
BV
505 if (sdi->status != SR_ST_ACTIVE)
506 return SR_ERR_DEV_CLOSED;
f4816ac6 507
be60a9e4
BV
508 /* If a probe group is specified, it must be a valid one. */
509 if (probe_group) {
510 if (probe_group != &devc->analog_groups[0]
511 && probe_group != &devc->analog_groups[1]) {
512 sr_err("Invalid probe group specified.");
513 return SR_ERR;
514 }
515 }
516
f4816ac6 517 ret = SR_OK;
035a1078 518 switch (id) {
1953564a 519 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 520 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 521 break;
1953564a 522 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 523 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
524 if (tmp_u64 != 0 && tmp_u64 != 1)
525 return SR_ERR;
526 g_free(devc->trigger_slope);
527 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
528 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 529 break;
1953564a 530 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
531 t_dbl = g_variant_get_double(data);
532 if (t_dbl < 0.0 || t_dbl > 1.0)
533 return SR_ERR;
534 devc->horiz_triggerpos = t_dbl;
535 /* We have the trigger offset as a percentage of the frame, but
536 * need to express this in seconds. */
bafd4890 537 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
254dd102 538 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 539 break;
1953564a 540 case SR_CONF_TIMEBASE:
f6a0ac9f 541 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
542 for (i = 0; i < devc->num_timebases; i++) {
543 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102
BV
544 devc->timebase = (float)p / q;
545 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
546 break;
547 }
548 }
bafd4890 549 if (i == devc->num_timebases)
254dd102 550 ret = SR_ERR_ARG;
e0b7d23c 551 break;
1953564a 552 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 553 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
554 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
555 if (!strcmp(trigger_sources[i], tmp_str)) {
556 g_free(devc->trigger_source);
557 devc->trigger_source = g_strdup(trigger_sources[i]);
558 if (!strcmp(devc->trigger_source, "AC Line"))
559 tmp_str = "ACL";
560 else if (!strcmp(devc->trigger_source, "CH1"))
561 tmp_str = "CHAN1";
562 else if (!strcmp(devc->trigger_source, "CH2"))
563 tmp_str = "CHAN2";
564 else
565 tmp_str = (char *)devc->trigger_source;
566 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
567 break;
568 }
4e108ace 569 }
254dd102
BV
570 if (i == ARRAY_SIZE(trigger_sources))
571 ret = SR_ERR_ARG;
e0b7d23c 572 break;
1953564a 573 case SR_CONF_VDIV:
be60a9e4
BV
574 if (!probe_group) {
575 sr_err("No probe group specified.");
576 return SR_ERR_PROBE_GROUP;
577 }
f6a0ac9f 578 g_variant_get(data, "(tt)", &p, &q);
f48e0249 579 for (i = 0; i < 2; i++) {
78bcc55a
BV
580 if (probe_group == &devc->analog_groups[i]) {
581 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
582 if (vdivs[j][0] != p || vdivs[j][1] != q)
583 continue;
584 devc->vdiv[i] = (float)p / q;
585 return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
586 devc->vdiv[i]);
587 }
588 return SR_ERR_ARG;
589 }
e0b7d23c 590 }
f48e0249 591 return SR_ERR_NA;
1953564a 592 case SR_CONF_COUPLING:
78bcc55a
BV
593 if (!probe_group) {
594 sr_err("No probe group specified.");
595 return SR_ERR_PROBE_GROUP;
596 }
f6a0ac9f 597 tmp_str = g_variant_get_string(data, NULL);
f48e0249 598 for (i = 0; i < 2; i++) {
78bcc55a
BV
599 if (probe_group == &devc->analog_groups[i]) {
600 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
601 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
602 g_free(devc->coupling[i]);
603 devc->coupling[i] = g_strdup(coupling[j]);
604 return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
605 devc->coupling[i]);
606 }
607 }
608 return SR_ERR_ARG;
e0b7d23c
ML
609 }
610 }
f48e0249 611 return SR_ERR_NA;
babab622
ML
612 case SR_CONF_DATA_SOURCE:
613 tmp_str = g_variant_get_string(data, NULL);
614 if (!strcmp(tmp_str, "Live"))
615 devc->data_source = DATA_SOURCE_LIVE;
616 else if (!strcmp(tmp_str, "Memory"))
617 devc->data_source = DATA_SOURCE_MEMORY;
618 else if (devc->model->protocol == PROTOCOL_IEEE488_2
619 && !strcmp(tmp_str, "Segmented"))
620 devc->data_source = DATA_SOURCE_SEGMENTED;
621 else
622 return SR_ERR;
623 break;
f4816ac6 624 default:
bd6fbf62 625 ret = SR_ERR_NA;
29d957ce 626 break;
f4816ac6
ML
627 }
628
629 return ret;
630}
631
8f996b89
ML
632static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
633 const struct sr_probe_group *probe_group)
a1c743fc 634{
861c447b
BV
635 GVariant *tuple, *rational[2];
636 GVariantBuilder gvb;
637 unsigned int i;
7cc1a550
ML
638 struct dev_context *devc = NULL;
639
640 if (sdi)
641 devc = sdi->priv;
8f996b89 642
e43fdd8d 643 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
644 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
645 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d
BV
646 return SR_OK;
647 } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
648 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
649 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
650 return SR_OK;
651 }
652
653 /* Every other option requires a valid device instance. */
654 if (!sdi || !(devc = sdi->priv))
655 return SR_ERR_ARG;
656
be60a9e4
BV
657 /* If a probe group is specified, it must be a valid one. */
658 if (probe_group) {
659 if (probe_group != &devc->analog_groups[0]
660 && probe_group != &devc->analog_groups[1]) {
661 sr_err("Invalid probe group specified.");
662 return SR_ERR;
663 }
664 }
665
e43fdd8d 666 switch (key) {
ca55277c 667 break;
9a6517d1 668 case SR_CONF_DEVICE_OPTIONS:
be60a9e4
BV
669 if (!probe_group) {
670 sr_err("No probe group specified.");
671 return SR_ERR_PROBE_GROUP;
672 }
e43fdd8d 673 if (probe_group == &devc->digital_group) {
f48e0249
ML
674 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
675 NULL, 0, sizeof(int32_t));
676 return SR_OK;
677 } else {
678 for (i = 0; i < 2; i++) {
679 if (probe_group == &devc->analog_groups[i]) {
680 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
681 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
682 return SR_OK;
683 }
684 }
685 return SR_ERR_NA;
686 }
5f77dffc 687 break;
2a7b113d 688 case SR_CONF_COUPLING:
be60a9e4
BV
689 if (!probe_group) {
690 sr_err("No probe group specified.");
691 return SR_ERR_PROBE_GROUP;
f48e0249 692 }
58f43369
BV
693 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
694 break;
e4f2b2ad 695 case SR_CONF_VDIV:
7cc1a550
ML
696 if (!devc)
697 /* Can't know this until we have the exact model. */
698 return SR_ERR_ARG;
be60a9e4
BV
699 if (!probe_group) {
700 sr_err("No probe group specified.");
701 return SR_ERR_PROBE_GROUP;
861c447b 702 }
58f43369 703 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
704 for (i = 0; i < devc->num_vdivs; i++) {
705 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
706 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
707 tuple = g_variant_new_tuple(rational, 2);
708 g_variant_builder_add_value(&gvb, tuple);
709 }
710 *data = g_variant_builder_end(&gvb);
711 break;
41f5bd09 712 case SR_CONF_TIMEBASE:
7cc1a550
ML
713 if (!devc)
714 /* Can't know this until we have the exact model. */
715 return SR_ERR_ARG;
861c447b 716 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
717 for (i = 0; i < devc->num_timebases; i++) {
718 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
719 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
720 tuple = g_variant_new_tuple(rational, 2);
721 g_variant_builder_add_value(&gvb, tuple);
722 }
723 *data = g_variant_builder_end(&gvb);
41f5bd09 724 break;
328bafab 725 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
726 if (!devc)
727 /* Can't know this until we have the exact model. */
728 return SR_ERR_ARG;
f6a0ac9f 729 *data = g_variant_new_strv(trigger_sources,
bafd4890 730 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 731 break;
babab622
ML
732 case SR_CONF_DATA_SOURCE:
733 if (!devc)
734 /* Can't know this until we have the exact model. */
735 return SR_ERR_ARG;
736 /* This needs tweaking by series/model! */
737 if (devc->model->series == RIGOL_DS2000)
738 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
739 else
740 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
741 break;
a1c743fc 742 default:
bd6fbf62 743 return SR_ERR_NA;
a1c743fc
BV
744 }
745
746 return SR_OK;
747}
748
254dd102 749static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 750{
ae1bc1cc 751 struct sr_scpi_dev_inst *scpi;
29d957ce 752 struct dev_context *devc;
254dd102
BV
753 struct sr_probe *probe;
754 GSList *l;
254dd102 755 char cmd[256];
29d957ce 756
e73ffd42
BV
757 if (sdi->status != SR_ST_ACTIVE)
758 return SR_ERR_DEV_CLOSED;
e0b7d23c 759
ae1bc1cc 760 scpi = sdi->conn;
29d957ce
UH
761 devc = sdi->priv;
762
babab622 763 if (devc->data_source == DATA_SOURCE_LIVE) {
17b5b202 764 if (sr_scpi_send(sdi->conn, ":RUN") != SR_OK)
babab622
ML
765 return SR_ERR;
766 } else if (devc->data_source == DATA_SOURCE_MEMORY) {
767 if (devc->model->series != RIGOL_DS2000) {
768 sr_err("Data source 'Memory' not supported for this device");
769 return SR_ERR;
770 }
771 } else if (devc->data_source == DATA_SOURCE_SEGMENTED) {
772 sr_err("Data source 'Segmented' not yet supported");
773 return SR_ERR;
774 }
775
254dd102
BV
776 for (l = sdi->probes; l; l = l->next) {
777 probe = l->data;
6bb192bc
ML
778 sr_dbg("handling probe %s", probe->name);
779 if (probe->type == SR_PROBE_ANALOG) {
780 if (probe->enabled)
781 devc->enabled_analog_probes = g_slist_append(
782 devc->enabled_analog_probes, probe);
783 if (probe->enabled != devc->analog_channels[probe->index]) {
784 /* Enabled channel is currently disabled, or vice versa. */
785 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
786 probe->enabled ? "ON" : "OFF");
17b5b202 787 if (sr_scpi_send(sdi->conn, cmd) != SR_OK)
6bb192bc
ML
788 return SR_ERR;
789 }
790 } else if (probe->type == SR_PROBE_LOGIC) {
791 if (probe->enabled)
792 devc->enabled_digital_probes = g_slist_append(
793 devc->enabled_digital_probes, probe);
794 if (probe->enabled != devc->digital_channels[probe->index]) {
795 /* Enabled channel is currently disabled, or vice versa. */
796 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
797 probe->enabled ? "ON" : "OFF");
17b5b202 798 if (sr_scpi_send(sdi->conn, cmd) != SR_OK)
6bb192bc
ML
799 return SR_ERR;
800 }
254dd102
BV
801 }
802 }
6bb192bc 803 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 804 return SR_ERR;
e0b7d23c 805
ae1bc1cc 806 sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
807
808 /* Send header packet to the session bus. */
29a27196 809 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 810
babab622 811 if (devc->model->protocol == PROTOCOL_LEGACY) {
bafd4890
ML
812 /* Fetch the first frame. */
813 if (devc->enabled_analog_probes) {
babab622 814 devc->analog_frame_size = DS1000_ANALOG_LIVE_WAVEFORM_SIZE;
bafd4890 815 devc->channel_frame = devc->enabled_analog_probes->data;
17b5b202 816 if (sr_scpi_send(sdi->conn, ":WAV:DATA? CHAN%d",
bafd4890
ML
817 devc->channel_frame->index + 1) != SR_OK)
818 return SR_ERR;
819 } else {
820 devc->channel_frame = devc->enabled_digital_probes->data;
17b5b202 821 if (sr_scpi_send(sdi->conn, ":WAV:DATA? DIG") != SR_OK)
bafd4890
ML
822 return SR_ERR;
823 }
824
825 devc->num_frame_bytes = 0;
6bb192bc 826 } else {
bafd4890 827 if (devc->enabled_analog_probes) {
babab622
ML
828 if (devc->data_source == DATA_SOURCE_MEMORY)
829 {
830 if (g_slist_length(devc->enabled_analog_probes) == 1)
831 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C;
832 else
833 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C;
834 /* Apparently for the DS2000 the memory
835 * depth can only be set in Running state -
836 * this matches the behaviour of the UI. */
17b5b202 837 if (sr_scpi_send(sdi->conn, ":RUN") != SR_OK)
babab622 838 return SR_ERR;
17b5b202 839 if (sr_scpi_send(sdi->conn, "ACQ:MDEP %d", devc->analog_frame_size) != SR_OK)
babab622 840 return SR_ERR;
17b5b202 841 if (sr_scpi_send(sdi->conn, ":STOP") != SR_OK)
babab622
ML
842 return SR_ERR;
843 } else
844 devc->analog_frame_size = DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
355de5a1 845 devc->channel_frame = devc->enabled_analog_probes->data;
babab622 846 if (rigol_ds_capture_start(sdi) != SR_OK)
bafd4890
ML
847 return SR_ERR;
848 }
6bb192bc 849 }
f4816ac6
ML
850
851 return SR_OK;
852}
853
254dd102 854static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 855{
29d957ce 856 struct dev_context *devc;
ae1bc1cc 857 struct sr_scpi_dev_inst *scpi;
29d957ce 858
f4816ac6
ML
859 (void)cb_data;
860
29d957ce
UH
861 devc = sdi->priv;
862
f4816ac6
ML
863 if (sdi->status != SR_ST_ACTIVE) {
864 sr_err("Device inactive, can't stop acquisition.");
865 return SR_ERR;
866 }
867
6bb192bc
ML
868 g_slist_free(devc->enabled_analog_probes);
869 g_slist_free(devc->enabled_digital_probes);
870 devc->enabled_analog_probes = NULL;
871 devc->enabled_digital_probes = NULL;
ae1bc1cc
ML
872 scpi = sdi->conn;
873 sr_scpi_source_remove(scpi);
f4816ac6
ML
874
875 return SR_OK;
876}
877
3086efdd
ML
878SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
879 .name = "rigol-ds",
880 .longname = "Rigol DS",
f4816ac6 881 .api_version = 1,
6078d2c9
UH
882 .init = init,
883 .cleanup = cleanup,
884 .scan = scan,
885 .dev_list = dev_list,
3b412e3a 886 .dev_clear = dev_clear,
d62d7ad1 887 .config_get = config_get,
035a1078 888 .config_set = config_set,
a1c743fc 889 .config_list = config_list,
6078d2c9
UH
890 .dev_open = dev_open,
891 .dev_close = dev_close,
254dd102
BV
892 .dev_acquisition_start = dev_acquisition_start,
893 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
894 .priv = NULL,
895};