+ // TODO: Check CRC
+ // copy response contents
+ if(response != NULL)
+ {
+ memcpy(response, Demod.output, Demod.len);
+ }
+ return Demod.len;
+}
+
+/* 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
+ */
+int iso14443b_select_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[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
+ // ATTRIB command (with space for CRC)
+ uint8_t attrib[] = { 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
+
+ // first, wake up the tag
+ CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
+ // ATQB too short?
+ if (Demod.len < 14)
+ {
+ return 2;
+ }
+
+ // select the tag
+ // copy the PUPI to ATTRIB
+ 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));
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
+ // Answer to ATTRIB too short?
+ if(Demod.len < 3)
+ {
+ return 2;
+ }
+ // reset PCB block number
+ pcb_blocknum = 0;
+ return 1;