mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
chg: i2c fixes. all working.
chg: 'sc info' now prints url to atr decoder. chg: 'sc reader' has more options A, S
This commit is contained in:
parent
0d8e3160f8
commit
714de99f82
5 changed files with 104 additions and 81 deletions
|
@ -894,14 +894,14 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
||||||
if ((cmd[i]>='0' && cmd[i]<='9') ||
|
if ((cmd[i]>='0' && cmd[i]<='9') ||
|
||||||
(cmd[i]>='a' && cmd[i]<='f') ||
|
(cmd[i]>='a' && cmd[i]<='f') ||
|
||||||
(cmd[i]>='A' && cmd[i]<='F') ) {
|
(cmd[i]>='A' && cmd[i]<='F') ) {
|
||||||
buf[strlen(buf)+1]=0;
|
buf[strlen(buf)+1] = 0;
|
||||||
buf[strlen(buf)]=cmd[i];
|
buf[strlen(buf)] = cmd[i];
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (strlen(buf)>=2) {
|
if (strlen(buf) >= 2) {
|
||||||
sscanf(buf,"%x",&temp);
|
sscanf(buf, "%x", &temp);
|
||||||
data[datalen]=(uint8_t)(temp & 0xff);
|
data[datalen] = (uint8_t)(temp & 0xff);
|
||||||
*buf=0;
|
*buf = 0;
|
||||||
if (++datalen >= sizeof(data)){
|
if (++datalen >= sizeof(data)){
|
||||||
if (crc)
|
if (crc)
|
||||||
PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data");
|
PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data");
|
||||||
|
@ -914,7 +914,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crc && datalen>0 && datalen < sizeof(data)-2) {
|
if (crc && datalen > 0 && datalen < sizeof(data)-2) {
|
||||||
uint8_t first, second;
|
uint8_t first, second;
|
||||||
if (topazmode) {
|
if (topazmode) {
|
||||||
compute_crc(CRC_14443_B, data, datalen, &first, &second);
|
compute_crc(CRC_14443_B, data, datalen, &first, &second);
|
||||||
|
@ -989,7 +989,7 @@ static int waitCmd(uint8_t iSelect) {
|
||||||
PrintAndLogEx(WARNING, "Can't select card.");
|
PrintAndLogEx(WARNING, "Can't select card.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(NORMAL, "received %i bytes:", len);
|
PrintAndLogEx(NORMAL, "received %i bytes", len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
|
|
|
@ -15,6 +15,8 @@ int usage_sm_raw(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>");
|
PrintAndLogEx(NORMAL, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>");
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
PrintAndLogEx(NORMAL, " h : this help");
|
||||||
PrintAndLogEx(NORMAL, " r : do not read response");
|
PrintAndLogEx(NORMAL, " r : do not read response");
|
||||||
|
PrintAndLogEx(NORMAL, " a : active signal field ON without select");
|
||||||
|
PrintAndLogEx(NORMAL, " s : active signal field ON with select");
|
||||||
PrintAndLogEx(NORMAL, " d <bytes> : bytes to send");
|
PrintAndLogEx(NORMAL, " d <bytes> : bytes to send");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
|
@ -53,6 +55,8 @@ int usage_sm_upgrade(void) {
|
||||||
int CmdSmartRaw(const char *Cmd) {
|
int CmdSmartRaw(const char *Cmd) {
|
||||||
|
|
||||||
int hexlen = 0;
|
int hexlen = 0;
|
||||||
|
bool active = false;
|
||||||
|
bool active_select = false;
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
bool errors = false, reply = true;
|
bool errors = false, reply = true;
|
||||||
uint8_t data[USB_CMD_DATA_SIZE] = {0x00};
|
uint8_t data[USB_CMD_DATA_SIZE] = {0x00};
|
||||||
|
@ -64,6 +68,14 @@ int CmdSmartRaw(const char *Cmd) {
|
||||||
reply = false;
|
reply = false;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
case 'a':
|
||||||
|
active = true;
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
active_select = true;
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
case 'd': {
|
case 'd': {
|
||||||
switch (param_gethex_to_eol(Cmd, cmdp+1, data, sizeof(data), &hexlen)) {
|
switch (param_gethex_to_eol(Cmd, cmdp+1, data, sizeof(data), &hexlen)) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -92,6 +104,17 @@ int CmdSmartRaw(const char *Cmd) {
|
||||||
// arg0 = RFU flags
|
// arg0 = RFU flags
|
||||||
// arg1 = length
|
// arg1 = length
|
||||||
UsbCommand c = {CMD_SMART_RAW, {0, hexlen, 0}};
|
UsbCommand c = {CMD_SMART_RAW, {0, hexlen, 0}};
|
||||||
|
|
||||||
|
if (active || active_select) {
|
||||||
|
c.arg[0] |= SC_CONNECT;
|
||||||
|
if (active)
|
||||||
|
c.arg[0] |= SC_NO_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hexlen > 0) {
|
||||||
|
c.arg[0] |= SC_RAW;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(c.d.asBytes, data, hexlen );
|
memcpy(c.d.asBytes, data, hexlen );
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
@ -103,14 +126,14 @@ int CmdSmartRaw(const char *Cmd) {
|
||||||
PrintAndLogEx(WARNING, "smart card response failed");
|
PrintAndLogEx(WARNING, "smart card response failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
uint32_t len = resp.arg[0];
|
||||||
|
|
||||||
if ( !resp.arg[0] ) {
|
if ( !len ) {
|
||||||
PrintAndLogEx(WARNING, "smart card response failed");
|
PrintAndLogEx(WARNING, "smart card response failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t len = resp.arg[1];
|
PrintAndLogEx(INFO, "received %i bytes", len);
|
||||||
PrintAndLogEx(INFO, "received %i bytes:", len);
|
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -246,7 +269,7 @@ int CmdSmartInfo(const char *Cmd){
|
||||||
}
|
}
|
||||||
|
|
||||||
//Validations
|
//Validations
|
||||||
if (errors || cmdp == 0 ) return usage_sm_info();
|
if (errors ) return usage_sm_info();
|
||||||
|
|
||||||
UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
|
UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -269,8 +292,9 @@ int CmdSmartInfo(const char *Cmd){
|
||||||
// print header
|
// print header
|
||||||
PrintAndLogEx(INFO, "\n--- Smartcard Information ---------");
|
PrintAndLogEx(INFO, "\n--- Smartcard Information ---------");
|
||||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||||
PrintAndLogEx(INFO, "ATR : %s", sprint_hex(card.atr, card.atr_len));
|
PrintAndLogEx(INFO, "ISO76183 ATR : %s", sprint_hex(card.atr, card.atr_len));
|
||||||
PrintAndLogEx(INFO, "\n todo - look up ATR ");
|
PrintAndLogEx(INFO, "look up ATR");
|
||||||
|
PrintAndLogEx(INFO, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len) );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,8 +336,7 @@ int CmdSmartReader(const char *Cmd){
|
||||||
smart_card_atr_t card;
|
smart_card_atr_t card;
|
||||||
memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
|
memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "ATR : %s", sprint_hex(card.atr, card.atr_len));
|
PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
88
common/i2c.c
88
common/i2c.c
|
@ -40,6 +40,9 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
||||||
#define I2C_DELAY_2CLK I2CSpinDelayClk(2)
|
#define I2C_DELAY_2CLK I2CSpinDelayClk(2)
|
||||||
#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
|
#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
|
||||||
|
|
||||||
|
|
||||||
|
#define ISO7618_MAX_FRAME 255
|
||||||
|
|
||||||
void I2C_init(void) {
|
void I2C_init(void) {
|
||||||
// 配置复位引脚,关闭上拉,推挽输出,默认高
|
// 配置复位引脚,关闭上拉,推挽输出,默认高
|
||||||
// Configure reset pin, close up pull up, push-pull output, default high
|
// Configure reset pin, close up pull up, push-pull output, default high
|
||||||
|
@ -125,12 +128,9 @@ bool WaitSCL_H(void) {
|
||||||
bool WaitSCL_L_300ms(void){
|
bool WaitSCL_L_300ms(void){
|
||||||
volatile uint16_t delay = 300;
|
volatile uint16_t delay = 300;
|
||||||
while ( delay-- ) {
|
while ( delay-- ) {
|
||||||
|
|
||||||
// exit on SCL LOW
|
// exit on SCL LOW
|
||||||
if (!SCL_read) {
|
if (!SCL_read)
|
||||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("300ms SCL delay counter %d", delay);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
SpinDelay(1);
|
SpinDelay(1);
|
||||||
}
|
}
|
||||||
|
@ -155,17 +155,14 @@ bool I2C_Start(void) {
|
||||||
|
|
||||||
bool I2C_WaitForSim() {
|
bool I2C_WaitForSim() {
|
||||||
// variable delay here.
|
// variable delay here.
|
||||||
if (!WaitSCL_L_300ms()) {
|
if (!WaitSCL_L_300ms())
|
||||||
if ( MF_DBGLEVEL > 3 ) DbpString(" 300ms SCL delay - timed out");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// 8051 speaks with smart card.
|
// 8051 speaks with smart card.
|
||||||
// 1000*50*3.07 = 153.5ms
|
// 1000*50*3.07 = 153.5ms
|
||||||
if (!WaitSCL_H_delay(1000*50) ) {
|
if (!WaitSCL_H_delay(1000*50) )
|
||||||
if ( MF_DBGLEVEL > 3 ) DbpString("wait for SCL HIGH - timed out");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +175,7 @@ void I2C_Stop(void) {
|
||||||
SDA_H;
|
SDA_H;
|
||||||
I2C_DELAY_XCLK(8);
|
I2C_DELAY_XCLK(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send i2c ACK
|
// Send i2c ACK
|
||||||
void I2C_Ack(void) {
|
void I2C_Ack(void) {
|
||||||
SCL_L; I2C_DELAY_2CLK;
|
SCL_L; I2C_DELAY_2CLK;
|
||||||
|
@ -400,7 +398,6 @@ uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
|
||||||
// 读取的第一个字节为后续长度
|
// 读取的第一个字节为后续长度
|
||||||
// The first byte in response is the message length
|
// The first byte in response is the message length
|
||||||
if (!readcount && (len > *data)) {
|
if (!readcount && (len > *data)) {
|
||||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("Old len %d , Repsonse message len %d", len, *data);
|
|
||||||
len = *data;
|
len = *data;
|
||||||
} else {
|
} else {
|
||||||
data++;
|
data++;
|
||||||
|
@ -523,18 +520,15 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_print_status(void) {
|
void I2C_print_status(void) {
|
||||||
|
|
||||||
DbpString("Smart card module (ISO 7816)");
|
DbpString("Smart card module (ISO 7816)");
|
||||||
uint8_t resp[] = {0,0,0};
|
uint8_t resp[] = {0,0,0,0};
|
||||||
I2C_init();
|
I2C_init();
|
||||||
I2C_Reset_EnterMainProgram();
|
I2C_Reset_EnterMainProgram();
|
||||||
uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN);
|
uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN);
|
||||||
if ( len > 0 ) {
|
if ( len > 0 )
|
||||||
Dbprintf(" version.................v%x.%02x", resp[0], resp[1]);
|
Dbprintf(" version. ................v%x.%02x", resp[0], resp[1]);
|
||||||
LogTrace(resp, len, 0, 0, NULL, false);
|
else
|
||||||
} else {
|
|
||||||
DbpString(" version.................FAILED");
|
DbpString(" version.................FAILED");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetATR(smart_card_atr_t *card_ptr) {
|
bool GetATR(smart_card_atr_t *card_ptr) {
|
||||||
|
@ -559,8 +553,6 @@ bool GetATR(smart_card_atr_t *card_ptr) {
|
||||||
if ( len == 0 )
|
if ( len == 0 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("counter %d", len);
|
|
||||||
if ( card_ptr ) {
|
if ( card_ptr ) {
|
||||||
card_ptr->atr_len = len;
|
card_ptr->atr_len = len;
|
||||||
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
|
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
|
||||||
|
@ -576,59 +568,61 @@ void SmartCardAtr(void) {
|
||||||
I2C_Reset_EnterMainProgram();
|
I2C_Reset_EnterMainProgram();
|
||||||
bool isOK = GetATR( &card );
|
bool isOK = GetATR( &card );
|
||||||
cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||||
LED_D_OFF();
|
set_tracing(false);
|
||||||
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) {
|
void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) {
|
||||||
|
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
|
||||||
|
smartcard_command_t flags = arg0;
|
||||||
|
|
||||||
|
if ((flags & SC_CONNECT))
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
//uint64_t flags = arg0;
|
|
||||||
|
|
||||||
#define ISO7618_MAX_FRAME 255
|
|
||||||
I2C_Reset_EnterMainProgram();
|
|
||||||
|
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME);
|
uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME);
|
||||||
|
|
||||||
smart_card_atr_t card;
|
if ((flags & SC_CONNECT)) {
|
||||||
bool isOK = GetATR( &card );
|
|
||||||
if ( !isOK )
|
I2C_Reset_EnterMainProgram();
|
||||||
goto out;
|
|
||||||
|
if ( !(flags & SC_NO_SELECT) ) {
|
||||||
|
smart_card_atr_t card;
|
||||||
|
bool gotATR = GetATR( &card );
|
||||||
|
//cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||||
|
if ( !gotATR )
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & SC_RAW)) {
|
||||||
|
|
||||||
// log raw bytes
|
|
||||||
LogTrace(data, arg1, 0, 0, NULL, true);
|
LogTrace(data, arg1, 0, 0, NULL, true);
|
||||||
|
|
||||||
// Send raw bytes
|
// Send raw bytes
|
||||||
// start [C0 02] A0 A4 00 00 02 stop
|
|
||||||
// asBytes = A0 A4 00 00 02
|
// asBytes = A0 A4 00 00 02
|
||||||
// arg1 = len 5
|
// arg1 = len 5
|
||||||
I2C_BufferWrite(data, arg1, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN);
|
I2C_BufferWrite(data, arg1, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN);
|
||||||
|
|
||||||
//wait for sim card to answer.
|
//wait for sim card to answer.
|
||||||
isOK = I2C_WaitForSim();
|
if ( !I2C_WaitForSim() )
|
||||||
if ( !isOK )
|
goto OUT;
|
||||||
goto out;
|
|
||||||
|
|
||||||
// read response
|
// read response
|
||||||
// start [C0 03 start C1 len aa bb cc stop]
|
// start [C0 03 start C1 len aa bb cc stop]
|
||||||
len = I2C_BufferRead(resp, ISO7618_MAX_FRAME, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
|
len = I2C_BufferRead(resp, ISO7618_MAX_FRAME, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
|
||||||
|
|
||||||
if ( len == 0)
|
|
||||||
isOK = false;
|
|
||||||
|
|
||||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("counter %d", len);
|
|
||||||
|
|
||||||
out:
|
|
||||||
cmd_send(CMD_ACK, isOK, len, 0, resp, len);
|
|
||||||
|
|
||||||
// log answer
|
|
||||||
if ( len )
|
|
||||||
LogTrace(resp, len, 0, 0, NULL, false);
|
LogTrace(resp, len, 0, 0, NULL, false);
|
||||||
|
}
|
||||||
|
|
||||||
LED_D_OFF();
|
OUT:
|
||||||
|
cmd_send(CMD_ACK, len, 0, 0, resp, len);
|
||||||
|
set_tracing(false);
|
||||||
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmartCardUpgrade(uint64_t arg0) {
|
void SmartCardUpgrade(uint64_t arg0) {
|
||||||
|
@ -653,7 +647,7 @@ void SmartCardUpgrade(uint64_t arg0) {
|
||||||
uint8_t msb = (pos >> 8) & 0xFF;
|
uint8_t msb = (pos >> 8) & 0xFF;
|
||||||
uint8_t lsb = pos & 0xFF;
|
uint8_t lsb = pos & 0xFF;
|
||||||
|
|
||||||
Dbprintf("FW %02X %02X", msb, lsb);
|
Dbprintf("FW %02X%02X", msb, lsb);
|
||||||
|
|
||||||
size_t size = MIN(I2C_BLOCK_SIZE, length);
|
size_t size = MIN(I2C_BLOCK_SIZE, length);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
|
#include "mifare.h"
|
||||||
|
|
||||||
#define I2C_DEVICE_ADDRESS_BOOT 0xB0
|
#define I2C_DEVICE_ADDRESS_BOOT 0xB0
|
||||||
#define I2C_DEVICE_ADDRESS_MAIN 0xC0
|
#define I2C_DEVICE_ADDRESS_MAIN 0xC0
|
||||||
|
|
|
@ -56,7 +56,6 @@ typedef struct {
|
||||||
byte_t cid;
|
byte_t cid;
|
||||||
} __attribute__((__packed__)) iso14b_card_select_t;
|
} __attribute__((__packed__)) iso14b_card_select_t;
|
||||||
|
|
||||||
|
|
||||||
typedef enum ISO14B_COMMAND {
|
typedef enum ISO14B_COMMAND {
|
||||||
ISO14B_CONNECT = (1 << 0),
|
ISO14B_CONNECT = (1 << 0),
|
||||||
ISO14B_DISCONNECT = (1 << 1),
|
ISO14B_DISCONNECT = (1 << 1),
|
||||||
|
@ -106,6 +105,13 @@ typedef struct {
|
||||||
uint8_t atr[30];
|
uint8_t atr[30];
|
||||||
} __attribute__((__packed__)) smart_card_atr_t;
|
} __attribute__((__packed__)) smart_card_atr_t;
|
||||||
|
|
||||||
|
typedef enum SMARTCARD_COMMAND {
|
||||||
|
SC_CONNECT = (1 << 0),
|
||||||
|
SC_NO_DISCONNECT = (1 << 1),
|
||||||
|
SC_RAW = (1 << 2),
|
||||||
|
SC_NO_SELECT = (1 << 3)
|
||||||
|
} smartcard_command_t;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// FeliCa
|
// FeliCa
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue