usb: gadget: move ep_matches() from epautoconf to udc-core
Move ep_matches() function to udc-core and rename it to usb_gadget_ep_match_desc(). This function can be used by UDC drivers in 'match_ep' callback to avoid writing lots of repetitive code. Replace all calls of ep_matches() with usb_gadget_ep_match_desc(). Signed-off-by: Robert Baldyga <r.baldyga@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
committed by
Felipe Balbi
parent
596c154d62
commit
4278c687f6
@@ -22,82 +22,6 @@
|
|||||||
|
|
||||||
#include "gadget_chips.h"
|
#include "gadget_chips.h"
|
||||||
|
|
||||||
static int
|
|
||||||
ep_matches (
|
|
||||||
struct usb_gadget *gadget,
|
|
||||||
struct usb_ep *ep,
|
|
||||||
struct usb_endpoint_descriptor *desc,
|
|
||||||
struct usb_ss_ep_comp_descriptor *ep_comp
|
|
||||||
)
|
|
||||||
{
|
|
||||||
u8 type;
|
|
||||||
u16 max;
|
|
||||||
int num_req_streams = 0;
|
|
||||||
|
|
||||||
/* endpoint already claimed? */
|
|
||||||
if (ep->claimed)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
type = usb_endpoint_type(desc);
|
|
||||||
max = 0x7ff & usb_endpoint_maxp(desc);
|
|
||||||
|
|
||||||
if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
|
|
||||||
return 0;
|
|
||||||
if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (max > ep->maxpacket_limit)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* "high bandwidth" works only at high speed */
|
|
||||||
if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case USB_ENDPOINT_XFER_CONTROL:
|
|
||||||
/* only support ep0 for portable CONTROL traffic */
|
|
||||||
return 0;
|
|
||||||
case USB_ENDPOINT_XFER_ISOC:
|
|
||||||
if (!ep->caps.type_iso)
|
|
||||||
return 0;
|
|
||||||
/* ISO: limit 1023 bytes full speed,
|
|
||||||
* 1024 high/super speed
|
|
||||||
*/
|
|
||||||
if (!gadget_is_dualspeed(gadget) && max > 1023)
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case USB_ENDPOINT_XFER_BULK:
|
|
||||||
if (!ep->caps.type_bulk)
|
|
||||||
return 0;
|
|
||||||
if (ep_comp && gadget_is_superspeed(gadget)) {
|
|
||||||
/* Get the number of required streams from the
|
|
||||||
* EP companion descriptor and see if the EP
|
|
||||||
* matches it
|
|
||||||
*/
|
|
||||||
num_req_streams = ep_comp->bmAttributes & 0x1f;
|
|
||||||
if (num_req_streams > ep->max_streams)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case USB_ENDPOINT_XFER_INT:
|
|
||||||
/* Bulk endpoints handle interrupt transfers,
|
|
||||||
* except the toggle-quirky iso-synch kind
|
|
||||||
*/
|
|
||||||
if (!ep->caps.type_int && !ep->caps.type_bulk)
|
|
||||||
return 0;
|
|
||||||
/* INT: limit 64 bytes full speed,
|
|
||||||
* 1024 high/super speed
|
|
||||||
*/
|
|
||||||
if (!gadget_is_dualspeed(gadget) && max > 64)
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MATCH!! */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct usb_ep *
|
static struct usb_ep *
|
||||||
find_ep (struct usb_gadget *gadget, const char *name)
|
find_ep (struct usb_gadget *gadget, const char *name)
|
||||||
{
|
{
|
||||||
@@ -180,10 +104,12 @@ struct usb_ep *usb_ep_autoconfig_ss(
|
|||||||
if (type == USB_ENDPOINT_XFER_INT) {
|
if (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, ep_comp))
|
if (ep && usb_gadget_ep_match_desc(gadget,
|
||||||
|
ep, desc, ep_comp))
|
||||||
goto found_ep;
|
goto found_ep;
|
||||||
ep = find_ep(gadget, "ep-f");
|
ep = find_ep(gadget, "ep-f");
|
||||||
if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
if (ep && usb_gadget_ep_match_desc(gadget,
|
||||||
|
ep, desc, ep_comp))
|
||||||
goto found_ep;
|
goto found_ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,20 +117,21 @@ struct usb_ep *usb_ep_autoconfig_ss(
|
|||||||
snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
|
snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
|
||||||
usb_endpoint_dir_in(desc) ? "in" : "out");
|
usb_endpoint_dir_in(desc) ? "in" : "out");
|
||||||
ep = find_ep(gadget, name);
|
ep = find_ep(gadget, name);
|
||||||
if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
|
||||||
goto found_ep;
|
goto found_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");
|
ep = find_ep(gadget, "ep3-bulk");
|
||||||
if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
if (ep && usb_gadget_ep_match_desc(gadget,
|
||||||
|
ep, desc, ep_comp))
|
||||||
goto found_ep;
|
goto found_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");
|
ep = find_ep(gadget, "ep2-bulk");
|
||||||
if (ep && ep_matches(gadget, ep, desc,
|
if (ep && usb_gadget_ep_match_desc(gadget,
|
||||||
ep_comp))
|
ep, desc, ep_comp))
|
||||||
goto found_ep;
|
goto found_ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,14 +150,14 @@ struct usb_ep *usb_ep_autoconfig_ss(
|
|||||||
ep = find_ep(gadget, "ep2out");
|
ep = find_ep(gadget, "ep2out");
|
||||||
} else
|
} else
|
||||||
ep = NULL;
|
ep = NULL;
|
||||||
if (ep && ep_matches(gadget, ep, desc, ep_comp))
|
if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
|
||||||
goto found_ep;
|
goto found_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, ep_comp))
|
if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
|
||||||
goto found_ep;
|
goto found_ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,75 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
|
||||||
|
struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
|
||||||
|
struct usb_ss_ep_comp_descriptor *ep_comp)
|
||||||
|
{
|
||||||
|
u8 type;
|
||||||
|
u16 max;
|
||||||
|
int num_req_streams = 0;
|
||||||
|
|
||||||
|
/* endpoint already claimed? */
|
||||||
|
if (ep->claimed)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
type = usb_endpoint_type(desc);
|
||||||
|
max = 0x7ff & usb_endpoint_maxp(desc);
|
||||||
|
|
||||||
|
if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
|
||||||
|
return 0;
|
||||||
|
if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (max > ep->maxpacket_limit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* "high bandwidth" works only at high speed */
|
||||||
|
if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case USB_ENDPOINT_XFER_CONTROL:
|
||||||
|
/* only support ep0 for portable CONTROL traffic */
|
||||||
|
return 0;
|
||||||
|
case USB_ENDPOINT_XFER_ISOC:
|
||||||
|
if (!ep->caps.type_iso)
|
||||||
|
return 0;
|
||||||
|
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
|
||||||
|
if (!gadget_is_dualspeed(gadget) && max > 1023)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case USB_ENDPOINT_XFER_BULK:
|
||||||
|
if (!ep->caps.type_bulk)
|
||||||
|
return 0;
|
||||||
|
if (ep_comp && gadget_is_superspeed(gadget)) {
|
||||||
|
/* Get the number of required streams from the
|
||||||
|
* EP companion descriptor and see if the EP
|
||||||
|
* matches it
|
||||||
|
*/
|
||||||
|
num_req_streams = ep_comp->bmAttributes & 0x1f;
|
||||||
|
if (num_req_streams > ep->max_streams)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case USB_ENDPOINT_XFER_INT:
|
||||||
|
/* Bulk endpoints handle interrupt transfers,
|
||||||
|
* except the toggle-quirky iso-synch kind
|
||||||
|
*/
|
||||||
|
if (!ep->caps.type_int && !ep->caps.type_bulk)
|
||||||
|
return 0;
|
||||||
|
/* INT: limit 64 bytes full speed, 1024 high/super speed */
|
||||||
|
if (!gadget_is_dualspeed(gadget) && max > 64)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void usb_gadget_state_work(struct work_struct *work)
|
static void usb_gadget_state_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct usb_gadget *gadget = work_to_gadget(work);
|
struct usb_gadget *gadget = work_to_gadget(work);
|
||||||
|
|||||||
@@ -1204,6 +1204,14 @@ extern void usb_gadget_giveback_request(struct usb_ep *ep,
|
|||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* utility to check if endpoint caps match descriptor needs */
|
||||||
|
|
||||||
|
extern int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
|
||||||
|
struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
|
||||||
|
struct usb_ss_ep_comp_descriptor *ep_comp);
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* utility to update vbus status for udc core, it may be scheduled */
|
/* utility to update vbus status for udc core, it may be scheduled */
|
||||||
extern void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status);
|
extern void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user