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
  38void usbip_list_usage(void)
  39{
  40        printf("usage: %s", usbip_list_usage_string);
  41}
  42
  43static 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
 127static 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
 151static 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
 160static void print_product_name(char *product_name, bool parsable)
 161{
 162        if (!parsable)
 163                printf("   %s\n", product_name);
 164}
 165
 166static 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
 241err_out:
 242        udev_enumerate_unref(enumerate);
 243        udev_unref(udev);
 244
 245        return ret;
 246}
 247
 248static 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
 318err_out:
 319        udev_enumerate_unref(enumerate);
 320        udev_unref(udev);
 321
 322        return ret;
 323}
 324
 325int 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
 366err_out:
 367        usbip_list_usage();
 368out:
 369        usbip_names_free();
 370
 371        return ret;
 372}
 373