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