2022-01-06 09:19:46 +08:00
//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
2019-08-08 22:57:33 +08:00
# include "felica.h"
# include "proxmark3_arm.h"
2017-10-21 02:30:17 +08:00
# include "BigBuf.h"
# include "util.h"
2017-12-24 17:30:29 +08:00
# include "protocols.h"
2019-10-23 15:21:43 +08:00
# include "crc16.h"
2019-08-08 22:57:33 +08:00
# include "fpgaloader.h"
# include "string.h"
# include "commonutil.h"
# include "dbprint.h"
# include "ticks.h"
2020-10-02 20:31:52 +08:00
# include "iso18.h"
2018-01-29 20:42:02 +08:00
2018-01-30 10:29:37 +08:00
// FeliCa timings
2019-08-06 19:51:10 +08:00
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
2018-01-30 10:29:37 +08:00
# ifndef FELICA_REQUEST_GUARD_TIME
2019-10-21 00:28:07 +08:00
# define FELICA_REQUEST_GUARD_TIME (6800 / 16 + 1) // 426
2018-01-30 10:29:37 +08:00
# endif
// FRAME DELAY TIME 2672 carrier cycles
# ifndef FELICA_FRAME_DELAY_TIME
2019-10-21 00:28:07 +08:00
# define FELICA_FRAME_DELAY_TIME (2672 / 16 + 1) // 168
2018-01-30 10:29:37 +08:00
# endif
# ifndef DELAY_AIR2ARM_AS_READER
2019-10-21 00:28:07 +08:00
# define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) // 91
2018-01-30 10:29:37 +08:00
# endif
# ifndef DELAY_ARM2AIR_AS_READER
2019-10-21 00:28:07 +08:00
# define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) // 209
2018-01-30 10:29:37 +08:00
# endif
2020-01-22 01:07:18 +08:00
# define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))
2018-02-01 22:22:01 +08:00
2018-01-30 10:29:37 +08:00
static uint32_t felica_timeout ;
static uint32_t felica_nexttransfertime ;
static uint32_t felica_lasttime_prox2air_start ;
2019-01-09 19:05:29 +08:00
static void iso18092_setup ( uint8_t fpga_minor_mode ) ;
2018-01-29 20:42:02 +08:00
static uint8_t felica_select_card ( felica_card_select_t * card ) ;
2022-02-27 22:00:50 +08:00
static void TransmitFor18092_AsReader ( uint8_t * frame , uint16_t len , uint32_t * timing , uint8_t power , uint8_t highspeed ) ;
2020-05-19 23:05:43 +08:00
static bool WaitForFelicaReply ( uint16_t maxbytes ) ;
2017-10-21 02:30:17 +08:00
2020-05-10 22:59:38 +08:00
static void iso18092_set_timeout ( uint32_t timeout ) {
2019-03-10 07:00:59 +08:00
felica_timeout = timeout + ( DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER ) / ( 16 * 8 ) + 2 ;
2018-01-30 10:29:37 +08:00
}
2017-10-21 02:30:17 +08:00
2020-05-10 22:59:38 +08:00
static uint32_t iso18092_get_timeout ( void ) {
2019-03-10 07:00:59 +08:00
return felica_timeout - ( DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER ) / ( 16 * 8 ) - 2 ;
2018-01-30 10:29:37 +08:00
}
2018-01-29 20:42:02 +08:00
2019-01-09 19:05:29 +08:00
# ifndef FELICA_MAX_FRAME_SIZE
2019-03-10 07:00:59 +08:00
# define FELICA_MAX_FRAME_SIZE 260
2018-01-29 20:42:02 +08:00
# endif
2017-10-21 02:30:17 +08:00
2019-03-09 15:59:13 +08:00
//structure to hold outgoing NFC frame
2019-03-10 07:00:59 +08:00
static uint8_t frameSpace [ FELICA_MAX_FRAME_SIZE + 4 ] ;
2018-01-30 10:29:37 +08:00
2017-10-21 02:30:17 +08:00
//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
static struct {
enum {
STATE_UNSYNCD ,
STATE_TRYING_SYNC ,
STATE_GET_LENGTH ,
STATE_GET_DATA ,
STATE_GET_CRC ,
STATE_FULL
} state ;
uint16_t shiftReg ; //for synchronization and offset calculation
int posCnt ;
2019-03-10 03:34:41 +08:00
bool crc_ok ;
2017-10-21 02:30:17 +08:00
int rem_len ;
uint16_t len ;
uint8_t byte_offset ;
2019-03-10 03:34:41 +08:00
uint8_t * framebytes ;
2019-03-10 07:00:59 +08:00
//should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc
// 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc
2019-01-07 03:42:51 +08:00
} FelicaFrame ;
2017-10-21 02:30:17 +08:00
//b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in
//bit order in byte -reverse, I guess? [((bt>>0)&1),((bt>>1)&1),((bt>>2)&1),((bt>>3)&1),((bt>>4)&1),((bt>>5)&1),((bt>>6)&1),((bt>>7)&1)] -at least in the mode that I read those in
2018-01-30 10:29:37 +08:00
# ifndef SYNC_16BIT
2019-01-07 03:42:51 +08:00
# define SYNC_16BIT 0xB24D
2018-01-30 10:29:37 +08:00
# endif
2017-10-21 02:30:17 +08:00
2020-05-10 22:59:38 +08:00
static void FelicaFrameReset ( void ) {
2019-01-07 03:42:51 +08:00
FelicaFrame . state = STATE_UNSYNCD ;
FelicaFrame . posCnt = 0 ;
FelicaFrame . crc_ok = false ;
FelicaFrame . byte_offset = 0 ;
2018-01-29 20:42:02 +08:00
}
2019-03-10 18:20:22 +08:00
static void FelicaFrameinit ( uint8_t * data ) {
2019-03-10 03:34:41 +08:00
FelicaFrame . framebytes = data ;
FelicaFrameReset ( ) ;
2017-10-21 02:30:17 +08:00
}
//shift byte into frame, reversing it at the same time
2019-03-10 18:20:22 +08:00
static void shiftInByte ( uint8_t bt ) {
2019-03-10 03:34:41 +08:00
uint8_t j ;
2019-03-10 07:00:59 +08:00
for ( j = 0 ; j < FelicaFrame . byte_offset ; j + + ) {
FelicaFrame . framebytes [ FelicaFrame . posCnt ] = ( FelicaFrame . framebytes [ FelicaFrame . posCnt ] < < 1 ) + ( bt & 1 ) ;
2017-10-21 02:30:17 +08:00
bt > > = 1 ;
}
2019-01-07 03:42:51 +08:00
FelicaFrame . posCnt + + ;
FelicaFrame . rem_len - - ;
2019-03-10 07:00:59 +08:00
for ( j = FelicaFrame . byte_offset ; j < 8 ; j + + ) {
FelicaFrame . framebytes [ FelicaFrame . posCnt ] = ( FelicaFrame . framebytes [ FelicaFrame . posCnt ] < < 1 ) + ( bt & 1 ) ;
2017-10-21 02:30:17 +08:00
bt > > = 1 ;
}
}
2019-03-10 18:20:22 +08:00
static void Process18092Byte ( uint8_t bt ) {
2019-01-07 03:42:51 +08:00
switch ( FelicaFrame . state ) {
2019-03-10 03:34:41 +08:00
case STATE_UNSYNCD : {
2019-10-16 20:17:52 +08:00
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case
2019-03-10 03:34:41 +08:00
if ( bt > 0 ) {
FelicaFrame . shiftReg = reflect8 ( bt ) ;
FelicaFrame . state = STATE_TRYING_SYNC ;
}
break ;
}
case STATE_TRYING_SYNC : {
if ( bt = = 0 ) {
//desync
FelicaFrame . shiftReg = bt ;
FelicaFrame . state = STATE_UNSYNCD ;
} else {
2019-03-10 07:00:59 +08:00
for ( uint8_t i = 0 ; i < 8 ; i + + ) {
2019-03-10 03:34:41 +08:00
if ( FelicaFrame . shiftReg = = SYNC_16BIT ) {
//SYNC done!
FelicaFrame . state = STATE_GET_LENGTH ;
FelicaFrame . framebytes [ 0 ] = 0xb2 ;
FelicaFrame . framebytes [ 1 ] = 0x4d ;
FelicaFrame . byte_offset = i ;
//shift in remaining byte, slowly...
2019-03-10 07:00:59 +08:00
for ( uint8_t j = i ; j < 8 ; j + + ) {
2019-03-10 03:34:41 +08:00
FelicaFrame . framebytes [ 2 ] = ( FelicaFrame . framebytes [ 2 ] < < 1 ) + ( bt & 1 ) ;
bt > > = 1 ;
}
FelicaFrame . posCnt = 2 ;
2019-03-10 07:00:59 +08:00
if ( i = = 0 )
2019-03-10 03:34:41 +08:00
break ;
}
FelicaFrame . shiftReg = ( FelicaFrame . shiftReg < < 1 ) + ( bt & 1 ) ;
bt > > = 1 ;
}
//that byte was last byte of sync
if ( FelicaFrame . shiftReg = = SYNC_16BIT ) {
//Force SYNC on next byte
FelicaFrame . state = STATE_GET_LENGTH ;
FelicaFrame . framebytes [ 0 ] = 0xb2 ;
FelicaFrame . framebytes [ 1 ] = 0x4d ;
FelicaFrame . byte_offset = 0 ;
FelicaFrame . posCnt = 1 ;
}
}
break ;
}
case STATE_GET_LENGTH : {
shiftInByte ( bt ) ;
FelicaFrame . rem_len = FelicaFrame . framebytes [ 2 ] - 1 ;
FelicaFrame . len = FelicaFrame . framebytes [ 2 ] + 4 ; //with crc and sync
FelicaFrame . state = STATE_GET_DATA ;
break ;
}
case STATE_GET_DATA : {
shiftInByte ( bt ) ;
if ( FelicaFrame . rem_len < = 0 ) {
FelicaFrame . state = STATE_GET_CRC ;
FelicaFrame . rem_len = 2 ;
}
break ;
}
case STATE_GET_CRC : {
shiftInByte ( bt ) ;
2019-03-10 07:00:59 +08:00
if ( FelicaFrame . rem_len < = 0 ) {
2019-10-16 20:17:52 +08:00
FelicaFrame . rem_len = 0 ;
2019-03-10 03:34:41 +08:00
// skip sync 2bytes. IF ok, residue should be 0x0000
2019-03-10 07:00:59 +08:00
FelicaFrame . crc_ok = check_crc ( CRC_FELICA , FelicaFrame . framebytes + 2 , FelicaFrame . len - 2 ) ;
2019-03-10 03:34:41 +08:00
FelicaFrame . state = STATE_FULL ;
}
break ;
}
case STATE_FULL : //ignore byte. Don't forget to clear frame to receive next one...
default :
break ;
}
2017-10-21 02:30:17 +08:00
}
2018-01-29 20:42:02 +08:00
/* Perform FeliCa polling card
* Currently does NOT do any collision handling .
* It expects 0 - 1 cards in the device ' s range .
2019-10-16 20:17:52 +08:00
* return 0 if selection was successful
2018-01-29 20:42:02 +08:00
*/
2019-03-10 18:20:22 +08:00
static uint8_t felica_select_card ( felica_card_select_t * card ) {
2017-10-21 02:30:17 +08:00
2019-03-10 03:34:41 +08:00
// POLL command
// 0xB2 0x4B = sync code
// 0x06 = len
// 0x00 = rfu
2019-10-16 20:17:52 +08:00
// 0xff = system code service
// 0xff = system code service
// 0x00 = request code
2019-10-17 19:48:34 +08:00
// b7 = automatic switching of data rate
// b6-b2 = reserved
// b1 = fc/32 (414kbps)
// b0 = fc/64 (212kbps)
2019-03-10 03:34:41 +08:00
// 0x00 = timeslot
// 0x09 0x21 = crc
2019-03-10 07:00:59 +08:00
static uint8_t poll [ 10 ] = { 0xb2 , 0x4d , 0x06 , FELICA_POLL_REQ , 0xFF , 0xFF , 0x00 , 0x00 , 0x09 , 0x21 } ;
2021-04-16 03:43:48 +08:00
int len = 10 ;
2019-03-10 03:34:41 +08:00
2021-04-16 03:43:48 +08:00
// We try 10 times, or if answer was received.
2019-03-10 03:34:41 +08:00
do {
// end-of-reception response packet data, wait approx. 501μs
// end-of-transmission command packet data, wait approx. 197μs
// polling card
TransmitFor18092_AsReader ( poll , sizeof ( poll ) , NULL , 1 , 0 ) ;
// polling card, break if success
2019-10-16 20:17:52 +08:00
if ( WaitForFelicaReply ( 1024 ) & & FelicaFrame . framebytes [ 3 ] = = FELICA_POLL_ACK )
2019-03-10 03:34:41 +08:00
break ;
WDT_HIT ( ) ;
} while ( - - len ) ;
// timed-out
2019-10-17 19:48:34 +08:00
if ( len = = 0 ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG )
2019-10-16 20:17:52 +08:00
Dbprintf ( " Error: Time out card selection! " ) ;
2019-03-10 03:34:41 +08:00
return 1 ;
2019-10-16 20:17:52 +08:00
}
2019-03-10 03:34:41 +08:00
// wrong answer
2019-10-17 19:48:34 +08:00
if ( FelicaFrame . framebytes [ 3 ] ! = FELICA_POLL_ACK ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG )
2019-10-17 19:48:34 +08:00
Dbprintf ( " Error: Wrong answer selecting card! " ) ;
2019-03-10 03:34:41 +08:00
return 2 ;
2019-10-16 20:17:52 +08:00
}
2019-03-10 03:34:41 +08:00
// VALIDATE CRC residue is 0, hence if crc is a value it failed.
2019-10-17 19:48:34 +08:00
if ( ! check_crc ( CRC_FELICA , FelicaFrame . framebytes + 2 , FelicaFrame . len - 2 ) ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2019-10-16 20:17:52 +08:00
Dbprintf ( " Error: CRC check failed! " ) ;
Dbprintf ( " CRC check was done on Frame: " ) ;
Dbhexdump ( FelicaFrame . len - 2 , FelicaFrame . framebytes + 2 , 0 ) ;
}
2019-03-10 03:34:41 +08:00
return 3 ;
2019-10-16 20:17:52 +08:00
}
2019-03-10 03:34:41 +08:00
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG )
2019-10-16 20:17:52 +08:00
Dbprintf ( " Card selection successful! " ) ;
2019-03-10 03:34:41 +08:00
// copy UID
// idm 8
if ( card ) {
memcpy ( card - > IDm , FelicaFrame . framebytes + 4 , 8 ) ;
memcpy ( card - > PMm , FelicaFrame . framebytes + 4 + 8 , 8 ) ;
//memcpy(card->servicecode, FelicaFrame.framebytes + 4 + 8 + 8, 2);
memcpy ( card - > code , card - > IDm , 2 ) ;
memcpy ( card - > uid , card - > IDm + 2 , 6 ) ;
memcpy ( card - > iccode , card - > PMm , 2 ) ;
2019-03-10 07:00:59 +08:00
memcpy ( card - > mrt , card - > PMm + 2 , 6 ) ;
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2019-10-16 20:17:52 +08:00
Dbprintf ( " Received Frame: " ) ;
Dbhexdump ( FelicaFrame . len , FelicaFrame . framebytes , 0 ) ;
}
2019-03-10 03:34:41 +08:00
}
// more status bytes?
return 0 ;
2017-10-21 02:30:17 +08:00
}
// poll-0: 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21,
// resp: 0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80,0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f,
// poll-1 (reply with available system codes - NFC Tag3 specs, IIRC): 0xb2,0x4d,0x06,0x00,0xff,0xff,0x01,0x00,0x3a,0x10
// resp: 0xb2,0x4d,0x14,0x01, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0x0c,0xe2,
// page-req: 0xb2,0x4d,0x10,0x06, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x01, 0x0b,0x00, 0x01, 0x80,0x00, 0x2e,0xb3,
2019-03-09 15:59:13 +08:00
// page-req: 0x06, IDm(8), ServiceNum(1),Slist(2*num) BLocknum (1) BLockids(2-3*num)
2017-10-21 02:30:17 +08:00
// page-resp: 0xb2,0x4d,0x1d,0x07, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00, 0x00, 0x01, 0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23, 0xcb,0x6e,
2019-03-09 15:59:13 +08:00
// builds a readblock frame for felica lite(s). Using SERVICE: SERVICE_FELICA_LITE_READONLY
// Felica standard has a different file system, AFAIK,
2018-01-30 10:29:37 +08:00
// 8-byte IDm, number of blocks, blocks numbers
2017-10-21 02:30:17 +08:00
// number of blocks limited to 4 for FelicaLite(S)
2022-02-27 22:00:50 +08:00
static void BuildFliteRdblk ( const uint8_t * idm , uint8_t blocknum , const uint16_t * blocks ) {
2017-11-11 08:26:53 +08:00
if ( blocknum > 4 | | blocknum < = 0 )
2019-01-09 19:05:29 +08:00
Dbprintf ( " Invalid number of blocks, %d != 4 " , blocknum ) ;
2019-03-09 15:59:13 +08:00
2018-01-29 20:42:02 +08:00
uint8_t c = 0 , i = 0 ;
2019-03-09 15:59:13 +08:00
2020-01-22 01:07:18 +08:00
// Sync bytes
2017-11-11 08:26:53 +08:00
frameSpace [ c + + ] = 0xb2 ;
frameSpace [ c + + ] = 0x4d ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
c + + ; //set length later
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
frameSpace [ c + + ] = FELICA_RDBLK_REQ ; //command number
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
//card IDm, from poll
frameSpace [ c + + ] = idm [ 0 ] ;
frameSpace [ c + + ] = idm [ 1 ] ;
frameSpace [ c + + ] = idm [ 2 ] ;
frameSpace [ c + + ] = idm [ 3 ] ;
frameSpace [ c + + ] = idm [ 4 ] ;
frameSpace [ c + + ] = idm [ 5 ] ;
frameSpace [ c + + ] = idm [ 6 ] ;
frameSpace [ c + + ] = idm [ 7 ] ;
2018-01-30 10:29:37 +08:00
2019-03-10 03:34:41 +08:00
//number of services
2019-03-09 15:59:13 +08:00
frameSpace [ c + + ] = 0x01 ;
2019-03-10 03:34:41 +08:00
//service code
frameSpace [ c + + ] = ( SERVICE_FELICA_LITE_READONLY > > 8 ) ;
2018-01-30 10:29:37 +08:00
frameSpace [ c + + ] = SERVICE_FELICA_LITE_READONLY & 0xFF ;
2019-03-10 03:34:41 +08:00
//number of blocks
2018-01-30 10:29:37 +08:00
frameSpace [ c + + ] = blocknum ;
2018-01-29 20:42:02 +08:00
2019-03-10 07:00:59 +08:00
for ( i = 0 ; i < blocknum ; i + + ) {
2017-11-11 08:26:53 +08:00
2019-03-10 03:34:41 +08:00
//3-byte block
if ( blocks [ i ] > = 256 ) {
2019-03-10 07:00:59 +08:00
frameSpace [ c + + ] = 0x00 ;
frameSpace [ c + + ] = ( blocks [ i ] > > 8 ) ; //block number, little endian....
frameSpace [ c + + ] = ( blocks [ i ] & 0xff ) ;
2017-11-11 08:26:53 +08:00
} else {
frameSpace [ c + + ] = 0x80 ;
frameSpace [ c + + ] = blocks [ i ] ;
2017-10-21 02:30:17 +08:00
}
}
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
//set length
2019-03-10 07:00:59 +08:00
frameSpace [ 2 ] = c - 2 ;
2020-01-22 01:07:18 +08:00
//Add CRC
AddCrc ( frameSpace + 2 , c - 2 ) ;
2017-10-21 02:30:17 +08:00
}
2022-02-27 22:00:50 +08:00
static void TransmitFor18092_AsReader ( uint8_t * frame , uint16_t len , uint32_t * timing , uint8_t power , uint8_t highspeed ) {
2020-07-06 21:16:00 +08:00
uint16_t flags = FPGA_MAJOR_MODE_HF_ISO18092 ;
2019-03-10 07:00:59 +08:00
if ( power )
2019-03-10 03:34:41 +08:00
flags | = FPGA_HF_ISO18092_FLAG_READER ;
if ( highspeed )
flags | = FPGA_HF_ISO18092_FLAG_424K ;
2017-10-21 02:30:17 +08:00
2019-03-10 03:34:41 +08:00
FpgaWriteConfWord ( flags ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
uint32_t curr_transfer_time = ( ( MAX ( felica_nexttransfertime , GetCountSspClk ( ) ) & 0xfffffff8 ) + 8 ) ;
2018-01-30 10:29:37 +08:00
2019-03-10 03:34:41 +08:00
while ( GetCountSspClk ( ) < curr_transfer_time ) { } ;
2018-01-30 10:29:37 +08:00
2019-03-10 03:34:41 +08:00
felica_lasttime_prox2air_start = curr_transfer_time ;
2019-03-09 15:59:13 +08:00
2018-01-29 20:42:02 +08:00
// preamble
2019-03-10 03:34:41 +08:00
// sending 0x00 0x00 0x00 0x00 0x00 0x00
uint16_t c = 0 ;
while ( c < 6 ) {
// keep tx buffer in a defined state anyway.
if ( AT91C_BASE_SSC - > SSC_SR & ( AT91C_SSC_TXRDY ) ) {
AT91C_BASE_SSC - > SSC_THR = 0x00 ;
c + + ;
}
}
2019-10-16 20:17:52 +08:00
// sending data with sync bytes
2019-03-10 03:34:41 +08:00
c = 0 ;
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2019-10-16 20:17:52 +08:00
Dbprintf ( " Sending frame: " ) ;
Dbhexdump ( len , frame , 0 ) ;
}
2019-03-10 03:34:41 +08:00
while ( c < len ) {
// Put byte into tx holding register as soon as it is ready
if ( AT91C_BASE_SSC - > SSC_SR & ( AT91C_SSC_TXRDY ) ) {
AT91C_BASE_SSC - > SSC_THR = frame [ c + + ] ;
}
}
2017-10-21 02:30:17 +08:00
2019-03-10 07:00:59 +08:00
/**/
2019-03-10 03:34:41 +08:00
while ( ! ( AT91C_BASE_SSC - > SSC_SR & ( AT91C_SSC_TXRDY ) ) ) { } ;
AT91C_BASE_SSC - > SSC_THR = 0x00 ; //minimum delay
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
while ( ! ( AT91C_BASE_SSC - > SSC_SR & ( AT91C_SSC_TXRDY ) ) ) { } ;
AT91C_BASE_SSC - > SSC_THR = 0x00 ; //spin
2019-03-10 07:00:59 +08:00
/**/
2017-10-21 02:30:17 +08:00
2019-03-10 03:34:41 +08:00
// log
LogTrace (
frame ,
len ,
2019-03-10 07:00:59 +08:00
( felica_lasttime_prox2air_start < < 4 ) + DELAY_ARM2AIR_AS_READER ,
( ( felica_lasttime_prox2air_start + felica_lasttime_prox2air_start ) < < 4 ) + DELAY_ARM2AIR_AS_READER ,
2019-03-10 03:34:41 +08:00
NULL ,
true
) ;
2019-03-10 07:00:59 +08:00
felica_nexttransfertime = MAX ( felica_nexttransfertime , felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME ) ;
2018-01-29 20:42:02 +08:00
}
2018-01-30 10:29:37 +08:00
// Wait for tag reply
// stop when button is pressed
// or return TRUE when command is captured
2019-03-10 18:20:22 +08:00
bool WaitForFelicaReply ( uint16_t maxbytes ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG )
2019-10-16 20:17:52 +08:00
Dbprintf ( " WaitForFelicaReply Start " ) ;
2019-03-10 03:34:41 +08:00
uint32_t c = 0 ;
// power, no modulation
2020-01-12 07:30:23 +08:00
FpgaWriteConfWord ( FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD ) ;
2019-03-10 03:34:41 +08:00
FelicaFrameReset ( ) ;
2018-01-29 20:42:02 +08:00
2019-03-10 03:34:41 +08:00
// clear RXRDY:
uint8_t b = ( uint8_t ) AT91C_BASE_SSC - > SSC_RHR ;
2020-01-02 05:13:24 +08:00
( void ) b ;
2019-03-10 03:34:41 +08:00
uint32_t timeout = iso18092_get_timeout ( ) ;
2019-10-22 21:56:05 +08:00
2019-03-10 07:00:59 +08:00
for ( ; ; ) {
2019-03-09 15:59:13 +08:00
WDT_HIT ( ) ;
2019-03-10 03:34:41 +08:00
if ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_RXRDY ) {
b = ( uint8_t ) ( AT91C_BASE_SSC - > SSC_RHR ) ;
Process18092Byte ( b ) ;
if ( FelicaFrame . state = = STATE_FULL ) {
2019-10-22 21:56:05 +08:00
felica_nexttransfertime = MAX ( felica_nexttransfertime ,
2019-11-01 22:19:09 +08:00
( GetCountSspClk ( ) & 0xfffffff8 ) - ( DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER ) / 16 + FELICA_FRAME_DELAY_TIME ) ;
2019-11-01 22:06:48 +08:00
2019-03-10 03:34:41 +08:00
LogTrace (
FelicaFrame . framebytes ,
FelicaFrame . len ,
2019-03-10 07:00:59 +08:00
( ( GetCountSspClk ( ) & 0xfffffff8 ) < < 4 ) - DELAY_AIR2ARM_AS_READER - timeout ,
( ( GetCountSspClk ( ) & 0xfffffff8 ) < < 4 ) - DELAY_AIR2ARM_AS_READER ,
2019-03-10 03:34:41 +08:00
NULL ,
false
) ;
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) Dbprintf ( " All bytes received! STATE_FULL " ) ;
2019-03-10 03:34:41 +08:00
return true ;
2020-05-13 06:36:52 +08:00
} else if ( c + + > timeout & & ( FelicaFrame . state = = STATE_UNSYNCD | | FelicaFrame . state = = STATE_TRYING_SYNC ) ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) Dbprintf ( " Error: Timeout! STATE_UNSYNCD " ) ;
2019-03-10 03:34:41 +08:00
return false ;
2019-10-17 17:46:59 +08:00
}
2019-03-10 03:34:41 +08:00
}
}
2018-01-29 20:42:02 +08:00
}
// Set up FeliCa communication (similar to iso14443a_setup)
// field is setup for "Sending as Reader"
2019-03-10 18:20:22 +08:00
static void iso18092_setup ( uint8_t fpga_minor_mode ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) Dbprintf ( " Start iso18092_setup " ) ;
2018-08-13 03:54:31 +08:00
2019-03-10 03:34:41 +08:00
LEDsoff ( ) ;
2021-08-22 05:43:06 +08:00
# if defined XC3
FpgaDownloadAndGo ( FPGA_BITSTREAM_HF ) ;
# else
2020-07-09 05:11:29 +08:00
FpgaDownloadAndGo ( FPGA_BITSTREAM_HF_FELICA ) ;
2021-08-22 05:43:06 +08:00
# endif
2019-03-10 03:34:41 +08:00
// allocate command receive buffer
2019-03-10 07:00:59 +08:00
BigBuf_free ( ) ;
BigBuf_Clear_ext ( false ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// Initialize Demod and Uart structs
2019-11-01 22:06:48 +08:00
// DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
2019-03-10 03:34:41 +08:00
FelicaFrameinit ( BigBuf_malloc ( FELICA_MAX_FRAME_SIZE ) ) ;
2018-01-29 20:42:02 +08:00
2019-03-10 03:34:41 +08:00
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER ;
iso18092_set_timeout ( 2120 ) ; // 106 * 20ms maximum start-up time of card
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
init_table ( CRC_FELICA ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// connect Demodulated Signal to ADC:
SetAdcMuxFor ( GPIO_MUXSEL_HIPKD ) ;
2018-01-29 20:42:02 +08:00
2019-03-10 03:34:41 +08:00
// Set up the synchronous serial port
2020-07-07 19:18:53 +08:00
FpgaSetupSsc ( FPGA_MAJOR_MODE_HF_ISO18092 ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// LSB transfer. Remember to set it back to MSB with
AT91C_BASE_SSC - > SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD ( 8 ) | SSC_FRAME_MODE_WORDS_PER_TRANSFER ( 0 ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// Signal field is on with the appropriate LED
2020-01-12 07:30:23 +08:00
FpgaWriteConfWord ( FPGA_MAJOR_MODE_HF_ISO18092 | fpga_minor_mode ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
//20.4 ms generate field, start sending polling command afterwars.
SpinDelay ( 100 ) ;
2018-01-29 20:42:02 +08:00
2019-03-10 03:34:41 +08:00
// Start the timer
StartCountSspClk ( ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
LED_D_ON ( ) ;
2018-01-29 20:42:02 +08:00
}
2019-10-17 17:46:59 +08:00
2020-05-10 22:59:38 +08:00
static void felica_reset_frame_mode ( void ) {
2019-10-17 17:46:59 +08:00
switch_off ( ) ;
//Resetting Frame mode (First set in fpgaloader.c)
AT91C_BASE_SSC - > SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD ( 8 ) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER ( 0 ) ;
}
2018-01-29 20:42:02 +08:00
//-----------------------------------------------------------------------------
// RAW FeliCa commands. Send out commands and store answers.
//-----------------------------------------------------------------------------
2019-03-10 03:34:41 +08:00
// arg0 FeliCa flags
// arg1 len of commandbytes
2019-03-09 15:59:13 +08:00
// d.asBytes command bytes to send
2019-04-18 18:43:35 +08:00
void felica_sendraw ( PacketCommandNG * c ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) Dbprintf ( " FeliCa_sendraw Enter " ) ;
2018-01-29 20:42:02 +08:00
2019-04-18 06:12:52 +08:00
felica_command_t param = c - > oldarg [ 0 ] ;
size_t len = c - > oldarg [ 1 ] & 0xffff ;
uint8_t * cmd = c - > data . asBytes ;
2019-04-16 21:05:01 +08:00
uint32_t arg0 ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
felica_card_select_t card ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
if ( ( param & FELICA_CONNECT ) )
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) Dbprintf ( " Clear trace " ) ;
2019-10-17 19:48:34 +08:00
clear_trace ( ) ;
2018-01-29 20:42:02 +08:00
2019-03-10 03:34:41 +08:00
set_tracing ( true ) ;
2019-10-16 20:17:52 +08:00
iso18092_setup ( FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD ) ;
2018-01-29 20:42:02 +08:00
2019-03-10 03:34:41 +08:00
if ( ( param & FELICA_CONNECT ) ) {
// notify client selecting status.
// if failed selecting, turn off antenna and quite.
2019-03-10 07:00:59 +08:00
if ( ! ( param & FELICA_NO_SELECT ) ) {
2019-03-10 03:34:41 +08:00
arg0 = felica_select_card ( & card ) ;
2019-10-17 17:46:59 +08:00
reply_mix ( CMD_ACK , arg0 , sizeof ( card . uid ) , 0 , & card , sizeof ( felica_card_select_t ) ) ;
2019-10-17 19:48:34 +08:00
if ( arg0 > 0 ) {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) Dbprintf ( " Error: Failed selecting card! " ) ;
2019-10-17 17:46:59 +08:00
felica_reset_frame_mode ( ) ;
return ;
2019-10-16 20:17:52 +08:00
}
2019-03-10 03:34:41 +08:00
}
2019-10-17 19:48:34 +08:00
} else {
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) Dbprintf ( " No card selection " ) ;
2019-03-10 03:34:41 +08:00
}
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
if ( ( param & FELICA_RAW ) ) {
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// 2 sync, 1 len, 2crc == 5
2019-03-10 07:00:59 +08:00
uint8_t * buf = BigBuf_malloc ( len + 5 ) ;
2019-03-10 03:34:41 +08:00
// add sync bits
buf [ 0 ] = 0xb2 ;
buf [ 1 ] = 0x4d ;
buf [ 2 ] = len ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// copy command
2019-03-10 07:00:59 +08:00
memcpy ( buf + 2 , cmd , len ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
if ( ( param & FELICA_APPEND_CRC ) ) {
// Don't append crc on empty bytearray...
2019-03-10 07:00:59 +08:00
if ( len > 0 ) {
2022-04-27 10:38:28 +08:00
AddCrc ( buf + 2 , len ) ;
2019-03-10 03:34:41 +08:00
}
}
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2019-10-16 20:17:52 +08:00
Dbprintf ( " Transmit Frame (no CRC shown): " ) ;
Dbhexdump ( len , buf , 0 ) ;
Dbprintf ( " Buffer Length: %i " , buf [ 2 ] + 4 ) ;
} ;
2019-03-10 07:00:59 +08:00
TransmitFor18092_AsReader ( buf , buf [ 2 ] + 4 , NULL , 1 , 0 ) ;
2019-10-16 20:17:52 +08:00
arg0 = WaitForFelicaReply ( 1024 ) ;
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2019-10-17 17:46:59 +08:00
Dbprintf ( " Received Frame Code: %d " , arg0 ) ;
2019-10-16 20:17:52 +08:00
Dbhexdump ( FelicaFrame . len , FelicaFrame . framebytes , 0 ) ;
} ;
2019-10-21 00:28:07 +08:00
2019-10-17 17:46:59 +08:00
uint32_t result = reply_mix ( CMD_ACK , FelicaFrame . len , arg0 , 0 , FelicaFrame . framebytes , FelicaFrame . len ) ;
2019-10-17 19:48:34 +08:00
if ( result ) {
2019-10-17 17:46:59 +08:00
Dbprintf ( " Reply to Client Error Code: %i " , result ) ;
}
2019-03-10 03:34:41 +08:00
}
2019-10-17 19:48:34 +08:00
if ( ( param & FELICA_NO_DISCONNECT ) ) {
2019-10-16 20:17:52 +08:00
Dbprintf ( " Disconnect " ) ;
2019-10-17 17:46:59 +08:00
}
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG )
2019-10-17 17:46:59 +08:00
Dbprintf ( " FeliCa_sendraw Exit " ) ;
felica_reset_frame_mode ( ) ;
return ;
2018-01-29 20:42:02 +08:00
}
2019-03-10 18:20:22 +08:00
void felica_sniff ( uint32_t samplesToSkip , uint32_t triggersToSkip ) {
2021-03-27 04:01:50 +08:00
2019-11-01 22:06:48 +08:00
clear_trace ( ) ;
set_tracing ( true ) ;
2019-03-10 07:00:59 +08:00
iso18092_setup ( FPGA_HF_ISO18092_FLAG_NOMOD ) ;
2021-03-27 04:01:50 +08:00
2019-10-30 20:35:03 +08:00
LED_D_ON ( ) ;
2021-03-27 04:01:50 +08:00
int retval = PM3_SUCCESS ;
int remFrames = ( samplesToSkip ) ? samplesToSkip : 0 ;
2019-11-01 22:06:48 +08:00
int trigger_cnt = 0 ;
uint32_t timeout = iso18092_get_timeout ( ) ;
2019-11-01 22:37:53 +08:00
bool isReaderFrame = true ;
2021-03-27 04:01:50 +08:00
uint8_t flip = 0 ;
uint16_t checker = 0 ;
for ( ; ; ) {
2019-10-30 20:35:03 +08:00
WDT_HIT ( ) ;
2021-03-27 04:01:50 +08:00
// since simulation is a tight time critical loop,
2021-04-08 16:44:31 +08:00
// we only check for user request to end at iteration 3000, 9000.
2021-03-27 04:01:50 +08:00
if ( flip = = 3 ) {
if ( data_available ( ) ) {
retval = PM3_EOPABORTED ;
break ;
}
flip = 0 ;
}
if ( checker > = 3000 ) {
if ( BUTTON_PRESS ( ) ) {
retval = PM3_EOPABORTED ;
break ;
}
flip + + ;
checker = 0 ;
}
+ + checker ;
2018-01-29 20:42:02 +08:00
if ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_RXRDY ) {
2021-03-27 04:01:50 +08:00
2018-01-29 20:42:02 +08:00
uint8_t dist = ( uint8_t ) ( AT91C_BASE_SSC - > SSC_RHR ) ;
2019-01-09 19:05:29 +08:00
Process18092Byte ( dist ) ;
2021-03-27 04:01:50 +08:00
2020-01-04 22:55:50 +08:00
if ( ( dist > = 178 ) & & ( + + trigger_cnt > triggersToSkip ) ) {
2021-03-27 04:01:50 +08:00
Dbprintf ( " triggers To skip kicked %d " , dist ) ;
2019-11-01 22:06:48 +08:00
break ;
2018-01-29 20:42:02 +08:00
}
2019-01-07 03:42:51 +08:00
if ( FelicaFrame . state = = STATE_FULL ) {
2019-11-01 22:37:53 +08:00
if ( ( FelicaFrame . framebytes [ 3 ] % 2 ) = = 0 ) {
isReaderFrame = true ; // All Reader Frames are even and all Tag frames are odd
} else {
isReaderFrame = false ;
}
2018-01-29 20:42:02 +08:00
remFrames - - ;
2019-11-01 22:19:09 +08:00
if ( remFrames < = 0 ) {
2021-03-27 04:01:50 +08:00
Dbprintf ( " Stop Sniffing - samples To skip reached! " ) ;
2019-11-01 22:06:48 +08:00
break ;
}
LogTrace ( FelicaFrame . framebytes ,
FelicaFrame . len ,
( ( GetCountSspClk ( ) & 0xfffffff8 ) < < 4 ) - DELAY_AIR2ARM_AS_READER - timeout ,
( ( GetCountSspClk ( ) & 0xfffffff8 ) < < 4 ) - DELAY_AIR2ARM_AS_READER ,
NULL ,
2019-11-01 22:37:53 +08:00
isReaderFrame
2019-11-01 22:19:09 +08:00
) ;
2019-03-10 03:34:41 +08:00
FelicaFrameReset ( ) ;
2018-01-29 20:42:02 +08:00
}
}
}
2019-03-10 03:34:41 +08:00
switch_off ( ) ;
2018-01-29 20:42:02 +08:00
//reset framing
AT91C_BASE_SSC - > SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD ( 8 ) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER ( 0 ) ;
2021-03-27 04:01:50 +08:00
Dbprintf ( " Felica sniffing done, tracelen: %i " , BigBuf_get_traceLen ( ) ) ;
reply_ng ( CMD_HF_FELICA_SNIFF , retval , NULL , 0 ) ;
2019-10-30 20:35:03 +08:00
LED_D_OFF ( ) ;
2017-10-21 02:30:17 +08:00
}
2017-11-11 08:26:53 +08:00
# define R_POLL0_LEN 0x16
# define R_POLL1_LEN 0x18
# define R_READBLK_LEN 0x21
2017-10-21 02:30:17 +08:00
//simulate NFC Tag3 card - for now only poll response works
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
2021-03-25 16:39:40 +08:00
void felica_sim_lite ( uint8_t * uid ) {
2018-01-30 10:29:37 +08:00
2021-03-25 16:39:40 +08:00
// prepare our 3 responses...
2019-03-10 07:00:59 +08:00
uint8_t resp_poll0 [ R_POLL0_LEN ] = { 0xb2 , 0x4d , 0x12 , FELICA_POLL_ACK , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xf1 , 0x00 , 0x00 , 0x00 , 0x01 , 0x43 , 0x00 , 0xb3 , 0x7f } ;
uint8_t resp_poll1 [ R_POLL1_LEN ] = { 0xb2 , 0x4d , 0x14 , FELICA_POLL_ACK , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xf1 , 0x00 , 0x00 , 0x00 , 0x01 , 0x43 , 0x00 , 0x88 , 0xb4 , 0xb3 , 0x7f } ;
uint8_t resp_readblk [ R_READBLK_LEN ] = { 0xb2 , 0x4d , 0x1d , FELICA_RDBLK_ACK , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x10 , 0x04 , 0x01 , 0x00 , 0x0d , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x23 , 0xcb , 0x6e } ;
2019-03-09 15:59:13 +08:00
2021-03-25 16:39:40 +08:00
// NFC tag 3/ ISo technically. Many overlapping standards
DbpString ( " Felica Lite-S simulation start " ) ;
2017-11-11 08:26:53 +08:00
Dbprintf ( " NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x " ,
2021-03-25 16:39:40 +08:00
uid [ 0 ] , uid [ 1 ] , uid [ 2 ] , uid [ 3 ] , uid [ 4 ] , uid [ 5 ] , uid [ 6 ] , uid [ 7 ]
2019-03-10 07:00:59 +08:00
) ;
2019-03-09 15:59:13 +08:00
2021-03-25 16:39:40 +08:00
// fill in blanks
for ( uint8_t i = 0 ; i < 8 ; i + + ) {
resp_poll0 [ i + 4 ] = uid [ i ] ;
resp_poll1 [ i + 4 ] = uid [ i ] ;
resp_readblk [ i + 4 ] = uid [ i ] ;
2017-10-21 02:30:17 +08:00
}
2018-01-30 10:29:37 +08:00
2021-03-25 16:39:40 +08:00
// calculate and set CRC
2021-11-18 19:20:09 +08:00
AddCrc ( & resp_poll0 [ 2 ] , resp_poll0 [ 2 ] ) ;
AddCrc ( & resp_poll1 [ 2 ] , resp_poll1 [ 2 ] ) ;
AddCrc ( & resp_readblk [ 2 ] , resp_readblk [ 2 ] ) ;
2017-10-21 02:30:17 +08:00
2019-03-10 07:00:59 +08:00
iso18092_setup ( FPGA_HF_ISO18092_FLAG_NOMOD ) ;
2017-10-21 02:30:17 +08:00
2021-03-25 16:39:40 +08:00
int retval = PM3_SUCCESS ;
int curlen = 0 ;
uint8_t * curresp = NULL ;
2019-03-10 03:34:41 +08:00
bool listenmode = true ;
2021-03-25 16:39:40 +08:00
// uint32_t frtm = GetCountSspClk();
2021-04-08 16:44:31 +08:00
2021-03-25 16:39:40 +08:00
uint8_t flip = 0 ;
uint16_t checker = 0 ;
2019-03-10 07:00:59 +08:00
for ( ; ; ) {
2021-03-25 16:39:40 +08:00
WDT_HIT ( ) ;
// since simulation is a tight time critical loop,
2021-04-08 16:44:31 +08:00
// we only check for user request to end at iteration 3000, 9000.
2021-03-25 16:39:40 +08:00
if ( flip = = 3 ) {
if ( data_available ( ) ) {
retval = PM3_EOPABORTED ;
break ;
}
flip = 0 ;
}
if ( checker > = 3000 ) {
if ( BUTTON_PRESS ( ) ) {
retval = PM3_EOPABORTED ;
break ;
}
flip + + ;
checker = 0 ;
}
+ + checker ;
2017-10-21 02:30:17 +08:00
WDT_HIT ( ) ;
if ( listenmode ) {
2021-03-25 16:39:40 +08:00
// waiting for request...
2017-10-21 02:30:17 +08:00
if ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_RXRDY ) {
2019-03-10 03:34:41 +08:00
uint8_t dist = ( uint8_t ) ( AT91C_BASE_SSC - > SSC_RHR ) ;
2021-03-25 16:39:40 +08:00
// frtm = GetCountSspClk();
2019-03-10 03:34:41 +08:00
Process18092Byte ( dist ) ;
2019-03-09 15:59:13 +08:00
2019-01-07 03:42:51 +08:00
if ( FelicaFrame . state = = STATE_FULL ) {
2017-10-21 02:30:17 +08:00
2019-01-07 03:42:51 +08:00
if ( FelicaFrame . crc_ok ) {
2019-03-09 15:59:13 +08:00
2019-01-07 03:42:51 +08:00
if ( FelicaFrame . framebytes [ 2 ] = = 6 & & FelicaFrame . framebytes [ 3 ] = = 0 ) {
2021-11-19 21:59:45 +08:00
static uint8_t timeslot = 0 ;
2017-10-21 02:30:17 +08:00
2021-03-25 16:39:40 +08:00
// polling... there are two types of polling we answer to
2019-03-10 03:34:41 +08:00
if ( FelicaFrame . framebytes [ 6 ] = = 0 ) {
curresp = resp_poll0 ;
curlen = R_POLL0_LEN ;
listenmode = false ;
}
if ( FelicaFrame . framebytes [ 6 ] = = 1 ) {
curresp = resp_poll1 ;
curlen = R_POLL1_LEN ;
2021-11-18 22:04:42 +08:00
listenmode = false ;
2019-03-10 03:34:41 +08:00
}
2021-11-19 21:59:45 +08:00
if ( timeslot > FelicaFrame . framebytes [ 7 ] ) {
// framebytes[7] contains the maximum time slot in which we are allowed to respond (#0..#15)
timeslot = 0 ;
}
// first time slot (#0) starts after 512 * 64 / fc, slot length equals 256 * 64 / fc
felica_nexttransfertime = GetCountSspClk ( ) - ( DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER ) / 16 + ( 512 + timeslot * 256 ) * 64 / 16 + 1 ;
timeslot + + ; // we should use a random time slot, but responding in incremental slots should do just fine for now
2017-10-21 02:30:17 +08:00
}
2019-03-09 15:59:13 +08:00
2019-01-07 03:42:51 +08:00
if ( FelicaFrame . framebytes [ 2 ] > 5 & & FelicaFrame . framebytes [ 3 ] = = 0x06 ) {
2021-03-25 16:39:40 +08:00
// we should rebuild it depending on page size, but...
// Let's see first
2017-10-21 02:30:17 +08:00
curresp = resp_readblk ;
curlen = R_READBLK_LEN ;
listenmode = false ;
}
2021-03-25 16:39:40 +08:00
// clear frame
2019-01-07 03:42:51 +08:00
FelicaFrameReset ( ) ;
2017-10-21 02:30:17 +08:00
} else {
2021-03-25 16:39:40 +08:00
// frame invalid, clear it out to allow for the next one
2019-03-10 03:34:41 +08:00
FelicaFrameReset ( ) ;
}
}
}
}
2021-03-25 16:39:40 +08:00
if ( listenmode = = false ) {
// trying to answer... here to start answering immediately.
// this one is a bit finicky. Seems that being a bit late is better than earlier
// TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0);
2019-03-10 03:34:41 +08:00
TransmitFor18092_AsReader ( curresp , curlen , NULL , 0 , 0 ) ;
2021-03-25 16:39:40 +08:00
// switch back
2020-01-12 07:30:23 +08:00
FpgaWriteConfWord ( FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD ) ;
2019-03-10 03:34:41 +08:00
FelicaFrameReset ( ) ;
listenmode = true ;
curlen = 0 ;
curresp = NULL ;
2017-10-21 02:30:17 +08:00
}
}
2019-03-09 15:59:13 +08:00
2018-01-06 00:39:04 +08:00
switch_off ( ) ;
2018-01-30 10:29:37 +08:00
2021-03-25 16:39:40 +08:00
// reset framing
2018-01-30 10:29:37 +08:00
AT91C_BASE_SSC - > SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD ( 8 ) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER ( 0 ) ;
2021-03-25 16:39:40 +08:00
Dbprintf ( " FeliCa Lite-S emulator stopped. Trace length: %d " , BigBuf_get_traceLen ( ) ) ;
reply_ng ( CMD_HF_FELICALITE_SIMULATE , retval , NULL , 0 ) ;
2017-10-21 02:30:17 +08:00
}
2019-10-20 04:12:33 +08:00
# define RES_SVC_LEN 11 + 3
2019-10-19 04:42:56 +08:00
2020-05-10 22:59:38 +08:00
void felica_dump_lite_s ( void ) {
2019-03-10 03:34:41 +08:00
uint8_t ndef [ 8 ] ;
2019-03-10 07:00:59 +08:00
uint8_t poll [ 10 ] = { 0xb2 , 0x4d , 0x06 , FELICA_POLL_REQ , 0xff , 0xff , 0x00 , 0x00 , 0x09 , 0x21 } ;
uint16_t liteblks [ 28 ] = { 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x80 , 0x81 , 0x82 , 0x83 , 0x84 , 0x85 , 0x86 , 0x87 , 0x88 , 0x90 , 0x91 , 0x92 , 0xa0 } ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// setup device.
iso18092_setup ( FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
uint8_t blknum ;
bool isOK = false ;
uint16_t cnt = 0 , cntfails = 0 ;
uint8_t * dest = BigBuf_get_addr ( ) ;
2017-10-21 02:30:17 +08:00
2022-01-07 02:41:45 +08:00
while ( ( BUTTON_PRESS ( ) = = false ) & & ( data_available ( ) = = false ) ) {
2019-03-10 03:34:41 +08:00
WDT_HIT ( ) ;
// polling?
//TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0);
TransmitFor18092_AsReader ( poll , 10 , NULL , 1 , 0 ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
if ( WaitForFelicaReply ( 512 ) & & FelicaFrame . framebytes [ 3 ] = = FELICA_POLL_ACK ) {
// copy 8bytes to ndef.
memcpy ( ndef , FelicaFrame . framebytes + 4 , 8 ) ;
// for (c=0; c < 8; c++)
2019-03-10 07:00:59 +08:00
// ndef[c] = FelicaFrame.framebytes[c+4];
2018-01-29 20:42:02 +08:00
2019-08-01 06:14:09 +08:00
for ( blknum = 0 ; blknum < ARRAYLEN ( liteblks ) ; ) {
2019-03-10 03:34:41 +08:00
// block to read.
BuildFliteRdblk ( ndef , 1 , & liteblks [ blknum ] ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
//TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0);
2019-03-09 15:59:13 +08:00
2020-01-22 01:07:18 +08:00
TransmitFor18092_AsReader ( frameSpace , frameSpace [ 2 ] + 4 , NULL , 1 , 0 ) ;
2019-03-10 03:34:41 +08:00
// read block
if ( WaitForFelicaReply ( 1024 ) & & FelicaFrame . framebytes [ 3 ] = = FELICA_RDBLK_ACK ) {
2017-10-21 02:30:17 +08:00
2019-03-10 03:34:41 +08:00
dest [ cnt + + ] = liteblks [ blknum ] ;
2017-10-21 02:30:17 +08:00
2019-03-10 03:34:41 +08:00
uint8_t * fb = FelicaFrame . framebytes ;
dest [ cnt + + ] = fb [ 12 ] ;
dest [ cnt + + ] = fb [ 13 ] ;
2017-10-21 02:30:17 +08:00
2019-03-10 03:34:41 +08:00
//memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16);
//cnt += 16;
2019-03-10 07:00:59 +08:00
for ( uint8_t j = 0 ; j < 16 ; j + + )
dest [ cnt + + ] = fb [ 15 + j ] ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
blknum + + ;
cntfails = 0 ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
// // print raw log.
// Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt);
2019-03-10 07:00:59 +08:00
Dbhexdump ( FelicaFrame . len , FelicaFrame . framebytes + 15 , 0 ) ;
2019-03-10 03:34:41 +08:00
} else {
cntfails + + ;
if ( cntfails > 12 ) {
blknum + + ;
cntfails = 0 ;
}
}
}
2020-01-22 01:07:18 +08:00
2019-03-10 03:34:41 +08:00
isOK = true ;
break ;
}
}
switch_off ( ) ;
2018-01-06 00:39:04 +08:00
2019-03-10 03:34:41 +08:00
//Resetting Frame mode (First set in fpgaloader.c)
2017-10-21 02:30:17 +08:00
AT91C_BASE_SSC - > SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD ( 8 ) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER ( 0 ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
//setting tracelen - important! it was set by buffer overflow before
2017-10-21 02:30:17 +08:00
set_tracelen ( cnt ) ;
2020-04-08 11:29:22 +08:00
reply_mix ( CMD_ACK , isOK , cnt , 0 , 0 , 0 ) ;
2018-01-29 20:42:02 +08:00
}