]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds1xx2/api.c
rigol-ds1xx2: Don't assume valid sdi
[libsigrok.git] / hardware / rigol-ds1xx2 / 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>
f4816ac6
ML
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
e0b7d23c
ML
21#include <fcntl.h>
22#include <unistd.h>
23#include <stdlib.h>
24#include <string.h>
f4816ac6
ML
25#include <glib.h>
26#include "libsigrok.h"
27#include "libsigrok-internal.h"
28#include "protocol.h"
29
d62d7ad1
BV
30#define NUM_TIMEBASE 12
31#define NUM_VDIV 8
32
ca55277c
ML
33static const int32_t hwopts[] = {
34 SR_CONF_CONN,
35};
36
f6a0ac9f 37static const int32_t hwcaps[] = {
1953564a 38 SR_CONF_OSCILLOSCOPE,
1953564a
BV
39 SR_CONF_TIMEBASE,
40 SR_CONF_TRIGGER_SOURCE,
41 SR_CONF_TRIGGER_SLOPE,
42 SR_CONF_HORIZ_TRIGGERPOS,
d62d7ad1 43 SR_CONF_NUM_TIMEBASE,
f48e0249
ML
44};
45
46static const int32_t analog_hwcaps[] = {
d62d7ad1 47 SR_CONF_NUM_VDIV,
f48e0249
ML
48 SR_CONF_VDIV,
49 SR_CONF_COUPLING
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 },
e0b7d23c
ML
88};
89
f6a0ac9f 90static const uint64_t vdivs[][2] = {
e0b7d23c
ML
91 /* millivolts */
92 { 2, 1000 },
93 { 5, 1000 },
94 { 10, 1000 },
95 { 20, 1000 },
96 { 50, 1000 },
97 { 100, 1000 },
98 { 200, 1000 },
99 { 500, 1000 },
100 /* volts */
101 { 1, 1 },
102 { 2, 1 },
103 { 5, 1 },
104 { 10, 1 },
e0b7d23c
ML
105};
106
107static const char *trigger_sources[] = {
108 "CH1",
109 "CH2",
110 "EXT",
111 "AC Line",
6bb192bc
ML
112 "D0",
113 "D1",
114 "D2",
115 "D3",
116 "D4",
117 "D5",
118 "D6",
119 "D7",
120 "D8",
121 "D9",
122 "D10",
123 "D11",
124 "D12",
125 "D13",
126 "D14",
127 "D15",
e0b7d23c
ML
128};
129
130static const char *coupling[] = {
131 "AC",
132 "DC",
133 "GND",
e0b7d23c
ML
134};
135
512bb890
BV
136static const char *supported_models[] = {
137 "DS1052E",
138 "DS1102E",
b775d753 139 "DS1152E",
512bb890 140 "DS1052D",
333bf022 141 "DS1102D",
b775d753 142 "DS1152D",
512bb890
BV
143};
144
f4816ac6
ML
145SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info;
146static struct sr_dev_driver *di = &rigol_ds1xx2_driver_info;
147
fa85f376 148static void clear_helper(void *priv)
f4816ac6 149{
f4816ac6 150 struct dev_context *devc;
f4816ac6 151
3d3a601e
ML
152 for (l = drvc->instances; l; l = l->next) {
153 if (!(sdi = l->data))
154 continue;
155
156 if (sdi->conn)
157 sr_serial_dev_inst_free(sdi->conn);
158
159 g_slist_free(sdi->probe_groups);
160
161 if (!(devc = sdi->priv))
162 continue;
163
3d3a601e
ML
164 g_free(devc->coupling[0]);
165 g_free(devc->coupling[1]);
166 g_free(devc->trigger_source);
167 g_free(devc->trigger_slope);
168 g_slist_free(devc->analog_groups[0].probes);
169 g_slist_free(devc->analog_groups[1].probes);
170 g_slist_free(devc->digital_group.probes);
3d3a601e
ML
171
172 sr_dev_inst_free(sdi);
173 }
f4816ac6 174
fa85f376
UH
175 g_free(devc->coupling[0]);
176 g_free(devc->coupling[1]);
177 g_free(devc->trigger_source);
178 g_free(devc->trigger_slope);
179}
f4816ac6 180
3b412e3a 181static int dev_clear(void)
fa85f376
UH
182{
183 return std_dev_clear(di, clear_helper);
f4816ac6
ML
184}
185
254dd102
BV
186static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
187{
254dd102
BV
188 va_list args;
189 char buf[256];
190
254dd102
BV
191 va_start(args, format);
192 vsnprintf(buf, 255, format, args);
193 va_end(args);
9bd4c956 194 if (rigol_ds1xx2_send(sdi, buf) != SR_OK)
254dd102
BV
195 return SR_ERR;
196
197 /* When setting a bunch of parameters in a row, the DS1052E scrambles
198 * some of them unless there is at least 100ms delay in between. */
8f35be72 199 sr_spew("delay %dms", 100);
e31d410d 200 g_usleep(100000);
254dd102
BV
201
202 return SR_OK;
203}
204
6078d2c9 205static int init(struct sr_context *sr_ctx)
f4816ac6 206{
f6beaac5 207 return std_init(sr_ctx, di, LOG_PREFIX);
f4816ac6
ML
208}
209
cc9fd2d2 210static int probe_port(const char *port, GSList **devices)
f4816ac6 211{
cc9fd2d2
BV
212 struct dev_context *devc;
213 struct sr_dev_inst *sdi;
9bd4c956 214 struct sr_serial_dev_inst *serial;
cc9fd2d2 215 struct sr_probe *probe;
f6a0ac9f 216 unsigned int i;
9bd4c956 217 int len, num_tokens;
cc9fd2d2 218 gboolean matched, has_digital;
512bb890 219 const char *manufacturer, *model, *version;
fb6e5ba8 220 char buf[256];
cc9fd2d2 221 gchar **tokens, *channel_name;
fb6e5ba8 222
46a743c1 223 *devices = NULL;
cc9fd2d2 224 if (!(serial = sr_serial_dev_inst_new(port, NULL)))
9bd4c956
ML
225 return SR_ERR_MALLOC;
226
227 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
228 return SR_ERR;
cc9fd2d2 229 len = serial_write(serial, "*IDN?", 5);
9bd4c956
ML
230 len = serial_read(serial, buf, sizeof(buf));
231 if (serial_close(serial) != SR_OK)
232 return SR_ERR;
233
234 sr_serial_dev_inst_free(serial);
235
ca55277c
ML
236 if (len == 0)
237 return SR_ERR_NA;
f4816ac6 238
ca55277c 239 buf[len] = 0;
cc9fd2d2
BV
240 tokens = g_strsplit(buf, ",", 0);
241 sr_dbg("response: %s [%s]", port, buf);
4b97c74e 242
ca55277c 243 for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
e0b7d23c 244
ca55277c
ML
245 if (num_tokens < 4) {
246 g_strfreev(tokens);
247 return SR_ERR_NA;
248 }
e0b7d23c 249
ca55277c
ML
250 manufacturer = tokens[0];
251 model = tokens[1];
252 version = tokens[3];
fb6e5ba8 253
ca55277c
ML
254 if (strcmp(manufacturer, "Rigol Technologies")) {
255 g_strfreev(tokens);
256 return SR_ERR_NA;
257 }
fb6e5ba8 258
46a743c1 259 matched = has_digital = FALSE;
ca55277c
ML
260 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
261 if (!strcmp(model, supported_models[i])) {
cc9fd2d2 262 matched = TRUE;
ca55277c
ML
263 has_digital = g_str_has_suffix(model, "D");
264 break;
fb6e5ba8 265 }
ca55277c 266 }
fb6e5ba8 267
ca55277c
ML
268 if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
269 manufacturer, model, version))) {
270 g_strfreev(tokens);
271 return SR_ERR_NA;
272 }
fb6e5ba8 273
ca55277c 274 g_strfreev(tokens);
fb6e5ba8 275
cc9fd2d2 276 if (!(sdi->conn = sr_serial_dev_inst_new(port, NULL)))
ca55277c 277 return SR_ERR_MALLOC;
cc9fd2d2 278 sdi->driver = di;
fa85f376 279 sdi->inst_type = SR_INST_SERIAL;
512bb890 280
cc9fd2d2 281 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
ca55277c 282 return SR_ERR_MALLOC;
cc9fd2d2 283 devc->limit_frames = 0;
ca55277c 284 devc->has_digital = has_digital;
512bb890 285
ca55277c 286 for (i = 0; i < 2; i++) {
3d3a601e
ML
287 channel_name = (i == 0 ? "CH1" : "CH2");
288 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name)))
ca55277c
ML
289 return SR_ERR_MALLOC;
290 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
291 devc->analog_groups[i].name = channel_name;
292 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
293 sdi->probe_groups = g_slist_append(sdi->probe_groups,
294 &devc->analog_groups[i]);
ca55277c 295 }
512bb890 296
ca55277c
ML
297 if (devc->has_digital) {
298 for (i = 0; i < 16; i++) {
299 if (!(channel_name = g_strdup_printf("D%d", i)))
300 return SR_ERR_MALLOC;
301 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
302 g_free(channel_name);
303 if (!probe)
304 return SR_ERR_MALLOC;
305 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
306 devc->digital_group.probes = g_slist_append(
307 devc->digital_group.probes, probe);
308 devc->digital_group.name = "LA";
309 sdi->probe_groups = g_slist_append(sdi->probe_groups,
310 &devc->digital_group);
512bb890 311 }
ca55277c 312 }
cc9fd2d2
BV
313 sdi->priv = devc;
314
315 *devices = g_slist_append(NULL, sdi);
512bb890 316
ca55277c
ML
317 return SR_OK;
318}
512bb890 319
6078d2c9 320static GSList *scan(GSList *options)
ca55277c
ML
321{
322 struct drv_context *drvc;
ca55277c 323 struct sr_config *src;
cc9fd2d2 324 GSList *l, *devices;
ca55277c 325 GDir *dir;
ca55277c 326 int ret;
cc9fd2d2
BV
327 const gchar *dev_name;
328 gchar *port = NULL;
fb6e5ba8 329
ca55277c 330 drvc = di->priv;
d2e0b1fa 331
ca55277c
ML
332 for (l = options; l; l = l->next) {
333 src = l->data;
334 if (src->key == SR_CONF_CONN) {
cc9fd2d2 335 port = (char *)g_variant_get_string(src->data, NULL);
ca55277c 336 break;
fb6e5ba8 337 }
ca55277c 338 }
fb6e5ba8 339
46a743c1 340 devices = NULL;
cc9fd2d2
BV
341 if (port) {
342 if (probe_port(port, &devices) == SR_ERR_MALLOC)
ca55277c 343 return NULL;
ca55277c 344 } else {
da970d24
BV
345 if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
346 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
347 return NULL;
ca55277c 348 while ((dev_name = g_dir_read_name(dir))) {
cc9fd2d2 349 if (strncmp(dev_name, "usbtmc", 6))
ca55277c 350 continue;
cc9fd2d2
BV
351 port = g_strconcat("/dev/", dev_name, NULL);
352 ret = probe_port(port, &devices);
353 g_free(port);
ca55277c
ML
354 if (ret == SR_ERR_MALLOC) {
355 g_dir_close(dir);
ca55277c 356 return NULL;
6bb192bc
ML
357 }
358 }
ca55277c
ML
359 g_dir_close(dir);
360 }
f4816ac6 361
46a743c1
BV
362 /* Tack a copy of the newly found devices onto the driver list. */
363 l = g_slist_copy(devices);
364 drvc->instances = g_slist_concat(drvc->instances, l);
cc9fd2d2 365
f4816ac6
ML
366 return devices;
367}
368
6078d2c9 369static GSList *dev_list(void)
f4816ac6 370{
0e94d524 371 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
372}
373
6078d2c9 374static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 375{
9bd4c956
ML
376
377 if (serial_open(sdi->conn, SERIAL_RDWR) != SR_OK)
e0b7d23c 378 return SR_ERR;
e0b7d23c 379
254dd102 380 if (rigol_ds1xx2_get_dev_cfg(sdi) != SR_OK)
254dd102 381 return SR_ERR;
f4816ac6 382
46a743c1 383 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 384
f4816ac6
ML
385 return SR_OK;
386}
387
6078d2c9 388static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 389{
cc9fd2d2 390 struct sr_serial_dev_inst *serial;
e0b7d23c 391
cc9fd2d2
BV
392 serial = sdi->conn;
393 if (serial && serial->fd != -1) {
394 serial_close(serial);
395 sdi->status = SR_ST_INACTIVE;
396 }
f4816ac6
ML
397
398 return SR_OK;
399}
400
6078d2c9 401static int cleanup(void)
f4816ac6 402{
3b412e3a 403 return dev_clear();
f4816ac6
ML
404}
405
8f996b89
ML
406static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
407 const struct sr_probe_group *probe_group)
d62d7ad1 408{
e43fdd8d 409 struct dev_context *devc;
f48e0249 410 unsigned int i;
d62d7ad1 411
e43fdd8d
BV
412 if (!sdi || !(devc = sdi->priv))
413 return SR_ERR_ARG;
414
d62d7ad1
BV
415 switch (id) {
416 case SR_CONF_NUM_TIMEBASE:
417 *data = g_variant_new_int32(NUM_TIMEBASE);
418 break;
419 case SR_CONF_NUM_VDIV:
f48e0249 420 for (i = 0; i < 2; i++) {
e43fdd8d 421 if (probe_group == &devc->analog_groups[i]) {
f48e0249
ML
422 *data = g_variant_new_int32(NUM_VDIV);
423 return SR_OK;
424 }
425 }
426 return SR_ERR_NA;
d62d7ad1 427 default:
bd6fbf62 428 return SR_ERR_NA;
d62d7ad1
BV
429 }
430
431 return SR_OK;
432}
433
8f996b89
ML
434static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
435 const struct sr_probe_group *probe_group)
f4816ac6 436{
29d957ce 437 struct dev_context *devc;
f6a0ac9f 438 uint64_t tmp_u64, p, q;
254dd102 439 double t_dbl;
f48e0249 440 unsigned int i, j;
254dd102
BV
441 int ret;
442 const char *tmp_str;
f4816ac6 443
e43fdd8d
BV
444 if (!(devc = sdi->priv))
445 return SR_ERR_ARG;
29d957ce 446
e73ffd42
BV
447 if (sdi->status != SR_ST_ACTIVE)
448 return SR_ERR_DEV_CLOSED;
f4816ac6
ML
449
450 ret = SR_OK;
035a1078 451 switch (id) {
1953564a 452 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 453 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 454 break;
1953564a 455 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 456 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
457 if (tmp_u64 != 0 && tmp_u64 != 1)
458 return SR_ERR;
459 g_free(devc->trigger_slope);
460 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
461 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 462 break;
1953564a 463 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
464 t_dbl = g_variant_get_double(data);
465 if (t_dbl < 0.0 || t_dbl > 1.0)
466 return SR_ERR;
467 devc->horiz_triggerpos = t_dbl;
468 /* We have the trigger offset as a percentage of the frame, but
469 * need to express this in seconds. */
470 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
471 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 472 break;
1953564a 473 case SR_CONF_TIMEBASE:
f6a0ac9f 474 g_variant_get(data, "(tt)", &p, &q);
f6a0ac9f
BV
475 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
476 if (timebases[i][0] == p && timebases[i][1] == q) {
254dd102
BV
477 devc->timebase = (float)p / q;
478 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
479 break;
480 }
481 }
254dd102
BV
482 if (i == ARRAY_SIZE(timebases))
483 ret = SR_ERR_ARG;
e0b7d23c 484 break;
1953564a 485 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 486 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
487 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
488 if (!strcmp(trigger_sources[i], tmp_str)) {
489 g_free(devc->trigger_source);
490 devc->trigger_source = g_strdup(trigger_sources[i]);
491 if (!strcmp(devc->trigger_source, "AC Line"))
492 tmp_str = "ACL";
493 else if (!strcmp(devc->trigger_source, "CH1"))
494 tmp_str = "CHAN1";
495 else if (!strcmp(devc->trigger_source, "CH2"))
496 tmp_str = "CHAN2";
497 else
498 tmp_str = (char *)devc->trigger_source;
499 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
500 break;
501 }
4e108ace 502 }
254dd102
BV
503 if (i == ARRAY_SIZE(trigger_sources))
504 ret = SR_ERR_ARG;
e0b7d23c 505 break;
1953564a 506 case SR_CONF_VDIV:
f6a0ac9f 507 g_variant_get(data, "(tt)", &p, &q);
f48e0249
ML
508 for (i = 0; i < 2; i++) {
509 if (probe_group == &devc->analog_groups[i])
510 {
511 for (j = 0; j < ARRAY_SIZE(vdivs); j++)
512 {
513 if (vdivs[j][0] != p || vdivs[j][1] != q)
514 continue;
515 devc->vdiv[i] = (float)p / q;
516 return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
517 devc->vdiv[i]);
518 }
519 return SR_ERR_ARG;
520 }
e0b7d23c 521 }
f48e0249 522 return SR_ERR_NA;
1953564a 523 case SR_CONF_COUPLING:
f6a0ac9f 524 tmp_str = g_variant_get_string(data, NULL);
f48e0249
ML
525 for (i = 0; i < 2; i++) {
526 if (probe_group == &devc->analog_groups[i])
527 {
528 for (j = 0; j < ARRAY_SIZE(coupling); j++)
529 {
530 if (!strcmp(tmp_str, coupling[j]))
531 {
532 g_free(devc->coupling[i]);
533 devc->coupling[i] = g_strdup(coupling[j]);
534 return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
535 devc->coupling[i]);
536 }
537 }
538 return SR_ERR_ARG;
e0b7d23c
ML
539 }
540 }
f48e0249 541 return SR_ERR_NA;
f4816ac6 542 default:
bd6fbf62 543 ret = SR_ERR_NA;
29d957ce 544 break;
f4816ac6
ML
545 }
546
547 return ret;
548}
549
8f996b89
ML
550static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
551 const struct sr_probe_group *probe_group)
a1c743fc 552{
861c447b
BV
553 GVariant *tuple, *rational[2];
554 GVariantBuilder gvb;
555 unsigned int i;
e43fdd8d 556 struct dev_context *devc;
8f996b89 557
e43fdd8d 558 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
559 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
560 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d
BV
561 return SR_OK;
562 } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
563 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
564 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
565 return SR_OK;
566 }
567
568 /* Every other option requires a valid device instance. */
569 if (!sdi || !(devc = sdi->priv))
570 return SR_ERR_ARG;
571
572 switch (key) {
ca55277c 573 break;
9a6517d1 574 case SR_CONF_DEVICE_OPTIONS:
e43fdd8d 575 if (probe_group == &devc->digital_group) {
f48e0249
ML
576 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
577 NULL, 0, sizeof(int32_t));
578 return SR_OK;
579 } else {
580 for (i = 0; i < 2; i++) {
581 if (probe_group == &devc->analog_groups[i]) {
582 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
583 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
584 return SR_OK;
585 }
586 }
587 return SR_ERR_NA;
588 }
2a7b113d 589 case SR_CONF_COUPLING:
f48e0249
ML
590 for (i = 0; i < 2; i++) {
591 if (probe_group == &devc->analog_groups[i]) {
592 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
593 return SR_OK;
594 }
595 }
596 return SR_ERR_NA;
e4f2b2ad 597 case SR_CONF_VDIV:
f48e0249
ML
598 for (i = 0; i < 2; i++) {
599 if (probe_group == &devc->analog_groups[i]) {
600 rational[0] = g_variant_new_uint64(vdivs[i][0]);
601 rational[1] = g_variant_new_uint64(vdivs[i][1]);
602 *data = g_variant_new_tuple(rational, 2);
603 return SR_OK;
604 }
861c447b 605 }
f48e0249 606 return SR_ERR_NA;
41f5bd09 607 case SR_CONF_TIMEBASE:
861c447b
BV
608 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
609 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
610 rational[0] = g_variant_new_uint64(timebases[i][0]);
611 rational[1] = g_variant_new_uint64(timebases[i][1]);
612 tuple = g_variant_new_tuple(rational, 2);
613 g_variant_builder_add_value(&gvb, tuple);
614 }
615 *data = g_variant_builder_end(&gvb);
41f5bd09 616 break;
328bafab 617 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 618 *data = g_variant_new_strv(trigger_sources,
6bb192bc 619 devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 620 break;
a1c743fc 621 default:
bd6fbf62 622 return SR_ERR_NA;
a1c743fc
BV
623 }
624
625 return SR_OK;
626}
627
254dd102 628static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 629{
9bd4c956 630 struct sr_serial_dev_inst *serial;
29d957ce 631 struct dev_context *devc;
254dd102
BV
632 struct sr_probe *probe;
633 GSList *l;
254dd102 634 char cmd[256];
29d957ce 635
e73ffd42
BV
636 if (sdi->status != SR_ST_ACTIVE)
637 return SR_ERR_DEV_CLOSED;
e0b7d23c 638
9bd4c956 639 serial = sdi->conn;
29d957ce
UH
640 devc = sdi->priv;
641
254dd102
BV
642 for (l = sdi->probes; l; l = l->next) {
643 probe = l->data;
6bb192bc
ML
644 sr_dbg("handling probe %s", probe->name);
645 if (probe->type == SR_PROBE_ANALOG) {
646 if (probe->enabled)
647 devc->enabled_analog_probes = g_slist_append(
648 devc->enabled_analog_probes, probe);
649 if (probe->enabled != devc->analog_channels[probe->index]) {
650 /* Enabled channel is currently disabled, or vice versa. */
651 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
652 probe->enabled ? "ON" : "OFF");
9bd4c956 653 if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
6bb192bc
ML
654 return SR_ERR;
655 }
656 } else if (probe->type == SR_PROBE_LOGIC) {
657 if (probe->enabled)
658 devc->enabled_digital_probes = g_slist_append(
659 devc->enabled_digital_probes, probe);
660 if (probe->enabled != devc->digital_channels[probe->index]) {
661 /* Enabled channel is currently disabled, or vice versa. */
662 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
663 probe->enabled ? "ON" : "OFF");
9bd4c956 664 if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
6bb192bc
ML
665 return SR_ERR;
666 }
254dd102
BV
667 }
668 }
6bb192bc 669 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 670 return SR_ERR;
e0b7d23c 671
9bd4c956 672 sr_source_add(serial->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi);
e0b7d23c
ML
673
674 /* Send header packet to the session bus. */
29a27196 675 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 676
254dd102 677 /* Fetch the first frame. */
6bb192bc
ML
678 if (devc->enabled_analog_probes) {
679 devc->channel_frame = devc->enabled_analog_probes->data;
9bd4c956 680 if (rigol_ds1xx2_send(sdi, ":WAV:DATA? CHAN%d",
6bb192bc
ML
681 devc->channel_frame->index + 1) != SR_OK)
682 return SR_ERR;
683 } else {
684 devc->channel_frame = devc->enabled_digital_probes->data;
9bd4c956 685 if (rigol_ds1xx2_send(sdi, ":WAV:DATA? DIG") != SR_OK)
6bb192bc
ML
686 return SR_ERR;
687 }
f4816ac6 688
ee7e9bee
ML
689 devc->num_frame_bytes = 0;
690
f4816ac6
ML
691 return SR_OK;
692}
693
254dd102 694static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 695{
29d957ce 696 struct dev_context *devc;
cc9fd2d2 697 struct sr_serial_dev_inst *serial;
29d957ce 698
f4816ac6
ML
699 (void)cb_data;
700
29d957ce
UH
701 devc = sdi->priv;
702
f4816ac6
ML
703 if (sdi->status != SR_ST_ACTIVE) {
704 sr_err("Device inactive, can't stop acquisition.");
705 return SR_ERR;
706 }
707
6bb192bc
ML
708 g_slist_free(devc->enabled_analog_probes);
709 g_slist_free(devc->enabled_digital_probes);
710 devc->enabled_analog_probes = NULL;
711 devc->enabled_digital_probes = NULL;
cc9fd2d2
BV
712 serial = sdi->conn;
713 sr_source_remove(serial->fd);
f4816ac6
ML
714
715 return SR_OK;
716}
717
718SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
719 .name = "rigol-ds1xx2",
720 .longname = "Rigol DS1xx2",
721 .api_version = 1,
6078d2c9
UH
722 .init = init,
723 .cleanup = cleanup,
724 .scan = scan,
725 .dev_list = dev_list,
3b412e3a 726 .dev_clear = dev_clear,
d62d7ad1 727 .config_get = config_get,
035a1078 728 .config_set = config_set,
a1c743fc 729 .config_list = config_list,
6078d2c9
UH
730 .dev_open = dev_open,
731 .dev_close = dev_close,
254dd102
BV
732 .dev_acquisition_start = dev_acquisition_start,
733 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
734 .priv = NULL,
735};