Skip to content

Commit

Permalink
Q5 PWM sniff decoder. HEX files now include Indala CRC.
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamLaurie committed Jul 9, 2015
1 parent fc80e73 commit 02abc5c
Show file tree
Hide file tree
Showing 9 changed files with 31,670 additions and 31,053 deletions.
29,093 changes: 14,652 additions & 14,441 deletions firmware/Pic32/RFIDler.X/dist/debug/production/RFIDler.X.production.hex

Large diffs are not rendered by default.

3,939 changes: 1,993 additions & 1,946 deletions firmware/Pic32/RFIDler.X/dist/debug/production/production.map

Large diffs are not rendered by default.

29,471 changes: 14,843 additions & 14,628 deletions firmware/Pic32/RFIDler.X/dist/default/production/RFIDler.X.production.hex

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions firmware/Pic32/RFIDler.X/include/q5.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@

#define Q5_SOFT_RESET "00" // reset (test mode)
#define Q5_DIRECT_ACCESS "10" // direct read in pwd or non-pwd mode
#define Q5_STD_WRITE_P0 "10" // write page 0
#define Q5_STD_WRITE_P1 "11" // write page 1
#define Q5_WRITE_P0 "10" // write page 0
#define Q5_WRITE_P1 "11" // write page 1
#define Q5_GET_TRACE_DATA "11" // get 64 bits tracebility data
#define Q5_AOR "10" // Answer On Request (wakeup)
#define Q5_MODULATION_DEFEAT "00011" // tell tag to go quiet
Expand All @@ -155,6 +155,9 @@

