# 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,
*/
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);
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);
}
frame_clean(f);
- /* Bitbang the receiver */
- LINE_IN;
-
// calibrate the prng.
legic_prng_forward(2);
data = legic_prng_get_bits(bits);
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);
// 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();
}
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;
}
* - 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) {
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);
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;
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();