]> git.zerfleddert.de Git - proxmark3-svn/blame - winsrc/prox.cpp
fix crash in client when no buffer is loaded
[proxmark3-svn] / winsrc / prox.cpp
CommitLineData
6658905f 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
9760414b 16int offline = 0;\r
6658905f 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 memset(&ov, 0, sizeof(ov));\r
198 WriteFile(UsbHandle, buf, 65, &written, &ov);\r
199 if(GetLastError() != ERROR_IO_PENDING) {\r
200 ShowError();\r
201 exit(-1);\r
202 }\r
203\r
204 while(!HasOverlappedIoCompleted(&ov)) {\r
205 Sleep(0);\r
206 }\r
207\r
208 if(!GetOverlappedResult(UsbHandle, &ov, &written, FALSE)) {\r
209 ShowError();\r
210 exit(-1);\r
211 }\r
212\r
213 if(wantAck) {\r
214 UsbCommand ack;\r
215 ReceiveCommand(&ack);\r
216 if(ack.cmd != CMD_ACK) {\r
217 printf("bad ACK\n");\r
218 exit(-1);\r
219 }\r
220 }\r
221}\r
222\r
223static DWORD ExpectedAddr;\r
224static BYTE QueuedToSend[256];\r
225static BOOL AllWritten;\r
226\r
227static void FlushPrevious(void)\r
228{\r
229 UsbCommand c;\r
230 memset(&c, 0, sizeof(c));\r
231\r
232 printf("expected = %08x flush, ", ExpectedAddr);\r
233\r
234 int i;\r
235 for(i = 0; i < 240; i += 48) {\r
236 c.cmd = CMD_SETUP_WRITE;\r
237 memcpy(c.d.asBytes, QueuedToSend+i, 48);\r
238 c.ext1 = (i/4);\r
239 SendCommand(&c, TRUE);\r
240 }\r
241\r
242 c.cmd = CMD_FINISH_WRITE;\r
243 c.ext1 = (ExpectedAddr-1) & (~255);\r
244 printf("c.ext1 = %08x\r", c.ext1);\r
245 memcpy(c.d.asBytes, QueuedToSend+240, 16);\r
246 SendCommand(&c, TRUE);\r
247\r
248 AllWritten = TRUE;\r
249}\r
250\r
251static void GotByte(DWORD where, BYTE which)\r
252{\r
253 AllWritten = FALSE;\r
254\r
255 if(where != ExpectedAddr) {\r
256 printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr);\r
257 exit(-1);\r
258 }\r
259 QueuedToSend[where & 255] = which;\r
260 ExpectedAddr++;\r
261\r
262 if((where & 255) == 255) {\r
263 // we have completed a full page\r
264 FlushPrevious();\r
265 }\r
266}\r
267\r
268static int HexVal(int c)\r
269{\r
270 c = tolower(c);\r
271 if(c >= '0' && c <= '9') {\r
272 return c - '0';\r
273 } else if(c >= 'a' && c <= 'f') {\r
274 return (c - 'a') + 10;\r
275 } else {\r
276 printf("bad hex digit '%c'\n", c);\r
277 exit(-1);\r
278 }\r
279}\r
280\r
281static BYTE HexByte(char *s)\r
282{\r
283 return (HexVal(s[0]) << 4) | HexVal(s[1]);\r
284}\r
285\r
286static void LoadFlashFromSRecords(char *file, int addr)\r
287{\r
288 ExpectedAddr = addr;\r
289\r
290 FILE *f = fopen(file, "r");\r
291 if(!f) {\r
292 printf("couldn't open file\n");\r
293 exit(-1);\r
294 }\r
295\r
296 char line[512];\r
297 while(fgets(line, sizeof(line), f)) {\r
298 if(memcmp(line, "S3", 2)==0) {\r
299 char *s = line + 2;\r
300 int len = HexByte(s) - 5;\r
301 s += 2;\r
302\r
303 char addrStr[9];\r
304 memcpy(addrStr, s, 8);\r
305 addrStr[8] = '\0';\r
306 DWORD addr;\r
307 sscanf(addrStr, "%x", &addr);\r
308 s += 8;\r
309\r
310 int i;\r
311 for(i = 0; i < len; i++) {\r
312 while((addr+i) > ExpectedAddr) {\r
313 GotByte(ExpectedAddr, 0xff);\r
314 }\r
315 GotByte(addr+i, HexByte(s));\r
316 s += 2;\r
317 }\r
318 }\r
319 }\r
320\r
321 if(!AllWritten) FlushPrevious();\r
322\r
323 fclose(f);\r
324 printf("\ndone.\n");\r
325}\r
326\r
327int main(int argc, char **argv)\r
328{\r
329 int i = 0;\r
9760414b 330 \r
6658905f 331 if(argc < 2) {\r
332 printf("Usage: %s bootrom file.s19\n", argv[0]);\r
333 printf(" %s load osimage.s19\n", argv[0]);\r
334 printf(" %s fpga fpgaimg.s19\n", argv[0]);\r
335 printf(" %s gui\n", argv[0]);\r
9760414b 336 printf(" %s offline\n", argv[0]);\r
6658905f 337 return -1;\r
338 }\r
9760414b 339 \r
340 // Only do this if NOT in offline mode\r
341 if (strcmp(argv[1], "offline"))\r
342 {\r
343 for(;;) {\r
344 if(UsbConnect()) {\r
345 break;\r
346 }\r
347 if(i == 0) {\r
348 printf("...no device connected, polling for it now\n");\r
349 }\r
350 if(i > 50000) {\r
351 printf("Could not connect to USB device; exiting.\n");\r
352 return -1;\r
353 }\r
354 i++;\r
355 Sleep(5);\r
6658905f 356 }\r
6658905f 357 }\r
9760414b 358 \r
6658905f 359 if(strcmp(argv[1], "bootrom")==0 || strcmp(argv[1], "load")==0 || strcmp(argv[1], "fpga")==0) {\r
360 if(argc != 3) {\r
361 printf("Need filename.\n");\r
362 return -1;\r
363 }\r
364 if(strcmp(argv[1], "bootrom")==0) {\r
365 LoadFlashFromSRecords(argv[2], 0);\r
366 } else if(strcmp(argv[1], "fpga")==0) {\r
367 LoadFlashFromSRecords(argv[2], 0x2000);\r
368 } else {\r
369 LoadFlashFromSRecords(argv[2], 0x10000);\r
370 }\r
371 } else if(strcmp(argv[1], "gui")==0) {\r
372 ShowGui();\r
9760414b 373 } else if(strcmp(argv[1], "offline")==0) {\r
374 offline = 1;\r
375 ShowGui();\r
6658905f 376 } else if(strcmp(argv[1], "cmd")==0) {\r
377 if(argc != 3) {\r
378 printf("Need command.\n");\r
379 return -1;\r
380 }\r
381 ExecCmd(argv[2]);\r
382 } else {\r
383 printf("Command '%s' not recognized.\n", argv[1]);\r
384 return -1;\r
385 }\r
386\r
387 return 0;\r
388}\r
Impressum, Datenschutz