]> git.zerfleddert.de Git - proxmark3-svn/blame - bootrom/usb_hid.c
fixed USB GPIO bug reported by gregy, and fixed 'hf 14a reader' command
[proxmark3-svn] / bootrom / usb_hid.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"
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
18typedef 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 51static 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 86static 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 103static 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 151static const uint8_t StringDescriptor0[] = {
fdcc61d3 152 0x04, // Length
153 0x03, // Type is string
154 0x09, // English
155 0x04, // US
156};
157
f7e3ed82 158static 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 174static 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.
207static 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 220static const uint8_t * const StringDescriptors[] = {
fdcc61d3 221 StringDescriptor0,
222 StringDescriptor1,
223 StringDescriptor2,
602ac4d7 224 StringDescriptor3,
fdcc61d3 225};
226
227
f7e3ed82 228static uint8_t UsbBuffer[64];
fdcc61d3 229static int UsbSoFarCount;
230
f7e3ed82 231static uint8_t CurrentConfiguration;
fdcc61d3 232
f7e3ed82 233static 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
271static 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
284static 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
297static 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 393void 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
420static 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
465void 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 483int UsbConnected()
fdcc61d3 484{
485 if (AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG)
486 return TRUE;
487 else
488 return FALSE;
489}
490
f7e3ed82 491int 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}
Impressum, Datenschutz