[PATCH v14 06/10] usbip: exporting devices: modifications to attach and detach

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Refactoring to attach and detach operation to reuse common portion to 
application(vhci)-side daemon.

The new application(vhci)-side daemon executes same procedures as 
attach and detach. Most of common code to access vhci has been 
implemented in VHCI userspace wrapper(libsrc/vhci_driver.c) but left in 
attach and detach. With this patch, an accessor of vhci driver and 
tracking of vhci connections in attach and detach are moved to the VHCI 
userspace wrapper.

Functions to create and delete port status file also moved to the 
wrapper. Timing to execute these function are corrected to keep 
consistent with attached status of vhci.
 
Here, attach, detach and application(vhci)-side daemon is EXISTING-5, 
EXISTING-6 and NEW-1 respectively in diagram below. 

EXISTING) - invites devices from application(vhci)-side
         +------+                               +------------------+
 device--+ STUB |                               | application/VHCI |
         +------+                               +------------------+
         (server)                               (client)
 1) # usbipd ... start daemon
 = = =
 2) # usbip list --local
 3) # usbip bind
                  <--- list bound devices ---  4) # usbip list --remote
                  <--- import a device ------  5) # usbip attach
 = = =
                     X disconnected            6) # usbip detach
 7) usbip unbind

NEW) - dedicates devices from device(stub)-side
         +------+                               +------------------+
 device--+ STUB |                               | application/VHCI |
         +------+                               +------------------+
         (client)                               (server)
                                            1) # usbipa ... start daemon
 = = =
 2) # usbip list --local
 3) # usbip connect    --- export a device ------>
 = = =
 4) # usbip disconnect --- un-export a device --->

 Bind and unbind are done in connect and disconnect internally.

Signed-off-by: Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx>
---
 tools/usb/usbip/libsrc/vhci_driver.c | 96 +++++++++++++++++++++++----
 tools/usb/usbip/libsrc/vhci_driver.h |  3 +
 tools/usb/usbip/src/usbip_attach.c   | 99 +++++++++-------------------
 tools/usb/usbip/src/usbip_detach.c   | 17 ++---
 4 files changed, 124 insertions(+), 91 deletions(-)

diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
index ad92047..5843f43 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.c
+++ b/tools/usb/usbip/libsrc/vhci_driver.c
@@ -7,6 +7,8 @@
 #include <limits.h>
 #include <netdb.h>
 #include <libudev.h>
+#include <fcntl.h>
+#include <errno.h>
 #include "sysfs_utils.h"
 
 #undef  PROGNAME
@@ -215,6 +217,25 @@ static int read_record(int rhport, char *host, unsigned long host_len,
 	return 0;
 }
 
+#define OPEN_HC_MODE_FIRST	0
+#define OPEN_HC_MODE_REOPEN	1
+
+static int open_hc_device(int mode)
+{
+	if (mode == OPEN_HC_MODE_REOPEN)
+		udev_device_unref(vhci_driver->hc_device);
+
+	vhci_driver->hc_device =
+		udev_device_new_from_subsystem_sysname(udev_context,
+						       USBIP_VHCI_BUS_TYPE,
+						       USBIP_VHCI_DRV_NAME);
+	if (!vhci_driver->hc_device) {
+		err("udev_device_new_from_subsystem_sysname failed");
+		return -1;
+	}
+	return 0;
+}
+
 /* ---------------------------------------------------------------------- */
 
 int usbip_vhci_driver_open(void)
@@ -227,28 +248,21 @@ int usbip_vhci_driver_open(void)
 
 	vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver));
 
-	/* will be freed in usbip_driver_close() */
-	vhci_driver->hc_device =
-		udev_device_new_from_subsystem_sysname(udev_context,
-						       USBIP_VHCI_BUS_TYPE,
-						       USBIP_VHCI_DRV_NAME);
-	if (!vhci_driver->hc_device) {
-		err("udev_device_new_from_subsystem_sysname failed");
-		goto err;
-	}
+	if (open_hc_device(OPEN_HC_MODE_FIRST))
+		goto err_free_driver;
 
 	vhci_driver->nports = get_nports();
 
 	dbg("available ports: %d", vhci_driver->nports);
 
 	if (refresh_imported_device_list())
-		goto err;
+		goto err_unref_device;
 
 	return 0;
 
