Merge pull request #1 from Proxmark/master

sync
This commit is contained in:
andrerodr 2020-02-12 00:02:35 +01:00 committed by GitHub
commit d5975d4dfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 1282 additions and 1257 deletions

View file

@ -50,8 +50,7 @@ THUMBSRC = start.c \
printf.c \
util.c \
string.c \
usb_cdc.c \
cmd.c
usb_cdc.c
# Compile these in thumb mode optimized for speed (still smaller than ARM mode)
THUMBOPTSRC = $(SRC_ISO15693)

View file

@ -13,7 +13,6 @@
#include <stdarg.h>
#include "usb_cdc.h"
#include "cmd.h"
#include "proxmark3.h"
#include "apps.h"
#include "fpga.h"
@ -312,6 +311,7 @@ void set_hw_capabilities(void) {
void SendVersion(void) {
LED_A_ON();
set_hw_capabilities();
char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
@ -347,7 +347,8 @@ void SendVersion(void) {
// Send Chip ID and used flash memory
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
uint32_t compressed_data_section_size = common_area.arg1;
cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, hw_capabilities, VersionString, strlen(VersionString));
cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, hw_capabilities, VersionString, strlen(VersionString) + 1);
LED_A_OFF();
}
// measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
@ -363,13 +364,11 @@ void printUSBSpeed(void) {
uint32_t start_time = end_time = GetTickCount();
uint32_t bytes_transferred = 0;
LED_B_ON();
while(end_time < start_time + USB_SPEED_TEST_MIN_TIME) {
while (end_time < start_time + USB_SPEED_TEST_MIN_TIME) {
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, 0, USB_CMD_DATA_SIZE, 0, test_data, USB_CMD_DATA_SIZE);
end_time = GetTickCount();
bytes_transferred += USB_CMD_DATA_SIZE;
}
LED_B_OFF();
Dbprintf(" Time elapsed: %dms", end_time - start_time);
Dbprintf(" Bytes transferred: %d", bytes_transferred);
@ -382,6 +381,7 @@ void printUSBSpeed(void) {
* Prints runtime information about the PM3.
**/
void SendStatus(void) {
LED_A_ON();
BigBuf_print_status();
Fpga_print_status();
#ifdef WITH_SMARTCARD
@ -394,7 +394,8 @@ void SendStatus(void) {
Dbprintf(" ToSendMax..........%d", ToSendMax);
Dbprintf(" ToSendBit..........%d", ToSendBit);
cmd_send(CMD_ACK,1,0,0,0,0);
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
LED_A_OFF();
}
#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF_StandAlone)
@ -936,9 +937,7 @@ void ListenReaderField(int limit) {
}
void UsbPacketReceived(uint8_t *packet, int len) {
UsbCommand *c = (UsbCommand *)packet;
void UsbPacketReceived(UsbCommand *c) {
// 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]);
@ -1337,9 +1336,11 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break;
case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
LED_A_ON();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200);
LED_D_OFF(); // LED D indicates field ON or OFF
LED_A_OFF();
break;
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
@ -1428,7 +1429,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_DEVICE_INFO: {
uint32_t dev_info = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;
if(common_area.flags.bootrom_present) dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0);
cmd_send_old(CMD_DEVICE_INFO,dev_info,0,0,0,0);
break;
}
default:
@ -1479,13 +1480,12 @@ void __attribute__((noreturn)) AppMain(void) {
LCDInit();
#endif
uint8_t rx[sizeof(UsbCommand)];
size_t rx_len;
UsbCommand rx;
for(;;) {
WDT_HIT();
if (usb_poll() && (rx_len = usb_read(rx, sizeof(rx)))) {
UsbPacketReceived(rx, rx_len);
if (cmd_receive(&rx)) {
UsbPacketReceived(&rx);
} else {
#if defined(WITH_LF_StandAlone) && !defined(WITH_ISO14443a_StandAlone)
if (BUTTON_HELD(1000) > 0)

View file

@ -112,8 +112,4 @@ void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
// cmd.h
bool cmd_receive(UsbCommand* cmd);
bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
#endif

View file

@ -15,7 +15,7 @@
#include "iso14443a.h"
#include "iso14443b.h"
#include "epa.h"
#include "cmd.h"
#include "usb_cdc.h"
#include "fpgaloader.h"
#include "string.h"
#include "util.h"
@ -453,20 +453,17 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
//-----------------------------------------------------------------------------
// Perform the PACE protocol by replaying given APDUs
//-----------------------------------------------------------------------------
void EPA_PACE_Replay(UsbCommand *c)
{
void EPA_PACE_Replay(UsbCommand *c) {
uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};
// if an APDU has been passed, save it
// if an APDU has been passed, just save it
if (c->arg[0] != 0) {
// make sure it's not too big
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len)
{
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len) {
cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
return;
}
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
c->d.asBytes,
c->arg[2]);
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], c->d.asBytes, c->arg[2]);
// save/update APDU length
if (c->arg[1] == 0) {
apdu_lengths_replay[c->arg[0] - 1] = c->arg[2];

View file

@ -14,7 +14,7 @@
#include "BigBuf.h"
#include "util.h"
#include "apps.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "usb_cdc.h"
#include "fpga.h"
#include "fpgaloader.h"

View file

@ -19,7 +19,7 @@
#include "hitag2.h"
#include "proxmark3.h"
#include "cmd.h"
#include "usb_cdc.h"
#include "apps.h"
#include "util.h"
#include "hitag.h"

View file

@ -17,6 +17,7 @@
#include <stdlib.h>
#include "proxmark3.h"
#include "apps.h"
#include "usb_cdc.h"
#include "util.h"
#include "hitag.h"
#include "string.h"

View file

@ -18,6 +18,7 @@
#include "mifareutil.h" // for MF_DBGLEVEL
#include "BigBuf.h"
#include "apps.h"
#include "usb_cdc.h"
#ifdef WITH_SMARTCARD
#include "smartcard.h"

View file

@ -24,7 +24,7 @@
#include "string.h"
#include "printf.h"
#include "common.h"
#include "cmd.h"
#include "usb_cdc.h"
#include "iso14443a.h"
#include "iso15693.h"
// Needed for CRC in emulation mode;
@ -34,7 +34,6 @@
#include "iso15693tools.h"
#include "protocols.h"
#include "optimized_cipher.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "fpgaloader.h"
// iCLASS has a slightly different timing compared to ISO15693. According to the picopass data sheet the tag response is expected 330us after
@ -675,14 +674,14 @@ static bool selectIclassTag(uint8_t *card_data, uint32_t *eof_time) {
// Send act_all
ReaderTransmitIClass(act_all, 1, &start_time);
// Card present?
if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return false;//Fail
if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return false; //Fail
//Send Identify
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
ReaderTransmitIClass(identify, 1, &start_time);
//We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC
uint8_t len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time);
if (len != 10) return false;//Fail
if (len != 10) return false; //Fail
//Copy the Anti-collision CSN to our select-packet
memcpy(&select[1], resp, 8);
@ -691,7 +690,7 @@ static bool selectIclassTag(uint8_t *card_data, uint32_t *eof_time) {
ReaderTransmitIClass(select, sizeof(select), &start_time);
//We expect a 10-byte response here, 8 byte CSN and 2 byte CRC
len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time);
if (len != 10) return false;//Fail
if (len != 10) return false; //Fail
//Success - we got CSN
//Save CSN in response data
@ -734,42 +733,42 @@ void ReaderIClass(uint8_t flags) {
if (selectIclassTag(resp, &eof_time)) {
result_status = FLAG_ICLASS_READER_CSN;
memcpy(card_data, resp, 8);
}
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
//Read block 1, config
if (flags & FLAG_ICLASS_READER_CONF) {
if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
result_status |= FLAG_ICLASS_READER_CONF;
memcpy(card_data+8, resp, 8);
} else {
Dbprintf("Failed to read config block");
}
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
}
//Read block 2, e-purse
if (flags & FLAG_ICLASS_READER_CC) {
if (sendCmdGetResponseWithRetries(readEpurse, sizeof(readEpurse), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
result_status |= FLAG_ICLASS_READER_CC;
memcpy(card_data + (8*2), resp, 8);
} else {
Dbprintf("Failed to read e-purse");
//Read block 1, config
if (flags & FLAG_ICLASS_READER_CONF) {
if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
result_status |= FLAG_ICLASS_READER_CONF;
memcpy(card_data+8, resp, 8);
} else {
Dbprintf("Failed to read config block");
}
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
}
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
}
//Read block 5, AA
if (flags & FLAG_ICLASS_READER_AA) {
if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
result_status |= FLAG_ICLASS_READER_AA;
memcpy(card_data + (8*5), resp, 8);
} else {
Dbprintf("Failed to read AA block");
//Read block 2, e-purse
if (flags & FLAG_ICLASS_READER_CC) {
if (sendCmdGetResponseWithRetries(readEpurse, sizeof(readEpurse), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
result_status |= FLAG_ICLASS_READER_CC;
memcpy(card_data + (8*2), resp, 8);
} else {
Dbprintf("Failed to read e-purse");
}
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
}
//Read block 5, AA
if (flags & FLAG_ICLASS_READER_AA) {
if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
result_status |= FLAG_ICLASS_READER_AA;
memcpy(card_data + (8*5), resp, 8);
} else {
Dbprintf("Failed to read AA block");
}
}
}
cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
LED_A_OFF();
@ -820,9 +819,9 @@ void iClass_ReadBlk(uint8_t blockno) {
uint8_t readblockdata[10];
bool isOK = iClass_ReadBlock(blockno, readblockdata);
cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
LED_A_OFF();
}
@ -900,11 +899,10 @@ void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) {
} else {
Dbprintf("Write block [%02x] failed", blockNo);
}
cmd_send(CMD_ACK, isOK, 0, 0, 0, 0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
cmd_send(CMD_ACK, isOK, 0, 0, 0, 0);
LED_A_OFF();
}
@ -935,6 +933,5 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
LED_D_OFF();
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
LED_A_OFF();
}

View file

@ -17,7 +17,7 @@
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "cmd.h"
#include "usb_cdc.h"
#include "iso14443crc.h"
#include "crapto1/crapto1.h"
#include "mifareutil.h"
@ -942,7 +942,7 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info, uint8_
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) {
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, uint8_t* data) {
uint8_t sak;
@ -1701,13 +1701,13 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) {
// if anticollision is false, then the UID must be provided in uid_ptr[]
// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
// requests ATS unless no_rats is true
int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
uint8_t sel_all[] = { 0x93,0x20 };
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
uint8_t resp[MAX_FRAME_SIZE]; // theoretically. A usual RATS will be much smaller
uint8_t resp_par[MAX_PARITY_SIZE];
byte_t uid_resp[4];
uint8_t uid_resp[4];
size_t uid_resp_len;
uint8_t sak = 0x04; // cascade uid
@ -2020,21 +2020,21 @@ void ReaderIso14443a(UsbCommand *c) {
size_t lenbits = c->arg[1] >> 16;
uint32_t timeout = c->arg[2];
uint32_t arg0 = 0;
byte_t buf[USB_CMD_DATA_SIZE] = {0};
uint8_t buf[USB_CMD_DATA_SIZE] = {0};
uint8_t par[MAX_PARITY_SIZE];
bool cantSELECT = false;
set_tracing(true);
if(param & ISO14A_CLEAR_TRACE) {
if (param & ISO14A_CLEAR_TRACE) {
clear_trace();
}
if(param & ISO14A_REQUEST_TRIGGER) {
if (param & ISO14A_REQUEST_TRIGGER) {
iso14a_set_trigger(true);
}
if(param & ISO14A_CONNECT) {
if (param & ISO14A_CONNECT) {
LED_A_ON();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
if(!(param & ISO14A_NO_SELECT)) {
@ -2048,16 +2048,16 @@ void ReaderIso14443a(UsbCommand *c) {
}
FpgaDisableTracing();
LED_B_ON();
cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
cmd_send(CMD_NACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
LED_B_OFF();
}
}
if(param & ISO14A_SET_TIMEOUT) {
if (param & ISO14A_SET_TIMEOUT) {
iso14a_set_timeout(timeout);
}
if(param & ISO14A_APDU && !cantSELECT) {
if (param & ISO14A_APDU && !cantSELECT) {
uint8_t res;
arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res);
FpgaDisableTracing();
@ -2066,8 +2066,8 @@ void ReaderIso14443a(UsbCommand *c) {
LED_B_OFF();
}
if(param & ISO14A_RAW && !cantSELECT) {
if(param & ISO14A_APPEND_CRC) {
if (param & ISO14A_RAW && !cantSELECT) {
if (param & ISO14A_APPEND_CRC) {
if(param & ISO14A_TOPAZMODE) {
AppendCrc14443b(cmd,len);
} else {
@ -2076,8 +2076,8 @@ void ReaderIso14443a(UsbCommand *c) {
len += 2;
if (lenbits) lenbits += 16;
}
if(lenbits>0) { // want to send a specific number of bits (e.g. short commands)
if(param & ISO14A_TOPAZMODE) {
if (lenbits > 0) { // want to send a specific number of bits (e.g. short commands)
if (param & ISO14A_TOPAZMODE) {
int bits_to_send = lenbits;
uint16_t i = 0;
ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity
@ -2091,7 +2091,7 @@ void ReaderIso14443a(UsbCommand *c) {
ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity
}
} else { // want to send complete bytes only
if(param & ISO14A_TOPAZMODE) {
if (param & ISO14A_TOPAZMODE) {
uint16_t i = 0;
ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy
while (i < len) {
@ -2105,15 +2105,15 @@ void ReaderIso14443a(UsbCommand *c) {
FpgaDisableTracing();
LED_B_ON();
cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
cmd_send(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
LED_B_OFF();
}
if(param & ISO14A_REQUEST_TRIGGER) {
if (param & ISO14A_REQUEST_TRIGGER) {
iso14a_set_trigger(false);
}
if(param & ISO14A_NO_DISCONNECT) {
if (param & ISO14A_NO_DISCONNECT) {
return;
}

View file

@ -13,6 +13,7 @@
#ifndef __ISO14443A_H
#define __ISO14443A_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "usb_cmd.h"
@ -31,7 +32,7 @@ extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
extern void AppendCrc14443a(uint8_t *data, int len);
extern void RAMFUNC SnoopIso14443a(uint8_t param);
extern void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t *data);
extern void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, uint8_t *data);
extern void ReaderIso14443a(UsbCommand *c);
extern void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing);
extern void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);

View file

@ -14,6 +14,7 @@
#include "proxmark3.h"
#include "apps.h"
#include "usb_cdc.h"
#include "util.h"
#include "string.h"
#include "iso14443crc.h"

View file

@ -58,7 +58,7 @@
#include "string.h"
#include "iso15693tools.h"
#include "protocols.h"
#include "cmd.h"
#include "usb_cdc.h"
#include "BigBuf.h"
#include "fpgaloader.h"

View file

@ -14,6 +14,7 @@
#include "proxmark3.h"
#include "apps.h"
#include "usb_cdc.h"
#include "util.h"
#include "string.h"
#include "legic_prng.h"

View file

@ -17,7 +17,7 @@
#include "lfdemod.h"
#include "lfsampling.h"
#include "protocols.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "usb_cdc.h"
#include "fpgaloader.h"
/**

View file

@ -18,7 +18,7 @@
#include <stdint.h>
#include "proxmark3.h"
#include "cmd.h"
#include "usb_cdc.h"
#include "crapto1/crapto1.h"
#include "iso14443a.h"
#include "BigBuf.h"
@ -111,11 +111,12 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
@ -202,9 +203,10 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
return;
}
cmd_send(CMD_ACK,1,0,0,dataout,16);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
cmd_send(CMD_ACK,1,0,0,dataout,16);
LED_A_OFF();
}
@ -266,12 +268,13 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
// Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));
LED_B_OFF();
// Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
@ -362,10 +365,11 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= MF_DBG_DEBUG) Dbprintf("Blocks read %d", countblocks);
cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0);
BigBuf_free();
LED_A_OFF();
}
@ -431,13 +435,14 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
// Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,0,0);
LED_B_OFF();
// Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
@ -475,8 +480,9 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
cmd_send(CMD_ACK,1,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK,1,0,0,0,0);
LEDsoff();
}
*/
@ -544,8 +550,9 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
cmd_send(CMD_ACK,1,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK,1,0,0,0,0);
LEDsoff();
}
@ -613,8 +620,9 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
return;
};
cmd_send(CMD_ACK,1,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK,1,0,0,0,0);
LEDsoff();
}
@ -743,16 +751,17 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
crypto1_destroy(pcs);
if (field_off) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
LED_B_ON();
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
LED_B_OFF();
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
if (field_off) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
}
@ -978,13 +987,14 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
memcpy(buf+16, &target_ks[1], 4);
memcpy(buf+20, &authentication_timeout, 4);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
LED_B_ON();
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
LED_B_OFF();
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
@ -1352,13 +1362,14 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
break;
}
// reset fpga
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// send USB response
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,NULL,0);
LED_B_OFF();
// reset fpga
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
return;
@ -1490,14 +1501,15 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
break;
}
if ((workFlags & 0x10) || (!isOK)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,uid,4);
LED_B_OFF();
if ((workFlags & 0x10) || (!isOK)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
LEDsoff();
}
@ -1574,6 +1586,10 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
break;
}
if ((workFlags & 0x10) || (!isOK)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
LED_B_ON();
if (workFlags & 0x20) {
if (isOK)
@ -1583,10 +1599,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
cmd_send(CMD_ACK,isOK,0,0,data,18);
LED_B_OFF();
if ((workFlags & 0x10) || (!isOK)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
LEDsoff();
}
void MifareCIdent(){
@ -1622,11 +1635,12 @@ void MifareCIdent(){
// From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.
mifare_classic_halt(NULL, 0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,0,0);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
@ -1657,7 +1671,8 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
}
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));
cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));
}
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
@ -1671,16 +1686,17 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
isOK = mifare_desfire_des_auth2(cuid, key, dataout);
if( isOK) {
if (isOK) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");
OnError(4);
return;
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}

View file

@ -20,7 +20,6 @@
#include "fpgaloader.h"
#include "proxmark3.h"
#include "usb_cdc.h"
#include "cmd.h"
#include "protocols.h"
#include "apps.h"

View file

@ -18,7 +18,7 @@
#include "crapto1/crapto1.h"
#include "mifareutil.h"
#include "common.h"
#include "cmd.h"
#include "usb_cdc.h"
#include "BigBuf.h"
#include "fpgaloader.h"
@ -152,7 +152,7 @@ bool intMfSniffSend() {
while (pckLen > 0) {
pckSize = MIN(USB_CMD_DATA_SIZE, pckLen);
LED_B_ON();
cmd_send(CMD_ACK, 1, BigBuf_get_traceLen(), pckSize, trace + BigBuf_get_traceLen() - pckLen, pckSize);
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, 1, BigBuf_get_traceLen(), pckSize, trace + BigBuf_get_traceLen() - pckLen, pckSize);
LED_B_OFF();
pckLen -= pckSize;
@ -160,7 +160,7 @@ bool intMfSniffSend() {
}
LED_B_ON();
cmd_send(CMD_ACK,2,0,0,0,0);
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,2,0,0,0,0);
LED_B_OFF();
clear_trace();

View file

@ -1,5 +1,6 @@
#include "proxmark3.h"
#include "apps.h"
#include "usb_cdc.h"
#include "lfsampling.h"
#include "pcf7931.h"
#include "util.h"

View file

@ -8,12 +8,13 @@
// Utility functions used in many places, not specific to any piece of code.
//-----------------------------------------------------------------------------
#ifndef __UTIL_H
#define __UTIL_H
#ifndef UTIL_H__
#define UTIL_H__
#include <stddef.h>
#include <stdint.h>
#include "common.h"
#include "at91sam7s512.h"
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
@ -33,40 +34,40 @@
#define REV32(x) (REV16(x) | (REV16(x >> 16) << 16))
#define REV64(x) (REV32(x) | (REV32(x >> 32) << 32))
void print_result(char *name, uint8_t *buf, size_t len);
size_t nbytes(size_t nbits);
uint32_t SwapBits(uint32_t value, int nrbits);
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);
void rol(uint8_t *data, const size_t len);
void lsl (uint8_t *data, size_t len);
extern void print_result(char *name, uint8_t *buf, size_t len);
extern size_t nbytes(size_t nbits);
extern uint32_t SwapBits(uint32_t value, int nrbits);
extern void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
extern uint64_t bytes_to_num(uint8_t* src, size_t len);
extern void rol(uint8_t *data, const size_t len);
extern void lsl (uint8_t *data, size_t len);
void LED(int led, int ms);
void LEDsoff();
void LEDson();
void LEDsinvert();
int BUTTON_CLICKED(int ms);
int BUTTON_HELD(int ms);
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
extern void LED(int led, int ms);
extern void LEDsoff();
extern void LEDson();
extern void LEDsinvert();
extern int BUTTON_CLICKED(int ms);
extern int BUTTON_HELD(int ms);
extern void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
//iceman's ticks.h
#ifndef GET_TICKS
# define GET_TICKS GetTicks()
#endif
void SpinDelay(int ms);
void SpinDelayUs(int us);
extern void SpinDelay(int ms);
extern void SpinDelayUs(int us);
void StartTickCount();
uint32_t RAMFUNC GetTickCount();
extern void StartTickCount();
extern uint32_t RAMFUNC GetTickCount();
void StartCountUS();
uint32_t RAMFUNC GetCountUS();
uint32_t RAMFUNC GetDeltaCountUS();
extern void StartCountUS();
extern uint32_t RAMFUNC GetCountUS();
extern uint32_t RAMFUNC GetDeltaCountUS();
void StartCountSspClk();
void ResetSspClk(void);
uint32_t GetCountSspClk();
extern void StartCountSspClk();
extern void ResetSspClk(void);
extern uint32_t GetCountSspClk();
extern void StartTicks(void);
extern uint32_t GetTicks(void);
@ -78,6 +79,6 @@ extern void ResetTimer(AT91PS_TC timer);
extern void StopTicks(void);
// end iceman's ticks.h
uint32_t prand();
extern uint32_t prand();
#endif

View file

@ -8,7 +8,7 @@
# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code
ARMSRC =
THUMBSRC = cmd.c usb_cdc.c bootrom.c
THUMBSRC = usb_cdc.c bootrom.c
ASMSRC = ram-reset.s flash-reset.s
VERSIONSRC = version.c

View file

@ -6,17 +6,15 @@
// Main code for the bootloader
//-----------------------------------------------------------------------------
#include <proxmark3.h>
#include "proxmark3.h"
#include "usb_cdc.h"
#include "cmd.h"
//#include "usb_hid.h"
void DbpString(char *str) {
byte_t len = 0;
uint8_t len = 0;
while (str[len] != 0x00) {
len++;
}
cmd_send(CMD_DEBUG_PRINT_STRING,len,0,0,(byte_t*)str,len);
cmd_send_old(CMD_DEBUG_PRINT_STRING,len,0,0,(uint8_t*)str,len);
}
struct common_area common_area __attribute__((section(".commonarea")));
@ -89,26 +87,22 @@ static void Fatal(void)
for(;;);
}
void UsbPacketReceived(uint8_t *packet, int len) {
void UsbPacketReceived(UsbCommand *c) {
int i, dont_ack=0;
UsbCommand* c = (UsbCommand *)packet;
volatile uint32_t *p;
if(len != sizeof(UsbCommand)) {
Fatal();
}
uint32_t arg0 = (uint32_t)c->arg[0];
switch(c->cmd) {
case CMD_DEVICE_INFO: {
dont_ack = 1;
arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |
DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH;
arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT
| DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
| DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH;
if(common_area.flags.osimage_present) {
arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;
}
cmd_send(CMD_DEVICE_INFO,arg0,1,2,0,0);
cmd_send_old(CMD_DEVICE_INFO,arg0,1,2,0,0);
} break;
case CMD_SETUP_WRITE: {
@ -134,7 +128,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
if( ((flash_address+AT91C_IFLASH_PAGE_SIZE-1) >= end_addr) || (flash_address < start_addr) ) {
/* Disallow write */
dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0);
cmd_send_old(CMD_NACK,0,0,0,0,0);
} else {
uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE;
/* Translate address to flash page and do flash, update here for the 512k part */
@ -148,7 +142,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY));
if(sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0);
cmd_send_old(CMD_NACK,0,0,0,0,0);
}
}
} break;
@ -179,7 +173,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
} else {
start_addr = end_addr = 0;
dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0);
cmd_send_old(CMD_NACK,0,0,0,0,0);
}
}
} break;
@ -190,7 +184,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
}
if(!dont_ack) {
cmd_send(CMD_ACK,arg0,0,0,0,0);
cmd_send_old(CMD_ACK,arg0,0,0,0,0);
}
}
@ -199,21 +193,17 @@ static void flash_mode(int externally_entered)
start_addr = 0;
end_addr = 0;
bootrom_unlocked = 0;
byte_t rx[sizeof(UsbCommand)];
size_t rx_len;
UsbCommand rx;
usb_enable();
for (volatile size_t i=0; i<0x100000; i++) {};
usb_enable();
for (volatile size_t i=0; i<0x100000; i++) {};
for(;;) {
WDT_HIT();
if (usb_poll()) {
rx_len = usb_read(rx,sizeof(UsbCommand));
if (rx_len) {
UsbPacketReceived(rx,rx_len);
}
}
if (cmd_receive(&rx)) {
UsbPacketReceived(&rx);
}
if(!externally_entered && !BUTTON_PRESS()) {
/* Perform a reset to leave flash mode */

View file

@ -46,28 +46,28 @@ int CmdHF14AList(const char *Cmd)
return 0;
}
int Hf14443_4aGetCardData(iso14a_card_select_t * card) {
int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
WaitForResponse(CMD_NACK, &resp);
memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if(select_status == 0) {
if (select_status == 0) {
PrintAndLog("E->iso14443a card select failed");
return 1;
}
if(select_status == 2) {
if (select_status == 2) {
PrintAndLog("E->Card doesn't support iso14443-4 mode");
return 1;
}
if(select_status == 3) {
if (select_status == 3) {
PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision");
PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]);
return 1;
@ -156,20 +156,24 @@ int CmdHF14AReader(const char *Cmd) {
return 0;
}
int CmdHF14AInfo(const char *Cmd)
{
int CmdHF14AInfo(const char *Cmd) {
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
if (!WaitForResponseTimeout(CMD_NACK, &resp, 500)) {
if (Cmd[0] != 's') PrintAndLog("Error: No response from Proxmark.\n");
return 0;
}
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if(select_status == 0) {
if (select_status == 0) {
if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
// disconnect
c.arg[0] = 0;
@ -217,13 +221,13 @@ int CmdHF14AInfo(const char *Cmd)
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
WaitForResponse(CMD_NACK,&resp);
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
if(select_status == 0) {
if (select_status == 0) {
//PrintAndLog("iso14443a card select failed");
// disconnect
c.arg[0] = 0;
@ -272,7 +276,7 @@ int CmdHF14AInfo(const char *Cmd)
// Double & triple sized UID, can be mapped to a manufacturer.
// HACK: does this apply for Ultralight cards?
if ( card.uidlen > 4 ) {
if (card.uidlen > 4) {
PrintAndLog("MANUFACTURER : %s", getManufacturerName(card.uid[0]));
}
@ -430,7 +434,7 @@ int CmdHF14AInfo(const char *Cmd)
(void)mfCIdentify();
if (isMifareClassic) {
switch(DetectClassicPrng()) {
switch (DetectClassicPrng()) {
case 0:
PrintAndLog("Prng detection: HARDENED (hardnested)");
break;
@ -462,7 +466,7 @@ int CmdHF14ACUIDs(const char *Cmd)
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
WaitForResponse(CMD_NACK,&resp);
iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;

View file

@ -333,7 +333,7 @@ int HFiClassReader(bool loop, bool verbose) {
while (!ukbhit()) {
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
uint8_t readStatus = resp.arg[0] & 0xff;
uint8_t *data = resp.d.asBytes;
@ -368,7 +368,8 @@ int HFiClassReader(bool loop, bool verbose) {
if (tagFound && !loop) return 1;
} else {
if (verbose) PrintAndLog("Command execute timeout");
if (verbose) PrintAndLog("Error: No response from Proxmark.");
break;
}
if (!loop) break;
}

View file

@ -2672,7 +2672,7 @@ int CmdHF14AMfSniff(const char *Cmd){
}
UsbCommand resp;
if (WaitForResponseTimeoutW(CMD_ACK, &resp, 2000, false)) {
if (WaitForResponseTimeoutW(CMD_UNKNOWN, &resp, 2000, false)) {
res = resp.arg[0] & 0xff;
uint16_t traceLen = resp.arg[1];
len = resp.arg[2];

View file

@ -12,6 +12,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "comms.h"
#include "usb_cmd.h"
#include "cmdmain.h"

View file

@ -10,6 +10,7 @@
#include "cmdsmartcard.h"
#include <ctype.h>
#include <string.h>
#include "ui.h"
#include "cmdparser.h"

View file

@ -11,10 +11,13 @@
#include "comms.h"
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <pthread.h>
#if defined(__linux__) && !defined(NO_UNLINK)
#include <unistd.h> // for unlink()
#endif
#include <inttypes.h>
#include <time.h>
#include "uart.h"
#include "ui.h"
#include "common.h"
@ -31,7 +34,6 @@ static bool offline;
typedef struct {
bool run; // If TRUE, continue running the uart_communication thread
bool block_after_ACK; // if true, block after receiving an ACK package
} communication_arg_t;
static communication_arg_t conn;
@ -45,6 +47,9 @@ static pthread_cond_t txBufferSig = PTHREAD_COND_INITIALIZER;
// Used by UsbReceiveCommand as a ring buffer for messages that are yet to be
// processed by a command handler (WaitForResponse{,Timeout})
#define CMD_BUFFER_SIZE 50
#define CMD_BUFFER_CHECK_TIME 10 // maximum time (in ms) to wait in getCommand()
static UsbCommand rxBuffer[CMD_BUFFER_SIZE];
// Points to the next empty position to write to
@ -55,6 +60,7 @@ static int cmd_tail = 0;
// to lock rxBuffer operations from different threads
static pthread_mutex_t rxBufferMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t rxBufferSig = PTHREAD_COND_INITIALIZER;
// These wrappers are required because it is not possible to access a static
// global variable outside of the context of a single file.
@ -69,17 +75,17 @@ bool IsOffline() {
void SendCommand(UsbCommand *c) {
#ifdef COMMS_DEBUG
printf("Sending %04x cmd\n", c->cmd);
printf("Sending %04" PRIx64 " cmd\n", c->cmd);
#endif
if (offline) {
PrintAndLog("Sending bytes to proxmark failed - offline");
return;
}
}
pthread_mutex_lock(&txBufferMutex);
/**
This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive,
This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive,
but comm thread just spins here. Not good.../holiman
**/
while (txBuffer_pending) {
@ -101,8 +107,7 @@ void SendCommand(UsbCommand *c) {
* A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which
* operation. Right now we'll just have to live with this.
*/
void clearCommandBuffer()
{
void clearCommandBuffer() {
//This is a very simple operation
pthread_mutex_lock(&rxBufferMutex);
cmd_tail = cmd_head;
@ -113,11 +118,9 @@ void clearCommandBuffer()
* @brief storeCommand stores a USB command in a circular buffer
* @param UC
*/
static void storeCommand(UsbCommand *command)
{
static void storeCommand(UsbCommand *command) {
pthread_mutex_lock(&rxBufferMutex);
if( (cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail)
{
if ((cmd_head + 1) % CMD_BUFFER_SIZE == 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!");
@ -127,7 +130,8 @@ static void storeCommand(UsbCommand *command)
UsbCommand* destination = &rxBuffer[cmd_head];
memcpy(destination, command, sizeof(UsbCommand));
cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap
cmd_head = (cmd_head + 1) % CMD_BUFFER_SIZE; //increment head and wrap
pthread_cond_signal(&rxBufferSig); // tell main thread that a new command can be retreived
pthread_mutex_unlock(&rxBufferMutex);
}
@ -135,21 +139,32 @@ static void storeCommand(UsbCommand *command)
/**
* @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
* @return 1 if response was returned, 0 if nothing has been received in time
*/
static int getCommand(UsbCommand* response)
{
static int getCommand(UsbCommand* response, uint32_t ms_timeout) {
struct timespec end_time;
clock_gettime(CLOCK_REALTIME, &end_time);
end_time.tv_sec += ms_timeout / 1000;
end_time.tv_nsec += (ms_timeout % 1000) * 1000000;
if (end_time.tv_nsec > 1000000000) {
end_time.tv_nsec -= 1000000000;
end_time.tv_sec += 1;
}
pthread_mutex_lock(&rxBufferMutex);
//If head == tail, there's nothing to read, or if we just got initialized
if (cmd_head == cmd_tail){
int res = 0;
while (cmd_head == cmd_tail && !res) {
res = pthread_cond_timedwait(&rxBufferSig, &rxBufferMutex, &end_time);
}
if (res) { // timeout
pthread_mutex_unlock(&rxBufferMutex);
return 0;
}
//Pick out the next unread command
// Pick out the next unread command
UsbCommand* last_unread = &rxBuffer[cmd_tail];
memcpy(response, last_unread, sizeof(UsbCommand));
//Increment tail - this is a circular buffer, so modulo buffer size
// Increment tail - this is a circular buffer, so modulo buffer size
cmd_tail = (cmd_tail + 1) % CMD_BUFFER_SIZE;
pthread_mutex_unlock(&rxBufferMutex);
@ -161,15 +176,14 @@ static int getCommand(UsbCommand* response)
// Entry point into our code: called whenever we received a packet over USB.
// Handle debug commands directly, store all other commands in circular buffer.
//----------------------------------------------------------------------------------
static void UsbCommandReceived(UsbCommand *UC)
{
switch(UC->cmd) {
static void UsbCommandReceived(UsbCommand *UC) {
switch (UC->cmd) {
// First check if we are handling a debug message
case CMD_DEBUG_PRINT_STRING: {
char s[USB_CMD_DATA_SIZE+1];
memset(s, 0x00, sizeof(s));
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
memcpy(s,UC->d.asBytes,len);
size_t len = MIN(UC->arg[0], USB_CMD_DATA_SIZE);
memcpy(s, UC->d.asBytes,len);
PrintAndLog("#db# %s", s);
return;
} break;
@ -180,64 +194,103 @@ static void UsbCommandReceived(UsbCommand *UC)
} break;
default:
storeCommand(UC);
storeCommand(UC);
break;
}
}
static bool receive_from_serial(serial_port sp, uint8_t *rx_buf, size_t len, size_t *received_len) {
size_t bytes_read = 0;
*received_len = 0;
// we eventually need to call uart_receive several times because it may timeout in the middle of a transfer
while (uart_receive(sp, rx_buf + *received_len, len - *received_len, &bytes_read) && bytes_read && *received_len < len) {
#ifdef COMMS_DEBUG
if (bytes_read != len - *received_len) {
printf("uart_receive() returned true but not enough bytes could be received. received: %zd, wanted to receive: %zd, already received before: %zd\n",
bytes_read, len - *received_len, *received_len);
}
#endif
*received_len += bytes_read;
bytes_read = 0;
}
return (*received_len == len);
}
static void
#ifdef __has_attribute
#if __has_attribute(force_align_arg_pointer)
__attribute__((force_align_arg_pointer))
__attribute__((force_align_arg_pointer))
#endif
#endif
*uart_communication(void *targ) {
communication_arg_t *conn = (communication_arg_t*)targ;
size_t rxlen;
UsbCommand rx;
UsbCommand *prx = &rx;
uint8_t rx[sizeof(UsbCommand)];
size_t rxlen = 0;
uint8_t *prx = rx;
UsbCommand *command = (UsbCommand*)rx;
UsbResponse *response = (UsbResponse*)rx;
#if defined(__MACH__) && defined(__APPLE__)
disableAppNap("Proxmark3 polling UART");
#endif
while (conn->run) {
rxlen = 0;
bool ACK_received = false;
if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx-&rx), &rxlen) && rxlen) {
prx = rx;
size_t bytes_to_read = offsetof(UsbResponse, d); // the fixed part of a new style UsbResponse. Otherwise this will be cmd and arg[0] (64 bit each)
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
prx += rxlen;
if (prx-&rx < sizeof(UsbCommand)) {
continue;
}
UsbCommandReceived(&rx);
if (rx.cmd == CMD_ACK) {
ACK_received = true;
}
}
prx = &rx;
pthread_mutex_lock(&txBufferMutex);
if (conn->block_after_ACK) {
// if we just received an ACK, wait here until a new command is to be transmitted
if (ACK_received) {
while (!txBuffer_pending) {
pthread_cond_wait(&txBufferSig, &txBufferMutex);
if (response->cmd & CMD_VARIABLE_SIZE_FLAG) { // new style response with variable size
#ifdef COMMS_DEBUG
PrintAndLog("received new style response %04" PRIx16 ", datalen = %zd, arg[0] = %08" PRIx32 ", arg[1] = %08" PRIx32 ", arg[2] = %08" PRIx32,
response->cmd, response->datalen, response->arg[0], response->arg[1], response->arg[2]);
#endif
bytes_to_read = response->datalen;
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
UsbCommand resp;
resp.cmd = response->cmd & ~CMD_VARIABLE_SIZE_FLAG; // remove the flag
resp.arg[0] = response->arg[0];
resp.arg[1] = response->arg[1];
resp.arg[2] = response->arg[2];
memcpy(&resp.d.asBytes, &response->d.asBytes, response->datalen);
UsbCommandReceived(&resp);
if (resp.cmd == CMD_ACK) {
ACK_received = true;
}
}
} else { // old style response uses same data structure as commands. Fixed size.
#ifdef COMMS_DEBUG
PrintAndLog("received old style response %016" PRIx64 ", arg[0] = %016" PRIx64, command->cmd, command->arg[0]);
#endif
bytes_to_read = sizeof(UsbCommand) - bytes_to_read;
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
UsbCommandReceived(command);
if (command->cmd == CMD_ACK) {
ACK_received = true;
}
}
}
}
if(txBuffer_pending) {
pthread_mutex_lock(&txBufferMutex);
// if we received an ACK the PM has done its job and waits for another command.
// We therefore can wait here as well until a new command is to be transmitted.
// The advantage is that the next command will be transmitted immediately without the need to wait for a receive timeout
if (ACK_received) {
while (!txBuffer_pending) {
pthread_cond_wait(&txBufferSig, &txBufferMutex);
}
}
if (txBuffer_pending) {
if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) {
PrintAndLog("Sending bytes to proxmark failed");
}
txBuffer_pending = false;
pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty
}
pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty
pthread_mutex_unlock(&txBufferMutex);
}
@ -262,21 +315,30 @@ __attribute__((force_align_arg_pointer))
* @param show_warning display message after 2 seconds
* @return true if command was returned, otherwise false
*/
bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning)
{
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
SendCommand(&c);
bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning) {
uint64_t start_time = msclock();
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
SendCommand(&c);
UsbCommand resp;
if (response == NULL) {
if (response == NULL) {
response = &resp;
}
int bytes_completed = 0;
while(true) {
if (getCommand(response)) {
while (true) {
if (msclock() - start_time > ms_timeout) {
break; // timeout
}
if (msclock() - start_time > 2000 && show_warning) {
// 2 seconds elapsed (but this doesn't mean the timeout was exceeded)
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("You can cancel this operation by pressing the pm3 button");
show_warning = false;
}
if (getCommand(response, CMD_BUFFER_CHECK_TIME)) {
if (response->cmd == CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
int copy_bytes = MIN(bytes - bytes_completed, response->arg[1]);
memcpy(dest + response->arg[0], response->d.asBytes, copy_bytes);
@ -285,35 +347,30 @@ bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *respon
return true;
}
}
if (msclock() - start_time > ms_timeout) {
break;
}
if (msclock() - start_time > 2000 && show_warning) {
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("You can cancel this operation by pressing the pm3 button");
show_warning = false;
}
}
return false;
}
bool GetFromFpgaRAM(uint8_t *dest, int bytes)
{
UsbCommand c = {CMD_HF_PLOT, {0, 0, 0}};
SendCommand(&c);
bool GetFromFpgaRAM(uint8_t *dest, int bytes) {
uint64_t start_time = msclock();
UsbCommand c = {CMD_HF_PLOT, {0, 0, 0}};
SendCommand(&c);
UsbCommand response;
int bytes_completed = 0;
bool show_warning = true;
while(true) {
if (getCommand(&response)) {
while (true) {
if (msclock() - start_time > 2000 && show_warning) {
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("You can cancel this operation by pressing the pm3 button");
show_warning = false;
}
if (getCommand(&response, CMD_BUFFER_CHECK_TIME)) {
if (response.cmd == CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
int copy_bytes = MIN(bytes - bytes_completed, response.arg[1]);
memcpy(dest + response.arg[0], response.d.asBytes, copy_bytes);
@ -322,19 +379,13 @@ bool GetFromFpgaRAM(uint8_t *dest, int bytes)
return true;
}
}
if (msclock() - start_time > 2000 && show_warning) {
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("You can cancel this operation by pressing the pm3 button");
show_warning = false;
}
}
return false;
}
bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) {
bool OpenProxmark(void *port, bool wait_for_port, int timeout) {
char *portname = (char *)port;
if (!wait_for_port) {
sp = uart_open(portname);
@ -347,7 +398,7 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode)
msleep(1000);
printf(".");
fflush(stdout);
} while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT));
} while (++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT));
printf("\n");
}
@ -366,7 +417,6 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode)
// start the USB communication thread
serial_port_name = portname;
conn.run = true;
conn.block_after_ACK = flash_mode;
pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn);
return true;
}
@ -394,15 +444,6 @@ void CloseProxmark(void) {
uart_close(sp);
}
#if defined(__linux__) && !defined(NO_UNLINK)
// Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/*
//
// This may be disabled at compile-time with -DNO_UNLINK (used for a JNI-based serial port on Android).
if (serial_port_name) {
unlink(serial_port_name);
}
#endif
// Clean up our state
sp = NULL;
serial_port_name = NULL;
@ -430,30 +471,28 @@ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeo
printf("Waiting for %04x cmd\n", cmd);
#endif
uint64_t start_time = msclock();
if (response == NULL) {
response = &resp;
}
uint64_t start_time = msclock();
// Wait until the command is received
while (true) {
while(getCommand(response)) {
if (cmd == CMD_UNKNOWN || response->cmd == cmd) {
return true;
}
if (ms_timeout != -1 && msclock() > start_time + ms_timeout) {
break; // timeout
}
if (msclock() - start_time > ms_timeout) {
break;
}
if (msclock() - start_time > 2000 && show_warning) {
// 2 seconds elapsed (but this doesn't mean the timeout was exceeded)
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("You can cancel this operation by pressing the pm3 button");
show_warning = false;
}
if (getCommand(response, CMD_BUFFER_CHECK_TIME)) {
if (cmd == CMD_UNKNOWN || response->cmd == cmd) {
return true;
}
}
}
return false;
}

View file

@ -9,32 +9,24 @@
// Code for communicating with the proxmark3 hardware.
//-----------------------------------------------------------------------------
#ifndef COMMS_H_
#define COMMS_H_
#ifndef COMMS_H__
#define COMMS_H__
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include "usb_cmd.h"
#include "uart.h"
#ifndef CMD_BUFFER_SIZE
#define CMD_BUFFER_SIZE 50
#endif
extern void SetOffline(bool new_offline);
extern bool IsOffline();
extern bool OpenProxmark(void *port, bool wait_for_port, int timeout);
extern void CloseProxmark(void);
extern void SendCommand(UsbCommand *c);
extern void clearCommandBuffer();
extern bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning);
extern bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
extern bool WaitForResponse(uint32_t cmd, UsbCommand* response);
extern bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning);
extern bool GetFromFpgaRAM(uint8_t *dest, int bytes);
void SetOffline(bool new_offline);
bool IsOffline();
bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode);
void CloseProxmark(void);
void SendCommand(UsbCommand *c);
void clearCommandBuffer();
bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning);
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
bool WaitForResponse(uint32_t cmd, UsbCommand* response);
bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning);
bool GetFromFpgaRAM(uint8_t *dest, int bytes);
#endif // COMMS_H_
#endif // COMMS_H__

View file

@ -185,9 +185,9 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) {
return 0;
}
// Load an ELF file and prepare it for flashing
int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl)
{
int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl) {
FILE *fd = NULL;
Elf32_Ehdr ehdr;
Elf32_Phdr *phdrs = NULL;
@ -267,9 +267,9 @@ fail:
return -1;
}
// Get the state of the proxmark, backwards compatible
static int get_proxmark_state(uint32_t *state)
{
static int get_proxmark_state(uint32_t *state) {
UsbCommand c = {0};
c.cmd = CMD_DEVICE_INFO;
SendCommand(&c);
@ -300,9 +300,9 @@ static int get_proxmark_state(uint32_t *state)
return 0;
}
// Enter the bootloader to be able to start flashing
static int enter_bootloader(char *serial_port_name)
{
static int enter_bootloader(char *serial_port_name) {
uint32_t state;
if (get_proxmark_state(&state) < 0)
@ -314,7 +314,7 @@ static int enter_bootloader(char *serial_port_name)
}
if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) {
fprintf(stderr,"Entering bootloader...\n");
fprintf(stderr, "Entering bootloader...\n");
UsbCommand c;
memset(&c, 0, sizeof (c));
@ -336,7 +336,9 @@ static int enter_bootloader(char *serial_port_name)
msleep(100);
CloseProxmark();
bool opened = OpenProxmark(serial_port_name, true, 120, true); // wait for 2 minutes
msleep(1000); // wait for OS to detect device disconnect.
bool opened = OpenProxmark(serial_port_name, true, 120); // wait for 2 minutes
if (opened) {
fprintf(stderr," Found.\n");
return 0;
@ -350,6 +352,7 @@ static int enter_bootloader(char *serial_port_name)
return -1;
}
static int wait_for_ack(void)
{
UsbCommand ack;
@ -361,11 +364,11 @@ static int wait_for_ack(void)
return 0;
}
// Go into flashing mode
int flash_start_flashing(int enable_bl_writes,char *serial_port_name)
{
uint32_t state;
if (enter_bootloader(serial_port_name) < 0)
return -1;

View file

@ -17,7 +17,7 @@
#include "flash.h"
#include "comms.h"
#include "usb_cmd.h"
#include "uart.h"
void cmd_debug(UsbCommand* UC) {
// Debug
@ -83,7 +83,7 @@ int main(int argc, char **argv)
char* serial_port_name = argv[1];
if (!OpenProxmark(serial_port_name, true, 120, true)) { // wait for 2 minutes
if (!OpenProxmark(serial_port_name, true, 120)) { // wait for 2 minutes
fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name);
return -1;
} else {

View file

@ -1164,7 +1164,7 @@ int DetectClassicPrng(void){
clearCommandBuffer();
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
if (!WaitForResponseTimeout(CMD_NACK, &resp, 2000)) {
PrintAndLog("PRNG UID: Reply timeout.");
return -1;
}

View file

@ -28,7 +28,7 @@
#include "cmdhw.h"
#include "whereami.h"
#include "comms.h"
#include "uart.h"
void
#ifdef __has_attribute
@ -286,7 +286,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(argv[1], waitCOMPort, 20);
#ifdef HAVE_GUI
#ifdef _WIN32
@ -309,8 +309,10 @@ int main(int argc, char* argv[]) {
main_loop(script_cmds_file, script_cmd, usb_present);
#endif
// Clean up the port
// Switch off field and clean up the port
if (usb_present) {
UsbCommand c = {CMD_FPGA_MAJOR_MODE_OFF};
SendCommand(&c);
CloseProxmark();
}

View file

@ -14,6 +14,7 @@
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <string.h>
#include "proxmark3.h"
#include "comms.h"
#include "usb_cmd.h"

View file

@ -1,79 +0,0 @@
/*
* Proxmark send and receive commands
*
* Copyright (c) 2012, Roel Verdult
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file cmd.c
* @brief
*/
#include "cmd.h"
#include "string.h"
#include "proxmark3.h"
bool cmd_receive(UsbCommand* cmd) {
// Check if there is a usb packet available
if (!usb_poll()) return false;
// Try to retrieve the available command frame
size_t rxlen = usb_read((byte_t*)cmd,sizeof(UsbCommand));
// Check if the transfer was complete
if (rxlen != sizeof(UsbCommand)) return false;
// Received command successfully
return true;
}
bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len) {
UsbCommand txcmd;
for (size_t i=0; i<sizeof(UsbCommand); i++) {
((byte_t*)&txcmd)[i] = 0x00;
}
// Compose the outgoing command frame
txcmd.cmd = cmd;
txcmd.arg[0] = arg0;
txcmd.arg[1] = arg1;
txcmd.arg[2] = arg2;
// Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE
if (data && len) {
len = MIN(len,USB_CMD_DATA_SIZE);
for (size_t i=0; i<len; i++) {
txcmd.d.asBytes[i] = ((byte_t*)data)[i];
}
}
// Send frame and make sure all bytes are transmitted
if (usb_write((byte_t*)&txcmd,sizeof(UsbCommand)) != 0) return false;
return true;
}

View file

@ -1,44 +0,0 @@
/*
* Proxmark send and receive commands
*
* Copyright (c) 2010, Roel Verdult
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file cmd.h
* @brief
*/
#ifndef _PROXMARK_CMD_H_
#define _PROXMARK_CMD_H_
#include "common.h"
#include "usb_cmd.h"
#include "usb_cdc.h"
bool cmd_receive(UsbCommand* cmd);
bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
#endif // _PROXMARK_CMD_H_

View file

@ -33,10 +33,15 @@
*/
#include "usb_cdc.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "common.h"
#include "at91sam7s512.h"
#include "config_gpio.h"
#define AT91C_EP_CONTROL 0
#define AT91C_EP_OUT 1
#define AT91C_EP_IN 2
@ -49,6 +54,7 @@
#define STR_MANUFACTURER 0x01
#define STR_PRODUCT 0x02
static const char devDescriptor[] = {
/* Device descriptor */
0x12, // bLength
@ -67,6 +73,7 @@ static const char devDescriptor[] = {
0x01 // bNumConfigs
};
static const char cfgDescriptor[] = {
/* ============== CONFIGURATION 1 =========== */
/* Configuration 1 descriptor */
@ -157,47 +164,50 @@ static const char cfgDescriptor[] = {
0x00 // bInterval
};
static const char StrDescLanguageCodes[] = {
4, // Length
0x03, // Type is string
0x09, 0x04 // supported language Code 0 = 0x0409 (English)
4, // Length
0x03, // Type is string
0x09, 0x04 // supported language Code 0 = 0x0409 (English)
};
// Note: ModemManager (Linux) ignores Proxmark3 devices by matching the
// manufacturer string "proxmark.org". Don't change this.
static const char StrDescManufacturer[] = {
26, // Length
0x03, // Type is string
'p', 0x00,
'r', 0x00,
'o', 0x00,
'x', 0x00,
'm', 0x00,
'a', 0x00,
'r', 0x00,
'k', 0x00,
'.', 0x00,
'o', 0x00,
'r', 0x00,
'g', 0x00
26, // Length
0x03, // Type is string
'p', 0x00,
'r', 0x00,
'o', 0x00,
'x', 0x00,
'm', 0x00,
'a', 0x00,
'r', 0x00,
'k', 0x00,
'.', 0x00,
'o', 0x00,
'r', 0x00,
'g', 0x00
};
static const char StrDescProduct[] = {
20, // Length
0x03, // Type is string
'p', 0x00,
'r', 0x00,
'o', 0x00,
'x', 0x00,
'm', 0x00,
'a', 0x00,
'r', 0x00,
'k', 0x00,
'3', 0x00
20, // Length
0x03, // Type is string
'p', 0x00,
'r', 0x00,
'o', 0x00,
'x', 0x00,
'm', 0x00,
'a', 0x00,
'r', 0x00,
'k', 0x00,
'3', 0x00
};
const char* getStringDescriptor(uint8_t idx)
{
static const char* getStringDescriptor(uint8_t idx) {
switch (idx) {
case STR_LANGUAGE_CODES:
return StrDescLanguageCodes;
@ -210,29 +220,31 @@ const char* getStringDescriptor(uint8_t idx)
}
}
// Bitmap for all status bits in CSR which must be written as 1 to cause no effect
#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
|AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
|AT91C_UDP_TXCOMP
#define REG_NO_EFFECT_1_ALL (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_TXCOMP)
// Clear flags in the UDP_CSR register
#define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
volatile unsigned int reg; \
reg = pUdp->UDP_CSR[(endpoint)]; \
reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \
reg |= REG_NO_EFFECT_1_ALL; \
reg &= ~(flags); \
pUdp->UDP_CSR[(endpoint)] = reg; \
}
AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \
}
// Set flags in the UDP_CSR register
#define UDP_SET_EP_FLAGS(endpoint, flags) { \
volatile unsigned int reg; \
reg = pUdp->UDP_CSR[(endpoint)]; \
reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \
reg |= REG_NO_EFFECT_1_ALL; \
reg |= (flags); \
pUdp->UDP_CSR[(endpoint)] = reg; \
AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \
}
/* USB standard request codes */
#define STD_GET_STATUS_ZERO 0x0080
#define STD_GET_STATUS_INTERFACE 0x0081
@ -260,6 +272,7 @@ const char* getStringDescriptor(uint8_t idx)
#define SET_LINE_CODING 0x2021
#define SET_CONTROL_LINE_STATE 0x2221
typedef struct {
unsigned int dwDTERRate;
char bCharFormat;
@ -267,19 +280,17 @@ typedef struct {
char bDataBits;
} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
AT91S_CDC_LINE_CODING line = {
static AT91S_CDC_LINE_CODING line = {
115200, // baudrate
0, // 1 Stop Bit
0, // None Parity
8}; // 8 Data bits
void AT91F_CDC_Enumerate();
AT91PS_UDP pUdp = AT91C_BASE_UDP;
byte_t btConfiguration = 0;
byte_t btConnection = 0;
byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
static uint8_t btConfiguration = 0;
static uint8_t btConnection = 0;
static uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
//*----------------------------------------------------------------------------
@ -291,8 +302,8 @@ void usb_disable() {
AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
// Clear all lingering interrupts
if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {
pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
if (AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
}
}
@ -322,7 +333,7 @@ void usb_enable() {
usb_disable();
// Wait for a short while
for (volatile size_t i=0; i<0x100000; i++);
for (volatile size_t i = 0; i < 0x100000; i++);
// Reconnect USB reconnect
AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
@ -330,34 +341,242 @@ void usb_enable() {
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendZlp
//* \brief Send zero length packet through an endpoint
//*----------------------------------------------------------------------------
static void AT91F_USB_SendZlp(uint8_t endpoint) {
UDP_SET_EP_FLAGS(endpoint, AT91C_UDP_TXPKTRDY);
while (!(AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP))
/* wait */;
UDP_CLEAR_EP_FLAGS(endpoint, AT91C_UDP_TXCOMP);
while (AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP)
/* wait */;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendData
//* \brief Send Data through the control endpoint
//*----------------------------------------------------------------------------
static void AT91F_USB_SendData(const char *pData, uint32_t length) {
uint32_t cpt = 0;
AT91_REG csr;
do {
cpt = MIN(length, 8);
length -= cpt;
while (cpt--)
AT91C_BASE_UDP->UDP_FDR[0] = *pData++;
if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
/* wait */;
}
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
do {
csr = AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL];
// Data IN stage has been stopped by a status OUT
if (csr & AT91C_UDP_RX_DATA_BK0) {
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
return;
}
} while (!(csr & AT91C_UDP_TXCOMP));
} while (length);
if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
/* wait */;
}
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendStall
//* \brief Stall the control endpoint
//*----------------------------------------------------------------------------
static void AT91F_USB_SendStall(void) {
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR))
/* wait */;
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR))
/* wait */;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_CDC_Enumerate
//* \brief This function is a callback invoked when a SETUP packet is received
//*----------------------------------------------------------------------------
static void AT91F_CDC_Enumerate() {
uint8_t bmRequestType, bRequest;
uint16_t wValue, wIndex, wLength, wStatus;
if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP))
return;
bmRequestType = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];
bRequest = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];
wValue = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wValue |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
wIndex = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wIndex |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
wLength = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wLength |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR))
/* wait */;
}
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)
/* wait */;
// Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
switch ((bRequest << 8) | bmRequestType) {
case STD_GET_DESCRIPTOR:
if (wValue == 0x100) // Return Device Descriptor
AT91F_USB_SendData(devDescriptor, MIN(sizeof(devDescriptor), wLength));
else if (wValue == 0x200) // Return Configuration Descriptor
AT91F_USB_SendData(cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
const char *strDescriptor = getStringDescriptor(wValue & 0xff);
if (strDescriptor != NULL) {
AT91F_USB_SendData(strDescriptor, MIN(strDescriptor[0], wLength));
} else {
AT91F_USB_SendStall();
}
}
else
AT91F_USB_SendStall();
break;
case STD_SET_ADDRESS:
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
AT91C_BASE_UDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
break;
case STD_SET_CONFIGURATION:
btConfiguration = wValue;
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
break;
case STD_GET_CONFIGURATION:
AT91F_USB_SendData((char *) &(btConfiguration), sizeof(btConfiguration));
break;
case STD_GET_STATUS_ZERO:
wStatus = 0; // Device is Bus powered, remote wakeup disabled
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_INTERFACE:
wStatus = 0; // reserved for future use
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_ENDPOINT:
wStatus = 0;
wIndex &= 0x0F;
if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
} else if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
} else
AT91F_USB_SendStall();
break;
case STD_SET_FEATURE_ZERO:
AT91F_USB_SendStall();
break;
case STD_SET_FEATURE_INTERFACE:
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
break;
case STD_SET_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
AT91C_BASE_UDP->UDP_CSR[wIndex] = 0;
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
} else
AT91F_USB_SendStall();
break;
case STD_CLEAR_FEATURE_ZERO:
AT91F_USB_SendStall();
break;
case STD_CLEAR_FEATURE_INTERFACE:
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
break;
case STD_CLEAR_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
if (wIndex == AT91C_EP_OUT)
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
else if (wIndex == AT91C_EP_IN)
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
else if (wIndex == AT91C_EP_NOTIFY)
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
}
else
AT91F_USB_SendStall();
break;
// handle CDC class requests
case SET_LINE_CODING:
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0))
/* wait */;
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
break;
case GET_LINE_CODING:
AT91F_USB_SendData((char *) &line, MIN(sizeof(line), wLength));
break;
case SET_CONTROL_LINE_STATE:
btConnection = wValue;
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
break;
default:
AT91F_USB_SendStall();
break;
}
}
//*----------------------------------------------------------------------------
//* \fn usb_check
//* \brief Test if the device is configured and handle enumeration
//*----------------------------------------------------------------------------
bool usb_check() {
AT91_REG isr = pUdp->UDP_ISR;
static bool usb_check() {
AT91_REG isr = AT91C_BASE_UDP->UDP_ISR;
if (isr & AT91C_UDP_ENDBUSRES) {
pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
// reset all endpoints
pUdp->UDP_RSTEP = (unsigned int)-1;
pUdp->UDP_RSTEP = 0;
AT91C_BASE_UDP->UDP_RSTEP = (unsigned int)-1;
AT91C_BASE_UDP->UDP_RSTEP = 0;
// Enable the function
pUdp->UDP_FADDR = AT91C_UDP_FEN;
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
// Configure endpoint 0
pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
} else if (isr & AT91C_UDP_EPINT0) {
pUdp->UDP_ICR = AT91C_UDP_EPINT0;
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_EPINT0;
AT91F_CDC_Enumerate();
}
return (btConfiguration) ? true : false;
}
bool usb_poll()
{
bool usb_poll() {
if (!usb_check()) return false;
return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
}
@ -369,30 +588,30 @@ bool usb_poll()
that the length available to read is non-zero, thus hopefully fixes the
bug.
**/
bool usb_poll_validate_length()
{
bool usb_poll_validate_length() {
if (!usb_check()) return false;
if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
}
//*----------------------------------------------------------------------------
//* \fn usb_read
//* \brief Read available data from Endpoint OUT
//*----------------------------------------------------------------------------
uint32_t usb_read(byte_t* data, size_t len) {
byte_t bank = btReceiveBank;
static uint32_t usb_read(uint8_t* data, size_t len) {
uint8_t bank = btReceiveBank;
uint32_t packetSize, nbBytesRcv = 0;
uint32_t time_out = 0;
while (len) {
if (!usb_check()) break;
if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {
packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);
if ( AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & bank ) {
packetSize = MIN(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16, len);
len -= packetSize;
while(packetSize--)
data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
while (packetSize--)
data[nbBytesRcv++] = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_OUT];
UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);
if (bank == AT91C_UDP_RX_DATA_BK0) {
bank = AT91C_UDP_RX_DATA_BK1;
@ -412,7 +631,7 @@ uint32_t usb_read(byte_t* data, size_t len) {
//* \fn usb_write
//* \brief Send through endpoint 2
//*----------------------------------------------------------------------------
uint32_t usb_write(const byte_t* data, const size_t len) {
static uint32_t usb_write(const uint8_t* data, const size_t len) {
size_t length = len;
uint32_t cpt = 0;
@ -423,239 +642,122 @@ uint32_t usb_write(const byte_t* data, const size_t len) {
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while (cpt--) {
pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;
}
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))
/* wait */;
while (length) {
// Fill the next bank
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while (cpt--) {
pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;
}
// Wait for the previous bank to be sent
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
if (!usb_check()) return length;
}
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))
/* wait */;
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
/* wait */;
}
// Wait for the end of transfer
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
if (!usb_check()) return length;
}
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
/* wait */;
if (len % AT91C_EP_IN_SIZE == 0) { // need to send a zero length packet to complete the transfer
AT91F_USB_SendZlp(AT91C_EP_IN);
}
return length;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendData
//* \brief Send Data through the control endpoint
//*----------------------------------------------------------------------------
unsigned int csrTab[100] = {0x00};
unsigned char csrIdx = 0;
//***************************************************************************
// Interface to the main program
//***************************************************************************
static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
uint32_t cpt = 0;
AT91_REG csr;
// The function to receive a command from the client via USB
bool cmd_receive(UsbCommand* cmd) {
do {
cpt = MIN(length, 8);
length -= cpt;
// Check if there is a usb packet available
if (!usb_poll())
return false;
while (cpt--)
pUdp->UDP_FDR[0] = *pData++;
// Try to retrieve the available command frame
size_t rxlen = usb_read((uint8_t*)cmd, sizeof(UsbCommand));
if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);
// Check if the transfer was complete
if (rxlen != sizeof(UsbCommand))
return false;
// Received command successfully
return true;
}
// The function to send a response to the client via USB
bool cmd_send(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen) {
UsbResponse txcmd;
// Compose the outgoing response frame
txcmd.cmd = cmd | CMD_VARIABLE_SIZE_FLAG;
txcmd.arg[0] = arg0;
txcmd.arg[1] = arg1;
txcmd.arg[2] = arg2;
// Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE
if (data) {
datalen = MIN(datalen, USB_CMD_DATA_SIZE);
for (uint16_t i = 0; i < datalen; i++) {
txcmd.d.asBytes[i] = ((uint8_t*)data)[i];
}
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
do {
csr = pUdp->UDP_CSR[AT91C_EP_CONTROL];
// Data IN stage has been stopped by a status OUT
if (csr & AT91C_UDP_RX_DATA_BK0) {
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
return;
}
} while ( !(csr & AT91C_UDP_TXCOMP) );
} while (length);
if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);
txcmd.datalen = datalen;
} else {
txcmd.datalen = 0;
}
// Send frame and make sure all bytes are transmitted
size_t tx_size = offsetof(UsbResponse, d) + datalen;
if (usb_write((uint8_t*)&txcmd, tx_size) != 0) return false;
return true;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendZlp
//* \brief Send zero length packet through the control endpoint
//*----------------------------------------------------------------------------
void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) );
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);
}
// For compatibility only: legacy function to send a response with fixed size to the client via USB
bool cmd_send_old(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen) {
UsbCommand txcmd;
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendStall
//* \brief Stall the control endpoint
//*----------------------------------------------------------------------------
void AT91F_USB_SendStall(AT91PS_UDP pUdp) {
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR) );
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
}
// Compose the outgoing response frame
txcmd.cmd = cmd;
txcmd.arg[0] = arg0;
txcmd.arg[1] = arg1;
txcmd.arg[2] = arg2;
//*----------------------------------------------------------------------------
//* \fn AT91F_CDC_Enumerate
//* \brief This function is a callback invoked when a SETUP packet is received
//*----------------------------------------------------------------------------
void AT91F_CDC_Enumerate() {
byte_t bmRequestType, bRequest;
uint16_t wValue, wIndex, wLength, wStatus;
if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) )
return;
bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];
bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];
wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) );
// Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE
if (data) {
datalen = MIN(datalen, USB_CMD_DATA_SIZE);
for (uint16_t i = 0; i < datalen; i++) {
txcmd.d.asBytes[i] = ((uint8_t*)data)[i];
}
}
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) );
// Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
switch ((bRequest << 8) | bmRequestType) {
case STD_GET_DESCRIPTOR:
if (wValue == 0x100) // Return Device Descriptor
AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
else if (wValue == 0x200) // Return Configuration Descriptor
AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
const char *strDescriptor = getStringDescriptor(wValue & 0xff);
if (strDescriptor != NULL) {
AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));
} else {
AT91F_USB_SendStall(pUdp);
}
}
else
AT91F_USB_SendStall(pUdp);
break;
case STD_SET_ADDRESS:
AT91F_USB_SendZlp(pUdp);
pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);
pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
break;
case STD_SET_CONFIGURATION:
btConfiguration = wValue;
AT91F_USB_SendZlp(pUdp);
pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
break;
case STD_GET_CONFIGURATION:
AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));
break;
case STD_GET_STATUS_ZERO:
wStatus = 0; // Device is Bus powered, remote wakeup disabled
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_INTERFACE:
wStatus = 0; // reserved for future use
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_ENDPOINT:
wStatus = 0;
wIndex &= 0x0F;
if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
}
else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
}
else
AT91F_USB_SendStall(pUdp);
break;
case STD_SET_FEATURE_ZERO:
AT91F_USB_SendStall(pUdp);
break;
case STD_SET_FEATURE_INTERFACE:
AT91F_USB_SendZlp(pUdp);
break;
case STD_SET_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
pUdp->UDP_CSR[wIndex] = 0;
AT91F_USB_SendZlp(pUdp);
}
else
AT91F_USB_SendStall(pUdp);
break;
case STD_CLEAR_FEATURE_ZERO:
AT91F_USB_SendStall(pUdp);
break;
case STD_CLEAR_FEATURE_INTERFACE:
AT91F_USB_SendZlp(pUdp);
break;
case STD_CLEAR_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
if (wIndex == AT91C_EP_OUT)
pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
else if (wIndex == AT91C_EP_IN)
pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
else if (wIndex == AT91C_EP_NOTIFY)
pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
AT91F_USB_SendZlp(pUdp);
}
else
AT91F_USB_SendStall(pUdp);
break;
// Send frame and make sure all bytes are transmitted
if (usb_write((uint8_t*)&txcmd, sizeof(UsbCommand)) != 0) return false;
// handle CDC class requests
case SET_LINE_CODING:
while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0) );
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
AT91F_USB_SendZlp(pUdp);
break;
case GET_LINE_CODING:
AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));
break;
case SET_CONTROL_LINE_STATE:
btConnection = wValue;
AT91F_USB_SendZlp(pUdp);
break;
default:
AT91F_USB_SendStall(pUdp);
break;
}
return true;
}

