mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-19 12:59:44 -07:00
Merge pull request #216 from marshmellow42/master
EM4x05/EM4x69 command rewrite and improvements
This commit is contained in:
commit
2d0717853d
17 changed files with 748 additions and 184 deletions
|
@ -5,6 +5,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- Added EM4x05/EM4x69 chip detection to lf search (marshmellow)
|
||||||
|
- Added lf em 4x05dump command to read and output all the blocks of the chip (marshmellow)
|
||||||
|
- Added lf em 4x05info command to read and display information about the chip (marshmellow)
|
||||||
- Added lf cotag read, and added it to lf search (iceman)
|
- Added lf cotag read, and added it to lf search (iceman)
|
||||||
- Added hitag2 read UID only and added that to lf search (marshmellow)
|
- Added hitag2 read UID only and added that to lf search (marshmellow)
|
||||||
- Added lf pyramid commands (iceman)
|
- Added lf pyramid commands (iceman)
|
||||||
|
@ -38,6 +41,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Added option c to 'hf list' (mark CRC bytes) (piwi)
|
- Added option c to 'hf list' (mark CRC bytes) (piwi)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- small changes to lf psk and fsk demods to improve results when the trace begins with noise or the chip isn't broadcasting yet (marshmellow)
|
||||||
|
- NOTE CHANGED ALL `lf em4x em*` cmds to simpler `lf em ` - example: `lf em4x em410xdemod` is now `lf em 410xdemod`
|
||||||
|
- Renamed and rebuilt `lf em readword` && readwordpwd to `lf em 4x05readword` - it now demods and outputs the read block (marshmellow/iceman)
|
||||||
|
- Renamed and rebuilt `lf em writeword` && writewordpwd to `lf em 4x05writeword` - it now also reads validation output from the tag (marshmellow/iceman)
|
||||||
- Fixed bug in lf sim and continuous demods not turning off antenna when finished
|
- Fixed bug in lf sim and continuous demods not turning off antenna when finished
|
||||||
- Fixed bug(s) in hf iclass write
|
- Fixed bug(s) in hf iclass write
|
||||||
- Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
|
- Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
|
||||||
|
|
|
@ -1017,10 +1017,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
WritePCF7931(c->d.asBytes[0],c->d.asBytes[1],c->d.asBytes[2],c->d.asBytes[3],c->d.asBytes[4],c->d.asBytes[5],c->d.asBytes[6], c->d.asBytes[9], c->d.asBytes[7]-128,c->d.asBytes[8]-128, c->arg[0], c->arg[1], c->arg[2]);
|
WritePCF7931(c->d.asBytes[0],c->d.asBytes[1],c->d.asBytes[2],c->d.asBytes[3],c->d.asBytes[4],c->d.asBytes[5],c->d.asBytes[6], c->d.asBytes[9], c->d.asBytes[7]-128,c->d.asBytes[8]-128, c->arg[0], c->arg[1], c->arg[2]);
|
||||||
break;
|
break;
|
||||||
case CMD_EM4X_READ_WORD:
|
case CMD_EM4X_READ_WORD:
|
||||||
EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]);
|
EM4xReadWord(c->arg[0], c->arg[1],c->arg[2]);
|
||||||
break;
|
break;
|
||||||
case CMD_EM4X_WRITE_WORD:
|
case CMD_EM4X_WRITE_WORD:
|
||||||
EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
|
EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2]);
|
||||||
break;
|
break;
|
||||||
case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
|
case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
|
||||||
CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
|
CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
|
||||||
|
|
|
@ -88,7 +88,7 @@ void T55xxWakeUp(uint32_t Pwd);
|
||||||
void TurnReadLFOn();
|
void TurnReadLFOn();
|
||||||
//void T55xxReadTrace(void);
|
//void T55xxReadTrace(void);
|
||||||
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
||||||
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd);
|
||||||
void Cotag(uint32_t arg0);
|
void Cotag(uint32_t arg0);
|
||||||
|
|
||||||
/// iso14443.h
|
/// iso14443.h
|
||||||
|
|
|
@ -684,7 +684,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
|
||||||
for (i=0; i<size; i++){
|
for (i=0; i<size; i++){
|
||||||
askSimBit(BitStream[i]^invert, &n, clk, encoding);
|
askSimBit(BitStream[i]^invert, &n, clk, encoding);
|
||||||
}
|
}
|
||||||
if (encoding==0 && BitStream[0]==BitStream[size-1]){ //run a second set inverted (for biphase phase)
|
if (encoding==0 && BitStream[0]==BitStream[size-1]){ //run a second set inverted (for ask/raw || biphase phase)
|
||||||
for (i=0; i<size; i++){
|
for (i=0; i<size; i++){
|
||||||
askSimBit(BitStream[i]^invert^1, &n, clk, encoding);
|
askSimBit(BitStream[i]^invert^1, &n, clk, encoding);
|
||||||
}
|
}
|
||||||
|
@ -1358,7 +1358,7 @@ void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t
|
||||||
//Config for Indala (RF/32;PSK1 with RF/2;Maxblock=7)
|
//Config for Indala (RF/32;PSK1 with RF/2;Maxblock=7)
|
||||||
data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (7 << T55x7_MAXBLOCK_SHIFT);
|
data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (7 << T55x7_MAXBLOCK_SHIFT);
|
||||||
//TODO add selection of chip for Q5 or T55x7
|
//TODO add selection of chip for Q5 or T55x7
|
||||||
// data[0] = (((32-2)/2)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK1 | 7 << T5555_MAXBLOCK_SHIFT;
|
// data[0] = (((32-2)>>1)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK1 | 7 << T5555_MAXBLOCK_SHIFT;
|
||||||
WriteT55xx(data, 0, 8);
|
WriteT55xx(data, 0, 8);
|
||||||
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=7;Inverse data)
|
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=7;Inverse data)
|
||||||
// T5567WriteBlock(0x603E10E2,0);
|
// T5567WriteBlock(0x603E10E2,0);
|
||||||
|
@ -1367,7 +1367,7 @@ void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t
|
||||||
// clone viking tag to T55xx
|
// clone viking tag to T55xx
|
||||||
void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5) {
|
void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5) {
|
||||||
uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), block1, block2};
|
uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), block1, block2};
|
||||||
if (Q5) data[0] = (32 << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT;
|
if (Q5) data[0] = ( ((32-2)>>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT;
|
||||||
// Program the data blocks for supplied ID and the block 0 config
|
// Program the data blocks for supplied ID and the block 0 config
|
||||||
WriteT55xx(data, 0, 3);
|
WriteT55xx(data, 0, 3);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
@ -1571,8 +1571,6 @@ void SendForward(uint8_t fwd_bit_count) {
|
||||||
fwd_write_ptr = forwardLink_data;
|
fwd_write_ptr = forwardLink_data;
|
||||||
fwd_bit_sz = fwd_bit_count;
|
fwd_bit_sz = fwd_bit_count;
|
||||||
|
|
||||||
LED_D_ON();
|
|
||||||
|
|
||||||
// Set up FPGA, 125kHz
|
// Set up FPGA, 125kHz
|
||||||
LFSetupFPGAForADC(95, true);
|
LFSetupFPGAForADC(95, true);
|
||||||
|
|
||||||
|
@ -1580,9 +1578,9 @@ void SendForward(uint8_t fwd_bit_count) {
|
||||||
fwd_bit_sz--; //prepare next bit modulation
|
fwd_bit_sz--; //prepare next bit modulation
|
||||||
fwd_write_ptr++;
|
fwd_write_ptr++;
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
SpinDelayUs(55*8); //55 cycles off (8us each)for 4305
|
SpinDelayUs(56*8); //55 cycles off (8us each)for 4305 /another reader has 37 here...
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
|
||||||
SpinDelayUs(16*8); //16 cycles on (8us each)
|
SpinDelayUs(18*8); //16 cycles on (8us each) // another reader has 18 here
|
||||||
|
|
||||||
// now start writting
|
// now start writting
|
||||||
while(fwd_bit_sz-- > 0) { //prepare next bit modulation
|
while(fwd_bit_sz-- > 0) { //prepare next bit modulation
|
||||||
|
@ -1591,9 +1589,9 @@ void SendForward(uint8_t fwd_bit_count) {
|
||||||
else {
|
else {
|
||||||
//These timings work for 4469/4269/4305 (with the 55*8 above)
|
//These timings work for 4469/4269/4305 (with the 55*8 above)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
SpinDelayUs(23*8); //16-4 cycles off (8us each)
|
SpinDelayUs(23*8); //16-4 cycles off (8us each) //23 //one reader goes as high as 25 here
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
|
||||||
SpinDelayUs(9*8); //16 cycles on (8us each)
|
SpinDelayUs(16*8); //16 cycles on (8us each) //9 // another reader goes to 17 here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1615,13 +1613,11 @@ void EM4xLogin(uint32_t Password) {
|
||||||
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
||||||
|
|
||||||
uint8_t fwd_bit_count;
|
uint8_t fwd_bit_count;
|
||||||
uint8_t *dest = BigBuf_get_addr();
|
|
||||||
uint16_t bufferlength = BigBuf_max_traceLen();
|
|
||||||
uint32_t i = 0;
|
|
||||||
|
|
||||||
// Clear destination buffer before sending the command
|
// Clear destination buffer before sending the command
|
||||||
BigBuf_Clear_ext(false);
|
BigBuf_Clear_ext(false);
|
||||||
|
|
||||||
|
LED_A_ON();
|
||||||
//If password mode do login
|
//If password mode do login
|
||||||
if (PwdMode == 1) EM4xLogin(Pwd);
|
if (PwdMode == 1) EM4xLogin(Pwd);
|
||||||
|
|
||||||
|
@ -1629,36 +1625,28 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
||||||
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
|
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
|
||||||
fwd_bit_count += Prepare_Addr( Address );
|
fwd_bit_count += Prepare_Addr( Address );
|
||||||
|
|
||||||
// Connect the A/D to the peak-detected low-frequency path.
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
|
||||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
|
||||||
FpgaSetupSsc();
|
|
||||||
|
|
||||||
SendForward(fwd_bit_count);
|
SendForward(fwd_bit_count);
|
||||||
|
SpinDelayUs(400);
|
||||||
// Now do the acquisition
|
// Now do the acquisition
|
||||||
i = 0;
|
DoPartialAcquisition(20, true, 6000);
|
||||||
for(;;) {
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
|
||||||
}
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
|
||||||
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
i++;
|
|
||||||
if (i >= bufferlength) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
|
LED_A_OFF();
|
||||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||||
LED_D_OFF();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) {
|
||||||
|
|
||||||
|
bool PwdMode = (flag & 0xF);
|
||||||
|
uint8_t Address = (flag >> 8) & 0xFF;
|
||||||
uint8_t fwd_bit_count;
|
uint8_t fwd_bit_count;
|
||||||
|
|
||||||
|
//clear buffer now so it does not interfere with timing later
|
||||||
|
BigBuf_Clear_ext(false);
|
||||||
|
|
||||||
|
LED_A_ON();
|
||||||
//If password mode do login
|
//If password mode do login
|
||||||
if (PwdMode == 1) EM4xLogin(Pwd);
|
if (PwdMode) EM4xLogin(Pwd);
|
||||||
|
|
||||||
forward_ptr = forwardLink_data;
|
forward_ptr = forwardLink_data;
|
||||||
fwd_bit_count = Prepare_Cmd( FWD_CMD_WRITE );
|
fwd_bit_count = Prepare_Cmd( FWD_CMD_WRITE );
|
||||||
|
@ -1668,9 +1656,15 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode
|
||||||
SendForward(fwd_bit_count);
|
SendForward(fwd_bit_count);
|
||||||
|
|
||||||
//Wait for write to complete
|
//Wait for write to complete
|
||||||
SpinDelay(20);
|
//SpinDelay(10);
|
||||||
|
|
||||||
|
SpinDelayUs(6500);
|
||||||
|
//Capture response if one exists
|
||||||
|
DoPartialAcquisition(20, true, 6000);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
LED_D_OFF();
|
LED_A_OFF();
|
||||||
|
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Reading a COTAG.
|
Reading a COTAG.
|
||||||
|
|
|
@ -119,11 +119,11 @@ void LFSetupFPGAForADC(int divisor, bool lf_field)
|
||||||
* @param silent - is true, now outputs are made. If false, dbprints the status
|
* @param silent - is true, now outputs are made. If false, dbprints the status
|
||||||
* @return the number of bits occupied by the samples.
|
* @return the number of bits occupied by the samples.
|
||||||
*/
|
*/
|
||||||
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent)
|
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize)
|
||||||
{
|
{
|
||||||
//.
|
//.
|
||||||
uint8_t *dest = BigBuf_get_addr();
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int bufsize = BigBuf_max_traceLen();
|
bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen();
|
||||||
|
|
||||||
//memset(dest, 0, bufsize); //creates issues with cmdread (marshmellow)
|
//memset(dest, 0, bufsize); //creates issues with cmdread (marshmellow)
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
|
||||||
*/
|
*/
|
||||||
uint32_t DoAcquisition_default(int trigger_threshold, bool silent)
|
uint32_t DoAcquisition_default(int trigger_threshold, bool silent)
|
||||||
{
|
{
|
||||||
return DoAcquisition(1,8,0,trigger_threshold,silent);
|
return DoAcquisition(1,8,0,trigger_threshold,silent,0);
|
||||||
}
|
}
|
||||||
uint32_t DoAcquisition_config( bool silent)
|
uint32_t DoAcquisition_config( bool silent)
|
||||||
{
|
{
|
||||||
|
@ -221,7 +221,12 @@ uint32_t DoAcquisition_config( bool silent)
|
||||||
,config.bits_per_sample
|
,config.bits_per_sample
|
||||||
,config.averaging
|
,config.averaging
|
||||||
,config.trigger_threshold
|
,config.trigger_threshold
|
||||||
,silent);
|
,silent
|
||||||
|
,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size) {
|
||||||
|
return DoAcquisition(1,8,0,trigger_threshold,silent,sample_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ReadLF(bool activeField, bool silent)
|
uint32_t ReadLF(bool activeField, bool silent)
|
||||||
|
|
|
@ -24,9 +24,11 @@ uint32_t SampleLF(bool silent);
|
||||||
* Initializes the FPGA for snoop-mode (field off), and acquires the samples.
|
* Initializes the FPGA for snoop-mode (field off), and acquires the samples.
|
||||||
* @return number of bits sampled
|
* @return number of bits sampled
|
||||||
**/
|
**/
|
||||||
|
|
||||||
uint32_t SnoopLF();
|
uint32_t SnoopLF();
|
||||||
|
|
||||||
|
// adds sample size to default options
|
||||||
|
uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Does sample acquisition, ignoring the config values set in the sample_config.
|
* @brief Does sample acquisition, ignoring the config values set in the sample_config.
|
||||||
* This method is typically used by tag-specific readers who just wants to read the samples
|
* This method is typically used by tag-specific readers who just wants to read the samples
|
||||||
|
|
|
@ -22,6 +22,7 @@ command_t * CmdDataCommands();
|
||||||
int CmdData(const char *Cmd);
|
int CmdData(const char *Cmd);
|
||||||
void printDemodBuff(void);
|
void printDemodBuff(void);
|
||||||
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
|
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
|
||||||
|
int CmdPrintDemodBuff(const char *Cmd);
|
||||||
int CmdAskEM410xDemod(const char *Cmd);
|
int CmdAskEM410xDemod(const char *Cmd);
|
||||||
int CmdVikingDemod(const char *Cmd);
|
int CmdVikingDemod(const char *Cmd);
|
||||||
int CmdG_Prox_II_Demod(const char *Cmd);
|
int CmdG_Prox_II_Demod(const char *Cmd);
|
||||||
|
|
|
@ -1078,9 +1078,29 @@ int CmdVchDemod(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//by marshmellow
|
||||||
|
int CheckChipType(char cmdp) {
|
||||||
|
uint32_t wordData = 0;
|
||||||
|
|
||||||
|
//check for em4x05/em4x69 chips first
|
||||||
|
save_restoreGB(1);
|
||||||
|
if ((!offline && (cmdp != '1')) && EM4x05Block0Test(&wordData)) {
|
||||||
|
PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nTry lf em 4x05... commands\n");
|
||||||
|
save_restoreGB(0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO check for t55xx chip...
|
||||||
|
|
||||||
|
save_restoreGB(0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//by marshmellow
|
//by marshmellow
|
||||||
int CmdLFfind(const char *Cmd)
|
int CmdLFfind(const char *Cmd)
|
||||||
{
|
{
|
||||||
|
uint32_t wordData = 0;
|
||||||
int ans=0;
|
int ans=0;
|
||||||
size_t minLength = 1000;
|
size_t minLength = 1000;
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
@ -1115,7 +1135,12 @@ int CmdLFfind(const char *Cmd)
|
||||||
// only run if graphbuffer is just noise as it should be for hitag/cotag
|
// only run if graphbuffer is just noise as it should be for hitag/cotag
|
||||||
if (graphJustNoise(GraphBuffer, testLen)) {
|
if (graphJustNoise(GraphBuffer, testLen)) {
|
||||||
// only run these tests if we are in online mode
|
// only run these tests if we are in online mode
|
||||||
if (!offline && (cmdp != '1')){
|
if (!offline && (cmdp != '1')) {
|
||||||
|
// test for em4x05 in reader talk first mode.
|
||||||
|
if (EM4x05Block0Test(&wordData)) {
|
||||||
|
PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
ans=CmdLFHitagReader("26");
|
ans=CmdLFHitagReader("26");
|
||||||
if (ans==0) {
|
if (ans==0) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1132,49 +1157,49 @@ int CmdLFfind(const char *Cmd)
|
||||||
ans=CmdFSKdemodIO("");
|
ans=CmdFSKdemodIO("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid IO Prox ID Found!");
|
PrintAndLog("\nValid IO Prox ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdFSKdemodPyramid("");
|
ans=CmdFSKdemodPyramid("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid Pyramid ID Found!");
|
PrintAndLog("\nValid Pyramid ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdFSKdemodParadox("");
|
ans=CmdFSKdemodParadox("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid Paradox ID Found!");
|
PrintAndLog("\nValid Paradox ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdFSKdemodAWID("");
|
ans=CmdFSKdemodAWID("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid AWID ID Found!");
|
PrintAndLog("\nValid AWID ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdFSKdemodHID("");
|
ans=CmdFSKdemodHID("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid HID Prox ID Found!");
|
PrintAndLog("\nValid HID Prox ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdAskEM410xDemod("");
|
ans=CmdAskEM410xDemod("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid EM410x ID Found!");
|
PrintAndLog("\nValid EM410x ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdG_Prox_II_Demod("");
|
ans=CmdG_Prox_II_Demod("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid G Prox II ID Found!");
|
PrintAndLog("\nValid G Prox II ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdFDXBdemodBI("");
|
ans=CmdFDXBdemodBI("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid FDX-B ID Found!");
|
PrintAndLog("\nValid FDX-B ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=EM4x50Read("", false);
|
ans=EM4x50Read("", false);
|
||||||
|
@ -1186,24 +1211,25 @@ int CmdLFfind(const char *Cmd)
|
||||||
ans=CmdVikingDemod("");
|
ans=CmdVikingDemod("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid Viking ID Found!");
|
PrintAndLog("\nValid Viking ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdIndalaDecode("");
|
ans=CmdIndalaDecode("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid Indala ID Found!");
|
PrintAndLog("\nValid Indala ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ans=CmdPSKNexWatch("");
|
ans=CmdPSKNexWatch("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("\nValid NexWatch ID Found!");
|
PrintAndLog("\nValid NexWatch ID Found!");
|
||||||
return 1;
|
return CheckChipType(cmdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLog("\nNo Known Tags Found!\n");
|
PrintAndLog("\nNo Known Tags Found!\n");
|
||||||
if (testRaw=='u' || testRaw=='U'){
|
if (testRaw=='u' || testRaw=='U'){
|
||||||
//test unknown tag formats (raw mode)
|
ans=CheckChipType(cmdp);
|
||||||
|
//test unknown tag formats (raw mode)0
|
||||||
PrintAndLog("\nChecking for Unknown tags:\n");
|
PrintAndLog("\nChecking for Unknown tags:\n");
|
||||||
ans=AutoCorrelate(4000, FALSE, FALSE);
|
ans=AutoCorrelate(4000, FALSE, FALSE);
|
||||||
if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
|
if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
|
||||||
|
@ -1239,7 +1265,7 @@ static command_t CommandTable[] =
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
{"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"},
|
{"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"},
|
||||||
{"cotag", CmdLFCOTAG, 1, "{ COTAG RFIDs... }"},
|
{"cotag", CmdLFCOTAG, 1, "{ COTAG RFIDs... }"},
|
||||||
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
|
{"em", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
|
||||||
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
||||||
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
|
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
|
||||||
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
||||||
|
|
|
@ -140,7 +140,7 @@ int CmdAWIDClone(const char *Cmd) {
|
||||||
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_awid_clone();
|
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_awid_clone();
|
||||||
|
|
||||||
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
|
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
|
||||||
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 3<<T5555_MAXBLOCK_SHIFT;
|
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | ((50-2)>>1)<<T5555_BITRATE_SHIFT | 3<<T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
if ((fc & 0xFF) != fc) {
|
if ((fc & 0xFF) != fc) {
|
||||||
fc &= 0xFF;
|
fc &= 0xFF;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
#include "cmdlf.h"
|
#include "cmdlf.h"
|
||||||
|
#include "cmdmain.h"
|
||||||
#include "cmdlfem4x.h"
|
#include "cmdlfem4x.h"
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
|
|
||||||
|
@ -71,9 +72,9 @@ int CmdEM410xSim(const char *Cmd)
|
||||||
uint8_t uid[5] = {0x00};
|
uint8_t uid[5] = {0x00};
|
||||||
|
|
||||||
if (cmdp == 'h' || cmdp == 'H') {
|
if (cmdp == 'h' || cmdp == 'H') {
|
||||||
PrintAndLog("Usage: lf em4x em410xsim <UID> <clock>");
|
PrintAndLog("Usage: lf em 410xsim <UID> <clock>");
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
PrintAndLog(" sample: lf em4x em410xsim 0F0368568B");
|
PrintAndLog(" sample: lf em 410xsim 0F0368568B");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* clock is 64 in EM410x tags */
|
/* clock is 64 in EM410x tags */
|
||||||
|
@ -227,6 +228,7 @@ int CmdEM410xWrite(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//**************** Start of EM4x50 Code ************************
|
||||||
bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
|
bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
|
||||||
{
|
{
|
||||||
if (rows*cols>size) return false;
|
if (rows*cols>size) return false;
|
||||||
|
@ -285,7 +287,7 @@ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
/* Read the transmitted data of an EM4x50 tag
|
/* Read the transmitted data of an EM4x50 tag from the graphbuffer
|
||||||
* Format:
|
* Format:
|
||||||
*
|
*
|
||||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||||
|
@ -498,116 +500,497 @@ int CmdEM4x50Read(const char *Cmd)
|
||||||
return EM4x50Read(Cmd, true);
|
return EM4x50Read(Cmd, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdReadWord(const char *Cmd)
|
//**************** Start of EM4x05/EM4x69 Code ************************
|
||||||
{
|
int usage_lf_em_read(void) {
|
||||||
int Word = -1; //default to invalid word
|
PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. ");
|
||||||
UsbCommand c;
|
PrintAndLog("");
|
||||||
|
PrintAndLog("Usage: lf em 4x05readword [h] <address> <pwd>");
|
||||||
sscanf(Cmd, "%d", &Word);
|
PrintAndLog("Options:");
|
||||||
|
PrintAndLog(" h - this help");
|
||||||
if ( (Word > 15) | (Word < 0) ) {
|
PrintAndLog(" address - memory address to read. (0-15)");
|
||||||
PrintAndLog("Word must be between 0 and 15");
|
PrintAndLog(" pwd - password (hex) (optional)");
|
||||||
return 1;
|
PrintAndLog("samples:");
|
||||||
}
|
PrintAndLog(" lf em 4x05readword 1");
|
||||||
|
PrintAndLog(" lf em 4x05readword 1 11223344");
|
||||||
PrintAndLog("Reading word %d", Word);
|
|
||||||
|
|
||||||
c.cmd = CMD_EM4X_READ_WORD;
|
|
||||||
c.d.asBytes[0] = 0x0; //Normal mode
|
|
||||||
c.arg[0] = 0;
|
|
||||||
c.arg[1] = Word;
|
|
||||||
c.arg[2] = 0;
|
|
||||||
SendCommand(&c);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdReadWordPWD(const char *Cmd)
|
// for command responses from em4x05 or em4x69
|
||||||
{
|
// download samples from device and copy them to the Graphbuffer
|
||||||
int Word = -1; //default to invalid word
|
bool downloadSamplesEM() {
|
||||||
int Password = 0xFFFFFFFF; //default to blank password
|
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
|
||||||
UsbCommand c;
|
uint8_t got[6000];
|
||||||
|
GetFromBigBuf(got, sizeof(got), 0);
|
||||||
|
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) {
|
||||||
|
PrintAndLog("command execution time out");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
setGraphBuf(got, sizeof(got));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) {
|
||||||
|
// em4x05/em4x69 command response preamble is 00001010
|
||||||
|
// skip first two 0 bits as they might have been missed in the demod
|
||||||
|
uint8_t preamble[] = {0,0,1,0,1,0};
|
||||||
|
size_t startIdx = 0;
|
||||||
|
|
||||||
|
// set size to 20 to only test first 14 positions for the preamble or less if not a read command
|
||||||
|
size_t size = (readCmd) ? 20 : 11;
|
||||||
|
// sanity check
|
||||||
|
size = (size > DemodBufferLen) ? DemodBufferLen : size;
|
||||||
|
// test preamble
|
||||||
|
if ( !onePreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx) ) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if this is a readword command, get the read bytes and test the parities
|
||||||
|
if (readCmd) {
|
||||||
|
if (!EM_EndParityTest(DemodBuffer + startIdx + sizeof(preamble), 45, 5, 9, 0)) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - End Parity check failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// test for even parity bits.
|
||||||
|
if ( removeParity(DemodBuffer, startIdx + sizeof(preamble),9,0,44) == 0 ) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - Parity not detected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDemodBuf(DemodBuffer, 40, 0);
|
||||||
|
*word = bytebits_to_byteLSBF(DemodBuffer, 32);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE
|
||||||
|
// should cover 90% of known used configs
|
||||||
|
// the rest will need to be manually demoded for now...
|
||||||
|
int demodEM4x05resp(uint32_t *word, bool readCmd) {
|
||||||
|
int ans = 0;
|
||||||
|
|
||||||
|
// test for FSK wave (easiest to 99% ID)
|
||||||
|
if (GetFskClock("", false, false)) {
|
||||||
|
//valid fsk clocks found
|
||||||
|
ans = FSKrawDemod("0 0", false);
|
||||||
|
if (!ans) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed, ans: %d", ans);
|
||||||
|
} else {
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... )
|
||||||
|
ans = GetPskClock("", false, false);
|
||||||
|
if (ans>0) {
|
||||||
|
//try psk1
|
||||||
|
ans = PSKDemod("0 0 6", false);
|
||||||
|
if (!ans) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans);
|
||||||
|
} else {
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
//try psk2
|
||||||
|
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//try psk1 inverted
|
||||||
|
ans = PSKDemod("0 1 6", false);
|
||||||
|
if (!ans) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans);
|
||||||
|
} else {
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
//try psk2
|
||||||
|
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// manchester is more common than biphase... try first
|
||||||
|
bool stcheck = false;
|
||||||
|
// try manchester - NOTE: ST only applies to T55x7 tags.
|
||||||
|
ans = ASKDemod_ext("0,0,1", false, false, 1, &stcheck);
|
||||||
|
if (!ans) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed, ans: %d", ans);
|
||||||
|
} else {
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//try biphase
|
||||||
|
ans = ASKbiphaseDemod("0 0 1", false);
|
||||||
|
if (!ans) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans);
|
||||||
|
} else {
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//try diphase (differential biphase or inverted)
|
||||||
|
ans = ASKbiphaseDemod("0 1 1", false);
|
||||||
|
if (!ans) {
|
||||||
|
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans);
|
||||||
|
} else {
|
||||||
|
if (EM4x05testDemodReadData(word, readCmd)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *wordData) {
|
||||||
|
UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}};
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommand(&c);
|
||||||
|
UsbCommand resp;
|
||||||
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)){
|
||||||
|
PrintAndLog("Command timed out");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ( !downloadSamplesEM() ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000;
|
||||||
|
if (graphJustNoise(GraphBuffer, testLen)) {
|
||||||
|
PrintAndLog("no tag not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//attempt demod:
|
||||||
|
return demodEM4x05resp(wordData, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) {
|
||||||
|
uint32_t wordData = 0;
|
||||||
|
int success = EM4x05ReadWord_ext(addr, pwd, usePwd, &wordData);
|
||||||
|
if (success == 1)
|
||||||
|
PrintAndLog("%s Address %02d | %08X", (addr>13) ? "Lock":" Got",addr,wordData);
|
||||||
|
else
|
||||||
|
PrintAndLog("Read Address %02d | failed",addr);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdEM4x05ReadWord(const char *Cmd) {
|
||||||
|
uint8_t addr;
|
||||||
|
uint32_t pwd;
|
||||||
|
bool usePwd = false;
|
||||||
|
uint8_t ctmp = param_getchar(Cmd, 0);
|
||||||
|
if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_read();
|
||||||
|
|
||||||
|
addr = param_get8ex(Cmd, 0, 50, 10);
|
||||||
|
// for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
|
||||||
|
pwd = param_get32ex(Cmd, 1, 1, 16);
|
||||||
|
|
||||||
sscanf(Cmd, "%d %x", &Word, &Password);
|
if ( (addr > 15) ) {
|
||||||
|
PrintAndLog("Address must be between 0 and 15");
|
||||||
if ( (Word > 15) | (Word < 0) ) {
|
|
||||||
PrintAndLog("Word must be between 0 and 15");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if ( pwd == 1 ) {
|
||||||
PrintAndLog("Reading word %d with password %08X", Word, Password);
|
PrintAndLog("Reading address %02u", addr);
|
||||||
|
} else {
|
||||||
c.cmd = CMD_EM4X_READ_WORD;
|
usePwd = true;
|
||||||
c.d.asBytes[0] = 0x1; //Password mode
|
PrintAndLog("Reading address %02u | password %08X", addr, pwd);
|
||||||
c.arg[0] = 0;
|
}
|
||||||
c.arg[1] = Word;
|
|
||||||
c.arg[2] = Password;
|
return EM4x05ReadWord(addr, pwd, usePwd);
|
||||||
SendCommand(&c);
|
}
|
||||||
|
|
||||||
|
int usage_lf_em_dump(void) {
|
||||||
|
PrintAndLog("Dump EM4x05/EM4x69. Tag must be on antenna. ");
|
||||||
|
PrintAndLog("");
|
||||||
|
PrintAndLog("Usage: lf em 4x05dump [h] <pwd>");
|
||||||
|
PrintAndLog("Options:");
|
||||||
|
PrintAndLog(" h - this help");
|
||||||
|
PrintAndLog(" pwd - password (hex) (optional)");
|
||||||
|
PrintAndLog("samples:");
|
||||||
|
PrintAndLog(" lf em 4x05dump");
|
||||||
|
PrintAndLog(" lf em 4x05dump 11223344");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdWriteWord(const char *Cmd)
|
int CmdEM4x05dump(const char *Cmd) {
|
||||||
{
|
uint8_t addr = 0;
|
||||||
int Word = 16; //default to invalid block
|
uint32_t pwd;
|
||||||
int Data = 0xFFFFFFFF; //default to blank data
|
bool usePwd = false;
|
||||||
UsbCommand c;
|
uint8_t ctmp = param_getchar(Cmd, 0);
|
||||||
|
if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump();
|
||||||
|
|
||||||
|
// for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
|
||||||
|
pwd = param_get32ex(Cmd, 0, 1, 16);
|
||||||
|
|
||||||
sscanf(Cmd, "%x %d", &Data, &Word);
|
if ( pwd != 1 ) {
|
||||||
|
usePwd = true;
|
||||||
if (Word > 15) {
|
|
||||||
PrintAndLog("Word must be between 0 and 15");
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
int success = 1;
|
||||||
PrintAndLog("Writing word %d with data %08X", Word, Data);
|
for (; addr < 16; addr++) {
|
||||||
|
if (addr == 2) {
|
||||||
c.cmd = CMD_EM4X_WRITE_WORD;
|
if (usePwd) {
|
||||||
c.d.asBytes[0] = 0x0; //Normal mode
|
PrintAndLog(" PWD Address %02u | %08X",addr,pwd);
|
||||||
c.arg[0] = Data;
|
} else {
|
||||||
c.arg[1] = Word;
|
PrintAndLog(" PWD Address 02 | cannot read");
|
||||||
c.arg[2] = 0;
|
}
|
||||||
SendCommand(&c);
|
} else {
|
||||||
|
success &= EM4x05ReadWord(addr, pwd, usePwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int usage_lf_em_write(void) {
|
||||||
|
PrintAndLog("Write EM4x05/EM4x69. Tag must be on antenna. ");
|
||||||
|
PrintAndLog("");
|
||||||
|
PrintAndLog("Usage: lf em 4x05writeword [h] <address> <data> <pwd>");
|
||||||
|
PrintAndLog("Options:");
|
||||||
|
PrintAndLog(" h - this help");
|
||||||
|
PrintAndLog(" address - memory address to write to. (0-15)");
|
||||||
|
PrintAndLog(" data - data to write (hex)");
|
||||||
|
PrintAndLog(" pwd - password (hex) (optional)");
|
||||||
|
PrintAndLog("samples:");
|
||||||
|
PrintAndLog(" lf em 4x05writeword 1");
|
||||||
|
PrintAndLog(" lf em 4x05writeword 1 deadc0de 11223344");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdWriteWordPWD(const char *Cmd)
|
int CmdEM4x05WriteWord(const char *Cmd) {
|
||||||
{
|
uint8_t ctmp = param_getchar(Cmd, 0);
|
||||||
int Word = 16; //default to invalid word
|
if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write();
|
||||||
int Data = 0xFFFFFFFF; //default to blank data
|
|
||||||
int Password = 0xFFFFFFFF; //default to blank password
|
|
||||||
UsbCommand c;
|
|
||||||
|
|
||||||
sscanf(Cmd, "%x %d %x", &Data, &Word, &Password);
|
bool usePwd = false;
|
||||||
|
|
||||||
|
uint8_t addr = 16; // default to invalid address
|
||||||
|
uint32_t data = 0xFFFFFFFF; // default to blank data
|
||||||
|
uint32_t pwd = 0xFFFFFFFF; // default to blank password
|
||||||
|
|
||||||
if (Word > 15) {
|
addr = param_get8ex(Cmd, 0, 16, 10);
|
||||||
PrintAndLog("Word must be between 0 and 15");
|
data = param_get32ex(Cmd, 1, 0, 16);
|
||||||
|
pwd = param_get32ex(Cmd, 2, 1, 16);
|
||||||
|
|
||||||
|
|
||||||
|
if ( (addr > 15) ) {
|
||||||
|
PrintAndLog("Address must be between 0 and 15");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if ( pwd == 1 )
|
||||||
|
PrintAndLog("Writing address %d data %08X", addr, data);
|
||||||
|
else {
|
||||||
|
usePwd = true;
|
||||||
|
PrintAndLog("Writing address %d data %08X using password %08X", addr, data, pwd);
|
||||||
|
}
|
||||||
|
|
||||||
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password);
|
uint16_t flag = (addr << 8 ) | usePwd;
|
||||||
|
|
||||||
c.cmd = CMD_EM4X_WRITE_WORD;
|
UsbCommand c = {CMD_EM4X_WRITE_WORD, {flag, data, pwd}};
|
||||||
c.d.asBytes[0] = 0x1; //Password mode
|
clearCommandBuffer();
|
||||||
c.arg[0] = Data;
|
|
||||||
c.arg[1] = Word;
|
|
||||||
c.arg[2] = Password;
|
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
return 0;
|
UsbCommand resp;
|
||||||
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)){
|
||||||
|
PrintAndLog("Error occurred, device did not respond during write operation.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ( !downloadSamplesEM() ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//check response for 00001010 for write confirmation!
|
||||||
|
//attempt demod:
|
||||||
|
uint32_t dummy = 0;
|
||||||
|
int result = demodEM4x05resp(&dummy,false);
|
||||||
|
if (result == 1) {
|
||||||
|
PrintAndLog("Write Verified");
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Write could not be verified");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printEM4x05config(uint32_t wordData) {
|
||||||
|
uint16_t datarate = (((wordData & 0x3F)+1)*2);
|
||||||
|
uint8_t encoder = ((wordData >> 6) & 0xF);
|
||||||
|
char enc[14];
|
||||||
|
memset(enc,0,sizeof(enc));
|
||||||
|
|
||||||
|
uint8_t PSKcf = (wordData >> 10) & 0x3;
|
||||||
|
char cf[10];
|
||||||
|
memset(cf,0,sizeof(cf));
|
||||||
|
uint8_t delay = (wordData >> 12) & 0x3;
|
||||||
|
char cdelay[33];
|
||||||
|
memset(cdelay,0,sizeof(cdelay));
|
||||||
|
uint8_t LWR = (wordData >> 14) & 0xF; //last word read
|
||||||
|
|
||||||
|
switch (encoder) {
|
||||||
|
case 0: snprintf(enc,sizeof(enc),"NRZ"); break;
|
||||||
|
case 1: snprintf(enc,sizeof(enc),"Manchester"); break;
|
||||||
|
case 2: snprintf(enc,sizeof(enc),"Biphase"); break;
|
||||||
|
case 3: snprintf(enc,sizeof(enc),"Miller"); break;
|
||||||
|
case 4: snprintf(enc,sizeof(enc),"PSK1"); break;
|
||||||
|
case 5: snprintf(enc,sizeof(enc),"PSK2"); break;
|
||||||
|
case 6: snprintf(enc,sizeof(enc),"PSK3"); break;
|
||||||
|
case 7: snprintf(enc,sizeof(enc),"Unknown"); break;
|
||||||
|
case 8: snprintf(enc,sizeof(enc),"FSK1"); break;
|
||||||
|
case 9: snprintf(enc,sizeof(enc),"FSK2"); break;
|
||||||
|
default: snprintf(enc,sizeof(enc),"Unknown"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (PSKcf) {
|
||||||
|
case 0: snprintf(cf,sizeof(cf),"RF/2"); break;
|
||||||
|
case 1: snprintf(cf,sizeof(cf),"RF/8"); break;
|
||||||
|
case 2: snprintf(cf,sizeof(cf),"RF/4"); break;
|
||||||
|
case 3: snprintf(cf,sizeof(cf),"unknown"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (delay) {
|
||||||
|
case 0: snprintf(cdelay, sizeof(cdelay),"no delay"); break;
|
||||||
|
case 1: snprintf(cdelay, sizeof(cdelay),"BP/8 or 1/8th bit period delay"); break;
|
||||||
|
case 2: snprintf(cdelay, sizeof(cdelay),"BP/4 or 1/4th bit period delay"); break;
|
||||||
|
case 3: snprintf(cdelay, sizeof(cdelay),"no delay"); break;
|
||||||
|
}
|
||||||
|
PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData);
|
||||||
|
PrintAndLog("Config Breakdown:", wordData);
|
||||||
|
PrintAndLog(" Data Rate: %02u | RF/%u", wordData & 0x3F, datarate);
|
||||||
|
PrintAndLog(" Encoder: %u | %s", encoder, enc);
|
||||||
|
PrintAndLog(" PSK CF: %u | %s", PSKcf, cf);
|
||||||
|
PrintAndLog(" Delay: %u | %s", delay, cdelay);
|
||||||
|
PrintAndLog(" LastWordR: %02u | Address of last word for default read", LWR);
|
||||||
|
PrintAndLog(" ReadLogin: %u | Read Login is %s", (wordData & 0x40000)>>18, (wordData & 0x40000) ? "Required" : "Not Required");
|
||||||
|
PrintAndLog(" ReadHKL: %u | Read Housekeeping Words Login is %s", (wordData & 0x80000)>>19, (wordData & 0x80000) ? "Required" : "Not Required");
|
||||||
|
PrintAndLog("WriteLogin: %u | Write Login is %s", (wordData & 0x100000)>>20, (wordData & 0x100000) ? "Required" : "Not Required");
|
||||||
|
PrintAndLog(" WriteHKL: %u | Write Housekeeping Words Login is %s", (wordData & 0x200000)>>21, (wordData & 0x200000) ? "Required" : "Not Required");
|
||||||
|
PrintAndLog(" R.A.W.: %u | Read After Write is %s", (wordData & 0x400000)>>22, (wordData & 0x400000) ? "On" : "Off");
|
||||||
|
PrintAndLog(" Disable: %u | Disable Command is %s", (wordData & 0x800000)>>23, (wordData & 0x800000) ? "Accepted" : "Not Accepted");
|
||||||
|
PrintAndLog(" R.T.F.: %u | Reader Talk First is %s", (wordData & 0x1000000)>>24, (wordData & 0x1000000) ? "Enabled" : "Disabled");
|
||||||
|
PrintAndLog(" Pigeon: %u | Pigeon Mode is %s\n", (wordData & 0x4000000)>>26, (wordData & 0x4000000) ? "Enabled" : "Disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t serial) {
|
||||||
|
switch (chipType) {
|
||||||
|
case 9: PrintAndLog("\n Chip Type: %u | EM4305", chipType); break;
|
||||||
|
case 4: PrintAndLog(" Chip Type: %u | Unknown", chipType); break;
|
||||||
|
case 2: PrintAndLog(" Chip Type: %u | EM4469", chipType); break;
|
||||||
|
//add more here when known
|
||||||
|
default: PrintAndLog(" Chip Type: %u Unknown", chipType); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cap) {
|
||||||
|
case 3: PrintAndLog(" Cap Type: %u | 330pF",cap); break;
|
||||||
|
case 2: PrintAndLog(" Cap Type: %u | %spF",cap, (chipType==2)? "75":"210"); break;
|
||||||
|
case 1: PrintAndLog(" Cap Type: %u | 250pF",cap); break;
|
||||||
|
case 0: PrintAndLog(" Cap Type: %u | no resonant capacitor",cap); break;
|
||||||
|
default: PrintAndLog(" Cap Type: %u | unknown",cap); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog(" Cust Code: %03u | %s", custCode, (custCode == 0x200) ? "Default": "Unknown");
|
||||||
|
if (serial != 0) {
|
||||||
|
PrintAndLog("\n Serial #: %08X\n", serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printEM4x05ProtectionBits(uint32_t wordData) {
|
||||||
|
for (uint8_t i = 0; i < 15; i++) {
|
||||||
|
PrintAndLog(" Word: %02u | %s", i, (((1 << i) & wordData ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked");
|
||||||
|
if (i==14) {
|
||||||
|
PrintAndLog(" Word: %02u | %s", i+1, (((1 << i) & wordData ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//quick test for EM4x05/EM4x69 tag
|
||||||
|
bool EM4x05Block0Test(uint32_t *wordData) {
|
||||||
|
if (EM4x05ReadWord_ext(0,0,false,wordData) == 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdEM4x05info(const char *Cmd) {
|
||||||
|
//uint8_t addr = 0;
|
||||||
|
uint32_t pwd;
|
||||||
|
uint32_t wordData = 0;
|
||||||
|
bool usePwd = false;
|
||||||
|
uint8_t ctmp = param_getchar(Cmd, 0);
|
||||||
|
if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump();
|
||||||
|
|
||||||
|
// for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
|
||||||
|
pwd = param_get32ex(Cmd, 0, 1, 16);
|
||||||
|
|
||||||
|
if ( pwd != 1 ) {
|
||||||
|
usePwd = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read word 0 (chip info)
|
||||||
|
// block 0 can be read even without a password.
|
||||||
|
if ( !EM4x05Block0Test(&wordData) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint8_t chipType = (wordData >> 1) & 0xF;
|
||||||
|
uint8_t cap = (wordData >> 5) & 3;
|
||||||
|
uint16_t custCode = (wordData >> 9) & 0x3FF;
|
||||||
|
|
||||||
|
// read word 1 (serial #) doesn't need pwd
|
||||||
|
wordData = 0;
|
||||||
|
if (EM4x05ReadWord_ext(1, 0, false, &wordData) != 1) {
|
||||||
|
//failed, but continue anyway...
|
||||||
|
}
|
||||||
|
printEM4x05info(chipType, cap, custCode, wordData);
|
||||||
|
|
||||||
|
// read word 4 (config block)
|
||||||
|
// needs password if one is set
|
||||||
|
wordData = 0;
|
||||||
|
if ( EM4x05ReadWord_ext(4, pwd, usePwd, &wordData) != 1 ) {
|
||||||
|
//failed
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printEM4x05config(wordData);
|
||||||
|
|
||||||
|
// read word 14 and 15 to see which is being used for the protection bits
|
||||||
|
wordData = 0;
|
||||||
|
if ( EM4x05ReadWord_ext(14, pwd, usePwd, &wordData) != 1 ) {
|
||||||
|
//failed
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// if status bit says this is not the used protection word
|
||||||
|
if (!(wordData & 0x8000)) {
|
||||||
|
if ( EM4x05ReadWord_ext(15, pwd, usePwd, &wordData) != 1 ) {
|
||||||
|
//failed
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(wordData & 0x8000)) {
|
||||||
|
//something went wrong
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printEM4x05ProtectionBits(wordData);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static command_t CommandTable[] =
|
static command_t CommandTable[] =
|
||||||
{
|
{
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
|
{"410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
|
||||||
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
|
{"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
|
||||||
{"em410xsim", CmdEM410xSim, 0, "<UID> [clock rate] -- Simulate EM410x tag"},
|
{"410xsim", CmdEM410xSim, 0, "<UID> [clock rate] -- Simulate EM410x tag"},
|
||||||
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
{"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||||
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
{"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||||
{"em410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
{"410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
||||||
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
|
{"4x05dump", CmdEM4x05dump, 0, "(pwd) -- Read EM4x05/EM4x69 all word data"},
|
||||||
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
|
{"4x05info", CmdEM4x05info, 0, "(pwd) -- Get info from EM4x05/EM4x69 tag"},
|
||||||
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
|
{"4x05readword", CmdEM4x05ReadWord, 0, "<Word> (pwd) -- Read EM4x05/EM4x69 word data"},
|
||||||
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
|
{"4x05writeword", CmdEM4x05WriteWord, 0, "<Word> <data> (pwd) -- Write EM4x05/EM4x69 word data"},
|
||||||
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
|
{"4x50read", CmdEM4x50Read, 1, "demod data from EM4x50 tag from the graph buffer"},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,14 @@ int CmdEM410xWatch(const char *Cmd);
|
||||||
int CmdEM410xWatchnSpoof(const char *Cmd);
|
int CmdEM410xWatchnSpoof(const char *Cmd);
|
||||||
int CmdEM410xWrite(const char *Cmd);
|
int CmdEM410xWrite(const char *Cmd);
|
||||||
int CmdEM4x50Read(const char *Cmd);
|
int CmdEM4x50Read(const char *Cmd);
|
||||||
int CmdLFEM4X(const char *Cmd);
|
|
||||||
int CmdReadWord(const char *Cmd);
|
|
||||||
int CmdReadWordPWD(const char *Cmd);
|
|
||||||
int CmdWriteWord(const char *Cmd);
|
|
||||||
int CmdWriteWordPWD(const char *Cmd);
|
|
||||||
int EM4x50Read(const char *Cmd, bool verbose);
|
int EM4x50Read(const char *Cmd, bool verbose);
|
||||||
|
int CmdLFEM4X(const char *Cmd);
|
||||||
|
bool EM4x05Block0Test(uint32_t *wordData);
|
||||||
|
int CmdEM4x05info(const char *Cmd);
|
||||||
|
int CmdEM4x05WriteWord(const char *Cmd);
|
||||||
|
int CmdEM4x05dump(const char *Cmd);
|
||||||
|
int CmdEM4x05ReadWord(const char *Cmd);
|
||||||
|
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *wordData);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -178,7 +178,7 @@ int CmdPrescoClone(const char *Cmd) {
|
||||||
if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
|
if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
|
||||||
|
|
||||||
if (Q5)
|
if (Q5)
|
||||||
blocks[0] = T5555_MODULATION_MANCHESTER | 32<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
|
blocks[0] = T5555_MODULATION_MANCHESTER | ((32-2)>>1)<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
|
||||||
|
|
||||||
if ((sitecode & 0xFF) != sitecode) {
|
if ((sitecode & 0xFF) != sitecode) {
|
||||||
sitecode &= 0xFF;
|
sitecode &= 0xFF;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
|
#include "cmddata.h" //for g_debugmode
|
||||||
|
|
||||||
int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||||
int GraphTraceLen;
|
int GraphTraceLen;
|
||||||
|
@ -255,7 +256,7 @@ uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose)
|
||||||
if (size==0) return 0;
|
if (size==0) return 0;
|
||||||
uint16_t ans = countFC(BitStream, size, 1);
|
uint16_t ans = countFC(BitStream, size, 1);
|
||||||
if (ans==0) {
|
if (ans==0) {
|
||||||
if (verbose) PrintAndLog("DEBUG: No data found");
|
if (verbose || g_debugMode) PrintAndLog("DEBUG: No data found");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*fc1 = (ans >> 8) & 0xFF;
|
*fc1 = (ans >> 8) & 0xFF;
|
||||||
|
@ -263,7 +264,7 @@ uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose)
|
||||||
|
|
||||||
*rf1 = detectFSKClk(BitStream, size, *fc1, *fc2);
|
*rf1 = detectFSKClk(BitStream, size, *fc1, *fc2);
|
||||||
if (*rf1==0) {
|
if (*rf1==0) {
|
||||||
if (verbose) PrintAndLog("DEBUG: Clock detect error");
|
if (verbose || g_debugMode) PrintAndLog("DEBUG: Clock detect error");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -110,6 +110,23 @@ void print_hex(const uint8_t * data, const size_t len)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) {
|
||||||
|
|
||||||
|
int rownum = 0;
|
||||||
|
printf("[%02d] | ", rownum);
|
||||||
|
for (int i = 0; i < len; ++i) {
|
||||||
|
|
||||||
|
printf("%02X ", data[i]);
|
||||||
|
|
||||||
|
// check if a line break is needed
|
||||||
|
if ( breaks > 0 && !((i+1) % breaks) && (i+1 < len) ) {
|
||||||
|
++rownum;
|
||||||
|
printf("\n[%02d] | ", rownum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
char *sprint_hex(const uint8_t *data, const size_t len) {
|
char *sprint_hex(const uint8_t *data, const size_t len) {
|
||||||
|
|
||||||
int maxLen = ( len > 1024/3) ? 1024/3 : len;
|
int maxLen = ( len > 1024/3) ? 1024/3 : len;
|
||||||
|
@ -139,7 +156,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea
|
||||||
|
|
||||||
size_t in_index = 0;
|
size_t in_index = 0;
|
||||||
// loop through the out_index to make sure we don't go too far
|
// loop through the out_index to make sure we don't go too far
|
||||||
for (size_t out_index=0; out_index < max_len; out_index++) {
|
for (size_t out_index=0; out_index < max_len-1; out_index++) {
|
||||||
// set character - (should be binary but verify it isn't more than 1 digit)
|
// set character - (should be binary but verify it isn't more than 1 digit)
|
||||||
if (data[in_index]<10)
|
if (data[in_index]<10)
|
||||||
sprintf(tmp++, "%u", (unsigned int) data[in_index]);
|
sprintf(tmp++, "%u", (unsigned int) data[in_index]);
|
||||||
|
@ -158,6 +175,41 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea
|
||||||
char *sprint_bin(const uint8_t *data, const size_t len) {
|
char *sprint_bin(const uint8_t *data, const size_t len) {
|
||||||
return sprint_bin_break(data, len, 0);
|
return sprint_bin_break(data, len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *sprint_hex_ascii(const uint8_t *data, const size_t len) {
|
||||||
|
static char buf[1024];
|
||||||
|
char *tmp = buf;
|
||||||
|
memset(buf, 0x00, 1024);
|
||||||
|
size_t max_len = (len > 1010) ? 1010 : len;
|
||||||
|
|
||||||
|
sprintf(tmp, "%s| ", sprint_hex(data, max_len) );
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
size_t pos = (max_len * 3)+2;
|
||||||
|
while(i < max_len){
|
||||||
|
char c = data[i];
|
||||||
|
if ( (c < 32) || (c == 127))
|
||||||
|
c = '.';
|
||||||
|
sprintf(tmp+pos+i, "%c", c);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *sprint_ascii(const uint8_t *data, const size_t len) {
|
||||||
|
static char buf[1024];
|
||||||
|
char *tmp = buf;
|
||||||
|
memset(buf, 0x00, 1024);
|
||||||
|
size_t max_len = (len > 1010) ? 1010 : len;
|
||||||
|
size_t i = 0;
|
||||||
|
while(i < max_len){
|
||||||
|
char c = data[i];
|
||||||
|
tmp[i] = ((c < 32) || (c == 127)) ? '.' : c;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
|
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
|
||||||
{
|
{
|
||||||
while (len--) {
|
while (len--) {
|
||||||
|
@ -184,6 +236,15 @@ void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//least significant bit first
|
||||||
|
void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest) {
|
||||||
|
for(int i = 0 ; i < len ; ++i) {
|
||||||
|
dest[i] = n & 1;
|
||||||
|
n >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
|
// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
|
||||||
// to
|
// to
|
||||||
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
|
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
|
||||||
|
@ -200,6 +261,16 @@ uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockS
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// takes a uint8_t src array, for len items and reverses the byte order in blocksizes (8,16,32,64),
|
||||||
|
// returns: the dest array contains the reordered src array.
|
||||||
|
void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest){
|
||||||
|
for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){
|
||||||
|
for (size_t i = 0; i < blockSize; i++){
|
||||||
|
dest[i+(blockSize*block)] = src[(blockSize-1-i)+(blockSize*block)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//assumes little endian
|
//assumes little endian
|
||||||
char * printBits(size_t const size, void const * const ptr)
|
char * printBits(size_t const size, void const * const ptr)
|
||||||
{
|
{
|
||||||
|
@ -332,8 +403,6 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base)
|
||||||
return strtoull(&line[bg], NULL, base);
|
return strtoull(&line[bg], NULL, base);
|
||||||
else
|
else
|
||||||
return deflt;
|
return deflt;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
|
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
|
||||||
|
@ -490,6 +559,7 @@ void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
|
||||||
*(target)= GetParity(source + length / 2, ODD, length / 2);
|
*(target)= GetParity(source + length / 2, ODD, length / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xor two arrays together for len items. The dst array contains the new xored values.
|
||||||
void xor(unsigned char *dst, unsigned char *src, size_t len) {
|
void xor(unsigned char *dst, unsigned char *src, size_t len) {
|
||||||
for( ; len > 0; len--,dst++,src++)
|
for( ; len > 0; len--,dst++,src++)
|
||||||
*dst ^= *src;
|
*dst ^= *src;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h> //time, gmtime
|
||||||
#include "data.h" //for FILE_PATH_SIZE
|
#include "data.h" //for FILE_PATH_SIZE
|
||||||
|
|
||||||
#ifndef ROTR
|
#ifndef ROTR
|
||||||
|
@ -42,12 +42,16 @@ void print_hex(const uint8_t * data, const size_t len);
|
||||||
char * sprint_hex(const uint8_t * data, const size_t len);
|
char * sprint_hex(const uint8_t * data, const size_t len);
|
||||||
char * sprint_bin(const uint8_t * data, const size_t len);
|
char * sprint_bin(const uint8_t * data, const size_t len);
|
||||||
char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks);
|
char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks);
|
||||||
|
char * sprint_hex_ascii(const uint8_t *data, const size_t len);
|
||||||
|
char * sprint_ascii(const uint8_t *data, const size_t len);
|
||||||
|
|
||||||
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
|
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
|
||||||
uint64_t bytes_to_num(uint8_t* src, size_t len);
|
uint64_t bytes_to_num(uint8_t* src, size_t len);
|
||||||
void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest);
|
void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest);
|
||||||
|
void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest);
|
||||||
char * printBits(size_t const size, void const * const ptr);
|
char * printBits(size_t const size, void const * const ptr);
|
||||||
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
|
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
|
||||||
|
void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest);
|
||||||
|
|
||||||
char param_getchar(const char *line, int paramnum);
|
char param_getchar(const char *line, int paramnum);
|
||||||
int param_getptr(const char *line, int *bg, int *en, int paramnum);
|
int param_getptr(const char *line, int *bg, int *en, int paramnum);
|
||||||
|
|
121
common/lfdemod.c
121
common/lfdemod.c
|
@ -62,7 +62,7 @@ uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType)
|
||||||
for (uint8_t i = 0; i < bitLen; i++){
|
for (uint8_t i = 0; i < bitLen; i++){
|
||||||
ans ^= ((bits >> i) & 1);
|
ans ^= ((bits >> i) & 1);
|
||||||
}
|
}
|
||||||
//PrintAndLog("DEBUG: ans: %d, ptype: %d",ans,pType);
|
if (g_debugMode) prnt("DEBUG: ans: %d, ptype: %d, bits: %08X",ans,pType,bits);
|
||||||
return (ans == pType);
|
return (ans == pType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +73,13 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
|
||||||
{
|
{
|
||||||
uint32_t parityWd = 0;
|
uint32_t parityWd = 0;
|
||||||
size_t j = 0, bitCnt = 0;
|
size_t j = 0, bitCnt = 0;
|
||||||
for (int word = 0; word < (bLen); word+=pLen){
|
for (int word = 0; word < (bLen); word+=pLen) {
|
||||||
for (int bit=0; bit < pLen; bit++){
|
for (int bit=0; bit < pLen; bit++) {
|
||||||
parityWd = (parityWd << 1) | BitStream[startIdx+word+bit];
|
parityWd = (parityWd << 1) | BitStream[startIdx+word+bit];
|
||||||
BitStream[j++] = (BitStream[startIdx+word+bit]);
|
BitStream[j++] = (BitStream[startIdx+word+bit]);
|
||||||
}
|
}
|
||||||
|
if (word+pLen >= bLen) break;
|
||||||
|
|
||||||
j--; // overwrite parity with next data
|
j--; // overwrite parity with next data
|
||||||
// if parity fails then return 0
|
// if parity fails then return 0
|
||||||
switch (pType) {
|
switch (pType) {
|
||||||
|
@ -148,6 +150,9 @@ uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
|
||||||
//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length
|
//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length
|
||||||
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx)
|
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx)
|
||||||
{
|
{
|
||||||
|
// Sanity check. If preamble length is bigger than bitstream length.
|
||||||
|
if ( *size <= pLen ) return 0;
|
||||||
|
|
||||||
uint8_t foundCnt=0;
|
uint8_t foundCnt=0;
|
||||||
for (int idx=0; idx < *size - pLen; idx++){
|
for (int idx=0; idx < *size - pLen; idx++){
|
||||||
if (memcmp(BitStream+idx, preamble, pLen) == 0){
|
if (memcmp(BitStream+idx, preamble, pLen) == 0){
|
||||||
|
@ -165,6 +170,49 @@ uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found)
|
||||||
|
// does not look for a repeating preamble
|
||||||
|
// em4x05/4x69 only sends preamble once, so look for it once in the first pLen bits
|
||||||
|
// leave it generic so it could be reused later...
|
||||||
|
bool onePreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx) {
|
||||||
|
// Sanity check. If preamble length is bigger than bitstream length.
|
||||||
|
if ( size <= pLen ) return false;
|
||||||
|
for (size_t idx = 0; idx < size - pLen; idx++) {
|
||||||
|
if (memcmp(BitStream+idx, preamble, pLen) == 0) {
|
||||||
|
if (g_debugMode) prnt("DEBUG: preamble found at %u", idx);
|
||||||
|
*startIdx = idx;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find start of modulating data (for fsk and psk) in case of beginning noise or slow chip startup.
|
||||||
|
size_t findModStart(uint8_t dest[], size_t size, uint8_t threshold_value, uint8_t expWaveSize) {
|
||||||
|
size_t i = 0;
|
||||||
|
size_t waveSizeCnt = 0;
|
||||||
|
uint8_t thresholdCnt = 0;
|
||||||
|
bool isAboveThreshold = dest[i++] >= threshold_value;
|
||||||
|
for (; i < size-20; i++ ) {
|
||||||
|
if(dest[i] < threshold_value && isAboveThreshold) {
|
||||||
|
thresholdCnt++;
|
||||||
|
if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break;
|
||||||
|
isAboveThreshold = false;
|
||||||
|
waveSizeCnt = 0;
|
||||||
|
} else if (dest[i] >= threshold_value && !isAboveThreshold) {
|
||||||
|
thresholdCnt++;
|
||||||
|
if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break;
|
||||||
|
isAboveThreshold = true;
|
||||||
|
waveSizeCnt = 0;
|
||||||
|
} else {
|
||||||
|
waveSizeCnt++;
|
||||||
|
}
|
||||||
|
if (thresholdCnt > 10) break;
|
||||||
|
}
|
||||||
|
if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at %u, count: %u",i, thresholdCnt);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
//by marshmellow
|
//by marshmellow
|
||||||
//takes 1s and 0s and searches for EM410x format - output EM ID
|
//takes 1s and 0s and searches for EM410x format - output EM ID
|
||||||
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo)
|
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo)
|
||||||
|
@ -474,7 +522,6 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
|
||||||
{
|
{
|
||||||
size_t last_transition = 0;
|
size_t last_transition = 0;
|
||||||
size_t idx = 1;
|
size_t idx = 1;
|
||||||
//uint32_t maxVal=0;
|
|
||||||
if (fchigh==0) fchigh=10;
|
if (fchigh==0) fchigh=10;
|
||||||
if (fclow==0) fclow=8;
|
if (fclow==0) fclow=8;
|
||||||
//set the threshold close to 0 (graph) or 128 std to avoid static
|
//set the threshold close to 0 (graph) or 128 std to avoid static
|
||||||
|
@ -482,19 +529,22 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
|
||||||
size_t preLastSample = 0;
|
size_t preLastSample = 0;
|
||||||
size_t LastSample = 0;
|
size_t LastSample = 0;
|
||||||
size_t currSample = 0;
|
size_t currSample = 0;
|
||||||
// sync to first lo-hi transition, and threshold
|
if ( size < 1024 ) return 0; // not enough samples
|
||||||
|
|
||||||
|
//find start of modulating data in trace
|
||||||
|
idx = findModStart(dest, size, threshold_value, fchigh);
|
||||||
|
|
||||||
// Need to threshold first sample
|
// Need to threshold first sample
|
||||||
// skip 160 samples to allow antenna/samples to settle
|
if(dest[idx] < threshold_value) dest[0] = 0;
|
||||||
if(dest[160] < threshold_value) dest[0] = 0;
|
|
||||||
else dest[0] = 1;
|
else dest[0] = 1;
|
||||||
|
idx++;
|
||||||
|
|
||||||
size_t numBits = 0;
|
size_t numBits = 0;
|
||||||
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
|
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
|
||||||
// or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
|
// or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
|
||||||
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
|
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
|
||||||
// (could also be fc/5 && fc/7 for fsk1 = 4-9)
|
// (could also be fc/5 && fc/7 for fsk1 = 4-9)
|
||||||
for(idx = 161; idx < size-20; idx++) {
|
for(; idx < size-20; idx++) {
|
||||||
// threshold current value
|
// threshold current value
|
||||||
|
|
||||||
if (dest[idx] < threshold_value) dest[idx] = 0;
|
if (dest[idx] < threshold_value) dest[idx] = 0;
|
||||||
|
@ -509,13 +559,14 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
|
||||||
//do nothing with extra garbage
|
//do nothing with extra garbage
|
||||||
} else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5)
|
} else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5)
|
||||||
//correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
|
//correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
|
||||||
if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1) || preLastSample == 0 )){
|
if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){
|
||||||
dest[numBits-1]=1;
|
dest[numBits-1]=1;
|
||||||
}
|
}
|
||||||
dest[numBits++]=1;
|
dest[numBits++]=1;
|
||||||
|
|
||||||
} else if (currSample > (fchigh) && !numBits) { //12 + and first bit = unusable garbage
|
} else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage
|
||||||
//do nothing with beginning garbage
|
//do nothing with beginning garbage and reset.. should be rare..
|
||||||
|
numBits = 0;
|
||||||
} else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
|
} else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
|
||||||
dest[numBits++]=1;
|
dest[numBits++]=1;
|
||||||
} else { //9+ = 10 sample waves (or 6+ = 7)
|
} else { //9+ = 10 sample waves (or 6+ = 7)
|
||||||
|
@ -1292,7 +1343,10 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc
|
||||||
continue;
|
continue;
|
||||||
// else new peak
|
// else new peak
|
||||||
// if we got less than the small fc + tolerance then set it to the small fc
|
// if we got less than the small fc + tolerance then set it to the small fc
|
||||||
if (fcCounter < fcLow+fcTol)
|
// if it is inbetween set it to the last counter
|
||||||
|
if (fcCounter < fcHigh && fcCounter > fcLow)
|
||||||
|
fcCounter = lastFCcnt;
|
||||||
|
else if (fcCounter < fcLow+fcTol)
|
||||||
fcCounter = fcLow;
|
fcCounter = fcLow;
|
||||||
else //set it to the large fc
|
else //set it to the large fc
|
||||||
fcCounter = fcHigh;
|
fcCounter = fcHigh;
|
||||||
|
@ -1358,7 +1412,7 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ii<0) return 0; // oops we went too far
|
if (ii<2) return 0; // oops we went too far
|
||||||
|
|
||||||
return clk[ii];
|
return clk[ii];
|
||||||
}
|
}
|
||||||
|
@ -1372,10 +1426,10 @@ uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj)
|
||||||
uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
uint8_t fcLensFnd = 0;
|
uint8_t fcLensFnd = 0;
|
||||||
uint8_t lastFCcnt=0;
|
uint8_t lastFCcnt = 0;
|
||||||
uint8_t fcCounter = 0;
|
uint8_t fcCounter = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
if (size == 0) return 0;
|
if (size < 180) return 0;
|
||||||
|
|
||||||
// prime i to first up transition
|
// prime i to first up transition
|
||||||
for (i = 160; i < size-20; i++)
|
for (i = 160; i < size-20; i++)
|
||||||
|
@ -1462,27 +1516,37 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
|
||||||
|
|
||||||
size_t numBits=0;
|
size_t numBits=0;
|
||||||
uint8_t curPhase = *invert;
|
uint8_t curPhase = *invert;
|
||||||
size_t i, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0;
|
size_t i=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0;
|
||||||
uint8_t fc=0, fullWaveLen=0, tol=1;
|
uint16_t fc=0, fullWaveLen=0, tol=1;
|
||||||
uint16_t errCnt=0, waveLenCnt=0;
|
uint16_t errCnt=0, waveLenCnt=0, errCnt2=0;
|
||||||
fc = countFC(dest, *size, 0);
|
fc = countFC(dest, *size, 1);
|
||||||
|
uint8_t fc2 = fc >> 8;
|
||||||
|
if (fc2 == 10) return -1; //fsk found - quit
|
||||||
|
fc = fc & 0xFF;
|
||||||
if (fc!=2 && fc!=4 && fc!=8) return -1;
|
if (fc!=2 && fc!=4 && fc!=8) return -1;
|
||||||
//PrintAndLog("DEBUG: FC: %d",fc);
|
//PrintAndLog("DEBUG: FC: %d",fc);
|
||||||
*clock = DetectPSKClock(dest, *size, *clock);
|
*clock = DetectPSKClock(dest, *size, *clock);
|
||||||
if (*clock == 0) return -1;
|
if (*clock == 0) return -1;
|
||||||
int avgWaveVal=0, lastAvgWaveVal=0;
|
|
||||||
|
//find start of modulating data in trace
|
||||||
|
uint8_t threshold_value = 123; //-5
|
||||||
|
i = findModStart(dest, *size, threshold_value, fc);
|
||||||
|
|
||||||
//find first phase shift
|
//find first phase shift
|
||||||
for (i=0; i<loopCnt; i++){
|
int avgWaveVal=0, lastAvgWaveVal=0;
|
||||||
|
waveStart = i;
|
||||||
|
for (; i<loopCnt; i++) {
|
||||||
|
// find peak
|
||||||
if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){
|
if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){
|
||||||
waveEnd = i+1;
|
waveEnd = i+1;
|
||||||
//PrintAndLog("DEBUG: waveEnd: %d",waveEnd);
|
if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u",waveEnd, waveStart);
|
||||||
waveLenCnt = waveEnd-waveStart;
|
waveLenCnt = waveEnd-waveStart;
|
||||||
if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+2)){ //not first peak and is a large wave but not out of whack
|
if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+3)){ //not first peak and is a large wave but not out of whack
|
||||||
lastAvgWaveVal = avgWaveVal/(waveLenCnt);
|
lastAvgWaveVal = avgWaveVal/(waveLenCnt);
|
||||||
firstFullWave = waveStart;
|
firstFullWave = waveStart;
|
||||||
fullWaveLen=waveLenCnt;
|
fullWaveLen=waveLenCnt;
|
||||||
//if average wave value is > graph 0 then it is an up wave or a 1
|
//if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting)
|
||||||
if (lastAvgWaveVal > 123) curPhase ^= 1; //fudge graph 0 a little 123 vs 128
|
if (lastAvgWaveVal > threshold_value) curPhase ^= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
waveStart = i+1;
|
waveStart = i+1;
|
||||||
|
@ -1503,7 +1567,7 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
|
||||||
//set start of wave as clock align
|
//set start of wave as clock align
|
||||||
lastClkBit = firstFullWave;
|
lastClkBit = firstFullWave;
|
||||||
if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen);
|
if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen);
|
||||||
if (g_debugMode==2) prnt("DEBUG: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc);
|
if (g_debugMode==2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc);
|
||||||
waveStart = 0;
|
waveStart = 0;
|
||||||
dest[numBits++] = curPhase; //set first read bit
|
dest[numBits++] = curPhase; //set first read bit
|
||||||
for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){
|
for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){
|
||||||
|
@ -1534,6 +1598,9 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
|
||||||
} else if (i+1 > lastClkBit + *clock + tol + fc){
|
} else if (i+1 > lastClkBit + *clock + tol + fc){
|
||||||
lastClkBit += *clock; //no phase shift but clock bit
|
lastClkBit += *clock; //no phase shift but clock bit
|
||||||
dest[numBits++] = curPhase;
|
dest[numBits++] = curPhase;
|
||||||
|
} else if (waveLenCnt < fc - 1) { //wave is smaller than field clock (shouldn't happen often)
|
||||||
|
errCnt2++;
|
||||||
|
if(errCnt2 > 101) return errCnt2;
|
||||||
}
|
}
|
||||||
avgWaveVal = 0;
|
avgWaveVal = 0;
|
||||||
waveStart = i+1;
|
waveStart = i+1;
|
||||||
|
|
|
@ -39,6 +39,7 @@ int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert);
|
||||||
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert);
|
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert);
|
||||||
uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
|
uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
|
||||||
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
|
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
|
||||||
|
bool onePreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx);
|
||||||
int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
|
int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
|
||||||
void psk2TOpsk1(uint8_t *BitStream, size_t size);
|
void psk2TOpsk1(uint8_t *BitStream, size_t size);
|
||||||
void psk1TOpsk2(uint8_t *BitStream, size_t size);
|
void psk1TOpsk2(uint8_t *BitStream, size_t size);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue