echo $REPOSITORY_EP;
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
sudo apt-get update -qq;
- sudo apt-get install -y gcc-arm-none-eabi;
+ sudo apt-get install -y gcc-arm-none-eabi libpcsclite-dev;
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew update;
if [[ "$REPOSITORY_EP" == "" ]]; then
#include "LCD.h"
#endif
+static uint32_t hw_capabilities;
// Craig Young - 14a stand-alone code
#ifdef WITH_ISO14443a
extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
+void set_hw_capabilities(void)
+{
+ if (I2C_is_available()) {
+ hw_capabilities |= HAS_SMARTCARD_SLOT;
+ }
+
+ if (false) { // TODO: implement a test
+ hw_capabilities |= HAS_EXTRA_FLASH_MEM;
+ }
+}
+
+
void SendVersion(void)
{
+ set_hw_capabilities();
+
char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
char VersionString[USB_CMD_DATA_SIZE] = { '\0' };
// Send Chip ID and used flash memory
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
uint32_t compressed_data_section_size = common_area.arg1;
- cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString));
+ cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, hw_capabilities, VersionString, strlen(VersionString));
}
// measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
if ( !sc_rx_bytes(card_ptr->atr, &len) )
return false;
- uint8_t pos_td = 1;
- if ( (card_ptr->atr[1] & 0x10) == 0x10) pos_td++;
- if ( (card_ptr->atr[1] & 0x20) == 0x20) pos_td++;
- if ( (card_ptr->atr[1] & 0x40) == 0x40) pos_td++;
-
- // T0 indicate presence T=0 vs T=1. T=1 has checksum TCK
- if ( (card_ptr->atr[1] & 0x80) == 0x80) {
-
- pos_td++;
-
- // 1 == T1 , presence of checksum TCK
- if ( (card_ptr->atr[pos_td] & 0x01) == 0x01) {
- uint8_t chksum = 0;
- // xor property. will be zero when xored with chksum.
- for (uint8_t i = 1; i < len; ++i)
- chksum ^= card_ptr->atr[i];
- if ( chksum ) {
- if ( MF_DBGLEVEL > 2) DbpString("Wrong ATR checksum");
- }
- }
- }
-
card_ptr->atr_len = len;
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
include ../common/Makefile_Enabled_Options.common
CFLAGS += $(APP_CFLAGS)
ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
- SRC_SMARTCARD = cmdsmartcard.c
+ SRC_SMARTCARD = cmdsmartcard.c pcsc.c
else
SRC_SMARTCARD =
endif
-LUAPLATFORM = generic
platform = $(shell uname)
+
+ifneq (,$(findstring MINGW,$(platform)))
+ PCSC_INCLUDES :=
+ PCSC_LIBS = -lwinscard
+else
+ ifeq ($(platform),Darwin)
+ PCSC_INCLUDES =
+ PCSC_LIBS = -framework PCSC
+ else
+ PCSC_INCLUDES := $(shell pkg-config --cflags libpcsclite)
+ PCSC_LIBS := $(shell pkg-config --libs libpcsclite)
+ endif
+endif
+
+LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform)))
LUAPLATFORM = mingw
else
all-static: LDLIBS:=-static $(LDLIBS)
all-static: proxmark3 flasher fpga_compress
-proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(QTLDLIBS)
+proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(QTLDLIBS) $(PCSC_LIBS)
proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua
$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@
%.o: %.c
$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d
- $(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $<
+ $(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) $(PCSC_INCLUDES) -c -o $@ $<
$(POSTCOMPILE)
%.o: %.cpp
#include "cmdmain.h"
#include "cmddata.h"
-/* low-level hardware control */
+
+static uint32_t hw_capabilities = 0;
static int CmdHelp(const char *Cmd);
return CmdTuneSamples(Cmd);
}
+bool PM3hasSmartcardSlot(void) {
+ return (hw_capabilities & HAS_SMARTCARD_SLOT);
+}
+
int CmdVersion(const char *Cmd)
{
UsbCommand resp = {0, {0, 0, 0}};
SendCommand(&c);
- if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
+ if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
PrintAndLog("Prox/RFID mark3 RFID instrument");
PrintAndLog((char*)resp.d.asBytes);
lookupChipID(resp.arg[0], resp.arg[1]);
+ hw_capabilities = resp.arg[2];
}
return 0;
}
#ifndef CMDHW_H__
#define CMDHW_H__
+#include <stdbool.h>
+
int CmdHW(const char *Cmd);
int CmdDetectReader(const char *Cmd);
int CmdSetMux(const char *Cmd);
int CmdTune(const char *Cmd);
int CmdVersion(const char *Cmd);
+bool PM3hasSmartcardSlot(void);
#endif
#include "smartcard.h"
#include "comms.h"
#include "protocols.h"
+#include "cmdhw.h"
#include "cmdhflist.h"
#include "emv/apduinfo.h" // APDUcode description
#include "emv/emvcore.h" // decodeTVL
#include "crypto/libpcrypto.h" // sha512hash
#include "emv/dump.h" // dump_buffer
+#include "pcsc.h"
#define SC_UPGRADE_FILES_DIRECTORY "sc_upgrade_firmware/"
+static bool UseAlternativeSmartcardReader = false; // default: use PM3 RDV40 Smartcard Slot (if available)
+
static int CmdHelp(const char *Cmd);
static int usage_sm_raw(void) {
return 0;
}
+static int usage_sm_select(void) {
+ PrintAndLogEx(NORMAL, "Usage: sc select [h|<reader name>] ");
+ PrintAndLogEx(NORMAL, " h : this help");
+ PrintAndLogEx(NORMAL, " <reader name> : a card reader's name, wildcards allowed, leave empty to pick from available readers");
+ PrintAndLogEx(NORMAL, "");
+ PrintAndLogEx(NORMAL, "Examples:");
+ PrintAndLogEx(NORMAL, " sc select : list available card readers and pick");
+ PrintAndLogEx(NORMAL, " sc select Gemalto* : select a connected Gemalto card reader" );
+ return 0;
+}
+
static int usage_sm_reader(void) {
PrintAndLogEx(NORMAL, "Usage: sc reader [h|s]");
PrintAndLogEx(NORMAL, " h : this help");
uint8_t T0 = atr[1];
uint8_t K = T0 & 0x0F;
uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0;
+ bool protocol_T0_present = true;
+ bool protocol_T15_present = false;
if (T0 & 0x10) {
PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]);
if (T0 & 0x80) {
TD1 = atr[2 + T1len];
PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f);
+ protocol_T0_present = false;
+ if ((TD1 & 0x0f) == 0) {
+ protocol_T0_present = true;
+ }
+ if ((TD1 & 0x0f) == 15) {
+ protocol_T15_present = true;
+ }
+
T1len++;
if (TD1 & 0x10) {
if (TD1 & 0x80) {
uint8_t TDi = atr[2 + T1len + TD1len];
PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f);
+ if ((TDi & 0x0f) == 0) {
+ protocol_T0_present = true;
+ }
+ if ((TDi & 0x0f) == 15) {
+ protocol_T15_present = true;
+ }
TD1len++;
bool nextCycle = true;
}
}
- uint8_t vxor = 0;
- for (int i = 1; i < atrlen; i++)
- vxor ^= atr[i];
+ if (!protocol_T0_present || protocol_T15_present) { // there is CRC Check Byte TCK
+ uint8_t vxor = 0;
+ for (int i = 1; i < atrlen; i++)
+ vxor ^= atr[i];
+
+ if (vxor)
+ PrintAndLogEx(WARNING, "Check sum error. Must be 0 got 0x%02X", vxor);
+ else
+ PrintAndLogEx(INFO, "Check sum OK.");
+ }
- if (vxor)
- PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor);
- else
- PrintAndLogEx(INFO, "Check summ OK.");
-
if (atr[0] != 0x3b)
PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]);
-
uint8_t calen = 2 + T1len + TD1len + TDilen + K;
if (atrlen != calen && atrlen != calen + 1) // may be CRC
PrintAndLogEx(ERR, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K);
if (K > 0)
- PrintAndLogEx(INFO, "\nHistorical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]);
+ PrintAndLogEx(INFO, "\nHistorical bytes | len %02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]);
if (K > 1) {
PrintAndLogEx(INFO, "\tHistorical bytes");
return 0;
}
-static bool smart_select(bool silent) {
- UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
- clearCommandBuffer();
- SendCommand(&c);
- UsbCommand resp;
- if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
- if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
- return false;
+static bool smart_getATR(smart_card_atr_t *card)
+{
+ if (UseAlternativeSmartcardReader) {
+ return pcscGetATR(card);
+ } else {
+ UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
+ SendCommand(&c);
+
+ UsbCommand resp;
+ if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
+ return false;
+ }
+
+ if (resp.arg[0] & 0xff) {
+ return resp.arg[0] & 0xFF;
+ }
+
+ memcpy(card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
+
+ return true;
}
+}
- uint8_t isok = resp.arg[0] & 0xFF;
- if (!isok) {
+static bool smart_select(bool silent) {
+
+ smart_card_atr_t card;
+ if (!smart_getATR(&card)) {
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
return false;
}
if (!silent) {
- smart_card_atr_t card;
- memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
-
PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
}
return datalen;
}
+
+int CmdSmartSelect(const char *Cmd) {
+
+ const char *readername;
+
+ if (tolower(param_getchar(Cmd, 0)) == 'h') {
+ return usage_sm_select();
+ }
+
+ if (!PM3hasSmartcardSlot() && !pcscCheckForCardReaders()) {
+ PrintAndLogEx(WARNING, "No Smartcard Readers available");
+ UseAlternativeSmartcardReader = false;
+ return 1;
+ }
+
+ int bg, en;
+ if (param_getptr(Cmd, &bg, &en, 0)) {
+ UseAlternativeSmartcardReader = pcscSelectAlternativeCardReader(NULL);
+ } else {
+ readername = Cmd + bg;
+ UseAlternativeSmartcardReader = pcscSelectAlternativeCardReader(readername);
+ }
+
+ return 0;
+}
+
int CmdSmartRaw(const char *Cmd) {
int hexlen = 0;
//Validations
if (errors ) return usage_sm_info();
- UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
- clearCommandBuffer();
- SendCommand(&c);
- UsbCommand resp;
- if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
- if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
- return 1;
- }
-
- uint8_t isok = resp.arg[0] & 0xFF;
- if (!isok) {
+ smart_card_atr_t card;
+ if (!smart_getATR(&card)) {
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
return 1;
}
- smart_card_atr_t card;
- memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
-
// print header
PrintAndLogEx(INFO, "--- Smartcard Information ---------");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
//Validations
if (errors ) return usage_sm_reader();
- UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
- clearCommandBuffer();
- SendCommand(&c);
- UsbCommand resp;
- if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
- if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
- return 1;
- }
-
- uint8_t isok = resp.arg[0] & 0xFF;
- if (!isok) {
+ smart_card_atr_t card;
+ if (!smart_getATR(&card)) {
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
return 1;
}
- smart_card_atr_t card;
- memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
return 0;
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
+ {"select", CmdSmartSelect, 1, "Select the Smartcard Reader to use"},
{"list", CmdSmartList, 0, "List ISO 7816 history"},
{"info", CmdSmartInfo, 0, "Tag information"},
{"reader", CmdSmartReader, 0, "Act like an IS07816 reader"},
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2019 piwi
+//
+// 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.
+//-----------------------------------------------------------------------------
+// PCSC functions to use alternative Smartcard Readers
+//-----------------------------------------------------------------------------
+
+#include "pcsc.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined (__APPLE__)
+#include <PCSC/winscard.h>
+#include <PCSC/wintypes.h>
+#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
+#define SCARD_CLASS_ICC_STATE 9
+#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303)
+#elif defined (_WIN32)
+#include <winscard.h>
+#else
+#include <winscard.h>
+#include <reader.h>
+#endif
+
+#include "ui.h"
+#include "util.h"
+#include "cmdhw.h"
+
+static SCARDCONTEXT SC_Context;
+static SCARDHANDLE SC_Card;
+static DWORD SC_Protocol;
+static char* AlternativeSmartcardReader = NULL;
+
+
+char *getAlternativeSmartcardReader(void)
+{
+ return AlternativeSmartcardReader;
+}
+
+
+bool pcscCheckForCardReaders(void)
+{
+ LONG res = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &SC_Context);
+ if (res != SCARD_S_SUCCESS) {
+ return false;
+ }
+
+ DWORD pcchReaders;
+ res = SCardListReaders(SC_Context, NULL, NULL, &pcchReaders);
+ if (res != SCARD_S_SUCCESS) {
+ SCardReleaseContext(SC_Context);
+ return false;
+ }
+
+ if (res == SCARD_E_NO_READERS_AVAILABLE || res == SCARD_E_NO_SERVICE) {
+ SCardReleaseContext(SC_Context);
+ return false;
+ }
+
+ return true;
+}
+
+
+static char *pickReader(LPTSTR readerlist)
+{
+ PrintAndLogEx(NORMAL, "Please select one of these:");
+ PrintAndLogEx(NORMAL, " [0] PM3 RDV40 Smartcard Slot %s", PM3hasSmartcardSlot() ? "(default)" : "(default, not available)");
+
+ int num = 1;
+ for (LPTSTR p = readerlist; *p != '\0'; ) {
+ PrintAndLogEx(NORMAL, " [%1d] %s", num++, p);
+ while (*p++ != '\0') ; // advance to next entry
+ }
+
+ num--;
+
+ if (num == 1) {
+ printf("Your choice (0 or 1)?");
+ } else {
+ printf("Your choice (0...%d)? ", num);
+ }
+ int selection = getch() - '0';
+ printf("\n");
+
+ if (selection == 0) {
+ PrintAndLogEx(INFO, "Selected RDV40 Smartcard Slot");
+ return NULL;
+ }
+
+ if (selection >= 1 && selection <= num) {
+ LPTSTR p = readerlist;
+ for (int i = 1; i < selection; i++) {
+ while (*p++ != '\0') ; // advance to next entry
+ }
+ PrintAndLogEx(INFO, "Selected %s", p);
+ return p;
+ }
+
+ PrintAndLogEx(INFO, "Invalid selection. Using RDV40 Smartcard Slot");
+ return NULL;
+
+}
+
+
+char *matchString(LPTSTR readerlist, const char *readername)
+{
+ return pickReader(readerlist);
+}
+
+
+bool pcscSelectAlternativeCardReader(const char *readername)
+{
+ DWORD readerlist_len;
+ LONG res = SCardListReaders(SC_Context, NULL, NULL, &readerlist_len);
+ if (res != SCARD_S_SUCCESS) {
+ return false;
+ }
+
+ LPTSTR readerlist = calloc(readerlist_len, sizeof(char));
+ res = SCardListReaders(SC_Context, NULL, readerlist, &readerlist_len);
+ if (res != SCARD_S_SUCCESS) {
+ free(readerlist);
+ return false;
+ }
+
+ char *selected_readername = NULL;
+ if (readername) {
+ selected_readername = matchString(readerlist, readername);
+ } else {
+ selected_readername = pickReader(readerlist);
+ }
+
+ if (selected_readername == NULL) {
+ free(readerlist);
+ return false;
+ }
+
+ free(AlternativeSmartcardReader);
+ AlternativeSmartcardReader = malloc((strlen(selected_readername) + 1) * sizeof(char));
+ strcpy(AlternativeSmartcardReader, selected_readername);
+
+ return true;
+}
+
+
+bool pcscGetATR(smart_card_atr_t *card)
+{
+ if (!card) {
+ return false;
+ }
+
+ card->atr_len = 0;
+ memset(card->atr, 0, sizeof(card->atr));
+
+ LONG res = SCardConnect(SC_Context, AlternativeSmartcardReader, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &SC_Card, &SC_Protocol);
+ if (res != SCARD_S_SUCCESS) {
+ return false;
+ }
+
+ DWORD atr_len = sizeof(card->atr);
+ res = SCardGetAttrib(SC_Card, SCARD_ATTR_ATR_STRING, card->atr, &atr_len);
+ if (res != SCARD_S_SUCCESS) {
+ return false;
+ }
+ card->atr_len = atr_len;
+
+ // TODO: LogTrace without device
+
+ return true;
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2019 piwi
+//
+// 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.
+//-----------------------------------------------------------------------------
+// PCSC functions to use alternative Smartcard Readers
+//-----------------------------------------------------------------------------
+
+#ifndef PCSC_H__
+#define PCSC_H__
+
+#include <stdbool.h>
+#include "smartcard.h"
+
+char *getAlternativeSmartcardReader(void);
+bool pcscCheckForCardReaders(void);
+bool pcscSelectAlternativeCardReader(const char *readername);
+bool pcscGetATR(smart_card_atr_t *card);
+
+#endif
#include "cmdhw.h"
#include "whereami.h"
#include "comms.h"
+#include "pcsc.h"
+
void
#ifdef __has_attribute
SetOffline(true);
}
+
// file with script
FILE *script_file = NULL;
char script_cmd_buf[256] = {0}; // iceman, needs lua script the same file_path_buffer as the rest
return ( error == 0 ? cnt : -1 );
}
-#else
+char getch(void)
+{
+ char c;
+ int error;
+ struct termios Otty, Ntty;
+ if ( tcgetattr(STDIN_FILENO, &Otty) == -1 ) return -1;
+ Ntty = Otty;
+ Ntty.c_lflag &= ~ICANON; /* disable buffered i/o */
+ if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) { // set new attributes
+ c = getchar();
+ error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes
+ }
+ return ( error == 0 ? c : -1 );
+}
+
+#else // _WIN32
#include <conio.h>
int ukbhit(void) {
#endif
extern int ukbhit(void);
+#ifndef _WIN32
+extern char getch(void);
+#else
+#include <conio.h>
+#endif
extern void AddLogLine(char *fileName, char *extData, char *c);
extern void AddLogHex(char *fileName, char *extData, const uint8_t * data, const size_t len);
#ifndef __SMARTCARD_H
#define __SMARTCARD_H
+#include <stdint.h>
+
//-----------------------------------------------------------------------------
// ISO 7618 Smart Card
//-----------------------------------------------------------------------------
uint32_t asDwords[USB_CMD_DATA_SIZE/4];
} d;
} PACKED UsbCommand;
+
// A struct used to send sample-configs over USB
typedef struct{
uint8_t decimation;
#define CMD_STATUS 0x0108
#define CMD_PING 0x0109
+// controlling the ADC input multiplexer
+#define CMD_SET_ADC_MUX 0x020F
+
// RDV40, Smart card operations
#define CMD_SMART_RAW 0x0140
#define CMD_SMART_UPGRADE 0x0141
#define CMD_HID_SIM_TAG 0x020C
#define CMD_SET_LF_DIVISOR 0x020D
#define CMD_LF_SIMULATE_BIDIR 0x020E
-#define CMD_SET_ADC_MUX 0x020F
#define CMD_HID_CLONE_TAG 0x0210
#define CMD_EM410X_WRITE_TAG 0x0211
#define CMD_INDALA_CLONE_TAG 0x0212
#define CMD_VIKING_CLONE_TAG 0x0223
#define CMD_T55XX_WAKEUP 0x0224
#define CMD_COTAG 0x0225
-// misc extra
#define CMD_PARADOX_CLONE_TAG 0x0226
-
-/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
-
// For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
#define CMD_READ_SRI512_TAG 0x0303
#define CMD_SNOOP_HITAG 0x0370
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
-
#define CMD_SIMULATE_HITAG_S 0x0368
#define CMD_TEST_HITAGS_TRACES 0x0367
#define CMD_READ_HITAG_S 0x0373
#define CMD_WR_HITAG_S 0x0375
#define CMD_EMU_HITAG_S 0x0376
-
#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
#define FLAG_TUNE_HF 2
#define FLAG_TUNE_ALL 3
+// Hardware capabilities
+#define HAS_EXTRA_FLASH_MEM (1 << 0)
+#define HAS_SMARTCARD_SLOT (1 << 1)
+
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
/* Whether a bootloader that understands the common_area is present */