3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
11 #include "usbip_network.h"
13 #include <sys/types.h>
19 static const char version[] = PACKAGE_STRING;
22 /* /sys/devices/platform/vhci_hcd/usb6/6-1/6-1:1.1 -> 1 */
23 static int get_interface_number(char *path)
27 c = strstr(path, vhci_driver->hc_device->bus_id);
29 return -1; /* hc exist? */
31 /* -> usb6/6-1/6-1:1.1 */
35 return -1; /* hc exist? */
41 return -1; /* no interface path */
47 return -1; /* no configuration? */
53 return -1; /* no interface? */
62 static struct sysfs_device *open_usb_interface(struct usb_device *udev, int i)
64 struct sysfs_device *suinf;
65 char busid[SYSFS_BUS_ID_SIZE];
67 snprintf(busid, SYSFS_BUS_ID_SIZE, "%s:%d.%d",
68 udev->busid, udev->bConfigurationValue, i);
70 suinf = sysfs_open_device("usb", busid);
72 err("sysfs_open_device %s", busid);
79 static int record_connection(char *host, char *port, char *busid, int rhport)
82 char path[PATH_MAX+1];
83 char buff[MAX_BUFF+1];
86 mkdir(VHCI_STATE_PATH, 0700);
88 snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
90 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
94 snprintf(buff, MAX_BUFF, "%s %s %s\n",
97 ret = write(fd, buff, strlen(buff));
98 if (ret != (ssize_t) strlen(buff)) {
108 static int read_record(int rhport, char *host, char *port, char *busid)
111 char path[PATH_MAX+1];
113 snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
115 file = fopen(path, "r");
121 if (fscanf(file, "%s %s %s\n", host, port, busid) != 3) {
133 int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
135 char product_name[100];
136 char host[NI_MAXHOST] = "unknown host";
137 char serv[NI_MAXSERV] = "unknown port";
138 char remote_busid[SYSFS_BUS_ID_SIZE];
141 if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) {
142 info("Port %02d: <%s>", idev->port, usbip_status_string(idev->status));
146 ret = read_record(idev->port, host, serv, remote_busid);
152 info("Port %02d: <%s> at %s", idev->port,
153 usbip_status_string(idev->status), usbip_speed_string(idev->udev.speed));
155 usbip_names_get_product(product_name, sizeof(product_name),
156 idev->udev.idVendor, idev->udev.idProduct);
158 info(" %s", product_name);
160 info("%10s -> usbip://%s:%s/%s (remote devid %08x (bus/dev %03d/%03d))",
161 idev->udev.busid, host, serv, remote_busid,
163 idev->busnum, idev->devnum);
165 for (int i=0; i < idev->udev.bNumInterfaces; i++) {
166 /* show interface information */
167 struct sysfs_device *suinf;
169 suinf = open_usb_interface(&idev->udev, i);
173 info(" %6s used by %-17s", suinf->bus_id, suinf->driver_name);
174 sysfs_close_device(suinf);
176 /* show class device information */
177 struct usbip_class_device *cdev;
179 dlist_for_each_data(idev->cdev_list, cdev,
180 struct usbip_class_device) {
181 int ifnum = get_interface_number(cdev->dev_path);
183 info(" %s", cdev->class_path);
194 static int query_exported_devices(int sockfd)
197 struct op_devlist_reply rep;
198 uint16_t code = OP_REP_DEVLIST;
200 bzero(&rep, sizeof(rep));
202 ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
204 err("send op_common");
208 ret = usbip_recv_op_common(sockfd, &code);
210 err("recv op_common");
214 ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));
216 err("recv op_devlist");
220 PACK_OP_DEVLIST_REPLY(0, &rep);
221 dbg("exportable %d devices", rep.ndev);
223 for (unsigned int i=0; i < rep.ndev; i++) {
224 char product_name[100];
225 char class_name[100];
226 struct usb_device udev;
228 bzero(&udev, sizeof(udev));
230 ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));
232 err("recv usb_device[%d]", i);
235 pack_usb_device(0, &udev);
237 usbip_names_get_product(product_name, sizeof(product_name),
238 udev.idVendor, udev.idProduct);
239 usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,
240 udev.bDeviceSubClass, udev.bDeviceProtocol);
242 info("%8s: %s", udev.busid, product_name);
243 info("%8s: %s", " ", udev.path);
244 info("%8s: %s", " ", class_name);
246 for (int j=0; j < udev.bNumInterfaces; j++) {
247 struct usb_interface uinf;
249 ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));
251 err("recv usb_interface[%d]", j);
255 pack_usb_interface(0, &uinf);
256 usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass,
257 uinf.bInterfaceSubClass, uinf.bInterfaceProtocol);
259 info("%8s: %2d - %s", " ", j, class_name);
268 static int import_device(int sockfd, struct usb_device *udev)
273 ret = usbip_vhci_driver_open();
275 err("open vhci_driver");
279 port = usbip_vhci_get_free_port();
282 usbip_vhci_driver_close();
286 ret = usbip_vhci_attach_device(port, sockfd, udev->busnum,
287 udev->devnum, udev->speed);
289 err("import device");
290 usbip_vhci_driver_close();
294 usbip_vhci_driver_close();
300 static int query_import_device(int sockfd, char *busid)
303 struct op_import_request request;
304 struct op_import_reply reply;
305 uint16_t code = OP_REP_IMPORT;
307 bzero(&request, sizeof(request));
308 bzero(&reply, sizeof(reply));
312 ret = usbip_send_op_common(sockfd, OP_REQ_IMPORT, 0);
314 err("send op_common");
318 strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
320 PACK_OP_IMPORT_REQUEST(0, &request);
322 ret = usbip_send(sockfd, (void *) &request, sizeof(request));
324 err("send op_import_request");
329 /* recieve a reply */
330 ret = usbip_recv_op_common(sockfd, &code);
332 err("recv op_common");
336 ret = usbip_recv(sockfd, (void *) &reply, sizeof(reply));
338 err("recv op_import_reply");
342 PACK_OP_IMPORT_REPLY(0, &reply);
345 /* check the reply */
346 if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
347 err("recv different busid %s", reply.udev.busid);
352 /* import a device */
353 return import_device(sockfd, &reply.udev);
356 static int attach_device(char *host, char *busid)
362 sockfd = tcp_connect(host, USBIP_PORT_STRING);
368 rhport = query_import_device(sockfd, busid);
376 ret = record_connection(host, USBIP_PORT_STRING,
379 err("record connection");
386 static int detach_port(char *port)
391 for (unsigned int i=0; i < strlen(port); i++)
392 if (!isdigit(port[i])) {
393 err("invalid port %s", port);
399 portnum = atoi(port);
401 ret = usbip_vhci_driver_open();
403 err("open vhci_driver");
407 ret = usbip_vhci_detach_device(portnum);
411 usbip_vhci_driver_close();
416 static int show_exported_devices(char *host)
421 sockfd = tcp_connect(host, USBIP_PORT_STRING);
423 err("- %s failed", host);
429 ret = query_exported_devices(sockfd);
439 static int attach_exported_devices(char *host, int sockfd)
442 struct op_devlist_reply rep;
443 uint16_t code = OP_REP_DEVLIST;
445 bzero(&rep, sizeof(rep));
447 ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
449 err("send op_common");
453 ret = usbip_recv_op_common(sockfd, &code);
455 err("recv op_common");
459 ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));
461 err("recv op_devlist");
465 PACK_OP_DEVLIST_REPLY(0, &rep);
466 dbg("exportable %d devices", rep.ndev);
468 for(unsigned int i=0; i < rep.ndev; i++) {
469 char product_name[100];
470 char class_name[100];
471 struct usb_device udev;
473 bzero(&udev, sizeof(udev));
475 ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));
477 err("recv usb_device[%d]", i);
480 pack_usb_device(0, &udev);
482 usbip_names_get_product(product_name, sizeof(product_name),
483 udev.idVendor, udev.idProduct);
484 usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,
485 udev.bDeviceSubClass, udev.bDeviceProtocol);
487 dbg("Attaching usb port %s from host %s on usbip, with deviceid: %s", udev.busid, host, product_name);
489 for (int j=0; j < udev.bNumInterfaces; j++) {
490 struct usb_interface uinf;
492 ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));
494 err("recv usb_interface[%d]", j);
498 pack_usb_interface(0, &uinf);
499 usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass,
500 uinf.bInterfaceSubClass, uinf.bInterfaceProtocol);
502 dbg("interface %2d - %s", j, class_name);
505 attach_device(host, udev.busid);
511 static int attach_devices_all(char *host)
516 sockfd = tcp_connect(host, USBIP_PORT_STRING);
518 err("- %s failed", host);
524 ret = attach_exported_devices(host, sockfd);
535 const char help_message[] = "\
536 Usage: usbip [options] \n\
537 -a, --attach [host] [bus_id] \n\
538 Attach a remote USB device. \n\
540 -x, --attachall [host] \n\
541 Attach all remote USB devices on the specific host. \n\
543 -d, --detach [ports] \n\
544 Detach an imported USB device. \n\
546 -l, --list [hosts] \n\
547 List exported USB devices. \n\
550 List virtual USB port status. \n\
553 Print debugging information. \n\
559 Print this help. \n";
561 static void show_help(void)
563 printf("%s", help_message);
566 static int show_port_status(void)
569 struct usbip_imported_device *idev;
571 ret = usbip_vhci_driver_open();
575 for (int i = 0; i < vhci_driver->nports; i++) {
576 idev = &vhci_driver->idev[i];
578 if (usbip_vhci_imported_device_dump(idev) < 0)
582 usbip_vhci_driver_close();
589 static const struct option longopts[] = {
590 {"attach", no_argument, NULL, 'a'},
591 {"attachall", no_argument, NULL, 'x'},
592 {"detach", no_argument, NULL, 'd'},
593 {"port", no_argument, NULL, 'p'},
594 {"list", no_argument, NULL, 'l'},
595 {"version", no_argument, NULL, 'v'},
596 {"help", no_argument, NULL, 'h'},
597 {"debug", no_argument, NULL, 'D'},
598 {"syslog", no_argument, NULL, 'S'},
602 int main(int argc, char *argv[])
616 usbip_use_stderr = 1;
619 g_warning("running non-root?");
621 ret = usbip_names_init(USBIDS_FILE);
623 notice("failed to open %s", USBIDS_FILE);
629 c = getopt_long(argc, argv, "adplvhDSx", longopts, &index);
677 usbip_use_syslog = 1;
690 if (optind == argc - 2)
691 ret = attach_device(argv[optind], argv[optind+1]);
696 while (optind < argc)
697 ret = detach_port(argv[optind++]);
700 ret = show_port_status();
703 while (optind < argc)
704 ret = show_exported_devices(argv[optind++]);
708 ret = attach_devices_all(argv[optind++]);
711 printf("%s\n", version);
723 exit((ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE);