Received: by 10.223.176.5 with SMTP id f5csp4032523wra; Tue, 30 Jan 2018 00:47:30 -0800 (PST) X-Google-Smtp-Source: AH8x227PyfIC6wsg+9/xjUMlQRk9WFr+OpsdpeyPKbv+N3PC0k9Ag2i8Wr2bly38btrkAZ6y03zp X-Received: by 10.99.96.81 with SMTP id u78mr23702848pgb.427.1517302050818; Tue, 30 Jan 2018 00:47:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517302050; cv=none; d=google.com; s=arc-20160816; b=odD+2ZAjNyvJG7tkvQELqlVbEMtTA44sQbgAaEJaP248QeimZoT9vAvloemIgehI2B 929ZSYjFB+quwL2mS+AMvOf8e4LPgH/82qaYC0tGpH9QJahg7mM5bngOoZ/wInxBqaZS Jde9NxnWfqrakucS0iptYn5jFlOCaBWXEH9iT7S0ASZKi2OoRcHq2XalTXJNrUcWKIZA SVR9Rof0R6NqIdg2GmJ4V44O8RkDEjMWCPpf1iwuH7P8h+z6stWFFeUfTToItlv9hpCE meGlAC32bAKlnm5gZdUuxkGMzzYYc4dHfSmNv4Tc7JdUKSaq7lRzcGgvTJN2eJDpJdpm t7BA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=Lr/tTUP5Ij6Ep3Nxskqjddazi63nkdUTR+fU3dR1r38=; b=Yo6gmc5Rq09KU+fUcrt2x54Yy3ajirqi4ozQN7uEfXhtN+KtsnC447UluDFBuPvzUY MkFDS3lbH+jhELpP0mNSlgBmDNF9gfc7SqXu8T/WUVqK2Y0meNA7VRdG2CdWsPfesyIx XCge2/J3puNSFc0iAzoh5PMW8C+DbL95z2+TFSiZVzZx0wRnS93yH7ZAfqwusOeDTXIS MVJy3Noz2qa5J0utoFPL+0Dal6dR6kKl7iSi2ENDgbuqL+6m4pBIADJ2caAGK+OOvkel 3FmUdy9bOZJQO3RLA0cqvthMykfEIUjs0UoawCr/3bliQftQyUKKLtTwpviB/RVKkCw9 VF/g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z190si8854893pgd.688.2018.01.30.00.47.16; Tue, 30 Jan 2018 00:47:30 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752088AbeA3IpA convert rfc822-to-8bit (ORCPT + 99 others); Tue, 30 Jan 2018 03:45:00 -0500 Received: from smtp.qindel.com ([89.140.90.34]:59718 "EHLO thor.qindel.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751710AbeA3IoN (ORCPT ); Tue, 30 Jan 2018 03:44:13 -0500 Received: from localhost (localhost [127.0.0.1]) by thor.qindel.com (Postfix) with ESMTP id 10E78601F1; Tue, 30 Jan 2018 09:37:36 +0100 (CET) Received: from thor.qindel.com ([127.0.0.1]) by localhost (thor.qindel.com [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id 2hr9vEKi6fMj; Tue, 30 Jan 2018 09:37:35 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by thor.qindel.com (Postfix) with ESMTP id DA61C601F3; Tue, 30 Jan 2018 09:37:35 +0100 (CET) X-Virus-Scanned: amavisd-new at thor.qindel.com Received: from thor.qindel.com ([127.0.0.1]) by localhost (thor.qindel.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id gKbb3SqCoTBQ; Tue, 30 Jan 2018 09:37:35 +0100 (CET) Received: from atun.int.qindel.com (unknown [172.26.9.84]) by thor.qindel.com (Postfix) with ESMTP id 8C5CD601F1; Tue, 30 Jan 2018 09:37:28 +0100 (CET) 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: 8BIT Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Salvador Fandiño 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ño --- 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/Makefile.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 := usbip usbipd usbip_SOURCES := 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 usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_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" static const char usbip_attach_usage_string[] = "usbip attach \n" @@ -48,7 +49,8 @@ void usbip_attach_usage(void) } #define MAX_BUFF 100 -static int record_connection(char *host, char *port, char *busid, int rhport) +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, char *busid, int rhport) return -1; } - snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport); + snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d-%d", vhci_ix, rhport); fd = 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; } -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 = udev->speed; + int rc = -1; - rc = 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 = vhci_enumerate(); + if (!enumerate) { + err("unable to list vhci_hcd drivers"); + return -1; + } + + list = udev_enumerate_get_list_entry(enumerate); + if (!list) { + err("unable to list vhci_hcd drivers"); + return -1; } - do { - port = 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 = udev_list_entry_get_name(entry); + int port, vhci_ix; + + if (usbip_vhci_driver_open_path(path) < 0) + continue; + + vhci_ix = 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 = usbip_vhci_get_free_port(speed); + if (port < 0) + break; + + dbg("got free port %d at %s", port, path); + rc = usbip_vhci_attach_device(port, sockfd, + udev->busnum, + udev->devnum, + speed); + + if (rc >= 0 || errno != EBUSY) + break; + + usbip_vhci_refresh_device_list(); } - dbg("got free port %d", port); + usbip_vhci_driver_close(); - rc = usbip_vhci_attach_device(port, sockfd, udev->busnum, - udev->devnum, udev->speed); - if (rc < 0 && errno != EBUSY) { - err("import device"); - goto err_driver_close; + if (rc >= 0) { + *pport = port; + *pvhci_ix = vhci_ix; + goto done; } - } while (rc < 0); - - usbip_vhci_driver_close(); + } + err("import device failed"); - return port; +done: + udev_enumerate_unref(enumerate); -err_driver_close: - usbip_vhci_driver_close(); -err_out: - return -1; + return rc; } -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 *busid) } /* import a device */ - return import_device(sockfd, &reply.udev); + return import_device(sockfd, &reply.udev, pvhci_ix, pport); } 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; sockfd = 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; } - rhport = query_import_device(sockfd, busid); - if (rhport < 0) { + rc = query_import_device(sockfd, busid, &vhci_ix, &rhport); + if (rc < 0) { err("query"); return -1; } close(sockfd); - rc = record_connection(host, usbip_port_string, busid, rhport); + rc = record_connection(host, usbip_port_string, busid, vhci_ix, rhport); if (rc < 0) { err("record connection"); return -1; diff --git a/tools/usb/usbip/src/usbip_detach.c b/tools/usb/usbip/src/usbip_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" static const char usbip_detach_usage_string[] = "usbip detach \n" - " -p, --port= " USBIP_VHCI_DRV_NAME - " port the device is on\n"; + " -i, --vhci-ix= index of the " + USBIP_VHCI_DRV_NAME + " the device is on (defaults to 0)\n" + " -p, --port= port the device is on\n"; void usbip_detach_usage(void) { printf("usage: %s", usbip_detach_usage_string); } -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]; - unsigned int port_len = strlen(port); - - for (unsigned int i = 0; i < port_len; i++) - if (!isdigit(port[i])) { - err("invalid port %s", port); - return -1; - } - - /* check max port */ - - portnum = atoi(port); - /* remove the port state file */ - snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum); + snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d-%d", vhci_ix, port); remove(path); rmdir(VHCI_STATE_PATH); - ret = usbip_vhci_driver_open(); + ret = usbip_vhci_driver_open_ix(vhci_ix); if (ret < 0) { err("open vhci_driver"); return -1; } - ret = usbip_vhci_detach_device(portnum); + ret = usbip_vhci_detach_device(port); if (ret < 0) return -1; @@ -85,28 +75,45 @@ int usbip_detach(int argc, char *argv[]) { static const struct option opts[] = { { "port", required_argument, NULL, 'p' }, + { "vhci-ix", 0, NULL, 'i' }, { NULL, 0, NULL, 0 } }; int opt; - int ret = -1; + int port = -1; + int vhci_ix = 0; for (;;) { - opt = getopt_long(argc, argv, "p:", opts, NULL); + opt = getopt_long(argc, argv, "p:i:", opts, NULL); if (opt == -1) break; switch (opt) { case 'p': - ret = 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); 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ón 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 = NULL; + struct udev_enumerate *enumerate = NULL; + int rc; + + udev_context = udev_new(); + if (!udev_context) { + err("udev_new failed"); + return NULL; + } + + enumerate = 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 = udev_enumerate_scan_devices(enumerate); + if (rc < 0) { + err("udev_enumerate_scan_devices failed: %d", rc); + udev_enumerate_unref(enumerate); + enumerate = 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. */ +#include + #include "vhci_driver.h" #include "usbip_common.h" +#include "usbip_enumerate.h" +#include "utils.h" + +static const char usbip_port_usage_string[] = + "usbip port \n" + " -i, --vhci-ix= 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); +} static int list_imported_devices(void) { int i; struct usbip_imported_device *idev; - int ret; + int ret = 0; + + for (i = 0; i < vhci_driver->nports; i++) { + idev = &vhci_driver->idev[i]; + if (usbip_vhci_imported_device_dump(idev) < 0) { + err("unable to list device %d", i); + ret = -1; + } + } + return ret; +} + +static void list_imported_devices_header(void) +{ + printf("Imported USB devices\n"); + printf("====================\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); - ret = usbip_vhci_driver_open(); + ret = usbip_vhci_driver_open_ix(vhci_ix); if (ret < 0) { err("open vhci_driver"); goto err_names_free; } - printf("Imported USB devices\n"); - printf("====================\n"); + list_imported_devices_header(); + ret = list_imported_devices(); + usbip_vhci_driver_close(); +err_names_free: + usbip_names_free(); + return ret; +} - for (i = 0; i < vhci_driver->nports; i++) { - idev = &vhci_driver->idev[i]; +static int list_imported_devices_all(void) +{ + struct udev_enumerate *enumerate = NULL; + struct udev_list_entry *list, *entry; + int rc = 0; + + if (usbip_names_init(USBIDS_FILE)) + err("failed to open %s", USBIDS_FILE); - if (usbip_vhci_imported_device_dump(idev) < 0) - goto err_driver_close; + enumerate = vhci_enumerate(); + if (!enumerate) { + err("Unable to list vhci_hcd drivers"); + return -1; } - usbip_vhci_driver_close(); - usbip_names_free(); + list = udev_enumerate_get_list_entry(enumerate); + if (!list) { + err("Unable to list vhci_hcd drivers"); + return -1; + } - return ret; + list_imported_devices_header(); -err_driver_close: - usbip_vhci_driver_close(); -err_names_free: + udev_list_entry_foreach(entry, list) { + const char *path = udev_list_entry_get_name(entry); + int i; + int len = printf("VHCI: %s\n", path); + + /* write a line of dashes */ + for (i = 1; i < len; i++) + putchar('-'); + putchar('\n'); + + if (usbip_vhci_driver_open_path(path) < 0) { + err("usbip_vhci_driver_open_path"); + rc = -1; + continue; + } + if (list_imported_devices() < 0) + rc = -1; + usbip_vhci_driver_close(); + } usbip_names_free(); - return -1; + udev_enumerate_unref(enumerate); + + return rc; } int usbip_port_show(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) { - int ret; + int vhci_ix = 0; + int all = 0; + static const struct option opts[] = { + { "vhci-ix", 0, NULL, 'i' }, + { "all", 0, NULL, 'a' }, + { NULL, 0, NULL, 0 } + }; - ret = list_imported_devices(); - if (ret < 0) - err("list imported devices"); + for (;;) { + int opt = getopt_long(argc, argv, "i:a", opts, NULL); - return ret; + if (opt == -1) + break; + switch (opt) { + case 'i': + if (atoi_with_check(optarg, &vhci_ix) < 0) { + err("Bad vhci index"); + return -1; + } + break; + case 'a': + all = 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 #include "usbip_common.h" #include "utils.h" @@ -53,3 +55,17 @@ int modify_match_busid(char *busid, int add) return 0; } + +int atoi_with_check(const char *str, int *pi) +{ + ssize_t len = strlen(str); + + for (ssize_t i = 0; i < len; i++) { + if (!isdigit(str[i])) { + err("%s is not a number", str); + return -1; + } + } + *pi = 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 int modify_match_busid(char *busid, int add); +int atoi_with_check(const char *str, int *pi); #endif /* __UTILS_H */ -- 2.14.1