From nobody Mon Sep 28 10:43:23 2026 Received: from mail-yw1-f182.google.com (mail-yw1-f182.google.com [209.85.128.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 11BF43290D2 for ; Sat, 22 Aug 2026 20:38:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787431112; cv=none; b=ZvyPrHegg8YrMutoIfpABtq61Ag4Fmy2qdRMZKcXYZp80S2tQdzhbr5eDGW5+/Skkn61KifhefD6U/0xBc5oXPEX0VHlX7E/GNlq7PHZPaH23wstPs5eM9WydmO37+7N6eZxVhRArk87dVb4kBwjJ2GA8sK2dZpQPYR24jl/8F8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787431112; c=relaxed/simple; bh=xasbg8xg0V6mGthcRH9BjgxbF+lt+jr2vn8oSbt+EtE=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=GQ6C/DtkhonqSUufkvrZrl5omSVoRKjueDoAkReqTFki44023+2sH20XP73Rn0BOwpx5uhfD+DRjDa9Ujq8hgcV5vi0O/1ggebZ7fsZHC6abmYOJn9vor07t8DqvgkKuY9j/XqhUuX4zH5zilS9ic7eeFrYa/3xgiFBbeZbSqkI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=R4SorSJy; arc=none smtp.client-ip=209.85.128.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="R4SorSJy" Received: by mail-yw1-f182.google.com with SMTP id 00721157ae682-81ed2a06b9eso21709437b3.3 for ; Sat, 22 Aug 2026 13:38:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787431110; x=1788035910; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=c/0oonYeNYdcmlvpj9HRZq3vqMjbDlIOZXAp4v7qnLg=; b=R4SorSJyx8vdsG2w2+waSm0h/E97IV8//WY7meWyWFfc3jvEZ/VZ8xW/b/zmGpoM/n M/mSEyPxIfC4sfS9KgGfDAJ1YbUWbAb5LSdQV+XJDZDoDRdubDC4+FZ4pPk/nR7M65mW /bkGR8RUEg5QkU0ZzzUfq9uXc8HjixD/9pLq8GBhcQFBrus6zm/J2R5H0cRun7dn3HD4 kUil0FMIOlI/a2/QbDjbkrjl1m+LLfWL5EHsImLtVHTu4gkLgzYDwYMgcVNHvAAxjDLF /NuOwyhwoUmi3yWZiHa8eQuNc5FRWITtNcWznPd0Xwgo4TmhgxRwyiCfQM7puXB9u1vM rJ9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787431110; x=1788035910; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=c/0oonYeNYdcmlvpj9HRZq3vqMjbDlIOZXAp4v7qnLg=; b=lmoV884XsMj/NQ5/1cnCQhxeCe0k/bEnbah5E7BdcrCvgeboER9GzdG9Gh/xEtNxWf 1RHsuSeKGTwDzfVPYC/ftURVSAj1x2Fwdvc5jC1qJABFB3YDhfeFhe6GYlgFNWWaWnEy So1VHou1rYHKwLp6z0dvv3mkT5UV1owQUbpdtfiz2ye3HV0nNlj//ub2REQgVJOup2UY jn0w0o/rU4A4OLGvx2J5GOWoKzDiIskD/b0kd9AtTMgKXv33uyl2YWBaSKrZQAcgzuYp 5ytBn306+DqGmSOVE1OvV2WRPcEFAgm9q7nzzB3W74OiOEJ3sJ3ve2OmBtzCu9to8ISh y6SA== X-Forwarded-Encrypted: i=1; AHgh+RpoRcvUDZHM9X1AjB3y3+UCjhhHD8b/UbkAS8SEDIAi6Rp8nfNq3q0TwCHVaccfPGx7YvNzMCc6LdIqjr4=@vger.kernel.org X-Gm-Message-State: AFuF++nOktPAnkrQsvvLz+MpwcpzDl5lcnSBDoqJpP+8mRmSOgAoFSe6 xQ5JB5H0QLkJSQVJ94++b08W++ejo+IILQHv8SF6VTWYSo/Q8LU9TdPz X-Gm-Gg: AR+sD12tlXxZrEZo1kpk0Dnx6VkAtk4NAm4N/8PCZffBvT5s2h7hDH+3cN3JCjnO/Ci YJBTFB5sKaEz4K63016vrt+XqxG4btnWm7L/gqoipbQ3d3QF38Uf34vMPxRpUTkOWXQcTS7VtN7 5t3I8V8v9sLpq1kanvUTUwspRzw4kgyLoPEo8qTrUOFaG8+6Dn6gyPGh3CGM6SfKlNz8oLml5V6 u9Ijmj+PSeSgKM10L+zvxWaMV0O2hatjnEcwVTbPD5jd/wnrX+70GgjbchGxTDfoUqKlijh0BWb 5+LCfDB2dGXDxv1i+4vnZEJJmm8ZzmzCKq921jl9AKQeGNedSi5UuhTnM5KE0xz6N4awzVt5MWw I422uHYPq2LxvUCs7orV9JryaFJg1EMQhYvitH1Do9YuZA1OS/2KPz88BO4JaUMwSqDZEd1BSXF Te6UeSNPb7JO4JojgNzoQB4lbRA+bqlc3uoJGeSEbBRtBfbrI6IoZi6NUX5LrfHJth4Z7QYsS+F /8H2++YZKg1lYiY26aKiZKdvlIidRlWvsFXL7OjORdy5j3fCIle0kJ7a7iJAHN7y+5hMyMohMdh JtPLieZUuIsJ8fjdUNIiApff+/o/TfHhk5w1z5OuhVRMiUUQ5Jk2+lTEgbDPl3ZHyaxXdDJSpMV bbEoGahaDaMkFI2YDwC1l/Pnc8Eg2yEA1Qlq8bZd84XTn3k665oX0O68XFzeqpwupoJV45bGKTf wAKaOEMeJzzFfqOD9f X-Received: by 2002:a05:690c:580d:b0:845:d58c:cc8 with SMTP id 00721157ae682-849f4a7ae61mr44731597b3.20.1787431109746; Sat, 22 Aug 2026 13:38:29 -0700 (PDT) Received: from 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa (c-76-108-143-213.hsd1.fl.comcast.net. [76.108.143.213]) by smtp.gmail.com with ESMTPSA id 00721157ae682-84cac4ef4edsm14125047b3.45.2026.08.22.13.38.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Aug 2026 13:38:29 -0700 (PDT) From: Jason Colapietro To: shuah@kernel.org, skhan@linuxfoundation.org, valentina.manea.m@gmail.com Cc: greg@kroah.com, i@zenithal.me, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v6] usbip: make remote list honor parsable output Date: Sat, 22 Aug 2026 16:38:28 -0400 Message-ID: <178743110815.11397.14988078342421111980@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The -p option is accepted in every list mode and `usbip help list` documents it as "Parsable list format", but it only ever reached the local (-l) and gadget (-d) paths. list_exported_devices() never took the flag, so -r ignores it and always prints the human-readable report. Both commands below pass -p, and only the local one honors it: $ usbip list -p -l busid=3D1-2#usbid=3D1a86:55d4# busid=3D2-1#usbid=3D0627:0001# $ usbip list -p -r localhost Exportable USB devices =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - localhost 2-3: ATECH FLASH TECHNOLOGY : Kingston SNA-DC/U (11b0:6298) : /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3 : (Defined at Interface level) (00/00/00) `usbip list -r ` and `usbip list -p -r ` produce byte-identical output, so a script has to scrape the decorated report instead: the column padding, the " - " banner, the blank line between devices and the per-interface lines. That is what the reporter hit in bugzilla 219502. Use one file-scope flag for the list command and honor it in 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. After the change -r produces the record shape -l already does: $ usbip list -p -r 127.0.0.1 busid=3D1-1#usbid=3D0781:5583# busid=3D1-2#usbid=3D046d:c52b# so the obvious loop works against a remote host: for b in $(usbip list -p -r "$host" | sed 's/^busid=3D//; s/#.*//'); do usbip attach -r "$host" -b "$b" done Without -p the remote output is unchanged. Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=3D219502 Assisted-by: LLM Signed-off-by: Jason Colapietro --- v5 -> v6: - Fold a condensed before/after into the commit message, as Shuah asked for on v2. No code changes; the diff is identical to v5. - Restore the Assisted-by tag, in the format required by Documentation/process/coding-assistants.rst. v2 carried it as "Assisted-by: Codex:gpt-5", which predates that document. Tooling disclosure, per Documentation/process/generated-content.rst: an AI coding assistant was used for the original code change, and in this revision to rewrite the commit message so it carries the before/after requested on v2. The code is byte-identical to v5. checkpatch.pl --strict reports no errors, and the patch applies cleanly with git am onto mainline. v4 -> v5: - Drop Cc: stable@vger.kernel.org. This changes the user-visible output of "usbip list -r -p", so it is not a stable backport candidate. v3 -> v4: - Make parsable file-scope instead of passing it through list helpers. - Drop the option-ordering change to preserve existing behavior. Two behaviours I checked beyond the output quoted above: - The connection stays in sync. Interface records are still read from the socket in parsable mode, only the printf is suppressed. To confirm that rather than assert it, I had the test server withhold the final 4-byte usbip_usb_interface record for 3 seconds: the patched client with -p blocks for the full 3 seconds, so it really is draining every record. - With no exported devices, -p prints nothing on stdout ("no exportable devices found on " still goes to stderr), so stdout stays clean. Testing disclosure: my checkout is on macOS, so I have not run a native USB/IP stack end to end. The output above comes from building the real usbip_list.c, usbip_network.c, usbip_common.c and names.c against a stub libudev -- the remote path never calls udev, and the stubs abort if reached -- and pointing that binary at a small mock usbipd answering OP_REQ_DEVLIST with a real OP_REP_DEVLIST payload. The -p -l side is a second build with a fake udev backend presenting the same devices. So it is the real listing path over a real socket, but not usbip-host or usbip-vudc on hardware. I am happy to redo the runs on a Linux box, or to wait for someone with a usbip setup to confirm, before this goes in. v5: https://lore.kernel.org/r/20260816041518.48053-1-jasoncola1@gmail.com v4: https://lore.kernel.org/r/20260812210326.21485-1-jasoncola1@gmail.com tools/usb/usbip/src/usbip_list.c | 48 +++++++++++++++++++------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_l= ist.c index 3d810bcc..482f11d7 100644 --- a/tools/usb/usbip/src/usbip_list.c +++ b/tools/usb/usbip/src/usbip_list.c @@ -36,6 +36,8 @@ static const char usbip_list_usage_string[] =3D " -l, --local List the local USB devices\n" " -d, --device List the local USB gadgets bound to usbip-vud= c\n"; =20 +static bool parsable; + void usbip_list_usage(void) { printf("usage: %s", usbip_list_usage_string); @@ -80,9 +82,11 @@ static int get_exported_devices(char *host, int sockfd) return 0; } =20 - printf("Exportable USB devices\n"); - printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D\n"); - printf(" - %s\n", host); + if (!parsable) { + printf("Exportable USB devices\n"); + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D\n"); + printf(" - %s\n", host); + } =20 for (i =3D 0; i < reply.ndev; i++) { memset(&udev, 0, sizeof(udev)); @@ -98,9 +102,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=3D%s#usbid=3D%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); + } =20 for (j =3D 0; j < udev.bNumInterfaces; j++) { rc =3D usbip_net_recv(sockfd, &uintf, sizeof(uintf)); @@ -116,10 +125,12 @@ static int get_exported_devices(char *host, int sockf= d) uintf.bInterfaceClass, uintf.bInterfaceSubClass, uintf.bInterfaceProtocol); - printf("%11s: %2d - %s\n", "", j, class_name); + if (!parsable) + printf("%11s: %2d - %s\n", "", j, class_name); } =20 - printf("\n"); + if (!parsable) + printf("\n"); } =20 return 0; @@ -150,7 +161,7 @@ static int list_exported_devices(char *host) } =20 static void print_device(const char *busid, const char *vendor, - const char *product, bool parsable) + const char *product) { if (parsable) printf("busid=3D%s#usbid=3D%.4s:%.4s#", busid, vendor, product); @@ -158,13 +169,13 @@ static void print_device(const char *busid, const cha= r *vendor, printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product); } =20 -static void print_product_name(char *product_name, bool parsable) +static void print_product_name(char *product_name) { if (!parsable) printf(" %s\n", product_name); } =20 -static int list_devices(bool parsable) +static int list_devices(void) { struct udev *udev; struct udev_enumerate *enumerate; @@ -229,8 +240,8 @@ static int list_devices(bool parsable) strtol(idProduct, NULL, 16)); =20 /* Print information. */ - print_device(busid, idVendor, idProduct, parsable); - print_product_name(product_name, parsable); + print_device(busid, idVendor, idProduct); + print_product_name(product_name); =20 printf("\n"); =20 @@ -246,7 +257,7 @@ err_out: return ret; } =20 -static int list_gadget_devices(bool parsable) +static int list_gadget_devices(void) { int ret =3D -1; struct udev *udev; @@ -307,8 +318,8 @@ static int list_gadget_devices(bool parsable) le16toh(idProduct)); =20 /* Print information. */ - print_device(busid, idVendor_buf, idProduct_buf, parsable); - print_product_name(product_name, parsable); + print_device(busid, idVendor_buf, idProduct_buf); + print_product_name(product_name); =20 printf("\n"); =20 @@ -333,7 +344,6 @@ int usbip_list(int argc, char *argv[]) { NULL, 0, NULL, 0 } }; =20 - bool parsable =3D false; int opt; int ret =3D -1; =20 @@ -354,10 +364,10 @@ int usbip_list(int argc, char *argv[]) ret =3D list_exported_devices(optarg); goto out; case 'l': - ret =3D list_devices(parsable); + ret =3D list_devices(); goto out; case 'd': - ret =3D list_gadget_devices(parsable); + ret =3D list_gadget_devices(); goto out; default: goto err_out; --=20 2.50.1 (Apple Git-155)