-err:
+err_unref_device:
 	udev_device_unref(vhci_driver->hc_device);
-
+err_free_driver:
 	if (vhci_driver)
 		free(vhci_driver);
 
@@ -277,7 +291,8 @@ void usbip_vhci_driver_close(void)
 
 int usbip_vhci_refresh_device_list(void)
 {
-
+	if (open_hc_device(OPEN_HC_MODE_REOPEN))
+		goto err;
 	if (refresh_imported_device_list())
 		goto err;
 
@@ -409,3 +424,58 @@ int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
 
 	return 0;
 }
+
+#define MAX_BUFF 100
+int usbip_vhci_create_record(char *host, char *port, char *busid, int rhport)
+{
+	int fd;
+	char path[PATH_MAX+1];
+	char buff[MAX_BUFF+1];
+	int ret;
+
+	ret = mkdir(VHCI_STATE_PATH, 0700);
+	if (ret < 0) {
+		/* if VHCI_STATE_PATH exists, then it better be a directory */
+		if (errno == EEXIST) {
+			struct stat s;
+
+			ret = stat(VHCI_STATE_PATH, &s);
+			if (ret < 0)
+				return -1;
+			if (!(s.st_mode & S_IFDIR))
+				return -1;
+		} else
+			return -1;
+	}
+
+	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
+
+	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0700);
+	if (fd < 0)
+		return -1;
+
+	snprintf(buff, MAX_BUFF, "%s %s %s\n",
+			host, port, busid);
+
+	ret = write(fd, buff, strlen(buff));
+	if (ret != (ssize_t) strlen(buff)) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+
+	return 0;
+}
+
+int usbip_vhci_delete_record(int rhport)
+{
+	char path[PATH_MAX+1];
+
+	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
+
+	remove(path);
+	rmdir(VHCI_STATE_PATH);
+
+	return 0;
+}
diff --git a/tools/usb/usbip/libsrc/vhci_driver.h b/tools/usb/usbip/libsrc/vhci_driver.h
index fa2316c..c85988c 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.h
+++ b/tools/usb/usbip/libsrc/vhci_driver.h
@@ -54,6 +54,9 @@ int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
 
 int usbip_vhci_detach_device(uint8_t port);
 
+int usbip_vhci_create_record(char *host, char *port, char *busid, int rhport);
+int usbip_vhci_delete_record(int rhport);
+
 int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev);
 
 #endif /* __VHCI_DRIVER_H */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index 695b2e5..17a84ea 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2015-2016 Samsung Electronics
  *               Igor Kotrasinski <i.kotrasinsk@xxxxxxxxxxx>
  *               Krzysztof Opasiak <k.opasiak@xxxxxxxxxxx>
+ * Copyright (C) 2015-2016 Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx>
  *
  * 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
@@ -26,7 +27,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <fcntl.h>
 #include <getopt.h>
 #include <unistd.h>
 #include <errno.h>
@@ -47,83 +47,53 @@ void usbip_attach_usage(void)
 	printf("usage: %s", usbip_attach_usage_string);
 }
 
