From 3dfafaa278941de0a7c20677a9ba51083aa06957 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 13 Dec 2021 23:09:33 +0100 Subject: [PATCH] GreaseWeazle autodetection now works (at least on Linux). --- lib/usb/greaseweazle.h | 2 ++ lib/usb/usb.cc | 78 ++++++++++++++++++++++++++---------------- lib/usb/usb.proto | 6 ++-- lib/usb/usbfinder.cc | 14 ++++++-- lib/usb/usbfinder.h | 3 +- 5 files changed, 66 insertions(+), 37 deletions(-) diff --git a/lib/usb/greaseweazle.h b/lib/usb/greaseweazle.h index 667f6db3..acb83f42 100644 --- a/lib/usb/greaseweazle.h +++ b/lib/usb/greaseweazle.h @@ -4,6 +4,8 @@ #define GREASEWEAZLE_VID 0x1209 #define GREASEWEAZLE_PID 0x4d69 +#define GREASEWEAZLE_ID ((GREASEWEAZLE_VID<<16) | GREASEWEAZLE_PID) + #define EP_OUT 0x02 #define EP_IN 0x83 diff --git a/lib/usb/usb.cc b/lib/usb/usb.cc index 1b0c25d0..0f764422 100644 --- a/lib/usb/usb.cc +++ b/lib/usb/usb.cc @@ -1,11 +1,14 @@ #include "globals.h" #include "flags.h" #include "usb.h" +#include "libusbp_config.h" +#include "libusbp.hpp" #include "protocol.h" #include "fluxmap.h" #include "bytes.h" #include "proto.h" #include "usbfinder.h" +#include "greaseweazle.h" #include "fmt/format.h" static USB* usb = NULL; @@ -13,41 +16,58 @@ static USB* usb = NULL; USB::~USB() {} +static std::unique_ptr selectDevice() +{ + auto candidates = findUsbDevices({ FLUXENGINE_ID, GREASEWEAZLE_ID }); + if (candidates.size() == 0) + Error() << "no devices found (is one plugged in? Do you have the appropriate " + "permissions?"; + + if (config.usb().has_serial()) + { + auto wantedSerial = config.usb().serial(); + for (auto& c : candidates) + { + if (c->serial == wantedSerial) + return std::move(c); + } + Error() << "serial number not found (try without one to list or autodetect devices)"; + } + + if (candidates.size() == 1) + return std::move(candidates[0]); + + std::cerr << "More than one device detected; use --usb.serial= to select one:\n"; + for (const auto& c : candidates) + { + std::cerr << " "; + switch (c->id) + { + case FLUXENGINE_ID: + std::cerr << fmt::format("FluxEngine: {}\n", c->serial); + break; + + case GREASEWEAZLE_ID: + std::cerr << fmt::format("GreaseWeazle: {} on {}\n", c->serial, c->serialPort); + break; + } + } + exit(1); +} + USB* get_usb_impl() { - switch (config.usb().device_case()) + auto candidate = selectDevice(); + switch (candidate->id) { - case UsbProto::kFluxengine: - { - auto candidates = findUsbDevices(FLUXENGINE_ID); - for (auto& c : candidates) - { - if (c->serial == config.usb().fluxengine()) - return createFluxengineUsb(c->device); - } - Error() << "that FluxEngine device could not be found (is it plugged in? Do you have the " - "appropriate permissions?"; - } + case FLUXENGINE_ID: + return createFluxengineUsb(candidate->device); - case UsbProto::kGreaseweazle: - return createGreaseWeazleUsb(config.usb().greaseweazle()); + case GREASEWEAZLE_ID: + return createGreaseWeazleUsb(candidate->serialPort); default: - { - auto candidates = findUsbDevices(FLUXENGINE_ID); - if (candidates.size() == 0) - Error() << "no FluxEngine devices found (is one plugged in? Do you have the appropriate " - "permissions?"; - if (candidates.size() != 1) - { - std::cerr << "More than one FluxEngine detected; use --usb.fluxengine= to\n" - "select one:\n"; - for (const auto& c : candidates) - std::cerr << " " << c->serial << std::endl; - exit(1); - } - return createFluxengineUsb(candidates[0]->device); - } + Error() << "internal"; } } diff --git a/lib/usb/usb.proto b/lib/usb/usb.proto index d977d08f..f78f5fd2 100644 --- a/lib/usb/usb.proto +++ b/lib/usb/usb.proto @@ -4,9 +4,7 @@ import "lib/common.proto"; message UsbProto { oneof device { - string fluxengine = 1 - [(help) = "serial number of FluxEngine device to use"]; - string greaseweazle = 2 - [(help) = "serial port of GreaseWeazle device to use"]; + string serial = 1 + [(help) = "serial number of FluxEngine or GreaseWeazle device to use"]; } } diff --git a/lib/usb/usbfinder.cc b/lib/usb/usbfinder.cc index 853008a8..95b74d76 100644 --- a/lib/usb/usbfinder.cc +++ b/lib/usb/usbfinder.cc @@ -4,6 +4,7 @@ #include "bytes.h" #include "fmt/format.h" #include "usbfinder.h" +#include "greaseweazle.h" #include "libusbp.hpp" static const std::string get_serial_number(const libusbp::device& device) @@ -20,7 +21,7 @@ static const std::string get_serial_number(const libusbp::device& device) } } -std::vector> findUsbDevices(uint32_t candidateId) +std::vector> findUsbDevices(const std::set& ids) { std::vector> candidates; for (const auto& it : libusbp::list_connected_devices()) @@ -29,10 +30,17 @@ std::vector> findUsbDevices(uint32_t candidateI candidate->device = it; uint32_t id = (it.get_vendor_id() << 16) | it.get_product_id(); - if (id == candidateId) + if (ids.contains(id)) { - candidate->id = candidateId; + candidate->id = id; candidate->serial = get_serial_number(it); + + if (id == GREASEWEAZLE_ID) + { + libusbp::serial_port port(candidate->device); + candidate->serialPort = port.get_name(); + } + candidates.push_back(std::move(candidate)); } } diff --git a/lib/usb/usbfinder.h b/lib/usb/usbfinder.h index eb5e82f3..29b1e030 100644 --- a/lib/usb/usbfinder.h +++ b/lib/usb/usbfinder.h @@ -9,9 +9,10 @@ struct CandidateDevice libusbp::device device; uint32_t id; std::string serial; + std::string serialPort; }; -extern std::vector> findUsbDevices(uint32_t id); +extern std::vector> findUsbDevices(const std::set& id); #endif