Implementation of new disconnect operation. This is linked as a part of
usbip command. With this patch, usbip command has following operations.
bind
unbind
list (local/remote)
attach
detach
port
connect ... previous patch
disconnect ... this patch
In device side node, this sends an un-export request, receives an
un-export response and unbind corresponding device internally. The
definition of the request and response are defined in original code:
tools/usb/usbip/usbip_network.h but was not used. It's corresponding to
NEW-4 in following diagram.
To find disconnecting device, requesting host and requested
bus-id-in-requester identifies the target. So it cannot to disconnect a
device from other host than a host which connected the device.
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 <[email protected]>
---
tools/usb/usbip/src/Makefile.am | 2 +-
tools/usb/usbip/src/usbip.c | 6 +
tools/usb/usbip/src/usbip.h | 2 +
tools/usb/usbip/src/usbip_disconnect.c | 200 +++++++++++++++++++++++++
4 files changed, 209 insertions(+), 1 deletion(-)
diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefile.am
index 0947476..42760c3 100644
--- a/tools/usb/usbip/src/Makefile.am
+++ b/tools/usb/usbip/src/Makefile.am
@@ -7,6 +7,6 @@ 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_connect.c
+ usbip_connect.c usbip_disconnect.c
usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c
diff --git a/tools/usb/usbip/src/usbip.c b/tools/usb/usbip/src/usbip.c
index ad2a259..ead88a2 100644
--- a/tools/usb/usbip/src/usbip.c
+++ b/tools/usb/usbip/src/usbip.c
@@ -83,6 +83,12 @@ static const struct command cmds[] = {
.usage = usbip_connect_usage
},
{
+ .name = "disconnect",
+ .fn = usbip_disconnect,
+ .help = "Disconnect a USB device from a remote computer",
+ .usage = usbip_disconnect_usage
+ },
+ {
.name = "list",
.fn = usbip_list,
.help = "List exportable or local USB devices",
diff --git a/tools/usb/usbip/src/usbip.h b/tools/usb/usbip/src/usbip.h
index 3c22c27..b6537ef 100644
--- a/tools/usb/usbip/src/usbip.h
+++ b/tools/usb/usbip/src/usbip.h
@@ -32,6 +32,7 @@ int usbip_bind(int argc, char *argv[]);
int usbip_unbind(int argc, char *argv[]);
int usbip_port_show(int argc, char *argv[]);
int usbip_connect(int argc, char *argv[]);
+int usbip_disconnect(int argc, char *argv[]);
void usbip_attach_usage(void);
void usbip_detach_usage(void);
@@ -39,6 +40,7 @@ void usbip_list_usage(void);
void usbip_bind_usage(void);
void usbip_unbind_usage(void);
void usbip_connect_usage(void);
+void usbip_disconnect_usage(void);
int usbip_bind_device(char *busid);
int usbip_unbind_device(char *busid);
diff --git a/tools/usb/usbip/src/usbip_disconnect.c
b/tools/usb/usbip/src/usbip_disconnect.c
new file mode 100644
index 0000000..4ee7feb
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_disconnect.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2011 matt mooney <[email protected]>
+ * 2005-2007 Takahiro Hirofuchi
+ * Copyright (C) 2015-2016 Nobuo Iwata <[email protected]>
+ *
+ * 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/>.
+ */
+
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include "usbip_host_driver.h"
+#include "usbip_host_common.h"
+#include "usbip_device_driver.h"
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static struct usbip_host_driver *driver = &host_driver;
+
+static const char usbip_disconnect_usage_string[] =
+ "usbip disconnect <args>\n"
+ " -r, --remote=<host> Address of a remote computer\n"
+ " -b, --busid=<busid> Bus ID of a device to be disconnected\n"
+ " -d, --device Run with an alternate driver, e.g. vUDC\n";
+
+void usbip_disconnect_usage(void)
+{
+ printf("usage: %s", usbip_disconnect_usage_string);
+}
+
+static int send_unexport_device(int sockfd, struct usbip_usb_device *udev)
+{
+ int rc;
+ struct op_unexport_request request;
+ uint16_t code = OP_REP_UNEXPORT;
+
+ /* send a request */
+ rc = usbip_net_send_op_common(sockfd, OP_REQ_UNEXPORT, 0);
+ if (rc < 0) {
+ err("send op_common");
+ return -1;
+ }
+
+ memset(&request, 0, sizeof(request));
+ memcpy(&request.udev, udev, sizeof(request.udev));
+
+ PACK_OP_UNEXPORT_REQUEST(0, &request);
+
+ rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
+ if (rc < 0) {
+ err("send op_export_request");
+ return -1;
+ }
+
+ /* receive a reply */
+ rc = usbip_net_recv_op_common(sockfd, &code);
+ if (rc < 0) {
+ err("recv op_common");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int unexport_device(char *busid, int sockfd)
+{
+ int rc;
+ struct usbip_exported_device *edev;
+
+ rc = usbip_driver_open(driver);
+ if (rc < 0) {
+ err("open driver");
+ goto err_out;
+ }
+
+ rc = usbip_refresh_device_list(driver);
+ if (rc < 0) {
+ err("could not refresh device list");
+ goto err_driver_close;
+ }
+
+ edev = usbip_get_device(driver, busid);
+ if (edev == NULL) {
+ err("find device");
+ goto err_driver_close;
+ }
+
+ rc = send_unexport_device(sockfd, &edev->udev);
+ if (rc < 0) {
+ err("send unexport");
+ goto err_driver_close;
+ }
+
+ usbip_driver_close(driver);
+
+ return 0;
+
+err_driver_close:
+ usbip_driver_close(driver);
+err_out:
+ return -1;
+}
+
+static int disconnect_device(char *host, char *busid, int unbind)
+{
+ int sockfd;
+ int rc;
+
+ sockfd = usbip_net_tcp_connect(host, usbip_port_string);
+ if (sockfd < 0) {
+ err("tcp connect");
+ return -1;
+ }
+
+ rc = unexport_device(busid, sockfd);
+ if (rc < 0) {
+ err("unexport");
+ close(sockfd);
+ return -1;
+ }
+
+ close(sockfd);
+
+ if (unbind) {
+ rc = usbip_unbind_device(busid);
+ if (rc) {
+ err("unbind");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int usbip_disconnect(int argc, char *argv[])
+{
+ static const struct option opts[] = {
+ { "remote", required_argument, NULL, 'r' },
+ { "busid", required_argument, NULL, 'b' },
+ { "device", no_argument, NULL, 'd' },
+ { NULL, 0, NULL, 0 }
+ };
+ char *host = NULL;
+ char *busid = NULL;
+ int opt;
+ int unbind = 1;
+ int ret = -1;
+
+ for (;;) {
+ opt = getopt_long(argc, argv, "r:b:d", opts, NULL);
+
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'r':
+ host = optarg;
+ break;
+ case 'b':
+ busid = optarg;
+ break;
+ case 'd':
+ driver = &device_driver;
+ unbind = 0;
+ break;
+ default:
+ goto err_out;
+ }
+ }
+
+ if (!host || !busid)
+ goto err_out;
+
+ ret = disconnect_device(host, busid, unbind);
+ goto out;
+
+err_out:
+ usbip_disconnect_usage();
+out:
+ return ret;
+}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html