// convert null-terminated BCD UID (8 digits) to 96 bit hid26 encoded binary array BOOL bcd_to_hid26_bin(unsigned char *hid26, unsigned char *bcd) { unsigned char tmp1[8], tmp2[26]; unsigned int tmpint; if(strlen(bcd) != 8) return FALSE; // convert BCD site code to HEX sscanf(bcd, "%03d", &tmpint); sprintf(tmp2, "%02x", tmpint); memcpy(tmp1, tmp2, 2); // convert BCD ID to HEX sscanf(bcd + 3, "%05d", &tmpint);; sprintf(tmp2, "%04x", tmpint); // copy with trailing NULL memcpy(tmp1 + 2, tmp2, 5); // convert full HEX to binary, leaving room for parity prefix hextobinarray(tmp2 + 1, tmp1); wiegand_add_parity(tmp2, tmp2 + 1, 24); // magic 44 bit hid26 header hextobinarray(hid26, "1D555955556"); // add manchester encoded hid data manchester_encode(hid26 + 44, tmp2, 26); return TRUE; }
// convert 96 bit HID FSK data to 8 digit BCD UID BOOL hid26_hex_to_uid(unsigned char *response, unsigned char *hid26) { BYTE tmp[96], tmp1[7]; unsigned int site; unsigned int id; // todo parity checking etc. if(!hextobinarray(tmp, hid26)) return FALSE; // skip 44 bit header memcpy(tmp, tmp + 44, 52); // manchester decode if(manchester_decode(tmp, tmp, 52) != 26) return FALSE; // convert to hex, ignoring parity bits if(!binarraytohex(tmp1, tmp + 1, 24)) return FALSE; // convert hex to site/id sscanf(tmp1,"%2X%4X", &site, &id); // final output 8 byte BCD sprintf(response,"%03d%05d", site, id); return TRUE; }
// convert 16 hex digit/64 bit EM4X02 ID to 40 bit raw UID // safe to do in-place as we use a scratchpad BOOL em4x02_hex_to_bin(unsigned char *bin, unsigned char *em) { unsigned char i, j, colparity[4]= {0,0,0,0}; if(!hextobinarray(TmpBits, em)) return FALSE; // check header for(i= 0 ; i < 9 ; ++i) if(TmpBits[i] != 0x01) return FALSE; // skip 9 bit header and strip/check parity bits - every 5th bit for(i= 0 ; i < 10 ; ++i) { memcpy(bin + i * 4, (TmpBits + 9) + i * 5, 4); if(parity(bin + i * 4, EVEN, 4) != TmpBits[9 + i * 5 + 4]) return FALSE; } // check column parity for(i= 0 ; i < 10 ; ++i) for(j= 0; j < 4 ; ++j) colparity[j] += bin[i * 4 + j]; for(i= 0 ; i < 4 ; ++i) if(colparity[i] % 2 != TmpBits[9 + 50 + i]) return FALSE; return TRUE; }
// print a hex value as binary void printhexasbin(unsigned char *hex) { unsigned int length; length= hextobinarray(TmpBits,hex); printbinarray(TmpBits, length); }
// convert hex to unsigned long long unsigned long long hextoulonglong(BYTE *hex) { BYTE tmp[64]; if(hextobinarray(tmp, hex) != 64) return 0L; return binarraytoulonglong(tmp, 64); }
BOOL send_ask_hex(unsigned char *data, unsigned int pulsewidth, unsigned int tpb, unsigned int repeat) { unsigned int length; if(!(length= hextobinarray(TmpBits, data))) return FALSE; return send_ask_bin(TmpBits, length, pulsewidth, tpb, repeat); }
// convert hex to human readable binary string unsigned int hextobinstring(unsigned char *target, unsigned char *source) { unsigned int length; if(!(length= hextobinarray(target, source))) return 0; binarraytobinstring(target, target, length); return length; }
// convert null-terminated BCD UID (8 digits) to 96 bit awid26 encoded binary array BOOL bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd) { unsigned char i, p, tmp1[8], tmp2[26]; unsigned int tmpint; if(strlen(bcd) != 8) return FALSE; // convert BCD site code to HEX sscanf(bcd, "%03d", &tmpint); sprintf(tmp2, "%02x", tmpint); memcpy(tmp1, tmp2, 2); // convert BCD ID to HEX sscanf(bcd + 3, "%05d", &tmpint);; sprintf(tmp2, "%04x", tmpint); // copy with trailing NULL memcpy(tmp1 + 2, tmp2, 5); // convert full HEX to binary, leaving room for parity prefix hextobinarray(tmp2 + 1, tmp1); wiegand_add_parity(tmp2, tmp2 + 1, 24); memset(awid26, '\x0', 96); // magic 18 bit awid26 header (we will overwrite the last two bits) hextobinarray(awid26, "011D8"); // copy to target leaving space for parity bits for(i= 0, p= 18 ; i < 26 ; ++i, ++p) { // skip target bit if this is a parity location if(!((p + 1) % 4)) p += 1; awid26[p]= tmp2[i]; } // add parity bits for(i= 1 ; i < 24 ; ++i) awid26[((i + 1) * 4) - 1]= parity(&awid26[i * 4], ODD, 3); return TRUE; }
BOOL send_psk1_hex(unsigned char *data, unsigned int pulsewidth, unsigned int tpb, unsigned int c0, unsigned int repeat) { unsigned int length; BYTE tmp[256]; if(!(length= hextobinarray(tmp, data))) return FALSE; return send_psk1_bin(tmp, length, pulsewidth, tpb, c0, repeat); }
BOOL send_fsk_hex(unsigned char *data, unsigned long pulsewidth, unsigned int cpb, unsigned int c0, unsigned int c1, unsigned int repeat) { unsigned int length; if(!(length= hextobinarray(TmpBits, data))) return 0; // manchester encoding with FSK is not done in the baseband, so pre-encode if(RFIDlerConfig.Manchester) length= manchester_encode(TmpBits, TmpBits, length); return send_fsk_bin(TmpBits, length, pulsewidth, cpb, c0, c1, repeat); }
// convert 96 bit AWID FSK data to 8 digit BCD UID BOOL awid26_hex_to_uid(unsigned char *response, unsigned char *awid26) { BYTE i, tmp[96], tmp1[7]; unsigned int site; unsigned int id; if(!hextobinarray(tmp, awid26)) return FALSE; // data is in blocks of 4 bits - every 4th bit is parity, except the first // block which is all zeros for(i= 0 ; i < 4 ; ++i) if(tmp[i] != 0x00) return FALSE; // discard 1st block memcpy(tmp, tmp + 4, 92); // check and strip parity on the rest for(i= 1 ; i < 23 ; ++i) if(tmp[(i * 4) - 1] != parity(tmp + (i - 1) * 4, ODD, 3)) return FALSE; else memcpy((tmp + (i - 1) * 3), tmp + (i - 1) * 4, 3); // discard the rest of the header - 1 more 3 bit block memcpy(tmp, tmp + 3, 66); // next 8 bits is data length - should be 26: 0x1A binarraytohex(tmp1, tmp, 8); if(strcmp(tmp1, "1A") != 0) return FALSE; memcpy(tmp, tmp +8, 58); // standard wiegand parity check - even for 1st 12 bits, odd for 2nd 12 if(tmp[0] != parity(tmp + 1, EVEN, 12)) return FALSE; if(tmp[25] != parity(tmp + 13, ODD, 12)) return FALSE; // convert to hex, ignoring parity bits if(!binarraytohex(tmp1, tmp + 1, 24)) return FALSE; // convert hex to site/id sscanf(tmp1,"%2X%4X", &site, &id); // final output 8 byte BCD sprintf(response,"%03d%05d", site, id); return TRUE; }
// convert null-terminated hex UID (10 digits) to 64 bit em4x02 encoded binary array BOOL hex_to_em4x02_bin(unsigned char *em, unsigned char *hex) { unsigned char tmp1[10], tmp2[40]; if(strlen(hex) > 10) return FALSE; // pad to 10 hex digits memset(tmp1, '0', 10); memcpy(tmp1 + 10 - strlen(hex), hex, strlen(hex)); hextobinarray(tmp2, tmp1); // encoding is the same as unique, but source data is in a different order bin_to_em4x02_bin(em, tmp2); return TRUE; }
// convert 16 hex digit/64 bit EM4X02 ID to 40 bit raw UID // safe to do in-place as we use a scratchpad // todo: check parity BOOL em4x02_hex_to_bin(unsigned char *bin, unsigned char *em) { unsigned char i; if(!hextobinarray(TmpBits, em)) return FALSE; // check header for(i= 0 ; i < 9 ; ++i) if(TmpBits[i] != 0x01) return FALSE; // skip 9 bit header and strip parity bits - every 5th bit for(i= 0 ; i < 10 ; ++i) memcpy(bin + i * 4, (TmpBits + 9) + i * 5, 4); return TRUE; }
// convert null-terminated hex UID (10 digits) to unique encoded 64 bit binary array // which is the same as EM4X02 but with source hex arranged in a different order BOOL hex_to_unique_bin(unsigned char *unique, unsigned char *hex) { unsigned char tmp1[10], tmp2[40]; if(strlen(hex) > 10) return FALSE; // pad to 10 hex digits memset(tmp1, '0', 10); memcpy(tmp1 + 10 - strlen(hex), hex, strlen(hex)); // juggle into correct nibble order string_reverse(tmp1, 10); string_byteswap(tmp1, 10); // convert to binary hextobinarray(tmp2, tmp1); string_reverse(tmp2, 40); // encode for em4x02 bin_to_em4x02_bin(unique, tmp2); return TRUE; }
// copy raw UID to data blocks for re-transmission by target tag void tag_raw_uid_to_data(BYTE *data, BYTE *uid, BYTE host_tagtype) { BYTE tmp[MAXUID + 1]; unsigned int i; switch(host_tagtype) { // EM4X05 sends everything LSB, so reverse data case TAG_TYPE_EM4X05: hextobinarray(tmp, uid); for(i= 0 ; i < HEXTOBITS(strlen(uid)) ; i += EM4X05_BLOCKSIZE) string_reverse(tmp + i, EM4X05_BLOCKSIZE); binarraytohex(data, tmp, HEXTOBITS(strlen(uid))); break; // for most tags a straight copy will do default: strcpy(data, uid); break; } }
// convert 32 hex digit/128 bit FDXB ID to 64 bit raw UID // safe to do in-place as we use a scratchpad BOOL hdx_hex_to_bin(BYTE *response, BYTE *fdxb) { BYTE i, crc_check[8], trailer[9]= {0,0,0,0,0,0,0,0,1}, tmp[128]; unsigned int crctag; hextobinarray(tmp, fdxb); // check header - should be 10 x 0x00 + 0x01 for(i= 0 ; i < 10 ; ++i) if(tmp[i] != 0x00) return FALSE; if(tmp[10] != 0x01) return FALSE; // check CRC // calculate crc for 64 bits of data (8 blocks of 8 plus obfuscation bit) for(i= 0 ; i < 8 ; ++i) crc_check[i]= (BYTE) binarraytoint(tmp + 11 + i * 9, 8); // stored crc (2 x 8 + 1) is at offset 83 (11 + 64 + 8) crctag= binarraytoint(tmp + 83, 8) << 8; crctag += binarraytoint(tmp + 92, 8); if (crctag != crc_ccitt(crc_check, 8)) return FALSE; // check trailer - '000000001' x 3 at offset 101 for(i= 0 ; i < 3 ; ++i) if(memcmp(tmp + 101 + i * 9, trailer, 9) != 0) return FALSE; // data is 8 blocks of 8 bits, plus obfuscation bit so check and strip every 9th bit for(i= 0 ; i < 8 ; ++i) { if(tmp[11 + ((i + 1) * 9) - 1] != 0x01) return FALSE; memcpy(response + i * 8, tmp + 11 + (i * 9), 8); } return TRUE; }