Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
epautoconf.c
Go to the documentation of this file.
1 /*
2  * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
3  *
4  * Copyright (C) 2004 David Brownell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/types.h>
16 #include <linux/device.h>
17 
18 #include <linux/ctype.h>
19 #include <linux/string.h>
20 
21 #include <linux/usb/ch9.h>
22 #include <linux/usb/gadget.h>
23 
24 #include "gadget_chips.h"
25 
26 /*
27  * This should work with endpoints from controller drivers sharing the
28  * same endpoint naming convention. By example:
29  *
30  * - ep1, ep2, ... address is fixed, not direction or type
31  * - ep1in, ep2out, ... address and direction are fixed, not type
32  * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
33  * - ep1in-bulk, ep2out-iso, ... all three are fixed
34  * - ep-* ... no functionality restrictions
35  *
36  * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
37  * Less common restrictions are implied by gadget_is_*().
38  *
39  * NOTE: each endpoint is unidirectional, as specified by its USB
40  * descriptor; and isn't specific to a configuration or altsetting.
41  */
42 static int
43 ep_matches (
44  struct usb_gadget *gadget,
45  struct usb_ep *ep,
47  struct usb_ss_ep_comp_descriptor *ep_comp
48 )
49 {
50  u8 type;
51  const char *tmp;
52  u16 max;
53 
54  int num_req_streams = 0;
55 
56  /* endpoint already claimed? */
57  if (NULL != ep->driver_data)
58  return 0;
59 
60  /* only support ep0 for portable CONTROL traffic */
62  if (USB_ENDPOINT_XFER_CONTROL == type)
63  return 0;
64 
65  /* some other naming convention */
66  if ('e' != ep->name[0])
67  return 0;
68 
69  /* type-restriction: "-iso", "-bulk", or "-int".
70  * direction-restriction: "in", "out".
71  */
72  if ('-' != ep->name[2]) {
73  tmp = strrchr (ep->name, '-');
74  if (tmp) {
75  switch (type) {
77  /* bulk endpoints handle interrupt transfers,
78  * except the toggle-quirky iso-synch kind
79  */
80  if ('s' == tmp[2]) // == "-iso"
81  return 0;
82  /* for now, avoid PXA "interrupt-in";
83  * it's documented as never using DATA1.
84  */
85  if (gadget_is_pxa (gadget)
86  && 'i' == tmp [1])
87  return 0;
88  break;
90  if ('b' != tmp[1]) // != "-bulk"
91  return 0;
92  break;
94  if ('s' != tmp[2]) // != "-iso"
95  return 0;
96  }
97  } else {
98  tmp = ep->name + strlen (ep->name);
99  }
100 
101  /* direction-restriction: "..in-..", "out-.." */
102  tmp--;
103  if (!isdigit (*tmp)) {
104  if (desc->bEndpointAddress & USB_DIR_IN) {
105  if ('n' != *tmp)
106  return 0;
107  } else {
108  if ('t' != *tmp)
109  return 0;
110  }
111  }
112  }
113 
114  /*
115  * Get the number of required streams from the EP companion
116  * descriptor and see if the EP matches it
117  */
118  if (usb_endpoint_xfer_bulk(desc)) {
119  if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
120  num_req_streams = ep_comp->bmAttributes & 0x1f;
121  if (num_req_streams > ep->max_streams)
122  return 0;
123  }
124 
125  }
126 
127  /*
128  * If the protocol driver hasn't yet decided on wMaxPacketSize
129  * and wants to know the maximum possible, provide the info.
130  */
131  if (desc->wMaxPacketSize == 0)
132  desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
133 
134  /* endpoint maxpacket size is an input parameter, except for bulk
135  * where it's an output parameter representing the full speed limit.
136  * the usb spec fixes high speed bulk maxpacket at 512 bytes.
137  */
138  max = 0x7ff & usb_endpoint_maxp(desc);
139  switch (type) {
141  /* INT: limit 64 bytes full speed, 1024 high/super speed */
142  if (!gadget_is_dualspeed(gadget) && max > 64)
143  return 0;
144  /* FALLTHROUGH */
145 
147  /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
148  if (ep->maxpacket < max)
149  return 0;
150  if (!gadget_is_dualspeed(gadget) && max > 1023)
151  return 0;
152 
153  /* BOTH: "high bandwidth" works only at high speed */
154  if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
155  if (!gadget_is_dualspeed(gadget))
156  return 0;
157  /* configure your hardware with enough buffering!! */
158  }
159  break;
160  }
161 
162  /* MATCH!! */
163 
164  /* report address */
165  desc->bEndpointAddress &= USB_DIR_IN;
166  if (isdigit (ep->name [2])) {
167  u8 num = simple_strtoul (&ep->name [2], NULL, 10);
168  desc->bEndpointAddress |= num;
169  } else if (desc->bEndpointAddress & USB_DIR_IN) {
170  if (++gadget->in_epnum > 15)
171  return 0;
172  desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
173  } else {
174  if (++gadget->out_epnum > 15)
175  return 0;
176  desc->bEndpointAddress |= gadget->out_epnum;
177  }
178 
179  /* report (variable) full speed bulk maxpacket */
180  if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
181  int size = ep->maxpacket;
182 
183  /* min() doesn't work on bitfields with gcc-3.5 */
184  if (size > 64)
185  size = 64;
186  desc->wMaxPacketSize = cpu_to_le16(size);
187  }
188  ep->address = desc->bEndpointAddress;
189  return 1;
190 }
191 
192 static struct usb_ep *
193 find_ep (struct usb_gadget *gadget, const char *name)
194 {
195  struct usb_ep *ep;
196 
197  list_for_each_entry (ep, &gadget->ep_list, ep_list) {
198  if (0 == strcmp (ep->name, name))
199  return ep;
200  }
201  return NULL;
202 }
203 
249  struct usb_gadget *gadget,
250  struct usb_endpoint_descriptor *desc,
251  struct usb_ss_ep_comp_descriptor *ep_comp
252 )
253 {
254  struct usb_ep *ep;
255  u8 type;
256 
258 
259  /* First, apply chip-specific "best usage" knowledge.
260  * This might make a good usb_gadget_ops hook ...
261  */
262  if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
263  /* ep-e, ep-f are PIO with only 64 byte fifos */
264  ep = find_ep (gadget, "ep-e");
265  if (ep && ep_matches(gadget, ep, desc, ep_comp))
266  goto found_ep;
267  ep = find_ep (gadget, "ep-f");
268  if (ep && ep_matches(gadget, ep, desc, ep_comp))
269  goto found_ep;
270 
271  } else if (gadget_is_goku (gadget)) {
272  if (USB_ENDPOINT_XFER_INT == type) {
273  /* single buffering is enough */
274  ep = find_ep(gadget, "ep3-bulk");
275  if (ep && ep_matches(gadget, ep, desc, ep_comp))
276  goto found_ep;
277  } else if (USB_ENDPOINT_XFER_BULK == type
278  && (USB_DIR_IN & desc->bEndpointAddress)) {
279  /* DMA may be available */
280  ep = find_ep(gadget, "ep2-bulk");
281  if (ep && ep_matches(gadget, ep, desc,
282  ep_comp))
283  goto found_ep;
284  }
285 
286 #ifdef CONFIG_BLACKFIN
287  } else if (gadget_is_musbhdrc(gadget)) {
288  if ((USB_ENDPOINT_XFER_BULK == type) ||
289  (USB_ENDPOINT_XFER_ISOC == type)) {
290  if (USB_DIR_IN & desc->bEndpointAddress)
291  ep = find_ep (gadget, "ep5in");
292  else
293  ep = find_ep (gadget, "ep6out");
294  } else if (USB_ENDPOINT_XFER_INT == type) {
295  if (USB_DIR_IN & desc->bEndpointAddress)
296  ep = find_ep(gadget, "ep1in");
297  else
298  ep = find_ep(gadget, "ep2out");
299  } else
300  ep = NULL;
301  if (ep && ep_matches(gadget, ep, desc, ep_comp))
302  goto found_ep;
303 #endif
304  }
305 
306  /* Second, look at endpoints until an unclaimed one looks usable */
307  list_for_each_entry (ep, &gadget->ep_list, ep_list) {
308  if (ep_matches(gadget, ep, desc, ep_comp))
309  goto found_ep;
310  }
311 
312  /* Fail */
313  return NULL;
314 found_ep:
315  ep->desc = NULL;
316  ep->comp_desc = NULL;
317  return ep;
318 }
320 
353  struct usb_gadget *gadget,
354  struct usb_endpoint_descriptor *desc
355 )
356 {
357  return usb_ep_autoconfig_ss(gadget, desc, NULL);
358 }
360 
370 void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
371 {
372  struct usb_ep *ep;
373 
374  list_for_each_entry (ep, &gadget->ep_list, ep_list) {
375  ep->driver_data = NULL;
376  }
377  gadget->in_epnum = 0;
378  gadget->out_epnum = 0;
379 }