]> sigrok.org Git - libsigrok.git/blob - hardware/rigol-ds1xx2/api.c
rigol-ds1xx2: better error handling in hw_scan.
[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                         continue;
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                         continue;
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                         continue;
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                         continue;
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                         goto hw_scan_abort;
293                 }
294
295                 devc->limit_frames = 0;
296                 devc->device = device;
297                 devc->has_digital = has_digital;
298                 sdi->priv = devc;
299                 sdi->driver = di;
300                 drvc->instances = g_slist_append(drvc->instances, sdi);
301                 devices = g_slist_append(devices, sdi);
302
303                 for (i = 0; i < 2; i++) {
304                         if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
305                                     i == 0 ? "CH1" : "CH2")))
306                                 goto hw_scan_abort;
307                         sdi->probes = g_slist_append(sdi->probes, probe);
308                 }
309
310                 if (devc->has_digital) {
311                         for (i = 0; i < 16; i++) {
312                                 if (!(channel_name = g_strdup_printf("D%d", i)))
313                                         goto hw_scan_abort;
314                                 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
315                                 g_free(channel_name);
316                                 if (!probe)
317                                         goto hw_scan_abort;
318                                 sdi->probes = g_slist_append(sdi->probes, probe);
319                         }
320                 }
321         }
322
323         g_dir_close(dir);
324
325         return devices;
326
327 hw_scan_abort:
328         g_dir_close(dir);
329         g_slist_free(devices);
330         clear_instances();
331         return NULL;
332 }
333
334 static GSList *hw_dev_list(void)
335 {
336         return ((struct drv_context *)(di->priv))->instances;
337 }
338
339 static int hw_dev_open(struct sr_dev_inst *sdi)
340 {
341         struct dev_context *devc;
342         int fd;
343
344         devc = sdi->priv;
345
346         if ((fd = open(devc->device, O_RDWR)) == -1)
347                 return SR_ERR;
348         devc->fd = fd;
349
350         if (rigol_ds1xx2_get_dev_cfg(sdi) != SR_OK)
351                 /* TODO: force configuration? */
352                 return SR_ERR;
353
354         return SR_OK;
355 }
356
357 static int hw_dev_close(struct sr_dev_inst *sdi)
358 {
359         struct dev_context *devc;
360
361         devc = sdi->priv;
362
363         close(devc->fd);
364
365         return SR_OK;
366 }
367
368 static int hw_cleanup(void)
369 {
370         clear_instances();
371
372         return SR_OK;
373 }
374
375 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
376 {
377
378         (void)sdi;
379
380         switch (id) {
381         case SR_CONF_NUM_TIMEBASE:
382                 *data = g_variant_new_int32(NUM_TIMEBASE);
383                 break;
384         case SR_CONF_NUM_VDIV:
385                 *data = g_variant_new_int32(NUM_VDIV);
386                 break;
387         default:
388                 return SR_ERR_NA;
389         }
390
391         return SR_OK;
392 }
393
394 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
395 {
396         struct dev_context *devc;
397         uint64_t tmp_u64, p, q;
398         double t_dbl;
399         unsigned int i;
400         int ret;
401         const char *tmp_str;
402
403         devc = sdi->priv;
404
405         if (sdi->status != SR_ST_ACTIVE) {
406                 sr_err("Device inactive, can't set config options.");
407                 return SR_ERR;
408         }
409
410         ret = SR_OK;
411         switch (id) {
412         case SR_CONF_LIMIT_FRAMES:
413                 devc->limit_frames = g_variant_get_uint64(data);
414                 break;
415         case SR_CONF_TRIGGER_SLOPE:
416                 tmp_u64 = g_variant_get_uint64(data);
417                 if (tmp_u64 != 0 && tmp_u64 != 1)
418                         return SR_ERR;
419                 g_free(devc->trigger_slope);
420                 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
421                 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
422                 break;
423         case SR_CONF_HORIZ_TRIGGERPOS:
424                 t_dbl = g_variant_get_double(data);
425                 if (t_dbl < 0.0 || t_dbl > 1.0)
426                         return SR_ERR;
427                 devc->horiz_triggerpos = t_dbl;
428                 /* We have the trigger offset as a percentage of the frame, but
429                  * need to express this in seconds. */
430                 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
431                 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
432                 break;
433         case SR_CONF_TIMEBASE:
434                 g_variant_get(data, "(tt)", &p, &q);
435                 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
436                         if (timebases[i][0] == p && timebases[i][1] == q) {
437                                 devc->timebase = (float)p / q;
438                                 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
439                                 break;
440                         }
441                 }
442                 if (i == ARRAY_SIZE(timebases))
443                         ret = SR_ERR_ARG;
444                 break;
445         case SR_CONF_TRIGGER_SOURCE:
446                 tmp_str = g_variant_get_string(data, NULL);
447                 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
448                         if (!strcmp(trigger_sources[i], tmp_str)) {
449                                 g_free(devc->trigger_source);
450                                 devc->trigger_source = g_strdup(trigger_sources[i]);
451                                 if (!strcmp(devc->trigger_source, "AC Line"))
452                                         tmp_str = "ACL";
453                                 else if (!strcmp(devc->trigger_source, "CH1"))
454                                         tmp_str = "CHAN1";
455                                 else if (!strcmp(devc->trigger_source, "CH2"))
456                                         tmp_str = "CHAN2";
457                                 else
458                                         tmp_str = (char *)devc->trigger_source;
459                                 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
460                                 break;
461                         }
462                 }
463                 if (i == ARRAY_SIZE(trigger_sources))
464                         ret = SR_ERR_ARG;
465                 break;
466         case SR_CONF_VDIV:
467                 g_variant_get(data, "(tt)", &p, &q);
468                 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
469                         if (vdivs[i][0] != p || vdivs[i][1] != q)
470                                 continue;
471                         devc->vdiv[0] = devc->vdiv[1] = (float)p / q;
472                         set_cfg(sdi, ":CHAN1:SCAL %.3f", devc->vdiv[0]);
473                         ret = set_cfg(sdi, ":CHAN2:SCAL %.3f", devc->vdiv[1]);
474                         break;
475                 }
476                 if (i == ARRAY_SIZE(vdivs))
477                         ret = SR_ERR_ARG;
478                 break;
479         case SR_CONF_COUPLING:
480                 /* TODO: Not supporting coupling per channel yet. */
481                 tmp_str = g_variant_get_string(data, NULL);
482                 for (i = 0; i < ARRAY_SIZE(coupling); i++) {
483                         if (!strcmp(tmp_str, coupling[i])) {
484                                 g_free(devc->coupling[0]);
485                                 g_free(devc->coupling[1]);
486                                 devc->coupling[0] = g_strdup(coupling[i]);
487                                 devc->coupling[1] = g_strdup(coupling[i]);
488                                 set_cfg(sdi, ":CHAN1:COUP %s", devc->coupling[0]);
489                                 ret = set_cfg(sdi, ":CHAN2:COUP %s", devc->coupling[1]);
490                                 break;
491                         }
492                 }
493                 if (i == ARRAY_SIZE(coupling))
494                         ret = SR_ERR_ARG;
495                 break;
496         default:
497                 ret = SR_ERR_NA;
498                 break;
499         }
500
501         return ret;
502 }
503
504 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
505 {
506         GVariant *tuple, *rational[2];
507         GVariantBuilder gvb;
508         unsigned int i;
509         struct dev_context *devc;
510
511         switch (key) {
512         case SR_CONF_DEVICE_OPTIONS:
513                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
514                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
515                 break;
516         case SR_CONF_COUPLING:
517                 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
518                 break;
519         case SR_CONF_VDIV:
520                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
521                 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
522                         rational[0] = g_variant_new_uint64(vdivs[i][0]);
523                         rational[1] = g_variant_new_uint64(vdivs[i][1]);
524                         tuple = g_variant_new_tuple(rational, 2);
525                         g_variant_builder_add_value(&gvb, tuple);
526                 }
527                 *data = g_variant_builder_end(&gvb);
528                 break;
529         case SR_CONF_TIMEBASE:
530                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
531                 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
532                         rational[0] = g_variant_new_uint64(timebases[i][0]);
533                         rational[1] = g_variant_new_uint64(timebases[i][1]);
534                         tuple = g_variant_new_tuple(rational, 2);
535                         g_variant_builder_add_value(&gvb, tuple);
536                 }
537                 *data = g_variant_builder_end(&gvb);
538                 break;
539         case SR_CONF_TRIGGER_SOURCE:
540                 if (!sdi || !sdi->priv)
541                         /* Can't know this until we have the exact model. */
542                         return SR_ERR_ARG;
543                 devc = sdi->priv;
544                 *data = g_variant_new_strv(trigger_sources,
545                                 devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
546                 break;
547         default:
548                 return SR_ERR_NA;
549         }
550
551         return SR_OK;
552 }
553
554 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
555 {
556         struct dev_context *devc;
557         struct sr_probe *probe;
558         GSList *l;
559         char cmd[256];
560
561         (void)cb_data;
562
563         devc = sdi->priv;
564
565         for (l = sdi->probes; l; l = l->next) {
566                 probe = l->data;
567                 sr_dbg("handling probe %s", probe->name);
568                 if (probe->type == SR_PROBE_ANALOG) {
569                         if (probe->enabled)
570                                 devc->enabled_analog_probes = g_slist_append(
571                                                 devc->enabled_analog_probes, probe);
572                         if (probe->enabled != devc->analog_channels[probe->index]) {
573                                 /* Enabled channel is currently disabled, or vice versa. */
574                                 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
575                                                 probe->enabled ? "ON" : "OFF");
576                                 if (rigol_ds1xx2_send(devc, cmd) != SR_OK)
577                                         return SR_ERR;
578                         }
579                 } else if (probe->type == SR_PROBE_LOGIC) {
580                         if (probe->enabled)
581                                 devc->enabled_digital_probes = g_slist_append(
582                                                 devc->enabled_digital_probes, probe);
583                         if (probe->enabled != devc->digital_channels[probe->index]) {
584                                 /* Enabled channel is currently disabled, or vice versa. */
585                                 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
586                                                 probe->enabled ? "ON" : "OFF");
587                                 if (rigol_ds1xx2_send(devc, cmd) != SR_OK)
588                                         return SR_ERR;
589                         }
590                 }
591         }
592         if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
593                 return SR_ERR;
594
595         sr_source_add(devc->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi);
596
597         /* Send header packet to the session bus. */
598         std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
599
600         /* Fetch the first frame. */
601         if (devc->enabled_analog_probes) {
602                 devc->channel_frame = devc->enabled_analog_probes->data;
603                 if (rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%d",
604                                 devc->channel_frame->index + 1) != SR_OK)
605                         return SR_ERR;
606         } else {
607                 devc->channel_frame = devc->enabled_digital_probes->data;
608                 if (rigol_ds1xx2_send(devc, ":WAV:DATA? DIG") != SR_OK)
609                         return SR_ERR;
610         }
611
612         devc->num_frame_bytes = 0;
613
614         return SR_OK;
615 }
616
617 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
618 {
619         struct dev_context *devc;
620
621         (void)cb_data;
622
623         devc = sdi->priv;
624
625         if (sdi->status != SR_ST_ACTIVE) {
626                 sr_err("Device inactive, can't stop acquisition.");
627                 return SR_ERR;
628         }
629
630         g_slist_free(devc->enabled_analog_probes);
631         g_slist_free(devc->enabled_digital_probes);
632         devc->enabled_analog_probes = NULL;
633         devc->enabled_digital_probes = NULL;
634         sr_source_remove(devc->fd);
635
636         return SR_OK;
637 }
638
639 SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
640         .name = "rigol-ds1xx2",
641         .longname = "Rigol DS1xx2",
642         .api_version = 1,
643         .init = hw_init,
644         .cleanup = hw_cleanup,
645         .scan = hw_scan,
646         .dev_list = hw_dev_list,
647         .dev_clear = clear_instances,
648         .config_get = config_get,
649         .config_set = config_set,
650         .config_list = config_list,
651         .dev_open = hw_dev_open,
652         .dev_close = hw_dev_close,
653         .dev_acquisition_start = dev_acquisition_start,
654         .dev_acquisition_stop = dev_acquisition_stop,
655         .priv = NULL,
656 };