cancel
Showing results for 
Search instead for 
Did you mean: 

How to send ISO 14443A command frames with manual parity bits (ST25R3911B-DISCO)

Alex_Wolf
Associate II

Hi there!

I'm working on a Windows console application which uses ST25R3911DISCOComm DLL to communicate with ST25R3911B-DISCO board to process a ISO 14443A card (ST25R3911DISCOComm DLL is located in ST25R3911B_Discovery_GUI App installation directory).
My goal is to send commands with manual parity bits and CRC bytes. The problem I'm facing is no response from the card when RFAL_TXRX_FLAGS_PAR_TX_NONE flag is set.

For experimental purposes I tried to send a well known command RATS and to receive a well known response ATS from the card.

First of all I tried to send RATS command with auto generated parity bits yet manually calculated CRC bytes to see that the card returns the correct ATS answer:

 

 

flags = (RFAL_TXRX_FLAGS_NFCIP1_OFF | RFAL_TXRX_FLAGS_AGC_OFF | RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_CRC_RX_KEEP | RFAL_TXRX_FLAGS_CRC_TX_MANUAL); // here RFAL_TXRX_FLAGS_PAR_TX_NONE is not set so parity bit are generated automatically
memcpy(txBuf, "\xE0\x80\x31\x73", 4);
txBufLen = 4; // expressed in number of bytes

printf("Tx...\n");
ErrorCode = rfalTransceiveBlockingTx(Handle, txBuf, txBufLen, flags, fwt);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

printf("Rx...\n");
ErrorCode = rfalTransceiveBlockingRx(Handle, rxBuf, rxBufLen, &actLen);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

 

 

Here txBuf array contains command bytes to send: 'E0 80' - RATS command code and Param byte, '31 73' - CRC-16 value for 'E0 80'.
The card returns 72 bits (actLen = 72) as expected: 6 bytes of ATS value (48 bits in total) + 2 CRC bytes (16 bits in total) + 8 parity bits (1 parity bit for each byte).
I examined content of rxBuf array and the principle of data and parity bits placement in rxBuf array was understood.
My next step - similar to data and parity bits placement in rxBuf I prepared content of txBuf for RATS command with manually calculated parity bits and CRC bytes and tried several Tx functions from DLL to send RATS command:

1. Using function rfalTransceiveBlockingTx() with flag RFAL_TXRX_FLAGS_PAR_TX_NONE is set.

 

 

memcpy(txBuf, "\xE0\x00\xC5\x98\x03", 5);
flags = (RFAL_TXRX_FLAGS_NFCIP1_OFF | RFAL_TXRX_FLAGS_AGC_OFF | RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_CRC_RX_KEEP | RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_PAR_TX_NONE);
txBufLen = 4; // expressed in number of bytes

printf("Tx...\n");
ErrorCode = rfalTransceiveBlockingTx(Handle, txBuf, txBufLen, flags, fwt);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

printf("Rx...\n");
ErrorCode = rfalTransceiveBlockingRx(Handle, rxBuf, rxBufLen, &actLen);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

 

 

2. Using function rfalStartTransceive() with flag RFAL_TXRX_FLAGS_PAR_TX_NONE is set.

 

 

memcpy(txBuf, "\xE0\x00\xC5\x98\x03", 5);
flags = (RFAL_TXRX_FLAGS_NFCIP1_OFF | RFAL_TXRX_FLAGS_AGC_OFF | RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_CRC_RX_KEEP | RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_PAR_TX_NONE);
txBufLen = 36; // expressed in number of bits

printf("Tx...\n");
ErrorCode = rfalStartTransceive(Handle, txBuf, txBufLen, flags, fwt);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

printf("Rx...\n");
ErrorCode = rfalTransceiveBlockingRx(Handle, rxBuf, rxBufLen, &actLen);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

 

 

In both cases the card does not returns any response. Function CheckErrorCode (after calling rfalTransceiveBlockingRx) prints "Error Timeout".

One more thing. If assume that I make a mistake with the placements or values of the data and parity bits in txBuf array (but the total number of bits is still correct - 36 bits) the card should response with 4 bit error code anyway. Unfortunately the card does not returns anything. I guess for some reason ST25R3911B-DISCO does not send correct number of bits in the command.

I would be grateful for any help!

This discussion has been locked for participation. If you have a question, please start a new topic in order to ask your question
1 ACCEPTED SOLUTION

Accepted Solutions

