Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48767a4e authored by Tatyana Brokhman's avatar Tatyana Brokhman Committed by Greg Kroah-Hartman
Browse files

usb: gadget: configure endpoint according to gadget speed



Add config_ep_by_speed() to configure the endpoint
according to the gadget speed.

Using this function will spare the FDs from handling
the endpoint chosen descriptor.

Signed-off-by: default avatarTatyana Brokhman <tlinder@codeaurora.org>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 72c973dd
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
@@ -74,6 +74,91 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
static char composite_manufacturer[50];

/*-------------------------------------------------------------------------*/
/**
 * next_ep_desc() - advance to the next EP descriptor
 * @t: currect pointer within descriptor array
 *
 * Return: next EP descriptor or NULL
 *
 * Iterate over @t until either EP descriptor found or
 * NULL (that indicates end of list) encountered
 */
static struct usb_descriptor_header**
next_ep_desc(struct usb_descriptor_header **t)
{
	for (; *t; t++) {
		if ((*t)->bDescriptorType == USB_DT_ENDPOINT)
			return t;
	}
	return NULL;
}

/*
 * for_each_ep_desc()- iterate over endpoint descriptors in the
 *		descriptors list
 * @start:	pointer within descriptor array.
 * @ep_desc:	endpoint descriptor to use as the loop cursor
 */
#define for_each_ep_desc(start, ep_desc) \
	for (ep_desc = next_ep_desc(start); \
	      ep_desc; ep_desc = next_ep_desc(ep_desc+1))

/**
 * config_ep_by_speed() - configures the given endpoint
 * according to gadget speed.
 * @g: pointer to the gadget
 * @f: usb function
 * @_ep: the endpoint to configure
 *
 * Return: error code, 0 on success
 *
 * This function chooses the right descriptors for a given
 * endpoint according to gadget speed and saves it in the
 * endpoint desc field. If the endpoint already has a descriptor
 * assigned to it - overwrites it with currently corresponding
 * descriptor. The endpoint maxpacket field is updated according
 * to the chosen descriptor.
 * Note: the supplied function should hold all the descriptors
 * for supported speeds
 */
int config_ep_by_speed(struct usb_gadget *g,
			struct usb_function *f,
			struct usb_ep *_ep)
{
	struct usb_endpoint_descriptor *chosen_desc = NULL;
	struct usb_descriptor_header **speed_desc = NULL;

	struct usb_descriptor_header **d_spd; /* cursor for speed desc */

	if (!g || !f || !_ep)
		return -EIO;

	/* select desired speed */
	switch (g->speed) {
	case USB_SPEED_HIGH:
		if (gadget_is_dualspeed(g)) {
			speed_desc = f->hs_descriptors;
			break;
		}
		/* else: fall through */
	default:
		speed_desc = f->descriptors;
	}
	/* find descriptors */
	for_each_ep_desc(speed_desc, d_spd) {
		chosen_desc = (struct usb_endpoint_descriptor *)*d_spd;
		if (chosen_desc->bEndpointAddress == _ep->address)
			goto ep_found;
	}
	return -EIO;

ep_found:
	/* commit results */
	_ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize);
	_ep->desc = chosen_desc;

	return 0;
}

/**
 * usb_add_function() - add a function to a configuration
+1 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ ep_matches (
			size = 64;
		desc->wMaxPacketSize = cpu_to_le16(size);
	}
	ep->address = desc->bEndpointAddress;
	return 1;
}

+3 −0
Original line number Diff line number Diff line
@@ -145,6 +145,9 @@ int usb_function_activate(struct usb_function *);

int usb_interface_id(struct usb_configuration *, struct usb_function *);

int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
			struct usb_ep *_ep);

/**
 * ep_choose - select descriptor endpoint at current device speed
 * @g: gadget, connected and running at some speed
+3 −0
Original line number Diff line number Diff line
@@ -133,6 +133,8 @@ struct usb_ep_ops {
 *	value can sometimes be reduced (hardware allowing), according to
 *      the endpoint descriptor used to configure the endpoint.
 * @driver_data:for use by the gadget driver.
 * @address: used to identify the endpoint when finding descriptor that
 *	matches connection speed
 * @desc: endpoint descriptor.  This pointer is set before the endpoint is
 *	enabled and remains valid until the endpoint is disabled.
 *
@@ -147,6 +149,7 @@ struct usb_ep {
	const struct usb_ep_ops	*ops;
	struct list_head	ep_list;
	unsigned		maxpacket:16;
	u8			address;
	const struct usb_endpoint_descriptor	*desc;
};