mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-15 01:33:00 -07:00
Redesign of lf hid card format handler as discussed with @marshmellow42
The new handler accepts multiple formats of the same length. Because of this, the existing pack/unpack commands are unsupported and have been removed and replaced with 'lf hid encode' and 'lf hid decode'. The decode command will test a packed Prox ID against all programmed formats and return results for all matching formats. The encode command takes the parameter of format name instead of bit length (as per the old pack command). Additionally, an 'lf hid write' command has been added as a single-command combination of encode and clone. To support easier addition of new formats, a library for handling card fields has been added. This will allow direct access to the card bits, to linear fields, and to non-linear (jumping) fields in a single line of code without having to resort to managing bit positions or masks on the underlying data. A number of new formats have been added as working examples of the new support functions.
This commit is contained in:
parent
18a3bf6119
commit
b5a5fc4d9f
7 changed files with 874 additions and 304 deletions
|
@ -28,223 +28,10 @@
|
|||
#include "cmdparser.h"
|
||||
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
||||
#include "lfdemod.h" // for HIDdemodFSK
|
||||
#include "parity.h" // for parity
|
||||
#include "hidcardformats.h"
|
||||
#include "hidcardformatutils.h"
|
||||
#include "util.h" // for param_get8,32,64
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
/**
|
||||
* Packs an HID ID from component parts.
|
||||
*
|
||||
* This only works with 26, 34, 35, 37, and 48 bit card IDs.
|
||||
*
|
||||
* Returns false on invalid inputs.
|
||||
*/
|
||||
bool pack_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const hid_info *info) {
|
||||
uint32_t higher = 0, high = 0, low = 0;
|
||||
|
||||
switch (info->fmtLen) {
|
||||
case 26: // HID H10301
|
||||
low |= (info->cardnum & 0xffff) << 1;
|
||||
low |= (info->fc & 0xff) << 17;
|
||||
|
||||
if (info->parityValid) {
|
||||
// Calculate parity
|
||||
low |= oddparity32((low >> 1) & 0xfff) & 1;
|
||||
low |= (evenparity32((low >> 13) & 0xfff) & 1) << 25;
|
||||
}
|
||||
break;
|
||||
|
||||
case 34: // H10306
|
||||
low |= (info->cardnum & 0xffff) << 1;
|
||||
low |= (info->fc & 0x7fff) << 17;
|
||||
high |= (info->fc & 0x8000) >> 15;
|
||||
|
||||
if (info->parityValid) {
|
||||
// Calculate parity
|
||||
high |= (evenparity32((high & 0x00000001) ^ (low & 0xFFFE0000)) & 1) << 1;
|
||||
low |= (oddparity32(low & 0x0001FFFE) & 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 35: // (Corporate 1000 35-bit)
|
||||
low |= (info->cardnum & 0xfffff) << 1;
|
||||
low |= (info->fc & 0x7ff) << 21;
|
||||
high |= (info->fc & 0x800) >> 11;
|
||||
|
||||
if (info->parityValid) {
|
||||
// Calculate parity
|
||||
high |= (evenparity32((high & 0x00000001) ^ (low & 0xB6DB6DB6)) & 1) << 1;
|
||||
low |= (oddparity32( (high & 0x00000003) ^ (low & 0x6DB6DB6C)) & 1);
|
||||
high |= (oddparity32( (high & 0x00000003) ^ (low & 0xFFFFFFFF)) & 1) << 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 37: //H10304
|
||||
low |= (info->cardnum & 0x7ffff) << 1;
|
||||
low |= (info->fc & 0xfff) << 20;
|
||||
high |= (info->fc & 0xf000) >> 12;
|
||||
|
||||
if (info->parityValid) {
|
||||
// Calculate parity
|
||||
high |= (evenparity32((high & 0x0000000F) ^ (low & 0xFFFC0000)) & 1) << 4;
|
||||
low |= (oddparity32(low & 0x0007FFFE) & 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 48: // Corporate 1000 48-bit
|
||||
low |= (info->cardnum & 0x7FFFFF) << 1;
|
||||
low |= (info->fc & 0xff) << 24;
|
||||
high |= (info->fc & 0x3FFF00) >> 8;
|
||||
|
||||
if (info->parityValid) {
|
||||
// Calculate parity
|
||||
high |= (evenparity32((high & 0x00001B6D) ^ (low & 0xB6DB6DB6)) & 1) << 14;
|
||||
low |= (oddparity32( (high & 0x000036DB) ^ (low & 0x6DB6DB6C)) & 1);
|
||||
high |= (oddparity32( (high & 0x00007FFF) ^ (low & 0xFFFFFFFF)) & 1) << 15;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Invalid / unsupported length
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the format length bits
|
||||
if (info->fmtLen < 37) {
|
||||
// Bit 37 is always set
|
||||
high |= 0x20;
|
||||
|
||||
// Set the bit corresponding to the length.
|
||||
if (info->fmtLen < 32)
|
||||
low |= 1 << info->fmtLen;
|
||||
else
|
||||
high |= 1 << (info->fmtLen - 32);
|
||||
|
||||
} else if (info->fmtLen > 37){
|
||||
if (info->fmtLen < 64)
|
||||
high |= 1 << (info->fmtLen - 32);
|
||||
else
|
||||
higher |= 1 << (info->fmtLen - 64);
|
||||
}
|
||||
// Return result only if successful.
|
||||
*hi2 = higher;
|
||||
*hi = high;
|
||||
*lo = low;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpacks an HID ID into its component parts.
|
||||
*
|
||||
* This only works with 26, 34, 35, 37, and 48 bit card IDs.
|
||||
*
|
||||
* Returns false on invalid inputs.
|
||||
*/
|
||||
bool unpack_hid(hid_info *out, uint32_t hi2, uint32_t hi, uint32_t lo) {
|
||||
memset(out, 0, sizeof(hid_info));
|
||||
uint8_t fmtLen = 0;
|
||||
|
||||
uint32_t hFmt; // for calculating card length
|
||||
if ((hi2 & 0x000FFFFF) > 0) { // > 64 bits
|
||||
hFmt = hi2 & 0x000FFFFF;
|
||||
fmtLen = 64;
|
||||
} else if ((hi & 0xFFFFFFC0) > 0) { // < 63-38 bits
|
||||
hFmt = hi & 0xFFFFFFC0;
|
||||
fmtLen = 32;
|
||||
} else if ((hi & 0x00000020) == 0) { // 37 bits
|
||||
hFmt = 0;
|
||||
fmtLen = 37;
|
||||
} else if ((hi & 0x0000001F) > 0){ // 36-32 bits
|
||||
hFmt = hi & 0x0000001F;
|
||||
fmtLen = 32;
|
||||
} else { // <32 bits
|
||||
hFmt = lo;
|
||||
fmtLen = 0;
|
||||
}
|
||||
|
||||
while (hFmt > 1) {
|
||||
hFmt >>= 1;
|
||||
fmtLen++;
|
||||
}
|
||||
out->fmtLen = fmtLen;
|
||||
switch (out->fmtLen) {
|
||||
case 26: // HID H10301
|
||||
out->cardnum = (lo >> 1) & 0xFFFF;
|
||||
out->fc = (lo >> 17) & 0xFF;
|
||||
|
||||
if (g_debugMode) {
|
||||
PrintAndLog("oddparity : input=%x, calculated=%d, provided=%d",
|
||||
(lo >> 1) & 0xFFF, oddparity32((lo >> 1) & 0xFFF), lo & 1);
|
||||
PrintAndLog("evenparity: input=%x, calculated=%d, provided=%d",
|
||||
(lo >> 13) & 0xFFF, evenparity32((lo >> 13) & 0xFFF) & 1, (lo >> 25) & 1);
|
||||
}
|
||||
|
||||
out->parityValid =
|
||||
(oddparity32((lo >> 1) & 0xFFF) == (lo & 1)) &&
|
||||
((evenparity32((lo >> 13) & 0xFFF) & 1) == ((lo >> 25) & 1));
|
||||
break;
|
||||
|
||||
case 34: // HID H10306
|
||||
out->cardnum = (lo >> 1) & 0xFFFF;
|
||||
out->fc = ((hi & 1) << 15) | (lo >> 17);
|
||||
out->parityValid =
|
||||
((evenparity32((hi & 0x00000001) ^ (lo & 0xFFFE0000)) & 1) == ((hi >> 1) & 1)) &&
|
||||
((oddparity32(lo & 0x0001FFFE) & 1) == ((lo & 1)));
|
||||
break;
|
||||
|
||||
case 35: // HID Corporate 1000-35
|
||||
out->cardnum = (lo >> 1) & 0xFFFFF;
|
||||
out->fc = ((hi & 1) << 11) | (lo >> 21);
|
||||
out->parityValid =
|
||||
(evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)) == ((hi >> 1) & 1)) &&
|
||||
(oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) &&
|
||||
(oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)) == ((hi >> 2) & 1));
|
||||
if (g_debugMode) {
|
||||
PrintAndLog("Parity check: calculated {%d, %d, %d}, provided {%d, %d, %d}",
|
||||
evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)),
|
||||
oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)),
|
||||
oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)),
|
||||
((hi >> 1) & 1),
|
||||
((lo >> 0) & 1),
|
||||
((hi >> 2) & 1)
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 37: // HID H10304
|
||||
out->fmtLen = 37;
|
||||
out->cardnum = (lo >> 1) & 0x7FFFF;
|
||||
out->fc = ((hi & 0xF) << 12) | (lo >> 20);
|
||||
out->parityValid =
|
||||
(evenparity32((hi & 0x0000000F) ^ (lo & 0xFFFC0000)) == ((hi >> 4) & 1)) &&
|
||||
(oddparity32( lo & 0x0007FFFE) == (lo & 1));
|
||||
break;
|
||||
|
||||
case 48: // HID Corporate 1000-48
|
||||
out->cardnum = (lo >> 1) & 0x7FFFFF; //Start 24, 23 length
|
||||
out->fc = ((hi & 0x3FFF) << 8 ) | (lo >> 24); //Start 2, 22 length
|
||||
out->parityValid =
|
||||
(evenparity32((hi & 0x00001B6D) ^ (lo & 0xB6DB6DB6)) == ((hi >> 14) & 1)) &&
|
||||
(oddparity32( (hi & 0x000036DB) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) &&
|
||||
(oddparity32( (hi & 0x00007FFF) ^ (lo & 0xFFFFFFFF)) == ((hi >> 15) & 1));
|
||||
if (g_debugMode) {
|
||||
PrintAndLog("Parity check: calculated {%d, %d, %d}, provided {%d, %d, %d}",
|
||||
evenparity32((hi & 0x00001B6D) ^ (lo & 0xB6DB6DB6)),
|
||||
oddparity32( (hi & 0x000036DB) ^ (lo & 0x6DB6DB6C)),
|
||||
oddparity32( (hi & 0x00007FFF) ^ (lo & 0xFFFFFFFF)),
|
||||
((hi >> 14) & 1),
|
||||
((lo >> 0) & 1),
|
||||
((hi >> 15) & 1)
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hex string to component "hi2", "hi" and "lo" 32-bit integers, one nibble
|
||||
|
@ -301,21 +88,18 @@ int CmdFSKdemodHID(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
hid_info card_info;
|
||||
bool ret = unpack_hid(&card_info, (uint32_t)hi2, (uint32_t)hi, (uint32_t)lo);
|
||||
|
||||
if (hi2 != 0)
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x%08x",
|
||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo
|
||||
);
|
||||
else
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x",
|
||||
(unsigned int) hi, (unsigned int) lo
|
||||
);
|
||||
|
||||
hidproxmessage_t packed = initialize_proxmessage_object(hi2, hi, lo);
|
||||
bool ret = HIDTryUnpack(&packed);
|
||||
|
||||
if (card_info.fmtLen == 26 || card_info.fmtLen == 35 || card_info.fmtLen == 48) {
|
||||
PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
|
||||
}
|
||||
if (!ret) {
|
||||
PrintAndLog("Invalid or unsupported tag length.");
|
||||
}
|
||||
|
@ -370,7 +154,7 @@ int CmdHIDClone(const char *Cmd)
|
|||
}
|
||||
|
||||
c.cmd = CMD_HID_CLONE_TAG;
|
||||
c.arg[0] = hi2;
|
||||
c.arg[0] = (hi2 & 0x000FFFFF);
|
||||
c.arg[1] = hi;
|
||||
c.arg[2] = lo;
|
||||
|
||||
|
@ -378,73 +162,118 @@ int CmdHIDClone(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHIDPack(const char *Cmd) {
|
||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||
|
||||
int CmdHIDDecode(const char *Cmd){
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: lf hid pack <length> <facility code (decimal)> <card number (decimal)>");
|
||||
PrintAndLog(" sample: lf hid pack 26 123 4567");
|
||||
PrintAndLog("Usage: lf hid decode <id>");
|
||||
PrintAndLog(" sample: lf hid decode 2006f623ae");
|
||||
return 0;
|
||||
}
|
||||
uint8_t fmtLen = param_get8(Cmd, 0);
|
||||
|
||||
hid_info card_info;
|
||||
card_info.fmtLen = fmtLen;
|
||||
card_info.fc = param_get32ex(Cmd, 1, 0, 10);
|
||||
card_info.cardnum = param_get64ex(Cmd, 2, 0, 10);
|
||||
card_info.parityValid = true;
|
||||
uint32_t top = 0, mid = 0, bot = 0;
|
||||
hexstring_to_int96(&top, &mid, &bot, Cmd);
|
||||
hidproxmessage_t packed = initialize_proxmessage_object(top, mid, bot);
|
||||
HIDTryUnpack(&packed);
|
||||
return 0;
|
||||
}
|
||||
int CmdHIDEncode(const char *Cmd) {
|
||||
if (strlen(Cmd) == 0) {
|
||||
PrintAndLog("Usage: lf hid encode <format> <facility code (decimal)> <card number (decimal)>");
|
||||
PrintAndLog(" sample: lf hid encode H10301 123 4567");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ret = pack_hid(&hi2, &hi, &lo, &card_info);
|
||||
if (ret) {
|
||||
if (hi2 != 0) {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
int formatIndex = -1;
|
||||
if (!strcmp(Cmd, "help") || !strcmp(Cmd, "h") || !strcmp(Cmd, "list") || !strcmp(Cmd, "?")){
|
||||
HIDListFormats();
|
||||
return 0;
|
||||
} else {
|
||||
char format[16];
|
||||
memset(format, 0, sizeof(format));
|
||||
param_getstr(Cmd, 0, format, sizeof(format));
|
||||
formatIndex = HIDFindCardFormat(format);
|
||||
if (formatIndex == -1) {
|
||||
HIDListFormats();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hidproxcard_t card;
|
||||
memset(&card, 0, sizeof(hidproxcard_t));
|
||||
card.FacilityCode = param_get32ex(Cmd, 1, 0, 10);
|
||||
card.CardNumber = param_get64ex(Cmd, 2, 0, 10);
|
||||
card.ParitySupported = true; // Try to encode parity if supported.
|
||||
|
||||
hidproxmessage_t packed;
|
||||
memset(&packed, 0, sizeof(hidproxmessage_t));
|
||||
if (HIDPack(formatIndex, &card, &packed)){
|
||||
if (packed.top != 0) {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x%08x",
|
||||
(unsigned int)packed.top, (unsigned int)packed.mid, (unsigned int)packed.bot);
|
||||
} else {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x",
|
||||
(unsigned int)packed.mid, (unsigned int)packed.bot);
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Invalid or unsupported tag length.");
|
||||
PrintAndLog("The provided data could not be encoded with the selected format.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHIDUnpack(const char *Cmd)
|
||||
{
|
||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||
if (strlen(Cmd)<1) {
|
||||
PrintAndLog("Usage: lf hid unpack <ID>");
|
||||
PrintAndLog(" sample: lf hid unpack 2006f623ae");
|
||||
int CmdHIDWrite(const char *Cmd) {
|
||||
if (strlen(Cmd) == 0) {
|
||||
PrintAndLog("Usage: lf hid write <format> <facility code (decimal)> <card number (decimal)>");
|
||||
PrintAndLog(" sample: lf hid write H10301 123 4567");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hexstring_to_int96(&hi2, &hi, &lo, Cmd);
|
||||
|
||||
hid_info card_info;
|
||||
bool ret = unpack_hid(&card_info, hi2, hi, lo);
|
||||
|
||||
if (hi2 != 0) {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
int formatIndex = -1;
|
||||
if (!strcmp(Cmd, "help") || !strcmp(Cmd, "h") || !strcmp(Cmd, "list") || !strcmp(Cmd, "?")){
|
||||
HIDListFormats();
|
||||
return 0;
|
||||
} else {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
char format[16];
|
||||
memset(format, 0, sizeof(format));
|
||||
param_getstr(Cmd, 0, format, sizeof(format));
|
||||
formatIndex = HIDFindCardFormat(format);
|
||||
if (formatIndex == -1) {
|
||||
HIDListFormats();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
|
||||
|
||||
if (!ret) {
|
||||
PrintAndLog("Invalid or unsupported tag length.");
|
||||
|
||||
hidproxcard_t card;
|
||||
memset(&card, 0, sizeof(hidproxcard_t));
|
||||
card.FacilityCode = param_get32ex(Cmd, 1, 0, 10);
|
||||
card.CardNumber = param_get64ex(Cmd, 2, 0, 10);
|
||||
card.ParitySupported = true; // Try to encode parity if supported.
|
||||
|
||||
hidproxmessage_t packed;
|
||||
memset(&packed, 0, sizeof(hidproxmessage_t));
|
||||
if (HIDPack(formatIndex, &card, &packed)){
|
||||
UsbCommand c;
|
||||
if (packed.top != 0) {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x%08x",
|
||||
(unsigned int)packed.top, (unsigned int)packed.mid, (unsigned int)packed.bot);
|
||||
c.d.asBytes[0] = 1;
|
||||
} else {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x",
|
||||
(unsigned int)packed.mid, (unsigned int)packed.bot);
|
||||
c.d.asBytes[0] = 0;
|
||||
}
|
||||
|
||||
c.cmd = CMD_HID_CLONE_TAG;
|
||||
c.arg[0] = (packed.top & 0x000FFFFF);
|
||||
c.arg[1] = packed.mid;
|
||||
c.arg[2] = packed.bot;
|
||||
SendCommand(&c);
|
||||
|
||||
} else {
|
||||
PrintAndLog("The provided data could not be encoded with the selected format.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int CmdHelp(const char *Cmd); // define this now so the below won't error out.
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
|
@ -452,8 +281,9 @@ static command_t CommandTable[] =
|
|||
{"read", CmdHIDReadFSK, 0, "['1'] Realtime HID FSK Read from antenna (option '1' for one tag only)"},
|
||||
{"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
|
||||
{"clone", CmdHIDClone, 0, "<ID> -- Clone HID to T55x7 (tag must be in antenna)"},
|
||||
{"pack", CmdHIDPack, 1, "<len> <fc> <num> -- packs an HID ID from its length, facility code and card number"},
|
||||
{"unpack", CmdHIDUnpack, 1, "<ID> -- unpacks an HID ID to its length, facility code and card number"},
|
||||
{"decode", CmdHIDDecode, 1, "<ID> -- Try to decode an HID tag and show its contents"},
|
||||
{"encode", CmdHIDEncode, 1, "<format> <fc> <num> -- Encode an HID ID with the specified format, facility code and card number"},
|
||||
{"write", CmdHIDWrite, 0, "<format> <fc> <num> -- Encode and write to a T55x7 tag (tag must be in antenna)"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue