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)
#include <stdarg.h>
#include "usb_cdc.h"
-#include "cmd.h"
#include "proxmark3.h"
#include "apps.h"
#include "fpga.h"
void SendVersion(void) {
+ LED_A_ON();
set_hw_capabilities();
char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
// 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.
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);
* Prints runtime information about the PM3.
**/
void SendStatus(void) {
+ LED_A_ON();
BigBuf_print_status();
Fpga_print_status();
#ifdef WITH_SMARTCARD
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)
}
-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]);
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:
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:
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)
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
#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"
//-----------------------------------------------------------------------------
// 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];
#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"
#include "hitag2.h"
#include "proxmark3.h"
-#include "cmd.h"
+#include "usb_cdc.h"
#include "apps.h"
#include "util.h"
#include "hitag.h"
#include <stdlib.h>
#include "proxmark3.h"
#include "apps.h"
+#include "usb_cdc.h"
#include "util.h"
#include "hitag.h"
#include "string.h"
#include "mifareutil.h" // for MF_DBGLEVEL
#include "BigBuf.h"
#include "apps.h"
+#include "usb_cdc.h"
#ifdef WITH_SMARTCARD
#include "smartcard.h"
#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;
#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
// 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);
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
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;
+ 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");
+ //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 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 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;
}
- 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 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();
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();
}
} 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();
}
LED_D_OFF();
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
-
LED_A_OFF();
}
#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"
// 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;
// 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
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)) {
}
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();
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 {
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
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) {
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;
}
#ifndef __ISO14443A_H
#define __ISO14443A_H
+#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "usb_cmd.h"
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);
#include "proxmark3.h"
#include "apps.h"
+#include "usb_cdc.h"
#include "util.h"
#include "string.h"
#include "iso14443crc.h"
#include "string.h"
#include "iso15693tools.h"
#include "protocols.h"
-#include "cmd.h"
+#include "usb_cdc.h"
#include "BigBuf.h"
#include "fpgaloader.h"
#include "proxmark3.h"
#include "apps.h"
+#include "usb_cdc.h"
#include "util.h"
#include "string.h"
#include "legic_prng.h"
#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"
/**
#include <stdint.h>\r
\r
#include "proxmark3.h"\r
-#include "cmd.h"\r
+#include "usb_cdc.h"\r
#include "crapto1/crapto1.h"\r
#include "iso14443a.h"\r
#include "BigBuf.h"\r
\r
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r
\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);\r
LED_B_OFF();\r
\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
\r
return;\r
}\r
\r
- cmd_send(CMD_ACK,1,0,0,dataout,16);\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LED_D_OFF();\r
+\r
+ cmd_send(CMD_ACK,1,0,0,dataout,16);\r
LED_A_OFF();\r
}\r
\r
\r
if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");\r
\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));\r
LED_B_OFF();\r
\r
- // Thats it...\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
\r
\r
if (MF_DBGLEVEL >= MF_DBG_DEBUG) Dbprintf("Blocks read %d", countblocks);\r
\r
- cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0);\r
-\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LED_D_OFF();\r
+\r
+ cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0);\r
+\r
BigBuf_free();\r
LED_A_OFF();\r
}\r
\r
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,0,0);\r
LED_B_OFF();\r
\r
\r
- // Thats it...\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
\r
\r
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
\r
- cmd_send(CMD_ACK,1,0,0,0,0);\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
+ cmd_send(CMD_ACK,1,0,0,0,0);\r
LEDsoff();\r
}\r
*/\r
\r
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
\r
- cmd_send(CMD_ACK,1,0,0,0,0);\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
+ cmd_send(CMD_ACK,1,0,0,0,0);\r
LEDsoff();\r
}\r
\r
return;\r
};\r
\r
- cmd_send(CMD_ACK,1,0,0,0,0);\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
+ cmd_send(CMD_ACK,1,0,0,0,0);\r
LEDsoff();\r
}\r
\r
\r
crypto1_destroy(pcs);\r
\r
+ if (field_off) {\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+ }\r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));\r
LED_B_OFF();\r
\r
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");\r
\r
- if (field_off) {\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
- LEDsoff();\r
- }\r
}\r
\r
\r
memcpy(buf+16, &target_ks[1], 4);\r
memcpy(buf+20, &authentication_timeout, 4);\r
\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
+ if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");\r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));\r
LED_B_OFF();\r
\r
- if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");\r
-\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
\r
break;\r
}\r
\r
+ // reset fpga\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
// send USB response\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,NULL,0);\r
LED_B_OFF();\r
\r
- // reset fpga\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
\r
return;\r
break;\r
}\r
\r
+ if ((workFlags & 0x10) || (!isOK)) {\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ }\r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,uid,4);\r
LED_B_OFF();\r
\r
- if ((workFlags & 0x10) || (!isOK)) {\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
- LEDsoff();\r
- }\r
+ LEDsoff();\r
}\r
\r
\r
break;\r
}\r
\r
+ if ((workFlags & 0x10) || (!isOK)) {\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ }\r
+\r
LED_B_ON();\r
if (workFlags & 0x20) {\r
if (isOK)\r
cmd_send(CMD_ACK,isOK,0,0,data,18);\r
LED_B_OFF();\r
\r
- if ((workFlags & 0x10) || (!isOK)) {\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
- LEDsoff();\r
- }\r
+ LEDsoff();\r
}\r
\r
void MifareCIdent(){\r
// From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.\r
mifare_classic_halt(NULL, 0);\r
\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,0,0);\r
LED_B_OFF();\r
\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
\r
}\r
\r
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");\r
- cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));\r
+\r
+ cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));\r
}\r
\r
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){\r
\r
isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
\r
- if( isOK) {\r
+ if (isOK) {\r
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");\r
OnError(4);\r
return;\r
}\r
\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+\r
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
\r
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
\r
#include "fpgaloader.h"
#include "proxmark3.h"
#include "usb_cdc.h"
-#include "cmd.h"
#include "protocols.h"
#include "apps.h"
#include "crapto1/crapto1.h"
#include "mifareutil.h"
#include "common.h"
-#include "cmd.h"
+#include "usb_cdc.h"
#include "BigBuf.h"
#include "fpgaloader.h"
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;
}
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();
#include "proxmark3.h"
#include "apps.h"
+#include "usb_cdc.h"
#include "lfsampling.h"
#include "pcf7931.h"
#include "util.h"
// 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 )
#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);
-
-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 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);
+
+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);
extern void StopTicks(void);
// end iceman's ticks.h
-uint32_t prand();
+extern uint32_t prand();
#endif
# 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
// 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")));
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: {
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 */
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;
} 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;
}
if(!dont_ack) {
- cmd_send(CMD_ACK,arg0,0,0,0,0);
+ cmd_send_old(CMD_ACK,arg0,0,0,0,0);
}
}
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 */
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;
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;
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;
// 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]));
}
(void)mfCIdentify();
if (isMifareClassic) {
- switch(DetectClassicPrng()) {
+ switch (DetectClassicPrng()) {
case 0:
PrintAndLog("Prng detection: HARDENED (hardnested)");
break;
SendCommand(&c);
UsbCommand resp;
- WaitForResponse(CMD_ACK,&resp);
+ WaitForResponse(CMD_NACK,&resp);
iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;
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;
if (tagFound && !loop) return 1;
} else {
- if (verbose) PrintAndLog("Command execute timeout");
+ if (verbose) PrintAndLog("Error: No response from Proxmark.");
+ break;
}
if (!loop) break;
}
}\r
\r
UsbCommand resp;\r
- if (WaitForResponseTimeoutW(CMD_ACK, &resp, 2000, false)) {\r
+ if (WaitForResponseTimeoutW(CMD_UNKNOWN, &resp, 2000, false)) {\r
res = resp.arg[0] & 0xff;\r
uint16_t traceLen = resp.arg[1];\r
len = resp.arg[2];\r
#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include "comms.h"
#include "usb_cmd.h"
#include "cmdmain.h"
#include "cmdsmartcard.h"
#include <ctype.h>
+#include <string.h>
#include "ui.h"
#include "cmdparser.h"
#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"
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;
// 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
// 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.
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) {
* 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;
* @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!");
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);
}
/**
* @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);
// 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;
} 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 = ℞
+ 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;
+ 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;
+ }
+ }
}
}
- prx = ℞
-
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 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 (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);
}
* @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);
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);
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);
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");
}
// 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;
}
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;
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 (msclock() - start_time > ms_timeout) {
- break;
+ if (ms_timeout != -1 && 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 (cmd == CMD_UNKNOWN || response->cmd == cmd) {
+ return true;
+ }
+ }
}
return false;
}
// 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
-
-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_
+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);
+
+#endif // COMMS_H__
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;
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);
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)
}
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));
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;
return -1;
}
+
static int wait_for_ack(void)
{
UsbCommand ack;
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;
#include "flash.h"
#include "comms.h"
#include "usb_cmd.h"
-
+#include "uart.h"
void cmd_debug(UsbCommand* UC) {
// Debug
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 {
clearCommandBuffer();
SendCommand(&c);
- if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
+ if (!WaitForResponseTimeout(CMD_NACK, &resp, 2000)) {
PrintAndLog("PRNG UID: Reply timeout.");
return -1;
}
#include "cmdhw.h"
#include "whereami.h"
#include "comms.h"
-
+#include "uart.h"
void
#ifdef __has_attribute
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
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();
}
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
+#include <string.h>
#include "proxmark3.h"
#include "comms.h"
#include "usb_cmd.h"
+++ /dev/null
-/*\r
- * Proxmark send and receive commands\r
- *\r
- * Copyright (c) 2012, Roel Verdult\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- * 3. Neither the name of the copyright holders nor the\r
- * names of its contributors may be used to endorse or promote products\r
- * derived from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY\r
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\r
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * @file cmd.c\r
- * @brief\r
- */\r
-\r
-#include "cmd.h"\r
-#include "string.h"\r
-#include "proxmark3.h"\r
-\r
-bool cmd_receive(UsbCommand* cmd) {\r
- \r
- // Check if there is a usb packet available\r
- if (!usb_poll()) return false;\r
- \r
- // Try to retrieve the available command frame\r
- size_t rxlen = usb_read((byte_t*)cmd,sizeof(UsbCommand));\r
-\r
- // Check if the transfer was complete\r
- if (rxlen != sizeof(UsbCommand)) return false;\r
- \r
- // Received command successfully\r
- return true;\r
-}\r
-\r
-bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len) {\r
- UsbCommand txcmd;\r
-\r
- for (size_t i=0; i<sizeof(UsbCommand); i++) {\r
- ((byte_t*)&txcmd)[i] = 0x00;\r
- }\r
- \r
- // Compose the outgoing command frame\r
- txcmd.cmd = cmd;\r
- txcmd.arg[0] = arg0;\r
- txcmd.arg[1] = arg1; \r
- txcmd.arg[2] = arg2;\r
-\r
- // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE\r
- if (data && len) {\r
- len = MIN(len,USB_CMD_DATA_SIZE);\r
- for (size_t i=0; i<len; i++) {\r
- txcmd.d.asBytes[i] = ((byte_t*)data)[i];\r
- }\r
- }\r
- \r
- // Send frame and make sure all bytes are transmitted\r
- if (usb_write((byte_t*)&txcmd,sizeof(UsbCommand)) != 0) return false;\r
- \r
- return true;\r
-}\r
-\r
-\r
+++ /dev/null
-/*\r
- * Proxmark send and receive commands\r
- *\r
- * Copyright (c) 2010, Roel Verdult\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- * 3. Neither the name of the copyright holders nor the\r
- * names of its contributors may be used to endorse or promote products\r
- * derived from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY\r
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\r
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * @file cmd.h\r
- * @brief\r
- */\r
-\r
-#ifndef _PROXMARK_CMD_H_\r
-#define _PROXMARK_CMD_H_\r
-\r
-#include "common.h"\r
-#include "usb_cmd.h"\r
-#include "usb_cdc.h"\r
-\r
-bool cmd_receive(UsbCommand* cmd);\r
-bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);\r
-\r
-#endif // _PROXMARK_CMD_H_\r
-\r
*/\r
\r
#include "usb_cdc.h"\r
+\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+\r
+#include "common.h"\r
#include "at91sam7s512.h"\r
#include "config_gpio.h"\r
\r
-\r
#define AT91C_EP_CONTROL 0\r
#define AT91C_EP_OUT 1\r
#define AT91C_EP_IN 2\r
#define STR_MANUFACTURER 0x01\r
#define STR_PRODUCT 0x02\r
\r
+\r
static const char devDescriptor[] = {\r
/* Device descriptor */\r
0x12, // bLength\r
0x01 // bNumConfigs\r
};\r
\r
+\r
static const char cfgDescriptor[] = {\r
/* ============== CONFIGURATION 1 =========== */\r
/* Configuration 1 descriptor */\r
0x00 // bInterval\r
};\r
\r
+\r
static const char StrDescLanguageCodes[] = {\r
- 4, // Length\r
- 0x03, // Type is string\r
- 0x09, 0x04 // supported language Code 0 = 0x0409 (English)\r
+ 4, // Length\r
+ 0x03, // Type is string\r
+ 0x09, 0x04 // supported language Code 0 = 0x0409 (English)\r
};\r
\r
+\r
// Note: ModemManager (Linux) ignores Proxmark3 devices by matching the\r
// manufacturer string "proxmark.org". Don't change this.\r
static const char StrDescManufacturer[] = {\r
- 26, // Length\r
- 0x03, // Type is string\r
- 'p', 0x00,\r
- 'r', 0x00,\r
- 'o', 0x00,\r
- 'x', 0x00,\r
- 'm', 0x00,\r
- 'a', 0x00,\r
- 'r', 0x00,\r
- 'k', 0x00,\r
- '.', 0x00,\r
- 'o', 0x00,\r
- 'r', 0x00,\r
- 'g', 0x00\r
+ 26, // Length\r
+ 0x03, // Type is string\r
+ 'p', 0x00,\r
+ 'r', 0x00,\r
+ 'o', 0x00,\r
+ 'x', 0x00,\r
+ 'm', 0x00,\r
+ 'a', 0x00,\r
+ 'r', 0x00,\r
+ 'k', 0x00,\r
+ '.', 0x00,\r
+ 'o', 0x00,\r
+ 'r', 0x00,\r
+ 'g', 0x00\r
};\r
\r
+\r
static const char StrDescProduct[] = {\r
- 20, // Length\r
- 0x03, // Type is string\r
- 'p', 0x00,\r
- 'r', 0x00,\r
- 'o', 0x00,\r
- 'x', 0x00,\r
- 'm', 0x00,\r
- 'a', 0x00,\r
- 'r', 0x00,\r
- 'k', 0x00,\r
- '3', 0x00\r
+ 20, // Length\r
+ 0x03, // Type is string\r
+ 'p', 0x00,\r
+ 'r', 0x00,\r
+ 'o', 0x00,\r
+ 'x', 0x00,\r
+ 'm', 0x00,\r
+ 'a', 0x00,\r
+ 'r', 0x00,\r
+ 'k', 0x00,\r
+ '3', 0x00\r
};\r
\r
-const char* getStringDescriptor(uint8_t idx)\r
-{\r
+\r
+static const char* getStringDescriptor(uint8_t idx) {\r
switch (idx) {\r
case STR_LANGUAGE_CODES:\r
return StrDescLanguageCodes;\r
}\r
}\r
\r
+\r
// Bitmap for all status bits in CSR which must be written as 1 to cause no effect\r
-#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \\r
- |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \\r
- |AT91C_UDP_TXCOMP\r
+#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)\r
+\r
\r
// Clear flags in the UDP_CSR register\r
#define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \\r
volatile unsigned int reg; \\r
- reg = pUdp->UDP_CSR[(endpoint)]; \\r
+ reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \\r
reg |= REG_NO_EFFECT_1_ALL; \\r
reg &= ~(flags); \\r
- pUdp->UDP_CSR[(endpoint)] = reg; \\r
-} \r
+ AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \\r
+}\r
+\r
\r
// Set flags in the UDP_CSR register\r
#define UDP_SET_EP_FLAGS(endpoint, flags) { \\r
volatile unsigned int reg; \\r
- reg = pUdp->UDP_CSR[(endpoint)]; \\r
+ reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \\r
reg |= REG_NO_EFFECT_1_ALL; \\r
reg |= (flags); \\r
- pUdp->UDP_CSR[(endpoint)] = reg; \\r
+ AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \\r
}\r
\r
+\r
/* USB standard request codes */\r
#define STD_GET_STATUS_ZERO 0x0080\r
#define STD_GET_STATUS_INTERFACE 0x0081\r
#define SET_LINE_CODING 0x2021\r
#define SET_CONTROL_LINE_STATE 0x2221\r
\r
+\r
typedef struct {\r
unsigned int dwDTERRate;\r
char bCharFormat;\r
char bDataBits;\r
} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;\r
\r
-AT91S_CDC_LINE_CODING line = {\r
+\r
+static AT91S_CDC_LINE_CODING line = {\r
115200, // baudrate\r
0, // 1 Stop Bit\r
0, // None Parity\r
8}; // 8 Data bits\r
\r
\r
-void AT91F_CDC_Enumerate();\r
-\r
-AT91PS_UDP pUdp = AT91C_BASE_UDP;\r
-byte_t btConfiguration = 0;\r
-byte_t btConnection = 0;\r
-byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;\r
+static uint8_t btConfiguration = 0;\r
+static uint8_t btConnection = 0;\r
+static uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;\r
\r
\r
//*----------------------------------------------------------------------------\r
AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;\r
\r
// Clear all lingering interrupts\r
- if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {\r
- pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
+ if (AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {\r
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
}\r
}\r
\r
usb_disable();\r
\r
// Wait for a short while\r
- for (volatile size_t i=0; i<0x100000; i++);\r
+ for (volatile size_t i = 0; i < 0x100000; i++);\r
\r
// Reconnect USB reconnect\r
AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;\r
\r
\r
//*----------------------------------------------------------------------------\r
-//* \fn usb_check\r
-//* \brief Test if the device is configured and handle enumeration\r
-//*----------------------------------------------------------------------------\r
-bool usb_check() {\r
- AT91_REG isr = pUdp->UDP_ISR;\r
-\r
- if (isr & AT91C_UDP_ENDBUSRES) {\r
- pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
- // reset all endpoints\r
- pUdp->UDP_RSTEP = (unsigned int)-1;\r
- pUdp->UDP_RSTEP = 0;\r
- // Enable the function\r
- pUdp->UDP_FADDR = AT91C_UDP_FEN;\r
- // Configure endpoint 0\r
- pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);\r
- } else if (isr & AT91C_UDP_EPINT0) {\r
- pUdp->UDP_ICR = AT91C_UDP_EPINT0;\r
- AT91F_CDC_Enumerate();\r
- }\r
- return (btConfiguration) ? true : false;\r
-}\r
-\r
-\r
-bool usb_poll()\r
-{\r
- if (!usb_check()) return false;\r
- return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);\r
-}\r
-\r
-\r
-/**\r
- In github PR #129, some users appears to get a false positive from\r
- usb_poll, which returns true, but the usb_read operation\r
- still returns 0.\r
- This check is basically the same as above, but also checks\r
- that the length available to read is non-zero, thus hopefully fixes the\r
- bug.\r
-**/\r
-bool usb_poll_validate_length()\r
-{\r
- if (!usb_check()) return false;\r
- if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;\r
- return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;\r
-}\r
-\r
-//*----------------------------------------------------------------------------\r
-//* \fn usb_read\r
-//* \brief Read available data from Endpoint OUT\r
-//*----------------------------------------------------------------------------\r
-uint32_t usb_read(byte_t* data, size_t len) {\r
- byte_t bank = btReceiveBank;\r
- uint32_t packetSize, nbBytesRcv = 0;\r
- uint32_t time_out = 0;\r
- \r
- while (len) {\r
- if (!usb_check()) break;\r
-\r
- if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {\r
- packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);\r
- len -= packetSize;\r
- while(packetSize--)\r
- data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];\r
- UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);\r
- if (bank == AT91C_UDP_RX_DATA_BK0) {\r
- bank = AT91C_UDP_RX_DATA_BK1;\r
- } else {\r
- bank = AT91C_UDP_RX_DATA_BK0;\r
- }\r
- }\r
- if (time_out++ == 0x1fff) break;\r
- }\r
-\r
- btReceiveBank = bank;\r
- return nbBytesRcv;\r
-}\r
-\r
-\r
-//*----------------------------------------------------------------------------\r
-//* \fn usb_write\r
-//* \brief Send through endpoint 2\r
+//* \fn AT91F_USB_SendZlp\r
+//* \brief Send zero length packet through an endpoint\r
//*----------------------------------------------------------------------------\r
-uint32_t usb_write(const byte_t* data, const size_t len) {\r
- size_t length = len;\r
- uint32_t cpt = 0;\r
-\r
- if (!length) return 0;\r
- if (!usb_check()) return 0;\r
-\r
- // Send the first packet\r
- cpt = MIN(length, AT91C_EP_IN_SIZE);\r
- length -= cpt;\r
- while (cpt--) {\r
- pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
- }\r
- UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);\r
-\r
- while (length) {\r
- // Fill the next bank\r
- cpt = MIN(length, AT91C_EP_IN_SIZE);\r
- length -= cpt;\r
- while (cpt--) {\r
- pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
- }\r
- // Wait for the previous bank to be sent\r
- while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
- if (!usb_check()) return length;\r
- }\r
- UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);\r
- while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
- UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);\r
- }\r
-\r
- // Wait for the end of transfer\r
- while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
- if (!usb_check()) return length;\r
- }\r
-\r
- UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);\r
- while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
-\r
- return length;\r
+static void AT91F_USB_SendZlp(uint8_t endpoint) {\r
+ UDP_SET_EP_FLAGS(endpoint, AT91C_UDP_TXPKTRDY);\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP))\r
+ /* wait */;\r
+ UDP_CLEAR_EP_FLAGS(endpoint, AT91C_UDP_TXCOMP);\r
+ while (AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP)\r
+ /* wait */;\r
}\r
\r
\r
//* \fn AT91F_USB_SendData\r
//* \brief Send Data through the control endpoint\r
//*----------------------------------------------------------------------------\r
-unsigned int csrTab[100] = {0x00};\r
-unsigned char csrIdx = 0;\r
-\r
-static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {\r
+static void AT91F_USB_SendData(const char *pData, uint32_t length) {\r
uint32_t cpt = 0;\r
AT91_REG csr;\r
\r
length -= cpt;\r
\r
while (cpt--)\r
- pUdp->UDP_FDR[0] = *pData++;\r
+ AT91C_BASE_UDP->UDP_FDR[0] = *pData++;\r
\r
- if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {\r
+ if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {\r
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);\r
- while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);\r
+ while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)\r
+ /* wait */;\r
}\r
\r
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);\r
do {\r
- csr = pUdp->UDP_CSR[AT91C_EP_CONTROL];\r
+ csr = AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL];\r
\r
// Data IN stage has been stopped by a status OUT\r
if (csr & AT91C_UDP_RX_DATA_BK0) {\r
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);\r
return;\r
}\r
- } while ( !(csr & AT91C_UDP_TXCOMP) );\r
+ } while (!(csr & AT91C_UDP_TXCOMP));\r
\r
} while (length);\r
\r
- if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {\r
+ if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {\r
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);\r
- while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);\r
+ while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)\r
+ /* wait */;\r
}\r
}\r
\r
\r
-//*----------------------------------------------------------------------------\r
-//* \fn AT91F_USB_SendZlp\r
-//* \brief Send zero length packet through the control endpoint\r
-//*----------------------------------------------------------------------------\r
-void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {\r
- UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);\r
- while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) );\r
- UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);\r
- while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);\r
-}\r
-\r
-\r
//*----------------------------------------------------------------------------\r
//* \fn AT91F_USB_SendStall\r
//* \brief Stall the control endpoint\r
//*----------------------------------------------------------------------------\r
-void AT91F_USB_SendStall(AT91PS_UDP pUdp) {\r
+static void AT91F_USB_SendStall(void) {\r
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);\r
- while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR) );\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR))\r
+ /* wait */;\r
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);\r
- while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));\r
+ while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR))\r
+ /* wait */;\r
}\r
\r
\r
//* \fn AT91F_CDC_Enumerate\r
//* \brief This function is a callback invoked when a SETUP packet is received\r
//*----------------------------------------------------------------------------\r
-void AT91F_CDC_Enumerate() {\r
- byte_t bmRequestType, bRequest;\r
+static void AT91F_CDC_Enumerate() {\r
+ uint8_t bmRequestType, bRequest;\r
uint16_t wValue, wIndex, wLength, wStatus;\r
\r
- if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) )\r
+ if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP))\r
return;\r
\r
- bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];\r
- bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];\r
- wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);\r
- wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);\r
- wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);\r
- wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);\r
- wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);\r
- wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);\r
+ bmRequestType = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];\r
+ bRequest = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];\r
+ wValue = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);\r
+ wValue |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);\r
+ wIndex = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);\r
+ wIndex |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);\r
+ wLength = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);\r
+ wLength |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);\r
\r
- if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host\r
+ if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host\r
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);\r
- while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) );\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR))\r
+ /* wait */;\r
}\r
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);\r
- while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) );\r
+ while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)\r
+ /* wait */;\r
\r
// Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1\r
switch ((bRequest << 8) | bmRequestType) {\r
case STD_GET_DESCRIPTOR:\r
if (wValue == 0x100) // Return Device Descriptor\r
- AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));\r
+ AT91F_USB_SendData(devDescriptor, MIN(sizeof(devDescriptor), wLength));\r
else if (wValue == 0x200) // Return Configuration Descriptor\r
- AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));\r
+ AT91F_USB_SendData(cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));\r
else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor\r
const char *strDescriptor = getStringDescriptor(wValue & 0xff);\r
if (strDescriptor != NULL) {\r
- AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));\r
+ AT91F_USB_SendData(strDescriptor, MIN(strDescriptor[0], wLength));\r
} else {\r
- AT91F_USB_SendStall(pUdp);\r
+ AT91F_USB_SendStall();\r
}\r
}\r
else\r
- AT91F_USB_SendStall(pUdp);\r
+ AT91F_USB_SendStall();\r
break;\r
case STD_SET_ADDRESS:\r
- AT91F_USB_SendZlp(pUdp);\r
- pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);\r
- pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
+ AT91C_BASE_UDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);\r
+ AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;\r
break;\r
case STD_SET_CONFIGURATION:\r
btConfiguration = wValue;\r
- AT91F_USB_SendZlp(pUdp);\r
- pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;\r
- pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;\r
- pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;\r
- pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
+ AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;\r
+ AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;\r
+ AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;\r
+ AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;\r
break;\r
case STD_GET_CONFIGURATION:\r
- AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));\r
+ AT91F_USB_SendData((char *) &(btConfiguration), sizeof(btConfiguration));\r
break;\r
case STD_GET_STATUS_ZERO:\r
- wStatus = 0; // Device is Bus powered, remote wakeup disabled\r
- AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
+ wStatus = 0; // Device is Bus powered, remote wakeup disabled\r
+ AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));\r
break;\r
case STD_GET_STATUS_INTERFACE:\r
- wStatus = 0; // reserved for future use\r
- AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
+ wStatus = 0; // reserved for future use\r
+ AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));\r
break;\r
case STD_GET_STATUS_ENDPOINT:\r
wStatus = 0;\r
wIndex &= 0x0F;\r
- if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {\r
- wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
- AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
- }\r
- else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {\r
- wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
- AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
- }\r
- else\r
- AT91F_USB_SendStall(pUdp);\r
+ if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {\r
+ wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
+ AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));\r
+ } else if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {\r
+ wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
+ AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));\r
+ } else\r
+ AT91F_USB_SendStall();\r
break;\r
case STD_SET_FEATURE_ZERO:\r
- AT91F_USB_SendStall(pUdp);\r
- break;\r
+ AT91F_USB_SendStall();\r
+ break;\r
case STD_SET_FEATURE_INTERFACE:\r
- AT91F_USB_SendZlp(pUdp);\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
break;\r
case STD_SET_FEATURE_ENDPOINT:\r
wIndex &= 0x0F;\r
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {\r
- pUdp->UDP_CSR[wIndex] = 0;\r
- AT91F_USB_SendZlp(pUdp);\r
- }\r
- else\r
- AT91F_USB_SendStall(pUdp);\r
+ AT91C_BASE_UDP->UDP_CSR[wIndex] = 0;\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
+ } else\r
+ AT91F_USB_SendStall();\r
break;\r
case STD_CLEAR_FEATURE_ZERO:\r
- AT91F_USB_SendStall(pUdp);\r
- break;\r
+ AT91F_USB_SendStall();\r
+ break;\r
case STD_CLEAR_FEATURE_INTERFACE:\r
- AT91F_USB_SendZlp(pUdp);\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
break;\r
case STD_CLEAR_FEATURE_ENDPOINT:\r
wIndex &= 0x0F;\r
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {\r
if (wIndex == AT91C_EP_OUT)\r
- pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);\r
+ AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);\r
else if (wIndex == AT91C_EP_IN)\r
- pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);\r
+ AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);\r
else if (wIndex == AT91C_EP_NOTIFY)\r
- pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);\r
- AT91F_USB_SendZlp(pUdp);\r
+ AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
}\r
else\r
- AT91F_USB_SendStall(pUdp);\r
+ AT91F_USB_SendStall();\r
break;\r
\r
// handle CDC class requests\r
case SET_LINE_CODING:\r
- while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0) );\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0))\r
+ /* wait */;\r
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);\r
- AT91F_USB_SendZlp(pUdp);\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
break;\r
case GET_LINE_CODING:\r
- AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));\r
+ AT91F_USB_SendData((char *) &line, MIN(sizeof(line), wLength));\r
break;\r
case SET_CONTROL_LINE_STATE:\r
btConnection = wValue;\r
- AT91F_USB_SendZlp(pUdp);\r
+ AT91F_USB_SendZlp(AT91C_EP_CONTROL);\r
break;\r
default:\r
- AT91F_USB_SendStall(pUdp);\r
- break;\r
+ AT91F_USB_SendStall();\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+//*----------------------------------------------------------------------------\r
+//* \fn usb_check\r
+//* \brief Test if the device is configured and handle enumeration\r
+//*----------------------------------------------------------------------------\r
+static bool usb_check() {\r
+ AT91_REG isr = AT91C_BASE_UDP->UDP_ISR;\r
+\r
+ if (isr & AT91C_UDP_ENDBUSRES) {\r
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
+ // reset all endpoints\r
+ AT91C_BASE_UDP->UDP_RSTEP = (unsigned int)-1;\r
+ AT91C_BASE_UDP->UDP_RSTEP = 0;\r
+ // Enable the function\r
+ AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;\r
+ // Configure endpoint 0\r
+ AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);\r
+ } else if (isr & AT91C_UDP_EPINT0) {\r
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_EPINT0;\r
+ AT91F_CDC_Enumerate();\r
+ }\r
+ return (btConfiguration) ? true : false;\r
+}\r
+\r
+\r
+bool usb_poll() {\r
+ if (!usb_check()) return false;\r
+ return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);\r
+}\r
+\r
+\r
+/**\r
+ In github PR #129, some users appears to get a false positive from\r
+ usb_poll, which returns true, but the usb_read operation\r
+ still returns 0.\r
+ This check is basically the same as above, but also checks\r
+ that the length available to read is non-zero, thus hopefully fixes the\r
+ bug.\r
+**/\r
+bool usb_poll_validate_length() {\r
+ if (!usb_check()) return false;\r
+ if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;\r
+ return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;\r
+}\r
+\r
+\r
+//*----------------------------------------------------------------------------\r
+//* \fn usb_read\r
+//* \brief Read available data from Endpoint OUT\r
+//*----------------------------------------------------------------------------\r
+static uint32_t usb_read(uint8_t* data, size_t len) {\r
+ uint8_t bank = btReceiveBank;\r
+ uint32_t packetSize, nbBytesRcv = 0;\r
+ uint32_t time_out = 0;\r
+\r
+ while (len) {\r
+ if (!usb_check()) break;\r
+\r
+ if ( AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & bank ) {\r
+ packetSize = MIN(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16, len);\r
+ len -= packetSize;\r
+ while (packetSize--)\r
+ data[nbBytesRcv++] = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_OUT];\r
+ UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);\r
+ if (bank == AT91C_UDP_RX_DATA_BK0) {\r
+ bank = AT91C_UDP_RX_DATA_BK1;\r
+ } else {\r
+ bank = AT91C_UDP_RX_DATA_BK0;\r
+ }\r
+ }\r
+ if (time_out++ == 0x1fff) break;\r
+ }\r
+\r
+ btReceiveBank = bank;\r
+ return nbBytesRcv;\r
+}\r
+\r
+\r
+//*----------------------------------------------------------------------------\r
+//* \fn usb_write\r
+//* \brief Send through endpoint 2\r
+//*----------------------------------------------------------------------------\r
+static uint32_t usb_write(const uint8_t* data, const size_t len) {\r
+ size_t length = len;\r
+ uint32_t cpt = 0;\r
+\r
+ if (!length) return 0;\r
+ if (!usb_check()) return 0;\r
+\r
+ // Send the first packet\r
+ cpt = MIN(length, AT91C_EP_IN_SIZE);\r
+ length -= cpt;\r
+ while (cpt--) {\r
+ AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;\r
+ }\r
+ UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))\r
+ /* wait */;\r
+\r
+ while (length) {\r
+ // Fill the next bank\r
+ cpt = MIN(length, AT91C_EP_IN_SIZE);\r
+ length -= cpt;\r
+ while (cpt--) {\r
+ AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;\r
+ }\r
+ // Wait for the previous bank to be sent\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
+ if (!usb_check()) return length;\r
+ }\r
+ UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))\r
+ /* wait */;\r
+ UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);\r
+ while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)\r
+ /* wait */;\r
+ }\r
+\r
+ // Wait for the end of transfer\r
+ while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
+ if (!usb_check()) return length;\r
+ }\r
+ UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);\r
+ while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)\r
+ /* wait */;\r
+\r
+ if (len % AT91C_EP_IN_SIZE == 0) { // need to send a zero length packet to complete the transfer\r
+ AT91F_USB_SendZlp(AT91C_EP_IN);\r
}\r
+\r
+ return length;\r
+}\r
+\r
+\r
+//***************************************************************************\r
+// Interface to the main program\r
+//***************************************************************************\r
+\r
+// The function to receive a command from the client via USB\r
+bool cmd_receive(UsbCommand* cmd) {\r
+\r
+ // Check if there is a usb packet available\r
+ if (!usb_poll())\r
+ return false;\r
+\r
+ // Try to retrieve the available command frame\r
+ size_t rxlen = usb_read((uint8_t*)cmd, sizeof(UsbCommand));\r
+\r
+ // Check if the transfer was complete\r
+ if (rxlen != sizeof(UsbCommand))\r
+ return false;\r
+\r
+ // Received command successfully\r
+ return true;\r
}\r
+\r
+\r
+// The function to send a response to the client via USB\r
+bool cmd_send(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen) {\r
+\r
+ UsbResponse txcmd;\r
+\r
+ // Compose the outgoing response frame\r
+ txcmd.cmd = cmd | CMD_VARIABLE_SIZE_FLAG;\r
+ txcmd.arg[0] = arg0;\r
+ txcmd.arg[1] = arg1;\r
+ txcmd.arg[2] = arg2;\r
+\r
+ // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE\r
+ if (data) {\r
+ datalen = MIN(datalen, USB_CMD_DATA_SIZE);\r
+ for (uint16_t i = 0; i < datalen; i++) {\r
+ txcmd.d.asBytes[i] = ((uint8_t*)data)[i];\r
+ }\r
+ txcmd.datalen = datalen;\r
+ } else {\r
+ txcmd.datalen = 0;\r
+ }\r
+\r
+ // Send frame and make sure all bytes are transmitted\r
+ size_t tx_size = offsetof(UsbResponse, d) + datalen;\r
+ if (usb_write((uint8_t*)&txcmd, tx_size) != 0) return false;\r
+\r
+ return true;\r
+}\r
+\r
+\r
+// For compatibility only: legacy function to send a response with fixed size to the client via USB\r
+bool cmd_send_old(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen) {\r
+\r
+ UsbCommand txcmd;\r
+\r
+ // Compose the outgoing response frame\r
+ txcmd.cmd = cmd;\r
+ txcmd.arg[0] = arg0;\r
+ txcmd.arg[1] = arg1;\r
+ txcmd.arg[2] = arg2;\r
+\r
+ // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE\r
+ if (data) {\r
+ datalen = MIN(datalen, USB_CMD_DATA_SIZE);\r
+ for (uint16_t i = 0; i < datalen; i++) {\r
+ txcmd.d.asBytes[i] = ((uint8_t*)data)[i];\r
+ }\r
+ }\r
+\r
+ // Send frame and make sure all bytes are transmitted\r
+ if (usb_write((uint8_t*)&txcmd, sizeof(UsbCommand)) != 0) return false;\r
+\r
+ return true;\r
+}\r
+\r
* @brief\r
*/\r
\r
-#ifndef _USB_CDC_H_\r
-#define _USB_CDC_H_\r
+#ifndef USB_CDC_H__\r
+#define USB_CDC_H__\r
\r
-#include "common.h"\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+#include "usb_cmd.h"\r
\r
-void usb_disable();\r
-void usb_enable();\r
-bool usb_check();\r
-bool usb_poll();\r
-bool usb_poll_validate_length();\r
-uint32_t usb_read(byte_t* data, size_t len);\r
-uint32_t usb_write(const byte_t* data, const size_t len);\r
-\r
-#endif // _USB_CDC_H_\r
+extern void usb_disable();\r
+extern void usb_enable();\r
+extern bool usb_poll();\r
+extern bool usb_poll_validate_length();\r
+extern bool cmd_receive(UsbCommand* cmd);\r
+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\r
+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\r
\r
+#endif // USB_CDC_H__\r
// 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
# 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
// 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>
#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;
int samples_to_skip;
} sample_config;
+
// For the bootloader
#define CMD_DEVICE_INFO 0x0000
#define CMD_SETUP_WRITE 0x0001
#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
#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
#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
// 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.
* @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
*
* 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.
*
* 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.
*/
/* 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__
-/*
- * 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
-
+/*\r
+ * Generic uart / rs232/ serial port library\r
+ *\r
+ * Copyright (c) 2013, Roel Verdult\r
+ * Copyright (c) 2018 Google\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * 3. Neither the name of the copyright holders nor the\r
+ * names of its contributors may be used to endorse or promote products\r
+ * derived from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY\r
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\r
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * @file uart_posix.c\r
+ *\r
+ * This version of the library has functionality removed which was not used by\r
+ * proxmark3 project.\r
+ */\r
+\r
+// Test if we are dealing with posix operating systems\r
+#ifndef _WIN32\r
+#define _DEFAULT_SOURCE\r
+\r
+#include "uart.h"\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdbool.h>\r
+#include <termios.h>\r
+#include <sys/ioctl.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <sys/socket.h>\r
+#include <netinet/tcp.h>\r
+#include <netdb.h>\r
+#include <sys/time.h>\r
+#include <errno.h>\r
+\r
+// Fix missing definition on OS X.\r
+// Taken from https://github.com/unbit/uwsgi/commit/b608eb1772641d525bfde268fe9d6d8d0d5efde7\r
+#ifndef SOL_TCP\r
+#define SOL_TCP IPPROTO_TCP\r
+#endif\r
+\r
+typedef struct termios term_info;\r
+typedef struct {\r
+ int fd; // Serial port file descriptor\r
+ term_info tiOld; // Terminal info before using the port\r
+ term_info tiNew; // Terminal info during the transaction\r
+} serial_port_unix;\r
+\r
+// Set time-out on 30 miliseconds\r
+static struct timeval timeout = {\r
+ .tv_sec = 0, // 0 second\r
+ .tv_usec = 30000 // 30000 micro seconds\r
+};\r
+\r
+\r
+void uart_close(const serial_port sp) {\r
+ serial_port_unix* spu = (serial_port_unix*)sp;\r
+ tcflush(spu->fd, TCIOFLUSH);\r
+ tcsetattr(spu->fd, TCSANOW, &(spu->tiOld));\r
+ struct flock fl;\r
+ fl.l_type = F_UNLCK;\r
+ fl.l_whence = SEEK_SET;\r
+ fl.l_start = 0;\r
+ fl.l_len = 0;\r
+ fl.l_pid = getpid();\r
+ fcntl(spu->fd, F_SETLK, &fl);\r
+ close(spu->fd);\r
+ free(sp);\r
+}\r
+\r
+\r
+serial_port uart_open(const char* pcPortName) {\r
+\r
+ serial_port_unix* sp = malloc(sizeof(serial_port_unix));\r
+ if (sp == 0) return INVALID_SERIAL_PORT;\r
+\r
+ if (memcmp(pcPortName, "tcp:", 4) == 0) {\r
+ struct addrinfo *addr = NULL, *rp;\r
+ char *addrstr = strdup(pcPortName + 4);\r
+ if (addrstr == NULL) {\r
+ printf("Error: strdup\n");\r
+ return INVALID_SERIAL_PORT;\r
+ }\r
+ char *colon = strrchr(addrstr, ':');\r
+ char *portstr;\r
+\r
+ // Set time-out to 300 milliseconds only for TCP port\r
+ timeout.tv_usec = 300000;\r
+\r
+ if (colon) {\r
+ portstr = colon + 1;\r
+ *colon = '\0';\r
+ } else {\r
+ portstr = "7901";\r
+ }\r
+\r
+ struct addrinfo info;\r
+\r
+ memset(&info, 0, sizeof(info));\r
+\r
+ info.ai_socktype = SOCK_STREAM;\r
+\r
+ int s = getaddrinfo(addrstr, portstr, &info, &addr);\r
+ if (s != 0) {\r
+ printf("Error: getaddrinfo: %s\n", gai_strerror(s));\r
+ return INVALID_SERIAL_PORT;\r
+ }\r
+\r
+ int sfd;\r
+ for (rp = addr; rp != NULL; rp = rp->ai_next) {\r
+ sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\r
+ if (sfd == -1)\r
+ continue;\r
+ if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)\r
+ break;\r
+ close(sfd);\r
+ }\r
+\r
+ if (rp == NULL) { /* No address succeeded */\r
+ printf("Error: Could not connect\n");\r
+ return INVALID_SERIAL_PORT;\r
+ }\r
+\r
+ freeaddrinfo(addr);\r
+ free(addrstr);\r
+\r
+ sp->fd = sfd;\r
+\r
+ int one = 1;\r
+ setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));\r
+ return sp;\r
+ }\r
+\r
+ sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);\r
+ if (sp->fd == -1) {\r
+ uart_close(sp);\r
+ return INVALID_SERIAL_PORT;\r
+ }\r
+\r
+ // Finally figured out a way to claim a serial port interface under unix\r
+ // We just try to set a (advisory) lock on the file descriptor\r
+ struct flock fl;\r
+ fl.l_type = F_WRLCK;\r
+ fl.l_whence = SEEK_SET;\r
+ fl.l_start = 0;\r
+ fl.l_len = 0;\r
+ fl.l_pid = getpid();\r
+\r
+ // Does the system allows us to place a lock on this file descriptor\r
+ if (fcntl(sp->fd, F_SETLK, &fl) == -1) {\r
+ // A conflicting lock is held by another process\r
+ free(sp);\r
+ return CLAIMED_SERIAL_PORT;\r
+ }\r
+\r
+ // Try to retrieve the old (current) terminal info struct\r
+ if (tcgetattr(sp->fd,&sp->tiOld) == -1) {\r
+ uart_close(sp);\r
+ return INVALID_SERIAL_PORT;\r
+ }\r
+\r
+ // Duplicate the (old) terminal info struct\r
+ sp->tiNew = sp->tiOld;\r
+\r
+ // Configure the serial port\r
+ sp->tiNew.c_cflag &= ~(CSIZE | PARENB);\r
+ sp->tiNew.c_cflag |= (CS8 | CLOCAL | CREAD);\r
+ sp->tiNew.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);\r
+ sp->tiNew.c_iflag |= IGNPAR;\r
+ sp->tiNew.c_oflag &= ~OPOST;\r
+ sp->tiNew.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);\r
+\r
+\r
+ // Try to set the new terminal info struct\r
+ if (tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) {\r
+ uart_close(sp);\r
+ return INVALID_SERIAL_PORT;\r
+ }\r
+\r
+ // Flush all lingering data that may exist\r
+ tcflush(sp->fd, TCIOFLUSH);\r
+\r
+ return sp;\r
+}\r
+\r
+\r
+bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t szMaxRxLen, size_t* pszRxLen) {\r
+\r
+ *pszRxLen = 0;\r
+\r
+ if (szMaxRxLen == 0) return true;\r
+\r
+ struct timeval t_current;\r
+ gettimeofday(&t_current, NULL);\r
+ struct timeval t_end;\r
+ timeradd(&t_current, &timeout, &t_end);\r
+\r
+ while (true) {\r
+ int res = read(((serial_port_unix*)sp)->fd, pbtRx, szMaxRxLen - *pszRxLen);\r
+ if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) return false;\r
+ if (res > 0) {\r
+ *pszRxLen += res;\r
+ pbtRx += res;\r
+ }\r
+ if (*pszRxLen == szMaxRxLen) return true; // we could read all requested bytes in time\r
+ gettimeofday(&t_current, NULL);\r
+ if (timercmp(&t_current, &t_end, >)) return true; // timeout\r
+ // set next select timeout\r
+ struct timeval t_remains;\r
+ timersub(&t_end, &t_current, &t_remains);\r
+ // Set the file descriptor set\r
+ fd_set rfds;\r
+ FD_ZERO(&rfds);\r
+ FD_SET(((serial_port_unix*)sp)->fd, &rfds);\r
+ // wait for more bytes available\r
+ res = select(((serial_port_unix*)sp)->fd+1, &rfds, NULL, NULL, &t_remains);\r
+ if (res < 0) return false;\r
+ if (res == 0) return true; // timeout\r
+ }\r
+ return true; // should never come here\r
+}\r
+\r
+\r
+bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) {\r
+\r
+ if (szTxLen == 0) return true;\r
+\r
+ size_t bytes_written = 0;\r
+\r
+ struct timeval t_current;\r
+ gettimeofday(&t_current, NULL);\r
+ struct timeval t_end;\r
+ timeradd(&t_current, &timeout, &t_end);\r
+\r
+ while (true) {\r
+ int res = write(((serial_port_unix*)sp)->fd, pbtTx, szTxLen - bytes_written);\r
+ if (res < 0 && res != EAGAIN && res != EWOULDBLOCK) return false;\r
+ if (res > 0) {\r
+ pbtTx += res;\r
+ bytes_written += res;\r
+ }\r
+ if (bytes_written == szTxLen) return true; // we could write all bytes\r
+ gettimeofday(&t_current, NULL);\r
+ if (timercmp(&t_current, &t_end, >)) return false; // timeout\r
+ // set next select timeout\r
+ struct timeval t_remains;\r
+ timersub(&t_end, &t_current, &t_remains);\r
+ // Set the file descriptor set\r
+ fd_set wfds;\r
+ FD_ZERO(&wfds);\r
+ FD_SET(((serial_port_unix*)sp)->fd, &wfds);\r
+ // wait until more bytes can be written\r
+ res = select(((serial_port_unix*)sp)->fd+1, NULL, &wfds, NULL, &t_remains);\r
+ if (res < 0) return false; // error\r
+ if (res == 0) return false; // timeout\r
+ }\r
+ return true;\r
+}\r
+\r
+\r
+bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {\r
+ const serial_port_unix* spu = (serial_port_unix*)sp;\r
+ speed_t stPortSpeed;\r
+ switch (uiPortSpeed) {\r
+ case 0: stPortSpeed = B0; break;\r
+ case 50: stPortSpeed = B50; break;\r
+ case 75: stPortSpeed = B75; break;\r
+ case 110: stPortSpeed = B110; break;\r
+ case 134: stPortSpeed = B134; break;\r
+ case 150: stPortSpeed = B150; break;\r
+ case 300: stPortSpeed = B300; break;\r
+ case 600: stPortSpeed = B600; break;\r
+ case 1200: stPortSpeed = B1200; break;\r
+ case 1800: stPortSpeed = B1800; break;\r
+ case 2400: stPortSpeed = B2400; break;\r
+ case 4800: stPortSpeed = B4800; break;\r
+ case 9600: stPortSpeed = B9600; break;\r
+ case 19200: stPortSpeed = B19200; break;\r
+ case 38400: stPortSpeed = B38400; break;\r
+# ifdef B57600\r
+ case 57600: stPortSpeed = B57600; break;\r
+# endif\r
+# ifdef B115200\r
+ case 115200: stPortSpeed = B115200; break;\r
+# endif\r
+# ifdef B230400\r
+ case 230400: stPortSpeed = B230400; break;\r
+# endif\r
+# ifdef B460800\r
+ case 460800: stPortSpeed = B460800; break;\r
+# endif\r
+# ifdef B921600\r
+ case 921600: stPortSpeed = B921600; break;\r
+# endif\r
+ default: return false;\r
+ };\r
+ struct termios ti;\r
+ if (tcgetattr(spu->fd, &ti) == -1) return false;\r
+ // Set port speed (Input and Output)\r
+ cfsetispeed(&ti,stPortSpeed);\r
+ cfsetospeed(&ti,stPortSpeed);\r
+ return (tcsetattr(spu->fd, TCSANOW, &ti) != -1);\r
+}\r
+\r
+uint32_t uart_get_speed(const serial_port sp) {\r
+ struct termios ti;\r
+ uint32_t uiPortSpeed;\r
+ const serial_port_unix* spu = (serial_port_unix*)sp;\r
+ if (tcgetattr(spu->fd, &ti) == -1) return 0;\r
+ // Set port speed (Input)\r
+ speed_t stPortSpeed = cfgetispeed(&ti);\r
+ switch (stPortSpeed) {\r
+ case B0: uiPortSpeed = 0; break;\r
+ case B50: uiPortSpeed = 50; break;\r
+ case B75: uiPortSpeed = 75; break;\r
+ case B110: uiPortSpeed = 110; break;\r
+ case B134: uiPortSpeed = 134; break;\r
+ case B150: uiPortSpeed = 150; break;\r
+ case B300: uiPortSpeed = 300; break;\r
+ case B600: uiPortSpeed = 600; break;\r
+ case B1200: uiPortSpeed = 1200; break;\r
+ case B1800: uiPortSpeed = 1800; break;\r
+ case B2400: uiPortSpeed = 2400; break;\r
+ case B4800: uiPortSpeed = 4800; break;\r
+ case B9600: uiPortSpeed = 9600; break;\r
+ case B19200: uiPortSpeed = 19200; break;\r
+ case B38400: uiPortSpeed = 38400; break;\r
+# ifdef B57600\r
+ case B57600: uiPortSpeed = 57600; break;\r
+# endif\r
+# ifdef B115200\r
+ case B115200: uiPortSpeed = 115200; break;\r
+# endif\r
+# ifdef B230400\r
+ case B230400: uiPortSpeed = 230400; break;\r
+# endif\r
+# ifdef B460800\r
+ case B460800: uiPortSpeed = 460800; break;\r
+# endif\r
+# ifdef B921600\r
+ case B921600: uiPortSpeed = 921600; break;\r
+# endif\r
+ default: return 0;\r
+ };\r
+ return uiPortSpeed;\r
+}\r
+\r
+#endif\r
#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