1588b48caSValentina Manea /* 2588b48caSValentina Manea * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 3588b48caSValentina Manea * 2005-2007 Takahiro Hirofuchi 4e0546fd8SIgor Kotrasinski * Copyright (C) 2015-2016 Samsung Electronics 5e0546fd8SIgor Kotrasinski * Igor Kotrasinski <i.kotrasinsk@samsung.com> 6e0546fd8SIgor Kotrasinski * Krzysztof Opasiak <k.opasiak@samsung.com> 7588b48caSValentina Manea * 8588b48caSValentina Manea * This program is free software: you can redistribute it and/or modify 9588b48caSValentina Manea * it under the terms of the GNU General Public License as published by 10588b48caSValentina Manea * the Free Software Foundation, either version 2 of the License, or 11588b48caSValentina Manea * (at your option) any later version. 12588b48caSValentina Manea * 13588b48caSValentina Manea * This program is distributed in the hope that it will be useful, 14588b48caSValentina Manea * but WITHOUT ANY WARRANTY; without even the implied warranty of 15588b48caSValentina Manea * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16588b48caSValentina Manea * GNU General Public License for more details. 17588b48caSValentina Manea * 18588b48caSValentina Manea * You should have received a copy of the GNU General Public License 19588b48caSValentina Manea * along with this program. If not, see <http://www.gnu.org/licenses/>. 20588b48caSValentina Manea */ 21588b48caSValentina Manea 22588b48caSValentina Manea #include <sys/types.h> 23588b48caSValentina Manea #include <libudev.h> 24588b48caSValentina Manea 25588b48caSValentina Manea #include <errno.h> 26588b48caSValentina Manea #include <stdbool.h> 27588b48caSValentina Manea #include <stdint.h> 28588b48caSValentina Manea #include <stdio.h> 29588b48caSValentina Manea #include <stdlib.h> 30588b48caSValentina Manea #include <string.h> 31588b48caSValentina Manea 32588b48caSValentina Manea #include <getopt.h> 33588b48caSValentina Manea #include <netdb.h> 34588b48caSValentina Manea #include <unistd.h> 35588b48caSValentina Manea 36e0546fd8SIgor Kotrasinski #include <dirent.h> 37e0546fd8SIgor Kotrasinski 38e0546fd8SIgor Kotrasinski #include <linux/usb/ch9.h> 39e0546fd8SIgor Kotrasinski 40588b48caSValentina Manea #include "usbip_common.h" 41588b48caSValentina Manea #include "usbip_network.h" 42588b48caSValentina Manea #include "usbip.h" 43588b48caSValentina Manea 44588b48caSValentina Manea static const char usbip_list_usage_string[] = 45588b48caSValentina Manea "usbip list [-p|--parsable] <args>\n" 46588b48caSValentina Manea " -p, --parsable Parsable list format\n" 47588b48caSValentina Manea " -r, --remote=<host> List the exportable USB devices on <host>\n" 48588b48caSValentina Manea " -l, --local List the local USB devices\n"; 49588b48caSValentina Manea 50588b48caSValentina Manea void usbip_list_usage(void) 51588b48caSValentina Manea { 52588b48caSValentina Manea printf("usage: %s", usbip_list_usage_string); 53588b48caSValentina Manea } 54588b48caSValentina Manea 55588b48caSValentina Manea static int get_exported_devices(char *host, int sockfd) 56588b48caSValentina Manea { 57588b48caSValentina Manea char product_name[100]; 58588b48caSValentina Manea char class_name[100]; 59588b48caSValentina Manea struct op_devlist_reply reply; 60588b48caSValentina Manea uint16_t code = OP_REP_DEVLIST; 61588b48caSValentina Manea struct usbip_usb_device udev; 62588b48caSValentina Manea struct usbip_usb_interface uintf; 63588b48caSValentina Manea unsigned int i; 64588b48caSValentina Manea int rc, j; 65588b48caSValentina Manea 66588b48caSValentina Manea rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); 67588b48caSValentina Manea if (rc < 0) { 68588b48caSValentina Manea dbg("usbip_net_send_op_common failed"); 69588b48caSValentina Manea return -1; 70588b48caSValentina Manea } 71588b48caSValentina Manea 72588b48caSValentina Manea rc = usbip_net_recv_op_common(sockfd, &code); 73588b48caSValentina Manea if (rc < 0) { 74588b48caSValentina Manea dbg("usbip_net_recv_op_common failed"); 75588b48caSValentina Manea return -1; 76588b48caSValentina Manea } 77588b48caSValentina Manea 78588b48caSValentina Manea memset(&reply, 0, sizeof(reply)); 79588b48caSValentina Manea rc = usbip_net_recv(sockfd, &reply, sizeof(reply)); 80588b48caSValentina Manea if (rc < 0) { 81588b48caSValentina Manea dbg("usbip_net_recv_op_devlist failed"); 82588b48caSValentina Manea return -1; 83588b48caSValentina Manea } 84588b48caSValentina Manea PACK_OP_DEVLIST_REPLY(0, &reply); 85588b48caSValentina Manea dbg("exportable devices: %d\n", reply.ndev); 86588b48caSValentina Manea 87588b48caSValentina Manea if (reply.ndev == 0) { 88588b48caSValentina Manea info("no exportable devices found on %s", host); 89588b48caSValentina Manea return 0; 90588b48caSValentina Manea } 91588b48caSValentina Manea 92588b48caSValentina Manea printf("Exportable USB devices\n"); 93588b48caSValentina Manea printf("======================\n"); 94588b48caSValentina Manea printf(" - %s\n", host); 95588b48caSValentina Manea 96588b48caSValentina Manea for (i = 0; i < reply.ndev; i++) { 97588b48caSValentina Manea memset(&udev, 0, sizeof(udev)); 98588b48caSValentina Manea rc = usbip_net_recv(sockfd, &udev, sizeof(udev)); 99588b48caSValentina Manea if (rc < 0) { 100588b48caSValentina Manea dbg("usbip_net_recv failed: usbip_usb_device[%d]", i); 101588b48caSValentina Manea return -1; 102588b48caSValentina Manea } 103588b48caSValentina Manea usbip_net_pack_usb_device(0, &udev); 104588b48caSValentina Manea 105588b48caSValentina Manea usbip_names_get_product(product_name, sizeof(product_name), 106588b48caSValentina Manea udev.idVendor, udev.idProduct); 107588b48caSValentina Manea usbip_names_get_class(class_name, sizeof(class_name), 108588b48caSValentina Manea udev.bDeviceClass, udev.bDeviceSubClass, 109588b48caSValentina Manea udev.bDeviceProtocol); 110588b48caSValentina Manea printf("%11s: %s\n", udev.busid, product_name); 111588b48caSValentina Manea printf("%11s: %s\n", "", udev.path); 112588b48caSValentina Manea printf("%11s: %s\n", "", class_name); 113588b48caSValentina Manea 114588b48caSValentina Manea for (j = 0; j < udev.bNumInterfaces; j++) { 115588b48caSValentina Manea rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf)); 116588b48caSValentina Manea if (rc < 0) { 117588b48caSValentina Manea err("usbip_net_recv failed: usbip_usb_intf[%d]", 118588b48caSValentina Manea j); 119588b48caSValentina Manea 120588b48caSValentina Manea return -1; 121588b48caSValentina Manea } 122588b48caSValentina Manea usbip_net_pack_usb_interface(0, &uintf); 123588b48caSValentina Manea 124588b48caSValentina Manea usbip_names_get_class(class_name, sizeof(class_name), 125588b48caSValentina Manea uintf.bInterfaceClass, 126588b48caSValentina Manea uintf.bInterfaceSubClass, 127588b48caSValentina Manea uintf.bInterfaceProtocol); 128588b48caSValentina Manea printf("%11s: %2d - %s\n", "", j, class_name); 129588b48caSValentina Manea } 130588b48caSValentina Manea 131588b48caSValentina Manea printf("\n"); 132588b48caSValentina Manea } 133588b48caSValentina Manea 134588b48caSValentina Manea return 0; 135588b48caSValentina Manea } 136588b48caSValentina Manea 137588b48caSValentina Manea static int list_exported_devices(char *host) 138588b48caSValentina Manea { 139588b48caSValentina Manea int rc; 140588b48caSValentina Manea int sockfd; 141588b48caSValentina Manea 142588b48caSValentina Manea sockfd = usbip_net_tcp_connect(host, usbip_port_string); 143588b48caSValentina Manea if (sockfd < 0) { 144588b48caSValentina Manea err("could not connect to %s:%s: %s", host, 145588b48caSValentina Manea usbip_port_string, gai_strerror(sockfd)); 146588b48caSValentina Manea return -1; 147588b48caSValentina Manea } 148588b48caSValentina Manea dbg("connected to %s:%s", host, usbip_port_string); 149588b48caSValentina Manea 150588b48caSValentina Manea rc = get_exported_devices(host, sockfd); 151588b48caSValentina Manea if (rc < 0) { 152588b48caSValentina Manea err("failed to get device list from %s", host); 153588b48caSValentina Manea return -1; 154588b48caSValentina Manea } 155588b48caSValentina Manea 156588b48caSValentina Manea close(sockfd); 157588b48caSValentina Manea 158588b48caSValentina Manea return 0; 159588b48caSValentina Manea } 160588b48caSValentina Manea 161588b48caSValentina Manea static void print_device(const char *busid, const char *vendor, 162588b48caSValentina Manea const char *product, bool parsable) 163588b48caSValentina Manea { 164588b48caSValentina Manea if (parsable) 165588b48caSValentina Manea printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product); 166588b48caSValentina Manea else 167588b48caSValentina Manea printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product); 168588b48caSValentina Manea } 169588b48caSValentina Manea 170588b48caSValentina Manea static void print_product_name(char *product_name, bool parsable) 171588b48caSValentina Manea { 172588b48caSValentina Manea if (!parsable) 173588b48caSValentina Manea printf(" %s\n", product_name); 174588b48caSValentina Manea } 175588b48caSValentina Manea 176588b48caSValentina Manea static int list_devices(bool parsable) 177588b48caSValentina Manea { 178588b48caSValentina Manea struct udev *udev; 179588b48caSValentina Manea struct udev_enumerate *enumerate; 180588b48caSValentina Manea struct udev_list_entry *devices, *dev_list_entry; 181588b48caSValentina Manea struct udev_device *dev; 182588b48caSValentina Manea const char *path; 183588b48caSValentina Manea const char *idVendor; 184588b48caSValentina Manea const char *idProduct; 185588b48caSValentina Manea const char *bConfValue; 186588b48caSValentina Manea const char *bNumIntfs; 187588b48caSValentina Manea const char *busid; 188588b48caSValentina Manea char product_name[128]; 189588b48caSValentina Manea int ret = -1; 190ef824501SShuah Khan const char *devpath; 191588b48caSValentina Manea 192588b48caSValentina Manea /* Create libudev context. */ 193588b48caSValentina Manea udev = udev_new(); 194588b48caSValentina Manea 195588b48caSValentina Manea /* Create libudev device enumeration. */ 196588b48caSValentina Manea enumerate = udev_enumerate_new(udev); 197588b48caSValentina Manea 198588b48caSValentina Manea /* Take only USB devices that are not hubs and do not have 199588b48caSValentina Manea * the bInterfaceNumber attribute, i.e. are not interfaces. 200588b48caSValentina Manea */ 201588b48caSValentina Manea udev_enumerate_add_match_subsystem(enumerate, "usb"); 202588b48caSValentina Manea udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09"); 203588b48caSValentina Manea udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL); 204588b48caSValentina Manea udev_enumerate_scan_devices(enumerate); 205588b48caSValentina Manea 206588b48caSValentina Manea devices = udev_enumerate_get_list_entry(enumerate); 207588b48caSValentina Manea 208588b48caSValentina Manea /* Show information about each device. */ 209588b48caSValentina Manea udev_list_entry_foreach(dev_list_entry, devices) { 210588b48caSValentina Manea path = udev_list_entry_get_name(dev_list_entry); 211588b48caSValentina Manea dev = udev_device_new_from_syspath(udev, path); 212588b48caSValentina Manea 213ef824501SShuah Khan /* Ignore devices attached to vhci_hcd */ 214ef824501SShuah Khan devpath = udev_device_get_devpath(dev); 215ef824501SShuah Khan if (strstr(devpath, USBIP_VHCI_DRV_NAME)) { 216ef824501SShuah Khan dbg("Skip the device %s already attached to %s\n", 217ef824501SShuah Khan devpath, USBIP_VHCI_DRV_NAME); 218ef824501SShuah Khan continue; 219ef824501SShuah Khan } 220ef824501SShuah Khan 221588b48caSValentina Manea /* Get device information. */ 222588b48caSValentina Manea idVendor = udev_device_get_sysattr_value(dev, "idVendor"); 223588b48caSValentina Manea idProduct = udev_device_get_sysattr_value(dev, "idProduct"); 224e0546fd8SIgor Kotrasinski bConfValue = udev_device_get_sysattr_value(dev, 225e0546fd8SIgor Kotrasinski "bConfigurationValue"); 226e0546fd8SIgor Kotrasinski bNumIntfs = udev_device_get_sysattr_value(dev, 227e0546fd8SIgor Kotrasinski "bNumInterfaces"); 228588b48caSValentina Manea busid = udev_device_get_sysname(dev); 229588b48caSValentina Manea if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { 230588b48caSValentina Manea err("problem getting device attributes: %s", 231588b48caSValentina Manea strerror(errno)); 232588b48caSValentina Manea goto err_out; 233588b48caSValentina Manea } 234588b48caSValentina Manea 235588b48caSValentina Manea /* Get product name. */ 236588b48caSValentina Manea usbip_names_get_product(product_name, sizeof(product_name), 237588b48caSValentina Manea strtol(idVendor, NULL, 16), 238588b48caSValentina Manea strtol(idProduct, NULL, 16)); 239588b48caSValentina Manea 240588b48caSValentina Manea /* Print information. */ 241588b48caSValentina Manea print_device(busid, idVendor, idProduct, parsable); 242588b48caSValentina Manea print_product_name(product_name, parsable); 243588b48caSValentina Manea 244588b48caSValentina Manea printf("\n"); 245588b48caSValentina Manea 246588b48caSValentina Manea udev_device_unref(dev); 247588b48caSValentina Manea } 248588b48caSValentina Manea 249588b48caSValentina Manea ret = 0; 250588b48caSValentina Manea 251588b48caSValentina Manea err_out: 252588b48caSValentina Manea udev_enumerate_unref(enumerate); 253588b48caSValentina Manea udev_unref(udev); 254588b48caSValentina Manea 255588b48caSValentina Manea return ret; 256588b48caSValentina Manea } 257588b48caSValentina Manea 258e0546fd8SIgor Kotrasinski static int list_gadget_devices(bool parsable) 259e0546fd8SIgor Kotrasinski { 260e0546fd8SIgor Kotrasinski int ret = -1; 261e0546fd8SIgor Kotrasinski struct udev *udev; 262e0546fd8SIgor Kotrasinski struct udev_enumerate *enumerate; 263e0546fd8SIgor Kotrasinski struct udev_list_entry *devices, *dev_list_entry; 264e0546fd8SIgor Kotrasinski struct udev_device *dev; 265e0546fd8SIgor Kotrasinski const char *path; 266e0546fd8SIgor Kotrasinski const char *driver; 267e0546fd8SIgor Kotrasinski 268e0546fd8SIgor Kotrasinski const struct usb_device_descriptor *d_desc; 269e0546fd8SIgor Kotrasinski const char *descriptors; 270e0546fd8SIgor Kotrasinski char product_name[128]; 271e0546fd8SIgor Kotrasinski 272e0546fd8SIgor Kotrasinski uint16_t idVendor; 273e0546fd8SIgor Kotrasinski char idVendor_buf[8]; 274e0546fd8SIgor Kotrasinski uint16_t idProduct; 275e0546fd8SIgor Kotrasinski char idProduct_buf[8]; 276e0546fd8SIgor Kotrasinski const char *busid; 277e0546fd8SIgor Kotrasinski 278e0546fd8SIgor Kotrasinski udev = udev_new(); 279e0546fd8SIgor Kotrasinski enumerate = udev_enumerate_new(udev); 280e0546fd8SIgor Kotrasinski 281e0546fd8SIgor Kotrasinski udev_enumerate_add_match_subsystem(enumerate, "platform"); 282e0546fd8SIgor Kotrasinski 283e0546fd8SIgor Kotrasinski udev_enumerate_scan_devices(enumerate); 284e0546fd8SIgor Kotrasinski devices = udev_enumerate_get_list_entry(enumerate); 285e0546fd8SIgor Kotrasinski 286e0546fd8SIgor Kotrasinski udev_list_entry_foreach(dev_list_entry, devices) { 287e0546fd8SIgor Kotrasinski path = udev_list_entry_get_name(dev_list_entry); 288e0546fd8SIgor Kotrasinski dev = udev_device_new_from_syspath(udev, path); 289e0546fd8SIgor Kotrasinski 290e0546fd8SIgor Kotrasinski driver = udev_device_get_driver(dev); 291e0546fd8SIgor Kotrasinski /* We only have mechanism to enumerate gadgets bound to vudc */ 292e0546fd8SIgor Kotrasinski if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME)) 293e0546fd8SIgor Kotrasinski continue; 294e0546fd8SIgor Kotrasinski 295e0546fd8SIgor Kotrasinski /* Get device information. */ 296e0546fd8SIgor Kotrasinski descriptors = udev_device_get_sysattr_value(dev, 297e0546fd8SIgor Kotrasinski VUDC_DEVICE_DESCR_FILE); 298e0546fd8SIgor Kotrasinski 299e0546fd8SIgor Kotrasinski if (!descriptors) { 300e0546fd8SIgor Kotrasinski err("problem getting device attributes: %s", 301e0546fd8SIgor Kotrasinski strerror(errno)); 302e0546fd8SIgor Kotrasinski goto err_out; 303e0546fd8SIgor Kotrasinski } 304e0546fd8SIgor Kotrasinski 305e0546fd8SIgor Kotrasinski d_desc = (const struct usb_device_descriptor *) descriptors; 306e0546fd8SIgor Kotrasinski 307e0546fd8SIgor Kotrasinski idVendor = le16toh(d_desc->idVendor); 308e0546fd8SIgor Kotrasinski sprintf(idVendor_buf, "0x%4x", idVendor); 309e0546fd8SIgor Kotrasinski idProduct = le16toh(d_desc->idProduct); 310e0546fd8SIgor Kotrasinski sprintf(idProduct_buf, "0x%4x", idVendor); 311e0546fd8SIgor Kotrasinski busid = udev_device_get_sysname(dev); 312e0546fd8SIgor Kotrasinski 313e0546fd8SIgor Kotrasinski /* Get product name. */ 314e0546fd8SIgor Kotrasinski usbip_names_get_product(product_name, sizeof(product_name), 315e0546fd8SIgor Kotrasinski le16toh(idVendor), 316e0546fd8SIgor Kotrasinski le16toh(idProduct)); 317e0546fd8SIgor Kotrasinski 318e0546fd8SIgor Kotrasinski /* Print information. */ 319e0546fd8SIgor Kotrasinski print_device(busid, idVendor_buf, idProduct_buf, parsable); 320e0546fd8SIgor Kotrasinski print_product_name(product_name, parsable); 321e0546fd8SIgor Kotrasinski 322e0546fd8SIgor Kotrasinski printf("\n"); 323e0546fd8SIgor Kotrasinski 324e0546fd8SIgor Kotrasinski udev_device_unref(dev); 325e0546fd8SIgor Kotrasinski } 326e0546fd8SIgor Kotrasinski ret = 0; 327e0546fd8SIgor Kotrasinski 328e0546fd8SIgor Kotrasinski err_out: 329e0546fd8SIgor Kotrasinski udev_enumerate_unref(enumerate); 330e0546fd8SIgor Kotrasinski udev_unref(udev); 331e0546fd8SIgor Kotrasinski 332e0546fd8SIgor Kotrasinski return ret; 333e0546fd8SIgor Kotrasinski } 334e0546fd8SIgor Kotrasinski 335588b48caSValentina Manea int usbip_list(int argc, char *argv[]) 336588b48caSValentina Manea { 337588b48caSValentina Manea static const struct option opts[] = { 338588b48caSValentina Manea { "parsable", no_argument, NULL, 'p' }, 339588b48caSValentina Manea { "remote", required_argument, NULL, 'r' }, 340588b48caSValentina Manea { "local", no_argument, NULL, 'l' }, 341e0546fd8SIgor Kotrasinski { "device", no_argument, NULL, 'd' }, 342588b48caSValentina Manea { NULL, 0, NULL, 0 } 343588b48caSValentina Manea }; 344588b48caSValentina Manea 345588b48caSValentina Manea bool parsable = false; 346588b48caSValentina Manea int opt; 347588b48caSValentina Manea int ret = -1; 348588b48caSValentina Manea 349588b48caSValentina Manea if (usbip_names_init(USBIDS_FILE)) 350588b48caSValentina Manea err("failed to open %s", USBIDS_FILE); 351588b48caSValentina Manea 352588b48caSValentina Manea for (;;) { 353e0546fd8SIgor Kotrasinski opt = getopt_long(argc, argv, "pr:ld", opts, NULL); 354588b48caSValentina Manea 355588b48caSValentina Manea if (opt == -1) 356588b48caSValentina Manea break; 357588b48caSValentina Manea 358588b48caSValentina Manea switch (opt) { 359588b48caSValentina Manea case 'p': 360588b48caSValentina Manea parsable = true; 361588b48caSValentina Manea break; 362588b48caSValentina Manea case 'r': 363588b48caSValentina Manea ret = list_exported_devices(optarg); 364588b48caSValentina Manea goto out; 365588b48caSValentina Manea case 'l': 366588b48caSValentina Manea ret = list_devices(parsable); 367588b48caSValentina Manea goto out; 368e0546fd8SIgor Kotrasinski case 'd': 369e0546fd8SIgor Kotrasinski ret = list_gadget_devices(parsable); 370e0546fd8SIgor Kotrasinski goto out; 371588b48caSValentina Manea default: 372588b48caSValentina Manea goto err_out; 373588b48caSValentina Manea } 374588b48caSValentina Manea } 375588b48caSValentina Manea 376588b48caSValentina Manea err_out: 377588b48caSValentina Manea usbip_list_usage(); 378588b48caSValentina Manea out: 379588b48caSValentina Manea usbip_names_free(); 380588b48caSValentina Manea 381588b48caSValentina Manea return ret; 382588b48caSValentina Manea } 383