backend.c 9.84 KB
Newer Older
1 2 3
/*
 * This file is part of the sigrok project.
 *
4
 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5
 * Copyright (C) 2012 Peter Stuge <peter@stuge.se>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <glib.h>
Uwe Hermann's avatar
Uwe Hermann committed
22
#include "config.h" /* Needed for HAVE_LIBUSB_1_0 and others. */
23 24
#include "libsigrok.h"
#include "libsigrok-internal.h"
25

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/**
 * @mainpage libsigrok API
 *
 * @section sec_intro Introduction
 *
 * The <a href="http://sigrok.org">sigrok</a> project aims at creating a
 * portable, cross-platform, Free/Libre/Open-Source signal analysis software
 * suite that supports various device types (such as logic analyzers,
 * oscilloscopes, multimeters, and more).
 *
 * <a href="http://sigrok.org/wiki/Libsigrok">libsigrok</a> is a shared
 * library written in C which provides the basic API for talking to
 * <a href="http://sigrok.org/wiki/Supported_hardware">supported hardware</a>
 * and reading/writing the acquired data into various
 * <a href="http://sigrok.org/wiki/Input_output_formats">input/output
 * file formats</a>.
 *
43
 * @section sec_api API reference
44
 *
45 46 47 48 49 50
 * See the "Modules" page for an introduction to various libsigrok
 * related topics and the detailed API documentation of the respective
 * functions.
 *
 * You can also browse the API documentation by file, or review all
 * data structures.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
 *
 * @section sec_mailinglists Mailing lists
 *
 * There are two mailing lists for sigrok/libsigrok: <a href="https://lists.sourceforge.net/lists/listinfo/sigrok-devel">sigrok-devel</a> and <a href="https://lists.sourceforge.net/lists/listinfo/sigrok-commits">sigrok-commits</a>.
 *
 * @section sec_irc IRC
 *
 * You can find the sigrok developers in the
 * <a href="irc://chat.freenode.net/sigrok">\#sigrok</a>
 * IRC channel on Freenode.
 *
 * @section sec_website Website
 *
 * <a href="http://sigrok.org/wiki/Libsigrok">sigrok.org/wiki/Libsigrok</a>
 */

67 68 69 70 71 72
/**
 * @file
 *
 * Initializing and shutting down libsigrok.
 */

73 74 75 76 77
/**
 * @defgroup grp_init Initialization
 *
 * Initializing and shutting down libsigrok.
 *
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
 * Before using any of the libsigrok functionality, sr_init() must
 * be called to initialize the library, which will return a struct sr_context
 * when the initialization was successful.
 *
 * When libsigrok functionality is no longer needed, sr_exit() should be
 * called, which will (among other things) free the struct sr_context.
 *
 * Example for a minimal program using libsigrok:
 *
 * @code{.c}
 *   #include <stdio.h>
 *   #include <libsigrok/libsigrok.h>
 *
 *   int main(int argc, char **argv)
 *   {
 *   	int ret;
 *   	struct sr_context *sr_ctx;
 *
 *   	if ((ret = sr_init(&sr_ctx)) != SR_OK) {
 *   		printf("Error initializing libsigrok (%s): %s.",
 *   		       sr_strerror_name(ret), sr_strerror(ret));
 *   		return 1;
 *   	}
 *
 *   	// Use libsigrok functions here...
 *
 *   	if ((ret = sr_exit(sr_ctx)) != SR_OK) {
 *   		printf("Error shutting down libsigrok (%s): %s.",
 *   		       sr_strerror_name(ret), sr_strerror(ret));
 *   		return 1;
 *   	}
 *
 *   	return 0;
 *   }
 * @endcode
 *
114 115 116
 * @{
 */

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
/**
 * Sanity-check all libsigrok drivers.
 *
 * @return SR_OK if all drivers are OK, SR_ERR if one or more have issues.
 */
