]> sigrok.org Git - libsigrok.git/blob - src/hardware/hung-chang-dso-2100/api.c
55b9922b3a24fe736383ce2924380bf6b1369344
[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(sr_ctx, di, 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 GSList *dev_list(const struct sr_dev_driver *di)
234 {
235         return ((struct drv_context *)(di->context))->instances;
236 }
237
238 static void clear_private(void *priv)
239 {
240         struct dev_context *devc = priv;
241
242         g_slist_free(devc->enabled_channel);
243 }
244
245 static int dev_clear(const struct sr_dev_driver *di)
246 {
247         struct drv_context *drvc = di->context;
248         struct sr_dev_inst *sdi;
249         GSList *l;
250
251         if (drvc) {
252                 for (l = drvc->instances; l; l = l->next) {
253                         sdi = l->data;
254                         ieee1284_unref(sdi->conn);
255                 }
256         }
257
258         return std_dev_clear(di, clear_private);
259 }
260
261 static int dev_open(struct sr_dev_inst *sdi)
262 {
263         struct dev_context *devc = sdi->priv;
264         int i;
265
266         if (sdi->status != SR_ST_INACTIVE)
267                 goto fail1;
268
269         if (ieee1284_open(sdi->conn, 0, &i) != E1284_OK)
270                 goto fail1;
271
272         if (ieee1284_claim(sdi->conn) != E1284_OK)
273                 goto fail2;
274
275         if (ieee1284_data_dir(sdi->conn, 1) != E1284_OK)
276                 goto fail3;
277
278         if (hung_chang_dso_2100_move_to(sdi, 1))
279                 goto fail3;
280
281         devc->samples = g_try_malloc(1000 * sizeof(*devc->samples));
282         if (!devc->samples)
283                 goto fail3;
284
285         sdi->status = SR_ST_ACTIVE;
286
287         return SR_OK;
288
289 fail3:
290         hung_chang_dso_2100_reset_port(sdi->conn);
291         ieee1284_release(sdi->conn);
292 fail2:
293         ieee1284_close(sdi->conn);
294 fail1:
295         return SR_ERR;
296 }
297
298 static int dev_close(struct sr_dev_inst *sdi)
299 {
300         struct dev_context *devc = sdi->priv;
301
302         if (sdi->status != SR_ST_ACTIVE)
303                 return SR_OK;
304
305         g_free(devc->samples);
306         hung_chang_dso_2100_reset_port(sdi->conn);
307         ieee1284_release(sdi->conn);
308         ieee1284_close(sdi->conn);
309         sdi->status = SR_ST_INACTIVE;
310
311         return SR_OK;
312 }
313
314 static int find_in_array(GVariant *data, const GVariantType *type,
315                          const void *arr, int n)
316 {
317         const char * const *sarr;
318         const char *s;
319         const uint64_t *u64arr;
320         const uint8_t *u8arr;
321         uint64_t u64;
322         uint8_t u8;
323         int i;
324
325         if (!g_variant_is_of_type(data, type))
326                 return -1;
327
328         switch (g_variant_classify(data)) {
329         case G_VARIANT_CLASS_STRING:
330                 s = g_variant_get_string(data, NULL);
331                 sarr = arr;
332
333                 for (i = 0; i < n; i++)
334                         if (!strcmp(s, sarr[i]))
335                                 return i;
336                 break;
337         case G_VARIANT_CLASS_UINT64:
338                 u64 = g_variant_get_uint64(data);
339                 u64arr = arr;
340
341                 for (i = 0; i < n; i++)
342                         if (u64 == u64arr[i])
343                                 return i;
344                 break;
345         case G_VARIANT_CLASS_BYTE:
346                 u8 = g_variant_get_byte(data);
347                 u8arr = arr;
348
349                 for (i = 0; i < n; i++)
350                         if (u8 == u8arr[i])
351                                 return i;
352         default:
353                 break;
354         }
355
356         return -1;
357 }
358
359 static int reverse_map(uint8_t u, const uint8_t *arr, int n)
360 {
361         GVariant *v = g_variant_new_byte(u);
362         int i = find_in_array(v, G_VARIANT_TYPE_BYTE, arr, n);
363         g_variant_unref(v);
364         return i;
365 }
366
367 static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
368                 const struct sr_channel_group *cg)
369 {
370         struct dev_context *devc = sdi->priv;
371         struct parport *port;
372         int ret, i, ch = -1;
373
374         if (cg) /* sr_config_get will validate cg using config_list */
375                 ch = ((struct sr_channel *)cg->channels->data)->index;
376
377         ret = SR_OK;
378         switch (key) {
379         case SR_CONF_CONN:
380                 port = sdi->conn;
381                 *data = g_variant_new_string(port->name);
382                 break;
383         case SR_CONF_LIMIT_FRAMES:
384                 *data = g_variant_new_uint64(devc->frame_limit);
385                 break;
386         case SR_CONF_SAMPLERATE:
387                 *data = g_variant_new_uint64(samplerates[devc->rate]);
388                 break;
389         case SR_CONF_TRIGGER_SOURCE:
390                 i = reverse_map(devc->cctl[0] & 0xC0, trigger_sources_map,
391                                 ARRAY_SIZE(trigger_sources_map));
392                 if (i == -1)
393                         ret = SR_ERR;
394                 else
395                         *data = g_variant_new_string(trigger_sources[i]);
396                 break;
397         case SR_CONF_TRIGGER_SLOPE:
398                 if (devc->edge >= ARRAY_SIZE(trigger_slopes))
399                         ret = SR_ERR;
400                 else
401                         *data = g_variant_new_string(trigger_slopes[devc->edge]);
402                 break;
403         case SR_CONF_BUFFERSIZE:
404                 *data = g_variant_new_uint64(buffersizes[devc->last_step]);
405                 break;
406         case SR_CONF_VDIV:
407                 if (ch == -1) {
408                         ret = SR_ERR_CHANNEL_GROUP;
409                 } else {
410                         i = reverse_map(devc->cctl[ch] & 0x33, vdivs_map,
411                                         ARRAY_SIZE(vdivs_map));
412                         if (i == -1)
413                                 ret = SR_ERR;
414                         else
415                                 *data = g_variant_new("(tt)", vdivs[i][0],
416                                                       vdivs[i][1]);
417                 }
418                 break;
419         case SR_CONF_COUPLING:
420                 if (ch == -1) {
421                         ret = SR_ERR_CHANNEL_GROUP;
422                 } else {
423                         i = reverse_map(devc->cctl[ch] & 0x0C, coupling_map,
424                                         ARRAY_SIZE(coupling_map));
425                         if (i == -1)
426                                 ret = SR_ERR;
427                         else
428                                 *data = g_variant_new_string(coupling[i]);
429                 }
430                 break;
431         case SR_CONF_PROBE_FACTOR:
432                 if (ch == -1)
433                         ret = SR_ERR_CHANNEL_GROUP;
434                 else
435                         *data = g_variant_new_uint64(devc->probe[ch]);
436                 break;
437         default:
438                 ret = SR_ERR_NA;
439         }
440
441         return ret;
442 }
443
444 static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
445                 const struct sr_channel_group *cg)
446 {
447         struct dev_context *devc = sdi->priv;
448         int ret, i, ch = -1;
449         uint64_t u, v;
450
451         if (cg) /* sr_config_set will validate cg using config_list */
452                 ch = ((struct sr_channel *)cg->channels->data)->index;
453
454         if (sdi->status != SR_ST_ACTIVE)
455                 return SR_ERR_DEV_CLOSED;
456
457         ret = SR_OK;
458         switch (key) {
459         case SR_CONF_LIMIT_FRAMES:
460                 devc->frame_limit = g_variant_get_uint64(data);
461                 break;
462         case SR_CONF_SAMPLERATE:
463                 i = find_in_array(data, G_VARIANT_TYPE_UINT64,
464                                   samplerates, ARRAY_SIZE(samplerates));
465                 if (i == -1)
466                         ret = SR_ERR_ARG;
467                 else
468                         devc->rate = i;
469                 break;
470         case SR_CONF_TRIGGER_SOURCE:
471                 i = find_in_array(data, G_VARIANT_TYPE_STRING,
472                                   trigger_sources, ARRAY_SIZE(trigger_sources));
473                 if (i == -1)
474                         ret = SR_ERR_ARG;
475                 else
476                         devc->cctl[0] = (devc->cctl[0] & 0x3F)
477                                       | trigger_sources_map[i];
478                 break;
479         case SR_CONF_TRIGGER_SLOPE:
480                 i = find_in_array(data, G_VARIANT_TYPE_STRING,
481                                   trigger_slopes, ARRAY_SIZE(trigger_slopes));
482                 if (i == -1)
483                         ret = SR_ERR_ARG;
484                 else
485                         devc->edge = i;
486                 break;
487         case SR_CONF_BUFFERSIZE:
488                 i = find_in_array(data, G_VARIANT_TYPE_UINT64,
489                                   buffersizes, ARRAY_SIZE(buffersizes));
490                 if (i == -1)
491                         ret = SR_ERR_ARG;
492                 else
493                         devc->last_step = i;
494                 break;
495         case SR_CONF_VDIV:
496                 if (ch == -1) {
497                         ret = SR_ERR_CHANNEL_GROUP;
498                 } else if (!g_variant_is_of_type(data, G_VARIANT_TYPE("(tt)"))) {
499                         ret = SR_ERR_ARG;
500                 } else {
501                         g_variant_get(data, "(tt)", &u, &v);
502                         for (i = 0; i < (int)ARRAY_SIZE(vdivs); i++)
503                                 if (vdivs[i][0] == u && vdivs[i][1] == v)
504                                         break;
505                         if (i == ARRAY_SIZE(vdivs))
506                                 ret = SR_ERR_ARG;
507                         else
508                                 devc->cctl[ch] = (devc->cctl[ch] & 0xCC)
509                                                | vdivs_map[i];
510                 }
511                 break;
512         case SR_CONF_COUPLING:
513                 if (ch == -1) {
514                         ret = SR_ERR_CHANNEL_GROUP;
515                 } else {
516                         i = find_in_array(data, G_VARIANT_TYPE_STRING,
517                                           coupling, ARRAY_SIZE(coupling));
518                         if (i == -1)
519                                 ret = SR_ERR_ARG;
520                         else
521                                 devc->cctl[ch] = (devc->cctl[ch] & 0xF3)
522                                                | coupling_map[i];
523                 }
524                 break;
525         case SR_CONF_PROBE_FACTOR:
526                 if (ch == -1) {
527                         ret = SR_ERR_CHANNEL_GROUP;
528                 } else {
529                         u = g_variant_get_uint64(data);
530                         if (!u)
531                                 ret = SR_ERR_ARG;
532                         else
533                                 devc->probe[ch] = u;
534                 }
535                 break;
536         default:
537                 ret = SR_ERR_NA;
538         }
539
540         return ret;
541 }
542
543 static int config_channel_set(const struct sr_dev_inst *sdi,
544                               struct sr_channel *ch,
545                               unsigned int changes)
546 {
547         struct dev_context *devc = sdi->priv;
548         uint8_t v;
549
550         if (changes & SR_CHANNEL_SET_ENABLED) {
551                 if (ch->enabled) {
552                         v = devc->channel | (1 << ch->index);
553                         if (v & (v - 1))
554                                 return SR_ERR;
555                         devc->channel = v;
556                         devc->enabled_channel->data = ch;
557                 } else {
558                         devc->channel &= ~(1 << ch->index);
559                 }
560         }
561         return SR_OK;
562 }
563
564 static int config_commit(const struct sr_dev_inst *sdi)
565 {
566         uint8_t state = hung_chang_dso_2100_read_mbox(sdi->conn, 0.02);
567         int ret;
568
569         if (sdi->status != SR_ST_ACTIVE)
570                 return SR_ERR_DEV_CLOSED;
571
572         switch (state) {
573         case 0x03:
574         case 0x14:
575         case 0x21:
576                 /* we will travel the complete config path on our way to state 1 */
577                 break;
578         case 0x00:
579                 state = 0x01;
580         default:
581                 ret = hung_chang_dso_2100_move_to(sdi, 1);
582                 if (ret != SR_OK)
583                         return ret;
584         case 0x01:
585                 hung_chang_dso_2100_write_mbox(sdi->conn, 4);
586         }
587         ret = hung_chang_dso_2100_move_to(sdi, 1);
588         if (ret != SR_OK)
589                 return ret;
590         return hung_chang_dso_2100_move_to(sdi, state);
591 }
592
593 static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
594                 const struct sr_channel_group *cg)
595 {
596         GVariantBuilder gvb;
597         GVariant *gvar, *rational[2];
598         GSList *l;
599         int i;
600
601         switch (key) {
602                 case SR_CONF_SCAN_OPTIONS:
603         case SR_CONF_DEVICE_OPTIONS:
604                 break;
605         case SR_CONF_SAMPLERATE:
606         case SR_CONF_TRIGGER_SOURCE:
607         case SR_CONF_TRIGGER_SLOPE:
608         case SR_CONF_BUFFERSIZE:
609                 if (!sdi || cg)
610                         return SR_ERR_NA;
611                 break;
612         case SR_CONF_VDIV:
613         case SR_CONF_COUPLING:
614                 if (!sdi)
615                         return SR_ERR_NA;
616                 if (!cg)
617                         return SR_ERR_CHANNEL_GROUP;
618                 l = g_slist_find(sdi->channel_groups, cg);
619                 if (!l)
620                         return SR_ERR_ARG;
621                 break;
622         default:
623                 return SR_ERR_NA;
624         }
625
626         switch (key) {
627         case SR_CONF_SCAN_OPTIONS:
628                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
629                                 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
630                 break;
631         case SR_CONF_DEVICE_OPTIONS:
632                 if (!sdi)
633                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
634                                         drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
635                 else if (!cg)
636                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
637                                         devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
638                 else
639                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
640                                         cgopts, ARRAY_SIZE(cgopts), sizeof(uint32_t));
641                 break;
642         case SR_CONF_SAMPLERATE:
643                 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
644                 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
645                                 samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t));
646                 g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar);
647                 *data = g_variant_builder_end(&gvb);
648                 break;
649         case SR_CONF_TRIGGER_SOURCE:
650                 *data = g_variant_new_strv(trigger_sources, ARRAY_SIZE(trigger_sources));
651                 break;
652         case SR_CONF_TRIGGER_SLOPE:
653                 *data = g_variant_new_strv(trigger_slopes, ARRAY_SIZE(trigger_slopes));
654                 break;
655         case SR_CONF_BUFFERSIZE:
656                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT64,
657                                 buffersizes, ARRAY_SIZE(buffersizes), sizeof(uint64_t));
658                 break;
659         case SR_CONF_VDIV:
660                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
661                 for (i = 0; i < (int)ARRAY_SIZE(vdivs); i++) {
662                         rational[0] = g_variant_new_uint64(vdivs[i][0]);
663                         rational[1] = g_variant_new_uint64(vdivs[i][1]);
664                         gvar = g_variant_new_tuple(rational, 2);
665                         g_variant_builder_add_value(&gvb, gvar);
666                 }
667                 *data = g_variant_builder_end(&gvb);
668                 break;
669         case SR_CONF_COUPLING:
670                 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
671                 break;
672         }
673
674         return SR_OK;
675 }
676
677 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
678 {
679         struct dev_context *devc = sdi->priv;
680         int ret;
681
682         if (sdi->status != SR_ST_ACTIVE)
683                 return SR_ERR_DEV_CLOSED;
684
685         if (devc->channel) {
686                 static const float res_array[] = {0.5, 1, 2, 5};
687                 static const uint8_t relays[] = {100, 10, 10, 1};
688                 devc->factor = devc->probe[devc->channel - 1] / 32.0;
689                 devc->factor *= res_array[devc->cctl[devc->channel - 1] & 0x03];
690                 devc->factor /= relays[(devc->cctl[devc->channel - 1] >> 4) & 0x03];
691         }
692         devc->frame = 0;
693         devc->state_known = TRUE;
694         devc->step = 0;
695         devc->adc2 = FALSE;
696         devc->retries = MAX_RETRIES;
697
698         ret = hung_chang_dso_2100_move_to(sdi, 0x21);
699         if (ret != SR_OK)
700                 return ret;
701
702         std_session_send_df_header(sdi, LOG_PREFIX);
703
704         sr_session_source_add(sdi->session, -1, 0, 8,
705                               hung_chang_dso_2100_poll, (void *)sdi);
706
707         return SR_OK;
708 }
709
710 SR_PRIV int hung_chang_dso_2100_dev_acquisition_stop(const struct sr_dev_inst *sdi)
711 {
712         if (sdi->status != SR_ST_ACTIVE)
713                 return SR_ERR_DEV_CLOSED;
714
715         std_session_send_df_end(sdi, LOG_PREFIX);
716         sr_session_source_remove(sdi->session, -1);
717         hung_chang_dso_2100_move_to(sdi, 1);
718
719         return SR_OK;
720 }
721
722 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
723 {
724         return hung_chang_dso_2100_dev_acquisition_stop(sdi);
725 }
726
727 SR_PRIV struct sr_dev_driver hung_chang_dso_2100_driver_info = {
728         .name = "hung-chang-dso-2100",
729         .longname = "Hung-Chang DSO-2100",
730         .api_version = 1,
731         .init = init,
732         .cleanup = std_cleanup,
733         .scan = scan,
734         .dev_list = dev_list,
735         .dev_clear = dev_clear,
736         .config_get = config_get,
737         .config_set = config_set,
738         .config_channel_set = config_channel_set,
739         .config_commit = config_commit,
740         .config_list = config_list,
741         .dev_open = dev_open,
742         .dev_close = dev_close,
743         .dev_acquisition_start = dev_acquisition_start,
744         .dev_acquisition_stop = dev_acquisition_stop,
745         .context = NULL,
746 };