[PATCH v2 RESEND] usbip: make remote list honor parsable output

Jason Colapietro posted 1 patch 1 month, 2 weeks ago
There is a newer version of this series
tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
[PATCH v2 RESEND] usbip: make remote list honor parsable output
Posted by Jason Colapietro 1 month, 2 weeks ago
The -p option only affects local devices and gadgets. Remote lists still
print their human-readable headings and details, so scripts cannot parse
them using the documented option.

Pass the parsable flag through the remote listing path. Emit the same busid
and usbid record used for local devices while continuing to consume every
interface record from the server.

Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219502
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5
Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
---
Changes in v2:
- Make the email From header match Signed-off-by.
- Add Cc: stable@vger.kernel.org.

 tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index 3d810bcca02..b9d60b87e47 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -41,7 +41,7 @@ void usbip_list_usage(void)
 	printf("usage: %s", usbip_list_usage_string);
 }

-static int get_exported_devices(char *host, int sockfd)
+static int get_exported_devices(char *host, int sockfd, bool parsable)
 {
 	char product_name[100];
 	char class_name[100];
@@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
 		return 0;
 	}

-	printf("Exportable USB devices\n");
-	printf("======================\n");
-	printf(" - %s\n", host);
+	if (!parsable) {
+		printf("Exportable USB devices\n");
+		printf("======================\n");
+		printf(" - %s\n", host);
+	}

 	for (i = 0; i < reply.ndev; i++) {
 		memset(&udev, 0, sizeof(udev));
@@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
 		usbip_names_get_class(class_name, sizeof(class_name),
 				      udev.bDeviceClass, udev.bDeviceSubClass,
 				      udev.bDeviceProtocol);
-		printf("%11s: %s\n", udev.busid, product_name);
-		printf("%11s: %s\n", "", udev.path);
-		printf("%11s: %s\n", "", class_name);
+		if (parsable) {
+			printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
+			       udev.idVendor, udev.idProduct);
+		} else {
+			printf("%11s: %s\n", udev.busid, product_name);
+			printf("%11s: %s\n", "", udev.path);
+			printf("%11s: %s\n", "", class_name);
+		}

 		for (j = 0; j < udev.bNumInterfaces; j++) {
 			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
@@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
 					uintf.bInterfaceClass,
 					uintf.bInterfaceSubClass,
 					uintf.bInterfaceProtocol);
-			printf("%11s: %2d - %s\n", "", j, class_name);
+			if (!parsable)
+				printf("%11s: %2d - %s\n", "", j, class_name);
 		}

-		printf("\n");
+		if (!parsable)
+			printf("\n");
 	}

 	return 0;
 }

-static int list_exported_devices(char *host)
+static int list_exported_devices(char *host, bool parsable)
 {
 	int rc;
 	int sockfd;
@@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
 	}
 	dbg("connected to %s:%s", host, usbip_port_string);