View file

@ -32,18 +32,20 @@
* @brief
*/
#ifndef _USB_CDC_H_
#define _USB_CDC_H_
#ifndef USB_CDC_H__
#define USB_CDC_H__
#include "common.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "usb_cmd.h"
void usb_disable();
void usb_enable();
bool usb_check();
bool usb_poll();
bool usb_poll_validate_length();
uint32_t usb_read(byte_t* data, size_t len);
uint32_t usb_write(const byte_t* data, const size_t len);
#endif // _USB_CDC_H_
extern void usb_disable();
extern void usb_enable();
extern bool usb_poll();
extern bool usb_poll_validate_length();
extern bool cmd_receive(UsbCommand* cmd);
extern bool cmd_send(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen); // new variable sized response
extern bool cmd_send_old(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen); // old fixed size response
#endif // USB_CDC_H__

View file

@ -9,13 +9,9 @@
// Interlib Definitions
//-----------------------------------------------------------------------------
#ifndef __COMMON_H
#define __COMMON_H
#ifndef COMMON_H__
#define COMMON_H__
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <at91sam7s512.h>
typedef unsigned char byte_t;
#ifndef MIN
@ -25,10 +21,9 @@ typedef unsigned char byte_t;
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef ABS
# define ABS(a) ( ((a)<0) ? -(a) : (a) )
# define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
#define RAMFUNC __attribute((long_call, section(".ramfunc")))
#endif

