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