![]() |
|
|||
0001 // SPDX-License-Identifier: GPL-2.0+ 0002 /* 0003 * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers 0004 * 0005 * Copyright (C) 2004 David Brownell 0006 */ 0007 0008 #include <linux/kernel.h> 0009 #include <linux/module.h> 0010 #include <linux/types.h> 0011 #include <linux/device.h> 0012 0013 #include <linux/ctype.h> 0014 #include <linux/string.h> 0015 0016 #include <linux/usb/ch9.h> 0017 #include <linux/usb/gadget.h> 0018 0019 /** 0020 * usb_ep_autoconfig_ss() - choose an endpoint matching the ep 0021 * descriptor and ep companion descriptor 0022 * @gadget: The device to which the endpoint must belong. 0023 * @desc: Endpoint descriptor, with endpoint direction and transfer mode 0024 * initialized. For periodic transfers, the maximum packet 0025 * size must also be initialized. This is modified on 0026 * success. 0027 * @ep_comp: Endpoint companion descriptor, with the required 0028 * number of streams. Will be modified when the chosen EP 0029 * supports a different number of streams. 0030 * 0031 * This routine replaces the usb_ep_autoconfig when needed 0032 * superspeed enhancments. If such enhancemnets are required, 0033 * the FD should call usb_ep_autoconfig_ss directly and provide 0034 * the additional ep_comp parameter. 0035 * 0036 * By choosing an endpoint to use with the specified descriptor, 0037 * this routine simplifies writing gadget drivers that work with 0038 * multiple USB device controllers. The endpoint would be 0039 * passed later to usb_ep_enable(), along with some descriptor. 0040 * 0041 * That second descriptor won't always be the same as the first one. 0042 * For example, isochronous endpoints can be autoconfigured for high 0043 * bandwidth, and then used in several lower bandwidth altsettings. 0044 * Also, high and full speed descriptors will be different. 0045 * 0046 * Be sure to examine and test the results of autoconfiguration 0047 * on your hardware. This code may not make the best choices 0048 * about how to use the USB controller, and it can't know all 0049 * the restrictions that may apply. Some combinations of driver 0050 * and hardware won't be able to autoconfigure. 0051 * 0052 * On success, this returns an claimed usb_ep, and modifies the endpoint 0053 * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value 0054 * is initialized as if the endpoint were used at full speed and 0055 * the bmAttribute field in the ep companion descriptor is 0056 * updated with the assigned number of streams if it is 0057 * different from the original value. To prevent the endpoint 0058 * from being returned by a later autoconfig call, claims it by 0059 * assigning ep->claimed to true. 0060 * 0061 * On failure, this returns a null endpoint descriptor. 0062 */ 0063 struct usb_ep *usb_ep_autoconfig_ss( 0064 struct usb_gadget *gadget, 0065 struct usb_endpoint_descriptor *desc, 0066 struct usb_ss_ep_comp_descriptor *ep_comp 0067 ) 0068 { 0069 struct usb_ep *ep; 0070 0071 if (gadget->ops->match_ep) { 0072 ep = gadget->ops->match_ep(gadget, desc, ep_comp); 0073 if (ep) 0074 goto found_ep; 0075 } 0076 0077 /* Second, look at endpoints until an unclaimed one looks usable */ 0078 list_for_each_entry (ep, &gadget->ep_list, ep_list) { 0079 if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) 0080 goto found_ep; 0081 } 0082 0083 /* Fail */ 0084 return NULL; 0085 found_ep: 0086 0087 /* 0088 * If the protocol driver hasn't yet decided on wMaxPacketSize 0089 * and wants to know the maximum possible, provide the info. 0090 */ 0091 if (desc->wMaxPacketSize == 0) 0092 desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit); 0093 0094 /* report address */ 0095 desc->bEndpointAddress &= USB_DIR_IN; 0096 if (isdigit(ep->name[2])) { 0097 u8 num = simple_strtoul(&ep->name[2], NULL, 10); 0098 desc->bEndpointAddress |= num; 0099 } else if (desc->bEndpointAddress & USB_DIR_IN) { 0100 if (++gadget->in_epnum > 15) 0101 return NULL; 0102 desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum; 0103 } else { 0104 if (++gadget->out_epnum > 15) 0105 return NULL; 0106 desc->bEndpointAddress |= gadget->out_epnum; 0107 } 0108 0109 ep->address = desc->bEndpointAddress; 0110 ep->desc = NULL; 0111 ep->comp_desc = NULL; 0112 ep->claimed = true; 0113 return ep; 0114 } 0115 EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); 0116 0117 /** 0118 * usb_ep_autoconfig() - choose an endpoint matching the 0119 * descriptor 0120 * @gadget: The device to which the endpoint must belong. 0121 * @desc: Endpoint descriptor, with endpoint direction and transfer mode 0122 * initialized. For periodic transfers, the maximum packet 0123 * size must also be initialized. This is modified on success. 0124 * 0125 * By choosing an endpoint to use with the specified descriptor, this 0126 * routine simplifies writing gadget drivers that work with multiple 0127 * USB device controllers. The endpoint would be passed later to 0128 * usb_ep_enable(), along with some descriptor. 0129 * 0130 * That second descriptor won't always be the same as the first one. 0131 * For example, isochronous endpoints can be autoconfigured for high 0132 * bandwidth, and then used in several lower bandwidth altsettings. 0133 * Also, high and full speed descriptors will be different. 0134 * 0135 * Be sure to examine and test the results of autoconfiguration on your 0136 * hardware. This code may not make the best choices about how to use the 0137 * USB controller, and it can't know all the restrictions that may apply. 0138 * Some combinations of driver and hardware won't be able to autoconfigure. 0139 * 0140 * On success, this returns an claimed usb_ep, and modifies the endpoint 0141 * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value 0142 * is initialized as if the endpoint were used at full speed. Because of 0143 * that the users must consider adjusting the autoconfigured descriptor. 0144 * To prevent the endpoint from being returned by a later autoconfig call, 0145 * claims it by assigning ep->claimed to true. 0146 * 0147 * On failure, this returns a null endpoint descriptor. 0148 */ 0149 struct usb_ep *usb_ep_autoconfig( 0150 struct usb_gadget *gadget, 0151 struct usb_endpoint_descriptor *desc 0152 ) 0153 { 0154 struct usb_ep *ep; 0155 u8 type; 0156 0157 ep = usb_ep_autoconfig_ss(gadget, desc, NULL); 0158 if (!ep) 0159 return NULL; 0160 0161 type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; 0162 0163 /* report (variable) full speed bulk maxpacket */ 0164 if (type == USB_ENDPOINT_XFER_BULK) { 0165 int size = ep->maxpacket_limit; 0166 0167 /* min() doesn't work on bitfields with gcc-3.5 */ 0168 if (size > 64) 0169 size = 64; 0170 desc->wMaxPacketSize = cpu_to_le16(size); 0171 } 0172 0173 return ep; 0174 } 0175 EXPORT_SYMBOL_GPL(usb_ep_autoconfig); 0176 0177 /** 0178 * usb_ep_autoconfig_release - releases endpoint and set it to initial state 0179 * @ep: endpoint which should be released 0180 * 0181 * This function can be used during function bind for endpoints obtained 0182 * from usb_ep_autoconfig(). It unclaims endpoint claimed by 0183 * usb_ep_autoconfig() to make it available for other functions. Endpoint 0184 * which was released is no longer valid and shouldn't be used in 0185 * context of function which released it. 0186 */ 0187 void usb_ep_autoconfig_release(struct usb_ep *ep) 0188 { 0189 ep->claimed = false; 0190 ep->driver_data = NULL; 0191 } 0192 EXPORT_SYMBOL_GPL(usb_ep_autoconfig_release); 0193 0194 /** 0195 * usb_ep_autoconfig_reset - reset endpoint autoconfig state 0196 * @gadget: device for which autoconfig state will be reset 0197 * 0198 * Use this for devices where one configuration may need to assign 0199 * endpoint resources very differently from the next one. It clears 0200 * state such as ep->claimed and the record of assigned endpoints 0201 * used by usb_ep_autoconfig(). 0202 */ 0203 void usb_ep_autoconfig_reset (struct usb_gadget *gadget) 0204 { 0205 struct usb_ep *ep; 0206 0207 list_for_each_entry (ep, &gadget->ep_list, ep_list) { 0208 ep->claimed = false; 0209 ep->driver_data = NULL; 0210 } 0211 gadget->in_epnum = 0; 0212 gadget->out_epnum = 0; 0213 } 0214 EXPORT_SYMBOL_GPL(usb_ep_autoconfig_reset);
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |