+ if (!GetATQA(resp, resp_par)) {
+ return 0;
+ }
+
+ if(p_hi14a_card) {
+ memcpy(p_hi14a_card->atqa, resp, 2);
+ }
+
+ if (anticollision) {
+ // clear uid
+ if (uid_ptr) {
+ memset(uid_ptr,0,10);
+ }
+ }
+
+ // check for proprietary anticollision:
+ if ((resp[0] & 0x1F) == 0) {
+ return 3;
+ }
+
+ // 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 3rd 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;
+
+ if (anticollision) {
+ // SELECT_ALL
+ ReaderTransmit(sel_all, sizeof(sel_all), NULL);
+ if (!ReaderReceive(resp, resp_par)) {
+ return 0;
+ }
+
+ if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
+ memset(uid_resp, 0, 4);
+ uint16_t uid_resp_bits = 0;
+ uint16_t collision_answer_offset = 0;
+ // anti-collision-loop:
+ while (Demod.collisionPos) {
+ Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
+ for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point
+ uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01;
+ uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8);
+ }
+ uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
+ uid_resp_bits++;
+ // construct anticollosion command:
+ sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
+ for (uint16_t i = 0; i <= uid_resp_bits/8; i++) {
+ sel_uid[2+i] = uid_resp[i];
+ }
+ collision_answer_offset = uid_resp_bits%8;
+ ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
+ if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) {
+ return 0;
+ }
+ }
+ // finally, add the last bits and BCC of the UID
+ for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
+ uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01;
+ uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8);
+ }
+
+ } else { // no collision, use the response to SELECT_ALL as current uid
+ memcpy(uid_resp, resp, 4);
+ }
+ } else {
+ if (cascade_level < num_cascades - 1) {
+ uid_resp[0] = 0x88;
+ memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3);
+ } else {
+ memcpy(uid_resp, uid_ptr+cascade_level*3, 4);
+ }
+ }
+ uid_resp_len = 4;
+
+ // calculate crypto UID. Always use last 4 Bytes.
+ if(cuid_ptr) {
+ *cuid_ptr = bytes_to_num(uid_resp, 4);
+ }
+
+ // Construct SELECT UID command
+ sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
+ memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID
+ sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
+ AppendCrc14443a(sel_uid, 7); // calculate and add CRC
+ ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
+
+ // Receive the SAK
+ if (!ReaderReceive(resp, resp_par)) {
+ return 0;
+ }
+ sak = resp[0];
+
+ // Test if more parts of the uid are coming
+ 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
+ uid_resp[0] = uid_resp[1];
+ uid_resp[1] = uid_resp[2];
+ uid_resp[2] = uid_resp[3];
+ uid_resp_len = 3;
+ }
+
+ if(uid_ptr && anticollision) {
+ memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
+ }
+
+ if(p_hi14a_card) {
+ 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;
+ }
+
+ // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0)
+ if( (sak & 0x20) == 0) return 2;
+
+ if (!no_rats) {
+ // Request for answer to select
+ AppendCrc14443a(rats, 2);
+ ReaderTransmit(rats, sizeof(rats), NULL);
+
+ if (!(len = ReaderReceive(resp, resp_par))) {
+ return 0;
+ }
+
+ if(p_hi14a_card) {
+ memcpy(p_hi14a_card->ats, resp, len);
+ p_hi14a_card->ats_len = len;
+ }
+
+ // reset the PCB block number
+ iso14_pcb_blocknum = 0;
+
+ // set default timeout and delay next transfer based on ATS
+ iso14a_set_ATS_times(resp);
+
+ }
+ return 1;
+}
+
+
+void iso14443a_setup(uint8_t fpga_minor_mode) {
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ // Set up the synchronous serial port
+ FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
+ // connect Demodulated Signal to ADC:
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+ // Signal field is on with the appropriate LED
+ if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD
+ || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
+ LED_D_ON();
+ } else {
+ LED_D_OFF();
+ }
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
+
+ // Set ADC to read field strength
+ AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
+ AT91C_BASE_ADC->ADC_MR =
+ ADC_MODE_PRESCALE(63) |
+ ADC_MODE_STARTUP_TIME(1) |
+ ADC_MODE_SAMPLE_HOLD_TIME(15);
+ AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF_LOW);
+
+ // Start the timer
+ StartCountSspClk();
+
+ DemodReset();
+ UartReset();
+ LastTimeProxToAirStart = 0;
+ FpgaSendQueueDelay = 0;
+ LastProxToAirDuration = 20; // arbitrary small value. Avoid lock in EmGetCmd()
+ NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
+ iso14a_set_timeout(1060); // 10ms default
+}
+
+/* Peter Fillmore 2015
+Added card id field to the function
+ info from ISO14443A standard
+b1 = Block Number
+b2 = RFU (always 1)
+b3 = depends on block
+b4 = Card ID following if set to 1
+b5 = depends on block type
+b6 = depends on block type
+b7,b8 = block type.
+Coding of I-BLOCK:
+b8 b7 b6 b5 b4 b3 b2 b1
+0 0 0 x x x 1 x
+b5 = chaining bit
+Coding of R-block:
+b8 b7 b6 b5 b4 b3 b2 b1
+1 0 1 x x 0 1 x
+b5 = ACK/NACK
+Coding of S-block:
+b8 b7 b6 b5 b4 b3 b2 b1
+1 1 x x x 0 1 0
+b5,b6 = 00 - DESELECT
+ 11 - WTX
+*/
+int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res) {
+ uint8_t parity[MAX_PARITY_SIZE];
+ uint8_t real_cmd[cmd_len + 4];
+
+ if (cmd_len) {
+ // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02
+ real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00)
+ if (send_chaining) {
+ real_cmd[0] |= 0x10;
+ }
+ // put block number into the PCB
+ real_cmd[0] |= iso14_pcb_blocknum;
+ memcpy(real_cmd + 1, cmd, cmd_len);
+ } else {
+ // R-block. ACK
+ real_cmd[0] = 0xA2; // r-block + ACK
+ real_cmd[0] |= iso14_pcb_blocknum;
+ }
+ AppendCrc14443a(real_cmd, cmd_len + 1);