linux/tools/usb/usbip/libsrc/usbip_common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
   4 */
   5
   6#include <libudev.h>
   7#include "usbip_common.h"
   8#include "names.h"
   9
  10#undef  PROGNAME
  11#define PROGNAME "libusbip"
  12
  13int usbip_use_syslog;
  14int usbip_use_stderr;
  15int usbip_use_debug;
  16
  17extern struct udev *udev_context;
  18
  19struct speed_string {
  20        int num;
  21        char *speed;
  22        char *desc;
  23};
  24
  25static const struct speed_string speed_strings[] = {
  26        { USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
  27        { USB_SPEED_LOW,  "1.5", "Low Speed(1.5Mbps)"  },
  28        { USB_SPEED_FULL, "12",  "Full Speed(12Mbps)" },
  29        { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
  30        { USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
  31        { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
  32        { 0, NULL, NULL }
  33};
  34
  35struct portst_string {
  36        int num;
  37        char *desc;
  38};
  39
  40static struct portst_string portst_strings[] = {
  41        { SDEV_ST_AVAILABLE,    "Device Available" },
  42        { SDEV_ST_USED,         "Device in Use" },
  43        { SDEV_ST_ERROR,        "Device Error"},
  44        { VDEV_ST_NULL,         "Port Available"},
  45        { VDEV_ST_NOTASSIGNED,  "Port Initializing"},
  46        { VDEV_ST_USED,         "Port in Use"},
  47        { VDEV_ST_ERROR,        "Port Error"},
  48        { 0, NULL}
  49};
  50
  51const char *usbip_status_string(int32_t status)
  52{
  53        for (int i = 0; portst_strings[i].desc != NULL; i++)
  54                if (portst_strings[i].num == status)
  55                        return portst_strings[i].desc;
  56
  57        return "Unknown Status";
  58}
  59
  60const char *usbip_speed_string(int num)
  61{
  62        for (int i = 0; speed_strings[i].speed != NULL; i++)
  63                if (speed_strings[i].num == num)
  64                        return speed_strings[i].desc;
  65
  66        return "Unknown Speed";
  67}
  68
  69
  70#define DBG_UDEV_INTEGER(name)\
  71        dbg("%-20s = %x", to_string(name), (int) udev->name)
  72
  73#define DBG_UINF_INTEGER(name)\
  74        dbg("%-20s = %x", to_string(name), (int) uinf->name)
  75
  76void dump_usb_interface(struct usbip_usb_interface *uinf)
  77{
  78        char buff[100];
  79
  80        usbip_names_get_class(buff, sizeof(buff),
  81                        uinf->bInterfaceClass,
  82                        uinf->bInterfaceSubClass,
  83                        uinf->bInterfaceProtocol);
  84        dbg("%-20s = %s", "Interface(C/SC/P)", buff);
  85}
  86
  87void dump_usb_device(struct usbip_usb_device *udev)
  88{
  89        char buff[100];
  90
  91        dbg("%-20s = %s", "path",  udev->path);
  92        dbg("%-20s = %s", "busid", udev->busid);
  93
  94        usbip_names_get_class(buff, sizeof(buff),
  95                        udev->bDeviceClass,
  96                        udev->bDeviceSubClass,
  97                        udev->bDeviceProtocol);
  98        dbg("%-20s = %s", "Device(C/SC/P)", buff);
  99
 100        DBG_UDEV_INTEGER(bcdDevice);
 101
 102        usbip_names_get_product(buff, sizeof(buff),
 103                        udev->idVendor,
 104                        udev->idProduct);
 105        dbg("%-20s = %s", "Vendor/Product", buff);
 106
 107        DBG_UDEV_INTEGER(bNumConfigurations);
 108        DBG_UDEV_INTEGER(bNumInterfaces);
 109
 110        dbg("%-20s = %s", "speed",
 111                        usbip_speed_string(udev->speed));
 112
 113        DBG_UDEV_INTEGER(busnum);
 114        DBG_UDEV_INTEGER(devnum);
 115}
 116
 117
 118int read_attr_value(struct udev_device *dev, const char *name,
 119                    const char *format)
 120{
 121        const char *attr;
 122        int num = 0;
 123        int ret;
 124
 125        attr = udev_device_get_sysattr_value(dev, name);
 126        if (!attr) {
 127                err("udev_device_get_sysattr_value failed");
 128                goto err;
 129        }
 130
 131        /* The client chooses the device configuration
 132         * when attaching it so right after being bound
 133         * to usbip-host on the server the device will
 134         * have no configuration.
 135         * Therefore, attributes such as bConfigurationValue
 136         * and bNumInterfaces will not exist and sscanf will
 137         * fail. Check for these cases and don't treat them
 138         * as errors.
 139         */
 140
 141        ret = sscanf(attr, format, &num);
 142        if (ret < 1) {
 143                if (strcmp(name, "bConfigurationValue") &&
 144                                strcmp(name, "bNumInterfaces")) {
 145                        err("sscanf failed for attribute %s", name);
 146                        goto err;
 147                }
 148        }
 149
 150err:
 151
 152        return num;
 153}
 154
 155
 156int read_attr_speed(struct udev_device *dev)
 157{
 158        const char *speed;
 159
 160        speed = udev_device_get_sysattr_value(dev, "speed");
 161        if (!speed) {
 162                err("udev_device_get_sysattr_value failed");
 163                goto err;
 164        }
 165
 166        for (int i = 0; speed_strings[i].speed != NULL; i++) {
 167                if (!strcmp(speed, speed_strings[i].speed))
 168                        return speed_strings[i].num;
 169        }
 170
 171err:
 172
 173        return USB_SPEED_UNKNOWN;
 174}
 175
 176#define READ_ATTR(object, type, dev, name, format)                            \
 177        do {                                                                  \
 178                (object)->name = (type) read_attr_value(dev, to_string(name), \
 179                                                        format);              \
 180        } while (0)
 181
 182
 183int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
 184{
 185        uint32_t busnum, devnum;
 186        const char *path, *name;
 187
 188        READ_ATTR(udev, uint8_t,  sdev, bDeviceClass,           "%02x\n");
 189        READ_ATTR(udev, uint8_t,  sdev, bDeviceSubClass,        "%02x\n");
 190        READ_ATTR(udev, uint8_t,  sdev, bDeviceProtocol,        "%02x\n");
 191
 192        READ_ATTR(udev, uint16_t, sdev, idVendor,               "%04x\n");
 193        READ_ATTR(udev, uint16_t, sdev, idProduct,              "%04x\n");
 194        READ_ATTR(udev, uint16_t, sdev, bcdDevice,              "%04x\n");
 195
 196        READ_ATTR(udev, uint8_t,  sdev, bConfigurationValue,    "%02x\n");
 197        READ_ATTR(udev, uint8_t,  sdev, bNumConfigurations,     "%02x\n");
 198        READ_ATTR(udev, uint8_t,  sdev, bNumInterfaces,         "%02x\n");
 199
 200        READ_ATTR(udev, uint8_t,  sdev, devnum,                 "%d\n");
 201        udev->speed = read_attr_speed(sdev);
 202
 203        path = udev_device_get_syspath(sdev);
 204        name = udev_device_get_sysname(sdev);
 205
 206        strncpy(udev->path,  path,  SYSFS_PATH_MAX);
 207        strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE);
 208
 209        sscanf(name, "%u-%u", &busnum, &devnum);
 210        udev->busnum = busnum;
 211
 212        return 0;
 213}
 214
 215int read_usb_interface(struct usbip_usb_device *udev, int i,
 216                       struct usbip_usb_interface *uinf)
 217{
 218        char busid[SYSFS_BUS_ID_SIZE];
 219        int size;
 220        struct udev_device *sif;
 221
 222        size = snprintf(busid, sizeof(busid), "%s:%d.%d",
 223                        udev->busid, udev->bConfigurationValue, i);
 224        if (size < 0 || (unsigned int)size >= sizeof(busid)) {
 225                err("busid length %i >= %lu or < 0", size,
 226                    (long unsigned)sizeof(busid));
 227                return -1;
 228        }
 229
 230        sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
 231        if (!sif) {
 232                err("udev_device_new_from_subsystem_sysname %s failed", busid);
 233                return -1;
 234        }
 235
 236        READ_ATTR(uinf, uint8_t,  sif, bInterfaceClass,         "%02x\n");
 237        READ_ATTR(uinf, uint8_t,  sif, bInterfaceSubClass,      "%02x\n");
 238        READ_ATTR(uinf, uint8_t,  sif, bInterfaceProtocol,      "%02x\n");
 239
 240        return 0;
 241}
 242
 243int usbip_names_init(char *f)
 244{
 245        return names_init(f);
 246}
 247
 248void usbip_names_free(void)
 249{
 250        names_free();
 251}
 252
 253void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
 254                             uint16_t product)
 255{
 256        const char *prod, *vend;
 257
 258        prod = names_product(vendor, product);
 259        if (!prod)
 260                prod = "unknown product";
 261
 262
 263        vend = names_vendor(vendor);
 264        if (!vend)
 265                vend = "unknown vendor";
 266
 267        snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
 268}
 269
 270void usbip_names_get_class(char *buff, size_t size, uint8_t class,
 271                           uint8_t subclass, uint8_t protocol)
 272{
 273        const char *c, *s, *p;
 274
 275        if (class == 0 && subclass == 0 && protocol == 0) {
 276                snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
 277                return;
 278        }
 279
 280        p = names_protocol(class, subclass, protocol);
 281        if (!p)
 282                p = "unknown protocol";
 283
 284        s = names_subclass(class, subclass);
 285        if (!s)
 286                s = "unknown subclass";
 287
 288        c = names_class(class);
 289        if (!c)
 290                c = "unknown class";
 291
 292        snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
 293}
 294