// config blocks
#define Q5_DEFAULT_CONFIG_BLOCK "E601F004" // q5 native mode (also em4x02/unique)
#define Q5_PWD_CONIG_BLOCK "E601F404" // q5 native mode with PWD enabled
#define Q5_AOR_CONIG_BLOCK "E601F804" // q5 native mode with AOR enabled
#define Q5_PWD_AOR_CONIG_BLOCK "E601FC04" // q5 native mode with PWD and AOR enabled
#define Q5_FDXB_CONFIG_BLOCK "E600F0E8" // emulate fdx-b
#define Q5_HID_26_CONFIG_BLOCK "E6018056" // hid 26 bit
#define Q5_INDALA_64_CONFIG_BLOCK "E600F014" // emulate indala 64 bit
Expand Down
168 changes: 148 additions & 20 deletions firmware/Pic32/RFIDler.X/src/q5.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ BOOL q5_send_command(BYTE *response, BYTE *command, BYTE length, BOOL reset, BOO
// send command
if(!rwd_send(command, length, reset, BLOCK, RWD_STATE_START_SEND, RFIDlerConfig.FrameClock, Q5_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))
return FALSE;

if(!response_length)
return TRUE;

Expand Down Expand Up @@ -216,9 +216,9 @@ BOOL q5_read_block(BYTE *response, BYTE block)
memcpy(tmp, Q5_DIRECT_ACCESS, 2);
if(PWD_Mode)
{
tmp[2]= '1';
hextobinstring(tmp + 3, Password);
inttobinstring(tmp + 34, (unsigned int) block, 3);
hextobinstring(tmp + 2, Password);
tmp[34]= '0';
inttobinstring(tmp + 35, (unsigned int) block, 3);
}
else
{
Expand All @@ -233,8 +233,6 @@ BOOL q5_read_block(BYTE *response, BYTE block)
//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;
Expand All @@ -252,7 +250,7 @@ BOOL q5_write_block(BYTE block, BYTE *data, BOOL lock, BOOL verify)
memset(tmp, '\0', sizeof(tmp));

// command
memcpy(tmp, Q5_STD_WRITE_P0, 2);
memcpy(tmp, Q5_WRITE_P0, 2);
p= 2;

// password
Expand Down Expand Up @@ -296,7 +294,7 @@ BOOL q5_write_block(BYTE block, BYTE *data, BOOL lock, BOOL verify)
// set password and mode, and return UID
BOOL q5_login(BYTE *response, BYTE *pass)
{
BYTE tmp[35];
BYTE tmp[36];

// check we need password - if we can get UID without, then we don't
if(q5_get_uid(tmp))
Expand All @@ -310,7 +308,7 @@ BOOL q5_login(BYTE *response, BYTE *pass)
tmp[34]= '\0';

// send password
if (!q5_send_command(response, tmp, strlen(tmp), RESET, NO_SYNC, 0))
if (!q5_send_command(NULL, tmp, strlen(tmp), NO_RESET, NO_SYNC, 0))
return FALSE;

// see if we can now get UID
Expand Down Expand Up @@ -502,22 +500,152 @@ BOOL q5_emulate_config_block(BYTE *config, BYTE target_tagtype)
// decode externally sniffed PWM
BOOL q5_decode_pwm(unsigned long pulses[], unsigned long gaps[], unsigned int count)
{
unsigned int i, j;
BOOL decoded= FALSE;
BYTE out[65]; // max response from hitag2 is 64 bits
unsigned int i;
BOOL decoded= FALSE, sequence;
static BOOL pwd= FALSE;
BYTE tmp[4], out[71], *p; // max response from q5 is 70 bits

j= 0;
while(j < count)
i= 0;
while(i < count)
{
i= generic_decode_pwm(out, &pulses[j], 10, 512, &gaps[j], 20, 500, count - j);
if(i)
// we can't use generic_decode_pwm as Q5 commands may be all 0 or all 1
for(p= out, sequence= FALSE ; i < count ; ++i)
if(gaps[i] >= 100 && gaps[i] <= 512)
{
if(pulses[i] <= 512)
{
if(approx(pulses[i], 128, 20))
*(p++)= '0';
else
*(p++)= '1';
sequence= TRUE;
}
else
{
++i;
break;
}
}
*p= '\0';

if(sequence)
{
// there are only 7 message sizes, so decode accordingly
switch(strlen(out))
{
// GET Trace Data (UID)) or RESET
case 2:
if(memcmp(out, Q5_GET_TRACE_DATA, 2) == 0)
UserMessage("\r\n%s, GET_TRACE_DATA", out);
else
if(memcmp(out, Q5_SOFT_RESET, 2) == 0)
UserMessage("\r\n%s, RESET", out);
else
UserMessage("\r\n%s, ?INVALID?", out);
break;

// modulation defeat
case 5:
if(memcmp(out, Q5_MODULATION_DEFEAT, 5) == 0)
UserMessage("\r\n%s, MODULATION_DEFEAT", out);
else
UserMessage("\r\n%s, ?INVALID?", out);
break;

// read
case 6:
if(memcmp(out, Q5_DIRECT_ACCESS, 2) == 0)
UserMessage("\r\n%s, DIRECT_ACCESS:", out);
else
{
UserMessage("\r\n%s, ?INVALID?", out);
break;
}
// PWD mode (should be 0))
UserMessage("%0.1s:", out + 2);
// ADDRESS
binstringtohex(tmp, out + 3);
UserMessage("%0.2s", tmp);
pwd= FALSE;
break;

// login (AOR followed by PWD)
case 34:
if(memcmp(out, Q5_AOR, 2) == 0)
UserMessage("\r\n%s, AOR:", out);
else
{
UserMessage("\r\n%s, ?INVALID?", out);
break;
}
// PWD
binstringtohex(tmp, out + 2);
UserMessage("%0.8s", tmp);
pwd= TRUE;
break;

// PWD read/ STD write
// note the only way to tell these apart is by knowing we are in PWD mode
case 38:
if(pwd && memcmp(out, Q5_DIRECT_ACCESS, 2) == 0)
{
UserMessage("\r\n%s, PWD_DIRECT_ACCESS:", out);
// PWD
binstringtohex(tmp, out + 2);
UserMessage("%0.8s:", tmp);
// Lock BIT
UserMessage("%0.1s:", out + 34);
// ADDRESS
binstringtohex(tmp, out + 35);
UserMessage("%0.1s", tmp);
break;
}

if(!pwd && memcmp(out, Q5_WRITE_P0, 2) == 0)
UserMessage("\r\n%s, WRITE_P0:", out);
else
{
UserMessage("\r\n%s, ?INVALID?", out);
break;
}
// Lock BIT
UserMessage("%0.1s:", out + 2);
// DATA
binstringtohex(tmp, out + 3);
UserMessage("%0.8s:", tmp);
// ADDRESS
binstringtohex(tmp, out + 35);
UserMessage("%0.1s", tmp);
break;

// PWD write
case 70:
if(memcmp(out, Q5_WRITE_P0, 2) == 0)
UserMessage("\r\n%s, PWD_WRITE_P0:", out);
else
{
UserMessage("\r\n%s, ?INVALID?", out);
break;
}
// PWD
binstringtohex(tmp, out + 2);
UserMessage("%0.8s:", tmp);
// Lock BIT
UserMessage("%0.1s:", out + 34);
// DATA
binstringtohex(tmp, out + 35);
UserMessage("%0.8s:", tmp);
// ADDRESS
binstringtohex(tmp, out + 67);
UserMessage("%0.1s", tmp);
pwd= TRUE;
break;

default:
UserMessage("\r\n%s, ?INVALID?", out);
}
decoded= TRUE;
UserMessage("\r\n%s", out);
j += i;
}
else
break;
}

UserMessage("%s", "\r\n");
Expand Down
3 changes: 2 additions & 1 deletion firmware/Pic32/RFIDler.X/src/rwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
#include "HardwareProfile.h"
#include "rfidler.h"
#include "rwd.h"
#include "util.h"

// set default parameters for RWD PWM commands
void rwd_set_pwm(unsigned long fc, unsigned long sleep, unsigned int wake, unsigned int pw0, unsigned int pw1, unsigned int gap, unsigned int wait_txrx, unsigned int wait_rxtx)
Expand Down Expand Up @@ -175,7 +176,7 @@ BOOL rwd_send(unsigned char *command, unsigned int length, BOOL reset, BOOL bloc
}
else
memcpy(RWD_Command_Buff, command, length);

RWD_Command_Buff[length]= '*';
RWD_Command_ThisBit= RWD_Command_Buff;

Expand Down
4 changes: 3 additions & 1 deletion firmware/Pic32/RFIDler.X/src/sniff.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
#include "util.h"

// watch external clock for PWM messages
// specify minimum gap to look for in us
// specify minimum gap to look for in uS
void sniff_pwm(unsigned int min)
{
BOOL toggle;
Expand Down Expand Up @@ -199,6 +199,7 @@ void sniff_pwm(unsigned int min)
decode_pwm(pulses, gaps, i);
}

// values are in uS
void decode_pwm(unsigned long pulses[], unsigned long gaps[], unsigned int count)
{
unsigned int i;
Expand Down Expand Up @@ -235,6 +236,7 @@ void decode_pwm(unsigned long pulses[], unsigned long gaps[], unsigned int count

// convert pwm array to human readable binary
// terminates at end of first sequence and returns number of samples processed
// pulse widths in uS
BYTE generic_decode_pwm(BYTE *result, unsigned long pulses[], unsigned int minpulse, unsigned int maxpulse, unsigned long gaps[], unsigned int mingap, unsigned int maxgap, unsigned int count)
{
unsigned int one, zero, i;
Expand Down
1 change: 1 addition & 0 deletions firmware/Pic32/RFIDler.X/src/tags.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ BOOL tag_set(BYTE tag)
RFIDlerConfig.RWD_One_Period= 48; //54; // 54 nominal, 48 - 63 normal, 24 - 31 fast write mode
RFIDlerConfig.RWD_Wait_Switch_TX_RX= 48; //64; // q5 will exit downlink mode after 64 but may not yet be damped!
RFIDlerConfig.RWD_Wait_Switch_RX_TX= 192; // the longer the better!
PWD_Mode= FALSE;
break;

case TAG_TYPE_T55X7:
Expand Down
37 changes: 23 additions & 14 deletions firmware/Pic32/RFIDler.X/src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,20 +419,24 @@ unsigned int hextobinstring(unsigned char *target, unsigned char *source)
// return number of bits converted
unsigned int binarraytohex(unsigned char *target, unsigned char *source, unsigned int length)
{
unsigned char i, x;
unsigned char i, x, shift;
unsigned int j= length;

if(j % 4)
return 0;
// disabled this test as we get a lot of funny sized binary strings we need to convert!
//if(j % 4)
// return 0;
if(length <= 4)
shift= length;
else
shift= 4;

while(j)
{
for(i= x= 0 ; i < 4 ; ++i)
x += (source[i] << (3 - i));
for(i= x= 0 ; i < 4 ; ++i, --j)
x += (source[i] << ((shift - 1) - i));
sprintf(target,"%X", x);
++target;
source += 4;
j -= 4;
source += i;
}

return length;
Expand All @@ -449,21 +453,26 @@ void hexprintbinarray(BYTE *bin, unsigned int length)
// return number of bits converted
unsigned int binstringtohex(unsigned char *target, unsigned char *source)
{
unsigned char i, x;
unsigned char i, x, shift;
unsigned int j, length;

length= j= strlen(source);
if(j % 4)
return 0;
if(length <= 4)
shift= length;
else
shift= 4;

// disabled this check as we need to convert odd binary string lengths
//if(j % 4)
// return 0;

while(j)
{
for(i= x= 0 ; i < 4 ; ++i)
x += ((source[i] - '0') << (3 - i));
for(i= x= 0 ; i < 4 && source[i] != '\0'; ++i, --j)
x += ((source[i] - '0') << ((shift - 1) - i));
sprintf(target,"%X", x);
++target;
source += 4;
j -= 4;
source += i;
}

return length;
Expand Down

0 comments on commit 02abc5c

Please sign in to comment.