]> sigrok.org Git - libsigrok.git/blob - hardware/rigol-ds1xx2/api.c
drivers: return SR_ERR_NA on unsupported config key
[libsigrok.git] / hardware / rigol-ds1xx2 / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
5  * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib.h>
26 #include "libsigrok.h"
27 #include "libsigrok-internal.h"
28 #include "protocol.h"
29
30 #define NUM_TIMEBASE  12
31 #define NUM_VDIV      8
32
33 static const int32_t hwcaps[] = {
34         SR_CONF_OSCILLOSCOPE,
35         SR_CONF_TIMEBASE,
36         SR_CONF_TRIGGER_SOURCE,
37         SR_CONF_TRIGGER_SLOPE,
38         SR_CONF_HORIZ_TRIGGERPOS,
39         SR_CONF_VDIV,
40         SR_CONF_COUPLING,
41         SR_CONF_NUM_TIMEBASE,
42         SR_CONF_NUM_VDIV,
43 };
44
45 static const uint64_t timebases[][2] = {
46         /* nanoseconds */
47         { 2, 1000000000 },
48         { 5, 1000000000 },
49         { 10, 1000000000 },
50         { 20, 1000000000 },
51         { 50, 1000000000 },
52         { 100, 1000000000 },
53         { 500, 1000000000 },
54         /* microseconds */
55         { 1, 1000000 },
56         { 2, 1000000 },
57         { 5, 1000000 },
58         { 10, 1000000 },
59         { 20, 1000000 },
60         { 50, 1000000 },
61         { 100, 1000000 },
62         { 200, 1000000 },
63         { 500, 1000000 },
64         /* milliseconds */
65         { 1, 1000 },
66         { 2, 1000 },
67         { 5, 1000 },
68         { 10, 1000 },
69         { 20, 1000 },
70         { 50, 1000 },
71         { 100, 1000 },
72         { 200, 1000 },
73         { 500, 1000 },
74         /* seconds */
75         { 1, 1 },
76         { 2, 1 },
77         { 5, 1 },
78         { 10, 1 },
79         { 20, 1 },
80         { 50, 1 },
81 };
82
83 static const uint64_t vdivs[][2] = {
84         /* millivolts */
85         { 2, 1000 },
86         { 5, 1000 },
87         { 10, 1000 },
88         { 20, 1000 },
89         { 50, 1000 },
90         { 100, 1000 },
91         { 200, 1000 },
92         { 500, 1000 },
93         /* volts */
94         { 1, 1 },
95         { 2, 1 },
96         { 5, 1 },
97         { 10, 1 },
98 };
99
100 static const char *trigger_sources[] = {
101         "CH1",
102         "CH2",
103         "EXT",
104         "AC Line",
105         "D0",
106         "D1",
107         "D2",
108         "D3",
109         "D4",
110         "D5",
111         "D6",
112         "D7",
113         "D8",
114         "D9",
115         "D10",
116         "D11",
117         "D12",
118         "D13",
119         "D14",
120         "D15",
121 };
122
123 static const char *coupling[] = {
124         "AC",
125         "DC",
126         "GND",
127 };
128
129 static const char *supported_models[] = {
130         "DS1052E",
131         "DS1102E",
132         "DS1052D",
133         "DS1102D",
134 };
135
136 SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info;
137 static struct sr_dev_driver *di = &rigol_ds1xx2_driver_info;
138
139 /* Properly close and free all devices. */
140 static int clear_instances(void)
141 {
142         struct sr_dev_inst *sdi;
143         struct drv_context *drvc;
144         struct dev_context *devc;
145         GSList *l;
146
147         if (!(drvc = di->priv))
148                 return SR_OK;
149
150         for (l = drvc->instances; l; l = l->next) {
151                 if (!(sdi = l->data))
152                         continue;
153                 if (!(devc = sdi->priv))
154                         continue;
155
156                 g_free(devc->device);
157                 g_free(devc->coupling[0]);
158                 g_free(devc->coupling[1]);
159                 g_free(devc->trigger_source);
160                 g_free(devc->trigger_slope);
161                 close(devc->fd);
162
163                 sr_dev_inst_free(sdi);
164         }
165
166         g_slist_free(drvc->instances);
167         drvc->instances = NULL;
168
169         return SR_OK;
170 }
171
172 static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
173 {
174         struct dev_context *devc;
175         va_list args;
176         char buf[256];
177
178         devc = sdi->priv;
179
180         va_start(args, format);
181         vsnprintf(buf, 255, format, args);
182         va_end(args);
183         if (rigol_ds1xx2_send(devc, buf) != SR_OK)
184                 return SR_ERR;
185
186         /* When setting a bunch of parameters in a row, the DS1052E scrambles
187          * some of them unless there is at least 100ms delay in between. */
188         sr_spew("delay %dms", 100);
189         g_usleep(100);
190
191         return SR_OK;
192 }
193
194 static int hw_init(struct sr_context *sr_ctx)
195 {
196         return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
197 }
198
199 static GSList *hw_scan(GSList *options)
200 {
201         struct drv_context *drvc;
202         struct sr_dev_inst *sdi;
203         struct dev_context *devc;
204         struct sr_probe *probe;
205         GSList *devices;
206         GDir *dir;
207         const gchar *dev_name;
208         const gchar *dev_dir = "/dev/";
209         const gchar *prefix = "usbtmc";
210         gchar *device;
211         const gchar *idn_query = "*IDN?";
212         unsigned int i;
213         int len, num_tokens, fd;
214         const gchar *delimiter = ",";
215         gchar **tokens;
216         const char *manufacturer, *model, *version;
217         gboolean matched = FALSE;
218         gboolean has_digital = FALSE;
219         char buf[256];
220         gchar *channel_name;
221
222         (void)options;
223
224         drvc = di->priv;
225         drvc->instances = NULL;
226
227         devices = NULL;
228
229         dir = g_dir_open("/sys/class/usb/", 0, NULL);
230
231         if (dir == NULL)
232                 return NULL;
233
234         while ((dev_name = g_dir_read_name(dir)) != NULL) {
235                 if (strncmp(dev_name, prefix, strlen(prefix))) 
236                         continue;
237
238                 device = g_strconcat(dev_dir, dev_name, NULL);
239
240                 fd = open(device, O_RDWR);
241                 len = write(fd, idn_query, strlen(idn_query));
242                 len = read(fd, buf, sizeof(buf));
243                 close(fd);
244                 if (len == 0) {
245                         g_free(device);
246                         return NULL;
247                 }
248
249                 buf[len] = 0;
250                 tokens = g_strsplit(buf, delimiter, 0);
251                 close(fd);
252                 sr_dbg("response: %s %d [%s]", device, len, buf);
253
254                 for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
255
256                 if (num_tokens < 4) {
257                         g_strfreev(tokens);
258                         g_free(device);
259                         return NULL;
260                 }
261
262                 manufacturer = tokens[0];
263                 model = tokens[1];
264                 version = tokens[3];
265
266                 if (strcmp(manufacturer, "Rigol Technologies")) {
267                         g_strfreev(tokens);
268                         g_free(device);
269                         return NULL;
270                 }
271
272                 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
273                         if (!strcmp(model, supported_models[i])) {
274                                 matched = 1;
275                                 has_digital = g_str_has_suffix(model, "D");
276                                 break;
277                         }
278                 }
279
280                 if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
281                         manufacturer, model, version))) {
282                         g_strfreev(tokens);
283                         g_free(device);
284                         return NULL;
285                 }
286
287                 g_strfreev(tokens);
288
289                 if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
290                         sr_err("Device context malloc failed.");
291                         g_free(device);
292                         return NULL;
293                 }
294                 devc->limit_frames = 0;
295                 devc->device = device;
296                 devc->has_digital = has_digital;
297                 sdi->priv = devc;
298                 sdi->driver = di;
299
300                 for (i = 0; i < 2; i++) {
301                         if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
302                             i == 0 ? "CH1" : "CH2")))
303                                 return NULL;
304                         sdi->probes = g_slist_append(sdi->probes, probe);
305                 }
306
307                 if (devc->has_digital) {
308                         for (i = 0; i < 16; i++) {
309                                 if (!(channel_name = g_strdup_printf("D%d", i)))
310                                         return NULL;
311                                 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
312                                 g_free(channel_name);
313                                 if (!probe)
314                                         return NULL;
315                                 sdi->probes = g_slist_append(sdi->probes, probe);
316                         }
317                 }
318
319                 drvc->instances = g_slist_append(drvc->instances, sdi);
320                 devices = g_slist_append(devices, sdi);
321         }
322
323         g_dir_close(dir);
324
325         return devices;
326 }
327
328 static GSList *hw_dev_list(void)
329 {
330         return ((struct drv_context *)(di->priv))->instances;
331 }
332
333 static int hw_dev_open(struct sr_dev_inst *sdi)
334 {
335         struct dev_context *devc;
336         int fd;
337
338         devc = sdi->priv;
339
340         if ((fd = open(devc->device, O_RDWR)) == -1)
341                 return SR_ERR;
342         devc->fd = fd;
343
344         if (rigol_ds1xx2_get_dev_cfg(sdi) != SR_OK)
345                 /* TODO: force configuration? */
346                 return SR_ERR;
347
348         return SR_OK;
349 }
350
351 static int hw_dev_close(struct sr_dev_inst *sdi)
352 {
353         struct dev_context *devc;
354
355         devc = sdi->priv;
356
357         close(devc->fd);
358
359         return SR_OK;
360 }
361
362 static int hw_cleanup(void)
363 {
364         clear_instances();
365
366         return SR_OK;
367 }
368
369 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
370 {
371
372         (void)sdi;
373
374         switch (id) {
375         case SR_CONF_NUM_TIMEBASE:
376                 *data = g_variant_new_int32(NUM_TIMEBASE);
377                 break;
378         case SR_CONF_NUM_VDIV:
379                 *data = g_variant_new_int32(NUM_VDIV);
380                 break;
381         default:
382                 return SR_ERR_NA;
383         }
384
385         return SR_OK;
386 }
387
388 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
389 {
390         struct dev_context *devc;
391         uint64_t tmp_u64, p, q;
392         double t_dbl;
393         unsigned int i;
394         int ret;
395         const char *tmp_str;
396
397         devc = sdi->priv;
398
399         if (sdi->status != SR_ST_ACTIVE) {
400                 sr_err("Device inactive, can't set config options.");
401                 return SR_ERR;
402         }
403
404         ret = SR_OK;
405         switch (id) {
406         case SR_CONF_LIMIT_FRAMES:
407                 devc->limit_frames = g_variant_get_uint64(data);
408                 break;
409         case SR_CONF_TRIGGER_SLOPE:
410                 tmp_u64 = g_variant_get_uint64(data);
411                 if (tmp_u64 != 0 && tmp_u64 != 1)
412                         return SR_ERR;
413                 g_free(devc->trigger_slope);
414                 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
415                 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
416                 break;
417         case SR_CONF_HORIZ_TRIGGERPOS:
418                 t_dbl = g_variant_get_double(data);
419                 if (t_dbl < 0.0 || t_dbl > 1.0)
420                         return SR_ERR;
421                 devc->horiz_triggerpos = t_dbl;
422                 /* We have the trigger offset as a percentage of the frame, but
423                  * need to express this in seconds. */
424                 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
425                 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
426                 break;
427         case SR_CONF_TIMEBASE:
428                 g_variant_get(data, "(tt)", &p, &q);
429                 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
430                         if (timebases[i][0] == p && timebases[i][1] == q) {
431                                 devc->timebase = (float)p / q;
432                                 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
433                                 break;
434                         }
435                 }
436                 if (i == ARRAY_SIZE(timebases))
437                         ret = SR_ERR_ARG;
438                 break;
439         case SR_CONF_TRIGGER_SOURCE:
440                 tmp_str = g_variant_get_string(data, NULL);
441                 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
442                         if (!strcmp(trigger_sources[i], tmp_str)) {
443                                 g_free(devc->trigger_source);
444                                 devc->trigger_source = g_strdup(trigger_sources[i]);
445                                 if (!strcmp(devc->trigger_source, "AC Line"))
446                                         tmp_str = "ACL";
447                                 else if (!strcmp(devc->trigger_source, "CH1"))
448                                         tmp_str = "CHAN1";
449                                 else if (!strcmp(devc->trigger_source, "CH2"))
450                                         tmp_str = "CHAN2";
451                                 else
452                                         tmp_str = (char *)devc->trigger_source;
453                                 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
454                                 break;
455                         }
456                 }
457                 if (i == ARRAY_SIZE(trigger_sources))
458                         ret = SR_ERR_ARG;
459                 break;
460         case SR_CONF_VDIV:
461                 g_variant_get(data, "(tt)", &p, &q);
462                 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
463                         if (vdivs[i][0] != p || vdivs[i][1] != q)
464                                 continue;
465                         devc->vdiv[0] = devc->vdiv[1] = (float)p / q;
466                         set_cfg(sdi, ":CHAN1:SCAL %.3f", devc->vdiv[0]);
467                         ret = set_cfg(sdi, ":CHAN2:SCAL %.3f", devc->vdiv[1]);
468                         break;
469                 }
470                 if (i == ARRAY_SIZE(vdivs))
471                         ret = SR_ERR_ARG;
472                 break;
473         case SR_CONF_COUPLING:
474                 /* TODO: Not supporting coupling per channel yet. */
475                 tmp_str = g_variant_get_string(data, NULL);
476                 for (i = 0; i < ARRAY_SIZE(coupling); i++) {
477                         if (!strcmp(tmp_str, coupling[i])) {
478                                 g_free(devc->coupling[0]);
479                                 g_free(devc->coupling[1]);
480                                 devc->coupling[0] = g_strdup(coupling[i]);
481                                 devc->coupling[1] = g_strdup(coupling[i]);
482                                 set_cfg(sdi, ":CHAN1:COUP %s", devc->coupling[0]);
483                                 ret = set_cfg(sdi, ":CHAN2:COUP %s", devc->coupling[1]);
484                                 break;
485                         }
486                 }
487                 if (i == ARRAY_SIZE(coupling))
488                         ret = SR_ERR_ARG;
489                 break;
490         default:
491                 ret = SR_ERR_NA;
492                 break;
493         }
494
495         return ret;
496 }
497
498 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
499 {
500         GVariant *tuple, *rational[2];
501         GVariantBuilder gvb;
502         unsigned int i;
503         struct dev_context *devc;
504
505         switch (key) {
506         case SR_CONF_DEVICE_OPTIONS:
507                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
508                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
509                 break;
510         case SR_CONF_COUPLING:
511                 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
512                 break;
513         case SR_CONF_VDIV:
514                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
515                 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
516                         rational[0] = g_variant_new_uint64(vdivs[i][0]);
517                         rational[1] = g_variant_new_uint64(vdivs[i][1]);
518                         tuple = g_variant_new_tuple(rational, 2);
519                         g_variant_builder_add_value(&gvb, tuple);
520                 }
521                 *data = g_variant_builder_end(&gvb);
522                 break;
523         case SR_CONF_TIMEBASE:
524                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
525                 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
526                         rational[0] = g_variant_new_uint64(timebases[i][0]);
527                         rational[1] = g_variant_new_uint64(timebases[i][1]);
528                         tuple = g_variant_new_tuple(rational, 2);
529                         g_variant_builder_add_value(&gvb, tuple);
530                 }
531                 *data = g_variant_builder_end(&gvb);
532                 break;
533         case SR_CONF_TRIGGER_SOURCE:
534                 if (!sdi || !sdi->priv)
535                         /* Can't know this until we have the exact model. */
536                         return SR_ERR_ARG;
537                 devc = sdi->priv;
538                 *data = g_variant_new_strv(trigger_sources,
539                                 devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
540                 break;
541         default:
542                 return SR_ERR_NA;
543         }
544
545         return SR_OK;
546 }
547
548 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
549 {
550         struct dev_context *devc;
551         struct sr_probe *probe;
552         GSList *l;
553         char cmd[256];
554
555         (void)cb_data;
556
557         devc = sdi->priv;
558
559         for (l = sdi->probes; l; l = l->next) {
560                 probe = l->data;
561                 sr_dbg("handling probe %s", probe->name);
562                 if (probe->type == SR_PROBE_ANALOG) {
563                         if (probe->enabled)
564                                 devc->enabled_analog_probes = g_slist_append(
565                                                 devc->enabled_analog_probes, probe);
566                         if (probe->enabled != devc->analog_channels[probe->index]) {
567                                 /* Enabled channel is currently disabled, or vice versa. */
568                                 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
569                                                 probe->enabled ? "ON" : "OFF");
570                                 if (rigol_ds1xx2_send(devc, cmd) != SR_OK)
571                                         return SR_ERR;
572                         }
573                 } else if (probe->type == SR_PROBE_LOGIC) {
574                         if (probe->enabled)
575                                 devc->enabled_digital_probes = g_slist_append(
576                                                 devc->enabled_digital_probes, probe);
577                         if (probe->enabled != devc->digital_channels[probe->index]) {
578                                 /* Enabled channel is currently disabled, or vice versa. */
579                                 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
580                                                 probe->enabled ? "ON" : "OFF");
581                                 if (rigol_ds1xx2_send(devc, cmd) != SR_OK)
582                                         return SR_ERR;
583                         }
584                 }
585         }
586         if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
587                 return SR_ERR;
588
589         sr_source_add(devc->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi);
590
591         /* Send header packet to the session bus. */
592         std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
593
594         /* Fetch the first frame. */
595         if (devc->enabled_analog_probes) {
596                 devc->channel_frame = devc->enabled_analog_probes->data;
597                 if (rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%d",
598                                 devc->channel_frame->index + 1) != SR_OK)
599                         return SR_ERR;
600         } else {
601                 devc->channel_frame = devc->enabled_digital_probes->data;
602                 if (rigol_ds1xx2_send(devc, ":WAV:DATA? DIG") != SR_OK)
603                         return SR_ERR;
604         }
605
606         devc->num_frame_bytes = 0;
607
608         return SR_OK;
609 }
610
611 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
612 {
613         struct dev_context *devc;
614
615         (void)cb_data;
616
617         devc = sdi->priv;
618
619         if (sdi->status != SR_ST_ACTIVE) {
620                 sr_err("Device inactive, can't stop acquisition.");
621                 return SR_ERR;
622         }
623
624         g_slist_free(devc->enabled_analog_probes);
625         g_slist_free(devc->enabled_digital_probes);
626         devc->enabled_analog_probes = NULL;
627         devc->enabled_digital_probes = NULL;
628         sr_source_remove(devc->fd);
629
630         return SR_OK;
631 }
632
633 SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
634         .name = "rigol-ds1xx2",
635         .longname = "Rigol DS1xx2",
636         .api_version = 1,
637         .init = hw_init,
638         .cleanup = hw_cleanup,
639         .scan = hw_scan,
640         .dev_list = hw_dev_list,
641         .dev_clear = clear_instances,
642         .config_get = config_get,
643         .config_set = config_set,
644         .config_list = config_list,
645         .dev_open = hw_dev_open,
646         .dev_close = hw_dev_close,
647         .dev_acquisition_start = dev_acquisition_start,
648         .dev_acquisition_stop = dev_acquisition_stop,
649         .priv = NULL,
650 };