root/drivers/usb/core/endpoint.c

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

DEFINITIONS

This source file includes following definitions.
  1. wMaxPacketSize_show
  2. type_show
  3. interval_show
  4. direction_show
  5. ep_device_release
  6. usb_create_ep_devs
  7. usb_remove_ep_devs

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * drivers/usb/core/endpoint.c
   4  *
   5  * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman
   6  * (C) Copyright 2002,2004 IBM Corp.
   7  * (C) Copyright 2006 Novell Inc.
   8  *
   9  * Released under the GPLv2 only.
  10  *
  11  * Endpoint sysfs stuff
  12  */
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/spinlock.h>
  16 #include <linux/slab.h>
  17 #include <linux/usb.h>
  18 #include "usb.h"
  19 
  20 struct ep_device {
  21         struct usb_endpoint_descriptor *desc;
  22         struct usb_device *udev;
  23         struct device dev;
  24 };
  25 #define to_ep_device(_dev) \
  26         container_of(_dev, struct ep_device, dev)
  27 
  28 struct ep_attribute {
  29         struct attribute attr;
  30         ssize_t (*show)(struct usb_device *,
  31                         struct usb_endpoint_descriptor *, char *);
  32 };
  33 #define to_ep_attribute(_attr) \
  34         container_of(_attr, struct ep_attribute, attr)
  35 
  36 #define usb_ep_attr(field, format_string)                       \
  37 static ssize_t field##_show(struct device *dev,                 \
  38                                struct device_attribute *attr,   \
  39                                char *buf)                       \
  40 {                                                               \
  41         struct ep_device *ep = to_ep_device(dev);               \
  42         return sprintf(buf, format_string, ep->desc->field);    \
  43 }                                                               \
  44 static DEVICE_ATTR_RO(field)
  45 
  46 usb_ep_attr(bLength, "%02x\n");
  47 usb_ep_attr(bEndpointAddress, "%02x\n");
  48 usb_ep_attr(bmAttributes, "%02x\n");
  49 usb_ep_attr(bInterval, "%02x\n");
  50 
  51 static ssize_t wMaxPacketSize_show(struct device *dev,
  52                                    struct device_attribute *attr, char *buf)
  53 {
  54         struct ep_device *ep = to_ep_device(dev);
  55         return sprintf(buf, "%04x\n", usb_endpoint_maxp(ep->desc));
  56 }
  57 static DEVICE_ATTR_RO(wMaxPacketSize);
  58 
  59 static ssize_t type_show(struct device *dev, struct device_attribute *attr,
  60                          char *buf)
  61 {
  62         struct ep_device *ep = to_ep_device(dev);
  63         char *type = "unknown";
  64 
  65         switch (usb_endpoint_type(ep->desc)) {
  66         case USB_ENDPOINT_XFER_CONTROL:
  67                 type = "Control";
  68                 break;
  69         case USB_ENDPOINT_XFER_ISOC:
  70                 type = "Isoc";
  71                 break;
  72         case USB_ENDPOINT_XFER_BULK:
  73                 type = "Bulk";
  74                 break;
  75         case USB_ENDPOINT_XFER_INT:
  76                 type = "Interrupt";
  77                 break;
  78         }
  79         return sprintf(buf, "%s\n", type);
  80 }
  81 static DEVICE_ATTR_RO(type);
  82 
  83 static ssize_t interval_show(struct device *dev, struct device_attribute *attr,
  84                              char *buf)
  85 {
  86         struct ep_device *ep = to_ep_device(dev);
  87         char unit;
  88         unsigned interval = 0;
  89         unsigned in;
  90 
  91         in = (ep->desc->bEndpointAddress & USB_DIR_IN);
  92 
  93         switch (usb_endpoint_type(ep->desc)) {
  94         case USB_ENDPOINT_XFER_CONTROL:
  95                 if (ep->udev->speed == USB_SPEED_HIGH)
  96                         /* uframes per NAK */
  97                         interval = ep->desc->bInterval;
  98                 break;
  99 
 100         case USB_ENDPOINT_XFER_ISOC:
 101                 interval = 1 << (ep->desc->bInterval - 1);
 102                 break;
 103 
 104         case USB_ENDPOINT_XFER_BULK:
 105                 if (ep->udev->speed == USB_SPEED_HIGH && !in)
 106                         /* uframes per NAK */
 107                         interval = ep->desc->bInterval;
 108                 break;
 109 
 110         case USB_ENDPOINT_XFER_INT:
 111                 if (ep->udev->speed == USB_SPEED_HIGH)
 112                         interval = 1 << (ep->desc->bInterval - 1);
 113                 else
 114                         interval = ep->desc->bInterval;
 115                 break;
 116         }
 117         interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
 118         if (interval % 1000)
 119                 unit = 'u';
 120         else {
 121                 unit = 'm';
 122                 interval /= 1000;
 123         }
 124 
 125         return sprintf(buf, "%d%cs\n", interval, unit);
 126 }
 127 static DEVICE_ATTR_RO(interval);
 128 
 129 static ssize_t direction_show(struct device *dev, struct device_attribute *attr,
 130                               char *buf)
 131 {
 132         struct ep_device *ep = to_ep_device(dev);
 133         char *direction;
 134 
 135         if (usb_endpoint_xfer_control(ep->desc))
 136                 direction = "both";
 137         else if (usb_endpoint_dir_in(ep->desc))
 138                 direction = "in";
 139         else
 140                 direction = "out";
 141         return sprintf(buf, "%s\n", direction);
 142 }
 143 static DEVICE_ATTR_RO(direction);
 144 
 145 static struct attribute *ep_dev_attrs[] = {
 146         &dev_attr_bLength.attr,
 147         &dev_attr_bEndpointAddress.attr,
 148         &dev_attr_bmAttributes.attr,
 149         &dev_attr_bInterval.attr,
 150         &dev_attr_wMaxPacketSize.attr,
 151         &dev_attr_interval.attr,
 152         &dev_attr_type.attr,
 153         &dev_attr_direction.attr,
 154         NULL,
 155 };
 156 static struct attribute_group ep_dev_attr_grp = {
 157         .attrs = ep_dev_attrs,
 158 };
 159 static const struct attribute_group *ep_dev_groups[] = {
 160         &ep_dev_attr_grp,
 161         NULL
 162 };
 163 
 164 static void ep_device_release(struct device *dev)
 165 {
 166         struct ep_device *ep_dev = to_ep_device(dev);
 167 
 168         kfree(ep_dev);
 169 }
 170 
 171 struct device_type usb_ep_device_type = {
 172         .name =         "usb_endpoint",
 173         .release = ep_device_release,
 174 };
 175 
 176 int usb_create_ep_devs(struct device *parent,
 177                         struct usb_host_endpoint *endpoint,
 178                         struct usb_device *udev)
 179 {
 180         struct ep_device *ep_dev;
 181         int retval;
 182 
 183         ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
 184         if (!ep_dev) {
 185                 retval = -ENOMEM;
 186                 goto exit;
 187         }
 188 
 189         ep_dev->desc = &endpoint->desc;
 190         ep_dev->udev = udev;
 191         ep_dev->dev.groups = ep_dev_groups;
 192         ep_dev->dev.type = &usb_ep_device_type;
 193         ep_dev->dev.parent = parent;
 194         dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
 195 
 196         retval = device_register(&ep_dev->dev);
 197         if (retval)
 198                 goto error_register;
 199 
 200         device_enable_async_suspend(&ep_dev->dev);
 201         endpoint->ep_dev = ep_dev;
 202         return retval;
 203 
 204 error_register:
 205         put_device(&ep_dev->dev);
 206 exit:
 207         return retval;
 208 }
 209 
 210 void usb_remove_ep_devs(struct usb_host_endpoint *endpoint)
 211 {
 212         struct ep_device *ep_dev = endpoint->ep_dev;
 213 
 214         if (ep_dev) {
 215                 device_unregister(&ep_dev->dev);
 216                 endpoint->ep_dev = NULL;
 217         }
 218 }

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