]> sigrok.org Git - libsigrok.git/blob - src/hardware/rohde-schwarz-sme-0x/api.c
rohde-schwarz-sme-0x: Initial device support
[libsigrok.git] / src / hardware / rohde-schwarz-sme-0x / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2016 Vlad Ivanov <vlad.ivanov@lab-systems.ru>
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 <libserialport.h>
22 #include <scpi.h>
23 #include <string.h>
24
25 #include "protocol.h"
26
27 SR_PRIV struct sr_dev_driver rohde_schwarz_sme_0x_driver_info;
28
29 static const char * manufacturer = "Rohde&Schwarz";
30
31 static const struct rs_device_model device_models[] = {{
32         .model_str = "SME02",
33         .freq_max = SR_GHZ(1.5),
34         .freq_min = SR_KHZ(5),
35         .power_max = 16,
36         .power_min = -144
37 }, {
38         .model_str = "SME03E",
39         .freq_max = SR_GHZ(2.2),
40         .freq_min = SR_KHZ(5),
41         .power_max = 16,
42         .power_min = -144
43 }, {
44         .model_str = "SME03A",
45         .freq_max = SR_GHZ(3),
46         .freq_min = SR_KHZ(5),
47         .power_max = 16,
48         .power_min = -144
49 }, {
50         .model_str = "SME03",
51         .freq_max = SR_GHZ(3),
52         .freq_min = SR_KHZ(5),
53         .power_max = 16,
54         .power_min = -144
55 }, {
56         .model_str = "SME06",
57         .freq_max = SR_GHZ(1.5),
58         .freq_min = SR_KHZ(5),
59         .power_max = 16,
60         .power_min = -144
61 }};
62
63 static const uint32_t scanopts[] = {
64         SR_CONF_CONN,
65         SR_CONF_SERIALCOMM,
66 };
67
68 static const uint32_t devopts[] = {
69         SR_CONF_OUTPUT_FREQUENCY | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
70         SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
71 };
72
73 static int check_manufacturer(const char *str)
74 {
75         if (!strcmp(str, manufacturer)) {
76                 return SR_OK;
77         }
78
79         return SR_ERR;
80 }
81
82 static int rs_init_device(struct sr_dev_inst *sdi)
83 {
84         struct dev_context *devc;
85         uint8_t model_found;
86
87         devc = sdi->priv;
88         model_found = 0;
89
90         for (size_t i = 0; i < ARRAY_SIZE(device_models); i++) {
91                 if (!strcmp(device_models[i].model_str, sdi->model)) {
92                         model_found = 1;
93                         devc->model_config = &device_models[i];
94                         break;
95                 }
96         }
97
98         if (!model_found) {
99                 sr_dbg("Device %s %s is not supported by this driver", manufacturer, sdi->model);
100                 return SR_ERR_NA;
101         }
102
103         return SR_OK;
104 }
105
106 static struct sr_dev_inst *rs_probe_serial_device(struct sr_scpi_dev_inst *scpi)
107 {
108         struct sr_dev_inst *sdi;
109         struct dev_context *devc;
110         struct sr_scpi_hw_info *hw_info;
111
112         sdi = NULL;
113         devc = NULL;
114         hw_info = NULL;
115
116         rs_sme0x_mode_remote(scpi);
117
118         if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
119                 goto fail;
120         }
121
122         if (check_manufacturer(hw_info->manufacturer) != SR_OK) {
123                 goto fail;
124         }
125
126         sdi = g_malloc0(sizeof(struct sr_dev_inst));
127         sdi->vendor = g_strdup(hw_info->manufacturer);
128         sdi->model = g_strdup(hw_info->model);
129         sdi->version = g_strdup(hw_info->firmware_version);
130         sdi->serial_num = g_strdup(hw_info->serial_number);
131         sdi->driver = &rohde_schwarz_sme_0x_driver_info;
132         sdi->inst_type = SR_INST_SCPI;
133         sdi->conn = scpi;
134
135         sr_scpi_hw_info_free(hw_info);
136         hw_info = NULL;
137
138         devc = g_malloc0(sizeof(struct dev_context));
139         sdi->priv = devc;
140
141         if (rs_init_device(sdi) != SR_OK) {
142                 goto fail;
143         }
144
145         return sdi;
146
147 fail:
148         if (hw_info) {
149                 sr_scpi_hw_info_free(hw_info);
150         }
151
152         if (sdi) {
153                 sr_dev_inst_free(sdi);
154         }
155
156         g_free(devc);
157         return NULL;
158 }
159
160 static GSList *scan(struct sr_dev_driver *di, GSList *options)
161 {
162         return sr_scpi_scan(di->context, options, rs_probe_serial_device);
163 }
164
165 static int dev_clear(const struct sr_dev_driver *di)
166 {
167         return std_dev_clear(di, NULL);
168 }
169
170 static int dev_open(struct sr_dev_inst *sdi)
171 {
172         if (sdi->status != SR_ST_ACTIVE && sr_scpi_open(sdi->conn) != SR_OK) {
173                 return SR_ERR;
174         }
175
176         sdi->status = SR_ST_ACTIVE;
177
178         return SR_OK;
179 }
180
181 static int dev_close(struct sr_dev_inst *sdi)
182 {
183         if (sdi->status == SR_ST_INACTIVE) {
184                 return SR_OK;
185         }
186
187         sr_scpi_close(sdi->conn);
188
189         sdi->status = SR_ST_INACTIVE;
190
191         return SR_OK;
192 }
193
194 static int config_get(uint32_t key, GVariant **data,
195         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
196 {
197         double value_f;
198
199         (void) cg;
200
201         switch (key) {
202         case SR_CONF_OUTPUT_FREQUENCY:
203                 rs_sme0x_get_freq(sdi, &value_f);
204                 *data = g_variant_new_double(value_f);
205                 break;
206         case SR_CONF_AMPLITUDE:
207                 rs_sme0x_get_power(sdi, &value_f);
208                 *data = g_variant_new_double(value_f);
209                 break;
210         default:
211                 return SR_ERR_NA;
212         }
213
214         return SR_OK;
215 }
216
217 static int config_set(uint32_t key, GVariant *data,
218         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
219 {
220         double value_f;
221
222         (void)cg;
223
224         if (!sdi) {
225                 return SR_ERR_ARG;
226         }
227
228         if (sdi->status != SR_ST_ACTIVE) {
229                 return SR_ERR_DEV_CLOSED;
230         }
231
232         switch (key) {
233         case SR_CONF_OUTPUT_FREQUENCY:
234                 value_f = g_variant_get_double(data);
235                 rs_sme0x_set_freq(sdi, value_f);
236                 break;
237         case SR_CONF_AMPLITUDE:
238                 value_f = g_variant_get_double(data);
239                 rs_sme0x_set_power(sdi, value_f);
240                 break;
241         default:
242                 return SR_ERR_NA;
243         }
244
245         return SR_OK;
246 }
247
248 static int config_list(uint32_t key, GVariant **data,
249         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
250 {
251         (void)sdi;
252         (void)cg;
253
254         switch (key) {
255         case SR_CONF_SCAN_OPTIONS:
256                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
257                 break;
258         case SR_CONF_DEVICE_OPTIONS:
259                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
260                 break;
261         default:
262                 return SR_ERR_NA;
263         }
264
265         return SR_OK;
266 }
267
268 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
269 {
270         if (sdi->status != SR_ST_ACTIVE) {
271                 return SR_ERR_DEV_CLOSED;
272         }
273
274         return SR_OK;
275 }
276
277 SR_PRIV struct sr_dev_driver rohde_schwarz_sme_0x_driver_info = {
278         .name = "rohde-schwarz-sme-0x",
279         .longname = "Rohde&Schwarz SME-0x",
280         .api_version = 1,
281         .init = std_init,
282         .cleanup = std_cleanup,
283         .scan = scan,
284         .dev_list = std_dev_list,
285         .dev_clear = dev_clear,
286         .config_get = config_get,
287         .config_set = config_set,
288         .config_list = config_list,
289         .dev_open = dev_open,
290         .dev_close = dev_close,
291         .dev_acquisition_start = dev_acquisition_start,
292         .dev_acquisition_stop = std_serial_dev_acquisition_stop,
293         .context = NULL,
294 };
295
296 SR_REGISTER_DEV_DRIVER(rohde_schwarz_sme_0x_driver_info);