1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers |
4 | * |
5 | * Copyright (C) 2004 David Brownell |
6 | */ |
7 | |
8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> |
10 | #include <linux/types.h> |
11 | #include <linux/device.h> |
12 | |
13 | #include <linux/ctype.h> |
14 | #include <linux/string.h> |
15 | |
16 | #include <linux/usb/ch9.h> |
17 | #include <linux/usb/gadget.h> |
18 | |
19 | /** |
20 | * usb_ep_autoconfig_ss() - choose an endpoint matching the ep |
21 | * descriptor and ep companion descriptor |
22 | * @gadget: The device to which the endpoint must belong. |
23 | * @desc: Endpoint descriptor, with endpoint direction and transfer mode |
24 | * initialized. For periodic transfers, the maximum packet |
25 | * size must also be initialized. This is modified on |
26 | * success. |
27 | * @ep_comp: Endpoint companion descriptor, with the required |
28 | * number of streams. Will be modified when the chosen EP |
29 | * supports a different number of streams. |
30 | * |
31 | * This routine replaces the usb_ep_autoconfig when needed |
32 | * superspeed enhancments. If such enhancemnets are required, |
33 | * the FD should call usb_ep_autoconfig_ss directly and provide |
34 | * the additional ep_comp parameter. |
35 | * |
36 | * By choosing an endpoint to use with the specified descriptor, |
37 | * this routine simplifies writing gadget drivers that work with |
38 | * multiple USB device controllers. The endpoint would be |
39 | * passed later to usb_ep_enable(), along with some descriptor. |
40 | * |
41 | * That second descriptor won't always be the same as the first one. |
42 | * For example, isochronous endpoints can be autoconfigured for high |
43 | * bandwidth, and then used in several lower bandwidth altsettings. |
44 | * Also, high and full speed descriptors will be different. |
45 | * |
46 | * Be sure to examine and test the results of autoconfiguration |
47 | * on your hardware. This code may not make the best choices |
48 | * about how to use the USB controller, and it can't know all |
49 | * the restrictions that may apply. Some combinations of driver |
50 | * and hardware won't be able to autoconfigure. |
51 | * |
52 | * On success, this returns an claimed usb_ep, and modifies the endpoint |
53 | * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value |
54 | * is initialized as if the endpoint were used at full speed and |
55 | * the bmAttribute field in the ep companion descriptor is |
56 | * updated with the assigned number of streams if it is |
57 | * different from the original value. To prevent the endpoint |
58 | * from being returned by a later autoconfig call, claims it by |
59 | * assigning ep->claimed to true. |
60 | * |
61 | * On failure, this returns a null endpoint descriptor. |
62 | */ |
63 | struct usb_ep *usb_ep_autoconfig_ss( |
64 | struct usb_gadget *gadget, |
65 | struct usb_endpoint_descriptor *desc, |
66 | struct usb_ss_ep_comp_descriptor *ep_comp |
67 | ) |
68 | { |
69 | struct usb_ep *ep; |
70 | |
71 | if (gadget->ops->match_ep) { |
72 | ep = gadget->ops->match_ep(gadget, desc, ep_comp); |
73 | if (ep) |
74 | goto found_ep; |
75 | } |
76 | |
77 | /* Second, look at endpoints until an unclaimed one looks usable */ |
78 | list_for_each_entry (ep, &gadget->ep_list, ep_list) { |
79 | if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) |
80 | goto found_ep; |
81 | } |
82 | |
83 | /* Fail */ |
84 | return NULL; |
85 | found_ep: |
86 | |
87 | /* |
88 | * If the protocol driver hasn't yet decided on wMaxPacketSize |
89 | * and wants to know the maximum possible, provide the info. |
90 | */ |
91 | if (desc->wMaxPacketSize == 0) |
92 | desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit); |
93 | |
94 | /* report address */ |
95 | desc->bEndpointAddress &= USB_DIR_IN; |
96 | if (isdigit(c: ep->name[2])) { |
97 | u8 num = simple_strtoul(&ep->name[2], NULL, 10); |
98 | desc->bEndpointAddress |= num; |
99 | } else if (desc->bEndpointAddress & USB_DIR_IN) { |
100 | if (++gadget->in_epnum > 15) |
101 | return NULL; |
102 | desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum; |
103 | } else { |
104 | if (++gadget->out_epnum > 15) |
105 | return NULL; |
106 | desc->bEndpointAddress |= gadget->out_epnum; |
107 | } |
108 | |
109 | ep->address = desc->bEndpointAddress; |
110 | ep->desc = NULL; |
111 | ep->comp_desc = NULL; |
112 | ep->claimed = true; |
113 | return ep; |
114 | } |
115 | EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); |
116 | |
117 | /** |
118 | * usb_ep_autoconfig() - choose an endpoint matching the |
119 | * descriptor |
120 | * @gadget: The device to which the endpoint must belong. |
121 | * @desc: Endpoint descriptor, with endpoint direction and transfer mode |
122 | * initialized. For periodic transfers, the maximum packet |
123 | * size must also be initialized. This is modified on success. |
124 | * |
125 | * By choosing an endpoint to use with the specified descriptor, this |
126 | * routine simplifies writing gadget drivers that work with multiple |
127 | * USB device controllers. The endpoint would be passed later to |
128 | * usb_ep_enable(), along with some descriptor. |
129 | * |
130 | * That second descriptor won't always be the same as the first one. |
131 | * For example, isochronous endpoints can be autoconfigured for high |
132 | * bandwidth, and then used in several lower bandwidth altsettings. |
133 | * Also, high and full speed descriptors will be different. |
134 | * |
135 | * Be sure to examine and test the results of autoconfiguration on your |
136 | * hardware. This code may not make the best choices about how to use the |
137 | * USB controller, and it can't know all the restrictions that may apply. |
138 | * Some combinations of driver and hardware won't be able to autoconfigure. |
139 | * |
140 | * On success, this returns an claimed usb_ep, and modifies the endpoint |
141 | * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value |
142 | * is initialized as if the endpoint were used at full speed. Because of |
143 | * that the users must consider adjusting the autoconfigured descriptor. |
144 | * To prevent the endpoint from being returned by a later autoconfig call, |
145 | * claims it by assigning ep->claimed to true. |
146 | * |
147 | * On failure, this returns a null endpoint descriptor. |
148 | */ |
149 | struct usb_ep *usb_ep_autoconfig( |
150 | struct usb_gadget *gadget, |
151 | struct usb_endpoint_descriptor *desc |
152 | ) |
153 | { |
154 | struct usb_ep *ep; |
155 | u8 type; |
156 | |
157 | ep = usb_ep_autoconfig_ss(gadget, desc, NULL); |
158 | if (!ep) |
159 | return NULL; |
160 | |
161 | type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; |
162 | |
163 | /* report (variable) full speed bulk maxpacket */ |
164 | if (type == USB_ENDPOINT_XFER_BULK) { |
165 | int size = ep->maxpacket_limit; |
166 | |
167 | /* min() doesn't work on bitfields with gcc-3.5 */ |
168 | if (size > 64) |
169 | size = 64; |
170 | desc->wMaxPacketSize = cpu_to_le16(size); |
171 | } |
172 | |
173 | return ep; |
174 | } |
175 | EXPORT_SYMBOL_GPL(usb_ep_autoconfig); |
176 | |
177 | /** |
178 | * usb_ep_autoconfig_release - releases endpoint and set it to initial state |
179 | * @ep: endpoint which should be released |
180 | * |
181 | * This function can be used during function bind for endpoints obtained |
182 | * from usb_ep_autoconfig(). It unclaims endpoint claimed by |
183 | * usb_ep_autoconfig() to make it available for other functions. Endpoint |
184 | * which was released is no longer valid and shouldn't be used in |
185 | * context of function which released it. |
186 | */ |
187 | void usb_ep_autoconfig_release(struct usb_ep *ep) |
188 | { |
189 | ep->claimed = false; |
190 | ep->driver_data = NULL; |
191 | } |
192 | EXPORT_SYMBOL_GPL(usb_ep_autoconfig_release); |
193 | |
194 | /** |
195 | * usb_ep_autoconfig_reset - reset endpoint autoconfig state |
196 | * @gadget: device for which autoconfig state will be reset |
197 | * |
198 | * Use this for devices where one configuration may need to assign |
199 | * endpoint resources very differently from the next one. It clears |
200 | * state such as ep->claimed and the record of assigned endpoints |
201 | * used by usb_ep_autoconfig(). |
202 | */ |
203 | void usb_ep_autoconfig_reset (struct usb_gadget *gadget) |
204 | { |
205 | struct usb_ep *ep; |
206 | |
207 | list_for_each_entry (ep, &gadget->ep_list, ep_list) { |
208 | ep->claimed = false; |
209 | ep->driver_data = NULL; |
210 | } |
211 | gadget->in_epnum = 0; |
212 | gadget->out_epnum = 0; |
213 | } |
214 | EXPORT_SYMBOL_GPL(usb_ep_autoconfig_reset); |
215 | |