mirror of
				https://github.com/RfidResearchGroup/proxmark3.git
				synced 2025-10-25 21:46:35 +08:00 
			
		
		
		
	Found that USBcommands from the device are silently overwritten if the host does not quickly enough read them, which causes problems in several places. Implemented a circular buffer which stores up to 50 commands (still tiny, memorywise) and prints out a message if the buffer wraps around (overwrites).
This commit is contained in:
		
							parent
							
								
									79c3611cf3
								
							
						
					
					
						commit
						a808a224f5
					
				
					 1 changed files with 84 additions and 51 deletions
				
			
		
							
								
								
									
										135
									
								
								client/cmdmain.c
									
										
									
									
									
								
							
							
						
						
									
										135
									
								
								client/cmdmain.c
									
										
									
									
									
								
							|  | @ -33,6 +33,14 @@ UsbCommand current_response_user; | ||||||
| static int CmdHelp(const char *Cmd); | static int CmdHelp(const char *Cmd); | ||||||
| static int CmdQuit(const char *Cmd); | static int CmdQuit(const char *Cmd); | ||||||
| 
 | 
 | ||||||
|  | //For storing command that are received from the device
 | ||||||
|  | #define CMD_BUFFER_SIZE 50 | ||||||
|  | static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; | ||||||
|  | //Points to the next empty position to write to
 | ||||||
|  | static int cmd_head;//Starts as 0
 | ||||||
|  | //Points to the position of the last unread command
 | ||||||
|  | static int cmd_tail = -1;//Starts as -1
 | ||||||
|  | 
 | ||||||
| static command_t CommandTable[] =  | static command_t CommandTable[] =  | ||||||
| { | { | ||||||
|   {"help",  CmdHelp,  1, "This help. Use '<command> help' for details of the following commands:\n"}, |   {"help",  CmdHelp,  1, "This help. Use '<command> help' for details of the following commands:\n"}, | ||||||
|  | @ -56,30 +64,31 @@ int CmdQuit(const char *Cmd) | ||||||
|   exit(0); |   exit(0); | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | /**
 | ||||||
|  |  * Waits for a certain response type. This method waits for a maximum of | ||||||
|  |  * ms_timeout milliseconds for a specified response command. | ||||||
|  |  *@brief WaitForResponseTimeout | ||||||
|  |  * @param cmd command to wait for | ||||||
|  |  * @param response struct to copy received command into. | ||||||
|  |  * @param ms_timeout | ||||||
|  |  * @return true if command was returned, otherwise false | ||||||
|  |  */ | ||||||
| bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { | bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { | ||||||
| 
 | 
 | ||||||
| 	// Wait until the command is received
 |   // Wait until the command is received
 | ||||||
|   for(size_t i=0; received_command != cmd && i < ms_timeout/10; i++) { |   for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { | ||||||
| 		msleep(10); // XXX ugh
 | 
 | ||||||
|     if (i == 200) { // Two seconds elapsed
 |       if(getCommand(response) && response->cmd == cmd){ | ||||||
|       PrintAndLog("Waiting for a response from the proxmark..."); |           //We got what we expected
 | ||||||
|       PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); |           return true; | ||||||
|     } |       } | ||||||
|  |         msleep(10); // XXX ugh
 | ||||||
|  |         if (dm_seconds == 200) { // Two seconds elapsed
 | ||||||
|  |           PrintAndLog("Waiting for a response from the proxmark..."); | ||||||
|  |           PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); | ||||||
|  |         } | ||||||
| 	} | 	} | ||||||
| 	 |     return false; | ||||||
|   // Check if timeout occured
 |  | ||||||
|   if(received_command != cmd) return false; |  | ||||||
| 
 |  | ||||||
| 	// Copy the received response (if supplied)
 |  | ||||||
|   if (response) { |  | ||||||
|     memcpy(response, ¤t_response, sizeof(UsbCommand)); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| 	// Reset the received command
 |  | ||||||
|   received_command = CMD_UNKNOWN; |  | ||||||
| 
 |  | ||||||
| 	return true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool WaitForResponse(uint32_t cmd, UsbCommand* response) { | bool WaitForResponse(uint32_t cmd, UsbCommand* response) { | ||||||
|  | @ -183,37 +192,61 @@ void UsbCommandReceived(UsbCommand *UC) | ||||||
|         default: { |         default: { | ||||||
|         } break; |         } break; | ||||||
|       } |       } | ||||||
| //      // Store the last received command
 |  | ||||||
| //      memcpy(¤t_response, UC, sizeof(UsbCommand));
 |  | ||||||
| //      received_command = UC->cmd;
 |  | ||||||
|     } break; |     } break; | ||||||
|   } |   } | ||||||
|   // Store the last received command
 |  | ||||||
