]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - client/proxmark3.c
Refactoring uart interface (#341)
[proxmark3-svn] / client / proxmark3.c
... / ...
CommitLineData
1//-----------------------------------------------------------------------------
2// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
3// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
4//
5// This code is licensed to you under the terms of the GNU GPL, version 2 or,
6// at your option, any later version. See the LICENSE.txt file for the text of
7// the license.
8//-----------------------------------------------------------------------------
9// Main binary
10//-----------------------------------------------------------------------------
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <pthread.h>
16#include <unistd.h>
17#include <readline/readline.h>
18#include <readline/history.h>
19
20#include "proxmark3.h"
21#include "proxgui.h"
22#include "cmdmain.h"
23#include "uart.h"
24#include "ui.h"
25#include "cmdparser.h"
26#include "cmdhw.h"
27#include "whereami.h"
28
29
30// a global mutex to prevent interlaced printing from different threads
31pthread_mutex_t print_lock;
32
33static serial_port sp;
34static UsbCommand txcmd;
35volatile static bool txcmd_pending = false;
36
37void SendCommand(UsbCommand *c) {
38 #if 0
39 printf("Sending %d bytes\n", sizeof(UsbCommand));
40 #endif
41
42 if (offline) {
43 PrintAndLog("Sending bytes to proxmark failed - offline");
44 return;
45 }
46 /**
47 The while-loop below causes hangups at times, when the pm3 unit is unresponsive
48 or disconnected. The main console thread is alive, but comm thread just spins here.
49 Not good.../holiman
50 **/
51 while(txcmd_pending);
52 txcmd = *c;
53 txcmd_pending = true;
54}
55
56struct receiver_arg {
57 int run;
58};
59
60byte_t rx[sizeof(UsbCommand)];
61byte_t* prx = rx;
62
63static void *uart_receiver(void *targ) {
64 struct receiver_arg *arg = (struct receiver_arg*)targ;
65 size_t rxlen;
66
67 while (arg->run) {
68 rxlen = 0;
69 if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen)) {
70 prx += rxlen;
71 if (prx-rx < sizeof(UsbCommand)) {
72 continue;
73 }
74
75 UsbCommandReceived((UsbCommand*)rx);
76 }
77 prx = rx;
78
79 if(txcmd_pending) {
80 if (!uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand))) {
81 PrintAndLog("Sending bytes to proxmark failed");
82 }
83 txcmd_pending = false;
84 }
85 }
86
87 pthread_exit(NULL);
88 return NULL;
89}
90
91
92void main_loop(char *script_cmds_file, bool usb_present) {
93 struct receiver_arg rarg;
94 char *cmd = NULL;
95 pthread_t reader_thread;
96
97 if (usb_present) {
98 rarg.run = 1;
99 pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
100 // cache Version information now:
101 CmdVersion(NULL);
102 }
103
104 FILE *script_file = NULL;
105 char script_cmd_buf[256]; // iceman, needs lua script the same file_path_buffer as the rest
106
107 if (script_cmds_file) {
108 script_file = fopen(script_cmds_file, "r");
109 if (script_file) {
110 printf("using 'scripting' commands file %s\n", script_cmds_file);
111 }
112 }
113
114 read_history(".history");
115
116 while(1) {
117
118 // If there is a script file
119 if (script_file)
120 {
121 if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), script_file)) {
122 fclose(script_file);
123 script_file = NULL;
124 } else {
125 char *nl;
126 nl = strrchr(script_cmd_buf, '\r');
127 if (nl) *nl = '\0';
128
129 nl = strrchr(script_cmd_buf, '\n');
130 if (nl) *nl = '\0';
131
132 if ((cmd = (char*) malloc(strlen(script_cmd_buf) + 1)) != NULL) {
133 memset(cmd, 0, strlen(script_cmd_buf));
134 strcpy(cmd, script_cmd_buf);
135 printf("%s\n", cmd);
136 }
137 }
138 }
139
140 if (!script_file) {
141 cmd = readline(PROXPROMPT);
142 }
143
144 if (cmd) {
145
146 while(cmd[strlen(cmd) - 1] == ' ')
147 cmd[strlen(cmd) - 1] = 0x00;
148
149 if (cmd[0] != 0x00) {
150 int ret = CommandReceived(cmd);
151 add_history(cmd);
152 if (ret == 99) { // exit or quit
153 break;
154 }
155 }
156 free(cmd);
157 } else {
158 printf("\n");
159 break;
160 }
161 }
162
163 write_history(".history");
164
165 if (usb_present) {
166 rarg.run = 0;
167 pthread_join(reader_thread, NULL);
168 }
169
170 if (script_file) {
171 fclose(script_file);
172 script_file = NULL;
173 }
174
175}
176
177static void dumpAllHelp(int markdown)
178{
179 printf("\n%sProxmark3 command dump%s\n\n",markdown?"# ":"",markdown?"":"\n======================");
180 printf("Some commands are available only if a Proxmark is actually connected.%s\n",markdown?" ":"");
181 printf("Check column \"offline\" for their availability.\n");
182 printf("\n");
183 command_t *cmds = getTopLevelCommandTable();
184 dumpCommandsRecursive(cmds, markdown);
185}
186
187static char *my_executable_path = NULL;
188static char *my_executable_directory = NULL;
189
190const char *get_my_executable_path(void)
191{
192 return my_executable_path;
193}
194
195const char *get_my_executable_directory(void)
196{
197 return my_executable_directory;
198}
199
200static void set_my_executable_path(void)
201{
202 int path_length = wai_getExecutablePath(NULL, 0, NULL);
203 if (path_length != -1) {
204 my_executable_path = (char*)malloc(path_length + 1);
205 int dirname_length = 0;
206 if (wai_getExecutablePath(my_executable_path, path_length, &dirname_length) != -1) {
207 my_executable_path[path_length] = '\0';
208 my_executable_directory = (char *)malloc(dirname_length + 2);
209 strncpy(my_executable_directory, my_executable_path, dirname_length+1);
210 my_executable_directory[dirname_length+1] = '\0';
211 }
212 }
213}
214
215
216int main(int argc, char* argv[]) {
217 srand(time(0));
218
219 if (argc < 2) {
220 printf("syntax: %s <port>\n\n",argv[0]);
221 printf("\tLinux example:'%s /dev/ttyACM0'\n\n", argv[0]);
222 printf("help: %s -h\n\n", argv[0]);
223 printf("\tDump all interactive help at once\n");
224 printf("markdown: %s -m\n\n", argv[0]);
225 printf("\tDump all interactive help at once in markdown syntax\n");
226 return 1;
227 }
228 if (strcmp(argv[1], "-h") == 0) {
229 printf("syntax: %s <port>\n\n",argv[0]);
230 printf("\tLinux example:'%s /dev/ttyACM0'\n\n", argv[0]);
231 dumpAllHelp(0);
232 return 0;
233 }
234 if (strcmp(argv[1], "-m") == 0) {
235 dumpAllHelp(1);
236 return 0;
237 }
238
239 set_my_executable_path();
240
241 bool usb_present = false;
242 char *script_cmds_file = NULL;
243
244 sp = uart_open(argv[1]);
245 if (sp == INVALID_SERIAL_PORT) {
246 printf("ERROR: invalid serial port\n");
247 usb_present = false;
248 offline = 1;
249 } else if (sp == CLAIMED_SERIAL_PORT) {
250 printf("ERROR: serial port is claimed by another process\n");
251 usb_present = false;
252 offline = 1;
253 } else {
254 usb_present = true;
255 offline = 0;
256 }
257
258 // If the user passed the filename of the 'script' to execute, get it
259 if (argc > 2 && argv[2]) {
260 if (argv[2][0] == 'f' && //buzzy, if a word 'flush' passed, flush the output after every log entry.
261 argv[2][1] == 'l' &&
262 argv[2][2] == 'u' &&
263 argv[2][3] == 's' &&
264 argv[2][4] == 'h')
265 {
266 printf("Output will be flushed after every print.\n");
267 flushAfterWrite = 1;
268 }
269 else
270 script_cmds_file = argv[2];
271 }
272
273 // create a mutex to avoid interlacing print commands from our different threads
274 pthread_mutex_init(&print_lock, NULL);
275
276#ifdef HAVE_GUI
277 InitGraphics(argc, argv, script_cmds_file, usb_present);
278 MainGraphics();
279#else
280 main_loop(script_cmds_file, usb_present);
281#endif
282
283 // Clean up the port
284 if (usb_present) {
285 uart_close(sp);
286 }
287
288 // clean up mutex
289 pthread_mutex_destroy(&print_lock);
290
291 exit(0);
292}
Impressum, Datenschutz