uint8_t response6[] = { 0x03, 0x3B, 0x00, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS
ComputeCrc14443(CRC_14443_A, response6, 3, &response6[3], &response6[4]);
- uint8_t *resp;
+ uint8_t *resp = NULL;
int respLen;
// Longest possible response will be 16 bytes + 2 CRC = 18 bytes
}
//-----------------------------------------------------------------------------
-// Code a 7-bit command without parity bit
-// This is especially for 0x26 and 0x52 (REQA and WUPA)
+// Prepare reader command (in bits, support short frames) to send to FPGA
//-----------------------------------------------------------------------------
-void ShortFrameFromReader(const uint8_t bt)
-{
- int j;
- int last;
- uint8_t b;
-
- ToSendReset();
-
- // Start of Communication (Seq. Z)
- ToSend[++ToSendMax] = SEC_Z;
- last = 0;
-
- b = bt;
- for(j = 0; j < 7; j++) {
- if(b & 1) {
- // Sequence X
- ToSend[++ToSendMax] = SEC_X;
- last = 1;
- } else {
- if(last == 0) {
- // Sequence Z
- ToSend[++ToSendMax] = SEC_Z;
- }
- else {
- // Sequence Y
- ToSend[++ToSendMax] = SEC_Y;
- last = 0;
- }
- }
- b >>= 1;
- }
-
- // End of Communication
- if(last == 0) {
- // Sequence Z
- ToSend[++ToSendMax] = SEC_Z;
- }
- else {
- // Sequence Y
- ToSend[++ToSendMax] = SEC_Y;
- last = 0;
- }
- // Sequence Y
- ToSend[++ToSendMax] = SEC_Y;
-
- // Just to be sure!
- ToSend[++ToSendMax] = SEC_Y;
- ToSend[++ToSendMax] = SEC_Y;
- ToSend[++ToSendMax] = SEC_Y;
-
- // Convert from last character reference to length
- ToSendMax++;
-}
-
-//-----------------------------------------------------------------------------
-// Prepare reader command to send to FPGA
-//
-//-----------------------------------------------------------------------------
-void CodeIso14443aAsReaderPar(const uint8_t * cmd, int len, uint32_t dwParity)
+void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, int bits, uint32_t dwParity)
{
int i, j;
int last;
ToSend[++ToSendMax] = SEC_Z;
last = 0;
+ size_t bytecount = nbytes(bits);
// Generate send structure for the data bits
- for (i = 0; i < len; i++) {
+ for (i = 0; i < bytecount; i++) {
// Get the current byte to send
b = cmd[i];
+ size_t bitsleft = MIN((bits-(i*8)),8);
- for (j = 0; j < 8; j++) {
+ for (j = 0; j < bitsleft; j++) {
if (b & 1) {
// Sequence X
ToSend[++ToSendMax] = SEC_X;
b >>= 1;
}
- // Get the parity bit
- if ((dwParity >> i) & 0x01) {
- // Sequence X
- ToSend[++ToSendMax] = SEC_X;
- last = 1;
- } else {
- if (last == 0) {
- // Sequence Z
- ToSend[++ToSendMax] = SEC_Z;
+ // Only transmit (last) parity bit if we transmitted a complete byte
+ if (j == 8) {
+ // Get the parity bit
+ if ((dwParity >> i) & 0x01) {
+ // Sequence X
+ ToSend[++ToSendMax] = SEC_X;
+ last = 1;
} else {
- // Sequence Y
- ToSend[++ToSendMax] = SEC_Y;
- last = 0;
+ if (last == 0) {
+ // Sequence Z
+ ToSend[++ToSendMax] = SEC_Z;
+ } else {
+ // Sequence Y
+ ToSend[++ToSendMax] = SEC_Y;
+ last = 0;
+ }
}
}
}
ToSendMax++;
}
+//-----------------------------------------------------------------------------
+// Prepare reader command to send to FPGA
+//-----------------------------------------------------------------------------
+void CodeIso14443aAsReaderPar(const uint8_t * cmd, int len, uint32_t dwParity)
+{
+ CodeIso14443aBitsAsReaderPar(cmd,len*8,dwParity);
+}
+
//-----------------------------------------------------------------------------
// Wait for commands from reader
// Stop when button is pressed (return 1) or field was gone (return 2)
}
}
-void ReaderTransmitShort(const uint8_t* bt)
+void ReaderTransmitBitsPar(uint8_t* frame, int bits, uint32_t par)
{
int wait = 0;
int samples = 0;
-
- ShortFrameFromReader(*bt);
-
- // Select the card
- TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);
-
- // Store reader command in buffer
- if (tracing) LogTrace(bt,1,0,GetParity(bt,1),TRUE);
-}
-
-void ReaderTransmitPar(uint8_t* frame, int len, uint32_t par)
-{
- int wait = 0;
- int samples = 0;
-
+
// This is tied to other size changes
// uint8_t* frame_addr = ((uint8_t*)BigBuf) + 2024;
- CodeIso14443aAsReaderPar(frame,len,par);
-
+ CodeIso14443aBitsAsReaderPar(frame,bits,par);
+
// Select the card
TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);
if(trigger)
LED_A_ON();
-
+
// Store reader command in buffer
- if (tracing) LogTrace(frame,len,0,par,TRUE);
+ if (tracing) LogTrace(frame,nbytes(bits),0,par,TRUE);
}
+void ReaderTransmitPar(uint8_t* frame, int len, uint32_t par)
+{
+ ReaderTransmitBitsPar(frame,len*8,par);
+}
void ReaderTransmit(uint8_t* frame, int len)
{
// Generate parity and redirect
- ReaderTransmitPar(frame,len,GetParity(frame,len));
+ ReaderTransmitBitsPar(frame,len*8,GetParity(frame,len));
}
int ReaderReceive(uint8_t* receivedAnswer)
* fills the uid pointer unless NULL
* fills resp_data unless NULL */
int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) {
- uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
- 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 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); // was 3560 - tied to other size changes
+ uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
+ 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 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); // was 3560 - tied to other size changes
byte_t uid_resp[4];
size_t uid_resp_len;
- uint8_t sak = 0x04; // cascade uid
- int cascade_level = 0;
- int len;
+ uint8_t sak = 0x04; // cascade uid
+ int cascade_level = 0;
+ int len;
- // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
- ReaderTransmitShort(wupa);
- // Receive the ATQA
- if(!ReaderReceive(resp)) return 0;
+ // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
+ ReaderTransmitBitsPar(wupa,7,0);
+ // Receive the ATQA
+ if(!ReaderReceive(resp)) return 0;
// Dbprintf("atqa: %02x %02x",resp[0],resp[1]);
- if(p_hi14a_card) {
- memcpy(p_hi14a_card->atqa, resp, 2);
+ if(p_hi14a_card) {
+ memcpy(p_hi14a_card->atqa, resp, 2);
p_hi14a_card->uidlen = 0;
memset(p_hi14a_card->uid,0,10);
}
// clear uid
if (uid_ptr) {
- memset(uid_ptr,0,10);
+ memset(uid_ptr,0,8);
}
- // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
- // which case we need to make a cascade 2 request and select - this is a long UID
- // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
- for(; sak & 0x04; cascade_level++)
- {
- // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
- sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
+ // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
+ // which case we need to make a cascade 2 request and select - this is a long UID
+ // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
+ for(; sak & 0x04; cascade_level++) {
+ // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
+ sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
- // SELECT_ALL
- ReaderTransmit(sel_all,sizeof(sel_all));
- if (!ReaderReceive(resp)) return 0;
+ // SELECT_ALL
+ ReaderTransmit(sel_all,sizeof(sel_all));
+ if (!ReaderReceive(resp)) return 0;
- // First backup the current uid
+ // First backup the current uid
memcpy(uid_resp,resp,4);
uid_resp_len = 4;
// Dbprintf("uid: %02x %02x %02x %02x",uid_resp[0],uid_resp[1],uid_resp[2],uid_resp[3]);
*cuid_ptr = bytes_to_num(uid_resp, 4);
}
- // Construct SELECT UID command
+ // Construct SELECT UID command
memcpy(sel_uid+2,resp,5);
- AppendCrc14443a(sel_uid,7);
- ReaderTransmit(sel_uid,sizeof(sel_uid));
+ AppendCrc14443a(sel_uid,7);
+ ReaderTransmit(sel_uid,sizeof(sel_uid));
- // Receive the SAK
- if (!ReaderReceive(resp)) return 0;
- sak = resp[0];
+ // Receive the SAK
+ if (!ReaderReceive(resp)) return 0;
+ sak = resp[0];
// Test if more parts of the uid are comming
if ((sak & 0x04) && uid_resp[0] == 0x88) {
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
// http://www.nxp.com/documents/application_note/AN10927.pdf
- memcpy(uid_ptr, uid_ptr + 1, 3);
+ memcpy(uid_resp, uid_resp + 1, 3);
uid_resp_len = 3;
}
memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len);
p_hi14a_card->uidlen += uid_resp_len;
}
- }
+ }
- if(p_hi14a_card) {
- p_hi14a_card->sak = sak;
- p_hi14a_card->ats_len = 0;
- }
+ if(p_hi14a_card) {
+ p_hi14a_card->sak = sak;
+ p_hi14a_card->ats_len = 0;
+ }
- if( (sak & 0x20) == 0) {
- return 2; // non iso14443a compliant tag
+ if( (sak & 0x20) == 0) {
+ return 2; // non iso14443a compliant tag
}
- // Request for answer to select
+ // Request for answer to select
AppendCrc14443a(rats, 2);
ReaderTransmit(rats, sizeof(rats));
if (!(len = ReaderReceive(resp))) return 0;
if(p_hi14a_card) {
- memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats));
- p_hi14a_card->ats_len = len;
- }
+ memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats));
+ p_hi14a_card->ats_len = len;
+ }
- // reset the PCB block number
- iso14_pcb_blocknum = 0;
- return 1;
+ // reset the PCB block number
+ iso14_pcb_blocknum = 0;
+ return 1;
}
void iso14443a_setup() {
Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.byteCnt=%x Uart.byteCntMax=%x", maxDataLen, Uart.state, Uart.byteCnt, Uart.byteCntMax);
LEDsoff();
-}
\ No newline at end of file
+}