-	rc = get_exported_devices(host, sockfd);
+	rc = get_exported_devices(host, sockfd, parsable);
 	if (rc < 0) {
 		err("failed to get device list from %s", host);
 		return -1;
@@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
 			parsable = true;
 			break;
 		case 'r':
-			ret = list_exported_devices(optarg);
+			ret = list_exported_devices(optarg, parsable);
 			goto out;
 		case 'l':
 			ret = list_devices(parsable);
-- 
2.50.1 (Apple Git-155)
Re: [PATCH v2 RESEND] usbip: make remote list honor parsable output
Posted by Shuah Khan 1 month, 2 weeks ago
On 8/10/26 21:42, Jason Colapietro wrote:
> The -p option only affects local devices and gadgets. Remote lists still
> print their human-readable headings and details, so scripts cannot parse
> them using the documented option.
> 
> Pass the parsable flag through the remote listing path. Emit the same busid
> and usbid record used for local devices while continuing to consume every
> interface record from the server.

What happens without this patch? Can you elaborate with some examples?

> 
> Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219502
> Cc: stable@vger.kernel.org
> Assisted-by: Codex:gpt-5
> Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
> ---
> Changes in v2:
> - Make the email From header match Signed-off-by.
> - Add Cc: stable@vger.kernel.org.
> 
>   tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
>   1 file changed, 21 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
> index 3d810bcca02..b9d60b87e47 100644
> --- a/tools/usb/usbip/src/usbip_list.c
> +++ b/tools/usb/usbip/src/usbip_list.c
> @@ -41,7 +41,7 @@ void usbip_list_usage(void)
>   	printf("usage: %s", usbip_list_usage_string);
>   }
> 
> -static int get_exported_devices(char *host, int sockfd)
> +static int get_exported_devices(char *host, int sockfd, bool parsable)
>   {
>   	char product_name[100];
>   	char class_name[100];
> @@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
>   		return 0;
>   	}
> 
> -	printf("Exportable USB devices\n");
> -	printf("======================\n");
> -	printf(" - %s\n", host);
> +	if (!parsable) {
> +		printf("Exportable USB devices\n");
> +		printf("======================\n");
> +		printf(" - %s\n", host);
> +	}
> 
>   	for (i = 0; i < reply.ndev; i++) {
>   		memset(&udev, 0, sizeof(udev));
> @@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
>   		usbip_names_get_class(class_name, sizeof(class_name),
>   				      udev.bDeviceClass, udev.bDeviceSubClass,
>   				      udev.bDeviceProtocol);
> -		printf("%11s: %s\n", udev.busid, product_name);
> -		printf("%11s: %s\n", "", udev.path);
> -		printf("%11s: %s\n", "", class_name);
> +		if (parsable) {
> +			printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
> +			       udev.idVendor, udev.idProduct);
> +		} else {
> +			printf("%11s: %s\n", udev.busid, product_name);
> +			printf("%11s: %s\n", "", udev.path);
> +			printf("%11s: %s\n", "", class_name);
> +		}
> 
>   		for (j = 0; j < udev.bNumInterfaces; j++) {
>   			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
> @@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
>   					uintf.bInterfaceClass,
>   					uintf.bInterfaceSubClass,
>   					uintf.bInterfaceProtocol);
> -			printf("%11s: %2d - %s\n", "", j, class_name);
> +			if (!parsable)
> +				printf("%11s: %2d - %s\n", "", j, class_name);
>   		}
> 
> -		printf("\n");
> +		if (!parsable)
> +			printf("\n");
>   	}
> 
>   	return 0;
>   }
> 
> -static int list_exported_devices(char *host)
> +static int list_exported_devices(char *host, bool parsable)
>   {
>   	int rc;
>   	int sockfd;
> @@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
>   	}
>   	dbg("connected to %s:%s", host, usbip_port_string);
> 
> -	rc = get_exported_devices(host, sockfd);
> +	rc = get_exported_devices(host, sockfd, parsable);
>   	if (rc < 0) {
>   		err("failed to get device list from %s", host);
>   		return -1;
> @@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
>   			parsable = true;
>   			break;
>   		case 'r':
> -			ret = list_exported_devices(optarg);
> +			ret = list_exported_devices(optarg, parsable);
>   			goto out;
>   		case 'l':
>   			ret = list_devices(parsable);

thanks,
-- Shuah
Re: [PATCH v2 RESEND] usbip: make remote list honor parsable output
Posted by Jason Colapietro 1 month, 2 weeks ago
Jason Colapietro <jasoncola1@gmail.com>
11:26 PM (1 minute ago)
to Shuah, Valentina, skhan, Hongren, Greg, linux-usb, linux-kernel, stable

The -p option only affects local devices and gadgets. Remote lists still
print their human-readable headings and details, so scripts cannot parse
them using the documented option.

Pass the parsable flag through the remote listing path. Emit the same busid
and usbid record used for local devices while continuing to consume every
interface record from the server.

Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
Closes: https://www.google.com/url?q=https://bugzilla.kernel.org/show_bug.cgi?id%3D219502&source=gmail&ust=1786591574713000&sa=E
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5
Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
---
Changes in v3:
- No functional change; resent as 1/2 of a series.
- 2/2 makes -p work regardless of where it appears on the command line.

tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index 3d810bcca02..b9d60b87e47 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -41,7 +41,7 @@ void usbip_list_usage(void)
printf("usage: %s", usbip_list_usage_string);
}

-static int get_exported_devices(char *host, int sockfd)
+static int get_exported_devices(char *host, int sockfd, bool parsable)
{
char product_name[100];
char class_name[100];
@@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
return 0;
}

- printf("Exportable USB devices\n");
- printf("======================\n");
- printf(" - %s\n", host);
+ if (!parsable) {
+ printf("Exportable USB devices\n");
+ printf("======================\n");
+ printf(" - %s\n", host);
+ }

for (i = 0; i < reply.ndev; i++) {
memset(&udev, 0, sizeof(udev));
@@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
usbip_names_get_class(class_name, sizeof(class_name),
udev.bDeviceClass, udev.bDeviceSubClass,
udev.bDeviceProtocol);
- printf("%11s: %s\n", udev.busid, product_name);
- printf("%11s: %s\n", "", udev.path);
- printf("%11s: %s\n", "", class_name);
+ if (parsable) {
+ printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
+ udev.idVendor, udev.idProduct);
+ } else {
+ printf("%11s: %s\n", udev.busid, product_name);
+ printf("%11s: %s\n", "", udev.path);
+ printf("%11s: %s\n", "", class_name);
+ }

for (j = 0; j < udev.bNumInterfaces; j++) {
rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
@@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
uintf.bInterfaceClass,
uintf.bInterfaceSubClass,
uintf.bInterfaceProtocol);
- printf("%11s: %2d - %s\n", "", j, class_name);
+ if (!parsable)
+ printf("%11s: %2d - %s\n", "", j, class_name);
}

