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