diff --git a/armsrc/Makefile b/armsrc/Makefile index 15e04bbd1..1e40148da 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -21,6 +21,7 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_ISO14443b \ -DWITH_ISO14443a \ -DWITH_ICLASS \ + -DWITH_FELICA \ -DWITH_HFSNOOP \ -DWITH_HF_YOUNG \ -fno-strict-aliasing -ffunction-sections -fdata-sections @@ -45,6 +46,7 @@ SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c epa.c SRC_ISO14443b = iso14443b.c +SRC_FELICA = felica.c SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c SRC_EMV = tlv.c emvdataels.c emvutil.c emvcmd.c @@ -93,6 +95,7 @@ ARMSRC = fpgaloader.c \ $(SRC_ICLASS) \ $(SRC_EMV) \ $(SRC_CRC) \ + $(SRC_FELICA) \ parity.c \ usb_cdc.c \ cmd.c \ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 46a1a3439..8dbf412e3 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -766,6 +766,18 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; #endif +#ifdef WITH_FELICA + case CMD_FELICA_LITE_SIM: + HfSimLite(c->arg[0]); + break; + case CMD_FELICA_SNOOP: + HfSnoopISO18(c->arg[0], c->arg[1]); + break; + case CMD_FELICA_LITE_DUMP: + HfDumpFelicaLiteS(); + break; +#endif + #ifdef WITH_ISO14443a case CMD_SNOOP_ISO_14443a: SniffIso14443a(c->arg[0]); diff --git a/armsrc/apps.h b/armsrc/apps.h index 2661d32c4..d23efa17f 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -233,6 +233,11 @@ bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* d // util.h void HfSnoop(int , int); +//felica.c +extern void HfSnoopISO18(uint32_t samples, uint32_t triggers); +extern void HfSimLite(uint64_t uid); +extern void HfDumpFelicaLiteS(); + //EMV functions // emvcmd.h extern void EMVTransaction(void); diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 9e1b31cbe..557a136ea 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -85,4 +85,14 @@ extern void switch_off(); #define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) #define FPGA_HF_ISO14443A_READER_MOD (4<<0) + +//options for Felica. +#define FPGA_MAJOR_MODE_ISO18092 (5<<5) +#define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) //disable modulation module +#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // should enable 414k mode (untested). No autodetect +#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // enables antenna power, to act as a reader instead of tag + + + + #endif \ No newline at end of file diff --git a/client/cmdhf.c b/client/cmdhf.c index 3f59533ae..8051ac463 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -745,6 +745,114 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui return tracepos; } +void printFelica(uint16_t traceLen, uint8_t *trace) +{ + PrintAndLog(" Gap | Src | Data | CRC | Annotation |"); + PrintAndLog("--------|-----|---------------------------------|----------|-------------------|"); + uint16_t tracepos=0; + //I am stripping SYNC + while(tracepos=traceLen) break; + uint16_t gap= (uint16_t)trace[tracepos+1]+((uint16_t)trace[tracepos]>>8); + uint16_t crc_ok=trace[tracepos+2]; + tracepos+=3; + if(tracepos+3>=traceLen) break; + uint16_t len=trace[tracepos+2]; + //printf("!!! %02x %02x %02x %02x %02x %02x %d",trace[tracepos+0],trace[tracepos+1],trace[tracepos+2],trace[tracepos+3],trace[tracepos+4],trace[tracepos+5],len); + tracepos+=3; //skip SYNC + if(tracepos+len+1>=traceLen) break; + uint8_t cmd=trace[tracepos]; + uint8_t isResponse=cmd&1; + char line[32][110]; + for (int j = 0; j < len+1 && j/8 < 32; j++) + { + snprintf(line[j/8]+(( j % 8) * 4), 110, " %02x ", trace[tracepos+j]); + } + char expbuf[50]; + switch(cmd) + { + case FELICA_POLL_REQ:snprintf(expbuf,49,"Poll Req");break; + case FELICA_POLL_ACK :snprintf(expbuf,49,"Poll Resp");break; + + case FELICA_REQSRV_REQ :snprintf(expbuf,49,"Request Srvc Req");break; +case FELICA_REQSRV_ACK :snprintf(expbuf,49,"Request Srv Resp");break; + +case FELICA_RDBLK_REQ :snprintf(expbuf,49,"Read block(s) Req");break; +case FELICA_RDBLK_ACK :snprintf(expbuf,49,"Read block(s) Resp");break; + +case FELICA_WRTBLK_REQ :snprintf(expbuf,49,"Write block(s) Req");break; +case FELICA_WRTBLK_ACK :snprintf(expbuf,49,"Write block(s) Resp");break; +case FELICA_SRCHSYSCODE_REQ :snprintf(expbuf,49,"Search syscode Req");break; +case FELICA_SRCHSYSCODE_ACK :snprintf(expbuf,49,"Search syscode Resp");break; + +case FELICA_REQSYSCODE_REQ :snprintf(expbuf,49,"Request syscode Req");break; +case FELICA_REQSYSCODE_ACK :snprintf(expbuf,49,"Request syscode Resp");break; + +case FELICA_AUTH1_REQ :snprintf(expbuf,49,"Auth1 Req");break; +case FELICA_AUTH1_ACK :snprintf(expbuf,49,"Auth1 Resp");break; + +case FELICA_AUTH2_REQ :snprintf(expbuf,49,"Auth2 Req");break; +case FELICA_AUTH2_ACK :snprintf(expbuf,49,"Auth2 Resp");break; + +case FELICA_RDSEC_REQ :snprintf(expbuf,49,"Secure read Req");break; +case FELICA_RDSEC_ACK :snprintf(expbuf,49,"Secure read Resp");break; + +case FELICA_WRTSEC_REQ :snprintf(expbuf,49,"Secure write Req");break; +case FELICA_WRTSEC_ACK :snprintf(expbuf,49,"Secure write Resp");break; + +case FELICA_REQSRV2_REQ :snprintf(expbuf,49,"Request Srvc v2 Req");break; +case FELICA_REQSRV2_ACK :snprintf(expbuf,49,"Request Srvc v2 Resp");break; + +case FELICA_GETSTATUS_REQ :snprintf(expbuf,49,"Get status Req");break; +case FELICA_GETSTATUS_ACK :snprintf(expbuf,49,"Get status Resp");break; + +case FELICA_OSVER_REQ :snprintf(expbuf,49,"Get OS Version Req");break; +case FELICA_OSVER_ACK :snprintf(expbuf,49,"Get OS Version Resp");break; + +case FELICA_RESET_MODE_REQ :snprintf(expbuf,49,"Reset mode Req");break; +case FELICA_RESET_MODE_ACK :snprintf(expbuf,49,"Reset mode Resp");break; + +case FELICA_AUTH1V2_REQ :snprintf(expbuf,49,"Auth1 v2 Req");break; +case FELICA_AUTH1V2_ACK :snprintf(expbuf,49,"Auth1 v2 Resp");break; + +case FELICA_AUTH2V2_REQ :snprintf(expbuf,49,"Auth2 v2 Req");break; +case FELICA_AUTH2V2_ACK :snprintf(expbuf,49,"Auth2 v2 Resp");break; + +case FELICA_RDSECV2_REQ :snprintf(expbuf,49,"Secure read v2 Req");break; +case FELICA_RDSECV2_ACK :snprintf(expbuf,49,"Secure read v2 Resp");break; +case FELICA_WRTSECV2_REQ :snprintf(expbuf,49,"Secure write v2 Req");break; +case FELICA_WRTSECV2_ACK :snprintf(expbuf,49,"Secure write v2 Resp");break; + +case FELICA_UPDATE_RNDID_REQ :snprintf(expbuf,49,"Update IDr Req");break; +case FELICA_UPDATE_RNDID_ACK :snprintf(expbuf,49,"Update IDr Resp");break; + default: snprintf(expbuf,49,"Unknown");break; + } + + int num_lines = MIN((len )/16 + 1, 16); + for (int j = 0; j < num_lines ; j++) + { + if (j == 0) { + PrintAndLog("%7d | %s |%-32s |%02x %02x %s| %s", + gap, + (isResponse ? "Tag" : "Rdr"), + line[j], + trace[tracepos+len], + trace[tracepos+len+1], + (crc_ok) ? "OK" : "NG", + expbuf); + } else { + PrintAndLog(" | |%-32s | | ", + line[j]); + } + } + tracepos+=len+1; + } + PrintAndLog(""); + +} + + int usage_hf_list(){ PrintAndLog("List protocol data in trace buffer."); PrintAndLog("Usage: hf list [f][c]"); @@ -863,6 +971,12 @@ int CmdHFList(const char *Cmd) { PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen); PrintAndLog(""); + if(protocol==FELICA) +{ +printFelica(traceLen,trace); +} +else +{ PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); if ( protocol == ISO_14443A ) PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)"); @@ -882,7 +996,7 @@ int CmdHFList(const char *Cmd) { while(tracepos < traceLen) { tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes); } - +} free(trace); return 0; } diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index aeebd919b..643a7b744 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -13,23 +13,44 @@ static int CmdHelp(const char *Cmd); int usage_hf_felica_sim(void) { PrintAndLog("\n Emulating ISO/18092 FeliCa tag \n"); - PrintAndLog("usage: hf felica sim [h] t u [v]"); + PrintAndLog("usage: hf felica sim [h] t [v]"); PrintAndLog("options: "); PrintAndLog(" h : This help"); PrintAndLog(" t : 1 = FeliCa"); - PrintAndLog(" : 2 = FeliCaS"); + PrintAndLog(" : 2 = FeliCaLiteS"); PrintAndLog(" v : (Optional) Verbose"); PrintAndLog("samples:"); - PrintAndLog(" hf felica sim t 1 u 11223344556677"); + PrintAndLog(" hf felica sim t 1 "); return 0; } + int usage_hf_felica_sniff(void){ PrintAndLog("It get data from the field and saves it into command buffer."); PrintAndLog("Buffer accessible from command 'hf list felica'"); - PrintAndLog("Usage: hf felica sniff [c][r]"); - PrintAndLog("c - triggered by first data from card"); - PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)"); - PrintAndLog("sample: hf felica sniff c r"); + PrintAndLog("Usage: hf felica sniff "); + PrintAndLog(" s samples to skip (decimal)"); + PrintAndLog(" t triggers to skip (decimal)"); + PrintAndLog("samples:"); + PrintAndLog(" hf felica sniff s 1000"); + return 0; +} +int usage_hf_felica_simlite(void) { + PrintAndLog("\n Emulating ISO/18092 FeliCa Lite tag \n"); + PrintAndLog("usage: hf felica litesim [h] u "); + PrintAndLog("options: "); + PrintAndLog(" h : This help"); + PrintAndLog(" uid : UID in hexsymbol"); + PrintAndLog("samples:"); + PrintAndLog(" hf felica litesim 11223344556677"); + return 0; +} +int usage_hf_felica_dumplite(void) { + PrintAndLog("\n Dump ISO/18092 FeliCa Lite tag \n"); + PrintAndLog("usage: hf felica litedump [h]"); + PrintAndLog("options: "); + PrintAndLog(" h : This help"); + PrintAndLog("samples:"); + PrintAndLog(" hf felica litedump"); return 0; } int usage_hf_felica_raw(void){ @@ -66,13 +87,6 @@ int CmdHFFelicaReader(const char *Cmd) { iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - - /* - 0: couldn't read - 1: OK, with ATS - 2: OK, no ATS - 3: proprietary Anticollision - */ uint64_t select_status = resp.arg[0]; if (select_status == 0) { @@ -81,10 +95,6 @@ int CmdHFFelicaReader(const char *Cmd) { return 0; } - PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); - return select_status; } @@ -98,8 +108,8 @@ int CmdHFFelicaSim(const char *Cmd) { int uidlen = 0; bool verbose = false; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (param_getchar(Cmd, cmdp)) { case 'h': case 'H': return usage_hf_felica_sim(); @@ -155,22 +165,211 @@ int CmdHFFelicaSim(const char *Cmd) { return 0; } -int CmdHFFelicaSniff(const char *Cmd) { - int param = 0; - uint8_t ctmp; - for (int i = 0; i < 2; i++) { - ctmp = param_getchar(Cmd, i); - if (ctmp == 'h' || ctmp == 'H') return usage_hf_felica_sniff(); - if (ctmp == 'c' || ctmp == 'C') param |= 0x01; - if (ctmp == 'r' || ctmp == 'R') param |= 0x02; - } +int CmdHFFelicaSniff(const char *Cmd) { - UsbCommand c = {CMD_FELICA_SNOOP, {param, 0, 0}}; + uint8_t cmdp = 0; + uint64_t samples2skip = 0; + uint64_t triggers2skip = 0; + bool errors = false; + + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_hf_felica_sniff(); + case 's': + case 'S': + samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 't': + case 'T': + triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0) return usage_hf_felica_sniff(); + + UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; } +// uid hex +int CmdHFFelicaSimLite(const char *Cmd) { + + uint64_t uid = param_get64ex(Cmd, 0, 0, 16); + + if (!uid) + return usage_hf_felica_simlite(); + + UsbCommand c = {CMD_FELICA_LITE_SIM, {uid, 0, 0} }; + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace,uint16_t tracelen) { + if (tracepos+19 >= tracelen) + return tracelen; + + trace += tracepos; + uint8_t blocknum = trace[0]; + uint8_t status1 = trace[1]; + uint8_t status2 = trace[2]; + + char line[110] = {0}; + for (int j = 0; j < 16; j++) { + snprintf(line+( j * 4),110, "%02x ", trace[j+3]); + } + + PrintAndLog( "Block number %02x, status: %02x %02x",blocknum,status1, status2); + switch (blocknum) { + case 0x00: PrintAndLog( "S_PAD0: %s",line);break; + case 0x01: PrintAndLog( "S_PAD1: %s",line);break; + case 0x02: PrintAndLog( "S_PAD2: %s",line);break; + case 0x03: PrintAndLog( "S_PAD3: %s",line);break; + case 0x04: PrintAndLog( "S_PAD4: %s",line);break; + case 0x05: PrintAndLog( "S_PAD5: %s",line);break; + case 0x06: PrintAndLog( "S_PAD6: %s",line);break; + case 0x07: PrintAndLog( "S_PAD7: %s",line);break; + case 0x08: PrintAndLog( "S_PAD8: %s",line);break; + case 0x09: PrintAndLog( "S_PAD9: %s",line);break; + case 0x0a: PrintAndLog( "S_PAD10: %s",line);break; + case 0x0b: PrintAndLog( "S_PAD11: %s",line);break; + case 0x0c: PrintAndLog( "S_PAD12: %s",line);break; + case 0x0d: PrintAndLog( "S_PAD13: %s",line);break; + case 0x0E: { + uint32_t regA = trace[3] + (trace[4]>>8) + (trace[5]>>16) + (trace[6]>>24); + uint32_t regB = trace[7] + (trace[8]>>8) + (trace[9]>>16) + (trace[10]>>24); + line[0] = 0; + for (int j = 0; j < 8; j++) + snprintf(line+( j * 2),110, "%02x", trace[j+11]); + PrintAndLog( "REG: regA: %d regB: %d regC: %s ", regA, regB, line); + } + break; + case 0x80: PrintAndLog( "Random Challenge, WO: %s ", line); break; + case 0x81: PrintAndLog( "MAC, only set on dual read: %s ", line); break; + case 0x82: { + char idd[20]; + char idm[20]; + for (int j = 0; j < 8; j++) + snprintf(idd+( j * 2),20, "%02x", trace[j+3]); + + for (int j = 0; j < 6; j++) + snprintf(idm+( j * 2),20, "%02x", trace[j+13]); + + PrintAndLog( "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); + } + break; + case 0x83: { + char idm[20]; + char pmm[20]; + for (int j = 0; j < 8; j++) + snprintf(idm+( j * 2),20, "%02x", trace[j+3]); + + for (int j = 0; j < 8; j++) + snprintf(pmm+( j * 2),20, "%02x", trace[j+11]); + + PrintAndLog( "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); + } + break; + case 0x84: PrintAndLog( "SER_C: 0x%02x%02x ", trace[3], trace[4]); break; + case 0x85: PrintAndLog( "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break; + case 0x86: PrintAndLog( "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break; + case 0x87: PrintAndLog( "CK (card key), WO: %s ", line); break; + case 0x88: { + PrintAndLog( "Memory Configuration (MC):"); + PrintAndLog( "MAC needed to write state: %s", trace[3+12]? "on" : "off"); + //order might be off here... + PrintAndLog("Write with MAC for S_PAD : %s ", sprint_bin(trace+3+10, 2) ); + PrintAndLog("Write with AUTH for S_PAD : %s ", sprint_bin(trace+3+8, 2) ); + PrintAndLog("Read after AUTH for S_PAD : %s ", sprint_bin(trace+3+6, 2) ); + PrintAndLog( "MAC needed to write CK and CKV: %s", trace[3+5] ? "on" : "off"); + PrintAndLog( "RF parameter: %02x", (trace[3+4] & 0x7) ); + PrintAndLog( "Compatible with NDEF: %s", trace[3+3] ? "yes" : "no"); + PrintAndLog( "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no"); + PrintAndLog("RW access for S_PAD : %s ", sprint_bin(trace+3, 2) ); + } + break; + case 0x90: { + PrintAndLog( "Write count, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]); + } + break; + case 0x91: { + PrintAndLog( "MAC_A, RW (auth): %s ", line); + } + break; + case 0x92: { + PrintAndLog( "State:"); + PrintAndLog( "Polling disabled: %s", trace[3+8] ? "yes" : "no"); + PrintAndLog( "Authenticated: %s", trace[3] ? "yes" : "no"); + } + break; + case 0xa0: { + PrintAndLog( "CRC of all bloacks match : %s", (trace[3+2]==0xff) ? "no" : "yes"); + } + break; + default: + PrintAndLog( "INVALID %d: %s", blocknum, line); + break; + } + return tracepos+19; +} + +int CmdHFFelicaDumpLite(const char *Cmd) { + + //usage_hf_felica_dumplite(); + + UsbCommand c = {CMD_FELICA_LITE_DUMP, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + + uint16_t tracepos = 0; + uint8_t *trace; + + trace = malloc(USB_CMD_DATA_SIZE); + if ( trace == NULL ) { + PrintAndLog("Cannot allocate memory for trace"); + return 1; + } + + // Query for the size of the trace + UsbCommand response; + GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0); + if ( !WaitForResponseTimeout(CMD_ACK, &response, 4000) ) { + PrintAndLog("timeout while waiting for reply."); + return 1; + } + + uint16_t traceLen = response.arg[2]; + if (traceLen > USB_CMD_DATA_SIZE) { + uint8_t *p = realloc(trace, traceLen); + if (p == NULL) { + PrintAndLog("Cannot allocate memory for trace"); + free(trace); + return 2; + } + trace = p; + GetFromBigBuf(trace, traceLen, 0); + WaitForResponse(CMD_ACK, NULL); + } + + PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen); + while (tracepos < traceLen) { + tracepos = PrintFliteBlock(tracepos, trace, traceLen); + } + free(trace); + return 0; +} + int CmdHFFelicaCmdRaw(const char *cmd) { UsbCommand c = {CMD_FELICA_COMMAND, {0, 0, 0}}; bool reply = 1; @@ -323,12 +522,15 @@ void waitCmdFelica(uint8_t iSelect) { } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"}, - {"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"}, - {"sim", CmdHFFelicaSim, 0, " -- Simulate ISO 18092/FeliCa tag"}, - {"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"}, - {"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"}, + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"}, + {"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"}, + {"sim", CmdHFFelicaSim, 0, " -- Simulate ISO 18092/FeliCa tag"}, + {"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"}, + {"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"}, + + {"litesim", CmdHFFelicaSimLite, 0, " - only reply to poll request"}, + {"litedump", CmdHFFelicaDumpLite, 0, "Wait for and try dumping FelicaLite"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index 62786c193..bd0ec30ba 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -38,4 +38,9 @@ extern int usage_hf_felica_sniff(void); extern int usage_hf_fFelica_raw(void); void waitCmdFelica(uint8_t iSelect); + +//temp +extern int CmdHFFelicaSimLite(const char *Cmd); +extern int CmdHFFelicaDumpLite(const char *Cmd); + #endif diff --git a/common/protocols.h b/common/protocols.h index 04c203e87..f58b82d36 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -436,6 +436,67 @@ uint32_t GetT55xxClockBit(uint32_t clock); #define EM4x05_DISABLE_ALLOWED 1<<23 #define EM4x05_READER_TALK_FIRST 1<<24 + + +#define FLITE_SERVICE_RO 0x000B +#define FLITE_SERVICE_RW 0x0009 + +#define FELICA_POLL_REQ 0x00 +#define FELICA_POLL_ACK 0x01 + +#define FELICA_REQSRV_REQ 0x02 +#define FELICA_REQSRV_ACK 0x03 + +#define FELICA_RDBLK_REQ 0x06 +#define FELICA_RDBLK_ACK 0x07 + +#define FELICA_WRTBLK_REQ 0x08 +#define FELICA_WRTBLK_ACK 0x09 + +#define FELICA_SRCHSYSCODE_REQ 0x0a +#define FELICA_SRCHSYSCODE_ACK 0x0b + +#define FELICA_REQSYSCODE_REQ 0x0c +#define FELICA_REQSYSCODE_ACK 0x0d + +#define FELICA_AUTH1_REQ 0x10 +#define FELICA_AUTH1_ACK 0x11 + +#define FELICA_AUTH2_REQ 0x12 +#define FELICA_AUTH2_ACK 0x13 + +#define FELICA_RDSEC_REQ 0x14 +#define FELICA_RDSEC_ACK 0x15 + +#define FELICA_WRTSEC_REQ 0x16 +#define FELICA_WRTSEC_ACK 0x17 + +#define FELICA_REQSRV2_REQ 0x32 +#define FELICA_REQSRV2_ACK 0x33 + +#define FELICA_GETSTATUS_REQ 0x38 +#define FELICA_GETSTATUS_ACK 0x39 + +#define FELICA_OSVER_REQ 0x3c +#define FELICA_OSVER_ACK 0x3d + +#define FELICA_RESET_MODE_REQ 0x3e +#define FELICA_RESET_MODE_ACK 0x3f + +#define FELICA_AUTH1V2_REQ 0x40 +#define FELICA_AUTH1V2_ACK 0x41 + +#define FELICA_AUTH2V2_REQ 0x42 +#define FELICA_AUTH2V2_ACK 0x43 + +#define FELICA_RDSECV2_REQ 0x44 +#define FELICA_RDSECV2_ACK 0x45 +#define FELICA_WRTSECV2_REQ 0x46 +#define FELICA_WRTSECV2_ACK 0x47 + +#define FELICA_UPDATE_RNDID_REQ 0x4C +#define FELICA_UPDATE_RNDID_ACK 0x4D + // iclass / picopass chip config structures and shared routines typedef struct { uint8_t app_limit; //[8] diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 59b25f924..77a9331c0 100644 Binary files a/fpga/fpga_hf.bit and b/fpga/fpga_hf.bit differ diff --git a/fpga/fpga_hf.v b/fpga/fpga_hf.v index 264e1b0c6..d056253db 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -18,6 +18,8 @@ `include "hi_simulate.v" `include "hi_iso14443a.v" `include "hi_sniffer.v" +`include "hi_flite.v" +//`include "hf_fmod.v" `include "util.v" module fpga_hf( @@ -73,7 +75,10 @@ wire hi_read_tx_shallow_modulation = conf_word[0]; wire hi_read_rx_xcorr_848 = conf_word[0]; // and whether to drive the coil (reader) or just short it (snooper) wire hi_read_rx_xcorr_snoop = conf_word[1]; +// divide subcarrier frequency by 4 +wire hi_read_rx_xcorr_quarter = conf_word[2]; +wire [1:0] hi_read_tx_speed= conf_word [2:1]; // For the high-frequency simulated tag: what kind of modulation to use. wire [2:0] hi_simulate_mod_type = conf_word[2:0]; @@ -90,8 +95,19 @@ hi_read_tx ht( ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk, cross_hi, cross_lo, ht_dbg, - hi_read_tx_shallow_modulation + hi_read_tx_shallow_modulation,hi_read_tx_speed, 1'b1 ); + +/*hi_fmod hmf( + pck0, ck_1356meg, ck_1356megb, + hmf_pwr_lo, hmf_pwr_hi, hmf_pwr_oe1, hmf_pwr_oe2, hmf_pwr_oe3, hmf_pwr_oe4, + adc_d, ht_adc_clk, + hmf_ssp_frame, hmf_ssp_din, ssp_dout, hmf_ssp_clk, + cross_hi, cross_lo, + hmf_dbg, + hi_simulate_mod_type +);*/ + hi_read_rx_xcorr hrxc( pck0, ck_1356meg, ck_1356megb, @@ -100,7 +116,7 @@ hi_read_rx_xcorr hrxc( hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk, cross_hi, cross_lo, hrxc_dbg, - hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop + hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter ); hi_simulate hs( @@ -133,6 +149,16 @@ hi_sniffer he( hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter ); +hi_flite hfl( + pck0, ck_1356meg, ck_1356megb, + hfl_pwr_lo, hfl_pwr_hi, hfl_pwr_oe1, hfl_pwr_oe2, hfl_pwr_oe3, hfl_pwr_oe4, + adc_d, hfl_adc_clk, + hfl_ssp_frame, hfl_ssp_din, ssp_dout, hfl_ssp_clk, + cross_hi, cross_lo, + hfl_dbg, + hi_simulate_mod_type +); + // Major modes: // 000 -- HF reader, transmitting to tag; modulation depth selectable @@ -140,19 +166,34 @@ hi_sniffer he( // 010 -- HF simulated tag // 011 -- HF ISO14443-A // 100 -- HF Snoop +// 101 -- HF demod test +// 110 -- Felica modulation, reusing HF reader // 111 -- everything off -mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, 1'b0, 1'b0, 1'b0); +//mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, hmf_ssp_clk, 1'b0); +//mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, hmf_ssp_din, 1'b0); +//mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, hmf_ssp_frame, 1'b0); +//mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, hmf_pwr_oe1, 1'b0); +//mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, hmf_pwr_oe2, 1'b0); +//mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, hmf_pwr_oe3, 1'b0); +//mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, hmf_pwr_oe4, 1'b0); +//mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, hmf_pwr_lo, 1'b0); +//mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, hmf_pwr_hi, 1'b0); +//mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, hmf_adc_clk, 1'b0); +//mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, hmf_dbg, 1'b0); + + +mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index 43fbee16c..5574a6bcf 100644 Binary files a/fpga/fpga_lf.bit and b/fpga/fpga_lf.bit differ diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 14b3caafe..1b7a11276 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -103,7 +103,7 @@ lo_edge_detect le( // Major modes: // 000 -- LF reader (generic) // 001 -- LF edge detect (generic) -// 010 -- LF passthru +// 010 -- LF passthrough mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); diff --git a/fpga/fpga_nfc.bit b/fpga/fpga_nfc.bit index 46483c715..a1e55d24d 100644 Binary files a/fpga/fpga_nfc.bit and b/fpga/fpga_nfc.bit differ diff --git a/fpga/fpga_nfc.v b/fpga/fpga_nfc.v index dbc608fb5..e2d328b5f 100644 --- a/fpga/fpga_nfc.v +++ b/fpga/fpga_nfc.v @@ -16,6 +16,7 @@ `include "hi_flite.v" `include "util.v" +`include "hi_sniffer.v" module fpga_nfc( input spck, output miso, input mosi, input ncs, @@ -67,11 +68,11 @@ assign major_mode = conf_word[7:5]; // For the high-frequency receive correlator: frequency against which to // correlate. -//wire hi_read_rx_xcorr_848 = conf_word[0]; +wire hi_read_rx_xcorr_848 = conf_word[0]; // and whether to drive the coil (reader) or just short it (snooper) -//wire hi_read_rx_xcorr_snoop = conf_word[1]; +wire hi_read_rx_xcorr_snoop = conf_word[1]; // divide subcarrier frequency by 4 -//wire hi_read_rx_xcorr_quarter = conf_word[2]; +wire hi_read_rx_xcorr_quarter = conf_word[2]; // For the high-frequency simulated tag: what kind of modulation to use. wire [2:0] hi_simulate_mod_type = conf_word[2:0]; @@ -81,6 +82,15 @@ wire [2:0] hi_simulate_mod_type = conf_word[2:0]; // major modes, and use muxes to connect the outputs of the active mode to // the output pins. //----------------------------------------------------------------------------- +hi_sniffer he( + pck0, ck_1356meg, ck_1356megb, + he_pwr_lo, he_pwr_hi, he_pwr_oe1, he_pwr_oe2, he_pwr_oe3, he_pwr_oe4, + adc_d, he_adc_clk, + he_ssp_frame, he_ssp_din, ssp_dout, he_ssp_clk, + cross_hi, cross_lo, + he_dbg, + hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter +); hi_flite hfl( @@ -103,17 +113,17 @@ hi_flite hfl( // 101 -- HF NFC demod, just to copy it for now // 111 -- everything off -mux8 mux_ssp_clk (major_mode, ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_ssp_clk, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_ssp_din, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_ssp_frame, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe1, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe2, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe3, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe4, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_lo, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_hi, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_adc_clk, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_dbg, 1'b0, 1'b0); +mux8 mux_ssp_clk (major_mode, ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, 1'b0, 1'b0, 1'b0, 1'b0, hfl_dbg, hfl_dbg, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/hi_flite.v b/fpga/hi_flite.v index c7b9d4648..8c8e26d39 100644 --- a/fpga/hi_flite.v +++ b/fpga/hi_flite.v @@ -1,15 +1,11 @@ -// Satsuoni, October 2017, Added FeliCa support -// + //this code demodulates and modulates signal as described in ISO/IEC 18092. That includes packets used for Felica, NFC Tag 3, etc. (which do overlap) //simple envelope following algorithm is used (modification of fail0verflow LF one) is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave) -// only 212 kbps (fc/64) for now 414 is relatively straightforward... +// only 212 kbps (fc/64) for now 414 is relatively straightforward... though for reader, the selection has to come from ARM // modulation waits for - //market sprocket -doesn't really mean anything ;) -`define SNIFFER 3'b000 -`define TAGSIM_LISTEN 3'b001 //same as SNIFFER, really. demod does not distinguish tag from reader -`define TAGSIM_MODULATE 3'b010 -`define TAGSIM_MOD_NODELAY 3'b011 //not implemented yet. for use with commands other than polling, which might require different timing, as per Felica standard +//redefining mod_type: bits 210: bit 2 - reader drive/power on/off, bit 1 - speed bit, 0:212, 1 -424 bit 0: listen or modulate + module hi_flite( pck0, ck_1356meg, ck_1356megb, @@ -18,7 +14,8 @@ module hi_flite( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - mod_type // maybe used + mod_type // used + ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -28,15 +25,18 @@ module hi_flite( output ssp_frame, ssp_din, ssp_clk; input cross_hi, cross_lo; output dbg; - input [2:0] mod_type; // maybe used. + input [2:0] mod_type; // used. assign dbg=0; -// Most off, oe4 for modulation; No reader emulation (would presumably just require switching power on, but I am not sure) -assign pwr_hi = 1'b0; +wire power= mod_type[2]; +wire speed= mod_type[1]; +wire disabl= mod_type[0]; + +// Most off, oe4 for modulation; +// Trying reader emulation (would presumably just require switching power on, but I am not sure) + //;// 1'b0; assign pwr_lo = 1'b0; -assign pwr_oe1 = 1'b0; -assign pwr_oe2 = 1'b0; -assign pwr_oe3 = 1'b0; + //512x64/fc -wait before ts0, 32768 ticks @@ -51,7 +51,7 @@ assign adc_clk = ck_1356meg; `define ithrmin 91//-13'd8 `define ithrmax 160// 13'd8 - +`define min_bitdelay_212 8 //minimum values and corresponding thresholds reg [8:0] curmin=`imin; @@ -76,9 +76,13 @@ reg did_sync=0; `define bithalf_212 32 //half-bit length for 212 kbit -`define bitlen_212 64 //full-bit length for 212 kbit `define bitmlen_212 63 //bit transition edge -`define bitmhalf_212 31 //mod flip + +`define bithalf_424 16 //half-bit length for 212 kbit +`define bitmlen_424 31 //bit transition edge + +wire [7:0]bithalf= speed ? `bithalf_424 : `bithalf_212; +wire [7:0]bitmlen= speed ? `bitmlen_424 : `bitmlen_212; //ssp clock and current values @@ -98,57 +102,36 @@ reg [8:0] ssp_cnt=9'd0; always @(posedge adc_clk) ssp_cnt <= (ssp_cnt + 1); - -reg getting_arm_data=1'b0; - - -reg [47:0] delayline=48'd0; //48-bit preamble delay line. Just push the data into it starting from first SYNC (1) bit coming from ARM Made this long to keep all ARM data received during preamble -reg [5:0] delay_read_ptr=6'd0; // this is supposed to count ARM delay in the buffer. -reg preamble=0; // whether we are sending preamble - - +//maybe change it so that ARM sends preamble as well. +//then: ready bits sent to ARM, 8 bits sent from ARM (all ones), then preamble (all zeros, presumably) - which starts modulation always @(negedge adc_clk) begin //count fc/64 - transfer bits to ARM at the rate they are received - if(ssp_cnt[5:0] == 6'b000000) + if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed &&(ssp_cnt[4:0] == 5'b00000))) begin ssp_clk <= 1'b1; + // if(mod_type[2]) + // begin + // ssp_din<=outp[0];//after_hysteresis; + + //outp<={1'b0,outp[7:1]}; + // end + // else ssp_din <= curbit; - //sample ssp_dout? - if(mod_type==`TAGSIM_MODULATE||mod_type==`TAGSIM_MOD_NODELAY) - begin - delayline<={delayline[46:0],ssp_dout}; - if ((~getting_arm_data) && ssp_dout) - begin - getting_arm_data <=1'b1; - delay_read_ptr<=delay_read_ptr+1; - end - else - begin - if (getting_arm_data & preamble) - begin - delay_read_ptr<=delay_read_ptr+1; - end - end - end - else - begin - getting_arm_data <=1'b0; - delay_read_ptr<=6'd0; - end + //sample ssp_dout end - if(ssp_cnt[5:0] == 6'b100000) + if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000)) ssp_clk <= 1'b0; //create frame pulses. TBH, I still don't know what they do exactly, but they are crucial for ARM->FPGA transfer. If the frame is in the beginning of the byte, transfer slows to a crawl for some reason // took me a day to figure THAT out. - if(ssp_cnt[8:0] == 9'd31) + if(( (~speed) && (ssp_cnt[8:0] == 9'd31))||(speed && ssp_cnt[7:0] == 8'd15)) begin ssp_frame <= 1'b1; end - if(ssp_cnt[8:0] == 9'b1011111) + if(( (~speed) && (ssp_cnt[8:0] == 9'b1011111))||(speed &&ssp_cnt[7:0] == 8'b101111) ) begin ssp_frame <= 1'b0; end @@ -158,7 +141,7 @@ end //send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise) -reg ssp_din; +reg ssp_din;//= outp[0]; @@ -168,28 +151,74 @@ reg prv =1'b1; reg[7:0] mid=8'd128; //for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry. -//modulated coil. set to 1 to modulate low, 0 to keep signal high -reg mod_sig_coil=1'b0; // set TAGSIM__MODULATE on ARM if we want to write... (frame would get lost if done mid-frame...) // start sending over 1s on ssp->arm when we start sending preamble reg counting_desync=1'b0; // are we counting bits since last frame? reg sending=1'b0; // are we actively modulating? -reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. +reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. might remove those? +//reg [2:0]old_mod; + +//always @(mod_type) //when moving from modulate_mode +//begin +//if (mod_type[2]==1&&old_mod[2]==0) +// bit_counts=0; +//old_mod=mod_type; +//end +//we need some way to flush bit_counts triggers on mod_type changes don't compile +reg dlay; always @(negedge adc_clk) //every data ping? begin //envelope follow code... //////////// - if ((mod_type==`SNIFFER )||(mod_type==`TAGSIM_LISTEN)) + + //move the counter to the outside... + // if (adc_d>=curminthres||try_sync) + if(fccount==bitmlen) begin + if((~try_sync)&&(adc_d768) // should be over ts0 now, without ARM interference... stop counting... + begin + bit_counts<=0; + // counting_desync<=0; + end + else + if((power)) + bit_counts<=0; + else + bit_counts<=bit_counts+1; + // end + end + else + begin + if((~try_sync)&&(adc_dcurmaxthres) //rising edge begin case (state) 0: begin - curmax <= adc_d>155? adc_d :155; + curmax <= adc_d>`imax? adc_d :`imax; state <= 2; end 1: begin @@ -214,7 +243,7 @@ begin begin case (state) 0: begin - curmin <=adc_d<96? adc_d :96; + curmin <=adc_d<`imin? adc_d :`imin; state <=1; end 1: begin @@ -224,7 +253,7 @@ begin 2: begin curminthres <= ( (curmin>>1)+(curmin>>2)+(curmin>>4)+(curmax>>3)+(curmax>>4)); curmaxthres <= ( (curmax>>1)+(curmax>>2)+(curmax>>4)+(curmin>>3)+(curmin>>4)); - curmin <=adc_d<96? adc_d :96; + curmin <=adc_d<`imin? adc_d :`imin; state <=1; end default: @@ -235,7 +264,7 @@ begin if (~try_sync ) //begin modulation, lower edge... begin try_sync <=1; - counting_desync<=1'b0; + //counting_desync<=1'b0; fccount <= 1; did_sync<=0; curbit<=0; @@ -259,7 +288,7 @@ begin if (tsinceedge>=(128)) begin //we might need to start counting... assuming ARM wants to reply to the frame. - counting_desync<=1'b1; + // counting_desync<=1'b1; bit_counts<=1;// i think? 128 is about 2 bits passed... but 1 also works try_sync<=0; did_sync<=0;//desync @@ -278,32 +307,13 @@ begin end end - //move the counter to the outside... - if (adc_d>=curminthres||try_sync) - if(fccount==`bitmlen_212) - begin - fccount<=0; - if (counting_desync) - begin - - if(bit_counts>768) // should be over ts0 now, without ARM interference... stop counting... - begin - bit_counts<=0; - counting_desync<=0; - end - else - bit_counts<=bit_counts+1; - end - end - else - begin - fccount<=fccount+1; - end + + if (try_sync && tsinceedge<128) begin //detect bits in their middle ssp sampling is in sync, so it would sample all bits in order - if (fccount==`bithalf_212) + if (fccount==bithalf) begin if ((~did_sync) && ((prv==1&&(mid>128))||(prv==0&&(mid<=128)))) begin @@ -336,7 +346,7 @@ begin end else begin - if (fccount==`bitmlen_212) + if (fccount==bitmlen) begin // fccount <=0; prv <=(mid>128)?1:0; @@ -367,61 +377,40 @@ begin begin end sending <=0; - - end //listen mode end - else - begin //sim mode start - //not sure how precise do the time slots have to be... is anything within Ts ok? - //keep counting until 576, just in case - if(fccount==`bitmlen_212) - begin - if (bit_counts==512) // - curbit<=1; - else - begin - if(bit_counts>512) - curbit<=mod_sig_coil;//delayline[delay_read_ptr];//bit_counts[0]; - else - curbit<=0; - end - - fccount<=0; - if (bit_counts<=576) //we don't need to count after that... - begin - bit_counts<=bit_counts+1; - if (bit_counts== 512) //should start sending from next tick... i think? - begin - sending <=1; - mod_sig_coil <=1;//modulate... down? - preamble<=1; - end - else - if (bit_counts== 559) - begin - preamble<=0; - end - end - if (sending) - begin //need next bit - if(preamble) - mod_sig_coil<=1; - else - mod_sig_coil<=~delayline[delay_read_ptr]; - end - end - else - begin - fccount<=fccount+1; - - if ((fccount==`bitmhalf_212)&&(sending)) //flip modulation mid-bit - begin - mod_sig_coil<=~mod_sig_coil;//flip - end - end - end //sim mode end - end +//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that +reg pwr_hi; +reg pwr_oe1; +reg pwr_oe2; +reg pwr_oe3; +reg pwr_oe4; -assign pwr_oe4 = mod_sig_coil & (mod_type == `TAGSIM_MODULATE)&sending; +wire mod=((fccount>=bithalf)^dlay)&(~disabl); + +always @(ck_1356megb or ssp_dout or power or disabl or mod) + begin +if (power) + begin + pwr_hi <= ck_1356megb; + pwr_oe1 <= mod; + pwr_oe2 <= mod; + pwr_oe3 <= mod; + pwr_oe4 <= 1'b0; + end +else + begin + pwr_hi <= 1'b0; + pwr_oe1 <= 1'b0; + pwr_oe2 <= 1'b0; + pwr_oe3 <= 1'b0; + pwr_oe4 <= mod; + end + end +//assign pwr_oe4 = 1'b0;// mod_sig_coil & (modulate_mode)&sending & (~mod_type[2]); +//try shallow mod for reader? +//assign pwr_hi= (mod_type[2]) & ck_1356megb; +//assign pwr_oe1= 1'b0; //mod_sig_coil & (modulate_mode)&sending & (mod_type[2]); +//assign pwr_oe2 = 1'b0;// mod_sig_coil & (modulate_mode)&sending & (mod_type[2]); +//assign pwr_oe3 = 1'b0; //mod_sig_coil & (modulate_mode)&sending & (mod_type[2]); endmodule diff --git a/fpga/hi_read_rx_xcorr.v b/fpga/hi_read_rx_xcorr.v index bbd28b0f5..dc8b01bc5 100644 --- a/fpga/hi_read_rx_xcorr.v +++ b/fpga/hi_read_rx_xcorr.v @@ -10,7 +10,7 @@ module hi_read_rx_xcorr( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - xcorr_is_848, snoop + xcorr_is_848, snoop, xcorr_quarter_freq ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -20,7 +20,7 @@ module hi_read_rx_xcorr( output ssp_frame, ssp_din, ssp_clk; input cross_hi, cross_lo; output dbg; - input xcorr_is_848, snoop; + input xcorr_is_848, snoop, xcorr_quarter_freq; // Carrier is steady on through this, unless we're snooping. assign pwr_hi = ck_1356megb & (~snoop); @@ -28,18 +28,20 @@ assign pwr_oe1 = 1'b0; assign pwr_oe3 = 1'b0; assign pwr_oe4 = 1'b0; -// Clock divider -reg [0:0] fc_divider; +reg [2:0] fc_div; always @(negedge ck_1356megb) - fc_divider <= fc_divider + 1; -wire fc_div2 = fc_divider[0]; + fc_div <= fc_div + 1; -reg adc_clk; -always @(ck_1356megb) - if (xcorr_is_848) +(* clock_signal = "yes" *) reg adc_clk; // sample frequency, always 16 * fc +always @(ck_1356megb, xcorr_is_848, xcorr_quarter_freq, fc_div) + if (xcorr_is_848 & ~xcorr_quarter_freq) // fc = 847.5 kHz adc_clk <= ck_1356megb; - else - adc_clk <= fc_div2; + else if (~xcorr_is_848 & ~xcorr_quarter_freq) // fc = 424.25 kHz + adc_clk <= fc_div[0]; + else if (xcorr_is_848 & xcorr_quarter_freq) // fc = 212.125 kHz + adc_clk <= fc_div[1]; + else // fc = 106.0625 kHz + adc_clk <= fc_div[2]; // When we're a reader, we just need to do the BPSK demod; but when we're an // eavesdropper, we also need to pick out the commands sent by the reader, @@ -71,8 +73,7 @@ end // so we need a 6-bit counter. reg [5:0] corr_i_cnt; // And a couple of registers in which to accumulate the correlations. -// we would add at most 32 times adc_d, the result can be held in 13 bits. -// Need one additional bit because it can be negative as well +// we would add/sub at most 32 times adc_d, the signed result can be held in 14 bits. reg signed [13:0] corr_i_accum; reg signed [13:0] corr_q_accum; reg signed [7:0] corr_i_out; diff --git a/fpga/hi_read_tx.v b/fpga/hi_read_tx.v index f12e64eb6..23d25deff 100644 --- a/fpga/hi_read_tx.v +++ b/fpga/hi_read_tx.v @@ -12,7 +12,7 @@ module hi_read_tx( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - shallow_modulation + shallow_modulation, speed, power ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -23,6 +23,8 @@ module hi_read_tx( input cross_hi, cross_lo; output dbg; input shallow_modulation; + input [1:0] speed; + input power; // The high-frequency stuff. For now, for testing, just bring out the carrier, // and allow the ARM to modulate it over the SSP. @@ -32,6 +34,8 @@ reg pwr_oe2; reg pwr_oe3; reg pwr_oe4; always @(ck_1356megb or ssp_dout or shallow_modulation) +begin +if (power) begin if(shallow_modulation) begin @@ -50,6 +54,15 @@ begin pwr_oe4 <= 1'b0; end end +else +begin + pwr_hi <= 1'b0; + pwr_oe1 <= 1'b0; + pwr_oe2 <= 1'b0; + pwr_oe3 <= 1'b0; + pwr_oe4 <= ~ssp_dout; +end +end // Then just divide the 13.56 MHz clock down to produce appropriate clocks // for the synchronous serial port. @@ -59,7 +72,7 @@ reg [6:0] hi_div_by_128; always @(posedge ck_1356meg) hi_div_by_128 <= hi_div_by_128 + 1; -assign ssp_clk = hi_div_by_128[6]; +assign ssp_clk = speed[1]? (speed[0]? hi_div_by_128[3]: hi_div_by_128[4]) : (speed[0]? hi_div_by_128[5]: hi_div_by_128[6]); reg [2:0] hi_byte_div; @@ -76,7 +89,7 @@ assign adc_clk = ck_1356meg; reg after_hysteresis; always @(negedge adc_clk) begin - if(& adc_d[7:0]) after_hysteresis <= 1'b1; + if(& adc_d[7:4]) after_hysteresis <= 1'b1; else if(~(| adc_d[7:0])) after_hysteresis <= 1'b0; end diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index 6139cfad2..0768c29de 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -53,11 +53,6 @@ end // Divide 13.56 MHz by 32 to produce the SSP_CLK // The register is bigger to allow higher division factors of up to /128 -// FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) // 0000 -// FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) // 0001 -// FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) // 0010 -// FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) // 0100 -// FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 reg [10:0] ssp_clk_divider; always @(posedge adc_clk) @@ -91,8 +86,8 @@ end // Divide SSP_CLK by 8 to produce the byte framing signal; the phase of // this is arbitrary, because it's just a bitstream. // One nasty issue, though: I can't make it work with both rx and tx at -// once. The phase wrt ssp_clk must be changed. -// TODO to find out why that is and make a better fix. +// once. The phase wrt ssp_clk must be changed. TODO to find out why +// that is and make a better fix. reg [2:0] ssp_frame_divider_to_arm; always @(posedge ssp_clk) ssp_frame_divider_to_arm <= (ssp_frame_divider_to_arm + 1); diff --git a/fpga/hi_sniffer.v b/fpga/hi_sniffer.v index 3a989ce62..3d39413a3 100644 --- a/fpga/hi_sniffer.v +++ b/fpga/hi_sniffer.v @@ -17,8 +17,11 @@ module hi_sniffer( output dbg; input xcorr_is_848, snoop, xcorr_quarter_freq; // not used. + +// let's try hi-pass + // We are only snooping, all off. -assign pwr_hi = 1'b0; +assign pwr_hi = ck_1356megb & xcorr_quarter_freq;//1'b0; assign pwr_lo = 1'b0; assign pwr_oe1 = 1'b0; assign pwr_oe2 = 1'b0; @@ -29,8 +32,12 @@ reg ssp_frame; reg [7:0] adc_d_out = 8'd0; reg [2:0] ssp_cnt = 3'd0; -assign adc_clk = ck_1356meg; -assign ssp_clk = ~ck_1356meg; + +reg [12:0] avg=13'd0; + +assign adc_clk = ck_1356megb; +assign ssp_clk = ~ck_1356megb; + always @(posedge ssp_clk) begin @@ -41,7 +48,9 @@ begin if(ssp_cnt[2:0] == 3'b000) // set frame length begin - adc_d_out[7:0] <= adc_d; + // adc_d_out[7:0] <= (alias_buf>>>3) +8'd126;//( $signed(adc_d-adc_d_old)>1 | $signed(adc_d_old-adc_d)>1)? alias_buf+adc_d-adc_d_old:alias_buf; //alias_buf[11:3]+8'd126;//adc_d; + // adc_d_out[7:0]<=adc_d; + adc_d_out[7:0] <=adc_d;//-(avg>>3) +8'd126; ssp_frame <= 1'b1; end else diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 31ebaef12..271954413 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -171,6 +171,9 @@ typedef struct{ #define CMD_FELICA_SIMULATE_TAG 0x03A0 #define CMD_FELICA_SNOOP 0x03A1 #define CMD_FELICA_COMMAND 0x03A2 +//temp +#define CMD_FELICA_LITE_DUMP 0x03AA +#define CMD_FELICA_LITE_SIM 0x03AB // For measurements of the antenna tuning #define CMD_MEASURE_ANTENNA_TUNING 0x0400