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