Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions examples/htool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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."},
{}};
Expand Down
74 changes: 13 additions & 61 deletions examples/htool_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions transports/libhoth_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "transports/libhoth_device.h"

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

Expand Down Expand Up @@ -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;
}

Expand Down
24 changes: 14 additions & 10 deletions transports/libhoth_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions transports/libhoth_usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions transports/libhoth_usb_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading