Skip to content

Commit

Permalink
Add CLI option to enable detection of devices with reset interface
Browse files Browse the repository at this point in the history
  • Loading branch information
tomas-pecserke committed Jun 4, 2023
1 parent b203309 commit 83ad4f0
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 20 deletions.
30 changes: 18 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ PICOTOOL:
Tool for interacting with a RP2040 device in BOOTSEL mode, or with a RP2040 binary
SYNOPSIS:
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-f] [-F]
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
picotool info [-b] [-p] [-d] [-l] [-a] <filename> [-t <type>]
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-f] [-F]
picotool save [-p] [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
picotool save -a [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
picotool verify [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>] [-r <from> <to>] [-o <offset>]
picotool reboot [-a] [-u] [--bus <bus>] [--address <addr>] [-f] [-F]
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
picotool save [-p] [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
picotool save -a [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
picotool verify [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>] [-r <from> <to>] [-o <offset>]
picotool reboot [-a] [-u] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
picotool version [-s]
picotool help [<cmd>]
Expand Down Expand Up @@ -111,7 +111,7 @@ INFO:
Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode
SYNOPSIS:
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-f] [-F]
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
picotool info [-b] [-p] [-d] [-l] [-a] <filename> [-t <type>]
OPTIONS:
Expand All @@ -133,6 +133,8 @@ TARGET SELECTION:
Filter devices by USB bus number
--address <addr>
Filter devices by USB device address
-i, --enable-reset-interface
Enable detection of stdio_usb-compatible reset interface for custom USB devices
-f, --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
Expand Down Expand Up @@ -218,7 +220,7 @@ LOAD:
Load the program / memory range stored in a file onto the device.
SYNOPSIS:
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-f] [-F]
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
OPTIONS:
Post load actions
Expand Down Expand Up @@ -249,6 +251,8 @@ OPTIONS:
Filter devices by USB bus number
--address <addr>
Filter devices by USB device address
-i, --enable-reset-interface
Enable detection of stdio_usb-compatible reset interface for custom USB devices
-f, --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
Expand All @@ -275,9 +279,9 @@ SAVE:
Save the program / memory stored in flash on the device to a file.
SYNOPSIS:
picotool save [-p] [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
picotool save -a [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
picotool save [-p] [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
picotool save -a [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
OPTIONS:
Selection of data to save
Expand All @@ -297,6 +301,8 @@ OPTIONS:
Filter devices by USB bus number
--address <addr>
Filter devices by USB device address
-i, --enable-reset-interface
Enable detection of stdio_usb-compatible reset interface for custom USB devices
-f, --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
Expand Down
28 changes: 21 additions & 7 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ struct _settings {
bool reboot_app_specified = false;
bool force = false;
bool force_no_reboot = false;
bool enable_reset_interface = false;

struct {
bool show_basic = false;
Expand Down Expand Up @@ -297,7 +298,9 @@ auto device_selection =
(option("--bus") & integer("bus").min_value(0).max_value(255).set(settings.bus)
.if_missing([] { return "missing bus number"; })) % "Filter devices by USB bus number" +
(option("--address") & integer("addr").min_value(1).max_value(127).set(settings.address)
.if_missing([] { return "missing address"; })) % "Filter devices by USB device address"
.if_missing([] { return "missing address"; })) % "Filter devices by USB device address" +
option('i', "--enable-reset-interface").set(settings.enable_reset_interface)
% "Enable detection of devices with stdio_usb-compatible reset interface"
#if !defined(_WIN32)
+ 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" +
option('F', "--force-no-reboot").set(settings.force_no_reboot) % "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 left connected and accessible to picotool, but without the RPI-RP2 drive mounted"
Expand Down Expand Up @@ -2110,7 +2113,10 @@ static int reboot_device(libusb_device *device, bool bootsel, uint disable_mask=

bool reboot_command::execute(device_map &devices) {
if (settings.force) {
reboot_device(devices[dr_vidpid_stdio_usb][0].first, settings.reboot_usb);
auto &to_reboot = devices[dr_vidpid_stdio_usb].empty()
? devices[dr_vidpid_stdio_usb][0].first
: devices[dr_reset_interface][0].first;
reboot_device(to_reboot, settings.reboot_usb);
if (!quiet) {
if (settings.reboot_usb) {
std::cout << "The device was asked to reboot into BOOTSEL mode.\n";
Expand Down Expand Up @@ -2230,7 +2236,7 @@ int main(int argc, char **argv) {
if (handle) {
to_close.push_back(handle);
}
if (result != dr_error) {
if (result != dr_error && (result != dr_reset_interface || settings.enable_reset_interface)) {
devices[result].push_back(std::make_pair(*dev, handle));
}
}
Expand All @@ -2242,7 +2248,7 @@ int main(int argc, char **argv) {
// fall thru
case cmd::device_support::one:
if (devices[dr_vidpid_bootrom_ok].empty() &&
(!settings.force || devices[dr_vidpid_stdio_usb].empty())) {
(!settings.force || (devices[dr_vidpid_stdio_usb].empty() && devices[dr_reset_interface].empty()))) {
bool had_note = false;
fos << missing_device_string(tries>0);
if (tries > 0) {
Expand Down Expand Up @@ -2276,19 +2282,25 @@ int main(int argc, char **argv) {
#if defined(_WIN32)
printer(dr_vidpid_stdio_usb,
" appears to be a RP2040 device with a USB serial connection, not in BOOTSEL mode. You can force reboot into BOOTSEL mode via 'picotool reboot -f -u' first.");
printer(dr_reset_interface,
" appears to be a RP2040 device with a USB reset interface, not in BOOTSEL mode. You can force reboot into BOOTSEL mode via 'picotool reboot -f -u' first.");
#else
printer(dr_vidpid_stdio_usb,
" appears to be a RP2040 device with a USB serial connection, so consider -f (or -F) to force reboot in order to run the command.");
printer(dr_reset_interface,
" appears to be a RP2040 device with a USB reset interface, so consider -f (or -F) to force reboot in order to run the command.");
#endif
} else {
// special case message for what is actually just reboot (the only command that doesn't require reboot first)
printer(dr_vidpid_stdio_usb,
" appears to be a RP2040 device with a USB serial connection, so consider -f to force the reboot.");
printer(dr_reset_interface,
" appears to be a RP2040 device with a USB reset interface, so consider -f to force the reboot.");
}
rc = ERROR_NO_DEVICE;
} else if (supported == cmd::device_support::one) {
if (devices[dr_vidpid_bootrom_ok].size() > 1 ||
(devices[dr_vidpid_bootrom_ok].empty() && devices[dr_vidpid_stdio_usb].size() > 1)) {
(devices[dr_vidpid_bootrom_ok].empty() && (devices[dr_vidpid_stdio_usb].size() + devices[dr_reset_interface].size()) > 1)) {
fail(ERROR_NOT_POSSIBLE, "Command requires a single RP2040 device to be targeted.");
}
if (!devices[dr_vidpid_bootrom_ok].empty()) {
Expand All @@ -2306,13 +2318,15 @@ int main(int argc, char **argv) {
}
if (!rc) {
if (settings.force && ctx) { // actually ctx should never be null as we are targeting device if force is set, but still
if (devices[dr_vidpid_stdio_usb].size() != 1) {
if ((devices[dr_vidpid_stdio_usb].size() + devices[dr_reset_interface].size()) != 1) {
fail(ERROR_NOT_POSSIBLE,
"Forced command requires a single rebootable RP2040 device to be targeted.");
}
if (selected_cmd->force_requires_pre_reboot()) {
// we reboot into BOOTSEL mode and disable MSC interface (the 1 here)
auto &to_reboot = devices[dr_vidpid_stdio_usb][0].first;
auto &to_reboot = devices[dr_vidpid_stdio_usb].empty()
? devices[dr_vidpid_stdio_usb][0].first
: devices[dr_reset_interface][0].first;
reboot_device(to_reboot, true, 1);
fos << "The device was asked to reboot into BOOTSEL mode so the command can be executed.\n\n";
for (const auto &handle : to_close) {
Expand Down
2 changes: 1 addition & 1 deletion picoboot_connection/picoboot_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ enum picoboot_device_result picoboot_open_device(libusb_device *device, libusb_d
if (0xff == config->interface[i].altsetting[0].bInterfaceClass &&
RESET_INTERFACE_SUBCLASS == config->interface[i].altsetting[0].bInterfaceSubClass &&
RESET_INTERFACE_PROTOCOL == config->interface[i].altsetting[0].bInterfaceProtocol) {
return dr_vidpid_stdio_usb;
return dr_reset_interface;
}
}

Expand Down
1 change: 1 addition & 0 deletions picoboot_connection/picoboot_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum picoboot_device_result {
dr_vidpid_unknown,
dr_error,
dr_vidpid_stdio_usb,
dr_reset_interface,
};

enum picoboot_device_result picoboot_open_device(libusb_device *device, libusb_device_handle **dev_handle);
Expand Down

0 comments on commit 83ad4f0

Please sign in to comment.