|   memcpy(¤t_response, UC, sizeof(UsbCommand)); |  | ||||||
|   received_command = UC->cmd; |  | ||||||
| /*
 |  | ||||||
|   // Maybe it's a response:
 |  | ||||||
|   switch(current_command) { |  | ||||||
|     case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: |  | ||||||
|       if (UC->cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) goto unexpected_response; |  | ||||||
|       int i; |  | ||||||
|       for(i=0; i<48; i++) sample_buf[i] = UC->d.asBytes[i]; |  | ||||||
|       received_command = UC->cmd; |  | ||||||
|       return; |  | ||||||
|     case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K: |  | ||||||
|     case CMD_DOWNLOADED_SIM_SAMPLES_125K: |  | ||||||
|       if (UC->cmd != CMD_ACK) goto unexpected_response; |  | ||||||
|       // got ACK
 |  | ||||||
|       received_command = UC->cmd; |  | ||||||
|       return; |  | ||||||
|     default: |  | ||||||
|     unexpected_response: |  | ||||||
| 
 | 
 | ||||||
| 	if(UC->cmd != CMD_ACK) |   storeCommand(UC); | ||||||
| 		PrintAndLog("unrecognized command %08x       \n", UC->cmd); | 
 | ||||||
| 	else | } | ||||||
| 		memcpy(¤t_response, UC, sizeof(UsbCommand)); | /**
 | ||||||
| 	received_command = UC->cmd; |  * @brief storeCommand stores a USB command in a circular buffer | ||||||
|   } |  * @param UC | ||||||
|  */ |  */ | ||||||
|  | void storeCommand(UsbCommand *command) | ||||||
|  | { | ||||||
|  |     if(cmd_head == cmd_tail) | ||||||
|  |     { | ||||||
|  |         //If these two are equal, we're about to overwrite in the
 | ||||||
|  |         // circular buffer.
 | ||||||
|  |         PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!"); | ||||||
|  |     } | ||||||
|  |     //Store the command at the 'head' location
 | ||||||
|  |     UsbCommand* destination = &cmdBuffer[cmd_head]; | ||||||
|  |     memcpy(destination, command, sizeof(UsbCommand)); | ||||||
|  | 
 | ||||||
|  |     //Also, if cmd_tail is still -1 because the buffer was
 | ||||||
|  |     // previously empty, set it to head
 | ||||||
|  |     if(cmd_tail < 0) { | ||||||
|  |         cmd_tail = cmd_head; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     cmd_head++; //increment head
 | ||||||
|  |     cmd_head %= CMD_BUFFER_SIZE;//wrap around
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | /**
 | ||||||
|  |  * @brief getCommand gets a command from an internal circular buffer. | ||||||
|  |  * @param response location to write command | ||||||
|  |  * @return 1 if response was returned, 0 if nothing has been received | ||||||
|  |  */ | ||||||
|  | int getCommand(UsbCommand* response) | ||||||
|  | { | ||||||
|  |     //If head == tail, there's nothing to read, or if we just got initialized
 | ||||||
|  |     if(cmd_head == cmd_tail || cmd_tail == -1){ | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |     //Pick out the next unread command
 | ||||||
|  |     UsbCommand* last_unread = &cmdBuffer[cmd_tail]; | ||||||
|  |     memcpy(response, last_unread, sizeof(UsbCommand)); | ||||||
|  |     //Increment tail - this is a circular buffer, so modulo buffer size
 | ||||||
|  |     cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE; | ||||||
|  |     //In order to detect when the buffer overwrites itself, we set the
 | ||||||
|  |     // tail to -1 whenever it 'catches up' with head : this means the buffer is empty.
 | ||||||
|  |     // Otherwise, head==tail could mean both: either empty or full.
 | ||||||
|  |     if(cmd_tail == cmd_head){ | ||||||
|  |         cmd_tail = -1 ; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return 1; | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue