mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Merge pull request #3096 from kormax/felica-ng-frames
felica: use NG frames for commands
This commit is contained in:
+68
-27
@@ -62,14 +62,19 @@ static uint32_t iso18092_get_timeout(void) {
|
||||
return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) - 2;
|
||||
}
|
||||
|
||||
#ifndef FELICA_MAX_FRAME_SIZE
|
||||
// 255 base length (max 254 data + 1 len byte) + 2 sync + 2 crc + 1 extra for safety
|
||||
#define FELICA_MAX_FRAME_SIZE 260
|
||||
#ifndef FELICA_MAX_DATA_SIZE
|
||||
// FeliCa length byte includes itself, so application level payload max is 254 bytes.
|
||||
#define FELICA_MAX_DATA_SIZE 254
|
||||
#endif
|
||||
|
||||
#ifndef FELICA_MAX_RF_FRAME_SIZE
|
||||
// 255 base length (max 254 data + 1 len byte) + 2 sync + 2 crc + 1 extra for safety.
|
||||
#define FELICA_MAX_RF_FRAME_SIZE 260
|
||||
#endif
|
||||
|
||||
|
||||
//structure to hold outgoing NFC frame
|
||||
static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE];
|
||||
static uint8_t frameSpace[FELICA_MAX_RF_FRAME_SIZE];
|
||||
|
||||
//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
|
||||
static struct {
|
||||
@@ -492,7 +497,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||
#endif
|
||||
// allocate command receive buffer
|
||||
BigBuf_free();
|
||||
FelicaFrameinit(BigBuf_calloc(FELICA_MAX_FRAME_SIZE));
|
||||
FelicaFrameinit(BigBuf_calloc(FELICA_MAX_RF_FRAME_SIZE));
|
||||
|
||||
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; // 418
|
||||
// iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card
|
||||
@@ -533,14 +538,30 @@ static void felica_reset_frame_mode(void) {
|
||||
//-----------------------------------------------------------------------------
|
||||
// RAW FeliCa commands. Send out commands and store answers.
|
||||
//-----------------------------------------------------------------------------
|
||||
// arg0 FeliCa flags
|
||||
// arg1 len of commandbytes
|
||||
// d.asBytes command bytes to send
|
||||
void felica_sendraw(const PacketCommandNG *c) {
|
||||
|
||||
felica_command_t param = c->oldarg[0];
|
||||
size_t len = c->oldarg[1] & 0xffff;
|
||||
uint32_t arg0;
|
||||
felica_command_t param = 0;
|
||||
size_t len = 0;
|
||||
const uint8_t *payload = NULL;
|
||||
|
||||
if (!c->ng) {
|
||||
reply_ng(CMD_HF_FELICA_COMMAND, PM3_EINVARG, NULL, 0);
|
||||
return;
|
||||
}
|
||||
if (c->length < sizeof(felica_raw_cmd_t)) {
|
||||
reply_ng(CMD_HF_FELICA_COMMAND, PM3_EINVARG, NULL, 0);
|
||||
return;
|
||||
}
|
||||
const felica_raw_cmd_t *request = (const felica_raw_cmd_t *)c->data.asBytes;
|
||||
if ((size_t)request->rawlen > PM3_CMD_DATA_SIZE || FELICA_RAW_LEN(request->rawlen) > c->length) {
|
||||
reply_ng(CMD_HF_FELICA_COMMAND, PM3_EINVARG, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
param = request->flags;
|
||||
len = request->rawlen;
|
||||
payload = request->raw;
|
||||
|
||||
bool do_connect = ((param & FELICA_CONNECT) == FELICA_CONNECT);
|
||||
bool no_disconnect = ((param & FELICA_NO_DISCONNECT) == FELICA_NO_DISCONNECT);
|
||||
|
||||
@@ -560,26 +581,42 @@ void felica_sendraw(const PacketCommandNG *c) {
|
||||
|
||||
// notify client selecting status.
|
||||
// if failed selecting, turn off antenna and quit.
|
||||
felica_card_select_t card;
|
||||
arg0 = felica_select_card(&card);
|
||||
reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
||||
if (arg0) {
|
||||
felica_card_select_t card = {0};
|
||||
uint8_t select_result = felica_select_card(&card);
|
||||
|
||||
int select_status = PM3_SUCCESS;
|
||||
switch (select_result) {
|
||||
case 1:
|
||||
select_status = PM3_ETIMEOUT;
|
||||
break;
|
||||
case 2:
|
||||
select_status = PM3_EWRONGANSWER;
|
||||
break;
|
||||
case 3:
|
||||
select_status = PM3_ECRC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
reply_ng(CMD_HF_FELICA_COMMAND, select_status, (uint8_t *)&card, sizeof(felica_card_select_t));
|
||||
if (select_status != PM3_SUCCESS) {
|
||||
felica_reset_frame_mode();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((param & FELICA_RAW) == FELICA_RAW) {
|
||||
if (len > FELICA_MAX_FRAME_SIZE) {
|
||||
Dbprintf("FeliCa raw payload too long: %u (max %u)", len, FELICA_MAX_FRAME_SIZE);
|
||||
reply_mix(CMD_ACK, 0, PM3_ELENGTH, 0, NULL, 0);
|
||||
if (len > FELICA_MAX_DATA_SIZE) {
|
||||
Dbprintf("FeliCa raw payload too long: %u (max %u)", len, FELICA_MAX_DATA_SIZE);
|
||||
reply_ng(CMD_HF_FELICA_COMMAND, PM3_ELENGTH, NULL, 0);
|
||||
if (!no_disconnect) {
|
||||
felica_reset_frame_mode();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t buf[FELICA_MAX_FRAME_SIZE];
|
||||
uint8_t buf[FELICA_MAX_RF_FRAME_SIZE];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
// add sync bits
|
||||
@@ -590,7 +627,7 @@ void felica_sendraw(const PacketCommandNG *c) {
|
||||
buf[2] = len + 1;
|
||||
|
||||
// copy command
|
||||
memcpy(buf + 3, c->data.asBytes, len);
|
||||
memcpy(buf + 3, payload, len);
|
||||
|
||||
if ((param & FELICA_APPEND_CRC) == FELICA_APPEND_CRC) {
|
||||
// Don't append crc on empty bytearray...
|
||||
@@ -609,17 +646,16 @@ void felica_sendraw(const PacketCommandNG *c) {
|
||||
};
|
||||
|
||||
TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
|
||||
arg0 = WaitForFelicaReply(1024);
|
||||
bool got_frame = WaitForFelicaReply(1024);
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
Dbprintf("Received Frame Code: %d", arg0);
|
||||
Dbprintf("Received Frame Code: %d", got_frame);
|
||||
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||
};
|
||||
|
||||
uint32_t result = reply_mix(CMD_ACK, FelicaFrame.len, arg0, 0, FelicaFrame.framebytes, FelicaFrame.len);
|
||||
if (result) {
|
||||
Dbprintf("Reply to Client Error Code: %i", result);
|
||||
}
|
||||
int status = got_frame ? PM3_SUCCESS : PM3_ERFTRANS;
|
||||
uint16_t frame_len = got_frame ? FelicaFrame.len : 0;
|
||||
reply_ng(CMD_HF_FELICA_COMMAND, status, got_frame ? FelicaFrame.framebytes : NULL, frame_len);
|
||||
}
|
||||
|
||||
if (no_disconnect) {
|
||||
@@ -937,5 +973,10 @@ void felica_dump_lite_s(void) {
|
||||
// setting tracelen - important! it was set by buffer overflow before
|
||||
// iceman: is this still needed?!?
|
||||
set_tracelen(cnt);
|
||||
reply_mix(CMD_ACK, isOK, cnt, 0, 0, 0);
|
||||
|
||||
felica_lite_dump_resp_t payload = {
|
||||
.completed = isOK,
|
||||
.tracelen = cnt,
|
||||
};
|
||||
reply_ng(CMD_HF_FELICALITE_DUMP, isOK ? PM3_SUCCESS : PM3_EOPABORTED, (uint8_t *)&payload, sizeof(payload));
|
||||
}
|
||||
|
||||
+120
-59
@@ -52,6 +52,7 @@
|
||||
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose);
|
||||
static felica_card_select_t last_known_card;
|
||||
|
||||
static void set_last_known_card(felica_card_select_t card) {
|
||||
@@ -281,12 +282,19 @@ static const char *felica_model_name(uint8_t rom_type, uint8_t ic_type) {
|
||||
* @param verbose prints out the response received.
|
||||
*/
|
||||
static bool waitCmdFelica(bool iSelect, PacketResponseNG *resp, bool verbose) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, resp, 2000) == false) {
|
||||
if (WaitForResponseTimeout(CMD_HF_FELICA_COMMAND, resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t len = (iSelect) ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff);
|
||||
if (resp->status != PM3_SUCCESS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "FeliCa command failed (%d)", resp->status);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t len = resp->length;
|
||||
|
||||
if (verbose) {
|
||||
|
||||
@@ -298,11 +306,15 @@ static bool waitCmdFelica(bool iSelect, PacketResponseNG *resp, bool verbose) {
|
||||
PrintAndLogEx(SUCCESS, "(%u) %s", len, sprint_hex(resp->data.asBytes, len));
|
||||
|
||||
if (iSelect == false) {
|
||||
if (len < 4) {
|
||||
PrintAndLogEx(ERR, "received too short frame!");
|
||||
return false;
|
||||
}
|
||||
if (check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2) == false) {
|
||||
PrintAndLogEx(WARNING, "CRC ( " _RED_("fail") " )");
|
||||
}
|
||||
|
||||
if (resp->data.asBytes[0] != 0xB2 && resp->data.asBytes[1] != 0x4D) {
|
||||
if (resp->data.asBytes[0] != 0xB2 || resp->data.asBytes[1] != 0x4D) {
|
||||
PrintAndLogEx(ERR, "received incorrect frame format!");
|
||||
return false;
|
||||
}
|
||||
@@ -335,26 +347,35 @@ int read_felica_uid(bool loop, bool verbose) {
|
||||
int res = PM3_ETIMEOUT;
|
||||
|
||||
do {
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_FELICA_COMMAND, FELICA_CONNECT, 0, 0, NULL, 0);
|
||||
clear_and_send_command(FELICA_CONNECT, 0, NULL, false);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_FELICA_COMMAND, &resp, 2500)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xFF;
|
||||
int status = resp.status;
|
||||
|
||||
if (loop) {
|
||||
if (status != 0) {
|
||||
if (status != PM3_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// when not in continuous mode
|
||||
if (status != 0) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed");
|
||||
res = PM3_EOPABORTED;
|
||||
if (status != PM3_SUCCESS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "FeliCa card select failed (%d)", status);
|
||||
}
|
||||
res = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (resp.length < sizeof(felica_card_select_t)) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "FeliCa card select returned invalid payload");
|
||||
}
|
||||
res = PM3_ESOFT;
|
||||
break;
|
||||
}
|
||||
|
||||
felica_card_select_t card;
|
||||
memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t));
|
||||
if (loop == false) {
|
||||
@@ -399,50 +420,60 @@ static int CmdHFFelicaReader(const char *Cmd) {
|
||||
|
||||
static int info_felica(bool verbose) {
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_FELICA_COMMAND, FELICA_CONNECT, 0, 0, NULL, 0);
|
||||
clear_and_send_command(FELICA_CONNECT, 0, NULL, false);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||
if (WaitForResponseTimeout(CMD_HF_FELICA_COMMAND, &resp, 2500) == false) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
switch (resp.status) {
|
||||
case PM3_ETIMEOUT:
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "card timeout");
|
||||
}
|
||||
break;
|
||||
case PM3_EWRONGANSWER:
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "card answered wrong");
|
||||
}
|
||||
break;
|
||||
case PM3_ECRC:
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "CRC check failed");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "FeliCa card select failed (%d)", resp.status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
if (resp.length < sizeof(felica_card_select_t)) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "FeliCa card select returned invalid payload");
|
||||
}
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
felica_card_select_t card;
|
||||
memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t));
|
||||
uint64_t status = resp.oldarg[0];
|
||||
|
||||
switch (status) {
|
||||
case 1: {
|
||||
if (verbose)
|
||||
PrintAndLogEx(WARNING, "card timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
case 2: {
|
||||
if (verbose)
|
||||
PrintAndLogEx(WARNING, "card answered wrong");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
case 3: {
|
||||
if (verbose)
|
||||
PrintAndLogEx(WARNING, "CRC check failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
case 0: {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
||||
PrintAndLogEx(INFO, "IDm............ " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm)));
|
||||
PrintAndLogEx(INFO, "Code........... %s ", sprint_hex_inrow(card.code, sizeof(card.code)));
|
||||
PrintAndLogEx(INFO, "NFCID2......... %s", sprint_hex_inrow(card.uid, sizeof(card.uid)));
|
||||
PrintAndLogEx(INFO, "Parameter");
|
||||
PrintAndLogEx(INFO, "PAD............ " _YELLOW_("%s"), sprint_hex_inrow(card.PMm, sizeof(card.PMm)));
|
||||
PrintAndLogEx(INFO, "IC code........ %s ( " _YELLOW_("%s") " )", sprint_hex_inrow(card.iccode, sizeof(card.iccode)), felica_model_name(card.iccode[0], card.iccode[1]));
|
||||
PrintAndLogEx(INFO, "MRT............ %s", sprint_hex_inrow(card.mrt, sizeof(card.mrt)));
|
||||
PrintAndLogEx(INFO, "Service code... " _YELLOW_("%s"), sprint_hex(card.servicecode, sizeof(card.servicecode)));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
set_last_known_card(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
||||
PrintAndLogEx(INFO, "IDm............ " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm)));
|
||||
PrintAndLogEx(INFO, "Code........... %s ", sprint_hex_inrow(card.code, sizeof(card.code)));
|
||||
PrintAndLogEx(INFO, "NFCID2......... %s", sprint_hex_inrow(card.uid, sizeof(card.uid)));
|
||||
PrintAndLogEx(INFO, "Parameter");
|
||||
PrintAndLogEx(INFO, "PAD............ " _YELLOW_("%s"), sprint_hex_inrow(card.PMm, sizeof(card.PMm)));
|
||||
PrintAndLogEx(INFO, "IC code........ %s ( " _YELLOW_("%s") " )", sprint_hex_inrow(card.iccode, sizeof(card.iccode)), felica_model_name(card.iccode[0], card.iccode[1]));
|
||||
PrintAndLogEx(INFO, "MRT............ %s", sprint_hex_inrow(card.mrt, sizeof(card.mrt)));
|
||||
PrintAndLogEx(INFO, "Service code... " _YELLOW_("%s"), sprint_hex(card.servicecode, sizeof(card.servicecode)));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
set_last_known_card(card);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -462,10 +493,9 @@ static int CmdHFFelicaInfo(const char *Cmd) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears command buffer and sends the given data to pm3 with mix mode.
|
||||
* Clears command buffer and sends the given data to pm3 with NG mode.
|
||||
*/
|
||||
static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose) {
|
||||
uint16_t numbits = 0;
|
||||
static void clear_and_send_command_ex(uint8_t flags, uint16_t datalen, uint8_t *data, uint16_t numbits, bool verbose, bool normalize_frame) {
|
||||
uint16_t payload_len = 0;
|
||||
uint8_t *payload = data;
|
||||
|
||||
@@ -473,7 +503,7 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat
|
||||
// A bunch of code in this module adds length byte at data[0] regardless of that, which is wrong
|
||||
// This is a workaround to extract the actual payload correctly so that length byte isn't repeated
|
||||
// It also strips CRC if present, as ARMSRC adds it too
|
||||
if (data && datalen) {
|
||||
if (normalize_frame && data && datalen) {
|
||||
if (datalen >= data[0] && data[0] > 0) {
|
||||
payload_len = data[0] - 1;
|
||||
if (payload_len > datalen - 1) {
|
||||
@@ -483,13 +513,29 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat
|
||||
} else {
|
||||
payload_len = datalen;
|
||||
}
|
||||
} else {
|
||||
payload_len = datalen;
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Send raw command - Frame: %s", sprint_hex(payload, payload_len));
|
||||
}
|
||||
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (payload_len & 0xFFFF) | (uint32_t)(numbits << 16), 0, payload, payload_len);
|
||||
|
||||
uint8_t packet_buf[sizeof(felica_raw_cmd_t) + PM3_CMD_DATA_SIZE] = {0};
|
||||
felica_raw_cmd_t *packet = (felica_raw_cmd_t *)packet_buf;
|
||||
packet->flags = flags;
|
||||
packet->numbits = numbits;
|
||||
packet->rawlen = payload_len;
|
||||
if (payload_len) {
|
||||
memcpy(packet->raw, payload, payload_len);
|
||||
}
|
||||
|
||||
SendCommandNG(CMD_HF_FELICA_COMMAND, packet_buf, FELICA_RAW_LEN(payload_len));
|
||||
}
|
||||
|
||||
static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose) {
|
||||
clear_and_send_command_ex(flags, datalen, data, 0, verbose, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3015,7 +3061,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or " _GREEN_("<Enter>") " to abort dumping");
|
||||
|
||||
uint8_t timeout = 0;
|
||||
while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
while (WaitForResponseTimeout(CMD_HF_FELICALITE_DUMP, &resp, 2000) == false) {
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
@@ -3041,12 +3087,28 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (resp.oldarg[0] == 0) {
|
||||
if (resp.status == PM3_EOPABORTED) {
|
||||
PrintAndLogEx(WARNING, "Button pressed, aborted");
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
uint16_t tracelen = resp.oldarg[1];
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "FeliCa lite dump failed (%d)", resp.status);
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
if (resp.length < sizeof(felica_lite_dump_resp_t)) {
|
||||
PrintAndLogEx(WARNING, "Unexpected dump response length");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
felica_lite_dump_resp_t *dump_resp = (felica_lite_dump_resp_t *)resp.data.asBytes;
|
||||
if (dump_resp->completed == 0) {
|
||||
PrintAndLogEx(WARNING, "Button pressed, aborted");
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
uint16_t tracelen = dump_resp->tracelen;
|
||||
if (tracelen == 0) {
|
||||
PrintAndLogEx(WARNING, "No trace data! Maybe not a FeliCa Lite card?");
|
||||
return PM3_ESOFT;
|
||||
@@ -3065,7 +3127,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||
}
|
||||
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen);
|
||||
PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", (uint32_t)tracelen);
|
||||
print_hex_break(trace, tracelen, 32);
|
||||
printSep();
|
||||
|
||||
@@ -3145,10 +3207,9 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||
// Max transport buffer is PM3_CMD_DATA_SIZE
|
||||
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
|
||||
|
||||
clearCommandBuffer();
|
||||
PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(data, datalen));
|
||||
|
||||
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen);
|
||||
clear_and_send_command_ex(flags, datalen, data, numbits, false, false);
|
||||
|
||||
if (reply) {
|
||||
|
||||
|
||||
@@ -28,6 +28,20 @@ typedef enum FELICA_COMMAND {
|
||||
FELICA_NO_SELECT = (1 << 6),
|
||||
} felica_command_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t flags; // PM3 flags, see felica_command_t
|
||||
uint16_t numbits; // optional number of bits for raw exchange
|
||||
uint16_t rawlen; // bytes in raw[]
|
||||
uint8_t raw[];
|
||||
} PACKED felica_raw_cmd_t;
|
||||
|
||||
#define FELICA_RAW_LEN(x) (sizeof(felica_raw_cmd_t) + (x))
|
||||
|
||||
typedef struct {
|
||||
uint8_t completed;
|
||||
uint16_t tracelen;
|
||||
} PACKED felica_lite_dump_resp_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FeliCa
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user