]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge remote-tracking branch 'Proxmark/master' into iclass
authormarshmellow42 <marshmellowrf@gmail.com>
Wed, 7 Oct 2015 13:34:47 +0000 (09:34 -0400)
committermarshmellow42 <marshmellowrf@gmail.com>
Wed, 7 Oct 2015 13:34:47 +0000 (09:34 -0400)
Conflicts:
CHANGELOG.md

26 files changed:
CHANGELOG.md
armsrc/BigBuf.c
armsrc/BigBuf.h
armsrc/appmain.c
armsrc/apps.h
armsrc/fpgaloader.c
armsrc/fpgaloader.h
armsrc/iso14443a.c
armsrc/lfops.c
armsrc/lfsampling.c
armsrc/lfsampling.h
armsrc/mifarecmd.c
armsrc/mifareutil.h
armsrc/util.c
client/cmddata.c
client/cmdhfmf.c
client/cmdhw.c
client/cmdlfpcf7931.c
client/cmdlfpcf7931.h
client/cmdmain.c
client/lualibs/commands.lua
client/scripts/mifare_autopwn.lua
client/util.h
doc/RFID_Antenna-Basic-Form.stl [new file with mode: 0755]
doc/RFID_Antenna-With-Lanyard-Hook.stl [new file with mode: 0755]
include/usb_cmd.h

index dffe9a81a464b107ac3fddf3b33ddac15a948f28..c5ccc8f751a1c28176dd7382c64c2966b9a861c0 100644 (file)
@@ -13,11 +13,19 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
 - `hf iclass encryptblk` - to encrypt a data block hex to prep for writing that block (marshmellow)
 - ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards  (Craig Young) 
 - AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young)
+- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman) 
+- Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman)
+- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman)
 
 ### Changed
