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