]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/legicrf.c
CHG: reordered the "hf search" internal checks. The iclass check takes 4.5sec to...
[proxmark3-svn] / armsrc / legicrf.c
index 223a777209cf401175fd08e0bbb5ff15f6249869..f9092103ea1f0b1a70037731ba64fd81b2b0f3d3 100644 (file)
@@ -92,11 +92,7 @@ static void setup_timer(void) {
 # define OPEN_COIL     HIGH(GPIO_SSC_DOUT);
 #endif
 #ifndef LINE_IN
-# define LINE_IN \
-       do { \
-       AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_DIN; \
-       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DIN; \
-       } while (0); 
+# define LINE_IN  AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DIN;
 #endif
 // Pause pulse,  off in 20us / 30ticks,
 // ONE / ZERO bit pulse,  
@@ -205,8 +201,7 @@ void frame_send_tag(uint16_t response, uint8_t bits) {
  */
 void frame_sendAsReader(uint32_t data, uint8_t bits){
 
-       uint32_t starttime = GET_TICKS, send = 0;
-       uint16_t mask = 1;
+       uint32_t starttime = GET_TICKS, send = 0, mask = 1;
        
        // xor lsfr onto data.
        send = data ^ legic_prng_get_bits(bits);
@@ -222,7 +217,7 @@ void frame_sendAsReader(uint32_t data, uint8_t bits){
        COIL_PULSE(0);
        
        // log
-       uint8_t cmdbytes[] = {bits,     BYTEx(data, 0), BYTEx(data, 1), BYTEx(send, 0), BYTEx(send, 1)};
+       uint8_t cmdbytes[] = {bits, BYTEx(data,0), BYTEx(data,1), BYTEx(data,2), BYTEx(send,0), BYTEx(send,1), BYTEx(send,2)};
        LogTrace(cmdbytes, sizeof(cmdbytes), starttime, GET_TICKS, NULL, TRUE);
 }
 
@@ -258,9 +253,6 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) {
        
        frame_clean(f);
        
-       /* Bitbang the receiver */
-       LINE_IN;
-       
        // calibrate the prng.
        legic_prng_forward(2);
        data = legic_prng_get_bits(bits);
@@ -348,10 +340,11 @@ static void LegicCommonInit(void) {
        SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
 
        /* Bitbang the transmitter */
-       LOW(GPIO_SSC_DOUT);
+       SHORT_COIL;
        AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
        AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
-
+       AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_DIN;
+       
        // reserve a cardmem,  meaning we can use the tracelog function in bigbuff easier.
        cardmem = BigBuf_get_EM_addr();
        memset(cardmem, 0x00, LEGIC_CARD_MEMSIZE);
@@ -365,7 +358,7 @@ static void LegicCommonInit(void) {
 
 // Switch off carrier, make sure tag is reset
 static void switch_off_tag_rwd(void) {
-       LOW(GPIO_SSC_DOUT);
+       SHORT_COIL;
        WaitUS(20);
        WDT_HIT();
 }
@@ -396,7 +389,7 @@ int legic_read_byte( uint16_t index, uint8_t cmd_sz) {
        calcCrc = legic4Crc(LEGIC_READ, index, byte, cmd_sz);
 
        if( calcCrc != crc ) {
-               Dbprintf("!!! crc mismatch: expected %x but got %x !!!",  calcCrc, crc);
+               Dbprintf("!!! crc mismatch: %x != %x !!!",  calcCrc, crc);
                return -1;
        }
 
@@ -409,66 +402,66 @@ int legic_read_byte( uint16_t index, uint8_t cmd_sz) {
  * - wait until the tag sends back an ACK ('1' bit unencrypted)
  * - forward the prng based on the timing
  */
-int legic_write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
-
-       // crc
-       crc_clear(&legic_crc);
-       crc_update(&legic_crc, 0, 1); /* CMD_WRITE */
-       crc_update(&legic_crc, index, addr_sz);
-       crc_update(&legic_crc, byte, 8);
-       uint32_t crc = crc_finish(&legic_crc);
-       /*
-       uint32_t crc2 = legic4Crc(LEGIC_WRITE, index, byte, addr_sz+1);
-       if ( crc != crc2 ) {
-               Dbprintf("crc is missmatch");
-               return 1;
-       }
-       */
+bool legic_write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
+
+       bool isOK = false;
+       int8_t i = 40;
+       uint8_t edges = 0;
+       uint8_t cmd_sz = addr_sz+1+8+4; //crc+data+cmd;
+       uint32_t steps = 0, next_bit_at, start, crc, old_level = 0;
+
+       crc = legic4Crc(LEGIC_WRITE, index, byte, addr_sz+1);
+
        // send write command
-       uint32_t cmd = ((crc     <<(addr_sz+1+8)) //CRC
-                   |(byte    <<(addr_sz+1))   //Data
-                   |(index    <<1)             //index
-                   | LEGIC_WRITE);            //CMD = Write
-                                  
-    uint32_t cmd_sz = addr_sz+1+8+4;          //crc+data+cmd
-
-    legic_prng_forward(2);
+       uint32_t cmd = LEGIC_WRITE;
+       cmd |= index << 1;                        // index
+       cmd |= byte  << (addr_sz+1);  // Data   
+       cmd     |= (crc & 0xF ) << (addr_sz+1+8);       // CRC
        
-       WaitTicks(330);
+       WaitTicks(240);
        
        frame_sendAsReader(cmd, cmd_sz);
-
-       /* Bitbang the receiver */
+       
        LINE_IN;
 
-    int t, old_level = 0, edges = 0;
-    int next_bit_at = 0;
+       start = GET_TICKS;
 
-       // ACK 3.6ms = 3600us * 1.5 = 5400ticks.
+       // ACK,  - one single "1" bit after 3.6ms
+       // 3.6ms = 3600us * 1.5 = 5400ticks.
        WaitTicks(5400);
-
-    for( t = 0; t < 80; ++t) {
+       
+       next_bit_at = GET_TICKS + TAG_BIT_PERIOD;
+       
+    while ( i-- ) {
+               WDT_HIT();
         edges = 0;
-               next_bit_at += TAG_BIT_PERIOD;
-        while(timer->TC_CV < next_bit_at) {
+        while ( GET_TICKS < next_bit_at) {
+                       
             volatile uint32_t level = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN);
-            if(level != old_level)
-                edges++;
+            
+                       if (level != old_level)
+                ++edges;
 
             old_level = level;
         }
-               /* expected are 42 edges (ONE) */
+               
+               next_bit_at += TAG_BIT_PERIOD;
+               
+               // We expect 42 edges (ONE)
         if(edges > 20 ) {
-                       int t = timer->TC_CV;
-                       int c = t / TAG_BIT_PERIOD;
-                       
-                       ResetTimer(timer);
-                       legic_prng_forward(c);
-               return 0;
+                       steps = ( (GET_TICKS - start) / TAG_BIT_PERIOD);                        
+                       legic_prng_forward(steps);
+               isOK = true;
+                       goto OUT;
         }
     }
-
-       return -1;
+               
+OUT: ;
+       legic_prng_forward(1);
+       
+       uint8_t cmdbytes[] = {1, isOK, BYTEx(steps, 0), BYTEx(steps, 1) };
+       LogTrace(cmdbytes, sizeof(cmdbytes), start, GET_TICKS, NULL, FALSE);
+       return isOK;
 }
 
 int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
@@ -484,13 +477,9 @@ int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
                goto OUT;
        }
 
-       switch_off_tag_rwd();
-
        if (len + offset >= card.cardsize)
                len = card.cardsize - offset;
 
-       setup_phase_reader(iv);
-               
        LED_B_ON();
        while (i < len) {
                int r = legic_read_byte(offset + i, card.cmdsize);
@@ -515,8 +504,6 @@ OUT:
 void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
 
        #define LOWERLIMIT 4
-
-       int r = 0;
        uint8_t isOK = 1;
        legic_card_select_t card;
        
@@ -533,28 +520,21 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
                goto OUT;
        }
        
-       switch_off_tag_rwd();
-       
        if ( len + offset + LOWERLIMIT >= card.cardsize) {
                isOK = 0;
                goto OUT;
        }
-       
-       setup_phase_reader(iv);
 
     LED_B_ON();        
        while( len > 0 ) {
-
-               int r = legic_write_byte( len + offset + LOWERLIMIT, data[len], card.addrsize);
-               if ( r == -1 ) {
-                       Dbprintf("operation aborted @ 0x%03.3x", len);
+               --len;          
+               if ( !legic_write_byte( len + offset, data[len], card.addrsize) ) {
+                       Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len] );
                        isOK = 0;
                        goto OUT;
                }
-               --len;
                WDT_HIT();
        }
-
 OUT:
        cmd_send(CMD_ACK, isOK, 0,0,0,0);
        switch_off_tag_rwd();
Impressum, Datenschutz