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