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
 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
 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