]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
rigol-ds: Fix check for probe group validity.
[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 466 /* If a probe group is specified, it must be a valid one. */
969edf63
ML
467 if (probe_group && !g_slist_find(sdi->probe_groups, probe_group))
468 {
469 sr_err("Invalid probe group specified.");
470 return SR_ERR;
be60a9e4
BV
471 }
472
d62d7ad1
BV
473 switch (id) {
474 case SR_CONF_NUM_TIMEBASE:
0709197d 475 *data = g_variant_new_int32(devc->model->num_horizontal_divs);
d62d7ad1
BV
476 break;
477 case SR_CONF_NUM_VDIV:
0709197d 478 *data = g_variant_new_int32(8);
babab622
ML
479 case SR_CONF_DATA_SOURCE:
480 if (devc->data_source == DATA_SOURCE_LIVE)
481 *data = g_variant_new_string("Live");
482 else if (devc->data_source == DATA_SOURCE_MEMORY)
483 *data = g_variant_new_string("Memory");
484 else
485 *data = g_variant_new_string("Segmented");
486 break;
d62d7ad1 487 default:
bd6fbf62 488 return SR_ERR_NA;
d62d7ad1
BV
489 }
490
491 return SR_OK;
492}
493
8f996b89
ML
494static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
495 const struct sr_probe_group *probe_group)
f4816ac6 496{
29d957ce 497 struct dev_context *devc;
f6a0ac9f 498 uint64_t tmp_u64, p, q;
254dd102 499 double t_dbl;
f48e0249 500 unsigned int i, j;
254dd102
BV
501 int ret;
502 const char *tmp_str;
f4816ac6 503
e43fdd8d
BV
504 if (!(devc = sdi->priv))
505 return SR_ERR_ARG;
29d957ce 506
e73ffd42
BV
507 if (sdi->status != SR_ST_ACTIVE)
508 return SR_ERR_DEV_CLOSED;
f4816ac6 509
be60a9e4 510 /* If a probe group is specified, it must be a valid one. */
969edf63
ML
511 if (probe_group && !g_slist_find(sdi->probe_groups, probe_group))
512 {
513 sr_err("Invalid probe group specified.");
514 return SR_ERR;
be60a9e4
BV
515 }
516
f4816ac6 517 ret = SR_OK;
035a1078 518 switch (id) {
1953564a 519 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 520 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 521 break;
1953564a 522 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 523 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
524 if (tmp_u64 != 0 && tmp_u64 != 1)
525 return SR_ERR;
526 g_free(devc->trigger_slope);
527 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
528 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 529 break;
1953564a 530 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
531 t_dbl = g_variant_get_double(data);
532 if (t_dbl < 0.0 || t_dbl > 1.0)
533 return SR_ERR;
534 devc->horiz_triggerpos = t_dbl;
535 /* We have the trigger offset as a percentage of the frame, but
536 * need to express this in seconds. */
bafd4890 537 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
254dd102 538 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 539 break;
1953564a 540 case SR_CONF_TIMEBASE:
f6a0ac9f 541 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
542 for (i = 0; i < devc->num_timebases; i++) {
543 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102
BV
544 devc->timebase = (float)p / q;
545 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
546 break;
547 }
548 }
bafd4890 549 if (i == devc->num_timebases)
254dd102 550 ret = SR_ERR_ARG;
e0b7d23c 551 break;
1953564a 552 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 553 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
554 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
555 if (!strcmp(trigger_sources[i], tmp_str)) {
556 g_free(devc->trigger_source);
557 devc->trigger_source = g_strdup(trigger_sources[i]);
558 if (!strcmp(devc->trigger_source, "AC Line"))
559 tmp_str = "ACL";
560 else if (!strcmp(devc->trigger_source, "CH1"))
561 tmp_str = "CHAN1";
562 else if (!strcmp(devc->trigger_source, "CH2"))
563 tmp_str = "CHAN2";
821fbcad
ML
564 else if (!strcmp(devc->trigger_source, "CH3"))
565 tmp_str = "CHAN3";
566 else if (!strcmp(devc->trigger_source, "CH4"))
567 tmp_str = "CHAN4";
254dd102
BV
568 else
569 tmp_str = (char *)devc->trigger_source;
570 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
571 break;
572 }
4e108ace 573 }
254dd102
BV
574 if (i == ARRAY_SIZE(trigger_sources))
575 ret = SR_ERR_ARG;
e0b7d23c 576 break;
1953564a 577 case SR_CONF_VDIV:
be60a9e4
BV
578 if (!probe_group) {
579 sr_err("No probe group specified.");
580 return SR_ERR_PROBE_GROUP;
581 }
f6a0ac9f 582 g_variant_get(data, "(tt)", &p, &q);
f48e0249 583 for (i = 0; i < 2; i++) {
78bcc55a
BV
584 if (probe_group == &devc->analog_groups[i]) {
585 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
586 if (vdivs[j][0] != p || vdivs[j][1] != q)
587 continue;
588 devc->vdiv[i] = (float)p / q;
589 return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
590 devc->vdiv[i]);
591 }
592 return SR_ERR_ARG;
593 }
e0b7d23c 594 }
f48e0249 595 return SR_ERR_NA;
1953564a 596 case SR_CONF_COUPLING:
78bcc55a
BV
597 if (!probe_group) {
598 sr_err("No probe group specified.");
599 return SR_ERR_PROBE_GROUP;
600 }
f6a0ac9f 601 tmp_str = g_variant_get_string(data, NULL);
f48e0249 602 for (i = 0; i < 2; i++) {
78bcc55a
BV
603 if (probe_group == &devc->analog_groups[i]) {
604 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
605 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
606 g_free(devc->coupling[i]);
607 devc->coupling[i] = g_strdup(coupling[j]);
608 return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
609 devc->coupling[i]);
610 }
611 }
612 return SR_ERR_ARG;
e0b7d23c
ML
613 }
614 }
f48e0249 615 return SR_ERR_NA;
babab622
ML
616 case SR_CONF_DATA_SOURCE:
617 tmp_str = g_variant_get_string(data, NULL);
618 if (!strcmp(tmp_str, "Live"))
619 devc->data_source = DATA_SOURCE_LIVE;
620 else if (!strcmp(tmp_str, "Memory"))
621 devc->data_source = DATA_SOURCE_MEMORY;
622 else if (devc->model->protocol == PROTOCOL_IEEE488_2
623 && !strcmp(tmp_str, "Segmented"))
624 devc->data_source = DATA_SOURCE_SEGMENTED;
625 else
626 return SR_ERR;
627 break;
f4816ac6 628 default:
bd6fbf62 629 ret = SR_ERR_NA;
29d957ce 630 break;
f4816ac6
ML
631 }
632
633 return ret;
634}
635
8f996b89
ML
636static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
637 const struct sr_probe_group *probe_group)
a1c743fc 638{
861c447b
BV
639 GVariant *tuple, *rational[2];
640 GVariantBuilder gvb;
641 unsigned int i;
7cc1a550
ML
642 struct dev_context *devc = NULL;
643
644 if (sdi)
645 devc = sdi->priv;
8f996b89 646
e43fdd8d 647 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
648 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
649 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d
BV
650 return SR_OK;
651 } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
652 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
653 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
654 return SR_OK;
655 }
656
657 /* Every other option requires a valid device instance. */
658 if (!sdi || !(devc = sdi->priv))
659 return SR_ERR_ARG;
660
be60a9e4
BV
661 /* If a probe group is specified, it must be a valid one. */
662 if (probe_group) {
663 if (probe_group != &devc->analog_groups[0]
664 && probe_group != &devc->analog_groups[1]) {
665 sr_err("Invalid probe group specified.");
666 return SR_ERR;
667 }
668 }
669
e43fdd8d 670 switch (key) {
9a6517d1 671 case SR_CONF_DEVICE_OPTIONS:
be60a9e4
BV
672 if (!probe_group) {
673 sr_err("No probe group specified.");
674 return SR_ERR_PROBE_GROUP;
675 }
e43fdd8d 676 if (probe_group == &devc->digital_group) {
f48e0249
ML
677 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
678 NULL, 0, sizeof(int32_t));
679 return SR_OK;
680 } else {
681 for (i = 0; i < 2; i++) {
682 if (probe_group == &devc->analog_groups[i]) {
683 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
684 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
685 return SR_OK;
686 }
687 }
688 return SR_ERR_NA;
689 }
5f77dffc 690 break;
2a7b113d 691 case SR_CONF_COUPLING:
be60a9e4
BV
692 if (!probe_group) {
693 sr_err("No probe group specified.");
694 return SR_ERR_PROBE_GROUP;
f48e0249 695 }
58f43369
BV
696 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
697 break;
e4f2b2ad 698 case SR_CONF_VDIV:
7cc1a550
ML
699 if (!devc)
700 /* Can't know this until we have the exact model. */
701 return SR_ERR_ARG;
be60a9e4
BV
702 if (!probe_group) {
703 sr_err("No probe group specified.");
704 return SR_ERR_PROBE_GROUP;
861c447b 705 }
58f43369 706 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
0709197d 707 for (i = 0; i < NUM_VDIV; i++) {
bafd4890
ML
708 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
709 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
710 tuple = g_variant_new_tuple(rational, 2);
711 g_variant_builder_add_value(&gvb, tuple);
712 }
713 *data = g_variant_builder_end(&gvb);
714 break;
41f5bd09 715 case SR_CONF_TIMEBASE:
7cc1a550
ML
716 if (!devc)
717 /* Can't know this until we have the exact model. */
718 return SR_ERR_ARG;
a31b2ccb
AJ
719 if (devc->num_timebases <= 0)
720 return SR_ERR_NA;
861c447b 721 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
722 for (i = 0; i < devc->num_timebases; i++) {
723 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
724 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
725 tuple = g_variant_new_tuple(rational, 2);
726 g_variant_builder_add_value(&gvb, tuple);
727 }
728 *data = g_variant_builder_end(&gvb);
41f5bd09 729 break;
328bafab 730 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
731 if (!devc)
732 /* Can't know this until we have the exact model. */
733 return SR_ERR_ARG;
f6a0ac9f 734 *data = g_variant_new_strv(trigger_sources,
bafd4890 735 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 736 break;
babab622
ML
737 case SR_CONF_DATA_SOURCE:
738 if (!devc)
739 /* Can't know this until we have the exact model. */
740 return SR_ERR_ARG;
741 /* This needs tweaking by series/model! */
742 if (devc->model->series == RIGOL_DS2000)
743 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
744 else
745 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
746 break;
a1c743fc 747 default:
bd6fbf62 748 return SR_ERR_NA;
a1c743fc
BV
749 }
750
751 return SR_OK;
752}
753
254dd102 754static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 755{
ae1bc1cc 756 struct sr_scpi_dev_inst *scpi;
29d957ce 757 struct dev_context *devc;
254dd102
BV
758 struct sr_probe *probe;
759 GSList *l;
29d957ce 760
e73ffd42
BV
761 if (sdi->status != SR_ST_ACTIVE)
762 return SR_ERR_DEV_CLOSED;
e0b7d23c 763
ae1bc1cc 764 scpi = sdi->conn;
29d957ce
UH
765 devc = sdi->priv;
766
254dd102
BV
767 for (l = sdi->probes; l; l = l->next) {
768 probe = l->data;
6bb192bc
ML
769 sr_dbg("handling probe %s", probe->name);
770 if (probe->type == SR_PROBE_ANALOG) {
771 if (probe->enabled)
772 devc->enabled_analog_probes = g_slist_append(
773 devc->enabled_analog_probes, probe);
774 if (probe->enabled != devc->analog_channels[probe->index]) {
775 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
776 if (set_cfg(sdi, ":CHAN%d:DISP %s", probe->index + 1,
777 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
778 return SR_ERR;
779 }
780 } else if (probe->type == SR_PROBE_LOGIC) {
781 if (probe->enabled)
782 devc->enabled_digital_probes = g_slist_append(
783 devc->enabled_digital_probes, probe);
784 if (probe->enabled != devc->digital_channels[probe->index]) {
785 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
786 if (set_cfg(sdi, ":DIG%d:TURN %s", probe->index,
787 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
788 return SR_ERR;
789 }
254dd102
BV
790 }
791 }
1fed20cb 792
6bb192bc 793 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 794 return SR_ERR;
e0b7d23c 795
1fed20cb 796 if (devc->data_source == DATA_SOURCE_LIVE) {
6396b0a7 797 if (set_cfg(sdi, ":RUN") != SR_OK)
1fed20cb
ML
798 return SR_ERR;
799 } else if (devc->data_source == DATA_SOURCE_MEMORY) {
800 if (devc->model->series != RIGOL_DS2000) {
801 sr_err("Data source 'Memory' not supported for this device");
802 return SR_ERR;
803 }
804 } else if (devc->data_source == DATA_SOURCE_SEGMENTED) {
805 sr_err("Data source 'Segmented' not yet supported");
806 return SR_ERR;
807 }
808
ae1bc1cc 809 sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
810
811 /* Send header packet to the session bus. */
29a27196 812 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 813
821fbcad
ML
814 if (devc->enabled_analog_probes)
815 devc->channel_entry = devc->enabled_analog_probes;
816 else
817 devc->channel_entry = devc->enabled_digital_probes;
818
babab622 819 if (devc->model->protocol == PROTOCOL_LEGACY) {
9e4b7d98
ML
820 devc->analog_frame_size = (devc->model->series == RIGOL_VS5000 ?
821 VS5000_ANALOG_LIVE_WAVEFORM_SIZE :
822 DS1000_ANALOG_LIVE_WAVEFORM_SIZE);
bafd4890 823 /* Fetch the first frame. */
677f85d0
ML
824 if (rigol_ds_channel_start(sdi) != SR_OK)
825 return SR_ERR;
6bb192bc 826 } else {
bafd4890 827 if (devc->enabled_analog_probes) {
babab622
ML
828 if (devc->data_source == DATA_SOURCE_MEMORY)
829 {
830 if (g_slist_length(devc->enabled_analog_probes) == 1)
831 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C;
832 else
833 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C;
834 /* Apparently for the DS2000 the memory
835 * depth can only be set in Running state -
836 * this matches the behaviour of the UI. */
6396b0a7 837 if (set_cfg(sdi, ":RUN") != SR_OK)
babab622 838 return SR_ERR;
6396b0a7 839 if (set_cfg(sdi, "ACQ:MDEP %d", devc->analog_frame_size) != SR_OK)
babab622 840 return SR_ERR;
6396b0a7 841 if (set_cfg(sdi, ":STOP") != SR_OK)
babab622 842 return SR_ERR;
0d9f5a12
ML
843 } else {
844 if (devc->model->series == AGILENT_DSO1000)
845 devc->analog_frame_size = DSO1000_ANALOG_LIVE_WAVEFORM_SIZE;
846 else
847 devc->analog_frame_size = DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
848 }
babab622 849 if (rigol_ds_capture_start(sdi) != SR_OK)
bafd4890
ML
850 return SR_ERR;
851 }
6bb192bc 852 }
f4816ac6
ML
853
854 return SR_OK;
855}
856
254dd102 857static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 858{
29d957ce 859 struct dev_context *devc;
ae1bc1cc 860 struct sr_scpi_dev_inst *scpi;
29d957ce 861
f4816ac6
ML
862 (void)cb_data;
863
29d957ce
UH
864 devc = sdi->priv;
865
f4816ac6
ML
866 if (sdi->status != SR_ST_ACTIVE) {
867 sr_err("Device inactive, can't stop acquisition.");
868 return SR_ERR;
869 }
870
6bb192bc
ML
871 g_slist_free(devc->enabled_analog_probes);
872 g_slist_free(devc->enabled_digital_probes);
873 devc->enabled_analog_probes = NULL;
874 devc->enabled_digital_probes = NULL;
ae1bc1cc
ML
875 scpi = sdi->conn;
876 sr_scpi_source_remove(scpi);
f4816ac6
ML
877
878 return SR_OK;
879}
880
3086efdd
ML
881SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
882 .name = "rigol-ds",
883 .longname = "Rigol DS",
f4816ac6 884 .api_version = 1,
6078d2c9
UH
885 .init = init,
886 .cleanup = cleanup,
887 .scan = scan,
888 .dev_list = dev_list,
3b412e3a 889 .dev_clear = dev_clear,
d62d7ad1 890 .config_get = config_get,
035a1078 891 .config_set = config_set,
a1c743fc 892 .config_list = config_list,
6078d2c9
UH
893 .dev_open = dev_open,
894 .dev_close = dev_close,
254dd102
BV
895 .dev_acquisition_start = dev_acquisition_start,
896 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
897 .priv = NULL,
898};