- printf("\n");
+ if (!parsable)
+ printf("\n");
}

return 0;
}

-static int list_exported_devices(char *host)
+static int list_exported_devices(char *host, bool parsable)
{
int rc;
int sockfd;
@@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
}
dbg("connected to %s:%s", host, usbip_port_string);

- rc = get_exported_devices(host, sockfd);
+ rc = get_exported_devices(host, sockfd, parsable);
if (rc < 0) {
err("failed to get device list from %s", host);
return -1;
@@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
parsable = true;
break;
case 'r':
- ret = list_exported_devices(optarg);
+ ret = list_exported_devices(optarg, parsable);
goto out;
case 'l':
ret = list_devices(parsable);
--
2.50.1 (Apple Git-155)
-Jason

On Tue, Aug 11, 2026 at 6:48 PM Shuah Khan <skhan@linuxfoundation.org> wrote:
>
> On 8/10/26 21:42, Jason Colapietro wrote:
> > The -p option only affects local devices and gadgets. Remote lists still
> > print their human-readable headings and details, so scripts cannot parse
> > them using the documented option.
> >
> > Pass the parsable flag through the remote listing path. Emit the same busid
> > and usbid record used for local devices while continuing to consume every
> > interface record from the server.
>
> What happens without this patch? Can you elaborate with some examples?
>
> >
> > Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
> > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219502
> > Cc: stable@vger.kernel.org
> > Assisted-by: Codex:gpt-5
> > Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
> > ---
> > Changes in v2:
> > - Make the email From header match Signed-off-by.
> > - Add Cc: stable@vger.kernel.org.
> >
> >   tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
> >   1 file changed, 21 insertions(+), 12 deletions(-)
> >
> > diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
> > index 3d810bcca02..b9d60b87e47 100644
> > --- a/tools/usb/usbip/src/usbip_list.c
> > +++ b/tools/usb/usbip/src/usbip_list.c
> > @@ -41,7 +41,7 @@ void usbip_list_usage(void)
> >       printf("usage: %s", usbip_list_usage_string);
> >   }
> >
> > -static int get_exported_devices(char *host, int sockfd)
> > +static int get_exported_devices(char *host, int sockfd, bool parsable)
> >   {
> >       char product_name[100];
> >       char class_name[100];
> > @@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
> >               return 0;
> >       }
> >
> > -     printf("Exportable USB devices\n");
> > -     printf("======================\n");
> > -     printf(" - %s\n", host);
> > +     if (!parsable) {
> > +             printf("Exportable USB devices\n");
> > +             printf("======================\n");
> > +             printf(" - %s\n", host);
> > +     }
> >
> >       for (i = 0; i < reply.ndev; i++) {
> >               memset(&udev, 0, sizeof(udev));
> > @@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
> >               usbip_names_get_class(class_name, sizeof(class_name),
> >                                     udev.bDeviceClass, udev.bDeviceSubClass,
> >                                     udev.bDeviceProtocol);
> > -             printf("%11s: %s\n", udev.busid, product_name);
> > -             printf("%11s: %s\n", "", udev.path);
> > -             printf("%11s: %s\n", "", class_name);
> > +             if (parsable) {
> > +                     printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
> > +                            udev.idVendor, udev.idProduct);
> > +             } else {
> > +                     printf("%11s: %s\n", udev.busid, product_name);
> > +                     printf("%11s: %s\n", "", udev.path);
> > +                     printf("%11s: %s\n", "", class_name);
> > +             }
> >
> >               for (j = 0; j < udev.bNumInterfaces; j++) {
> >                       rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
> > @@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
> >                                       uintf.bInterfaceClass,
> >                                       uintf.bInterfaceSubClass,
> >                                       uintf.bInterfaceProtocol);
> > -                     printf("%11s: %2d - %s\n", "", j, class_name);
> > +                     if (!parsable)
> > +                             printf("%11s: %2d - %s\n", "", j, class_name);
> >               }
> >
> > -             printf("\n");
> > +             if (!parsable)
> > +                     printf("\n");
> >       }
> >
> >       return 0;
> >   }
> >
> > -static int list_exported_devices(char *host)
> > +static int list_exported_devices(char *host, bool parsable)
> >   {
> >       int rc;
> >       int sockfd;
> > @@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
> >       }
> >       dbg("connected to %s:%s", host, usbip_port_string);
> >
> > -     rc = get_exported_devices(host, sockfd);
> > +     rc = get_exported_devices(host, sockfd, parsable);
> >       if (rc < 0) {
> >               err("failed to get device list from %s", host);
> >               return -1;
> > @@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
> >                       parsable = true;
> >                       break;
> >               case 'r':
> > -                     ret = list_exported_devices(optarg);
> > +                     ret = list_exported_devices(optarg, parsable);
> >                       goto out;
> >               case 'l':
> >                       ret = list_devices(parsable);
>
> thanks,
> -- Shuah