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