Discussion:
[libusb] [PATCH] core: Introduce libusb_set_option() API function
Chris Dickens
2017-07-11 05:51:57 UTC
Permalink
This new function allows more flexibility in extending the library to
support more user-configurable options. It is intended to provide a
single API that can support a wide variety of needs and eliminates the
need for new API functions to set future options.

The function is introduced with a single option (LIBUSB_OPTION_LOG_LEVEL)
that replaces the libusb_set_debug() function. Documentation relating to
libusb_set_debug() and the uses of this function in the examples and
tests have been updated accordingly.

Signed-off-by: Chris Dickens <***@gmail.com>
---
examples/fxload.c | 2 +-
examples/xusb.c | 4 +-
libusb/core.c | 105 +++++++++++++++++++++++++++++++-------------------
libusb/libusb-1.0.def | 2 +
libusb/libusb.h | 49 ++++++++++++++++++-----
libusb/version_nano.h | 2 +-
tests/stress.c | 4 +-
7 files changed, 113 insertions(+), 55 deletions(-)

diff --git a/examples/fxload.c b/examples/fxload.c
index 5aa5226..1cea9c3 100644
--- a/examples/fxload.c
+++ b/examples/fxload.c
@@ -178,7 +178,7 @@ int main(int argc, char*argv[])
logerror("libusb_init() failed: %s\n", libusb_error_name(status));
return -1;
}
- libusb_set_debug(NULL, verbose);
+ libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, verbose);

/* try to pick up missing parameters from known devices */
if ((type == NULL) || (device_id == NULL) || (device_path != NULL)) {
diff --git a/examples/xusb.c b/examples/xusb.c
index 352a5d7..b2e2424 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -1095,7 +1095,7 @@ int main(int argc, char** argv)
}

// xusb is commonly used as a debug tool, so it's convenient to have debug output during libusb_init(),
- // but since we can't call on libusb_set_debug() before libusb_init(), we use the env variable method
+ // but since we can't call on libusb_set_option() before libusb_init(), we use the env variable method
old_dbg_str = getenv("LIBUSB_DEBUG");
if (debug_mode) {
if (putenv("LIBUSB_DEBUG=4") != 0) // LIBUSB_LOG_LEVEL_DEBUG
@@ -1110,7 +1110,7 @@ int main(int argc, char** argv)

// If not set externally, and no debug option was given, use info log level
if ((old_dbg_str == NULL) && (!debug_mode))
- libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_INFO);
+ libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
if (error_lang != NULL) {
r = libusb_setlocale(error_lang);
if (r < 0)
diff --git a/libusb/core.c b/libusb/core.c
index f842fe9..ef526dc 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -116,15 +116,17 @@ 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_debug(), 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_debug() 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), 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) 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.
*
* The logged messages are unstructured. There is no one-to-one correspondence
* between messages being logged and success or failure return codes from
@@ -139,18 +141,20 @@ 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_debug() parameter. When this
+ * which is interpreted the same as the
+ * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL) parameter. When this
* environment variable is set, the message logging verbosity level is fixed
- * and libusb_set_debug() effectively does nothing.
+ * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL) effectively does
+ * nothing.
*
* libusb can be compiled without any logging functions, useful for embedded
- * systems. In this case, libusb_set_debug() and the LIBUSB_DEBUG environment
- * variable have no effects.
+ * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL) and
+ * the LIBUSB_DEBUG environment variable have no effects.
*
* 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_debug() and the LIBUSB_DEBUG environment variable
- * have no effects.
+ * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL) and the
+ * LIBUSB_DEBUG environment variable have no effects.
*
* \section remarks Other remarks
*
@@ -297,7 +301,7 @@ 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_debug() calls
+ * "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.
*
@@ -422,6 +426,7 @@ if (cfg != desired)
* - libusb_set_debug()
* - libusb_set_interface_alt_setting()
* - libusb_set_iso_packet_lengths()
+ * - libusb_set_option()
* - libusb_setlocale()
* - libusb_set_pollfd_notifiers()
* - libusb_strerror()
@@ -465,6 +470,7 @@ if (cfg != desired)
* - \ref libusb_iso_sync_type
* - \ref libusb_iso_usage_type
* - \ref libusb_log_level
+ * - \ref libusb_option
* - \ref libusb_request_recipient
* - \ref libusb_request_type
* - \ref libusb_speed
@@ -2002,29 +2008,8 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver(
}

/** \ingroup libusb_lib
- * Set 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 stdout/stderr file descriptors.
- *
- * 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.
- *
- * \param ctx the context to operate on, or NULL for the default context
- * \param level debug level to set
+ * \deprecated Use libusb_set_option() instead using the
+ * \ref LIBUSB_OPTION_LOG_LEVEL option.
*/
void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level)
{
@@ -2039,6 +2024,48 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level)
}

