+
+// Initialize the proxmark as iso15k reader
+// (this might produces glitches that confuse some tags
+static void Iso15693InitReader() {
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ // Setup SSC
+ // FpgaSetupSsc();
+
+ // Start from off (no field generated)
+ LED_D_OFF();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ SpinDelay(10);
+
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+
+ // Give the tags time to energize
+ LED_D_ON();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+ SpinDelay(250);
+}
+
+///////////////////////////////////////////////////////////////////////
+// ISO 15693 Part 3 - Air Interface
+// This section basically contains transmission and receiving of bits
+///////////////////////////////////////////////////////////////////////
+
+
+// uid is in transmission order (which is reverse of display order)
+static void BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
+{
+ uint8_t cmd[13];
+
+ uint16_t crc;
+ // If we set the Option_Flag in this request, the VICC will respond with the security status of the block
+ // followed by the block data
+ cmd[0] = ISO15693_REQ_OPTION | ISO15693_REQ_ADDRESS | ISO15693_REQ_DATARATE_HIGH;
+ // READ BLOCK command code
+ cmd[1] = ISO15693_READBLOCK;
+ // UID may be optionally specified here
+ // 64-bit UID
+ cmd[2] = uid[0];
+ cmd[3] = uid[1];
+ cmd[4] = uid[2];
+ cmd[5] = uid[3];
+ cmd[6] = uid[4];
+ cmd[7] = uid[5];
+ cmd[8] = uid[6];
+ cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique)
+ // Block number to read
+ cmd[10] = blockNumber;
+ //Now the CRC
+ crc = Crc(cmd, 11); // the crc needs to be calculated over 11 bytes
+ cmd[11] = crc & 0xff;
+ cmd[12] = crc >> 8;
+
+ CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+
+// Now the VICC>VCD responses when we are simulating a tag
+static void BuildInventoryResponse(uint8_t *uid)
+{
+ uint8_t cmd[12];
+
+ uint16_t crc;
+
+ cmd[0] = 0; // No error, no protocol format extension
+ cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
+ // 64-bit UID
+ cmd[2] = uid[7]; //0x32;
+ cmd[3] = uid[6]; //0x4b;
+ cmd[4] = uid[5]; //0x03;
+ cmd[5] = uid[4]; //0x01;
+ cmd[6] = uid[3]; //0x00;
+ cmd[7] = uid[2]; //0x10;
+ cmd[8] = uid[1]; //0x05;
+ cmd[9] = uid[0]; //0xe0;
+ //Now the CRC
+ crc = Crc(cmd, 10);
+ cmd[10] = crc & 0xff;
+ cmd[11] = crc >> 8;
+
+ CodeIso15693AsTag(cmd, sizeof(cmd));
+}
+
+// Universal Method for sending to and recv bytes from a tag
+// init ... should we initialize the reader?
+// speed ... 0 low speed, 1 hi speed
+// *recv will contain the tag's answer
+// return: lenght of received data
+int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *recv, uint16_t max_recv_len, uint32_t start_time) {
+
+ LED_A_ON();
+ LED_B_OFF();
+ LED_C_OFF();
+
+ if (init) Iso15693InitReader();
+
+ int answerLen=0;
+
+ if (!speed) {
+ // low speed (1 out of 256)
+ CodeIso15693AsReader256(send, sendlen);
+ } else {
+ // high speed (1 out of 4)
+ CodeIso15693AsReader(send, sendlen);
+ }
+
+ TransmitTo15693Tag(ToSend, ToSendMax, start_time);
+
+ // Now wait for a response
+ if (recv != NULL) {
+ answerLen = GetIso15693AnswerFromTag(recv, max_recv_len, DELAY_ISO15693_VCD_TO_VICC * 2);
+ }
+
+ LED_A_OFF();
+
+ return answerLen;
+}
+
+
+// --------------------------------------------------------------------
+// Debug Functions
+// --------------------------------------------------------------------
+
+// Decodes a message from a tag and displays its metadata and content
+#define DBD15STATLEN 48
+void DbdecodeIso15693Answer(int len, uint8_t *d) {
+ char status[DBD15STATLEN+1]={0};
+ uint16_t crc;
+
+ if (len > 3) {
+ if (d[0] & ISO15693_RES_EXT)
+ strncat(status,"ProtExt ", DBD15STATLEN);
+ if (d[0] & ISO15693_RES_ERROR) {
+ // error
+ strncat(status,"Error ", DBD15STATLEN);
+ switch (d[1]) {
+ case 0x01:
+ strncat(status,"01:notSupp", DBD15STATLEN);
+ break;
+ case 0x02:
+ strncat(status,"02:notRecog", DBD15STATLEN);
+ break;
+ case 0x03:
+ strncat(status,"03:optNotSupp", DBD15STATLEN);
+ break;
+ case 0x0f:
+ strncat(status,"0f:noInfo", DBD15STATLEN);
+ break;
+ case 0x10:
+ strncat(status,"10:doesn'tExist", DBD15STATLEN);
+ break;
+ case 0x11:
+ strncat(status,"11:lockAgain", DBD15STATLEN);
+ break;
+ case 0x12:
+ strncat(status,"12:locked", DBD15STATLEN);
+ break;
+ case 0x13:
+ strncat(status,"13:progErr", DBD15STATLEN);
+ break;
+ case 0x14:
+ strncat(status,"14:lockErr", DBD15STATLEN);
+ break;
+ default:
+ strncat(status,"unknownErr", DBD15STATLEN);
+ }
+ strncat(status," ", DBD15STATLEN);
+ } else {
+ strncat(status,"NoErr ", DBD15STATLEN);
+ }
+
+ crc=Crc(d,len-2);
+ if ( (( crc & 0xff ) == d[len-2]) && (( crc >> 8 ) == d[len-1]) )
+ strncat(status,"CrcOK",DBD15STATLEN);
+ else
+ strncat(status,"CrcFail!",DBD15STATLEN);
+
+ Dbprintf("%s",status);
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////
+// Functions called via USB/Client
+///////////////////////////////////////////////////////////////////////
+
+void SetDebugIso15693(uint32_t debug) {
+ DEBUG=debug;
+ Dbprintf("Iso15693 Debug is now %s",DEBUG?"on":"off");
+ return;
+}
+
+