126 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>4 * 2005-2007 Takahiro Hirofuchi5 */6 7#include <ctype.h>8#include <limits.h>9#include <stdint.h>10#include <stdio.h>11#include <stdlib.h>12#include <string.h>13 14#include <getopt.h>15#include <unistd.h>16 17#include "vhci_driver.h"18#include "usbip_common.h"19#include "usbip_network.h"20#include "usbip.h"21 22static const char usbip_detach_usage_string[] =23 "usbip detach <args>\n"24 " -p, --port=<port> " USBIP_VHCI_DRV_NAME25 " port the device is on\n";26 27void usbip_detach_usage(void)28{29 printf("usage: %s", usbip_detach_usage_string);30}31 32static int detach_port(char *port)33{34 int ret = 0;35 uint8_t portnum;36 char path[PATH_MAX+1];37 int i;38 struct usbip_imported_device *idev;39 int found = 0;40 41 unsigned int port_len = strlen(port);42 43 for (unsigned int i = 0; i < port_len; i++)44 if (!isdigit(port[i])) {45 err("invalid port %s", port);46 return -1;47 }48 49 portnum = atoi(port);50 51 ret = usbip_vhci_driver_open();52 if (ret < 0) {53 err("open vhci_driver (is vhci_hcd loaded?)");54 return -1;55 }56 57 /* check for invalid port */58 for (i = 0; i < vhci_driver->nports; i++) {59 idev = &vhci_driver->idev[i];60 61 if (idev->port == portnum) {62 found = 1;63 if (idev->status != VDEV_ST_NULL)64 break;65 info("Port %d is already detached!\n", idev->port);66 goto call_driver_close;67 }68 }69 70 if (!found) {71 ret = -1;72 err("Invalid port %s > maxports %d",73 port, vhci_driver->nports);74 goto call_driver_close;75 }76 77 /* remove the port state file */78 snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);79 80 remove(path);81 rmdir(VHCI_STATE_PATH);82 83 ret = usbip_vhci_detach_device(portnum);84 if (ret < 0) {85 ret = -1;86 err("Port %d detach request failed!\n", portnum);87 goto call_driver_close;88 }89 info("Port %d is now detached!\n", portnum);90 91call_driver_close:92 usbip_vhci_driver_close();93 94 return ret;95}96 97int usbip_detach(int argc, char *argv[])98{99 static const struct option opts[] = {100 { "port", required_argument, NULL, 'p' },101 { NULL, 0, NULL, 0 }102 };103 int opt;104 int ret = -1;105 106 for (;;) {107 opt = getopt_long(argc, argv, "p:", opts, NULL);108 109 if (opt == -1)110 break;111 112 switch (opt) {113 case 'p':114 ret = detach_port(optarg);115 goto out;116 default:117 goto err_out;118 }119 }120 121err_out:122 usbip_detach_usage();123out:124 return ret;125}126