root/tools/usb/usbip/libsrc/usbip_host_common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_attr_usbip_status
  2. usbip_exported_device_new
  3. refresh_exported_devices
  4. usbip_exported_device_destroy
  5. usbip_generic_driver_open
  6. usbip_generic_driver_close
  7. usbip_generic_refresh_device_list
  8. usbip_export_device
  9. usbip_generic_get_device

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2015-2016 Samsung Electronics
   4  *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
   5  *               Krzysztof Opasiak <k.opasiak@samsung.com>
   6  *
   7  * Refactored from usbip_host_driver.c, which is:
   8  * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
   9  *               2005-2007 Takahiro Hirofuchi
  10  */
  11 
  12 #include <sys/types.h>
  13 #include <sys/stat.h>
  14 #include <fcntl.h>
  15 
  16 #include <errno.h>
  17 #include <unistd.h>
  18 
  19 #include <libudev.h>
  20 
  21 #include "usbip_common.h"
  22 #include "usbip_host_common.h"
  23 #include "list.h"
  24 #include "sysfs_utils.h"
  25 
  26 struct udev *udev_context;
  27 
  28 static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
  29 {
  30         char status_attr_path[SYSFS_PATH_MAX];
  31         int size;
  32         int fd;
  33         int length;
  34         char status[2] = { 0 };
  35         int value = 0;
  36 
  37         size = snprintf(status_attr_path, sizeof(status_attr_path),
  38                         "%s/usbip_status", udev->path);
  39         if (size < 0 || (unsigned int)size >= sizeof(status_attr_path)) {
  40                 err("usbip_status path length %i >= %lu or < 0", size,
  41                     (long unsigned)sizeof(status_attr_path));
  42                 return -1;
  43         }
  44 
  45 
  46         fd = open(status_attr_path, O_RDONLY);
  47         if (fd < 0) {
  48                 err("error opening attribute %s", status_attr_path);
  49                 return -1;
  50         }
  51 
  52         length = read(fd, status, 1);
  53         if (length < 0) {
  54                 err("error reading attribute %s", status_attr_path);
  55                 close(fd);
  56                 return -1;
  57         }
  58 
  59         value = atoi(status);
  60         close(fd);
  61         return value;
  62 }
  63 
  64 static
  65 struct usbip_exported_device *usbip_exported_device_new(
  66                 struct usbip_host_driver *hdriver, const char *sdevpath)
  67 {
  68         struct usbip_exported_device *edev = NULL;
  69         struct usbip_exported_device *edev_old;
  70         size_t size;
  71         int i;
  72 
  73         edev = calloc(1, sizeof(struct usbip_exported_device));
  74 
  75         edev->sudev =
  76                 udev_device_new_from_syspath(udev_context, sdevpath);
  77         if (!edev->sudev) {
  78                 err("udev_device_new_from_syspath: %s", sdevpath);
  79                 goto err;
  80         }
  81 
  82         if (hdriver->ops.read_device(edev->sudev, &edev->udev) < 0)
  83                 goto err;
  84 
  85         edev->status = read_attr_usbip_status(&edev->udev);
  86         if (edev->status < 0)
  87                 goto err;
  88 
  89         /* reallocate buffer to include usb interface data */
  90         size = sizeof(struct usbip_exported_device) +
  91                 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
  92 
  93         edev_old = edev;
  94         edev = realloc(edev, size);
  95         if (!edev) {
  96                 edev = edev_old;
  97                 dbg("realloc failed");
  98                 goto err;
  99         }
 100 
 101         for (i = 0; i < edev->udev.bNumInterfaces; i++) {
 102                 /* vudc does not support reading interfaces */
 103                 if (!hdriver->ops.read_interface)
 104                         break;
 105                 hdriver->ops.read_interface(&edev->udev, i, &edev->uinf[i]);
 106         }
 107 
 108         return edev;
 109 err:
 110         if (edev->sudev)
 111                 udev_device_unref(edev->sudev);
 112         if (edev)
 113                 free(edev);
 114 
 115         return NULL;
 116 }
 117 
 118 static int refresh_exported_devices(struct usbip_host_driver *hdriver)
 119 {
 120         struct usbip_exported_device *edev;
 121         struct udev_enumerate *enumerate;
 122         struct udev_list_entry *devices, *dev_list_entry;
 123         struct udev_device *dev;
 124         const char *path;
 125 
 126         enumerate = udev_enumerate_new(udev_context);
 127         udev_enumerate_add_match_subsystem(enumerate, hdriver->udev_subsystem);
 128         udev_enumerate_scan_devices(enumerate);
 129 
 130         devices = udev_enumerate_get_list_entry(enumerate);
 131 
 132         udev_list_entry_foreach(dev_list_entry, devices) {
 133                 path = udev_list_entry_get_name(dev_list_entry);
 134                 dev = udev_device_new_from_syspath(udev_context,
 135                                                    path);
 136                 if (dev == NULL)
 137                         continue;
 138 
 139                 /* Check whether device uses usbip driver. */
 140                 if (hdriver->ops.is_my_device(dev)) {
 141                         edev = usbip_exported_device_new(hdriver, path);
 142                         if (!edev) {
 143                                 dbg("usbip_exported_device_new failed");
 144                                 continue;
 145                         }
 146 
 147                         list_add(&edev->node, &hdriver->edev_list);
 148                         hdriver->ndevs++;
 149                 }
 150         }
 151 
 152         return 0;
 153 }
 154 
 155 static void usbip_exported_device_destroy(struct list_head *devs)
 156 {
 157         struct list_head *i, *tmp;
 158         struct usbip_exported_device *edev;
 159 
 160         list_for_each_safe(i, tmp, devs) {
 161                 edev = list_entry(i, struct usbip_exported_device, node);
 162                 list_del(i);
 163                 free(edev);
 164         }
 165 }
 166 
 167 int usbip_generic_driver_open(struct usbip_host_driver *hdriver)
 168 {
 169         int rc;
 170 
 171         udev_context = udev_new();
 172         if (!udev_context) {
 173                 err("udev_new failed");
 174                 return -1;
 175         }
 176 
 177         rc = refresh_exported_devices(hdriver);
 178         if (rc < 0)
 179                 goto err;
 180         return 0;
 181 err:
 182         udev_unref(udev_context);
 183         return -1;
 184 }
 185 
 186 void usbip_generic_driver_close(struct usbip_host_driver *hdriver)
 187 {
 188         if (!hdriver)
 189                 return;
 190 
 191         usbip_exported_device_destroy(&hdriver->edev_list);
 192 
 193         udev_unref(udev_context);
 194 }
 195 
 196 int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver)
 197 {
 198         int rc;
 199 
 200         usbip_exported_device_destroy(&hdriver->edev_list);
 201 
 202         hdriver->ndevs = 0;
 203         INIT_LIST_HEAD(&hdriver->edev_list);
 204 
 205         rc = refresh_exported_devices(hdriver);
 206         if (rc < 0)
 207                 return -1;
 208 
 209         return 0;
 210 }
 211 
 212 int usbip_export_device(struct usbip_exported_device *edev, int sockfd)
 213 {
 214         char attr_name[] = "usbip_sockfd";
 215         char sockfd_attr_path[SYSFS_PATH_MAX];
 216         int size;
 217         char sockfd_buff[30];
 218         int ret;
 219 
 220         if (edev->status != SDEV_ST_AVAILABLE) {
 221                 dbg("device not available: %s", edev->udev.busid);
 222                 switch (edev->status) {
 223                 case SDEV_ST_ERROR:
 224                         dbg("status SDEV_ST_ERROR");
 225                         ret = ST_DEV_ERR;
 226                         break;
 227                 case SDEV_ST_USED:
 228                         dbg("status SDEV_ST_USED");
 229                         ret = ST_DEV_BUSY;
 230                         break;
 231                 default:
 232                         dbg("status unknown: 0x%x", edev->status);
 233                         ret = -1;
 234                 }
 235                 return ret;
 236         }
 237 
 238         /* only the first interface is true */
 239         size = snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
 240                         edev->udev.path, attr_name);
 241         if (size < 0 || (unsigned int)size >= sizeof(sockfd_attr_path)) {
 242                 err("exported device path length %i >= %lu or < 0", size,
 243                     (long unsigned)sizeof(sockfd_attr_path));
 244                 return -1;
 245         }
 246 
 247         size = snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
 248         if (size < 0 || (unsigned int)size >= sizeof(sockfd_buff)) {
 249                 err("socket length %i >= %lu or < 0", size,
 250                     (long unsigned)sizeof(sockfd_buff));
 251                 return -1;
 252         }
 253 
 254         ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
 255                                     strlen(sockfd_buff));
 256         if (ret < 0) {
 257                 err("write_sysfs_attribute failed: sockfd %s to %s",
 258                     sockfd_buff, sockfd_attr_path);
 259                 return ret;
 260         }
 261 
 262         info("connect: %s", edev->udev.busid);
 263 
 264         return ret;
 265 }
 266 
 267 struct usbip_exported_device *usbip_generic_get_device(
 268                 struct usbip_host_driver *hdriver, int num)
 269 {
 270         struct list_head *i;
 271         struct usbip_exported_device *edev;
 272         int cnt = 0;
 273 
 274         list_for_each(i, &hdriver->edev_list) {
 275                 edev = list_entry(i, struct usbip_exported_device, node);
 276                 if (num == cnt)
 277                         return edev;
 278                 cnt++;
 279         }
 280 
 281         return NULL;
 282 }

/* [<][>][^][v][top][bottom][index][help] */