Skip to content
Draft
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
2 changes: 2 additions & 0 deletions examples/htool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,8 @@ static const struct htool_param GLOBAL_FLAGS[] = {
"'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 = "usb_path", .default_value = "",
.desc = "Glob Pattern for matching the USB device path."},
{HTOOL_FLAG_BOOL, .name = "version", .default_value = "false",
.desc = "Print htool version."},
{}};
Expand Down
31 changes: 30 additions & 1 deletion examples/htool_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <ctype.h>
#include <errno.h>
#include <fnmatch.h>
#include <libusb.h>
#include <stdbool.h>
#include <stddef.h>
Expand Down Expand Up @@ -75,6 +76,7 @@ static void print_device(void* cb_param, libusb_device* dev,
}

libusb_device_handle* dev_handle;
char sys_path[256];
rv = libusb_open(dev, &dev_handle);
if (rv != LIBUSB_SUCCESS) {
fprintf(stderr, " (unable to open device: %s)", libusb_strerror(rv));
Expand All @@ -95,6 +97,12 @@ static void print_device(void* cb_param, libusb_device* dev,
cleanup2:
libusb_close(dev_handle);
cleanup:
rv = libhoth_get_usb_sys_path(dev, sys_path, sizeof(sys_path));
if (rv != LIBUSB_SUCCESS) {
fprintf(stderr, " (unable to get sys path: %s)", libusb_strerror(rv));
} else {
fprintf(stderr, " (%s)", sys_path);
}
fprintf(stderr, "\n");
}

Expand Down Expand Up @@ -256,6 +264,20 @@ bool filter_by_usb_product_substr(
return strstr(product_name, usb_product_substr) != NULL;
}

static bool filter_by_usb_path_glob(
void* cb_param, libusb_device* dev,
const struct libusb_device_descriptor* descriptor) {
const char* glob_pattern = (const char*)cb_param;
char sys_path[256];
int rv = libhoth_get_usb_sys_path(dev, sys_path, sizeof(sys_path));
if (rv != LIBUSB_SUCCESS) {
fprintf(stderr, "libhoth_get_usb_sys_path failed: %s\n",
libusb_strerror(rv));
return false;
}
return fnmatch(glob_pattern, sys_path, 0) == 0;
}

bool filter_allow_all(void* cb_param, libusb_device* dev,
const struct libusb_device_descriptor* descriptor) {
return true;
Expand All @@ -272,10 +294,13 @@ libusb_device* htool_libusb_device(void) {
}
const char* usb_loc_str;
const char* usb_product_substr;
const char* usb_path_glob_str;
int rv =
htool_get_param_string(htool_global_flags(), "usb_loc", &usb_loc_str) ||
htool_get_param_string(htool_global_flags(), "usb_product",
&usb_product_substr);
&usb_product_substr) ||
htool_get_param_string(htool_global_flags(), "usb_path",
&usb_path_glob_str);
if (rv) {
return NULL;
}
Expand All @@ -292,6 +317,10 @@ libusb_device* htool_libusb_device(void) {
return select_device(ctx, filter_by_usb_product_substr,
(void*)usb_product_substr);
}
if (strlen(usb_path_glob_str) > 0) {
return select_device(ctx, filter_by_usb_path_glob,
(void*)usb_path_glob_str);
}
return select_device(ctx, filter_allow_all, NULL);
}

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

#include <libusb.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

#include "transports/libhoth_device.h"
Expand Down Expand Up @@ -348,3 +350,39 @@ int libhoth_usb_get_device(libusb_context* ctx,
libusb_free_device_list(device, /*unref_devices=*/1);
return found_device ? LIBHOTH_OK : LIBHOTH_ERR_INTERFACE_NOT_FOUND;
}

int libhoth_get_usb_sys_path(libusb_device* dev, char* path, size_t path_len) {
struct libhoth_usb_loc loc;
char bus_port_path[PATH_MAX];
int ret;

if (dev == NULL || path == NULL || path_len == 0) {
return LIBUSB_ERROR_INVALID_PARAM;
}

ret = libhoth_get_usb_loc(dev, &loc);
if (ret) {
return ret;
}

ret = snprintf(bus_port_path, sizeof(bus_port_path),
"/sys/bus/usb/devices/%d-%d", loc.bus, loc.ports[0]);
if (ret < 0 || (size_t)ret >= sizeof(bus_port_path)) {
return LIBUSB_ERROR_OVERFLOW;
}

for (int i = 1; i < loc.num_ports; i++) {
size_t current_len = strlen(bus_port_path);
ret = snprintf(bus_port_path + current_len,
sizeof(bus_port_path) - current_len, ".%d", loc.ports[i]);
if (ret < 0 || current_len + (size_t)ret >= sizeof(bus_port_path)) {
return LIBUSB_ERROR_OVERFLOW;
}
}

if (realpath(bus_port_path, path) == NULL) {
return LIBUSB_ERROR_OTHER;
}

return LIBUSB_SUCCESS;
}
4 changes: 4 additions & 0 deletions transports/libhoth_usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ int libhoth_usb_get_device(libusb_context* ctx,
libusb_device** out);
int libhoth_get_usb_loc(libusb_device* dev, struct libhoth_usb_loc* result);

// Returns the sysfs path for the given libusb_device.
// Returns LIBUSB_SUCCESS on success, or a libusb error code on failure.
int libhoth_get_usb_sys_path(libusb_device* dev, char* path, size_t path_len);

#ifdef __cplusplus
}
#endif
Expand Down