Skip to content

Commit dc6d6bc

Browse files
Add Serial ID device target filter
1 parent 9c7cb43 commit dc6d6bc

File tree

2 files changed

+75
-35
lines changed

2 files changed

+75
-35
lines changed

README.md

Lines changed: 17 additions & 11 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>] [--serial <serial>] [-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>] [--serial <serial>] [-f] [-F]
76+
picotool save [-p] [--bus <bus>] [--address <addr>] [--serial <serial>] [-f] [-F] <filename> [-t <type>]
77+
picotool save -a [--bus <bus>] [--address <addr>] [--serial <serial>] [-f] [-F] <filename> [-t <type>]
78+
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [--serial <serial>] [-f] [-F] <filename> [-t <type>]
79+
picotool verify [--bus <bus>] [--address <addr>] [--serial <serial>] [-f] [-F] <filename> [-t <type>] [-r <from> <to>] [-o <offset>]
80+
picotool reboot [-a] [-u] [--bus <bus>] [--address <addr>] [--serial <serial>] [-f] [-F]
8181
picotool version [-s]
8282
picotool help [<cmd>]
8383
@@ -133,6 +133,8 @@ TARGET SELECTION:
133133
Filter devices by USB bus number
134134
--address <addr>
135135
Filter devices by USB device address
136+
--serial <serial>
137+
Filter devices by serial id
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>] [--serial <serial>] [-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+
--serial <serial>
255+
Filter devices by serial id
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>] [--serial <serial>] [-f] [-F] <filename> [-t <type>]
283+
picotool save -a [--bus <bus>] [--address <addr>] [--serial <serial>] [-f] [-F] <filename> [-t <type>]
284+
picotool save -r <from> <to> [--bus <bus>] [--address <addr>] [--serial <serial>] [-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+
--serial <serial>
305+
Filter devices by serial id
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: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <memory>
2626
#include <functional>
2727
#include <ctime>
28+
#include <sstream>
2829

2930
#include "boot/uf2.h"
3031
#include "picoboot_connection_cxx.h"
@@ -255,6 +256,7 @@ struct _settings {
255256
uint32_t binary_start = FLASH_START;
256257
int bus=-1;
257258
int address=-1;
259+
string serial;
258260
uint32_t offset = 0;
259261
uint32_t from = 0;
260262
uint32_t to = 0;
@@ -295,12 +297,25 @@ std::shared_ptr<cmd> selected_cmd;
295297
auto device_selection =
296298
(
297299
(option("--bus") & integer("bus").min_value(0).max_value(255).set(settings.bus)
298-
.if_missing([] { return "missing bus number"; })) % "Filter devices by USB bus number" +
299-
(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"
300+
.if_missing([] { return "missing bus number"; }))
301+
% "Filter devices by USB bus number"
302+
+ (option("--address") & integer("addr").min_value(1).max_value(127).set(settings.address)
303+
.if_missing([] { return "missing address"; }))
304+
% "Filter devices by USB device address"
305+
).min(0).doc_non_optional(true) +
306+
(
307+
(option("--serial") & value("serial").set(settings.serial)
308+
.if_missing([] { return "missing serial id"; }))
309+
% "Filter devices by serial id"
301310
#if !defined(_WIN32)
302-
+ 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" +
303-
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"
311+
+ option('f', "--force").set(settings.force)
312+
% "Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. "
313+
"After executing the command (unless the command itself is a 'reboot') "
314+
"the device will be rebooted back to application mode"
315+
+ option('F', "--force-no-reboot").set(settings.force_no_reboot)
316+
% "Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. "
317+
"After executing the command (unless the command itself is a 'reboot') the device will be left connected "
318+
"and accessible to picotool, but without the RPI-RP2 drive mounted"
304319
#endif
305320
).min(0).doc_non_optional(true);
306321

@@ -1582,28 +1597,25 @@ void info_guts(memory_access &raw_access) {
15821597
}
15831598

15841599
string missing_device_string(bool wasRetry) {
1585-
char b[256];
1586-
if (wasRetry) {
1587-
strcpy(b, "Despite the reboot attempt, no ");
1588-
} else {
1589-
strcpy(b, "No ");
1600+
std::ostringstream oss;
1601+
oss << (wasRetry ? "Despite the reboot attempt, no" : "No") << " accessible RP2040 device";
1602+
if (settings.bus != -1 && settings.serial.empty()) {
1603+
oss << 's';
1604+
}
1605+
oss << " in BOOTSEL mode";
1606+
if (!settings.serial.empty()) {
1607+
oss << " with serial ID '" << settings.serial << '\'';
1608+
}
1609+
oss << " was found";
1610+
if (settings.bus != -1) {
1611+
oss << " at bus " << settings.bus;
15901612
}
1591-
char *buf = b + strlen(b);
1592-
int buf_len = b + sizeof(b) - buf;
15931613
if (settings.address != -1) {
1594-
if (settings.bus != -1) {
1595-
snprintf(buf, buf_len, "accessible RP2040 device in BOOTSEL mode was found at bus %d, address %d.", settings.bus, settings.address);
1596-
} else {
1597-
snprintf(buf, buf_len, "accessible RP2040 devices in BOOTSEL mode were found with address %d.", settings.address);
1598-
}
1599-
} else {
1600-
if (settings.bus != -1) {
1601-
snprintf(buf, buf_len, "accessible RP2040 devices in BOOTSEL mode were found found on bus %d.", settings.bus);
1602-
} else {
1603-
snprintf(buf, buf_len,"accessible RP2040 devices in BOOTSEL mode were found.");
1604-
}
1614+
oss << (settings.bus == -1 ? " with" : ",") << " address " << settings.address;
16051615
}
1606-
return b;
1616+
oss << '.';
1617+
1618+
return oss.str();
16071619
}
16081620

16091621
bool help_command::execute(device_map &devices) {
@@ -2180,6 +2192,27 @@ void cancelled(int) {
21802192
throw cancelled_exception();
21812193
}
21822194

2195+
string get_usb_device_serial(libusb_device *device, libusb_device_handle *handle) {
2196+
struct libusb_device_descriptor desc{};
2197+
int ret = libusb_get_device_descriptor(device, &desc);
2198+
if (ret) {
2199+
return "";
2200+
}
2201+
if (handle == nullptr) {
2202+
ret = libusb_open(device, &handle);
2203+
}
2204+
if (ret) {
2205+
return "";
2206+
}
2207+
unsigned char data[33];
2208+
if (libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, data, 31)) {
2209+
data[32] = '\0';
2210+
return reinterpret_cast<char const*>(data);
2211+
}
2212+
2213+
return "";
2214+
}
2215+
21832216
int main(int argc, char **argv) {
21842217
libusb_context *ctx = nullptr;
21852218

@@ -2230,6 +2263,7 @@ int main(int argc, char **argv) {
22302263
if (handle) {
22312264
to_close.push_back(handle);
22322265
}
2266+
if (!settings.serial.empty() && settings.serial != get_usb_device_serial(*dev, handle)) continue;
22332267
if (result != dr_error) {
22342268
devices[result].push_back(std::make_pair(*dev, handle));
22352269
}

0 commit comments

Comments
 (0)