-#define MAX_BUFF 100
-static int record_connection(char *host, char *port, char *busid, int rhport)
-{
-	int fd;
-	char path[PATH_MAX+1];
-	char buff[MAX_BUFF+1];
-	int ret;
-
-	ret = mkdir(VHCI_STATE_PATH, 0700);
-	if (ret < 0) {
-		/* if VHCI_STATE_PATH exists, then it better be a directory */
-		if (errno == EEXIST) {
-			struct stat s;
-
-			ret = stat(VHCI_STATE_PATH, &s);
-			if (ret < 0)
-				return -1;
-			if (!(s.st_mode & S_IFDIR))
-				return -1;
-		} else
-			return -1;
-	}
-
-	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
-
-	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
-	if (fd < 0)
-		return -1;
-
-	snprintf(buff, MAX_BUFF, "%s %s %s\n",
-			host, port, busid);
-
-	ret = write(fd, buff, strlen(buff));
-	if (ret != (ssize_t) strlen(buff)) {
-		close(fd);
-		return -1;
-	}
-
-	close(fd);
-
-	return 0;
-}
-
-static int import_device(int sockfd, struct usbip_usb_device *udev)
+static int import_device(int sockfd, struct usbip_usb_device *udev,
+			 char *host, char *port, char *busid)
 {
 	int rc;
-	int port;
+	int rhport;
 
 	rc = usbip_vhci_driver_open();
 	if (rc < 0) {
 		err("open vhci_driver");
-		return -1;
+		goto err_out;
 	}
 
 	do {
-		port = usbip_vhci_get_free_port();
-		if (port < 0) {
+		rhport = usbip_vhci_get_free_port();
+		if (rhport < 0) {
 			err("no free port");
-			usbip_vhci_driver_close();
-			return -1;
+			goto err_driver_close;
 		}
 
-		rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
+		rc = usbip_vhci_attach_device(rhport, sockfd, udev->busnum,
 					      udev->devnum, udev->speed);
 		if (rc < 0 && errno != EBUSY) {
 			err("import device");
-			usbip_vhci_driver_close();
+			goto err_driver_close;
 			return -1;
 		}
 	} while (rc < 0);
 
+	rc = usbip_vhci_create_record(host, port, busid, rhport);
+	if (rc < 0) {
+		err("record connection");
+		goto err_detach_device;
+	}
+
 	usbip_vhci_driver_close();
 
-	return port;
+	return 0;
+
+err_detach_device:
+	usbip_vhci_detach_device(rhport);
+err_driver_close:
+	usbip_vhci_driver_close();
+err_out:
+	return -1;
 }
 
-static int query_import_device(int sockfd, char *busid)
+static int query_import_device(int sockfd, char *host, char *port, char *busid)
 {
 	int rc;
 	struct op_import_request request;
@@ -171,15 +141,13 @@ static int query_import_device(int sockfd, char *busid)
 		return -1;
 	}
 
-	/* import a device */
-	return import_device(sockfd, &reply.udev);
+	return import_device(sockfd, &reply.udev, host, port, busid);
 }
 
-static int attach_device(char *host, char *busid)
+static int attach_device(char *host, char *port, char *busid)
 {
 	int sockfd;
 	int rc;
-	int rhport;
 
 	sockfd = usbip_net_tcp_connect(host, usbip_port_string);
 	if (sockfd < 0) {
@@ -187,20 +155,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, host, port, busid);
+	if (rc < 0) {
 		err("query");
+		close(sockfd);
 		return -1;
 	}
 
 	close(sockfd);
 
-	rc = record_connection(host, usbip_port_string, busid, rhport);
-	if (rc < 0) {
-		err("record connection");
-		return -1;
-	}
-
 	return 0;
 }
 
@@ -239,7 +202,7 @@ int usbip_attach(int argc, char *argv[])
 	if (!host || !busid)
 		goto err_out;
 
-	ret = attach_device(host, busid);
+	ret = attach_device(host, usbip_port_string, busid);
 	goto out;
 
 err_out:
diff --git a/tools/usb/usbip/src/usbip_detach.c b/tools/usb/usbip/src/usbip_detach.c
index 9db9d21..d6d9e99 100644
--- a/tools/usb/usbip/src/usbip_detach.c
+++ b/tools/usb/usbip/src/usbip_detach.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2011 matt mooney <mfm@xxxxxxxxxxxxx>
  *               2005-2007 Takahiro Hirofuchi
+ * Copyright (C) 2015-2016 Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx>
  *
  * 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
@@ -45,7 +46,6 @@ static int detach_port(char *port)
 {
 	int ret;
 	uint8_t portnum;
-	char path[PATH_MAX+1];
 
 	unsigned int port_len = strlen(port);
 
@@ -59,13 +59,6 @@ static int detach_port(char *port)
 
 	portnum = atoi(port);
 
-	/* remove the port state file */
-
-	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);
-
-	remove(path);
-	rmdir(VHCI_STATE_PATH);
-
 	ret = usbip_vhci_driver_open();
 	if (ret < 0) {
 		err("open vhci_driver");
@@ -73,12 +66,16 @@ static int detach_port(char *port)
 	}
 
 	ret = usbip_vhci_detach_device(portnum);
-	if (ret < 0)
+	if (ret < 0) {
+		usbip_vhci_driver_close();
 		return -1;
+	}
+
+	usbip_vhci_delete_record(portnum);
 
 	usbip_vhci_driver_close();
 
-	return ret;
+	return 0;
 }
 
 int usbip_detach(int argc, char *argv[])
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux