]> sigrok.org Git - libsigrok.git/blob - src/hardware/gwinstek-gds-800/api.c
gwinstek-gds-800: Initial driver implementation.
[libsigrok.git] / src / hardware / gwinstek-gds-800 / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2015 Martin Lederhilger <martin.lederhilger@gmx.at>
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 <string.h>
21 #include "protocol.h"
22
23 static const uint32_t scanopts[] = {
24         SR_CONF_CONN,
25         SR_CONF_SERIALCOMM,
26 };
27
28 static const uint32_t devopts[] = {
29         SR_CONF_OSCILLOSCOPE,
30         SR_CONF_LIMIT_FRAMES | SR_CONF_SET,
31         SR_CONF_SAMPLERATE | SR_CONF_GET,
32 };
33
34 SR_PRIV struct sr_dev_driver gwinstek_gds_800_driver_info;
35
36 static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
37 {
38         return std_init(sr_ctx, di, LOG_PREFIX);
39 }
40
41 static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
42 {
43         struct dev_context *devc;
44         struct sr_dev_inst *sdi;
45         struct sr_scpi_hw_info *hw_info;
46         struct sr_channel_group *cg;
47
48         if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
49                 sr_info("Couldn't get IDN response.");
50                 return NULL;
51         }
52
53         if (strcmp(hw_info->manufacturer, "GW") != 0 ||
54             strncmp(hw_info->model, "GDS-8", 5) != 0) {
55                 sr_scpi_hw_info_free(hw_info);
56                 return NULL;
57         }
58
59         sdi = g_malloc0(sizeof(struct sr_dev_inst));
60         sdi->status = SR_ST_ACTIVE;
61         sdi->vendor = g_strdup(hw_info->manufacturer);
62         sdi->model = g_strdup(hw_info->model);
63         sdi->version = g_strdup(hw_info->firmware_version);
64         sdi->conn = scpi;
65         sdi->driver = &gwinstek_gds_800_driver_info;
66         sdi->inst_type = SR_INST_SCPI;
67         sdi->serial_num = g_strdup(hw_info->serial_number);
68         sdi->channels = NULL;
69         sdi->channel_groups = NULL;
70
71         sr_scpi_hw_info_free(hw_info);
72
73         devc = g_malloc0(sizeof(struct dev_context));
74         devc->frame_limit = 1;
75         devc->sample_rate = 0.;
76         devc->df_started  = FALSE;
77         sdi->priv = devc;
78
79         sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "CH1");
80         sr_channel_new(sdi, 1, SR_CHANNEL_ANALOG, TRUE, "CH2");
81
82         cg = g_malloc0(sizeof(struct sr_channel_group));
83         cg->name = g_strdup("");
84         cg->channels = g_slist_append(cg->channels, g_slist_nth_data(sdi->channels, 0));
85         cg->channels = g_slist_append(cg->channels, g_slist_nth_data(sdi->channels, 1));
86         cg->priv = NULL;
87         sdi->channel_groups = g_slist_append(NULL, cg);
88
89         return sdi;
90 }
91
92 static GSList *scan(struct sr_dev_driver *di, GSList *options)
93 {
94         return sr_scpi_scan(di->context, options, probe_device);
95 }
96
97 static GSList *dev_list(const struct sr_dev_driver *di)
98 {
99         return ((struct drv_context *)(di->context))->instances;
100 }
101
102 static int dev_clear(const struct sr_dev_driver *di)
103 {
104         return std_dev_clear(di, NULL);
105 }
106
107 static int dev_open(struct sr_dev_inst *sdi)
108 {
109         int ret;
110         struct sr_scpi_dev_inst *scpi = sdi->conn;
111
112         if ((ret = sr_scpi_open(scpi)) < 0) {
113                 sr_err("Failed to open SCPI device: %s.", sr_strerror(ret));
114                 return SR_ERR;
115         }
116
117         sdi->status = SR_ST_ACTIVE;
118
119         return SR_OK;
120 }
121
122 static int dev_close(struct sr_dev_inst *sdi)
123 {
124         struct sr_scpi_dev_inst *scpi;
125
126         if (sdi->status != SR_ST_ACTIVE)
127                 return SR_ERR_DEV_CLOSED;
128
129         scpi = sdi->conn;
130         if (scpi) {
131                 if (sr_scpi_close(scpi) < 0)
132                         return SR_ERR;
133                 sdi->status = SR_ST_INACTIVE;
134         }
135
136         return SR_OK;
137 }
138
139 static int cleanup(const struct sr_dev_driver *di)
140 {
141         dev_clear(di);
142
143         return SR_OK;
144 }
145
146 static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
147                 const struct sr_channel_group *cg)
148 {
149         struct dev_context *devc;
150
151         (void)cg;
152
153         if (!sdi || !(devc = sdi->priv))
154                 return SR_ERR_ARG;
155
156         switch (key) {
157         case SR_CONF_SAMPLERATE:
158                 *data = g_variant_new_uint64(devc->sample_rate);
159                 break;
160         default:
161                 return SR_ERR_NA;
162         }
163
164         return SR_OK;
165 }
166
167 static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
168                 const struct sr_channel_group *cg)
169 {
170         struct dev_context *devc;
171
172         (void)cg;
173
174         if (!sdi || !(devc = sdi->priv))
175                 return SR_ERR_ARG;
176
177         if (sdi->status != SR_ST_ACTIVE)
178                 return SR_ERR_DEV_CLOSED;
179
180         switch (key) {
181         case SR_CONF_LIMIT_FRAMES:
182                 devc->frame_limit = g_variant_get_uint64(data);
183                 break;
184         default:
185                 return SR_ERR_NA;
186         }
187
188         return SR_OK;
189 }
190
191 static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
192                 const struct sr_channel_group *cg)
193 {
194         (void)sdi;
195         (void)cg;
196
197         switch (key) {
198         case SR_CONF_SCAN_OPTIONS:
199                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
200                         scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
201                 return SR_OK;
202         case SR_CONF_DEVICE_OPTIONS:
203                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
204                         devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
205                 return SR_OK;
206         default:
207                 return SR_ERR_NA;
208         }
209
210         return SR_OK;
211 }
212
213 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
214 {
215         struct sr_scpi_dev_inst *scpi;
216         struct dev_context *devc;
217
218         (void)cb_data;
219
220         scpi = sdi->conn;
221         devc = sdi->priv;
222
223         if (sdi->status != SR_ST_ACTIVE)
224                 return SR_ERR_DEV_CLOSED;
225
226         devc->state = START_ACQUISITION;
227         devc->cur_acq_frame = 0;
228
229         sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
230                         gwinstek_gds_800_receive_data, (void *)sdi);
231
232         return SR_OK;
233 }
234
235 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
236 {
237         struct sr_scpi_dev_inst *scpi;
238         struct dev_context *devc;
239         struct sr_datafeed_packet packet;
240
241         (void)cb_data;
242
243         scpi = sdi->conn;
244         devc = sdi->priv;
245
246         if (sdi->status != SR_ST_ACTIVE) {
247                 sr_err("Device inactive, can't stop acquisition.");
248                 return SR_ERR;
249         }
250
251         if (devc->df_started) {
252                 packet.type = SR_DF_FRAME_END;
253                 sr_session_send(sdi, &packet);
254
255                 packet.type = SR_DF_END;
256                 sr_session_send(sdi, &packet);
257
258                 devc->df_started = FALSE;
259         }
260
261         sr_scpi_source_remove(sdi->session, scpi);
262
263         return SR_OK;
264 }
265
266 SR_PRIV struct sr_dev_driver gwinstek_gds_800_driver_info = {
267         .name = "gwinstek-gds-800",
268         .longname = "GW Instek GDS-800 series",
269         .api_version = 1,
270         .init = init,
271         .cleanup = cleanup,
272         .scan = scan,
273         .dev_list = dev_list,
274         .dev_clear = dev_clear,
275         .config_get = config_get,
276         .config_set = config_set,
277         .config_list = config_list,
278         .dev_open = dev_open,
279         .dev_close = dev_close,
280         .dev_acquisition_start = dev_acquisition_start,
281         .dev_acquisition_stop = dev_acquisition_stop,
282         .context = NULL,
283 };