// read from start to end blocks. data will need to be large enough // to hold all blocks. BOOL read_tag(BYTE *data, unsigned int startblock, unsigned int endblock) { unsigned int i, p= 0; for(i= startblock; i <= endblock ; ++i, ++p) { switch(RFIDlerConfig.TagType) { case TAG_TYPE_Q5: case TAG_TYPE_T55X7: if(!q5_read_block(data + p * HEXDIGITS(RFIDlerConfig.BlockSize), (BYTE) i)) return FALSE; break; case TAG_TYPE_HITAG1: if (!hitag1_read_page(data + p * HEXDIGITS(RFIDlerConfig.BlockSize), (BYTE) i)) return FALSE; break; case TAG_TYPE_HITAG2: if (!hitag2_read_page(data + p * HEXDIGITS(RFIDlerConfig.BlockSize), (BYTE) i)) return FALSE; break; default: return FALSE; } } return TRUE; }
// optional verify as writing config block may casue next read to fail BOOL q5_write_block(BYTE block, BYTE *data, BOOL lock, BOOL verify) { BYTE tmp[71], p; if(block > Q5_DATABLOCKS - 1) return FALSE; // create 38 or 70 bit command block: Q5_STD_WRITE_P0 + [PWD] + Lock Bit + 32 bits Data + 3 bits address memset(tmp, '\0', sizeof(tmp)); // command memcpy(tmp, Q5_STD_WRITE_P0, 2); p= 2; // password if(PWD_Mode) { hextobinstring(tmp + p, Password); p += 32; } // lockbit inttobinstring(tmp + p, (unsigned int) lock, 1); ++p; // data hextobinstring(tmp + p, data); p += Q5_BLOCKSIZE; // address inttobinstring(tmp + p, (unsigned int) block, 3); p += 3; // send if(!q5_send_command(NULL, tmp, strlen(tmp), NO_RESET, NO_SYNC, 0)) return FALSE; // no ack, so read back and verify // delay for long enough to allow write plus TX->RX period Delay_us((Q5_WRITE_DELAY * RFIDlerConfig.FrameClock + RFIDlerConfig.RWD_Wait_Switch_TX_RX * RFIDlerConfig.FrameClock) / 100L); if(!verify) return TRUE; if(!q5_read_block(tmp, block)) return FALSE; if(memcmp(tmp, data, HEXDIGITS(Q5_BLOCKSIZE)) != 0) return FALSE; return TRUE; }
// try to find values that correctly transmit all commands to q5 // to test this properly, q5 should have invalid data in it's data blocks // so that only a GET_TRACE_DATA command will return a true value BOOL q5_rwd_test(BYTE *pattern) { BYTE start_gap, gap, one, zero, i, tmp[Q5_BLOCKSIZE + 1]; BOOL found= FALSE, blank; // min/max from datasheets for(one= 48 ; one <= 63 ; ++one) for(zero= 16; zero <= 31 ; ++zero) for(gap= 10 ; gap <= 50 ; ++gap) for(start_gap= 11 ; start_gap <= 50 ; ++start_gap) { RFIDlerConfig.Manchester= TRUE; blank= TRUE; if(get_user_abort()) return found; RFIDlerConfig.RWD_Gap_Period= gap; RFIDlerConfig.RWD_One_Period= one; RFIDlerConfig.RWD_Zero_Period= zero; // reset tag get_tag_uid(tmp); // try to switch off modulation // send command with start gap: reset with sleep time set to start gap, and wake time set to 0 as we transmit the 1st bit immediately // note that we must also subtract standard gap period as it will be added to the front of the first bit by default. rwd_send(Q5_MODULATION_DEFEAT, strlen(Q5_MODULATION_DEFEAT), NO_RESET, BLOCK, RWD_STATE_START_SEND, RFIDlerConfig.FrameClock, start_gap - RFIDlerConfig.RWD_Gap_Period, 0, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX); // read a block with no sync & no manchester - will be all '0' if not modulating RFIDlerConfig.Manchester= FALSE; if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, RFIDlerConfig.DataBits, RFIDlerConfig.Sync, 0, RFIDlerConfig.Timeout, NO_ONESHOT_READ, HEX) == RFIDlerConfig.DataBits) { for(i= 0 ; i < HEXDIGITS(RFIDlerConfig.DataBits) ; ++i) if(tmp[i] != '0') blank= FALSE; RFIDlerConfig.Manchester= TRUE; if(blank && get_tag_uid(tmp) && q5_read_block(tmp, 0)) { UserMessageNum("\r\nFound tag with start_gap %d", start_gap); UserMessageNum(" gap %d", gap); UserMessageNum(" one %d", one); UserMessageNum(" zero %d", zero); found= TRUE; } } } UserMessage("%s", "\r\n"); return found; }
// try to find values that correctly transmit all commands to q5 // to test this properly, q5 should have invalid data in it's data blocks // so that only a GET_TRACE_DATA command will return a true value BOOL q5_rwd_test(BYTE *pattern) { BYTE gap, one, zero, tmp[Q5_BLOCKSIZE + 1]; BOOL found= FALSE, blank; // min/max from datasheets for(one= 48 ; one <= 63 ; ++one) for(zero= 16; zero <= 31 ; ++zero) for(gap= 10 ; gap <= 50 ; ++gap) { RFIDlerConfig.Manchester= TRUE; blank= TRUE; if(get_user_abort()) return found; RFIDlerConfig.RWD_Gap_Period= gap; RFIDlerConfig.RWD_One_Period= one; RFIDlerConfig.RWD_Zero_Period= zero; // reset tag get_tag_uid(tmp); // try to switch off modulation rwd_send(Q5_MODULATION_DEFEAT, strlen(Q5_MODULATION_DEFEAT), NO_RESET, BLOCK, RWD_STATE_START_SEND, RFIDlerConfig.FrameClock, RFIDlerConfig.RWD_Gap_Period, 0, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX); // read a block with no sync & no manchester - will be all '0' if not modulating RFIDlerConfig.Manchester= FALSE; if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, RFIDlerConfig.DataBits, RFIDlerConfig.Sync, 0, RFIDlerConfig.Timeout, NO_ONESHOT_READ, HEX) == RFIDlerConfig.DataBits) { if(strcmp(tmp, "0000000000000000") != 0) blank= FALSE; RFIDlerConfig.Manchester= TRUE; if(blank && get_tag_uid(tmp) && q5_read_block(tmp, 0)) { UserMessageNum("\r\nFound tag with gap %d", gap); UserMessageNum(" one %d", one); UserMessageNum(" zero %d", zero); found= TRUE; } } } UserMessage("%s", "\r\n"); return found; }