]> cvs.zerfleddert.de Git - proxmark3-svn/blame - common/usb.c
fixed windows compile
[proxmark3-svn] / common / usb.c
CommitLineData
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
17typedef 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 50static 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 85static 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 102static 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 150static const uint8_t StringDescriptor0[] = {
fdcc61d3 151 0x04, // Length
152 0x03, // Type is string
153 0x09, // English
154 0x04, // US
155};
156
f7e3ed82 157static 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 173static 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.
206static 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 219static const uint8_t * const StringDescriptors[] = {
fdcc61d3 220 StringDescriptor0,
221 StringDescriptor1,
222 StringDescriptor2,
602ac4d7 223 StringDescriptor3,
fdcc61d3 224};
225
226
f7e3ed82 227static uint8_t UsbBuffer[64];
fdcc61d3 228static int UsbSoFarCount;
229
f7e3ed82 230static uint8_t CurrentConfiguration;
fdcc61d3 231
f7e3ed82 232static 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
270static 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
283static 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
296static 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 392void 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
d19929cb 404 while(!(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP)) {
405 WDT_HIT();
406 }
407
fdcc61d3 408 AT91C_BASE_UDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP;
409
d19929cb 410 while(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP) {
411 WDT_HIT();
412 }
fdcc61d3 413
414 len -= thisTime;
415 packet += thisTime;
416 }
417}
418
419static void HandleRxdData(void)
420{
421 int i, len;
422
423 if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) {
424 len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]);
425
426 for(i = 0; i < len; i++) {
427 UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1];
428 UsbSoFarCount++;
429 }
430
431 AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK0;
d19929cb 432 while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) {
433 WDT_HIT();
434 }
fdcc61d3 435
436 if(UsbSoFarCount >= 64) {
437 UsbPacketReceived(UsbBuffer, UsbSoFarCount);
438 UsbSoFarCount = 0;
439 }
440 }
441
442 if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) {
443 len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]);
444
445 for(i = 0; i < len; i++) {
446 UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1];
447 UsbSoFarCount++;
448 }
449
450 AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK1;
d19929cb 451 while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) {
452 WDT_HIT();
453 }
454
fdcc61d3 455 if(UsbSoFarCount >= 64) {
456 UsbPacketReceived(UsbBuffer, UsbSoFarCount);
457 UsbSoFarCount = 0;
458 }
459 }
d19929cb 460
461 WDT_HIT();
fdcc61d3 462}
463
464void UsbStart(void)
465{
466 volatile int i;
467
468 UsbSoFarCount = 0;
469
470 USB_D_PLUS_PULLUP_OFF();
471
472 for(i = 0; i < 1000000; i++)
473 ;
474
475 USB_D_PLUS_PULLUP_ON();
476
477 if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {
478 AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
479 }
480}
481
f7e3ed82 482int UsbConnected()
fdcc61d3 483{
484 if (AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG)
485 return TRUE;
486 else
487 return FALSE;
488}
489
f7e3ed82 490int UsbPoll(int blinkLeds)
fdcc61d3 491{
f7e3ed82 492 int ret = FALSE;
fdcc61d3 493
494 if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {
495 AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
496
497 // following a reset we should be ready to receive a setup packet
498 AT91C_BASE_UDP->UDP_RSTEP = 0xf;
499 AT91C_BASE_UDP->UDP_RSTEP = 0;
500
501 AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
502
503 AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS;
504
505 CurrentConfiguration = 0;
506
507 ret = TRUE;
508 }
509
510 if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(0)) {
511 if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) {
512 HandleRxdSetupData();
513 ret = TRUE;
514 }
515 }
516
517 if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(1)) {
518 HandleRxdData();
519 ret = TRUE;
520 }
521
522 return ret;
523}
Impressum, Datenschutz