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