Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
usbip_attach.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 matt mooney <[email protected]>
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 <sys/stat.h>
20 #include <sysfs/libsysfs.h>
21 
22 #include <limits.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include <fcntl.h>
28 #include <getopt.h>
29 #include <unistd.h>
30 
31 #include "vhci_driver.h"
32 #include "usbip_common.h"
33 #include "usbip_network.h"
34 #include "usbip.h"
35 
36 static const char usbip_attach_usage_string[] =
37  "usbip attach <args>\n"
38  " -h, --host=<host> The machine with exported USB devices\n"
39  " -b, --busid=<busid> Busid of the device on <host>\n";
40 
42 {
43  printf("usage: %s", usbip_attach_usage_string);
44 }
45 
46 #define MAX_BUFF 100
47 static int record_connection(char *host, char *port, char *busid, int rhport)
48 {
49  int fd;
50  char path[PATH_MAX+1];
51  char buff[MAX_BUFF+1];
52  int ret;
53 
54  ret = mkdir(VHCI_STATE_PATH, 0700);
55  if (ret < 0)
56  return -1;
57 
58  snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
59 
60  fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
61  if (fd < 0)
62  return -1;
63 
64  snprintf(buff, MAX_BUFF, "%s %s %s\n",
65  host, port, busid);
66 
67  ret = write(fd, buff, strlen(buff));
68  if (ret != (ssize_t) strlen(buff)) {
69  close(fd);
70  return -1;
71  }
72 
73  close(fd);
74 
75  return 0;
76 }
77 
78 static int import_device(int sockfd, struct usbip_usb_device *udev)
79 {
80  int rc;
81  int port;
82 
84  if (rc < 0) {
85  err("open vhci_driver");
86  return -1;
87  }
88 
89  port = usbip_vhci_get_free_port();
90  if (port < 0) {
91  err("no free port");
93  return -1;
94  }
95 
96  rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
97  udev->devnum, udev->speed);
98  if (rc < 0) {
99  err("import device");
101  return -1;
102  }
103 
105 
106  return port;
107 }
108 
109 static int query_import_device(int sockfd, char *busid)
110 {
111  int rc;
112  struct op_import_request request;
113  struct op_import_reply reply;
115 
116  memset(&request, 0, sizeof(request));
117  memset(&reply, 0, sizeof(reply));
118 
119  /* send a request */
120  rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0);
121  if (rc < 0) {
122  err("send op_common");
123  return -1;
124  }
125 
126  strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
127 
129 
130  rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
131  if (rc < 0) {
132  err("send op_import_request");
133  return -1;
134  }
135 
136  /* recieve a reply */
137  rc = usbip_net_recv_op_common(sockfd, &code);
138  if (rc < 0) {
139  err("recv op_common");
140  return -1;
141  }
142 
143  rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply));
144  if (rc < 0) {
145  err("recv op_import_reply");
146  return -1;
147  }
148 
149  PACK_OP_IMPORT_REPLY(0, &reply);
150 
151  /* check the reply */
152  if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
153  err("recv different busid %s", reply.udev.busid);
154  return -1;
155  }
156 
157  /* import a device */
158  return import_device(sockfd, &reply.udev);
159 }
160 
161 static int attach_device(char *host, char *busid)
162 {
163  int sockfd;
164  int rc;
165  int rhport;
166 
168  if (sockfd < 0) {
169  err("tcp connect");
170  return -1;
171  }
172 
173  rhport = query_import_device(sockfd, busid);
174  if (rhport < 0) {
175  err("query");
176  return -1;
177  }
178 
179  close(sockfd);
180 
181  rc = record_connection(host, USBIP_PORT_STRING, busid, rhport);
182  if (rc < 0) {
183  err("record connection");
184  return -1;
185  }
186 
187  return 0;
188 }
189 
190 int usbip_attach(int argc, char *argv[])
191 {
192  static const struct option opts[] = {
193  { "host", required_argument, NULL, 'h' },
194  { "busid", required_argument, NULL, 'b' },
195  { NULL, 0, NULL, 0 }
196  };
197  char *host = NULL;
198  char *busid = NULL;
199  int opt;
200  int ret = -1;
201 
202  for (;;) {
203  opt = getopt_long(argc, argv, "h:b:", opts, NULL);
204 
205  if (opt == -1)
206  break;
207 
208  switch (opt) {
209  case 'h':
210  host = optarg;
211  break;
212  case 'b':
213  busid = optarg;
214  break;
215  default:
216  goto err_out;
217  }
218  }
219 
220  if (!host || !busid)
221  goto err_out;
222 
223  ret = attach_device(host, busid);
224  goto out;
225 
226 err_out:
228 out:
229  return ret;
230 }