]> sigrok.org Git - libsigrok.git/blame - hardware/hameg-hmo/api.c
hameg-hmo: Minor cosmetics, coding-style fixes.
[libsigrok.git] / hardware / hameg-hmo / api.c
CommitLineData
06a3e78a
DJ
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.com>
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
13f2b9d7
DJ
20#include <stdlib.h>
21#include <glib/gstdio.h>
06a3e78a
DJ
22#include "protocol.h"
23
13f2b9d7
DJ
24#define SERIALCOMM "115200/8n1/flow=1"
25
26static const int32_t hwopts[] = {
27 SR_CONF_CONN,
28 SR_CONF_SERIALCOMM,
29};
30
31struct usb_id_info {
32 uint16_t vendor_id;
33 uint16_t product_id;
89280b1a 34};
13f2b9d7
DJ
35
36static struct usb_id_info ho_models[] = {
89280b1a
UH
37 { 0x0403, 0xed72 }, /* HO720 */
38 { 0x0403, 0xed73 }, /* HO730 */
13f2b9d7 39};
06a3e78a
DJ
40
41static int init(struct sr_context *sr_ctx)
42{
43 return std_init(sr_ctx, di, LOG_PREFIX);
44}
45
13f2b9d7
DJ
46/**
47 * Find USB serial devices via the USB vendor ID and product ID.
48 *
89280b1a
UH
49 * @param vendor_id Vendor ID of the USB device.
50 * @param product_id Product ID of the USB device.
13f2b9d7 51 *
89280b1a
UH
52 * @return A GSList of strings containing the path of the serial device or
53 * NULL if no serial device is found. The returned list must be freed
54 * by the caller.
13f2b9d7 55 */
89280b1a 56static GSList *auto_find_usb(uint16_t vendor_id, uint16_t product_id)
13f2b9d7
DJ
57{
58#ifdef __linux__
59 const gchar *usb_dev;
60 const char device_tree[] = "/sys/bus/usb/devices/";
89280b1a 61 GDir *devices_dir, *device_dir;
13f2b9d7 62 GSList *l = NULL;
89280b1a 63 GSList *tty_devs;
13f2b9d7 64 GSList *matched_paths;
89280b1a
UH
65 FILE *fd;
66 char tmp[5];
67 gchar *vendor_path, *product_path, *path_copy;
68 gchar *prefix, *subdir_path, *device_path, *tty_path;
69 unsigned long read_vendor_id, read_product_id;
70 const char *file;
13f2b9d7
DJ
71
72 l = NULL;
89280b1a 73 tty_devs = NULL;
13f2b9d7
DJ
74 matched_paths = NULL;
75
76 if (!(devices_dir = g_dir_open(device_tree, 0, NULL)))
77 return NULL;
78
79 /*
80 * Find potential candidates using the vendor ID and product ID
89280b1a 81 * and store them in matched_paths.
13f2b9d7
DJ
82 */
83 while ((usb_dev = g_dir_read_name(devices_dir))) {
13f2b9d7
DJ
84 vendor_path = g_strconcat(device_tree,
85 usb_dev, "/idVendor", NULL);
86 product_path = g_strconcat(device_tree,
87 usb_dev, "/idProduct", NULL);
88
89 if (!g_file_test(vendor_path, G_FILE_TEST_EXISTS) ||
90 !g_file_test(product_path, G_FILE_TEST_EXISTS))
91 goto skip_device;
92
93 if ((fd = g_fopen(vendor_path, "r")) == NULL)
94 goto skip_device;
95
96 if (fgets(tmp, sizeof(tmp), fd) == NULL) {
97 fclose(fd);
98 goto skip_device;
99 }
100 read_vendor_id = strtoul(tmp, NULL, 16);
101
102 fclose(fd);
103
104 if ((fd = g_fopen(product_path, "r")) == NULL)
105 goto skip_device;
106
107 if (fgets(tmp, sizeof(tmp), fd) == NULL) {
108 fclose(fd);
109 goto skip_device;
110 }
111 read_product_id = strtoul(tmp, NULL, 16);
112
113 fclose(fd);
114
115 if (vendor_id == read_vendor_id &&
116 product_id == read_product_id) {
13f2b9d7
DJ
117 path_copy = g_strdup(usb_dev);
118 matched_paths = g_slist_prepend(matched_paths,
119 path_copy);
120 }
121
89280b1a 122skip_device:
13f2b9d7
DJ
123 g_free(vendor_path);
124 g_free(product_path);
125 }
126 g_dir_close(devices_dir);
127
89280b1a 128 /* For every matched device try to find a ttyUSBX subfolder. */
13f2b9d7 129 for (l = matched_paths; l; l = l->next) {
13f2b9d7
DJ
130 subdir_path = NULL;
131
132 device_path = g_strconcat(device_tree, l->data, NULL);
133
134 if (!(device_dir = g_dir_open(device_path, 0, NULL))) {
135 g_free(device_path);
136 continue;
137 }
138
139 prefix = g_strconcat(l->data, ":", NULL);
140
141 while ((file = g_dir_read_name(device_dir))) {
142 if (g_str_has_prefix(file, prefix)) {
143 subdir_path = g_strconcat(device_path,
89280b1a 144 "/", file, NULL);
13f2b9d7
DJ
145 break;
146 }
147 }
148 g_dir_close(device_dir);
149
150 g_free(prefix);
151 g_free(device_path);
152
153 if (subdir_path) {
154 if (!(device_dir = g_dir_open(subdir_path, 0, NULL))) {
155 g_free(subdir_path);
156 continue;
157 }
158 g_free(subdir_path);
159
160 while ((file = g_dir_read_name(device_dir))) {
161 if (g_str_has_prefix(file, "ttyUSB")) {
13f2b9d7
DJ
162 tty_path = g_strconcat("/dev/",
163 file, NULL);
89280b1a 164 sr_dbg("Found USB device %04x:%04x attached to %s.",
13f2b9d7 165 vendor_id, product_id, tty_path);
89280b1a
UH
166 tty_devs = g_slist_prepend(tty_devs,
167 tty_path);
13f2b9d7
DJ
168 break;
169 }
170 }
171 g_dir_close(device_dir);
172 }
173 }
174 g_slist_free_full(matched_paths, g_free);
175
89280b1a 176 return tty_devs;
13f2b9d7
DJ
177#else
178 return NULL;
179#endif
180}
181
06a3e78a
DJ
182static GSList *scan(GSList *options)
183{
06a3e78a 184 GSList *devices;
13f2b9d7
DJ
185 struct drv_context *drvc;
186 struct sr_dev_inst *sdi;
89280b1a
UH
187 const char *serial_device, *serial_options;
188 GSList *l, *tty_devs;
189 unsigned int i;
06a3e78a 190
13f2b9d7
DJ
191 serial_device = NULL;
192 serial_options = SERIALCOMM;
13f2b9d7 193 sdi = NULL;
06a3e78a
DJ
194 devices = NULL;
195 drvc = di->priv;
196 drvc->instances = NULL;
197
13f2b9d7
DJ
198 if (sr_serial_extract_options(options, &serial_device,
199 &serial_options) == SR_OK) {
200 sdi = hameg_probe_serial_device(serial_device, serial_options);
13f2b9d7
DJ
201 if (sdi != NULL) {
202 devices = g_slist_append(devices, sdi);
203 drvc->instances = g_slist_append(drvc->instances, sdi);
204 }
13f2b9d7 205 } else {
89280b1a 206 tty_devs = NULL;
13f2b9d7
DJ
207
208 for (i = 0; i < ARRAY_SIZE(ho_models); i++) {
209 if ((l = auto_find_usb(ho_models[i].vendor_id,
210 ho_models[i].product_id)) == NULL)
211 continue;
89280b1a 212 tty_devs = g_slist_concat(tty_devs, l);
13f2b9d7
DJ
213 }
214
89280b1a 215 for (l = tty_devs; l; l = l->next) {
13f2b9d7
DJ
216 sdi = hameg_probe_serial_device(l->data, serial_options);
217 if (sdi != NULL) {
218 devices = g_slist_append(devices, sdi);
219 drvc->instances = g_slist_append(drvc->instances, sdi);
220 }
221 }
222
89280b1a 223 g_slist_free_full(tty_devs, g_free);
13f2b9d7 224 }
06a3e78a
DJ
225
226 return devices;
227}
228
229static GSList *dev_list(void)
230{
231 return ((struct drv_context *)(di->priv))->instances;
232}
233
13f2b9d7
DJ
234static void clear_helper(void *priv)
235{
236 unsigned int i;
13f2b9d7
DJ
237 struct dev_context *devc;
238 struct scope_config *model;
239
240 devc = priv;
241 model = devc->model_config;
242
243 scope_state_free(devc->model_state);
244
89280b1a 245 for (i = 0; i < model->analog_channels; ++i)
13f2b9d7 246 g_slist_free(devc->analog_groups[i].probes);
13f2b9d7
DJ
247
248 for (i = 0; i < model->digital_pods; ++i) {
249 g_slist_free(devc->digital_groups[i].probes);
250 g_free(devc->digital_groups[i].name);
251 }
252
253 g_free(devc->analog_groups);
254 g_free(devc->digital_groups);
255
256 g_free(devc);
257}
258
06a3e78a
DJ
259static int dev_clear(void)
260{
13f2b9d7 261 return std_dev_clear(di, clear_helper);
06a3e78a
DJ
262}
263
264static int dev_open(struct sr_dev_inst *sdi)
265{
13f2b9d7
DJ
266 if (sdi->status != SR_ST_ACTIVE &&
267 serial_open(sdi->conn, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
268 return SR_ERR;
06a3e78a 269
13f2b9d7
DJ
270 if (scope_state_get(sdi) != SR_OK)
271 return SR_ERR;
06a3e78a
DJ
272
273 sdi->status = SR_ST_ACTIVE;
274
275 return SR_OK;
276}
277
278static int dev_close(struct sr_dev_inst *sdi)
279{
13f2b9d7
DJ
280 if (sdi->status == SR_ST_INACTIVE)
281 return SR_OK;
06a3e78a 282
13f2b9d7 283 serial_close(sdi->conn);
06a3e78a
DJ
284
285 sdi->status = SR_ST_INACTIVE;
286
287 return SR_OK;
288}
289
290static int cleanup(void)
291{
292 dev_clear();
293
06a3e78a
DJ
294 return SR_OK;
295}
296
13f2b9d7
DJ
297static int check_probe_group(struct dev_context *devc,
298 const struct sr_probe_group *probe_group)
299{
300 unsigned int i;
301 struct scope_config *model;
302
303 model = devc->model_config;
304
305 if (!probe_group)
306 return PG_NONE;
307
308 for (i = 0; i < model->analog_channels; ++i)
309 if (probe_group == &devc->analog_groups[i])
310 return PG_ANALOG;
311
312 for (i = 0; i < model->digital_pods; ++i)
313 if (probe_group == &devc->digital_groups[i])
314 return PG_DIGITAL;
315
316 sr_err("Invalid probe group specified.");
89280b1a 317
13f2b9d7
DJ
318 return PG_INVALID;
319}
320
321static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
322 const struct sr_probe_group *probe_group)
06a3e78a 323{
89280b1a 324 int ret, pg_type;
13f2b9d7 325 unsigned int i;
13f2b9d7
DJ
326 struct dev_context *devc;
327 struct scope_config *model;
328
329 if (!sdi || !(devc = sdi->priv))
330 return SR_ERR_ARG;
331
332 if ((pg_type = check_probe_group(devc, probe_group)) == PG_INVALID)
333 return SR_ERR;
06a3e78a 334
13f2b9d7
DJ
335 ret = SR_ERR_NA;
336 model = devc->model_config;
06a3e78a 337
06a3e78a 338 switch (key) {
13f2b9d7
DJ
339 case SR_CONF_NUM_TIMEBASE:
340 *data = g_variant_new_int32(model->num_xdivs);
341 ret = SR_OK;
342 break;
13f2b9d7
DJ
343 case SR_CONF_NUM_VDIV:
344 if (pg_type == PG_NONE) {
345 sr_err("No probe group specified.");
346 return SR_ERR_PROBE_GROUP;
13f2b9d7
DJ
347 } else if (pg_type == PG_ANALOG) {
348 for (i = 0; i < model->analog_channels; ++i) {
349 if (probe_group == &devc->analog_groups[i]) {
350 *data = g_variant_new_int32(model->num_ydivs);
351 ret = SR_OK;
352 break;
353 }
354 }
355
356 } else {
357 ret = SR_ERR_NA;
358 }
359 break;
06a3e78a 360 default:
13f2b9d7 361 ret = SR_ERR_NA;
06a3e78a
DJ
362 }
363
364 return ret;
365}
366
13f2b9d7
DJ
367static GVariant *build_tuples(const uint64_t (*array)[][2], unsigned int n)
368{
369 unsigned int i;
13f2b9d7
DJ
370 GVariant *rational[2];
371 GVariantBuilder gvb;
372
373 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
374
375 for (i = 0; i < n; i++) {
376 rational[0] = g_variant_new_uint64((*array)[i][0]);
377 rational[1] = g_variant_new_uint64((*array)[i][1]);
378
89280b1a 379 /* FIXME: Valgrind reports a memory leak here. */
13f2b9d7
DJ
380 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
381 }
382
383 return g_variant_builder_end(&gvb);
384}
385
386static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
387 const struct sr_probe_group *probe_group)
06a3e78a 388{
89280b1a
UH
389 int ret, pg_type;
390 unsigned int i, j;
13f2b9d7 391 char command[MAX_COMMAND_SIZE];
13f2b9d7
DJ
392 struct dev_context *devc;
393 struct scope_config *model;
394 struct scope_state *state;
89280b1a
UH
395 const char *tmp;
396 uint64_t p, q, tmp_u64;
397 double tmp_d;
06a3e78a 398
13f2b9d7
DJ
399 if (!sdi || !(devc = sdi->priv))
400 return SR_ERR_ARG;
401
402 if ((pg_type = check_probe_group(devc, probe_group)) == PG_INVALID)
403 return SR_ERR;
404
405 model = devc->model_config;
406 state = devc->model_state;
407
408 ret = SR_ERR_NA;
06a3e78a 409
06a3e78a 410 switch (key) {
13f2b9d7
DJ
411 case SR_CONF_LIMIT_FRAMES:
412 devc->frame_limit = g_variant_get_uint64(data);
413 ret = SR_OK;
414 break;
13f2b9d7 415 case SR_CONF_TRIGGER_SOURCE:
13f2b9d7 416 tmp = g_variant_get_string(data, NULL);
13f2b9d7
DJ
417 for (i = 0; (*model->trigger_sources)[i]; i++) {
418 if (!g_strcmp0(tmp, (*model->trigger_sources)[i])) {
419 state->trigger_source = i;
13f2b9d7
DJ
420 g_snprintf(command, sizeof(command),
421 (*model->scpi_dialect)[SCPI_CMD_SET_TRIGGER_SOURCE],
422 (*model->trigger_sources)[i]);
423
424 ret = sr_scpi_send(sdi->conn, command);
425 break;
426 }
427 }
89280b1a 428 break;
13f2b9d7 429 case SR_CONF_VDIV:
13f2b9d7
DJ
430 if (pg_type == PG_NONE) {
431 sr_err("No probe group specified.");
432 return SR_ERR_PROBE_GROUP;
433 }
434
435 g_variant_get(data, "(tt)", &p, &q);
436
437 for (i = 0; i < model->num_vdivs; i++) {
438 if (p == (*model->vdivs)[i][0] &&
89280b1a 439 q == (*model->vdivs)[i][1]) {
13f2b9d7
DJ
440 for (j = 1; j <= model->analog_channels; ++j) {
441 if (probe_group == &devc->analog_groups[j - 1]) {
89280b1a 442 state->analog_channels[j - 1].vdiv = (float) p / q;
13f2b9d7
DJ
443 g_snprintf(command, sizeof(command),
444 (*model->scpi_dialect)[SCPI_CMD_SET_VERTICAL_DIV],
445 j, state->analog_channels[j-1].vdiv);
446
447 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
448 sr_scpi_get_opc(sdi->conn) != SR_OK)
449 return SR_ERR;
450
451 break;
452 }
453 }
454
455 ret = SR_OK;
456 break;
457 }
458 }
89280b1a 459 break;
13f2b9d7 460 case SR_CONF_TIMEBASE:
13f2b9d7
DJ
461 g_variant_get(data, "(tt)", &p, &q);
462
463 for (i = 0; i < model->num_timebases; i++) {
464 if (p == (*model->timebases)[i][0] &&
89280b1a 465 q == (*model->timebases)[i][1]) {
13f2b9d7
DJ
466 state->timebase = (float) p / q;
467 g_snprintf(command, sizeof(command),
468 (*model->scpi_dialect)[SCPI_CMD_SET_TIMEBASE],
469 state->timebase);
470
471 ret = sr_scpi_send(sdi->conn, command);
472 break;
473 }
474 }
89280b1a 475 break;
13f2b9d7 476 case SR_CONF_HORIZ_TRIGGERPOS:
89280b1a 477 tmp_d = g_variant_get_double(data);
13f2b9d7 478
89280b1a 479 if (tmp_d < 0.0 || tmp_d > 1.0)
13f2b9d7
DJ
480 return SR_ERR;
481
89280b1a 482 state->horiz_triggerpos = -(tmp_d - 0.5) * state->timebase * model->num_xdivs;
13f2b9d7
DJ
483 g_snprintf(command, sizeof(command),
484 (*model->scpi_dialect)[SCPI_CMD_SET_HORIZ_TRIGGERPOS],
485 state->horiz_triggerpos);
486
487 ret = sr_scpi_send(sdi->conn, command);
89280b1a 488 break;
13f2b9d7 489 case SR_CONF_TRIGGER_SLOPE:
89280b1a 490 tmp_u64 = g_variant_get_uint64(data);
13f2b9d7 491
89280b1a 492 if (tmp_u64 != 0 && tmp_u64 != 1)
13f2b9d7
DJ
493 return SR_ERR;
494
89280b1a 495 state->trigger_slope = tmp_u64;
13f2b9d7
DJ
496
497 g_snprintf(command, sizeof(command),
498 (*model->scpi_dialect)[SCPI_CMD_SET_TRIGGER_SLOPE],
89280b1a 499 tmp_u64 ? "POS" : "NEG");
13f2b9d7
DJ
500
501 ret = sr_scpi_send(sdi->conn, command);
89280b1a 502 break;
13f2b9d7 503 case SR_CONF_COUPLING:
13f2b9d7
DJ
504 if (pg_type == PG_NONE) {
505 sr_err("No probe group specified.");
506 return SR_ERR_PROBE_GROUP;
507 }
508
509 tmp = g_variant_get_string(data, NULL);
510
511 for (i = 0; (*model->coupling_options)[i]; i++) {
512 if (!strcmp(tmp, (*model->coupling_options)[i])) {
513 for (j = 1; j <= model->analog_channels; ++j) {
514 if (probe_group == &devc->analog_groups[j - 1]) {
515 state->analog_channels[j-1].coupling = i;
516
517 g_snprintf(command, sizeof(command),
518 (*model->scpi_dialect)[SCPI_CMD_SET_COUPLING],
519 j, tmp);
520
521 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
522 sr_scpi_get_opc(sdi->conn) != SR_OK)
523 return SR_ERR;
524 break;
525 }
526 }
527
528 ret = SR_OK;
529 break;
530 }
531 }
89280b1a 532 break;
06a3e78a
DJ
533 default:
534 ret = SR_ERR_NA;
13f2b9d7 535 break;
06a3e78a
DJ
536 }
537
13f2b9d7
DJ
538 if (ret == SR_OK)
539 ret = sr_scpi_get_opc(sdi->conn);
540
06a3e78a
DJ
541 return ret;
542}
543
13f2b9d7 544static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
89280b1a 545 const struct sr_probe_group *probe_group)
06a3e78a 546{
13f2b9d7 547 int pg_type;
13f2b9d7
DJ
548 struct dev_context *devc;
549 struct scope_config *model;
550
551 if (!sdi || !(devc = sdi->priv))
552 return SR_ERR_ARG;
06a3e78a 553
13f2b9d7
DJ
554 if ((pg_type = check_probe_group(devc, probe_group)) == PG_INVALID)
555 return SR_ERR;
556
557 model = devc->model_config;
06a3e78a 558
06a3e78a 559 switch (key) {
13f2b9d7
DJ
560 case SR_CONF_DEVICE_OPTIONS:
561 if (pg_type == PG_NONE) {
562 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
89280b1a
UH
563 model->hw_caps, model->num_hwcaps,
564 sizeof(int32_t));
13f2b9d7
DJ
565 } else if (pg_type == PG_ANALOG) {
566 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
89280b1a
UH
567 model->analog_hwcaps, model->num_analog_hwcaps,
568 sizeof(int32_t));
13f2b9d7
DJ
569 } else {
570 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
89280b1a 571 NULL, 0, sizeof(int32_t));
13f2b9d7
DJ
572 }
573 break;
13f2b9d7
DJ
574 case SR_CONF_COUPLING:
575 if (pg_type == PG_NONE)
576 return SR_ERR_PROBE_GROUP;
13f2b9d7 577 *data = g_variant_new_strv(*model->coupling_options,
89280b1a 578 g_strv_length((char **)*model->coupling_options));
13f2b9d7 579 break;
13f2b9d7
DJ
580 case SR_CONF_TRIGGER_SOURCE:
581 *data = g_variant_new_strv(*model->trigger_sources,
89280b1a 582 g_strv_length((char **)*model->trigger_sources));
13f2b9d7 583 break;
13f2b9d7
DJ
584 case SR_CONF_TIMEBASE:
585 *data = build_tuples(model->timebases, model->num_timebases);
586 break;
13f2b9d7
DJ
587 case SR_CONF_VDIV:
588 if (pg_type == PG_NONE)
589 return SR_ERR_PROBE_GROUP;
13f2b9d7
DJ
590 *data = build_tuples(model->vdivs, model->num_vdivs);
591 break;
06a3e78a
DJ
592 default:
593 return SR_ERR_NA;
594 }
595
13f2b9d7 596 return SR_OK;
06a3e78a
DJ
597}
598
13f2b9d7 599SR_PRIV int hmo_request_data(const struct sr_dev_inst *sdi)
06a3e78a 600{
13f2b9d7 601 char command[MAX_COMMAND_SIZE];
13f2b9d7
DJ
602 struct sr_probe *probe;
603 struct dev_context *devc;
604 struct scope_config *model;
605
606 devc = sdi->priv;
607 model = devc->model_config;
608
609 probe = devc->current_probe->data;
610
611 switch (probe->type) {
612 case SR_PROBE_ANALOG:
613 g_snprintf(command, sizeof(command),
614 (*model->scpi_dialect)[SCPI_CMD_GET_ANALOG_DATA],
615 probe->index + 1);
616 break;
617 case SR_PROBE_LOGIC:
618 g_snprintf(command, sizeof(command),
619 (*model->scpi_dialect)[SCPI_CMD_GET_DIG_DATA],
620 probe->index < 8 ? 1 : 2);
621 break;
622 default:
89280b1a 623 sr_err("Invalid probe type.");
13f2b9d7
DJ
624 break;
625 }
626
627 return sr_scpi_send(sdi->conn, command);
628}
629
630static int hmo_check_probes(GSList *probes)
631{
632 GSList *l;
13f2b9d7 633 struct sr_probe *probe;
89280b1a 634 gboolean enabled_pod1, enabled_pod2, enabled_chan3, enabled_chan4;
13f2b9d7 635
89280b1a 636 enabled_pod1 = enabled_pod2 = enabled_chan3 = enabled_chan4 = FALSE;
13f2b9d7
DJ
637
638 for (l = probes; l; l = l->next) {
639 probe = l->data;
13f2b9d7
DJ
640 switch (probe->type) {
641 case SR_PROBE_ANALOG:
642 if (probe->index == 2)
643 enabled_chan3 = TRUE;
644 else if (probe->index == 3)
645 enabled_chan4 = TRUE;
646 break;
13f2b9d7
DJ
647 case SR_PROBE_LOGIC:
648 if (probe->index < 8)
649 enabled_pod1 = TRUE;
650 else
651 enabled_pod2 = TRUE;
652 break;
13f2b9d7
DJ
653 default:
654 return SR_ERR;
655 }
656 }
657
658 if ((enabled_pod1 && enabled_chan3) ||
659 (enabled_pod2 && enabled_chan4))
660 return SR_ERR;
661
662 return SR_OK;
663}
664
665static int hmo_setup_probes(const struct sr_dev_inst *sdi)
666{
667 GSList *l;
668 unsigned int i;
669 gboolean *pod_enabled;
670 char command[MAX_COMMAND_SIZE];
13f2b9d7
DJ
671 struct scope_state *state;
672 struct scope_config *model;
13f2b9d7
DJ
673 struct sr_probe *probe;
674 struct dev_context *devc;
675 struct sr_serial_dev_inst *serial;
676
677 devc = sdi->priv;
678 serial = sdi->conn;
679 state = devc->model_state;
680 model = devc->model_config;
681
682 pod_enabled = g_try_malloc0(sizeof(gboolean) * model->digital_pods);
683
684 for (l = sdi->probes; l; l = l->next) {
685 probe = l->data;
13f2b9d7
DJ
686 switch (probe->type) {
687 case SR_PROBE_ANALOG:
13f2b9d7
DJ
688 if (probe->enabled != state->analog_channels[probe->index].state) {
689 g_snprintf(command, sizeof(command),
690 (*model->scpi_dialect)[SCPI_CMD_SET_ANALOG_CHAN_STATE],
691 probe->index + 1, probe->enabled);
692
693 if (sr_scpi_send(serial, command) != SR_OK)
694 return SR_ERR;
695 state->analog_channels[probe->index].state = probe->enabled;
696 }
89280b1a 697 break;
13f2b9d7 698 case SR_PROBE_LOGIC:
13f2b9d7
DJ
699 /*
700 * A digital POD needs to be enabled for every group of
701 * 8 probes.
702 */
703 if (probe->enabled)
704 pod_enabled[probe->index < 8 ? 0 : 1] = TRUE;
705
706 if (probe->enabled != state->digital_channels[probe->index]) {
707 g_snprintf(command, sizeof(command),
708 (*model->scpi_dialect)[SCPI_CMD_SET_DIG_CHAN_STATE],
709 probe->index, probe->enabled);
710
711 if (sr_scpi_send(serial, command) != SR_OK)
712 return SR_ERR;
713
714 state->digital_channels[probe->index] = probe->enabled;
715 }
89280b1a 716 break;
13f2b9d7
DJ
717 default:
718 return SR_ERR;
719 }
720 }
721
722 for (i = 1; i <= model->digital_pods; ++i) {
89280b1a 723 if (state->digital_pods[i - 1] != pod_enabled[i - 1]) {
13f2b9d7
DJ
724 g_snprintf(command, sizeof(command),
725 (*model->scpi_dialect)[SCPI_CMD_SET_DIG_POD_STATE],
89280b1a 726 i, pod_enabled[i - 1]);
13f2b9d7
DJ
727
728 if (sr_scpi_send(serial, command) != SR_OK)
729 return SR_ERR;
730
89280b1a 731 state->digital_pods[i - 1] = pod_enabled[i - 1];
13f2b9d7
DJ
732 }
733 }
734
735 g_free(pod_enabled);
736
737 return SR_OK;
738}
739
740static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
741{
742 GSList *l;
743 gboolean digital_added;
13f2b9d7
DJ
744 struct sr_probe *probe;
745 struct dev_context *devc;
746 struct sr_serial_dev_inst *serial;
06a3e78a
DJ
747
748 if (sdi->status != SR_ST_ACTIVE)
749 return SR_ERR_DEV_CLOSED;
750
13f2b9d7
DJ
751 serial = sdi->conn;
752 devc = sdi->priv;
753 digital_added = FALSE;
754
755 for (l = sdi->probes; l; l = l->next) {
756 probe = l->data;
13f2b9d7 757 if (probe->enabled) {
89280b1a
UH
758 /* Only add a single digital probe. */
759 if (probe->type != SR_PROBE_LOGIC || !digital_added) {
760 devc->enabled_probes = g_slist_append(
761 devc->enabled_probes, probe);
13f2b9d7
DJ
762 if (probe->type == SR_PROBE_LOGIC)
763 digital_added = TRUE;
764 }
765 }
766 }
06a3e78a 767
13f2b9d7
DJ
768 if (!devc->enabled_probes)
769 return SR_ERR;
770
771 if (hmo_check_probes(devc->enabled_probes) != SR_OK) {
772 sr_err("Invalid probe configuration specified!");
773 return SR_ERR_NA;
774 }
775
776 if (hmo_setup_probes(sdi) != SR_OK) {
777 sr_err("Failed to setup probe configuration!");
778 return SR_ERR;
779 }
780
781 sr_source_add(serial->fd, G_IO_IN, 50, hameg_hmo_receive_data, (void *)sdi);
782
783 /* Send header packet to the session bus. */
784 std_session_send_df_header(cb_data, LOG_PREFIX);
785
786 devc->current_probe = devc->enabled_probes;
787
788 return hmo_request_data(sdi);
06a3e78a
DJ
789}
790
791static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
792{
13f2b9d7
DJ
793 struct dev_context *devc;
794 struct sr_serial_dev_inst *serial;
795
06a3e78a
DJ
796 (void)cb_data;
797
798 if (sdi->status != SR_ST_ACTIVE)
799 return SR_ERR_DEV_CLOSED;
800
13f2b9d7
DJ
801 devc = sdi->priv;
802
803 g_slist_free(devc->enabled_probes);
804 devc->enabled_probes = NULL;
805 serial = sdi->conn;
806 sr_source_remove(serial->fd);
06a3e78a
DJ
807
808 return SR_OK;
809}
810
811SR_PRIV struct sr_dev_driver hameg_hmo_driver_info = {
812 .name = "hameg-hmo",
89280b1a 813 .longname = "Hameg HMO",
06a3e78a
DJ
814 .api_version = 1,
815 .init = init,
816 .cleanup = cleanup,
817 .scan = scan,
818 .dev_list = dev_list,
819 .dev_clear = dev_clear,
820 .config_get = config_get,
821 .config_set = config_set,
822 .config_list = config_list,
823 .dev_open = dev_open,
824 .dev_close = dev_close,
825 .dev_acquisition_start = dev_acquisition_start,
826 .dev_acquisition_stop = dev_acquisition_stop,
827 .priv = NULL,
828};