linux/tools/usb/usbip/src/usbip_list.c
<<
>>
Prefs
   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
  44static 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
  50void usbip_list_usage(void)
  51{
  52        printf("usage: %s", usbip_list_usage_string);
  53}
  54
  55static 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
 137static 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
 161static 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
 170static void print_product_name(char *product_name, bool parsable)
 171{
 172        if (!parsable)
 173                printf("   %s\n", product_name);
 174}
 175
 176static 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
 251err_out:
 252        udev_enumerate_unref(enumerate);
 253        udev_unref(udev);
 254
 255        return ret;
 256}
 257
 258static 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
 328err_out:
 329        udev_enumerate_unref(enumerate);
 330        udev_unref(udev);
 331
 332        return ret;
 333}
 334
 335int 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
 376err_out:
 377        usbip_list_usage();
 378out:
 379        usbip_names_free();
 380
 381        return ret;
 382}
 383