]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - winsrc/prox.cpp
maintain alphabetic order!
[proxmark3-svn] / winsrc / prox.cpp
... / ...
CommitLineData
1#include <windows.h>\r
2#include <setupapi.h>\r
3#include <stdio.h>\r
4#include <ctype.h>\r
5#include <stdlib.h>\r
6extern "C" {\r
7#include "include/hidsdi.h"\r
8#include "include/hidpi.h"\r
9}\r
10\r
11#include "prox.h"\r
12\r
13#define OUR_VID 0x9ac4\r
14#define OUR_PID 0x4b8f\r
15\r
16int offline = 0;\r
17HANDLE UsbHandle;\r
18\r
19static void ShowError(void)\r
20{\r
21 char buf[1024];\r
22 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,\r
23 buf, sizeof(buf), NULL);\r
24 printf("ERROR: %s", buf);\r
25}\r
26\r
27static BOOL UsbConnect(void)\r
28{\r
29 typedef void (__stdcall *GetGuidProc)(GUID *);\r
30 typedef BOOLEAN (__stdcall *GetAttrProc)(HANDLE, HIDD_ATTRIBUTES *);\r
31 typedef BOOLEAN (__stdcall *GetPreparsedProc)(HANDLE,\r
32 PHIDP_PREPARSED_DATA *);\r
33 typedef NTSTATUS (__stdcall *GetCapsProc)(PHIDP_PREPARSED_DATA, PHIDP_CAPS);\r
34 GetGuidProc getGuid;\r
35 GetAttrProc getAttr;\r
36 GetPreparsedProc getPreparsed;\r
37 GetCapsProc getCaps;\r
38\r
39 HMODULE h = LoadLibrary("hid.dll");\r
40 getGuid = (GetGuidProc)GetProcAddress(h, "HidD_GetHidGuid");\r
41 getAttr = (GetAttrProc)GetProcAddress(h, "HidD_GetAttributes");\r
42 getPreparsed = (GetPreparsedProc)GetProcAddress(h, "HidD_GetPreparsedData");\r
43 getCaps = (GetCapsProc)GetProcAddress(h, "HidP_GetCaps");\r
44\r
45 GUID hidGuid;\r
46 getGuid(&hidGuid);\r
47\r
48 HDEVINFO devInfo;\r
49 devInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL,\r
50 DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);\r
51\r
52 SP_DEVICE_INTERFACE_DATA devInfoData;\r
53 devInfoData.cbSize = sizeof(devInfoData);\r
54\r
55 int i;\r
56 for(i = 0;; i++) {\r
57 if(!SetupDiEnumDeviceInterfaces(devInfo, 0, &hidGuid, i, &devInfoData))\r
58 {\r
59 if(GetLastError() != ERROR_NO_MORE_ITEMS) {\r
60// printf("SetupDiEnumDeviceInterfaces failed\n");\r
61 }\r
62// printf("done list\n");\r
63 SetupDiDestroyDeviceInfoList(devInfo);\r
64 return FALSE;\r
65 }\r
66\r
67// printf("item %d:\n", i);\r
68\r
69 DWORD sizeReqd = 0;\r
70 if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData,\r
71 NULL, 0, &sizeReqd, NULL))\r
72 {\r
73 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {\r
74// printf("SetupDiGetDeviceInterfaceDetail (0) failed\n");\r
75 continue;\r
76 }\r
77 }\r
78\r
79 SP_DEVICE_INTERFACE_DETAIL_DATA *devInfoDetailData =\r
80 (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(sizeReqd);\r
81 devInfoDetailData->cbSize = sizeof(*devInfoDetailData);\r
82\r
83 if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData,\r
84 devInfoDetailData, 87, NULL, NULL))\r
85 {\r
86// printf("SetupDiGetDeviceInterfaceDetail (1) failed\n");\r
87 continue;\r
88 }\r
89\r
90 char *path = devInfoDetailData->DevicePath;\r
91\r
92 UsbHandle = CreateFile(path, /*GENERIC_READ |*/ GENERIC_WRITE,\r
93 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,\r
94 FILE_FLAG_OVERLAPPED, NULL);\r
95\r
96 if(UsbHandle == INVALID_HANDLE_VALUE) {\r
97 ShowError();\r
98// printf("CreateFile failed: for '%s'\n", path);\r
99 continue;\r
100 }\r
101\r
102 HIDD_ATTRIBUTES attr;\r
103 attr.Size = sizeof(attr);\r
104 if(!getAttr(UsbHandle, &attr)) {\r
105 ShowError();\r
106// printf("HidD_GetAttributes failed\n");\r
107 continue;\r
108 }\r
109\r
110// printf("VID: %04x PID %04x\n", attr.VendorID, attr.ProductID);\r
111\r
112 if(attr.VendorID != OUR_VID || attr.ProductID != OUR_PID) {\r
113 CloseHandle(UsbHandle);\r
114// printf(" nope, not us\n");\r
115 continue;\r
116 }\r
117\r
118// printf ("got it!\n");\r
119 CloseHandle(UsbHandle);\r
120\r
121 UsbHandle = CreateFile(path, GENERIC_READ | GENERIC_WRITE,\r
122 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,\r
123 FILE_FLAG_OVERLAPPED, NULL);\r
124\r
125 if(UsbHandle == INVALID_HANDLE_VALUE) {\r
126 ShowError();\r
127// printf("Error, couldn't open our own handle as desired.\n");\r
128 return FALSE;\r
129 }\r
130\r
131 PHIDP_PREPARSED_DATA pp;\r
132 getPreparsed(UsbHandle, &pp);\r
133 HIDP_CAPS caps;\r
134\r
135 if(getCaps(pp, &caps) != HIDP_STATUS_SUCCESS) {\r
136// printf("getcaps failed\n");\r
137 return FALSE;\r
138 }\r
139\r
140// printf("input/out report %d/%d\n", caps.InputReportByteLength,\r
141// caps.OutputReportByteLength);\r
142\r
143\r
144 return TRUE;\r
145 }\r
146 return FALSE;\r
147}\r
148\r
149BOOL ReceiveCommandPoll(UsbCommand *c)\r
150{\r
151 static BOOL ReadInProgress = FALSE;\r
152 static OVERLAPPED Ov;\r
153 static BYTE Buf[65];\r
154 static DWORD HaveRead;\r
155\r
156 if(!ReadInProgress) {\r
157 memset(&Ov, 0, sizeof(Ov));\r
158 ReadFile(UsbHandle, Buf, 65, &HaveRead, &Ov);\r
159 if(GetLastError() != ERROR_IO_PENDING) {\r
160 ShowError();\r
161 exit(-1);\r
162 }\r
163 ReadInProgress = TRUE;\r
164 }\r
165\r
166 if(HasOverlappedIoCompleted(&Ov)) {\r
167 ReadInProgress = FALSE;\r
168\r
169 if(!GetOverlappedResult(UsbHandle, &Ov, &HaveRead, FALSE)) {\r
170 ShowError();\r
171 exit(-1);\r
172 }\r
173\r
174 memcpy(c, Buf+1, 64);\r
175\r
176 return TRUE;\r
177 } else {\r
178 return FALSE;\r
179 }\r
180}\r
181\r
182void ReceiveCommand(UsbCommand *c)\r
183{\r
184 while(!ReceiveCommandPoll(c)) {\r
185 Sleep(0);\r
186 }\r
187}\r
188\r
189void SendCommand(UsbCommand *c, BOOL wantAck)\r
190{\r
191 BYTE buf[65];\r
192 buf[0] = 0;\r
193 memcpy(buf+1, c, 64);\r
194\r
195 DWORD written;\r
196 OVERLAPPED ov;\r
197\r
198 memset(&ov, 0, sizeof(ov));\r
199 WriteFile(UsbHandle, buf, 65, &written, &ov);\r
200 if(GetLastError() != ERROR_IO_PENDING) {\r
201 ShowError();\r
202 exit(-1);\r
203 }\r
204\r
205 while(!HasOverlappedIoCompleted(&ov)) {\r
206 Sleep(0);\r
207 }\r
208\r
209 if(!GetOverlappedResult(UsbHandle, &ov, &written, FALSE)) {\r
210 ShowError();\r
211 exit(-1);\r
212 }\r
213\r
214 if(wantAck) {\r
215 UsbCommand ack;\r
216 ReceiveCommand(&ack);\r
217 if(ack.cmd != CMD_ACK) {\r
218 printf("bad ACK\n");\r
219 exit(-1);\r
220 }\r
221 }\r
222}\r
223\r
224static DWORD ExpectedAddr;\r
225static BYTE QueuedToSend[256];\r
226static BOOL AllWritten;\r
227\r
228static void FlushPrevious(void)\r
229{\r
230 UsbCommand c;\r
231 memset(&c, 0, sizeof(c));\r
232\r
233 int i;\r
234 for(i = 0; i < 240; i += 48) {\r
235 c.cmd = CMD_SETUP_WRITE;\r
236 memcpy(c.d.asBytes, QueuedToSend+i, 48);\r
237 c.ext1 = (i/4);\r
238 SendCommand(&c, TRUE);\r
239 }\r
240\r
241 c.cmd = CMD_FINISH_WRITE;\r
242 c.ext1 = (ExpectedAddr-1) & (~255);\r
243 printf("Flashing address: %08x\r", c.ext1);\r
244 memcpy(c.d.asBytes, QueuedToSend+240, 16);\r
245 SendCommand(&c, TRUE);\r
246\r
247 AllWritten = TRUE;\r
248}\r
249\r
250static void GotByte(DWORD where, BYTE which)\r
251{\r
252 AllWritten = FALSE;\r
253\r
254 if(where != ExpectedAddr) {\r
255 printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr);\r
256 exit(-1);\r
257 }\r
258 QueuedToSend[where & 255] = which;\r
259 ExpectedAddr++;\r
260\r
261 if((where & 255) == 255) {\r
262 // we have completed a full page\r
263 FlushPrevious();\r
264 }\r
265}\r
266\r
267static int HexVal(int c)\r
268{\r
269 c = tolower(c);\r
270 if(c >= '0' && c <= '9') {\r
271 return c - '0';\r
272 } else if(c >= 'a' && c <= 'f') {\r
273 return (c - 'a') + 10;\r
274 } else {\r
275 printf("bad hex digit '%c'\n", c);\r
276 exit(-1);\r
277 }\r
278}\r
279\r
280static BYTE HexByte(char *s)\r
281{\r
282 return (HexVal(s[0]) << 4) | HexVal(s[1]);\r
283}\r
284\r
285static void LoadFlashFromSRecords(char *file, int addr)\r
286{\r
287 ExpectedAddr = addr;\r
288\r
289 FILE *f = fopen(file, "r");\r
290 if(!f) {\r
291 printf("couldn't open file\n");\r
292 exit(-1);\r
293 }\r
294\r
295 char line[512];\r
296 while(fgets(line, sizeof(line), f)) {\r
297 if(memcmp(line, "S3", 2)==0) {\r
298 char *s = line + 2;\r
299 int len = HexByte(s) - 5;\r
300 s += 2;\r
301\r
302 char addrStr[9];\r
303 memcpy(addrStr, s, 8);\r
304 addrStr[8] = '\0';\r
305 DWORD addr;\r
306 sscanf(addrStr, "%x", &addr);\r
307 s += 8;\r
308\r
309 int i;\r
310 for(i = 0; i < len; i++) {\r
311 while((addr+i) > ExpectedAddr) {\r
312 GotByte(ExpectedAddr, 0xff);\r
313 }\r
314 GotByte(addr+i, HexByte(s));\r
315 s += 2;\r
316 }\r
317 }\r
318 }\r
319\r
320 if(!AllWritten) FlushPrevious();\r
321\r
322 fclose(f);\r
323 printf("\ndone.\n");\r
324}\r
325\r
326int main(int argc, char **argv)\r
327{\r
328 int i = 0;\r
329 \r
330 if(argc < 2) {\r
331 printf("Usage: %s bootrom file.s19\n", argv[0]);\r
332 printf(" %s load osimage.s19\n", argv[0]);\r
333 printf(" %s fpga fpgaimg.s19\n", argv[0]);\r
334 printf(" %s gui\n", argv[0]);\r
335 printf(" %s offline\n", argv[0]);\r
336 return -1;\r
337 }\r
338 \r
339 // Only do this if NOT in offline mode\r
340 if (strcmp(argv[1], "offline"))\r
341 {\r
342 for(;;) {\r
343 if(UsbConnect()) {\r
344 break;\r
345 }\r
346 if(i == 0) {\r
347 printf("...no device connected, polling for it now\n");\r
348 }\r
349 if(i > 50000) {\r
350 printf("Could not connect to USB device; exiting.\n");\r
351 return -1;\r
352 }\r
353 i++;\r
354 Sleep(5);\r
355 }\r
356 }\r
357 \r
358 if(strcmp(argv[1], "bootrom")==0 || strcmp(argv[1], "load")==0 || strcmp(argv[1], "fpga")==0) {\r
359 if(argc != 3) {\r
360 printf("Need filename.\n");\r
361 return -1;\r
362 }\r
363 if(strcmp(argv[1], "bootrom")==0) {\r
364 LoadFlashFromSRecords(argv[2], 0);\r
365 } else if(strcmp(argv[1], "fpga")==0) {\r
366 LoadFlashFromSRecords(argv[2], 0x2000);\r
367 } else {\r
368 LoadFlashFromSRecords(argv[2], 0x10000);\r
369 }\r
370 } else if(strcmp(argv[1], "gui")==0) {\r
371 ShowGui();\r
372 } else if(strcmp(argv[1], "offline")==0) {\r
373 offline = 1;\r
374 ShowGui();\r
375 } else if(strcmp(argv[1], "cmd")==0) {\r
376 if(argc != 3) {\r
377 printf("Need command.\n");\r
378 return -1;\r
379 }\r
380 ExecCmd(argv[2]);\r
381 } else {\r
382 printf("Command '%s' not recognized.\n", argv[1]);\r
383 return -1;\r
384 }\r
385\r
386 return 0;\r
387}\r
Impressum, Datenschutz