root/drivers/usb/usbip/vudc_sysfs.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_gadget_descs
  2. dev_desc_read
  3. usbip_sockfd_store
  4. usbip_status_show

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
   4  * Copyright (C) 2015-2016 Samsung Electronics
   5  *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
   6  *               Krzysztof Opasiak <k.opasiak@samsung.com>
   7  */
   8 
   9 #include <linux/device.h>
  10 #include <linux/list.h>
  11 #include <linux/usb/gadget.h>
  12 #include <linux/usb/ch9.h>
  13 #include <linux/sysfs.h>
  14 #include <linux/kthread.h>
  15 #include <linux/byteorder/generic.h>
  16 
  17 #include "usbip_common.h"
  18 #include "vudc.h"
  19 
  20 #include <net/sock.h>
  21 
  22 /* called with udc->lock held */
  23 int get_gadget_descs(struct vudc *udc)
  24 {
  25         struct vrequest *usb_req;
  26         struct vep *ep0 = to_vep(udc->gadget.ep0);
  27         struct usb_device_descriptor *ddesc = &udc->dev_desc;
  28         struct usb_ctrlrequest req;
  29         int ret;
  30 
  31         if (!udc->driver || !udc->pullup)
  32                 return -EINVAL;
  33 
  34         req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
  35         req.bRequest = USB_REQ_GET_DESCRIPTOR;
  36         req.wValue = cpu_to_le16(USB_DT_DEVICE << 8);
  37         req.wIndex = cpu_to_le16(0);
  38         req.wLength = cpu_to_le16(sizeof(*ddesc));
  39 
  40         spin_unlock(&udc->lock);
  41         ret = udc->driver->setup(&(udc->gadget), &req);
  42         spin_lock(&udc->lock);
  43         if (ret < 0)
  44                 goto out;
  45 
  46         /* assuming request queue is empty; request is now on top */
  47         usb_req = list_last_entry(&ep0->req_queue, struct vrequest, req_entry);
  48         list_del(&usb_req->req_entry);
  49 
  50         if (usb_req->req.length > sizeof(*ddesc)) {
  51                 ret = -EOVERFLOW;
  52                 goto giveback_req;
  53         }
  54 
  55         memcpy(ddesc, usb_req->req.buf, sizeof(*ddesc));
  56         udc->desc_cached = 1;
  57         ret = 0;
  58 giveback_req:
  59         usb_req->req.status = 0;
  60         usb_req->req.actual = usb_req->req.length;
  61         usb_gadget_giveback_request(&(ep0->ep), &(usb_req->req));
  62 out:
  63         return ret;
  64 }
  65 
  66 /*
  67  * Exposes device descriptor from the gadget driver.
  68  */
  69 static ssize_t dev_desc_read(struct file *file, struct kobject *kobj,
  70                              struct bin_attribute *attr, char *out,
  71                              loff_t off, size_t count)
  72 {
  73         struct device *dev = kobj_to_dev(kobj);
  74         struct vudc *udc = (struct vudc *)dev_get_drvdata(dev);
  75         char *desc_ptr = (char *) &udc->dev_desc;
  76         unsigned long flags;
  77         int ret;
  78 
  79         spin_lock_irqsave(&udc->lock, flags);
  80         if (!udc->desc_cached) {
  81                 ret = -ENODEV;
  82                 goto unlock;
  83         }
  84 
  85         memcpy(out, desc_ptr + off, count);
  86         ret = count;
  87 unlock:
  88         spin_unlock_irqrestore(&udc->lock, flags);
  89         return ret;
  90 }
  91 static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor));
  92 
  93 static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr,
  94                      const char *in, size_t count)
  95 {
  96         struct vudc *udc = (struct vudc *) dev_get_drvdata(dev);
  97         int rv;
  98         int sockfd = 0;
  99         int err;
 100         struct socket *socket;
 101         unsigned long flags;
 102         int ret;
 103 
 104         rv = kstrtoint(in, 0, &sockfd);
 105         if (rv != 0)
 106                 return -EINVAL;
 107 
 108         if (!udc) {
 109                 dev_err(dev, "no device");
 110                 return -ENODEV;
 111         }
 112         spin_lock_irqsave(&udc->lock, flags);
 113         /* Don't export what we don't have */
 114         if (!udc->driver || !udc->pullup) {
 115                 dev_err(dev, "gadget not bound");
 116                 ret = -ENODEV;
 117                 goto unlock;
 118         }
 119 
 120         if (sockfd != -1) {
 121                 if (udc->connected) {
 122                         dev_err(dev, "Device already connected");
 123                         ret = -EBUSY;
 124                         goto unlock;
 125                 }
 126 
 127                 spin_lock_irq(&udc->ud.lock);
 128 
 129                 if (udc->ud.status != SDEV_ST_AVAILABLE) {
 130                         ret = -EINVAL;
 131                         goto unlock_ud;
 132                 }
 133 
 134                 socket = sockfd_lookup(sockfd, &err);
 135                 if (!socket) {
 136                         dev_err(dev, "failed to lookup sock");
 137                         ret = -EINVAL;
 138                         goto unlock_ud;
 139                 }
 140 
 141                 udc->ud.tcp_socket = socket;
 142 
 143                 spin_unlock_irq(&udc->ud.lock);
 144                 spin_unlock_irqrestore(&udc->lock, flags);
 145 
 146                 udc->ud.tcp_rx = kthread_get_run(&v_rx_loop,
 147                                                     &udc->ud, "vudc_rx");
 148                 udc->ud.tcp_tx = kthread_get_run(&v_tx_loop,
 149                                                     &udc->ud, "vudc_tx");
 150 
 151                 spin_lock_irqsave(&udc->lock, flags);
 152                 spin_lock_irq(&udc->ud.lock);
 153                 udc->ud.status = SDEV_ST_USED;
 154                 spin_unlock_irq(&udc->ud.lock);
 155 
 156                 ktime_get_ts64(&udc->start_time);
 157                 v_start_timer(udc);
 158                 udc->connected = 1;
 159         } else {
 160                 if (!udc->connected) {
 161                         dev_err(dev, "Device not connected");
 162                         ret = -EINVAL;
 163                         goto unlock;
 164                 }
 165 
 166                 spin_lock_irq(&udc->ud.lock);
 167                 if (udc->ud.status != SDEV_ST_USED) {
 168                         ret = -EINVAL;
 169                         goto unlock_ud;
 170                 }
 171                 spin_unlock_irq(&udc->ud.lock);
 172 
 173                 usbip_event_add(&udc->ud, VUDC_EVENT_DOWN);
 174         }
 175 
 176         spin_unlock_irqrestore(&udc->lock, flags);
 177 
 178         return count;
 179 
 180 unlock_ud:
 181         spin_unlock_irq(&udc->ud.lock);
 182 unlock:
 183         spin_unlock_irqrestore(&udc->lock, flags);
 184 
 185         return ret;
 186 }
 187 static DEVICE_ATTR_WO(usbip_sockfd);
 188 
 189 static ssize_t usbip_status_show(struct device *dev,
 190                                struct device_attribute *attr, char *out)
 191 {
 192         struct vudc *udc = (struct vudc *) dev_get_drvdata(dev);
 193         int status;
 194 
 195         if (!udc) {
 196                 dev_err(dev, "no device");
 197                 return -ENODEV;
 198         }
 199         spin_lock_irq(&udc->ud.lock);
 200         status = udc->ud.status;
 201         spin_unlock_irq(&udc->ud.lock);
 202 
 203         return snprintf(out, PAGE_SIZE, "%d\n", status);
 204 }
 205 static DEVICE_ATTR_RO(usbip_status);
 206 
 207 static struct attribute *dev_attrs[] = {
 208         &dev_attr_usbip_sockfd.attr,
 209         &dev_attr_usbip_status.attr,
 210         NULL,
 211 };
 212 
 213 static struct bin_attribute *dev_bin_attrs[] = {
 214         &bin_attr_dev_desc,
 215         NULL,
 216 };
 217 
 218 static const struct attribute_group vudc_attr_group = {
 219         .attrs = dev_attrs,
 220         .bin_attrs = dev_bin_attrs,
 221 };
 222 
 223 const struct attribute_group *vudc_groups[] = {
 224         &vudc_attr_group,
 225         NULL,
 226 };

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