]> git.zerfleddert.de Git - proxmark3-svn/blame - client/wingui.c
Tweak JTAG config file
[proxmark3-svn] / client / wingui.c
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// Routines for the user interface when doing interactive things with prox\r
3// cards; this is basically a command line thing, in one window, and then\r
4// another window to do the graphs.\r
5// Jonathan Westhues, Sept 2005\r
6//-----------------------------------------------------------------------------\r
7#include <windows.h>\r
8#include <limits.h>\r
9#include <commctrl.h>\r
10#include <stdlib.h>\r
11#include <stdio.h>\r
12#include <math.h>\r
393c3ef9 13#include "graph.h"\r
14#include "proxusb.h"\r
15#include "cmdmain.h"\r
16#include "ui.h"\r
6658905f 17\r
18#define oops() do { \\r
19 char line[100]; \\r
20 sprintf(line, "Internal error at line %d file '%s'", __LINE__, \\r
21 __FILE__); \\r
22 MessageBox(NULL, line, "Error", MB_ICONERROR); \\r
23 exit(-1); \\r
24} while(0)\r
25\r
26void dbp(char *str, ...)\r
27{\r
28 va_list f;\r
29 char buf[1024];\r
30 va_start(f, str);\r
31 vsprintf(buf, str, f);\r
32 OutputDebugString(buf);\r
33 OutputDebugString("\n");\r
34}\r
35\r
36int GraphBuffer[MAX_GRAPH_TRACE_LEN];\r
37int GraphTraceLen;\r
bb2d45ec 38int PlotGridX, PlotGridY;\r
6658905f 39\r
bd4cc2c9 40HPEN GreyPenLite, GreyPen, GreenPen, WhitePen, YellowPen;\r
6658905f 41HBRUSH GreenBrush, YellowBrush;\r
42\r
43static int GraphStart = 0;\r
44static double GraphPixelsPerPoint = 1;\r
45\r
46static int CursorAPos;\r
47static int CursorBPos;\r
48double CursorScaleFactor = 1.0;\r
49static HPEN CursorAPen;\r
50static HPEN CursorBPen;\r
51\r
52static HWND CommandWindow;\r
53static HWND GraphWindow;\r
54static HWND ScrollbackEdit;\r
55static HWND CommandEdit;\r
56\r
57#define COMMAND_HISTORY_MAX 16\r
58static char CommandHistory[COMMAND_HISTORY_MAX][256];\r
59static int CommandHistoryPos = -1;\r
60static int CommandHistoryNext;\r
61\r
62static HFONT MyFixedFont;\r
63#define FixedFont(x) SendMessage((x), WM_SETFONT, (WPARAM)MyFixedFont, TRUE)\r
64\r
65void ExecCmd(char *cmd)\r
66{\r
6658905f 67}\r
bd4cc2c9 68\r
6658905f 69int CommandFinished;\r
30f2a7d3 70int offset = 64;\r
6658905f 71\r
72static void ResizeCommandWindow(void)\r
73{\r
74 int w, h;\r
75 RECT r;\r
76 GetClientRect(CommandWindow, &r);\r
77 w = r.right - r.left;\r
78 h = r.bottom - r.top;\r
79 MoveWindow(ScrollbackEdit, 10, 10, w - 20, h - 50, TRUE);\r
80 MoveWindow(CommandEdit, 10, h - 29, w - 20, 22, TRUE);\r
81}\r
82\r
83void RepaintGraphWindow(void)\r
84{\r
85 InvalidateRect(GraphWindow, NULL, TRUE);\r
86}\r
87\r
88static LRESULT CALLBACK\r
89 CommandWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
90{\r
91 switch (msg) {\r
92 case WM_DESTROY:\r
93 case WM_QUIT:\r
94 exit(0);\r
95 return 0;\r
96\r
97 case WM_SIZE:\r
98 ResizeCommandWindow();\r
99 return 0;\r
100\r
101 case WM_SETFOCUS:\r
102 SetFocus(CommandEdit);\r
103 break;\r
104\r
105 default:\r
106 return DefWindowProc(hwnd, msg, wParam, lParam);\r
107 }\r
108\r
109 return 1;\r
110}\r
111\r
112static void PaintGraph(HDC hdc)\r
113{\r
bd4cc2c9 114 RECT r;\r
6658905f 115 HBRUSH brush;\r
116 HPEN pen;\r
bd4cc2c9 117 char str[250];\r
118 int yMin = INT_MAX;\r
119 int yMax = INT_MIN;\r
120 int yMean = 0;\r
121 int startMax = 0;\r
122 int absYMax = 1;\r
123 int n = 0, i = 0;\r
6658905f 124\r
125 brush = GreenBrush;\r
126 pen = GreenPen;\r
127\r
6658905f 128 GetClientRect(GraphWindow, &r);\r
bd4cc2c9 129 int zeroHeight = (r.top + r.bottom) >> 1;\r
130\r
131 // plot X and Y grid lines\r
132 if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) {\r
133 for(i = offset; i < r.right; i += (int)(PlotGridX * GraphPixelsPerPoint)) {\r
134 SelectObject(hdc, GreyPenLite);\r
135 MoveToEx(hdc, r.left + i, r.top, NULL);\r
136 LineTo(hdc, r.left + i, r.bottom);\r
137 }\r
138 }\r
139\r
140 if ((PlotGridY > 0) && ((PlotGridY * GraphPixelsPerPoint) > 1)){\r
141 for(i = 0; i < ((r.top + r.bottom)>>1); i += (int)(PlotGridY * GraphPixelsPerPoint)) {\r
142 SelectObject(hdc, GreyPenLite);\r
143 MoveToEx(hdc, r.left, zeroHeight + i, NULL);\r
144 LineTo(hdc, r.right, zeroHeight + i);\r
145 MoveToEx(hdc, r.left, zeroHeight - i, NULL);\r
146 LineTo(hdc, r.right, zeroHeight - i);\r
147 }\r
148 }\r
6658905f 149\r
bd4cc2c9 150 // print vertical separator white line on the left of the window\r
6658905f 151 SelectObject(hdc, WhitePen);\r
30f2a7d3 152 MoveToEx(hdc, r.left + offset, r.top, NULL);\r
153 LineTo(hdc, r.left + offset, r.bottom);\r
6658905f 154\r
bd4cc2c9 155 // print horizontal grey zero axis line\r
6658905f 156 SelectObject(hdc, GreyPen);\r
157 MoveToEx(hdc, r.left, zeroHeight, NULL);\r
158 LineTo(hdc, r.right, zeroHeight);\r
159\r
bd4cc2c9 160 startMax = (GraphTraceLen - (int)((r.right - r.left - offset) / GraphPixelsPerPoint));\r
161 // check boundaries\r
162 if(startMax < 0) startMax = 0;\r
163 if(GraphStart > startMax) GraphStart = startMax;\r
164 if(GraphStart < 0) GraphStart = 0;\r
6658905f 165\r
6658905f 166\r
167 SelectObject(hdc, pen);\r
168\r
bd4cc2c9 169 // go over the portion of the graph to be displayed and find the largest\r
170 // absolute value which will be used to auto scale the graph when displayed\r
6658905f 171 for(i = GraphStart; ; i++) {\r
172 if(i >= GraphTraceLen) {\r
173 break;\r
174 }\r
175 if(fabs((double)GraphBuffer[i]) > absYMax) {\r
176 absYMax = (int)fabs((double)GraphBuffer[i]);\r
177 }\r
30f2a7d3 178 int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint);\r
6658905f 179 if(x > r.right) {\r
180 break;\r
181 }\r
182 }\r
183\r
184 absYMax = (int)(absYMax*1.2 + 1);\r
185 SelectObject(hdc, MyFixedFont);\r
186 SetTextColor(hdc, RGB(255, 255, 255));\r
187 SetBkColor(hdc, RGB(0, 0, 0));\r
188\r
189 // number of points that will be plotted\r
30f2a7d3 190 double span = (int)((r.right - r.left) / GraphPixelsPerPoint);\r
191\r
192 // one label every offset pixels, let us say\r
193 int labels = (r.right - r.left - offset) / offset;\r
6658905f 194 if(labels <= 0) labels = 1;\r
30f2a7d3 195 // round to nearest power of 2\r
196 int pointsPerLabel = (int)(log(span / labels)/log(2.0));\r
6658905f 197 if(pointsPerLabel <= 0) pointsPerLabel = 1;\r
30f2a7d3 198 pointsPerLabel = (int)pow(2.0,pointsPerLabel);\r
6658905f 199\r
bd4cc2c9 200 // go over the graph and plot samples and labels\r
6658905f 201 for(i = GraphStart; ; i++) {\r
202 if(i >= GraphTraceLen) {\r
203 break;\r
204 }\r
30f2a7d3 205 int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint);\r
6658905f 206 if(x > r.right + GraphPixelsPerPoint) {\r
207 break;\r
208 }\r
209\r
210 int y = GraphBuffer[i];\r
bd4cc2c9 211 if(y < yMin) yMin = y;\r
212 if(y > yMax) yMax = y;\r
6658905f 213 yMean += y;\r
214 n++;\r
215\r
216 y = (y * (r.top - r.bottom) / (2*absYMax)) + zeroHeight;\r
217 if(i == GraphStart) {\r
218 MoveToEx(hdc, x, y, NULL);\r
219 } else {\r
220 LineTo(hdc, x, y);\r
221 }\r
222\r
223 if(GraphPixelsPerPoint > 10) {\r
224 RECT f;\r
225 f.left = x - 3;\r
226 f.top = y - 3;\r
227 f.right = x + 3;\r
228 f.bottom = y + 3;\r
229 FillRect(hdc, &f, brush);\r
230 }\r
231\r
bd4cc2c9 232 // plot labels\r
6658905f 233 if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {\r
234 SelectObject(hdc, WhitePen);\r
30f2a7d3 235 MoveToEx(hdc, x, zeroHeight - 8, NULL);\r
236 LineTo(hdc, x, zeroHeight + 8);\r
6658905f 237\r
bd4cc2c9 238 sprintf(str, "+%d", i);\r
6658905f 239 SIZE size;\r
240 GetTextExtentPoint32(hdc, str, strlen(str), &size);\r
241 TextOut(hdc, x - size.cx, zeroHeight + 8, str, strlen(str));\r
242\r
243 SelectObject(hdc, pen);\r
244 MoveToEx(hdc, x, y, NULL);\r
245 }\r
246\r
bd4cc2c9 247 // plot measurement cursors\r
6658905f 248 if(i == CursorAPos || i == CursorBPos) {\r
249 if(i == CursorAPos) {\r
250 SelectObject(hdc, CursorAPen);\r
251 } else {\r
252 SelectObject(hdc, CursorBPen);\r
253 }\r
254 MoveToEx(hdc, x, r.top, NULL);\r
255 LineTo(hdc, x, r.bottom);\r
256\r
257 SelectObject(hdc, pen);\r
258 MoveToEx(hdc, x, y, NULL);\r
259 }\r
260 }\r
261\r
262 if(n != 0) {\r
263 yMean /= n;\r
264 }\r
265\r
bd4cc2c9 266 // print misc information at bottom of graph window\r
67b9b62a 267 sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f] zoom=%.3f CursorA=%d [%d] CursorB=%d [%d]",\r
6658905f 268 GraphStart, yMax, yMin, yMean, n, GraphTraceLen,\r
48f8a3d6 269 CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor, GraphPixelsPerPoint,\r
270 CursorAPos, GraphBuffer[CursorAPos], CursorBPos, GraphBuffer[CursorBPos]);\r
6658905f 271 TextOut(hdc, 50, r.bottom - 20, str, strlen(str));\r
272}\r
273\r
274static LRESULT CALLBACK\r
275 GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
276{\r
277 switch (msg) {\r
278 case WM_DESTROY:\r
279 case WM_QUIT:\r
280 GraphWindow = NULL;\r
281 return DefWindowProc(hwnd, msg, wParam, lParam);\r
282\r
283 case WM_SIZE:\r
284 RepaintGraphWindow();\r
285 return 0;\r
286\r
287 case WM_PAINT: {\r
288 PAINTSTRUCT ps;\r
289 HDC hdc = BeginPaint(hwnd, &ps);\r
290 if(GraphStart < 0) {\r
291 GraphStart = 0;\r
292 }\r
293 // This draws the trace.\r
294 PaintGraph(hdc);\r
295 EndPaint(hwnd, &ps);\r
296 break;\r
297 }\r
298 case WM_KEYDOWN:\r
299 switch(wParam) {\r
300 case VK_DOWN:\r
30f2a7d3 301 if(GraphPixelsPerPoint <= 8) {\r
6658905f 302 GraphPixelsPerPoint *= 2;\r
303 }\r
304 break;\r
305\r
306 case VK_UP:\r
30f2a7d3 307 if(GraphPixelsPerPoint >= 0.01) {\r
6658905f 308 GraphPixelsPerPoint /= 2;\r
309 }\r
310 break;\r
311\r
312 case VK_RIGHT:\r
30f2a7d3 313 if(GraphPixelsPerPoint < 16) {\r
314 GraphStart += (int)(16 / GraphPixelsPerPoint);\r
6658905f 315 } else {\r
316 GraphStart++;\r
317 }\r
318 break;\r
319\r
320 case VK_LEFT:\r
30f2a7d3 321 if(GraphPixelsPerPoint < 16) {\r
322 GraphStart -= (int)(16 / GraphPixelsPerPoint);\r
6658905f 323 } else {\r
324 GraphStart--;\r
325 }\r
326 break;\r
327\r
328 default:\r
329 goto nopaint;\r
330 }\r
331 RepaintGraphWindow();\r
332nopaint:\r
333 break;\r
334\r
335 case WM_LBUTTONDOWN:\r
336 case WM_RBUTTONDOWN: {\r
337 int x = LOWORD(lParam);\r
30f2a7d3 338 x -= offset;\r
6658905f 339 x = (int)(x / GraphPixelsPerPoint);\r
340 x += GraphStart;\r
48f8a3d6 341\r
6658905f 342 if(msg == WM_LBUTTONDOWN) {\r
343 CursorAPos = x;\r
344 } else {\r
345 CursorBPos = x;\r
346 }\r
347 RepaintGraphWindow();\r
348 break;\r
349 }\r
350 default:\r
351 return DefWindowProc(hwnd, msg, wParam, lParam);\r
352 }\r
353\r
354 return 1;\r
355}\r
356\r
357void PrintToScrollback(char *fmt, ...)\r
358{\r
359 va_list f;\r
360 char str[1024];\r
361 strcpy(str, "\r\n");\r
362 va_start(f, fmt);\r
363 vsprintf(str+2, fmt, f);\r
364\r
365 static char TextBuf[1024*32];\r
366 SendMessage(ScrollbackEdit, WM_GETTEXT, (WPARAM)sizeof(TextBuf),\r
367 (LPARAM)TextBuf);\r
368\r
369 if(strlen(TextBuf) + strlen(str) + 1 <= sizeof(TextBuf)) {\r
370 strcat(TextBuf, str);\r
371 } else {\r
372 lstrcpyn(TextBuf, str, sizeof(TextBuf));\r
373 }\r
374\r
375 SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)TextBuf);\r
376 SendMessage(ScrollbackEdit, EM_LINESCROLL, 0, (LPARAM)INT_MAX);\r
377}\r
378\r
379void ShowGraphWindow(void)\r
380{\r
381 if(GraphWindow) return;\r
382\r
383 GraphWindow = CreateWindowEx(0, "Graph", "graphed",\r
384 WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |\r
385 WS_SIZEBOX | WS_VISIBLE, 200, 150, 600, 500, NULL, NULL, NULL,\r
386 NULL);\r
387 if(!GraphWindow) oops();\r
388}\r
389\r
390void HideGraphWindow(void)\r
391{\r
392 if(GraphWindow) {\r
393 DestroyWindow(GraphWindow);\r
394 GraphWindow = NULL;\r
395 }\r
396}\r
397\r
398static void SetCommandEditTo(char *str)\r
399{\r
400 SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)str);\r
401 SendMessage(CommandEdit, EM_SETSEL, strlen(str), strlen(str));\r
402}\r
403\r
9760414b 404void ShowGui()\r
6658905f 405{\r
406 WNDCLASSEX wc;\r
407 memset(&wc, 0, sizeof(wc));\r
408 wc.cbSize = sizeof(wc);\r
409\r
410 wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC;\r
411 wc.lpfnWndProc = (WNDPROC)CommandWindowProc;\r
412 wc.hInstance = NULL;\r
413 wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW);\r
414 wc.lpszClassName = "Command";\r
415 wc.lpszMenuName = NULL;\r
416 wc.hCursor = LoadCursor(NULL, IDC_ARROW);\r
417\r
418 if(!RegisterClassEx(&wc)) oops();\r
419\r
420 wc.lpszClassName = "Graph";\r
421 wc.lpfnWndProc = (WNDPROC)GraphWindowProc;\r
422 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);\r
423\r
424 if(!RegisterClassEx(&wc)) oops();\r
425\r
426 CommandWindow = CreateWindowEx(0, "Command", "prox",\r
427 WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |\r
428 WS_SIZEBOX | WS_VISIBLE, 20, 20, 500, 400, NULL, NULL, NULL,\r
429 NULL);\r
430 if(!CommandWindow) oops();\r
431\r
432 ScrollbackEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",\r
433 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_MULTILINE |\r
434 ES_AUTOVSCROLL | WS_VSCROLL, 0, 0, 0, 0, CommandWindow, NULL,\r
435 NULL, NULL);\r
436\r
437 CommandEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",\r
438 WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE |\r
439 ES_AUTOHSCROLL, 0, 0, 0, 0, CommandWindow, NULL, NULL, NULL);\r
440\r
441 MyFixedFont = CreateFont(14, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,\r
442 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,\r
443 FF_DONTCARE, "Lucida Console");\r
444 if(!MyFixedFont)\r
445 MyFixedFont = (HFONT)GetStockObject(SYSTEM_FONT);\r
446\r
447 FixedFont(ScrollbackEdit);\r
448 FixedFont(CommandEdit);\r
449\r
450 ResizeCommandWindow();\r
451 SetFocus(CommandEdit);\r
452\r
453 PrintToScrollback(">> Started prox, built " __DATE__ " " __TIME__);\r
454 PrintToScrollback(">> Connected to device");\r
455\r
bd4cc2c9 456 GreyPenLite = CreatePen(PS_SOLID, 1, RGB(50, 50, 50));\r
6658905f 457 GreyPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100));\r
458 GreenPen = CreatePen(PS_SOLID, 1, RGB(100, 255, 100));\r
459 YellowPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0));\r
460 GreenBrush = CreateSolidBrush(RGB(100, 255, 100));\r
461 YellowBrush = CreateSolidBrush(RGB(255, 255, 0));\r
462 WhitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
463\r
464 CursorAPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));\r
465 CursorBPen = CreatePen(PS_DASH, 1, RGB(255, 0, 255));\r
466\r
467 MSG msg;\r
468 for(;;) {\r
469 if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {\r
470 if(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN) {\r
471 char got[1024];\r
472 SendMessage(CommandEdit, WM_GETTEXT, (WPARAM)sizeof(got),\r
473 (LPARAM)got);\r
474\r
475 if(strcmp(got, "cls")==0) {\r
476 SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)"");\r
477 } else {\r
478 CommandReceived(got);\r
479 }\r
480 SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");\r
481\r
482 // Insert it into the command history, unless it is\r
483 // identical to the previous command in the history.\r
484 int prev = CommandHistoryNext - 1;\r
485 if(prev < 0) prev += COMMAND_HISTORY_MAX;\r
486 if(strcmp(CommandHistory[prev], got) != 0) {\r
487 strcpy(CommandHistory[CommandHistoryNext], got);\r
488 CommandHistoryNext++;\r
489 if(CommandHistoryNext == COMMAND_HISTORY_MAX) {\r
490 CommandHistoryNext = 0;\r
491 }\r
492 }\r
493 CommandHistoryPos = -1;\r
494 } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_UP &&\r
495 msg.hwnd == CommandEdit)\r
496 {\r
497 if(CommandHistoryPos == -1) {\r
498 CommandHistoryPos = CommandHistoryNext;\r
499 }\r
500 CommandHistoryPos--;\r
501 if(CommandHistoryPos < 0) {\r
502 CommandHistoryPos = COMMAND_HISTORY_MAX-1;\r
503 }\r
504 SetCommandEditTo(CommandHistory[CommandHistoryPos]);\r
505 } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_DOWN &&\r
506 msg.hwnd == CommandEdit)\r
507 {\r
508 CommandHistoryPos++;\r
509 if(CommandHistoryPos >= COMMAND_HISTORY_MAX) {\r
510 CommandHistoryPos = 0;\r
511 }\r
512 SetCommandEditTo(CommandHistory[CommandHistoryPos]);\r
513 } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE &&\r
514 msg.hwnd == CommandEdit)\r
515 {\r
516 SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");\r
517 } else {\r
518 if(msg.message == WM_KEYDOWN) {\r
519 CommandHistoryPos = -1;\r
520 }\r
521 TranslateMessage(&msg);\r
522 DispatchMessage(&msg);\r
523 }\r
524 }\r
525\r
9760414b 526 if (!offline)\r
527 {\r
528 UsbCommand c;\r
529 if(ReceiveCommandPoll(&c))\r
530 UsbCommandReceived(&c);\r
6658905f 531 }\r
532\r
533 Sleep(10);\r
534 }\r
535}\r
Impressum, Datenschutz