]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds1xx2/api.c
Enforce open device before config_set()/dev_acquisition_start()
[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,
43 SR_CONF_VDIV,
44 SR_CONF_COUPLING,
d62d7ad1
BV
45 SR_CONF_NUM_TIMEBASE,
46 SR_CONF_NUM_VDIV,
e0b7d23c
ML
47};
48
f6a0ac9f 49static const uint64_t timebases[][2] = {
e0b7d23c
ML
50 /* nanoseconds */
51 { 2, 1000000000 },
52 { 5, 1000000000 },
53 { 10, 1000000000 },
54 { 20, 1000000000 },
55 { 50, 1000000000 },
56 { 100, 1000000000 },
57 { 500, 1000000000 },
58 /* microseconds */
59 { 1, 1000000 },
60 { 2, 1000000 },
61 { 5, 1000000 },
62 { 10, 1000000 },
63 { 20, 1000000 },
64 { 50, 1000000 },
65 { 100, 1000000 },
66 { 200, 1000000 },
67 { 500, 1000000 },
68 /* milliseconds */
69 { 1, 1000 },
70 { 2, 1000 },
71 { 5, 1000 },
72 { 10, 1000 },
73 { 20, 1000 },
74 { 50, 1000 },
75 { 100, 1000 },
76 { 200, 1000 },
77 { 500, 1000 },
78 /* seconds */
79 { 1, 1 },
80 { 2, 1 },
81 { 5, 1 },
82 { 10, 1 },
83 { 20, 1 },
84 { 50, 1 },
e0b7d23c
ML
85};
86
f6a0ac9f 87static const uint64_t vdivs[][2] = {
e0b7d23c
ML
88 /* millivolts */
89 { 2, 1000 },
90 { 5, 1000 },
91 { 10, 1000 },
92 { 20, 1000 },
93 { 50, 1000 },
94 { 100, 1000 },
95 { 200, 1000 },
96 { 500, 1000 },
97 /* volts */
98 { 1, 1 },
99 { 2, 1 },
100 { 5, 1 },
101 { 10, 1 },
e0b7d23c
ML
102};
103
104static const char *trigger_sources[] = {
105 "CH1",
106 "CH2",
107 "EXT",
108 "AC Line",
6bb192bc
ML
109 "D0",
110 "D1",
111 "D2",
112 "D3",
113 "D4",
114 "D5",
115 "D6",
116 "D7",
117 "D8",
118 "D9",
119 "D10",
120 "D11",
121 "D12",
122 "D13",
123 "D14",
124 "D15",
e0b7d23c
ML
125};
126
127static const char *coupling[] = {
128 "AC",
129 "DC",
130 "GND",
e0b7d23c
ML
131};
132
512bb890
BV
133static const char *supported_models[] = {
134 "DS1052E",
135 "DS1102E",
136 "DS1052D",
333bf022 137 "DS1102D",
512bb890
BV
138};
139
f4816ac6
ML
140SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info;
141static struct sr_dev_driver *di = &rigol_ds1xx2_driver_info;
142
143/* Properly close and free all devices. */
144static int clear_instances(void)
145{
146 struct sr_dev_inst *sdi;
147 struct drv_context *drvc;
148 struct dev_context *devc;
149 GSList *l;
150
151 if (!(drvc = di->priv))
152 return SR_OK;
153
154 for (l = drvc->instances; l; l = l->next) {
155 if (!(sdi = l->data))
156 continue;
f4816ac6 157
cc9fd2d2 158 if (sdi->conn)
9bd4c956 159 sr_serial_dev_inst_free(sdi->conn);
9bd4c956
ML
160
161 if ((devc = sdi->priv)) {
9bd4c956
ML
162 g_free(devc->coupling[0]);
163 g_free(devc->coupling[1]);
164 g_free(devc->trigger_source);
165 g_free(devc->trigger_slope);
166 }
f4816ac6
ML
167 sr_dev_inst_free(sdi);
168 }
169
170 g_slist_free(drvc->instances);
171 drvc->instances = NULL;
172
173 return SR_OK;
174}
175
254dd102
BV
176static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
177{
254dd102
BV
178 va_list args;
179 char buf[256];
180
254dd102
BV
181 va_start(args, format);
182 vsnprintf(buf, 255, format, args);
183 va_end(args);
9bd4c956 184 if (rigol_ds1xx2_send(sdi, buf) != SR_OK)
254dd102
BV
185 return SR_ERR;
186
187 /* When setting a bunch of parameters in a row, the DS1052E scrambles
188 * some of them unless there is at least 100ms delay in between. */
8f35be72 189 sr_spew("delay %dms", 100);
e31d410d 190 g_usleep(100000);
254dd102
BV
191
192 return SR_OK;
193}
194
e0b7d23c 195static int hw_init(struct sr_context *sr_ctx)
f4816ac6 196{
063e7aef 197 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
f4816ac6
ML
198}
199
cc9fd2d2 200static int probe_port(const char *port, GSList **devices)
f4816ac6 201{
cc9fd2d2
BV
202 struct dev_context *devc;
203 struct sr_dev_inst *sdi;
9bd4c956 204 struct sr_serial_dev_inst *serial;
cc9fd2d2 205 struct sr_probe *probe;
f6a0ac9f 206 unsigned int i;
9bd4c956 207 int len, num_tokens;
cc9fd2d2 208 gboolean matched, has_digital;
512bb890 209 const char *manufacturer, *model, *version;
fb6e5ba8 210 char buf[256];
cc9fd2d2 211 gchar **tokens, *channel_name;
fb6e5ba8 212
46a743c1 213 *devices = NULL;
cc9fd2d2 214 if (!(serial = sr_serial_dev_inst_new(port, NULL)))
9bd4c956
ML
215 return SR_ERR_MALLOC;
216
217 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
218 return SR_ERR;
cc9fd2d2 219 len = serial_write(serial, "*IDN?", 5);
9bd4c956
ML
220 len = serial_read(serial, buf, sizeof(buf));
221 if (serial_close(serial) != SR_OK)
222 return SR_ERR;
223
224 sr_serial_dev_inst_free(serial);
225
ca55277c
ML
226 if (len == 0)
227 return SR_ERR_NA;
f4816ac6 228
ca55277c 229 buf[len] = 0;
cc9fd2d2
BV
230 tokens = g_strsplit(buf, ",", 0);
231 sr_dbg("response: %s [%s]", port, buf);
4b97c74e 232
ca55277c 233 for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
e0b7d23c 234
ca55277c
ML
235 if (num_tokens < 4) {
236 g_strfreev(tokens);
237 return SR_ERR_NA;
238 }
e0b7d23c 239
ca55277c
ML
240 manufacturer = tokens[0];
241 model = tokens[1];
242 version = tokens[3];
fb6e5ba8 243
ca55277c
ML
244 if (strcmp(manufacturer, "Rigol Technologies")) {
245 g_strfreev(tokens);
246 return SR_ERR_NA;
247 }
fb6e5ba8 248
46a743c1 249 matched = has_digital = FALSE;
ca55277c
ML
250 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
251 if (!strcmp(model, supported_models[i])) {
cc9fd2d2 252 matched = TRUE;
ca55277c
ML
253 has_digital = g_str_has_suffix(model, "D");
254 break;
fb6e5ba8 255 }
ca55277c 256 }
fb6e5ba8 257
ca55277c
ML
258 if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
259 manufacturer, model, version))) {
260 g_strfreev(tokens);
261 return SR_ERR_NA;
262 }
fb6e5ba8 263
ca55277c 264 g_strfreev(tokens);
fb6e5ba8 265
cc9fd2d2 266 if (!(sdi->conn = sr_serial_dev_inst_new(port, NULL)))
ca55277c 267 return SR_ERR_MALLOC;
cc9fd2d2 268 sdi->driver = di;
512bb890 269
cc9fd2d2 270 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
ca55277c 271 return SR_ERR_MALLOC;
cc9fd2d2 272 devc->limit_frames = 0;
ca55277c 273 devc->has_digital = has_digital;
512bb890 274
ca55277c
ML
275 for (i = 0; i < 2; i++) {
276 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
277 i == 0 ? "CH1" : "CH2")))
278 return SR_ERR_MALLOC;
279 sdi->probes = g_slist_append(sdi->probes, probe);
280 }
512bb890 281
ca55277c
ML
282 if (devc->has_digital) {
283 for (i = 0; i < 16; i++) {
284 if (!(channel_name = g_strdup_printf("D%d", i)))
285 return SR_ERR_MALLOC;
286 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
287 g_free(channel_name);
288 if (!probe)
289 return SR_ERR_MALLOC;
290 sdi->probes = g_slist_append(sdi->probes, probe);
512bb890 291 }
ca55277c 292 }
cc9fd2d2
BV
293 sdi->priv = devc;
294
295 *devices = g_slist_append(NULL, sdi);
512bb890 296
ca55277c
ML
297 return SR_OK;
298}
512bb890 299
ca55277c
ML
300static GSList *hw_scan(GSList *options)
301{
302 struct drv_context *drvc;
ca55277c 303 struct sr_config *src;
cc9fd2d2 304 GSList *l, *devices;
ca55277c 305 GDir *dir;
ca55277c 306 int ret;
cc9fd2d2
BV
307 const gchar *dev_name;
308 gchar *port = NULL;
fb6e5ba8 309
ca55277c 310 drvc = di->priv;
d2e0b1fa 311
ca55277c
ML
312 for (l = options; l; l = l->next) {
313 src = l->data;
314 if (src->key == SR_CONF_CONN) {
cc9fd2d2 315 port = (char *)g_variant_get_string(src->data, NULL);
ca55277c 316 break;
fb6e5ba8 317 }
ca55277c 318 }
fb6e5ba8 319
46a743c1 320 devices = NULL;
cc9fd2d2
BV
321 if (port) {
322 if (probe_port(port, &devices) == SR_ERR_MALLOC)
ca55277c 323 return NULL;
ca55277c
ML
324 } else {
325 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
326 return NULL;
327 while ((dev_name = g_dir_read_name(dir))) {
cc9fd2d2 328 if (strncmp(dev_name, "usbtmc", 6))
ca55277c 329 continue;
cc9fd2d2
BV
330 port = g_strconcat("/dev/", dev_name, NULL);
331 ret = probe_port(port, &devices);
332 g_free(port);
ca55277c
ML
333 if (ret == SR_ERR_MALLOC) {
334 g_dir_close(dir);
ca55277c 335 return NULL;
6bb192bc
ML
336 }
337 }
ca55277c
ML
338 g_dir_close(dir);
339 }
f4816ac6 340
46a743c1
BV
341 /* Tack a copy of the newly found devices onto the driver list. */
342 l = g_slist_copy(devices);
343 drvc->instances = g_slist_concat(drvc->instances, l);
cc9fd2d2 344
f4816ac6
ML
345 return devices;
346}
347
348static GSList *hw_dev_list(void)
349{
0e94d524 350 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
351}
352
353static int hw_dev_open(struct sr_dev_inst *sdi)
354{
9bd4c956
ML
355
356 if (serial_open(sdi->conn, SERIAL_RDWR) != SR_OK)
e0b7d23c 357 return SR_ERR;
e0b7d23c 358
254dd102 359 if (rigol_ds1xx2_get_dev_cfg(sdi) != SR_OK)
254dd102 360 return SR_ERR;
f4816ac6 361
46a743c1 362 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 363
f4816ac6
ML
364 return SR_OK;
365}
366
367static int hw_dev_close(struct sr_dev_inst *sdi)
368{
cc9fd2d2 369 struct sr_serial_dev_inst *serial;
e0b7d23c 370
cc9fd2d2
BV
371 serial = sdi->conn;
372 if (serial && serial->fd != -1) {
373 serial_close(serial);
374 sdi->status = SR_ST_INACTIVE;
375 }
f4816ac6
ML
376
377 return SR_OK;
378}
379
380static int hw_cleanup(void)
381{
382 clear_instances();
383
f4816ac6
ML
384 return SR_OK;
385}
386
d62d7ad1
BV
387static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
388{
389
390 (void)sdi;
391
392 switch (id) {
393 case SR_CONF_NUM_TIMEBASE:
394 *data = g_variant_new_int32(NUM_TIMEBASE);
395 break;
396 case SR_CONF_NUM_VDIV:
397 *data = g_variant_new_int32(NUM_VDIV);
398 break;
399 default:
bd6fbf62 400 return SR_ERR_NA;
d62d7ad1
BV
401 }
402
403 return SR_OK;
404}
405
f6a0ac9f 406static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
f4816ac6 407{
29d957ce 408 struct dev_context *devc;
f6a0ac9f 409 uint64_t tmp_u64, p, q;
254dd102 410 double t_dbl;
f6a0ac9f 411 unsigned int i;
254dd102
BV
412 int ret;
413 const char *tmp_str;
f4816ac6 414
29d957ce
UH
415 devc = sdi->priv;
416
e73ffd42
BV
417 if (sdi->status != SR_ST_ACTIVE)
418 return SR_ERR_DEV_CLOSED;
f4816ac6
ML
419
420 ret = SR_OK;
035a1078 421 switch (id) {
1953564a 422 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 423 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 424 break;
1953564a 425 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 426 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
427 if (tmp_u64 != 0 && tmp_u64 != 1)
428 return SR_ERR;
429 g_free(devc->trigger_slope);
430 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
431 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 432 break;
1953564a 433 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
434 t_dbl = g_variant_get_double(data);
435 if (t_dbl < 0.0 || t_dbl > 1.0)
436 return SR_ERR;
437 devc->horiz_triggerpos = t_dbl;
438 /* We have the trigger offset as a percentage of the frame, but
439 * need to express this in seconds. */
440 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
441 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 442 break;
1953564a 443 case SR_CONF_TIMEBASE:
f6a0ac9f 444 g_variant_get(data, "(tt)", &p, &q);
f6a0ac9f
BV
445 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
446 if (timebases[i][0] == p && timebases[i][1] == q) {
254dd102
BV
447 devc->timebase = (float)p / q;
448 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
449 break;
450 }
451 }
254dd102
BV
452 if (i == ARRAY_SIZE(timebases))
453 ret = SR_ERR_ARG;
e0b7d23c 454 break;
1953564a 455 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 456 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
457 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
458 if (!strcmp(trigger_sources[i], tmp_str)) {
459 g_free(devc->trigger_source);
460 devc->trigger_source = g_strdup(trigger_sources[i]);
461 if (!strcmp(devc->trigger_source, "AC Line"))
462 tmp_str = "ACL";
463 else if (!strcmp(devc->trigger_source, "CH1"))
464 tmp_str = "CHAN1";
465 else if (!strcmp(devc->trigger_source, "CH2"))
466 tmp_str = "CHAN2";
467 else
468 tmp_str = (char *)devc->trigger_source;
469 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
470 break;
471 }
4e108ace 472 }
254dd102
BV
473 if (i == ARRAY_SIZE(trigger_sources))
474 ret = SR_ERR_ARG;
e0b7d23c 475 break;
1953564a 476 case SR_CONF_VDIV:
f6a0ac9f 477 g_variant_get(data, "(tt)", &p, &q);
f6a0ac9f
BV
478 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
479 if (vdivs[i][0] != p || vdivs[i][1] != q)
480 continue;
254dd102
BV
481 devc->vdiv[0] = devc->vdiv[1] = (float)p / q;
482 set_cfg(sdi, ":CHAN1:SCAL %.3f", devc->vdiv[0]);
483 ret = set_cfg(sdi, ":CHAN2:SCAL %.3f", devc->vdiv[1]);
f6a0ac9f 484 break;
e0b7d23c 485 }
f6a0ac9f 486 if (i == ARRAY_SIZE(vdivs))
e0b7d23c
ML
487 ret = SR_ERR_ARG;
488 break;
1953564a 489 case SR_CONF_COUPLING:
e0b7d23c 490 /* TODO: Not supporting coupling per channel yet. */
f6a0ac9f
BV
491 tmp_str = g_variant_get_string(data, NULL);
492 for (i = 0; i < ARRAY_SIZE(coupling); i++) {
493 if (!strcmp(tmp_str, coupling[i])) {
254dd102
BV
494 g_free(devc->coupling[0]);
495 g_free(devc->coupling[1]);
496 devc->coupling[0] = g_strdup(coupling[i]);
497 devc->coupling[1] = g_strdup(coupling[i]);
498 set_cfg(sdi, ":CHAN1:COUP %s", devc->coupling[0]);
499 ret = set_cfg(sdi, ":CHAN2:COUP %s", devc->coupling[1]);
e0b7d23c
ML
500 break;
501 }
502 }
f6a0ac9f 503 if (i == ARRAY_SIZE(coupling))
e0b7d23c
ML
504 ret = SR_ERR_ARG;
505 break;
f4816ac6 506 default:
bd6fbf62 507 ret = SR_ERR_NA;
29d957ce 508 break;
f4816ac6
ML
509 }
510
511 return ret;
512}
513
f6a0ac9f 514static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
a1c743fc 515{
861c447b
BV
516 GVariant *tuple, *rational[2];
517 GVariantBuilder gvb;
518 unsigned int i;
a7be14ad 519 struct dev_context *devc;
a1c743fc
BV
520
521 switch (key) {
ca55277c
ML
522 case SR_CONF_SCAN_OPTIONS:
523 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
524 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
525 break;
9a6517d1 526 case SR_CONF_DEVICE_OPTIONS:
f6a0ac9f
BV
527 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
528 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 529 break;
2a7b113d 530 case SR_CONF_COUPLING:
169dbe85
UH
531 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
532 break;
e4f2b2ad 533 case SR_CONF_VDIV:
861c447b
BV
534 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
535 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
536 rational[0] = g_variant_new_uint64(vdivs[i][0]);
537 rational[1] = g_variant_new_uint64(vdivs[i][1]);
538 tuple = g_variant_new_tuple(rational, 2);
539 g_variant_builder_add_value(&gvb, tuple);
540 }
541 *data = g_variant_builder_end(&gvb);
e4f2b2ad 542 break;
41f5bd09 543 case SR_CONF_TIMEBASE:
861c447b
BV
544 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
545 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
546 rational[0] = g_variant_new_uint64(timebases[i][0]);
547 rational[1] = g_variant_new_uint64(timebases[i][1]);
548 tuple = g_variant_new_tuple(rational, 2);
549 g_variant_builder_add_value(&gvb, tuple);
550 }
551 *data = g_variant_builder_end(&gvb);
41f5bd09 552 break;
328bafab 553 case SR_CONF_TRIGGER_SOURCE:
a7be14ad
BV
554 if (!sdi || !sdi->priv)
555 /* Can't know this until we have the exact model. */
556 return SR_ERR_ARG;
557 devc = sdi->priv;
f6a0ac9f 558 *data = g_variant_new_strv(trigger_sources,
6bb192bc 559 devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 560 break;
a1c743fc 561 default:
bd6fbf62 562 return SR_ERR_NA;
a1c743fc
BV
563 }
564
565 return SR_OK;
566}
567
254dd102 568static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 569{
9bd4c956 570 struct sr_serial_dev_inst *serial;
29d957ce 571 struct dev_context *devc;
254dd102
BV
572 struct sr_probe *probe;
573 GSList *l;
254dd102 574 char cmd[256];
29d957ce 575
e73ffd42
BV
576 if (sdi->status != SR_ST_ACTIVE)
577 return SR_ERR_DEV_CLOSED;
e0b7d23c 578
9bd4c956 579 serial = sdi->conn;
29d957ce
UH
580 devc = sdi->priv;
581
254dd102
BV
582 for (l = sdi->probes; l; l = l->next) {
583 probe = l->data;
6bb192bc
ML
584 sr_dbg("handling probe %s", probe->name);
585 if (probe->type == SR_PROBE_ANALOG) {
586 if (probe->enabled)
587 devc->enabled_analog_probes = g_slist_append(
588 devc->enabled_analog_probes, probe);
589 if (probe->enabled != devc->analog_channels[probe->index]) {
590 /* Enabled channel is currently disabled, or vice versa. */
591 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
592 probe->enabled ? "ON" : "OFF");
9bd4c956 593 if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
6bb192bc
ML
594 return SR_ERR;
595 }
596 } else if (probe->type == SR_PROBE_LOGIC) {
597 if (probe->enabled)
598 devc->enabled_digital_probes = g_slist_append(
599 devc->enabled_digital_probes, probe);
600 if (probe->enabled != devc->digital_channels[probe->index]) {
601 /* Enabled channel is currently disabled, or vice versa. */
602 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
603 probe->enabled ? "ON" : "OFF");
9bd4c956 604 if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
6bb192bc
ML
605 return SR_ERR;
606 }
254dd102
BV
607 }
608 }
6bb192bc 609 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 610 return SR_ERR;
e0b7d23c 611
9bd4c956 612 sr_source_add(serial->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi);
e0b7d23c
ML
613
614 /* Send header packet to the session bus. */
4afdfd46 615 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
e0b7d23c 616
254dd102 617 /* Fetch the first frame. */
6bb192bc
ML
618 if (devc->enabled_analog_probes) {
619 devc->channel_frame = devc->enabled_analog_probes->data;
9bd4c956 620 if (rigol_ds1xx2_send(sdi, ":WAV:DATA? CHAN%d",
6bb192bc
ML
621 devc->channel_frame->index + 1) != SR_OK)
622 return SR_ERR;
623 } else {
624 devc->channel_frame = devc->enabled_digital_probes->data;
9bd4c956 625 if (rigol_ds1xx2_send(sdi, ":WAV:DATA? DIG") != SR_OK)
6bb192bc
ML
626 return SR_ERR;
627 }
f4816ac6 628
ee7e9bee
ML
629 devc->num_frame_bytes = 0;
630
f4816ac6
ML
631 return SR_OK;
632}
633
254dd102 634static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 635{
29d957ce 636 struct dev_context *devc;
cc9fd2d2 637 struct sr_serial_dev_inst *serial;
29d957ce 638
f4816ac6
ML
639 (void)cb_data;
640
29d957ce
UH
641 devc = sdi->priv;
642
f4816ac6
ML
643 if (sdi->status != SR_ST_ACTIVE) {
644 sr_err("Device inactive, can't stop acquisition.");
645 return SR_ERR;
646 }
647
6bb192bc
ML
648 g_slist_free(devc->enabled_analog_probes);
649 g_slist_free(devc->enabled_digital_probes);
650 devc->enabled_analog_probes = NULL;
651 devc->enabled_digital_probes = NULL;
cc9fd2d2
BV
652 serial = sdi->conn;
653 sr_source_remove(serial->fd);
f4816ac6
ML
654
655 return SR_OK;
656}
657
658SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
659 .name = "rigol-ds1xx2",
660 .longname = "Rigol DS1xx2",
661 .api_version = 1,
662 .init = hw_init,
663 .cleanup = hw_cleanup,
664 .scan = hw_scan,
665 .dev_list = hw_dev_list,
666 .dev_clear = clear_instances,
d62d7ad1 667 .config_get = config_get,
035a1078 668 .config_set = config_set,
a1c743fc 669 .config_list = config_list,
f4816ac6
ML
670 .dev_open = hw_dev_open,
671 .dev_close = hw_dev_close,
254dd102
BV
672 .dev_acquisition_start = dev_acquisition_start,
673 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
674 .priv = NULL,
675};