static int sanity_check_all_drivers(void)
{
	int i, errors, ret = SR_OK;
	struct sr_dev_driver **drivers;
	const char *d;

	sr_spew("Sanity-checking all drivers.");

	drivers = sr_driver_list();
	for (i = 0; drivers[i]; i++) {
		errors = 0;

		d = (drivers[i]->name) ? drivers[i]->name : "NULL";

		if (!drivers[i]->name) {
			sr_err("No name in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->longname) {
			sr_err("No longname in driver %d ('%s').", i, d);
			errors++;
		}
		if (drivers[i]->api_version < 1) {
			sr_err("API version in driver %d ('%s') < 1.", i, d);
			errors++;
		}
		if (!drivers[i]->init) {
			sr_err("No init in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->cleanup) {
			sr_err("No cleanup in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->scan) {
			sr_err("No scan in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->dev_list) {
			sr_err("No dev_list in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->dev_clear) {
			sr_err("No dev_clear in driver %d ('%s').", i, d);
			errors++;
		}
Uwe Hermann's avatar
Uwe Hermann committed
168 169 170 171 172 173 174 175 176
		/* Note: config_get() is optional. */
		if (!drivers[i]->config_set) {
			sr_err("No config_set in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->config_list) {
			sr_err("No config_list in driver %d ('%s').", i, d);
			errors++;
		}
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
		if (!drivers[i]->dev_open) {
			sr_err("No dev_open in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->dev_close) {
			sr_err("No dev_close in driver %d ('%s').", i, d);
			errors++;
		}
		if (!drivers[i]->dev_acquisition_start) {
			sr_err("No dev_acquisition_start in driver %d ('%s').",
			       i, d);
			errors++;
		}
		if (!drivers[i]->dev_acquisition_stop) {
			sr_err("No dev_acquisition_stop in driver %d ('%s').",
			       i, d);
			errors++;
		}

		/* Note: 'priv' is allowed to be NULL. */

		if (errors == 0)
			continue;

		ret = SR_ERR;
	}

	return ret;
}

207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
/**
 * Sanity-check all libsigrok input modules.
 *
 * @return SR_OK if all modules are OK, SR_ERR if one or more have issues.
 */
static int sanity_check_all_input_modules(void)
{
	int i, errors, ret = SR_OK;
	struct sr_input_format **inputs;
	const char *d;

	sr_spew("Sanity-checking all input modules.");

	inputs = sr_input_list();
	for (i = 0; inputs[i]; i++) {
		errors = 0;

		d = (inputs[i]->id) ? inputs[i]->id : "NULL";

		if (!inputs[i]->id) {
			sr_err("No ID in module %d ('%s').", i, d);
			errors++;
		}
		if (!inputs[i]->description) {
			sr_err("No description in module %d ('%s').", i, d);
			errors++;
		}
		if (!inputs[i]->format_match) {
			sr_err("No format_match in module %d ('%s').", i, d);
			errors++;
		}
		if (!inputs[i]->init) {
			sr_err("No init in module %d ('%s').", i, d);
			errors++;
		}
		if (!inputs[i]->loadfile) {
			sr_err("No loadfile in module %d ('%s').", i, d);
			errors++;
		}

		if (errors == 0)
			continue;

		ret = SR_ERR;
	}

	return ret;
}

/**
 * Sanity-check all libsigrok output modules.
 *
 * @return SR_OK if all modules are OK, SR_ERR if one or more have issues.
 */
static int sanity_check_all_output_modules(void)
{
	int i, errors, ret = SR_OK;
	struct sr_output_format **outputs;
	const char *d;

	sr_spew("Sanity-checking all output modules.");

	outputs = sr_output_list();
	for (i = 0; outputs[i]; i++) {
		errors = 0;

		d = (outputs[i]->id) ? outputs[i]->id : "NULL";

		if (!outputs[i]->id) {
			sr_err("No ID in module %d ('%s').", i, d);
			errors++;
		}
		if (!outputs[i]->description) {
			sr_err("No description in module %d ('%s').", i, d);
			errors++;
		}
		if (outputs[i]->df_type < 10000 || outputs[i]->df_type > 10007) {
			sr_err("Invalid df_type %d in module %d ('%s').",
			       outputs[i]->df_type, i, d);
			errors++;
		}

		/* All modules must provide a data or recv API callback. */
		if (!outputs[i]->data && !outputs[i]->recv) {
			sr_err("No data/recv in module %d ('%s').", i, d);
			errors++;
		}

		/*
		 * Currently most API calls are optional (their function
		 * pointers can thus be NULL) in theory: init, event, cleanup.
		 */

		if (errors == 0)
			continue;

		ret = SR_ERR;
	}

	return ret;
}

309 310 311
/**
 * Initialize libsigrok.
 *
312 313 314 315 316 317 318 319 320 321
 * This function must be called before any other libsigrok function.
 *
 * @param ctx Pointer to a libsigrok context struct pointer. Must not be NULL.
 *            This will be a pointer to a newly allocated libsigrok context
 *            object upon success, and is undefined upon errors.
 *
 * @return SR_OK upon success, a (negative) error code otherwise. Upon errors
 *         the 'ctx' pointer is undefined and should not be used. Upon success,
 *         the context will be free'd by sr_exit() as part of the libsigrok
 *         shutdown.
322 323
 *
 * @since 0.1.0 (but the API changed in 0.2.0)
324
 */
325
SR_API int sr_init(struct sr_context **ctx)
326
{
327 328 329
	int ret = SR_ERR;
	struct sr_context *context;

330 331 332 333 334
	if (!ctx) {
		sr_err("%s(): libsigrok context was NULL.", __func__);
		return SR_ERR;
	}

335 336 337 338 339
	if (sanity_check_all_drivers() < 0) {
		sr_err("Internal driver error(s), aborting.");
		return ret;
	}

340 341 342 343 344 345 346 347 348 349
	if (sanity_check_all_input_modules() < 0) {
		sr_err("Internal input module error(s), aborting.");
		return ret;
	}

	if (sanity_check_all_output_modules() < 0) {
		sr_err("Internal output module error(s), aborting.");
		return ret;
	}

350 351 352 353 354 355 356 357
	/* + 1 to handle when struct sr_context has no members. */
	context = g_try_malloc0(sizeof(struct sr_context) + 1);

	if (!context) {
		ret = SR_ERR_MALLOC;
		goto done;
	}

358 359
#ifdef HAVE_LIBUSB_1_0
	ret = libusb_init(&context->libusb_ctx);
360
	if (LIBUSB_SUCCESS != ret) {
361
		sr_err("libusb_init() returned %s.\n", libusb_error_name(ret));
362
		ret = SR_ERR;
363 364 365 366
		goto done;
	}
#endif

367
	*ctx = context;
368
	context = NULL;
369 370 371
	ret = SR_OK;

done:
372 373
	if (context)
		g_free(context);
374
	return ret;
375 376
}

377 378 379
/**
 * Shutdown libsigrok.
 *
380 381
 * @param ctx Pointer to a libsigrok context struct. Must not be NULL.
 *
382
 * @return SR_OK upon success, a (negative) error code otherwise.
383 384
 *
 * @since 0.1.0 (but the API changed in 0.2.0)
385
 */
386
SR_API int sr_exit(struct sr_context *ctx)
387
{
388 389 390 391 392
	if (!ctx) {
		sr_err("%s(): libsigrok context was NULL.", __func__);
		return SR_ERR;
	}

393
	sr_hw_cleanup_all();
394

395 396 397 398
#ifdef HAVE_LIBUSB_1_0
	libusb_exit(ctx->libusb_ctx);
#endif

399 400
	g_free(ctx);

401
	return SR_OK;
402
}
403 404

/** @} */