linux/tools/usb/usbip/src/usbip_list.c
<<
>>
Prefs
   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
  32static 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        "    -d, --device           List the local USB gadgets bound to usbip-vudc\n";
  38
  39void usbip_list_usage(void)
  40{
  41        printf("usage: %s", usbip_list_usage_string);
  42}
  43
  44static int get_exported_devices(char *host, int sockfd)
  45{
  46        char product_name[100];
  47        char class_name[100];
  48        struct op_devlist_reply reply;
  49        uint16_t code = OP_REP_DEVLIST;
  50        struct usbip_usb_device udev;
  51        struct usbip_usb_interface uintf;
  52        unsigned int i;
  53        int rc, j;
  54        int status;
  55
  56        rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
  57        if (rc < 0) {
  58                dbg("usbip_net_send_op_common failed");
  59                return -1;
  60        }
  61
  62        rc = usbip_net_recv_op_common(sockfd, &code, &status);
  63        if (rc < 0) {
  64                err("Exported Device List Request failed - %s\n",
  65                    usbip_op_common_status_string(status));
  66                return -1;
  67        }
  68
  69        memset(&reply, 0, sizeof(reply));
  70        rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
  71        if (rc < 0) {
  72                dbg("usbip_net_recv_op_devlist failed");
  73                return -1;
  74        }
  75        PACK_OP_DEVLIST_REPLY(0, &reply);
  76        dbg("exportable devices: %d\n", reply.ndev);
  77
  78        if (reply.ndev == 0) {
  79                info("no exportable devices found on %s", host);
  80                return 0;
  81        }
  82
  83        printf("Exportable USB devices\n");
  84        printf("======================\n");
  85        printf(" - %s\n", host);
  86
  87        for (i = 0; i < reply.ndev; i++) {
  88                memset(&udev, 0, sizeof(udev));
  89                rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
  90                if (rc < 0) {
  91                        dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
  92                        return -1;
  93                }
  94                usbip_net_pack_usb_device(0, &udev);
  95
  96                usbip_names_get_product(product_name, sizeof(product_name),
  97                                        udev.idVendor, udev.idProduct);
  98                usbip_names_get_class(class_name, sizeof(class_name),
  99                                      udev.bDeviceClass, udev.bDeviceSubClass,
 100                                      udev.bDeviceProtocol);
 101                printf("%11s: %s\n", udev.busid, product_name);
 102                printf("%11s: %s\n", "", udev.path);
 103                printf("%11s: %s\n", "", class_name);
 104
 105                for (j = 0; j < udev.bNumInterfaces; j++) {
 106                        rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
 107                        if (rc < 0) {
 108                                err("usbip_net_recv failed: usbip_usb_intf[%d]",
 109                                                j);
 110
 111                                return -1;
 112                        }
 113                        usbip_net_pack_usb_interface(0, &uintf);
 114
 115                        usbip_names_get_class(class_name, sizeof(class_name),
 116                                        uintf.bInterfaceClass,
 117                                        uintf.bInterfaceSubClass,
 118                                        uintf.bInterfaceProtocol);
 119                        printf("%11s: %2d - %s\n", "", j, class_name);
 120                }
 121
 122                printf("\n");
 123        }
 124
 125        return 0;
 126}
 127
 128static int list_exported_devices(char *host)
 129{
 130        int rc;
 131        int sockfd;
 132
 133        sockfd = usbip_net_tcp_connect(host, usbip_port_string);
 134        if (sockfd < 0) {
 135                err("could not connect to %s:%s: %s", host,
 136                    usbip_port_string, gai_strerror(sockfd));
 137                return -1;
 138        }
 139        dbg("connected to %s:%s", host, usbip_port_string);
 140
 141        rc = get_exported_devices(host, sockfd);
 142        if (rc < 0) {
 143                err("failed to get device list from %s", host);
 144                return -1;
 145        }
 146
 147        close(sockfd);
 148
 149        return 0;
 150}
 151
 152static void print_device(const char *busid, const char *vendor,
 153                         const char *product, bool parsable)
 154{
 155        if (parsable)
 156                printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
 157        else
 158                printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
 159}
 160
 161static void print_product_name(char *product_name, bool parsable)
 162{
 163        if (!parsable)
 164                printf("   %s\n", product_name);
 165}
 166
 167static int list_devices(bool parsable)
 168{
 169        struct udev *udev;
 170        struct udev_enumerate *enumerate;
 171        struct udev_list_entry *devices, *dev_list_entry;
 172        struct udev_device *dev;
 173        const char *path;
 174        const char *idVendor;
 175        const char *idProduct;
 176        const char *bConfValue;
 177        const char *bNumIntfs;
 178        const char *busid;
 179        char product_name[128];
 180        int ret = -1;
 181        const char *devpath;
 182
 183        /* Create libudev context. */
 184        udev = udev_new();
 185
 186        /* Create libudev device enumeration. */
 187        enumerate = udev_enumerate_new(udev);
 188
 189        /* Take only USB devices that are not hubs and do not have
 190         * the bInterfaceNumber attribute, i.e. are not interfaces.
 191         */
 192        udev_enumerate_add_match_subsystem(enumerate, "usb");
 193        udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");
 194        udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);
 195        udev_enumerate_scan_devices(enumerate);
 196
 197        devices = udev_enumerate_get_list_entry(enumerate);
 198
 199        /* Show information about each device. */
 200        udev_list_entry_foreach(dev_list_entry, devices) {
 201                path = udev_list_entry_get_name(dev_list_entry);
 202                dev = udev_device_new_from_syspath(udev, path);
 203
 204                /* Ignore devices attached to vhci_hcd */
 205                devpath = udev_device_get_devpath(dev);
 206                if (strstr(devpath, USBIP_VHCI_DRV_NAME)) {
 207                        dbg("Skip the device %s already attached to %s\n",
 208                            devpath, USBIP_VHCI_DRV_NAME);
 209                        continue;
 210                }
 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
 242err_out:
 243        udev_enumerate_unref(enumerate);
 244        udev_unref(udev);
 245
 246        return ret;
 247}
 248
 249static 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
 319err_out:
 320        udev_enumerate_unref(enumerate);
 321        udev_unref(udev);
 322
 323        return ret;
 324}
 325
 326int 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
 367err_out:
 368        usbip_list_usage();
 369out:
 370        usbip_names_free();
 371
 372        return ret;
 373}
 374