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