/** \ingroup libusb_lib
+ * Set an option in the library.
+ *
+ * Use this function to configure a specific option within the library.
+ *
+ * Some options require one or more arguments to be provided. Consult each
+ * option's documentation for specific requirements.
+ *
+ * Since version 1.0.22, \ref LIBUSB_API_VERSION >= 0x01000106
+ *
+ * \param ctx context on which to operate
+ * \param option which option to set
+ * \param ... any required arguments for the specified option
+ *
+ * \returns LIBUSB_SUCCESS on success
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid
+ * \returns LIBUSB_ERROR_NOT_SUPPORTED if the option is not supported
+ */
+int API_EXPORTED libusb_set_option(libusb_context *ctx,
+ enum libusb_option option, ...)
+{
+ int r = LIBUSB_SUCCESS;
+ va_list ap;
+
+ USBI_GET_CONTEXT(ctx);
+
+ va_start(ap, option);
+ switch (option) {
+ case LIBUSB_OPTION_LOG_LEVEL:
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+ if (!ctx->debug_fixed)
+ ctx->debug = va_arg(ap, int);
+#endif
+ break;
+ default:
+ r = LIBUSB_ERROR_INVALID_PARAM;
+ }
+ va_end(ap);
+
+ return r;
+}
+
+/** \ingroup libusb_lib
* Initialize libusb. This function must be called before calling any other
* libusb function.
*
diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def
index 2443d9b..92c26d4 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -152,6 +152,8 @@ EXPORTS
***@12 = libusb_set_interface_alt_setting
libusb_setlocale
***@4 = libusb_setlocale
+ libusb_set_option
+ ***@8 = libusb_set_option
libusb_set_pollfd_notifiers
***@16 = libusb_set_pollfd_notifiers
libusb_strerror
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 70ee2ca..480a5ad 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -147,7 +147,7 @@ typedef unsigned __int32 uint32_t;
* Internally, LIBUSB_API_VERSION is defined as follows:
* (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
*/
-#define LIBUSB_API_VERSION 0x01000105
+#define LIBUSB_API_VERSION 0x01000106

/* The following is kept for compatibility, but will be deprecated in the future */
#define LIBUSBX_API_VERSION LIBUSB_API_VERSION
@@ -921,7 +921,7 @@ struct libusb_version {
* sessions allows for your program to use two libraries (or dynamically
* load two modules) which both independently use libusb. This will prevent
* interference between the individual libusb users - for example
- * libusb_set_debug() will not affect the other user of the library, and
+ * libusb_set_option() will not affect the other user of the library, and
* libusb_exit() will not destroy resources that the other user is still
* using.
*
@@ -1278,21 +1278,20 @@ enum libusb_capability {
* - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default)
* - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr
* - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr
- * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning
- * and error messages are printed to stderr
- * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout,
- * warnings and errors to stderr
+ * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr
+ * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr
*/
enum libusb_log_level {
LIBUSB_LOG_LEVEL_NONE = 0,
- LIBUSB_LOG_LEVEL_ERROR,
- LIBUSB_LOG_LEVEL_WARNING,
- LIBUSB_LOG_LEVEL_INFO,
- LIBUSB_LOG_LEVEL_DEBUG,
+ LIBUSB_LOG_LEVEL_ERROR = 1,
+ LIBUSB_LOG_LEVEL_WARNING = 2,
+ LIBUSB_LOG_LEVEL_INFO = 3,
+ LIBUSB_LOG_LEVEL_DEBUG = 4,
};

int LIBUSB_CALL libusb_init(libusb_context **ctx);
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);
const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
int LIBUSB_CALL libusb_has_capability(uint32_t capability);
@@ -1989,6 +1988,36 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,
void LIBUSB_CALL libusb_hotplug_deregister_callback(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,
+};
+
+int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...);
+
#ifdef __cplusplus
}
#endif
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 1862589..e245291 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11208
+#define LIBUSB_NANO 11209
diff --git a/tests/stress.c b/tests/stress.c
index 0f50003..0e2dbe5 100644
--- a/tests/stress.c
+++ b/tests/stress.c
@@ -126,8 +126,8 @@ static libusb_testlib_result test_default_context_change(libusb_testlib_ctx * tc
}

/* Enable debug output, to be sure to use the context */
- libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG);
- libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_DEBUG);
+ libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
+ libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);

/* Now create a reference to the default context */
r = libusb_init(NULL);
--
2.11.0
Loading...