root/tools/usb/usbip/src/usbip_attach.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbip_attach_usage
  2. record_connection
  3. import_device
  4. query_import_device
  5. attach_device
  6. usbip_attach

   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  * Copyright (C) 2015-2016 Samsung Electronics
   6  *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
   7  *               Krzysztof Opasiak <k.opasiak@samsung.com>
   8  */
   9 
  10 #include <sys/stat.h>
  11 
  12 #include <limits.h>
  13 #include <stdint.h>
  14 #include <stdio.h>
  15 #include <string.h>
  16 
  17 #include <fcntl.h>
  18 #include <getopt.h>
  19 #include <unistd.h>
  20 #include <errno.h>
  21 
  22 #include "vhci_driver.h"
  23 #include "usbip_common.h"
  24 #include "usbip_network.h"
  25 #include "usbip.h"
  26 
  27 static const char usbip_attach_usage_string[] =
  28         "usbip attach <args>\n"
  29         "    -r, --remote=<host>      The machine with exported USB devices\n"
  30         "    -b, --busid=<busid>    Busid of the device on <host>\n"
  31         "    -d, --device=<devid>    Id of the virtual UDC on <host>\n";
  32 
  33 void usbip_attach_usage(void)
  34 {
  35         printf("usage: %s", usbip_attach_usage_string);
  36 }
  37 
  38 #define MAX_BUFF 100
  39 static int record_connection(char *host, char *port, char *busid, int rhport)
  40 {
  41         int fd;
  42         char path[PATH_MAX+1];
  43         char buff[MAX_BUFF+1];
  44         int ret;
  45 
  46         ret = mkdir(VHCI_STATE_PATH, 0700);
  47         if (ret < 0) {
  48                 /* if VHCI_STATE_PATH exists, then it better be a directory */
  49                 if (errno == EEXIST) {
  50                         struct stat s;
  51 
  52                         ret = stat(VHCI_STATE_PATH, &s);
  53                         if (ret < 0)
  54                                 return -1;
  55                         if (!(s.st_mode & S_IFDIR))
  56                                 return -1;
  57                 } else
  58                         return -1;
  59         }
  60 
  61         snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
  62 
  63         fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
  64         if (fd < 0)
  65                 return -1;
  66 
  67         snprintf(buff, MAX_BUFF, "%s %s %s\n",
  68                         host, port, busid);
  69 
  70         ret = write(fd, buff, strlen(buff));
  71         if (ret != (ssize_t) strlen(buff)) {
  72                 close(fd);
  73                 return -1;
  74         }
  75 
  76         close(fd);
  77 
  78         return 0;
  79 }
  80 
  81 static int import_device(int sockfd, struct usbip_usb_device *udev)
  82 {
  83         int rc;
  84         int port;
  85         uint32_t speed = udev->speed;
  86 
  87         rc = usbip_vhci_driver_open();
  88         if (rc < 0) {
  89                 err("open vhci_driver");
  90                 goto err_out;
  91         }
  92 
  93         do {
  94                 port = usbip_vhci_get_free_port(speed);
  95                 if (port < 0) {
  96                         err("no free port");
  97                         goto err_driver_close;
  98                 }
  99 
 100                 dbg("got free port %d", port);
 101 
 102                 rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
 103                                               udev->devnum, udev->speed);
 104                 if (rc < 0 && errno != EBUSY) {
 105                         err("import device");
 106                         goto err_driver_close;
 107                 }
 108         } while (rc < 0);
 109 
 110         usbip_vhci_driver_close();
 111 
 112         return port;
 113 
 114 err_driver_close:
 115         usbip_vhci_driver_close();
 116 err_out:
 117         return -1;
 118 }
 119 
 120 static int query_import_device(int sockfd, char *busid)
 121 {
 122         int rc;
 123         struct op_import_request request;
 124         struct op_import_reply   reply;
 125         uint16_t code = OP_REP_IMPORT;
 126         int status;
 127 
 128         memset(&request, 0, sizeof(request));
 129         memset(&reply, 0, sizeof(reply));
 130 
 131         /* send a request */
 132         rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0);
 133         if (rc < 0) {
 134                 err("send op_common");
 135                 return -1;
 136         }
 137 
 138         strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
 139 
 140         PACK_OP_IMPORT_REQUEST(0, &request);
 141 
 142         rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
 143         if (rc < 0) {
 144                 err("send op_import_request");
 145                 return -1;
 146         }
 147 
 148         /* receive a reply */
 149         rc = usbip_net_recv_op_common(sockfd, &code, &status);
 150         if (rc < 0) {
 151                 err("Attach Request for %s failed - %s\n",
 152                     busid, usbip_op_common_status_string(status));
 153                 return -1;
 154         }
 155 
 156         rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply));
 157         if (rc < 0) {
 158                 err("recv op_import_reply");
 159                 return -1;
 160         }
 161 
 162         PACK_OP_IMPORT_REPLY(0, &reply);
 163 
 164         /* check the reply */
 165         if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
 166                 err("recv different busid %s", reply.udev.busid);
 167                 return -1;
 168         }
 169 
 170         /* import a device */
 171         return import_device(sockfd, &reply.udev);
 172 }
 173 
 174 static int attach_device(char *host, char *busid)
 175 {
 176         int sockfd;
 177         int rc;
 178         int rhport;
 179 
 180         sockfd = usbip_net_tcp_connect(host, usbip_port_string);
 181         if (sockfd < 0) {
 182                 err("tcp connect");
 183                 return -1;
 184         }
 185 
 186         rhport = query_import_device(sockfd, busid);
 187         if (rhport < 0)
 188                 return -1;
 189 
 190         close(sockfd);
 191 
 192         rc = record_connection(host, usbip_port_string, busid, rhport);
 193         if (rc < 0) {
 194                 err("record connection");
 195                 return -1;
 196         }
 197 
 198         return 0;
 199 }
 200 
 201 int usbip_attach(int argc, char *argv[])
 202 {
 203         static const struct option opts[] = {
 204                 { "remote", required_argument, NULL, 'r' },
 205                 { "busid",  required_argument, NULL, 'b' },
 206                 { "device",  required_argument, NULL, 'd' },
 207                 { NULL, 0,  NULL, 0 }
 208         };
 209         char *host = NULL;
 210         char *busid = NULL;
 211         int opt;
 212         int ret = -1;
 213 
 214         for (;;) {
 215                 opt = getopt_long(argc, argv, "d:r:b:", opts, NULL);
 216 
 217                 if (opt == -1)
 218                         break;
 219 
 220                 switch (opt) {
 221                 case 'r':
 222                         host = optarg;
 223                         break;
 224                 case 'd':
 225                 case 'b':
 226                         busid = optarg;
 227                         break;
 228                 default:
 229                         goto err_out;
 230                 }
 231         }
 232 
 233         if (!host || !busid)
 234                 goto err_out;
 235 
 236         ret = attach_device(host, busid);
 237         goto out;
 238 
 239 err_out:
 240         usbip_attach_usage();
 241 out:
 242         return ret;
 243 }

/* [<][>][^][v][top][bottom][index][help] */