]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge branch 'master' into topaz
authorpwpiwi <pwpiwi@users.noreply.github.com>
Wed, 1 Jul 2015 06:17:00 +0000 (08:17 +0200)
committerpwpiwi <pwpiwi@users.noreply.github.com>
Wed, 1 Jul 2015 06:17:00 +0000 (08:17 +0200)
Conflicts:
client/Makefile
client/cmdhf.c
client/cmdhf14a.c

1  2 
armsrc/BigBuf.c
armsrc/iso14443a.c
client/Makefile
client/cmdhf.c
client/cmdhf14a.c
common/Makefile.common
common/protocols.h

diff --combined armsrc/BigBuf.c
index 51fafdebc22b3b872a8a6b1cba3a9f34bfc2567e,510f7befe720a3628432086273ff537a25a85d0e..a22c0cb0e499692054b66413c1af5214b290f063
@@@ -96,9 -96,6 +96,6 @@@ uint16_t BigBuf_max_traceLen(void
  }
  
  void clear_trace() {
-       uint8_t *trace = BigBuf_get_addr();
-       uint16_t max_traceLen = BigBuf_max_traceLen();
-       memset(trace, 0x44, max_traceLen);
        traceLen = 0;
  }
  
@@@ -171,12 -168,8 +168,12 @@@ bool RAMFUNC LogTrace(const uint8_t *bt
        traceLen += iLen;
  
        // parity bytes
 -      if (parity != NULL && iLen != 0) {
 -              memcpy(trace + traceLen, parity, num_paritybytes);
 +      if (iLen != 0) {
 +              if (parity != NULL) {
 +                      memcpy(trace + traceLen, parity, num_paritybytes);
 +              } else {
 +                      memset(trace + traceLen, 0x00, num_paritybytes);
 +              }
        }
        traceLen += num_paritybytes;
  
@@@ -225,8 -218,6 +222,8 @@@ int LogTraceHitag(const uint8_t * btByt
  
        return TRUE;
  }
 +
 +
  // Emulator memory
  uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
        uint8_t* mem = BigBuf_get_EM_addr();
diff --combined armsrc/iso14443a.c
index 81cb9728ff52cf216b3b977d682a696ae6fb50c9,5c7367a15e634ae035bdf2af4f26470a75df216c..a4e5ceaf1ece9ea5bc57eeade9c2ed77aa1ccc5e
@@@ -213,12 -213,6 +213,12 @@@ void AppendCrc14443a(uint8_t* data, in
        ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
  }
  
 +void AppendCrc14443b(uint8_t* data, int len)
 +{
 +      ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1);
 +}
 +
 +
  //=============================================================================
  // ISO 14443 Type A - Miller decoder
  //=============================================================================
  static tUart Uart;
  
  // Lookup-Table to decide if 4 raw bits are a modulation.
 -// We accept two or three consecutive "0" in any position with the rest "1"
 +// We accept the following:
 +// 0001  -   a 3 tick wide pause
 +// 0011  -   a 2 tick wide pause, or a three tick wide pause shifted left
 +// 0111  -   a 2 tick wide pause shifted left
 +// 1001  -   a 2 tick wide pause shifted right
  const bool Mod_Miller_LUT[] = {
 -      TRUE,  TRUE,  FALSE, TRUE,  FALSE, FALSE, FALSE, FALSE,
 -      TRUE,  TRUE,  FALSE, FALSE, TRUE,  FALSE, FALSE, FALSE
 +      FALSE,  TRUE, FALSE, TRUE,  FALSE, FALSE, FALSE, TRUE,
 +      FALSE,  TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
  };
 -#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x00F0) >> 4])
 -#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x000F)])
 +#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
 +#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
  
  void UartReset()
  {
        Uart.parityLen = 0;                                     // number of decoded parity bytes
        Uart.shiftReg = 0;                                      // shiftreg to hold decoded data bits
        Uart.parityBits = 0;                            // holds 8 parity bits
 -      Uart.twoBits = 0x0000;                          // buffer for 2 Bits
 -      Uart.highCnt = 0;
        Uart.startTime = 0;
        Uart.endTime = 0;
  }
@@@ -266,7 -258,6 +266,7 @@@ void UartInit(uint8_t *data, uint8_t *p
  {
        Uart.output = data;
        Uart.parity = parity;
 +      Uart.fourBits = 0x00000000;                     // clear the buffer for 4 Bits
        UartReset();
  }
  
  static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
  {
  
 -      Uart.twoBits = (Uart.twoBits << 8) | bit;
 +      Uart.fourBits = (Uart.fourBits << 8) | bit;
        
        if (Uart.state == STATE_UNSYNCD) {                                                                                      // not yet synced
        
 -              if (Uart.highCnt < 2) {                                                                                                 // wait for a stable unmodulated signal
 -                      if (Uart.twoBits == 0xffff) {
 -                              Uart.highCnt++;
 -                      } else {
 -                              Uart.highCnt = 0;
 -                      }
 -              } else {        
 -                      Uart.syncBit = 0xFFFF;                                                                                          // not set
 -                                                                                                                                                              // we look for a ...1111111100x11111xxxxxx pattern (the start bit)
 -                      if              ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8;           // mask is   11x11111 xxxxxxxx, 
 -                                                                                                                                                              // check for 00x11111 xxxxxxxx
 -                      else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7;           // both masks shifted right one bit, left padded with '1'
 -                      else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6;           // ...
 -                      else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5;
 -                      else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4;
 -                      else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3;
 -                      else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2;
 -                      else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1;
 -                      if (Uart.syncBit != 0xFFFF) {                                                                           // found a sync bit
 -                              Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
 -                              Uart.startTime -= Uart.syncBit;
 -                              Uart.endTime = Uart.startTime;
 -                              Uart.state = STATE_START_OF_COMMUNICATION;
 -                      }
 +              Uart.syncBit = 9999;                                                                                                    // not set
 +              // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
 +              // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
 +              // we therefore look for a ...xx11111111111100x11111xxxxxx... pattern 
 +              // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
 +              #define ISO14443A_STARTBIT_MASK         0x07FFEF80                                                      // mask is    00000111 11111111 11101111 10000000
 +              #define ISO14443A_STARTBIT_PATTERN      0x07FF8F80                                                      // pattern is 00000111 11111111 10001111 10000000
 +              if              ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0;
 +
 +              if (Uart.syncBit != 9999) {                                                                                             // found a sync bit
 +                      Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
 +                      Uart.startTime -= Uart.syncBit;
 +                      Uart.endTime = Uart.startTime;
 +                      Uart.state = STATE_START_OF_COMMUNICATION;
                }
  
        } else {
  
 -              if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) {                  
 -                      if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) {          // Modulation in both halves - error
 +              if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {                 
 +                      if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) {         // Modulation in both halves - error
                                UartReset();
                        } else {                                                                                                                        // Modulation in first half = Sequence Z = logic "0"
                                if (Uart.state == STATE_MILLER_X) {                                                             // error - must not follow after X
                                }
                        }
                } else {
 -                      if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) {          // Modulation second half = Sequence X = logic "1"
 +                      if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) {         // Modulation second half = Sequence X = logic "1"
                                Uart.bitCount++;
                                Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100;                                   // add a 1 to the shiftreg
                                Uart.state = STATE_MILLER_X;
                                                return TRUE;                                                                                    // we are finished with decoding the raw data sequence
                                        } else {
                                                UartReset();                                                                                    // Nothing received - start over
 -                                              Uart.highCnt = 1;
                                        }
                                }
                                if (Uart.state == STATE_START_OF_COMMUNICATION) {                               // error - must not follow directly after SOC
                                        UartReset();
 -                                      Uart.highCnt = 1;
                                } else {                                                                                                                // a logic "0"
                                        Uart.bitCount++;
                                        Uart.shiftReg = (Uart.shiftReg >> 1);                                           // add a 0 to the shiftreg
@@@ -555,12 -551,8 +555,8 @@@ void RAMFUNC SnoopIso14443a(uint8_t par
        
        LEDsoff();
  
-       // We won't start recording the frames that we acquire until we trigger;
-       // a good trigger condition to get started is probably when we see a
-       // response from the tag.
-       // triggered == FALSE -- to wait first for card
-       bool triggered = !(param & 0x03); 
-       
+       iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
        // Allocate memory from BigBuf for some buffers
        // free all previous allocations first
        BigBuf_free();
        bool TagIsActive = FALSE;
        bool ReaderIsActive = FALSE;
        
-       iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
        // Set up the demodulator for tag -> reader responses.
        DemodInit(receivedResponse, receivedResponsePar);
        
        // Setup and start DMA.
        FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
        
+       // We won't start recording the frames that we acquire until we trigger;
+       // a good trigger condition to get started is probably when we see a
+       // response from the tag.
+       // triggered == FALSE -- to wait first for card
+       bool triggered = !(param & 0x03); 
+       
        // And now we loop, receiving samples.
        for(uint32_t rsamples = 0; TRUE; ) {
  
  
                                        // And ready to receive another response.
                                        DemodReset();
 +                                      // And reset the Miller decoder including itS (now outdated) input buffer
 +                                      UartInit(receivedCmd, receivedCmdPar);
 +
                                        LED_C_OFF();
                                } 
                                TagIsActive = (Demod.state != DEMOD_UNSYNCD);
@@@ -1033,6 -1026,9 +1033,9 @@@ void SimulateIso14443aTag(int tagType, 
                .modulation_n = 0
        };
    
+       // We need to listen to the high-frequency, peak-detected path.
+       iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
        BigBuf_free_keep_EM();
  
        // allocate buffers:
        int happened2 = 0;
        int cmdsRecvd = 0;
  
-       // We need to listen to the high-frequency, peak-detected path.
-       iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
        cmdsRecvd = 0;
        tag_response_info_t* p_response;
  
@@@ -1344,7 -1337,7 +1344,7 @@@ void CodeIso14443aBitsAsReaderPar(cons
                }
  
                // Only transmit parity bit if we transmitted a complete byte
 -              if (j == 8) {
 +              if (j == 8 && parity != NULL) {
                        // Get the parity bit
                        if (parity[i>>3] & (0x80 >> (i&0x0007))) {
                                // Sequence X
@@@ -1638,7 -1631,6 +1638,7 @@@ static int GetIso14443aAnswerFromTag(ui
        }
  }
  
 +
  void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing)
  {
        CodeIso14443aBitsAsReaderPar(frame, bits, par);
        }
  }
  
 +
  void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing)
  {
    ReaderTransmitBitsPar(frame, len*8, par, timing);
  }
  
 +
  void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
  {
    // Generate parity and redirect
    ReaderTransmitBitsPar(frame, len, par, timing);
  }
  
 +
  void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
  {
    // Generate parity and redirect
@@@ -1730,11 -1719,6 +1730,11 @@@ int iso14443a_select_card(byte_t *uid_p
                memset(uid_ptr,0,10);
        }
  
 +      // check for proprietary anticollision:
 +      if ((resp[0] & 0x1F) == 0) {
 +              return 3;
 +      }
 +      
        // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
        // which case we need to make a cascade 2 request and select - this is a long UID
        // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
@@@ -1943,38 -1927,15 +1943,38 @@@ void ReaderIso14443a(UsbCommand *c
  
        if(param & ISO14A_RAW) {
                if(param & ISO14A_APPEND_CRC) {
 -                      AppendCrc14443a(cmd,len);
 +                      if(param & ISO14A_TOPAZMODE) {
 +                              AppendCrc14443b(cmd,len);
 +                      } else {
 +                              AppendCrc14443a(cmd,len);
 +                      }
                        len += 2;
                        if (lenbits) lenbits += 16;
                }
 -              if(lenbits>0) {
 -                      GetParity(cmd, lenbits/8, par);
 -                      ReaderTransmitBitsPar(cmd, lenbits, par, NULL);
 -              } else {
 -                      ReaderTransmit(cmd,len, NULL);
 +              if(lenbits>0) {                         // want to send a specific number of bits (e.g. short commands)
 +                      if(param & ISO14A_TOPAZMODE) {
 +                              int bits_to_send = lenbits;
 +                              uint16_t i = 0;
 +                              ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL);             // first byte is always short (7bits) and no parity
 +                              bits_to_send -= 7;
 +                              while (bits_to_send > 0) {
 +                                      ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL);     // following bytes are 8 bit and no parity
 +                                      bits_to_send -= 8;
 +                              }
 +                      } else {
 +                              GetParity(cmd, lenbits/8, par);
 +                              ReaderTransmitBitsPar(cmd, lenbits, par, NULL);                                                 // bytes are 8 bit with odd parity
 +                      }
 +              } else {                                        // want to send complete bytes only
 +                      if(param & ISO14A_TOPAZMODE) {
 +                              uint16_t i = 0;
 +                              ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL);                                                // first byte: 7 bits, no paritiy
 +                              while (i < len) {
 +                                      ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL);                                        // following bytes: 8 bits, no paritiy
 +                              }
 +                      } else {
 +                              ReaderTransmit(cmd,len, NULL);                                                                                  // 8 bits, odd parity
 +                      }
                }
                arg0 = ReaderReceive(buf, par);
                cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
@@@ -2010,7 -1971,7 +2010,7 @@@ int32_t dist_nt(uint32_t nt1, uint32_t 
                nttmp1 = prng_successor(nttmp1, 1);
                if (nttmp1 == nt2) return i;
                nttmp2 = prng_successor(nttmp2, 1);
-                       if (nttmp2 == nt1) return -i;
+               if (nttmp2 == nt1) return -i;
                }
        
        return(-99999); // either nt1 or nt2 are invalid nonces
@@@ -2033,6 -1994,10 +2033,10 @@@ void ReaderMifare(bool first_try
        uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
        uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
  
+       if (first_try) { 
+               iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
+       }
+       
        // free eventually allocated BigBuf memory. We want all for tracing.
        BigBuf_free();
        
  
        if (first_try) { 
                mf_nr_ar3 = 0;
-               iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
                sync_time = GetCountSspClk() & 0xfffffff8;
                sync_cycles = 65536;                                                                    // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
                nt_attacked = 0;
        LED_B_OFF();
        LED_C_OFF();
        
-   
+       #define DARKSIDE_MAX_TRIES      32              // number of tries to sync on PRNG cycle. Then give up.
+       uint16_t unsuccessfull_tries = 0;
+       
        for(uint16_t i = 0; TRUE; i++) {
                
+               LED_C_ON();
                WDT_HIT();
  
                // Test if the action was cancelled
                if(BUTTON_PRESS()) {
+                       isOK = -1;
                        break;
                }
                
-               LED_C_ON();
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
                        if (MF_DBGLEVEL >= 1)   Dbprintf("Mifare: Can't select card");
                        continue;
                                nt_attacked = nt;
                        }
                        else {
-                               if (nt_distance == -99999) { // invalid nonce received, try again
-                                       continue;
+                               if (nt_distance == -99999) { // invalid nonce received
+                                       unsuccessfull_tries++;
+                                       if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) {
+                                               isOK = -3;              // Card has an unpredictable PRNG. Give up      
+                                               break;
+                                       } else {
+                                               continue;               // continue trying...
+                                       }
                                }
                                sync_cycles = (sync_cycles - nt_distance);
                                if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
                        if (nt_diff == 0 && first_try)
                        {
                                par[0]++;
+                               if (par[0] == 0x00) {           // tried all 256 possible parities without success. Card doesn't send NACK.
+                                       isOK = -2;
+                                       break;
+                               }
                        } else {
                                par[0] = ((par[0] & 0x1F) + 1) | par_low;
                        }
        memcpy(buf + 16, ks_list, 8);
        memcpy(buf + 24, mf_nr_ar, 4);
                
-       cmd_send(CMD_ACK,isOK,0,0,buf,28);
+       cmd_send(CMD_ACK, isOK, 0, 0, buf, 28);
  
        // Thats it...
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@@@ -2265,13 -2242,6 +2281,6 @@@ void Mifare1ksim(uint8_t flags, uint8_
        uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
        uint8_t ar_nr_collected = 0;
  
-       // free eventually allocated BigBuf memory but keep Emulator Memory
-       BigBuf_free_keep_EM();
-       // clear trace
-       clear_trace();
-       set_tracing(TRUE);
        // Authenticate response - nonce
        uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
        
        if (_7BUID) {
                rATQA[0] = 0x44;
                rUIDBCC1[0] = 0x88;
+               rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
                rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
        }
  
-       // We need to listen to the high-frequency, peak-detected path.
-       iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
        if (MF_DBGLEVEL >= 1)   {
                if (!_7BUID) {
                        Dbprintf("4B UID: %02x%02x%02x%02x", 
                }
        }
  
+       // We need to listen to the high-frequency, peak-detected path.
+       iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
+       // free eventually allocated BigBuf memory but keep Emulator Memory
+       BigBuf_free_keep_EM();
+       // clear trace
+       clear_trace();
+       set_tracing(TRUE);
        bool finished = FALSE;
        while (!BUTTON_PRESS() && !finished) {
                WDT_HIT();
                                                || receivedCmd[0] == 0xB0) { // transfer
                                        if (receivedCmd[1] >= 16 * 4) {
                                                EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
-                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
                                                break;
                                        }
  
                                        if (receivedCmd[1] / 4 != cardAUTHSC) {
                                                EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
-                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC);
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC);
                                                break;
                                        }
                                }
@@@ -2745,10 -2723,8 +2762,8 @@@ void RAMFUNC SniffMifare(uint8_t param
        uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
        uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE];
  
-       // As we receive stuff, we copy it from receivedCmd or receivedResponse
-       // into trace, along with its length and other annotations.
-       //uint8_t *trace = (uint8_t *)BigBuf;
-       
+       iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
        // free eventually allocated BigBuf memory
        BigBuf_free();
        // allocate the DMA buffer, used to stream samples from the FPGA
        bool ReaderIsActive = FALSE;
        bool TagIsActive = FALSE;
  
-       iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
        // Set up the demodulator for tag -> reader responses.
        DemodInit(receivedResponse, receivedResponsePar);
  
                                        if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break;
  
                                        /* And ready to receive another command. */
 -                                      UartReset();
 +                                      UartInit(receivedCmd, receivedCmdPar);
                                        
                                        /* And also reset the demod code */
                                        DemodReset();
  
                                        // And ready to receive another response.
                                        DemodReset();
 +                                      // And reset the Miller decoder including its (now outdated) input buffer
 +                                      UartInit(receivedCmd, receivedCmdPar);
                                }
                                TagIsActive = (Demod.state != DEMOD_UNSYNCD);
                        }
diff --combined client/Makefile
index 48cbdfaa9d1c27107846d5ce566021b33dbf3db4,c454533d7822ca63febae2f6152a28f4480cb0bf..f768f3d8ef1e3e6328472151a8433a5b72fcb437
@@@ -9,12 -9,13 +9,13 @@@ include ../common/Makefile.commo
  CC=gcc
  CXX=g++
  #COMMON_FLAGS = -m32
- VPATH = ../common
+ VPATH = ../common ../zlib
  OBJDIR = obj
  
- LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
+ LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm
+ LUALIB = ../liblua/liblua.a
  LDFLAGS = $(COMMON_FLAGS)
- CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
+ CFLAGS = -std=c99 -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
  LUAPLATFORM = generic
  
  ifneq (,$(findstring MINGW,$(platform)))
@@@ -35,14 -36,13 +36,13 @@@ else ifeq ($(platform),Darwin
  else
      CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4
      QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
+     LUALIB +=  -ldl
      MOC = $(shell pkg-config --variable=moc_location QtCore)
-     LDLIBS +=  -ldl
      # Below is a variant you can use if you have problems compiling with QT5 on ubuntu. see http://www.proxmark.org/forum/viewtopic.php?id=1661 for more info. 
      #MOC = /usr/lib/x86_64-linux-gnu/qt4/bin/moc
      LUAPLATFORM = linux
  endif
  
  ifneq ($(QTLDLIBS),)
      QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
      CFLAGS += -DHAVE_GUI
@@@ -57,65 -57,72 +57,73 @@@ CORESRCS =         uart.c 
  
  
  CMDSRCS =     nonce2key/crapto1.c\
--              nonce2key/crypto1.c\
--              nonce2key/nonce2key.c\
--              loclass/cipher.c \
--              loclass/cipherutils.c \
--              loclass/des.c \
--              loclass/ikeys.c \
--              loclass/elite_crack.c\
--              loclass/fileutils.c\
-               mifarehost.c\
-               crc.c \
-               crc16.c \
-               iso14443crc.c \
-               iso15693tools.c \
-               data.c \
-               graph.c \
-               ui.c \
-               cmddata.c \
-               lfdemod.c \
-               cmdhf.c \
-               cmdhf14a.c \
-               cmdhf14b.c \
-               cmdhf15.c \
-               cmdhfepa.c \
-               cmdhflegic.c \
-               cmdhficlass.c \
-               cmdhfmf.c \
-         cmdhfmfu.c \
-               cmdhftopaz.c \
-               cmdhw.c \
-               cmdlf.c \
-               cmdlfio.c \
-               cmdlfhid.c \
-               cmdlfem4x.c \
-               cmdlfhitag.c \
-               cmdlfti.c \
-               cmdparser.c \
-               cmdmain.c \
-               cmdlft55xx.c \
-               cmdlfpcf7931.c\
-               pm3_binlib.c\
-               scripting.c\
-               cmdscript.c\
-               pm3_bitlib.c\
-               aes.c\
-               protocols.c
++                      nonce2key/crypto1.c\
++                      nonce2key/nonce2key.c\
++                      loclass/cipher.c \
++                      loclass/cipherutils.c \
++                      loclass/des.c \
++                      loclass/ikeys.c \
++                      loclass/elite_crack.c\
++                      loclass/fileutils.c\
+                       mifarehost.c\
+                       crc.c \
+                       crc16.c \
+                       crc64.c \
+                       iso14443crc.c \
+                       iso15693tools.c \
+                       data.c \
+                       graph.c \
+                       ui.c \
+                       cmddata.c \
+                       lfdemod.c \
+                       cmdhf.c \
+                       cmdhf14a.c \
+                       cmdhf14b.c \
+                       cmdhf15.c \
+                       cmdhfepa.c \
+                       cmdhflegic.c \
+                       cmdhficlass.c \
+                       cmdhfmf.c \
+             cmdhfmfu.c \
++                      cmdhftopaz.c \
+                       cmdhw.c \
+                       cmdlf.c \
+                       cmdlfio.c \
+                       cmdlfhid.c \
+                       cmdlfem4x.c \
+                       cmdlfhitag.c \
+                       cmdlfti.c \
+                       cmdparser.c \
+                       cmdmain.c \
+                       cmdlft55xx.c \
+                       cmdlfpcf7931.c\
+                       pm3_binlib.c\
+                       scripting.c\
+                       cmdscript.c\
+                       pm3_bitlib.c\
+                       aes.c\
+                       protocols.c\
+                       sha1.c\
+ ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
+ ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED 
+ #-DDEBUG -Dverbose=1
  
  COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
  CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o)
+ ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o)
  
  RM = rm -f
- BINS = proxmark3 flasher #snooper cli
- CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp
+ BINS = proxmark3 flasher fpga_compress #snooper cli
+ CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe fpga_compress fpga_compress.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp
  
  all: lua_build $(BINS) 
  
  all-static: LDLIBS:=-static $(LDLIBS)
- all-static: snooper cli flasher
-       
- proxmark3: LDLIBS+=$(QTLDLIBS)
+ all-static: snooper cli flasher fpga_compress
+ proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS)
  proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUI)
        $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
  
@@@ -128,8 -135,11 +136,11 @@@ cli: $(OBJDIR)/cli.o $(COREOBJS) $(CMDO
  flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS)
        $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
  
+ fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS)
+       $(CXX) $(CXXFLAGS) $(ZLIB_FLAGS) $^ $(LDLIBS) -o $@
  $(OBJDIR)/%.o: %.c
-       $(CC) $(CFLAGS) -c -o $@ $<
+       $(CC) $(CFLAGS) $(ZLIB_FLAGS) -c -o $@ $<
  
  $(OBJDIR)/%.o: %.cpp
        $(CXX) $(CXXFLAGS) -c -o $@ $<
diff --combined client/cmdhf.c
index ad8e53690ff8db1114e9c8647c65f6e71c99b997,4c5db58939671992b9b798d4ebc1ddec5e1e0278..4777a0f40295b40408e03a3a505eeb73560f041c
@@@ -23,7 -23,6 +23,7 @@@
  #include "cmdhficlass.h"
  #include "cmdhfmf.h"
  #include "cmdhfmfu.h"
 +#include "cmdhftopaz.h"
  #include "protocols.h"
  
  static int CmdHelp(const char *Cmd);
@@@ -72,11 -71,57 +72,57 @@@ void annotateIso14443a(char *exp, size_
        case MIFARE_CMD_DEC:                    snprintf(exp,size,"DEC(%d)",cmd[1]); break;
        case MIFARE_CMD_RESTORE:                snprintf(exp,size,"RESTORE(%d)",cmd[1]); break;
        case MIFARE_CMD_TRANSFER:               snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break;
-       case MIFARE_AUTH_KEYA:                  snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break;
+       case MIFARE_AUTH_KEYA:{
+               if ( cmdsize > 3)
+                       snprintf(exp,size,"AUTH-A(%d)",cmd[1]); 
+               else
+                       //      case MIFARE_ULEV1_VERSION :  both 0x60.
+                       snprintf(exp,size,"EV1 VERSION");
+               break;
+       }
        case MIFARE_AUTH_KEYB:                  snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
        case MIFARE_MAGICWUPC1:                 snprintf(exp,size,"MAGIC WUPC1"); break;
        case MIFARE_MAGICWUPC2:                 snprintf(exp,size,"MAGIC WUPC2"); break;
        case MIFARE_MAGICWIPEC:                 snprintf(exp,size,"MAGIC WIPEC"); break;
+       case MIFARE_ULC_AUTH_1:         snprintf(exp,size,"AUTH "); break;
+       case MIFARE_ULC_AUTH_2:         snprintf(exp,size,"AUTH_ANSW"); break;
+       case MIFARE_ULEV1_AUTH:
+               if ( cmdsize == 7 )
+                       snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] );
+               else
+                       snprintf(exp,size,"PWD-AUTH");
+               break;
+       case MIFARE_ULEV1_FASTREAD:{
+               if ( cmdsize >=3 && cmd[2] <= 0xE6)
+                       snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); 
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULC_WRITE:{
+               if ( cmd[1] < 0x21 )
+                       snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); 
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULEV1_READ_CNT:{
+               if ( cmd[1] < 5 )
+                       snprintf(exp,size,"READ CNT(%d)",cmd[1]);
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULEV1_INCR_CNT:{
+               if ( cmd[1] < 5 )
+                       snprintf(exp,size,"INCR(%d)",cmd[1]);
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULEV1_READSIG:              snprintf(exp,size,"READ_SIG"); break;
+       case MIFARE_ULEV1_CHECKTEAR:    snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
+       case MIFARE_ULEV1_VCSL:         snprintf(exp,size,"VCSL"); break;
        default:                                                snprintf(exp,size,"?"); break;
        }
        return;
@@@ -142,26 -187,6 +188,26 @@@ void annotateIso15693(char *exp, size_
        }
  }
  
 +
 +void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
 +{
 +      switch(cmd[0]) {
 +              case TOPAZ_REQA                                         :snprintf(exp, size, "REQA");break;
 +              case TOPAZ_WUPA                                         :snprintf(exp, size, "WUPA");break;
 +              case TOPAZ_RID                                          :snprintf(exp, size, "RID");break;
 +              case TOPAZ_RALL                                         :snprintf(exp, size, "RALL");break;
 +              case TOPAZ_READ                                         :snprintf(exp, size, "READ");break;
 +              case TOPAZ_WRITE_E                                      :snprintf(exp, size, "WRITE-E");break;
 +              case TOPAZ_WRITE_NE                                     :snprintf(exp, size, "WRITE-NE");break;
 +              case TOPAZ_RSEG                                         :snprintf(exp, size, "RSEG");break;
 +              case TOPAZ_READ8                                        :snprintf(exp, size, "READ8");break;
 +              case TOPAZ_WRITE_E8                                     :snprintf(exp, size, "WRITE-E8");break;
 +              case TOPAZ_WRITE_NE8                            :snprintf(exp, size, "WRITE-NE8");break;
 +              default:                            snprintf(exp,size,"?"); break;
 +      }
 +}
 +
 +
  /**
  06 00 = INITIATE
  0E xx = SELECT ID (xx = Chip-ID)
@@@ -193,34 -218,7 +239,34 @@@ void annotateIso14443b(char *exp, size_
  }
  
  /**
 - * @brief iso14443B_CRC_Ok Checks CRC in command or response
 + * @brief iso14443A_CRC_check Checks CRC in command or response
 + * @param isResponse
 + * @param data
 + * @param len
 + * @return  0 : CRC-command, CRC not ok
 + *          1 : CRC-command, CRC ok
 + *          2 : Not crc-command
 + */
 +
 +uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
 +{
 +      uint8_t b1,b2;
 +
 +      if(len <= 2) return 2;
 +
 +      if(isResponse & (len < 6)) return 2;
 +      
 +      ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2);
 +      if (b1 != data[len-2] || b2 != data[len-1]) {
 +              return 0;
 +      } else {
 +              return 1;
 +      }
 +}
 +
 +
 +/**
 + * @brief iso14443B_CRC_check Checks CRC in command or response
   * @param isResponse
   * @param data
   * @param len
@@@ -237,10 -235,9 +283,10 @@@ uint8_t iso14443B_CRC_check(bool isResp
  
        ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2);
        if(b1 != data[len-2] || b2 != data[len-1]) {
 -        return 0;
 +              return 0;
 +      } else {
 +              return 1;
        }
 -      return 1;
  }
  
  /**
@@@ -304,66 -301,11 +350,66 @@@ uint8_t iclass_CRC_check(bool isRespons
        }
  }
  
 -uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
 +
 +bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen)
  {
 -      bool isResponse;
 -      uint16_t duration, data_len, parity_len;
 +      return(tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen);
 +}
 +
 +
 +bool next_record_is_response(uint16_t tracepos, uint8_t *trace)
 +{
 +      uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t)));
 +      
 +      return(next_records_datalen & 0x8000);
 +}
 +
 +
 +bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len)
 +{
 +
 +#define MAX_TOPAZ_READER_CMD_LEN      16
 +
 +      uint32_t last_timestamp = timestamp + *duration;
 +
 +      if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false;
  
 +      memcpy(topaz_reader_command, frame, *data_len);
 +
 +      while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) {
 +              uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos));
 +              *tracepos += sizeof(uint32_t);
 +              uint16_t next_duration = *((uint16_t *)(trace + *tracepos));
 +              *tracepos += sizeof(uint16_t);
 +              uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF;
 +              *tracepos += sizeof(uint16_t);
 +              uint8_t *next_frame = (trace + *tracepos);
 +              *tracepos += next_data_len;
 +              if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) {
 +                      memcpy(topaz_reader_command + *data_len, next_frame, next_data_len);
 +                      *data_len += next_data_len;
 +                      last_timestamp = next_timestamp + next_duration;
 +              } else {
 +                      // rewind and exit
 +                      *tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t);
 +                      break;
 +              }
 +              uint16_t next_parity_len = (next_data_len-1)/8 + 1;
 +              *tracepos += next_parity_len;
 +      }
 +
 +      *duration = last_timestamp - timestamp;
 +      
 +      return true;
 +}
 +
 +
 +uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes)
 +{
 +      bool isResponse;
 +      uint16_t data_len, parity_len;
 +      uint32_t duration;
 +      uint8_t topaz_reader_command[9];
        uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
        char explanation[30] = {0};
  
        uint8_t *parityBytes = trace + tracepos;
        tracepos += parity_len;
  
 +      if (protocol == TOPAZ && !isResponse) {
 +              // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
 +              // merge them:
 +              if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) {
 +                      frame = topaz_reader_command;
 +              }
 +      }
 +      
        //Check the CRC status
        uint8_t crcStatus = 2;
  
        if (data_len > 2) {
 -              uint8_t b1, b2;
 -              if(protocol == ICLASS)
 -              {
 -                      crcStatus = iclass_CRC_check(isResponse, frame, data_len);
 -
 -              }else if (protocol == ISO_14443B)
 -              {
 -                      crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
 -              }
 -              else if (protocol == ISO_14443A){//Iso 14443a
 -
 -                      ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
 -
 -                      if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
 -                              if(!(isResponse & (data_len < 6)))
 -                              {
 -                                              crcStatus = 0;
 -                              }
 -                      }
 +              switch (protocol) {
 +                      case ICLASS:
 +                              crcStatus = iclass_CRC_check(isResponse, frame, data_len);
 +                              break;
 +                      case ISO_14443B:
 +                      case TOPAZ:
 +                              crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); 
 +                              break;
 +                      case ISO_14443A:
 +                              crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
 +                              break;
 +                      default: 
 +                              break;
                }
        }
        //0 CRC-command, CRC not ok
                        oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
                }
                uint8_t parityBits = parityBytes[j>>3];
-               if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
-                       snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x!", frame[j]);
+               if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+                       snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
 -
                } else {
 -                      snprintf(line[j/16]+(( j % 16) * 4),110, "%02x  ", frame[j]);
 +                      snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
                }
  
        }
 -      if(crcStatus == 1)
 -      {//CRC-command
 -              char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1;
 -              (*pos1) = '[';
 -              char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2;
 -              (*pos2) = ']';
 +
 +      if (markCRCBytes) {
 +              if(crcStatus == 0 || crcStatus == 1)
 +              {//CRC-command
 +                      char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4);
 +                      (*pos1) = '[';
 +                      char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4);
 +                      sprintf(pos2, "%c", ']');
 +              }
        }
 +
        if(data_len == 0)
        {
                if(data_len == 0){
  
        if(!isResponse)
        {
 -              if(protocol == ICLASS)
 -                      annotateIclass(explanation,sizeof(explanation),frame,data_len);
 -              else if (protocol == ISO_14443A)
 -                      annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
 -              else if(protocol == ISO_14443B)
 -                      annotateIso14443b(explanation,sizeof(explanation),frame,data_len);
 +              switch(protocol) {
 +                      case ICLASS:            annotateIclass(explanation,sizeof(explanation),frame,data_len); break;
 +                      case ISO_14443A:        annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break;
 +                      case ISO_14443B:        annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break;
 +                      case TOPAZ:                     annotateTopaz(explanation,sizeof(explanation),frame,data_len); break;
 +                      default:                        break;
 +              }
        }
  
        int num_lines = MIN((data_len - 1)/16 + 1, 16);
        for (int j = 0; j < num_lines ; j++) {
                if (j == 0) {
 -                      PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
 +                      PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s",
                                (timestamp - first_timestamp),
                                (EndOfTransmissionTimestamp - first_timestamp),
                                (isResponse ? "Tag" : "Rdr"),
                                (j == num_lines-1) ? crc : "    ",
                                (j == num_lines-1) ? explanation : "");
                } else {
 -                      PrintAndLog("           |           |     | %-64s| %s| %s",
 +                      PrintAndLog("            |            |     |%-64s | %s| %s",
                                line[j],
 -                              (j == num_lines-1)?crc:"    ",
 +                              (j == num_lines-1) ? crc : "    ",
                                (j == num_lines-1) ? explanation : "");
                }
        }
  
 -      if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
 +      if (is_last_record(tracepos, trace, traceLen)) return traceLen;
        
 -      bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
 -
 -      if (showWaitCycles && !isResponse && next_isResponse) {
 +      if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
                uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
 -              if (next_timestamp != 0x44444444) {
 -                      PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
 -                              (EndOfTransmissionTimestamp - first_timestamp),
 -                              (next_timestamp - first_timestamp),
 -                              "   ",
 -                              (next_timestamp - EndOfTransmissionTimestamp));
 -              }
 +              PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
 +                      (EndOfTransmissionTimestamp - first_timestamp),
 +                      (next_timestamp - first_timestamp),
 +                      "   ",
 +                      (next_timestamp - EndOfTransmissionTimestamp));
        }
  
        return tracepos;
  int CmdHFList(const char *Cmd)
  {
        bool showWaitCycles = false;
 +      bool markCRCBytes = false;
        char type[40] = {0};
        int tlen = param_getstr(Cmd,0,type);
 -      char param = param_getchar(Cmd, 1);
 +      char param1 = param_getchar(Cmd, 1);
 +      char param2 = param_getchar(Cmd, 2);
        bool errors = false;
        uint8_t protocol = 0;
        //Validate params
 -      if(tlen == 0)
 -      {
 +
 +      if(tlen == 0) {
                errors = true;
        }
 -      if(param == 'h' || (param !=0 && param != 'f'))
 -      {
 +
 +      if(param1 == 'h'
 +                      || (param1 != 0 && param1 != 'f' && param1 != 'c')
 +                      || (param2 != 0 && param2 != 'f' && param2 != 'c')) {
                errors = true;
        }
 -      if(!errors)
 -      {
 -              if(strcmp(type, "iclass") == 0)
 -              {
 +
 +      if(!errors) {
 +              if(strcmp(type, "iclass") == 0) {
                        protocol = ICLASS;
 -              }else if(strcmp(type, "14a") == 0)
 -              {
 +              } else if(strcmp(type, "14a") == 0) {
                        protocol = ISO_14443A;
 -              }
 -              else if(strcmp(type, "14b") == 0)
 -              {
 +              } else if(strcmp(type, "14b") == 0)     {
                        protocol = ISO_14443B;
 -              }else if(strcmp(type,"raw")== 0)
 -              {
 +              } else if(strcmp(type,"topaz")== 0) {
 +                      protocol = TOPAZ;
 +              } else if(strcmp(type,"raw")== 0) {
                        protocol = -1;//No crc, no annotations
 -              }else{
 +              } else {
                        errors = true;
                }
        }
  
        if (errors) {
                PrintAndLog("List protocol data in trace buffer.");
 -              PrintAndLog("Usage:  hf list <protocol> [f]");
 +              PrintAndLog("Usage:  hf list <protocol> [f][c]");
                PrintAndLog("    f      - show frame delay times as well");
 +              PrintAndLog("    c      - mark CRC bytes");
                PrintAndLog("Supported <protocol> values:");
                PrintAndLog("    raw    - just show raw data without annotations");
                PrintAndLog("    14a    - interpret data as iso14443a communications");
                PrintAndLog("    14b    - interpret data as iso14443b communications");
                PrintAndLog("    iclass - interpret data as iclass communications");
 +              PrintAndLog("    topaz  - interpret data as topaz communications");
                PrintAndLog("");
                PrintAndLog("example: hf list 14a f");
                PrintAndLog("example: hf list iclass");
        }
  
  
 -      if (param == 'f') {
 +      if (param1 == 'f' || param2 == 'f') {
                showWaitCycles = true;
        }
  
 +      if (param1 == 'c' || param2 == 'c') {
 +              markCRCBytes = true;
 +      }
  
        uint8_t *trace;
        uint16_t tracepos = 0;
        PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
        PrintAndLog("iClass    - Timings are not as accurate");
        PrintAndLog("");
 -      PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
 -      PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
 +      PrintAndLog("      Start |        End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
 +      PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
  
        while(tracepos < traceLen)
        {
 -              tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
 +              tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
        }
  
        free(trace);
        return 0;
  }
  
+ int CmdHFSearch(const char *Cmd){
+       int ans = 0;
+       PrintAndLog("");
+       ans = CmdHF14AReader("s");
+       if (ans > 0) {
+               PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
+               return ans;
+       }
+       ans = HF14BInfo(false);
+       if (ans) {
+               PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
+               return ans;
+       }
+       ans = HFiClassReader("", false, false);
+       if (ans) {
+               PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
+               return ans;
+       }
+       ans = HF15Reader("", false);
+       if (ans) {
+               PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n");
+               return ans;
+       }
+       PrintAndLog("\nno known/supported 13.56 MHz tags found\n");
+       return 0;
+ }
  
  static command_t CommandTable[] = 
  {
++<<<<<<< HEAD
 +      {"help",        CmdHelp,                1, "This help"},
 +      {"14a",         CmdHF14A,               1, "{ ISO14443A RFIDs... }"},
 +      {"14b",         CmdHF14B,               1, "{ ISO14443B RFIDs... }"},
 +      {"15",          CmdHF15,                1, "{ ISO15693 RFIDs... }"},
 +      {"epa",         CmdHFEPA,               1, "{ German Identification Card... }"},
 +      {"legic",       CmdHFLegic,             0, "{ LEGIC RFIDs... }"},
 +      {"iclass",      CmdHFiClass,    1, "{ ICLASS RFIDs... }"},
 +      {"mf",          CmdHFMF,                1, "{ MIFARE RFIDs... }"},
 +      {"mfu",         CmdHFMFUltra,   1, "{ MIFARE Ultralight RFIDs... }"},
 +      {"topaz",       CmdHFTopaz,             1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
 +      {"tune",        CmdHFTune,              0, "Continuously measure HF antenna tuning"},
 +      {"list",        CmdHFList,              1, "List protocol data in trace buffer"},
 +      {NULL,          NULL,                   0, NULL}
++=======
+   {"help",        CmdHelp,          1, "This help"},
+   {"14a",         CmdHF14A,         1, "{ ISO14443A RFIDs... }"},
+   {"14b",         CmdHF14B,         1, "{ ISO14443B RFIDs... }"},
+   {"15",          CmdHF15,          1, "{ ISO15693 RFIDs... }"},
+   {"epa",         CmdHFEPA,         1, "{ German Identification Card... }"},
+   {"legic",       CmdHFLegic,       0, "{ LEGIC RFIDs... }"},
+   {"iclass",      CmdHFiClass,      1, "{ ICLASS RFIDs... }"},
+   {"mf",          CmdHFMF,          1, "{ MIFARE RFIDs... }"},
+   {"mfu",         CmdHFMFUltra,     1, "{ MIFARE Ultralight RFIDs... }"},
+   {"tune",        CmdHFTune,        0, "Continuously measure HF antenna tuning"},
+   {"list",        CmdHFList,        1, "List protocol data in trace buffer"},
+   {"search",      CmdHFSearch,      1, "Search for known HF tags [preliminary]"},
+       {NULL, NULL, 0, NULL}
++>>>>>>> master
  };
  
  int CmdHF(const char *Cmd)
diff --combined client/cmdhf14a.c
index 214ff1eccbffee92dddc397ac792600aaa42021b,9a761864b3fbc984ef21d839b0db886a69aeb647..cba179ec75cf55ae03a268525f0b0d1d00afb002
@@@ -23,6 -23,7 +23,7 @@@
  #include "common.h"
  #include "cmdmain.h"
  #include "mifare.h"
+ #include "cmdhfmfu.h"
  
  static int CmdHelp(const char *Cmd);
  static void waitCmd(uint8_t iLen);
@@@ -140,10 -141,10 +141,10 @@@ int CmdHF14AReader(const char *Cmd
        iso14a_card_select_t card;
        memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
  
 -      uint64_t select_status = resp.arg[0];           // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
 +      uint64_t select_status = resp.arg[0];           // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
        
        if(select_status == 0) {
-               PrintAndLog("iso14443a card select failed");
+               if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
                // disconnect
                c.arg[0] = 0;
                c.arg[1] = 0;
                return 0;
        }
  
-       PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
        PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
+       PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
        PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
  
-       // Double & triple sized UID, can be mapped to a manufacturer.
-       // HACK: does this apply for Ultralight cards?
-       if ( card.uidlen > 4 ) {
-               PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
-       }
        switch (card.sak) {
-               case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break;
+               case 0x00: 
+                       //***************************************test****************
+                       // disconnect
+                       c.arg[0] = 0;
+                       c.arg[1] = 0;
+                       c.arg[2] = 0;
+                       SendCommand(&c);
+                       
+                       uint32_t tagT = GetHF14AMfU_Type();
+                       ul_print_type(tagT, 0);
+                       //reconnect for further tests
+                       c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT;
+                       c.arg[1] = 0;
+                       c.arg[2] = 0;
+                       SendCommand(&c);
+                       UsbCommand resp;
+                       WaitForResponse(CMD_ACK,&resp);
+                       
+                       memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
+                       select_status = resp.arg[0];            // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
+                       
+                       if(select_status == 0) {
+                               //PrintAndLog("iso14443a card select failed");
+                               // disconnect
+                               c.arg[0] = 0;
+                               c.arg[1] = 0;
+                               c.arg[2] = 0;
+                               SendCommand(&c);
+                               return 0;
+                       }
+                       /*  orig
+                       // check if the tag answers to GETVERSION (0x60)
+                       c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
+                       c.arg[1] = 1;
+                       c.arg[2] = 0;
+                       c.d.asBytes[0] = 0x60;
+                       SendCommand(&c);
+                       WaitForResponse(CMD_ACK,&resp);
+                       uint8_t version[10] = {0};
+                       memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version));
+                       uint8_t len = resp.arg[0] & 0xff;
+                       switch ( len ){
+                               // todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command.
+                               // UL-EV1, size, check version[6] == 0x0b (smaller)  0x0b * 4 == 48
+                               case 0x0A:PrintAndLog("TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128);break;
+                               case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break;
+                               case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break;    
+                       }
+                       */
+                       break;
                case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break;
                case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
                case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break;
                default: ;
        }
  
