From 745e0685a4fc7db43dfae9c312f7d4d65e8262cd Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 22 Jan 2022 20:41:27 +0100 Subject: [PATCH] Allow specifying the GreaseWeazle serial port directly (for devices which don't have the GreaseWeazle VID/PID). --- lib/usb/usb.cc | 117 ++++++++++++++++++++++++------------------- lib/usb/usb.proto | 8 ++- lib/usb/usbfinder.cc | 84 +++++++++++-------------------- 3 files changed, 102 insertions(+), 107 deletions(-) diff --git a/lib/usb/usb.cc b/lib/usb/usb.cc index 2e54e66f..95c4577d 100644 --- a/lib/usb/usb.cc +++ b/lib/usb/usb.cc @@ -13,72 +13,87 @@ static USB* usb = NULL; -USB::~USB() -{} +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?"; + 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 (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]); + 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; + 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); + case GREASEWEAZLE_ID: + std::cerr << fmt::format( + "GreaseWeazle: {} on {}\n", c->serial, c->serialPort); + break; + } + } + exit(1); } USB* get_usb_impl() { - auto candidate = selectDevice(); - switch (candidate->id) - { - case FLUXENGINE_ID: - std::cerr << fmt::format("Using FluxEngine {}\n", candidate->serial); - return createFluxengineUsb(candidate->device); + /* Special case for certain configurations. */ - case GREASEWEAZLE_ID: - std::cerr << fmt::format("Using GreaseWeazle {} on {}\n", candidate->serial, candidate->serialPort); - return createGreaseWeazleUsb(candidate->serialPort, config.usb().greaseweazle()); + if (config.usb().has_greaseweazle() && + config.usb().greaseweazle().has_port()) + { + const auto& conf = config.usb().greaseweazle(); + std::cerr << fmt::format( + "Using GreaseWeazle on serial port {}\n", conf.port()); + return createGreaseWeazleUsb(conf.port(), conf); + } - default: - std::cerr << fmt::format("Using Unknown GW Compatible {} on {}\n", candidate->serial, candidate->serialPort); - GreaseWeazleProto gwconfig = config.usb().greaseweazle(); - return createGreaseWeazleUsb(candidate->serialPort, gwconfig ); - } + /* Otherwise, select a device by USB ID. */ + + auto candidate = selectDevice(); + switch (candidate->id) + { + case FLUXENGINE_ID: + std::cerr << fmt::format( + "Using FluxEngine {}\n", candidate->serial); + return createFluxengineUsb(candidate->device); + + case GREASEWEAZLE_ID: + std::cerr << fmt::format("Using GreaseWeazle {} on {}\n", + candidate->serial, + candidate->serialPort); + return createGreaseWeazleUsb( + candidate->serialPort, config.usb().greaseweazle()); + + default: Error() << "internal"; + } } USB& getUsb() { - if (!usb) - usb = get_usb_impl(); - return *usb; + if (!usb) + usb = get_usb_impl(); + return *usb; } - diff --git a/lib/usb/usb.proto b/lib/usb/usb.proto index f3d7c4b7..38ab5a9b 100644 --- a/lib/usb/usb.proto +++ b/lib/usb/usb.proto @@ -9,7 +9,9 @@ message GreaseWeazleProto { SHUGART = 2; }; - optional BusType bus_type = 1 + optional string port = 1 + [(help) = "GreaseWeazle serial port to use"]; + optional BusType bus_type = 2 [(help) = "which FDD bus type is in use", default = IBMPC]; } @@ -19,5 +21,7 @@ message UsbProto { [(help) = "serial number of FluxEngine or GreaseWeazle device to use"]; } - optional GreaseWeazleProto greaseweazle = 2 [(help) = "GreaseWeazle-specific options"]; + oneof config { + GreaseWeazleProto greaseweazle = 2 [(help) = "GreaseWeazle-specific options"]; + } } diff --git a/lib/usb/usbfinder.cc b/lib/usb/usbfinder.cc index 557a383f..dbba55a3 100644 --- a/lib/usb/usbfinder.cc +++ b/lib/usb/usbfinder.cc @@ -9,66 +9,42 @@ static const std::string get_serial_number(const libusbp::device& device) { - try - { - return device.get_serial_number(); - } - catch (const libusbp::error& e) - { - if (e.has_code(LIBUSBP_ERROR_NO_SERIAL_NUMBER)) - return "n/a"; - throw; - } + try + { + return device.get_serial_number(); + } + catch (const libusbp::error& e) + { + if (e.has_code(LIBUSBP_ERROR_NO_SERIAL_NUMBER)) + return "n/a"; + throw; + } } -std::vector> findUsbDevices(const std::set& ids) +std::vector> findUsbDevices( + const std::set& ids) { - std::vector> candidates; - for (const auto& it : libusbp::list_connected_devices()) - { - auto candidate = std::make_unique(); - candidate->device = it; + std::vector> candidates; + for (const auto& it : libusbp::list_connected_devices()) + { + auto candidate = std::make_unique(); + candidate->device = it; - uint32_t id = (it.get_vendor_id() << 16) | it.get_product_id(); - if (ids.contains(id)) - { - 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)); - } - } - - if (candidates.size() == 0) { - for (const auto& it : libusbp::list_connected_devices()) + uint32_t id = (it.get_vendor_id() << 16) | it.get_product_id(); + if (ids.contains(id)) { - auto candidate = std::make_unique(); - candidate->device = it; - uint32_t id = (it.get_vendor_id() << 16) | it.get_product_id(); - candidate->id = id; - candidate->serial = get_serial_number(it); - printf("USB ID %04x %04x: ", it.get_vendor_id(), it.get_product_id()); - try + candidate->id = id; + candidate->serial = get_serial_number(it); + + if (id == GREASEWEAZLE_ID) { - libusbp::serial_port port(candidate->device, 0, true); - candidate->serialPort = port.get_name(); - printf("generic serialPort found\n"); - candidates.push_back(std::move(candidate)); - } - catch(const libusbp::error & error) - { - // not a serial port! - printf("not a port!\n"); - continue; + libusbp::serial_port port(candidate->device); + candidate->serialPort = port.get_name(); } - } - } - return candidates; + candidates.push_back(std::move(candidate)); + } + } + + return candidates; }