Topic: Passive target mode initialization *without* secondary reader
Having experimented with the SCM SCL3710 dongle (bearing PN531 v4.2) I have found a workaround for the passive target mode initialization. In the approach described hereafter, it is not necessary to use the secondary “starting” reader for establishing the transparent target mode communication channel (used e.g. in nfc-emulate.c).
Well, regarding the anticollision emulation, there is still a problem with the communication speed (cf. here). On the other hand, I guess that removing the “starting” reader obstacle is worth it anyway. It can, for instance, serve as further inspiration for those approaches based on using high-speed communication interfaces of PN53x to speed up the anti-collision response (cf. here).
The alternative approach is based on direct register modification of the contactless unit of the PN531 controller. I call it DRH – Direct Register Hack method. There are two major steps:
1) issue a “dummy” TgInitTAMATargert command (D4 8C),
2) perform several direct register setups using the WriteRegister command (D4 08).
The first step ensures proper context clean up including (possible) certain internal variables of the embedded C51 core firmware. Without this step, the method did not work correctly if e.g. the dongle was configured in initiator mode before. It is important to say this is really a “dummy” command – we do not have to wait for its completion. In fact, it never completes without the secondary reader. The reset being desired, however, is done right at the start. What follows is running the anti-collision microcode command of the internal CL unit. Since we do not expect this will ever succeed, we directly continue with step two. Note that issuing the first WriteRegister command automatically cancels the still running “dummy” TgInitTAMATarget.
The second step ensures manual setup of those relevant registers of the internal CL unit. Finally, it starts the Transceive CL unit microcode, leaving the whole NFC controller in approximately the same state as it would be after a successful TgInitTAMATarget.
Long story short, the following procedure describes all necessary details. Note that issuing strictly “dummy” TgInitTAMATarget with libnfc would require a bit more coding. Since the aim of this demonstration was to experimentally enhance nfc-emulate.c in the simplest way, I decide to stand the implicit 30 seconds USB timeout enforced by pn53x_usb_transceive().
/* performs alternative target init */
bool target_init_alt2(nfc_device_t *pnd) {
bool r = true;
/*
* Issue standard TgInitTAMATarget cmd (encapsulated in nfc_target_init()).
* This gives a chance to use secondary starting reader.
* If not successfull, the command will at least reset the PN53x context.
* IMPORTANT: The context reset is neccessary, therefore this command
* must NOT be omitted even if secondary reader is not considered!
* It can be, however, issued directly, without the standard timeout then.
* Direct issuing is effective and elegant, but the code is then dependent
* on the particular transport layer (libusb, pcsc, etc.) used. Therefore,
* it cannot be written in such a simple way like this demo.
*/
printf("[+] Performing an enhanced passive target mode initialization.\n");
printf("[+] Now, you can use secondary reader to break the anti-collision.\n");
printf("[+] To do so, please send e.g. RATS after the anti-collision(select).\n");
printf("[+] ...for the alternative init, please do nothing - just wait for the timeout.\n");
if (nfc_target_init(pnd,abtRecv,&szRecvBits)) {
printf("[+] Target mode successfully started.\n");
printf("[+] Received initiator command: ");
print_hex_bits(abtRecv,szRecvBits);
return true;
}
/*
* Well, the standard initialization has obviously failed.
* Nevermind - we will enforce the passive target mode by
* the direct register hack (DRH) method instead.
*/
printf("[+] Secondary reader not met - performing DRH alternative setup.\n");
// INITIALLY - Stop eventual running CL unit microcode command
r *= pn53x_set_reg(pnd, 0x6331, 0x3f, 0x00);
// Configure WaterLevel
r *= pn53x_set_reg(pnd, 0x633b, 0x7f, 0x3a);
// Configure Diverse Control
r *= pn53x_set_reg(pnd, 0x633c, 0x7f, 0x00);
// Configure TxMode, preserve TxCRCEn flag
r *= pn53x_set_reg(pnd, 0x6302, 0x7f, 0x00);
// Configure RxMode, preserve RxCRCEn flag
r *= pn53x_set_reg(pnd, 0x6303, 0x7f, 0x00);
// Configure TxAuto
r *= pn53x_set_reg(pnd, 0x6305, 0xef, 0x00);
// Configure RxThreshold
r *= pn53x_set_reg(pnd, 0x6308, 0xf7, 0x85);
// Configure Demod
r *= pn53x_set_reg(pnd, 0x6309, 0xef, 0x61);
// Configure GsNLoadMod
r *= pn53x_set_reg(pnd, 0x6313, 0xff, 0x6f);
// Configure RFCfg
r *= pn53x_set_reg(pnd, 0x6316, 0xff, 0x59);
// Configure GsN
r *= pn53x_set_reg(pnd, 0x6317, 0xff, 0xf4);
// Configure CWGsP
r *= pn53x_set_reg(pnd, 0x6318, 0x3f, 0x3f);
// Configure ModGsP
r *= pn53x_set_reg(pnd, 0x6319, 0x3f, 0x30);
// Configure TMode
r *= pn53x_set_reg(pnd, 0x631a, 0xff, 0x00);
// FINALLY - Start Transceive CL unit microcode command
r *= pn53x_set_reg(pnd, 0x6331, 0x3f, 0x0c);
if (!r) {
printf("[+] DRH failed!\n");
return false;
}
printf("[+] Done, welcome to the passive target mode.\n");
// Force REG_CIU_BIT_FRAMING update before next Tx
pnd->ui8TxBits = 255;
return r;
}The aforesaid snippet is rather a simple illustrative procedure. At first, it tries to use the classic (i.e. with the secondary “starting” reader) target mode setup. If it fails (nfc_target_init() times out – other possible failures of nfc_target_init() are neglected here), the alternative DRH approach is used.
The complete version of the patched nfc-emulate.c can be downloaded here. It was successfully tested with SCM SCL3710 dongle bearing PN531 v4.2 and libnfc 1.3.4 under Ubuntu 9.04 with kernel 2.6.28-19-generic. Simply put this code into src/examples and recompile it (e.g. make clean; make all).
Future research
The DRH method was discovered by simply comparing PN531 registers snapshots taken in several important states (after reset, after successful/unsuccessful TgInitTAMATarger, during transparent target mode communication, etc.). Actually, I have taken quite a lot of samples to see which register states are constant (and probably important) and which ones are rather transient (and hence probably unimportant). This simple idea may serve as a hint for your own further experiments involving different PN53x controllers and/or different readers bearing these chips. Good luck!
Kind regards,
Tomas Rosa
Last edited by tom314 (2010-07-15 07:55:36)