11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2588b48caSValentina Manea /*
3588b48caSValentina Manea * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
4588b48caSValentina Manea * 2005-2007 Takahiro Hirofuchi
5588b48caSValentina Manea */
6588b48caSValentina Manea
7588b48caSValentina Manea #include <ctype.h>
8588b48caSValentina Manea #include <limits.h>
9588b48caSValentina Manea #include <stdint.h>
10588b48caSValentina Manea #include <stdio.h>
11588b48caSValentina Manea #include <stdlib.h>
12588b48caSValentina Manea #include <string.h>
13588b48caSValentina Manea
14588b48caSValentina Manea #include <getopt.h>
15588b48caSValentina Manea #include <unistd.h>
16588b48caSValentina Manea
17588b48caSValentina Manea #include "vhci_driver.h"
18588b48caSValentina Manea #include "usbip_common.h"
19588b48caSValentina Manea #include "usbip_network.h"
20588b48caSValentina Manea #include "usbip.h"
21588b48caSValentina Manea
22588b48caSValentina Manea static const char usbip_detach_usage_string[] =
23588b48caSValentina Manea "usbip detach <args>\n"
24588b48caSValentina Manea " -p, --port=<port> " USBIP_VHCI_DRV_NAME
25588b48caSValentina Manea " port the device is on\n";
26588b48caSValentina Manea
usbip_detach_usage(void)27588b48caSValentina Manea void usbip_detach_usage(void)
28588b48caSValentina Manea {
29588b48caSValentina Manea printf("usage: %s", usbip_detach_usage_string);
30588b48caSValentina Manea }
31588b48caSValentina Manea
detach_port(char * port)32588b48caSValentina Manea static int detach_port(char *port)
33588b48caSValentina Manea {
34d179f99aSShuah Khan (Samsung OSG) int ret = 0;
35588b48caSValentina Manea uint8_t portnum;
36588b48caSValentina Manea char path[PATH_MAX+1];
3740ecdeb1SShuah Khan (Samsung OSG) int i;
3840ecdeb1SShuah Khan (Samsung OSG) struct usbip_imported_device *idev;
3940ecdeb1SShuah Khan (Samsung OSG) int found = 0;
40588b48caSValentina Manea
410c618145SEric Curtin unsigned int port_len = strlen(port);
420c618145SEric Curtin
430c618145SEric Curtin for (unsigned int i = 0; i < port_len; i++)
44588b48caSValentina Manea if (!isdigit(port[i])) {
45588b48caSValentina Manea err("invalid port %s", port);
46588b48caSValentina Manea return -1;
47588b48caSValentina Manea }
48588b48caSValentina Manea
49588b48caSValentina Manea portnum = atoi(port);
50588b48caSValentina Manea
51588b48caSValentina Manea ret = usbip_vhci_driver_open();
52588b48caSValentina Manea if (ret < 0) {
530c7f35d2SGalen Guyer err("open vhci_driver (is vhci_hcd loaded?)");
54588b48caSValentina Manea return -1;
55588b48caSValentina Manea }
56588b48caSValentina Manea
5740ecdeb1SShuah Khan (Samsung OSG) /* check for invalid port */
5840ecdeb1SShuah Khan (Samsung OSG) for (i = 0; i < vhci_driver->nports; i++) {
5940ecdeb1SShuah Khan (Samsung OSG) idev = &vhci_driver->idev[i];
6040ecdeb1SShuah Khan (Samsung OSG)
6140ecdeb1SShuah Khan (Samsung OSG) if (idev->port == portnum) {
6240ecdeb1SShuah Khan (Samsung OSG) found = 1;
6340ecdeb1SShuah Khan (Samsung OSG) if (idev->status != VDEV_ST_NULL)
6440ecdeb1SShuah Khan (Samsung OSG) break;
6540ecdeb1SShuah Khan (Samsung OSG) info("Port %d is already detached!\n", idev->port);
6640ecdeb1SShuah Khan (Samsung OSG) goto call_driver_close;
6740ecdeb1SShuah Khan (Samsung OSG) }
6840ecdeb1SShuah Khan (Samsung OSG) }
6940ecdeb1SShuah Khan (Samsung OSG)
7040ecdeb1SShuah Khan (Samsung OSG) if (!found) {
71*53e0684fSZongmin Zhou ret = -1;
7240ecdeb1SShuah Khan (Samsung OSG) err("Invalid port %s > maxports %d",
7340ecdeb1SShuah Khan (Samsung OSG) port, vhci_driver->nports);
7440ecdeb1SShuah Khan (Samsung OSG) goto call_driver_close;
7540ecdeb1SShuah Khan (Samsung OSG) }
7640ecdeb1SShuah Khan (Samsung OSG)
7740ecdeb1SShuah Khan (Samsung OSG) /* remove the port state file */
7840ecdeb1SShuah Khan (Samsung OSG) snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);
7940ecdeb1SShuah Khan (Samsung OSG)
8040ecdeb1SShuah Khan (Samsung OSG) remove(path);
8140ecdeb1SShuah Khan (Samsung OSG) rmdir(VHCI_STATE_PATH);
8240ecdeb1SShuah Khan (Samsung OSG)
83588b48caSValentina Manea ret = usbip_vhci_detach_device(portnum);
84d179f99aSShuah Khan (Samsung OSG) if (ret < 0) {
85d179f99aSShuah Khan (Samsung OSG) ret = -1;
8640ecdeb1SShuah Khan (Samsung OSG) err("Port %d detach request failed!\n", portnum);
87d179f99aSShuah Khan (Samsung OSG) goto call_driver_close;
88d179f99aSShuah Khan (Samsung OSG) }
8940ecdeb1SShuah Khan (Samsung OSG) info("Port %d is now detached!\n", portnum);
90588b48caSValentina Manea
91d179f99aSShuah Khan (Samsung OSG) call_driver_close:
92588b48caSValentina Manea usbip_vhci_driver_close();
93588b48caSValentina Manea
94588b48caSValentina Manea return ret;
95588b48caSValentina Manea }
96588b48caSValentina Manea
usbip_detach(int argc,char * argv[])97588b48caSValentina Manea int usbip_detach(int argc, char *argv[])
98588b48caSValentina Manea {
99588b48caSValentina Manea static const struct option opts[] = {
100588b48caSValentina Manea { "port", required_argument, NULL, 'p' },
101588b48caSValentina Manea { NULL, 0, NULL, 0 }
102588b48caSValentina Manea };
103588b48caSValentina Manea int opt;
104588b48caSValentina Manea int ret = -1;
105588b48caSValentina Manea
106588b48caSValentina Manea for (;;) {
107588b48caSValentina Manea opt = getopt_long(argc, argv, "p:", opts, NULL);
108588b48caSValentina Manea
109588b48caSValentina Manea if (opt == -1)
110588b48caSValentina Manea break;
111588b48caSValentina Manea
112588b48caSValentina Manea switch (opt) {
113588b48caSValentina Manea case 'p':
114588b48caSValentina Manea ret = detach_port(optarg);
115588b48caSValentina Manea goto out;
116588b48caSValentina Manea default:
117588b48caSValentina Manea goto err_out;
118588b48caSValentina Manea }
119588b48caSValentina Manea }
120588b48caSValentina Manea
121588b48caSValentina Manea err_out:
122588b48caSValentina Manea usbip_detach_usage();
123588b48caSValentina Manea out:
124588b48caSValentina Manea return ret;
125588b48caSValentina Manea }
126