Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add files via upload #101

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Singed-Of-By.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Signed-off-by: Burkhard Arenfeld <[email protected]>
20 changes: 19 additions & 1 deletion lsusb.8.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\"SPDX-License-Identifier: GPL-2.0
.\"Copyright (c) 1999 Thomas Sailer <[email protected]>
.TH lsusb 8 "11 February 2019" "usbutils-VERSION" "Linux USB Utilities"
.TH lsusb 8 "15 November 2019" "usbutils-VERSION" "Linux USB Utilities"
.IX lsusb
.SH NAME
lsusb \- list USB devices
Expand Down Expand Up @@ -36,6 +36,14 @@ Both ID's are given in decimal and may be omitted.
Show only devices with the specified vendor and product ID.
Both ID's are given in hexadecimal.
.TP
.B \-f \fIFORMAT\fP
Change format of device list (not with \-D):
%b = bus number, %d = device number,
%v = vendor ID, %i = product ID,
%m = vendor name, %p = produce name,
%s = serial number, %x = serial as hex dump,
%% = literal %, %t = tab, %n = newline.
.TP
.B \-D \fIdevice\fP
Do not scan the /dev/bus/usb directory,
instead display only information
Expand All @@ -57,6 +65,16 @@ then exit successfully.
.SH RETURN VALUE
If the specified device is not found, a non-zero exit code is returned.

.SH EXAMPLE
.TP
.B lsusb -f 'Bus %b Device %d: ID %v:%i %m %p%n'
is the same as standard output format.
.TP
.B lsusb -d 0483:3748 -f '%b:%d %x %p%n'
List only this kind of device with bus and device number and hexadecimal dump of serial number.
Some devices (e.g. ST-LINK/V2) has binary data in serial number string. Serial number string is in UTF-16 format.
With ASCII encoding every second hex byte is 00.

.SH SEE ALSO
.BR lspci (8),
.BR usbview (8).
Expand Down
126 changes: 120 additions & 6 deletions lsusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static void dump_hub(const char *prefix, const unsigned char *p, int tt_type);
static void dump_ccid_device(const unsigned char *buf);
static void dump_billboard_device_capability_desc(libusb_device_handle *dev, unsigned char *buf);
static void dump_billboard_alt_mode_capability_desc(libusb_device_handle *dev, unsigned char *buf);
static void dump_serial(libusb_device *dev, struct libusb_device_descriptor *desc, int mode);

/* ---------------------------------------------------------------------- */

Expand Down Expand Up @@ -320,6 +321,59 @@ static void dump_device(
free(serial);
}


/* Dump only serial number as text (mode==0) or hexadecimal (mode!=0) */
static void dump_serial(libusb_device *dev, struct libusb_device_descriptor *desc, int mode)
{
libusb_device_handle *udev;
if (!desc->iSerialNumber) {
if (mode) // In hexadecimal mode print a hint
printf("NONE");
else
if (verblevel > 0)
fprintf(stderr, "Device without serial number descriptor\n");
return;
}
if (libusb_open(dev, &udev)) {
fprintf(stderr, "Couldn't open device, some information will be missing\n");
return;
}

if (mode) {
// For hexadecimal output
unsigned char buf[255]; // Warning: 256 doesn't work!
unsigned char *ptr=buf;
int cnt=libusb_get_descriptor(udev,LIBUSB_DT_STRING,desc->iSerialNumber,buf,sizeof buf);
// Read raw descriptor instead of string. String-Version:
// #define LANG_NEUTRAL 0x0000 // from https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings
// cnt=libusb_get_string_descriptor(udev,desc->iSerialNumber,LANG_NEUTRAL,buf,sizeof buf);
if (cnt<=2) { // First two bytes are header: length and type=LIBUSB_DT_STRING.
printf("NULL");
fprintf(stderr, "Serial number descriptor has zero length or error\n");
return;
}
if ((unsigned int)cnt>sizeof buf ) {
fprintf(stderr, "Error while reading serial number descriptor (size=%d)\n",cnt);
return;
}
ptr+=2; cnt-=2; // Skip header
while(cnt--) {
// printf("%c",*ptr>31?*ptr:'?');
printf("%02x",*ptr);
ptr++;
}

} else {
// For text output
char *serial = get_dev_string(udev, desc->iSerialNumber);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is odd, the serial number should work to be retrieved this way as well.

I think your device is broken and does not follow the specification, as this is required to be a string and not "hex values", correct? Have you asked if the device passes the USB certification process?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read about and agree that the ST.-Link/V2 device does abuse serial
number field. String should be a UTF-16 LE text.
But in reality it contains e.g. 0x06 and 0x02 as a character code.
The higher bytes are always zero.
Here my 2 devices with the modified lsusb:
5400ff006d00060072006600530053003000400002006700
4900ff007100060049007000530055004400460006008700
The device itself is working as it should with exception of the serial number.
I'm not the only one with this problem:

fputs(serial,stdout);
free(serial);
}
if (udev)
libusb_close(udev);
}


