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/types.h> 11 #include <libudev.h> 12 13 #include <errno.h> 14 #include <stdbool.h> 15 #include <stdint.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include <getopt.h> 21 #include <netdb.h> 22 #include <unistd.h> 23 24 #include <dirent.h> 25 26 #include <linux/usb/ch9.h> 27 28 #include "usbip_common.h" 29 #include "usbip_network.h" 30 #include "usbip.h" 31 32 static const char usbip_list_usage_string[] = 33 "usbip list [-p|--parsable] <args>\n" 34 " -p, --parsable Parsable list format\n" 35 " -r, --remote=<host> List the exportable USB devices on <host>\n" 36 " -l, --local List the local USB devices\n"; 37 38 void usbip_list_usage(void) 39 { 40 printf("usage: %s", usbip_list_usage_string); 41 } 42 43 static int get_exported_devices(char *host, int sockfd) 44 { 45 char product_name[100]; 46 char class_name[100]; 47 struct op_devlist_reply reply; 48 uint16_t code = OP_REP_DEVLIST; 49 struct usbip_usb_device udev; 50 struct usbip_usb_interface uintf; 51 unsigned int i; 52 int rc, j; 53 int status; 54 55 rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); 56 if (rc < 0) { 57 dbg("usbip_net_send_op_common failed"); 58 return -1; 59 } 60 61 rc = usbip_net_recv_op_common(sockfd, &code, &status); 62 if (rc < 0) { 63 err("Exported Device List Request failed - %s\n", 64 usbip_op_common_status_string(status)); 65 return -1; 66 } 67 68 memset(&reply, 0, sizeof(reply)); 69 rc = usbip_net_recv(sockfd, &reply, sizeof(reply)); 70 if (rc < 0) { 71 dbg("usbip_net_recv_op_devlist failed"); 72 return -1; 73 } 74 PACK_OP_DEVLIST_REPLY(0, &reply); 75 dbg("exportable devices: %d\n", reply.ndev); 76 77 if (reply.ndev == 0) { 78 info("no exportable devices found on %s", host); 79 return 0; 80 } 81 82 printf("Exportable USB devices\n"); 83 printf("======================\n"); 84 printf(" - %s\n", host); 85 86 for (i = 0; i < reply.ndev; i++) { 87 memset(&udev, 0, sizeof(udev)); 88 rc = usbip_net_recv(sockfd, &udev, sizeof(udev)); 89 if (rc < 0) { 90 dbg("usbip_net_recv failed: usbip_usb_device[%d]", i); 91 return -1; 92 } 93 usbip_net_pack_usb_device(0, &udev); 94 95 usbip_names_get_product(product_name, sizeof(product_name), 96 udev.idVendor, udev.idProduct); 97 usbip_names_get_class(class_name, sizeof(class_name), 98 udev.bDeviceClass, udev.bDeviceSubClass, 99 udev.bDeviceProtocol); 100 printf("%11s: %s\n", udev.busid, product_name); 101 printf("%11s: %s\n", "", udev.path); 102 printf("%11s: %s\n", "", class_name); 103 104 for (j = 0; j < udev.bNumInterfaces; j++) { 105 rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf)); 106 if (rc < 0) { 107 err("usbip_net_recv failed: usbip_usb_intf[%d]", 108 j); 109 110 return -1; 111 } 112 usbip_net_pack_usb_interface(0, &uintf); 113 114 usbip_names_get_class(class_name, sizeof(class_name), 115 uintf.bInterfaceClass, 116 uintf.bInterfaceSubClass, 117 uintf.bInterfaceProtocol); 118 printf("%11s: %2d - %s\n", "", j, class_name); 119 } 120 121 printf("\n"); 122 } 123 124 return 0; 125 } 126 127 static int list_exported_devices(char *host) 128 { 129 int rc; 130 int sockfd; 131 132 sockfd = usbip_net_tcp_connect(host, usbip_port_string); 133 if (sockfd < 0) { 134 err("could not connect to %s:%s: %s", host, 135 usbip_port_string, gai_strerror(sockfd)); 136 return -1; 137 } 138 dbg("connected to %s:%s", host, usbip_port_string); 139 140 rc = get_exported_devices(host, sockfd); 141 if (rc < 0) { 142 err("failed to get device list from %s", host); 143 return -1; 144 } 145 146 close(sockfd); 147 148 return 0; 149 } 150 151 static void print_device(const char *busid, const char *vendor, 152 const char *product, bool parsable) 153 { 154 if (parsable) 155 printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product); 156 else 157 printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product); 158 } 159 160 static void print_product_name(char *product_name, bool parsable) 161 { 162 if (!parsable) 163 printf(" %s\n", product_name); 164 } 165 166 static int list_devices(bool parsable) 167 { 168 struct udev *udev; 169 struct udev_enumerate *enumerate; 170 struct udev_list_entry *devices, *dev_list_entry; 171 struct udev_device *dev; 172 const char *path; 173 const char *idVendor; 174 const char *idProduct; 175 const char *bConfValue; 176 const char *bNumIntfs; 177 const char *busid; 178 char product_name[128]; 179 int ret = -1; 180 const char *devpath; 181 182 /* Create libudev context. */ 183 udev = udev_new(); 184 185 /* Create libudev device enumeration. */ 186 enumerate = udev_enumerate_new(udev); 187 188 /* Take only USB devices that are not hubs and do not have 189 * the bInterfaceNumber attribute, i.e. are not interfaces. 190 */ 191 udev_enumerate_add_match_subsystem(enumerate, "usb"); 192 udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09"); 193 udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL); 194 udev_enumerate_scan_devices(enumerate); 195 196 devices = udev_enumerate_get_list_entry(enumerate); 197 198 /* Show information about each device. */ 199 udev_list_entry_foreach(dev_list_entry, devices) { 200 path = udev_list_entry_get_name(dev_list_entry); 201 dev = udev_device_new_from_syspath(udev, path); 202 203 /* Ignore devices attached to vhci_hcd */ 204 devpath = udev_device_get_devpath(dev); 205 if (strstr(devpath, USBIP_VHCI_DRV_NAME)) { 206 dbg("Skip the device %s already attached to %s\n", 207 devpath, USBIP_VHCI_DRV_NAME); 208 continue; 209 } 210 211 /* Get device information. */ 212 idVendor = udev_device_get_sysattr_value(dev, "idVendor"); 213 idProduct = udev_device_get_sysattr_value(dev, "idProduct"); 214 bConfValue = udev_device_get_sysattr_value(dev, 215 "bConfigurationValue"); 216 bNumIntfs = udev_device_get_sysattr_value(dev, 217 "bNumInterfaces"); 218 busid = udev_device_get_sysname(dev); 219 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { 220 err("problem getting device attributes: %s", 221 strerror(errno)); 222 goto err_out; 223 } 224 225 /* Get product name. */ 226 usbip_names_get_product(product_name, sizeof(product_name), 227 strtol(idVendor, NULL, 16), 228 strtol(idProduct, NULL, 16)); 229 230 /* Print information. */ 231 print_device(busid, idVendor, idProduct, parsable); 232 print_product_name(product_name, parsable); 233 234 printf("\n"); 235 236 udev_device_unref(dev); 237 } 238 239 ret = 0; 240 241 err_out: 242 udev_enumerate_unref(enumerate); 243 udev_unref(udev); 244 245 return ret; 246 } 247 248 static int list_gadget_devices(bool parsable) 249 { 250 int ret = -1; 251 struct udev *udev; 252 struct udev_enumerate *enumerate; 253 struct udev_list_entry *devices, *dev_list_entry; 254 struct udev_device *dev; 255 const char *path; 256 const char *driver; 257 258 const struct usb_device_descriptor *d_desc; 259 const char *descriptors; 260 char product_name[128]; 261 262 uint16_t idVendor; 263 char idVendor_buf[8]; 264 uint16_t idProduct; 265 char idProduct_buf[8]; 266 const char *busid; 267 268 udev = udev_new(); 269 enumerate = udev_enumerate_new(udev); 270 271 udev_enumerate_add_match_subsystem(enumerate, "platform"); 272 273 udev_enumerate_scan_devices(enumerate); 274 devices = udev_enumerate_get_list_entry(enumerate); 275 276 udev_list_entry_foreach(dev_list_entry, devices) { 277 path = udev_list_entry_get_name(dev_list_entry); 278 dev = udev_device_new_from_syspath(udev, path); 279 280 driver = udev_device_get_driver(dev); 281 /* We only have mechanism to enumerate gadgets bound to vudc */ 282 if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME)) 283 continue; 284 285 /* Get device information. */ 286 descriptors = udev_device_get_sysattr_value(dev, 287 VUDC_DEVICE_DESCR_FILE); 288 289 if (!descriptors) { 290 err("problem getting device attributes: %s", 291 strerror(errno)); 292 goto err_out; 293 } 294 295 d_desc = (const struct usb_device_descriptor *) descriptors; 296 297 idVendor = le16toh(d_desc->idVendor); 298 sprintf(idVendor_buf, "0x%4x", idVendor); 299 idProduct = le16toh(d_desc->idProduct); 300 sprintf(idProduct_buf, "0x%4x", idVendor); 301 busid = udev_device_get_sysname(dev); 302 303 /* Get product name. */ 304 usbip_names_get_product(product_name, sizeof(product_name), 305 le16toh(idVendor), 306 le16toh(idProduct)); 307 308 /* Print information. */ 309 print_device(busid, idVendor_buf, idProduct_buf, parsable); 310 print_product_name(product_name, parsable); 311 312 printf("\n"); 313 314 udev_device_unref(dev); 315 } 316 ret = 0; 317 318 err_out: 319 udev_enumerate_unref(enumerate); 320 udev_unref(udev); 321 322 return ret; 323 } 324 325 int usbip_list(int argc, char *argv[]) 326 { 327 static const struct option opts[] = { 328 { "parsable", no_argument, NULL, 'p' }, 329 { "remote", required_argument, NULL, 'r' }, 330 { "local", no_argument, NULL, 'l' }, 331 { "device", no_argument, NULL, 'd' }, 332 { NULL, 0, NULL, 0 } 333 }; 334 335 bool parsable = false; 336 int opt; 337 int ret = -1; 338 339 if (usbip_names_init(USBIDS_FILE)) 340 err("failed to open %s", USBIDS_FILE); 341 342 for (;;) { 343 opt = getopt_long(argc, argv, "pr:ld", opts, NULL); 344 345 if (opt == -1) 346 break; 347 348 switch (opt) { 349 case 'p': 350 parsable = true; 351 break; 352 case 'r': 353 ret = list_exported_devices(optarg); 354 goto out; 355 case 'l': 356 ret = list_devices(parsable); 357 goto out; 358 case 'd': 359 ret = list_gadget_devices(parsable); 360 goto out; 361 default: 362 goto err_out; 363 } 364 } 365 366 err_out: 367 usbip_list_usage(); 368 out: 369 usbip_names_free(); 370 371 return ret; 372 } 373