]> sigrok.org Git - libsigrok.git/blame - src/hardware/rigol-ds/api.c
Change type of SR_CONF keys to uint32_t.
[libsigrok.git] / src / 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>
2b0e4a46 26#include <math.h>
f4816ac6
ML
27#include <glib.h>
28#include "libsigrok.h"
29#include "libsigrok-internal.h"
30#include "protocol.h"
31
584560f1 32static const uint32_t hwopts[] = {
ca55277c 33 SR_CONF_CONN,
0dc7b43e 34 SR_CONF_SERIALCOMM
ca55277c
ML
35};
36
584560f1 37static const uint32_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,
c1bcb8cc 44 SR_CONF_LIMIT_FRAMES,
4914dd4b 45 SR_CONF_SAMPLERATE,
f48e0249
ML
46};
47
584560f1 48static const uint32_t analog_hwcaps[] = {
d62d7ad1 49 SR_CONF_NUM_VDIV,
f48e0249 50 SR_CONF_VDIV,
78bcc55a 51 SR_CONF_COUPLING,
babab622 52 SR_CONF_DATA_SOURCE,
e0b7d23c
ML
53};
54
f6a0ac9f 55static const uint64_t timebases[][2] = {
e0b7d23c 56 /* nanoseconds */
8e06edf5 57 { 1, 1000000000 },
e0b7d23c
ML
58 { 2, 1000000000 },
59 { 5, 1000000000 },
60 { 10, 1000000000 },
61 { 20, 1000000000 },
62 { 50, 1000000000 },
63 { 100, 1000000000 },
64 { 500, 1000000000 },
65 /* microseconds */
66 { 1, 1000000 },
67 { 2, 1000000 },
68 { 5, 1000000 },
69 { 10, 1000000 },
70 { 20, 1000000 },
71 { 50, 1000000 },
72 { 100, 1000000 },
73 { 200, 1000000 },
74 { 500, 1000000 },
75 /* milliseconds */
76 { 1, 1000 },
77 { 2, 1000 },
78 { 5, 1000 },
79 { 10, 1000 },
80 { 20, 1000 },
81 { 50, 1000 },
82 { 100, 1000 },
83 { 200, 1000 },
84 { 500, 1000 },
85 /* seconds */
86 { 1, 1 },
87 { 2, 1 },
88 { 5, 1 },
89 { 10, 1 },
90 { 20, 1 },
91 { 50, 1 },
bafd4890
ML
92 { 100, 1 },
93 { 200, 1 },
94 { 500, 1 },
8e06edf5 95 { 1000, 1 },
e0b7d23c
ML
96};
97
f6a0ac9f 98static const uint64_t vdivs[][2] = {
bafd4890
ML
99 /* microvolts */
100 { 500, 1000000 },
e0b7d23c 101 /* millivolts */
bafd4890 102 { 1, 1000 },
e0b7d23c
ML
103 { 2, 1000 },
104 { 5, 1000 },
105 { 10, 1000 },
106 { 20, 1000 },
107 { 50, 1000 },
108 { 100, 1000 },
109 { 200, 1000 },
110 { 500, 1000 },
111 /* volts */
112 { 1, 1 },
113 { 2, 1 },
114 { 5, 1 },
115 { 10, 1 },
e0b7d23c
ML
116};
117
bafd4890
ML
118#define NUM_TIMEBASE ARRAY_SIZE(timebases)
119#define NUM_VDIV ARRAY_SIZE(vdivs)
120
e0b7d23c
ML
121static const char *trigger_sources[] = {
122 "CH1",
123 "CH2",
821fbcad
ML
124 "CH3",
125 "CH4",
e0b7d23c
ML
126 "EXT",
127 "AC Line",
6bb192bc
ML
128 "D0",
129 "D1",
130 "D2",
131 "D3",
132 "D4",
133 "D5",
134 "D6",
135 "D7",
136 "D8",
137 "D9",
138 "D10",
139 "D11",
140 "D12",
141 "D13",
142 "D14",
143 "D15",
e0b7d23c
ML
144};
145
5d336f11
AJ
146static const char *trigger_slopes[] = {
147 "r",
148 "f",
149};
150
e0b7d23c
ML
151static const char *coupling[] = {
152 "AC",
153 "DC",
154 "GND",
e0b7d23c
ML
155};
156
babab622
ML
157/* Do not change the order of entries */
158static const char *data_sources[] = {
159 "Live",
160 "Memory",
161 "Segmented",
162};
163
569d4dbd
ML
164enum vendor {
165 RIGOL,
166 AGILENT,
167};
168
169enum series {
170 VS5000,
171 DS1000,
172 DS2000,
173 DS2000A,
174 DSO1000,
175};
10afee13 176
569d4dbd
ML
177/* short name, full name */
178static const struct rigol_ds_vendor supported_vendors[] = {
179 [RIGOL] = {"Rigol", "Rigol Technologies"},
14e1aa6d 180 [AGILENT] = {"Agilent", "Agilent Technologies"},
569d4dbd
ML
181};
182
183#define VENDOR(x) &supported_vendors[x]
184/* vendor, series, protocol, max timebase, min vdiv, number of horizontal divs,
185 * live waveform samples, memory buffer samples */
186static const struct rigol_ds_series supported_series[] = {
187 [VS5000] = {VENDOR(RIGOL), "VS5000", PROTOCOL_V1, FORMAT_RAW,
188 {50, 1}, {2, 1000}, 14, 2048, 0},
189 [DS1000] = {VENDOR(RIGOL), "DS1000", PROTOCOL_V2, FORMAT_IEEE488_2,
190 {50, 1}, {2, 1000}, 12, 600, 1048576},
191 [DS2000] = {VENDOR(RIGOL), "DS2000", PROTOCOL_V3, FORMAT_IEEE488_2,
192 {500, 1}, {2, 1000}, 14, 1400, 14000},
193 [DS2000A] = {VENDOR(RIGOL), "DS2000A", PROTOCOL_V3, FORMAT_IEEE488_2,
194 {1000, 1}, {500, 1000000}, 14, 1400, 14000},
195 [DSO1000] = {VENDOR(AGILENT), "DSO1000", PROTOCOL_V3, FORMAT_IEEE488_2,
196 {50, 1}, {2, 1000}, 12, 600, 20480},
197};
10afee13 198
569d4dbd
ML
199#define SERIES(x) &supported_series[x]
200/* series, model, min timebase, analog channels, digital */
bafd4890 201static const struct rigol_ds_model supported_models[] = {
569d4dbd
ML
202 {SERIES(VS5000), "VS5022", {20, 1000000000}, 2, false},
203 {SERIES(VS5000), "VS5042", {10, 1000000000}, 2, false},
204 {SERIES(VS5000), "VS5062", {5, 1000000000}, 2, false},
205 {SERIES(VS5000), "VS5102", {2, 1000000000}, 2, false},
206 {SERIES(VS5000), "VS5202", {2, 1000000000}, 2, false},
207 {SERIES(VS5000), "VS5022D", {20, 1000000000}, 2, true},
208 {SERIES(VS5000), "VS5042D", {10, 1000000000}, 2, true},
209 {SERIES(VS5000), "VS5062D", {5, 1000000000}, 2, true},
210 {SERIES(VS5000), "VS5102D", {2, 1000000000}, 2, true},
211 {SERIES(VS5000), "VS5202D", {2, 1000000000}, 2, true},
212 {SERIES(DS1000), "DS1052E", {5, 1000000000}, 2, false},
213 {SERIES(DS1000), "DS1102E", {2, 1000000000}, 2, false},
214 {SERIES(DS1000), "DS1152E", {2, 1000000000}, 2, false},
215 {SERIES(DS1000), "DS1052D", {5, 1000000000}, 2, true},
216 {SERIES(DS1000), "DS1102D", {2, 1000000000}, 2, true},
217 {SERIES(DS1000), "DS1152D", {2, 1000000000}, 2, true},
218 {SERIES(DS2000), "DS2072", {5, 1000000000}, 2, false},
219 {SERIES(DS2000), "DS2102", {5, 1000000000}, 2, false},
220 {SERIES(DS2000), "DS2202", {2, 1000000000}, 2, false},
221 {SERIES(DS2000), "DS2302", {1, 1000000000}, 2, false},
222 {SERIES(DS2000A), "DS2072A", {5, 1000000000}, 2, false},
223 {SERIES(DS2000A), "DS2102A", {5, 1000000000}, 2, false},
224 {SERIES(DS2000A), "DS2202A", {2, 1000000000}, 2, false},
225 {SERIES(DS2000A), "DS2302A", {1, 1000000000}, 2, false},
226 {SERIES(DSO1000), "DSO1002A", {5, 1000000000}, 2, false},
227 {SERIES(DSO1000), "DSO1004A", {5, 1000000000}, 4, false},
228 {SERIES(DSO1000), "DSO1012A", {2, 1000000000}, 2, false},
229 {SERIES(DSO1000), "DSO1014A", {2, 1000000000}, 4, false},
230 {SERIES(DSO1000), "DSO1022A", {2, 1000000000}, 2, false},
231 {SERIES(DSO1000), "DSO1024A", {2, 1000000000}, 4, false},
512bb890
BV
232};
233
3086efdd
ML
234SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
235static struct sr_dev_driver *di = &rigol_ds_driver_info;
f4816ac6 236
fa85f376 237static void clear_helper(void *priv)
f4816ac6 238{
f4816ac6 239 struct dev_context *devc;
effb9dd1 240 unsigned int i;
f4816ac6 241
ba358ffd 242 devc = priv;
babab622
ML
243 g_free(devc->data);
244 g_free(devc->buffer);
effb9dd1
AJ
245 for (i = 0; i < ARRAY_SIZE(devc->coupling); i++)
246 g_free(devc->coupling[i]);
fa85f376
UH
247 g_free(devc->trigger_source);
248 g_free(devc->trigger_slope);
562b7ae5
SA
249 g_free(devc->analog_groups);
250 g_free(devc->digital_group);
251 g_free(devc);
fa85f376 252}
f4816ac6 253
3b412e3a 254static int dev_clear(void)
fa85f376
UH
255{
256 return std_dev_clear(di, clear_helper);
f4816ac6
ML
257}
258
6078d2c9 259static int init(struct sr_context *sr_ctx)
f4816ac6 260{
f6beaac5 261 return std_init(sr_ctx, di, LOG_PREFIX);
f4816ac6
ML
262}
263
9d3ae01b 264static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
f4816ac6 265{
cc9fd2d2
BV
266 struct dev_context *devc;
267 struct sr_dev_inst *sdi;
ae1bc1cc 268 struct sr_scpi_hw_info *hw_info;
ba7dd8bb 269 struct sr_channel *ch;
8dd0b290 270 long n[3];
f6a0ac9f 271 unsigned int i;
bafd4890 272 const struct rigol_ds_model *model = NULL;
569d4dbd 273 gchar *channel_name, **version;
fb6e5ba8 274
ae1bc1cc 275 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
05238d28
ML
276 sr_info("Couldn't get IDN response, retrying.");
277 sr_scpi_close(scpi);
278 sr_scpi_open(scpi);
279 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
280 sr_info("Couldn't get IDN response.");
281 return NULL;
282 }
ca55277c 283 }
e0b7d23c 284
ca55277c 285 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
569d4dbd
ML
286 if (!strcasecmp(hw_info->manufacturer,
287 supported_models[i].series->vendor->full_name) &&
10afee13 288 !strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 289 model = &supported_models[i];
ca55277c 290 break;
fb6e5ba8 291 }
ca55277c 292 }
fb6e5ba8 293
bafd4890 294 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
569d4dbd
ML
295 model->series->vendor->name,
296 model->name,
ae1bc1cc
ML
297 hw_info->firmware_version))) {
298 sr_scpi_hw_info_free(hw_info);
9d3ae01b 299 return NULL;
ca55277c 300 }
fb6e5ba8 301
ae1bc1cc 302 sdi->conn = scpi;
fb6e5ba8 303
cc9fd2d2 304 sdi->driver = di;
ae1bc1cc 305 sdi->inst_type = SR_INST_SCPI;
512bb890 306
cc9fd2d2 307 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
9d3ae01b 308 return NULL;
ae1bc1cc 309
cc9fd2d2 310 devc->limit_frames = 0;
bafd4890 311 devc->model = model;
569d4dbd 312 devc->format = model->series->format;
8dd0b290 313
569d4dbd
ML
314 /* DS1000 models with firmware before 0.2.4 used the old data format. */
315 if (model->series == SERIES(DS1000)) {
8dd0b290
BV
316 version = g_strsplit(hw_info->firmware_version, ".", 0);
317 do {
318 if (!version[0] || !version[1] || !version[2])
319 break;
320 if (version[0][0] == 0 || version[1][0] == 0 || version[2][0] == 0)
321 break;
322 for (i = 0; i < 3; i++) {
323 if (sr_atol(version[i], &n[i]) != SR_OK)
324 break;
325 }
326 if (i != 3)
327 break;
328 if (n[0] != 0 || n[1] > 2)
329 break;
330 if (n[1] == 2 && n[2] > 3)
331 break;
569d4dbd
ML
332 sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format.");
333 devc->format = FORMAT_RAW;
8dd0b290
BV
334 } while(0);
335 g_strfreev(version);
336 }
337
338 sr_scpi_hw_info_free(hw_info);
512bb890 339
562b7ae5
SA
340 devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
341 model->analog_channels);
342
821fbcad
ML
343 for (i = 0; i < model->analog_channels; i++) {
344 if (!(channel_name = g_strdup_printf("CH%d", i + 1)))
9d3ae01b 345 return NULL;
3f239f08 346 ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE, channel_name);
ba7dd8bb 347 sdi->channels = g_slist_append(sdi->channels, ch);
562b7ae5
SA
348
349 devc->analog_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
350
351 devc->analog_groups[i]->name = channel_name;
352 devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
660e398f 353 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 354 devc->analog_groups[i]);
ca55277c 355 }
512bb890 356
bafd4890 357 if (devc->model->has_digital) {
562b7ae5
SA
358 devc->digital_group = g_malloc0(sizeof(struct sr_channel_group*));
359
effb9dd1 360 for (i = 0; i < ARRAY_SIZE(devc->digital_channels); i++) {
ca55277c 361 if (!(channel_name = g_strdup_printf("D%d", i)))
9d3ae01b 362 return NULL;
3f239f08 363 ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, channel_name);
ca55277c 364 g_free(channel_name);
ba7dd8bb 365 if (!ch)
9d3ae01b 366 return NULL;
ba7dd8bb 367 sdi->channels = g_slist_append(sdi->channels, ch);
562b7ae5
SA
368 devc->digital_group->channels = g_slist_append(
369 devc->digital_group->channels, ch);
512bb890 370 }
562b7ae5 371 devc->digital_group->name = g_strdup("LA");
660e398f 372 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 373 devc->digital_group);
ca55277c 374 }
bafd4890
ML
375
376 for (i = 0; i < NUM_TIMEBASE; i++) {
377 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
378 devc->timebases = &timebases[i];
569d4dbd 379 if (!memcmp(&devc->model->series->max_timebase, &timebases[i], sizeof(uint64_t[2])))
bafd4890
ML
380 devc->num_timebases = &timebases[i] - devc->timebases + 1;
381 }
382
0709197d 383 for (i = 0; i < NUM_VDIV; i++)
569d4dbd 384 if (!memcmp(&devc->model->series->min_vdiv, &vdivs[i], sizeof(uint64_t[2])))
6ff1394e 385 devc->vdivs = &vdivs[i];
bafd4890 386
babab622 387 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
9d3ae01b 388 return NULL;
babab622 389 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
9d3ae01b 390 return NULL;
babab622
ML
391
392 devc->data_source = DATA_SOURCE_LIVE;
393
cc9fd2d2
BV
394 sdi->priv = devc;
395
9d3ae01b 396 return sdi;
ca55277c 397}
512bb890 398
6078d2c9 399static GSList *scan(GSList *options)
ca55277c 400{
9d3ae01b 401 return sr_scpi_scan(di->priv, options, probe_device);
f4816ac6
ML
402}
403
6078d2c9 404static GSList *dev_list(void)
f4816ac6 405{
0e94d524 406 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
407}
408
6078d2c9 409static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 410{
ae1bc1cc 411 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 412
ae1bc1cc 413 if (sr_scpi_open(scpi) < 0)
e0b7d23c 414 return SR_ERR;
e0b7d23c 415
3086efdd 416 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 417 return SR_ERR;
f4816ac6 418
46a743c1 419 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 420
f4816ac6
ML
421 return SR_OK;
422}
423
6078d2c9 424static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 425{
ae1bc1cc 426 struct sr_scpi_dev_inst *scpi;
22c19688 427 struct dev_context *devc;
ae1bc1cc 428
83dbd9f0
AJ
429 if (sdi->status != SR_ST_ACTIVE)
430 return SR_ERR_DEV_CLOSED;
464d4936 431
ae1bc1cc 432 scpi = sdi->conn;
22c19688
ML
433 devc = sdi->priv;
434
6e94eb41 435 if (devc->model->series->protocol == PROTOCOL_V2)
38354d9d 436 rigol_ds_config_set(sdi, ":KEY:LOCK DISABLE");
e0b7d23c 437
ae1bc1cc
ML
438 if (scpi) {
439 if (sr_scpi_close(scpi) < 0)
440 return SR_ERR;
cc9fd2d2
BV
441 sdi->status = SR_ST_INACTIVE;
442 }
f4816ac6
ML
443
444 return SR_OK;
445}
446
6078d2c9 447static int cleanup(void)
f4816ac6 448{
3b412e3a 449 return dev_clear();
f4816ac6
ML
450}
451
5415e602
ML
452static int analog_frame_size(const struct sr_dev_inst *sdi)
453{
454 struct dev_context *devc = sdi->priv;
ba7dd8bb
UH
455 struct sr_channel *ch;
456 int analog_channels = 0;
5415e602
ML
457 GSList *l;
458
ba7dd8bb
UH
459 for (l = sdi->channels; l; l = l->next) {
460 ch = l->data;
3f239f08 461 if (ch->type == SR_CHANNEL_ANALOG && ch->enabled)
ba7dd8bb 462 analog_channels++;
569d4dbd
ML
463 }
464
ba7dd8bb 465 if (analog_channels == 0)
824eb2ac
ML
466 return 0;
467
569d4dbd
ML
468 switch (devc->data_source) {
469 case DATA_SOURCE_LIVE:
470 return devc->model->series->live_samples;
471 case DATA_SOURCE_MEMORY:
ba7dd8bb 472 return devc->model->series->buffer_samples / analog_channels;
470140fc 473 default:
569d4dbd 474 return 0;
5415e602
ML
475 }
476}
477
d22250a9
ML
478static int digital_frame_size(const struct sr_dev_inst *sdi)
479{
480 struct dev_context *devc = sdi->priv;
481
569d4dbd
ML
482 switch (devc->data_source) {
483 case DATA_SOURCE_LIVE:
484 return devc->model->series->live_samples * 2;
485 case DATA_SOURCE_MEMORY:
486 return devc->model->series->buffer_samples * 2;
d22250a9
ML
487 default:
488 return 0;
489 }
490}
491
584560f1 492static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 493 const struct sr_channel_group *cg)
d62d7ad1 494{
e43fdd8d 495 struct dev_context *devc;
ba7dd8bb 496 struct sr_channel *ch;
2b0e4a46 497 const char *tmp_str;
c2b394d5 498 uint64_t samplerate;
2b0e4a46
AJ
499 int analog_channel = -1;
500 float smallest_diff = 0.0000000001;
501 int idx = -1;
502 unsigned i;
d62d7ad1 503
e43fdd8d
BV
504 if (!sdi || !(devc = sdi->priv))
505 return SR_ERR_ARG;
506
660e398f 507 /* If a channel group is specified, it must be a valid one. */
53b4680f 508 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 509 sr_err("Invalid channel group specified.");
969edf63 510 return SR_ERR;
be60a9e4
BV
511 }
512
53b4680f 513 if (cg) {
ba7dd8bb
UH
514 ch = g_slist_nth_data(cg->channels, 0);
515 if (!ch)
2b0e4a46 516 return SR_ERR;
3f239f08 517 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb 518 if (ch->name[2] < '1' || ch->name[2] > '4')
2b0e4a46 519 return SR_ERR;
ba7dd8bb 520 analog_channel = ch->name[2] - '1';
2b0e4a46
AJ
521 }
522 }
523
584560f1 524 switch (key) {
d62d7ad1 525 case SR_CONF_NUM_TIMEBASE:
569d4dbd 526 *data = g_variant_new_int32(devc->model->series->num_horizontal_divs);
d62d7ad1
BV
527 break;
528 case SR_CONF_NUM_VDIV:
72ecba02 529 *data = g_variant_new_int32(NUM_VDIV);
babab622
ML
530 case SR_CONF_DATA_SOURCE:
531 if (devc->data_source == DATA_SOURCE_LIVE)
532 *data = g_variant_new_string("Live");
533 else if (devc->data_source == DATA_SOURCE_MEMORY)
534 *data = g_variant_new_string("Memory");
535 else
536 *data = g_variant_new_string("Segmented");
537 break;
4914dd4b
ML
538 case SR_CONF_SAMPLERATE:
539 if (devc->data_source == DATA_SOURCE_LIVE) {
c2b394d5 540 samplerate = analog_frame_size(sdi) /
569d4dbd 541 (devc->timebase * devc->model->series->num_horizontal_divs);
4914dd4b 542 *data = g_variant_new_uint64(samplerate);
c2b394d5 543 } else {
4914dd4b 544 return SR_ERR_NA;
c2b394d5 545 }
4914dd4b 546 break;
2b0e4a46
AJ
547 case SR_CONF_TRIGGER_SOURCE:
548 if (!strcmp(devc->trigger_source, "ACL"))
549 tmp_str = "AC Line";
550 else if (!strcmp(devc->trigger_source, "CHAN1"))
551 tmp_str = "CH1";
552 else if (!strcmp(devc->trigger_source, "CHAN2"))
553 tmp_str = "CH2";
554 else if (!strcmp(devc->trigger_source, "CHAN3"))
555 tmp_str = "CH3";
556 else if (!strcmp(devc->trigger_source, "CHAN4"))
557 tmp_str = "CH4";
558 else
559 tmp_str = devc->trigger_source;
560 *data = g_variant_new_string(tmp_str);
561 break;
5d336f11
AJ
562 case SR_CONF_TRIGGER_SLOPE:
563 if (!strcmp(devc->trigger_slope, "POS"))
564 tmp_str = "r";
565 else if (!strcmp(devc->trigger_slope, "NEG"))
566 tmp_str = "f";
567 else
568 return SR_ERR_NA;
569 *data = g_variant_new_string(tmp_str);
570 break;
2b0e4a46
AJ
571 case SR_CONF_TIMEBASE:
572 for (i = 0; i < devc->num_timebases; i++) {
573 float tb = (float)devc->timebases[i][0] / devc->timebases[i][1];
574 float diff = fabs(devc->timebase - tb);
575 if (diff < smallest_diff) {
576 smallest_diff = diff;
577 idx = i;
578 }
579 }
580 if (idx < 0)
581 return SR_ERR_NA;
582 *data = g_variant_new("(tt)", devc->timebases[idx][0],
583 devc->timebases[idx][1]);
584 break;
585 case SR_CONF_VDIV:
586 if (analog_channel < 0)
587 return SR_ERR_NA;
588 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
589 float vdiv = (float)vdivs[i][0] / vdivs[i][1];
590 float diff = fabs(devc->vdiv[analog_channel] - vdiv);
591 if (diff < smallest_diff) {
592 smallest_diff = diff;
593 idx = i;
594 }
595 }
596 if (idx < 0)
597 return SR_ERR_NA;
598 *data = g_variant_new("(tt)", vdivs[idx][0], vdivs[idx][1]);
599 break;
600 case SR_CONF_COUPLING:
601 if (analog_channel < 0)
602 return SR_ERR_NA;
603 *data = g_variant_new_string(devc->coupling[analog_channel]);
604 break;
d62d7ad1 605 default:
bd6fbf62 606 return SR_ERR_NA;
d62d7ad1
BV
607 }
608
609 return SR_OK;
610}
611
584560f1 612static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 613 const struct sr_channel_group *cg)
f4816ac6 614{
29d957ce 615 struct dev_context *devc;
ca9b9f48 616 uint64_t p, q;
254dd102 617 double t_dbl;
f48e0249 618 unsigned int i, j;
254dd102
BV
619 int ret;
620 const char *tmp_str;
889ef4a0 621 char buffer[16];
f4816ac6 622
e43fdd8d
BV
623 if (!(devc = sdi->priv))
624 return SR_ERR_ARG;
29d957ce 625
e73ffd42
BV
626 if (sdi->status != SR_ST_ACTIVE)
627 return SR_ERR_DEV_CLOSED;
f4816ac6 628
660e398f 629 /* If a channel group is specified, it must be a valid one. */
53b4680f 630 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 631 sr_err("Invalid channel group specified.");
969edf63 632 return SR_ERR;
be60a9e4
BV
633 }
634
f4816ac6 635 ret = SR_OK;
584560f1 636 switch (key) {
1953564a 637 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 638 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 639 break;
1953564a 640 case SR_CONF_TRIGGER_SLOPE:
ca9b9f48
DE
641 tmp_str = g_variant_get_string(data, NULL);
642
643 if (!tmp_str || !(tmp_str[0] == 'f' || tmp_str[0] == 'r'))
644 return SR_ERR_ARG;
645
254dd102 646 g_free(devc->trigger_slope);
ca9b9f48 647 devc->trigger_slope = g_strdup((tmp_str[0] == 'r') ? "POS" : "NEG");
38354d9d 648 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 649 break;
1953564a 650 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
651 t_dbl = g_variant_get_double(data);
652 if (t_dbl < 0.0 || t_dbl > 1.0)
653 return SR_ERR;
654 devc->horiz_triggerpos = t_dbl;
655 /* We have the trigger offset as a percentage of the frame, but
656 * need to express this in seconds. */
bafd4890 657 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
889ef4a0 658 g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl);
38354d9d 659 ret = rigol_ds_config_set(sdi, ":TIM:OFFS %s", buffer);
e0b7d23c 660 break;
1953564a 661 case SR_CONF_TIMEBASE:
f6a0ac9f 662 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
663 for (i = 0; i < devc->num_timebases; i++) {
664 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102 665 devc->timebase = (float)p / q;
889ef4a0
AJ
666 g_ascii_formatd(buffer, sizeof(buffer), "%.9f",
667 devc->timebase);
38354d9d 668 ret = rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer);
f6a0ac9f
BV
669 break;
670 }
671 }
bafd4890 672 if (i == devc->num_timebases)
254dd102 673 ret = SR_ERR_ARG;
e0b7d23c 674 break;
1953564a 675 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 676 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
677 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
678 if (!strcmp(trigger_sources[i], tmp_str)) {
679 g_free(devc->trigger_source);
680 devc->trigger_source = g_strdup(trigger_sources[i]);
681 if (!strcmp(devc->trigger_source, "AC Line"))
682 tmp_str = "ACL";
683 else if (!strcmp(devc->trigger_source, "CH1"))
684 tmp_str = "CHAN1";
685 else if (!strcmp(devc->trigger_source, "CH2"))
686 tmp_str = "CHAN2";
821fbcad
ML
687 else if (!strcmp(devc->trigger_source, "CH3"))
688 tmp_str = "CHAN3";
689 else if (!strcmp(devc->trigger_source, "CH4"))
690 tmp_str = "CHAN4";
254dd102
BV
691 else
692 tmp_str = (char *)devc->trigger_source;
38354d9d 693 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
254dd102
BV
694 break;
695 }
4e108ace 696 }
254dd102
BV
697 if (i == ARRAY_SIZE(trigger_sources))
698 ret = SR_ERR_ARG;
e0b7d23c 699 break;
1953564a 700 case SR_CONF_VDIV:
53b4680f 701 if (!cg) {
660e398f
UH
702 sr_err("No channel group specified.");
703 return SR_ERR_CHANNEL_GROUP;
be60a9e4 704 }
f6a0ac9f 705 g_variant_get(data, "(tt)", &p, &q);
effb9dd1 706 for (i = 0; i < devc->model->analog_channels; i++) {
562b7ae5 707 if (cg == devc->analog_groups[i]) {
78bcc55a 708 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
709 if (vdivs[j][0] != p || vdivs[j][1] != q)
710 continue;
711 devc->vdiv[i] = (float)p / q;
889ef4a0
AJ
712 g_ascii_formatd(buffer, sizeof(buffer), "%.3f",
713 devc->vdiv[i]);
38354d9d 714 return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1,
889ef4a0 715 buffer);
f48e0249
ML
716 }
717 return SR_ERR_ARG;
718 }
e0b7d23c 719 }
f48e0249 720 return SR_ERR_NA;
1953564a 721 case SR_CONF_COUPLING:
53b4680f 722 if (!cg) {
660e398f
UH
723 sr_err("No channel group specified.");
724 return SR_ERR_CHANNEL_GROUP;
78bcc55a 725 }
f6a0ac9f 726 tmp_str = g_variant_get_string(data, NULL);
effb9dd1 727 for (i = 0; i < devc->model->analog_channels; i++) {
562b7ae5 728 if (cg == devc->analog_groups[i]) {
78bcc55a
BV
729 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
730 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
731 g_free(devc->coupling[i]);
732 devc->coupling[i] = g_strdup(coupling[j]);
38354d9d 733 return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1,
f48e0249
ML
734 devc->coupling[i]);
735 }
736 }
737 return SR_ERR_ARG;
e0b7d23c
ML
738 }
739 }
f48e0249 740 return SR_ERR_NA;
babab622
ML
741 case SR_CONF_DATA_SOURCE:
742 tmp_str = g_variant_get_string(data, NULL);
743 if (!strcmp(tmp_str, "Live"))
744 devc->data_source = DATA_SOURCE_LIVE;
569d4dbd
ML
745 else if (devc->model->series->protocol >= PROTOCOL_V2
746 && !strcmp(tmp_str, "Memory"))
babab622 747 devc->data_source = DATA_SOURCE_MEMORY;
569d4dbd 748 else if (devc->model->series->protocol >= PROTOCOL_V3
babab622
ML
749 && !strcmp(tmp_str, "Segmented"))
750 devc->data_source = DATA_SOURCE_SEGMENTED;
751 else
752 return SR_ERR;
753 break;
f4816ac6 754 default:
bd6fbf62 755 ret = SR_ERR_NA;
29d957ce 756 break;
f4816ac6
ML
757 }
758
759 return ret;
760}
761
584560f1 762static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 763 const struct sr_channel_group *cg)
a1c743fc 764{
861c447b
BV
765 GVariant *tuple, *rational[2];
766 GVariantBuilder gvb;
767 unsigned int i;
7cc1a550
ML
768 struct dev_context *devc = NULL;
769
770 if (sdi)
771 devc = sdi->priv;
8f996b89 772
e43fdd8d 773 if (key == SR_CONF_SCAN_OPTIONS) {
584560f1
BV
774 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
775 hwopts, ARRAY_SIZE(hwopts), sizeof(uint32_t));
e43fdd8d 776 return SR_OK;
53b4680f 777 } else if (key == SR_CONF_DEVICE_OPTIONS && cg == NULL) {
584560f1
BV
778 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
779 hwcaps, ARRAY_SIZE(hwcaps), sizeof(uint32_t));
e43fdd8d
BV
780 return SR_OK;
781 }
782
783 /* Every other option requires a valid device instance. */
784 if (!sdi || !(devc = sdi->priv))
785 return SR_ERR_ARG;
786
660e398f 787 /* If a channel group is specified, it must be a valid one. */
53b4680f 788 if (cg) {
effb9dd1
AJ
789 for (i = 0; i < devc->model->analog_channels; i++)
790 if (cg == devc->analog_groups[i])
791 break;
792 if (i >= devc->model->analog_channels) {
660e398f 793 sr_err("Invalid channel group specified.");
be60a9e4
BV
794 return SR_ERR;
795 }
796 }
797
e43fdd8d 798 switch (key) {
9a6517d1 799 case SR_CONF_DEVICE_OPTIONS:
53b4680f 800 if (!cg) {
660e398f
UH
801 sr_err("No channel group specified.");
802 return SR_ERR_CHANNEL_GROUP;
be60a9e4 803 }
562b7ae5 804 if (cg == devc->digital_group) {
584560f1
BV
805 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
806 NULL, 0, sizeof(uint32_t));
f48e0249
ML
807 return SR_OK;
808 } else {
effb9dd1 809 for (i = 0; i < devc->model->analog_channels; i++) {
562b7ae5 810 if (cg == devc->analog_groups[i]) {
584560f1
BV
811 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
812 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(uint32_t));
f48e0249
ML
813 return SR_OK;
814 }
815 }
816 return SR_ERR_NA;
817 }
5f77dffc 818 break;
2a7b113d 819 case SR_CONF_COUPLING:
53b4680f 820 if (!cg) {
660e398f
UH
821 sr_err("No channel group specified.");
822 return SR_ERR_CHANNEL_GROUP;
f48e0249 823 }
58f43369
BV
824 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
825 break;
e4f2b2ad 826 case SR_CONF_VDIV:
7cc1a550
ML
827 if (!devc)
828 /* Can't know this until we have the exact model. */
829 return SR_ERR_ARG;
53b4680f 830 if (!cg) {
660e398f
UH
831 sr_err("No channel group specified.");
832 return SR_ERR_CHANNEL_GROUP;
861c447b 833 }
58f43369 834 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
0709197d 835 for (i = 0; i < NUM_VDIV; i++) {
bafd4890
ML
836 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
837 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
838 tuple = g_variant_new_tuple(rational, 2);
839 g_variant_builder_add_value(&gvb, tuple);
840 }
841 *data = g_variant_builder_end(&gvb);
842 break;
41f5bd09 843 case SR_CONF_TIMEBASE:
7cc1a550
ML
844 if (!devc)
845 /* Can't know this until we have the exact model. */
846 return SR_ERR_ARG;
a31b2ccb
AJ
847 if (devc->num_timebases <= 0)
848 return SR_ERR_NA;
861c447b 849 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
850 for (i = 0; i < devc->num_timebases; i++) {
851 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
852 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
853 tuple = g_variant_new_tuple(rational, 2);
854 g_variant_builder_add_value(&gvb, tuple);
855 }
856 *data = g_variant_builder_end(&gvb);
41f5bd09 857 break;
328bafab 858 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
859 if (!devc)
860 /* Can't know this until we have the exact model. */
861 return SR_ERR_ARG;
f6a0ac9f 862 *data = g_variant_new_strv(trigger_sources,
bafd4890 863 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 864 break;
5d336f11
AJ
865 case SR_CONF_TRIGGER_SLOPE:
866 *data = g_variant_new_strv(trigger_slopes, ARRAY_SIZE(trigger_slopes));
867 break;
babab622
ML
868 case SR_CONF_DATA_SOURCE:
869 if (!devc)
870 /* Can't know this until we have the exact model. */
871 return SR_ERR_ARG;
569d4dbd
ML
872 switch (devc->model->series->protocol) {
873 case PROTOCOL_V1:
874 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2);
875 break;
876 case PROTOCOL_V2:
babab622 877 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
569d4dbd
ML
878 break;
879 default:
880 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
881 break;
882 }
babab622 883 break;
a1c743fc 884 default:
bd6fbf62 885 return SR_ERR_NA;
a1c743fc
BV
886 }
887
888 return SR_OK;
889}
890
254dd102 891static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 892{
ae1bc1cc 893 struct sr_scpi_dev_inst *scpi;
29d957ce 894 struct dev_context *devc;
ba7dd8bb 895 struct sr_channel *ch;
f76c24f6 896 struct sr_datafeed_packet packet;
254dd102 897 GSList *l;
29d957ce 898
e73ffd42
BV
899 if (sdi->status != SR_ST_ACTIVE)
900 return SR_ERR_DEV_CLOSED;
e0b7d23c 901
ae1bc1cc 902 scpi = sdi->conn;
29d957ce
UH
903 devc = sdi->priv;
904
51b294cd
ML
905 devc->num_frames = 0;
906
ba7dd8bb
UH
907 for (l = sdi->channels; l; l = l->next) {
908 ch = l->data;
909 sr_dbg("handling channel %s", ch->name);
3f239f08 910 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb
UH
911 if (ch->enabled)
912 devc->enabled_analog_channels = g_slist_append(
913 devc->enabled_analog_channels, ch);
914 if (ch->enabled != devc->analog_channels[ch->index]) {
6bb192bc 915 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
916 if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1,
917 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 918 return SR_ERR;
ba7dd8bb 919 devc->analog_channels[ch->index] = ch->enabled;
6bb192bc 920 }
3f239f08 921 } else if (ch->type == SR_CHANNEL_LOGIC) {
ba7dd8bb
UH
922 if (ch->enabled) {
923 devc->enabled_digital_channels = g_slist_append(
924 devc->enabled_digital_channels, ch);
04e8e01e
ML
925 /* Turn on LA module if currently off. */
926 if (!devc->la_enabled) {
38354d9d 927 if (rigol_ds_config_set(sdi, ":LA:DISP ON") != SR_OK)
04e8e01e
ML
928 return SR_ERR;
929 devc->la_enabled = TRUE;
930 }
931 }
ba7dd8bb 932 if (ch->enabled != devc->digital_channels[ch->index]) {
6bb192bc 933 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
934 if (rigol_ds_config_set(sdi, ":DIG%d:TURN %s", ch->index,
935 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 936 return SR_ERR;
ba7dd8bb 937 devc->digital_channels[ch->index] = ch->enabled;
6bb192bc 938 }
254dd102
BV
939 }
940 }
1fed20cb 941
ba7dd8bb 942 if (!devc->enabled_analog_channels && !devc->enabled_digital_channels)
254dd102 943 return SR_ERR;
e0b7d23c 944
ba7dd8bb
UH
945 /* Turn off LA module if on and no digital channels selected. */
946 if (devc->la_enabled && !devc->enabled_digital_channels)
38354d9d 947 if (rigol_ds_config_set(sdi, ":LA:DISP OFF") != SR_OK)
04e8e01e
ML
948 return SR_ERR;
949
e086b750
ML
950 /* Set memory mode. */
951 if (devc->data_source == DATA_SOURCE_SEGMENTED) {
952 sr_err("Data source 'Segmented' not yet supported");
953 return SR_ERR;
954 }
955
956 devc->analog_frame_size = analog_frame_size(sdi);
957 devc->digital_frame_size = digital_frame_size(sdi);
958
569d4dbd
ML
959 switch (devc->model->series->protocol) {
960 case PROTOCOL_V2:
99af83b7 961 if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK)
e086b750 962 return SR_ERR;
569d4dbd
ML
963 break;
964 case PROTOCOL_V3:
e086b750
ML
965 /* Apparently for the DS2000 the memory
966 * depth can only be set in Running state -
967 * this matches the behaviour of the UI. */
38354d9d 968 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
1fed20cb 969 return SR_ERR;
e086b750
ML
970 if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d",
971 devc->analog_frame_size) != SR_OK)
972 return SR_ERR;
973 if (rigol_ds_config_set(sdi, ":STOP") != SR_OK)
1fed20cb 974 return SR_ERR;
569d4dbd
ML
975 break;
976 default:
977 break;
1fed20cb
ML
978 }
979
e086b750
ML
980 if (devc->data_source == DATA_SOURCE_LIVE)
981 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
982 return SR_ERR;
983
102f1239
BV
984 sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
985 rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
986
987 /* Send header packet to the session bus. */
29a27196 988 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 989
ba7dd8bb
UH
990 if (devc->enabled_analog_channels)
991 devc->channel_entry = devc->enabled_analog_channels;
821fbcad 992 else
ba7dd8bb 993 devc->channel_entry = devc->enabled_digital_channels;
821fbcad 994
e086b750
ML
995 if (rigol_ds_capture_start(sdi) != SR_OK)
996 return SR_ERR;
f4816ac6 997
f76c24f6
ML
998 /* Start of first frame. */
999 packet.type = SR_DF_FRAME_BEGIN;
1000 sr_session_send(cb_data, &packet);
1001
f4816ac6
ML
1002 return SR_OK;
1003}
1004
254dd102 1005static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 1006{
29d957ce 1007 struct dev_context *devc;
ae1bc1cc 1008 struct sr_scpi_dev_inst *scpi;
b751cf7a 1009 struct sr_datafeed_packet packet;
29d957ce 1010
f4816ac6
ML
1011 (void)cb_data;
1012
29d957ce
UH
1013 devc = sdi->priv;
1014
f4816ac6
ML
1015 if (sdi->status != SR_ST_ACTIVE) {
1016 sr_err("Device inactive, can't stop acquisition.");
1017 return SR_ERR;
1018 }
1019
b751cf7a
ML
1020 /* End of last frame. */
1021 packet.type = SR_DF_END;
1022 sr_session_send(sdi, &packet);
1023
ba7dd8bb
UH
1024 g_slist_free(devc->enabled_analog_channels);
1025 g_slist_free(devc->enabled_digital_channels);
1026 devc->enabled_analog_channels = NULL;
1027 devc->enabled_digital_channels = NULL;
ae1bc1cc 1028 scpi = sdi->conn;
102f1239 1029 sr_scpi_source_remove(sdi->session, scpi);
f4816ac6
ML
1030
1031 return SR_OK;
1032}
1033
3086efdd
ML
1034SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
1035 .name = "rigol-ds",
1036 .longname = "Rigol DS",
f4816ac6 1037 .api_version = 1,
6078d2c9
UH
1038 .init = init,
1039 .cleanup = cleanup,
1040 .scan = scan,
1041 .dev_list = dev_list,
3b412e3a 1042 .dev_clear = dev_clear,
d62d7ad1 1043 .config_get = config_get,
035a1078 1044 .config_set = config_set,
a1c743fc 1045 .config_list = config_list,
6078d2c9
UH
1046 .dev_open = dev_open,
1047 .dev_close = dev_close,
254dd102
BV
1048 .dev_acquisition_start = dev_acquisition_start,
1049 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
1050 .priv = NULL,
1051};