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