Skip to content

Commit 83ad4f0

Browse files
Add CLI option to enable detection of devices with reset interface
1 parent b203309 commit 83ad4f0

File tree

4 files changed

+41
-20
lines changed

4 files changed

+41
-20
lines changed

README.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ PICOTOOL:
7070
Tool for interacting with a RP2040 device in BOOTSEL mode, or with a RP2040 binary
7171
7272
SYNOPSIS:
73-
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-f] [-F]
73+
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
7474
picotool info [-b] [-p] [-d] [-l] [-a] <filename> [-t <type>]
75-
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-f] [-F]
76-
picotool save [-p] [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
77-
picotool save -a [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
78-
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
79-
picotool verify [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>] [-r <from> <to>] [-o <offset>]
80-
picotool reboot [-a] [-u] [--bus <bus>] [--address <addr>] [-f] [-F]
75+
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
76+
picotool save [-p] [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
77+
picotool save -a [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
78+
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
79+
picotool verify [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>] [-r <from> <to>] [-o <offset>]
80+
picotool reboot [-a] [-u] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
8181
picotool version [-s]
8282
picotool help [<cmd>]
8383
@@ -111,7 +111,7 @@ INFO:
111111
Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode
112112
113113
SYNOPSIS:
114-
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-f] [-F]
114+
picotool info [-b] [-p] [-d] [-l] [-a] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
115115
picotool info [-b] [-p] [-d] [-l] [-a] <filename> [-t <type>]
116116
117117
OPTIONS:
@@ -133,6 +133,8 @@ TARGET SELECTION:
133133
Filter devices by USB bus number
134134
--address <addr>
135135
Filter devices by USB device address
136+
-i, --enable-reset-interface
137+
Enable detection of stdio_usb-compatible reset interface for custom USB devices
136138
-f, --force
137139
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing
138140
the command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
@@ -218,7 +220,7 @@ LOAD:
218220
Load the program / memory range stored in a file onto the device.
219221
220222
SYNOPSIS:
221-
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-f] [-F]
223+
picotool load [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [--bus <bus>] [--address <addr>] [-i] [-f] [-F]
222224
223225
OPTIONS:
224226
Post load actions
@@ -249,6 +251,8 @@ OPTIONS:
249251
Filter devices by USB bus number
250252
--address <addr>
251253
Filter devices by USB device address
254+
-i, --enable-reset-interface
255+
Enable detection of stdio_usb-compatible reset interface for custom USB devices
252256
-f, --force
253257
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing
254258
the command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
@@ -275,9 +279,9 @@ SAVE:
275279
Save the program / memory stored in flash on the device to a file.
276280
277281
SYNOPSIS:
278-
picotool save [-p] [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
279-
picotool save -a [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
280-
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-f] [-F] <filename> [-t <type>]
282+
picotool save [-p] [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
283+
picotool save -a [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
284+
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [-i] [-f] [-F] <filename> [-t <type>]
281285
282286
OPTIONS:
283287
Selection of data to save
@@ -297,6 +301,8 @@ OPTIONS:
297301
Filter devices by USB bus number
298302
--address <addr>
299303
Filter devices by USB device address
304+
-i, --enable-reset-interface
305+
Enable detection of stdio_usb-compatible reset interface for custom USB devices
300306
-f, --force
301307
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing
302308
the command (unless the command itself is a 'reboot') the device will be rebooted back to application mode

main.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ struct _settings {
264264
bool reboot_app_specified = false;
265265
bool force = false;
266266
bool force_no_reboot = false;
267+
bool enable_reset_interface = false;
267268

268269
struct {
269270
bool show_basic = false;
@@ -297,7 +298,9 @@ auto device_selection =
297298
(option("--bus") & integer("bus").min_value(0).max_value(255).set(settings.bus)
298299
.if_missing([] { return "missing bus number"; })) % "Filter devices by USB bus number" +
299300
(option("--address") & integer("addr").min_value(1).max_value(127).set(settings.address)
300-
.if_missing([] { return "missing address"; })) % "Filter devices by USB device address"
301+
.if_missing([] { return "missing address"; })) % "Filter devices by USB device address" +
302+
option('i', "--enable-reset-interface").set(settings.enable_reset_interface)
303+
% "Enable detection of devices with stdio_usb-compatible reset interface"
301304
#if !defined(_WIN32)
302305
+ 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" +
303306
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"
@@ -2110,7 +2113,10 @@ static int reboot_device(libusb_device *device, bool bootsel, uint disable_mask=
21102113

21112114
bool reboot_command::execute(device_map &devices) {
21122115
if (settings.force) {
2113-
reboot_device(devices[dr_vidpid_stdio_usb][0].first, settings.reboot_usb);
2116+
auto &to_reboot = devices[dr_vidpid_stdio_usb].empty()
2117+
? devices[dr_vidpid_stdio_usb][0].first
2118+
: devices[dr_reset_interface][0].first;
2119+
reboot_device(to_reboot, settings.reboot_usb);
21142120
if (!quiet) {
21152121
if (settings.reboot_usb) {
21162122
std::cout << "The device was asked to reboot into BOOTSEL mode.\n";
@@ -2230,7 +2236,7 @@ int main(int argc, char **argv) {
22302236
if (handle) {
22312237
to_close.push_back(handle);
22322238
}
2233-
if (result != dr_error) {
2239+
if (result != dr_error && (result != dr_reset_interface || settings.enable_reset_interface)) {
22342240
devices[result].push_back(std::make_pair(*dev, handle));
22352241
}
22362242
}
@@ -2242,7 +2248,7 @@ int main(int argc, char **argv) {
22422248
// fall thru
22432249
case cmd::device_support::one:
22442250
if (devices[dr_vidpid_bootrom_ok].empty() &&
2245-
(!settings.force || devices[dr_vidpid_stdio_usb].empty())) {
2251+
(!settings.force || (devices[dr_vidpid_stdio_usb].empty() && devices[dr_reset_interface].empty()))) {
22462252
bool had_note = false;
22472253
fos << missing_device_string(tries>0);
22482254
if (tries > 0) {
@@ -2276,19 +2282,25 @@ int main(int argc, char **argv) {
22762282
#if defined(_WIN32)
22772283
printer(dr_vidpid_stdio_usb,
22782284
" 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.");
2285+
printer(dr_reset_interface,
2286+
" 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.");
22792287
#else
22802288
printer(dr_vidpid_stdio_usb,
22812289
" 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.");
2290+
printer(dr_reset_interface,
2291+
" 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.");
22822292
#endif
22832293
} else {
22842294
// special case message for what is actually just reboot (the only command that doesn't require reboot first)
22852295
printer(dr_vidpid_stdio_usb,
22862296
" appears to be a RP2040 device with a USB serial connection, so consider -f to force the reboot.");
2297+
printer(dr_reset_interface,
2298+
" appears to be a RP2040 device with a USB reset interface, so consider -f to force the reboot.");
22872299
}
22882300
rc = ERROR_NO_DEVICE;
22892301
} else if (supported == cmd::device_support::one) {
22902302
if (devices[dr_vidpid_bootrom_ok].size() > 1 ||
2291-
(devices[dr_vidpid_bootrom_ok].empty() && devices[dr_vidpid_stdio_usb].size() > 1)) {
2303+
(devices[dr_vidpid_bootrom_ok].empty() && (devices[dr_vidpid_stdio_usb].size() + devices[dr_reset_interface].size()) > 1)) {
22922304
fail(ERROR_NOT_POSSIBLE, "Command requires a single RP2040 device to be targeted.");
22932305
}
22942306
if (!devices[dr_vidpid_bootrom_ok].empty()) {
@@ -2306,13 +2318,15 @@ int main(int argc, char **argv) {
23062318
}
23072319
if (!rc) {
23082320
if (settings.force && ctx) { // actually ctx should never be null as we are targeting device if force is set, but still
2309-
if (devices[dr_vidpid_stdio_usb].size() != 1) {
2321+
if ((devices[dr_vidpid_stdio_usb].size() + devices[dr_reset_interface].size()) != 1) {
23102322
fail(ERROR_NOT_POSSIBLE,
23112323
"Forced command requires a single rebootable RP2040 device to be targeted.");
23122324
}
23132325
if (selected_cmd->force_requires_pre_reboot()) {
23142326
// we reboot into BOOTSEL mode and disable MSC interface (the 1 here)
2315-
auto &to_reboot = devices[dr_vidpid_stdio_usb][0].first;
2327+
auto &to_reboot = devices[dr_vidpid_stdio_usb].empty()
2328+
? devices[dr_vidpid_stdio_usb][0].first
2329+
: devices[dr_reset_interface][0].first;
23162330
reboot_device(to_reboot, true, 1);
23172331
fos << "The device was asked to reboot into BOOTSEL mode so the command can be executed.\n\n";
23182332
for (const auto &handle : to_close) {

picoboot_connection/picoboot_connection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ enum picoboot_device_result picoboot_open_device(libusb_device *device, libusb_d
7676
if (0xff == config->interface[i].altsetting[0].bInterfaceClass &&
7777
RESET_INTERFACE_SUBCLASS == config->interface[i].altsetting[0].bInterfaceSubClass &&
7878
RESET_INTERFACE_PROTOCOL == config->interface[i].altsetting[0].bInterfaceProtocol) {
79-
return dr_vidpid_stdio_usb;
79+
return dr_reset_interface;
8080
}
8181
}
8282

picoboot_connection/picoboot_connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum picoboot_device_result {
2626
dr_vidpid_unknown,
2727
dr_error,
2828
dr_vidpid_stdio_usb,
29+
dr_reset_interface,
2930
};
3031

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

0 commit comments

Comments
 (0)