diff --git a/examples/htool.c b/examples/htool.c index 0ababc5..0b2192f 100644 --- a/examples/htool.c +++ b/examples/htool.c @@ -1796,11 +1796,10 @@ static const struct htool_param GLOBAL_FLAGS[] = { "or 'mtd' transports; for example '0x900000'."}, {HTOOL_FLAG_VALUE, .name = "dbus_hoth_id", .default_value = "", .desc = "The hoth ID associated with the RoT's hothd service."}, - {HTOOL_FLAG_VALUE, .name = "usb_retry_duration", .default_value = "1000ms", - .desc = "Maximum duration to retry opening a busy USB device (e.g., " - "'1s', '1500ms')."}, - {HTOOL_FLAG_VALUE, .name = "usb_retry_delay", .default_value = "50ms", - .desc = "Delay between USB open retries (e.g., '50ms', '10000us')."}, + {HTOOL_FLAG_VALUE, .name = "connect_timeout", .default_value = "1000ms", + .desc = + "Maximum duration to retry opening a busy libhoth transport (e.g., " + "'1s', '1500ms')."}, {HTOOL_FLAG_BOOL, .name = "version", .default_value = "false", .desc = "Print htool version."}, {}}; diff --git a/examples/htool_usb.c b/examples/htool_usb.c index e7f3108..0215af3 100644 --- a/examples/htool_usb.c +++ b/examples/htool_usb.c @@ -307,77 +307,29 @@ struct libhoth_device* htool_libhoth_usb_device(void) { } // Get retry parameters from global flags - const char* duration_str; - const char* delay_str; - if (htool_get_param_string(htool_global_flags(), "usb_retry_duration", - &duration_str) || - htool_get_param_string(htool_global_flags(), "usb_retry_delay", - &delay_str)) { + const char* timeout_str; + if (htool_get_param_string(htool_global_flags(), "connect_timeout", + &timeout_str)) { return NULL; } - int64_t retry_duration_us = parse_time_string_us(duration_str); - int64_t retry_delay_us = parse_time_string_us(delay_str); + int64_t timeout_us = parse_time_string_us(timeout_str); - if (retry_duration_us < 0) { - fprintf(stderr, "Invalid format for --usb_retry_duration: %s\n", - duration_str); + if (timeout_us < 0) { + fprintf(stderr, "Invalid format for --connect_timeout: %s\n", timeout_str); return NULL; } - if (retry_delay_us < 0) { - fprintf(stderr, "Invalid format for --usb_retry_delay: %s\n", delay_str); - return NULL; - } - // Convert duration to milliseconds for comparison with monotonic time helper - uint64_t retry_duration_ms = (uint64_t)retry_duration_us / 1000; uint32_t prng_seed = libhoth_prng_seed(); - struct libhoth_usb_device_init_options opts = { - .usb_device = usb_dev, .usb_ctx = ctx, .prng_seed = prng_seed}; - - int rv = LIBUSB_ERROR_BUSY; // Initialize rv to trigger the loop - uint64_t start_time_ms = libhoth_get_monotonic_ms(); - uint64_t current_time_ms; - - while (rv == LIBUSB_ERROR_BUSY) { - rv = libhoth_usb_open(&opts, &result); - if (rv == LIBUSB_SUCCESS) { - break; // Successfully opened - } - if (rv != LIBUSB_ERROR_BUSY) { - // A different error occurred, report it and exit - fprintf(stderr, "libhoth_usb_open error: %d (%s)\n", rv, - libusb_strerror(rv)); - return NULL; - } - - // Check elapsed time - current_time_ms = libhoth_get_monotonic_ms(); + struct libhoth_usb_device_init_options opts = {.usb_device = usb_dev, + .usb_ctx = ctx, + .prng_seed = prng_seed, + .timeout_us = timeout_us}; - // Handle potential timer wrap-around or error from get_monotonic_ms - if (current_time_ms < start_time_ms) { - fprintf(stderr, "Monotonic clock error detected during retry loop.\n"); - return NULL; - } - - if (current_time_ms - start_time_ms >= retry_duration_ms) { - fprintf(stderr, "libhoth_usb_open timed out after %s (error: %d (%s))\n", - duration_str, rv, libusb_strerror(rv)); - return NULL; // Timeout - } - - // Wait before retrying - // Ensure delay doesn't exceed reasonable limits for usleep (~10s) - useconds_t sleep_us = - (retry_delay_us > 10000000) ? 10000000 : (useconds_t)retry_delay_us; - usleep(sleep_us); - } - - if (rv != LIBUSB_SUCCESS) { - fprintf(stderr, "libhoth_usb_open error: %d (%s)\n", rv, - libusb_strerror(rv)); - result = NULL; + int rv = libhoth_usb_open(&opts, &result); + if (rv != LIBHOTH_OK) { + fprintf(stderr, "libhoth_usb_open failed: %d\n", rv); return NULL; } diff --git a/transports/libhoth_device.c b/transports/libhoth_device.c index 42828b6..7a56c3f 100644 --- a/transports/libhoth_device.c +++ b/transports/libhoth_device.c @@ -15,6 +15,7 @@ #include "transports/libhoth_device.h" #include +#include #include #include @@ -84,6 +85,8 @@ int libhoth_claim_device(struct libhoth_device* dev, uint32_t timeout_us) { if (total_waiting_us >= timeout_us) { // We've exhausted our waiting budget. We couldn't claim the device // within the configured timeout. + fprintf(stderr, "libhoth: timed out claiming transport after %dus\n", + timeout_us); return LIBHOTH_ERR_INTERFACE_BUSY; } diff --git a/transports/libhoth_usb.c b/transports/libhoth_usb.c index 20c4860..1a2dcae 100644 --- a/transports/libhoth_usb.c +++ b/transports/libhoth_usb.c @@ -91,6 +91,7 @@ static int libhoth_usb_release(struct libhoth_device* dev) { static int libhoth_usb_reconnect(struct libhoth_device* dev) { struct libhoth_usb_device* usb_dev = dev->user_ctx; libusb_context* usb_ctx = usb_dev->ctx; + uint64_t timeout_us = usb_dev->claim_timeout_us; struct libusb_device* libusb_dev = libusb_get_device(usb_dev->handle); @@ -142,6 +143,7 @@ static int libhoth_usb_reconnect(struct libhoth_device* dev) { struct libhoth_usb_device_init_options opts; opts.usb_ctx = usb_ctx; opts.usb_device = libusb_dev; + opts.timeout_us = timeout_us; opts.prng_seed = libhoth_prng_seed(); return libhoth_usb_open(&opts, &dev); @@ -196,12 +198,22 @@ int libhoth_usb_open(const struct libhoth_usb_device_init_options* options, } usb_dev->info = info; usb_dev->ctx = options->usb_ctx; + usb_dev->claim_timeout_us = options->timeout_us; status = libusb_open(options->usb_device, &usb_dev->handle); if (status != LIBUSB_SUCCESS) { goto err_out; } - status = libusb_claim_interface(usb_dev->handle, info.interface_id); - if (status != LIBUSB_SUCCESS) { + + dev->send = libhoth_usb_send_request; + dev->receive = libhoth_usb_receive_response; + dev->close = libhoth_usb_close; + dev->claim = libhoth_usb_claim; + dev->release = libhoth_usb_release; + dev->reconnect = libhoth_usb_reconnect; + dev->user_ctx = usb_dev; + + status = libhoth_claim_device(dev, options->timeout_us); + if (status != LIBHOTH_OK) { goto err_out; } @@ -221,14 +233,6 @@ int libhoth_usb_open(const struct libhoth_usb_device_init_options* options, if (status != LIBHOTH_OK) goto err_out; - dev->send = libhoth_usb_send_request; - dev->receive = libhoth_usb_receive_response; - dev->close = libhoth_usb_close; - dev->claim = libhoth_usb_claim; - dev->release = libhoth_usb_release; - dev->reconnect = libhoth_usb_reconnect; - dev->user_ctx = usb_dev; - *out = dev; libusb_free_config_descriptor(config_descriptor); return LIBHOTH_OK; diff --git a/transports/libhoth_usb.h b/transports/libhoth_usb.h index 0625399..0aed958 100644 --- a/transports/libhoth_usb.h +++ b/transports/libhoth_usb.h @@ -36,6 +36,8 @@ struct libhoth_usb_device_init_options { // Seed value to use for Pseudo-random number generator for communicating with // RoT over USB FIFO interface. Must be non-zero uint32_t prng_seed; + // Timeout for connecting to the USB bus + uint32_t timeout_us; }; #define LIBHOTH_NUM_PORTS 16 diff --git a/transports/libhoth_usb_device.h b/transports/libhoth_usb_device.h index 94d26e4..b9c9a46 100644 --- a/transports/libhoth_usb_device.h +++ b/transports/libhoth_usb_device.h @@ -71,6 +71,7 @@ struct libhoth_usb_interface_info { struct libhoth_usb_device { libusb_context* ctx; libusb_device_handle* handle; + uint32_t claim_timeout_us; struct libhoth_usb_interface_info info; union driver_data { struct libhoth_usb_mailbox mailbox;