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/sysfs.h> 18 #include <linux/usb.h> 19 #include "usb.h" 20 21 struct ep_device { 22 struct usb_endpoint_descriptor *desc; 23 struct usb_device *udev; 24 struct device dev; 25 }; 26 #define to_ep_device(_dev) \ 27 container_of(_dev, struct ep_device, dev) 28 29 #define usb_ep_attr(field, format_string) \ 30 static ssize_t field##_show(struct device *dev, \ 31 struct device_attribute *attr, \ 32 char *buf) \ 33 { \ 34 struct ep_device *ep = to_ep_device(dev); \ 35 return sysfs_emit(buf, format_string, ep->desc->field); \ 36 } \ 37 static DEVICE_ATTR_RO(field) 38 39 usb_ep_attr(bLength, "%02x\n"); 40 usb_ep_attr(bEndpointAddress, "%02x\n"); 41 usb_ep_attr(bmAttributes, "%02x\n"); 42 usb_ep_attr(bInterval, "%02x\n"); 43 44 static ssize_t wMaxPacketSize_show(struct device *dev, 45 struct device_attribute *attr, char *buf) 46 { 47 struct ep_device *ep = to_ep_device(dev); 48 return sysfs_emit(buf, "%04x\n", usb_endpoint_maxp(ep->desc)); 49 } 50 static DEVICE_ATTR_RO(wMaxPacketSize); 51 52 static ssize_t type_show(struct device *dev, struct device_attribute *attr, 53 char *buf) 54 { 55 struct ep_device *ep = to_ep_device(dev); 56 char *type = "unknown"; 57 58 switch (usb_endpoint_type(ep->desc)) { 59 case USB_ENDPOINT_XFER_CONTROL: 60 type = "Control"; 61 break; 62 case USB_ENDPOINT_XFER_ISOC: 63 type = "Isoc"; 64 break; 65 case USB_ENDPOINT_XFER_BULK: 66 type = "Bulk"; 67 break; 68 case USB_ENDPOINT_XFER_INT: 69 type = "Interrupt"; 70 break; 71 } 72 return sysfs_emit(buf, "%s\n", type); 73 } 74 static DEVICE_ATTR_RO(type); 75 76 static ssize_t interval_show(struct device *dev, struct device_attribute *attr, 77 char *buf) 78 { 79 struct ep_device *ep = to_ep_device(dev); 80 unsigned int interval; 81 char unit; 82 83 interval = usb_decode_interval(ep->desc, ep->udev->speed); 84 if (interval % 1000) { 85 unit = 'u'; 86 } else { 87 unit = 'm'; 88 interval /= 1000; 89 } 90 91 return sysfs_emit(buf, "%d%cs\n", interval, unit); 92 } 93 static DEVICE_ATTR_RO(interval); 94 95 static ssize_t direction_show(struct device *dev, struct device_attribute *attr, 96 char *buf) 97 { 98 struct ep_device *ep = to_ep_device(dev); 99 char *direction; 100 101 if (usb_endpoint_xfer_control(ep->desc)) 102 direction = "both"; 103 else if (usb_endpoint_dir_in(ep->desc)) 104 direction = "in"; 105 else 106 direction = "out"; 107 return sysfs_emit(buf, "%s\n", direction); 108 } 109 static DEVICE_ATTR_RO(direction); 110 111 static struct attribute *ep_dev_attrs[] = { 112 &dev_attr_bLength.attr, 113 &dev_attr_bEndpointAddress.attr, 114 &dev_attr_bmAttributes.attr, 115 &dev_attr_bInterval.attr, 116 &dev_attr_wMaxPacketSize.attr, 117 &dev_attr_interval.attr, 118 &dev_attr_type.attr, 119 &dev_attr_direction.attr, 120 NULL, 121 }; 122 static const struct attribute_group ep_dev_attr_grp = { 123 .attrs = ep_dev_attrs, 124 }; 125 static const struct attribute_group *ep_dev_groups[] = { 126 &ep_dev_attr_grp, 127 NULL 128 }; 129 130 static void ep_device_release(struct device *dev) 131 { 132 struct ep_device *ep_dev = to_ep_device(dev); 133 134 kfree(ep_dev); 135 } 136 137 const struct device_type usb_ep_device_type = { 138 .name = "usb_endpoint", 139 .release = ep_device_release, 140 }; 141 142 int usb_create_ep_devs(struct device *parent, 143 struct usb_host_endpoint *endpoint, 144 struct usb_device *udev) 145 { 146 struct ep_device *ep_dev; 147 int retval; 148 149 ep_dev = kzalloc_obj(*ep_dev); 150 if (!ep_dev) { 151 retval = -ENOMEM; 152 goto exit; 153 } 154 155 ep_dev->desc = &endpoint->desc; 156 ep_dev->udev = udev; 157 ep_dev->dev.groups = ep_dev_groups; 158 ep_dev->dev.type = &usb_ep_device_type; 159 ep_dev->dev.parent = parent; 160 dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress); 161 162 retval = device_register(&ep_dev->dev); 163 if (retval) 164 goto error_register; 165 166 device_enable_async_suspend(&ep_dev->dev); 167 endpoint->ep_dev = ep_dev; 168 return retval; 169 170 error_register: 171 put_device(&ep_dev->dev); 172 exit: 173 return retval; 174 } 175 176 void usb_remove_ep_devs(struct usb_host_endpoint *endpoint) 177 { 178 struct ep_device *ep_dev = endpoint->ep_dev; 179 180 if (ep_dev) { 181 device_unregister(&ep_dev->dev); 182 endpoint->ep_dev = NULL; 183 } 184 } 185