]> sigrok.org Git - libsigrok.git/blob - src/backend.c
Build: Set local include directories in Makefile.am
[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 #ifdef HAVE_LIBUSB_1_0
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, ", HAVE_LIBZIP_VER);
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         lv = libusb_get_version();
148         g_string_append_printf(s, "libusb-1.0 %d.%d.%d.%d%s, ",
149                 lv->major, lv->minor, lv->micro, lv->nano, lv->rc);
150 #endif
151 #ifdef HAVE_LIBFTDI
152         g_string_append_printf(s, "libftdi %s, ", HAVE_LIBFTDI_VER);
153 #endif
154 #ifdef HAVE_LIBGPIB
155         g_string_append_printf(s, "libgpib %s, ", HAVE_LIBGPIB_VER);
156 #endif
157 #ifdef HAVE_LIBREVISA
158         g_string_append_printf(s, "librevisa %s, ", HAVE_LIBREVISA_VER);
159 #endif
160         s->str[s->len - 2] = '.';
161         s->str[s->len - 1] = '\0';
162         sr_dbg("%s", s->str);
163
164         s = g_string_truncate(s, 0);
165         g_string_append_printf(s, "Host: %s, ", HOST);
166 #ifdef WORDS_BIGENDIAN
167         g_string_append_printf(s, "big-endian.");
168 #else
169         g_string_append_printf(s, "little-endian.");
170 #endif
171         sr_dbg("%s", s->str);
172
173         s = g_string_truncate(s, 0);
174         g_string_append_printf(s, "SCPI backends: ");
175
176         g_string_append_printf(s, "TCP, ");
177 #if HAVE_RPC
178         g_string_append_printf(s, "RPC, ");
179 #endif
180 #ifdef HAVE_LIBSERIALPORT
181         g_string_append_printf(s, "serial, ");
182 #endif
183 #ifdef HAVE_LIBREVISA
184         g_string_append_printf(s, "VISA, ");
185 #endif
186 #ifdef HAVE_LIBGPIB
187         g_string_append_printf(s, "GPIB, ");
188 #endif
189 #ifdef HAVE_LIBUSB_1_0
190         g_string_append_printf(s, "USBTMC, ");
191 #endif
192         s->str[s->len - 2] = '.';
193         s->str[s->len - 1] = '\0';
194         sr_dbg("%s", s->str);
195
196         g_string_free(s, TRUE);
197 }
198
199 /**
200  * Sanity-check all libsigrok drivers.
201  *
202  * @param[in] ctx Pointer to a libsigrok context struct. Must not be NULL.
203  *
204  * @retval SR_OK All drivers are OK
205  * @retval SR_ERR One or more drivers have issues.
206  * @retval SR_ERR_ARG Invalid argument.
207  */
208 static int sanity_check_all_drivers(const struct sr_context *ctx)
209 {
210         int i, errors, ret = SR_OK;
211         struct sr_dev_driver **drivers;
212         const char *d;
213
214         if (!ctx)
215                 return SR_ERR_ARG;
216
217         sr_spew("Sanity-checking all drivers.");
218
219         drivers = sr_driver_list(ctx);
220         for (i = 0; drivers[i]; i++) {
221                 errors = 0;
222
223                 d = (drivers[i]->name) ? drivers[i]->name : "NULL";
224
225                 if (!drivers[i]->name) {
226                         sr_err("No name in driver %d ('%s').", i, d);
227                         errors++;
228                 }
229                 if (!drivers[i]->longname) {
230                         sr_err("No longname in driver %d ('%s').", i, d);
231                         errors++;
232                 }
233                 if (drivers[i]->api_version < 1) {
234                         sr_err("API version in driver %d ('%s') < 1.", i, d);
235                         errors++;
236                 }
237                 if (!drivers[i]->init) {
238                         sr_err("No init in driver %d ('%s').", i, d);
239                         errors++;
240                 }
241                 if (!drivers[i]->cleanup) {
242                         sr_err("No cleanup in driver %d ('%s').", i, d);
243                         errors++;
244                 }
245                 if (!drivers[i]->scan) {
246                         sr_err("No scan in driver %d ('%s').", i, d);
247                         errors++;
248                 }
249                 if (!drivers[i]->dev_list) {
250                         sr_err("No dev_list in driver %d ('%s').", i, d);
251                         errors++;
252                 }
253                 /* Note: config_get() is optional. */
254                 if (!drivers[i]->config_set) {
255                         sr_err("No config_set in driver %d ('%s').", i, d);
256                         errors++;
257                 }
258                 if (!drivers[i]->config_list) {
259                         sr_err("No config_list in driver %d ('%s').", i, d);
260                         errors++;
261                 }
262                 if (!drivers[i]->dev_open) {
263                         sr_err("No dev_open in driver %d ('%s').", i, d);
264                         errors++;
265                 }
266                 if (!drivers[i]->dev_close) {
267                         sr_err("No dev_close in driver %d ('%s').", i, d);
268                         errors++;
269                 }
270                 if (!drivers[i]->dev_acquisition_start) {
271                         sr_err("No dev_acquisition_start in driver %d ('%s').",
272                                i, d);
273                         errors++;
274                 }
275                 if (!drivers[i]->dev_acquisition_stop) {
276                         sr_err("No dev_acquisition_stop in driver %d ('%s').",
277                                i, d);
278                         errors++;
279                 }
280
281                 /* Note: 'priv' is allowed to be NULL. */
282
283                 if (errors == 0)
284                         continue;
285
286                 ret = SR_ERR;
287         }
288
289         return ret;
290 }
291
292 /**
293  * Sanity-check all libsigrok input modules.
294  *
295  * @retval SR_OK All modules are OK
296  * @retval SR_ERR One or more modules have issues.
297  */
298 static int sanity_check_all_input_modules(void)
299 {
300         int i, errors, ret = SR_OK;
301         const struct sr_input_module **inputs;
302         const char *d;
303
304         sr_spew("Sanity-checking all input modules.");
305
306         inputs = sr_input_list();
307         for (i = 0; inputs[i]; i++) {
308                 errors = 0;
309
310                 d = (inputs[i]->id) ? inputs[i]->id : "NULL";
311
312                 if (!inputs[i]->id) {
313                         sr_err("No ID in module %d ('%s').", i, d);
314                         errors++;
315                 }
316                 if (!inputs[i]->name) {
317                         sr_err("No name in module %d ('%s').", i, d);
318                         errors++;
319                 }
320                 if (!inputs[i]->desc) {
321                         sr_err("No description in module %d ('%s').", i, d);
322                         errors++;
323                 }
324                 if (!inputs[i]->init) {
325                         sr_err("No init in module %d ('%s').", i, d);
326                         errors++;
327                 }
328                 if (!inputs[i]->receive) {
329                         sr_err("No receive in module %d ('%s').", i, d);
330                         errors++;
331                 }
332                 if (!inputs[i]->end) {
333                         sr_err("No end in module %d ('%s').", i, d);
334                         errors++;
335                 }
336
337                 if (errors == 0)
338                         continue;
339
340                 ret = SR_ERR;
341         }
342
343         return ret;
344 }
345
346 /**
347  * Sanity-check all libsigrok output modules.
348  *
349  * @retval SR_OK All modules are OK
350  * @retval SR_ERR One or more modules have issues.
351  */
352 static int sanity_check_all_output_modules(void)
353 {
354         int i, errors, ret = SR_OK;
355         const struct sr_output_module **outputs;
356         const char *d;
357
358         sr_spew("Sanity-checking all output modules.");
359
360         outputs = sr_output_list();
361         for (i = 0; outputs[i]; i++) {
362                 errors = 0;
363
364                 d = (outputs[i]->id) ? outputs[i]->id : "NULL";
365
366                 if (!outputs[i]->id) {
367                         sr_err("No ID in module %d ('%s').", i, d);
368                         errors++;
369                 }
370                 if (!outputs[i]->name) {
371                         sr_err("No name in module %d ('%s').", i, d);
372                         errors++;
373                 }
374                 if (!outputs[i]->desc) {
375                         sr_err("No description in module '%s'.", d);
376                         errors++;
377                 }
378                 if (!outputs[i]->receive) {
379                         sr_err("No receive in module '%s'.", d);
380                         errors++;
381                 }
382
383                 if (errors == 0)
384                         continue;
385
386                 ret = SR_ERR;
387         }
388
389         return ret;
390 }
391
392 /**
393  * Sanity-check all libsigrok transform modules.
394  *
395  * @retval SR_OK All modules are OK
396  * @retval SR_ERR One or more modules have issues.
397  */
398 static int sanity_check_all_transform_modules(void)
399 {
400         int i, errors, ret = SR_OK;
401         const struct sr_transform_module **transforms;
402         const char *d;
403
404         sr_spew("Sanity-checking all transform modules.");
405
406         transforms = sr_transform_list();
407         for (i = 0; transforms[i]; i++) {
408                 errors = 0;
409
410                 d = (transforms[i]->id) ? transforms[i]->id : "NULL";
411
412                 if (!transforms[i]->id) {
413                         sr_err("No ID in module %d ('%s').", i, d);
414                         errors++;
415                 }
416                 if (!transforms[i]->name) {
417                         sr_err("No name in module %d ('%s').", i, d);
418                         errors++;
419                 }
420                 if (!transforms[i]->desc) {
421                         sr_err("No description in module '%s'.", d);
422                         errors++;
423                 }
424                 /* Note: options() is optional. */
425                 /* Note: init() is optional. */
426                 if (!transforms[i]->receive) {
427                         sr_err("No receive in module '%s'.", d);
428                         errors++;
429                 }
430                 /* Note: cleanup() is optional. */
431
432                 if (errors == 0)
433                         continue;
434
435                 ret = SR_ERR;
436         }
437
438         return ret;
439 }
440
441 /**
442  * Initialize libsigrok.
443  *
444  * This function must be called before any other libsigrok function.
445  *
446  * @param ctx Pointer to a libsigrok context struct pointer. Must not be NULL.
447  *            This will be a pointer to a newly allocated libsigrok context
448  *            object upon success, and is undefined upon errors.
449  *
450  * @return SR_OK upon success, a (negative) error code otherwise. Upon errors
451  *         the 'ctx' pointer is undefined and should not be used. Upon success,
452  *         the context will be free'd by sr_exit() as part of the libsigrok
453  *         shutdown.
454  *
455  * @since 0.2.0
456  */
457 SR_API int sr_init(struct sr_context **ctx)
458 {
459         int ret = SR_ERR;
460         struct sr_context *context;
461         struct sr_dev_driver ***lists, **drivers;
462         GArray *array;
463
464         print_versions();
465
466         if (!ctx) {
467                 sr_err("%s(): libsigrok context was NULL.", __func__);
468                 return SR_ERR;
469         }
470
471         context = g_malloc0(sizeof(struct sr_context));
472
473         /* Generate ctx->driver_list at runtime. */
474         array = g_array_new(TRUE, FALSE, sizeof(struct sr_dev_driver *));
475         for (lists = drivers_lists; *lists; lists++)
476                 for (drivers = *lists; *drivers; drivers++)
477                         g_array_append_val(array, *drivers);
478         context->driver_list = (struct sr_dev_driver **)array->data;
479         g_array_free(array, FALSE);
480
481         if (sanity_check_all_drivers(context) < 0) {
482                 sr_err("Internal driver error(s), aborting.");
483                 return ret;
484         }
485
486         if (sanity_check_all_input_modules() < 0) {
487                 sr_err("Internal input module error(s), aborting.");
488                 return ret;
489         }
490
491         if (sanity_check_all_output_modules() < 0) {
492                 sr_err("Internal output module error(s), aborting.");
493                 return ret;
494         }
495
496         if (sanity_check_all_transform_modules() < 0) {
497                 sr_err("Internal transform module error(s), aborting.");
498                 return ret;
499         }
500
501 #ifdef HAVE_LIBUSB_1_0
502         ret = libusb_init(&context->libusb_ctx);
503         if (LIBUSB_SUCCESS != ret) {
504                 sr_err("libusb_init() returned %s.", libusb_error_name(ret));
505                 ret = SR_ERR;
506                 goto done;
507         }
508 #endif
509
510         *ctx = context;
511         context = NULL;
512         ret = SR_OK;
513
514 #ifdef HAVE_LIBUSB_1_0
515 done:
516 #endif
517         g_free(context);
518         return ret;
519 }
520
521 /**
522  * Shutdown libsigrok.
523  *
524  * @param ctx Pointer to a libsigrok context struct. Must not be NULL.
525  *
526  * @retval SR_OK Success
527  * @retval other Error code SR_ERR, ...
528  *
529  * @since 0.2.0
530  */
531 SR_API int sr_exit(struct sr_context *ctx)
532 {
533         if (!ctx) {
534                 sr_err("%s(): libsigrok context was NULL.", __func__);
535                 return SR_ERR;
536         }
537
538         sr_hw_cleanup_all(ctx);
539
540 #ifdef HAVE_LIBUSB_1_0
541         libusb_exit(ctx->libusb_ctx);
542 #endif
543
544         g_free(sr_driver_list(ctx));
545         g_free(ctx);
546
547         return SR_OK;
548 }
549
550 /** @} */