]> sigrok.org Git - libsigrok.git/blob - hardware/common/scpi.c
scpi: factorize dev_inst_new calls out of individual drivers
[libsigrok.git] / hardware / common / scpi.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.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 "libsigrok.h"
21 #include "libsigrok-internal.h"
22
23 #include <glib.h>
24 #include <string.h>
25
26 #define LOG_PREFIX "scpi"
27
28 #define SCPI_READ_RETRIES 100
29 #define SCPI_READ_RETRY_TIMEOUT 10000
30
31 /**
32  * Parse a string representation of a boolean-like value into a gboolean.
33  * Similar to sr_parse_boolstring but rejects strings which do not represent
34  * a boolean-like value.
35  *
36  * @param str String to convert.
37  * @param ret Pointer to a gboolean where the result of the conversion will be
38  * stored.
39  *
40  * @return SR_OK on success, SR_ERR on failure.
41  */
42 static int parse_strict_bool(const char *str, gboolean *ret)
43 {
44         if (!str)
45                 return SR_ERR_ARG;
46
47         if (!g_strcmp0(str, "1") ||
48             !g_ascii_strncasecmp(str, "y", 1) ||
49             !g_ascii_strncasecmp(str, "t", 1) ||
50             !g_ascii_strncasecmp(str, "yes", 3) ||
51             !g_ascii_strncasecmp(str, "true", 4) ||
52             !g_ascii_strncasecmp(str, "on", 2)) {
53                 *ret = TRUE;
54                 return SR_OK;
55         } else if (!g_strcmp0(str, "0") ||
56                    !g_ascii_strncasecmp(str, "n", 1) ||
57                    !g_ascii_strncasecmp(str, "f", 1) ||
58                    !g_ascii_strncasecmp(str, "no", 2) ||
59                    !g_ascii_strncasecmp(str, "false", 5) ||
60                    !g_ascii_strncasecmp(str, "off", 3)) {
61                 *ret = FALSE;
62                 return SR_OK;
63         }
64
65         return SR_ERR;
66 }
67
68 SR_PRIV struct sr_scpi_dev_inst *scpi_dev_inst_new(const char *resource,
69                 const char *serialcomm)
70 {
71         struct sr_scpi_dev_inst *scpi = NULL;
72         const char *usbtmc_prefix = "/dev/usbtmc";
73         const char *tcp_prefix = "tcp/";
74         const char *vxi_prefix = "vxi/";
75         gchar **tokens, *address, *port, *instrument;
76
77         if (strncmp(resource, usbtmc_prefix, strlen(usbtmc_prefix)) == 0) {
78                 sr_dbg("Opening USBTMC device %s.", resource);
79                 scpi = scpi_usbtmc_dev_inst_new(resource);
80         } else if (strncmp(resource, tcp_prefix, strlen(tcp_prefix)) == 0) {
81                 sr_dbg("Opening TCP connection %s.", resource);
82                 tokens = g_strsplit(resource + strlen(tcp_prefix), "/", 0);
83                 address = tokens[0];
84                 port = tokens[1];
85                 if (address && port && !tokens[2])
86                         scpi = scpi_tcp_dev_inst_new(address, port);
87                 else
88                         sr_err("Invalid parameters.");
89                 g_strfreev(tokens);
90         } else if (HAVE_RPC && !strncmp(resource, vxi_prefix, strlen(vxi_prefix))) {
91                 sr_dbg("Opening VXI connection %s.", resource);
92                 tokens = g_strsplit(resource + strlen(tcp_prefix), "/", 0);
93                 address = tokens[0];
94                 instrument = tokens[1];
95                 if (address && (!instrument || !tokens[2]))
96                         scpi = scpi_vxi_dev_inst_new(address, instrument);
97                 else
98                         sr_err("Invalid parameters.");
99                 g_strfreev(tokens);
100         } else {
101                 sr_dbg("Opening serial device %s.", resource);
102                 scpi = scpi_serial_dev_inst_new(resource, serialcomm);
103         }
104         return scpi;
105 }
106
107 /**
108  * Open SCPI device.
109  *
110  * @param scpi Previously initialized SCPI device structure.
111  *
112  * @return SR_OK on success, SR_ERR on failure.
113  */
114 SR_PRIV int sr_scpi_open(struct sr_scpi_dev_inst *scpi)
115 {
116         return scpi->open(scpi->priv);
117 }
118
119 /**
120  * Add an event source for an SCPI device.
121  *
122  * @param scpi Previously initialized SCPI device structure.
123  * @param events Events to check for.
124  * @param timeout Max time to wait before the callback is called, ignored if 0.
125  * @param cb Callback function to add. Must not be NULL.
126  * @param cb_data Data for the callback function. Can be NULL.
127  *
128  * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
129  *         SR_ERR_MALLOC upon memory allocation errors.
130  */
131 SR_PRIV int sr_scpi_source_add(struct sr_scpi_dev_inst *scpi, int events,
132                 int timeout, sr_receive_data_callback_t cb, void *cb_data)
133 {
134         return scpi->source_add(scpi->priv, events, timeout, cb, cb_data);
135 }
136
137 /**
138  * Remove event source for an SCPI device.
139  *
140  * @param scpi Previously initialized SCPI device structure.
141  *
142  * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
143  *         SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
144  *         internal errors.
145  */
146 SR_PRIV int sr_scpi_source_remove(struct sr_scpi_dev_inst *scpi)
147 {
148         return scpi->source_remove(scpi->priv);
149 }
150
151 /**
152  * Send a SCPI command.
153  *
154  * @param scpi Previously initialized SCPI device structure.
155  * @param format Format string, to be followed by any necessary arguments.
156  *
157  * @return SR_OK on success, SR_ERR on failure.
158  */
159 SR_PRIV int sr_scpi_send(struct sr_scpi_dev_inst *scpi,
160                          const char *format, ...)
161 {
162         va_list args;
163         int ret;
164
165         va_start(args, format);
166         ret = sr_scpi_send_variadic(scpi, format, args);
167         va_end(args);
168
169         return ret;
170 }
171
172 /**
173  * Send a SCPI command with a variadic argument list.
174  *
175  * @param scpi Previously initialized SCPI device structure.
176  * @param format Format string.
177  * @param args Argument list.
178  *
179  * @return SR_OK on success, SR_ERR on failure.
180  */
181 SR_PRIV int sr_scpi_send_variadic(struct sr_scpi_dev_inst *scpi,
182                          const char *format, va_list args)
183 {
184         va_list args_copy;
185         char *buf;
186         int len, ret;
187
188         /* Get length of buffer required. */
189         va_copy(args_copy, args);
190         len = vsnprintf(NULL, 0, format, args_copy);
191         va_end(args_copy);
192
193         /* Allocate buffer and write out command. */
194         buf = g_malloc(len + 1);
195         vsprintf(buf, format, args);
196
197         /* Send command. */
198         ret = scpi->send(scpi->priv, buf);
199
200         /* Free command buffer. */
201         g_free(buf);
202
203         return ret;
204 }
205
206 /**
207  * Begin receiving an SCPI reply.
208  *
209  * @param scpi Previously initialised SCPI device structure.
210  *
211  * @return SR_OK on success, SR_ERR on failure.
212  */
213 SR_PRIV int sr_scpi_read_begin(struct sr_scpi_dev_inst *scpi)
214 {
215         return scpi->read_begin(scpi->priv);
216 }
217
218 /**
219  * Read part of a response from SCPI device.
220  *
221  * @param scpi Previously initialised SCPI device structure.
222  * @param buf Buffer to store result.
223  * @param maxlen Maximum number of bytes to read.
224  *
225  * @return Number of bytes read, or SR_ERR upon failure.
226  */
227 SR_PRIV int sr_scpi_read_data(struct sr_scpi_dev_inst *scpi,
228                         char *buf, int maxlen)
229 {
230         return scpi->read_data(scpi->priv, buf, maxlen);
231 }
232
233 /**
234  * Check whether a complete SCPI response has been received.
235  *
236  * @param scpi Previously initialised SCPI device structure.
237  *
238  * @return 1 if complete, 0 otherwise.
239  */
240 SR_PRIV int sr_scpi_read_complete(struct sr_scpi_dev_inst *scpi)
241 {
242         return scpi->read_complete(scpi->priv);
243 }
244
245 /**
246  * Close SCPI device.
247  *
248  * @param scpi Previously initialized SCPI device structure.
249  *
250  * @return SR_OK on success, SR_ERR on failure.
251  */
252 SR_PRIV int sr_scpi_close(struct sr_scpi_dev_inst *scpi)
253 {
254         return scpi->close(scpi->priv);
255 }
256
257 /**
258  * Free SCPI device.
259  *
260  * @param scpi Previously initialized SCPI device structure.
261  *
262  * @return SR_OK on success, SR_ERR on failure.
263  */
264 SR_PRIV void sr_scpi_free(struct sr_scpi_dev_inst *scpi)
265 {
266         scpi->free(scpi->priv);
267         g_free(scpi);
268 }
269
270 /**
271  * Send a SCPI command, receive the reply and store the reply in scpi_response.
272  *
273  * @param scpi Previously initialised SCPI device structure.
274  * @param command The SCPI command to send to the device (can be NULL).
275  * @param scpi_response Pointer where to store the SCPI response.
276  *
277  * @return SR_OK on success, SR_ERR on failure.
278  */
279 SR_PRIV int sr_scpi_get_string(struct sr_scpi_dev_inst *scpi,
280                                const char *command, char **scpi_response)
281 {
282         char buf[256];
283         int len;
284         GString *response;
285
286         if (command)
287                 if (sr_scpi_send(scpi, command) != SR_OK)
288                         return SR_ERR;
289
290         if (sr_scpi_read_begin(scpi) != SR_OK)
291                 return SR_ERR;
292
293         response = g_string_new("");
294
295         *scpi_response = NULL;
296
297         while (!sr_scpi_read_complete(scpi)) {
298                 len = sr_scpi_read_data(scpi, buf, sizeof(buf));
299                 if (len < 0) {
300                         g_string_free(response, TRUE);
301                         return SR_ERR;
302                 }
303                 g_string_append_len(response, buf, len);
304         }
305
306         *scpi_response = response->str;
307         g_string_free(response, FALSE);
308
309         return SR_OK;
310 }
311
312 /**
313  * Send a SCPI command, read the reply, parse it as a bool value and store the
314  * result in scpi_response.
315  *
316  * @param scpi Previously initialised SCPI device structure.
317  * @param command The SCPI command to send to the device (can be NULL).
318  * @param scpi_response Pointer where to store the parsed result.
319  *
320  * @return SR_OK on success, SR_ERR on failure.
321  */
322 SR_PRIV int sr_scpi_get_bool(struct sr_scpi_dev_inst *scpi,
323                              const char *command, gboolean *scpi_response)
324 {
325         int ret;
326         char *response;
327
328         response = NULL;
329
330         if (sr_scpi_get_string(scpi, command, &response) != SR_OK)
331                 if (!response)
332                         return SR_ERR;
333
334         if (parse_strict_bool(response, scpi_response) == SR_OK)
335                 ret = SR_OK;
336         else
337                 ret = SR_ERR;
338
339         g_free(response);
340
341         return ret;
342 }
343
344 /**
345  * Send a SCPI command, read the reply, parse it as an integer and store the
346  * result in scpi_response.
347  *
348  * @param scpi Previously initialised SCPI device structure.
349  * @param command The SCPI command to send to the device (can be NULL).
350  * @param scpi_response Pointer where to store the parsed result.
351  *
352  * @return SR_OK on success, SR_ERR on failure.
353  */
354 SR_PRIV int sr_scpi_get_int(struct sr_scpi_dev_inst *scpi,
355                             const char *command, int *scpi_response)
356 {
357         int ret;
358         char *response;
359
360         response = NULL;
361
362         if (sr_scpi_get_string(scpi, command, &response) != SR_OK)
363                 if (!response)
364                         return SR_ERR;
365
366         if (sr_atoi(response, scpi_response) == SR_OK)
367                 ret = SR_OK;
368         else
369                 ret = SR_ERR;
370
371         g_free(response);
372
373         return ret;
374 }
375
376 /**
377  * Send a SCPI command, read the reply, parse it as a float and store the
378  * result in scpi_response.
379  *
380  * @param scpi Previously initialised SCPI device structure.
381  * @param command The SCPI command to send to the device (can be NULL).
382  * @param scpi_response Pointer where to store the parsed result.
383  *
384  * @return SR_OK on success, SR_ERR on failure.
385  */
386 SR_PRIV int sr_scpi_get_float(struct sr_scpi_dev_inst *scpi,
387                               const char *command, float *scpi_response)
388 {
389         int ret;
390         char *response;
391
392         response = NULL;
393
394         if (sr_scpi_get_string(scpi, command, &response) != SR_OK)
395                 if (!response)
396                         return SR_ERR;
397
398         if (sr_atof(response, scpi_response) == SR_OK)
399                 ret = SR_OK;
400         else
401                 ret = SR_ERR;
402
403         g_free(response);
404
405         return ret;
406 }
407
408 /**
409  * Send a SCPI command, read the reply, parse it as a double and store the
410  * result in scpi_response.
411  *
412  * @param scpi Previously initialised SCPI device structure.
413  * @param command The SCPI command to send to the device (can be NULL).
414  * @param scpi_response Pointer where to store the parsed result.
415  *
416  * @return SR_OK on success, SR_ERR on failure.
417  */
418 SR_PRIV int sr_scpi_get_double(struct sr_scpi_dev_inst *scpi,
419                                const char *command, double *scpi_response)
420 {
421         int ret;
422         char *response;
423
424         response = NULL;
425
426         if (sr_scpi_get_string(scpi, command, &response) != SR_OK)
427                 if (!response)
428                         return SR_ERR;
429
430         if (sr_atod(response, scpi_response) == SR_OK)
431                 ret = SR_OK;
432         else
433                 ret = SR_ERR;
434
435         g_free(response);
436
437         return ret;
438 }
439
440 /**
441  * Send a SCPI *OPC? command, read the reply and return the result of the
442  * command.
443  *
444  * @param scpi Previously initialised SCPI device structure.
445  *
446  * @return SR_OK on success, SR_ERR on failure.
447  */
448 SR_PRIV int sr_scpi_get_opc(struct sr_scpi_dev_inst *scpi)
449 {
450         unsigned int i;
451         gboolean opc;
452
453         for (i = 0; i < SCPI_READ_RETRIES; ++i) {
454                 sr_scpi_get_bool(scpi, SCPI_CMD_OPC, &opc);
455                 if (opc)
456                         return SR_OK;
457                 g_usleep(SCPI_READ_RETRY_TIMEOUT);
458         }
459
460         return SR_ERR;
461 }
462
463 /**
464  * Send a SCPI command, read the reply, parse it as comma separated list of
465  * floats and store the as an result in scpi_response.
466  *
467  * @param scpi Previously initialised SCPI device structure.
468  * @param command The SCPI command to send to the device (can be NULL).
469  * @param scpi_response Pointer where to store the parsed result.
470  *
471  * @return SR_OK upon successfully parsing all values, SR_ERR upon a parsing
472  *         error or upon no response. The allocated response must be freed by
473  *         the caller in the case of an SR_OK as well as in the case of
474  *         parsing error.
475  */
476 SR_PRIV int sr_scpi_get_floatv(struct sr_scpi_dev_inst *scpi,
477                                const char *command, GArray **scpi_response)
478 {
479         int ret;
480         float tmp;
481         char *response;
482         gchar **ptr, **tokens;
483         GArray *response_array;
484
485         ret = SR_OK;
486         response = NULL;
487         tokens = NULL;
488
489         if (sr_scpi_get_string(scpi, command, &response) != SR_OK)
490                 if (!response)
491                         return SR_ERR;
492
493         tokens = g_strsplit(response, ",", 0);
494         ptr = tokens;
495
496         response_array = g_array_sized_new(TRUE, FALSE, sizeof(float), 256);
497
498         while (*ptr) {
499                 if (sr_atof(*ptr, &tmp) == SR_OK)
500                         response_array = g_array_append_val(response_array,
501                                                             tmp);
502                 else
503                         ret = SR_ERR;
504
505                 ptr++;
506         }
507         g_strfreev(tokens);
508         g_free(response);
509
510         if (ret == SR_ERR && response_array->len == 0) {
511                 g_array_free(response_array, TRUE);
512                 *scpi_response = NULL;
513                 return SR_ERR;
514         }
515
516         *scpi_response = response_array;
517
518         return ret;
519 }
520
521 /**
522  * Send a SCPI command, read the reply, parse it as comma separated list of
523  * unsigned 8 bit integers and store the as an result in scpi_response.
524  *
525  * @param scpi Previously initialised SCPI device structure.
526  * @param command The SCPI command to send to the device (can be NULL).
527  * @param scpi_response Pointer where to store the parsed result.
528  *
529  * @return SR_OK upon successfully parsing all values, SR_ERR upon a parsing
530  *         error or upon no response. The allocated response must be freed by
531  *         the caller in the case of an SR_OK as well as in the case of
532  *         parsing error.
533  */
534 SR_PRIV int sr_scpi_get_uint8v(struct sr_scpi_dev_inst *scpi,
535                                const char *command, GArray **scpi_response)
536 {
537         int tmp, ret;
538         char *response;
539         gchar **ptr, **tokens;
540         GArray *response_array;
541
542         ret = SR_OK;
543         response = NULL;
544         tokens = NULL;
545
546         if (sr_scpi_get_string(scpi, command, &response) != SR_OK)
547                 if (!response)
548                         return SR_ERR;
549
550         tokens = g_strsplit(response, ",", 0);
551         ptr = tokens;
552
553         response_array = g_array_sized_new(TRUE, FALSE, sizeof(uint8_t), 256);
554
555         while (*ptr) {
556                 if (sr_atoi(*ptr, &tmp) == SR_OK)
557                         response_array = g_array_append_val(response_array,
558                                                             tmp);
559                 else
560                         ret = SR_ERR;
561
562                 ptr++;
563         }
564         g_strfreev(tokens);
565         g_free(response);
566
567         if (response_array->len == 0) {
568                 g_array_free(response_array, TRUE);
569                 *scpi_response = NULL;
570                 return SR_ERR;
571         }
572
573         *scpi_response = response_array;
574
575         return ret;
576 }
577
578 /**
579  * Send the *IDN? SCPI command, receive the reply, parse it and store the
580  * reply as a sr_scpi_hw_info structure in the supplied scpi_response pointer.
581  *
582  * The hw_info structure must be freed by the caller via sr_scpi_hw_info_free().
583  *
584  * @param scpi Previously initialised SCPI device structure.
585  * @param scpi_response Pointer where to store the hw_info structure.
586  *
587  * @return SR_OK upon success, SR_ERR on failure.
588  */
589 SR_PRIV int sr_scpi_get_hw_id(struct sr_scpi_dev_inst *scpi,
590                               struct sr_scpi_hw_info **scpi_response)
591 {
592         int num_tokens;
593         char *response;
594         char *newline;
595         gchar **tokens;
596         struct sr_scpi_hw_info *hw_info;
597
598         response = NULL;
599         tokens = NULL;
600
601         if (sr_scpi_get_string(scpi, SCPI_CMD_IDN, &response) != SR_OK)
602                 if (!response)
603                         return SR_ERR;
604
605         sr_info("Got IDN string: '%s'", response);
606
607         /* Remove trailing newline if present. */
608         if ((newline = g_strrstr(response, "\n")))
609                 newline[0] = '\0';
610
611         /*
612          * The response to a '*IDN?' is specified by the SCPI spec. It contains
613          * a comma-separated list containing the manufacturer name, instrument
614          * model, serial number of the instrument and the firmware version.
615          */
616         tokens = g_strsplit(response, ",", 0);
617
618         for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
619
620         if (num_tokens != 4) {
621                 sr_dbg("IDN response not according to spec: %80.s.", response);
622                 g_strfreev(tokens);
623                 g_free(response);
624                 return SR_ERR;
625         }
626         g_free(response);
627
628         hw_info = g_try_malloc(sizeof(struct sr_scpi_hw_info));
629         if (!hw_info) {
630                 g_strfreev(tokens);
631                 return SR_ERR_MALLOC;
632         }
633
634         hw_info->manufacturer = g_strdup(tokens[0]);
635         hw_info->model = g_strdup(tokens[1]);
636         hw_info->serial_number = g_strdup(tokens[2]);
637         hw_info->firmware_version = g_strdup(tokens[3]);
638
639         g_strfreev(tokens);
640
641         *scpi_response = hw_info;
642
643         return SR_OK;
644 }
645
646 /**
647  * Free a sr_scpi_hw_info struct.
648  *
649  * @param hw_info Pointer to the struct to free.
650  *
651  * This function is safe to call with a NULL pointer.
652  */
653 SR_PRIV void sr_scpi_hw_info_free(struct sr_scpi_hw_info *hw_info)
654 {
655         if (hw_info) {
656                 g_free(hw_info->manufacturer);
657                 g_free(hw_info->model);
658                 g_free(hw_info->serial_number);
659                 g_free(hw_info->firmware_version);
660                 g_free(hw_info);
661         }
662 }