+/* Perform the ISO 14443 B Card Selection procedure
+ * Currently does NOT do any collision handling.
+ * It expects 0-1 cards in the device's range.
+ * TODO: Support multiple cards (perform anticollision)
+ * TODO: Verify CRC checksums
+ */
+uint8_t iso14443b_select_card(iso14b_card_select_t *card )
+{
+ // WUPB command (including CRC)
+ // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state
+ static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
+ // ATTRIB command (with space for CRC)
+ uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
+
+ // temp to calc crc.
+ uint8_t crc[2] = {0x00, 0x00};
+
+ // first, wake up the tag
+ CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
+ GetTagSamplesFor14443bDemod(); //select_card
+
+ // ATQB too short?
+ if (Demod.len < 14) return 2;
+
+ // VALIDATE CRC
+ ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
+ if ( crc[0] != Demod.output[12] || crc[1] != Demod.output[13] )
+ return 3;
+
+ if (card) {
+ card->uidlen = 4;
+ memcpy(card->uid, Demod.output+1, 4);
+ memcpy(card->atqb, Demod.output+5, 7);
+ }
+
+ // copy the PUPI to ATTRIB ( PUPI == UID )
+ memcpy(attrib + 1, Demod.output + 1, 4);
+
+ // copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into ATTRIB (Param 3)
+ attrib[7] = Demod.output[10] & 0x0F;
+ ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10);
+
+ CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
+ GetTagSamplesFor14443bDemod();//select_card
+
+ // Answer to ATTRIB too short?
+ if(Demod.len < 3) return 2;
+
+ // VALIDATE CRC
+ ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
+ if ( crc[0] != Demod.output[1] || crc[1] != Demod.output[2] )
+ return 3;
+
+ if (card) {
+
+ // CID
+ card->cid = Demod.output[0];
+
+ // MAX FRAME
+ uint16_t maxFrame = card->atqb[5] >> 4;
+ if (maxFrame < 5) maxFrame = 8 * maxFrame + 16;
+ else if (maxFrame == 5) maxFrame = 64;
+ else if (maxFrame == 6) maxFrame = 96;
+ else if (maxFrame == 7) maxFrame = 128;
+ else if (maxFrame == 8) maxFrame = 256;
+ else maxFrame = 257;
+ iso14b_set_maxframesize(maxFrame);
+
+ // FWT
+ uint8_t fwt = card->atqb[6] >> 4;
+ if ( fwt < 16 ){
+ uint32_t fwt_time = (302 << fwt);
+ iso14b_set_timeout( fwt_time);
+ }
+ }
+ // reset PCB block number
+ pcb_blocknum = 0;
+ return 0;
+}
+
+// Set up ISO 14443 Type B communication (similar to iso14443a_setup)
+// field is setup for "Sending as Reader"
+void iso14443b_setup() {
+ if (MF_DBGLEVEL > 3) Dbprintf("iso1443b_setup Enter");
+ LEDsoff();
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ //BigBuf_free();
+ //BigBuf_Clear_ext(false);
+
+ // Initialize Demod and Uart structs
+ DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
+ UartInit(BigBuf_malloc(MAX_FRAME_SIZE));