linux/tools/usb/usbip/src/usbip_detach.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
   4 *               2005-2007 Takahiro Hirofuchi
   5 */
   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_NAME
  25        " 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");
  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                err("Invalid port %s > maxports %d",
  72                        port, vhci_driver->nports);
  73                goto call_driver_close;
  74        }
  75
  76        /* remove the port state file */
  77        snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);
  78
  79        remove(path);
  80        rmdir(VHCI_STATE_PATH);
  81
  82        ret = usbip_vhci_detach_device(portnum);
  83        if (ret < 0) {
  84                ret = -1;
  85                err("Port %d detach request failed!\n", portnum);
  86                goto call_driver_close;
  87        }
  88        info("Port %d is now detached!\n", portnum);
  89
  90call_driver_close:
  91        usbip_vhci_driver_close();
  92
  93        return ret;
  94}
  95
  96int usbip_detach(int argc, char *argv[])
  97{
  98        static const struct option opts[] = {
  99                { "port", required_argument, NULL, 'p' },
 100                { NULL, 0, NULL, 0 }
 101        };
 102        int opt;
 103        int ret = -1;
 104
 105        for (;;) {
 106                opt = getopt_long(argc, argv, "p:", opts, NULL);
 107
 108                if (opt == -1)
 109                        break;
 110
 111                switch (opt) {
 112                case 'p':
 113                        ret = detach_port(optarg);
 114                        goto out;
 115                default:
 116                        goto err_out;
 117                }
 118        }
 119
 120err_out:
 121        usbip_detach_usage();
 122out:
 123        return ret;
 124}
 125