+       // Double & triple sized UID, can be mapped to a manufacturer.
+       // HACK: does this apply for Ultralight cards?
+       if ( card.uidlen > 4 ) {
+               PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
+       }
        // try to request ATS even if tag claims not to support it
        if (select_status == 2) {
                uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
                SendCommand(&c);
                WaitForResponse(CMD_ACK,&resp);
                
-           memcpy(&card.ats, resp.d.asBytes, resp.arg[0]);
+           memcpy(card.ats, resp.d.asBytes, resp.arg[0]);
                card.ats_len = resp.arg[0];                             // note: ats_len includes CRC Bytes
        } 
  
@@@ -509,22 -565,20 +565,22 @@@ int CmdHF14ASnoop(const char *Cmd) 
    return 0;
  }
  
 +
  int CmdHF14ACmdRaw(const char *cmd) {
      UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
 -    uint8_t reply=1;
 -    uint8_t crc=0;
 -    uint8_t power=0;
 -    uint8_t active=0;
 -    uint8_t active_select=0;
 -    uint16_t numbits=0;
 -      uint32_t timeout=0;
 -      uint8_t bTimeout=0;
 +    bool reply=1;
 +    bool crc = FALSE;
 +    bool power = FALSE;
 +    bool active = FALSE;
 +    bool active_select = FALSE;
 +    uint16_t numbits = 0;
 +      bool bTimeout = FALSE;
 +      uint32_t timeout = 0;
 +      bool topazmode = FALSE;
      char buf[5]="";
 -    int i=0;
 +    int i = 0;
      uint8_t data[USB_CMD_DATA_SIZE];
 -      uint16_t datalen=0;
 +      uint16_t datalen = 0;
        uint32_t temp;
  
      if (strlen(cmd)<2) {
          PrintAndLog("       -s    active signal field ON with select");
          PrintAndLog("       -b    number of bits to send. Useful for send partial byte");
                PrintAndLog("       -t    timeout in ms");
 +              PrintAndLog("       -T    use Topaz protocol to send command");
          return 0;
      }
  
 +      
      // strip
      while (*cmd==' ' || *cmd=='\t') cmd++;
  
          if (cmd[i]=='-') {
              switch (cmd[i+1]) {
                  case 'r': 
 -                    reply=0;
 +                    reply = FALSE;
                      break;
                  case 'c':
 -                    crc=1;
 +                    crc = TRUE;
                      break;
                  case 'p':
 -                    power=1;
 +                    power = TRUE;
                      break;
                  case 'a':
 -                    active=1;
 +                    active = TRUE;
                      break;
                  case 's':
 -                    active_select=1;
 +                    active_select = TRUE;
                      break;
                  case 'b': 
                      sscanf(cmd+i+2,"%d",&temp);
                      i-=2;
                      break;
                                case 't':
 -                                      bTimeout=1;
 +                                      bTimeout = TRUE;
                                        sscanf(cmd+i+2,"%d",&temp);
                                        timeout = temp;
                                        i+=3;
                                        while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
                                        i-=2;
                                        break;
 +                case 'T':
 +                                      topazmode = TRUE;
 +                                      break;
                  default:
                      PrintAndLog("Invalid option");
                      return 0;
          PrintAndLog("Invalid char on input");
          return 0;
      }
 +
      if(crc && datalen>0 && datalen<sizeof(data)-2)
      {
          uint8_t first, second;
 -        ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
 +              if (topazmode) {
 +                      ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
 +              } else {
 +                      ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
 +              }
          data[datalen++] = first;
          data[datalen++] = second;
      }
      }
  
        if(bTimeout){
 -          #define MAX_TIMEOUT 40542464        // (2^32-1) * (8*16) / 13560000Hz * 1000ms/s = 
 +          #define MAX_TIMEOUT 40542464        // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
          c.arg[0] |= ISO14A_SET_TIMEOUT;
          if(timeout > MAX_TIMEOUT) {
              timeout = MAX_TIMEOUT;
          }
                c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
        }
 +
      if(power)
          c.arg[0] |= ISO14A_NO_DISCONNECT;
 -    if(datalen>0)
 +
 +      if(datalen > 0)
          c.arg[0] |= ISO14A_RAW;
  
 +      if(topazmode)
 +              c.arg[0] |= ISO14A_TOPAZMODE;
 +              
        // Max buffer is USB_CMD_DATA_SIZE
      c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
      memcpy(c.d.asBytes,data,datalen);
      return 0;
  }
  
 +
  static void waitCmd(uint8_t iSelect)
  {
      uint8_t *recv;
      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
          recv = resp.d.asBytes;
          uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0];
 -        PrintAndLog("received %i octets",iLen);
 +        PrintAndLog("received %i octets", iLen);
          if(!iLen)
              return;
          hexout = (char *)malloc(iLen * 3 + 1);
