1/* 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 3 * 2005-2007 Takahiro Hirofuchi 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#include <ctype.h> 20#include <limits.h> 21#include <stdint.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25 26#include <getopt.h> 27#include <unistd.h> 28 29#include "vhci_driver.h" 30#include "usbip_common.h" 31#include "usbip_network.h" 32#include "usbip.h" 33 34static const char usbip_detach_usage_string[] = 35 "usbip detach <args>\n" 36 " -p, --port=<port> " USBIP_VHCI_DRV_NAME 37 " port the device is on\n"; 38 39void usbip_detach_usage(void) 40{ 41 printf("usage: %s", usbip_detach_usage_string); 42} 43 44static int detach_port(char *port) 45{ 46 int ret; 47 uint8_t portnum; 48 char path[PATH_MAX+1]; 49 50 for (unsigned int i = 0; i < strlen(port); i++) 51 if (!isdigit(port[i])) { 52 err("invalid port %s", port); 53 return -1; 54 } 55 56 /* check max port */ 57 58 portnum = atoi(port); 59 60 /* remove the port state file */ 61 62 snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum); 63 64 remove(path); 65 rmdir(VHCI_STATE_PATH); 66 67 ret = usbip_vhci_driver_open(); 68 if (ret < 0) { 69 err("open vhci_driver"); 70 return -1; 71 } 72 73 ret = usbip_vhci_detach_device(portnum); 74 if (ret < 0) 75 return -1; 76 77 usbip_vhci_driver_close(); 78 79 return ret; 80} 81 82int usbip_detach(int argc, char *argv[]) 83{ 84 static const struct option opts[] = { 85 { "port", required_argument, NULL, 'p' }, 86 { NULL, 0, NULL, 0 } 87 }; 88 int opt; 89 int ret = -1; 90 91 for (;;) { 92 opt = getopt_long(argc, argv, "p:", opts, NULL); 93 94 if (opt == -1) 95 break; 96 97 switch (opt) { 98 case 'p': 99 ret = detach_port(optarg); 100 goto out; 101 default: 102 goto err_out; 103 } 104 } 105 106err_out: 107 usbip_detach_usage(); 108out: 109 return ret; 110} 111