static void dump_wire_adapter(const unsigned char *buf)
{

Expand Down Expand Up @@ -3684,7 +3738,7 @@ static int dump_one_device(libusb_context *ctx, const char *path)
return 0;
}

static int list_devices(libusb_context *ctx, int busnum, int devnum, int vendorid, int productid)
static int list_devices(libusb_context *ctx, int busnum, int devnum, int vendorid, int productid, const char *format)
{
libusb_device **list;
struct libusb_device_descriptor desc;
Expand Down Expand Up @@ -3726,7 +3780,55 @@ static int list_devices(libusb_context *ctx, int busnum, int devnum, int vendori

if (verblevel > 0)
printf("\n");
printf("Bus %03u Device %03u: ID %04x:%04x %s %s\n",
if (format != NULL) {
const char *ptr=format-1;
while(*++ptr) {
if (*ptr!='%') {
putchar(*ptr);
continue;
}
switch(*++ptr) {
case '%': // literal %
putchar('%');
break;
case 't': // tab
putchar('\t');
break;
case 'n': // newline
putchar('\n');
break;
case 'b': // bus number
printf("%03u",bnum);
break;
case 'd': // device number
printf("%03u",dnum);
break;
case 'v': // vendor id (hex)
printf("%04x",desc.idVendor);
break;
case 'i': // product id (hex)
printf("%04x",desc.idProduct);
break;
case 'm': // vendor name
fputs(vendor,stdout);
break;
case 'p': // product name
fputs(product,stdout);
break;
case 's': // serial number
dump_serial(dev,&desc,0);
break;
case 'x': // serial number as hex dump
dump_serial(dev,&desc,1);
break;
case 0: // bad ... unfinished sequence :-(
ptr--;
break;
// default: // ignoring unsupported sequence
}
}
} else
printf("Bus %03u Device %03u: ID %04x:%04x %s %s\n",
bnum, dnum,
desc.idVendor,
desc.idProduct,
Expand Down Expand Up @@ -3757,13 +3859,14 @@ int main(int argc, char *argv[])
unsigned int treemode = 0;
int bus = -1, devnum = -1, vendor = -1, product = -1;
const char *devdump = NULL;
const char *listformat = NULL;
int help = 0;
char *cp;
int status;

setlocale(LC_CTYPE, "");

while ((c = getopt_long(argc, argv, "D:vtP:p:s:d:Vh",
while ((c = getopt_long(argc, argv, "D:vtP:p:s:d:Vhf:",
long_options, NULL)) != EOF) {
switch (c) {
case 'V':
Expand Down Expand Up @@ -3812,14 +3915,18 @@ int main(int argc, char *argv[])
devdump = optarg;
break;

case 'f':
listformat = optarg;
break;

case '?':
default:
err++;
break;
}
}
if (err || argc > optind || help) {
fprintf(stderr, "Usage: lsusb [options]...\n"
fputs("Usage: lsusb [options]...\n"
"List USB devices\n"
" -v, --verbose\n"
" Increase verbosity (show descriptors)\n"
Expand All @@ -3829,6 +3936,13 @@ int main(int argc, char *argv[])
" -d vendor:[product]\n"
" Show only devices with the specified vendor and\n"
" product ID numbers (in hexadecimal)\n"
" -f FORMAT\n"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have two different things being added in one change. One is the format operation, which is nice to have. The second is your new ability to handle serial numbers in hex format, which is different.

Please break this up into at least 2 different changes and resubmit them as a patch series.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, right. I thought better to add some also useful functions instead of making a quick and dirty modification.
You really need to split? I hoped to show you that It's a useful feature even if normally only needed with devices, which breaks the rules of the serial number descriptor.
To be honest: If you make a release without the %x output it's useless for me :-(
It was the main reason why I made this changes.
And there are definitely devices with this bug :-(
If you really need it in two steps, I can split. Please send a note.

" Change format of device list (not with -D):\n"
" %b = bus number, %d = device number,\n"
" %v = vendor ID, %i = product ID,\n"
" %m = vendor name, %p = produce name,\n"
" %s = serial number, %x = serial as hex dump,\n"
" %% = literal %, %t = tab, %n = newline\n"
" -D device\n"
" Selects which device lsusb will examine\n"
" -t, --tree\n"
Expand All @@ -3837,7 +3951,7 @@ int main(int argc, char *argv[])
" Show version of program\n"
" -h, --help\n"
" Show usage and help\n"
);
,stderr);
return EXIT_FAILURE;
}

Expand All @@ -3863,7 +3977,7 @@ int main(int argc, char *argv[])
if (devdump)
status = dump_one_device(ctx, devdump);
else
status = list_devices(ctx, bus, devnum, vendor, product);
status = list_devices(ctx, bus, devnum, vendor, product, listformat);

names_exit();
libusb_exit(ctx);
Expand Down