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