+<<<<<<< HEAD
 - changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow) 
 - `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to muliple pages for the larger tags yet)
+=======
+- Revised workflow for StandAloneMode14a (Craig Young)
+>>>>>>> Proxmark/master
 - EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
+- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)
 
 ## [2.2.0][2015-07-12]
 
index 510f7befe720a3628432086273ff537a25a85d0e..a938d5c68db9a193463700f315564ca45dfd3267 100644 (file)
@@ -88,6 +88,16 @@ void BigBuf_free_keep_EM(void)
        }
 }
 
+void BigBuf_print_status(void)
+{
+       Dbprintf("Memory");
+       Dbprintf("  BIGBUF_SIZE.............%d", BIGBUF_SIZE);
+       Dbprintf("  BigBuf_hi  .............%d", BigBuf_hi);
+       Dbprintf("Tracing");
+       Dbprintf("  tracing ................%d", tracing);
+       Dbprintf("  traceLen ...............%d", traceLen);
+}
+
 
 // return the maximum trace length (i.e. the unallocated size of BigBuf)
 uint16_t BigBuf_max_traceLen(void)
index 0e2f174479b5db5a2110fe057f80bf5dba31d638..05b4180e4b21c77b1604734035b5478216b7918d 100644 (file)
@@ -28,7 +28,7 @@ extern void BigBuf_Clear(void);
 extern uint8_t *BigBuf_malloc(uint16_t);
 extern void BigBuf_free(void);
 extern void BigBuf_free_keep_EM(void);
-
+extern void BigBuf_print_status(void);
 extern uint16_t BigBuf_get_traceLen(void);
 extern void clear_trace();
 extern void set_tracing(bool enable);
index 994bfa6c2ac5c22abea07cf267cb539d28d491eb..48c9caef638975f3f4d22d338eb42918c090ffa0 100644 (file)
@@ -25,6 +25,7 @@
 #include <hitag2.h>
 #include "lfsampling.h"
 #include "BigBuf.h"
+#include "mifareutil.h"
 #ifdef WITH_LCD
  #include "LCD.h"
 #endif
@@ -298,6 +299,52 @@ void SendVersion(void)
        cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString));
 }
 
+// measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
+// Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the UsbCommand structure included.
+void printUSBSpeed(void) 
+{
+       Dbprintf("USB Speed:");
+       Dbprintf("  Sending USB packets to client...");
+
+       #define USB_SPEED_TEST_MIN_TIME 1500    // in milliseconds
+       uint8_t *test_data = BigBuf_get_addr();
+       uint32_t end_time;
+
+       uint32_t start_time = end_time = GetTickCount();
+       uint32_t bytes_transferred = 0;
+       
+       LED_B_ON();
+       while(end_time < start_time + USB_SPEED_TEST_MIN_TIME) {
+               cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, 0, USB_CMD_DATA_SIZE, 0, test_data, USB_CMD_DATA_SIZE);
+               end_time = GetTickCount();
+               bytes_transferred += USB_CMD_DATA_SIZE;
+       }
+       LED_B_OFF();
+
+       Dbprintf("  Time elapsed:      %dms", end_time - start_time);
+       Dbprintf("  Bytes transferred: %d", bytes_transferred);
+       Dbprintf("  USB Transfer Speed PM3 -> Client = %d Bytes/s", 
+               1000 * bytes_transferred / (end_time - start_time));
+
+}
+       
+/**
+  * Prints runtime information about the PM3.
+**/
+void SendStatus(void)
+{
+       BigBuf_print_status();
+       Fpga_print_status();
+       printConfig(); //LF Sampling config
+       printUSBSpeed();
+       Dbprintf("Various");
+       Dbprintf("  MF_DBGLEVEL......%d", MF_DBGLEVEL);
+       Dbprintf("  ToSendMax........%d",ToSendMax);
+       Dbprintf("  ToSendBit........%d",ToSendBit);
+
+       cmd_send(CMD_ACK,1,0,0,0,0);
+}
+
 #if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF)
 
 #define OPTS 2
@@ -329,11 +376,14 @@ void StandAloneMode14a()
        FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
 
        int selected = 0;
-       int playing = 0;
+       int playing = 0, iGotoRecord = 0, iGotoClone = 0;
        int cardRead[OPTS] = {0};
        uint8_t readUID[10] = {0};
        uint32_t uid_1st[OPTS]={0};
        uint32_t uid_2nd[OPTS]={0};
+       uint32_t uid_tmp1 = 0;
+       uint32_t uid_tmp2 = 0;
+       iso14a_card_select_t hi14a_card[OPTS];
 
        LED(selected + 1, 0);
 
@@ -341,24 +391,17 @@ void StandAloneMode14a()
        {
                usb_poll();
                WDT_HIT();
-
-               // Was our button held down or pressed?
-               int button_pressed = BUTTON_HELD(1000);
                SpinDelay(300);
 
-               // Button was held for a second, begin recording
-               if (button_pressed > 0 && cardRead[selected] == 0)
+               if (iGotoRecord == 1 || cardRead[selected] == 0)
                {
+                       iGotoRecord = 0;
                        LEDsoff();
                        LED(selected + 1, 0);
                        LED(LED_RED2, 0);
 
                        // record
                        Dbprintf("Enabling iso14443a reader mode for [Bank: %u]...", selected);
-
-                       // wait for button to be released
-                       while(BUTTON_PRESS())
-                               WDT_HIT();
                        /* need this delay to prevent catching some weird data */
                        SpinDelay(500);
                        /* Code for reading from 14a tag */
@@ -369,22 +412,54 @@ void StandAloneMode14a()
                        for ( ; ; )
                        {
                                WDT_HIT();
-                               if (!iso14443a_select_card(uid, NULL, &cuid))
+                               if (BUTTON_PRESS()) {
+                                       if (cardRead[selected]) {
+                                               Dbprintf("Button press detected -- replaying card in bank[%d]", selected);
+                                               break;
+                                       }
+                                       else if (cardRead[(selected+1)%OPTS]) {
+                                               Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS);
+                                               selected = (selected+1)%OPTS;
+                                               break; // playing = 1;
+                                       }
+                                       else {
+                                               Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
+                                               SpinDelay(300);
+                                       }
+                               }
+                               if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid))
                                        continue;
                                else
                                {
                                        Dbprintf("Read UID:"); Dbhexdump(10,uid,0);
                                        memcpy(readUID,uid,10*sizeof(uint8_t));
-                                       uint8_t *dst = (uint8_t *)&uid_1st[selected];
+                                       uint8_t *dst = (uint8_t *)&uid_tmp1;
                                        // Set UID byte order
                                        for (int i=0; i<4; i++)
                                                dst[i] = uid[3-i];
-                                       dst = (uint8_t *)&uid_2nd[selected];
+                                       dst = (uint8_t *)&uid_tmp2;
                                        for (int i=0; i<4; i++)
                                                dst[i] = uid[7-i];
-                                       break;
+                                       if (uid_1st[(selected+1)%OPTS] == uid_tmp1 && uid_2nd[(selected+1)%OPTS] == uid_tmp2) {
+                                               Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping.");
+                                       }
+                                       else {
+                                               if (uid_tmp2) {
+                                                       Dbprintf("Bank[%d] received a 7-byte UID",selected);
+                                                       uid_1st[selected] = (uid_tmp1)>>8;
+                                                       uid_2nd[selected] = (uid_tmp1<<24) + (uid_tmp2>>8);
+                                               }
+                                               else {
+                                                       Dbprintf("Bank[%d] received a 4-byte UID",selected);
+                                                       uid_1st[selected] = uid_tmp1;
+                                                       uid_2nd[selected] = uid_tmp2;
+                                               }
+                                               break;
+                                       }
                                }
                        }
+                       Dbprintf("ATQA = %02X%02X",hi14a_card[selected].atqa[0],hi14a_card[selected].atqa[1]);
+                       Dbprintf("SAK = %02X",hi14a_card[selected].sak);
                        LEDsoff();
                        LED(LED_GREEN,  200);
                        LED(LED_ORANGE, 200);
@@ -393,101 +468,101 @@ void StandAloneMode14a()
 
                        LEDsoff();
                        LED(selected + 1, 0);
-                       // Finished recording
 
-                       // If we were previously playing, set playing off
-                       // so next button push begins playing what we recorded
-                       playing = 0;
+                       // Next state is replay:
+                       playing = 1;
 
                        cardRead[selected] = 1;
-
                }
-               /* MF UID clone */
-               else if (button_pressed > 0 && cardRead[selected] == 1)
+               /* MF Classic UID clone */
+               else if (iGotoClone==1)
                {
-                                       LEDsoff();
-                                       LED(selected + 1, 0);
-                                       LED(LED_ORANGE, 250);
-
+                       iGotoClone=0;
+                       LEDsoff();
+                       LED(selected + 1, 0);
+                       LED(LED_ORANGE, 250);
 
-                                       // record
-                                       Dbprintf("Preparing to Clone card [Bank: %x]; uid: %08x", selected, uid_1st[selected]);
 
-                                       // wait for button to be released
-                                       while(BUTTON_PRESS())
-                                       {
-                                               // Delay cloning until card is in place
-                                               WDT_HIT();
-                                       }
-                                       Dbprintf("Starting clone. [Bank: %u]", selected);
-                                       // need this delay to prevent catching some weird data
-                                       SpinDelay(500);
-                                       // Begin clone function here:
-                                       /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
-                                                       UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};
-                                                       memcpy(c.d.asBytes, data, 16);
-                                                       SendCommand(&c);
-
-                                               Block read is similar:
-                                                       UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}};
-                                               We need to imitate that call with blockNo 0 to set a uid.
-
-                                               The get and set commands are handled in this file:
-                                                       // Work with "magic Chinese" card
-                                                       case CMD_MIFARE_CSETBLOCK:
-                                                                       MifareCSetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
-                                                                       break;
-                                                       case CMD_MIFARE_CGETBLOCK:
-                                                                       MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
-                                                                                                       //
-                                                                       break;
-
-                                               mfCSetUID provides example logic for UID set workflow:
-                                                       -Read block0 from card in field with MifareCGetBlock()
-                                                       -Configure new values without replacing reserved bytes
-                                                                       memcpy(block0, uid, 4); // Copy UID bytes from byte array
-                                                                       // Mifare UID BCC
-                                                                       block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5
-                                                                       Bytes 5-7 are reserved SAK and ATQA for mifare classic
-                                                       -Use mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER) to write it
-                                       */
-                                       uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0};
-                                       // arg0 = Flags == CSETBLOCK_SINGLE_OPER=0x1F, arg1=returnSlot, arg2=blockNo
-                                       MifareCGetBlock(0x1F, 1, 0, oldBlock0);
-                                       Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]);
-                                       memcpy(newBlock0,oldBlock0,16);
-                                       // Copy uid_1st for bank (2nd is for longer UIDs not supported if classic)
-
-                                       newBlock0[0] = uid_1st[selected]>>24;
-                                       newBlock0[1] = 0xFF & (uid_1st[selected]>>16);
-                                       newBlock0[2] = 0xFF & (uid_1st[selected]>>8);
-                                       newBlock0[3] = 0xFF & (uid_1st[selected]);
-                                       newBlock0[4] = newBlock0[0]^newBlock0[1]^newBlock0[2]^newBlock0[3];
-                                       // arg0 = needWipe, arg1 = workFlags, arg2 = blockNo, datain
-                                       MifareCSetBlock(0, 0xFF,0, newBlock0);
-                                       MifareCGetBlock(0x1F, 1, 0, testBlock0);
-                                       if (memcmp(testBlock0,newBlock0,16)==0)
-                                       {
-                                               DbpString("Cloned successfull!");
-                                               cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
-                                       }
-                                       LEDsoff();
-                                       LED(selected + 1, 0);
-                                       // Finished recording
+                       // record
+                       Dbprintf("Preparing to Clone card [Bank: %x]; uid: %08x", selected, uid_1st[selected]);
 
-                                       // If we were previously playing, set playing off
-                                       // so next button push begins playing what we recorded
+                       // wait for button to be released
+                       while(BUTTON_PRESS())
+                       {
+                               // Delay cloning until card is in place
+                               WDT_HIT();
+                       }
+                       Dbprintf("Starting clone. [Bank: %u]", selected);
+                       // need this delay to prevent catching some weird data
+                       SpinDelay(500);
+                       // Begin clone function here:
+                       /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
+                                       UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};
+                                       memcpy(c.d.asBytes, data, 16);
+                                       SendCommand(&c);
+
+                                       Block read is similar:
+                                       UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}};
+                                       We need to imitate that call with blockNo 0 to set a uid.
+
+                                       The get and set commands are handled in this file:
+                                       // Work with "magic Chinese" card
+                                       case CMD_MIFARE_CSETBLOCK:
+                                               MifareCSetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
+                                               break;
+                                       case CMD_MIFARE_CGETBLOCK:
+                                               MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
+                                               break;
+
+                               mfCSetUID provides example logic for UID set workflow:
+                                       -Read block0 from card in field with MifareCGetBlock()
+                                       -Configure new values without replacing reserved bytes
+                                                       memcpy(block0, uid, 4); // Copy UID bytes from byte array
+                                                       // Mifare UID BCC
+                                                       block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5
+                                                       Bytes 5-7 are reserved SAK and ATQA for mifare classic
+                                       -Use mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER) to write it
+                       */
+                       uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0};
+                       // arg0 = Flags == CSETBLOCK_SINGLE_OPER=0x1F, arg1=returnSlot, arg2=blockNo
+                       MifareCGetBlock(0x3F, 1, 0, oldBlock0);
+                       if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1]  && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) {
+                               Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected);
+                               playing = 1;
+                       }
+                       else {
+                               Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]);
+                               memcpy(newBlock0,oldBlock0,16);
+                               // Copy uid_1st for bank (2nd is for longer UIDs not supported if classic)
+
+                               newBlock0[0] = uid_1st[selected]>>24;
+                               newBlock0[1] = 0xFF & (uid_1st[selected]>>16);
+                               newBlock0[2] = 0xFF & (uid_1st[selected]>>8);
+                               newBlock0[3] = 0xFF & (uid_1st[selected]);
+                               newBlock0[4] = newBlock0[0]^newBlock0[1]^newBlock0[2]^newBlock0[3];
+                               // arg0 = needWipe, arg1 = workFlags, arg2 = blockNo, datain
+                               MifareCSetBlock(0, 0xFF,0, newBlock0);
+                               MifareCGetBlock(0x3F, 1, 0, testBlock0);
+                               if (memcmp(testBlock0,newBlock0,16)==0)
+                               {
+                                       DbpString("Cloned successfull!");
+                                       cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
                                        playing = 0;
+                                       iGotoRecord = 1;
+                                       selected = (selected+1) % OPTS;
+                               }
+                               else {
+                                       Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected);
+                                       playing = 1;
+                               }
+                       }
+                       LEDsoff();
+                       LED(selected + 1, 0);
 
                }
                // Change where to record (or begin playing)
-               else if (button_pressed && cardRead[selected])
+               else if (playing==1) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
                {
-                       // Next option if we were previously playing
-                       if (playing)
-                               selected = (selected + 1) % OPTS;
-                       playing = !playing;
-
                        LEDsoff();
                        LED(selected + 1, 0);
 
@@ -496,19 +571,45 @@ void StandAloneMode14a()
                        {
                                LED(LED_GREEN, 0);
                                DbpString("Playing");
-                               while (!BUTTON_HELD(500)) { // Loop simulating tag until the button is held a half-sec
+                               for ( ; ; ) {
+                                       WDT_HIT();
+                                       int button_action = BUTTON_HELD(1000);
+                                       if (button_action == 0) { // No button action, proceed with sim
+                                               uint8_t data[512] = {0}; // in case there is a read command received we shouldn't break
                                                Dbprintf("Simulating ISO14443a tag with uid[0]: %08x, uid[1]: %08x [Bank: %u]", uid_1st[selected],uid_2nd[selected],selected);
-                                               SimulateIso14443aTag(1,uid_1st[selected],uid_2nd[selected],NULL);
+                                               if (hi14a_card[selected].sak == 8 && hi14a_card[selected].atqa[0] == 4 && hi14a_card[selected].atqa[1] == 0) {
+                                                       DbpString("Mifare Classic");
+                                                       SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); // Mifare Classic
+                                               }
+                                               else if (hi14a_card[selected].sak == 0 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 0) {
+                                                       DbpString("Mifare Ultralight");
+                                                       SimulateIso14443aTag(2,uid_1st[selected],uid_2nd[selected],data); // Mifare Ultralight
+                                               }
+                                               else if (hi14a_card[selected].sak == 20 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 3) {
+                                                       DbpString("Mifare DESFire");
+                                                       SimulateIso14443aTag(3,uid_1st[selected],uid_2nd[selected],data); // Mifare DESFire
+                                               }
+                                               else {
+                                                       Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
+                                                       SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data);
+                                               }
+                                       }
+                                       else if (button_action == BUTTON_SINGLE_CLICK) {
+                                               selected = (selected + 1) % OPTS;
+                                               Dbprintf("Done playing. Switching to record mode on bank %d",selected);
+                                               iGotoRecord = 1;
+                                               break;
                                        }
-                               //cardRead[selected] = 1;
-                               Dbprintf("Done playing [Bank: %u]",selected);
+                                       else if (button_action == BUTTON_HOLD) {
+                                               Dbprintf("Playtime over. Begin cloning...");
+                                               iGotoClone = 1;
+                                               break;
+                                       }
+                                       WDT_HIT();
+                               }
 
                                /* We pressed a button so ignore it here with a delay */
                                SpinDelay(300);
-
-                               // when done, we're done playing, move to next option
-                               selected = (selected + 1) % OPTS;
-                               playing = !playing;
                                LEDsoff();
                                LED(selected + 1, 0);
                        }
@@ -886,6 +987,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        ReadPCF7931();
                        cmd_send(CMD_ACK,0,0,0,0,0);
                        break;
+               case CMD_PCF7931_WRITE:
+                       WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]);
+                       break;
                case CMD_EM4X_READ_WORD:
                        EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]);
                        break;
@@ -1161,7 +1265,12 @@ void UsbPacketReceived(uint8_t *packet, int len)
                case CMD_VERSION:
                        SendVersion();
                        break;
-
+               case CMD_STATUS:
+                       SendStatus();
+                       break;
+               case CMD_PING:
+                       cmd_send(CMD_ACK,0,0,0,0,0);
+                       break;
 #ifdef WITH_LCD
                case CMD_LCD_RESET:
                        LCDReset();
index 63b2edc5f2ba377113cdb9335a22be2c427dcdd0..79c9da8620b9b1db2996a6c26abbf2c211948df2 100644 (file)
@@ -61,6 +61,7 @@ void AcquireRawAdcSamples125k(int divisor);
 void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command);
 void ReadTItag(void);
 void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
+
 void AcquireTiType(void);
 void AcquireRawBitsTI(void);
 void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
@@ -85,6 +86,11 @@ int DemodPCF7931(uint8_t **outBlocks);
 int IsBlock0PCF7931(uint8_t *Block);
 int IsBlock1PCF7931(uint8_t *Block);
 void ReadPCF7931();
+void SendCmdPCF7931(uint32_t * tab);
+bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
+bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
+bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
+void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
 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);
 
index 16fed7c52469b857437a3d58474a1dd4d892f4b4..308dda8c09e6ebf8fd0a691df91ccb0c0c3189d2 100644 (file)
@@ -558,3 +558,11 @@ void SetAdcMuxFor(uint32_t whichGpio)
 
        HIGH(whichGpio);
 }
+
+void Fpga_print_status(void)
+{
+       Dbprintf("Fgpa");
+       if(downloaded_bitstream == FPGA_BITSTREAM_HF) Dbprintf("  mode.............HF");
+       else if(downloaded_bitstream == FPGA_BITSTREAM_LF) Dbprintf("  mode.............LF");
+       else Dbprintf("  mode.............%d", downloaded_bitstream);
+}
index 0bad38094b62d355dc6cd13fb427b8c3c9310876..52d6c67780388ab6f94b1893c337139af9f729de 100644 (file)
@@ -17,6 +17,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len);
 void FpgaSetupSsc(void);
 void SetupSpi(int mode);
 bool FpgaSetupSscDma(uint8_t *buf, int len);
+void Fpga_print_status();
 #define FpgaDisableSscDma(void)        AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
 #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
 void SetAdcMuxFor(uint32_t whichGpio);
index 5c7367a15e634ae035bdf2af4f26470a75df216c..0431876eca41eb756342de78d8a3e58a75711f78 100644 (file)
@@ -1063,7 +1063,6 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
        LED_A_ON();
        for(;;) {
                // Clean receive command buffer
-               
                if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
                        DbpString("Button press");
                        break;
@@ -2017,6 +2016,7 @@ void ReaderMifare(bool first_try)
        byte_t par_list[8] = {0x00};
        byte_t ks_list[8] = {0x00};
 
+       #define PRNG_SEQUENCE_LENGTH  (1 << 16);
        static uint32_t sync_time;
        static uint32_t sync_cycles;
        int catch_up_cycles = 0;
@@ -2027,7 +2027,7 @@ void ReaderMifare(bool first_try)
        if (first_try) { 
                mf_nr_ar3 = 0;
                sync_time = GetCountSspClk() & 0xfffffff8;
-               sync_cycles = 65536;                                                                    // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
+               sync_cycles = PRNG_SEQUENCE_LENGTH;                                                     // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the tag nonces).
                nt_attacked = 0;
                nt = 0;
                par[0] = 0;
@@ -2044,8 +2044,12 @@ void ReaderMifare(bool first_try)
        LED_C_OFF();
        
 
-       #define DARKSIDE_MAX_TRIES      32              // number of tries to sync on PRNG cycle. Then give up.
-       uint16_t unsuccessfull_tries = 0;
+       #define MAX_UNEXPECTED_RANDOM   4               // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up.
+       #define MAX_SYNC_TRIES                  16
+       uint16_t unexpected_random = 0;
+       uint16_t sync_tries = 0;
+       int16_t debug_info_nr = -1;
+       uint32_t debug_info[MAX_SYNC_TRIES];
        
        for(uint16_t i = 0; TRUE; i++) {
                
@@ -2063,16 +2067,20 @@ void ReaderMifare(bool first_try)
                        continue;
                }
 
-               sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
-               catch_up_cycles = 0;
+               if (debug_info_nr == -1) {
+                       sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
+                       catch_up_cycles = 0;
 
-               // if we missed the sync time already, advance to the next nonce repeat
-               while(GetCountSspClk() > sync_time) {
-                       sync_time = (sync_time & 0xfffffff8) + sync_cycles;
-               }
+                       // if we missed the sync time already, advance to the next nonce repeat
+                       while(GetCountSspClk() > sync_time) {
+                               sync_time = (sync_time & 0xfffffff8) + sync_cycles;
+                       }
 
-               // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) 
-               ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
+                       // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) 
+                       ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
+               } else {
+                       ReaderTransmit(mf_auth, sizeof(mf_auth), NULL);
+               }                       
 
                // Receive the (4 Byte) "random" nonce
                if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) {
@@ -2090,19 +2098,32 @@ void ReaderMifare(bool first_try)
                        int nt_distance = dist_nt(previous_nt, nt);
                        if (nt_distance == 0) {
                                nt_attacked = nt;
-                       }
-                       else {
+                       } else {
                                if (nt_distance == -99999) { // invalid nonce received
-                                       unsuccessfull_tries++;
-                                       if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) {
+                                       unexpected_random++;
+                                       if (!nt_attacked && unexpected_random > MAX_UNEXPECTED_RANDOM) {
                                                isOK = -3;              // Card has an unpredictable PRNG. Give up      
                                                break;
                                        } else {
                                                continue;               // continue trying...
                                        }
                                }
+                               if (++sync_tries > MAX_SYNC_TRIES) {
+                                       if (sync_tries > 2 * MAX_SYNC_TRIES) {
+                                               isOK = -4;                      // Card's PRNG runs at an unexpected frequency or resets unexpectedly
+                                               break;
+                                       } else {                                // continue for a while, just to collect some debug info
+                                               debug_info[++debug_info_nr] = nt_distance;
+                                               continue;
+                                       }
+                               }
                                sync_cycles = (sync_cycles - nt_distance);
-                               if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
+                               if (sync_cycles <= 0) {
+                                       sync_cycles += PRNG_SEQUENCE_LENGTH;
+                               }
+                               if (MF_DBGLEVEL >= 3) {
+                                       Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
+                               }
                                continue;
                        }
                }
@@ -2173,6 +2194,14 @@ void ReaderMifare(bool first_try)
 
 
        mf_nr_ar[3] &= 0x1F;
+
+       if (isOK == -4) {
+               if (MF_DBGLEVEL >= 3) {
+                       for(uint16_t i = 0; i < MAX_SYNC_TRIES; i++) {
+                               Dbprintf("collected debug info[%d] = %d\n", i, debug_info[i]);
+                       }
+               }
+       }
        
        byte_t buf[28];
        memcpy(buf + 0,  uid, 4);
index 733bc953ed04a8dd85129c87f9af6d027f8bfcd4..d7f91c533e041be303e657a79471f33f8535a682 100644 (file)
@@ -16,8 +16,7 @@
 #include "string.h"
 #include "lfdemod.h"
 #include "lfsampling.h"
-#include "usb_cdc.h"
-
+#include "usb_cdc.h" //test
 
 /**
  * Function to do a modulation and then get samples.
@@ -214,6 +213,8 @@ void ReadTItag(void)
        }
 }
 
+
+
 void WriteTIbyte(uint8_t b)
 {
        int i = 0;
@@ -310,11 +311,16 @@ void AcquireTiType(void)
        }
 }
 
+
+
+
 // arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc
 // if crc provided, it will be written with the data verbatim (even if bogus)
 // if not provided a valid crc will be computed from the data and written.
 void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
 {
+
+
        FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
        if(crc == 0) {
                crc = update_crc16(crc, (idlo)&0xff);
@@ -1705,6 +1711,8 @@ int DemodPCF7931(uint8_t **outBlocks) {
                if(num_blocks == 4) break;
        }
        memcpy(outBlocks, Blocks, 16*num_blocks);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+
        return num_blocks;
 }
 
@@ -1828,14 +1836,15 @@ void ReadPCF7931() {
        Dbprintf("Memory content:");
        Dbprintf("-----------------------------------------");
        for(i=0; i<max_blocks; i++) {
-               if(Blocks[i][ALLOC]==1)
+               if(Blocks[i][ALLOC]==1){
                        Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
                                         Blocks[i][0], Blocks[i][1], Blocks[i][2], Blocks[i][3], Blocks[i][4], Blocks[i][5], Blocks[i][6], Blocks[i][7],
                                        Blocks[i][8], Blocks[i][9], Blocks[i][10], Blocks[i][11], Blocks[i][12], Blocks[i][13], Blocks[i][14], Blocks[i][15]);
-               else
+               }else
                        Dbprintf("<missing block %d>", i);
        }
        Dbprintf("-----------------------------------------");
+       
 
        return ;
 }
@@ -2058,3 +2067,261 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
        LED_D_OFF();
 }
+
+
+#define T0_PCF 8 //period for the pcf7931 in us
+
+/* Write on a byte of a PCF7931 tag
+ * @param address : address of the block to write
+   @param byte : address of the byte to write
+    @param data : data to write
+ */
+void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data)
+{
+
+       uint32_t tab[1024]={0}; // data times frame
+       uint32_t u = 0;
+       uint8_t parity = 0;
+       bool comp = 0;
+
+
+       //BUILD OF THE DATA FRAME
+
+       //alimentation of the tag (time for initializing)
+       AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
+
+       //PMC
+       Dbprintf("Initialization delay : %d us", init_delay);
+       AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
+
+       Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
+
+       //password indication bit
+       AddBitPCF7931(1, tab, l, p);
+
+
+       //password (on 56 bits)
+       Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7);
+       AddBytePCF7931(pass1, tab, l, p);
+       AddBytePCF7931(pass2, tab, l, p);
+       AddBytePCF7931(pass3, tab, l, p);
+       AddBytePCF7931(pass4, tab, l, p);
+       AddBytePCF7931(pass5, tab, l, p);
+       AddBytePCF7931(pass6, tab, l, p);
+       AddBytePCF7931(pass7, tab, l, p);
+
+
+       //programming mode (0 or 1)
+       AddBitPCF7931(0, tab, l, p);
+
+       //block adress on 6 bits
+       Dbprintf("Block address : %02x", address);
+       for (u=0; u<6; u++)
+       {
+               if (address&(1<<u)) {   // bit 1
+                        parity++;
+                        AddBitPCF7931(1, tab, l, p);
+               } else{                                 // bit 0
+                        AddBitPCF7931(0, tab, l, p);
+               }
+       }
+
+       //byte address on 4 bits
+       Dbprintf("Byte address : %02x", byte);
+       for (u=0; u<4; u++)
+       {
+               if (byte&(1<<u)) {      // bit 1
+                        parity++;
+                        AddBitPCF7931(1, tab, l, p);
+               } else{                         // bit 0
+                        AddBitPCF7931(0, tab, l, p);
+               }
+       }
+
+       //data on 8 bits
+       Dbprintf("Data : %02x", data);
+       for (u=0; u<8; u++)
+       {
+               if (data&(1<<u)) {      // bit 1
+                        parity++;
+                        AddBitPCF7931(1, tab, l, p);
+               } else{                         //bit 0
+                        AddBitPCF7931(0, tab, l, p);
+               }
+       }
+
+
+       //parity bit
+       if((parity%2)==0){
+               AddBitPCF7931(0, tab, l, p); //even parity
+       }else{
+               AddBitPCF7931(1, tab, l, p);//odd parity
+       }
+
+       //time access memory
+       AddPatternPCF7931(5120+2680, 0, 0, tab);
+
+       //conversion of the scale time
+       for(u=0;u<500;u++){
+               tab[u]=(tab[u] * 3)/2;
+       }
+
+
+       //compennsation of the counter reload
+       while (!comp){
+               comp = 1;
+               for(u=0;tab[u]!=0;u++){
+                       if(tab[u] > 0xFFFF){
+                         tab[u] -= 0xFFFF;
+                         comp = 0;
+                       }
+               }
+       }
+
+       SendCmdPCF7931(tab);
+}
+
+
+
+/* Send a trame to a PCF7931 tags
+ * @param tab : array of the data frame
+ */
+
+void SendCmdPCF7931(uint32_t * tab){
+       uint16_t u=0;
+       uint16_t tempo=0;
+
+       Dbprintf("SENDING DATA FRAME...");
+
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
+
+       LED_A_ON();
+
+       // steal this pin from the SSP and use it to control the modulation
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+
+       //initialization of the timer
+       AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
+       AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
+       AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK;  //clock at 48/32 MHz
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
+       AT91C_BASE_TCB->TCB_BCR = 1;
+
+
+       tempo = AT91C_BASE_TC0->TC_CV;
+       for(u=0;tab[u]!= 0;u+=3){
+
+
+               // modulate antenna
+               HIGH(GPIO_SSC_DOUT);
+               while(tempo !=  tab[u]){
+                       tempo = AT91C_BASE_TC0->TC_CV;
+               }
+
+               // stop modulating antenna
+               LOW(GPIO_SSC_DOUT);
+               while(tempo !=  tab[u+1]){
+                       tempo = AT91C_BASE_TC0->TC_CV;
+               }
+
+
+               // modulate antenna
+               HIGH(GPIO_SSC_DOUT);
+               while(tempo !=  tab[u+2]){
+                       tempo = AT91C_BASE_TC0->TC_CV;
+               }
+
+
+       }
+
+       LED_A_OFF();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       SpinDelay(200);
+
+
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
+       DbpString("FINISH !");
+       DbpString("(Could be usefull to send the same trame many times)");
+       LED(0xFFFF, 1000);
+}
+
+
+/* Add a byte for building the data frame of PCF7931 tags 
+ * @param b : byte to add
+ * @param tab : array of the data frame
+ * @param l : offset on low pulse width
+ * @param p : offset on low pulse positioning
+ */
+
+bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
+
+       uint32_t u;
+       for (u=0; u<8; u++)
+       {
+               if (byte&(1<<u)) {      //bit Ã  1
+                       if(AddBitPCF7931(1, tab, l, p)==1)return 1;
+               } else { //bit Ã  0
+                       if(AddBitPCF7931(0, tab, l, p)==1)return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* Add a bits for building the data frame of PCF7931 tags 
+ * @param b : bit to add
+ * @param tab : array of the data frame
+ * @param l : offset on low pulse width
+ * @param p : offset on low pulse positioning
+ */
+bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
+       uint8_t u = 0;
+
+       for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
+       
+
+       if(b==1){       //add a bit 1
+               if(u==0) tab[u] = 34*T0_PCF+p;
+               else     tab[u] = 34*T0_PCF+tab[u-1]+p;
+
+               tab[u+1] = 6*T0_PCF+tab[u]+l;
+               tab[u+2] = 88*T0_PCF+tab[u+1]-l-p;
+               return 0;
+       }else{          //add a bit 0
+
+               if(u==0) tab[u] = 98*T0_PCF+p;
+               else     tab[u] = 98*T0_PCF+tab[u-1]+p;
+
+               tab[u+1] = 6*T0_PCF+tab[u]+l;
+               tab[u+2] = 24*T0_PCF+tab[u+1]-l-p;
+               return 0;
+       }
+
+       
+       return 1;
+}
+
+/* Add a custom pattern in the data frame
+ * @param a : delay of the first high pulse
+ * @param b : delay of the low pulse
+ * @param c : delay of the last high pulse
+ * @param tab : array of the data frame
+ */
+bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){
+       uint32_t u = 0;
+       for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
+
+       if(u==0) tab[u] = a;
+       else tab[u] = a + tab[u-1];
+
+       tab[u+1] = b+tab[u];
+       tab[u+2] = c+tab[u+1];
+
+       return 0;
+}
\ No newline at end of file
index 662ebf24a1b84702d37d6ffe3c31c79693a2d483..6e78376986daa167079608c83b2189d4c528ea42 100644 (file)
@@ -17,7 +17,7 @@ sample_config config = { 1, 8, 1, 95, 0 } ;
 
 void printConfig()
 {
-       Dbprintf("Sampling config: ");
+       Dbprintf("LF Sampling config: ");
        Dbprintf("  [q] divisor:           %d ", config.divisor);
        Dbprintf("  [b] bps:               %d ", config.bits_per_sample);
        Dbprintf("  [d] decimation:        %d ", config.decimation);
index 6c671ec8ca7a295b49a2d9200401a3ca69d49753..7d3925cddfff0d70e7032da25b3284276abd3e0d 100644 (file)
@@ -56,4 +56,8 @@ void LFSetupFPGAForADC(int divisor, bool lf_field);
 void setSamplingConfig(sample_config *sc);
 
 sample_config * getSamplingConfig();
+
+void printConfig();
+
+
 #endif // LFSAMPLING_H
index fd6fde63d2b54db97a999b8619954789a57bdcdf..a3d6609db3413a136b6d5415e3296e103f90a28a 100644 (file)
@@ -1143,6 +1143,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
        // bit 2 - need HALT after sequence\r
        // bit 3 - need init FPGA and field before sequence\r
        // bit 4 - need reset FPGA and LED\r
+       // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)\r
        uint8_t workFlags = arg0;\r
        uint8_t blockNo = arg2;\r
        \r
@@ -1202,7 +1203,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
        }\r
        \r
        LED_B_ON();\r
-       cmd_send(CMD_ACK,isOK,0,0,data,18);\r
+       if (workFlags & 0x20) {\r
+               if (isOK)\r
+                       memcpy(datain, data, 18);\r
+       }\r
+       else\r
+               cmd_send(CMD_ACK,isOK,0,0,data,18);\r
        LED_B_OFF();\r
 \r
        if ((workFlags & 0x10) || (!isOK)) {\r
index 85a34ef62104fa2445503eac3517436d43fa8438..7a09ce64cdac33707a13abdef1de3294d778cd58 100644 (file)
@@ -8,6 +8,7 @@
 //-----------------------------------------------------------------------------\r
 // code for work with mifare cards.\r
 //-----------------------------------------------------------------------------\r
+#include "crapto1.h"\r
 \r
 #ifndef __MIFAREUTIL_H\r
 #define __MIFAREUTIL_H\r
index 8576ddce5fcb7c641236d214bb224ca3221769b1..1dd8dc7544fe1cb2989548692f8449f19b6ca621 100644 (file)
@@ -304,11 +304,12 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
 
 void StartTickCount()
 {
-//  must be 0x40, but on my cpu - included divider is optimal
-//  0x20 - 1 ms / bit 
-//  0x40 - 2 ms / bit
-
-       AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST + 0x001D; // was 0x003B
+       // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz.
+       // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register.
+    uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff;                // = 16 * main clock frequency (16MHz) / slow clock frequency
+       // set RealTimeCounter divider to count at 1kHz:
+       AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf);
+       // note: worst case precision is approx 2.5%
 }
 
 /*
index cb1c7cd455adbfd9cb0d23837e227a6714c97c75..22da18053c4f80b35e899dbf029c67454e43111a 100644 (file)
@@ -24,6 +24,7 @@
 #include "usb_cmd.h"
 #include "crc.h"
 #include "crc16.h"
+#include "loclass/cipherutils.h"
 
 uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
 uint8_t g_debugMode=0;
@@ -1943,26 +1944,14 @@ int CmdHpf(const char *Cmd)
        RepaintGraphWindow();
        return 0;
 }
-typedef struct {
-       uint8_t * buffer;
-       uint32_t numbits;
-       uint32_t position;
-}BitstreamOut;
 
-bool _headBit( BitstreamOut *stream)
-{
-       int bytepos = stream->position >> 3; // divide by 8
-       int bitpos = (stream->position++) & 7; // mask out 00000111
-       return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1;
-}
-
-uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b)
+uint8_t getByte(uint8_t bits_per_sample, BitstreamIn* b)
 {
        int i;
        uint8_t val = 0;
        for(i =0 ; i < bits_per_sample; i++)
        {
-               val |= (_headBit(b) << (7-i));
+               val |= (headBit(b) << (7-i));
        }
        return val;
 }
@@ -2002,7 +1991,7 @@ int getSamples(const char *Cmd, bool silent)
        if(bits_per_sample < 8)
        {
                PrintAndLog("Unpacking...");
-               BitstreamOut bout = { got, bits_per_sample * n,  0};
+               BitstreamIn bout = { got, bits_per_sample * n,  0};
                int j =0;
                for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) {
                        uint8_t sample = getByte(bits_per_sample, &bout);
@@ -2265,6 +2254,99 @@ int CmdZerocrossings(const char *Cmd)
        return 0;
 }
 
+int usage_data_bin2hex(){
+               PrintAndLog("Usage: data bin2hex <binary_digits>");
+               PrintAndLog("       This function will ignore all characters not 1 or 0 (but stop reading on whitespace)");
+               return 0;
+}
+
+/**
+ * @brief Utility for conversion via cmdline.
+ * @param Cmd
+ * @return
+ */
+int Cmdbin2hex(const char *Cmd)
+{
+       int bg =0, en =0;
+       if(param_getptr(Cmd, &bg, &en, 0))
+       {
+               return usage_data_bin2hex();
+       }
+       //Number of digits supplied as argument
+       size_t length = en  - bg +1;
+       size_t bytelen = (length+7) / 8;
+       uint8_t* arr = (uint8_t *) malloc(bytelen);
+       memset(arr, 0, bytelen);
+       BitstreamOut bout = { arr, 0, 0 };
+
+       for(; bg <= en ;bg++)
+       {
+               char c = Cmd[bg];
+               if( c == '1')   pushBit(&bout, 1);
+               else if( c == '0')      pushBit(&bout, 0);
+               else PrintAndLog("Ignoring '%c'", c);
+       }
+
+       if(bout.numbits % 8 != 0)
+       {
+               printf("[padded with %d zeroes]\n", 8-(bout.numbits % 8));
+       }
+
+       //Uses printf instead of PrintAndLog since the latter
+       // adds linebreaks to each printout - this way was more convenient since we don't have to
+       // allocate a string and write to that first...
+       for(size_t x = 0; x  < bytelen ; x++)
+       {
+               printf("%02X", arr[x]);
+       }
+       printf("\n");
+       free(arr);
+       return 0;
+}
+
+int usage_data_hex2bin(){
+
+       PrintAndLog("Usage: data bin2hex <binary_digits>");
+       PrintAndLog("       This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
+       return 0;
+
+}
+
+int Cmdhex2bin(const char *Cmd)
+{
+       int bg =0, en =0;
+       if(param_getptr(Cmd, &bg, &en, 0))
+       {
+               return usage_data_hex2bin();
+       }
+
+
+       while(bg <= en )
+       {
+               char x = Cmd[bg++];
+               // capitalize
+               if (x >= 'a' && x <= 'f')
+                       x -= 32;
+               // convert to numeric value
+               if (x >= '0' && x <= '9')
+                       x -= '0';
+               else if (x >= 'A' && x <= 'F')
+                       x -= 'A' - 10;
+               else
+                       continue;
+
+               //Uses printf instead of PrintAndLog since the latter
+               // adds linebreaks to each printout - this way was more convenient since we don't have to
+               // allocate a string and write to that first...
+
+               for(int i= 0 ; i < 4 ; ++i)
+                       printf("%d",(x >> (3 - i)) & 1);
+       }
+       printf("\n");
+
+       return 0;
+}
+
 static command_t CommandTable[] =
 {
        {"help",            CmdHelp,            1, "This help"},
@@ -2273,6 +2355,7 @@ static command_t CommandTable[] =
        {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"},
        {"autocorr",        CmdAutoCorr,        1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"},
        {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
+       {"bin2hex",         Cmdbin2hex,         1, "bin2hex <digits>     -- Converts binary to hexadecimal"},
        {"bitsamples",      CmdBitsamples,      0, "Get raw samples as bitstring"},
        {"buffclear",       CmdBuffClear,       1, "Clear sample buffer and graph window"},
        {"dec",             CmdDec,             1, "Decimate samples"},
@@ -2287,6 +2370,7 @@ static command_t CommandTable[] =
        {"getbitstream",    CmdGetBitStream,    1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"},
        {"grid",            CmdGrid,            1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
        {"hexsamples",      CmdHexsamples,      0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
+       {"hex2bin",         Cmdhex2bin,         1, "hex2bin <hexadecimal> -- Converts hexadecimal to binary"},
        {"hide",            CmdHide,            1, "Hide graph window"},
        {"hpf",             CmdHpf,             1, "Remove DC offset from trace"},
        {"load",            CmdLoad,            1, "<filename> -- Load trace (to graph window"},
index c4a0aeebd615a60eb978942d5db30930798a4171..304e9c9c3b0d870e09f2f2096bec6785a7be50b3 100644 (file)
@@ -58,6 +58,7 @@ start:
                                case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;\r
                                case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;\r
                                case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;\r
+                               case -4 : PrintAndLog("The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). This needs to be fixed.\n"); break;\r
                                default: ;\r
                        }\r
                        break;\r
index 2b6f95187512a16c0e7fa8e9fda265d2aff457ad..33dc78aeb523c5731ec297e9432159336d774580 100644 (file)
@@ -18,6 +18,7 @@
 #include "cmdhw.h"
 #include "cmdmain.h"
 #include "cmddata.h"
+#include "data.h"
 
 /* low-level hardware control */
 
@@ -405,33 +406,72 @@ int CmdTune(const char *Cmd)
 int CmdVersion(const char *Cmd)
 {
 
+       clearCommandBuffer();
        UsbCommand c = {CMD_VERSION};
-       UsbCommand resp = {0, {0, 0, 0}};
+       static UsbCommand resp = {0, {0, 0, 0}};
 
-       SendCommand(&c);
-       if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
+       if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available
+               SendCommand(&c);
+               if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
+                       PrintAndLog("Prox/RFID mark3 RFID instrument");
+                       PrintAndLog((char*)resp.d.asBytes);
+                       lookupChipID(resp.arg[0], resp.arg[1]);
+               }
+       } else {
+               PrintAndLog("[[[ Cached information ]]]\n");
                PrintAndLog("Prox/RFID mark3 RFID instrument");
                PrintAndLog((char*)resp.d.asBytes);
                lookupChipID(resp.arg[0], resp.arg[1]);
+               PrintAndLog("");
+       }
+       return 0;
+}
+
+int CmdStatus(const char *Cmd)
+{
+       uint8_t speed_test_buffer[USB_CMD_DATA_SIZE];
+       sample_buf = speed_test_buffer;
+
+       clearCommandBuffer();
+       UsbCommand c = {CMD_STATUS};
+       SendCommand(&c);
+       if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) {
+               PrintAndLog("Status command failed. USB Speed Test timed out");
        }
+       return 0;
+}
+
 
+int CmdPing(const char *Cmd)
+{
+       clearCommandBuffer();
+       UsbCommand resp;
+       UsbCommand c = {CMD_PING};
+       SendCommand(&c);
+       if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
+               PrintAndLog("Ping successfull");
+       }else{
+               PrintAndLog("Ping failed");
+       }
        return 0;
 }
 
 static command_t CommandTable[] = 
 {
-  {"help",          CmdHelp,        1, "This help"},
-  {"detectreader",  CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
-  {"fpgaoff",       CmdFPGAOff,     0, "Set FPGA off"},
-  {"lcd",           CmdLCD,         0, "<HEX command> <count> -- Send command/data to LCD"},
-  {"lcdreset",      CmdLCDReset,    0, "Hardware reset LCD"},
-  {"readmem",       CmdReadmem,     0, "[address] -- Read memory at decimal address from flash"},
-  {"reset",         CmdReset,       0, "Reset the Proxmark3"},
-  {"setlfdivisor",  CmdSetDivisor,  0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
-  {"setmux",        CmdSetMux,      0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
-  {"tune",          CmdTune,        0, "Measure antenna tuning"},
-  {"version",       CmdVersion,     0, "Show version information about the connected Proxmark"},
-  {NULL, NULL, 0, NULL}
+       {"help",          CmdHelp,        1, "This help"},
+       {"detectreader",  CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
+       {"fpgaoff",       CmdFPGAOff,     0, "Set FPGA off"},
+       {"lcd",           CmdLCD,         0, "<HEX command> <count> -- Send command/data to LCD"},
+       {"lcdreset",      CmdLCDReset,    0, "Hardware reset LCD"},
+       {"readmem",       CmdReadmem,     0, "[address] -- Read memory at decimal address from flash"},
+       {"reset",         CmdReset,       0, "Reset the Proxmark3"},
+       {"setlfdivisor",  CmdSetDivisor,  0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
+       {"setmux",        CmdSetMux,      0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
+       {"tune",          CmdTune,        0, "Measure antenna tuning"},
+       {"version",       CmdVersion,     0, "Show version information about the connected Proxmark"},
+       {"status",        CmdStatus,      0, "Show runtime status information about the connected Proxmark"},
+       {"ping",          CmdPing,        0, "Test if the pm3 is responsive"},
+       {NULL, NULL, 0, NULL}
 };
 
 int CmdHW(const char *Cmd)
index 0d8fb93d4c2d89024d26507f8039e2657a66b4b5..b1e1ae9eaa47a788257f2ef6c33d25b35e02cc22 100644 (file)
@@ -1,6 +1,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
-//
+//               2015 Dake <thomas.cayrou at gmail.com>
+
 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
 // at your option, any later version. See the LICENSE.txt file for the text of
 // the license.
@@ -21,6 +22,8 @@
 
 static int CmdHelp(const char *Cmd);
 
+struct pcf7931_config configPcf = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},17500,{0,0}};
+
 int CmdLFPCF7931Read(const char *Cmd)
 {
   UsbCommand c = {CMD_PCF7931_READ};
@@ -30,10 +33,93 @@ int CmdLFPCF7931Read(const char *Cmd)
   return 0;
 }
 
+int CmdLFPCF7931Config(const char *Cmd)
+{ 
+  int res = 0;
+  res = sscanf(Cmd, "%02x %02x %02x %02x %02x %02x %02x %d %d %d", &configPcf.password[0], &configPcf.password[1], &configPcf.password[2], &configPcf.password[3], &configPcf.password[4], &configPcf.password[5], &configPcf.password[6], &configPcf.init_delay, &configPcf.offset[0], &configPcf.offset[1]);
+
+  if (res >= 7 || res < 1){
+      if(res == 7) configPcf.init_delay = 17500; //default value
+      
+      if(res<=8){
+        configPcf.offset[0] = 0; //default value
+        configPcf.offset[1] = 0; //default value
+      }
+     
+      if(res < 1){
+         PrintAndLog("Usage: <password byte 1 (in hex, lsb first)> <password byte 2  (in hex, lsb first)> [...] <password byte 7  (in hex, lsb first)> <tag initialization delay (in us)> <optional : offset on the low pulses width (in us)> <optional : offset on the low pulses position (in us)>");
+         PrintAndLog("The time offsets could be usefull to correct slew rate generated by the antenna.");
+      }
+
+      PrintAndLog("Current configuration :");
+      PrintAndLog("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", configPcf.password[0], configPcf.password[1], configPcf.password[2], configPcf.password[3], configPcf.password[4], configPcf.password[5], configPcf.password[6]);
+      PrintAndLog("Tag initialization delay : %d us", configPcf.init_delay);
+      PrintAndLog("Offsets : %d us on the low pulses width, %d us on the low pulses positions", configPcf.offset[0], configPcf.offset[1]);
+
+      return 0;
+  }
+
+  //default values
+  configPcf.password[0] = 0xFF;  
+  configPcf.password[1] = 0xFF;  
+  configPcf.password[2] = 0xFF;  
+  configPcf.password[3] = 0xFF;  
+  configPcf.password[4] = 0xFF;  
+  configPcf.password[5] = 0xFF;  
+  configPcf.password[6] = 0xFF;
+
+  configPcf.init_delay = 17500;
+  configPcf.offset[0] = 0; 
+  configPcf.offset[1] = 0; 
+
+  PrintAndLog("Incorrect format");
+  PrintAndLog("Examples of right usage : lf pcf7931 config 11 22 33 44 55 66 77 20000");
+  PrintAndLog("                          lf pcf7931 config FF FF FF FF FF FF FF 17500 -10 30");
+  return 0;
+}
+
+
+
+int CmdLFPCF7931Write(const char *Cmd)
+{
+  UsbCommand c = {CMD_PCF7931_WRITE};
+
+  int res = 0;
+  res = sscanf(Cmd, "%x %x %x", &c.arg[0], &c.arg[1], &c.arg[2]);
+
+  if(res < 1) {
+      PrintAndLog("Please specify the block address in hex");
+      return 0;
+  }
+  if (res == 1){ 
+    PrintAndLog("Please specify the byte address in hex");
+     return 0;
+  }
+  if(res == 2) {
+    PrintAndLog("Please specify the data in hex (1 byte)");
+     return 0;
+  }
+  if(res == 3) {
+    uint8_t n=0;
+    for(n=0;n<7;n++)  c.d.asDwords[n] = configPcf.password[n];
+    c.d.asDwords[7] = (configPcf.offset[0]+128);
+    c.d.asDwords[8] = (configPcf.offset[1]+128);
+    c.d.asDwords[9] = configPcf.init_delay;
+    SendCommand(&c);
+    return 0;
+  }
+
+  PrintAndLog("INCORRECT FORMAT");
+  return 0;
+}
+
+
 static command_t CommandTable[] = 
 {
   {"help", CmdHelp, 1, "This help"},
   {"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"},
+  {"write", CmdLFPCF7931Write, 1, "Write data on a PCF7931 transponder. Usage : lf pcf7931 write <bloc address> <byte address> <data>"},
+   {"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"},
   {NULL, NULL, 0, NULL}
 };
 
index ed60bc9102d39b99467ac6164cd9a0882718a42b..78eaff5d28080f3dd90e57aa296211623d5257b4 100644 (file)
@@ -1,6 +1,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
-//
+//                              2015 Dake <thomas.cayrou at gmail.com>
+
 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
 // at your option, any later version. See the LICENSE.txt file for the text of
 // the license.
 #ifndef CMDLFPCF7931_H__
 #define CMDLFPCF7931_H__
 
+struct pcf7931_config{
+       uint8_t password[7];
+       uint16_t init_delay;
+       int16_t offset[2];
+};
+
 int CmdLFPCF7931(const char *Cmd);
 
 int CmdLFPCF7931Read(const char *Cmd);
 
+int CmdLFPCF7931Write(const char *Cmd);
+
+int CmdLFPCF7931Config(const char *Cmd);
+
 #endif
index 512aa13cc91d7e6e950de83346e9342900aef9a1..deced5585c6dc343ebe2d74a8e7f6e6068ba25c1 100644 (file)
@@ -97,8 +97,9 @@ void storeCommand(UsbCommand *command)
     memcpy(destination, command, sizeof(UsbCommand));
 
     cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap
-
 }
+
+
 /**
  * @brief getCommand gets a command from an internal circular buffer.
  * @param response location to write command
@@ -117,9 +118,9 @@ int getCommand(UsbCommand* response)
     cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE;
 
     return 1;
-
 }
 
+
 /**
  * Waits for a certain response type. This method waits for a maximum of
  * ms_timeout milliseconds for a specified response command.
@@ -131,33 +132,34 @@ int getCommand(UsbCommand* response)
  */
 bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) {
   
-  UsbCommand resp;
+       UsbCommand resp;
        
-       if (response == NULL)
-    response = &resp;
-
-
-  // Wait until the command is received
-  for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
+       if (response == NULL) {
+               response = &resp;
+       }
 
+       // Wait until the command is received
+       for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
                while(getCommand(response)) {
-          if(response->cmd == cmd){
-          return true;
-          }
-      }
-        msleep(10); // XXX ugh
-        if (dm_seconds == 200) { // Two seconds elapsed
-          PrintAndLog("Waiting for a response from the proxmark...");
-          PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
-        }
+                       if(response->cmd == cmd){
+                               return true;
+                       }
+               }
+               msleep(10); // XXX ugh
+               if (dm_seconds == 200) { // Two seconds elapsed
+                       PrintAndLog("Waiting for a response from the proxmark...");
+                       PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
+               }
        }
-    return false;
+       return false;
 }
 
+
 bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
        return WaitForResponseTimeout(cmd,response,-1);
 }
 
+
 //-----------------------------------------------------------------------------
 // Entry point into our code: called whenever the user types a command and
 // then presses Enter, which the full command line that they typed.
@@ -166,6 +168,7 @@ void CommandReceived(char *Cmd) {
   CmdsParse(CommandTable, Cmd);
 }
 
+
 //-----------------------------------------------------------------------------
 // Entry point into our code: called whenever we received a packet over USB
 // that we weren't necessarily expecting, for example a debug print.
@@ -189,12 +192,13 @@ void UsbCommandReceived(UsbCommand *UC)
 
                case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
                        memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
+                       return;
                } break;
 
                default:
+                       storeCommand(UC);
                        break;
        }
 
-       storeCommand(UC);
 }
 
index 4e98bd28db1854b53eaa06930c47eae527a14e85..5f34976fa41141748d41f531435ae45460f98f13 100644 (file)
@@ -20,7 +20,8 @@ local _commands = {
        CMD_BUFF_CLEAR =                                                     0x0105,
        CMD_READ_MEM =                                                       0x0106,
        CMD_VERSION =                                                        0x0107,
-
+       CMD_STATUS =                                                         0x0108,
+       CMD_PING =                                                           0x0109,
        --// For low-frequency tags
        CMD_READ_TI_TYPE =                                                   0x0202,
        CMD_WRITE_TI_TYPE =                                                  0x0203,
index 9cc865f0172f41ab099bf8ebd7836c72cb72a7cc..77f36ae453550e5d4542df8f405bcf58eefe58a6 100644 (file)
@@ -112,6 +112,8 @@ function mfcrack_inner()
                                return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
                        elseif isOK == 0xFFFFFFFD then
                                return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+                       elseif isOK == 0xFFFFFFFC then
+                               return nil, "The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
                        elseif isOK ~= 1 then 
                                return nil, "Error occurred" 
                        end
index 19c346044eab61e4b4890d9e51fb83aef41d6d1a..8bf4f3881c28c624f13ec8026f0e0a03680791e5 100644 (file)
@@ -47,6 +47,7 @@ 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);
 
 char param_getchar(const char *line, int paramnum);
+int param_getptr(const char *line, int *bg, int *en, int paramnum);
 uint8_t param_get8(const char *line, int paramnum);
 uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
 uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
diff --git a/doc/RFID_Antenna-Basic-Form.stl b/doc/RFID_Antenna-Basic-Form.stl
new file mode 100755 (executable)
index 0000000..6679ae8
Binary files /dev/null and b/doc/RFID_Antenna-Basic-Form.stl differ
diff --git a/doc/RFID_Antenna-With-Lanyard-Hook.stl b/doc/RFID_Antenna-With-Lanyard-Hook.stl
new file mode 100755 (executable)
index 0000000..62f5397
Binary files /dev/null and b/doc/RFID_Antenna-With-Lanyard-Hook.stl differ
index 3afed7c3ff77ae598500608db0274fe41babb56d..0f649a69ab40490f7b95703cceba2cac02bc964c 100644 (file)
@@ -60,6 +60,8 @@ typedef struct{
 #define CMD_BUFF_CLEAR                                                    0x0105
 #define CMD_READ_MEM                                                      0x0106
 #define CMD_VERSION                                                       0x0107
+#define CMD_STATUS                                                                                                               0x0108
+#define CMD_PING                                                                                                                 0x0109
 
 // For low-frequency tags
 #define CMD_READ_TI_TYPE                                                  0x0202
@@ -85,6 +87,7 @@ typedef struct{
 #define CMD_T55XX_WRITE_BLOCK                                             0x0215
 #define CMD_T55XX_READ_TRACE                                              0x0216
 #define CMD_PCF7931_READ                                                  0x0217
+#define CMD_PCF7931_WRITE                                                 0x0222
 #define CMD_EM4X_READ_WORD                                                0x0218
 #define CMD_EM4X_WRITE_WORD                                               0x0219
 #define CMD_IO_DEMOD_FSK                                                  0x021A
@@ -97,6 +100,7 @@ typedef struct{
 #define CMD_PSK_SIM_TAG                                                   0x0220
 #define CMD_AWID_DEMOD_FSK                                                0x0221
 
+
 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
 
 // For the 13.56 MHz tags
Impressum, Datenschutz