diff --combined common/Makefile.common
index 7e264d286a8a5a61186834f75ae0c22fd0f313ca,98ff4d0d8aa2ae64b5caf4d74b63c6d22d0a77f7..7c94e041cee0551313f7494d74dc5e1752089d17
@@@ -25,6 -25,7 +25,7 @@@ CC    = $(CROSS)gc
  AS    = $(CROSS)as
  LD    = $(CROSS)ld
  OBJCOPY = $(CROSS)objcopy
+ GZIP=gzip
  
  OBJDIR        = obj
  
@@@ -61,19 -62,19 +62,19 @@@ DETECTED_OS=Window
  endif
  
  
- # Also search prerequisites in the common directory (for usb.c), and the fpga directory (for fpga.bit)
- VPATH = . ../common/ ../fpga/
+ # Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the zlib directory
+ VPATH = . ../common ../fpga ../zlib
  
  INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES)
  
 -CFLAGS =  -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os
 +CFLAGS =  -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 -Os $(APP_CFLAGS)
  LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
  
  LIBS = -lgcc
  
- THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(THUMBSRC))
- ARMOBJ   = $(ARMSRC:%.c=$(OBJDIR)/%.o)
- ASMOBJ   = $(patsubst %.s,$(OBJDIR)/%.o,$(ASMSRC))
+ THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(THUMBSRC)))
+ ARMOBJ   = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(ARMSRC)))
+ ASMOBJ   = $(patsubst %.s,$(OBJDIR)/%.o,$(notdir $(ASMSRC)))
  VERSIONOBJ = $(OBJDIR)/version.o
  
  $(THUMBOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES)
