]> sigrok.org Git - libsigrok.git/blame - src/hardware/hameg-hmo/api.c
sr_dev_open(): Set status to SR_ST_ACTIVE upon success.
[libsigrok.git] / src / 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
6ec6c43b 20#include <config.h>
13f2b9d7 21#include <stdlib.h>
5a1afc09 22#include "scpi.h"
06a3e78a
DJ
23#include "protocol.h"
24
13f2b9d7
DJ
25#define SERIALCOMM "115200/8n1/flow=1"
26
dd5c48a6 27static struct sr_dev_driver hameg_hmo_driver_info;
e9a62139
DJ
28
29static const char *manufacturers[] = {
30 "HAMEG",
da1726cc 31 "Rohde&Schwarz",
e9a62139
DJ
32};
33
6ec3ef9b
AJ
34static const uint32_t drvopts[] = {
35 SR_CONF_OSCILLOSCOPE,
36};
37
584560f1 38static const uint32_t scanopts[] = {
13f2b9d7
DJ
39 SR_CONF_CONN,
40 SR_CONF_SERIALCOMM,
41};
42
719eff68 43enum {
61e77667
UH
44 CG_INVALID = -1,
45 CG_NONE,
46 CG_ANALOG,
47 CG_DIGITAL,
719eff68
UH
48};
49
e9a62139
DJ
50static int check_manufacturer(const char *manufacturer)
51{
52 unsigned int i;
53
0a1f7b09 54 for (i = 0; i < ARRAY_SIZE(manufacturers); i++)
e9a62139
DJ
55 if (!strcmp(manufacturer, manufacturers[i]))
56 return SR_OK;
57
58 return SR_ERR;
59}
60
ca28abd6 61static struct sr_dev_inst *hmo_probe_serial_device(struct sr_scpi_dev_inst *scpi)
e9a62139
DJ
62{
63 struct sr_dev_inst *sdi;
64 struct dev_context *devc;
65 struct sr_scpi_hw_info *hw_info;
e9a62139
DJ
66
67 sdi = NULL;
68 devc = NULL;
e9a62139
DJ
69 hw_info = NULL;
70
e9a62139
DJ
71 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
72 sr_info("Couldn't get IDN response.");
73 goto fail;
74 }
75
76 if (check_manufacturer(hw_info->manufacturer) != SR_OK)
77 goto fail;
78
aac29cc1 79 sdi = g_malloc0(sizeof(struct sr_dev_inst));
0af636be
UH
80 sdi->vendor = g_strdup(hw_info->manufacturer);
81 sdi->model = g_strdup(hw_info->model);
82 sdi->version = g_strdup(hw_info->firmware_version);
83 sdi->serial_num = g_strdup(hw_info->serial_number);
4f840ce9 84 sdi->driver = &hameg_hmo_driver_info;
b33db61c
SA
85 sdi->inst_type = SR_INST_SCPI;
86 sdi->conn = scpi;
b33db61c 87
e9a62139
DJ
88 sr_scpi_hw_info_free(hw_info);
89 hw_info = NULL;
90
f57d8ffe 91 devc = g_malloc0(sizeof(struct dev_context));
e9a62139 92
e9a62139 93 sdi->priv = devc;
e9a62139
DJ
94
95 if (hmo_init_device(sdi) != SR_OK)
96 goto fail;
97
98 return sdi;
99
100fail:
7b365c47 101 sr_scpi_hw_info_free(hw_info);
4bf93988 102 sr_dev_inst_free(sdi);
b1f83103 103 g_free(devc);
e9a62139
DJ
104
105 return NULL;
106}
107
4f840ce9 108static GSList *scan(struct sr_dev_driver *di, GSList *options)
06a3e78a 109{
41812aca 110 return sr_scpi_scan(di->context, options, hmo_probe_serial_device);
06a3e78a
DJ
111}
112
13f2b9d7
DJ
113static void clear_helper(void *priv)
114{
13f2b9d7 115 struct dev_context *devc;
13f2b9d7
DJ
116
117 devc = priv;
13f2b9d7 118
719eff68 119 hmo_scope_state_free(devc->model_state);
13f2b9d7 120
13f2b9d7
DJ
121 g_free(devc->analog_groups);
122 g_free(devc->digital_groups);
123
124 g_free(devc);
125}
126
4f840ce9 127static int dev_clear(const struct sr_dev_driver *di)
06a3e78a 128{
13f2b9d7 129 return std_dev_clear(di, clear_helper);
06a3e78a
DJ
130}
131
132static int dev_open(struct sr_dev_inst *sdi)
133{
6402c379 134 if (sr_scpi_open(sdi->conn) != SR_OK)
13f2b9d7 135 return SR_ERR;
06a3e78a 136
719eff68 137 if (hmo_scope_state_get(sdi) != SR_OK)
13f2b9d7 138 return SR_ERR;
06a3e78a 139
06a3e78a
DJ
140 return SR_OK;
141}
142
143static int dev_close(struct sr_dev_inst *sdi)
144{
23f43dff 145 sr_scpi_close(sdi->conn);
06a3e78a
DJ
146
147 sdi->status = SR_ST_INACTIVE;
148
149 return SR_OK;
150}
151
660e398f 152static int check_channel_group(struct dev_context *devc,
53b4680f 153 const struct sr_channel_group *cg)
13f2b9d7
DJ
154{
155 unsigned int i;
329733d9 156 const struct scope_config *model;
13f2b9d7
DJ
157
158 model = devc->model_config;
159
53b4680f 160 if (!cg)
61e77667 161 return CG_NONE;
13f2b9d7 162
0a1f7b09 163 for (i = 0; i < model->analog_channels; i++)
562b7ae5 164 if (cg == devc->analog_groups[i])
61e77667 165 return CG_ANALOG;
13f2b9d7 166
0a1f7b09 167 for (i = 0; i < model->digital_pods; i++)
562b7ae5 168 if (cg == devc->digital_groups[i])
61e77667 169 return CG_DIGITAL;
13f2b9d7 170
660e398f 171 sr_err("Invalid channel group specified.");
89280b1a 172
61e77667 173 return CG_INVALID;
13f2b9d7
DJ
174}
175
584560f1 176static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 177 const struct sr_channel_group *cg)
06a3e78a 178{
61e77667 179 int ret, cg_type;
13f2b9d7 180 unsigned int i;
13f2b9d7 181 struct dev_context *devc;
329733d9 182 const struct scope_config *model;
14a2f74d 183 struct scope_state *state;
13f2b9d7 184
709468ba 185 if (!sdi)
13f2b9d7
DJ
186 return SR_ERR_ARG;
187
709468ba
UH
188 devc = sdi->priv;
189
61e77667 190 if ((cg_type = check_channel_group(devc, cg)) == CG_INVALID)
13f2b9d7 191 return SR_ERR;
06a3e78a 192
13f2b9d7
DJ
193 ret = SR_ERR_NA;
194 model = devc->model_config;
14a2f74d 195 state = devc->model_state;
06a3e78a 196
06a3e78a 197 switch (key) {
bf622e6d 198 case SR_CONF_NUM_HDIV:
13f2b9d7
DJ
199 *data = g_variant_new_int32(model->num_xdivs);
200 ret = SR_OK;
201 break;
3fd2dca2
DJ
202 case SR_CONF_TIMEBASE:
203 *data = g_variant_new("(tt)", (*model->timebases)[state->timebase][0],
204 (*model->timebases)[state->timebase][1]);
205 ret = SR_OK;
206 break;
13f2b9d7 207 case SR_CONF_NUM_VDIV:
61e77667 208 if (cg_type == CG_NONE) {
660e398f
UH
209 sr_err("No channel group specified.");
210 return SR_ERR_CHANNEL_GROUP;
61e77667 211 } else if (cg_type == CG_ANALOG) {
0a1f7b09 212 for (i = 0; i < model->analog_channels; i++) {
562b7ae5 213 if (cg != devc->analog_groups[i])
082972e8
UH
214 continue;
215 *data = g_variant_new_int32(model->num_ydivs);
216 ret = SR_OK;
217 break;
13f2b9d7
DJ
218 }
219
3fd2dca2
DJ
220 } else {
221 ret = SR_ERR_NA;
222 }
223 break;
224 case SR_CONF_VDIV:
61e77667
UH
225 if (cg_type == CG_NONE) {
226 sr_err("No channel group specified.");
227 return SR_ERR_CHANNEL_GROUP;
228 } else if (cg_type == CG_ANALOG) {
0a1f7b09 229 for (i = 0; i < model->analog_channels; i++) {
562b7ae5 230 if (cg != devc->analog_groups[i])
3fd2dca2
DJ
231 continue;
232 *data = g_variant_new("(tt)",
233 (*model->vdivs)[state->analog_channels[i].vdiv][0],
234 (*model->vdivs)[state->analog_channels[i].vdiv][1]);
235 ret = SR_OK;
236 break;
237 }
238
ccf14618
DJ
239 } else {
240 ret = SR_ERR_NA;
241 }
242 break;
243 case SR_CONF_TRIGGER_SOURCE:
244 *data = g_variant_new_string((*model->trigger_sources)[state->trigger_source]);
245 ret = SR_OK;
246 break;
3fd2dca2
DJ
247 case SR_CONF_TRIGGER_SLOPE:
248 *data = g_variant_new_string((*model->trigger_slopes)[state->trigger_slope]);
249 ret = SR_OK;
250 break;
251 case SR_CONF_HORIZ_TRIGGERPOS:
252 *data = g_variant_new_double(state->horiz_triggerpos);
253 ret = SR_OK;
254 break;
ccf14618 255 case SR_CONF_COUPLING:
61e77667 256 if (cg_type == CG_NONE) {
660e398f
UH
257 sr_err("No channel group specified.");
258 return SR_ERR_CHANNEL_GROUP;
61e77667 259 } else if (cg_type == CG_ANALOG) {
0a1f7b09 260 for (i = 0; i < model->analog_channels; i++) {
562b7ae5 261 if (cg != devc->analog_groups[i])
ccf14618
DJ
262 continue;
263 *data = g_variant_new_string((*model->coupling_options)[state->analog_channels[i].coupling]);
264 ret = SR_OK;
265 break;
266 }
267
13f2b9d7
DJ
268 } else {
269 ret = SR_ERR_NA;
270 }
271 break;
14a2f74d
DJ
272 case SR_CONF_SAMPLERATE:
273 *data = g_variant_new_uint64(state->sample_rate);
274 ret = SR_OK;
275 break;
06a3e78a 276 default:
13f2b9d7 277 ret = SR_ERR_NA;
06a3e78a
DJ
278 }
279
280 return ret;
281}
282
13f2b9d7
DJ
283static GVariant *build_tuples(const uint64_t (*array)[][2], unsigned int n)
284{
285 unsigned int i;
13f2b9d7
DJ
286 GVariant *rational[2];
287 GVariantBuilder gvb;
288
289 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
290
291 for (i = 0; i < n; i++) {
292 rational[0] = g_variant_new_uint64((*array)[i][0]);
293 rational[1] = g_variant_new_uint64((*array)[i][1]);
294
89280b1a 295 /* FIXME: Valgrind reports a memory leak here. */
13f2b9d7
DJ
296 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
297 }
298
299 return g_variant_builder_end(&gvb);
300}
301
584560f1 302static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 303 const struct sr_channel_group *cg)
06a3e78a 304{
61e77667 305 int ret, cg_type;
89280b1a 306 unsigned int i, j;
965b463d 307 char command[MAX_COMMAND_SIZE], float_str[30];
13f2b9d7 308 struct dev_context *devc;
329733d9 309 const struct scope_config *model;
13f2b9d7 310 struct scope_state *state;
89280b1a 311 const char *tmp;
ca9b9f48 312 uint64_t p, q;
89280b1a 313 double tmp_d;
23e1ea7a 314 gboolean update_sample_rate;
06a3e78a 315
b0baddef 316 if (!sdi)
13f2b9d7
DJ
317 return SR_ERR_ARG;
318
b0baddef
UH
319 devc = sdi->priv;
320
61e77667 321 if ((cg_type = check_channel_group(devc, cg)) == CG_INVALID)
13f2b9d7
DJ
322 return SR_ERR;
323
324 model = devc->model_config;
325 state = devc->model_state;
23e1ea7a 326 update_sample_rate = FALSE;
13f2b9d7
DJ
327
328 ret = SR_ERR_NA;
06a3e78a 329
06a3e78a 330 switch (key) {
13f2b9d7
DJ
331 case SR_CONF_LIMIT_FRAMES:
332 devc->frame_limit = g_variant_get_uint64(data);
333 ret = SR_OK;
334 break;
13f2b9d7 335 case SR_CONF_TRIGGER_SOURCE:
13f2b9d7 336 tmp = g_variant_get_string(data, NULL);
13f2b9d7 337 for (i = 0; (*model->trigger_sources)[i]; i++) {
082972e8
UH
338 if (g_strcmp0(tmp, (*model->trigger_sources)[i]) != 0)
339 continue;
340 state->trigger_source = i;
341 g_snprintf(command, sizeof(command),
342 (*model->scpi_dialect)[SCPI_CMD_SET_TRIGGER_SOURCE],
343 (*model->trigger_sources)[i]);
13f2b9d7 344
082972e8
UH
345 ret = sr_scpi_send(sdi->conn, command);
346 break;
13f2b9d7 347 }
89280b1a 348 break;
13f2b9d7 349 case SR_CONF_VDIV:
61e77667 350 if (cg_type == CG_NONE) {
660e398f
UH
351 sr_err("No channel group specified.");
352 return SR_ERR_CHANNEL_GROUP;
13f2b9d7
DJ
353 }
354
355 g_variant_get(data, "(tt)", &p, &q);
356
357 for (i = 0; i < model->num_vdivs; i++) {
082972e8
UH
358 if (p != (*model->vdivs)[i][0] ||
359 q != (*model->vdivs)[i][1])
360 continue;
0a1f7b09 361 for (j = 1; j <= model->analog_channels; j++) {
562b7ae5 362 if (cg != devc->analog_groups[j - 1])
082972e8 363 continue;
8de2dc3b 364 state->analog_channels[j - 1].vdiv = i;
965b463d 365 g_ascii_formatd(float_str, sizeof(float_str), "%E", (float) p / q);
082972e8
UH
366 g_snprintf(command, sizeof(command),
367 (*model->scpi_dialect)[SCPI_CMD_SET_VERTICAL_DIV],
965b463d 368 j, float_str);
082972e8
UH
369
370 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
371 sr_scpi_get_opc(sdi->conn) != SR_OK)
372 return SR_ERR;
13f2b9d7 373
13f2b9d7
DJ
374 break;
375 }
082972e8
UH
376
377 ret = SR_OK;
378 break;
13f2b9d7 379 }
89280b1a 380 break;
13f2b9d7 381 case SR_CONF_TIMEBASE:
13f2b9d7
DJ
382 g_variant_get(data, "(tt)", &p, &q);
383
384 for (i = 0; i < model->num_timebases; i++) {
082972e8
UH
385 if (p != (*model->timebases)[i][0] ||
386 q != (*model->timebases)[i][1])
387 continue;
8de2dc3b 388 state->timebase = i;
965b463d 389 g_ascii_formatd(float_str, sizeof(float_str), "%E", (float) p / q);
082972e8
UH
390 g_snprintf(command, sizeof(command),
391 (*model->scpi_dialect)[SCPI_CMD_SET_TIMEBASE],
965b463d 392 float_str);
13f2b9d7 393
082972e8 394 ret = sr_scpi_send(sdi->conn, command);
23e1ea7a 395 update_sample_rate = TRUE;
082972e8 396 break;
13f2b9d7 397 }
89280b1a 398 break;
13f2b9d7 399 case SR_CONF_HORIZ_TRIGGERPOS:
89280b1a 400 tmp_d = g_variant_get_double(data);
13f2b9d7 401
89280b1a 402 if (tmp_d < 0.0 || tmp_d > 1.0)
13f2b9d7
DJ
403 return SR_ERR;
404
422a1c0d
DJ
405 state->horiz_triggerpos = tmp_d;
406 tmp_d = -(tmp_d - 0.5) *
407 ((double) (*model->timebases)[state->timebase][0] /
408 (*model->timebases)[state->timebase][1])
409 * model->num_xdivs;
410
411 g_ascii_formatd(float_str, sizeof(float_str), "%E", tmp_d);
13f2b9d7
DJ
412 g_snprintf(command, sizeof(command),
413 (*model->scpi_dialect)[SCPI_CMD_SET_HORIZ_TRIGGERPOS],
422a1c0d 414 float_str);
13f2b9d7
DJ
415
416 ret = sr_scpi_send(sdi->conn, command);
89280b1a 417 break;
13f2b9d7 418 case SR_CONF_TRIGGER_SLOPE:
ca9b9f48 419 tmp = g_variant_get_string(data, NULL);
e3abd15d
SB
420 for (i = 0; (*model->trigger_slopes)[i]; i++) {
421 if (g_strcmp0(tmp, (*model->trigger_slopes)[i]) != 0)
422 continue;
423 state->trigger_slope = i;
424 g_snprintf(command, sizeof(command),
425 (*model->scpi_dialect)[SCPI_CMD_SET_TRIGGER_SLOPE],
426 (*model->trigger_slopes)[i]);
13f2b9d7 427
e3abd15d
SB
428 ret = sr_scpi_send(sdi->conn, command);
429 break;
430 }
89280b1a 431 break;
13f2b9d7 432 case SR_CONF_COUPLING:
61e77667 433 if (cg_type == CG_NONE) {
660e398f
UH
434 sr_err("No channel group specified.");
435 return SR_ERR_CHANNEL_GROUP;
13f2b9d7
DJ
436 }
437
438 tmp = g_variant_get_string(data, NULL);
439
440 for (i = 0; (*model->coupling_options)[i]; i++) {
082972e8
UH
441 if (strcmp(tmp, (*model->coupling_options)[i]) != 0)
442 continue;
0a1f7b09 443 for (j = 1; j <= model->analog_channels; j++) {
562b7ae5 444 if (cg != devc->analog_groups[j - 1])
082972e8
UH
445 continue;
446 state->analog_channels[j-1].coupling = i;
13f2b9d7 447
082972e8
UH
448 g_snprintf(command, sizeof(command),
449 (*model->scpi_dialect)[SCPI_CMD_SET_COUPLING],
450 j, tmp);
451
452 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
453 sr_scpi_get_opc(sdi->conn) != SR_OK)
454 return SR_ERR;
13f2b9d7
DJ
455 break;
456 }
082972e8
UH
457
458 ret = SR_OK;
459 break;
13f2b9d7 460 }
89280b1a 461 break;
06a3e78a
DJ
462 default:
463 ret = SR_ERR_NA;
13f2b9d7 464 break;
06a3e78a
DJ
465 }
466
13f2b9d7
DJ
467 if (ret == SR_OK)
468 ret = sr_scpi_get_opc(sdi->conn);
469
23e1ea7a
DJ
470 if (ret == SR_OK && update_sample_rate)
471 ret = hmo_update_sample_rate(sdi);
472
06a3e78a
DJ
473 return ret;
474}
475
584560f1 476static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 477 const struct sr_channel_group *cg)
06a3e78a 478{
6ec3ef9b
AJ
479 int cg_type = CG_NONE;
480 struct dev_context *devc = NULL;
329733d9 481 const struct scope_config *model = NULL;
13f2b9d7 482
4d399734
UH
483 if (sdi) {
484 devc = sdi->priv;
6ec3ef9b
AJ
485 if ((cg_type = check_channel_group(devc, cg)) == CG_INVALID)
486 return SR_ERR;
13f2b9d7 487
6ec3ef9b
AJ
488 model = devc->model_config;
489 }
06a3e78a 490
06a3e78a 491 switch (key) {
226363c4 492 case SR_CONF_SCAN_OPTIONS:
584560f1
BV
493 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
494 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
226363c4 495 break;
13f2b9d7 496 case SR_CONF_DEVICE_OPTIONS:
61e77667 497 if (cg_type == CG_NONE) {
6ec3ef9b
AJ
498 if (model)
499 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
500 model->devopts, model->num_devopts, sizeof(uint32_t));
501 else
502 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
503 drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
61e77667 504 } else if (cg_type == CG_ANALOG) {
584560f1 505 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
f254bc4b 506 model->analog_devopts, model->num_analog_devopts,
584560f1 507 sizeof(uint32_t));
13f2b9d7 508 } else {
584560f1
BV
509 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
510 NULL, 0, sizeof(uint32_t));
13f2b9d7
DJ
511 }
512 break;
13f2b9d7 513 case SR_CONF_COUPLING:
61e77667 514 if (cg_type == CG_NONE)
660e398f 515 return SR_ERR_CHANNEL_GROUP;
13f2b9d7 516 *data = g_variant_new_strv(*model->coupling_options,
89280b1a 517 g_strv_length((char **)*model->coupling_options));
13f2b9d7 518 break;
13f2b9d7 519 case SR_CONF_TRIGGER_SOURCE:
6ec3ef9b
AJ
520 if (!model)
521 return SR_ERR_ARG;
13f2b9d7 522 *data = g_variant_new_strv(*model->trigger_sources,
89280b1a 523 g_strv_length((char **)*model->trigger_sources));
13f2b9d7 524 break;
bbabdaf1 525 case SR_CONF_TRIGGER_SLOPE:
6ec3ef9b
AJ
526 if (!model)
527 return SR_ERR_ARG;
bbabdaf1
DJ
528 *data = g_variant_new_strv(*model->trigger_slopes,
529 g_strv_length((char **)*model->trigger_slopes));
530 break;
13f2b9d7 531 case SR_CONF_TIMEBASE:
6ec3ef9b
AJ
532 if (!model)
533 return SR_ERR_ARG;
13f2b9d7
DJ
534 *data = build_tuples(model->timebases, model->num_timebases);
535 break;
13f2b9d7 536 case SR_CONF_VDIV:
61e77667 537 if (cg_type == CG_NONE)
660e398f 538 return SR_ERR_CHANNEL_GROUP;
13f2b9d7
DJ
539 *data = build_tuples(model->vdivs, model->num_vdivs);
540 break;
06a3e78a
DJ
541 default:
542 return SR_ERR_NA;
543 }
544
13f2b9d7 545 return SR_OK;
06a3e78a
DJ
546}
547
13f2b9d7 548SR_PRIV int hmo_request_data(const struct sr_dev_inst *sdi)
06a3e78a 549{
13f2b9d7 550 char command[MAX_COMMAND_SIZE];
ba7dd8bb 551 struct sr_channel *ch;
13f2b9d7 552 struct dev_context *devc;
329733d9 553 const struct scope_config *model;
13f2b9d7
DJ
554
555 devc = sdi->priv;
556 model = devc->model_config;
557
ba7dd8bb 558 ch = devc->current_channel->data;
13f2b9d7 559
ba7dd8bb 560 switch (ch->type) {
3f239f08 561 case SR_CHANNEL_ANALOG:
13f2b9d7
DJ
562 g_snprintf(command, sizeof(command),
563 (*model->scpi_dialect)[SCPI_CMD_GET_ANALOG_DATA],
65a6794e
GS
564#ifdef WORDS_BIGENDIAN
565 "MSBF",
566#else
567 "LSBF",
568#endif
ba7dd8bb 569 ch->index + 1);
13f2b9d7 570 break;
3f239f08 571 case SR_CHANNEL_LOGIC:
13f2b9d7
DJ
572 g_snprintf(command, sizeof(command),
573 (*model->scpi_dialect)[SCPI_CMD_GET_DIG_DATA],
ba7dd8bb 574 ch->index < 8 ? 1 : 2);
13f2b9d7
DJ
575 break;
576 default:
ba7dd8bb 577 sr_err("Invalid channel type.");
13f2b9d7
DJ
578 break;
579 }
580
581 return sr_scpi_send(sdi->conn, command);
582}
583
ba7dd8bb 584static int hmo_check_channels(GSList *channels)
13f2b9d7
DJ
585{
586 GSList *l;
ba7dd8bb 587 struct sr_channel *ch;
4889acef
GS
588 gboolean enabled_chan[MAX_ANALOG_CHANNEL_COUNT];
589 gboolean enabled_pod[MAX_DIGITAL_GROUP_COUNT];
590 size_t idx;
591
592 /* Preset "not enabled" for all channels / pods. */
593 for (idx = 0; idx < ARRAY_SIZE(enabled_chan); idx++)
594 enabled_chan[idx] = FALSE;
595 for (idx = 0; idx < ARRAY_SIZE(enabled_pod); idx++)
596 enabled_pod[idx] = FALSE;
597
598 /*
599 * Determine which channels / pods are required for the caller's
600 * specified configuration.
601 */
ba7dd8bb
UH
602 for (l = channels; l; l = l->next) {
603 ch = l->data;
604 switch (ch->type) {
3f239f08 605 case SR_CHANNEL_ANALOG:
4889acef
GS
606 idx = ch->index;
607 if (idx < ARRAY_SIZE(enabled_chan))
608 enabled_chan[idx] = TRUE;
13f2b9d7 609 break;
3f239f08 610 case SR_CHANNEL_LOGIC:
4889acef
GS
611 idx = ch->index / 8;
612 if (idx < ARRAY_SIZE(enabled_pod))
613 enabled_pod[idx] = TRUE;
13f2b9d7 614 break;
13f2b9d7
DJ
615 default:
616 return SR_ERR;
617 }
618 }
619
4889acef
GS
620 /*
621 * Check for resource conflicts. Some channels can be either
622 * analog or digital, but never both at the same time.
623 *
624 * Note that the constraints might depend on the specific model.
625 * These tests might need some adjustment when support for more
626 * models gets added to the driver.
627 */
628 if (enabled_pod[0] && enabled_chan[2])
629 return SR_ERR;
630 if (enabled_pod[1] && enabled_chan[3])
13f2b9d7 631 return SR_ERR;
13f2b9d7
DJ
632 return SR_OK;
633}
634
ba7dd8bb 635static int hmo_setup_channels(const struct sr_dev_inst *sdi)
13f2b9d7
DJ
636{
637 GSList *l;
638 unsigned int i;
23e1ea7a 639 gboolean *pod_enabled, setup_changed;
13f2b9d7 640 char command[MAX_COMMAND_SIZE];
13f2b9d7 641 struct scope_state *state;
329733d9 642 const struct scope_config *model;
ba7dd8bb 643 struct sr_channel *ch;
13f2b9d7 644 struct dev_context *devc;
23f43dff 645 struct sr_scpi_dev_inst *scpi;
13f2b9d7
DJ
646
647 devc = sdi->priv;
23f43dff 648 scpi = sdi->conn;
13f2b9d7
DJ
649 state = devc->model_state;
650 model = devc->model_config;
23e1ea7a 651 setup_changed = FALSE;
13f2b9d7
DJ
652
653 pod_enabled = g_try_malloc0(sizeof(gboolean) * model->digital_pods);
654
ba7dd8bb
UH
655 for (l = sdi->channels; l; l = l->next) {
656 ch = l->data;
657 switch (ch->type) {
3f239f08 658 case SR_CHANNEL_ANALOG:
ba7dd8bb 659 if (ch->enabled == state->analog_channels[ch->index].state)
082972e8
UH
660 break;
661 g_snprintf(command, sizeof(command),
662 (*model->scpi_dialect)[SCPI_CMD_SET_ANALOG_CHAN_STATE],
ba7dd8bb 663 ch->index + 1, ch->enabled);
13f2b9d7 664
23f43dff 665 if (sr_scpi_send(scpi, command) != SR_OK)
082972e8 666 return SR_ERR;
ba7dd8bb 667 state->analog_channels[ch->index].state = ch->enabled;
23e1ea7a 668 setup_changed = TRUE;
89280b1a 669 break;
3f239f08 670 case SR_CHANNEL_LOGIC:
13f2b9d7
DJ
671 /*
672 * A digital POD needs to be enabled for every group of
ba7dd8bb 673 * 8 channels.
13f2b9d7 674 */
ba7dd8bb
UH
675 if (ch->enabled)
676 pod_enabled[ch->index < 8 ? 0 : 1] = TRUE;
13f2b9d7 677
ba7dd8bb 678 if (ch->enabled == state->digital_channels[ch->index])
082972e8
UH
679 break;
680 g_snprintf(command, sizeof(command),
681 (*model->scpi_dialect)[SCPI_CMD_SET_DIG_CHAN_STATE],
ba7dd8bb 682 ch->index, ch->enabled);
13f2b9d7 683
23f43dff 684 if (sr_scpi_send(scpi, command) != SR_OK)
082972e8 685 return SR_ERR;
13f2b9d7 686
ba7dd8bb 687 state->digital_channels[ch->index] = ch->enabled;
23e1ea7a 688 setup_changed = TRUE;
89280b1a 689 break;
13f2b9d7
DJ
690 default:
691 return SR_ERR;
692 }
693 }
694
0a1f7b09 695 for (i = 1; i <= model->digital_pods; i++) {
082972e8
UH
696 if (state->digital_pods[i - 1] == pod_enabled[i - 1])
697 continue;
698 g_snprintf(command, sizeof(command),
699 (*model->scpi_dialect)[SCPI_CMD_SET_DIG_POD_STATE],
700 i, pod_enabled[i - 1]);
23f43dff 701 if (sr_scpi_send(scpi, command) != SR_OK)
082972e8
UH
702 return SR_ERR;
703 state->digital_pods[i - 1] = pod_enabled[i - 1];
23e1ea7a 704 setup_changed = TRUE;
13f2b9d7
DJ
705 }
706
707 g_free(pod_enabled);
708
23e1ea7a
DJ
709 if (setup_changed && hmo_update_sample_rate(sdi) != SR_OK)
710 return SR_ERR;
711
13f2b9d7
DJ
712 return SR_OK;
713}
714
695dc859 715static int dev_acquisition_start(const struct sr_dev_inst *sdi)
13f2b9d7
DJ
716{
717 GSList *l;
1b0f62df 718 gboolean digital_added[MAX_DIGITAL_GROUP_COUNT];
e06875b2 719 size_t group, pod_count;
ba7dd8bb 720 struct sr_channel *ch;
13f2b9d7 721 struct dev_context *devc;
23f43dff 722 struct sr_scpi_dev_inst *scpi;
40a75c8e 723 int ret;
06a3e78a 724
23f43dff 725 scpi = sdi->conn;
13f2b9d7 726 devc = sdi->priv;
13f2b9d7 727
1b0f62df
GS
728 /* Preset empty results. */
729 for (group = 0; group < ARRAY_SIZE(digital_added); group++)
730 digital_added[group] = FALSE;
db81fbb5
SA
731 g_slist_free(devc->enabled_channels);
732 devc->enabled_channels = NULL;
733
1b0f62df 734 /*
e06875b2
GS
735 * Contruct the list of enabled channels. Determine the highest
736 * number of digital pods involved in the acquisition.
1b0f62df 737 */
e06875b2 738 pod_count = 0;
ba7dd8bb
UH
739 for (l = sdi->channels; l; l = l->next) {
740 ch = l->data;
741 if (!ch->enabled)
082972e8 742 continue;
1b0f62df
GS
743 /* Only add a single digital channel per group (pod). */
744 group = ch->index / 8;
745 if (ch->type != SR_CHANNEL_LOGIC || !digital_added[group]) {
ba7dd8bb
UH
746 devc->enabled_channels = g_slist_append(
747 devc->enabled_channels, ch);
e06875b2 748 if (ch->type == SR_CHANNEL_LOGIC) {
1b0f62df 749 digital_added[group] = TRUE;
e06875b2
GS
750 if (pod_count < group + 1)
751 pod_count = group + 1;
752 }
13f2b9d7
DJ
753 }
754 }
ba7dd8bb 755 if (!devc->enabled_channels)
13f2b9d7 756 return SR_ERR;
e06875b2
GS
757 devc->pod_count = pod_count;
758 devc->logic_data = NULL;
13f2b9d7 759
1b0f62df
GS
760 /*
761 * Check constraints. Some channels can be either analog or
762 * digital, but not both at the same time.
763 */
ba7dd8bb
UH
764 if (hmo_check_channels(devc->enabled_channels) != SR_OK) {
765 sr_err("Invalid channel configuration specified!");
40a75c8e
GS
766 ret = SR_ERR_NA;
767 goto free_enabled;
13f2b9d7
DJ
768 }
769
1b0f62df
GS
770 /*
771 * Configure the analog and digital channels and the
772 * corresponding digital pods.
773 */
ba7dd8bb
UH
774 if (hmo_setup_channels(sdi) != SR_OK) {
775 sr_err("Failed to setup channel configuration!");
40a75c8e
GS
776 ret = SR_ERR;
777 goto free_enabled;
13f2b9d7
DJ
778 }
779
1b0f62df
GS
780 /*
781 * Start acquisition on the first enabled channel. The
782 * receive routine will continue driving the acquisition.
783 */
102f1239
BV
784 sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
785 hmo_receive_data, (void *)sdi);
13f2b9d7 786
bee2b016 787 std_session_send_df_header(sdi);
13f2b9d7 788
ba7dd8bb 789 devc->current_channel = devc->enabled_channels;
13f2b9d7
DJ
790
791 return hmo_request_data(sdi);
40a75c8e
GS
792
793free_enabled:
794 g_slist_free(devc->enabled_channels);
795 devc->enabled_channels = NULL;
796 return ret;
06a3e78a
DJ
797}
798
695dc859 799static int dev_acquisition_stop(struct sr_dev_inst *sdi)
06a3e78a 800{
13f2b9d7 801 struct dev_context *devc;
23f43dff 802 struct sr_scpi_dev_inst *scpi;
13f2b9d7 803
bee2b016 804 std_session_send_df_end(sdi);
66e3219d 805
13f2b9d7
DJ
806 devc = sdi->priv;
807
ef1a346b 808 devc->num_frames = 0;
ba7dd8bb
UH
809 g_slist_free(devc->enabled_channels);
810 devc->enabled_channels = NULL;
23f43dff 811 scpi = sdi->conn;
102f1239 812 sr_scpi_source_remove(sdi->session, scpi);
06a3e78a
DJ
813
814 return SR_OK;
815}
816
dd5c48a6 817static struct sr_dev_driver hameg_hmo_driver_info = {
06a3e78a 818 .name = "hameg-hmo",
89280b1a 819 .longname = "Hameg HMO",
06a3e78a 820 .api_version = 1,
c2fdcc25 821 .init = std_init,
700d6b64 822 .cleanup = std_cleanup,
06a3e78a 823 .scan = scan,
c01bf34c 824 .dev_list = std_dev_list,
06a3e78a
DJ
825 .dev_clear = dev_clear,
826 .config_get = config_get,
827 .config_set = config_set,
828 .config_list = config_list,
829 .dev_open = dev_open,
830 .dev_close = dev_close,
831 .dev_acquisition_start = dev_acquisition_start,
832 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 833 .context = NULL,
06a3e78a 834};
dd5c48a6 835SR_REGISTER_DEV_DRIVER(hameg_hmo_driver_info);