Hi Alex_Wolf,

I was puzzled - for the GUI side function this length should have been a simple pass through. Unfortunately in the version on st.com this value gets essentially always rounded up to the next byte length.

As no new releases are planned as of now and we never released sources it is currently hard for me to offer you something right away - except if you are considering ugly hacks like changing the firmware to always rounding down the  ctx.txBufLen = txLen; to the nearest multiple of 9 or completely moving away from the DLL and do all USB HID reports on your own. Another option I am seeing is that there is the chance that latest ST25PC-NFC v3.0 contains a version which has this fixed. I expect you would need to move from 32-bit to 64-bit for using this one.

BR, Ulysses

 

View solution in original post

5 REPLIES 5
Ulysses HERNIOSUS
ST Employee

Hi Alex_Wolf,

 

for using bit-oriented frames you need to use the rfalStartTransceive() and rfalGetTransceiveStatus() API. The convenient blocking variants allow only the more common byte-oriented transceive.

I think https://community.st.com/t5/st25-nfc-rfid-tags-and-readers/nfc0541-read-mifare-classic-1k/m-p/255197#M5159 contains a recipe which you could use.

BR, Ulysses

Hi Ulysses,

I tried a combination of rfalStartTransceive() and rfalGetTransceiveStatus() functions but without success.

memcpy(txBuf, "\xE0\x00\xC5\x98\x03", 5);
flags = (RFAL_TXRX_FLAGS_NFCIP1_OFF | RFAL_TXRX_FLAGS_AGC_OFF | RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_CRC_RX_KEEP | RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_PAR_TX_NONE);
txBufLen = 36;  // expressed in number of bits

printf("Tx...\n");
ErrorCode = rfalStartTransceive(Handle, txBuf, txBufLen, flags, fwt);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

printf("Rx...\n");
do ErrorCode = rfalGetTransceiveStatus(Handle, rxBuf, rxBufLen, &actLen);
while (ErrorCode == Busy);
if (ErrorCode != NoError) CheckErrorCode(Handle, ErrorCode);

I got "Error Busy" and later "Error Timeout" after calling several times rfalGetTransceiveStatus() function (do...while loop is used to check ErrorCode value). fwt value is set to 10 ms.

I read the content of the topic https://community.st.com/t5/st25-nfc-rfid-tags-and-readers/nfc0541-read-mifare-classic-1k/m-p/255197#M5159. Unfortunately I did not find a solution to the problem. However, I was convinced that the bit sequence for RATS command was formed correctly by examining example of bit sequence presented in the topic for command 'a2 0f ...'.

Hi Ulysses,

It seems that I potentially have found a possible reason why the problem occurs. By reading ST25R3911B-DISCO firmware source code and examining an intercepted USB packet generated after calling rfalStartTransceive() function it can be seen that txLen has incorrect value. The intercepted USB packet has the following data content:

3515004400100000 4f 0028 e000c59803 0000003b 000211b0 cbcbcbcb...cb, where

4f - RFAL_CMD_START_TXRX command code;

0028 - txLen expressed in number of bits, but expected value is 0024 since in my C code txBufLen = 36 (4 bytes + 1 parity bit for each byte);

e000c59803 - sequence of data and parity bits of RATS command is Ok (memcpy(txBuf, "\xE0\x00\xC5\x98\x03", 5););

0000003b - flags value is Ok;

000211b0 - fwt value is Ok.

Is the source code for ST25R3911DISCOComm DLL available to possibly make a fix and recompile DLL? :)

Hi Alex_Wolf,

I was puzzled - for the GUI side function this length should have been a simple pass through. Unfortunately in the version on st.com this value gets essentially always rounded up to the next byte length.

As no new releases are planned as of now and we never released sources it is currently hard for me to offer you something right away - except if you are considering ugly hacks like changing the firmware to always rounding down the  ctx.txBufLen = txLen; to the nearest multiple of 9 or completely moving away from the DLL and do all USB HID reports on your own. Another option I am seeing is that there is the chance that latest ST25PC-NFC v3.0 contains a version which has this fixed. I expect you would need to move from 32-bit to 64-bit for using this one.

BR, Ulysses

 

Hi Ulysses,

Thank you for your reply!

I tried both 32- and 64-bit versions of ST25R3911DISCOComm DLL which I found in the ST25PC-NFC v3.0 sources. Unfortunately both versions behave like before.

In the end I applied "ugly hacks" to the firmware to overcome the problem.