+}
+
+
+// Simulate an ISO15693 TAG.
+// For Inventory command: print command and send Inventory Response with given UID
+// TODO: interpret other reader commands and send appropriate response
+void SimTagIso15693(uint32_t parameter, uint8_t *uid)
+{
+ LEDsoff();
+ LED_A_ON();
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
+ FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
+
+ 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 - DELAY_ARM_TO_READER;
+ TransmitTo15693Reader(ToSend, ToSendMax, start_time, slow);
+ }
+
+ Dbprintf("%d bytes read from reader:", cmd_len);
+ Dbhexdump(cmd_len, cmd, false);
+ }
+
+ 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[20];
+ uint8_t *recv=data;
+ int datalen=0, recvlen=0;
+
+ Iso15693InitReader();
+
+ // 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 = AddCrc(data,3);
+ recvlen = SendDataTag(data, datalen, false, speed, &recv);
+ WDT_HIT();
+ if (recvlen>=12) {
+ Dbprintf("NoAFI UID=%s",sprintUID(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=AddCrc(data,4);
+ recvlen=SendDataTag(data, datalen, false, speed, &recv);
+ WDT_HIT();
+ if (recvlen>=12) {
+ Dbprintf("AFI=%i UID=%s", i, sprintUID(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 = BigBuf_get_addr();
+
+ LED_A_ON();
+
+ if (DEBUG) {
+ Dbprintf("SEND");
+ Dbhexdump(datalen, data, false);
+ }
+
+ recvlen = SendDataTag(data, datalen, true, speed, (recv?&recvbuf:NULL));
+
+ if (recv) {
+ cmd_send(CMD_ACK, recvlen>48?48:recvlen, 0, 0, recvbuf, 48);
+
+ if (DEBUG) {
+ Dbprintf("RECV");
+ DbdecodeIso15693Answer(recvlen,recvbuf);
+ Dbhexdump(recvlen, recvbuf, false);
+ }
+ }
+
+ // 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);