]> sigrok.org Git - libsigrok.git/blob - src/hardware/yokogawa-dlm/api.c
Introduce standard cleanup helper
[libsigrok.git] / src / hardware / yokogawa-dlm / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 abraxa (Soeren Apel) <soeren@apelpie.net>
5  * Based on the Hameg HMO driver by poljar (Damir Jelić) <poljarinho@gmail.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include "scpi.h"
24 #include "protocol.h"
25
26 SR_PRIV struct sr_dev_driver yokogawa_dlm_driver_info;
27
28 static const char *MANUFACTURER_ID = "YOKOGAWA";
29 static const char *MANUFACTURER_NAME = "Yokogawa";
30
31 static const uint32_t dlm_scanopts[] = {
32         SR_CONF_CONN,
33 };
34
35 static const uint32_t dlm_drvopts[] = {
36         SR_CONF_LOGIC_ANALYZER,
37         SR_CONF_OSCILLOSCOPE,
38 };
39
40 static const uint32_t dlm_devopts[] = {
41         SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
42         SR_CONF_SAMPLERATE | SR_CONF_GET,
43         SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
44         SR_CONF_NUM_HDIV | SR_CONF_GET,
45         SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
46         SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
47         SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
48 };
49
50 static const uint32_t dlm_analog_devopts[] = {
51         SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
52         SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
53         SR_CONF_NUM_VDIV | SR_CONF_GET,
54 };
55
56 static const uint32_t dlm_digital_devopts[] = {
57 };
58
59 enum {
60         CG_INVALID = -1,
61         CG_NONE,
62         CG_ANALOG,
63         CG_DIGITAL,
64 };
65
66 static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
67 {
68         return std_init(sr_ctx, di, LOG_PREFIX);
69 }
70
71 static struct sr_dev_inst *probe_usbtmc_device(struct sr_scpi_dev_inst *scpi)
72 {
73         struct sr_dev_inst *sdi;
74         struct dev_context *devc;
75         struct sr_scpi_hw_info *hw_info;
76         char *model_name;
77         int model_index;
78
79         sdi = NULL;
80         devc = NULL;
81         hw_info = NULL;
82
83         if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
84                 sr_info("Couldn't get IDN response.");
85                 goto fail;
86         }
87
88         if (strcmp(hw_info->manufacturer, MANUFACTURER_ID) != 0)
89                 goto fail;
90
91         if (dlm_model_get(hw_info->model, &model_name, &model_index) != SR_OK)
92                 goto fail;
93
94         sdi = g_malloc0(sizeof(struct sr_dev_inst));
95         sdi->vendor = g_strdup(MANUFACTURER_NAME);
96         sdi->model = g_strdup(model_name);
97         sdi->version = g_strdup(hw_info->firmware_version);
98
99         sdi->serial_num = g_strdup(hw_info->serial_number);
100
101         sr_scpi_hw_info_free(hw_info);
102         hw_info = NULL;
103
104         devc = g_malloc0(sizeof(struct dev_context));
105
106         sdi->driver = &yokogawa_dlm_driver_info;
107         sdi->priv = devc;
108         sdi->inst_type = SR_INST_SCPI;
109         sdi->conn = scpi;
110
111         if (dlm_device_init(sdi, model_index) != SR_OK)
112                 goto fail;
113
114         return sdi;
115
116 fail:
117         if (hw_info)
118                 sr_scpi_hw_info_free(hw_info);
119         if (sdi)
120                 sr_dev_inst_free(sdi);
121         g_free(devc);
122
123         return NULL;
124 }
125
126 static GSList *scan(struct sr_dev_driver *di, GSList *options)
127 {
128         return sr_scpi_scan(di->context, options, probe_usbtmc_device);
129 }
130
131 static GSList *dev_list(const struct sr_dev_driver *di)
132 {
133         return ((struct drv_context *)(di->context))->instances;
134 }
135
136 static void clear_helper(void *priv)
137 {
138         struct dev_context *devc;
139
140         devc = priv;
141
142         dlm_scope_state_destroy(devc->model_state);
143
144         g_free(devc->analog_groups);
145         g_free(devc->digital_groups);
146         g_free(devc);
147 }
148
149 static int dev_clear(const struct sr_dev_driver *di)
150 {
151         return std_dev_clear(di, clear_helper);
152 }
153
154 static int dev_open(struct sr_dev_inst *sdi)
155 {
156         if (sdi->status != SR_ST_ACTIVE && sr_scpi_open(sdi->conn) != SR_OK)
157                 return SR_ERR;
158
159         if (dlm_scope_state_query(sdi) != SR_OK)
160                 return SR_ERR;
161
162         sdi->status = SR_ST_ACTIVE;
163
164         return SR_OK;
165 }
166
167 static int dev_close(struct sr_dev_inst *sdi)
168 {
169         if (sdi->status == SR_ST_INACTIVE)
170                 return SR_OK;
171
172         sr_scpi_close(sdi->conn);
173
174         sdi->status = SR_ST_INACTIVE;
175
176         return SR_OK;
177 }
178
179 /**
180  * Check which category a given channel group belongs to.
181  *
182  * @param devc Our internal device context.
183  * @param cg The channel group to check.
184  *
185  * @retval CG_NONE cg is NULL
186  * @retval CG_ANALOG cg is an analog group
187  * @retval CG_DIGITAL cg is a digital group
188  * @retval CG_INVALID cg is something else
189  */
190 static int check_channel_group(struct dev_context *devc,
191                         const struct sr_channel_group *cg)
192 {
193         unsigned int i;
194         const struct scope_config *model;
195
196         model = devc->model_config;
197
198         if (!cg)
199                 return CG_NONE;
200
201         for (i = 0; i < model->analog_channels; i++)
202                 if (cg == devc->analog_groups[i])
203                         return CG_ANALOG;
204
205         for (i = 0; i < model->pods; i++)
206                 if (cg == devc->digital_groups[i])
207                         return CG_DIGITAL;
208
209         sr_err("Invalid channel group specified.");
210         return CG_INVALID;
211 }
212
213 static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
214                 const struct sr_channel_group *cg)
215 {
216         int ret, cg_type;
217         unsigned int i;
218         struct dev_context *devc;
219         const struct scope_config *model;
220         struct scope_state *state;
221
222         if (!sdi || !(devc = sdi->priv))
223                 return SR_ERR_ARG;
224
225         if ((cg_type = check_channel_group(devc, cg)) == CG_INVALID)
226                 return SR_ERR;
227
228         model = devc->model_config;
229         state = devc->model_state;
230
231         switch (key) {
232         case SR_CONF_NUM_HDIV:
233                 *data = g_variant_new_int32(model->num_xdivs);
234                 ret = SR_OK;
235                 break;
236         case SR_CONF_TIMEBASE:
237                 *data = g_variant_new("(tt)",
238                                 dlm_timebases[state->timebase][0],
239                                 dlm_timebases[state->timebase][1]);
240                 ret = SR_OK;
241                 break;
242         case SR_CONF_NUM_VDIV:
243                 if (cg_type == CG_NONE) {
244                         sr_err("No channel group specified.");
245                         return SR_ERR_CHANNEL_GROUP;
246                 } else if (cg_type == CG_ANALOG) {
247                                 *data = g_variant_new_int32(model->num_ydivs);
248                                 ret = SR_OK;
249                                 break;
250                 } else {
251                         ret = SR_ERR_NA;
252                 }
253                 break;
254         case SR_CONF_VDIV:
255                 ret = SR_ERR_NA;
256                 if (cg_type == CG_NONE) {
257                         sr_err("No channel group specified.");
258                         return SR_ERR_CHANNEL_GROUP;
259                 } else if (cg_type != CG_ANALOG)
260                         break;
261
262                 for (i = 0; i < model->analog_channels; i++) {
263                         if (cg != devc->analog_groups[i])
264                                 continue;
265                         *data = g_variant_new("(tt)",
266                                         dlm_vdivs[state->analog_states[i].vdiv][0],
267                                         dlm_vdivs[state->analog_states[i].vdiv][1]);
268                         ret = SR_OK;
269                         break;
270                 }
271                 break;
272         case SR_CONF_TRIGGER_SOURCE:
273                 *data = g_variant_new_string((*model->trigger_sources)[state->trigger_source]);
274                 ret = SR_OK;
275                 break;
276         case SR_CONF_TRIGGER_SLOPE:
277                 *data = g_variant_new_string(dlm_trigger_slopes[state->trigger_slope]);
278                 ret = SR_OK;
279                 break;
280         case SR_CONF_HORIZ_TRIGGERPOS:
281                 *data = g_variant_new_double(state->horiz_triggerpos);
282                 ret = SR_OK;
283                 break;
284         case SR_CONF_COUPLING:
285                 ret = SR_ERR_NA;
286                 if (cg_type == CG_NONE) {
287                         sr_err("No channel group specified.");
288                         return SR_ERR_CHANNEL_GROUP;
289                 } else if (cg_type != CG_ANALOG)
290                         break;
291
292                 for (i = 0; i < model->analog_channels; i++) {
293                         if (cg != devc->analog_groups[i])
294                                 continue;
295                         *data = g_variant_new_string((*model->coupling_options)[state->analog_states[i].coupling]);
296                         ret = SR_OK;
297                         break;
298                 }
299                 break;
300         case SR_CONF_SAMPLERATE:
301                 *data = g_variant_new_uint64(state->sample_rate);
302                 ret = SR_OK;
303                 break;
304         default:
305                 ret = SR_ERR_NA;
306         }
307
308         return ret;
309 }
310
311 static GVariant *build_tuples(const uint64_t (*array)[][2], unsigned int n)
312 {
313         unsigned int i;
314         GVariant *rational[2];
315         GVariantBuilder gvb;
316
317         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
318
319         for (i = 0; i < n; i++) {
320                 rational[0] = g_variant_new_uint64((*array)[i][0]);
321                 rational[1] = g_variant_new_uint64((*array)[i][1]);
322
323                 /* FIXME: Valgrind reports a memory leak here. */
324                 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
325         }
326
327         return g_variant_builder_end(&gvb);
328 }
329
330 static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
331                 const struct sr_channel_group *cg)
332 {
333         int ret, cg_type;
334         unsigned int i, j;
335         char float_str[30];
336         struct dev_context *devc;
337         const struct scope_config *model;
338         struct scope_state *state;
339         const char *tmp;
340         uint64_t p, q;
341         double tmp_d;
342         gboolean update_sample_rate;
343
344         if (!sdi || !(devc = sdi->priv))
345                 return SR_ERR_ARG;
346
347         if ((cg_type = check_channel_group(devc, cg)) == CG_INVALID)
348                 return SR_ERR;
349
350         model = devc->model_config;
351         state = devc->model_state;
352         update_sample_rate = FALSE;
353
354         ret = SR_ERR_NA;
355
356         switch (key) {
357         case SR_CONF_LIMIT_FRAMES:
358                 devc->frame_limit = g_variant_get_uint64(data);
359                 ret = SR_OK;
360                 break;
361         case SR_CONF_TRIGGER_SOURCE:
362                 tmp = g_variant_get_string(data, NULL);
363                 for (i = 0; (*model->trigger_sources)[i]; i++) {
364                         if (g_strcmp0(tmp, (*model->trigger_sources)[i]) != 0)
365                                 continue;
366                         state->trigger_source = i;
367                         /* TODO: A and B trigger support possible? */
368                         ret = dlm_trigger_source_set(sdi->conn, (*model->trigger_sources)[i]);
369                         break;
370                 }
371                 break;
372         case SR_CONF_VDIV:
373                 if (cg_type == CG_NONE) {
374                         sr_err("No channel group specified.");
375                         return SR_ERR_CHANNEL_GROUP;
376                 }
377
378                 g_variant_get(data, "(tt)", &p, &q);
379
380                 for (i = 0; i < ARRAY_SIZE(dlm_vdivs); i++) {
381                         if (p != dlm_vdivs[i][0] ||
382                                         q != dlm_vdivs[i][1])
383                                 continue;
384                         for (j = 1; j <= model->analog_channels; j++) {
385                                 if (cg != devc->analog_groups[j - 1])
386                                         continue;
387                                 state->analog_states[j - 1].vdiv = i;
388                                 g_ascii_formatd(float_str, sizeof(float_str),
389                                                 "%E", (float) p / q);
390                                 if (dlm_analog_chan_vdiv_set(sdi->conn, j, float_str) != SR_OK ||
391                                                 sr_scpi_get_opc(sdi->conn) != SR_OK)
392                                         return SR_ERR;
393
394                                 break;
395                         }
396
397                         ret = SR_OK;
398                         break;
399                 }
400                 break;
401         case SR_CONF_TIMEBASE:
402                 g_variant_get(data, "(tt)", &p, &q);
403
404                 for (i = 0; i < ARRAY_SIZE(dlm_timebases); i++) {
405                         if (p != dlm_timebases[i][0] ||
406                                         q != dlm_timebases[i][1])
407                                 continue;
408                         state->timebase = i;
409                         g_ascii_formatd(float_str, sizeof(float_str),
410                                         "%E", (float) p / q);
411                         ret = dlm_timebase_set(sdi->conn, float_str);
412                         update_sample_rate = TRUE;
413                         break;
414                 }
415                 break;
416         case SR_CONF_HORIZ_TRIGGERPOS:
417                 tmp_d = g_variant_get_double(data);
418
419                 /* TODO: Check if the calculation makes sense for the DLM. */
420                 if (tmp_d < 0.0 || tmp_d > 1.0)
421                         return SR_ERR;
422
423                 state->horiz_triggerpos = tmp_d;
424                 tmp_d = -(tmp_d - 0.5) *
425                                 ((double) dlm_timebases[state->timebase][0] /
426                                 dlm_timebases[state->timebase][1])
427                                 * model->num_xdivs;
428
429                 g_ascii_formatd(float_str, sizeof(float_str), "%E", tmp_d);
430                 ret = dlm_horiz_trigger_pos_set(sdi->conn, float_str);
431                 break;
432         case SR_CONF_TRIGGER_SLOPE:
433                 tmp = g_variant_get_string(data, NULL);
434
435                 if (!tmp || !(tmp[0] == 'f' || tmp[0] == 'r'))
436                         return SR_ERR_ARG;
437
438                 /* Note: See dlm_trigger_slopes[] in protocol.c. */
439                 state->trigger_slope = (tmp[0] == 'r') ?
440                                 SLOPE_POSITIVE : SLOPE_NEGATIVE;
441
442                 ret = dlm_trigger_slope_set(sdi->conn, state->trigger_slope);
443                 break;
444         case SR_CONF_COUPLING:
445                 if (cg_type == CG_NONE) {
446                         sr_err("No channel group specified.");
447                         return SR_ERR_CHANNEL_GROUP;
448                 }
449
450                 tmp = g_variant_get_string(data, NULL);
451
452                 for (i = 0; (*model->coupling_options)[i]; i++) {
453                         if (strcmp(tmp, (*model->coupling_options)[i]) != 0)
454                                 continue;
455                         for (j = 1; j <= model->analog_channels; j++) {
456                                 if (cg != devc->analog_groups[j - 1])
457                                         continue;
458                                 state->analog_states[j-1].coupling = i;
459
460                                 if (dlm_analog_chan_coupl_set(sdi->conn, j, tmp) != SR_OK ||
461                                                 sr_scpi_get_opc(sdi->conn) != SR_OK)
462                                         return SR_ERR;
463                                 break;
464                         }
465
466                         ret = SR_OK;
467                         break;
468                 }
469                 break;
470         default:
471                 ret = SR_ERR_NA;
472                 break;
473         }
474
475         if (ret == SR_OK)
476                 ret = sr_scpi_get_opc(sdi->conn);
477
478         if (ret == SR_OK && update_sample_rate)
479                 ret = dlm_sample_rate_query(sdi);
480
481         return ret;
482 }
483
484 static int config_channel_set(const struct sr_dev_inst *sdi,
485                         struct sr_channel *ch, unsigned int changes)
486 {
487         /* Currently we only handle SR_CHANNEL_SET_ENABLED. */
488         if (changes != SR_CHANNEL_SET_ENABLED)
489                 return SR_ERR_NA;
490
491         return dlm_channel_state_set(sdi, ch->index, ch->enabled);
492 }
493
494 static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
495                 const struct sr_channel_group *cg)
496 {
497         int cg_type = CG_NONE;
498         struct dev_context *devc = NULL;
499         const struct scope_config *model = NULL;
500
501         /* SR_CONF_SCAN_OPTIONS is always valid, regardless of sdi or probe group. */
502         if (key == SR_CONF_SCAN_OPTIONS) {
503                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
504                                 dlm_scanopts, ARRAY_SIZE(dlm_scanopts), sizeof(uint32_t));
505                 return SR_OK;
506         }
507
508         /* If sdi is NULL, nothing except SR_CONF_DEVICE_OPTIONS can be provided. */
509         if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
510                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
511                                 dlm_drvopts, ARRAY_SIZE(dlm_drvopts), sizeof(uint32_t));
512                 return SR_OK;
513         }
514
515         if (!sdi)
516                 return SR_ERR_ARG;
517
518         devc = sdi->priv;
519         model = devc->model_config;
520
521         /*
522          * If cg is NULL, only the SR_CONF_DEVICE_OPTIONS that are not
523          * specific to a probe group must be returned.
524          */
525         if (!cg) {
526                 switch (key) {
527                 case SR_CONF_DEVICE_OPTIONS:
528                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
529                                         dlm_devopts, ARRAY_SIZE(dlm_devopts), sizeof(uint32_t));
530                         return SR_OK;
531                 case SR_CONF_TIMEBASE:
532                         *data = build_tuples(&dlm_timebases, ARRAY_SIZE(dlm_timebases));
533                         return SR_OK;
534                 case SR_CONF_TRIGGER_SOURCE:
535                         if (!model)
536                                 return SR_ERR_ARG;
537                         *data = g_variant_new_strv(*model->trigger_sources,
538                                         g_strv_length((char **)*model->trigger_sources));
539                         return SR_OK;
540                 case SR_CONF_TRIGGER_SLOPE:
541                         *data = g_variant_new_strv(dlm_trigger_slopes,
542                                         g_strv_length((char **)dlm_trigger_slopes));
543                         return SR_OK;
544                 case SR_CONF_NUM_HDIV:
545                         *data = g_variant_new_uint32(model->num_xdivs);
546                         return SR_OK;
547                 default:
548                         return SR_ERR_NA;
549                 }
550         }
551
552         if ((cg_type = check_channel_group(devc, cg)) == CG_INVALID)
553                 return SR_ERR;
554
555         switch (key) {
556         case SR_CONF_DEVICE_OPTIONS:
557                 if (cg_type == CG_ANALOG) {
558                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
559                                 dlm_analog_devopts, ARRAY_SIZE(dlm_analog_devopts), sizeof(uint32_t));
560                 } else if (cg_type == CG_DIGITAL) {
561                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
562                                 dlm_digital_devopts, ARRAY_SIZE(dlm_digital_devopts), sizeof(uint32_t));
563                 } else {
564                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
565                                 NULL, 0, sizeof(uint32_t));
566                 }
567                 break;
568         case SR_CONF_COUPLING:
569                 if (cg_type == CG_NONE)
570                         return SR_ERR_CHANNEL_GROUP;
571                 *data = g_variant_new_strv(*model->coupling_options,
572                                 g_strv_length((char **)*model->coupling_options));
573                 break;
574         case SR_CONF_VDIV:
575                 if (cg_type == CG_NONE)
576                         return SR_ERR_CHANNEL_GROUP;
577                 *data = build_tuples(&dlm_vdivs, ARRAY_SIZE(dlm_vdivs));
578                 break;
579         default:
580                 return SR_ERR_NA;
581         }
582
583         return SR_OK;
584 }
585
586 static int dlm_check_channels(GSList *channels)
587 {
588         GSList *l;
589         struct sr_channel *ch;
590         gboolean enabled_pod1, enabled_chan4;
591
592         enabled_pod1 = enabled_chan4 = FALSE;
593
594         /* Note: On the DLM2000, CH4 and Logic are shared. */
595         /* TODO Handle non-DLM2000 models. */
596         for (l = channels; l; l = l->next) {
597                 ch = l->data;
598                 switch (ch->type) {
599                 case SR_CHANNEL_ANALOG:
600                         if (ch->index == 3)
601                                 enabled_chan4 = TRUE;
602                         break;
603                 case SR_CHANNEL_LOGIC:
604                         enabled_pod1 = TRUE;
605                         break;
606                 default:
607                         return SR_ERR;
608                 }
609         }
610
611         if (enabled_pod1 && enabled_chan4)
612                 return SR_ERR;
613
614         return SR_OK;
615 }
616
617 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
618 {
619         GSList *l;
620         gboolean digital_added;
621         struct sr_channel *ch;
622         struct dev_context *devc;
623         struct sr_scpi_dev_inst *scpi;
624
625         if (sdi->status != SR_ST_ACTIVE)
626                 return SR_ERR_DEV_CLOSED;
627
628         scpi = sdi->conn;
629         devc = sdi->priv;
630         digital_added = FALSE;
631
632         g_slist_free(devc->enabled_channels);
633         devc->enabled_channels = NULL;
634
635         for (l = sdi->channels; l; l = l->next) {
636                 ch = l->data;
637                 if (!ch->enabled)
638                         continue;
639                 /* Only add a single digital channel. */
640                 if (ch->type != SR_CHANNEL_LOGIC || !digital_added) {
641                         devc->enabled_channels = g_slist_append(
642                                 devc->enabled_channels, ch);
643                         if (ch->type == SR_CHANNEL_LOGIC)
644                                 digital_added = TRUE;
645                 }
646         }
647
648         if (!devc->enabled_channels)
649                 return SR_ERR;
650
651         if (dlm_check_channels(devc->enabled_channels) != SR_OK) {
652                 sr_err("Invalid channel configuration specified!");
653                 return SR_ERR_NA;
654         }
655
656         /* Request data for the first enabled channel. */
657         devc->current_channel = devc->enabled_channels;
658         dlm_channel_data_request(sdi);
659
660         /* Call our callback when data comes in or after 5ms. */
661         sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 5,
662                         dlm_data_receive, (void *)sdi);
663
664         return SR_OK;
665 }
666
667 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
668 {
669         struct dev_context *devc;
670
671         std_session_send_df_end(sdi, LOG_PREFIX);
672
673         if (sdi->status != SR_ST_ACTIVE)
674                 return SR_ERR_DEV_CLOSED;
675
676         devc = sdi->priv;
677
678         devc->num_frames = 0;
679         g_slist_free(devc->enabled_channels);
680         devc->enabled_channels = NULL;
681
682         sr_scpi_source_remove(sdi->session, sdi->conn);
683
684         return SR_OK;
685 }
686
687 SR_PRIV struct sr_dev_driver yokogawa_dlm_driver_info = {
688         .name = "yokogawa-dlm",
689         .longname = "Yokogawa DL/DLM",
690         .api_version = 1,
691         .init = init,
692         .cleanup = std_cleanup,
693         .scan = scan,
694         .dev_list = dev_list,
695         .dev_clear = dev_clear,
696         .config_get = config_get,
697         .config_set = config_set,
698         .config_channel_set = config_channel_set,
699         .config_list = config_list,
700         .dev_open = dev_open,
701         .dev_close = dev_close,
702         .dev_acquisition_start = dev_acquisition_start,
703         .dev_acquisition_stop = dev_acquisition_stop,
704         .context = NULL,
705 };