From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Google-Smtp-Source: AH8x2245eFRVO3STa5q4UxeEfATGThQnkNYJWfPG4vSviYUL5LZ+cQVC1JvtOPLtBlpeIpHsJ7Fu ARC-Seal: i=1; a=rsa-sha256; t=1517301456; cv=none; d=google.com; s=arc-20160816; b=dHpuDnYjS91qlMQQMn4ViwpHFAfkuZXyxEhYeaHnUE9E5C6Y/LRmJDLa8soo/lpT8W SZnMjs+iyyNOPR9a2Shf6INxVxSTLgVnFGb+u8TkLRyZyYZspmjYqPm2bgbsxKgVZzbu vQdB+dIbGNhTedS5FkVbzojB9le/BBl/XufXr/7MsWHZVPG3HgPziXY3IohN2dAu0J/j 0SkAph4S6kvvb/yeH8i8U5uySbkFdlVXM178eMwryx0IzXATI1vyNLxwjXI8zWGGNUc6 rBVliY+EpVf0gDgxCKzcTLvTcPBuCw+IVX4FH3Yv0inFSWbTtN+DrF/E3cFOXq0TDIu2 EIkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=p6KPpJW3CIj7JqpPF0AwmGY2Zr/z6QMffhz80iChGRE=; b=cAoDx/m77qRDvIQc8D0VGcscK2aLRr2iI0Nq/3Z6JPct1dFv1Jxq1+AwGAlet2TXdF hv9AywpOcwxRjOE6gy0YxtN3CJkY6YGBq8MtIWISDKebMqQtmjXhkcXoUw9TVIVrnCPu gBJVScBLrQ5mwGPuz5yByeutWATPv03pNlIhr2mijHZvm4oM+0IxgEszZ+KS3a+Qryav 0wBQVH6bmtApdR/QGWzBVayWQF7SwaflS32AKXj06KMzEOhxGWbgj6uY7NM9cTVyIj6H dXPF6y3j/tRNXaeAmrfGSzLpnQ9/r0519gaNIoG/tyTJS0RtO4hycqfn7jMuf5w3y8M+ JCFw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of salva@qindel.com designates 89.140.90.34 as permitted sender) smtp.mailfrom=salva@qindel.com Authentication-Results: mx.google.com; spf=pass (google.com: domain of salva@qindel.com designates 89.140.90.34 as permitted sender) smtp.mailfrom=salva@qindel.com From: Salvador Fandino To: linux-usb@vger.kernel.org Cc: gregkh@linuxfoundation.org, valentina.manea.m@gmail.com, shuah@kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Salvador=20Fandi=C3=B1o?= Subject: [PATCH 3/4] usbip tools: use per vhci_hcd controller attributes Date: Tue, 30 Jan 2018 09:36:29 +0100 Message-Id: <20180130083630.26501-4-salva@qindel.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180130083630.26501-1-salva@qindel.com> References: <20180130083630.26501-1-salva@qindel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: =?utf-8?q?1591005892074812264?= X-GMAIL-MSGID: =?utf-8?q?1591005892074812264?= X-Mailing-List: linux-kernel@vger.kernel.org List-ID: From: Salvador Fandi=C3=B1o Now every vhci_hcd device is controlled by its own sysfs attributes (before all of them were controlled by vhci_hcd.0 attributes). This patch addapts the usbip tools to use the new interface through libusbip. The user visible changes are as follows: - The files containing port information are named as "port$ix-$port" (they were "port$port" before), as port numbers are local to the vhci_hcd device now. - Command "usbip port" by default only list ports attached to "vhci_hcd.0", the new flag "--vhci-ix" can be used to list other device. The flag "--all" is also available for listing all the devices (it has not been made the default because it inserts per vhci_hcd device headers, changing the output format). Signed-off-by: Salvador Fandi=C3=B1o --- tools/usb/usbip/src/Makefile.am | 3 +- tools/usb/usbip/src/usbip_attach.c | 101 ++++++++++++++++-------- tools/usb/usbip/src/usbip_detach.c | 57 ++++++++------ tools/usb/usbip/src/usbip_enumerate.c | 55 +++++++++++++ tools/usb/usbip/src/usbip_enumerate.h | 25 ++++++ tools/usb/usbip/src/usbip_port.c | 143 ++++++++++++++++++++++++++++= +----- tools/usb/usbip/src/utils.c | 16 ++++ tools/usb/usbip/src/utils.h | 1 + 8 files changed, 322 insertions(+), 79 deletions(-) create mode 100644 tools/usb/usbip/src/usbip_enumerate.c create mode 100644 tools/usb/usbip/src/usbip_enumerate.h diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefi= le.am index e26f39e0579d..50436aaa3900 100644 --- a/tools/usb/usbip/src/Makefile.am +++ b/tools/usb/usbip/src/Makefile.am @@ -7,6 +7,7 @@ sbin_PROGRAMS :=3D usbip usbipd =20 usbip_SOURCES :=3D usbip.h utils.h usbip.c utils.c usbip_network.c \ usbip_attach.c usbip_detach.c usbip_list.c \ - usbip_bind.c usbip_unbind.c usbip_port.c + usbip_bind.c usbip_unbind.c usbip_port.c \ + usbip_enumerate.c =20 usbipd_SOURCES :=3D usbip_network.h usbipd.c usbip_network.c diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usb= ip_attach.c index 7f07b2d50f59..3901dd507451 100644 --- a/tools/usb/usbip/src/usbip_attach.c +++ b/tools/usb/usbip/src/usbip_attach.c @@ -35,6 +35,7 @@ #include "usbip_common.h" #include "usbip_network.h" #include "usbip.h" +#include "usbip_enumerate.h" =20 static const char usbip_attach_usage_string[] =3D "usbip attach \n" @@ -48,7 +49,8 @@ void usbip_attach_usage(void) } =20 #define MAX_BUFF 100 -static int record_connection(char *host, char *port, char *busid, int rh= port) +static int record_connection(char *host, char *port, + char *busid, int vhci_ix, int rhport) { int fd; char path[PATH_MAX+1]; @@ -70,7 +72,7 @@ static int record_connection(char *host, char *port, ch= ar *busid, int rhport) return -1; } =20 - snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport); + snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d-%d", vhci_ix, rhport); =20 fd =3D open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU); if (fd < 0) @@ -90,46 +92,78 @@ static int record_connection(char *host, char *port, = char *busid, int rhport) return 0; } =20 -static int import_device(int sockfd, struct usbip_usb_device *udev) +static int import_device(int sockfd, struct usbip_usb_device *udev, + int *pvhci_ix, int *pport) { - int rc; - int port; uint32_t speed =3D udev->speed; + int rc =3D -1; =20 - rc =3D usbip_vhci_driver_open(); - if (rc < 0) { - err("open vhci_driver"); - goto err_out; + struct udev_enumerate *enumerate; + struct udev_list_entry *list, *entry; + + enumerate =3D vhci_enumerate(); + if (!enumerate) { + err("unable to list vhci_hcd drivers"); + return -1; + } + + list =3D udev_enumerate_get_list_entry(enumerate); + if (!list) { + err("unable to list vhci_hcd drivers"); + return -1; } =20 - do { - port =3D usbip_vhci_get_free_port(speed); - if (port < 0) { - err("no free port"); - goto err_driver_close; + udev_list_entry_foreach(entry, list) { + const char *path =3D udev_list_entry_get_name(entry); + int port, vhci_ix; + + if (usbip_vhci_driver_open_path(path) < 0) + continue; + + vhci_ix =3D usbip_vhci_driver_ix(); + + /* Between the moment we read and parse the status + * files and the one we try to attach a socket to the + * port, the later one may become occupied from some + * other process. In order to avoid that race + * condition, we retry on EBUSY errors. On any other + * error we just jump to the next vhci_hcd device + */ + while (1) { + port =3D usbip_vhci_get_free_port(speed); + if (port < 0) + break; + + dbg("got free port %d at %s", port, path); + rc =3D usbip_vhci_attach_device(port, sockfd, + udev->busnum, + udev->devnum, + speed); + + if (rc >=3D 0 || errno !=3D EBUSY) + break; + + usbip_vhci_refresh_device_list(); } =20 - dbg("got free port %d", port); + usbip_vhci_driver_close(); =20 - rc =3D usbip_vhci_attach_device(port, sockfd, udev->busnum, - udev->devnum, udev->speed); - if (rc < 0 && errno !=3D EBUSY) { - err("import device"); - goto err_driver_close; + if (rc >=3D 0) { + *pport =3D port; + *pvhci_ix =3D vhci_ix; + goto done; } - } while (rc < 0); - - usbip_vhci_driver_close(); + } + err("import device failed"); =20 - return port; +done: + udev_enumerate_unref(enumerate); =20 -err_driver_close: - usbip_vhci_driver_close(); -err_out: - return -1; + return rc; } =20 -static int query_import_device(int sockfd, char *busid) +static int query_import_device(int sockfd, char *busid, + int *pvhci_ix, int *pport) { int rc; struct op_import_request request; @@ -178,7 +212,7 @@ static int query_import_device(int sockfd, char *busi= d) } =20 /* import a device */ - return import_device(sockfd, &reply.udev); + return import_device(sockfd, &reply.udev, pvhci_ix, pport); } =20 static int attach_device(char *host, char *busid) @@ -186,6 +220,7 @@ static int attach_device(char *host, char *busid) int sockfd; int rc; int rhport; + int vhci_ix; =20 sockfd =3D usbip_net_tcp_connect(host, usbip_port_string); if (sockfd < 0) { @@ -193,15 +228,15 @@ static int attach_device(char *host, char *busid) return -1; } =20 - rhport =3D query_import_device(sockfd, busid); - if (rhport < 0) { + rc =3D query_import_device(sockfd, busid, &vhci_ix, &rhport); + if (rc < 0) { err("query"); return -1; } =20 close(sockfd); =20 - rc =3D record_connection(host, usbip_port_string, busid, rhport); + rc =3D record_connection(host, usbip_port_string, busid, vhci_ix, rhpor= t); if (rc < 0) { err("record connection"); return -1; diff --git a/tools/usb/usbip/src/usbip_detach.c b/tools/usb/usbip/src/usb= ip_detach.c index 9db9d21bb2ec..06ad88d9959b 100644 --- a/tools/usb/usbip/src/usbip_detach.c +++ b/tools/usb/usbip/src/usbip_detach.c @@ -30,49 +30,39 @@ #include "usbip_common.h" #include "usbip_network.h" #include "usbip.h" +#include "utils.h" =20 static const char usbip_detach_usage_string[] =3D "usbip detach \n" - " -p, --port=3D " USBIP_VHCI_DRV_NAME - " port the device is on\n"; + " -i, --vhci-ix=3D index of the " + USBIP_VHCI_DRV_NAME + " the device is on (defaults to 0)\n" + " -p, --port=3D port the device is on\n"; =20 void usbip_detach_usage(void) { printf("usage: %s", usbip_detach_usage_string); } =20 -static int detach_port(char *port) +static int detach_port(int vhci_ix, int port) { int ret; - uint8_t portnum; char path[PATH_MAX+1]; =20 - unsigned int port_len =3D strlen(port); - - for (unsigned int i =3D 0; i < port_len; i++) - if (!isdigit(port[i])) { - err("invalid port %s", port); - return -1; - } - - /* check max port */ - - portnum =3D atoi(port); - /* remove the port state file */ =20 - snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum); + snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d-%d", vhci_ix, port); =20 remove(path); rmdir(VHCI_STATE_PATH); =20 - ret =3D usbip_vhci_driver_open(); + ret =3D usbip_vhci_driver_open_ix(vhci_ix); if (ret < 0) { err("open vhci_driver"); return -1; } =20 - ret =3D usbip_vhci_detach_device(portnum); + ret =3D usbip_vhci_detach_device(port); if (ret < 0) return -1; =20 @@ -85,28 +75,45 @@ int usbip_detach(int argc, char *argv[]) { static const struct option opts[] =3D { { "port", required_argument, NULL, 'p' }, + { "vhci-ix", 0, NULL, 'i' }, { NULL, 0, NULL, 0 } }; int opt; - int ret =3D -1; + int port =3D -1; + int vhci_ix =3D 0; =20 for (;;) { - opt =3D getopt_long(argc, argv, "p:", opts, NULL); + opt =3D getopt_long(argc, argv, "p:i:", opts, NULL); =20 if (opt =3D=3D -1) break; =20 switch (opt) { case 'p': - ret =3D detach_port(optarg); - goto out; + if (atoi_with_check(optarg, &port) < 0) { + err("bad port number"); + return -1; + } + break; + case 'i': + if (atoi_with_check(optarg, &vhci_ix) < 0) { + err("bad vhci index"); + return -1; + } + break; default: goto err_out; } } + if (optind < argc) + goto err_out; + + if (port < 0) + goto err_out; + + return detach_port(vhci_ix, port); =20 err_out: usbip_detach_usage(); -out: - return ret; + return -1; } diff --git a/tools/usb/usbip/src/usbip_enumerate.c b/tools/usb/usbip/src/= usbip_enumerate.c new file mode 100644 index 000000000000..b6197435b476 --- /dev/null +++ b/tools/usb/usbip/src/usbip_enumerate.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 Qindel Formaci=C3=B3n y Servicios SL + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "usbip_enumerate.h" +#include "vhci_driver.h" + +struct udev_enumerate *vhci_enumerate(void) +{ + struct udev *udev_context =3D NULL; + struct udev_enumerate *enumerate =3D NULL; + int rc; + + udev_context =3D udev_new(); + if (!udev_context) { + err("udev_new failed"); + return NULL; + } + + enumerate =3D udev_enumerate_new(udev_context); + if (!enumerate) { + err("udev_enumerate_new failed"); + goto err; + } + + udev_enumerate_add_match_subsystem(enumerate, USBIP_VHCI_BUS_TYPE); + udev_enumerate_add_match_sysname(enumerate, + USBIP_VHCI_DEVICE_NAME_PATTERN); + rc =3D udev_enumerate_scan_devices(enumerate); + if (rc < 0) { + err("udev_enumerate_scan_devices failed: %d", rc); + udev_enumerate_unref(enumerate); + enumerate =3D NULL; + } + +err: + udev_unref(udev_context); + + return enumerate; +} diff --git a/tools/usb/usbip/src/usbip_enumerate.h b/tools/usb/usbip/src/= usbip_enumerate.h new file mode 100644 index 000000000000..ce1f4e6941d0 --- /dev/null +++ b/tools/usb/usbip/src/usbip_enumerate.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 Qindel Formacion y Servicios SL + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __USBIP_ENUMERATE_H +#define __USBIP_ENUMERATE_H + +#include + +struct udev_enumerate *vhci_enumerate(void); + +#endif /* __USBIP_ENUMERATE_H */ diff --git a/tools/usb/usbip/src/usbip_port.c b/tools/usb/usbip/src/usbip= _port.c index 7bd74fb3a9cd..a981a73b7dfb 100644 --- a/tools/usb/usbip/src/usbip_port.c +++ b/tools/usb/usbip/src/usbip_port.c @@ -13,54 +13,157 @@ * GNU General Public License for more details. */ =20 +#include + #include "vhci_driver.h" #include "usbip_common.h" +#include "usbip_enumerate.h" +#include "utils.h" + +static const char usbip_port_usage_string[] =3D + "usbip port \n" + " -i, --vhci-ix=3D index of the " + USBIP_VHCI_DRV_NAME + " the device is on (defaults to 0)\n" + " -a, --all list the ports from all the available " + USBIP_VHCI_DRV_NAME "'s\n"; + +void usbip_port_usage(void) +{ + printf("usage: %s", usbip_port_usage_string); +} =20 static int list_imported_devices(void) { int i; struct usbip_imported_device *idev; - int ret; + int ret =3D 0; + + for (i =3D 0; i < vhci_driver->nports; i++) { + idev =3D &vhci_driver->idev[i]; =20 + if (usbip_vhci_imported_device_dump(idev) < 0) { + err("unable to list device %d", i); + ret =3D -1; + } + } + return ret; +} + +static void list_imported_devices_header(void) +{ + printf("Imported USB devices\n"); + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"= ); +} + +static int list_imported_devices_ix(int vhci_ix) +{ + int ret; if (usbip_names_init(USBIDS_FILE)) err("failed to open %s", USBIDS_FILE); =20 - ret =3D usbip_vhci_driver_open(); + ret =3D usbip_vhci_driver_open_ix(vhci_ix); if (ret < 0) { err("open vhci_driver"); goto err_names_free; } =20 - printf("Imported USB devices\n"); - printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"= ); + list_imported_devices_header(); + ret =3D list_imported_devices(); + usbip_vhci_driver_close(); +err_names_free: + usbip_names_free(); + return ret; +} =20 - for (i =3D 0; i < vhci_driver->nports; i++) { - idev =3D &vhci_driver->idev[i]; +static int list_imported_devices_all(void) +{ + struct udev_enumerate *enumerate =3D NULL; + struct udev_list_entry *list, *entry; + int rc =3D 0; + + if (usbip_names_init(USBIDS_FILE)) + err("failed to open %s", USBIDS_FILE); =20 - if (usbip_vhci_imported_device_dump(idev) < 0) - goto err_driver_close; + enumerate =3D vhci_enumerate(); + if (!enumerate) { + err("Unable to list vhci_hcd drivers"); + return -1; } =20 - usbip_vhci_driver_close(); - usbip_names_free(); + list =3D udev_enumerate_get_list_entry(enumerate); + if (!list) { + err("Unable to list vhci_hcd drivers"); + return -1; + } =20 - return ret; + list_imported_devices_header(); =20 -err_driver_close: - usbip_vhci_driver_close(); -err_names_free: + udev_list_entry_foreach(entry, list) { + const char *path =3D udev_list_entry_get_name(entry); + int i; + int len =3D printf("VHCI: %s\n", path); + + /* write a line of dashes */ + for (i =3D 1; i < len; i++) + putchar('-'); + putchar('\n'); + + if (usbip_vhci_driver_open_path(path) < 0) { + err("usbip_vhci_driver_open_path"); + rc =3D -1; + continue; + } + if (list_imported_devices() < 0) + rc =3D -1; + usbip_vhci_driver_close(); + } usbip_names_free(); - return -1; + udev_enumerate_unref(enumerate); + + return rc; } =20 int usbip_port_show(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) { - int ret; + int vhci_ix =3D 0; + int all =3D 0; + static const struct option opts[] =3D { + { "vhci-ix", 0, NULL, 'i' }, + { "all", 0, NULL, 'a' }, + { NULL, 0, NULL, 0 } + }; =20 - ret =3D list_imported_devices(); - if (ret < 0) - err("list imported devices"); + for (;;) { + int opt =3D getopt_long(argc, argv, "i:a", opts, NULL); =20 - return ret; + if (opt =3D=3D -1) + break; + switch (opt) { + case 'i': + if (atoi_with_check(optarg, &vhci_ix) < 0) { + err("Bad vhci index"); + return -1; + } + break; + case 'a': + all =3D 1; + break; + default: + goto err_out; + } + } + + if (optind < argc) + goto err_out; + + if (all) + return list_imported_devices_all(); + else + return list_imported_devices_ix(vhci_ix); + +err_out: + usbip_port_usage(); + return -1; } diff --git a/tools/usb/usbip/src/utils.c b/tools/usb/usbip/src/utils.c index 3d7b42e77299..0c55ab4f3d98 100644 --- a/tools/usb/usbip/src/utils.c +++ b/tools/usb/usbip/src/utils.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include =20 #include "usbip_common.h" #include "utils.h" @@ -53,3 +55,17 @@ int modify_match_busid(char *busid, int add) =20 return 0; } + +int atoi_with_check(const char *str, int *pi) +{ + ssize_t len =3D strlen(str); + + for (ssize_t i =3D 0; i < len; i++) { + if (!isdigit(str[i])) { + err("%s is not a number", str); + return -1; + } + } + *pi =3D atoi(str); + return 0; +} diff --git a/tools/usb/usbip/src/utils.h b/tools/usb/usbip/src/utils.h index 5916fd3e02a6..a07d03c9bb12 100644 --- a/tools/usb/usbip/src/utils.h +++ b/tools/usb/usbip/src/utils.h @@ -20,6 +20,7 @@ #define __UTILS_H =20 int modify_match_busid(char *busid, int add); +int atoi_with_check(const char *str, int *pi); =20 #endif /* __UTILS_H */ =20 --=20 2.14.1