diff options
Diffstat (limited to 'drivers/usb/gadget/epautoconf.c')
-rw-r--r-- | drivers/usb/gadget/epautoconf.c | 132 |
1 files changed, 104 insertions, 28 deletions
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 9b7360ff5aa7..7a7e6b7e1fd6 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c | |||
@@ -63,13 +63,16 @@ static int | |||
63 | ep_matches ( | 63 | ep_matches ( |
64 | struct usb_gadget *gadget, | 64 | struct usb_gadget *gadget, |
65 | struct usb_ep *ep, | 65 | struct usb_ep *ep, |
66 | struct usb_endpoint_descriptor *desc | 66 | struct usb_endpoint_descriptor *desc, |
67 | struct usb_ss_ep_comp_descriptor *ep_comp | ||
67 | ) | 68 | ) |
68 | { | 69 | { |
69 | u8 type; | 70 | u8 type; |
70 | const char *tmp; | 71 | const char *tmp; |
71 | u16 max; | 72 | u16 max; |
72 | 73 | ||
74 | int num_req_streams = 0; | ||
75 | |||
73 | /* endpoint already claimed? */ | 76 | /* endpoint already claimed? */ |
74 | if (NULL != ep->driver_data) | 77 | if (NULL != ep->driver_data) |
75 | return 0; | 78 | return 0; |
@@ -129,6 +132,22 @@ ep_matches ( | |||
129 | } | 132 | } |
130 | 133 | ||
131 | /* | 134 | /* |
135 | * Get the number of required streams from the EP companion | ||
136 | * descriptor and see if the EP matches it | ||
137 | */ | ||
138 | if (usb_endpoint_xfer_bulk(desc)) { | ||
139 | if (ep_comp) { | ||
140 | num_req_streams = ep_comp->bmAttributes & 0x1f; | ||
141 | if (num_req_streams > ep->max_streams) | ||
142 | return 0; | ||
143 | /* Update the ep_comp descriptor if needed */ | ||
144 | if (num_req_streams != ep->max_streams) | ||
145 | ep_comp->bmAttributes = ep->max_streams; | ||
146 | } | ||
147 | |||
148 | } | ||
149 | |||
150 | /* | ||
132 | * If the protocol driver hasn't yet decided on wMaxPacketSize | 151 | * If the protocol driver hasn't yet decided on wMaxPacketSize |
133 | * and wants to know the maximum possible, provide the info. | 152 | * and wants to know the maximum possible, provide the info. |
134 | */ | 153 | */ |
@@ -142,13 +161,13 @@ ep_matches ( | |||
142 | max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); | 161 | max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); |
143 | switch (type) { | 162 | switch (type) { |
144 | case USB_ENDPOINT_XFER_INT: | 163 | case USB_ENDPOINT_XFER_INT: |
145 | /* INT: limit 64 bytes full speed, 1024 high speed */ | 164 | /* INT: limit 64 bytes full speed, 1024 high/super speed */ |
146 | if (!gadget->is_dualspeed && max > 64) | 165 | if (!gadget->is_dualspeed && max > 64) |
147 | return 0; | 166 | return 0; |
148 | /* FALLTHROUGH */ | 167 | /* FALLTHROUGH */ |
149 | 168 | ||
150 | case USB_ENDPOINT_XFER_ISOC: | 169 | case USB_ENDPOINT_XFER_ISOC: |
151 | /* ISO: limit 1023 bytes full speed, 1024 high speed */ | 170 | /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ |
152 | if (ep->maxpacket < max) | 171 | if (ep->maxpacket < max) |
153 | return 0; | 172 | return 0; |
154 | if (!gadget->is_dualspeed && max > 1023) | 173 | if (!gadget->is_dualspeed && max > 1023) |
@@ -183,7 +202,7 @@ ep_matches ( | |||
183 | } | 202 | } |
184 | 203 | ||
185 | /* report (variable) full speed bulk maxpacket */ | 204 | /* report (variable) full speed bulk maxpacket */ |
186 | if (USB_ENDPOINT_XFER_BULK == type) { | 205 | if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) { |
187 | int size = ep->maxpacket; | 206 | int size = ep->maxpacket; |
188 | 207 | ||
189 | /* min() doesn't work on bitfields with gcc-3.5 */ | 208 | /* min() doesn't work on bitfields with gcc-3.5 */ |
@@ -191,6 +210,7 @@ ep_matches ( | |||
191 | size = 64; | 210 | size = 64; |
192 | desc->wMaxPacketSize = cpu_to_le16(size); | 211 | desc->wMaxPacketSize = cpu_to_le16(size); |
193 | } | 212 | } |
213 | ep->address = desc->bEndpointAddress; | ||
194 | return 1; | 214 | return 1; |
195 | } | 215 | } |
196 | 216 | ||
@@ -207,38 +227,53 @@ find_ep (struct usb_gadget *gadget, const char *name) | |||
207 | } | 227 | } |
208 | 228 | ||
209 | /** | 229 | /** |
210 | * usb_ep_autoconfig - choose an endpoint matching the descriptor | 230 | * usb_ep_autoconfig_ss() - choose an endpoint matching the ep |
231 | * descriptor and ep companion descriptor | ||
211 | * @gadget: The device to which the endpoint must belong. | 232 | * @gadget: The device to which the endpoint must belong. |
212 | * @desc: Endpoint descriptor, with endpoint direction and transfer mode | 233 | * @desc: Endpoint descriptor, with endpoint direction and transfer mode |
213 | * initialized. For periodic transfers, the maximum packet | 234 | * initialized. For periodic transfers, the maximum packet |
214 | * size must also be initialized. This is modified on success. | 235 | * size must also be initialized. This is modified on |
236 | * success. | ||
237 | * @ep_comp: Endpoint companion descriptor, with the required | ||
238 | * number of streams. Will be modified when the chosen EP | ||
239 | * supports a different number of streams. | ||
215 | * | 240 | * |
216 | * By choosing an endpoint to use with the specified descriptor, this | 241 | * This routine replaces the usb_ep_autoconfig when needed |
217 | * routine simplifies writing gadget drivers that work with multiple | 242 | * superspeed enhancments. If such enhancemnets are required, |
218 | * USB device controllers. The endpoint would be passed later to | 243 | * the FD should call usb_ep_autoconfig_ss directly and provide |
219 | * usb_ep_enable(), along with some descriptor. | 244 | * the additional ep_comp parameter. |
245 | * | ||
246 | * By choosing an endpoint to use with the specified descriptor, | ||
247 | * this routine simplifies writing gadget drivers that work with | ||
248 | * multiple USB device controllers. The endpoint would be | ||
249 | * passed later to usb_ep_enable(), along with some descriptor. | ||
220 | * | 250 | * |
221 | * That second descriptor won't always be the same as the first one. | 251 | * That second descriptor won't always be the same as the first one. |
222 | * For example, isochronous endpoints can be autoconfigured for high | 252 | * For example, isochronous endpoints can be autoconfigured for high |
223 | * bandwidth, and then used in several lower bandwidth altsettings. | 253 | * bandwidth, and then used in several lower bandwidth altsettings. |
224 | * Also, high and full speed descriptors will be different. | 254 | * Also, high and full speed descriptors will be different. |
225 | * | 255 | * |
226 | * Be sure to examine and test the results of autoconfiguration on your | 256 | * Be sure to examine and test the results of autoconfiguration |
227 | * hardware. This code may not make the best choices about how to use the | 257 | * on your hardware. This code may not make the best choices |
228 | * USB controller, and it can't know all the restrictions that may apply. | 258 | * about how to use the USB controller, and it can't know all |
229 | * Some combinations of driver and hardware won't be able to autoconfigure. | 259 | * the restrictions that may apply. Some combinations of driver |
260 | * and hardware won't be able to autoconfigure. | ||
230 | * | 261 | * |
231 | * On success, this returns an un-claimed usb_ep, and modifies the endpoint | 262 | * On success, this returns an un-claimed usb_ep, and modifies the endpoint |
232 | * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value | 263 | * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value |
233 | * is initialized as if the endpoint were used at full speed. To prevent | 264 | * is initialized as if the endpoint were used at full speed and |
234 | * the endpoint from being returned by a later autoconfig call, claim it | 265 | * the bmAttribute field in the ep companion descriptor is |
235 | * by assigning ep->driver_data to some non-null value. | 266 | * updated with the assigned number of streams if it is |
267 | * different from the original value. To prevent the endpoint | ||
268 | * from being returned by a later autoconfig call, claim it by | ||
269 | * assigning ep->driver_data to some non-null value. | ||
236 | * | 270 | * |
237 | * On failure, this returns a null endpoint descriptor. | 271 | * On failure, this returns a null endpoint descriptor. |
238 | */ | 272 | */ |
239 | struct usb_ep *usb_ep_autoconfig ( | 273 | struct usb_ep *usb_ep_autoconfig_ss( |
240 | struct usb_gadget *gadget, | 274 | struct usb_gadget *gadget, |
241 | struct usb_endpoint_descriptor *desc | 275 | struct usb_endpoint_descriptor *desc, |
276 | struct usb_ss_ep_comp_descriptor *ep_comp | ||
242 | ) | 277 | ) |
243 | { | 278 | { |
244 | struct usb_ep *ep; | 279 | struct usb_ep *ep; |
@@ -252,23 +287,24 @@ struct usb_ep *usb_ep_autoconfig ( | |||
252 | if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) { | 287 | if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) { |
253 | /* ep-e, ep-f are PIO with only 64 byte fifos */ | 288 | /* ep-e, ep-f are PIO with only 64 byte fifos */ |
254 | ep = find_ep (gadget, "ep-e"); | 289 | ep = find_ep (gadget, "ep-e"); |
255 | if (ep && ep_matches (gadget, ep, desc)) | 290 | if (ep && ep_matches(gadget, ep, desc, ep_comp)) |
256 | return ep; | 291 | return ep; |
257 | ep = find_ep (gadget, "ep-f"); | 292 | ep = find_ep (gadget, "ep-f"); |
258 | if (ep && ep_matches (gadget, ep, desc)) | 293 | if (ep && ep_matches(gadget, ep, desc, ep_comp)) |
259 | return ep; | 294 | return ep; |
260 | 295 | ||
261 | } else if (gadget_is_goku (gadget)) { | 296 | } else if (gadget_is_goku (gadget)) { |
262 | if (USB_ENDPOINT_XFER_INT == type) { | 297 | if (USB_ENDPOINT_XFER_INT == type) { |
263 | /* single buffering is enough */ | 298 | /* single buffering is enough */ |
264 | ep = find_ep (gadget, "ep3-bulk"); | 299 | ep = find_ep(gadget, "ep3-bulk"); |
265 | if (ep && ep_matches (gadget, ep, desc)) | 300 | if (ep && ep_matches(gadget, ep, desc, ep_comp)) |
266 | return ep; | 301 | return ep; |
267 | } else if (USB_ENDPOINT_XFER_BULK == type | 302 | } else if (USB_ENDPOINT_XFER_BULK == type |
268 | && (USB_DIR_IN & desc->bEndpointAddress)) { | 303 | && (USB_DIR_IN & desc->bEndpointAddress)) { |
269 | /* DMA may be available */ | 304 | /* DMA may be available */ |
270 | ep = find_ep (gadget, "ep2-bulk"); | 305 | ep = find_ep(gadget, "ep2-bulk"); |
271 | if (ep && ep_matches (gadget, ep, desc)) | 306 | if (ep && ep_matches(gadget, ep, desc, |
307 | ep_comp)) | ||
272 | return ep; | 308 | return ep; |
273 | } | 309 | } |
274 | 310 | ||
@@ -287,14 +323,14 @@ struct usb_ep *usb_ep_autoconfig ( | |||
287 | ep = find_ep(gadget, "ep2out"); | 323 | ep = find_ep(gadget, "ep2out"); |
288 | } else | 324 | } else |
289 | ep = NULL; | 325 | ep = NULL; |
290 | if (ep && ep_matches (gadget, ep, desc)) | 326 | if (ep && ep_matches(gadget, ep, desc, ep_comp)) |
291 | return ep; | 327 | return ep; |
292 | #endif | 328 | #endif |
293 | } | 329 | } |
294 | 330 | ||
295 | /* Second, look at endpoints until an unclaimed one looks usable */ | 331 | /* Second, look at endpoints until an unclaimed one looks usable */ |
296 | list_for_each_entry (ep, &gadget->ep_list, ep_list) { | 332 | list_for_each_entry (ep, &gadget->ep_list, ep_list) { |
297 | if (ep_matches (gadget, ep, desc)) | 333 | if (ep_matches(gadget, ep, desc, ep_comp)) |
298 | return ep; | 334 | return ep; |
299 | } | 335 | } |
300 | 336 | ||
@@ -303,6 +339,46 @@ struct usb_ep *usb_ep_autoconfig ( | |||
303 | } | 339 | } |
304 | 340 | ||
305 | /** | 341 | /** |
342 | * usb_ep_autoconfig() - choose an endpoint matching the | ||
343 | * descriptor | ||
344 | * @gadget: The device to which the endpoint must belong. | ||
345 | * @desc: Endpoint descriptor, with endpoint direction and transfer mode | ||
346 | * initialized. For periodic transfers, the maximum packet | ||
347 | * size must also be initialized. This is modified on success. | ||
348 | * | ||
349 | * By choosing an endpoint to use with the specified descriptor, this | ||
350 | * routine simplifies writing gadget drivers that work with multiple | ||
351 | * USB device controllers. The endpoint would be passed later to | ||
352 | * usb_ep_enable(), along with some descriptor. | ||
353 | * | ||
354 | * That second descriptor won't always be the same as the first one. | ||
355 | * For example, isochronous endpoints can be autoconfigured for high | ||
356 | * bandwidth, and then used in several lower bandwidth altsettings. | ||
357 | * Also, high and full speed descriptors will be different. | ||
358 | * | ||
359 | * Be sure to examine and test the results of autoconfiguration on your | ||
360 | * hardware. This code may not make the best choices about how to use the | ||
361 | * USB controller, and it can't know all the restrictions that may apply. | ||
362 | * Some combinations of driver and hardware won't be able to autoconfigure. | ||
363 | * | ||
364 | * On success, this returns an un-claimed usb_ep, and modifies the endpoint | ||
365 | * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value | ||
366 | * is initialized as if the endpoint were used at full speed. To prevent | ||
367 | * the endpoint from being returned by a later autoconfig call, claim it | ||
368 | * by assigning ep->driver_data to some non-null value. | ||
369 | * | ||
370 | * On failure, this returns a null endpoint descriptor. | ||
371 | */ | ||
372 | struct usb_ep *usb_ep_autoconfig( | ||
373 | struct usb_gadget *gadget, | ||
374 | struct usb_endpoint_descriptor *desc | ||
375 | ) | ||
376 | { | ||
377 | return usb_ep_autoconfig_ss(gadget, desc, NULL); | ||
378 | } | ||
379 | |||
380 | |||
381 | /** | ||
306 | * usb_ep_autoconfig_reset - reset endpoint autoconfig state | 382 | * usb_ep_autoconfig_reset - reset endpoint autoconfig state |
307 | * @gadget: device for which autoconfig state will be reset | 383 | * @gadget: device for which autoconfig state will be reset |
308 | * | 384 | * |