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