1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/types.h>
25#include <linux/device.h>
26
27#include <linux/ctype.h>
28#include <linux/string.h>
29
30#include <linux/usb/ch9.h>
31#include <linux/usb/gadget.h>
32
33#include "gadget_chips.h"
34
35
36
37static unsigned epnum;
38
39
40#ifdef MANY_ENDPOINTS
41
42static unsigned in_epnum;
43#endif
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62static int
63ep_matches (
64 struct usb_gadget *gadget,
65 struct usb_ep *ep,
66 struct usb_endpoint_descriptor *desc
67)
68{
69 u8 type;
70 const char *tmp;
71 u16 max;
72
73
74 if (NULL != ep->driver_data)
75 return 0;
76
77
78 type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
79 if (USB_ENDPOINT_XFER_CONTROL == type)
80 return 0;
81
82
83 if ('e' != ep->name[0])
84 return 0;
85
86
87
88
89 if ('-' != ep->name[2]) {
90 tmp = strrchr (ep->name, '-');
91 if (tmp) {
92 switch (type) {
93 case USB_ENDPOINT_XFER_INT:
94
95
96
97 if ('s' == tmp[2])
98 return 0;
99
100
101
102 if (gadget_is_pxa (gadget)
103 && 'i' == tmp [1])
104 return 0;
105 break;
106 case USB_ENDPOINT_XFER_BULK:
107 if ('b' != tmp[1])
108 return 0;
109 break;
110 case USB_ENDPOINT_XFER_ISOC:
111 if ('s' != tmp[2])
112 return 0;
113 }
114 } else {
115 tmp = ep->name + strlen (ep->name);
116 }
117
118
119 tmp--;
120 if (!isdigit (*tmp)) {
121 if (desc->bEndpointAddress & USB_DIR_IN) {
122 if ('n' != *tmp)
123 return 0;
124 } else {
125 if ('t' != *tmp)
126 return 0;
127 }
128 }
129 }
130
131
132
133
134
135 max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
136 switch (type) {
137 case USB_ENDPOINT_XFER_INT:
138
139 if (!gadget->is_dualspeed && max > 64)
140 return 0;
141
142
143 case USB_ENDPOINT_XFER_ISOC:
144
145 if (ep->maxpacket < max)
146 return 0;
147 if (!gadget->is_dualspeed && max > 1023)
148 return 0;
149
150
151 if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
152 if (!gadget->is_dualspeed)
153 return 0;
154
155 }
156 break;
157 }
158
159
160
161
162 desc->bEndpointAddress &= USB_DIR_IN;
163 if (isdigit (ep->name [2])) {
164 u8 num = simple_strtoul (&ep->name [2], NULL, 10);
165 desc->bEndpointAddress |= num;
166#ifdef MANY_ENDPOINTS
167 } else if (desc->bEndpointAddress & USB_DIR_IN) {
168 if (++in_epnum > 15)
169 return 0;
170 desc->bEndpointAddress = USB_DIR_IN | in_epnum;
171#endif
172 } else {
173 if (++epnum > 15)
174 return 0;
175 desc->bEndpointAddress |= epnum;
176 }
177
178
179 if (USB_ENDPOINT_XFER_BULK == type) {
180 int size = ep->maxpacket;
181
182
183 if (size > 64)
184 size = 64;
185 desc->wMaxPacketSize = cpu_to_le16(size);
186 }
187 return 1;
188}
189
190static struct usb_ep *
191find_ep (struct usb_gadget *gadget, const char *name)
192{
193 struct usb_ep *ep;
194
195 list_for_each_entry (ep, &gadget->ep_list, ep_list) {
196 if (0 == strcmp (ep->name, name))
197 return ep;
198 }
199 return NULL;
200}
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232struct usb_ep *usb_ep_autoconfig (
233 struct usb_gadget *gadget,
234 struct usb_endpoint_descriptor *desc
235)
236{
237 struct usb_ep *ep;
238 u8 type;
239
240 type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
241
242
243
244
245 if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
246
247 ep = find_ep (gadget, "ep-e");
248 if (ep && ep_matches (gadget, ep, desc))
249 return ep;
250 ep = find_ep (gadget, "ep-f");
251 if (ep && ep_matches (gadget, ep, desc))
252 return ep;
253
254 } else if (gadget_is_goku (gadget)) {
255 if (USB_ENDPOINT_XFER_INT == type) {
256
257 ep = find_ep (gadget, "ep3-bulk");
258 if (ep && ep_matches (gadget, ep, desc))
259 return ep;
260 } else if (USB_ENDPOINT_XFER_BULK == type
261 && (USB_DIR_IN & desc->bEndpointAddress)) {
262
263 ep = find_ep (gadget, "ep2-bulk");
264 if (ep && ep_matches (gadget, ep, desc))
265 return ep;
266 }
267
268#ifdef CONFIG_BLACKFIN
269 } else if (gadget_is_musbhdrc(gadget)) {
270 if ((USB_ENDPOINT_XFER_BULK == type) ||
271 (USB_ENDPOINT_XFER_ISOC == type)) {
272 if (USB_DIR_IN & desc->bEndpointAddress)
273 ep = find_ep (gadget, "ep5in");
274 else
275 ep = find_ep (gadget, "ep6out");
276 } else if (USB_ENDPOINT_XFER_INT == type) {
277 if (USB_DIR_IN & desc->bEndpointAddress)
278 ep = find_ep(gadget, "ep1in");
279 else
280 ep = find_ep(gadget, "ep2out");
281 } else
282 ep = NULL;
283 if (ep && ep_matches (gadget, ep, desc))
284 return ep;
285#endif
286 }
287
288
289 list_for_each_entry (ep, &gadget->ep_list, ep_list) {
290 if (ep_matches (gadget, ep, desc))
291 return ep;
292 }
293
294
295 return NULL;
296}
297
298
299
300
301
302
303
304
305
306
307void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
308{
309 struct usb_ep *ep;
310
311 list_for_each_entry (ep, &gadget->ep_list, ep_list) {
312 ep->driver_data = NULL;
313 }
314#ifdef MANY_ENDPOINTS
315 in_epnum = 0;
316#endif
317 epnum = 0;
318}
319
320