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        int status;
  66
  67        rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
  68        if (rc < 0) {
  69                dbg("usbip_net_send_op_common failed");
  70                return -1;
  71        }
  72
  73        rc = usbip_net_recv_op_common(sockfd, &code, &status);
  74        if (rc < 0) {
  75                err("Exported Device List Request failed - %s\n",
  76                    usbip_op_common_status_string(status));
  77                return -1;
  78        }
  79
  80        memset(&reply, 0, sizeof(reply));
  81        rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
  82        if (rc < 0) {
  83                dbg("usbip_net_recv_op_devlist failed");
  84                return -1;
  85        }
  86        PACK_OP_DEVLIST_REPLY(0, &reply);
  87        dbg("exportable devices: %d\n", reply.ndev);
  88
  89        if (reply.ndev == 0) {
  90                info("no exportable devices found on %s", host);
  91                return 0;
  92        }
  93
  94        printf("Exportable USB devices\n");
  95        printf("======================\n");
  96        printf(" - %s\n", host);
  97
  98        for (i = 0; i < reply.ndev; i++) {
  99                memset(&udev, 0, sizeof(udev));
 100                rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
 101                if (rc < 0) {
 102                        dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
 103                        return -1;
 104                }
 105                usbip_net_pack_usb_device(0, &udev);
 106
 107                usbip_names_get_product(product_name, sizeof(product_name),
 108                                        udev.idVendor, udev.idProduct);
 109                usbip_names_get_class(class_name, sizeof(class_name),
 110                                      udev.bDeviceClass, udev.bDeviceSubClass,
 111                                      udev.bDeviceProtocol);
 112                printf("%11s: %s\n", udev.busid, product_name);
 113                printf("%11s: %s\n", "", udev.path);
 114                printf("%11s: %s\n", "", class_name);
 115
 116                for (j = 0; j < udev.bNumInterfaces; j++) {
 117                        rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
 118                        if (rc < 0) {
 119                                err("usbip_net_recv failed: usbip_usb_intf[%d]",
 120                                                j);
 121
 122                                return -1;
 123                        }
 124                        usbip_net_pack_usb_interface(0, &uintf);
 125
 126                        usbip_names_get_class(class_name, sizeof(class_name),
 127                                        uintf.bInterfaceClass,
 128                                        uintf.bInterfaceSubClass,
 129                                        uintf.bInterfaceProtocol);
 130                        printf("%11s: %2d - %s\n", "", j, class_name);
 131                }
 132
 133                printf("\n");
 134        }
 135
 136        return 0;
 137}
 138
 139static int list_exported_devices(char *host)
 140{
 141        int rc;
 142        int sockfd;
 143
 144        sockfd = usbip_net_tcp_connect(host, usbip_port_string);
 145        if (sockfd < 0) {
 146                err("could not connect to %s:%s: %s", host,
 147                    usbip_port_string, gai_strerror(sockfd));
 148                return -1;
 149        }
 150        dbg("connected to %s:%s", host, usbip_port_string);
 151
 152        rc = get_exported_devices(host, sockfd);
 153        if (rc < 0) {
 154                err("failed to get device list from %s", host);
 155                return -1;
 156        }
 157
 158        close(sockfd);
 159
 160        return 0;
 161}
 162
 163static void print_device(const char *busid, const char *vendor,
 164                         const char *product, bool parsable)
 165{
 166        if (parsable)
 167                printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
 168        else
 169                printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
 170}
 171
 172static void print_product_name(char *product_name, bool parsable)
 173{
 174        if (!parsable)
 175                printf("   %s\n", product_name);
 176}
 177
 178static int list_devices(bool parsable)
 179{
 180        struct udev *udev;
 181        struct udev_enumerate *enumerate;
 182        struct udev_list_entry *devices, *dev_list_entry;
 183        struct udev_device *dev;
 184        const char *path;
 185        const char *idVendor;
 186        const char *idProduct;
 187        const char *bConfValue;
 188        const char *bNumIntfs;
 189        const char *busid;
 190        char product_name[128];
 191        int ret = -1;
 192        const char *devpath;
 193
 194        /* Create libudev context. */
 195        udev = udev_new();
 196
 197        /* Create libudev device enumeration. */
 198        enumerate = udev_enumerate_new(udev);
 199
 200        /* Take only USB devices that are not hubs and do not have
 201         * the bInterfaceNumber attribute, i.e. are not interfaces.
 202         */
 203        udev_enumerate_add_match_subsystem(enumerate, "usb");
 204        udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");
 205        udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);
 206        udev_enumerate_scan_devices(enumerate);
 207
 208        devices = udev_enumerate_get_list_entry(enumerate);
 209
 210        /* Show information about each device. */
 211        udev_list_entry_foreach(dev_list_entry, devices) {
 212                path = udev_list_entry_get_name(dev_list_entry);
 213                dev = udev_device_new_from_syspath(udev, path);
 214
 215                /* Ignore devices attached to vhci_hcd */
 216                devpath = udev_device_get_devpath(dev);
 217                if (strstr(devpath, USBIP_VHCI_DRV_NAME)) {
 218                        dbg("Skip the device %s already attached to %s\n",
 219                            devpath, USBIP_VHCI_DRV_NAME);
 220                        continue;
 221                }
 222
 223                /* Get device information. */
 224                idVendor = udev_device_get_sysattr_value(dev, "idVendor");
 225                idProduct = udev_device_get_sysattr_value(dev, "idProduct");
 226                bConfValue = udev_device_get_sysattr_value(dev,
 227                                "bConfigurationValue");
 228                bNumIntfs = udev_device_get_sysattr_value(dev,
 229                                "bNumInterfaces");
 230                busid = udev_device_get_sysname(dev);
 231                if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
 232                        err("problem getting device attributes: %s",
 233                            strerror(errno));
 234                        goto err_out;
 235                }
 236
 237                /* Get product name. */
 238                usbip_names_get_product(product_name, sizeof(product_name),
 239                                        strtol(idVendor, NULL, 16),
 240                                        strtol(idProduct, NULL, 16));
 241
 242                /* Print information. */
 243                print_device(busid, idVendor, idProduct, parsable);
 244                print_product_name(product_name, parsable);
 245
 246                printf("\n");
 247
 248                udev_device_unref(dev);
 249        }
 250
 251        ret = 0;
 252
 253err_out:
 254        udev_enumerate_unref(enumerate);
 255        udev_unref(udev);
 256
 257        return ret;
 258}
 259
 260static int list_gadget_devices(bool parsable)
 261{
 262        int ret = -1;
 263        struct udev *udev;
 264        struct udev_enumerate *enumerate;
 265        struct udev_list_entry *devices, *dev_list_entry;
 266        struct udev_device *dev;
 267        const char *path;
 268        const char *driver;
 269
 270        const struct usb_device_descriptor *d_desc;
 271        const char *descriptors;
 272        char product_name[128];
 273
 274        uint16_t idVendor;
 275        char idVendor_buf[8];
 276        uint16_t idProduct;
 277        char idProduct_buf[8];
 278        const char *busid;
 279
 280        udev = udev_new();
 281        enumerate = udev_enumerate_new(udev);
 282
 283        udev_enumerate_add_match_subsystem(enumerate, "platform");
 284
 285        udev_enumerate_scan_devices(enumerate);
 286        devices = udev_enumerate_get_list_entry(enumerate);
 287
 288        udev_list_entry_foreach(dev_list_entry, devices) {
 289                path = udev_list_entry_get_name(dev_list_entry);
 290                dev = udev_device_new_from_syspath(udev, path);
 291
 292                driver = udev_device_get_driver(dev);
 293                /* We only have mechanism to enumerate gadgets bound to vudc */
 294                if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME))
 295                        continue;
 296
 297                /* Get device information. */
 298                descriptors = udev_device_get_sysattr_value(dev,
 299                                VUDC_DEVICE_DESCR_FILE);
 300
 301                if (!descriptors) {
 302                        err("problem getting device attributes: %s",
 303                            strerror(errno));
 304                        goto err_out;
 305                }
 306
 307                d_desc = (const struct usb_device_descriptor *) descriptors;
 308
 309                idVendor = le16toh(d_desc->idVendor);
 310                sprintf(idVendor_buf, "0x%4x", idVendor);
 311                idProduct = le16toh(d_desc->idProduct);
 312                sprintf(idProduct_buf, "0x%4x", idVendor);
 313                busid = udev_device_get_sysname(dev);
 314
 315                /* Get product name. */
 316                usbip_names_get_product(product_name, sizeof(product_name),
 317                                        le16toh(idVendor),
 318                                        le16toh(idProduct));
 319
 320                /* Print information. */
 321                print_device(busid, idVendor_buf, idProduct_buf, parsable);
 322                print_product_name(product_name, parsable);
 323
 324                printf("\n");
 325
 326                udev_device_unref(dev);
 327        }
 328        ret = 0;
 329
 330err_out:
 331        udev_enumerate_unref(enumerate);
 332        udev_unref(udev);
 333
 334        return ret;
 335}
 336
 337int usbip_list(int argc, char *argv[])
 338{
 339        static const struct option opts[] = {
 340                { "parsable", no_argument,       NULL, 'p' },
 341                { "remote",   required_argument, NULL, 'r' },
 342                { "local",    no_argument,       NULL, 'l' },
 343                { "device",    no_argument,       NULL, 'd' },
 344                { NULL,       0,                 NULL,  0  }
 345        };
 346
 347        bool parsable = false;
 348        int opt;
 349        int ret = -1;
 350
 351        if (usbip_names_init(USBIDS_FILE))
 352                err("failed to open %s", USBIDS_FILE);
 353
 354        for (;;) {
 355                opt = getopt_long(argc, argv, "pr:ld", opts, NULL);
 356
 357                if (opt == -1)
 358                        break;
 359
 360                switch (opt) {
 361                case 'p':
 362                        parsable = true;
 363                        break;
 364                case 'r':
 365                        ret = list_exported_devices(optarg);
 366                        goto out;
 367                case 'l':
 368                        ret = list_devices(parsable);
 369                        goto out;
 370                case 'd':
 371                        ret = list_gadget_devices(parsable);
 372                        goto out;
 373                default:
 374                        goto err_out;
 375                }
 376        }
 377
 378err_out:
 379        usbip_list_usage();
 380out:
 381        usbip_names_free();
 382
 383        return ret;
 384}
 385