From 6622f386f52807dac76c8a260c98aa02c311bc93 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sat, 20 Nov 2021 14:34:38 -0700 Subject: core: Add libusb_init_context() setting options at context creation The new initialization function addresses some shortcomings of the libusb_set_option() interface. Namely, it allows setting the no-enumeration option (and others) on only the contexts where it is requested. The old initialization function (libusb_init()) is deprecated and will be removed in a future release. For now it translates to a call to libusb_init_context() with no options specified. Closes #1026 Signed-off-by: Nathan Hjelm [Tormod: Doxygen description of libusb_init_option structure] Signed-off-by: Tormod Volden --- libusb/core.c | 92 ++++++++++++++++++++++------------ libusb/libusb-1.0.def | 2 + libusb/libusb.h | 136 ++++++++++++++++++++++++++++---------------------- libusb/version_nano.h | 2 +- 4 files changed, 139 insertions(+), 93 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 634002b..497c7f6 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ /* * Core functions for libusb - * Copyright © 2012-2013 Nathan Hjelm + * Copyright © 2012-2021 Nathan Hjelm * Copyright © 2007-2008 Daniel Drake * Copyright © 2001 Johannes Erdfelt * @@ -111,17 +111,18 @@ struct list_head active_contexts_list; * libusb uses stderr for all logging. By default, logging is set to NONE, * which means that no output will be produced. However, unless the library * has been compiled with logging disabled, then any application calls to - * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or the setting of the - * environmental variable LIBUSB_DEBUG outside of the application, can result - * in logging being produced. Your application should therefore not close - * stderr, but instead direct it to the null device if its output is - * undesirable. - * - * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) function can be - * used to enable logging of certain messages. Under standard configuration, - * libusb doesn't really log much so you are advised to use this function - * to enable all error/warning/ informational messages. It will help debug - * problems with your software. + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), + * libusb_init_context, or the setting of the environmental variable + * LIBUSB_DEBUG outside of the application, can result in logging being + * produced. Your application should therefore not close stderr, but instead + * direct it to the null device if its output is undesirable. + * + * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) or + * libusb_init_context functions can be used to enable logging of certain + * messages. With the default configuration, libusb will not log much so if + * you are advised to use one of these functions to enable all + * error/warning/informational messages. It will help debug problems with your + * software. * * The logged messages are unstructured. There is no one-to-one correspondence * between messages being logged and success or failure return codes from @@ -137,19 +138,19 @@ struct list_head active_contexts_list; * The LIBUSB_DEBUG environment variable can be used to enable message logging * at run-time. This environment variable should be set to a log level number, * which is interpreted the same as the - * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) parameter. When this - * environment variable is set, the message logging verbosity level is fixed - * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) effectively does - * nothing. + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or + * libusb_init_context(&ctx, &(struct libusb_init_option){.option = LIBUSB_OPTION_LOG_LEVEL, .value = {.ival = level}}, 0). + * When the environment variable is set, the message logging verbosity level is + * fixed and setting the LIBUSB_OPTION_LOG_LEVEL option has no effect. * * libusb can be compiled without any logging functions, useful for embedded - * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) - * and the LIBUSB_DEBUG environment variable have no effects. + * systems. In this case, neither the LIBUSB_OPTION_LOG_LEVEL option, nor the + * LIBUSB_DEBUG environment variable will have any effect. * * libusb can also be compiled with verbose debugging messages always. When * the library is compiled in this way, all messages of all verbosities are - * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) and - * the LIBUSB_DEBUG environment variable have no effects. + * always logged. Again, in this case, neither the LIBUSB_OPTION_LOG_LEVEL + * option, nor the LIBUSB_DEBUG environment variable will have any effect. * * \section remarks Other remarks * @@ -327,9 +328,9 @@ if (cfg != desired) * developed modules may both use libusb. * * libusb is written to allow for these multiple user scenarios. The two - * "instances" of libusb will not interfere: libusb_set_option() calls - * from one user will not affect the same settings for other users, other - * users can continue using libusb after one of them calls libusb_exit(), etc. + * "instances" of libusb will not interfere: an option set by one user will have + * no effect the same option for other users, other users can continue using + * libusb after one of them calls libusb_exit(), etc. * * This is made possible through libusb's context concept. When you * call libusb_init(), you are (optionally) given a context. You can then pass @@ -436,6 +437,7 @@ if (cfg != desired) * - libusb_hotplug_deregister_callback() * - libusb_hotplug_register_callback() * - libusb_init() + * - libusb_init_context() * - libusb_interrupt_event_handler() * - libusb_interrupt_transfer() * - libusb_kernel_driver_active() @@ -1209,11 +1211,10 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev) * handle for the underlying device. The handle allows you to use libusb to * perform I/O on the device in question. * - * Call libusb_set_option() with the parameters (NULL, - * \ref LIBUSB_OPTION_NO_DEVICE_DISCOVERY) before libusb_init() if you want - * to skip enumeration of USB devices. In particular, this might be - * needed on Android if you don't have authority to access USB devices - * in general. + * Call libusb_init_context with the LIBUSB_OPTION_NO_DEVICE_DISCOVERY + * option if you want to skip enumeration of USB devices. In particular, this + * might be needed on Android if you don't have authority to access USB + * devices in general. Setting this option with libusb_set_option is deprecated. * * On Linux, the system device handle must be a valid file descriptor opened * on the device node. @@ -2098,8 +2099,8 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( } /** \ingroup libusb_lib - * \deprecated Use libusb_set_option() instead using the - * \ref LIBUSB_OPTION_LOG_LEVEL option. + * \deprecated Use libusb_set_option() or libusb_init_context() instead + * using the \ref LIBUSB_OPTION_LOG_LEVEL option. */ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) { @@ -2271,7 +2272,8 @@ static enum libusb_log_level get_env_debug_level(void) * * If you do not provide an output location for a context pointer, a default * context will be created. If there was already a default context, it will - * be reused (and nothing will be initialized/reinitialized). + * be reused (and nothing will be initialized/reinitialized). Deprecated in + * favor of \ref libusb_init_context(). * * \param ctx Optional output location for context pointer. * Only valid on return code 0. @@ -2279,6 +2281,27 @@ static enum libusb_log_level get_env_debug_level(void) * \see libusb_contexts */ int API_EXPORTED libusb_init(libusb_context **ctx) +{ + return libusb_init_context(ctx, NULL, 0); +} + +/** \ingroup libusb_lib + * Initialize libusb. This function must be called before calling any other + * libusb function. + * + * If you do not provide an output location for a context pointer, a default + * context will be created. If there was already a default context, it will + * be reused (and nothing will be initialized/reinitialized and options will + * be ignored). If num_options is 0 then options is ignored and may be NULL. + * + * \param ctx Optional output location for context pointer. + * Only valid on return code 0. + * \param options Optional array of options to set on the new context. + * \param num_options Number of elements in the options array. + * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \see libusb_contexts + */ +int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options) { size_t priv_size = usbi_backend.context_priv_size; struct libusb_context *_ctx; @@ -2330,6 +2353,13 @@ int API_EXPORTED libusb_init(libusb_context **ctx) goto err_free_ctx; } + /* apply any options provided by the user */ + for (int i = 0 ; i < num_options ; ++i) { + r = libusb_set_option(_ctx, options[i].option, options[i].value.ival); + if (LIBUSB_SUCCESS != r) + goto err_free_ctx; + } + /* default context must be initialized before calling usbi_dbg */ if (!ctx) { usbi_default_context = _ctx; diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index a12a05d..0d41330 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -132,6 +132,8 @@ EXPORTS libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback libusb_init libusb_init@4 = libusb_init + libusb_init_context + libusb_init_context@12 = libusb_init_context libusb_interrupt_event_handler libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler libusb_interrupt_transfer diff --git a/libusb/libusb.h b/libusb/libusb.h index f7b0e19..a865bc8 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -3,7 +3,7 @@ * Copyright © 2001 Johannes Erdfelt * Copyright © 2007-2008 Daniel Drake * Copyright © 2012 Pete Batard - * Copyright © 2012-2018 Nathan Hjelm + * Copyright © 2012-2021 Nathan Hjelm * Copyright © 2014-2020 Chris Dickens * For more information, please visit: http://libusb.info * @@ -1445,6 +1445,78 @@ enum libusb_log_cb_mode { LIBUSB_LOG_CB_CONTEXT = (1 << 1) }; +/** \ingroup libusb_lib + * Available option values for libusb_set_option() and libusb_init_context(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL = 0, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling libusb_init(), or set at + * initialization with libusb_init_context() otherwise unspecified behavior + * may occur. + * + * Only valid on Windows. Ignored on all other platforms. + */ + LIBUSB_OPTION_USE_USBDK = 1, + + /** Do not scan for devices + * + * With this option set, libusb will skip scanning devices in + * libusb_init_context(). + * + * Hotplug functionality will also be deactivated. + * + * The option is useful in combination with libusb_wrap_sys_device(), + * which can access a device directly without prior device scanning. + * + * This is typically needed on Android, where access to USB devices + * is limited. + * + * Only valid on Linux. Ignored on all other platforms. + */ + LIBUSB_OPTION_NO_DEVICE_DISCOVERY = 2, + +#define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY + + LIBUSB_OPTION_MAX = 3 +}; + +/** \ingroup libusb_lib + * Structure used for setting options through \ref libusb_init_context. + * + */ +struct libusb_init_option { + /** Which option to set */ + enum libusb_option option; + /** An integer value used by the option (if applicable). */ + union { + int64_t ival; + } value; +}; + /** \ingroup libusb_lib * Callback function for handling log messages. * \param ctx the context which is related to the log message, or NULL if it @@ -1459,7 +1531,9 @@ enum libusb_log_cb_mode { typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, enum libusb_log_level level, const char *str); +LIBUSB_DEPRECATED_FOR(libusb_init_context) int LIBUSB_CALL libusb_init(libusb_context **ctx); +int LIBUSB_CALL libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options); void LIBUSB_CALL libusb_exit(libusb_context *ctx); LIBUSB_DEPRECATED_FOR(libusb_set_option) void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); @@ -2181,66 +2255,6 @@ void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, void * LIBUSB_CALL libusb_hotplug_get_user_data(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle); -/** \ingroup libusb_lib - * Available option values for libusb_set_option(). - */ -enum libusb_option { - /** Set the log message verbosity. - * - * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever - * printed. If you choose to increase the message verbosity level, ensure - * that your application does not close the stderr file descriptor. - * - * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative - * with its message logging and most of the time, will only log messages that - * explain error conditions and other oddities. This will help you debug - * your software. - * - * If the LIBUSB_DEBUG environment variable was set when libusb was - * initialized, this function does nothing: the message verbosity is fixed - * to the value in the environment variable. - * - * If libusb was compiled without any message logging, this function does - * nothing: you'll never get any messages. - * - * If libusb was compiled with verbose debug message logging, this function - * does nothing: you'll always get messages from all levels. - */ - LIBUSB_OPTION_LOG_LEVEL = 0, - - /** Use the UsbDk backend for a specific context, if available. - * - * This option should be set immediately after calling libusb_init(), otherwise - * unspecified behavior may occur. - * - * Only valid on Windows. - */ - LIBUSB_OPTION_USE_USBDK = 1, - - /** Do not scan for devices - * - * With this option set, libusb will skip scanning devices in - * libusb_init(). Must be set before calling libusb_init(). - * - * Hotplug functionality will also be deactivated. - * - * The option is useful in combination with libusb_wrap_sys_device(), - * which can access a device directly without prior device scanning. - * - * This is typically needed on Android, where access to USB devices - * is limited. - * - * For LIBUSB_API_VERSION 0x01000108 it was called LIBUSB_OPTION_WEAK_AUTHORITY - * - * Only valid on Linux. - */ - LIBUSB_OPTION_NO_DEVICE_DISCOVERY = 2, - -#define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY - - LIBUSB_OPTION_MAX = 3 -}; - int LIBUSB_CALLV libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); #ifdef _MSC_VER diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9eac25d..13076b2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11767 +#define LIBUSB_NANO 11768 -- cgit v1.2.1