|
@@ -63,13 +63,16 @@ static int
|
|
ep_matches (
|
|
ep_matches (
|
|
struct usb_gadget *gadget,
|
|
struct usb_gadget *gadget,
|
|
struct usb_ep *ep,
|
|
struct usb_ep *ep,
|
|
- struct usb_endpoint_descriptor *desc
|
|
|
|
|
|
+ struct usb_endpoint_descriptor *desc,
|
|
|
|
+ struct usb_ss_ep_comp_descriptor *ep_comp
|
|
)
|
|
)
|
|
{
|
|
{
|
|
u8 type;
|
|
u8 type;
|
|
const char *tmp;
|
|
const char *tmp;
|
|
u16 max;
|
|
u16 max;
|
|
|
|
|
|
|
|
+ int num_req_streams = 0;
|
|
|
|
+
|
|
/* endpoint already claimed? */
|
|
/* endpoint already claimed? */
|
|
if (NULL != ep->driver_data)
|
|
if (NULL != ep->driver_data)
|
|
return 0;
|
|
return 0;
|
|
@@ -128,6 +131,22 @@ ep_matches (
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Get the number of required streams from the EP companion
|
|
|
|
+ * descriptor and see if the EP matches it
|
|
|
|
+ */
|
|
|
|
+ if (usb_endpoint_xfer_bulk(desc)) {
|
|
|
|
+ if (ep_comp) {
|
|
|
|
+ num_req_streams = ep_comp->bmAttributes & 0x1f;
|
|
|
|
+ if (num_req_streams > ep->max_streams)
|
|
|
|
+ return 0;
|
|
|
|
+ /* Update the ep_comp descriptor if needed */
|
|
|
|
+ if (num_req_streams != ep->max_streams)
|
|
|
|
+ ep_comp->bmAttributes = ep->max_streams;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* If the protocol driver hasn't yet decided on wMaxPacketSize
|
|
* If the protocol driver hasn't yet decided on wMaxPacketSize
|
|
* and wants to know the maximum possible, provide the info.
|
|
* and wants to know the maximum possible, provide the info.
|
|
@@ -208,38 +227,53 @@ find_ep (struct usb_gadget *gadget, const char *name)
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * usb_ep_autoconfig - choose an endpoint matching the descriptor
|
|
|
|
|
|
+ * usb_ep_autoconfig_ss() - choose an endpoint matching the ep
|
|
|
|
+ * descriptor and ep companion descriptor
|
|
* @gadget: The device to which the endpoint must belong.
|
|
* @gadget: The device to which the endpoint must belong.
|
|
* @desc: Endpoint descriptor, with endpoint direction and transfer mode
|
|
* @desc: Endpoint descriptor, with endpoint direction and transfer mode
|
|
- * initialized. For periodic transfers, the maximum packet
|
|
|
|
- * size must also be initialized. This is modified on success.
|
|
|
|
|
|
+ * initialized. For periodic transfers, the maximum packet
|
|
|
|
+ * size must also be initialized. This is modified on
|
|
|
|
+ * success.
|
|
|
|
+ * @ep_comp: Endpoint companion descriptor, with the required
|
|
|
|
+ * number of streams. Will be modified when the chosen EP
|
|
|
|
+ * supports a different number of streams.
|
|
*
|
|
*
|
|
- * By choosing an endpoint to use with the specified descriptor, this
|
|
|
|
- * routine simplifies writing gadget drivers that work with multiple
|
|
|
|
- * USB device controllers. The endpoint would be passed later to
|
|
|
|
- * usb_ep_enable(), along with some descriptor.
|
|
|
|
|
|
+ * This routine replaces the usb_ep_autoconfig when needed
|
|
|
|
+ * superspeed enhancments. If such enhancemnets are required,
|
|
|
|
+ * the FD should call usb_ep_autoconfig_ss directly and provide
|
|
|
|
+ * the additional ep_comp parameter.
|
|
|
|
+ *
|
|
|
|
+ * By choosing an endpoint to use with the specified descriptor,
|
|
|
|
+ * this routine simplifies writing gadget drivers that work with
|
|
|
|
+ * multiple USB device controllers. The endpoint would be
|
|
|
|
+ * passed later to usb_ep_enable(), along with some descriptor.
|
|
*
|
|
*
|
|
* That second descriptor won't always be the same as the first one.
|
|
* That second descriptor won't always be the same as the first one.
|
|
* For example, isochronous endpoints can be autoconfigured for high
|
|
* For example, isochronous endpoints can be autoconfigured for high
|
|
* bandwidth, and then used in several lower bandwidth altsettings.
|
|
* bandwidth, and then used in several lower bandwidth altsettings.
|
|
* Also, high and full speed descriptors will be different.
|
|
* Also, high and full speed descriptors will be different.
|
|
*
|
|
*
|
|
- * Be sure to examine and test the results of autoconfiguration on your
|
|
|
|
- * hardware. This code may not make the best choices about how to use the
|
|
|
|
- * USB controller, and it can't know all the restrictions that may apply.
|
|
|
|
- * Some combinations of driver and hardware won't be able to autoconfigure.
|
|
|
|
|
|
+ * Be sure to examine and test the results of autoconfiguration
|
|
|
|
+ * on your hardware. This code may not make the best choices
|
|
|
|
+ * about how to use the USB controller, and it can't know all
|
|
|
|
+ * the restrictions that may apply. Some combinations of driver
|
|
|
|
+ * and hardware won't be able to autoconfigure.
|
|
*
|
|
*
|
|
* On success, this returns an un-claimed usb_ep, and modifies the endpoint
|
|
* On success, this returns an un-claimed usb_ep, and modifies the endpoint
|
|
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
|
|
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
|
|
- * is initialized as if the endpoint were used at full speed. To prevent
|
|
|
|
- * the endpoint from being returned by a later autoconfig call, claim it
|
|
|
|
- * by assigning ep->driver_data to some non-null value.
|
|
|
|
|
|
+ * is initialized as if the endpoint were used at full speed and
|
|
|
|
+ * the bmAttribute field in the ep companion descriptor is
|
|
|
|
+ * updated with the assigned number of streams if it is
|
|
|
|
+ * different from the original value. To prevent the endpoint
|
|
|
|
+ * from being returned by a later autoconfig call, claim it by
|
|
|
|
+ * assigning ep->driver_data to some non-null value.
|
|
*
|
|
*
|
|
* On failure, this returns a null endpoint descriptor.
|
|
* On failure, this returns a null endpoint descriptor.
|
|
*/
|
|
*/
|
|
-struct usb_ep *usb_ep_autoconfig (
|
|
|
|
|
|
+struct usb_ep *usb_ep_autoconfig_ss(
|
|
struct usb_gadget *gadget,
|
|
struct usb_gadget *gadget,
|
|
- struct usb_endpoint_descriptor *desc
|
|
|
|
|
|
+ struct usb_endpoint_descriptor *desc,
|
|
|
|
+ struct usb_ss_ep_comp_descriptor *ep_comp
|
|
)
|
|
)
|
|
{
|
|
{
|
|
struct usb_ep *ep;
|
|
struct usb_ep *ep;
|
|
@@ -253,23 +287,24 @@ struct usb_ep *usb_ep_autoconfig (
|
|
if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
|
|
if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
|
|
/* ep-e, ep-f are PIO with only 64 byte fifos */
|
|
/* ep-e, ep-f are PIO with only 64 byte fifos */
|
|
ep = find_ep (gadget, "ep-e");
|
|
ep = find_ep (gadget, "ep-e");
|
|
- if (ep && ep_matches (gadget, ep, desc))
|
|
|
|
|
|
+ if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
|
return ep;
|
|
return ep;
|
|
ep = find_ep (gadget, "ep-f");
|
|
ep = find_ep (gadget, "ep-f");
|
|
- if (ep && ep_matches (gadget, ep, desc))
|
|
|
|
|
|
+ if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
|
return ep;
|
|
return ep;
|
|
|
|
|
|
} else if (gadget_is_goku (gadget)) {
|
|
} else if (gadget_is_goku (gadget)) {
|
|
if (USB_ENDPOINT_XFER_INT == type) {
|
|
if (USB_ENDPOINT_XFER_INT == type) {
|
|
/* single buffering is enough */
|
|
/* single buffering is enough */
|
|
- ep = find_ep (gadget, "ep3-bulk");
|
|
|
|
- if (ep && ep_matches (gadget, ep, desc))
|
|
|
|
|
|
+ ep = find_ep(gadget, "ep3-bulk");
|
|
|
|
+ if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
|
return ep;
|
|
return ep;
|
|
} else if (USB_ENDPOINT_XFER_BULK == type
|
|
} else if (USB_ENDPOINT_XFER_BULK == type
|
|
&& (USB_DIR_IN & desc->bEndpointAddress)) {
|
|
&& (USB_DIR_IN & desc->bEndpointAddress)) {
|
|
/* DMA may be available */
|
|
/* DMA may be available */
|
|
- ep = find_ep (gadget, "ep2-bulk");
|
|
|
|
- if (ep && ep_matches (gadget, ep, desc))
|
|
|
|
|
|
+ ep = find_ep(gadget, "ep2-bulk");
|
|
|
|
+ if (ep && ep_matches(gadget, ep, desc,
|
|
|
|
+ ep_comp))
|
|
return ep;
|
|
return ep;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -288,14 +323,14 @@ struct usb_ep *usb_ep_autoconfig (
|
|
ep = find_ep(gadget, "ep2out");
|
|
ep = find_ep(gadget, "ep2out");
|
|
} else
|
|
} else
|
|
ep = NULL;
|
|
ep = NULL;
|
|
- if (ep && ep_matches (gadget, ep, desc))
|
|
|
|
|
|
+ if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
|
return ep;
|
|
return ep;
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/* Second, look at endpoints until an unclaimed one looks usable */
|
|
/* Second, look at endpoints until an unclaimed one looks usable */
|
|
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
|
|
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
|
|
- if (ep_matches (gadget, ep, desc))
|
|
|
|
|
|
+ if (ep_matches(gadget, ep, desc, ep_comp))
|
|
return ep;
|
|
return ep;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -303,6 +338,46 @@ struct usb_ep *usb_ep_autoconfig (
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * usb_ep_autoconfig() - choose an endpoint matching the
|
|
|
|
+ * descriptor
|
|
|
|
+ * @gadget: The device to which the endpoint must belong.
|
|
|
|
+ * @desc: Endpoint descriptor, with endpoint direction and transfer mode
|
|
|
|
+ * initialized. For periodic transfers, the maximum packet
|
|
|
|
+ * size must also be initialized. This is modified on success.
|
|
|
|
+ *
|
|
|
|
+ * By choosing an endpoint to use with the specified descriptor, this
|
|
|
|
+ * routine simplifies writing gadget drivers that work with multiple
|
|
|
|
+ * USB device controllers. The endpoint would be passed later to
|
|
|
|
+ * usb_ep_enable(), along with some descriptor.
|
|
|
|
+ *
|
|
|
|
+ * That second descriptor won't always be the same as the first one.
|
|
|
|
+ * For example, isochronous endpoints can be autoconfigured for high
|
|
|
|
+ * bandwidth, and then used in several lower bandwidth altsettings.
|
|
|
|
+ * Also, high and full speed descriptors will be different.
|
|
|
|
+ *
|
|
|
|
+ * Be sure to examine and test the results of autoconfiguration on your
|
|
|
|
+ * hardware. This code may not make the best choices about how to use the
|
|
|
|
+ * USB controller, and it can't know all the restrictions that may apply.
|
|
|
|
+ * Some combinations of driver and hardware won't be able to autoconfigure.
|
|
|
|
+ *
|
|
|
|
+ * On success, this returns an un-claimed usb_ep, and modifies the endpoint
|
|
|
|
+ * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
|
|
|
|
+ * is initialized as if the endpoint were used at full speed. To prevent
|
|
|
|
+ * the endpoint from being returned by a later autoconfig call, claim it
|
|
|
|
+ * by assigning ep->driver_data to some non-null value.
|
|
|
|
+ *
|
|
|
|
+ * On failure, this returns a null endpoint descriptor.
|
|
|
|
+ */
|
|
|
|
+struct usb_ep *usb_ep_autoconfig(
|
|
|
|
+ struct usb_gadget *gadget,
|
|
|
|
+ struct usb_endpoint_descriptor *desc
|
|
|
|
+)
|
|
|
|
+{
|
|
|
|
+ return usb_ep_autoconfig_ss(gadget, desc, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* usb_ep_autoconfig_reset - reset endpoint autoconfig state
|
|
* usb_ep_autoconfig_reset - reset endpoint autoconfig state
|
|
* @gadget: device for which autoconfig state will be reset
|
|
* @gadget: device for which autoconfig state will be reset
|