linux/tools/usb/usbip/libsrc/usbip_device_driver.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
   4 *               2015 Samsung Electronics
   5 * Author:       Igor Kotrasinski <i.kotrasinsk@samsung.com>
   6 *
   7 * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
   8 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
   9 *               2005-2007 Takahiro Hirofuchi
  10 */
  11
  12#include <fcntl.h>
  13#include <string.h>
  14#include <linux/usb/ch9.h>
  15
  16#include <unistd.h>
  17
  18#include "usbip_host_common.h"
  19#include "usbip_device_driver.h"
  20
  21#undef  PROGNAME
  22#define PROGNAME "libusbip"
  23
  24#define copy_descr_attr16(dev, descr, attr)                     \
  25                ((dev)->attr = le16toh((descr)->attr))          \
  26
  27#define copy_descr_attr(dev, descr, attr)                       \
  28                ((dev)->attr = (descr)->attr)                   \
  29
  30#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  31
  32static struct {
  33        enum usb_device_speed speed;
  34        const char *name;
  35} speed_names[] = {
  36        {
  37                .speed = USB_SPEED_UNKNOWN,
  38                .name = "UNKNOWN",
  39        },
  40        {
  41                .speed = USB_SPEED_LOW,
  42                .name = "low-speed",
  43        },
  44        {
  45                .speed = USB_SPEED_FULL,
  46                .name = "full-speed",
  47        },
  48        {
  49                .speed = USB_SPEED_HIGH,
  50                .name = "high-speed",
  51        },
  52        {
  53                .speed = USB_SPEED_WIRELESS,
  54                .name = "wireless",
  55        },
  56        {
  57                .speed = USB_SPEED_SUPER,
  58                .name = "super-speed",
  59        },
  60};
  61
  62static
  63int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
  64{
  65        const char *path, *name;
  66        char filepath[SYSFS_PATH_MAX];
  67        struct usb_device_descriptor descr;
  68        unsigned int i;
  69        FILE *fd = NULL;
  70        struct udev_device *plat;
  71        const char *speed;
  72        int ret = 0;
  73
  74        plat = udev_device_get_parent(sdev);
  75        path = udev_device_get_syspath(plat);
  76        snprintf(filepath, SYSFS_PATH_MAX, "%s/%s",
  77                 path, VUDC_DEVICE_DESCR_FILE);
  78        fd = fopen(filepath, "r");
  79        if (!fd)
  80                return -1;
  81        ret = fread((char *) &descr, sizeof(descr), 1, fd);
  82        if (ret < 0)
  83                goto err;
  84        fclose(fd);
  85
  86        copy_descr_attr(dev, &descr, bDeviceClass);
  87        copy_descr_attr(dev, &descr, bDeviceSubClass);
  88        copy_descr_attr(dev, &descr, bDeviceProtocol);
  89        copy_descr_attr(dev, &descr, bNumConfigurations);
  90        copy_descr_attr16(dev, &descr, idVendor);
  91        copy_descr_attr16(dev, &descr, idProduct);
  92        copy_descr_attr16(dev, &descr, bcdDevice);
  93
  94        strncpy(dev->path, path, SYSFS_PATH_MAX);
  95
  96        dev->speed = USB_SPEED_UNKNOWN;
  97        speed = udev_device_get_sysattr_value(sdev, "current_speed");
  98        if (speed) {
  99                for (i = 0; i < ARRAY_SIZE(speed_names); i++) {
 100                        if (!strcmp(speed_names[i].name, speed)) {
 101                                dev->speed = speed_names[i].speed;
 102                                break;
 103                        }
 104                }
 105        }
 106
 107        /* Only used for user output, little sense to output them in general */
 108        dev->bNumInterfaces = 0;
 109        dev->bConfigurationValue = 0;
 110        dev->busnum = 0;
 111
 112        name = udev_device_get_sysname(plat);
 113        strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE);
 114        return 0;
 115err:
 116        fclose(fd);
 117        return -1;
 118}
 119
 120static int is_my_device(struct udev_device *dev)
 121{
 122        const char *driver;
 123
 124        driver = udev_device_get_property_value(dev, "USB_UDC_NAME");
 125        return driver != NULL && !strcmp(driver, USBIP_DEVICE_DRV_NAME);
 126}
 127
 128static int usbip_device_driver_open(struct usbip_host_driver *hdriver)
 129{
 130        int ret;
 131
 132        hdriver->ndevs = 0;
 133        INIT_LIST_HEAD(&hdriver->edev_list);
 134
 135        ret = usbip_generic_driver_open(hdriver);
 136        if (ret)
 137                err("please load " USBIP_CORE_MOD_NAME ".ko and "
 138                    USBIP_DEVICE_DRV_NAME ".ko!");
 139
 140        return ret;
 141}
 142
 143struct usbip_host_driver device_driver = {
 144        .edev_list = LIST_HEAD_INIT(device_driver.edev_list),
 145        .udev_subsystem = "udc",
 146        .ops = {
 147                .open = usbip_device_driver_open,
 148                .close = usbip_generic_driver_close,
 149                .refresh_device_list = usbip_generic_refresh_device_list,
 150                .get_device = usbip_generic_get_device,
 151                .read_device = read_usb_vudc_device,
 152                .is_my_device = is_my_device,
 153        },
 154};
 155