]> sigrok.org Git - libsigrok.git/blob - src/hardware/hung-chang-dso-2100/api.c
eb2246f61a6a8465dfd1cb7b58ba386efc80524a
[libsigrok.git] / src / hardware / hung-chang-dso-2100 / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2015 Daniel Glöckner <daniel-gl@gmx.net>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <ieee1284.h>
22 #include <string.h>
23 #include "protocol.h"
24
25 SR_PRIV struct sr_dev_driver hung_chang_dso_2100_driver_info;
26
27 static const uint32_t scanopts[] = {
28         SR_CONF_CONN,
29 };
30
31 static const uint32_t drvopts[] = {
32         SR_CONF_OSCILLOSCOPE,
33 };
34
35 static const uint32_t devopts[] = {
36         SR_CONF_CONN | SR_CONF_GET,
37         SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
38         SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
39         SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
40         SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
41         SR_CONF_BUFFERSIZE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
42 };
43
44 static const uint32_t cgopts[] = {
45         SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
46         SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
47         SR_CONF_PROBE_FACTOR | SR_CONF_GET | SR_CONF_SET,
48 };
49
50 static const uint64_t samplerates[] = {
51         SR_MHZ(100), SR_MHZ(50),  SR_MHZ(25),   SR_MHZ(20),
52         SR_MHZ(10),  SR_MHZ(5),   SR_KHZ(2500), SR_MHZ(2),
53         SR_MHZ(1),   SR_KHZ(500), SR_KHZ(250),  SR_KHZ(200),
54         SR_KHZ(100), SR_KHZ(50),  SR_KHZ(25),   SR_KHZ(20),
55         SR_KHZ(10),  SR_KHZ(5),   SR_HZ(2500),  SR_KHZ(2),
56         SR_KHZ(1),   SR_HZ(500),  SR_HZ(250),   SR_HZ(200),
57         SR_HZ(100),  SR_HZ(50),   SR_HZ(25),    SR_HZ(20)
58 };
59
60 /* must be in sync with readout_steps[] in protocol.c */
61 static const uint64_t buffersizes[] = {
62         2 * 500, 3 * 500, 4 * 500, 5 * 500,
63         6 * 500, 7 * 500, 8 * 500, 9 * 500, 10 * 500,
64         12 * 500 - 2, 14 * 500 - 2, 16 * 500 - 2,
65         18 * 500 - 2, 20 * 500 - 2, 10240 - 2
66 };
67
68 static const uint64_t vdivs[][2] = {
69         { 10, 1000 },
70         { 20, 1000 },
71         { 50, 1000 },
72         { 100, 1000 },
73         { 200, 1000 },
74         { 500, 1000 },
75         { 1, 1 },
76         { 2, 1 },
77         { 5, 1 },
78 };
79
80 /* Bits 4 and 5 enable relays that add /10 filters to the chain
81  * Bits 0 and 1 select an output from a resistor array */
82 static const uint8_t vdivs_map[] = {
83         0x01, 0x02, 0x03, 0x21, 0x22, 0x23, 0x31, 0x32, 0x33
84 };
85
86
87 static const char *trigger_sources[] = {
88         "A", "B", "EXT"
89 };
90
91 static const uint8_t trigger_sources_map[] = {
92         0x00, 0x80, 0x40
93 };
94
95 static const char *trigger_slopes[] = {
96         "f", "r"
97 };
98
99 static const char *coupling[] = {
100         "DC", "AC", "GND"
101 };
102
103 static const uint8_t coupling_map[] = {
104         0x00, 0x08, 0x04
105 };
106
107 static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
108 {
109         return std_init(di, sr_ctx, LOG_PREFIX);
110 }
111
112 static GSList *scan_port(GSList *devices, struct sr_dev_driver *di,
113                          struct parport *port)
114 {
115         struct sr_dev_inst *sdi;
116         struct sr_channel *ch;
117         struct sr_channel_group *cg;
118         struct dev_context *devc;
119         struct drv_context *drvc;
120         int i;
121
122         if (ieee1284_open(port, 0, &i) != E1284_OK) {
123                 sr_err("Can't open parallel port %s", port->name);
124                 goto fail1;
125         }
126
127         if ((i & (CAP1284_RAW | CAP1284_BYTE)) != (CAP1284_RAW | CAP1284_BYTE)) {
128                 sr_err("Parallel port %s does not provide low-level bidirection access",
129                        port->name);
130                 goto fail2;
131         }
132
133         if (ieee1284_claim(port) != E1284_OK) {
134                 sr_err("Parallel port %s already in use", port->name);
135                 goto fail2;
136         }
137
138         if (!hung_chang_dso_2100_check_id(port))
139                 goto fail3;
140
141         sdi = g_malloc0(sizeof(struct sr_dev_inst));
142         sdi->status = SR_ST_INACTIVE;
143         sdi->vendor = g_strdup("Hung-Chang");
144         sdi->model = g_strdup("DSO-2100");
145         sdi->driver = di;
146         drvc = di->context;
147         sdi->inst_type = 0; /* FIXME */
148         sdi->conn = port;
149         ieee1284_ref(port);
150
151         for (i = 0; i < NUM_CHANNELS; i++) {
152                 cg = g_malloc0(sizeof(struct sr_channel_group));
153                 cg->name = g_strdup(trigger_sources[i]);
154                 ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, FALSE, trigger_sources[i]);
155                 cg->channels = g_slist_append(cg->channels, ch);
156                 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
157         }
158
159         devc = g_malloc0(sizeof(struct dev_context));
160         devc->enabled_channel = g_slist_append(NULL, NULL);
161         devc->channel = 0;
162         devc->rate = 0;
163         devc->probe[0] = 10;
164         devc->probe[1] = 10;
165         devc->cctl[0] = 0x31; /* 1V/div, DC coupling, trigger on channel A*/
166         devc->cctl[1] = 0x31; /* 1V/div, DC coupling, no tv sync trigger */
167         devc->edge = 0;
168         devc->tlevel = 0x80;
169         devc->pos[0] = 0x80;
170         devc->pos[1] = 0x80;
171         devc->offset[0] = 0x80;
172         devc->offset[1] = 0x80;
173         devc->gain[0] = 0x80;
174         devc->gain[1] = 0x80;
175         devc->frame_limit = 0;
176         devc->last_step = 0; /* buffersize = 1000 */
177         sdi->priv = devc;
178
179         drvc->instances = g_slist_append(drvc->instances, sdi);
180         devices = g_slist_append(devices, sdi);
181
182 fail3:
183         ieee1284_release(port);
184 fail2:
185         ieee1284_close(port);
186 fail1:
187         return devices;
188 }
189
190 static GSList *scan(struct sr_dev_driver *di, GSList *options)
191 {
192         struct parport_list ports;
193         struct sr_config *src;
194         const char *conn = NULL;
195         GSList *devices, *option;
196         gboolean port_found;
197         int i;
198
199
200         for (option = options; option; option = option->next) {
201                 src = option->data;
202                 if (src->key == SR_CONF_CONN) {
203                         conn = g_variant_get_string(src->data, NULL);
204                         break;
205                 }
206         }
207
208         if (!conn)
209                 return NULL;
210
211         if (ieee1284_find_ports(&ports, 0) != E1284_OK)
212                 return NULL;
213
214         devices = NULL;
215         port_found = FALSE;
216         for (i = 0; i < ports.portc; i++)
217                 if (!strcmp(ports.portv[i]->name, conn)) {
218                         port_found = TRUE;
219                         devices = scan_port(devices, di, ports.portv[i]);
220                 }
221
222         if (!port_found) {
223                 sr_err("Parallel port %s not found. Valid names are:", conn);
224                 for (i = 0; i < ports.portc; i++)
225                         sr_err("\t%s", ports.portv[i]->name);
226         }
227
228         ieee1284_free_ports(&ports);
229
230         return devices;
231 }
232
233 static void clear_private(void *priv)
234 {
235         struct dev_context *devc = priv;
236
237         g_slist_free(devc->enabled_channel);
238 }
239
240 static int dev_clear(const struct sr_dev_driver *di)
241 {
242         struct drv_context *drvc = di->context;
243         struct sr_dev_inst *sdi;
244         GSList *l;
245
246         if (drvc) {
247                 for (l = drvc->instances; l; l = l->next) {
248                         sdi = l->data;
249                         ieee1284_unref(sdi->conn);
250                 }
251         }
252
253         return std_dev_clear(di, clear_private);
254 }
255
256 static int dev_open(struct sr_dev_inst *sdi)
257 {
258         struct dev_context *devc = sdi->priv;
259         int i;
260
261         if (sdi->status != SR_ST_INACTIVE)
262                 goto fail1;
263
264         if (ieee1284_open(sdi->conn, 0, &i) != E1284_OK)
265                 goto fail1;
266
267         if (ieee1284_claim(sdi->conn) != E1284_OK)
268                 goto fail2;
269
270         if (ieee1284_data_dir(sdi->conn, 1) != E1284_OK)
271                 goto fail3;
272
273         if (hung_chang_dso_2100_move_to(sdi, 1))
274                 goto fail3;
275
276         devc->samples = g_try_malloc(1000 * sizeof(*devc->samples));
277         if (!devc->samples)
278                 goto fail3;
279
280         sdi->status = SR_ST_ACTIVE;
281
282         return SR_OK;
283
284 fail3:
285         hung_chang_dso_2100_reset_port(sdi->conn);
286         ieee1284_release(sdi->conn);
287 fail2:
288         ieee1284_close(sdi->conn);
289 fail1:
290         return SR_ERR;
291 }
292
293 static int dev_close(struct sr_dev_inst *sdi)
294 {
295         struct dev_context *devc = sdi->priv;
296
297         if (sdi->status != SR_ST_ACTIVE)
298                 return SR_OK;
299
300         g_free(devc->samples);
301         hung_chang_dso_2100_reset_port(sdi->conn);
302         ieee1284_release(sdi->conn);
303         ieee1284_close(sdi->conn);
304         sdi->status = SR_ST_INACTIVE;
305
306         return SR_OK;
307 }
308
309 static int find_in_array(GVariant *data, const GVariantType *type,
310                          const void *arr, int n)
311 {
312         const char * const *sarr;
313         const char *s;
314         const uint64_t *u64arr;
315         const uint8_t *u8arr;
316         uint64_t u64;
317         uint8_t u8;
318         int i;
319
320         if (!g_variant_is_of_type(data, type))
321                 return -1;
322
323         switch (g_variant_classify(data)) {
324         case G_VARIANT_CLASS_STRING:
325                 s = g_variant_get_string(data, NULL);
326                 sarr = arr;
327
328                 for (i = 0; i < n; i++)
329                         if (!strcmp(s, sarr[i]))
330                                 return i;
331                 break;
332         case G_VARIANT_CLASS_UINT64:
333                 u64 = g_variant_get_uint64(data);
334                 u64arr = arr;
335
336                 for (i = 0; i < n; i++)
337                         if (u64 == u64arr[i])
338                                 return i;
339                 break;
340         case G_VARIANT_CLASS_BYTE:
341                 u8 = g_variant_get_byte(data);
342                 u8arr = arr;
343
344                 for (i = 0; i < n; i++)
345                         if (u8 == u8arr[i])
346                                 return i;
347         default:
348                 break;
349         }
350
351         return -1;
352 }
353
354 static int reverse_map(uint8_t u, const uint8_t *arr, int n)
355 {
356         GVariant *v = g_variant_new_byte(u);
357         int i = find_in_array(v, G_VARIANT_TYPE_BYTE, arr, n);
358         g_variant_unref(v);
359         return i;
360 }
361
362 static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
363                 const struct sr_channel_group *cg)
364 {
365         struct dev_context *devc = sdi->priv;
366         struct parport *port;
367         int ret, i, ch = -1;
368
369         if (cg) /* sr_config_get will validate cg using config_list */
370                 ch = ((struct sr_channel *)cg->channels->data)->index;
371
372         ret = SR_OK;
373         switch (key) {
374         case SR_CONF_CONN:
375                 port = sdi->conn;
376                 *data = g_variant_new_string(port->name);
377                 break;
378         case SR_CONF_LIMIT_FRAMES:
379                 *data = g_variant_new_uint64(devc->frame_limit);
380                 break;
381         case SR_CONF_SAMPLERATE:
382                 *data = g_variant_new_uint64(samplerates[devc->rate]);
383                 break;
384         case SR_CONF_TRIGGER_SOURCE:
385                 i = reverse_map(devc->cctl[0] & 0xC0, trigger_sources_map,
386                                 ARRAY_SIZE(trigger_sources_map));
387                 if (i == -1)
388                         ret = SR_ERR;
389                 else
390                         *data = g_variant_new_string(trigger_sources[i]);
391                 break;
392         case SR_CONF_TRIGGER_SLOPE:
393                 if (devc->edge >= ARRAY_SIZE(trigger_slopes))
394                         ret = SR_ERR;
395                 else
396                         *data = g_variant_new_string(trigger_slopes[devc->edge]);
397                 break;
398         case SR_CONF_BUFFERSIZE:
399                 *data = g_variant_new_uint64(buffersizes[devc->last_step]);
400                 break;
401         case SR_CONF_VDIV:
402                 if (ch == -1) {
403                         ret = SR_ERR_CHANNEL_GROUP;
404                 } else {
405                         i = reverse_map(devc->cctl[ch] & 0x33, vdivs_map,
406                                         ARRAY_SIZE(vdivs_map));
407                         if (i == -1)
408                                 ret = SR_ERR;
409                         else
410                                 *data = g_variant_new("(tt)", vdivs[i][0],
411                                                       vdivs[i][1]);
412                 }
413                 break;
414         case SR_CONF_COUPLING:
415                 if (ch == -1) {
416                         ret = SR_ERR_CHANNEL_GROUP;
417                 } else {
418                         i = reverse_map(devc->cctl[ch] & 0x0C, coupling_map,
419                                         ARRAY_SIZE(coupling_map));
420                         if (i == -1)
421                                 ret = SR_ERR;
422                         else
423                                 *data = g_variant_new_string(coupling[i]);
424                 }
425                 break;
426         case SR_CONF_PROBE_FACTOR:
427                 if (ch == -1)
428                         ret = SR_ERR_CHANNEL_GROUP;
429                 else
430                         *data = g_variant_new_uint64(devc->probe[ch]);
431                 break;
432         default:
433                 ret = SR_ERR_NA;
434         }
435
436         return ret;
437 }
438
439 static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
440                 const struct sr_channel_group *cg)
441 {
442         struct dev_context *devc = sdi->priv;
443         int ret, i, ch = -1;
444         uint64_t u, v;
445
446         if (cg) /* sr_config_set will validate cg using config_list */
447                 ch = ((struct sr_channel *)cg->channels->data)->index;
448
449         if (sdi->status != SR_ST_ACTIVE)
450                 return SR_ERR_DEV_CLOSED;
451
452         ret = SR_OK;
453         switch (key) {
454         case SR_CONF_LIMIT_FRAMES:
455                 devc->frame_limit = g_variant_get_uint64(data);
456                 break;
457         case SR_CONF_SAMPLERATE:
458                 i = find_in_array(data, G_VARIANT_TYPE_UINT64,
459                                   samplerates, ARRAY_SIZE(samplerates));
460                 if (i == -1)
461                         ret = SR_ERR_ARG;
462                 else
463                         devc->rate = i;
464                 break;
465         case SR_CONF_TRIGGER_SOURCE:
466                 i = find_in_array(data, G_VARIANT_TYPE_STRING,
467                                   trigger_sources, ARRAY_SIZE(trigger_sources));
468                 if (i == -1)
469                         ret = SR_ERR_ARG;
470                 else
471                         devc->cctl[0] = (devc->cctl[0] & 0x3F)
472                                       | trigger_sources_map[i];
473                 break;
474         case SR_CONF_TRIGGER_SLOPE:
475                 i = find_in_array(data, G_VARIANT_TYPE_STRING,
476                                   trigger_slopes, ARRAY_SIZE(trigger_slopes));
477                 if (i == -1)
478                         ret = SR_ERR_ARG;
479                 else
480                         devc->edge = i;
481                 break;
482         case SR_CONF_BUFFERSIZE:
483                 i = find_in_array(data, G_VARIANT_TYPE_UINT64,
484                                   buffersizes, ARRAY_SIZE(buffersizes));
485                 if (i == -1)
486                         ret = SR_ERR_ARG;
487                 else
488                         devc->last_step = i;
489                 break;
490         case SR_CONF_VDIV:
491                 if (ch == -1) {
492                         ret = SR_ERR_CHANNEL_GROUP;
493                 } else if (!g_variant_is_of_type(data, G_VARIANT_TYPE("(tt)"))) {
494                         ret = SR_ERR_ARG;
495                 } else {
496                         g_variant_get(data, "(tt)", &u, &v);
497                         for (i = 0; i < (int)ARRAY_SIZE(vdivs); i++)
498                                 if (vdivs[i][0] == u && vdivs[i][1] == v)
499                                         break;
500                         if (i == ARRAY_SIZE(vdivs))
501                                 ret = SR_ERR_ARG;
502                         else
503                                 devc->cctl[ch] = (devc->cctl[ch] & 0xCC)
504                                                | vdivs_map[i];
505                 }
506                 break;
507         case SR_CONF_COUPLING:
508                 if (ch == -1) {
509                         ret = SR_ERR_CHANNEL_GROUP;
510                 } else {
511                         i = find_in_array(data, G_VARIANT_TYPE_STRING,
512                                           coupling, ARRAY_SIZE(coupling));
513                         if (i == -1)
514                                 ret = SR_ERR_ARG;
515                         else
516                                 devc->cctl[ch] = (devc->cctl[ch] & 0xF3)
517                                                | coupling_map[i];
518                 }
519                 break;
520         case SR_CONF_PROBE_FACTOR:
521                 if (ch == -1) {
522                         ret = SR_ERR_CHANNEL_GROUP;
523                 } else {
524                         u = g_variant_get_uint64(data);
525                         if (!u)
526                                 ret = SR_ERR_ARG;
527                         else
528                                 devc->probe[ch] = u;
529                 }
530                 break;
531         default:
532                 ret = SR_ERR_NA;
533         }
534
535         return ret;
536 }
537
538 static int config_channel_set(const struct sr_dev_inst *sdi,
539                               struct sr_channel *ch,
540                               unsigned int changes)
541 {
542         struct dev_context *devc = sdi->priv;
543         uint8_t v;
544
545         if (changes & SR_CHANNEL_SET_ENABLED) {
546                 if (ch->enabled) {
547                         v = devc->channel | (1 << ch->index);
548                         if (v & (v - 1))
549                                 return SR_ERR;
550                         devc->channel = v;
551                         devc->enabled_channel->data = ch;
552                 } else {
553                         devc->channel &= ~(1 << ch->index);
554                 }
555         }
556         return SR_OK;
557 }
558
559 static int config_commit(const struct sr_dev_inst *sdi)
560 {
561         uint8_t state = hung_chang_dso_2100_read_mbox(sdi->conn, 0.02);
562         int ret;
563
564         if (sdi->status != SR_ST_ACTIVE)
565                 return SR_ERR_DEV_CLOSED;
566
567         switch (state) {
568         case 0x03:
569         case 0x14:
570         case 0x21:
571                 /* we will travel the complete config path on our way to state 1 */
572                 break;
573         case 0x00:
574                 state = 0x01;
575         default:
576                 ret = hung_chang_dso_2100_move_to(sdi, 1);
577                 if (ret != SR_OK)
578                         return ret;
579         case 0x01:
580                 hung_chang_dso_2100_write_mbox(sdi->conn, 4);
581         }
582         ret = hung_chang_dso_2100_move_to(sdi, 1);
583         if (ret != SR_OK)
584                 return ret;
585         return hung_chang_dso_2100_move_to(sdi, state);
586 }
587
588 static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
589                 const struct sr_channel_group *cg)
590 {
591         GVariantBuilder gvb;
592         GVariant *gvar, *rational[2];
593         GSList *l;
594         int i;
595
596         switch (key) {
597                 case SR_CONF_SCAN_OPTIONS:
598         case SR_CONF_DEVICE_OPTIONS:
599                 break;
600         case SR_CONF_SAMPLERATE:
601         case SR_CONF_TRIGGER_SOURCE:
602         case SR_CONF_TRIGGER_SLOPE:
603         case SR_CONF_BUFFERSIZE:
604                 if (!sdi || cg)
605                         return SR_ERR_NA;
606                 break;
607         case SR_CONF_VDIV:
608         case SR_CONF_COUPLING:
609                 if (!sdi)
610                         return SR_ERR_NA;
611                 if (!cg)
612                         return SR_ERR_CHANNEL_GROUP;
613                 l = g_slist_find(sdi->channel_groups, cg);
614                 if (!l)
615                         return SR_ERR_ARG;
616                 break;
617         default:
618                 return SR_ERR_NA;
619         }
620
621         switch (key) {
622         case SR_CONF_SCAN_OPTIONS:
623                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
624                                 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
625                 break;
626         case SR_CONF_DEVICE_OPTIONS:
627                 if (!sdi)
628                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
629                                         drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
630                 else if (!cg)
631                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
632                                         devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
633                 else
634                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
635                                         cgopts, ARRAY_SIZE(cgopts), sizeof(uint32_t));
636                 break;
637         case SR_CONF_SAMPLERATE:
638                 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
639                 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
640                                 samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t));
641                 g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar);
642                 *data = g_variant_builder_end(&gvb);
643                 break;
644         case SR_CONF_TRIGGER_SOURCE:
645                 *data = g_variant_new_strv(trigger_sources, ARRAY_SIZE(trigger_sources));
646                 break;
647         case SR_CONF_TRIGGER_SLOPE:
648                 *data = g_variant_new_strv(trigger_slopes, ARRAY_SIZE(trigger_slopes));
649                 break;
650         case SR_CONF_BUFFERSIZE:
651                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT64,
652                                 buffersizes, ARRAY_SIZE(buffersizes), sizeof(uint64_t));
653                 break;
654         case SR_CONF_VDIV:
655                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
656                 for (i = 0; i < (int)ARRAY_SIZE(vdivs); i++) {
657                         rational[0] = g_variant_new_uint64(vdivs[i][0]);
658                         rational[1] = g_variant_new_uint64(vdivs[i][1]);
659                         gvar = g_variant_new_tuple(rational, 2);
660                         g_variant_builder_add_value(&gvb, gvar);
661                 }
662                 *data = g_variant_builder_end(&gvb);
663                 break;
664         case SR_CONF_COUPLING:
665                 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
666                 break;
667         }
668
669         return SR_OK;
670 }
671
672 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
673 {
674         struct dev_context *devc = sdi->priv;
675         int ret;
676
677         if (sdi->status != SR_ST_ACTIVE)
678                 return SR_ERR_DEV_CLOSED;
679
680         if (devc->channel) {
681                 static const float res_array[] = {0.5, 1, 2, 5};
682                 static const uint8_t relays[] = {100, 10, 10, 1};
683                 devc->factor = devc->probe[devc->channel - 1] / 32.0;
684                 devc->factor *= res_array[devc->cctl[devc->channel - 1] & 0x03];
685                 devc->factor /= relays[(devc->cctl[devc->channel - 1] >> 4) & 0x03];
686         }
687         devc->frame = 0;
688         devc->state_known = TRUE;
689         devc->step = 0;
690         devc->adc2 = FALSE;
691         devc->retries = MAX_RETRIES;
692
693         ret = hung_chang_dso_2100_move_to(sdi, 0x21);
694         if (ret != SR_OK)
695                 return ret;
696
697         std_session_send_df_header(sdi, LOG_PREFIX);
698
699         sr_session_source_add(sdi->session, -1, 0, 8,
700                               hung_chang_dso_2100_poll, (void *)sdi);
701
702         return SR_OK;
703 }
704
705 SR_PRIV int hung_chang_dso_2100_dev_acquisition_stop(const struct sr_dev_inst *sdi)
706 {
707         if (sdi->status != SR_ST_ACTIVE)
708                 return SR_ERR_DEV_CLOSED;
709
710         std_session_send_df_end(sdi, LOG_PREFIX);
711         sr_session_source_remove(sdi->session, -1);
712         hung_chang_dso_2100_move_to(sdi, 1);
713
714         return SR_OK;
715 }
716
717 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
718 {
719         return hung_chang_dso_2100_dev_acquisition_stop(sdi);
720 }
721
722 SR_PRIV struct sr_dev_driver hung_chang_dso_2100_driver_info = {
723         .name = "hung-chang-dso-2100",
724         .longname = "Hung-Chang DSO-2100",
725         .api_version = 1,
726         .init = init,
727         .cleanup = std_cleanup,
728         .scan = scan,
729         .dev_list = std_dev_list,
730         .dev_clear = dev_clear,
731         .config_get = config_get,
732         .config_set = config_set,
733         .config_channel_set = config_channel_set,
734         .config_commit = config_commit,
735         .config_list = config_list,
736         .dev_open = dev_open,
737         .dev_close = dev_close,
738         .dev_acquisition_start = dev_acquisition_start,
739         .dev_acquisition_stop = dev_acquisition_stop,
740         .context = NULL,
741 };