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