]>
Commit | Line | Data |
---|---|---|
1 | //----------------------------------------------------------------------------- | |
2 | // Jonathan Westhues, split Aug 14 2005 | |
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. | |
7 | //----------------------------------------------------------------------------- | |
8 | // The common USB driver used for both the bootloader and the application. | |
9 | //----------------------------------------------------------------------------- | |
10 | ||
11 | #include "proxmark3.h" | |
12 | ||
13 | #define min(a, b) (((a) > (b)) ? (b) : (a)) | |
14 | ||
15 | #define USB_REPORT_PACKET_SIZE 64 | |
16 | ||
17 | typedef struct PACKED { | |
18 | uint8_t bmRequestType; | |
19 | uint8_t bRequest; | |
20 | uint16_t wValue; | |
21 | uint16_t wIndex; | |
22 | uint16_t wLength; | |
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 | ||
50 | static const uint8_t HidReportDescriptor[] = { | |
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 | ||
85 | static const uint8_t DeviceDescriptor[] = { | |
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 | |
98 | 0x00, // Serial Number string descriptor index (None) | |
99 | 0x01, // Number of possible configurations (1) | |
100 | }; | |
101 | ||
102 | static const uint8_t ConfigurationDescriptor[] = { | |
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 | ||
150 | static const uint8_t StringDescriptor0[] = { | |
151 | 0x04, // Length | |
152 | 0x03, // Type is string | |
153 | 0x09, // English | |
154 | 0x04, // US | |
155 | }; | |
156 | ||
157 | static const uint8_t StringDescriptor1[] = { | |
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 | ||
173 | static const uint8_t StringDescriptor2[] = { | |
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 | ||
204 | static const uint8_t * const StringDescriptors[] = { | |
205 | StringDescriptor0, | |
206 | StringDescriptor1, | |
207 | StringDescriptor2, | |
208 | }; | |
209 | ||
210 | ||
211 | static uint8_t UsbBuffer[64]; | |
212 | static int UsbSoFarCount; | |
213 | ||
214 | static uint8_t CurrentConfiguration; | |
215 | ||
216 | static void UsbSendEp0(const uint8_t *data, int len) | |
217 | { | |
218 | int thisTime, i; | |
219 | ||
220 | do { | |
221 | thisTime = min(len, 8); | |
222 | len -= thisTime; | |
223 | ||
224 | for(i = 0; i < thisTime; i++) { | |
225 | AT91C_BASE_UDP->UDP_FDR[0] = *data; | |
226 | data++; | |
227 | } | |
228 | ||
229 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) { | |
230 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP; | |
231 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) | |
232 | ; | |
233 | } | |
234 | ||
235 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; | |
236 | ||
237 | do { | |
238 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) { | |
239 | // This means that the host is trying to write to us, so | |
240 | // abandon our write to them. | |
241 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0; | |
242 | return; | |
243 | } | |
244 | } while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)); | |
245 | } while(len > 0); | |
246 | ||
247 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) { | |
248 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP; | |
249 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) | |
250 | ; | |
251 | } | |
252 | } | |
253 | ||
254 | static void UsbSendZeroLength(void) | |
255 | { | |
256 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; | |
257 | ||
258 | while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)) | |
259 | ; | |
260 | ||
261 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP; | |
262 | ||
263 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) | |
264 | ; | |
265 | } | |
266 | ||
267 | static void UsbSendStall(void) | |
268 | { | |
269 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_FORCESTALL; | |
270 | ||
271 | while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT)) | |
272 | ; | |
273 | ||
274 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_STALLSENT; | |
275 | ||
276 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT) | |
277 | ; | |
278 | } | |
279 | ||
280 | static void HandleRxdSetupData(void) | |
281 | { | |
282 | int i; | |
283 | UsbSetupData usd; | |
284 | ||
285 | for(i = 0; i < sizeof(usd); i++) { | |
286 | ((uint8_t *)&usd)[i] = AT91C_BASE_UDP->UDP_FDR[0]; | |
287 | } | |
288 | ||
289 | if(usd.bmRequestType & 0x80) { | |
290 | AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR; | |
291 | while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_DIR)) | |
292 | ; | |
293 | } | |
294 | ||
295 | AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP; | |
296 | while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) | |
297 | ; | |
298 | ||
299 | switch(usd.bRequest) { | |
300 | case USB_REQUEST_GET_DESCRIPTOR: | |
301 | if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) { | |
302 | UsbSendEp0((uint8_t *)&DeviceDescriptor, | |
303 | min(sizeof(DeviceDescriptor), usd.wLength)); | |
304 | } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) { | |
305 | UsbSendEp0((uint8_t *)&ConfigurationDescriptor, | |
306 | min(sizeof(ConfigurationDescriptor), usd.wLength)); | |
307 | } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) { | |
308 | const uint8_t *s = StringDescriptors[usd.wValue & 0xff]; | |
309 | UsbSendEp0(s, min(s[0], usd.wLength)); | |
310 | } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) { | |
311 | UsbSendEp0((uint8_t *)&HidReportDescriptor, | |
312 | min(sizeof(HidReportDescriptor), usd.wLength)); | |
313 | } else { | |
314 | *((uint32_t *)0x00200000) = usd.wValue; | |
315 | } | |
316 | break; | |
317 | ||
318 | case USB_REQUEST_SET_ADDRESS: | |
319 | UsbSendZeroLength(); | |
320 | AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | usd.wValue ; | |
321 | if(usd.wValue != 0) { | |
322 | AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN; | |
323 | } else { | |
324 | AT91C_BASE_UDP->UDP_GLBSTATE = 0; | |
325 | } | |
326 | break; | |
327 | ||
328 | case USB_REQUEST_GET_CONFIGURATION: | |
329 | UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration)); | |
330 | break; | |
331 | ||
332 | case USB_REQUEST_GET_STATUS: { | |
333 | if(usd.bmRequestType & 0x80) { | |
334 | uint16_t w = 0; | |
335 | UsbSendEp0((uint8_t *)&w, sizeof(w)); | |
336 | } | |
337 | break; | |
338 | } | |
339 | case USB_REQUEST_SET_CONFIGURATION: | |
340 | CurrentConfiguration = usd.wValue; | |
341 | if(CurrentConfiguration) { | |
342 | AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG; | |
343 | AT91C_BASE_UDP->UDP_CSR[1] = AT91C_UDP_EPEDS | | |
344 | AT91C_UDP_EPTYPE_INT_OUT; | |
345 | AT91C_BASE_UDP->UDP_CSR[2] = AT91C_UDP_EPEDS | | |
346 | AT91C_UDP_EPTYPE_INT_IN; | |
347 | } else { | |
348 | AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN; | |
349 | AT91C_BASE_UDP->UDP_CSR[1] = 0; | |
350 | AT91C_BASE_UDP->UDP_CSR[2] = 0; | |
351 | } | |
352 | UsbSendZeroLength(); | |
353 | break; | |
354 | ||
355 | case USB_REQUEST_GET_INTERFACE: { | |
356 | uint8_t b = 0; | |
357 | UsbSendEp0(&b, sizeof(b)); | |
358 | break; | |
359 | } | |
360 | ||
361 | case USB_REQUEST_SET_INTERFACE: | |
362 | UsbSendZeroLength(); | |
363 | break; | |
364 | ||
365 | case USB_REQUEST_CLEAR_FEATURE: | |
366 | case USB_REQUEST_SET_FEATURE: | |
367 | UsbSendStall(); | |
368 | break; | |
369 | case USB_REQUEST_SET_DESCRIPTOR: | |
370 | case USB_REQUEST_SYNC_FRAME: | |
371 | default: | |
372 | break; | |
373 | } | |
374 | } | |
375 | ||
376 | void UsbSendPacket(uint8_t *packet, int len) | |
377 | { | |
378 | int i, thisTime; | |
379 | ||
380 | while(len > 0) { | |
381 | thisTime = min(len, 8); | |
382 | ||
383 | for(i = 0; i < thisTime; i++) { | |
384 | AT91C_BASE_UDP->UDP_FDR[2] = packet[i]; | |
385 | } | |
386 | AT91C_BASE_UDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY; | |
387 | ||
388 | while(!(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP)) | |
389 | ; | |
390 | AT91C_BASE_UDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP; | |
391 | ||
392 | while(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP) | |
393 | ; | |
394 | ||
395 | len -= thisTime; | |
396 | packet += thisTime; | |
397 | } | |
398 | } | |
399 | ||
400 | static void HandleRxdData(void) | |
401 | { | |
402 | int i, len; | |
403 | ||
404 | if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) { | |
405 | len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]); | |
406 | ||
407 | for(i = 0; i < len; i++) { | |
408 | UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1]; | |
409 | UsbSoFarCount++; | |
410 | } | |
411 | ||
412 | AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK0; | |
413 | while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) | |
414 | ; | |
415 | ||
416 | if(UsbSoFarCount >= 64) { | |
417 | UsbPacketReceived(UsbBuffer, UsbSoFarCount); | |
418 | UsbSoFarCount = 0; | |
419 | } | |
420 | } | |
421 | ||
422 | if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) { | |
423 | len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]); | |
424 | ||
425 | for(i = 0; i < len; i++) { | |
426 | UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1]; | |
427 | UsbSoFarCount++; | |
428 | } | |
429 | ||
430 | AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK1; | |
431 | while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) | |
432 | ; | |
433 | ||
434 | if(UsbSoFarCount >= 64) { | |
435 | UsbPacketReceived(UsbBuffer, UsbSoFarCount); | |
436 | UsbSoFarCount = 0; | |
437 | } | |
438 | } | |
439 | } | |
440 | ||
441 | void UsbStart(void) | |
442 | { | |
443 | volatile int i; | |
444 | ||
445 | UsbSoFarCount = 0; | |
446 | ||
447 | USB_D_PLUS_PULLUP_OFF(); | |
448 | ||
449 | for(i = 0; i < 1000000; i++) | |
450 | ; | |
451 | ||
452 | USB_D_PLUS_PULLUP_ON(); | |
453 | ||
454 | if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) { | |
455 | AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES; | |
456 | } | |
457 | } | |
458 | ||
459 | int UsbConnected() | |
460 | { | |
461 | if (AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG) | |
462 | return TRUE; | |
463 | else | |
464 | return FALSE; | |
465 | } | |
466 | ||
467 | int UsbPoll(int blinkLeds) | |
468 | { | |
469 | int ret = FALSE; | |
470 | ||
471 | if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) { | |
472 | AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES; | |
473 | ||
474 | // following a reset we should be ready to receive a setup packet | |
475 | AT91C_BASE_UDP->UDP_RSTEP = 0xf; | |
476 | AT91C_BASE_UDP->UDP_RSTEP = 0; | |
477 | ||
478 | AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN; | |
479 | ||
480 | AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS; | |
481 | ||
482 | CurrentConfiguration = 0; | |
483 | ||
484 | ret = TRUE; | |
485 | } | |
486 | ||
487 | if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(0)) { | |
488 | if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) { | |
489 | HandleRxdSetupData(); | |
490 | ret = TRUE; | |
491 | } | |
492 | } | |
493 | ||
494 | if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(1)) { | |
495 | HandleRxdData(); | |
496 | ret = TRUE; | |
497 | } | |
498 | ||
499 | return ret; | |
500 | } |