diff --git a/README.md b/README.md index 8c7451a..85ff009 100644 --- a/README.md +++ b/README.md @@ -70,14 +70,14 @@ PICOTOOL: Tool for interacting with a RP2040 device in BOOTSEL mode, or with a RP2040 binary SYNOPSYS: - picotool info [-b] [-p] [-d] [-l] [-a] [--bus ] [--address ] [--serial ] [-f] [-F] + picotool info [-b] [-p] [-d] [-l] [-a] [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] picotool info [-b] [-p] [-d] [-l] [-a] [-t ] - picotool load [-n] [-N] [-u] [-v] [-x] [-t ] [-o ] [--bus ] [--address ] [--serial ] [-f] [-F] - picotool save [-p] [--bus ] [--address ] [--serial ] [-f] [-F] [-t ] - picotool save -a [--bus ] [--address ] [--serial ] [-f] [-F] [-t ] - picotool save -r [--bus ] [--address ] [--serial ] [-f] [-F] [-t ] - picotool verify [--bus ] [--address ] [--serial ] [-f] [-F] [-t ] [-r ] [-o ] - picotool reboot [-a] [-u] [--bus ] [--address ] [--serial ] [-f] [-F] + picotool load [-n] [-N] [-u] [-v] [-x] [-t ] [-o ] [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] + picotool save [-p] [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] [-t ] + picotool save -a [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] [-t ] + picotool save -r [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] [-t ] + picotool verify [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] [-t ] [-r ] [-o ] + picotool reboot [-a] [-u] [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] picotool version [-s] picotool help [] @@ -111,7 +111,7 @@ INFO: Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode SYNOPSYS: - picotool info [-b] [-p] [-d] [-l] [-a] [--bus ] [--address ] [-f] [-F] + picotool info [-b] [-p] [-d] [-l] [-a] [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] picotool info [-b] [-p] [-d] [-l] [-a] [-t ] OPTIONS: @@ -133,6 +133,10 @@ TARGET SELECTION: Filter devices by USB bus number --address Filter devices by USB device address + --vid + Filter devices by vendor id + --pid + Filter devices by product id --serial Filter devices by serial id -f, --force @@ -220,9 +224,9 @@ SAVE: Save the program / memory stored in flash on the device to a file. SYNOPSYS: - picotool save [-p] [--bus ] [--address ] [-f] [-F] [-t ] - picotool save -a [--bus ] [--address ] [-f] [-F] [-t ] - picotool save -r [--bus ] [--address ] [-f] [-F] [-t ] + picotool save [-p] [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] [-t ] + picotool save -a [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] [-t ] + picotool save -r [--bus ] [--address ] [--vid ] [--pid ] [--serial ] [-f] [-F] [-t ] OPTIONS: Selection of data to save @@ -242,6 +246,10 @@ OPTIONS: Filter devices by USB bus number --address Filter devices by USB device address + --vid + Filter devices by vendor id + --pid + Filter devices by product id --serial Filter devices by serial id -f, --force diff --git a/main.cpp b/main.cpp index e2599c5..f8b3c4d 100644 --- a/main.cpp +++ b/main.cpp @@ -256,6 +256,8 @@ struct _settings { uint32_t binary_start = FLASH_START; int bus=-1; int address=-1; + int vid = -1; + int pid = -1; string serial; uint32_t offset = 0; uint32_t from = 0; @@ -302,13 +304,17 @@ auto device_selection = + (option("--address") & integer("addr").min_value(1).max_value(127).set(settings.address) .if_missing([] { return "missing address"; })) % "Filter devices by USB device address" - ).min(0).doc_non_optional(true) + - ( - (option("--serial") & value("serial").set(settings.serial) + + (option("--vid") & hex("vid").min_value(0).max_value(0xffff).set(settings.vid) + .if_missing([] { return "missing vendor id"; })) + % "Filter devices by vendor id" + + (option("--pid") & hex("pid").min_value(0).max_value(0xffff).set(settings.pid) + .if_missing([] { return "missing product id"; })) + % "Filter devices by product id" + + (option("--serial") & value("serial").set(settings.serial) .if_missing([] { return "missing serial id"; })) % "Filter devices by serial id" #if !defined(_WIN32) - + option('f', "--force").set(settings.force) + + option('f', "--force").set(settings.force) % "Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. " "After executing the command (unless the command itself is a 'reboot') " "the device will be rebooted back to application mode" @@ -1602,16 +1608,28 @@ string missing_device_string(bool wasRetry) { oss << 's'; } oss << " in BOOTSEL mode"; + + if (settings.vid != -1 && settings.pid != -1) { + oss << " with ID '" << std::hex << settings.vid << ':' << std::hex << settings.pid << '\''; + } else if (settings.vid != -1) { + oss << " with Vendor ID '" << std::hex << settings.vid << '\''; + } else if (settings.pid != -1) { + oss << " with Product ID '" << std::hex << settings.pid << '\''; + } + if (!settings.serial.empty()) { oss << " with serial ID '" << settings.serial << '\''; } + oss << " was found"; + if (settings.bus != -1) { oss << " at bus " << settings.bus; } if (settings.address != -1) { oss << (settings.bus == -1 ? " with" : ",") << " address " << settings.address; } + oss << '.'; return oss.str(); @@ -2205,6 +2223,16 @@ string get_usb_device_serial(libusb_device *device, libusb_device_handle *handle return ""; } +int get_usb_device_vid_pid(libusb_device *device, uint16_t &vid, uint16_t &pid) { + struct libusb_device_descriptor desc; + int ret = libusb_get_device_descriptor(device, &desc); + if (ret) { + return -1; + } + + return 0; +} + int main(int argc, char **argv) { libusb_context *ctx = nullptr; @@ -2250,6 +2278,12 @@ int main(int argc, char **argv) { for (libusb_device **dev = devs; *dev; dev++) { if (settings.bus != -1 && settings.bus != libusb_get_bus_number(*dev)) continue; if (settings.address != -1 && settings.address != libusb_get_device_address(*dev)) continue; + if (settings.vid != -1 || settings.pid != -1) { + uint16_t vid, pid; + int ret = get_usb_device_vid_pid(*dev, vid, pid); + if (settings.vid != -1 && (ret || settings.vid != vid)) continue; + if (settings.pid != -1 && (ret || settings.pid != vid)) continue; + } libusb_device_handle *handle = nullptr; auto result = picoboot_open_device(*dev, &handle); if (handle) {