View file

@ -10,13 +10,13 @@
// own protocol.
//-----------------------------------------------------------------------------
#ifndef __USB_CMD_H
#define __USB_CMD_H
#ifndef USB_CMD_H__
#define USB_CMD_H__
#ifdef _MSC_VER
typedef DWORD uint32_t;
typedef BYTE uint8_t;
#define PACKED
// stuff
#else
#include <stdint.h>
#include <stdbool.h>
@ -25,17 +25,29 @@ typedef BYTE uint8_t;
#define USB_CMD_DATA_SIZE 512
// the packets sent from client to PM3
typedef struct {
uint64_t cmd;
uint64_t arg[3];
union {
uint8_t asBytes[USB_CMD_DATA_SIZE];
uint32_t asDwords[USB_CMD_DATA_SIZE/4];
} d;
uint64_t cmd;
uint64_t arg[3];
union {
uint8_t asBytes[USB_CMD_DATA_SIZE];
uint32_t asDwords[USB_CMD_DATA_SIZE/4];
} d;
} PACKED UsbCommand;
// the packets sent from PM3 to client (a smaller version of UsbCommand)
typedef struct {
uint16_t cmd;
uint16_t datalen;
uint32_t arg[3];
union {
uint8_t asBytes[USB_CMD_DATA_SIZE];
uint32_t asDwords[USB_CMD_DATA_SIZE/4];
} d;
} PACKED UsbResponse;
// A struct used to send sample-configs over USB
typedef struct{
typedef struct {
uint8_t decimation;
uint8_t bits_per_sample;
bool averaging;
@ -44,6 +56,7 @@ typedef struct{
int samples_to_skip;
} sample_config;
// For the bootloader
#define CMD_DEVICE_INFO 0x0000
#define CMD_SETUP_WRITE 0x0001
@ -165,7 +178,7 @@ typedef struct{
#define CMD_ICLASS_WRITEBLOCK 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398
#define CMD_ICLASS_CHECK 0x0399
#define CMD_ICLASS_READCHECK 0x039A
#define CMD_ICLASS_READCHECK 0x039A
// For measurements of the antenna tuning
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
@ -208,7 +221,7 @@ typedef struct{
#define CMD_MIFAREU_WRITEBL 0x0722
#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
#define CMD_MIFAREUC_AUTH 0x0724
//0x0725 and 0x0726 no longer used
//0x0725 and 0x0726 no longer used
#define CMD_MIFAREUC_SETPWD 0x0727
@ -224,15 +237,16 @@ typedef struct{
#define CMD_HF_SNIFFER 0x0800
#define CMD_HF_PLOT 0x0801
#define CMD_VARIABLE_SIZE_FLAG 0x8000
#define CMD_UNKNOWN 0xFFFF
// Mifare simulation flags
#define FLAG_INTERACTIVE (1<<0)
#define FLAG_4B_UID_IN_DATA (1<<1)
#define FLAG_7B_UID_IN_DATA (1<<2)
#define FLAG_NR_AR_ATTACK (1<<4)
#define FLAG_RANDOM_NONCE (1<<5)
#define FLAG_INTERACTIVE (1<<0)
#define FLAG_4B_UID_IN_DATA (1<<1)
#define FLAG_7B_UID_IN_DATA (1<<2)
#define FLAG_NR_AR_ATTACK (1<<4)
#define FLAG_RANDOM_NONCE (1<<5)
// iCLASS reader flags
@ -266,19 +280,19 @@ typedef struct{
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
/* Whether a bootloader that understands the common_area is present */
#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0)
#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0)
/* Whether a osimage that understands the common_area is present */
#define DEVICE_INFO_FLAG_OSIMAGE_PRESENT (1<<1)
#define DEVICE_INFO_FLAG_OSIMAGE_PRESENT (1<<1)
/* Set if the bootloader is currently executing */
#define DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM (1<<2)
#define DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM (1<<2)
/* Set if the OS is currently executing */
#define DEVICE_INFO_FLAG_CURRENT_MODE_OS (1<<3)
#define DEVICE_INFO_FLAG_CURRENT_MODE_OS (1<<3)
/* Set if this device understands the extend start flash command */
#define DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH (1<<4)
#define DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH (1<<4)
/* CMD_START_FLASH may have three arguments: start of area to flash,
end of area to flash, optional magic.

View file

@ -29,24 +29,21 @@
* @file uart.h
*/
#ifndef _PM3_UART_H_
#define _PM3_UART_H_
#ifndef PM3_UART_H__
#define PM3_UART_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
/* Used to substitute for an example serial port path on each platform.
*/
#ifdef _WIN32
#define SERIAL_PORT_H "com3"
#define SERIAL_PORT_H "com3"
#elif __APPLE__
#define SERIAL_PORT_H "/dev/tty.usbmodem*"
#define SERIAL_PORT_H "/dev/tty.usbmodem*"
#else
#define SERIAL_PORT_H "/dev/ttyACM0"
#define SERIAL_PORT_H "/dev/ttyACM0"
#endif
/* serial_port is declared as a void*, which you should cast to whatever type
@ -69,11 +66,11 @@ typedef void* serial_port;
*
* On errors, this method returns INVALID_SERIAL_PORT or CLAIMED_SERIAL_PORT.
*/
serial_port uart_open(const char* pcPortName);
extern serial_port uart_open(const char* pcPortName);
/* Closes the given port.
*/
void uart_close(const serial_port sp);
extern void uart_close(const serial_port sp);
/* Reads from the given serial port for up to 30ms.
* pbtRx: A pointer to a buffer for the returned data to be written to.
@ -84,15 +81,17 @@ void uart_close(const serial_port sp);
*
* Returns FALSE if there was an error reading from the device. Note that a
* partial read may have completed into the buffer by the corresponding
* implementation, so pszRxLen should be checked to see if any data was written.
* implementation, so pszRxLen should be checked to see if any data was written.
*/
bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen);
extern bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen);
/* Sends a buffer to a given serial port.
* pbtTx: A pointer to a buffer containing the data to send.
* szTxLen: The amount of data to be sent.
*
* Returns TRUE if all data could be sent within 30ms.
*/
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen);
extern bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen);
/* Sets the current speed of the serial port, in baud.
*/
@ -100,7 +99,7 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed);
/* Gets the current speed of the serial port, in baud.
*/
uint32_t uart_get_speed(const serial_port sp);
extern uint32_t uart_get_speed(const serial_port sp);
#endif // _PM3_UART_H_
#endif // PM3_UART_H__

761
uart/uart_posix.c Normal file → Executable file
View file

@ -1,391 +1,370 @@
/*
* Generic uart / rs232/ serial port library
*
* Copyright (c) 2013, Roel Verdult
* Copyright (c) 2018 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file uart_posix.c
*
* This version of the library has functionality removed which was not used by
* proxmark3 project.
*/
// Test if we are dealing with posix operating systems
#ifndef _WIN32
#define _DEFAULT_SOURCE
#include "uart.h"
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
// Fix missing definition on OS X.
// Taken from https://github.com/unbit/uwsgi/commit/b608eb1772641d525bfde268fe9d6d8d0d5efde7
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
typedef struct termios term_info;
typedef struct {
int fd; // Serial port file descriptor
term_info tiOld; // Terminal info before using the port
term_info tiNew; // Terminal info during the transaction
} serial_port_unix;
// Set time-out on 30 miliseconds
struct timeval timeout = {
.tv_sec = 0, // 0 second
.tv_usec = 30000 // 30000 micro seconds
};
serial_port uart_open(const char* pcPortName)
{
serial_port_unix* sp = malloc(sizeof(serial_port_unix));
if (sp == 0) return INVALID_SERIAL_PORT;
if (memcmp(pcPortName, "tcp:", 4) == 0) {
struct addrinfo *addr = NULL, *rp;
char *addrstr = strdup(pcPortName + 4);
if (addrstr == NULL) {
printf("Error: strdup\n");
return INVALID_SERIAL_PORT;
}
char *colon = strrchr(addrstr, ':');
char *portstr;
// Set time-out to 300 miliseconds only for TCP port
timeout.tv_usec = 300000;
if (colon) {
portstr = colon + 1;
*colon = '\0';
} else
portstr = "7901";
struct addrinfo info;
memset (&info, 0, sizeof(info));
info.ai_socktype = SOCK_STREAM;
int s = getaddrinfo(addrstr, portstr, &info, &addr);
if (s != 0) {
printf("Error: getaddrinfo: %s\n", gai_strerror(s));
return INVALID_SERIAL_PORT;
}
int sfd;
for (rp = addr; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break;
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
printf("Error: Could not connect\n");
return INVALID_SERIAL_PORT;
}
freeaddrinfo(addr);
free(addrstr);
sp->fd = sfd;
int one = 1;
setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
return sp;
}
sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if(sp->fd == -1) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Finally figured out a way to claim a serial port interface under unix
// We just try to set a (advisory) lock on the file descriptor
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
// Does the system allows us to place a lock on this file descriptor
if (fcntl(sp->fd, F_SETLK, &fl) == -1) {
// A conflicting lock is held by another process
free(sp);
return CLAIMED_SERIAL_PORT;
}
// Try to retrieve the old (current) terminal info struct
if(tcgetattr(sp->fd,&sp->tiOld) == -1) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Duplicate the (old) terminal info struct
sp->tiNew = sp->tiOld;
// Configure the serial port
sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD;
sp->tiNew.c_iflag = IGNPAR;
sp->tiNew.c_oflag = 0;
sp->tiNew.c_lflag = 0;
// Block until n bytes are received
sp->tiNew.c_cc[VMIN] = 0;
// Block until a timer expires (n * 100 mSec.)
sp->tiNew.c_cc[VTIME] = 0;
// Try to set the new terminal info struct
if(tcsetattr(sp->fd,TCSANOW,&sp->tiNew) == -1) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Flush all lingering data that may exist
tcflush(sp->fd, TCIOFLUSH);
return sp;
}
void uart_close(const serial_port sp) {
serial_port_unix* spu = (serial_port_unix*)sp;
tcflush(spu->fd,TCIOFLUSH);
tcsetattr(spu->fd,TCSANOW,&(spu->tiOld));
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
fcntl(spu->fd, F_SETLK, &fl);
close(spu->fd);
free(sp);
}
bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) {
int res;
int byteCount;
fd_set rfds;
struct timeval tv;
// Reset the output count
*pszRxLen = 0;
do {
// Reset file descriptor
FD_ZERO(&rfds);
FD_SET(((serial_port_unix*)sp)->fd,&rfds);
tv = timeout;
res = select(((serial_port_unix*)sp)->fd+1, &rfds, NULL, NULL, &tv);
// Read error
if (res < 0) {
return false;
}
// Read time-out
if (res == 0) {
if (*pszRxLen == 0) {
// Error, we received no data
return false;
} else {
// We received some data, but nothing more is available
return true;
}
}
// Retrieve the count of the incoming bytes
res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount);
if (res < 0) return false;
// Cap the number of bytes, so we don't overrun the buffer
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
byteCount = pszMaxRxLen - (*pszRxLen);
}
// There is something available, read the data
res = read(((serial_port_unix*)sp)->fd, pbtRx+(*pszRxLen), byteCount);
// Stop if the OS has some troubles reading the data
if (res <= 0) return false;
*pszRxLen += res;
if (*pszRxLen == pszMaxRxLen) {
// We have all the data we wanted.
return true;
}
} while (byteCount);
return true;
}
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) {
int32_t res;
size_t szPos = 0;
fd_set rfds;
struct timeval tv;
while (szPos < szTxLen) {
// Reset file descriptor
FD_ZERO(&rfds);
FD_SET(((serial_port_unix*)sp)->fd,&rfds);
tv = timeout;
res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv);
// Write error
if (res < 0) {
return false;
}
// Write time-out
if (res == 0) {
return false;
}
// Send away the bytes
res = write(((serial_port_unix*)sp)->fd,pbtTx+szPos,szTxLen-szPos);
// Stop if the OS has some troubles sending the data
if (res <= 0) return false;
szPos += res;
}
return true;
}
bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
const serial_port_unix* spu = (serial_port_unix*)sp;
speed_t stPortSpeed;
switch (uiPortSpeed) {
case 0: stPortSpeed = B0; break;
case 50: stPortSpeed = B50; break;
case 75: stPortSpeed = B75; break;
case 110: stPortSpeed = B110; break;
case 134: stPortSpeed = B134; break;
case 150: stPortSpeed = B150; break;
case 300: stPortSpeed = B300; break;
case 600: stPortSpeed = B600; break;
case 1200: stPortSpeed = B1200; break;
case 1800: stPortSpeed = B1800; break;
case 2400: stPortSpeed = B2400; break;
case 4800: stPortSpeed = B4800; break;
case 9600: stPortSpeed = B9600; break;
case 19200: stPortSpeed = B19200; break;
case 38400: stPortSpeed = B38400; break;
# ifdef B57600
case 57600: stPortSpeed = B57600; break;
# endif
# ifdef B115200
case 115200: stPortSpeed = B115200; break;
# endif
# ifdef B230400
case 230400: stPortSpeed = B230400; break;
# endif
# ifdef B460800
case 460800: stPortSpeed = B460800; break;
# endif
# ifdef B921600
case 921600: stPortSpeed = B921600; break;
# endif
default: return false;
};
struct termios ti;
if (tcgetattr(spu->fd,&ti) == -1) return false;
// Set port speed (Input and Output)
cfsetispeed(&ti,stPortSpeed);
cfsetospeed(&ti,stPortSpeed);
return (tcsetattr(spu->fd,TCSANOW,&ti) != -1);
}
uint32_t uart_get_speed(const serial_port sp) {
struct termios ti;
uint32_t uiPortSpeed;
const serial_port_unix* spu = (serial_port_unix*)sp;
if (tcgetattr(spu->fd,&ti) == -1) return 0;
// Set port speed (Input)
speed_t stPortSpeed = cfgetispeed(&ti);
switch (stPortSpeed) {
case B0: uiPortSpeed = 0; break;
case B50: uiPortSpeed = 50; break;
case B75: uiPortSpeed = 75; break;
case B110: uiPortSpeed = 110; break;
case B134: uiPortSpeed = 134; break;
case B150: uiPortSpeed = 150; break;
case B300: uiPortSpeed = 300; break;
case B600: uiPortSpeed = 600; break;
case B1200: uiPortSpeed = 1200; break;
case B1800: uiPortSpeed = 1800; break;
case B2400: uiPortSpeed = 2400; break;
case B4800: uiPortSpeed = 4800; break;
case B9600: uiPortSpeed = 9600; break;
case B19200: uiPortSpeed = 19200; break;
case B38400: uiPortSpeed = 38400; break;
# ifdef B57600
case B57600: uiPortSpeed = 57600; break;
# endif
# ifdef B115200
case B115200: uiPortSpeed = 115200; break;
# endif
# ifdef B230400
case B230400: uiPortSpeed = 230400; break;
# endif
# ifdef B460800
case B460800: uiPortSpeed = 460800; break;
# endif
# ifdef B921600
case B921600: uiPortSpeed = 921600; break;
# endif
default: return 0;
};
return uiPortSpeed;
}
#endif
/*
* Generic uart / rs232/ serial port library
*
* Copyright (c) 2013, Roel Verdult
* Copyright (c) 2018 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file uart_posix.c
*
* This version of the library has functionality removed which was not used by
* proxmark3 project.
*/
// Test if we are dealing with posix operating systems
#ifndef _WIN32
#define _DEFAULT_SOURCE
#include "uart.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/time.h>
#include <errno.h>
// Fix missing definition on OS X.
// Taken from https://github.com/unbit/uwsgi/commit/b608eb1772641d525bfde268fe9d6d8d0d5efde7
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
typedef struct termios term_info;
typedef struct {
int fd; // Serial port file descriptor
term_info tiOld; // Terminal info before using the port
term_info tiNew; // Terminal info during the transaction
} serial_port_unix;
// Set time-out on 30 miliseconds
static struct timeval timeout = {
.tv_sec = 0, // 0 second
.tv_usec = 30000 // 30000 micro seconds
};
void uart_close(const serial_port sp) {
serial_port_unix* spu = (serial_port_unix*)sp;
tcflush(spu->fd, TCIOFLUSH);
tcsetattr(spu->fd, TCSANOW, &(spu->tiOld));
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
fcntl(spu->fd, F_SETLK, &fl);
close(spu->fd);
free(sp);
}
serial_port uart_open(const char* pcPortName) {
serial_port_unix* sp = malloc(sizeof(serial_port_unix));
if (sp == 0) return INVALID_SERIAL_PORT;
if (memcmp(pcPortName, "tcp:", 4) == 0) {
struct addrinfo *addr = NULL, *rp;
char *addrstr = strdup(pcPortName + 4);
if (addrstr == NULL) {
printf("Error: strdup\n");
return INVALID_SERIAL_PORT;
}
char *colon = strrchr(addrstr, ':');
char *portstr;
// Set time-out to 300 milliseconds only for TCP port
timeout.tv_usec = 300000;
if (colon) {
portstr = colon + 1;
*colon = '\0';
} else {
portstr = "7901";
}
struct addrinfo info;
memset(&info, 0, sizeof(info));
info.ai_socktype = SOCK_STREAM;
int s = getaddrinfo(addrstr, portstr, &info, &addr);
if (s != 0) {
printf("Error: getaddrinfo: %s\n", gai_strerror(s));
return INVALID_SERIAL_PORT;
}
int sfd;
for (rp = addr; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break;
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
printf("Error: Could not connect\n");
return INVALID_SERIAL_PORT;
}
freeaddrinfo(addr);
free(addrstr);
sp->fd = sfd;
int one = 1;
setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
return sp;
}
sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (sp->fd == -1) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Finally figured out a way to claim a serial port interface under unix
// We just try to set a (advisory) lock on the file descriptor
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
// Does the system allows us to place a lock on this file descriptor
if (fcntl(sp->fd, F_SETLK, &fl) == -1) {
// A conflicting lock is held by another process
free(sp);
return CLAIMED_SERIAL_PORT;
}
// Try to retrieve the old (current) terminal info struct
if (tcgetattr(sp->fd,&sp->tiOld) == -1) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Duplicate the (old) terminal info struct
sp->tiNew = sp->tiOld;
// Configure the serial port
sp->tiNew.c_cflag &= ~(CSIZE | PARENB);
sp->tiNew.c_cflag |= (CS8 | CLOCAL | CREAD);
sp->tiNew.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
sp->tiNew.c_iflag |= IGNPAR;
sp->tiNew.c_oflag &= ~OPOST;
sp->tiNew.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
// Try to set the new terminal info struct
if (tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Flush all lingering data that may exist
tcflush(sp->fd, TCIOFLUSH);
return sp;
}
bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t szMaxRxLen, size_t* pszRxLen) {
*pszRxLen = 0;
if (szMaxRxLen == 0) return true;
struct timeval t_current;
gettimeofday(&t_current, NULL);
struct timeval t_end;
timeradd(&t_current, &timeout, &t_end);
while (true) {
int res = read(((serial_port_unix*)sp)->fd, pbtRx, szMaxRxLen - *pszRxLen);
if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) return false;
if (res > 0) {
*pszRxLen += res;
pbtRx += res;
}
if (*pszRxLen == szMaxRxLen) return true; // we could read all requested bytes in time
gettimeofday(&t_current, NULL);
if (timercmp(&t_current, &t_end, >)) return true; // timeout
// set next select timeout
struct timeval t_remains;
timersub(&t_end, &t_current, &t_remains);
// Set the file descriptor set
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(((serial_port_unix*)sp)->fd, &rfds);
// wait for more bytes available
res = select(((serial_port_unix*)sp)->fd+1, &rfds, NULL, NULL, &t_remains);
if (res < 0) return false;
if (res == 0) return true; // timeout
}
return true; // should never come here
}
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) {
if (szTxLen == 0) return true;
size_t bytes_written = 0;
struct timeval t_current;
gettimeofday(&t_current, NULL);
struct timeval t_end;
timeradd(&t_current, &timeout, &t_end);
while (true) {
int res = write(((serial_port_unix*)sp)->fd, pbtTx, szTxLen - bytes_written);
if (res < 0 && res != EAGAIN && res != EWOULDBLOCK) return false;
if (res > 0) {
pbtTx += res;
bytes_written += res;
}
if (bytes_written == szTxLen) return true; // we could write all bytes
gettimeofday(&t_current, NULL);
if (timercmp(&t_current, &t_end, >)) return false; // timeout
// set next select timeout
struct timeval t_remains;
timersub(&t_end, &t_current, &t_remains);
// Set the file descriptor set
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(((serial_port_unix*)sp)->fd, &wfds);
// wait until more bytes can be written
res = select(((serial_port_unix*)sp)->fd+1, NULL, &wfds, NULL, &t_remains);
if (res < 0) return false; // error
if (res == 0) return false; // timeout
}
return true;
}
bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
const serial_port_unix* spu = (serial_port_unix*)sp;
speed_t stPortSpeed;
switch (uiPortSpeed) {
case 0: stPortSpeed = B0; break;
case 50: stPortSpeed = B50; break;
case 75: stPortSpeed = B75; break;
case 110: stPortSpeed = B110; break;
case 134: stPortSpeed = B134; break;
case 150: stPortSpeed = B150; break;
case 300: stPortSpeed = B300; break;
case 600: stPortSpeed = B600; break;
case 1200: stPortSpeed = B1200; break;
case 1800: stPortSpeed = B1800; break;
case 2400: stPortSpeed = B2400; break;
case 4800: stPortSpeed = B4800; break;
case 9600: stPortSpeed = B9600; break;
case 19200: stPortSpeed = B19200; break;
case 38400: stPortSpeed = B38400; break;
# ifdef B57600
case 57600: stPortSpeed = B57600; break;
# endif
# ifdef B115200
case 115200: stPortSpeed = B115200; break;
# endif
# ifdef B230400
case 230400: stPortSpeed = B230400; break;
# endif
# ifdef B460800
case 460800: stPortSpeed = B460800; break;
# endif
# ifdef B921600
case 921600: stPortSpeed = B921600; break;
# endif
default: return false;
};
struct termios ti;
if (tcgetattr(spu->fd, &ti) == -1) return false;
// Set port speed (Input and Output)
cfsetispeed(&ti,stPortSpeed);
cfsetospeed(&ti,stPortSpeed);
return (tcsetattr(spu->fd, TCSANOW, &ti) != -1);
}
uint32_t uart_get_speed(const serial_port sp) {
struct termios ti;
uint32_t uiPortSpeed;
const serial_port_unix* spu = (serial_port_unix*)sp;
if (tcgetattr(spu->fd, &ti) == -1) return 0;
// Set port speed (Input)
speed_t stPortSpeed = cfgetispeed(&ti);
switch (stPortSpeed) {
case B0: uiPortSpeed = 0; break;
case B50: uiPortSpeed = 50; break;
case B75: uiPortSpeed = 75; break;
case B110: uiPortSpeed = 110; break;
case B134: uiPortSpeed = 134; break;
case B150: uiPortSpeed = 150; break;
case B300: uiPortSpeed = 300; break;
case B600: uiPortSpeed = 600; break;
case B1200: uiPortSpeed = 1200; break;
case B1800: uiPortSpeed = 1800; break;
case B2400: uiPortSpeed = 2400; break;
case B4800: uiPortSpeed = 4800; break;
case B9600: uiPortSpeed = 9600; break;
case B19200: uiPortSpeed = 19200; break;
case B38400: uiPortSpeed = 38400; break;
# ifdef B57600
case B57600: uiPortSpeed = 57600; break;
# endif
# ifdef B115200
case B115200: uiPortSpeed = 115200; break;
# endif
# ifdef B230400
case B230400: uiPortSpeed = 230400; break;
# endif
# ifdef B460800
case B460800: uiPortSpeed = 460800; break;
# endif
# ifdef B921600
case B921600: uiPortSpeed = 921600; break;
# endif
default: return 0;
};
return uiPortSpeed;
}
#endif

