[PATCH v13 07/10] usbip: exporting devices: new application-side daemon

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

 



This patch is the new application(vhci)-side daemon specific code.

The daemons are consisting three files.
usbip.c : common code.
usbip_dev.c: device(stub)-side specific code.
usbip_app.c: application(vhci)-side specific code - this patch.

Here, device-side daemon is EXISTING-1 and application-side daemon is 
NEW-1 in figure below.

EXISTING) - invites devices from application(vhci)-side
         +------+                                 +------------------+
 device--+ STUB |                                 | application/VHCI |
         +------+                                 +------------------+
 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(stb)-side
         +------+                                 +------------------+
 device--+ STUB |                                 | application/VHCI |
         +------+                                 +------------------+
                                              1) usbipa ... start daemon
 = = =
 2) usbip list --local
 3) usbip connect     --- export a device ------>
 = = =
 4) usbip disconnect  --- un-export a device --->

Signed-off-by: Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx>
---
 tools/usb/usbip/libsrc/vhci_driver.c |  19 +++
 tools/usb/usbip/libsrc/vhci_driver.h |   1 +
 tools/usb/usbip/src/Makefile.am      |   7 +-
 tools/usb/usbip/src/usbipd.c         |  12 +-
 tools/usb/usbip/src/usbipd_app.c     | 242 +++++++++++++++++++++++++++
 5 files changed, 279 insertions(+), 2 deletions(-)

diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
index d2221c5..3fe92ff 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.c
+++ b/tools/usb/usbip/libsrc/vhci_driver.c
@@ -314,6 +314,25 @@ int usbip_vhci_get_free_port(void)
 	return -1;
 }
 
+struct usbip_imported_device *usbip_vhci_find_device(char *host, char *busid)
+{
+	int ret;
+	char rhost[NI_MAXHOST] = "unknown host";
+	char rserv[NI_MAXSERV] = "unknown port";
+	char rbusid[SYSFS_BUS_ID_SIZE];
+
+	for (int i = 0; i < vhci_driver->nports; i++) {
+		ret = read_record(vhci_driver->idev[i].port, rhost, NI_MAXHOST,
+				rserv, NI_MAXSERV, rbusid);
+		if (!ret &&
+			!strncmp(host, rhost, NI_MAXHOST) &&
+			!strncmp(busid, rbusid, SYSFS_BUS_ID_SIZE)) {
+			return vhci_driver->idev + i;
+		}
+	}
+	return NULL;
+}
+
 int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
 		uint32_t speed) {
 	char buff[200]; /* what size should be ? */
diff --git a/tools/usb/usbip/libsrc/vhci_driver.h b/tools/usb/usbip/libsrc/vhci_driver.h
index f955ada..acb427d 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.h
+++ b/tools/usb/usbip/libsrc/vhci_driver.h
@@ -46,6 +46,7 @@ int  usbip_vhci_refresh_device_list(void);
 
 
 int usbip_vhci_get_free_port(void);
+struct usbip_imported_device *usbip_vhci_find_device(char *host, char *busid);
 int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
 		uint32_t speed);
 
diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefile.am
index 1aa5156..8fdebce 100644
--- a/tools/usb/usbip/src/Makefile.am
+++ b/tools/usb/usbip/src/Makefile.am
@@ -2,11 +2,16 @@ AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
 AM_CFLAGS   = @EXTRA_CFLAGS@
 LDADD       = $(top_builddir)/libsrc/libusbip.la
 
-sbin_PROGRAMS := usbip usbipd
+sbin_PROGRAMS := usbip usbipd usbipa
 
 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_connect.c usbip_disconnect.c
+usbip_CFLAGS := $(AM_CFLAGS)
 
 usbipd_SOURCES := usbip_network.h usbipd.c usbipd_dev.c usbip_network.c
+usbipd_CFLAGS := $(AM_CFLAGS)
+
+usbipa_SOURCES := usbip_network.h usbipd.c usbipd_app.c usbip_network.c
+usbipa_CFLAGS := $(AM_CFLAGS) -DUSBIP_DAEMON_APP
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index bc4775f..8fe89d9 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -64,11 +64,13 @@ static const char usbipd_help_string[] =
 	"	-6, --ipv6\n"
 	"		Bind to IPv6. Default is both.\n"
 	"\n"
