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 191 /* Create libudev context. */ 192 udev = udev_new(); 193 194 /* Create libudev device enumeration. */ 195 enumerate = udev_enumerate_new(udev); 196 197 /* Take only USB devices that are not hubs and do not have 198 * the bInterfaceNumber attribute, i.e. are not interfaces. 199 */ 200 udev_enumerate_add_match_subsystem(enumerate, "usb"); 201 udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09"); 202 udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL); 203 udev_enumerate_scan_devices(enumerate); 204 205 devices = udev_enumerate_get_list_entry(enumerate); 206 207 /* Show information about each device. */ 208 udev_list_entry_foreach(dev_list_entry, devices) { 209 path = udev_list_entry_get_name(dev_list_entry); 210 dev = udev_device_new_from_syspath(udev, path); 211 212 /* Get device information. */ 213 idVendor = udev_device_get_sysattr_value(dev, "idVendor"); 214 idProduct = udev_device_get_sysattr_value(dev, "idProduct"); 215 bConfValue = udev_device_get_sysattr_value(dev, 216 "bConfigurationValue"); 217 bNumIntfs = udev_device_get_sysattr_value(dev, 218 "bNumInterfaces"); 219 busid = udev_device_get_sysname(dev); 220 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { 221 err("problem getting device attributes: %s", 222 strerror(errno)); 223 goto err_out; 224 } 225 226 /* Get product name. */ 227 usbip_names_get_product(product_name, sizeof(product_name), 228 strtol(idVendor, NULL, 16), 229 strtol(idProduct, NULL, 16)); 230 231 /* Print information. */ 232 print_device(busid, idVendor, idProduct, parsable); 233 print_product_name(product_name, parsable); 234 235 printf("\n"); 236 237 udev_device_unref(dev); 238 } 239 240 ret = 0; 241 242 err_out: 243 udev_enumerate_unref(enumerate); 244 udev_unref(udev); 245 246 return ret; 247 } 248 249 static int list_gadget_devices(bool parsable) 250 { 251 int ret = -1; 252 struct udev *udev; 253 struct udev_enumerate *enumerate; 254 struct udev_list_entry *devices, *dev_list_entry; 255 struct udev_device *dev; 256 const char *path; 257 const char *driver; 258 259 const struct usb_device_descriptor *d_desc; 260 const char *descriptors; 261 char product_name[128]; 262 263 uint16_t idVendor; 264 char idVendor_buf[8]; 265 uint16_t idProduct; 266 char idProduct_buf[8]; 267 const char *busid; 268 269 udev = udev_new(); 270 enumerate = udev_enumerate_new(udev); 271 272 udev_enumerate_add_match_subsystem(enumerate, "platform"); 273 274 udev_enumerate_scan_devices(enumerate); 275 devices = udev_enumerate_get_list_entry(enumerate); 276 277 udev_list_entry_foreach(dev_list_entry, devices) { 278 path = udev_list_entry_get_name(dev_list_entry); 279 dev = udev_device_new_from_syspath(udev, path); 280 281 driver = udev_device_get_driver(dev); 282 /* We only have mechanism to enumerate gadgets bound to vudc */ 283 if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME)) 284 continue; 285 286 /* Get device information. */ 287 descriptors = udev_device_get_sysattr_value(dev, 288 VUDC_DEVICE_DESCR_FILE); 289 290 if (!descriptors) { 291 err("problem getting device attributes: %s", 292 strerror(errno)); 293 goto err_out; 294 } 295 296 d_desc = (const struct usb_device_descriptor *) descriptors; 297 298 idVendor = le16toh(d_desc->idVendor); 299 sprintf(idVendor_buf, "0x%4x", idVendor); 300 idProduct = le16toh(d_desc->idProduct); 301 sprintf(idProduct_buf, "0x%4x", idVendor); 302 busid = udev_device_get_sysname(dev); 303 304 /* Get product name. */ 305 usbip_names_get_product(product_name, sizeof(product_name), 306 le16toh(idVendor), 307 le16toh(idProduct)); 308 309 /* Print information. */ 310 print_device(busid, idVendor_buf, idProduct_buf, parsable); 311 print_product_name(product_name, parsable); 312 313 printf("\n"); 314 315 udev_device_unref(dev); 316 } 317 ret = 0; 318 319 err_out: 320 udev_enumerate_unref(enumerate); 321 udev_unref(udev); 322 323 return ret; 324 } 325 326 int usbip_list(int argc, char *argv[]) 327 { 328 static const struct option opts[] = { 329 { "parsable", no_argument, NULL, 'p' }, 330 { "remote", required_argument, NULL, 'r' }, 331 { "local", no_argument, NULL, 'l' }, 332 { "device", no_argument, NULL, 'd' }, 333 { NULL, 0, NULL, 0 } 334 }; 335 336 bool parsable = false; 337 int opt; 338 int ret = -1; 339 340 if (usbip_names_init(USBIDS_FILE)) 341 err("failed to open %s", USBIDS_FILE); 342 343 for (;;) { 344 opt = getopt_long(argc, argv, "pr:ld", opts, NULL); 345 346 if (opt == -1) 347 break; 348 349 switch (opt) { 350 case 'p': 351 parsable = true; 352 break; 353 case 'r': 354 ret = list_exported_devices(optarg); 355 goto out; 356 case 'l': 357 ret = list_devices(parsable); 358 goto out; 359 case 'd': 360 ret = list_gadget_devices(parsable); 361 goto out; 362 default: 363 goto err_out; 364 } 365 } 366 367 err_out: 368 usbip_list_usage(); 369 out: 370 usbip_names_free(); 371 372 return ret; 373 } 374