I am using an TRF7970A trasciver combined with a MCU to try to get some information from a Java Card Applet. The problem I run into is that I managed to exchange information with the tag up to the Applet Activation command. That means I manage to do the anticollison procedure, select command, rats command, but when i get to activating the applet I get no answer, not even an error. The exact command secquence that I am sending from the device to the tag, I have tested it with an NFC debbugger and works ok. So it seems there is something with the applet activation command. Can someone indicate me a probable cause or a solution?
The command I am sending is: 0x02 0x00 0xA4 0x04 0x00 0x09 <9bytes the Applet ID>, I have also tried with 0x0A 0x00 0x00 0xA4 0x04 0x00 0x09 and still nothing.
The communication medium protocol is ISO14443 Type A, and IsoDep (which is the one I use to activate the applet).
Sry for not posting also the code. Here are the used functions:
1.This functions searches for a tag and retrives the information from it:
void NFC_TagSearch(uint8_t interface, uint8_t *state, uint8_t *RetrieTimer, uint8_t side)
{
Iso14443a_halt(interface, &gNFC[side]);if(*state==RF_1356_START_TAGSEARCH)
{
Iso14443aAnticollisionInitiate(0x01, iHFRF, &gNFC[side]);
*RetrieTimer=1;
while(*RetrieTimer <= RF_1356_WAIT_AFTER_COMMAND && gNFC[side].Status!=0xFF && gNFC[side].Status!=0x02){}
if(*RetrieTimer <= RF_1356_WAIT_AFTER_COMMAND)
{
char c[6];
hex2str(gNFC[side].Status,c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)c,4,DEBUG_MSG);
USART_AddBuffer(iDEBUG,(uint8_t *)"->",2,DEBUG_MSG);
uint8_t i=0;
for(i=0;i<gNFC[side].Size;i++)
{
hex2str(gNFC[side].Data[i],c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)&c[2],2,DEBUG_MSG);
}
USART_AddBuffer(iDEBUG,(uint8_t *)"\r\n",2,DEBUG_MSG);
USART_TransmitBuffers(iDEBUG);
}
else
{
USART_AddBuffer(iDEBUG,(uint8_t *)"Time\r\n",6,DEBUG_MSG);
USART_TransmitBuffers(iDEBUG);
}
*RetrieTimer=0;
if(gNFC[side].Status==0xFF || gNFC[side].Status==0x02)
{
memset(gNFC[side].uid,0x00,10);
if(Iso14443aAnticolissionLoop(iHFRF, &gNFC[side]))
{
/*We got and UID go to RATS*/
TRF7970A_CRC_ON(interface);
*state=RF_1356_WAITRATSANSWER;
Iso14443a_RATS(interface,&gNFC[side]);
*RetrieTimer=1;
while(*RetrieTimer <= RF_1356_WAIT_AFTER_COMMAND && gNFC[side].Status!=0xFF){}
if(*RetrieTimer <= RF_1356_WAIT_AFTER_COMMAND)
{
char c[6];
hex2str(gNFC[side].Status,c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)c,4,DEBUG_MSG);
USART_AddBuffer(iDEBUG,(uint8_t *)"->",2,DEBUG_MSG);
uint8_t i=0;
for(i=0;i<gNFC[side].Size;i++)
{
hex2str(gNFC[side].Data[i],c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)&c[2],2,DEBUG_MSG);
}
USART_AddBuffer(iDEBUG,(uint8_t *)"\r\n",2,DEBUG_MSG);
USART_TransmitBuffers(iDEBUG);
}
else
{
USART_AddBuffer(iDEBUG,(uint8_t *)"Time\r\n",6,DEBUG_MSG);
USART_TransmitBuffers(iDEBUG);
}
*RetrieTimer=0;
if((*RetrieTimer >= RF_1356_WAIT_AFTER_COMMAND) || (gNFC[side].Status==0xFF))
{
if((gNFC[side].Data[0]) == 0x05)
{
/*Command for activation of the applet*/
Iso14443a_ActivateApplet(interface,&gNFC[side]);
*RetrieTimer=1;
while(*RetrieTimer <= RF_1356_WAIT_AFTER_COMMAND && gNFC[side].Status!=0xFF){}
if(gNFC[0].Size>0/**RetrieTimer <= RF_1356_WAIT_AFTER_COMMAND*/)
{
char c[6];
hex2str(gNFC[0].Status,c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)c,4,DEBUG_MSG);
USART_AddBuffer(iDEBUG,(uint8_t *)"->",2,DEBUG_MSG);
uint8_t i=0;
for(i=0;i<gNFC[0].Size;i++)
{
hex2str(gNFC[0].Data[i],c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)&c[2],2,DEBUG_MSG);
}
USART_AddBuffer(iDEBUG,(uint8_t *)"\r\n",2,DEBUG_MSG);
USART_TransmitBuffers(iDEBUG);
}
else
{
USART_AddBuffer(iDEBUG,(uint8_t *)"Timeout\r\n",9,DEBUG_MSG);
USART_TransmitBuffers(iDEBUG);
}
if(gNFC[1].Size>0/**RetrieTimer <= RF_1356_WAIT_AFTER_COMMAND*/)
{
char c[6];
hex2str(gNFC[1].Status,c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)c,4,DEBUG_MSG);
USART_AddBuffer(iDEBUG,(uint8_t *)"->",2,DEBUG_MSG);
uint8_t i=0;
for(i=0;i<gNFC[1].Size;i++)
{
hex2str(gNFC[1].Data[i],c,1);
USART_AddBuffer(iDEBUG,(uint8_t *)&c[2],2,DEBUG_MSG);
}
USART_AddBuffer(iDEBUG,(uint8_t *)"\r\n",2,DEBUG_MSG);
USART_TransmitBuffers(iDEBUG);
}
*RetrieTimer=0;
if(gNFC[side].Status==0xFF)
{
if((gNFC[side].Data[0]) == 0x90 && (gNFC[side].Data[1]) == 0x00)
{
/*Command for activation of the applet*/
*state=RF_1356_START_TAGSEARCH;
*RetrieTimer=0;
gDevice.DeviceState=(/*DEVICE_STATE_WAIT_CARD*/0x01==gDevice.DeviceState)?(/*DEVICE_STATE_GOT_CARD*/0x04):(gDevice.DeviceState);
}
else
*state=RF_1356_START_TAGSEARCH;
}
else
{
/*Go back and send command again*/
*state=RF_1356_START_TAGSEARCH;
}
}
else
{
/*Go back and send command again*/
*state=RF_1356_START_TAGSEARCH;
}
}
else
{
/*Go back and send command again*/
*state=RF_1356_START_TAGSEARCH;
}
}
else
{
/*Go back and send command again*/
*state=RF_1356_START_TAGSEARCH;
}
}
else
{
/*Go back and send command again*/
*state=RF_1356_START_TAGSEARCH;
}
}
Iso14443a_halt(interface, &gNFC[side]);
Delay_ms(500);
LL_IWDG_ReloadCounter(IWDG);
}
2.Everithing works until the Applect Activation function for which command i get no answer, this is the functions:
void Iso14443a_ActivateApplet(uint8_t interface,__NFCInterfaces *NFC)
{
/*Tried also to reconfigure the chip, just in case*/
trf7970a_write_single(interface,TRF7970A_ISO_CTRL, TRF7970A_ISO_CTRL_14443A_106);
TRF7970A_CRC_ON(interface);
uint8_t length;
uint8_t buf[50];
NFC->CorruptedResponse=0;
NFC->Size=0;
NFC->Status=0x00;
length=0;
buf[length++] = 0x00; /*Length of the packet to be sent, this value is for the TRF7970A chip*/
buf[length++] = 0x00; /*Length of the packet to be sent, this value is for the TRF7970A chip*/
/*The sent packet*/
buf[length++] = 0x00;
buf[length++] = 0xA4;
buf[length++] = 0x04;
buf[length++] = 0x00;
buf[length++] = 0x09; //0x09
buf[length++] = 0xC2; //<-AID
buf[length++] = 0xB6;
buf[length++] = 0xCA;
buf[length++] = 0x27;
buf[length++] = 0xA1;
buf[length++] = 0x93;
buf[length++] = 0x1B;
buf[length++] = 0x14;
buf[length++] = 0x1D;
/*The sent packet*/
buf[0]=((length-2)>>4)&0x0F; /*Add the length high nibble to the buffer*/
buf[1]=((length-2)<<4)&0xF0; /*Add the length low nibble to the buffer*/
trf7970a_sendToTag(interface, 1, buf, length);
/*Tested commands*/
//02 00 A4040009 C2B6CA27A1931B141D
//0A 00 00 A4040000 C2B6CA27A1931B141D
//0A 00 00 A4040009 C2B6CA27A1931B141D
//0A0000A404000B4A617661436172644F530100/*CID present and 0*/
//0200A404000B4A617661436172644F530100/*CID not present*/
}
3.And this are the functions used in the ActivateApplet function:
uint8_t trf7970a_sendToTag(uint8_t interface, uint8_t crc, uint8_t *buf, uint8_t len)
{
/*Clear the chip FIFO buffer*/
trf7970a_command(interface, TRF7970A_CMD_FIFO_RESET);
/*Send command with or without crc*/
(crc)?(trf7970a_command(interface, TRF7970A_CMD_TRANSMIT)):(trf7970a_command(interface, TRF7970A_CMD_TRANSMIT_NO_CRC));
/*Send data to buffer starting from the length registers and then continuing with the FIFO buffer, first 2 bytes in buffer are the legth of data to be sent by the chip*/
trf7970a_write_continous(interface, TRF7970A_TX_LENGTH_BYTE1, buf,len);
return 1;
}
The functions used like trf7970a_write_continous, trf7970a_command, trf7970a_write_single and TRF7970A_CRC_ON I am sure they work cause I used them in other commands.
Also the chip configuration function is:
void trf7970a_init(uint8_t interface)
{
HFRF_ENABLECHIP;
Delay_ms(500);
trf7970a_command(interface, TRF7970A_CMD_SOFT_INIT);
trf7970a_command(interface, TRF7970A_CMD_IDLE);
uint8_t sysclkval=0x00;
trf7970a_write_single(interface, TRF7970A_MODULATOR_SYS_CLK_CTRL, sysclkval);
uint8_t regio=0x00 | TRF7970A_REG_IO_CTRL_VRS(7);
trf7970a_write_single(interface, TRF7970A_REG_IO_CTRL, regio);
trf7970a_write_single(interface, TRF7970A_CHIP_STATUS_CTRL, 0x00);
trf7970a_command(interface, TRF7970A_CMD_FIFO_RESET);
trf7970a_write_single(interface, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS, 0x0F);
trf7970a_read_single(interface, TRF7970A_IRQ_STATUS, ®io);
}
Related
I'm working with esp-idf and I found this repository that has implemented the Adafruit driver for the PN532 in "plain" esp-idf. This library works very well if I use it as is.
I'm trying to improve the code by changing the SPI functions to use directly the one provided by esp-idf.
I found this documentation (see section 6.1.1.1) and this other documentation (section 2.4.1) that slightly helped me in order to understand how to configure the SPI device, but I'm still missing something because I don't have the right response from PN532 when I use the settings shown below, nor in any other configuration.
So I'm searching for someone that can help me understand better what I'm missing here.
The original functions are:
void pn532_spi_init(pn532_t *obj, uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss)
{
obj->_clk = clk;
obj->_miso = miso;
obj->_mosi = mosi;
obj->_ss = ss;
gpio_pad_select_gpio(obj->_clk);
gpio_pad_select_gpio(obj->_miso);
gpio_pad_select_gpio(obj->_mosi);
gpio_pad_select_gpio(obj->_ss);
gpio_set_direction(obj->_ss, GPIO_MODE_OUTPUT);
gpio_set_level(obj->_ss, 1);
gpio_set_direction(obj->_clk, GPIO_MODE_OUTPUT);
gpio_set_direction(obj->_mosi, GPIO_MODE_OUTPUT);
gpio_set_direction(obj->_miso, GPIO_MODE_INPUT);
}
/**************************************************************************/
/*!
#brief Low-level SPI write wrapper
#param c 8-bit command to write to the SPI bus
*/
/**************************************************************************/
void pn532_spi_write(pn532_t *obj, uint8_t c)
{
int8_t i;
gpio_set_level(obj->_clk, 1);
for (i = 0; i < 8; i++)
{
gpio_set_level(obj->_clk, 0);
if (c & _BV(i))
{
gpio_set_level(obj->_mosi, 1);
}
else
{
gpio_set_level(obj->_mosi, 0);
}
gpio_set_level(obj->_clk, 1);
}
}
/**************************************************************************/
/*!
#brief Low-level SPI read wrapper
#returns The 8-bit value that was read from the SPI bus
*/
/**************************************************************************/
uint8_t pn532_spi_read(pn532_t *obj)
{
int8_t i, x;
x = 0;
gpio_set_level(obj->_clk, 1);
for (i = 0; i < 8; i++)
{
if (gpio_get_level(obj->_miso))
{
x |= _BV(i);
}
gpio_set_level(obj->_clk, 0);
gpio_set_level(obj->_clk, 1);
}
return x;
}
And my changes are:
void pn532_spi_init(pn532_t *obj, spi_host_device_t spiHostDevice, uint8_t ss) {
gpio_set_direction((gpio_num_t) ss, GPIO_MODE_OUTPUT);
gpio_set_level((gpio_num_t) ss, 1);
//Config Frequency and SS GPIO
spi_device_interface_config_t deviceInterfaceConfig = {
.mode = 0, //SPI mode 0
.clock_speed_hz= 1200000, // Uusually 1.2 Mhz
.input_delay_ns = 0,
.spics_io_num = ss,
.flags = (SPI_DEVICE_BIT_LSBFIRST),
.queue_size = 1
};
spi_device_handle_t spiDeviceHandle;
//Attach the pn532 to the SPI bus
ESP_ERROR_CHECK(spi_bus_add_device(spiHostDevice, &deviceInterfaceConfig, &spiDeviceHandle));
obj->spi = spiDeviceHandle;
obj->_ss = ss;
}
void pn532_spi_write(pn532_t *obj, uint8_t data) {
spi_transaction_t t;
memset(&t, 0, sizeof(t)); //Zero out the transaction
t.length = 8;
t.tx_buffer = &data;
//t.flags = SPI_TRANS_CS_KEEP_ACTIVE;
ESP_LOGI(TAG, "send data: 0b%s", toBinary(data,8));
//t.flags = (SPI_TRANS_MODE_OCT | SPI_TRANS_MODE_QIO);
ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));
}
uint8_t pn532_spi_read(pn532_t *obj) {
uint8_t data = 1;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); //Zero out the transaction
t.length = 8;
t.rxlength = 8;
t.tx_buffer = NULL;
t.rx_buffer = &data;
//t.flags = SPI_TRANS_CS_KEEP_ACTIVE;
//t.flags = (SPI_TRANS_MODE_OCT);
ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));
ESP_LOGI(TAG, "read data: 0b%s", toBinary(data,8));
return data;
}
Externally from this function I'm initializing the SPI bus and then calling the pn532 init and begin functions.
spi_bus_config_t spi_config = {
.mosi_io_num= PIN_NUM_MOSI,
.miso_io_num= PIN_NUM_MISO,
.sclk_io_num= PIN_NUM_CLK,
.quadwp_io_num= -1,
.quadhd_io_num= -1,
.max_transfer_sz= 4092
};
//Initialize the SPI bus
ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &spi_config, SPI_DMA_CH_AUTO));
static pn532_t nfc;
pn532_spi_init(&nfc, HSPI_HOST, GPIO_NUM_25);
pn532_begin(&nfc);
With this configuration, when I try to read from the SPI, the hex that return the PN532 is 0x08, were expecting 0x01 or 0x00. Seem that is a padding problem? The 1 is shifted in the wrong place?
I'm really lost! :(
I'm trying to use the esp-idf standard SPI management functions instead of custom ones.
The custom functions are:
// the initialization of the gpio:
void _spi_init(pn532_t *obj, uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss)
{
obj->_clk = clk;
obj->_miso = miso;
obj->_mosi = mosi;
obj->_ss = ss;
gpio_pad_select_gpio(obj->_clk);
gpio_pad_select_gpio(obj->_miso);
gpio_pad_select_gpio(obj->_mosi);
gpio_pad_select_gpio(obj->_ss);
gpio_set_direction(obj->_ss, GPIO_MODE_OUTPUT);
gpio_set_level(obj->_ss, 1);
gpio_set_direction(obj->_clk, GPIO_MODE_OUTPUT);
gpio_set_direction(obj->_mosi, GPIO_MODE_OUTPUT);
gpio_set_direction(obj->_miso, GPIO_MODE_INPUT);
}
// read and write to SPI
uint8_t _spi_read(pn532_t *obj)
{
int8_t i, x;
x = 0;
gpio_set_level(obj->_clk, 1);
for (i = 0; i < 8; i++)
{
if (gpio_get_level(obj->_miso))
{
x |= _BV(i);
}
gpio_set_level(obj->_clk, 0);
gpio_set_level(obj->_clk, 1);
}
return x;
}
void _spi_write(pn532_t *obj, uint8_t c)
{
int8_t i;
gpio_set_level(obj->_clk, 1);
for (i = 0; i < 8; i++)
{
gpio_set_level(obj->_clk, 0);
if (c & _BV(i))
{
gpio_set_level(obj->_mosi, 1);
}
else
{
gpio_set_level(obj->_mosi, 0);
}
gpio_set_level(obj->_clk, 1);
}
}
My refactoring currently is only for these 3 functions:
void _spi_init(pn532_t *obj, spi_host_device_t spiHostDevice, uint8_t ss) {
// the spi_bus_initialize is already initialized in the main function.
gpio_set_direction((gpio_num_t) ss, GPIO_MODE_OUTPUT);
gpio_set_level((gpio_num_t) ss, 1);
//Config Frequency and SS GPIO
spi_device_interface_config_t deviceInterfaceConfig = {
.mode = 0, //SPI mode 0
.clock_speed_hz= 1200000, // Usually 1.2 Mhz
.input_delay_ns = 0,
.spics_io_num = ss,
.flags = SPI_DEVICE_BIT_LSBFIRST, // the device use LSB
.queue_size = 1
};
spi_device_handle_t spiDeviceHandle;
//Attach the pn532 to the SPI bus
ESP_ERROR_CHECK(spi_bus_add_device(spiHostDevice, &deviceInterfaceConfig, &spiDeviceHandle));
obj->spi = spiDeviceHandle;
}
void _spi_write(pn532_t *obj, uint8_t data) {
spi_transaction_t t;
memset(&t, 0, sizeof(t)); //Zero out the transaction
t.length = 8;
t.tx_buffer = &data;
ESP_LOGI(TAG, "send data: 0b%s", toBinary(data,8));
ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));
}
uint8_t _spi_read(pn532_t *obj) {
uint8_t data = 1;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); //Zero out the transaction
t.length = 8;
t.rxlength = 8;
t.tx_buffer = NULL;
t.rx_buffer = &data;
ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));
ESP_LOGI(TAG, "read data: 0b%s", toBinary(data,8));
return data;
}
Currently, this rewrite is not working. I already did a lot of tries with any combination of config that makes sense, without success.
Practically, when I ask the device to give me the status, I'm expecting one byte in response, in form of 0x00 or 0x01. But I'm receiving 0x08. So still one bit up, but in the wrong position.
So I think I'm still missing some configuration on my rewrite.
Apprising any hit or test that I can do in order to found what is missing!
Thanks!
i have three nodemcu and I want to send a struct over nRF24l01+ , but my struct size is 52 byte and the nRf24l01+ module is just sending 32 byte !
how should I send my struct ?
my struct :
struct fullData{
unsigned long ttime;
String data1;
String data2;
String data3;
String data4;
}sndData,recData;
I tried this way but it dosen't work :
transmitter code:
void sendOverRadio(){
char data[sizeof(sndData)];
memcpy(data, &sndData, sizeof(sndData));
radio.stopListening();
int z = 0;
for(int i= 0 ; i<2 ; i++){
char dt[32];
dt[0] = i;
for(int j =1 ; j<32;j++){
dt[j]=data[z];
z +=1;
}
radio.write(&dt , sizeof(dt));
}
radio.startListening();
}
receiver code :
char data[sizeof(recData)];
void loop(){
if(radio.available()){
Serial.println("Radio Available...");
char dt[32];
while (radio.available()){
radio.read(&dt, sizeof(dt));
}
if(dt[0]==0){
memset(data, 0, sizeof(data));
memcpy(data, &dt[1], 32);
}else if(dt[0]==1){
memcpy(&data[32], &dt[1], 32);
memcpy(&recData, data, sizeof(recData));
}
}
}
RF24Network library handles payload splitting. Send your struct like this:
RF24NetworkHeader header(0, 'D');
if (!NETWORK.write(header, &sndData, sizeof(sndData))) {
Serial.println(F("Error."));
} else {
Serial.println(F("Success."));
}
I have a problem with an ATmega8 and Mifare RC-522 based NFC/RFID controller.
I'm using this library and I've managed to read the UID of a card.
However, I'd like to also read and write other parts of the card but whenever I try to use the MFRC522_Auth function I don't get the idle interrupt which I should, instead it gives me LoAlertIrq saying that FIFObuffer is almost empty.
Here are the docs for the reader and the card, and below are relevant parts of my code.
main.c :
byte = mfrc522_request(PICC_REQALL,str);
if(byte == CARD_FOUND)
{
byte = mfrc522_get_card_serial(str);
if(byte == CARD_FOUND)
{
byte = mfrc522_auth(PICC_AUTHENT1A, 7, sectorKeyA, str);
if( (byte == CARD_FOUND) )
{
byte = MFRC522_Read1(4, str);
if(byte == CARD_FOUND)
{
//write content of that block
}
}
}
Relevant functions from the library :
void mfrc522_write(uint8_t reg, uint8_t data)
{
ENABLE_CHIP();
spi_transmit((reg<<1)&0x7E);
spi_transmit(data);
DISABLE_CHIP();
}
uint8_t mfrc522_read(uint8_t reg)
{
uint8_t data;
ENABLE_CHIP();
spi_transmit(((reg<<1)&0x7E)|0x80);
data = spi_transmit(0x00);
DISABLE_CHIP();
return data;
}
uint8_t mfrc522_to_card(uint8_t cmd, uint8_t *send_data, uint8_t send_data_len, uint8_t *back_data, uint32_t *back_data_len)
{
uint8_t status = 0;
uint8_t irqEn = 0x00;
uint8_t waitIRq = 0x00;
uint8_t lastBits;
uint8_t n;
uint8_t tmp;
uint32_t i;
switch (cmd)
{
case MFAuthent_CMD: //Certification cards close
{
irqEn = 0x12;
waitIRq = 0x10;
break;
}
case Transceive_CMD: //Transmit FIFO data
{
irqEn = 0x77;
waitIRq = 0x30;
break;
}
default:
break;
}
mfrc522_write(ComIEnReg, irqEn|0x80); //Interrupt request
n=mfrc522_read(ComIrqReg);
mfrc522_write(ComIrqReg,n&(~0x80));//clear all interrupt bits
n=mfrc522_read(FIFOLevelReg);
mfrc522_write(FIFOLevelReg,n|0x80);//flush FIFO data
// mfrc522_write(CommandReg, Idle_CMD); //NO action; Cancel the current cmd???
n=mfrc522_read(CommandReg);
mfrc522_write(CommandReg,n|0x00);
//Writing data to the FIFO
for (i=0; i<send_data_len; i++)
{
mfrc522_write(FIFODataReg, send_data[i]);
}
//Execute the cmd
mfrc522_write(CommandReg, cmd);
if (cmd == Transceive_CMD)
{
n=mfrc522_read(BitFramingReg);
mfrc522_write(BitFramingReg,n|0x80);
}
//Waiting to receive data to complete
i = 2000; //i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms???
while (1) {
n = mfrc522_read(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
if (n & waitIRq) { // One of the interrupts that signal success has been set.
break;
}
if (n & 0x01) { // Timer interrupt - nothing received in 25ms
// return 6; //debug purpose
if (cmd == MFAuthent_CMD) {
LCD_Clear();
LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
_delay_ms(2500);
}
break;
}
if (--i == 0) { // The emergency break. If all other condions fail we will eventually terminate on this one after 35.7ms. Communication with the MFRC522 might be down.
if (cmd == MFAuthent_CMD) {
LCD_Clear();
LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
_delay_ms(2500);
}
break;
}
}
tmp=mfrc522_read(BitFramingReg);
mfrc522_write(BitFramingReg,tmp&(~0x80));
if (i != 0)
{
if(!(mfrc522_read(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr
{
status = CARD_FOUND;
if (n & irqEn & 0x01)
{
status = CARD_NOT_FOUND; //??
}
if (cmd == Transceive_CMD)
{
n = mfrc522_read(FIFOLevelReg);
lastBits = mfrc522_read(ControlReg) & 0x07;
if (lastBits)
{
*back_data_len = (n-1)*8 + lastBits;
}
else
{
*back_data_len = n*8;
}
if (n == 0)
{
n = 1;
}
if (n > MAX_LEN)
{
n = MAX_LEN;
}
//Reading the received data in FIFO
for (i=0; i<n; i++)
{
back_data[i] = mfrc522_read(FIFODataReg);
}
}
}
if (cmd == MFAuthent_CMD) {
LCD_WriteTextXY(1, 10, LCD_itoa16( mfrc522_read(Status2Reg) ) );
_delay_ms(2500);
}
} else status = 9;
return status;
}
uint8_t mfrc522_get_card_serial(uint8_t * serial_out)
{
uint8_t status;
uint8_t i;
uint8_t serNumCheck=0;
uint32_t unLen;
mfrc522_write(BitFramingReg, 0x00); //TxLastBists = BitFramingReg[2..0]
serial_out[0] = PICC_ANTICOLL;
serial_out[1] = 0x20;
status = mfrc522_to_card(Transceive_CMD, serial_out, 2, serial_out, &unLen);
if (status == CARD_FOUND)
{
//Check card serial number
for (i=0; i<4; i++)
{
serNumCheck ^= serial_out[i];
}
if (serNumCheck != serial_out[i])
{
status = ERROR;
}
}
return status;
}
uint8_t mfrc522_auth(uint8_t authMode, uint8_t BlockAddr, uint8_t *Sectorkey, uint8_t *serNum)
{
uint8_t status;
uint32_t recvBits;
uint8_t i;
uint8_t buff[12];
// Validate instruction block address + sector + password + card serial number
buff[0] = authMode;
buff[1] = BlockAddr;
for (i=0; i<6; i++)
{
buff[i+2] = 0xFF /**(Sectorkey+i)*/;
}
for (i=0; i<4; i++)
{
buff[i+8] = *(serNum+i);
}
status = mfrc522_to_card(MFAuthent_CMD, buff, 12, buff, &recvBits);
return status;
}
uint8_t MFRC522_Read1(uint8_t blockAddr, uint8_t *recvData)
{
uint8_t status = 0;
uint8_t unLen, efa;
recvData[0] = PICC_READ;
recvData[1] = blockAddr;
CalculateCRC(recvData, 2, &recvData);
status = mfrc522_to_card(Transceive_CMD, recvData, 4, recvData, &unLen);
if ((status != CARD_FOUND)|| (unLen != 0x90))
{
status = ERROR;
}
return status;
}
uint8_t CalculateCRC(uint8_t *pIndata, uint8_t len, uint8_t *pOutData)
{
uint8_t i, n;
uint8_t status = 0;
n = mfrc522_read(DivIrqReg);
mfrc522_write(DivIrqReg,n&(~0x04)); //CRCIrq = 0
n = mfrc522_read(FIFOLevelReg); //FIFO
mfrc522_write(FIFOLevelReg, n|0x80);
//Write_MFRC522(CommandReg, PCD_IDLE);
// Write data to the FIFO
for (i=0; i<len; i++)
{
mfrc522_write(FIFODataReg, *(pIndata+i));
}
mfrc522_write(CommandReg, CalcCRC_CMD);
// Read the CRC calculation result
i = 0xFF;
while(1){
n = mfrc522_read(DivIrqReg);
if (n & 0x04) {
break;
}
if (--i != 0) {
return 7;
}
}
// Read the CRC calculation result
pOutData[3] = mfrc522_read(CRCResultReg_2);
pOutData[4] = mfrc522_read(CRCResultReg_1);
return status = 0;
}
I'm trying to write block device driver that implements read/write operations.
The tricky thing is that the information is not in the hardware, but in a user space process. Therefore, during the read/write system call I would like to interact the user space (i.e. sendign signal to the user space).
However, my user space process catching the signal only after the read/write system call returned. adding wait in the system call implementation seems to be ignored somehow.
I used this code at the read system call:
ssize_t sleepy_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
struct siginfo info;
struct task_struct *t;
int ret;
#define SIG_TEST 44
memset(&info, 0, sizeof(struct siginfo));
info.si_signo = SIG_TEST;
info.si_code = SI_QUEUE;
info.si_int = 1234;
rcu_read_lock();
t = pid_task(find_pid_ns(current->pid, &init_pid_ns), PIDTYPE_PID);
if(t == NULL){
printk(KERN_ERR "no such pid\n");
rcu_read_unlock();
return -ENODEV;
}
rcu_read_unlock();
ret = send_sig_info(SIG_TEST, &info, t); //send the signal
if (ret < 0) {
printk("error sending signal\n");
return ret;
}
wait_event_interruptible(wq, flag != 0);
msleep(10000);
return (0);
}
and this code at user space:
#define SIG_TEST 44
int g_devFile = -1;
void receiveData(int n, siginfo_t *info, void *unused)
{
printf("received value %i\n", info->si_int);
}
int main(void)
{
struct sigaction sig;
sig.sa_sigaction = receiveData;
sig.sa_flags = SA_SIGINFO;
sigaction(SIG_TEST, &sig, NULL);
g_devFile = open(devname, O_RDWR);
if ( g_devFile < 0 ) {
fprintf(stderr,"Error opening device[%s] file err[%s]\n",devname,strerror(errno));
return -1;
} else {
fprintf (stderr, "device opened. ptr=%p\n", (void*)g_devFile);
}
i = read(g_devFile, &buff, 11);
}
Currently I'm catching my signal (in user space) only after the 10 seconds sleep expieres (the wait seems to be ignored).
Any idea will be appriceated. Thanks.