1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   4 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   5 // at your option, any later version. See the LICENSE.txt file for the text of 
   7 //----------------------------------------------------------------------------- 
   8 // Main command parser entry point 
   9 //----------------------------------------------------------------------------- 
  16 #include "cmdparser.h" 
  17 #include "proxmark3.h" 
  27 #include "cmdscript.h" 
  30 unsigned int current_command 
= CMD_UNKNOWN
; 
  31 //unsigned int received_command = CMD_UNKNOWN; 
  32 //UsbCommand current_response; 
  33 //UsbCommand current_response_user; 
  35 static int CmdHelp(const char *Cmd
); 
  36 static int CmdQuit(const char *Cmd
); 
  38 //For storing command that are received from the device 
  39 #define CMD_BUFFER_SIZE 50 
  40 static UsbCommand cmdBuffer
[CMD_BUFFER_SIZE
]; 
  41 //Points to the next empty position to write to 
  42 static int cmd_head
;//Starts as 0 
  43 //Points to the position of the last unread command 
  44 static int cmd_tail
;//Starts as 0 
  46 static command_t CommandTable
[] =  
  48   {"help",  CmdHelp
,  1, "This help. Use '<command> help' for details of the following commands:\n"}, 
  49   {"data",  CmdData
,  1, "{ Plot window / data buffer manipulation... }"}, 
  50   {"exit",  CmdQuit
,  1, "Exit program"}, 
  51   {"hf",    CmdHF
,    1, "{ HF commands... }"}, 
  52   {"hw",    CmdHW
,    1, "{ Hardware commands... }"}, 
  53   {"lf",    CmdLF
,    1, "{ LF commands... }"}, 
  54   {"quit",  CmdQuit
,  1, "Quit program"}, 
  55   {"script", CmdScript
,   1,"Run script"}, 
  59 int CmdHelp(const char *Cmd
) 
  61   CmdsHelp(CommandTable
); 
  65 int CmdQuit(const char *Cmd
) 
  71  * @brief This method should be called when sending a new command to the pm3. In case any old 
  72  *  responses from previous commands are stored in the buffer, a call to this method should clear them. 
  73  *  A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which 
  74  *  operation. Right now we'll just have to live with this. 
  76 void clearCommandBuffer() 
  78     //This is a very simple operation 
  83  * @brief storeCommand stores a USB command in a circular buffer 
  86 void storeCommand(UsbCommand 
*command
) 
  88     if( ( cmd_head
+1) % CMD_BUFFER_SIZE 
== cmd_tail
) 
  90         //If these two are equal, we're about to overwrite in the 
  92         PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!"); 
  94     //Store the command at the 'head' location 
  95     UsbCommand
* destination 
= &cmdBuffer
[cmd_head
]; 
  96     memcpy(destination
, command
, sizeof(UsbCommand
)); 
  98     cmd_head 
