diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h --- a/lib/libusb/libusb.h +++ b/lib/libusb/libusb.h @@ -243,17 +243,6 @@ LIBUSB_LOG_LEVEL_DEBUG }; -/* XXX */ -/* libusb_set_debug should take parameters from libusb_log_level - * above according to - * https://libusb.sourceforge.io/api-1.0/group__libusb__lib.html - */ -enum libusb_debug_level { - LIBUSB_DEBUG_NO=0, - LIBUSB_DEBUG_FUNCTION=1, - LIBUSB_DEBUG_TRANSFER=2, -}; - #define LIBUSB_HOTPLUG_MATCH_ANY -1 typedef enum { @@ -271,7 +260,8 @@ LIBUSB_OPTION_USE_USBDK = 1, LIBUSB_OPTION_NO_DEVICE_DISCOVERY = 2, LIBUSB_OPTION_WEAK_AUTHORITY = 2, - LIBUSB_OPTION_MAX = 3, + LIBUSB_OPTION_LOG_CB = 5, + LIBUSB_OPTION_MAX = 4, }; /* libusb structures */ @@ -282,6 +272,11 @@ struct libusb_device_handle; struct libusb_hotplug_callback_handle_struct; +typedef struct libusb_context libusb_context; + +typedef void (*libusb_log_cb)(libusb_context *ctx, enum libusb_log_level, + const char *str); + struct libusb_pollfd { int fd; short events; @@ -604,6 +599,7 @@ int libusb_free_streams(libusb_device_handle *dev, unsigned char *endpoints, int num_endpoints); void libusb_transfer_set_stream_id(struct libusb_transfer *transfer, uint32_t stream_id); uint32_t libusb_transfer_get_stream_id(struct libusb_transfer *transfer); +int libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); #if 0 { /* indent fix */ diff --git a/lib/libusb/libusb10.h b/lib/libusb/libusb10.h --- a/lib/libusb/libusb10.h +++ b/lib/libusb/libusb10.h @@ -44,26 +44,13 @@ #define CTX_TRYLOCK(ctx) pthread_mutex_trylock(&(ctx)->ctx_lock) #define CTX_UNLOCK(ctx) pthread_mutex_unlock(&(ctx)->ctx_lock) #define HOTPLUG_LOCK(ctx) pthread_mutex_lock(&(ctx)->hotplug_lock) -#define HOTPLUG_UNLOCK(ctx) pthread_mutex_unlock(&(ctx)->hotplug_lock) - -#define DPRINTF(ctx, dbg, format, ...) do { \ - switch (dbg) { \ - case LIBUSB_DEBUG_FUNCTION: \ - if ((ctx)->debug & LIBUSB_DEBUG_FUNCTION) { \ - printf("LIBUSB_FUNCTION: " \ - format "\n", ## __VA_ARGS__); \ - } \ - break; \ - case LIBUSB_DEBUG_TRANSFER: \ - if ((ctx)->debug & LIBUSB_DEBUG_TRANSFER) { \ - printf("LIBUSB_TRANSFER: " \ - format "\n", ## __VA_ARGS__); \ - } \ - break; \ - default: \ - break; \ - } \ -} while (0) +#define HOTPLUG_UNLOCK(ctx) pthread_mutex_unlock(&(ctx)->hotplug_lock) + +void libusb_log_va_args(struct libusb_context *ctx, enum libusb_log_level level, + const char *fmt, ...); + +#define DPRINTF(ctx, dbg, format, ...) \ + libusb_log_va_args(ctx, dbg, format, ##__VA_ARGS__); /* internal structures */ @@ -130,6 +117,9 @@ libusb_pollfd_added_cb fd_added_cb; libusb_pollfd_removed_cb fd_removed_cb; void *fd_cb_user_data; + libusb_log_cb log_cb; + enum libusb_log_level log_level; + int no_discovery; }; struct libusb_device { diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c --- a/lib/libusb/libusb10.c +++ b/lib/libusb/libusb10.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -54,13 +55,12 @@ #include "libusb.h" #include "libusb10.h" -#define LIBUSB_NUM_SW_ENDPOINTS (16 * 4) +#define LIBUSB_NUM_SW_ENDPOINTS (16 * 4) static pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER; struct libusb_context *usbi_default_context = NULL; /* Prototypes */ - static struct libusb20_transfer *libusb10_get_transfer(struct libusb20_device *, uint8_t, uint8_t); static int libusb10_get_buffsize(struct libusb20_device *, libusb_transfer *); static int libusb10_convert_error(uint8_t status); @@ -127,7 +127,7 @@ err = eventfd_write(ctx->event, 1); if (err < 0) { /* ignore error, if any */ - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "Waking up event loop failed!"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_ERROR, "Waking up event loop failed!"); } } @@ -242,6 +242,9 @@ } libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->event, POLLIN); + ctx->log_level = -1; + ctx->log_cb = NULL; + ctx->no_discovery = false; pthread_mutex_lock(&default_context_lock); if (usbi_default_context == NULL) { @@ -252,7 +255,7 @@ if (context) *context = ctx; - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_INFO, "libusb_init complete"); signal(SIGPIPE, SIG_IGN); @@ -601,7 +604,7 @@ if (ctx == NULL) return (NULL); /* be NULL safe */ - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_open_device_with_vid_pid enter"); if ((i = libusb_get_device_list(ctx, &devs)) < 0) return (NULL); @@ -625,7 +628,7 @@ } libusb_free_device_list(devs, 1); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid leave"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_open_device_with_vid_pid leave"); return (pdev); } @@ -1506,7 +1509,7 @@ dev = libusb_get_device(uxfer->dev_handle); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_submit_transfer enter"); sxfer = (struct libusb_super_transfer *)( (uint8_t *)uxfer - sizeof(*sxfer)); @@ -1541,7 +1544,7 @@ CTX_UNLOCK(dev->ctx); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_submit_transfer leave %d", err); return (err); } @@ -1570,7 +1573,7 @@ dev = libusb_get_device(devh); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_cancel_transfer enter"); sxfer = (struct libusb_super_transfer *)( (uint8_t *)uxfer - sizeof(*sxfer)); @@ -1631,7 +1634,7 @@ CTX_UNLOCK(dev->ctx); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_cancel_transfer leave"); return (retval); } @@ -1781,3 +1784,95 @@ return (0); } } + +void +libusb_log_va_args(struct libusb_context *ctx, enum libusb_log_level level, + const char *fmt, ...) +{ + static const char *log_prefix[5] = { + [LIBUSB_LOG_LEVEL_ERROR] = "LIBUSB_ERROR", + [LIBUSB_LOG_LEVEL_WARNING] = "LIBUSB_WARN", + [LIBUSB_LOG_LEVEL_INFO] = "LIBUSB_INFO", + [LIBUSB_LOG_LEVEL_DEBUG] = "LIBUSB_DEBUG", + }; + + char buffer[1024]; + char new_fmt[1024]; + va_list args; + + ctx = GET_CONTEXT(ctx); + va_start(args, fmt); + + if (ctx->debug < level) + return; + + snprintf(new_fmt, sizeof(new_fmt), "%s: %s\n", log_prefix[level], fmt); + vsnprintf(buffer, sizeof(buffer), new_fmt, args); + + if (ctx->log_cb) + ctx->log_cb(ctx, level, buffer); + else + fputs(buffer, stdout); + + va_end(args); +} + +int +libusb_set_option(libusb_context *ctx, enum libusb_option option, ...) +{ + int err = LIBUSB_SUCCESS; + enum libusb_log_level level; + va_list args; + libusb_log_cb callback; + + ctx = GET_CONTEXT(ctx); + va_start(args, option); + + switch (option) { + case LIBUSB_OPTION_LOG_LEVEL: + level = va_arg(args, enum libusb_log_level); + if (level < LIBUSB_LOG_LEVEL_NONE || + level > LIBUSB_LOG_LEVEL_DEBUG) { + err = LIBUSB_ERROR_INVALID_PARAM; + break; + } + + break; + case LIBUSB_OPTION_LOG_CB: + callback = va_arg(args, libusb_log_cb); + break; + } + + if (option >= LIBUSB_OPTION_MAX) { + err = LIBUSB_ERROR_INVALID_PARAM; + goto end; + } + + switch (option) { + case LIBUSB_OPTION_LOG_LEVEL: + if (ctx->debug_fixed) + break; + ctx->debug = level; + break; + case LIBUSB_OPTION_LOG_CB: + ctx->log_cb = callback; + break; + case LIBUSB_OPTION_NO_DEVICE_DISCOVERY: + ctx->no_discovery = true; + break; + /* + * We don't handle USBDK as it is a windows + * backend specified SDK + */ + case LIBUSB_OPTION_USE_USBDK: + break; + case LIBUSB_OPTION_MAX: + default: + err = LIBUSB_ERROR_INVALID_PARAM; + break; + } + +end: + va_end(args); + return (err); +} diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c --- a/lib/libusb/libusb10_hotplug.c +++ b/lib/libusb/libusb10_hotplug.c @@ -346,7 +346,7 @@ ctx = GET_CONTEXT(ctx); - if (ctx->usb_event_mode == usb_event_none) { + if (ctx->usb_event_mode == usb_event_none && !ctx->no_discovery) { HOTPLUG_LOCK(ctx); if (!netlink_init(ctx) && !devd_init(ctx)) ctx->usb_event_mode = usb_event_scan; @@ -364,8 +364,8 @@ return (LIBUSB_ERROR_NO_MEM); HOTPLUG_LOCK(ctx); - if (ctx->hotplug_handler == NO_THREAD) { - libusb_hotplug_enumerate(ctx, &ctx->hotplug_devs); + if (ctx->hotplug_handler == NO_THREAD && !ctx->no_discovery) { + libusb_hotplug_enumerate(ctx, &ctx->hotplug_devs); if (pthread_create(&ctx->hotplug_handler, NULL, &libusb_hotplug_scan, ctx) != 0) diff --git a/lib/libusb/libusb10_io.c b/lib/libusb/libusb10_io.c --- a/lib/libusb/libusb10_io.c +++ b/lib/libusb/libusb10_io.c @@ -108,7 +108,7 @@ int i; int err; - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb10_handle_events_sub enter"); nfds = 0; i = 0; @@ -230,7 +230,7 @@ /* Wakeup other waiters */ pthread_cond_broadcast(&ctx->ctx_cond); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub complete"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb10_handle_events_sub complete"); return (err); } @@ -314,7 +314,7 @@ int err; ctx = GET_CONTEXT(ctx); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_wait_for_event enter"); if (tv == NULL) { pthread_cond_wait(&ctx->ctx_cond, @@ -358,7 +358,7 @@ ctx = GET_CONTEXT(ctx); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_handle_events_timeout_completed enter"); libusb_lock_events(ctx); @@ -374,7 +374,7 @@ libusb_unlock_events(ctx); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed exit"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_handle_events_timeout_completed exit"); return (err); } @@ -523,7 +523,7 @@ ctx = libusb10_get_context_by_device_handle(transfer->dev_handle); - DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "sync I/O done"); pdone = transfer->user_data; *pdone = 1; @@ -613,12 +613,12 @@ ctx = libusb10_get_context_by_device_handle(devh); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_bulk_transfer enter"); ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_bulk_transfer leave"); return (ret); } @@ -632,12 +632,12 @@ ctx = libusb10_get_context_by_device_handle(devh); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_interrupt_transfer enter"); ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_interrupt_transfer leave"); return (ret); }