From 7e90d071d91428b5e316b90d27ff818ca52a2862 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Mon, 20 May 2024 16:18:50 +0200 Subject: [PATCH] libusb_ll: rework. Splitted scan method -> help futur dev with a common code to detect/select usb devices --- src/libusb_ll.cpp | 139 +++++++++++++++++++++++++++++++++++----------- src/libusb_ll.hpp | 13 ++++- src/main.cpp | 2 +- 3 files changed, 119 insertions(+), 35 deletions(-) diff --git a/src/libusb_ll.cpp b/src/libusb_ll.cpp index ce56639a52..dbdfae2c71 100644 --- a/src/libusb_ll.cpp +++ b/src/libusb_ll.cpp @@ -4,11 +4,14 @@ */ #include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "cable.hpp" #include "display.hpp" @@ -16,38 +19,104 @@ using namespace std; -libusb_ll::libusb_ll(int vid, int pid):_verbose(true) +libusb_ll::libusb_ll(int vid, int pid, int8_t _verbose): + _usb_ctx(nullptr), _verbose(_verbose >= 2) { (void)vid; (void)pid; if (libusb_init(&_usb_ctx) < 0) throw std::runtime_error("libusb_init_failed"); + ssize_t list_size = libusb_get_device_list(_usb_ctx, &_dev_list); + if (list_size < 0) + throw std::runtime_error("libusb_get_device_list_failed"); + if (list_size == 0) + printError("No USB devices found"); + if (_verbose) + printf("found %zd\n", list_size); } libusb_ll::~libusb_ll() { + libusb_free_device_list(_dev_list, 1); libusb_exit(_usb_ctx); } -bool libusb_ll::scan() +int libusb_ll::get_devices_list(const cable_t *cable) { + int vid = 0, pid = 0; + uint8_t bus_addr = 0, device_addr = 0; + bool vid_pid_filter = false; // if vid/pid only keep matching nodes + bool bus_dev_filter = false; // if bus/dev only keep matching nodes + + if (cable != nullptr) { + vid = cable->vid; + pid = cable->pid; + bus_addr = cable->bus_addr; + device_addr = cable->device_addr; + vid_pid_filter = (vid != 0) && (pid != 0); + bus_dev_filter = (bus_addr != 0) && (device_addr != 0); + } + int i = 0; - libusb_device **dev_list; libusb_device *usb_dev; - libusb_device_handle *handle; - /* iteration */ - ssize_t list_size = libusb_get_device_list(_usb_ctx, &dev_list); - if (_verbose) - printInfo("found " + std::to_string(list_size) + " USB device"); + _usb_dev_list.clear(); + + while ((usb_dev = _dev_list[i++]) != nullptr) { + if (_verbose) { + printf("%x %x %x %x\n", bus_addr, device_addr, + libusb_get_device_address(usb_dev), + libusb_get_bus_number(usb_dev)); + } + + /* bus addr and device addr provided: check */ + if (bus_dev_filter && ( + bus_addr != libusb_get_device_address(usb_dev) || + device_addr != libusb_get_bus_number(usb_dev))) + continue; + + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(usb_dev, &desc) != 0) { + printError("Unable to get device descriptor"); + continue; + } + + if (_verbose) { + printf("%x %x %x %x\n", vid, pid, + desc.idVendor, desc.idProduct); + } + + /* Linux host controller */ + if (desc.idVendor == 0x1d6b) + continue; + + /* check for VID/PID */ + if (vid_pid_filter && ( + vid != desc.idVendor || pid != desc.idProduct)) + continue; + + _usb_dev_list.push_back(usb_dev); + } + + return static_cast(_usb_dev_list.size()); +} + +bool libusb_ll::scan() +{ + char *mess = reinterpret_cast(malloc(1024)); + if (!mess) { + printError("Error: failed to allocate buffer"); + return false; + } + + get_devices_list(nullptr); - char *mess = (char *)malloc(1024); snprintf(mess, 1024, "%3s %3s %-13s %-15s %-12s %-20s %s", "Bus", "device", "vid:pid", "probe type", "manufacturer", "serial", "product"); printSuccess(mess); - while ((usb_dev = dev_list[i++]) != NULL) { + for (libusb_device *usb_dev : _usb_dev_list) { bool found = false; struct libusb_device_descriptor desc; if (libusb_get_device_descriptor(usb_dev, &desc) != 0) { @@ -57,35 +126,41 @@ bool libusb_ll::scan() char probe_type[256]; - /* Linux host controller */ - if (desc.idVendor == 0x1d6b) - continue; - /* ftdi devices */ // FIXME: missing iProduct in cable_list if (desc.idVendor == 0x403) { - if (desc.idProduct == 0x6010) + switch (desc.idProduct) { + case 0x6010: snprintf(probe_type, 256, "FTDI2232"); - else if (desc.idProduct == 0x6011) + break; + case 0x6011: snprintf(probe_type, 256, "ft4232"); - else if (desc.idProduct == 0x6001) + break; + case 0x6001: snprintf(probe_type, 256, "ft232RL"); - else if (desc.idProduct == 0x6014) + break; + case 0x6014: snprintf(probe_type, 256, "ft232H"); - else if (desc.idProduct == 0x6015) + break; + case 0x6015: snprintf(probe_type, 256, "ft231X"); - else if (desc.idProduct == 0x6043) + break; + case 0x6043: snprintf(probe_type, 256, "FT4232HP"); - else + break; + default: snprintf(probe_type, 256, "unknown FTDI"); + break; + } found = true; } else { // FIXME: DFU device can't be detected here - for (auto b = cable_list.begin(); b != cable_list.end(); b++) { - cable_t *c = &(*b).second; + for (const auto& b : cable_list) { + const cable_t *c = &b.second; if (c->vid == desc.idVendor && c->pid == desc.idProduct) { - snprintf(probe_type, 256, "%s", (*b).first.c_str()); + snprintf(probe_type, 256, "%s", b.first.c_str()); found = true; + break; } } } @@ -93,6 +168,7 @@ bool libusb_ll::scan() if (!found) continue; + libusb_device_handle *handle; int ret = libusb_open(usb_dev, &handle); if (ret != 0) { snprintf(mess, 1024, @@ -110,15 +186,15 @@ bool libusb_ll::scan() ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, iproduct, 200); if (ret < 0) - snprintf((char*)iproduct, 200, "none"); + snprintf(reinterpret_cast(iproduct), 200, "none"); ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, imanufacturer, 200); if (ret < 0) - snprintf((char*)imanufacturer, 200, "none"); + snprintf(reinterpret_cast(imanufacturer), 200, "none"); ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, iserial, 200); if (ret < 0) - snprintf((char*)iserial, 200, "none"); + snprintf(reinterpret_cast(iserial), 200, "none"); uint8_t bus_addr = libusb_get_bus_number(usb_dev); uint8_t dev_addr = libusb_get_device_address(usb_dev); @@ -132,7 +208,6 @@ bool libusb_ll::scan() libusb_close(handle); } - libusb_free_device_list(dev_list, 1); free(mess); return true; diff --git a/src/libusb_ll.hpp b/src/libusb_ll.hpp index 7cb8479699..28c6769f6f 100644 --- a/src/libusb_ll.hpp +++ b/src/libusb_ll.hpp @@ -8,16 +8,25 @@ #include +#include + +#include "cable.hpp" + class libusb_ll { public: - explicit libusb_ll(int vid = -1, int pid = -1); + explicit libusb_ll(int vid, int pid, int8_t verbose); ~libusb_ll(); bool scan(); + const std::vectorusb_dev_list() { return _usb_dev_list; } + int get_devices_list(const cable_t *cable); - private: + protected: struct libusb_context *_usb_ctx; bool _verbose; + private: + libusb_device **_dev_list; + std::vector _usb_dev_list; }; #endif // SRC_LIBUSB_LL_HPP_ diff --git a/src/main.cpp b/src/main.cpp index fe4ee0d8cd..573e2a4aab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1107,7 +1107,7 @@ void displaySupported(const struct arguments &args) } if (args.scan_usb) { - libusb_ll usb(0, 0); + libusb_ll usb(0, 0, args.verbose); usb.scan(); } }