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