+ StartCountSspClk();
+
+ uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH];
+
+ // Build a suitable response to the reader INVENTORY command
+ BuildInventoryResponse(uid);
+
+ // Listen to reader
+ while (!BUTTON_PRESS()) {
+ uint32_t eof_time = 0, start_time = 0;
+ int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &eof_time);
+
+ if ((cmd_len >= 5) && (cmd[0] & ISO15693_REQ_INVENTORY) && (cmd[1] == ISO15693_INVENTORY)) { // TODO: check more flags
+ bool slow = !(cmd[0] & ISO15693_REQ_DATARATE_HIGH);
+ start_time = eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM - DELAY_ARM_TO_READER_SIM;
+ TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow);
+ }
+
+ Dbprintf("%d bytes read from reader:", cmd_len);
+ Dbhexdump(cmd_len, cmd, false);
+ }
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LEDsoff();
+}
+
+
+// Since there is no standardized way of reading the AFI out of a tag, we will brute force it
+// (some manufactures offer a way to read the AFI, though)
+void BruteforceIso15693Afi(uint32_t speed)
+{
+ LEDsoff();
+ LED_A_ON();
+
+ uint8_t data[6];
+ uint8_t recv[ISO15693_MAX_RESPONSE_LENGTH];
+
+ int datalen=0, recvlen=0;
+
+ Iso15693InitReader();
+ StartCountSspClk();
+
+ // first without AFI
+ // Tags should respond without AFI and with AFI=0 even when AFI is active
+
+ data[0] = ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1;
+ data[1] = ISO15693_INVENTORY;
+ data[2] = 0; // mask length
+ datalen = Iso15693AddCrc(data,3);
+ recvlen = SendDataTag(data, datalen, false, speed, recv, sizeof(recv), 0);
+ uint32_t start_time = GetCountSspClk() + DELAY_ISO15693_VICC_TO_VCD_READER;
+ WDT_HIT();
+ if (recvlen>=12) {
+ Dbprintf("NoAFI UID=%s", Iso15693sprintUID(NULL, &recv[2]));
+ }
+
+ // now with AFI
+
+ data[0] = ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_AFI | ISO15693_REQINV_SLOT1;
+ data[1] = ISO15693_INVENTORY;
+ data[2] = 0; // AFI
+ data[3] = 0; // mask length
+
+ for (int i = 0; i < 256; i++) {
+ data[2] = i & 0xFF;
+ datalen = Iso15693AddCrc(data,4);
+ recvlen = SendDataTag(data, datalen, false, speed, recv, sizeof(recv), start_time);
+ start_time = GetCountSspClk() + DELAY_ISO15693_VICC_TO_VCD_READER;
+ WDT_HIT();
+ if (recvlen >= 12) {
+ Dbprintf("AFI=%i UID=%s", i, Iso15693sprintUID(NULL, &recv[2]));
+ }
+ }
+ Dbprintf("AFI Bruteforcing done.");
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LEDsoff();
+}
+
+// Allows to directly send commands to the tag via the client
+void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t data[]) {
+
+ int recvlen = 0;
+ uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
+
+ LED_A_ON();
+
+ if (DEBUG) {
+ Dbprintf("SEND:");
+ Dbhexdump(datalen, data, false);
+ }
+
+ recvlen = SendDataTag(data, datalen, true, speed, (recv?recvbuf:NULL), sizeof(recvbuf), 0);
+
+ if (recv) {
+ if (DEBUG) {
+ Dbprintf("RECV:");
+ Dbhexdump(recvlen, recvbuf, false);
+ DbdecodeIso15693Answer(recvlen, recvbuf);
+ }
+
+ cmd_send(CMD_ACK, recvlen>ISO15693_MAX_RESPONSE_LENGTH?ISO15693_MAX_RESPONSE_LENGTH:recvlen, 0, 0, recvbuf, ISO15693_MAX_RESPONSE_LENGTH);
+
+ }
+
+ // for the time being, switch field off to protect rdv4.0
+ // note: this prevents using hf 15 cmd with s option - which isn't implemented yet anyway
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);