root/tools/usb/usbip/src/usbip_list.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbip_list_usage
  2. get_exported_devices
  3. list_exported_devices
  4. print_device
  5. print_product_name
  6. list_devices
  7. list_gadget_devices
  8. usbip_list

   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 }

/* [<][>][^][v][top][bottom][index][help] */