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