View file

@ -38,97 +38,109 @@
#include "uart.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
// The windows serial port implementation
#ifdef _WIN32
#include <windows.h>
typedef struct {
HANDLE hPort; // Serial port handle
DCB dcb; // Device control settings
COMMTIMEOUTS ct; // Serial port time-out configuration
HANDLE hPort; // Serial port handle
DCB dcb; // Device control settings
COMMTIMEOUTS ct; // Serial port time-out configuration
} serial_port_windows;
void upcase(char *p) {
while(*p != '\0') {
if(*p >= 97 && *p <= 122) {
*p -= 32;
}
++p;
}
while(*p != '\0') {
if(*p >= 97 && *p <= 122) {
*p -= 32;
}
++p;
}
}
serial_port uart_open(const char* pcPortName) {
char acPortName[255];
serial_port_windows* sp = malloc(sizeof(serial_port_windows));
// Copy the input "com?" to "\\.\COM?" format
sprintf(acPortName,"\\\\.\\%s",pcPortName);
upcase(acPortName);
// Try to open the serial port
sp->hPort = CreateFileA(acPortName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if (sp->hPort == INVALID_HANDLE_VALUE) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Prepare the device control
memset(&sp->dcb, 0, sizeof(DCB));
sp->dcb.DCBlength = sizeof(DCB);
if(!BuildCommDCBA("baud=9600 data=8 parity=N stop=1",&sp->dcb)) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Update the active serial port
if(!SetCommState(sp->hPort,&sp->dcb)) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
sp->ct.ReadIntervalTimeout = 0;
sp->ct.ReadTotalTimeoutMultiplier = 0;
sp->ct.ReadTotalTimeoutConstant = 30;
sp->ct.WriteTotalTimeoutMultiplier = 0;
sp->ct.WriteTotalTimeoutConstant = 30;
if(!SetCommTimeouts(sp->hPort,&sp->ct)) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
return sp;
}
void uart_close(const serial_port sp) {
CloseHandle(((serial_port_windows*)sp)->hPort);
free(sp);
CloseHandle(((serial_port_windows*)sp)->hPort);
free(sp);
}
serial_port uart_open(const char* pcPortName) {
char acPortName[255];
serial_port_windows* sp = malloc(sizeof(serial_port_windows));
// Copy the input "com?" to "\\.\COM?" format
sprintf(acPortName,"\\\\.\\%s",pcPortName);
upcase(acPortName);
// Try to open the serial port
sp->hPort = CreateFileA(acPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (sp->hPort == INVALID_HANDLE_VALUE) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Prepare the device control
memset(&sp->dcb, 0, sizeof(DCB));
sp->dcb.DCBlength = sizeof(DCB);
if (!BuildCommDCBA("baud=9600 data=8 parity=N stop=1",&sp->dcb)) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
// Update the active serial port
if (!SetCommState(sp->hPort,&sp->dcb)) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
sp->ct.ReadIntervalTimeout = 0;
sp->ct.ReadTotalTimeoutMultiplier = 0;
sp->ct.ReadTotalTimeoutConstant = 30;
sp->ct.WriteTotalTimeoutMultiplier = 0;
sp->ct.WriteTotalTimeoutConstant = 30;
if (!SetCommTimeouts(sp->hPort, &sp->ct)) {
uart_close(sp);
return INVALID_SERIAL_PORT;
}
PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
return sp;
}
bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) {
return ReadFile(((serial_port_windows*)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL);
return ReadFile(((serial_port_windows*)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL);
}
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) {
DWORD dwTxLen = 0;
return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL);
DWORD dwTxLen = 0;
return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL);
}
bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
serial_port_windows* spw;
spw = (serial_port_windows*)sp;
spw->dcb.BaudRate = uiPortSpeed;
return SetCommState(spw->hPort, &spw->dcb);
serial_port_windows* spw;
spw = (serial_port_windows*)sp;
spw->dcb.BaudRate = uiPortSpeed;
return SetCommState(spw->hPort, &spw->dcb);
}
uint32_t uart_get_speed(const serial_port sp) {
const serial_port_windows* spw = (serial_port_windows*)sp;
if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) {
return spw->dcb.BaudRate;
}
return 0;
const serial_port_windows* spw = (serial_port_windows*)sp;
if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) {
return spw->dcb.BaudRate;
}
return 0;
}
#endif