@@@ -109,6 -110,7 +110,7 @@@ DEPENDENCY_FILES = $(patsubst %.c,$(OBJ
        $(patsubst %.s,$(OBJDIR)/%.d,$(notdir $(ASMSRC)))
  
  $(DEPENDENCY_FILES): Makefile ../common/Makefile.common
  $(patsubst %.o,%.d,$(THUMBOBJ) $(ARMOBJ)): $(OBJDIR)/%.d: %.c
        @$(CC) -MM -MT "$(@) $(@:.d=.o)" $(CFLAGS) $< > $@
  $(patsubst %.o,%.d,$(ASMOBJ)):$(OBJDIR)/%.d: %.s
diff --combined common/protocols.h
index b0f1657094aa5754b5e0529c4361b319e9d3a80e,580342728b866ee7f76d3f09537580da1c43c72d..169cee47d599023dc94ceef3adc60531d48886e5
@@@ -123,9 -123,21 +123,21 @@@ NXP/Philips CUSTOM COMMAND
  #define MIFARE_CMD_RESTORE      0xC2
  #define MIFARE_CMD_TRANSFER     0xB0
  
- #define MIFARE_ULC_WRITE        0xA0
+ #define MIFARE_ULC_WRITE        0xA2
+ //#define MIFARE_ULC__COMP_WRITE  0xA0
  #define MIFARE_ULC_AUTH_1       0x1A
- #define MIFARE_ULC_AUTH_2        0xAF
+ #define MIFARE_ULC_AUTH_2       0xAF
+ #define MIFARE_ULEV1_AUTH       0x1B
+ #define MIFARE_ULEV1_VERSION    0x60
+ #define MIFARE_ULEV1_FASTREAD   0x3A
+ //#define MIFARE_ULEV1_WRITE      0xA2
+ //#define MIFARE_ULEV1_COMP_WRITE 0xA0
+ #define MIFARE_ULEV1_READ_CNT   0x39
+ #define MIFARE_ULEV1_INCR_CNT   0xA5
+ #define MIFARE_ULEV1_READSIG    0x3C
+ #define MIFARE_ULEV1_CHECKTEAR  0x3E
+ #define MIFARE_ULEV1_VCSL       0x4B
  
  /**
  06 00 = INITIATE
  #define ISO15693_READ_MULTI_SECSTATUS 0x2C
  
  
 -#define ISO_14443A 0
 -#define ICLASS     1
 -#define ISO_14443B 2
 +// Topaz command set:
 +#define       TOPAZ_REQA                                              0x26    // Request
 +#define       TOPAZ_WUPA                                              0x52    // WakeUp
 +#define       TOPAZ_RID                                               0x78    // Read ID
 +#define       TOPAZ_RALL                                              0x00    // Read All (all bytes)
 +#define       TOPAZ_READ                                              0x01    // Read (a single byte)
 +#define       TOPAZ_WRITE_E                                   0x53    // Write-with-erase (a single byte)
 +#define       TOPAZ_WRITE_NE                                  0x1a    // Write-no-erase (a single byte)
 +// additional commands for Dynamic Memory Model
 +#define TOPAZ_RSEG                                            0x10    // Read segment
 +#define TOPAZ_READ8                                           0x02    // Read (eight bytes)
 +#define TOPAZ_WRITE_E8                                        0x54    // Write-with-erase (eight bytes)
 +#define TOPAZ_WRITE_NE8                                       0x1B    // Write-no-erase (eight bytes)
 +
 +
 +#define ISO_14443A    0
 +#define ICLASS                1
 +#define ISO_14443B    2
 +#define TOPAZ         3
  
  //-- Picopass fuses
  #define FUSE_FPERS   0x80
Impressum, Datenschutz