]> sigrok.org Git - libsigrok.git/blob - src/hardware/scpi-pps/api.c
scpi-pps: Generalize vendor name cleanup.
[libsigrok.git] / src / hardware / scpi-pps / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 Bert Vermeulen <bert@biot.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
20 #include <string.h>
21 #include "protocol.h"
22
23 SR_PRIV struct sr_dev_driver scpi_pps_driver_info;
24 static struct sr_dev_driver *di = &scpi_pps_driver_info;
25 extern unsigned int num_pps_profiles;
26 extern const struct scpi_pps pps_profiles[];
27
28 static const int32_t scanopts[] = {
29         SR_CONF_CONN,
30         SR_CONF_SERIALCOMM,
31 };
32
33 static int init(struct sr_context *sr_ctx)
34 {
35         return std_init(sr_ctx, di, LOG_PREFIX);
36 }
37
38 static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
39 {
40         struct dev_context *devc;
41         struct sr_dev_inst *sdi;
42         struct sr_scpi_hw_info *hw_info;
43         struct sr_channel_group *cg;
44         struct sr_channel *ch;
45         const struct scpi_pps *device;
46         const struct channel_group_spec *cgs;
47         struct pps_channel_group *pcg;
48         uint64_t mask;
49         unsigned int i, j;
50         const char *vendor;
51
52         if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
53                 sr_info("Couldn't get IDN response.");
54                 return NULL;
55         }
56
57         device = NULL;
58         for (i = 0; i < num_pps_profiles; i++) {
59                 vendor = get_vendor(hw_info->manufacturer);
60                 if (strcasecmp(vendor, pps_profiles[i].idn_vendor))
61                         continue;
62                 if (!strcmp(hw_info->model, pps_profiles[i].idn_model)) {
63                         device = &pps_profiles[i];
64                         break;
65                 }
66         }
67         if (!device) {
68                 sr_scpi_hw_info_free(hw_info);
69                 return NULL;
70         }
71
72         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, vendor,
73                         device->idn_model, hw_info->firmware_version);
74         sdi->conn = scpi;
75         sdi->driver = di;
76         sdi->inst_type = SR_INST_SCPI;
77         devc = g_malloc0(sizeof(struct dev_context));
78         devc->device = device;
79         sdi->priv = devc;
80
81         for (i = 0; i < device->num_channels; i++) {
82                 ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE,
83                                 device->channels[i].name);
84                 sdi->channels = g_slist_append(sdi->channels, ch);
85         }
86
87         for (i = 0; i < device->num_channel_groups; i++) {
88                 cgs = &device->channel_groups[i];
89                 cg = g_malloc0(sizeof(struct sr_channel_group));
90                 cg->name = g_strdup(cgs->name);
91                 for (j = 0, mask = 1; j < 64; j++, mask <<= 1) {
92                         if (cgs->channel_index_mask & mask) {
93                                 ch = g_slist_nth_data(sdi->channels, j);
94                                 cg->channels = g_slist_append(cg->channels, ch);
95                         }
96                 }
97                 pcg = g_malloc0(sizeof(struct pps_channel_group));
98                 pcg->features = cgs->features;
99                 cg->priv = pcg;
100                 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
101         }
102
103         /* SCPI devices commonly lock the panel keys when accessed remotely. */
104         scpi_cmd(sdi, SCPI_CMD_KEY_UNLOCK);
105         sr_scpi_close(scpi);
106
107         return sdi;
108 }
109
110 static GSList *scan(GSList *options)
111 {
112         return sr_scpi_scan(di->priv, options, probe_device);
113 }
114
115 static GSList *dev_list(void)
116 {
117         return ((struct drv_context *)(di->priv))->instances;
118 }
119
120 static int dev_clear(void)
121 {
122         return std_dev_clear(di, NULL);
123 }
124
125 static int dev_open(struct sr_dev_inst *sdi)
126 {
127         struct sr_scpi_dev_inst *scpi;
128
129         if (sdi->status != SR_ST_ACTIVE)
130                 return SR_ERR;
131
132         scpi = sdi->conn;
133         if (sr_scpi_open(scpi) < 0)
134                 return SR_ERR;
135
136         sdi->status = SR_ST_ACTIVE;
137
138         return SR_OK;
139 }
140
141 static int dev_close(struct sr_dev_inst *sdi)
142 {
143         struct sr_scpi_dev_inst *scpi;
144
145         if (sdi->status != SR_ST_ACTIVE)
146                 return SR_ERR_DEV_CLOSED;
147
148         scpi = sdi->conn;
149         if (scpi) {
150                 scpi_cmd(sdi, SCPI_CMD_KEY_UNLOCK);
151                 sr_scpi_close(scpi);
152                 sdi->status = SR_ST_INACTIVE;
153         }
154
155         return SR_OK;
156 }
157
158 static int cleanup(void)
159 {
160         return SR_OK;
161 }
162
163 static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
164                 const struct sr_channel_group *cg)
165 {
166         struct dev_context *devc;
167         struct sr_scpi_dev_inst *scpi;
168         struct sr_channel *ch;
169         double d;
170         int ret;
171         char *s;
172
173         if (!sdi)
174                 return SR_ERR_ARG;
175
176         devc = sdi->priv;
177         scpi = sdi->conn;
178
179         ret = SR_OK;
180         if (!cg) {
181                 /* No channel group: global options. */
182                 switch (key) {
183                 case SR_CONF_OVER_TEMPERATURE_PROTECTION:
184                         ret = SR_ERR;
185                         if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_TEMPERATURE_PROTECTION) == SR_OK) {
186                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
187                                         *data = g_variant_new_boolean(!strcmp(s, "ON"));
188                                         ret = SR_OK;
189                                 }
190                         }
191                         break;
192                         return SR_ERR_NA;
193                         break;
194                 case SR_CONF_OUTPUT_CHANNEL_CONFIG:
195                         ret = SR_ERR;
196                         if (scpi_cmd(sdi, SCPI_CMD_GET_OUTPUT_CHANNEL_CONFIG) == SR_OK) {
197                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
198                                         *data = g_variant_new_string(s);
199                                         g_free(s);
200                                         ret = SR_OK;
201                                 }
202                         }
203                         break;
204                 default:
205                         return SR_ERR_NA;
206                 }
207         } else {
208                 /*
209                  * These options only apply to channel groups with a single
210                  * channel -- they're per-channel settings for the device.
211                  */
212                 if (g_slist_length(cg->channels) > 1)
213                         return SR_ERR_NA;
214                 ch = cg->channels->data;
215
216                 switch (key) {
217                 case SR_CONF_OUTPUT_REGULATION:
218                         ret = SR_ERR;
219                         if (scpi_cmd(sdi, SCPI_CMD_GET_OUTPUT_REGULATION, ch->name) == SR_OK) {
220                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
221                                         if (strcmp(s, "CC") && strcmp(s, "CV") && strcmp(s, "UR")) {
222                                                 sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s);
223                                         } else {
224                                                 *data = g_variant_new_string(s);
225                                                 g_free(s);
226                                                 ret = SR_OK;
227                                         }
228                                 }
229                         }
230                         break;
231                 case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
232                         ret = SR_ERR;
233                         if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_ENABLED,
234                                         ch->name) == SR_OK) {
235                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
236                                         *data = g_variant_new_boolean(!strcmp(s, "ON"));
237                                         ret = SR_OK;
238                                 }
239                         }
240                         break;
241                 case SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE:
242                         ret = SR_ERR;
243                         if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_ACTIVE,
244                                         ch->name) == SR_OK) {
245                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
246                                         *data = g_variant_new_boolean(!strcmp(s, "YES"));
247                                         ret = SR_OK;
248                                 }
249                         }
250                         break;
251                 case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
252                         ret = SR_ERR;
253                         if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_THRESHOLD,
254                                         ch->name) == SR_OK) {
255                                 if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
256                                         *data = g_variant_new_double(d);
257                                         ret = SR_OK;
258                                 }
259                         }
260                         break;
261                 case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
262                         ret = SR_ERR;
263                         if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ENABLED,
264                                         ch->name) == SR_OK) {
265                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
266                                         *data = g_variant_new_boolean(!strcmp(s, "ON"));
267                                         ret = SR_OK;
268                                 }
269                         }
270                         break;
271                 case SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE:
272                         ret = SR_ERR;
273                         if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE,
274                                         ch->name) == SR_OK) {
275                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
276                                         *data = g_variant_new_boolean(!strcmp(s, "YES"));
277                                         ret = SR_OK;
278                                 }
279                         }
280                         break;
281                 case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
282                         ret = SR_ERR;
283                         if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD,
284                                         ch->name) == SR_OK) {
285                                 if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
286                                         *data = g_variant_new_double(d);
287                                         ret = SR_OK;
288                                 }
289                         }
290                         break;
291                 case SR_CONF_OUTPUT_VOLTAGE:
292                         ret = SR_ERR;
293                         if (scpi_cmd(sdi, SCPI_CMD_GET_MEAS_VOLTAGE, ch->name) == SR_OK) {
294                                 if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
295                                         *data = g_variant_new_double(d);
296                                         ret = SR_OK;
297                                 }
298                         }
299                         break;
300                 case SR_CONF_OUTPUT_VOLTAGE_MAX:
301                         ret = SR_ERR;
302                         if (scpi_cmd(sdi, SCPI_CMD_GET_VOLTAGE_MAX, ch->name) == SR_OK) {
303                                 if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
304                                         *data = g_variant_new_double(d);
305                                         ret = SR_OK;
306                                 }
307                         }
308                         break;
309                 case SR_CONF_OUTPUT_CURRENT:
310                         ret = SR_ERR;
311                         if (scpi_cmd(sdi, SCPI_CMD_GET_MEAS_CURRENT, ch->name) == SR_OK) {
312                                 if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
313                                         *data = g_variant_new_double(d);
314                                         ret = SR_OK;
315                                 }
316                         }
317                         break;
318                 case SR_CONF_OUTPUT_CURRENT_MAX:
319                         ret = SR_ERR;
320                         if (scpi_cmd(sdi, SCPI_CMD_GET_CURRENT_MAX, ch->name) == SR_OK) {
321                                 if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
322                                         *data = g_variant_new_double(d);
323                                         ret = SR_OK;
324                                 }
325                         }
326                         break;
327                 case SR_CONF_OUTPUT_ENABLED:
328                         ret = SR_ERR;
329                         if (scpi_cmd(sdi, SCPI_CMD_GET_OUTPUT_ENABLED, ch->name) == SR_OK) {
330                                 if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
331                                         *data = g_variant_new_boolean(!strcmp(s, "ON"));
332                                         ret = SR_OK;
333                                 }
334                         }
335                         break;
336                 default:
337                         return SR_ERR_NA;
338                 }
339         }
340
341         return ret;
342 }
343
344 static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
345                 const struct sr_channel_group *cg)
346 {
347         struct sr_channel *ch;
348         double d;
349         int ret;
350         const char *s;
351
352         if (sdi->status != SR_ST_ACTIVE)
353                 return SR_ERR_DEV_CLOSED;
354
355
356         ret = SR_OK;
357         if (!cg) {
358                 switch (key) {
359                 /* No channel group: global options. */
360                 case SR_CONF_OVER_TEMPERATURE_PROTECTION:
361                         s = g_variant_get_boolean(data) ? "ON" : "OFF";
362                         if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION, s) < 0)
363                                 ret = SR_ERR;
364                         break;
365                 case SR_CONF_OUTPUT_CHANNEL_CONFIG:
366                         s = g_variant_get_string(data, NULL);
367                         if (scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_CHANNEL_CONFIG, s) < 0)
368                                 ret = SR_ERR;
369                         break;
370                 default:
371                         ret = SR_ERR_NA;
372                 }
373         } else {
374                 /* Channel group specified. */
375                 if (!sdi)
376                         return SR_ERR_ARG;
377                 if (g_slist_length(cg->channels) > 1)
378                         return SR_ERR_NA;
379                 ch = cg->channels->data;
380                 switch (key) {
381                 case SR_CONF_OUTPUT_VOLTAGE_MAX:
382                         d = g_variant_get_double(data);
383                         if (scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_MAX, ch->name, d) < 0)
384                                 ret = SR_ERR;
385                         break;
386                 case SR_CONF_OUTPUT_CURRENT_MAX:
387                         d = g_variant_get_double(data);
388                         if (scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_MAX, ch->name, d) < 0)
389                                 ret = SR_ERR;
390                         break;
391                 case SR_CONF_OUTPUT_ENABLED:
392                         s = g_variant_get_boolean(data) ? "ON" : "OFF";
393                         if (scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLED, ch->name, s) < 0)
394                                 ret = SR_ERR;
395                         break;
396                 case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
397                         s = g_variant_get_boolean(data) ? "ON" : "OFF";
398                         if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLED,
399                                         ch->name, s) < 0)
400                                 ret = SR_ERR;
401                         break;
402                 case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
403                         d = g_variant_get_double(data);
404                         if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD,
405                                         ch->name, d) < 0)
406                                 ret = SR_ERR;
407                         break;
408                 case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
409                         s = g_variant_get_boolean(data) ? "ON" : "OFF";
410                         if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLED,
411                                         ch->name, s) < 0)
412                                 ret = SR_ERR;
413                         break;
414                 case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
415                         d = g_variant_get_double(data);
416                         if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD,
417                                         ch->name, d) < 0)
418                                 ret = SR_ERR;
419                         break;
420                 default:
421                         ret = SR_ERR_NA;
422                 }
423         }
424
425         return ret;
426 }
427
428 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
429                 const struct sr_channel_group *cg)
430 {
431         struct dev_context *devc;
432         struct sr_channel *ch;
433         struct channel_spec *ch_spec;
434         GVariant *gvar;
435         GVariantBuilder gvb;
436         int ret, i;
437         const char *s[16];
438
439         /* Always available, even without sdi. */
440         if (key == SR_CONF_SCAN_OPTIONS) {
441                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
442                                 scanopts, ARRAY_SIZE(scanopts), sizeof(int32_t));
443                 return SR_OK;
444         }
445
446         if (!sdi)
447                 return SR_ERR_ARG;
448         devc = sdi->priv;
449
450         ret = SR_OK;
451         if (!cg) {
452                 /* No channel group: global options. */
453                 switch (key) {
454                 case SR_CONF_DEVICE_OPTIONS:
455                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
456                                         devc->device->devopts, devc->device->num_devopts,
457                                         sizeof(int32_t));
458                         break;
459                 case SR_CONF_OUTPUT_CHANNEL_CONFIG:
460                         i = 0;
461                         if (devc->device->features & PPS_INDEPENDENT)
462                                 s[i++] = "Independent";
463                         if (devc->device->features & PPS_SERIES)
464                                 s[i++] = "Series";
465                         if (devc->device->features & PPS_PARALLEL)
466                                 s[i++] = "Parallel";
467                         if (i == 0) {
468                                 /*
469                                  * Shouldn't happen: independent-only devices
470                                  * shouldn't advertise this option at all.
471                                  */
472                                 return SR_ERR_NA;
473                         }
474                         *data = g_variant_new_strv(s, i);
475                         break;
476                 default:
477                         return SR_ERR_NA;
478                 }
479         } else {
480                 /* Channel group specified. */
481                 if (!sdi)
482                         return SR_ERR_ARG;
483                 /*
484                  * Per-channel-group options depending on a channel are actually
485                  * done with the first channel. Channel groups in PPS can have
486                  * more than one channel, but they will typically be of equal
487                  * specification for use in series or parallel mode. Drop requests
488                  * for groups with more than one channel just to make sure.
489                  */
490                 if (g_slist_length(cg->channels) > 1)
491                         return SR_ERR_NA;
492                 ch = cg->channels->data;
493
494                 switch (key) {
495                 case SR_CONF_DEVICE_OPTIONS:
496                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
497                                         devc->device->devopts_cg, devc->device->num_devopts_cg,
498                                         sizeof(int32_t));
499                         break;
500                 case SR_CONF_OUTPUT_VOLTAGE_MAX:
501                         ch_spec = &(devc->device->channels[ch->index]);
502                         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
503                         /* Min, max, write resolution. */
504                         for (i = 0; i < 3; i++) {
505                                 gvar = g_variant_new_double(ch_spec->voltage[i]);
506                                 g_variant_builder_add_value(&gvb, gvar);
507                         }
508                         *data = g_variant_builder_end(&gvb);
509                         break;
510                 case SR_CONF_OUTPUT_CURRENT_MAX:
511                         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
512                         /* Min, max, step. */
513                         for (i = 0; i < 3; i++) {
514                                 ch_spec = &(devc->device->channels[ch->index]);
515                                 gvar = g_variant_new_double(ch_spec->current[i]);
516                                 g_variant_builder_add_value(&gvb, gvar);
517                         }
518                         *data = g_variant_builder_end(&gvb);
519                         break;
520                 default:
521                         return SR_ERR_NA;
522                 }
523         }
524
525         return ret;
526 }
527
528 static int dev_acquisition_start(const struct sr_dev_inst *sdi,
529                 void *cb_data)
530 {
531         struct dev_context *devc;
532         struct sr_scpi_dev_inst *scpi;
533         struct sr_channel *ch;
534         int ret;
535
536         if (sdi->status != SR_ST_ACTIVE)
537                 return SR_ERR_DEV_CLOSED;
538
539         devc = sdi->priv;
540         scpi = sdi->conn;
541         devc->cb_data = cb_data;
542
543         if ((ret = sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 100,
544                         scpi_pps_receive_data, (void *)sdi)) != SR_OK)
545                 return ret;
546         std_session_send_df_header(sdi, LOG_PREFIX);
547
548         /* Prime the pipe. */
549         devc->state = STATE_VOLTAGE;
550         ch = sdi->channels->data;
551         devc->cur_channel = ch;
552         scpi_cmd(sdi, SCPI_CMD_GET_MEAS_VOLTAGE, ch->name);
553
554         return SR_OK;
555 }
556
557 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
558 {
559         struct dev_context *devc;
560         struct sr_scpi_dev_inst *scpi;
561         float f;
562
563         (void)cb_data;
564
565         if (sdi->status != SR_ST_ACTIVE)
566                 return SR_ERR_DEV_CLOSED;
567
568         devc = sdi->priv;
569         scpi = sdi->conn;
570
571         /*
572          * A requested value is certainly on the way. Retrieve it now,
573          * to avoid leaving the device in a state where it's not expecting
574          * commands.
575          */
576         sr_scpi_get_float(scpi, NULL, &f);
577         sr_scpi_source_remove(sdi->session, scpi);
578
579         /* Just in case something is queued up. */
580         devc->state = STATE_STOP;
581
582         return SR_OK;
583 }
584
585 SR_PRIV struct sr_dev_driver scpi_pps_driver_info = {
586         .name = "scpi-pps",
587         .longname = "SCPI PPS",
588         .api_version = 1,
589         .init = init,
590         .cleanup = cleanup,
591         .scan = scan,
592         .dev_list = dev_list,
593         .dev_clear = dev_clear,
594         .config_get = config_get,
595         .config_set = config_set,
596         .config_list = config_list,
597         .dev_open = dev_open,
598         .dev_close = dev_close,
599         .dev_acquisition_start = dev_acquisition_start,
600         .dev_acquisition_stop = dev_acquisition_stop,
601         .priv = NULL,
602 };