libusb_ll: rework. Splitted scan method -> help futur dev with a common code to detect/select usb devices

This commit is contained in:
Gwenhael Goavec-Merou 2024-05-20 16:18:50 +02:00
parent 37a0f9c03e
commit 7e90d071d9
3 changed files with 120 additions and 36 deletions

View File

@ -4,11 +4,14 @@
*/ */
#include <libusb.h> #include <libusb.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <string>
#include <stdexcept>
#include "cable.hpp" #include "cable.hpp"
#include "display.hpp" #include "display.hpp"
@ -16,38 +19,104 @@
using namespace std; 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)vid;
(void)pid; (void)pid;
if (libusb_init(&_usb_ctx) < 0) if (libusb_init(&_usb_ctx) < 0)
throw std::runtime_error("libusb_init_failed"); 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_ll::~libusb_ll()
{ {
libusb_free_device_list(_dev_list, 1);
libusb_exit(_usb_ctx); libusb_exit(_usb_ctx);
} }
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 *usb_dev;
_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<int>(_usb_dev_list.size());
}
bool libusb_ll::scan() bool libusb_ll::scan()
{ {
int i = 0; char *mess = reinterpret_cast<char *>(malloc(1024));
libusb_device **dev_list; if (!mess) {
libusb_device *usb_dev; printError("Error: failed to allocate buffer");
libusb_device_handle *handle; return false;
}
/* iteration */ get_devices_list(nullptr);
ssize_t list_size = libusb_get_device_list(_usb_ctx, &dev_list);
if (_verbose)
printInfo("found " + std::to_string(list_size) + " USB device");
char *mess = (char *)malloc(1024);
snprintf(mess, 1024, "%3s %3s %-13s %-15s %-12s %-20s %s", snprintf(mess, 1024, "%3s %3s %-13s %-15s %-12s %-20s %s",
"Bus", "device", "vid:pid", "probe type", "manufacturer", "Bus", "device", "vid:pid", "probe type", "manufacturer",
"serial", "product"); "serial", "product");
printSuccess(mess); printSuccess(mess);
while ((usb_dev = dev_list[i++]) != NULL) { for (libusb_device *usb_dev : _usb_dev_list) {
bool found = false; bool found = false;
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
if (libusb_get_device_descriptor(usb_dev, &desc) != 0) { if (libusb_get_device_descriptor(usb_dev, &desc) != 0) {
@ -57,35 +126,41 @@ bool libusb_ll::scan()
char probe_type[256]; char probe_type[256];
/* Linux host controller */
if (desc.idVendor == 0x1d6b)
continue;
/* ftdi devices */ /* ftdi devices */
// FIXME: missing iProduct in cable_list // FIXME: missing iProduct in cable_list
if (desc.idVendor == 0x403) { if (desc.idVendor == 0x403) {
if (desc.idProduct == 0x6010) switch (desc.idProduct) {
case 0x6010:
snprintf(probe_type, 256, "FTDI2232"); snprintf(probe_type, 256, "FTDI2232");
else if (desc.idProduct == 0x6011) break;
case 0x6011:
snprintf(probe_type, 256, "ft4232"); snprintf(probe_type, 256, "ft4232");
else if (desc.idProduct == 0x6001) break;
case 0x6001:
snprintf(probe_type, 256, "ft232RL"); snprintf(probe_type, 256, "ft232RL");
else if (desc.idProduct == 0x6014) break;
case 0x6014:
snprintf(probe_type, 256, "ft232H"); snprintf(probe_type, 256, "ft232H");
else if (desc.idProduct == 0x6015) break;
case 0x6015:
snprintf(probe_type, 256, "ft231X"); snprintf(probe_type, 256, "ft231X");
else if (desc.idProduct == 0x6043) break;
case 0x6043:
snprintf(probe_type, 256, "FT4232HP"); snprintf(probe_type, 256, "FT4232HP");
else break;
default:
snprintf(probe_type, 256, "unknown FTDI"); snprintf(probe_type, 256, "unknown FTDI");
break;
}
found = true; found = true;
} else { } else {
// FIXME: DFU device can't be detected here // FIXME: DFU device can't be detected here
for (auto b = cable_list.begin(); b != cable_list.end(); b++) { for (const auto& b : cable_list) {
cable_t *c = &(*b).second; const cable_t *c = &b.second;
if (c->vid == desc.idVendor && c->pid == desc.idProduct) { 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; found = true;
break;
} }
} }
} }
@ -93,6 +168,7 @@ bool libusb_ll::scan()
if (!found) if (!found)
continue; continue;
libusb_device_handle *handle;
int ret = libusb_open(usb_dev, &handle); int ret = libusb_open(usb_dev, &handle);
if (ret != 0) { if (ret != 0) {
snprintf(mess, 1024, snprintf(mess, 1024,
@ -110,15 +186,15 @@ bool libusb_ll::scan()
ret = libusb_get_string_descriptor_ascii(handle, ret = libusb_get_string_descriptor_ascii(handle,
desc.iProduct, iproduct, 200); desc.iProduct, iproduct, 200);
if (ret < 0) if (ret < 0)
snprintf((char*)iproduct, 200, "none"); snprintf(reinterpret_cast<char*>(iproduct), 200, "none");
ret = libusb_get_string_descriptor_ascii(handle, ret = libusb_get_string_descriptor_ascii(handle,
desc.iManufacturer, imanufacturer, 200); desc.iManufacturer, imanufacturer, 200);
if (ret < 0) if (ret < 0)
snprintf((char*)imanufacturer, 200, "none"); snprintf(reinterpret_cast<char*>(imanufacturer), 200, "none");
ret = libusb_get_string_descriptor_ascii(handle, ret = libusb_get_string_descriptor_ascii(handle,
desc.iSerialNumber, iserial, 200); desc.iSerialNumber, iserial, 200);
if (ret < 0) if (ret < 0)
snprintf((char*)iserial, 200, "none"); snprintf(reinterpret_cast<char*>(iserial), 200, "none");
uint8_t bus_addr = libusb_get_bus_number(usb_dev); uint8_t bus_addr = libusb_get_bus_number(usb_dev);
uint8_t dev_addr = libusb_get_device_address(usb_dev); uint8_t dev_addr = libusb_get_device_address(usb_dev);
@ -132,7 +208,6 @@ bool libusb_ll::scan()
libusb_close(handle); libusb_close(handle);
} }
libusb_free_device_list(dev_list, 1);
free(mess); free(mess);
return true; return true;

View File

@ -8,16 +8,25 @@
#include <libusb.h> #include <libusb.h>
#include <vector>
#include "cable.hpp"
class libusb_ll { class libusb_ll {
public: public:
explicit libusb_ll(int vid = -1, int pid = -1); explicit libusb_ll(int vid, int pid, int8_t verbose);
~libusb_ll(); ~libusb_ll();
bool scan(); bool scan();
const std::vector<struct libusb_device *>usb_dev_list() { return _usb_dev_list; }
int get_devices_list(const cable_t *cable);
private: protected:
struct libusb_context *_usb_ctx; struct libusb_context *_usb_ctx;
bool _verbose; bool _verbose;
private:
libusb_device **_dev_list;
std::vector<struct libusb_device *> _usb_dev_list;
}; };
#endif // SRC_LIBUSB_LL_HPP_ #endif // SRC_LIBUSB_LL_HPP_

View File

@ -1107,7 +1107,7 @@ void displaySupported(const struct arguments &args)
} }
if (args.scan_usb) { if (args.scan_usb) {
libusb_ll usb(0, 0); libusb_ll usb(0, 0, args.verbose);
usb.scan(); usb.scan();
} }
} }