+#ifndef USBIP_DAEMON_APP
 	"	-e, --device\n"
 	"		Run in device mode.\n"
 	"		Rather than drive an attached device, create\n"
 	"		a virtual UDC to bind gadgets to.\n"
 	"\n"
+#endif
 	"	-D, --daemon\n"
 	"		Run as a daemon process.\n"
 	"\n"
@@ -397,7 +399,9 @@ int main(int argc, char *argv[])
 		{ "ipv6",     no_argument,       NULL, '6' },
 		{ "daemon",   no_argument,       NULL, 'D' },
 		{ "debug",    no_argument,       NULL, 'd' },
+#ifndef USBIP_DAEMON_APP
 		{ "device",   no_argument,       NULL, 'e' },
+#endif
 		{ "pid",      optional_argument, NULL, 'P' },
 		{ "tcp-port", required_argument, NULL, 't' },
 		{ "help",     no_argument,       NULL, 'h' },
@@ -426,7 +430,11 @@ int main(int argc, char *argv[])
 	cmd = cmd_standalone_mode;
 	usbip_init_driver();
 	for (;;) {
-		opt = getopt_long(argc, argv, "46DdeP::t:hv", longopts, NULL);
+		opt = getopt_long(argc, argv, "46Dd"
+#ifndef USBIP_DAEMON_APP
+				  "e"
+#endif
+				  "P::t:hv", longopts, NULL);
 
 		if (opt == -1)
 			break;
@@ -456,9 +464,11 @@ int main(int argc, char *argv[])
 		case 'v':
 			cmd = cmd_version;
 			break;
+#ifndef USBIP_DAEMON_APP
 		case 'e':
 			usbip_update_driver();
 			break;
+#endif
 		case '?':
 			usbipd_help();
 		default:
diff --git a/tools/usb/usbip/src/usbipd_app.c b/tools/usb/usbip/src/usbipd_app.c
new file mode 100644
index 0000000..41f42f1
--- /dev/null
+++ b/tools/usb/usbip/src/usbipd_app.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *               2011 matt mooney <mfm@xxxxxxxxxxxxx>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "vhci_driver.h"
+#include "usbip_common.h"
+#include "usbip_network.h"
+
+char *usbip_progname = "usbipa";
+char *usbip_default_pid_file = "/var/run/usbipa";
+
+void usbip_init_driver(void)
+{
+}
+
+int usbip_open_driver(void)
+{
+	if (usbip_vhci_driver_open()) {
+		err("please load " USBIP_CORE_MOD_NAME ".ko and "
+			USBIP_VHCI_DRV_NAME ".ko!");
+		return -1;
+	}
+	return 0;
+}
+
+void usbip_close_driver(void)
+{
+	usbip_vhci_driver_close();
+}
+
+static int import_device(int sockfd, struct usbip_usb_device *udev)
+{
+	int rc;
+	int port;
+
+	dbg("Sockfd:%d", sockfd);
+	port = usbip_vhci_get_free_port();
+	if (port < 0) {
+		err("no free port");
+		return -1;
+	}
+
+	dump_usb_device(udev);
+	rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
+					udev->devnum, udev->speed);
+	if (rc < 0) {
+		err("import device");
+		return -1;
+	}
+
+	return port;
+}
+
+static int recv_request_export(int sockfd, char *host, char *port)
+{
+	struct op_export_request req;
+	struct op_export_reply reply;
+	int rhport = 0;
+	int error = 0;
+	int rc;
+
+	memset(&req, 0, sizeof(req));
+	memset(&reply, 0, sizeof(reply));
+
+	rc = usbip_net_recv(sockfd, &req, sizeof(req));
+	if (rc < 0) {
+		dbg("usbip_net_recv failed: export request");
+		return -1;
+	}
+	PACK_OP_EXPORT_REQUEST(0, &req);
+
+	rhport = import_device(sockfd, &req.udev);
+	if (rhport < 0) {
+		dbg("export request busid %s: failed", req.udev.busid);
+		error = 1;
+	}
+
+	rc = usbip_net_send_op_common(sockfd, OP_REP_EXPORT,
+				      (!error ? ST_OK : ST_NA));
+	if (rc < 0) {
+		dbg("usbip_net_send_op_common failed: %#0x", OP_REP_EXPORT);
+		return -1;
+	}
+
+	if (!error)
+		reply.returncode = 0;
+	else
+		reply.returncode = -1;
+
+	PACK_OP_EXPORT_REPLY(0, &rep);
+
+	rc = usbip_net_send(sockfd, &reply, sizeof(reply));
+	if (rc < 0) {
+		dbg("usbip_net_send failed: export reply");
+		return -1;
+	}
+
+	rc = usbip_vhci_create_record(host, port, req.udev.busid, rhport);
+	if (rc < 0) {
+		err("record connection");
+		return -1;
+	}
+
+	dbg("export request busid %s: complete", req.udev.busid);
+
+	return 0;
+}
+
+static int unimport_device(char *host, struct usbip_usb_device *udev)
+{
+	int rc;
+	struct usbip_imported_device *idev;
+
+	idev = usbip_vhci_find_device(host, udev->busid);
+	if (idev == NULL) {
+		err("no imported port %s %s", host, udev->busid);
+		return -1;
+	}
+
+	rc = usbip_vhci_detach_device(idev->port);
+	if (rc < 0) {
+		err("no imported port %d %s %s", idev->port, host, udev->busid);
+		return -1;
+	}
+	return idev->port;
+}
+
+static int recv_request_unexport(int sockfd, char *host)
+{
+	struct op_unexport_request req;
+	struct op_unexport_reply reply;
+	int rhport = 0;
+	int error = 0;
+	int rc;
+
+	memset(&req, 0, sizeof(req));
+	memset(&reply, 0, sizeof(reply));
+
+	rc = usbip_net_recv(sockfd, &req, sizeof(req));
+	if (rc < 0) {
+		dbg("usbip_net_recv failed: unexport request");
+		return -1;
+	}
+	PACK_OP_UNEXPORT_REQUEST(0, &req);
+
+	rhport = unimport_device(host, &req.udev);
+	if (rhport < 0)
+		error = 1;
+
+	rc = usbip_net_send_op_common(sockfd, OP_REP_UNEXPORT,
+				      (!error ? ST_OK : ST_NA));
+	if (rc < 0) {
+		dbg("usbip_net_send_op_common failed: %#0x", OP_REP_UNEXPORT);
+		return -1;
+	}
+
+	if (!error) {
+		reply.returncode = 0;
+	} else {
+		reply.returncode = -1;
+		dbg("unexport request busid %s: failed", req.udev.busid);
+		return -1;
+	}
+	PACK_OP_UNEXPORT_REPLY(0, &rep);
+
+	rc = usbip_net_send(sockfd, &reply, sizeof(reply));
+	if (rc < 0) {
+		dbg("usbip_net_send failed: unexport reply");
+		return -1;
+	}
+
+	usbip_vhci_delete_record(rhport);
+
+	dbg("unexport request busid %s: complete", req.udev.busid);
+
+	return 0;
+}
+
+int usbip_recv_pdu(int connfd, char *host, char *port)
+{
+	uint16_t code = OP_UNSPEC;
+	int ret;
+
+	ret = usbip_net_recv_op_common(connfd, &code);
+	if (ret < 0) {
+		dbg("could not receive opcode: %#0x", code);
+		return -1;
+	}
+
+	ret = usbip_vhci_refresh_device_list();
+	if (ret < 0) {
+		dbg("could not refresh device list: %d", ret);
+		return -1;
+	}
+
+	info("received request: %#0x(%d)", code, connfd);
+	switch (code) {
+	case OP_REQ_EXPORT:
+		ret = recv_request_export(connfd, host, port);
+		break;
+	case OP_REQ_UNEXPORT:
+		ret = recv_request_unexport(connfd, host);
+		break;
+	default:
+		err("received an unknown opcode: %#0x", code);
+		ret = -1;
+	}
+
+	if (ret == 0)
+		info("request %#0x(%s:%s): complete", code, host, port);
+	else
+		info("request %#0x(%s:%s): failed", code, host, port);
+
+	return ret;
+}
-- 
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