]>
Commit | Line | Data |
---|---|---|
fdcc61d3 | 1 | //----------------------------------------------------------------------------- |
fdcc61d3 | 2 | // Jonathan Westhues, split Aug 14 2005 |
bd20f8f4 | 3 | // |
4 | // This code is licensed to you under the terms of the GNU GPL, version 2 or, | |
5 | // at your option, any later version. See the LICENSE.txt file for the text of | |
6 | // the license. | |
fdcc61d3 | 7 | //----------------------------------------------------------------------------- |
bd20f8f4 | 8 | // The common USB driver used for both the bootloader and the application. |
9 | //----------------------------------------------------------------------------- | |
10 | ||
c1bd1140 | 11 | #include "proxmark3.h" |
fdcc61d3 | 12 | |
13 | #define min(a, b) (((a) > (b)) ? (b) : (a)) | |
14 | ||
15 | #define USB_REPORT_PACKET_SIZE 64 | |
16 | ||
17 | typedef struct PACKED { | |
f7e3ed82 | 18 | uint8_t bmRequestType; |
19 | uint8_t bRequest; | |
20 | uint16_t wValue; | |
21 | uint16_t wIndex; | |
22 | uint16_t wLength; | |
fdcc61d3 | 23 | } UsbSetupData; |
24 | ||
25 | #define USB_REQUEST_GET_STATUS 0 | |
26 | #define USB_REQUEST_CLEAR_FEATURE 1 | |
27 | #define USB_REQUEST_SET_FEATURE 3 | |
28 | #define USB_REQUEST_SET_ADDRESS 5 | |
29 | #define USB_REQUEST_GET_DESCRIPTOR 6 | |
30 | #define USB_REQUEST_SET_DESCRIPTOR 7 | |
31 | #define USB_REQUEST_GET_CONFIGURATION 8 | |
32 | #define USB_REQUEST_SET_CONFIGURATION 9 | |
33 | #define USB_REQUEST_GET_INTERFACE 10 | |
34 | #define USB_REQUEST_SET_INTERFACE 11 | |
35 | #define USB_REQUEST_SYNC_FRAME 12 | |
36 | ||
37 | #define USB_DESCRIPTOR_TYPE_DEVICE 1 | |
38 | #define USB_DESCRIPTOR_TYPE_CONFIGURATION 2 | |
39 | #define USB_DESCRIPTOR_TYPE_STRING 3 | |
40 | #define USB_DESCRIPTOR_TYPE_INTERFACE 4 | |
41 | #define USB_DESCRIPTOR_TYPE_ENDPOINT 5 | |
42 | #define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 6 | |
43 | #define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONF 7 | |
44 | #define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 8 | |
45 | #define USB_DESCRIPTOR_TYPE_HID 0x21 | |
46 | #define USB_DESCRIPTOR_TYPE_HID_REPORT 0x22 | |
47 | ||
48 | #define USB_DEVICE_CLASS_HID 0x03 | |
49 | ||
f7e3ed82 | 50 | static const uint8_t HidReportDescriptor[] = { |
fdcc61d3 | 51 | 0x06,0xA0,0xFF, // Usage Page (vendor defined) FFA0 |
52 | 0x09,0x01, // Usage (vendor defined) | |
53 | 0xA1,0x01, // Collection (Application) | |
54 | 0x09,0x02, // Usage (vendor defined) | |
55 | 0xA1,0x00, // Collection (Physical) | |
56 | 0x06,0xA1,0xFF, // Usage Page (vendor defined) | |
57 | ||
58 | //The,input report | |
59 | 0x09,0x03, // usage - vendor defined | |
60 | 0x09,0x04, // usage - vendor defined | |
61 | 0x15,0x80, // Logical Minimum (-128) | |
62 | 0x25,0x7F, // Logical Maximum (127) | |
63 | 0x35,0x00, // Physical Minimum (0) | |
64 | 0x45,0xFF, // Physical Maximum (255) | |
65 | 0x75,0x08, // Report Size (8) (bits) | |
66 | 0x95,0x40, // Report Count (64) (fields) | |
67 | 0x81,0x02, // Input (Data,Variable,Absolute) | |
68 | ||
69 | //The,output report | |
70 | 0x09,0x05, // usage - vendor defined | |
71 | 0x09,0x06, // usage - vendor defined | |
72 | 0x15,0x80, // Logical Minimum (-128) | |
73 | 0x25,0x7F, // Logical Maximum (127) | |
74 | 0x35,0x00, // Physical Minimum (0) | |
75 | 0x45,0xFF, // Physical Maximum (255) | |
76 | 0x75,0x08, // Report Size (8) (bits) | |
77 | 0x95,0x40, // Report Count (64) (fields) | |
78 | 0x91,0x02, // Output (Data,Variable,Absolute) | |
79 | ||
80 | 0xC0, // End Collection | |
81 | ||
82 | 0xC0, // End Collection | |
83 | }; | |
84 | ||
f7e3ed82 | 85 | static const uint8_t DeviceDescriptor[] = { |
fdcc61d3 | 86 | 0x12, // Descriptor length (18 bytes) |
87 | 0x01, // Descriptor type (Device) | |
88 | 0x10,0x01, // Complies with USB Spec. Release (0110h = release 1.10) | |
89 | 0x00, // Class code (0) | |
90 | 0x00, // Subclass code (0) | |
91 | 0x00, // Protocol (No specific protocol) | |
92 | 0x08, // Maximum packet size for Endpoint 0 (8 bytes) | |
93 | 0xc4,0x9a, // Vendor ID (random numbers) | |
94 | 0x8f,0x4b, // Product ID (random numbers) | |
95 | 0x01,0x00, // Device release number (0001) | |
96 | 0x01, // Manufacturer string descriptor index | |
97 | 0x02, // Product string descriptor index | |
602ac4d7 | 98 | 0x03, // Serial Number string descriptor index |
fdcc61d3 | 99 | 0x01, // Number of possible configurations (1) |
100 | }; | |
101 | ||
f7e3ed82 | 102 | static const uint8_t ConfigurationDescriptor[] = { |
fdcc61d3 | 103 | 0x09, // Descriptor length (9 bytes) |
104 | 0x02, // Descriptor type (Configuration) | |
105 | 0x29,0x00, // Total data length (41 bytes) | |
106 | 0x01, // Interface supported (1) | |
107 | 0x01, // Configuration value (1) | |
108 | 0x00, // Index of string descriptor (None) | |
109 | 0x80, // Configuration (Bus powered) | |
110 | 250, // Maximum power consumption (500mA) | |
111 | ||
112 | //interface | |
113 | 0x09, // Descriptor length (9 bytes) | |
114 | 0x04, // Descriptor type (Interface) | |
115 | 0x00, // Number of interface (0) | |
116 | 0x00, // Alternate setting (0) | |
117 | 0x02, // Number of interface endpoint (2) | |
118 | 0x03, // Class code (HID) | |
119 | 0x00, // Subclass code () | |
120 | 0x00, // Protocol code () | |
121 | 0x00, // Index of string() | |
122 | ||
123 | // class | |
124 | 0x09, // Descriptor length (9 bytes) | |
125 | 0x21, // Descriptor type (HID) | |
126 | 0x00,0x01, // HID class release number (1.00) | |
127 | 0x00, // Localized country code (None) | |
128 | 0x01, // # of HID class dscrptr to follow (1) | |
129 | 0x22, // Report descriptor type (HID) | |
130 | // Total length of report descriptor | |
131 | sizeof(HidReportDescriptor),0x00, | |
132 | ||
133 | // endpoint 1 | |
134 | 0x07, // Descriptor length (7 bytes) | |
135 | 0x05, // Descriptor type (Endpoint) | |
136 | 0x01, // Encoded address (Respond to OUT) | |
137 | 0x03, // Endpoint attribute (Interrupt transfer) | |
138 | 0x08,0x00, // Maximum packet size (8 bytes) | |
139 | 0x01, // Polling interval (1 ms) | |
140 | ||
141 | // endpoint 2 | |
142 | 0x07, // Descriptor length (7 bytes) | |
143 | 0x05, // Descriptor type (Endpoint) | |
144 | 0x82, // Encoded address (Respond to IN) | |
145 | 0x03, // Endpoint attribute (Interrupt transfer) | |
146 | 0x08,0x00, // Maximum packet size (8 bytes) | |
147 | 0x01, // Polling interval (1 ms) | |
148 | }; | |
149 | ||
f7e3ed82 | 150 | static const uint8_t StringDescriptor0[] = { |
fdcc61d3 | 151 | 0x04, // Length |
152 | 0x03, // Type is string | |
153 | 0x09, // English | |
154 | 0x04, // US | |
155 | }; | |
156 | ||
f7e3ed82 | 157 | static const uint8_t StringDescriptor1[] = { |
fdcc61d3 | 158 | 24, // Length |
159 | 0x03, // Type is string | |
160 | 'J', 0x00, | |
161 | '.', 0x00, | |
162 | ' ', 0x00, | |
163 | 'W', 0x00, | |
164 | 'e', 0x00, | |
165 | 's', 0x00, | |
166 | 't', 0x00, | |
167 | 'h', 0x00, | |
168 | 'u', 0x00, | |
169 | 'e', 0x00, | |
170 | 's', 0x00, | |
171 | }; | |
172 | ||
f7e3ed82 | 173 | static const uint8_t StringDescriptor2[] = { |
fdcc61d3 | 174 | 54, // Length |
175 | 0x03, // Type is string | |
176 | 'P', 0x00, | |
177 | 'r', 0x00, | |
178 | 'o', 0x00, | |
179 | 'x', 0x00, | |
180 | 'M', 0x00, | |
181 | 'a', 0x00, | |
182 | 'r', 0x00, | |
183 | 'k', 0x00, | |
184 | '-', 0x00, | |
185 | '3', 0x00, | |
186 | ' ', 0x00, | |
187 | 'R', 0x00, | |
188 | 'F', 0x00, | |
189 | 'I', 0x00, | |
190 | 'D', 0x00, | |
191 | ' ', 0x00, | |
192 | 'I', 0x00, | |
193 | 'n', 0x00, | |
194 | 's', 0x00, | |
195 | 't', 0x00, | |
196 | 'r', 0x00, | |
197 | 'u', 0x00, | |
198 | 'm', 0x00, | |
199 | 'e', 0x00, | |
200 | 'n', 0x00, | |
201 | 't', 0x00, | |
202 | }; | |
203 | ||
602ac4d7 | 204 | // Serial Number |
205 | // TODO: Pick yours! Don't forget to modify the length, if needed. | |
206 | static const uint8_t StringDescriptor3[] = { | |
207 | 18, // Length | |
208 | 0x03, // Type is string | |
209 | 'C', 0x00, | |
210 | 'h', 0x00, | |
211 | 'a', 0x00, | |
212 | 'n', 0x00, | |
213 | 'g', 0x00, | |
214 | 'e', 0x00, | |
215 | 'M', 0x00, | |
216 | 'e', 0x00, | |
217 | }; | |
218 | ||
f7e3ed82 | 219 | static const uint8_t * const StringDescriptors[] = { |
fdcc61d3 | 220 | StringDescriptor0, |
221 | StringDescriptor1, | |
222 | StringDescriptor2, | |
602ac4d7 | 223 | StringDescriptor3, |
fdcc61d3 | 224 | }; |
225 | ||
226 | ||
f7e3ed82 | 227 | static uint8_t UsbBuffer[64]; |
fdcc61d3 | 228 | static int UsbSoFarCount; |
229 | ||
f7e3ed82 | 230 | static uint8_t CurrentConfiguration; |
fdcc61d3 | 231 | |
f7e3ed82 | 232 | static void UsbSendEp0(const uint8_t *data, int len) |
fdcc61d3 | 233 | { |
234 | int thisTime, i; | |
235 | ||
236 | do { | |
237 | thisTime = min(len, 8); | |
238 | len -= thisTime; | |
239 | ||
240 | for(i = 0; i < thisTime; i++) { | |
241 | AT91C_BASE_UDP->UDP_FDR[0] = *data; | |
242 | data++; | |
243 | } | |
244 | ||
245 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) { | |
246 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP; | |
247 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) | |
248 | ; | |
249 | } | |
250 | ||
251 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; | |
252 | ||
253 | do { | |
254 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) { | |
255 | // This means that the host is trying to write to us, so | |
256 | // abandon our write to them. | |
257 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0; | |
258 | return; | |
259 | } | |
260 | } while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)); | |
261 | } while(len > 0); | |
262 | ||
263 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) { | |
264 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP; | |
265 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) | |
266 | ; | |
267 | } | |
268 | } | |
269 | ||
270 | static void UsbSendZeroLength(void) | |
271 | { | |
272 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; | |
273 | ||
274 | while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)) | |
275 | ; | |
276 | ||
277 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP; | |
278 | ||
279 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) | |
280 | ; | |
281 | } | |
282 | ||
283 | static void UsbSendStall(void) | |
284 | { | |
285 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_FORCESTALL; | |
286 | ||
287 | while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT)) | |
288 | ; | |
289 | ||
290 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_STALLSENT; | |
291 | ||
292 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT) | |
293 | ; | |
294 | } | |
295 | ||
296 | static void HandleRxdSetupData(void) | |
297 | { | |
298 | int i; | |
299 | UsbSetupData usd; | |
300 | ||
301 | for(i = 0; i < sizeof(usd); i++) { | |
f7e3ed82 | 302 | ((uint8_t *)&usd)[i] = AT91C_BASE_UDP->UDP_FDR[0]; |
fdcc61d3 | 303 | } |
304 | ||
305 | if(usd.bmRequestType & 0x80) { | |
306 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR; | |
307 | while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_DIR)) | |
308 | ; | |
309 | } | |
310 | ||
311 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP; | |
312 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) | |
313 | ; | |
314 | ||
315 | switch(usd.bRequest) { | |
316 | case USB_REQUEST_GET_DESCRIPTOR: | |
317 | if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) { | |
f7e3ed82 | 318 | UsbSendEp0((uint8_t *)&DeviceDescriptor, |
fdcc61d3 | 319 | min(sizeof(DeviceDescriptor), usd.wLength)); |
320 | } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) { | |
f7e3ed82 | 321 | UsbSendEp0((uint8_t *)&ConfigurationDescriptor, |
fdcc61d3 | 322 | min(sizeof(ConfigurationDescriptor), usd.wLength)); |
323 | } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) { | |
f7e3ed82 | 324 | const uint8_t *s = StringDescriptors[usd.wValue & 0xff]; |
fdcc61d3 | 325 | UsbSendEp0(s, min(s[0], usd.wLength)); |
326 | } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) { | |
f7e3ed82 | 327 | UsbSendEp0((uint8_t *)&HidReportDescriptor, |
fdcc61d3 | 328 | min(sizeof(HidReportDescriptor), usd.wLength)); |
329 | } else { | |
f7e3ed82 | 330 | *((uint32_t *)0x00200000) = usd.wValue; |
fdcc61d3 | 331 | } |
332 | break; | |
333 | ||
334 | case USB_REQUEST_SET_ADDRESS: | |
335 | UsbSendZeroLength(); | |
336 | AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | usd.wValue ; | |
337 | if(usd.wValue != 0) { | |
338 | AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN; | |
339 | } else { | |
340 | AT91C_BASE_UDP->UDP_GLBSTATE = 0; | |
341 | } | |
342 | break; | |
343 | ||
344 | case USB_REQUEST_GET_CONFIGURATION: | |
345 | UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration)); | |
346 | break; | |
347 | ||
348 | case USB_REQUEST_GET_STATUS: { | |
349 | if(usd.bmRequestType & 0x80) { | |
f7e3ed82 | 350 | uint16_t w = 0; |
351 | UsbSendEp0((uint8_t *)&w, sizeof(w)); | |
fdcc61d3 | 352 | } |
353 | break; | |
354 | } | |
355 | case USB_REQUEST_SET_CONFIGURATION: | |
356 | CurrentConfiguration = usd.wValue; | |
357 | if(CurrentConfiguration) { | |
358 | AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG; | |
359 | AT91C_BASE_UDP->UDP_CSR[1] = AT91C_UDP_EPEDS | | |
360 | AT91C_UDP_EPTYPE_INT_OUT; | |
361 | AT91C_BASE_UDP->UDP_CSR[2] = AT91C_UDP_EPEDS | | |
362 | AT91C_UDP_EPTYPE_INT_IN; | |
363 | } else { | |
364 | AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN; | |
365 | AT91C_BASE_UDP->UDP_CSR[1] = 0; | |
366 | AT91C_BASE_UDP->UDP_CSR[2] = 0; | |
367 | } | |
368 | UsbSendZeroLength(); | |
369 | break; | |
370 | ||
371 | case USB_REQUEST_GET_INTERFACE: { | |
f7e3ed82 | 372 | uint8_t b = 0; |
fdcc61d3 | 373 | UsbSendEp0(&b, sizeof(b)); |
374 | break; | |
375 | } | |
376 | ||
377 | case USB_REQUEST_SET_INTERFACE: | |
378 | UsbSendZeroLength(); | |
379 | break; | |
380 | ||
381 | case USB_REQUEST_CLEAR_FEATURE: | |
382 | case USB_REQUEST_SET_FEATURE: | |
383 | UsbSendStall(); | |
384 | break; | |
385 | case USB_REQUEST_SET_DESCRIPTOR: | |
386 | case USB_REQUEST_SYNC_FRAME: | |
387 | default: | |
388 | break; | |
389 | } | |
390 | } | |
391 | ||
f7e3ed82 | 392 | void UsbSendPacket(uint8_t *packet, int len) |
fdcc61d3 | 393 | { |
394 | int i, thisTime; | |
395 | ||
396 | while(len > 0) { | |
397 | thisTime = min(len, 8); | |
398 | ||
399 | for(i = 0; i < thisTime; i++) { | |
400 | AT91C_BASE_UDP->UDP_FDR[2] = packet[i]; | |
401 | } | |
402 | AT91C_BASE_UDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY; | |
403 | ||
404 | while(!(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP)) | |
405 | ; | |
406 | AT91C_BASE_UDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP; | |
407 | ||
408 | while(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP) | |
409 | ; | |
410 | ||
411 | len -= thisTime; | |
412 | packet += thisTime; | |
413 | } | |
414 | } | |
415 | ||
416 | static void HandleRxdData(void) | |
417 | { | |
418 | int i, len; | |
419 | ||
420 | if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) { | |
421 | len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]); | |
422 | ||
423 | for(i = 0; i < len; i++) { | |
424 | UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1]; | |
425 | UsbSoFarCount++; | |
426 | } | |
427 | ||
428 | AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK0; | |
429 | while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) | |
430 | ; | |
431 | ||
432 | if(UsbSoFarCount >= 64) { | |
433 | UsbPacketReceived(UsbBuffer, UsbSoFarCount); | |
434 | UsbSoFarCount = 0; | |
435 | } | |
436 | } | |
437 | ||
438 | if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) { | |
439 | len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]); | |
440 | ||
441 | for(i = 0; i < len; i++) { | |
442 | UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1]; | |
443 | UsbSoFarCount++; | |
444 | } | |
445 | ||
446 | AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK1; | |
447 | while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) | |
448 | ; | |
449 | ||
450 | if(UsbSoFarCount >= 64) { | |
451 | UsbPacketReceived(UsbBuffer, UsbSoFarCount); | |
452 | UsbSoFarCount = 0; | |
453 | } | |
454 | } | |
455 | } | |
456 | ||
457 | void UsbStart(void) | |
458 | { | |
459 | volatile int i; | |
460 | ||
461 | UsbSoFarCount = 0; | |
462 | ||
463 | USB_D_PLUS_PULLUP_OFF(); | |
464 | ||
465 | for(i = 0; i < 1000000; i++) | |
466 | ; | |
467 | ||
468 | USB_D_PLUS_PULLUP_ON(); | |
469 | ||
470 | if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) { | |
471 | AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES; | |
472 | } | |
473 | } | |
474 | ||
f7e3ed82 | 475 | int UsbConnected() |
fdcc61d3 | 476 | { |
477 | if (AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG) | |
478 | return TRUE; | |
479 | else | |
480 | return FALSE; | |
481 | } | |
482 | ||
f7e3ed82 | 483 | int UsbPoll(int blinkLeds) |
fdcc61d3 | 484 | { |
f7e3ed82 | 485 | int ret = FALSE; |
fdcc61d3 | 486 | |
487 | if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) { | |
488 | AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES; | |
489 | ||
490 | // following a reset we should be ready to receive a setup packet | |
491 | AT91C_BASE_UDP->UDP_RSTEP = 0xf; | |
492 | AT91C_BASE_UDP->UDP_RSTEP = 0; | |
493 | ||
494 | AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN; | |
495 | ||
496 | AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS; | |
497 | ||
498 | CurrentConfiguration = 0; | |
499 | ||
500 | ret = TRUE; | |
501 | } | |
502 | ||
503 | if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(0)) { | |
504 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) { | |
505 | HandleRxdSetupData(); | |
506 | ret = TRUE; | |
507 | } | |
508 | } | |
509 | ||
510 | if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(1)) { | |
511 | HandleRxdData(); | |
512 | ret = TRUE; | |
513 | } | |
514 | ||
515 | return ret; | |
516 | } |