// optional verify as writing config block may casue next read to fail BOOL t55x7_write_block(BYTE block, BYTE *data, BOOL lock, BOOL verify) { BYTE tmp[71], p; if(block > T55X7_DATABLOCKS - 1) return FALSE; // create 38 or 70 bit command block: T55X7_STD_WRITE_P0 + [PWD] + Lock Bit + 32 bits Data + 3 bits address memset(tmp, '\0', sizeof(tmp)); // command memcpy(tmp, T55X7_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 += T55X7_BLOCKSIZE; // address inttobinstring(tmp + p, (unsigned int) block, 3); p += 3; // send if(!t55x7_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((T55X7_WRITE_DELAY * RFIDlerConfig.FrameClock + RFIDlerConfig.RWD_Wait_Switch_TX_RX * RFIDlerConfig.FrameClock) / 100L); if(!verify) return TRUE; if(!t55x7_read_block(tmp, block)) return FALSE; if(memcmp(tmp, data, HEXDIGITS(T55X7_BLOCKSIZE)) != 0) return FALSE; return TRUE; }
// set password and mode, and return UID BOOL q5_login(BYTE *response, BYTE *pass) { BYTE tmp[35]; // check we need password - if we can get UID without, then we don't if(q5_get_uid(tmp)) return FALSE; if(strlen(pass) == 0) pass= Q5_DEFAULT_PWD; memcpy(tmp, Q5_AOR, 2); hextobinstring(tmp + 2, pass); tmp[34]= '\0'; // send password if (!q5_send_command(response, tmp, strlen(tmp), RESET, NO_SYNC, 0)) return FALSE; // see if we can now get UID if(!q5_get_uid(tmp)) return FALSE; PWD_Mode= TRUE; strcpy(Password, pass); strcpy(response, pass); return TRUE; }
BOOL q5_read_block(BYTE *response, BYTE block) { BYTE tmp[39], retry, reset= FALSE; if(block > Q5_DATABLOCKS - 1) return FALSE; // create 6 or 38 bit command block: Q5_DIRECT_ACCESS + PWD_Mode + [PWD] + 3 bits address memset(tmp, '\0', 39); memcpy(tmp, Q5_DIRECT_ACCESS, 2); if(PWD_Mode) { tmp[2]= '1'; hextobinstring(tmp + 3, Password); inttobinstring(tmp + 34, (unsigned int) block, 3); } else { tmp[2]= '0'; inttobinstring(tmp + 3, (unsigned int) block, 3); } retry= RFIDlerConfig.Repeat; while(retry--) { //DEBUG_PIN_4= !DEBUG_PIN_4; //DEBUG_PIN_4= !DEBUG_PIN_4; if(q5_send_command(response, tmp, strlen(tmp), reset, NO_SYNC, 32)) return TRUE; // try resetting tag reset= TRUE; } return FALSE; }
// auth in password mode BOOL hitag2_pwd_auth(BYTE *response, BYTE *pwd) { BYTE tmp[37]; // restart the tag if(!hitag2_get_uid(tmp)) return FALSE; if(strlen(pwd) == 0) pwd= HITAG2_PWD_DEFAULT; // use default transport key if none specified if(!hextobinstring(tmp, pwd)) return FALSE; // wait for RX->TX period, then send 32 bit PWD if(!rwd_send(tmp, strlen(tmp), NO_RESET, BLOCK, RWD_STATE_WAKING, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) return FALSE; // skip 1/2 bit to synchronise manchester HW_Skip_Bits= 1; // get 37 bit response: sync + config byte + 24 bit TAG pwd if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY) == 37) { // check sync bits if (memcmp(tmp, Hitag2Sync, 5) != 0) return FALSE; binarraytohex(response, tmp + 5, 32); return TRUE; } return FALSE; }
BOOL hitag1_write_page(BYTE block, BYTE *data) { BYTE crc, command[21], tmp[33], tmp1[4]; if(block > HITAG1_DATABLOCKS - 1) return FALSE; // get tag's UID for select command if(!hitag1_get_uid(tmp)) return FALSE; // select for read/write hitag1_select(tmp, tmp); // convert data to binstring for send if(hextobinstring(tmp, data) != 32) return FALSE; // create and send 12 bit command block: HITAG1_WRPPAGE (4 bits) + 8 bit address memcpy(command, HITAG1_WRPPAGE, 4); inttobinstring(command + 4, (unsigned int) block, 8); command[12]= '\0'; if(!hitag1_send_command(tmp1, command, NO_RESET, NO_SYNC, 0, ACK)) return FALSE; // delay to switch back to write mode Delay_us((RFIDlerConfig.RWD_Wait_Switch_RX_TX * RFIDlerConfig.FrameClock) / 100); // now send data if(!hitag1_send_command(tmp1, tmp, NO_RESET, NO_SYNC, 0, ACK)) return FALSE; // read back and verify // delay for long enough to allow write plus RX->TX period Delay_us((HITAG1_WRITE_DELAY * RFIDlerConfig.FrameClock + RFIDlerConfig.RWD_Wait_Switch_RX_TX * RFIDlerConfig.FrameClock) / 100); if(!hitag1_read_page(tmp, block)) return FALSE; if(memcmp(tmp, data, 8) != 0) return FALSE; return TRUE; }
// select HITAG1 for read/write operations - return config page BOOL hitag1_select(BYTE *response, BYTE *uid) { BYTE command[38], tmp1[33]; // command: 5 bit command + 32 bit uid + NULL strcpy(command, HITAG1_SELECT); if(!hextobinstring(command + 5, uid)) return FALSE; // send command and get back 1 sync bit + 32 bit configpage if(!hitag1_send_command(tmp1, command, NO_RESET, NO_SYNC, 33, NO_ACK)) return FALSE; // check sync bit if(tmp1[0] == 0x01) { binarraytohex(response, tmp1 + 1, 32); return TRUE; } return FALSE; }
BOOL hitag2_write_page(BYTE block, BYTE *data) { BYTE command[11], tmp[37], tmp1[37], tmp2[37], tmphex[9]; if(block > HITAG2_DATABLOCKS - 1) return FALSE; // create 10 bit command block: HITAG2_WRIE_PAGE + 3 bits address + invert(HITAG2_WRITE_PAGE + 3 bits address) memcpy(command, HITAG2_WRITE_PAGE, 2); inttobinstring(command + 2, (unsigned int) block, 3); invertbinstring(command + 5, command); command[10]= '\0'; // encrypt command if in crypto mode if(CryptoActive) hitag2_binstring_crypt(tmp, command); else memcpy(tmp, command, 11); // convert data to binstring for send if(hextobinstring(tmp1, data) != 32) return FALSE; // send command with RX->TX delay and no reset if(!rwd_send(tmp, strlen(tmp), NO_RESET, BLOCK, RWD_STATE_WAKING, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) return FALSE; // skip 1/2 bit to synchronise manchester HW_Skip_Bits= 1; // get ACK - 10 bytes + sync if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp2, 15, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY) == 15) { // check sync bits if (memcmp(tmp2, Hitag2Sync, 5) != 0) return FALSE; // decrypt if(CryptoActive) hitag2_binarray_crypt(tmp2 + 5, tmp2 + 5, 10); // check ACK - should be our original command echo'd back binarraytobinstring(tmp2 + 5, tmp2 + 5, 10); if(memcmp(command, tmp2 + 5, 10) != 0) return FALSE; } // encrypt data if in crypto mode if(CryptoActive) hitag2_binstring_crypt(tmp1, tmp1); // send data with RX->TX delay and no reset if(!rwd_send(tmp1, strlen(tmp1), NO_RESET, BLOCK, RWD_STATE_WAKING, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) return FALSE; // no ack, so read back and verify // delay for long enough to allow write plus RX->TX period Delay_us((HITAG2_WRITE_DELAY * RFIDlerConfig.FrameClock + RFIDlerConfig.RWD_Wait_Switch_RX_TX * RFIDlerConfig.FrameClock) / 100); if(!hitag2_read_page(tmp, block)) return FALSE; if(memcmp(tmp, data, 8) != 0) return FALSE; return TRUE; }