= (cmd_head 
+1) % CMD_BUFFER_SIZE
; //increment head and wrap 
 102  * @brief getCommand gets a command from an internal circular buffer. 
 103  * @param response location to write command 
 104  * @return 1 if response was returned, 0 if nothing has been received 
 106 int getCommand(UsbCommand
* response
) 
 108     //If head == tail, there's nothing to read, or if we just got initialized 
 109     if(cmd_head 
== cmd_tail
){ 
 112     //Pick out the next unread command 
 113     UsbCommand
* last_unread 
= &cmdBuffer
[cmd_tail
]; 
 114     memcpy(response
, last_unread
, sizeof(UsbCommand
)); 
 115     //Increment tail - this is a circular buffer, so modulo buffer size 
 116     cmd_tail 
= (cmd_tail 
+1 ) % CMD_BUFFER_SIZE
; 
 123  * Waits for a certain response type. This method waits for a maximum of 
 124  * ms_timeout milliseconds for a specified response command. 
 125  *@brief WaitForResponseTimeout 
 126  * @param cmd command to wait for 
 127  * @param response struct to copy received command into. 
 129  * @return true if command was returned, otherwise false 
 131 bool WaitForResponseTimeout(uint32_t cmd
, UsbCommand
* response
, size_t ms_timeout
) { 
 133   if (response 
== NULL
) { 
 138   // Wait until the command is received 
 139   for(size_t dm_seconds
=0; dm_seconds 
< ms_timeout
/10; dm_seconds
++) { 
 141       while(getCommand(response
)) 
 143           if(response
->cmd 
== cmd
){ 
 144           //We got what we expected 
 149         msleep(10); // XXX ugh 
 150         if (dm_seconds 
== 200) { // Two seconds elapsed 
 151           PrintAndLog("Waiting for a response from the proxmark..."); 
 152           PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); 
 158 bool WaitForResponse(uint32_t cmd
, UsbCommand
* response
) { 
 159         return WaitForResponseTimeout(cmd
,response
,-1); 
 162 //----------------------------------------------------------------------------- 
 163 // Entry point into our code: called whenever the user types a command and 
 164 // then presses Enter, which the full command line that they typed. 
 165 //----------------------------------------------------------------------------- 
 166 void CommandReceived(char *Cmd
) { 
 167   CmdsParse(CommandTable
, Cmd
); 
 170 //----------------------------------------------------------------------------- 
 171 // Entry point into our code: called whenever we received a packet over USB 
 172 // that we weren't necessarily expecting, for example a debug print. 
 173 //----------------------------------------------------------------------------- 
 174 void UsbCommandReceived(UsbCommand 
*UC
) 
 178   printf("UsbCommand length[len=%zd]\n",sizeof(UsbCommand)); 
 179   printf("  cmd[len=%zd]: %"llx"\n",sizeof(UC->cmd),UC->cmd); 
 180   printf(" arg0[len=%zd]: %"llx"\n",sizeof(UC->arg[0]),UC->arg[0]); 
 181   printf(" arg1[len=%zd]: %"llx"\n",sizeof(UC->arg[1]),UC->arg[1]); 
 182   printf(" arg2[len=%zd]: %"llx"\n",sizeof(UC->arg[2]),UC->arg[2]); 
 183   printf(" data[len=%zd]: %02x%02x%02x...\n",sizeof(UC->d.asBytes),UC->d.asBytes[0],UC->d.asBytes[1],UC->d.asBytes[2]); 
 186   //    printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command); 
 187   // If we recognize a response, return to avoid further processing 
 189       // First check if we are handling a debug message 
 190     case CMD_DEBUG_PRINT_STRING
: { 
 191       char s
[USB_CMD_DATA_SIZE
+1]; 
 192       size_t len 
= MIN(UC
->arg
[0],USB_CMD_DATA_SIZE
); 
 193       memcpy(s
,UC
->d
.asBytes
,len
); 
 195       PrintAndLog("#db# %s       ", s
); 
 199     case CMD_DEBUG_PRINT_INTEGERS
: { 
 200       PrintAndLog("#db# %08x, %08x, %08x       \r\n", UC
->arg
[0], UC
->arg
[1], UC
->arg
[2]); 
 204     case CMD_MEASURED_ANTENNA_TUNING
: { 
 206       int vLf125
, vLf134
, vHf
; 
 207       vLf125 
= UC
->arg
[0] & 0xffff; 
 208       vLf134 
= UC
->arg
[0] >> 16; 
 209       vHf 
= UC
->arg
[1] & 0xffff;; 
 210       peakf 
= UC
->arg
[2] & 0xffff; 
 211       peakv 
= UC
->arg
[2] >> 16; 
 213       PrintAndLog("# LF antenna: %5.2f V @   125.00 kHz", vLf125
/1000.0); 
 214       PrintAndLog("# LF antenna: %5.2f V @   134.00 kHz", vLf134
/1000.0); 
 215       PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1)); 
 216       PrintAndLog("# HF antenna: %5.2f V @    13.56 MHz", vHf
/1000.0); 
 218         PrintAndLog("# Your LF antenna is unusable."); 
 219       else if (peakv
<10000) 
 220         PrintAndLog("# Your LF antenna is marginal."); 
 222         PrintAndLog("# Your HF antenna is unusable."); 
 224         PrintAndLog("# Your HF antenna is marginal."); 
 227     case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
: { 
 228 //      printf("received samples: "); 
 229 //      print_hex(UC->d.asBytes,512); 
 230       sample_buf_len 
+= UC
->arg
[1]; 
 231 //      printf("samples: %zd offset: %d\n",sample_buf_len,UC->arg[0]); 
 232       memcpy(sample_buf
+(UC
->arg
[0]),UC
->d
.asBytes
,UC
->arg
[1]); 
 237 //      PrintAndLog("Receive ACK\n"); 
 241       // Maybe it's a response 
 243       switch(current_command) { 
 244         case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: { 
 245           if (UC->cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { 
 246             PrintAndLog("unrecognized command %08x\n", UC->cmd); 
 250           PrintAndLog("received samples %d\n",UC->arg[0]); 
 251           memcpy(sample_buf+UC->arg[0],UC->d.asBytes,48); 
 252           sample_buf_len += 48; 
 253 //          for(i=0; i<48; i++) sample_buf[i] = UC->d.asBytes[i]; 
 254           //received_command = UC->cmd;