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 class_device *cdev;
179 dlist_for_each_data(idev->cdev_list, cdev, struct class_device) {
180 int ifnum = get_interface_number(cdev->devpath);
182 info(" %s", cdev->clspath);
193 static int query_exported_devices(int sockfd)
196 struct op_devlist_reply rep;
197 uint16_t code = OP_REP_DEVLIST;
199 bzero(&rep, sizeof(rep));
201 ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
203 err("send op_common");
207 ret = usbip_recv_op_common(sockfd, &code);
209 err("recv op_common");
213 ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));
215 err("recv op_devlist");
219 PACK_OP_DEVLIST_REPLY(0, &rep);
220 dbg("exportable %d devices", rep.ndev);
222 for (unsigned int i=0; i < rep.ndev; i++) {
223 char product_name[100];
224 char class_name[100];
225 struct usb_device udev;
227 bzero(&udev, sizeof(udev));
229 ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));
231 err("recv usb_device[%d]", i);
234 pack_usb_device(0, &udev);
236 usbip_names_get_product(product_name, sizeof(product_name),
237 udev.idVendor, udev.idProduct);
238 usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,
239 udev.bDeviceSubClass, udev.bDeviceProtocol);
241 info("%8s: %s", udev.busid, product_name);
242 info("%8s: %s", " ", udev.path);
243 info("%8s: %s", " ", class_name);
245 for (int j=0; j < udev.bNumInterfaces; j++) {
246 struct usb_interface uinf;
248 ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));
250 err("recv usb_interface[%d]", j);
254 pack_usb_interface(0, &uinf);
255 usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass,
256 uinf.bInterfaceSubClass, uinf.bInterfaceProtocol);
258 info("%8s: %2d - %s", " ", j, class_name);
267 static int import_device(int sockfd, struct usb_device *udev)
272 ret = usbip_vhci_driver_open();
274 err("open vhci_driver");
278 port = usbip_vhci_get_free_port();
281 usbip_vhci_driver_close();
285 ret = usbip_vhci_attach_device(port, sockfd, udev->busnum,
286 udev->devnum, udev->speed);
288 err("import device");
289 usbip_vhci_driver_close();
293 usbip_vhci_driver_close();
299 static int query_import_device(int sockfd, char *busid)
302 struct op_import_request request;
303 struct op_import_reply reply;
304 uint16_t code = OP_REP_IMPORT;
306 bzero(&request, sizeof(request));
307 bzero(&reply, sizeof(reply));
311 ret = usbip_send_op_common(sockfd, OP_REQ_IMPORT, 0);
313 err("send op_common");
317 strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
319 PACK_OP_IMPORT_REQUEST(0, &request);
321 ret = usbip_send(sockfd, (void *) &request, sizeof(request));
323 err("send op_import_request");
328 /* recieve a reply */
329 ret = usbip_recv_op_common(sockfd, &code);
331 err("recv op_common");
335 ret = usbip_recv(sockfd, (void *) &reply, sizeof(reply));
337 err("recv op_import_reply");
341 PACK_OP_IMPORT_REPLY(0, &reply);
344 /* check the reply */
345 if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
346 err("recv different busid %s", reply.udev.busid);
351 /* import a device */
352 return import_device(sockfd, &reply.udev);
355 static int attach_device(char *host, char *busid)
361 sockfd = tcp_connect(host, USBIP_PORT_STRING);
367 rhport = query_import_device(sockfd, busid);
375 ret = record_connection(host, USBIP_PORT_STRING,
378 err("record connection");
385 static int detach_port(char *port)
390 for (unsigned int i=0; i < strlen(port); i++)
391 if (!isdigit(port[i])) {
392 err("invalid port %s", port);
398 portnum = atoi(port);
400 ret = usbip_vhci_driver_open();
402 err("open vhci_driver");
406 ret = usbip_vhci_detach_device(portnum);
410 usbip_vhci_driver_close();
415 static int show_exported_devices(char *host)
420 sockfd = tcp_connect(host, USBIP_PORT_STRING);
422 err("- %s failed", host);
428 ret = query_exported_devices(sockfd);
438 static int attach_exported_devices(char *host, int sockfd)
441 struct op_devlist_reply rep;
442 uint16_t code = OP_REP_DEVLIST;
444 bzero(&rep, sizeof(rep));
446 ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
448 err("send op_common");
452 ret = usbip_recv_op_common(sockfd, &code);
454 err("recv op_common");
458 ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));
460 err("recv op_devlist");
464 PACK_OP_DEVLIST_REPLY(0, &rep);
465 dbg("exportable %d devices", rep.ndev);
467 for(unsigned int i=0; i < rep.ndev; i++) {
468 char product_name[100];
469 char class_name[100];
470 struct usb_device udev;
472 bzero(&udev, sizeof(udev));
474 ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));
476 err("recv usb_device[%d]", i);
479 pack_usb_device(0, &udev);
481 usbip_names_get_product(product_name, sizeof(product_name),
482 udev.idVendor, udev.idProduct);
483 usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,
484 udev.bDeviceSubClass, udev.bDeviceProtocol);
486 dbg("Attaching usb port %s from host %s on usbip, with deviceid: %s", udev.busid, host, product_name);
488 for (int j=0; j < udev.bNumInterfaces; j++) {
489 struct usb_interface uinf;
491 ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));
493 err("recv usb_interface[%d]", j);
497 pack_usb_interface(0, &uinf);
498 usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass,
499 uinf.bInterfaceSubClass, uinf.bInterfaceProtocol);
501 dbg("interface %2d - %s", j, class_name);
504 attach_device(host, udev.busid);
510 static int attach_devices_all(char *host)
515 sockfd = tcp_connect(host, USBIP_PORT_STRING);
517 err("- %s failed", host);
523 ret = attach_exported_devices(host, sockfd);
534 const char help_message[] = "\
535 Usage: usbip [options] \n\
536 -a, --attach [host] [bus_id] \n\
537 Attach a remote USB device. \n\
539 -x, --attachall [host] \n\
540 Attach all remote USB devices on the specific host. \n\
542 -d, --detach [ports] \n\
543 Detach an imported USB device. \n\
545 -l, --list [hosts] \n\
546 List exported USB devices. \n\
549 List virtual USB port status. \n\
552 Print debugging information. \n\
558 Print this help. \n";
560 static void show_help(void)
562 printf("%s", help_message);
565 static int show_port_status(void)
568 struct usbip_imported_device *idev;
570 ret = usbip_vhci_driver_open();
574 for (int i = 0; i < vhci_driver->nports; i++) {
575 idev = &vhci_driver->idev[i];
577 if (usbip_vhci_imported_device_dump(idev) < 0)
581 usbip_vhci_driver_close();
588 static const struct option longopts[] = {
589 {"attach", no_argument, NULL, 'a'},
590 {"attachall", no_argument, NULL, 'x'},
591 {"detach", no_argument, NULL, 'd'},
592 {"port", no_argument, NULL, 'p'},
593 {"list", no_argument, NULL, 'l'},
594 {"version", no_argument, NULL, 'v'},
595 {"help", no_argument, NULL, 'h'},
596 {"debug", no_argument, NULL, 'D'},
597 {"syslog", no_argument, NULL, 'S'},
601 int main(int argc, char *argv[])
615 usbip_use_stderr = 1;
618 g_warning("running non-root?");
620 ret = usbip_names_init(USBIDS_FILE);
622 notice("failed to open %s", USBIDS_FILE);
628 c = getopt_long(argc, argv, "adplvhDSx", longopts, &index);
676 usbip_use_syslog = 1;
689 if (optind == argc - 2)
690 ret = attach_device(argv[optind], argv[optind+1]);
695 while (optind < argc)
696 ret = detach_port(argv[optind++]);
699 ret = show_port_status();
702 while (optind < argc)
703 ret = show_exported_devices(argv[optind++]);
707 ret = attach_devices_all(argv[optind++]);
710 printf("%s\n", version);
722 exit((ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE);