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