]> cvs.zerfleddert.de Git - proxmark3-svn/blame - common/usb.c
fixed an intermitent pain in the ass to track down crash in the GUI client due to...
[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
220 UDP_ENDPOINT_FIFO(0) = *data;\r
221 data++;\r
222 }\r
223\r
224 if(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED) {\r
225 UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;\r
226 while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)\r
227 ;\r
228 }\r
229\r
230 UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;\r
231\r
232 do {\r
233 if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {\r
234 // This means that the host is trying to write to us, so\r
235 // abandon our write to them.\r
236 UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;\r
237 return;\r
238 }\r
239 } while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED));\r
240 } while(len > 0);\r
241\r
242 if(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED) {\r
243 UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;\r
244 while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)\r
245 ;\r
246 }\r
247}\r
248\r
249static void UsbSendZeroLength(void)\r
250{\r
251 UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;\r
252\r
253 while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED))\r
254 ;\r
255\r
256 UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;\r
257\r
258 while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)\r
259 ;\r
260}\r
261\r
262static void HandleRxdSetupData(void)\r
263{\r
264 int i;\r
265 UsbSetupData usd;\r
266\r
267 for(i = 0; i < sizeof(usd); i++) {\r
268 ((BYTE *)&usd)[i] = UDP_ENDPOINT_FIFO(0);\r
269 }\r
270\r
271 if(usd.bmRequestType & 0x80) {\r
272 UDP_ENDPOINT_CSR(0) |= UDP_CSR_CONTROL_DATA_DIR;\r
273 while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_CONTROL_DATA_DIR))\r
274 ;\r
275 }\r
276\r
277 UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_HAVE_READ_SETUP_DATA;\r
278 while(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA)\r
279 ;\r
280\r
281 switch(usd.bRequest) {\r
282 case USB_REQUEST_GET_DESCRIPTOR:\r
283 if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) {\r
284 UsbSendEp0((BYTE *)&DeviceDescriptor,\r
285 min(sizeof(DeviceDescriptor), usd.wLength));\r
286 } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) {\r
287 UsbSendEp0((BYTE *)&ConfigurationDescriptor,\r
288 min(sizeof(ConfigurationDescriptor), usd.wLength));\r
289 } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) {\r
290 const BYTE *s = StringDescriptors[usd.wValue & 0xff];\r
291 UsbSendEp0(s, min(s[0], usd.wLength));\r
292 } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) {\r
293 UsbSendEp0((BYTE *)&HidReportDescriptor,\r
294 min(sizeof(HidReportDescriptor), usd.wLength));\r
295 } else {\r
296 *((DWORD *)0x00200000) = usd.wValue;\r
297 }\r
298 break;\r
299\r
300 case USB_REQUEST_SET_ADDRESS:\r
301 UsbSendZeroLength();\r
302 UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED | usd.wValue ;\r
303 if(usd.wValue != 0) {\r
304 UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;\r
305 } else {\r
306 UDP_GLOBAL_STATE = 0;\r
307 }\r
308 break;\r
309\r
310 case USB_REQUEST_GET_CONFIGURATION:\r
311 UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration));\r
312 break;\r
313\r
314 case USB_REQUEST_GET_STATUS: {\r
315 if(usd.bmRequestType & 0x80) {\r
316 WORD w = 0;\r
317 UsbSendEp0((BYTE *)&w, sizeof(w));\r
318 }\r
319 break;\r
320 }\r
321 case USB_REQUEST_SET_CONFIGURATION:\r
322 CurrentConfiguration = usd.wValue;\r
323 if(CurrentConfiguration) {\r
324 UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_CONFIGURED;\r
325 UDP_ENDPOINT_CSR(1) = UDP_CSR_ENABLE_EP |\r
326 UDP_CSR_EPTYPE_INTERRUPT_OUT;\r
327 UDP_ENDPOINT_CSR(2) = UDP_CSR_ENABLE_EP |\r
328 UDP_CSR_EPTYPE_INTERRUPT_IN;\r
329 } else {\r
330 UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;\r
331 UDP_ENDPOINT_CSR(1) = 0;\r
332 UDP_ENDPOINT_CSR(2) = 0;\r
333 }\r
334 UsbSendZeroLength();\r
335 break;\r
336\r
337 case USB_REQUEST_GET_INTERFACE: {\r
338 BYTE b = 0;\r
339 UsbSendEp0(&b, sizeof(b));\r
340 break;\r
341 }\r
342\r
343 case USB_REQUEST_SET_INTERFACE:\r
344 UsbSendZeroLength();\r
345 break;\r
346\r
347 case USB_REQUEST_CLEAR_FEATURE:\r
348 case USB_REQUEST_SET_FEATURE:\r
349 case USB_REQUEST_SET_DESCRIPTOR:\r
350 case USB_REQUEST_SYNC_FRAME:\r
351 default:\r
352 break;\r
353 }\r
354}\r
355\r
356void UsbSendPacket(BYTE *packet, int len)\r
357{\r
358 int i, thisTime;\r
359\r
360 while(len > 0) {\r
361 thisTime = min(len, 8);\r
362\r
363 for(i = 0; i < thisTime; i++) {\r
364 UDP_ENDPOINT_FIFO(2) = packet[i];\r
365 }\r
366 UDP_ENDPOINT_CSR(2) |= UDP_CSR_TX_PACKET;\r
367\r
368 while(!(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED))\r
369 ;\r
370 UDP_ENDPOINT_CSR(2) &= ~UDP_CSR_TX_PACKET_ACKED;\r
371\r
372 while(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED)\r
373 ;\r
374\r
375 len -= thisTime;\r
376 packet += thisTime;\r
377 }\r
378}\r
379\r
380static void HandleRxdData(void)\r
381{\r
382 int i, len;\r
383\r
384 if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {\r
385 len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));\r
386\r
387 for(i = 0; i < len; i++) {\r
388 UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);\r
389 UsbSoFarCount++;\r
390 }\r
391\r
392 UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;\r
393 while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0)\r
394 ;\r
395\r
396 if(UsbSoFarCount >= 64) {\r
397 UsbPacketReceived(UsbBuffer, UsbSoFarCount);\r
398 UsbSoFarCount = 0;\r
399 }\r
400 }\r
401\r
402 if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1) {\r
403 len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));\r
404\r
405 for(i = 0; i < len; i++) {\r
406 UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);\r
407 UsbSoFarCount++;\r
408 }\r
409\r
410 UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_1;\r
411 while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1)\r
412 ;\r
413\r
414 if(UsbSoFarCount >= 64) {\r
415 UsbPacketReceived(UsbBuffer, UsbSoFarCount);\r
416 UsbSoFarCount = 0;\r
417 }\r
418 }\r
419}\r
420\r
421void UsbStart(void)\r
422{\r
423 volatile int i;\r
424\r
425 UsbSoFarCount = 0;\r
426\r
427 USB_D_PLUS_PULLUP_OFF();\r
428\r
429 for(i = 0; i < 1000000; i++)\r
430 ;\r
431\r
432 USB_D_PLUS_PULLUP_ON();\r
433\r
434 if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {\r
435 UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;\r
436 }\r
437}\r
438\r
439BOOL UsbPoll(BOOL blinkLeds)\r
440{\r
441 BOOL ret = FALSE;\r
442\r
443 if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {\r
444 UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;\r
445\r
446 // following a reset we should be ready to receive a setup packet\r
447 UDP_RESET_ENDPOINT = 0xf;\r
448 UDP_RESET_ENDPOINT = 0;\r
449\r
450 UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED;\r
451\r
452 UDP_ENDPOINT_CSR(0) = UDP_CSR_EPTYPE_CONTROL | UDP_CSR_ENABLE_EP;\r
453\r
454 CurrentConfiguration = 0;\r
455\r
456 ret = TRUE;\r
457 }\r
458\r
459 if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(0)) {\r
460 if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA) {\r
461 HandleRxdSetupData();\r
462 ret = TRUE;\r
463 }\r
464 }\r
465\r
466 if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(1)) {\r
467 HandleRxdData();\r
468 ret = TRUE;\r
469 }\r
470\r
471 return ret;\r
472}\r
Impressum, Datenschutz