]> sigrok.org Git - libsigrok.git/blob - src/backend.c
Don't set _POSIX_C_SOURCE for VXI/RPC related files.
[libsigrok.git] / src / backend.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5  * Copyright (C) 2012 Peter Stuge <peter@stuge.se>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <glib.h>
22 #include "config.h" /* Needed for HAVE_LIBUSB_1_0 and others. */
23 #include <libsigrok/libsigrok.h>
24 #include "libsigrok-internal.h"
25
26 /** @cond PRIVATE */
27 #define LOG_PREFIX "backend"
28 /** @endcond */
29
30 /**
31  * @mainpage libsigrok API
32  *
33  * @section sec_intro Introduction
34  *
35  * The <a href="http://sigrok.org">sigrok</a> project aims at creating a
36  * portable, cross-platform, Free/Libre/Open-Source signal analysis software
37  * suite that supports various device types (such as logic analyzers,
38  * oscilloscopes, multimeters, and more).
39  *
40  * <a href="http://sigrok.org/wiki/Libsigrok">libsigrok</a> is a shared
41  * library written in C which provides the basic API for talking to
42  * <a href="http://sigrok.org/wiki/Supported_hardware">supported hardware</a>
43  * and reading/writing the acquired data into various
44  * <a href="http://sigrok.org/wiki/Input_output_formats">input/output
45  * file formats</a>.
46  *
47  * @section sec_api API reference
48  *
49  * See the "Modules" page for an introduction to various libsigrok
50  * related topics and the detailed API documentation of the respective
51  * functions.
52  *
53  * You can also browse the API documentation by file, or review all
54  * data structures.
55  *
56  * @section sec_mailinglists Mailing lists
57  *
58  * There is one mailing list for sigrok/libsigrok: <a href="https://lists.sourceforge.net/lists/listinfo/sigrok-devel">sigrok-devel</a>.
59  *
60  * @section sec_irc IRC
61  *
62  * You can find the sigrok developers in the
63  * <a href="irc://chat.freenode.net/sigrok">\#sigrok</a>
64  * IRC channel on Freenode.
65  *
66  * @section sec_website Website
67  *
68  * <a href="http://sigrok.org/wiki/Libsigrok">sigrok.org/wiki/Libsigrok</a>
69  */
70
71 /**
72  * @file
73  *
74  * Initializing and shutting down libsigrok.
75  */
76
77 /**
78  * @defgroup grp_init Initialization
79  *
80  * Initializing and shutting down libsigrok.
81  *
82  * Before using any of the libsigrok functionality (except for
83  * sr_log_loglevel_set()), sr_init() must be called to initialize the
84  * library, which will return a struct sr_context when the initialization
85  * was successful.
86  *
87  * When libsigrok functionality is no longer needed, sr_exit() should be
88  * called, which will (among other things) free the struct sr_context.
89  *
90  * Example for a minimal program using libsigrok:
91  *
92  * @code{.c}
93  *   #include <stdio.h>
94  *   #include <libsigrok/libsigrok.h>
95  *
96  *   int main(int argc, char **argv)
97  *   {
98  *      int ret;
99  *      struct sr_context *sr_ctx;
100  *
101  *      if ((ret = sr_init(&sr_ctx)) != SR_OK) {
102  *              printf("Error initializing libsigrok (%s): %s.\n",
103  *                     sr_strerror_name(ret), sr_strerror(ret));
104  *              return 1;
105  *      }
106  *
107  *      // Use libsigrok functions here...
108  *
109  *      if ((ret = sr_exit(sr_ctx)) != SR_OK) {
110  *              printf("Error shutting down libsigrok (%s): %s.\n",
111  *                     sr_strerror_name(ret), sr_strerror(ret));
112  *              return 1;
113  *      }
114  *
115  *      return 0;
116  *   }
117  * @endcode
118  *
119  * @{
120  */
121
122 static void print_versions(void)
123 {
124         GString *s;
125 #if defined(HAVE_LIBUSB_1_0) && !defined(__FreeBSD__)
126         const struct libusb_version *lv;
127 #endif
128
129         s = g_string_sized_new(200);
130
131         sr_dbg("libsigrok %s/%s (rt: %s/%s).",
132                 SR_PACKAGE_VERSION_STRING, SR_LIB_VERSION_STRING,
133                 sr_package_version_string_get(), sr_lib_version_string_get());
134
135         g_string_append(s, "Libs: ");
136         g_string_append_printf(s, "glib %d.%d.%d (rt: %d.%d.%d/%d:%d), ",
137                 GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
138                 glib_major_version, glib_minor_version, glib_micro_version,
139                 glib_binary_age, glib_interface_age);
140         g_string_append_printf(s, "libzip %s, ", CONF_LIBZIP_VERSION);
141 #ifdef HAVE_LIBSERIALPORT
142         g_string_append_printf(s, "libserialport %s/%s (rt: %s/%s), ",
143                 SP_PACKAGE_VERSION_STRING, SP_LIB_VERSION_STRING,
144                 sp_get_package_version_string(), sp_get_lib_version_string());
145 #endif
146 #ifdef HAVE_LIBUSB_1_0
147 #ifdef __FreeBSD__
148         g_string_append_printf(s, "libusb-1.0 %s, ", CONF_LIBUSB_1_0_VERSION);
149 #else
150         lv = libusb_get_version();
151         g_string_append_printf(s, "libusb-1.0 %d.%d.%d.%d%s, ",
152                 lv->major, lv->minor, lv->micro, lv->nano, lv->rc);
153 #endif
154 #endif
155 #ifdef HAVE_LIBFTDI
156         g_string_append_printf(s, "libftdi %s, ", CONF_LIBFTDI_VERSION);
157 #endif
158 #ifdef HAVE_LIBGPIB
159         g_string_append_printf(s, "libgpib %s, ", CONF_LIBGPIB_VERSION);
160 #endif
161 #ifdef HAVE_LIBREVISA
162         g_string_append_printf(s, "librevisa %s, ", CONF_LIBREVISA_VERSION);
163 #endif
164         s->str[s->len - 2] = '.';
165         s->str[s->len - 1] = '\0';
166         sr_dbg("%s", s->str);
167
168         s = g_string_truncate(s, 0);
169         g_string_append_printf(s, "Host: %s, ", CONF_HOST);
170 #ifdef WORDS_BIGENDIAN
171         g_string_append_printf(s, "big-endian.");
172 #else
173         g_string_append_printf(s, "little-endian.");
174 #endif
175         sr_dbg("%s", s->str);
176
177         s = g_string_truncate(s, 0);
178         g_string_append_printf(s, "SCPI backends: ");
179
180         g_string_append_printf(s, "TCP, ");
181 #if HAVE_RPC
182         g_string_append_printf(s, "RPC, ");
183 #endif
184 #ifdef HAVE_LIBSERIALPORT
185         g_string_append_printf(s, "serial, ");
186 #endif
187 #ifdef HAVE_LIBREVISA
188         g_string_append_printf(s, "VISA, ");
189 #endif
190 #ifdef HAVE_LIBGPIB
191         g_string_append_printf(s, "GPIB, ");
192 #endif
193 #ifdef HAVE_LIBUSB_1_0
194         g_string_append_printf(s, "USBTMC, ");
195 #endif
196         s->str[s->len - 2] = '.';
197         s->str[s->len - 1] = '\0';
198         sr_dbg("%s", s->str);
199
200         g_string_free(s, TRUE);
201 }
202
203 /**
204  * Sanity-check all libsigrok drivers.
205  *
206  * @param[in] ctx Pointer to a libsigrok context struct. Must not be NULL.
207  *
208  * @retval SR_OK All drivers are OK
209  * @retval SR_ERR One or more drivers have issues.
210  * @retval SR_ERR_ARG Invalid argument.
211  */
212 static int sanity_check_all_drivers(const struct sr_context *ctx)
213 {
214         int i, errors, ret = SR_OK;
215         struct sr_dev_driver **drivers;
216         const char *d;
217
218         if (!ctx)
219                 return SR_ERR_ARG;
220
221         sr_spew("Sanity-checking all drivers.");
222
223         drivers = sr_driver_list(ctx);
224         for (i = 0; drivers[i]; i++) {
225                 errors = 0;
226
227                 d = (drivers[i]->name) ? drivers[i]->name : "NULL";
228
229                 if (!drivers[i]->name) {
230                         sr_err("No name in driver %d ('%s').", i, d);
231                         errors++;
232                 }
233                 if (!drivers[i]->longname) {
234                         sr_err("No longname in driver %d ('%s').", i, d);
235                         errors++;
236                 }
237                 if (drivers[i]->api_version < 1) {
238                         sr_err("API version in driver %d ('%s') < 1.", i, d);
239                         errors++;
240                 }
241                 if (!drivers[i]->init) {
242                         sr_err("No init in driver %d ('%s').", i, d);
243                         errors++;
244                 }
245                 if (!drivers[i]->cleanup) {
246                         sr_err("No cleanup in driver %d ('%s').", i, d);
247                         errors++;
248                 }
249                 if (!drivers[i]->scan) {
250                         sr_err("No scan in driver %d ('%s').", i, d);
251                         errors++;
252                 }
253                 if (!drivers[i]->dev_list) {
254                         sr_err("No dev_list in driver %d ('%s').", i, d);
255                         errors++;
256                 }
257                 /* Note: config_get() is optional. */
258                 if (!drivers[i]->config_set) {
259                         sr_err("No config_set in driver %d ('%s').", i, d);
260                         errors++;
261                 }
262                 if (!drivers[i]->config_list) {
263                         sr_err("No config_list in driver %d ('%s').", i, d);
264                         errors++;
265                 }
266                 if (!drivers[i]->dev_open) {
267                         sr_err("No dev_open in driver %d ('%s').", i, d);
268                         errors++;
269                 }
270                 if (!drivers[i]->dev_close) {
271                         sr_err("No dev_close in driver %d ('%s').", i, d);
272                         errors++;
273                 }
274                 if (!drivers[i]->dev_acquisition_start) {
275                         sr_err("No dev_acquisition_start in driver %d ('%s').",
276                                i, d);
277                         errors++;
278                 }
279                 if (!drivers[i]->dev_acquisition_stop) {
280                         sr_err("No dev_acquisition_stop in driver %d ('%s').",
281                                i, d);
282                         errors++;
283                 }
284
285                 /* Note: 'priv' is allowed to be NULL. */
286
287                 if (errors == 0)
288                         continue;
289
290                 ret = SR_ERR;
291         }
292
293         return ret;
294 }
295
296 /**
297  * Sanity-check all libsigrok input modules.
298  *
299  * @retval SR_OK All modules are OK
300  * @retval SR_ERR One or more modules have issues.
301  */
302 static int sanity_check_all_input_modules(void)
303 {
304         int i, errors, ret = SR_OK;
305         const struct sr_input_module **inputs;
306         const char *d;
307
308         sr_spew("Sanity-checking all input modules.");
309
310         inputs = sr_input_list();
311         for (i = 0; inputs[i]; i++) {
312                 errors = 0;
313
314                 d = (inputs[i]->id) ? inputs[i]->id : "NULL";
315
316                 if (!inputs[i]->id) {
317                         sr_err("No ID in module %d ('%s').", i, d);
318                         errors++;
319                 }
320                 if (!inputs[i]->name) {
321                         sr_err("No name in module %d ('%s').", i, d);
322                         errors++;
323                 }
324                 if (!inputs[i]->desc) {
325                         sr_err("No description in module %d ('%s').", i, d);
326                         errors++;
327                 }
328                 if (!inputs[i]->init) {
329                         sr_err("No init in module %d ('%s').", i, d);
330                         errors++;
331                 }
332                 if (!inputs[i]->receive) {
333                         sr_err("No receive in module %d ('%s').", i, d);
334                         errors++;
335                 }
336                 if (!inputs[i]->end) {
337                         sr_err("No end in module %d ('%s').", i, d);
338                         errors++;
339                 }
340
341                 if (errors == 0)
342                         continue;
343
344                 ret = SR_ERR;
345         }
346
347         return ret;
348 }
349
350 /**
351  * Sanity-check all libsigrok output modules.
352  *
353  * @retval SR_OK All modules are OK
354  * @retval SR_ERR One or more modules have issues.
355  */
356 static int sanity_check_all_output_modules(void)
357 {
358         int i, errors, ret = SR_OK;
359         const struct sr_output_module **outputs;
360         const char *d;
361
362         sr_spew("Sanity-checking all output modules.");
363
364         outputs = sr_output_list();
365         for (i = 0; outputs[i]; i++) {
366                 errors = 0;
367
368                 d = (outputs[i]->id) ? outputs[i]->id : "NULL";
369
370                 if (!outputs[i]->id) {
371                         sr_err("No ID in module %d ('%s').", i, d);
372                         errors++;
373                 }
374                 if (!outputs[i]->name) {
375                         sr_err("No name in module %d ('%s').", i, d);
376                         errors++;
377                 }
378                 if (!outputs[i]->desc) {
379                         sr_err("No description in module '%s'.", d);
380                         errors++;
381                 }
382                 if (!outputs[i]->receive) {
383                         sr_err("No receive in module '%s'.", d);
384                         errors++;
385                 }
386
387                 if (errors == 0)
388                         continue;
389
390                 ret = SR_ERR;
391         }
392
393         return ret;
394 }
395
396 /**
397  * Sanity-check all libsigrok transform modules.
398  *
399  * @retval SR_OK All modules are OK
400  * @retval SR_ERR One or more modules have issues.
401  */
402 static int sanity_check_all_transform_modules(void)
403 {
404         int i, errors, ret = SR_OK;
405         const struct sr_transform_module **transforms;
406         const char *d;
407
408         sr_spew("Sanity-checking all transform modules.");
409
410         transforms = sr_transform_list();
411         for (i = 0; transforms[i]; i++) {
412                 errors = 0;
413
414                 d = (transforms[i]->id) ? transforms[i]->id : "NULL";
415
416                 if (!transforms[i]->id) {
417                         sr_err("No ID in module %d ('%s').", i, d);
418                         errors++;
419                 }
420                 if (!transforms[i]->name) {
421                         sr_err("No name in module %d ('%s').", i, d);
422                         errors++;
423                 }
424                 if (!transforms[i]->desc) {
425                         sr_err("No description in module '%s'.", d);
426                         errors++;
427                 }
428                 /* Note: options() is optional. */
429                 /* Note: init() is optional. */
430                 if (!transforms[i]->receive) {
431                         sr_err("No receive in module '%s'.", d);
432                         errors++;
433                 }
434                 /* Note: cleanup() is optional. */
435
436                 if (errors == 0)
437                         continue;
438
439                 ret = SR_ERR;
440         }
441
442         return ret;
443 }
444
445 /**
446  * Initialize libsigrok.
447  *
448  * This function must be called before any other libsigrok function.
449  *
450  * @param ctx Pointer to a libsigrok context struct pointer. Must not be NULL.
451  *            This will be a pointer to a newly allocated libsigrok context
452  *            object upon success, and is undefined upon errors.
453  *
454  * @return SR_OK upon success, a (negative) error code otherwise. Upon errors
455  *         the 'ctx' pointer is undefined and should not be used. Upon success,
456  *         the context will be free'd by sr_exit() as part of the libsigrok
457  *         shutdown.
458  *
459  * @since 0.2.0
460  */
461 SR_API int sr_init(struct sr_context **ctx)
462 {
463         int ret = SR_ERR;
464         struct sr_context *context;
465         struct sr_dev_driver ***lists, **drivers;
466         GArray *array;
467
468         print_versions();
469
470         if (!ctx) {
471                 sr_err("%s(): libsigrok context was NULL.", __func__);
472                 return SR_ERR;
473         }
474
475         context = g_malloc0(sizeof(struct sr_context));
476
477         /* Generate ctx->driver_list at runtime. */
478         array = g_array_new(TRUE, FALSE, sizeof(struct sr_dev_driver *));
479         for (lists = drivers_lists; *lists; lists++)
480                 for (drivers = *lists; *drivers; drivers++)
481                         g_array_append_val(array, *drivers);
482         context->driver_list = (struct sr_dev_driver **)array->data;
483         g_array_free(array, FALSE);
484
485         if (sanity_check_all_drivers(context) < 0) {
486                 sr_err("Internal driver error(s), aborting.");
487                 return ret;
488         }
489
490         if (sanity_check_all_input_modules() < 0) {
491                 sr_err("Internal input module error(s), aborting.");
492                 return ret;
493         }
494
495         if (sanity_check_all_output_modules() < 0) {
496                 sr_err("Internal output module error(s), aborting.");
497                 return ret;
498         }
499
500         if (sanity_check_all_transform_modules() < 0) {
501                 sr_err("Internal transform module error(s), aborting.");
502                 return ret;
503         }
504
505 #ifdef HAVE_LIBUSB_1_0
506         ret = libusb_init(&context->libusb_ctx);
507         if (LIBUSB_SUCCESS != ret) {
508                 sr_err("libusb_init() returned %s.", libusb_error_name(ret));
509                 ret = SR_ERR;
510                 goto done;
511         }
512 #endif
513
514         *ctx = context;
515         context = NULL;
516         ret = SR_OK;
517
518 #ifdef HAVE_LIBUSB_1_0
519 done:
520 #endif
521         g_free(context);
522         return ret;
523 }
524
525 /**
526  * Shutdown libsigrok.
527  *
528  * @param ctx Pointer to a libsigrok context struct. Must not be NULL.
529  *
530  * @retval SR_OK Success
531  * @retval other Error code SR_ERR, ...
532  *
533  * @since 0.2.0
534  */
535 SR_API int sr_exit(struct sr_context *ctx)
536 {
537         if (!ctx) {
538                 sr_err("%s(): libsigrok context was NULL.", __func__);
539                 return SR_ERR;
540         }
541
542         sr_hw_cleanup_all(ctx);
543
544 #ifdef HAVE_LIBUSB_1_0
545         libusb_exit(ctx->libusb_ctx);
546 #endif
547
548         g_free(sr_driver_list(ctx));
549         g_free(ctx);
550
551         return SR_OK;
552 }
553
554 /** @} */