diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 2ab2c4c0e..82a3015df 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -632,7 +632,6 @@ void ListenReaderField(int limit) { void UsbPacketReceived(uint8_t *packet, int len) { UsbCommand *c = (UsbCommand *)packet; - //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d", len, c->cmd, c->arg[0], c->arg[1], c->arg[2]); switch (c->cmd) { @@ -1106,8 +1105,12 @@ void UsbPacketReceived(uint8_t *packet, int len) { char dest[USB_CMD_DATA_SIZE]={'\0'}; - sprintf(dest, usart_dataavailable() ? "DATA!\r\n" : "no data\r\n"); - cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); + if (usart_dataavailable()) { + Dbprintf("RX DATA!"); + uint16_t len = usart_readbuffer((uint8_t*)dest); + dest[len] = '\0'; + Dbprintf("RX: %d | %02X %02X %02X %02X %02X %02X %02X %02X ", len, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); + } static const char *welcome = "Proxmark3 Serial interface via FPC ready\r\n"; usart_writebuffer((uint8_t *)welcome, strlen(welcome)); @@ -1126,9 +1129,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { //usb cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); - - sprintf(dest, usart_dataavailable() ? "DATA!\r\n" : "no data\r\n"); - cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); LED_A_OFF(); /* uint8_t my_rx[sizeof(UsbCommand)]; @@ -1560,16 +1560,17 @@ void __attribute__((noreturn)) AppMain(void) { // Check if there is a usb packet available if (usb_poll_validate_length()) { if (usb_read(rx, sizeof(rx))) +#ifdef WITH_FPC_HOST + reply_via_fpc = 0; +#endif UsbPacketReceived(rx, sizeof(rx)); } -#ifdef WITH_FPC - // Check is there is FPC package available - /* - usart_init(); - if (usart_readbuffer(rx, sizeof(rx)) ) - UsbPacketReceived(rx, sizeof(rx) ); - */ - +#ifdef WITH_FPC_HOST + // Check if there is a FPC packet available + if (usart_readcommand(rx) > 0) { + reply_via_fpc = 1; + UsbPacketReceived(rx, sizeof(rx)); + } #endif // Press button for one second to enter a possible standalone mode diff --git a/client/cmdhw.c b/client/cmdhw.c index d40e5db4c..080f5fb28 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -423,7 +423,7 @@ int CmdVersion(const char *Cmd) { #else PrintAndLogEx(NORMAL, "\n\e[34m [ Proxmark3 RFID instrument ]\e[0m\n"); #endif - char s[50] = {0}; + char s[60] = {0}; #if defined(WITH_FLASH) || defined(WITH_SMARTCARD) || defined(WITH_FPC) strncat(s, "build for RDV40 with ", sizeof(s) - strlen(s) - 1); #endif @@ -434,7 +434,11 @@ int CmdVersion(const char *Cmd) { strncat(s, "smartcard; ", sizeof(s) - strlen(s) - 1); #endif #ifdef WITH_FPC + #ifdef WITH_FPC_HOST + strncat(s, "fpc-host; ", sizeof(s) - strlen(s) - 1); + #else strncat(s, "fpc; ", sizeof(s) - strlen(s) - 1); + #endif #endif PrintAndLogEx(NORMAL, "\n [ CLIENT ]"); PrintAndLogEx(NORMAL, " client: iceman %s \n", s); diff --git a/client/comms.c b/client/comms.c index de6394915..9ffa37977 100644 --- a/client/comms.c +++ b/client/comms.c @@ -194,7 +194,7 @@ static void UsbCommandReceived(UsbCommand *c) { /* bool hookUpPM3() { bool ret = false; - sp = uart_open( comport ); + sp = uart_open( comport, speed ); if (sp == INVALID_SERIAL_PORT) { PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: invalid serial port)\n"); @@ -298,17 +298,17 @@ __attribute__((force_align_arg_pointer)) return NULL; } -bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) { +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) { char *portname = (char *)port; if (!wait_for_port) { - sp = uart_open(portname); + sp = uart_open(portname, speed); } else { PrintAndLogEx(SUCCESS, "Waiting for Proxmark to appear on " _YELLOW_("%s"), portname); fflush(stdout); int openCount = 0; do { - sp = uart_open(portname); + sp = uart_open(portname, speed); msleep(500); printf("."); fflush(stdout); diff --git a/client/comms.h b/client/comms.h index f56bdb57e..b0687ac60 100644 --- a/client/comms.h +++ b/client/comms.h @@ -54,7 +54,8 @@ void *uart_receiver(void *targ); void SendCommand(UsbCommand *c); void clearCommandBuffer(); -bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode); +#define FLASHMODE_SPEED 460800 +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed); void CloseProxmark(void); bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand *response, size_t ms_timeout, bool show_warning); diff --git a/client/flash.c b/client/flash.c index 7a8b86d20..defcd7feb 100644 --- a/client/flash.c +++ b/client/flash.c @@ -321,7 +321,7 @@ static int enter_bootloader(char *serial_port_name) { // Let time to OS to make the port disappear msleep(1000); - bool opened = OpenProxmark(serial_port_name, true, 60, true); + bool opened = OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED); if (opened) { fprintf(stdout, " " _GREEN_("Found") "\n"); return 0; diff --git a/client/flasher.c b/client/flasher.c index 6e79ca70c..bc744b339 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -81,7 +81,7 @@ int main(int argc, char **argv) { char *serial_port_name = argv[1]; - if (!OpenProxmark(serial_port_name, true, 60, true)) { + if (!OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { fprintf(stderr, "Could not find Proxmark on " _RED_("%s") ".\n\n", serial_port_name); return -1; } else { diff --git a/client/proxmark3.c b/client/proxmark3.c index e54f0ce74..add7cf287 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -259,6 +259,9 @@ int main(int argc, char *argv[]) { bool addLuaExec = false; char *script_cmds_file = NULL; char *script_cmd = NULL; + char *lastarg = NULL; + char *port = NULL; + uint32_t speed = 0; /* initialize history */ using_history(); @@ -272,7 +275,9 @@ int main(int argc, char *argv[]) { return 1; } - for (int i = 1; i < argc; i++) { + uint32_t i = 1; + port = argv[i++]; + for (i; i < argc; i++) { // helptext if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) { @@ -291,29 +296,58 @@ int main(int argc, char *argv[]) { if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-flush") == 0) { SetFlushAfterWrite(true); PrintAndLogEx(INFO, "Output will be flushed after every print.\n"); + continue; + } + + // set baudrate + if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-baud") == 0) { + uint32_t tmpspeed = strtoul(argv[i+1], NULL, 10); + if ((tmpspeed == ULONG_MAX) || (tmpspeed == 0)) { + PrintAndLogEx(WARNING, "ERROR: invalid baudrate: %s %s\n", argv[i], argv[i+1]); + return 1; + } + speed = tmpspeed; + i++; + continue; } // wait for comport if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-wait") == 0) { waitCOMPort = true; + continue; } // execute pm3 command if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-command") == 0) { executeCommand = true; + continue; } // execute lua script if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "-lua") == 0) { executeCommand = true; addLuaExec = true; + continue; + } + + if (i < argc - 1) { + // We got an unknown parameter + PrintAndLogEx(WARNING, "WARNING: ignoring invalid parameter: %s\n", argv[i]); + } + + if (i == argc - 1) { + // We got presumably a command or a filename + lastarg = argv[argc - 1]; } } + if (speed == 0) + speed = 460800; + // If the user passed the filename of the 'script' to execute, get it from last parameter - if (argc > 2 && argv[argc - 1] && argv[argc - 1][0] != '-') { + if (lastarg) { if (executeCommand) { - script_cmd = argv[argc - 1]; + script_cmd = lastarg; while (script_cmd[strlen(script_cmd) - 1] == ' ') script_cmd[strlen(script_cmd) - 1] = 0x00; @@ -336,7 +370,7 @@ int main(int argc, char *argv[]) { PrintAndLogEx(SUCCESS, "execute command from commandline: %s\n", script_cmd); } } else { - script_cmds_file = argv[argc - 1]; + script_cmds_file = lastarg; } } @@ -358,7 +392,7 @@ int main(int argc, char *argv[]) { set_my_executable_path(); // try to open USB connection to Proxmark - usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false); + usb_present = OpenProxmark(port, waitCOMPort, 20, false, speed); #ifdef HAVE_GUI diff --git a/common/Makefile.hal b/common/Makefile.hal index 0e109340e..717d59110 100644 --- a/common/Makefile.hal +++ b/common/Makefile.hal @@ -35,7 +35,7 @@ ifeq ($(PLATFORM),PM3RDV4) PLTNAME = Proxmark3 rdv4 else ifeq ($(PLATFORM),PM3RDV4FPC) MCU = AT91SAM7S512 - PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DWITH_FPC + PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DWITH_FPC_HOST PLTNAME = Proxmark3 rdv4 else ifeq ($(PLATFORM),PM3EVO) MCU = AT91SAM7S512 @@ -56,6 +56,11 @@ else $(error Invalid or empty PLATFORM: $(PLATFORM). Known platforms: $(KNOWN_PLATFORMS)) endif +# Add flags dependencies +ifneq (,$(findstring WITH_FPC_,$(PLATFORM_DEFS))) + PLATFORM_DEFS += -DWITH_FPC +endif + export PLATFORM export PLTNAME export MCU diff --git a/common/cmd.c b/common/cmd.c index 3b45c08ad..0f37fb2db 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -31,6 +31,17 @@ */ #include "cmd.h" +#ifdef WITH_FPC_HOST +// "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART +bool reply_via_fpc = 0; + +extern void Dbprintf(const char *fmt, ...); +#define Dbprintf_usb(...) {\ + reply_via_fpc = 0;\ + Dbprintf(__VA_ARGS__);\ + reply_via_fpc = 1;} +#endif + uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) { UsbCommand txcmd; @@ -53,11 +64,16 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void uint32_t sendlen = 0; // Send frame and make sure all bytes are transmitted - sendlen = usb_write((uint8_t *)&txcmd, sizeof(UsbCommand)); -#ifdef WITH_FPC -// usart_init(); -// usart_writebuffer( (uint8_t*)&txcmd, sizeof(UsbCommand) ); +#ifdef WITH_FPC_HOST + if (reply_via_fpc) { + sendlen = usart_writebuffer( (uint8_t*)&txcmd, sizeof(UsbCommand) ); + Dbprintf_usb("Sent %i bytes over usart", len); + } else { + sendlen = usb_write((uint8_t *)&txcmd, sizeof(UsbCommand)); + } +#else + sendlen = usb_write((uint8_t *)&txcmd, sizeof(UsbCommand)); #endif return sendlen; diff --git a/common/usart.c b/common/usart.c index 2bfa79280..b29c5cb88 100644 --- a/common/usart.c +++ b/common/usart.c @@ -10,6 +10,7 @@ //----------------------------------------------------------------------------- #include "usart.h" #include "string.h" +#include "apps.h" // for Dbprintf #define AT91_BAUD_RATE 115200 @@ -39,52 +40,58 @@ void usart_close(void) { } */ +static uint8_t us_inbuf[sizeof(UsbCommand)]; static uint8_t us_outbuf[sizeof(UsbCommand)]; -/// Reads data from an USART peripheral -/// \param data Pointer to the buffer where the received data will be stored. -/// \param len Size of the data buffer (in bytes). -inline int16_t usart_readbuffer(uint8_t *data, size_t len) { - - // Check if the first PDC bank is free - if (!(pUS1->US_RCR)) { - pUS1->US_RPR = (uint32_t)data; - pUS1->US_RCR = len; - - pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; - return 2; - } - // Check if the second PDC bank is free - else if (!(pUS1->US_RNCR)) { - pUS1->US_RNPR = (uint32_t)data; - pUS1->US_RNCR = len; - - pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; - return 1; +// transfer from client to device +inline int16_t usart_readbuffer(uint8_t *data) { + uint32_t rcr = pUS1->US_RCR; + if (rcr < sizeof(us_inbuf)) { + pUS1->US_PTCR = AT91C_PDC_RXTDIS; + memcpy(data, us_inbuf, sizeof(us_inbuf) - rcr); + // Reset DMA buffer + pUS1->US_RPR = (uint32_t)us_inbuf; + pUS1->US_RCR = sizeof(us_inbuf); + pUS1->US_PTCR = AT91C_PDC_RXTEN; + return sizeof(us_inbuf) - rcr; } else { return 0; } } inline bool usart_dataavailable(void) { - return (pUS1->US_CSR & AT91C_US_RXRDY) != 0; + return pUS1->US_RCR < sizeof(us_inbuf); +} + +inline int16_t usart_readcommand(uint8_t *data) { + if (pUS1->US_RCR == 0) + return usart_readbuffer(data); + else + return 0; +} + +inline bool usart_commandavailable(void) { + return pUS1->US_RCR == 0; } // transfer from device to client inline int16_t usart_writebuffer(uint8_t *data, size_t len) { - if (pUS1->US_TCR == 0) { + + + if (pUS1->US_CSR & AT91C_US_ENDTX) { memcpy(us_outbuf, data, len); pUS1->US_TPR = (uint32_t)us_outbuf; pUS1->US_TCR = len; - - pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTDIS; - while((pUS1->US_CSR & AT91C_US_TXEMPTY) ==0) {}; - return 2; + pUS1->US_PTCR = AT91C_PDC_TXTEN; + while(!(pUS1->US_CSR & AT91C_US_ENDTX)) {}; + pUS1->US_PTCR = AT91C_PDC_TXTDIS; + return len; } else { return 0; } } + void usart_init(void) { // For a nice detailed sample, interrupt driven but still relevant. @@ -128,6 +135,17 @@ void usart_init(void) { pUS1->US_FIDI = 0; pUS1->US_IF = 0; + // Disable double buffers for now + pUS1->US_TNPR = (uint32_t)0; + pUS1->US_TNCR = 0; + pUS1->US_RNPR = (uint32_t)0; + pUS1->US_RNCR = 0; + + // re-enable receiver / transmitter pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); + // ready to receive + pUS1->US_RPR = (uint32_t)us_inbuf; + pUS1->US_RCR = sizeof(us_inbuf); + pUS1->US_PTCR = AT91C_PDC_RXTEN; } diff --git a/common/usart.h b/common/usart.h index c49b0a8fd..f98424841 100644 --- a/common/usart.h +++ b/common/usart.h @@ -7,7 +7,9 @@ void usart_init(void); void usart_close(void); -int16_t usart_readbuffer(uint8_t *data, size_t len); +int16_t usart_readbuffer(uint8_t *data); int16_t usart_writebuffer(uint8_t *data, size_t len); bool usart_dataavailable(void); +int16_t usart_readcommand(uint8_t *data); +bool usart_commandavailable(void); #endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index a15229969..99563d0fa 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -34,6 +34,12 @@ typedef struct { uint32_t asDwords[USB_CMD_DATA_SIZE / 4]; } d; } PACKED UsbCommand; + +#ifdef WITH_FPC_HOST + // "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART + extern bool reply_via_fpc; +#endif + // A struct used to send sample-configs over USB typedef struct { uint8_t decimation; diff --git a/uart/uart.h b/uart/uart.h index 582f394e7..714f646b9 100644 --- a/uart/uart.h +++ b/uart/uart.h @@ -71,7 +71,7 @@ typedef void *serial_port; * * On errors, this method returns INVALID_SERIAL_PORT or CLAIMED_SERIAL_PORT. */ -serial_port uart_open(const char *pcPortName); +serial_port uart_open(const char *pcPortName, uint32_t speed); /* Closes the given port. */ diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 0b12cd76b..92af6774a 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -73,7 +73,7 @@ struct timeval timeout = { .tv_usec = 30000 // 30 000 micro seconds }; -serial_port uart_open(const char *pcPortName) { +serial_port uart_open(const char *pcPortName, uint32_t speed) { serial_port_unix *sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); if (sp == 0) return INVALID_SERIAL_PORT; @@ -194,14 +194,19 @@ serial_port uart_open(const char *pcPortName) { // Flush all lingering data that may exist tcflush(sp->fd, TCIOFLUSH); - // set speed, works for UBUNTU 14.04 - bool success = uart_set_speed(sp, 460800); - if (success) { - printf("[=] UART Setting serial baudrate 460800\n"); - } else { - uart_set_speed(sp, 115200); - printf("[=] UART Setting serial baudrate 115200\n"); + if (!uart_set_speed(sp, speed)) { + // trying some fallbacks automatically + speed = 115200; + if (!uart_set_speed(sp, speed)) { + speed = 9600; + if (!uart_set_speed(sp, speed)) { + uart_close(sp); + printf("[!] UART error while setting baudrate\n"); + return INVALID_SERIAL_PORT; + } + } } + printf("[=] UART Setting serial baudrate %i\n", speed); return sp; } diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 6107a564e..2ed5c9bcf 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -48,7 +48,7 @@ typedef struct { COMMTIMEOUTS ct; // Serial port time-out configuration } serial_port_windows; -serial_port uart_open(const char *pcPortName) { +serial_port uart_open(const char *pcPortName, uint32_t speed) { char acPortName[255]; serial_port_windows *sp = calloc(sizeof(serial_port_windows), sizeof(uint8_t)); @@ -87,6 +87,7 @@ serial_port uart_open(const char *pcPortName) { // all zero's configure: no timeout for read/write used. // took settings from libnfc/buses/uart.c #ifdef WITH_FPC + // Still relevant? sp->ct.ReadIntervalTimeout = 1000; sp->ct.ReadTotalTimeoutMultiplier = 0; sp->ct.ReadTotalTimeoutConstant = 1500; @@ -108,22 +109,19 @@ serial_port uart_open(const char *pcPortName) { PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); -#ifdef WITH_FPC - if (uart_set_speed(sp, 115200)) { - printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); - } else { - uart_set_speed(sp, 9600); - printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); + if (!uart_set_speed(sp, speed)) { + // trying some fallbacks automatically + speed = 115200; + if (!uart_set_speed(sp, speed)) { + speed = 9600; + if (!uart_set_speed(sp, speed)) { + uart_close(sp); + printf("[!] UART error while setting baudrate\n"); + return INVALID_SERIAL_PORT; + } + } } -#else - bool success = uart_set_speed(sp, 460800); - if (success) { - printf("[=] UART Setting serial baudrate 460800\n"); - } else { - uart_set_speed(sp, 115200); - printf("[=] UART Setting serial baudrate 115200\n"); - } -#endif + printf("[=] UART Setting serial baudrate %i\n", speed); return sp; }