cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

endpoint.c (4397B)


      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
     20struct 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
     28struct 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)			\
     37static 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}								\
     44static DEVICE_ATTR_RO(field)
     45
     46usb_ep_attr(bLength, "%02x\n");
     47usb_ep_attr(bEndpointAddress, "%02x\n");
     48usb_ep_attr(bmAttributes, "%02x\n");
     49usb_ep_attr(bInterval, "%02x\n");
     50
     51static 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}
     57static DEVICE_ATTR_RO(wMaxPacketSize);
     58
     59static 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}
     81static DEVICE_ATTR_RO(type);
     82
     83static 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	unsigned int interval;
     88	char unit;
     89
     90	interval = usb_decode_interval(ep->desc, ep->udev->speed);
     91	if (interval % 1000) {
     92		unit = 'u';
     93	} else {
     94		unit = 'm';
     95		interval /= 1000;
     96	}
     97
     98	return sprintf(buf, "%d%cs\n", interval, unit);
     99}
    100static DEVICE_ATTR_RO(interval);
    101
    102static ssize_t direction_show(struct device *dev, struct device_attribute *attr,
    103			      char *buf)
    104{
    105	struct ep_device *ep = to_ep_device(dev);
    106	char *direction;
    107
    108	if (usb_endpoint_xfer_control(ep->desc))
    109		direction = "both";
    110	else if (usb_endpoint_dir_in(ep->desc))
    111		direction = "in";
    112	else
    113		direction = "out";
    114	return sprintf(buf, "%s\n", direction);
    115}
    116static DEVICE_ATTR_RO(direction);
    117
    118static struct attribute *ep_dev_attrs[] = {
    119	&dev_attr_bLength.attr,
    120	&dev_attr_bEndpointAddress.attr,
    121	&dev_attr_bmAttributes.attr,
    122	&dev_attr_bInterval.attr,
    123	&dev_attr_wMaxPacketSize.attr,
    124	&dev_attr_interval.attr,
    125	&dev_attr_type.attr,
    126	&dev_attr_direction.attr,
    127	NULL,
    128};
    129static const struct attribute_group ep_dev_attr_grp = {
    130	.attrs = ep_dev_attrs,
    131};
    132static const struct attribute_group *ep_dev_groups[] = {
    133	&ep_dev_attr_grp,
    134	NULL
    135};
    136
    137static void ep_device_release(struct device *dev)
    138{
    139	struct ep_device *ep_dev = to_ep_device(dev);
    140
    141	kfree(ep_dev);
    142}
    143
    144struct device_type usb_ep_device_type = {
    145	.name =		"usb_endpoint",
    146	.release = ep_device_release,
    147};
    148
    149int usb_create_ep_devs(struct device *parent,
    150			struct usb_host_endpoint *endpoint,
    151			struct usb_device *udev)
    152{
    153	struct ep_device *ep_dev;
    154	int retval;
    155
    156	ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
    157	if (!ep_dev) {
    158		retval = -ENOMEM;
    159		goto exit;
    160	}
    161
    162	ep_dev->desc = &endpoint->desc;
    163	ep_dev->udev = udev;
    164	ep_dev->dev.groups = ep_dev_groups;
    165	ep_dev->dev.type = &usb_ep_device_type;
    166	ep_dev->dev.parent = parent;
    167	dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
    168
    169	retval = device_register(&ep_dev->dev);
    170	if (retval)
    171		goto error_register;
    172
    173	device_enable_async_suspend(&ep_dev->dev);
    174	endpoint->ep_dev = ep_dev;
    175	return retval;
    176
    177error_register:
    178	put_device(&ep_dev->dev);
    179exit:
    180	return retval;
    181}
    182
    183void usb_remove_ep_devs(struct usb_host_endpoint *endpoint)
    184{
    185	struct ep_device *ep_dev = endpoint->ep_dev;
    186
    187	if (ep_dev) {
    188		device_unregister(&ep_dev->dev);
    189		endpoint->ep_dev = NULL;
    190	}
    191}