]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
Use PRIu64 for format in pretty-printer.
[libsigrok.git] / 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>
f4816ac6
ML
26#include <glib.h>
27#include "libsigrok.h"
28#include "libsigrok-internal.h"
29#include "protocol.h"
30
ca55277c
ML
31static const int32_t hwopts[] = {
32 SR_CONF_CONN,
0dc7b43e 33 SR_CONF_SERIALCOMM
ca55277c
ML
34};
35
f6a0ac9f 36static const int32_t hwcaps[] = {
1953564a 37 SR_CONF_OSCILLOSCOPE,
1953564a
BV
38 SR_CONF_TIMEBASE,
39 SR_CONF_TRIGGER_SOURCE,
40 SR_CONF_TRIGGER_SLOPE,
41 SR_CONF_HORIZ_TRIGGERPOS,
d62d7ad1 42 SR_CONF_NUM_TIMEBASE,
f48e0249
ML
43};
44
45static const int32_t analog_hwcaps[] = {
d62d7ad1 46 SR_CONF_NUM_VDIV,
f48e0249 47 SR_CONF_VDIV,
78bcc55a 48 SR_CONF_COUPLING,
babab622 49 SR_CONF_DATA_SOURCE,
e0b7d23c
ML
50};
51
f6a0ac9f 52static const uint64_t timebases[][2] = {
e0b7d23c
ML
53 /* nanoseconds */
54 { 2, 1000000000 },
55 { 5, 1000000000 },
56 { 10, 1000000000 },
57 { 20, 1000000000 },
58 { 50, 1000000000 },
59 { 100, 1000000000 },
60 { 500, 1000000000 },
61 /* microseconds */
62 { 1, 1000000 },
63 { 2, 1000000 },
64 { 5, 1000000 },
65 { 10, 1000000 },
66 { 20, 1000000 },
67 { 50, 1000000 },
68 { 100, 1000000 },
69 { 200, 1000000 },
70 { 500, 1000000 },
71 /* milliseconds */
72 { 1, 1000 },
73 { 2, 1000 },
74 { 5, 1000 },
75 { 10, 1000 },
76 { 20, 1000 },
77 { 50, 1000 },
78 { 100, 1000 },
79 { 200, 1000 },
80 { 500, 1000 },
81 /* seconds */
82 { 1, 1 },
83 { 2, 1 },
84 { 5, 1 },
85 { 10, 1 },
86 { 20, 1 },
87 { 50, 1 },
bafd4890
ML
88 { 100, 1 },
89 { 200, 1 },
90 { 500, 1 },
91 /* { 1000, 1 }, Confuses other code? */
e0b7d23c
ML
92};
93
f6a0ac9f 94static const uint64_t vdivs[][2] = {
bafd4890
ML
95 /* microvolts */
96 { 500, 1000000 },
e0b7d23c 97 /* millivolts */
bafd4890 98 { 1, 1000 },
e0b7d23c
ML
99 { 2, 1000 },
100 { 5, 1000 },
101 { 10, 1000 },
102 { 20, 1000 },
103 { 50, 1000 },
104 { 100, 1000 },
105 { 200, 1000 },
106 { 500, 1000 },
107 /* volts */
108 { 1, 1 },
109 { 2, 1 },
110 { 5, 1 },
111 { 10, 1 },
e0b7d23c
ML
112};
113
bafd4890
ML
114#define NUM_TIMEBASE ARRAY_SIZE(timebases)
115#define NUM_VDIV ARRAY_SIZE(vdivs)
116
e0b7d23c
ML
117static const char *trigger_sources[] = {
118 "CH1",
119 "CH2",
821fbcad
ML
120 "CH3",
121 "CH4",
e0b7d23c
ML
122 "EXT",
123 "AC Line",
6bb192bc
ML
124 "D0",
125 "D1",
126 "D2",
127 "D3",
128 "D4",
129 "D5",
130 "D6",
131 "D7",
132 "D8",
133 "D9",
134 "D10",
135 "D11",
136 "D12",
137 "D13",
138 "D14",
139 "D15",
e0b7d23c
ML
140};
141
142static const char *coupling[] = {
143 "AC",
144 "DC",
145 "GND",
e0b7d23c
ML
146};
147
babab622
ML
148/* Do not change the order of entries */
149static const char *data_sources[] = {
150 "Live",
151 "Memory",
152 "Segmented",
153};
154
155/*
156 * name, series, protocol flavor, min timebase, max timebase, min vdiv,
157 * digital channels, number of horizontal divs
158 */
10afee13
ML
159
160#define RIGOL "Rigol Technologies"
161#define AGILENT "Agilent Technologies"
162
bafd4890 163static const struct rigol_ds_model supported_models[] = {
821fbcad
ML
164 {RIGOL, "DS1052E", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
165 {RIGOL, "DS1102E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
166 {RIGOL, "DS1152E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
167 {RIGOL, "DS1052D", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
168 {RIGOL, "DS1102D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
169 {RIGOL, "DS1152D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
170 {RIGOL, "DS2072", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
171 {RIGOL, "DS2102", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
172 {RIGOL, "DS2202", RIGOL_DS2000, PROTOCOL_IEEE488_2, {2, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
036d378a
AJ
173 {RIGOL, "DS2302", RIGOL_DS2000, PROTOCOL_IEEE488_2, {1, 1000000000}, {1000, 1}, {500, 1000000}, 2, false, 14},
174 {RIGOL, "DS2072A", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {1000, 1}, {500, 1000000}, 2, false, 14},
175 {RIGOL, "DS2102A", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {1000, 1}, {500, 1000000}, 2, false, 14},
176 {RIGOL, "DS2202A", RIGOL_DS2000, PROTOCOL_IEEE488_2, {2, 1000000000}, {1000, 1}, {500, 1000000}, 2, false, 14},
177 {RIGOL, "DS2302A", RIGOL_DS2000, PROTOCOL_IEEE488_2, {1, 1000000000}, {1000, 1}, {500, 1000000}, 2, false, 14},
821fbcad
ML
178 {RIGOL, "VS5022", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
179 {RIGOL, "VS5022D", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
180 {RIGOL, "VS5042", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
181 {RIGOL, "VS5042D", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
182 {RIGOL, "VS5062", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
183 {RIGOL, "VS5062D", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
184 {RIGOL, "VS5102", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
185 {RIGOL, "VS5102D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
186 {RIGOL, "VS5202", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
187 {RIGOL, "VS5202D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
227a0981
ML
188 {AGILENT, "DSO1002A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
189 {AGILENT, "DSO1004A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {5, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
190 {AGILENT, "DSO1012A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
821fbcad 191 {AGILENT, "DSO1014A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
227a0981
ML
192 {AGILENT, "DSO1022A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
193 {AGILENT, "DSO1024A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
512bb890
BV
194};
195
3086efdd
ML
196SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
197static struct sr_dev_driver *di = &rigol_ds_driver_info;
f4816ac6 198
fa85f376 199static void clear_helper(void *priv)
f4816ac6 200{
f4816ac6 201 struct dev_context *devc;
f4816ac6 202
ba358ffd 203 devc = priv;
babab622
ML
204 g_free(devc->data);
205 g_free(devc->buffer);
fa85f376
UH
206 g_free(devc->coupling[0]);
207 g_free(devc->coupling[1]);
208 g_free(devc->trigger_source);
209 g_free(devc->trigger_slope);
ba358ffd
BV
210 g_slist_free(devc->analog_groups[0].probes);
211 g_slist_free(devc->analog_groups[1].probes);
212 g_slist_free(devc->digital_group.probes);
fa85f376 213}
f4816ac6 214
3b412e3a 215static int dev_clear(void)
fa85f376
UH
216{
217 return std_dev_clear(di, clear_helper);
f4816ac6
ML
218}
219
254dd102
BV
220static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
221{
254dd102 222 va_list args;
4d7a9a14 223 int ret;
254dd102 224
254dd102 225 va_start(args, format);
4d7a9a14 226 ret = sr_scpi_send_variadic(sdi->conn, format, args);
254dd102 227 va_end(args);
4d7a9a14
ML
228
229 if (ret != SR_OK)
254dd102
BV
230 return SR_ERR;
231
232 /* When setting a bunch of parameters in a row, the DS1052E scrambles
233 * some of them unless there is at least 100ms delay in between. */
8f35be72 234 sr_spew("delay %dms", 100);
e31d410d 235 g_usleep(100000);
254dd102
BV
236
237 return SR_OK;
238}
239
6078d2c9 240static int init(struct sr_context *sr_ctx)
f4816ac6 241{
f6beaac5 242 return std_init(sr_ctx, di, LOG_PREFIX);
f4816ac6
ML
243}
244
3520422f 245static int probe_port(const char *resource, const char *serialcomm, GSList **devices)
f4816ac6 246{
cc9fd2d2
BV
247 struct dev_context *devc;
248 struct sr_dev_inst *sdi;
ae1bc1cc
ML
249 struct sr_scpi_dev_inst *scpi;
250 struct sr_scpi_hw_info *hw_info;
cc9fd2d2 251 struct sr_probe *probe;
f6a0ac9f 252 unsigned int i;
bafd4890 253 const struct rigol_ds_model *model = NULL;
ae1bc1cc 254 gchar *channel_name;
fb6e5ba8 255
46a743c1 256 *devices = NULL;
0dc7b43e 257
c3515cea
AJ
258 if (!(scpi = scpi_dev_inst_new(resource, serialcomm)))
259 return SR_ERR;
9bd4c956 260
ae1bc1cc 261 if (sr_scpi_open(scpi) != SR_OK) {
10afee13 262 sr_info("Couldn't open SCPI device.");
ae1bc1cc 263 sr_scpi_free(scpi);
9bd4c956 264 return SR_ERR;
ae1bc1cc 265 };
9bd4c956 266
ae1bc1cc
ML
267 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
268 sr_info("Couldn't get IDN response.");
269 sr_scpi_close(scpi);
270 sr_scpi_free(scpi);
271 return SR_ERR;
ca55277c 272 }
e0b7d23c 273
ca55277c 274 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
10afee13
ML
275 if (!strcasecmp(hw_info->manufacturer, supported_models[i].vendor) &&
276 !strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 277 model = &supported_models[i];
ca55277c 278 break;
fb6e5ba8 279 }
ca55277c 280 }
fb6e5ba8 281
bafd4890 282 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
ae1bc1cc
ML
283 hw_info->manufacturer, hw_info->model,
284 hw_info->firmware_version))) {
285 sr_scpi_hw_info_free(hw_info);
b4936bae 286 sr_scpi_close(scpi);
ae1bc1cc 287 sr_scpi_free(scpi);
ca55277c
ML
288 return SR_ERR_NA;
289 }
fb6e5ba8 290
ae1bc1cc 291 sr_scpi_hw_info_free(hw_info);
b4936bae 292 sr_scpi_close(scpi);
ae1bc1cc
ML
293
294 sdi->conn = scpi;
fb6e5ba8 295
cc9fd2d2 296 sdi->driver = di;
ae1bc1cc 297 sdi->inst_type = SR_INST_SCPI;
512bb890 298
cc9fd2d2 299 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
ca55277c 300 return SR_ERR_MALLOC;
ae1bc1cc 301
cc9fd2d2 302 devc->limit_frames = 0;
bafd4890 303 devc->model = model;
512bb890 304
821fbcad
ML
305 for (i = 0; i < model->analog_channels; i++) {
306 if (!(channel_name = g_strdup_printf("CH%d", i + 1)))
ca55277c 307 return SR_ERR_MALLOC;
821fbcad 308 probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name);
ca55277c 309 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
310 devc->analog_groups[i].name = channel_name;
311 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
312 sdi->probe_groups = g_slist_append(sdi->probe_groups,
313 &devc->analog_groups[i]);
ca55277c 314 }
512bb890 315
bafd4890 316 if (devc->model->has_digital) {
ca55277c
ML
317 for (i = 0; i < 16; i++) {
318 if (!(channel_name = g_strdup_printf("D%d", i)))
319 return SR_ERR_MALLOC;
320 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
321 g_free(channel_name);
322 if (!probe)
323 return SR_ERR_MALLOC;
324 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
325 devc->digital_group.probes = g_slist_append(
326 devc->digital_group.probes, probe);
512bb890 327 }
b3916147
ML
328 devc->digital_group.name = "LA";
329 sdi->probe_groups = g_slist_append(sdi->probe_groups,
330 &devc->digital_group);
ca55277c 331 }
bafd4890
ML
332
333 for (i = 0; i < NUM_TIMEBASE; i++) {
334 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
335 devc->timebases = &timebases[i];
336 if (!memcmp(&devc->model->max_timebase, &timebases[i], sizeof(uint64_t[2])))
337 devc->num_timebases = &timebases[i] - devc->timebases + 1;
338 }
339
0709197d
ML
340 for (i = 0; i < NUM_VDIV; i++)
341 if (!memcmp(&devc->model->min_vdiv, &vdivs[i], sizeof(uint64_t[2])))
6ff1394e 342 devc->vdivs = &vdivs[i];
bafd4890 343
babab622
ML
344 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
345 return SR_ERR_MALLOC;
346 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
347 return SR_ERR_MALLOC;
348
349 devc->data_source = DATA_SOURCE_LIVE;
350
cc9fd2d2
BV
351 sdi->priv = devc;
352
353 *devices = g_slist_append(NULL, sdi);
512bb890 354
ca55277c
ML
355 return SR_OK;
356}
512bb890 357
6078d2c9 358static GSList *scan(GSList *options)
ca55277c
ML
359{
360 struct drv_context *drvc;
ca55277c 361 struct sr_config *src;
cc9fd2d2 362 GSList *l, *devices;
ca55277c 363 GDir *dir;
ca55277c 364 int ret;
cc9fd2d2
BV
365 const gchar *dev_name;
366 gchar *port = NULL;
0dc7b43e 367 gchar *serialcomm = NULL;
fb6e5ba8 368
ca55277c 369 drvc = di->priv;
d2e0b1fa 370
ca55277c
ML
371 for (l = options; l; l = l->next) {
372 src = l->data;
0dc7b43e
ML
373 switch (src->key) {
374 case SR_CONF_CONN:
cc9fd2d2 375 port = (char *)g_variant_get_string(src->data, NULL);
ca55277c 376 break;
0dc7b43e
ML
377 case SR_CONF_SERIALCOMM:
378 serialcomm = (char *)g_variant_get_string(src->data, NULL);
379 break;
fb6e5ba8 380 }
ca55277c 381 }
fb6e5ba8 382
46a743c1 383 devices = NULL;
cc9fd2d2 384 if (port) {
0dc7b43e
ML
385 if (probe_port(port, serialcomm, &devices) == SR_ERR_MALLOC) {
386 g_free(port);
387 if (serialcomm)
388 g_free(serialcomm);
ca55277c 389 return NULL;
0dc7b43e 390 }
ca55277c 391 } else {
da970d24
BV
392 if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
393 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
394 return NULL;
ca55277c 395 while ((dev_name = g_dir_read_name(dir))) {
cc9fd2d2 396 if (strncmp(dev_name, "usbtmc", 6))
ca55277c 397 continue;
cc9fd2d2 398 port = g_strconcat("/dev/", dev_name, NULL);
0dc7b43e 399 ret = probe_port(port, serialcomm, &devices);
cc9fd2d2 400 g_free(port);
0dc7b43e
ML
401 if (serialcomm)
402 g_free(serialcomm);
ca55277c
ML
403 if (ret == SR_ERR_MALLOC) {
404 g_dir_close(dir);
ca55277c 405 return NULL;
6bb192bc
ML
406 }
407 }
ca55277c
ML
408 g_dir_close(dir);
409 }
f4816ac6 410
46a743c1
BV
411 /* Tack a copy of the newly found devices onto the driver list. */
412 l = g_slist_copy(devices);
413 drvc->instances = g_slist_concat(drvc->instances, l);
cc9fd2d2 414
f4816ac6
ML
415 return devices;
416}
417
6078d2c9 418static GSList *dev_list(void)
f4816ac6 419{
0e94d524 420 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
421}
422
6078d2c9 423static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 424{
ae1bc1cc 425 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 426
ae1bc1cc 427 if (sr_scpi_open(scpi) < 0)
e0b7d23c 428 return SR_ERR;
e0b7d23c 429
3086efdd 430 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 431 return SR_ERR;
f4816ac6 432
46a743c1 433 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 434
f4816ac6
ML
435 return SR_OK;
436}
437
6078d2c9 438static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 439{
ae1bc1cc
ML
440 struct sr_scpi_dev_inst *scpi;
441
442 scpi = sdi->conn;
e0b7d23c 443
ae1bc1cc
ML
444 if (scpi) {
445 if (sr_scpi_close(scpi) < 0)
446 return SR_ERR;
cc9fd2d2
BV
447 sdi->status = SR_ST_INACTIVE;
448 }
f4816ac6
ML
449
450 return SR_OK;
451}
452
6078d2c9 453static int cleanup(void)
f4816ac6 454{
3b412e3a 455 return dev_clear();
f4816ac6
ML
456}
457
8f996b89
ML
458static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
459 const struct sr_probe_group *probe_group)
d62d7ad1 460{
e43fdd8d 461 struct dev_context *devc;
d62d7ad1 462
e43fdd8d
BV
463 if (!sdi || !(devc = sdi->priv))
464 return SR_ERR_ARG;
465
be60a9e4
BV
466 /* If a probe group is specified, it must be a valid one. */
467 if (probe_group) {
468 if (probe_group != &devc->analog_groups[0]
469 && probe_group != &devc->analog_groups[1]) {
470 sr_err("Invalid probe group specified.");
471 return SR_ERR;
472 }
473 }
474
d62d7ad1
BV
475 switch (id) {
476 case SR_CONF_NUM_TIMEBASE:
0709197d 477 *data = g_variant_new_int32(devc->model->num_horizontal_divs);
d62d7ad1
BV
478 break;
479 case SR_CONF_NUM_VDIV:
0709197d 480 *data = g_variant_new_int32(8);
babab622
ML
481 case SR_CONF_DATA_SOURCE:
482 if (devc->data_source == DATA_SOURCE_LIVE)
483 *data = g_variant_new_string("Live");
484 else if (devc->data_source == DATA_SOURCE_MEMORY)
485 *data = g_variant_new_string("Memory");
486 else
487 *data = g_variant_new_string("Segmented");
488 break;
d62d7ad1 489 default:
bd6fbf62 490 return SR_ERR_NA;
d62d7ad1
BV
491 }
492
493 return SR_OK;
494}
495
8f996b89
ML
496static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
497 const struct sr_probe_group *probe_group)
f4816ac6 498{
29d957ce 499 struct dev_context *devc;
f6a0ac9f 500 uint64_t tmp_u64, p, q;
254dd102 501 double t_dbl;
f48e0249 502 unsigned int i, j;
254dd102
BV
503 int ret;
504 const char *tmp_str;
f4816ac6 505
e43fdd8d
BV
506 if (!(devc = sdi->priv))
507 return SR_ERR_ARG;
29d957ce 508
e73ffd42
BV
509 if (sdi->status != SR_ST_ACTIVE)
510 return SR_ERR_DEV_CLOSED;
f4816ac6 511
be60a9e4
BV
512 /* If a probe group is specified, it must be a valid one. */
513 if (probe_group) {
514 if (probe_group != &devc->analog_groups[0]
515 && probe_group != &devc->analog_groups[1]) {
516 sr_err("Invalid probe group specified.");
517 return SR_ERR;
518 }
519 }
520
f4816ac6 521 ret = SR_OK;
035a1078 522 switch (id) {
1953564a 523 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 524 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 525 break;
1953564a 526 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 527 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
528 if (tmp_u64 != 0 && tmp_u64 != 1)
529 return SR_ERR;
530 g_free(devc->trigger_slope);
531 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
532 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 533 break;
1953564a 534 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
535 t_dbl = g_variant_get_double(data);
536 if (t_dbl < 0.0 || t_dbl > 1.0)
537 return SR_ERR;
538 devc->horiz_triggerpos = t_dbl;
539 /* We have the trigger offset as a percentage of the frame, but
540 * need to express this in seconds. */
bafd4890 541 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
254dd102 542 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 543 break;
1953564a 544 case SR_CONF_TIMEBASE:
f6a0ac9f 545 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
546 for (i = 0; i < devc->num_timebases; i++) {
547 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102
BV
548 devc->timebase = (float)p / q;
549 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
550 break;
551 }
552 }
bafd4890 553 if (i == devc->num_timebases)
254dd102 554 ret = SR_ERR_ARG;
e0b7d23c 555 break;
1953564a 556 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 557 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
558 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
559 if (!strcmp(trigger_sources[i], tmp_str)) {
560 g_free(devc->trigger_source);
561 devc->trigger_source = g_strdup(trigger_sources[i]);
562 if (!strcmp(devc->trigger_source, "AC Line"))
563 tmp_str = "ACL";
564 else if (!strcmp(devc->trigger_source, "CH1"))
565 tmp_str = "CHAN1";
566 else if (!strcmp(devc->trigger_source, "CH2"))
567 tmp_str = "CHAN2";
821fbcad
ML
568 else if (!strcmp(devc->trigger_source, "CH3"))
569 tmp_str = "CHAN3";
570 else if (!strcmp(devc->trigger_source, "CH4"))
571 tmp_str = "CHAN4";
254dd102
BV
572 else
573 tmp_str = (char *)devc->trigger_source;
574 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
575 break;
576 }
4e108ace 577 }
254dd102
BV
578 if (i == ARRAY_SIZE(trigger_sources))
579 ret = SR_ERR_ARG;
e0b7d23c 580 break;
1953564a 581 case SR_CONF_VDIV:
be60a9e4
BV
582 if (!probe_group) {
583 sr_err("No probe group specified.");
584 return SR_ERR_PROBE_GROUP;
585 }
f6a0ac9f 586 g_variant_get(data, "(tt)", &p, &q);
f48e0249 587 for (i = 0; i < 2; i++) {
78bcc55a
BV
588 if (probe_group == &devc->analog_groups[i]) {
589 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
590 if (vdivs[j][0] != p || vdivs[j][1] != q)
591 continue;
592 devc->vdiv[i] = (float)p / q;
593 return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
594 devc->vdiv[i]);
595 }
596 return SR_ERR_ARG;
597 }
e0b7d23c 598 }
f48e0249 599 return SR_ERR_NA;
1953564a 600 case SR_CONF_COUPLING:
78bcc55a
BV
601 if (!probe_group) {
602 sr_err("No probe group specified.");
603 return SR_ERR_PROBE_GROUP;
604 }
f6a0ac9f 605 tmp_str = g_variant_get_string(data, NULL);
f48e0249 606 for (i = 0; i < 2; i++) {
78bcc55a
BV
607 if (probe_group == &devc->analog_groups[i]) {
608 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
609 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
610 g_free(devc->coupling[i]);
611 devc->coupling[i] = g_strdup(coupling[j]);
612 return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
613 devc->coupling[i]);
614 }
615 }
616 return SR_ERR_ARG;
e0b7d23c
ML
617 }
618 }
f48e0249 619 return SR_ERR_NA;
babab622
ML
620 case SR_CONF_DATA_SOURCE:
621 tmp_str = g_variant_get_string(data, NULL);
622 if (!strcmp(tmp_str, "Live"))
623 devc->data_source = DATA_SOURCE_LIVE;
624 else if (!strcmp(tmp_str, "Memory"))
625 devc->data_source = DATA_SOURCE_MEMORY;
626 else if (devc->model->protocol == PROTOCOL_IEEE488_2
627 && !strcmp(tmp_str, "Segmented"))
628 devc->data_source = DATA_SOURCE_SEGMENTED;
629 else
630 return SR_ERR;
631 break;
f4816ac6 632 default:
bd6fbf62 633 ret = SR_ERR_NA;
29d957ce 634 break;
f4816ac6
ML
635 }
636
637 return ret;
638}
639
8f996b89
ML
640static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
641 const struct sr_probe_group *probe_group)
a1c743fc 642{
861c447b
BV
643 GVariant *tuple, *rational[2];
644 GVariantBuilder gvb;
645 unsigned int i;
7cc1a550
ML
646 struct dev_context *devc = NULL;
647
648 if (sdi)
649 devc = sdi->priv;
8f996b89 650
e43fdd8d 651 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
652 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
653 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d
BV
654 return SR_OK;
655 } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
656 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
657 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
658 return SR_OK;
659 }
660
661 /* Every other option requires a valid device instance. */
662 if (!sdi || !(devc = sdi->priv))
663 return SR_ERR_ARG;
664
be60a9e4
BV
665 /* If a probe group is specified, it must be a valid one. */
666 if (probe_group) {
667 if (probe_group != &devc->analog_groups[0]
668 && probe_group != &devc->analog_groups[1]) {
669 sr_err("Invalid probe group specified.");
670 return SR_ERR;
671 }
672 }
673
e43fdd8d 674 switch (key) {
ca55277c 675 break;
9a6517d1 676 case SR_CONF_DEVICE_OPTIONS:
be60a9e4
BV
677 if (!probe_group) {
678 sr_err("No probe group specified.");
679 return SR_ERR_PROBE_GROUP;
680 }
e43fdd8d 681 if (probe_group == &devc->digital_group) {
f48e0249
ML
682 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
683 NULL, 0, sizeof(int32_t));
684 return SR_OK;
685 } else {
686 for (i = 0; i < 2; i++) {
687 if (probe_group == &devc->analog_groups[i]) {
688 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
689 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
690 return SR_OK;
691 }
692 }
693 return SR_ERR_NA;
694 }
5f77dffc 695 break;
2a7b113d 696 case SR_CONF_COUPLING:
be60a9e4
BV
697 if (!probe_group) {
698 sr_err("No probe group specified.");
699 return SR_ERR_PROBE_GROUP;
f48e0249 700 }
58f43369
BV
701 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
702 break;
e4f2b2ad 703 case SR_CONF_VDIV:
7cc1a550
ML
704 if (!devc)
705 /* Can't know this until we have the exact model. */
706 return SR_ERR_ARG;
be60a9e4
BV
707 if (!probe_group) {
708 sr_err("No probe group specified.");
709 return SR_ERR_PROBE_GROUP;
861c447b 710 }
58f43369 711 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
0709197d 712 for (i = 0; i < NUM_VDIV; i++) {
bafd4890
ML
713 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
714 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
715 tuple = g_variant_new_tuple(rational, 2);
716 g_variant_builder_add_value(&gvb, tuple);
717 }
718 *data = g_variant_builder_end(&gvb);
719 break;
41f5bd09 720 case SR_CONF_TIMEBASE:
7cc1a550
ML
721 if (!devc)
722 /* Can't know this until we have the exact model. */
723 return SR_ERR_ARG;
861c447b 724 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
725 for (i = 0; i < devc->num_timebases; i++) {
726 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
727 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
728 tuple = g_variant_new_tuple(rational, 2);
729 g_variant_builder_add_value(&gvb, tuple);
730 }
731 *data = g_variant_builder_end(&gvb);
41f5bd09 732 break;
328bafab 733 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
734 if (!devc)
735 /* Can't know this until we have the exact model. */
736 return SR_ERR_ARG;
f6a0ac9f 737 *data = g_variant_new_strv(trigger_sources,
bafd4890 738 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 739 break;
babab622
ML
740 case SR_CONF_DATA_SOURCE:
741 if (!devc)
742 /* Can't know this until we have the exact model. */
743 return SR_ERR_ARG;
744 /* This needs tweaking by series/model! */
745 if (devc->model->series == RIGOL_DS2000)
746 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
747 else
748 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
749 break;
a1c743fc 750 default:
bd6fbf62 751 return SR_ERR_NA;
a1c743fc
BV
752 }
753
754 return SR_OK;
755}
756
254dd102 757static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 758{
ae1bc1cc 759 struct sr_scpi_dev_inst *scpi;
29d957ce 760 struct dev_context *devc;
254dd102
BV
761 struct sr_probe *probe;
762 GSList *l;
29d957ce 763
e73ffd42
BV
764 if (sdi->status != SR_ST_ACTIVE)
765 return SR_ERR_DEV_CLOSED;
e0b7d23c 766
ae1bc1cc 767 scpi = sdi->conn;
29d957ce
UH
768 devc = sdi->priv;
769
254dd102
BV
770 for (l = sdi->probes; l; l = l->next) {
771 probe = l->data;
6bb192bc
ML
772 sr_dbg("handling probe %s", probe->name);
773 if (probe->type == SR_PROBE_ANALOG) {
774 if (probe->enabled)
775 devc->enabled_analog_probes = g_slist_append(
776 devc->enabled_analog_probes, probe);
777 if (probe->enabled != devc->analog_channels[probe->index]) {
778 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
779 if (set_cfg(sdi, ":CHAN%d:DISP %s", probe->index + 1,
780 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
781 return SR_ERR;
782 }
783 } else if (probe->type == SR_PROBE_LOGIC) {
784 if (probe->enabled)
785 devc->enabled_digital_probes = g_slist_append(
786 devc->enabled_digital_probes, probe);
787 if (probe->enabled != devc->digital_channels[probe->index]) {
788 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
789 if (set_cfg(sdi, ":DIG%d:TURN %s", probe->index,
790 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
791 return SR_ERR;
792 }
254dd102
BV
793 }
794 }
1fed20cb 795
6bb192bc 796 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 797 return SR_ERR;
e0b7d23c 798
1fed20cb 799 if (devc->data_source == DATA_SOURCE_LIVE) {
6396b0a7 800 if (set_cfg(sdi, ":RUN") != SR_OK)
1fed20cb
ML
801 return SR_ERR;
802 } else if (devc->data_source == DATA_SOURCE_MEMORY) {
803 if (devc->model->series != RIGOL_DS2000) {
804 sr_err("Data source 'Memory' not supported for this device");
805 return SR_ERR;
806 }
807 } else if (devc->data_source == DATA_SOURCE_SEGMENTED) {
808 sr_err("Data source 'Segmented' not yet supported");
809 return SR_ERR;
810 }
811
ae1bc1cc 812 sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
813
814 /* Send header packet to the session bus. */
29a27196 815 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 816
821fbcad
ML
817 if (devc->enabled_analog_probes)
818 devc->channel_entry = devc->enabled_analog_probes;
819 else
820 devc->channel_entry = devc->enabled_digital_probes;
821
babab622 822 if (devc->model->protocol == PROTOCOL_LEGACY) {
9e4b7d98
ML
823 devc->analog_frame_size = (devc->model->series == RIGOL_VS5000 ?
824 VS5000_ANALOG_LIVE_WAVEFORM_SIZE :
825 DS1000_ANALOG_LIVE_WAVEFORM_SIZE);
bafd4890 826 /* Fetch the first frame. */
677f85d0
ML
827 if (rigol_ds_channel_start(sdi) != SR_OK)
828 return SR_ERR;
6bb192bc 829 } else {
bafd4890 830 if (devc->enabled_analog_probes) {
babab622
ML
831 if (devc->data_source == DATA_SOURCE_MEMORY)
832 {
833 if (g_slist_length(devc->enabled_analog_probes) == 1)
834 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C;
835 else
836 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C;
837 /* Apparently for the DS2000 the memory
838 * depth can only be set in Running state -
839 * this matches the behaviour of the UI. */
6396b0a7 840 if (set_cfg(sdi, ":RUN") != SR_OK)
babab622 841 return SR_ERR;
6396b0a7 842 if (set_cfg(sdi, "ACQ:MDEP %d", devc->analog_frame_size) != SR_OK)
babab622 843 return SR_ERR;
6396b0a7 844 if (set_cfg(sdi, ":STOP") != SR_OK)
babab622 845 return SR_ERR;
0d9f5a12
ML
846 } else {
847 if (devc->model->series == AGILENT_DSO1000)
848 devc->analog_frame_size = DSO1000_ANALOG_LIVE_WAVEFORM_SIZE;
849 else
850 devc->analog_frame_size = DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
851 }
babab622 852 if (rigol_ds_capture_start(sdi) != SR_OK)
bafd4890
ML
853 return SR_ERR;
854 }
6bb192bc 855 }
f4816ac6
ML
856
857 return SR_OK;
858}
859
254dd102 860static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 861{
29d957ce 862 struct dev_context *devc;
ae1bc1cc 863 struct sr_scpi_dev_inst *scpi;
29d957ce 864
f4816ac6
ML
865 (void)cb_data;
866
29d957ce
UH
867 devc = sdi->priv;
868
f4816ac6
ML
869 if (sdi->status != SR_ST_ACTIVE) {
870 sr_err("Device inactive, can't stop acquisition.");
871 return SR_ERR;
872 }
873
6bb192bc
ML
874 g_slist_free(devc->enabled_analog_probes);
875 g_slist_free(devc->enabled_digital_probes);
876 devc->enabled_analog_probes = NULL;
877 devc->enabled_digital_probes = NULL;
ae1bc1cc
ML
878 scpi = sdi->conn;
879 sr_scpi_source_remove(scpi);
f4816ac6
ML
880
881 return SR_OK;
882}
883
3086efdd
ML
884SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
885 .name = "rigol-ds",
886 .longname = "Rigol DS",
f4816ac6 887 .api_version = 1,
6078d2c9
UH
888 .init = init,
889 .cleanup = cleanup,
890 .scan = scan,
891 .dev_list = dev_list,
3b412e3a 892 .dev_clear = dev_clear,
d62d7ad1 893 .config_get = config_get,
035a1078 894 .config_set = config_set,
a1c743fc 895 .config_list = config_list,
6078d2c9
UH
896 .dev_open = dev_open,
897 .dev_close = dev_close,
254dd102
BV
898 .dev_acquisition_start = dev_acquisition_start,
899 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
900 .priv = NULL,
901};