Skip to content

Commit f32f5eb

Browse files
lucarin91andersson
authored andcommitted
usb: add support for listing devices
When working with multiple devices and the --serial argument, the serial numbers must be known. Add a new command "qdl list" to list the connected devices in EDL mode and their serial number. Signed-off-by: lucarin91 <lucarin@protonmail.com> [bjorn: Replaced --list with list, changed output to only print serial, some stylistic changes] Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
1 parent 32f0d67 commit f32f5eb

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

qdl.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ static void print_usage(FILE *out)
417417

418418
fprintf(out, "Usage: %s [options] <prog.mbn> (<program-xml> | <patch-xml> | <read-xml>)...\n", __progname);
419419
fprintf(out, " %s [options] <prog.mbn> ((read | write) <address> <binary>)...\n", __progname);
420+
fprintf(out, " %s list\n", __progname);
420421
fprintf(out, " -d, --debug\t\t\tPrint detailed debug info\n");
421422
fprintf(out, " -v, --version\t\t\tPrint the current version and exit\n");
422423
fprintf(out, " -n, --dry-run\t\t\tDry run execution, no device reading or flashing\n");
@@ -440,6 +441,29 @@ static void print_usage(FILE *out)
440441
fprintf(out, "Example: %s prog_firehose_ddr.elf rawprogram*.xml patch*.xml\n", __progname);
441442
}
442443

444+
static int qdl_list(FILE *out)
445+
{
446+
struct qdl_device_desc *devices;
447+
unsigned int count;
448+
unsigned int i;
449+
450+
devices = usb_list(&count);
451+
if (!devices)
452+
return 1;
453+
454+
if (count == 0) {
455+
fprintf(out, "No devices found\n");
456+
} else {
457+
for (i = 0; i < count; i++)
458+
fprintf(out, "%04x:%04x\t%s\n",
459+
devices[i].vid, devices[i].pid, devices[i].serial);
460+
}
461+
462+
free(devices);
463+
464+
return 0;
465+
}
466+
443467
int main(int argc, char **argv)
444468
{
445469
enum qdl_storage_type storage_type = QDL_STORAGE_UFS;
@@ -478,6 +502,9 @@ int main(int argc, char **argv)
478502
{0, 0, 0, 0}
479503
};
480504

505+
if (argc == 2 && !strcmp(argv[1], "list"))
506+
return qdl_list(stdout);
507+
481508
while ((opt = getopt_long(argc, argv, "dvi:lu:S:D:s:fcnt:T:h", options, NULL)) != -1) {
482509
switch (opt) {
483510
case 'd':

qdl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ int qdl_vip_transfer_enable(struct qdl_device *qdl, const char *vip_table_path);
8989
struct qdl_device *usb_init(void);
9090
struct qdl_device *sim_init(void);
9191

92+
struct qdl_device_desc {
93+
int vid;
94+
int pid;
95+
char serial[16];
96+
};
97+
98+
struct qdl_device_desc *usb_list(unsigned int *devices_found);
99+
92100
int firehose_run(struct qdl_device *qdl);
93101
int firehose_provision(struct qdl_device *qdl);
94102
int firehose_read_buf(struct qdl_device *qdl, struct read_op *read_op, void *out_buf, size_t out_size);

usb.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,89 @@ static int usb_open(struct qdl_device *qdl, const char *serial)
223223
return -1;
224224
}
225225

226+
struct qdl_device_desc *usb_list(unsigned int *devices_found)
227+
{
228+
struct libusb_device_descriptor desc;
229+
struct libusb_device_handle *handle;
230+
struct qdl_device_desc *result;
231+
struct libusb_device **devices;
232+
struct libusb_device *dev;
233+
unsigned long serial_len;
234+
unsigned char buf[128];
235+
ssize_t device_count;
236+
unsigned int count = 0;
237+
char *serial;
238+
int ret;
239+
int i;
240+
241+
ret = libusb_init(NULL);
242+
if (ret < 0)
243+
err(1, "failed to initialize libusb");
244+
245+
device_count = libusb_get_device_list(NULL, &devices);
246+
if (device_count < 0)
247+
err(1, "failed to list USB devices");
248+
if (device_count == 0)
249+
return NULL;
250+
251+
result = calloc(device_count, sizeof(struct qdl_device));
252+
if (!result)
253+
err(1, "failed to allocate devices array\n");
254+
255+
for (i = 0; i < device_count; i++) {
256+
dev = devices[i];
257+
258+
ret = libusb_get_device_descriptor(dev, &desc);
259+
if (ret < 0) {
260+
warnx("failed to get USB device descriptor");
261+
continue;
262+
}
263+
264+
if (desc.idVendor != 0x05c6)
265+
continue;
266+
if (desc.idProduct != 0x9008 && desc.idProduct != 0x900e && desc.idProduct != 0x901d)
267+
continue;
268+
269+
ret = libusb_open(dev, &handle);
270+
if (ret < 0) {
271+
warnx("unable to open USB device");
272+
continue;
273+
}
274+
275+
ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, buf, sizeof(buf) - 1);
276+
if (ret < 0) {
277+
warnx("failed to read iProduct descriptor: %s", libusb_strerror(ret));
278+
continue;
279+
}
280+
buf[ret] = '\0';
281+
282+
serial = strstr((char *)buf, "_SN:");
283+
if (!serial) {
284+
ux_err("ignoring device with no serial number\n");
285+
continue;
286+
}
287+
288+
serial += strlen("_SN:");
289+
serial_len = strcspn(serial, " _");
290+
if (serial_len + 1 > sizeof(result[count].serial)) {
291+
ux_err("ignoring device with unexpectedly long serial number\n");
292+
continue;
293+
}
294+
295+
memcpy(result[count].serial, serial, serial_len);
296+
result[count].serial[serial_len] = '\0';
297+
298+
result[count].vid = desc.idVendor;
299+
result[count].pid = desc.idProduct;
300+
count++;
301+
}
302+
303+
libusb_free_device_list(devices, 1);
304+
*devices_found = count;
305+
306+
return result;
307+
}
308+
226309
static void usb_close(struct qdl_device *qdl)
227310
{
228311
struct qdl_device_usb *qdl_usb = container_of(qdl, struct qdl_device_usb, base);

0 commit comments

Comments
 (0)