basic ndef message works
This commit is contained in:
parent
1874e11fba
commit
dcf7940b3d
@ -5,7 +5,7 @@ AR=$(PREFIX)arm-none-eabi-ar
|
||||
|
||||
# ST related
|
||||
SRC = src/main.c src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
|
||||
SRC += src/fifo.c src/crypto.c src/attestation.c src/nfc.c
|
||||
SRC += src/fifo.c src/crypto.c src/attestation.c src/nfc.c src/ams.c
|
||||
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||
SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c)
|
||||
|
||||
|
340
targets/stm32l432/src/ams.c
Normal file
340
targets/stm32l432/src/ams.c
Normal file
@ -0,0 +1,340 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "stm32l4xx_ll_spi.h"
|
||||
|
||||
#include "ams.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include "device.h"
|
||||
|
||||
static void flush_rx()
|
||||
{
|
||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0)
|
||||
{
|
||||
LL_SPI_ReceiveData8(SPI1);
|
||||
}
|
||||
}
|
||||
static void wait_for_tx()
|
||||
{
|
||||
// while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1)
|
||||
// ;
|
||||
while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY)
|
||||
;
|
||||
}
|
||||
static void wait_for_rx()
|
||||
{
|
||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
static void ams_print_device(AMS_DEVICE * dev)
|
||||
{
|
||||
printf1(TAG_NFC, "AMS_DEVICE:\r\n");
|
||||
printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf);
|
||||
printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0);
|
||||
printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1);
|
||||
printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2);
|
||||
printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status);
|
||||
printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status);
|
||||
printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0);
|
||||
printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1);
|
||||
printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0);
|
||||
printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1);
|
||||
printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2);
|
||||
printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1);
|
||||
printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr);
|
||||
printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type);
|
||||
printf1(TAG_NFC, " product_subtype:%02x\r\n",dev->regs.product_subtype);
|
||||
printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj);
|
||||
printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min);
|
||||
}
|
||||
|
||||
static uint8_t send_recv(uint8_t b)
|
||||
{
|
||||
wait_for_tx();
|
||||
LL_SPI_TransmitData8(SPI1, b);
|
||||
wait_for_rx();
|
||||
b = LL_SPI_ReceiveData8(SPI1);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
void ams_write_reg(uint8_t addr, uint8_t tx)
|
||||
{
|
||||
send_recv(0x00| addr);
|
||||
send_recv(tx);
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
|
||||
uint8_t ams_read_reg(uint8_t addr)
|
||||
{
|
||||
send_recv(0x20| (addr & 0x1f));
|
||||
uint8_t data = send_recv(0);
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
return data;
|
||||
}
|
||||
|
||||
// data must be 14 bytes long
|
||||
void read_reg_block2(AMS_DEVICE * dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 0x20; i++)
|
||||
{
|
||||
dev->buf[i] = ams_read_reg(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// data must be 14 bytes long
|
||||
void read_reg_block(AMS_DEVICE * dev)
|
||||
{
|
||||
int i;
|
||||
uint8_t mode = 0x20 | (0 );
|
||||
flush_rx();
|
||||
|
||||
send_recv(mode);
|
||||
for (i = 0; i < 0x20; i++)
|
||||
{
|
||||
dev->buf[i] = send_recv(0);
|
||||
}
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
void ams_read_buffer(uint8_t * data, int len)
|
||||
{
|
||||
send_recv(0xa0);
|
||||
while(len--)
|
||||
{
|
||||
*data++ = send_recv(0x00);
|
||||
}
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
void ams_write_buffer(uint8_t * data, int len)
|
||||
{
|
||||
send_recv(0x80);
|
||||
while(len--)
|
||||
{
|
||||
send_recv(*data++);
|
||||
}
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
// data must be 4 bytes
|
||||
void ams_read_eeprom_block(uint8_t block, uint8_t * data)
|
||||
{
|
||||
send_recv(0x7f);
|
||||
send_recv(block << 1);
|
||||
|
||||
data[0] = send_recv(0);
|
||||
data[1] = send_recv(0);
|
||||
data[2] = send_recv(0);
|
||||
data[3] = send_recv(0);
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
|
||||
// data must be 4 bytes
|
||||
void ams_write_eeprom_block(uint8_t block, uint8_t * data)
|
||||
{
|
||||
send_recv(0x40);
|
||||
send_recv(block << 1);
|
||||
|
||||
send_recv(data[0]);
|
||||
send_recv(data[1]);
|
||||
send_recv(data[2]);
|
||||
send_recv(data[3]);
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
void ams_write_command(uint8_t cmd)
|
||||
{
|
||||
send_recv(0xc0 | cmd);
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
const char * ams_get_state_string(uint8_t regval)
|
||||
{
|
||||
if (regval & AMS_STATE_INVALID)
|
||||
{
|
||||
return "STATE_INVALID";
|
||||
}
|
||||
switch (regval & AMS_STATE_MASK)
|
||||
{
|
||||
case AMS_STATE_OFF:
|
||||
return "STATE_OFF";
|
||||
case AMS_STATE_SENSE:
|
||||
return "STATE_SENSE";
|
||||
case AMS_STATE_RESOLUTION:
|
||||
return "STATE_RESOLUTION";
|
||||
case AMS_STATE_RESOLUTION_L2:
|
||||
return "STATE_RESOLUTION_L2";
|
||||
case AMS_STATE_SELECTED:
|
||||
return "STATE_SELECTED";
|
||||
case AMS_STATE_SECTOR2:
|
||||
return "STATE_SECTOR2";
|
||||
case AMS_STATE_SECTORX_2:
|
||||
return "STATE_SECTORX_2";
|
||||
case AMS_STATE_SELECTEDX:
|
||||
return "STATE_SELECTEDX";
|
||||
case AMS_STATE_SENSEX_L2:
|
||||
return "STATE_SENSEX_L2";
|
||||
case AMS_STATE_SENSEX:
|
||||
return "STATE_SENSEX";
|
||||
case AMS_STATE_SLEEP:
|
||||
return "STATE_SLEEP";
|
||||
}
|
||||
return "STATE_WRONG";
|
||||
}
|
||||
|
||||
void ams_print_int0(uint8_t int0)
|
||||
{
|
||||
uint32_t tag = (TAG_NFC)|(TAG_NO_TAG);
|
||||
printf1(TAG_NFC," ");
|
||||
if (int0 & AMS_INT_XRF)
|
||||
printf1(tag," XRF");
|
||||
if (int0 & AMS_INT_TXE)
|
||||
printf1(tag," TXE");
|
||||
if (int0 & AMS_INT_RXE)
|
||||
printf1(tag," RXE");
|
||||
if (int0 & AMS_INT_EER_RF)
|
||||
printf1(tag," EER_RF");
|
||||
if (int0 & AMS_INT_EEW_RF)
|
||||
printf1(tag," EEW_RF");
|
||||
if (int0 & AMS_INT_SLP)
|
||||
printf1(tag," SLP");
|
||||
if (int0 & AMS_INT_WU_A)
|
||||
printf1(tag," WU_A");
|
||||
if (int0 & AMS_INT_INIT)
|
||||
printf1(tag," INIT");
|
||||
|
||||
printf1(tag,"\r\n");
|
||||
}
|
||||
|
||||
void ams_print_int1(uint8_t int0)
|
||||
{
|
||||
uint32_t tag = (TAG_NFC)|(TAG_NO_TAG);
|
||||
printf1(TAG_NFC," ");
|
||||
if (int0 & AMS_INT_ACC_ERR)
|
||||
printf1(tag," ACC_ERR");
|
||||
if (int0 & AMS_INT_EEAC_ERR)
|
||||
printf1(tag," EEAC_ERR");
|
||||
if (int0 & AMS_INT_IO_EEWR)
|
||||
printf1(tag," IO_EEWR");
|
||||
if (int0 & AMS_INT_BF_ERR)
|
||||
printf1(tag," BF_ERR");
|
||||
if (int0 & AMS_INT_CRC_ERR)
|
||||
printf1(tag," CRC_ERR");
|
||||
if (int0 & AMS_INT_PAR_ERR)
|
||||
printf1(tag," PAR_ERR");
|
||||
if (int0 & AMS_INT_FRM_ERR)
|
||||
printf1(tag," FRM_ERR");
|
||||
if (int0 & AMS_INT_RXS)
|
||||
printf1(tag," RXS");
|
||||
|
||||
printf1(tag,"\r\n");
|
||||
}
|
||||
|
||||
void ams_init()
|
||||
{
|
||||
|
||||
uint8_t block[4];
|
||||
|
||||
LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN);
|
||||
|
||||
LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW);
|
||||
LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE);
|
||||
LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable(SPI1);
|
||||
|
||||
delay(10);
|
||||
SELECT();
|
||||
delay(10);
|
||||
|
||||
|
||||
ams_write_command(AMS_CMD_DEFAULT);
|
||||
ams_write_command(AMS_CMD_CLEAR_BUFFER);
|
||||
|
||||
// enable tunneling mode and RF configuration
|
||||
ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD);
|
||||
|
||||
ams_read_eeprom_block(0, block);
|
||||
printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
ams_read_eeprom_block(0, block);
|
||||
printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
|
||||
printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
uint8_t sense1 = 0x44;
|
||||
uint8_t sense2 = 0x00;
|
||||
uint8_t selr = 0x20; // SAK
|
||||
|
||||
if(block[0] != sense1 || block[1] != sense2 || block[2] != selr)
|
||||
{
|
||||
printf1(TAG_NFC,"Writing config block 0\r\n");
|
||||
block[0] = sense1;
|
||||
block[1] = sense2;
|
||||
block[2] = selr;
|
||||
block[3] = 0x00;
|
||||
|
||||
ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
|
||||
UNSELECT();
|
||||
delay(10);
|
||||
SELECT();
|
||||
delay(10);
|
||||
|
||||
ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
|
||||
printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4);
|
||||
}
|
||||
|
||||
ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block);
|
||||
printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0;
|
||||
uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD;
|
||||
|
||||
if (block[0] != ic_cfg1 || block[1] != ic_cfg2)
|
||||
{
|
||||
printf1(TAG_NFC,"Writing config block 1\r\n");
|
||||
// set IC_CFG1
|
||||
block[0] = ic_cfg1;
|
||||
|
||||
// set IC_CFG2
|
||||
block[1] = ic_cfg2;
|
||||
|
||||
// mask interrupt bits
|
||||
block[2] = 0x80;
|
||||
block[3] = 0;
|
||||
|
||||
ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block);
|
||||
|
||||
UNSELECT();
|
||||
delay(10);
|
||||
SELECT();
|
||||
delay(10);
|
||||
|
||||
ams_read_eeprom_block(0x7F, block);
|
||||
printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4);
|
||||
}
|
||||
|
||||
}
|
127
targets/stm32l432/src/ams.h
Normal file
127
targets/stm32l432/src/ams.h
Normal file
@ -0,0 +1,127 @@
|
||||
#ifndef _AMS_H_
|
||||
#define _AMS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdint.h>
|
||||
#include "stm32l4xx_ll_gpio.h"
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t buf[0x20];
|
||||
struct {
|
||||
uint8_t io_conf; // 0x00
|
||||
uint8_t ic_conf0; // 0x01
|
||||
uint8_t ic_conf1; // 0x02
|
||||
uint8_t ic_conf2; // 0x03
|
||||
uint8_t rfid_status; // 0x04
|
||||
uint8_t ic_status; // 0x05
|
||||
uint8_t _nc0[2]; // 0x06 - 0x07
|
||||
uint8_t mask_int0; // 0x08
|
||||
uint8_t mask_int1; // 0x09
|
||||
uint8_t int0; // 0x0a
|
||||
uint8_t int1; // 0x0b
|
||||
uint8_t buffer_status2; // 0x0c
|
||||
uint8_t buffer_status1; // 0x0d
|
||||
uint8_t last_nfc_addr; // 0x0e
|
||||
uint8_t _nc1[0x1b - 0x0f + 1]; // 0x0f - 0x1b
|
||||
uint8_t product_type; // 0x1c
|
||||
uint8_t product_subtype; // 0x1d
|
||||
uint8_t version_maj; // 0x1e
|
||||
uint8_t version_min; // 0x1f
|
||||
} regs;
|
||||
} __attribute__((packed)) AMS_DEVICE;
|
||||
|
||||
#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
||||
#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
||||
|
||||
void ams_init();
|
||||
|
||||
void ams_read_buffer(uint8_t * data, int len);
|
||||
void ams_write_buffer(uint8_t * data, int len);
|
||||
|
||||
void ams_write_command(uint8_t cmd);
|
||||
|
||||
void read_reg_block(AMS_DEVICE * dev);
|
||||
|
||||
uint8_t ams_read_reg(uint8_t addr);
|
||||
|
||||
void ams_write_reg(uint8_t addr, uint8_t tx);
|
||||
|
||||
|
||||
#define AMS_REG_IO_CONF 0x00
|
||||
#define AMS_REG_IC_CONF0 0x01
|
||||
#define AMS_REG_IC_CONF1 0x02
|
||||
#define AMS_REG_IC_CONF2 0x03
|
||||
#define AMS_RFCFG_EN 0x80
|
||||
#define AMS_TUN_MOD 0x40
|
||||
#define AMS_REG_RFID_STATUS 0x04
|
||||
#define AMS_HF_PON 0x80
|
||||
#define AMS_STATE_MASK 0x78
|
||||
#define AMS_STATE_INVALID 0x04
|
||||
#define AMS_STATE_OFF (0 << 3)
|
||||
#define AMS_STATE_SENSE (1 << 3)
|
||||
#define AMS_STATE_RESOLUTION (3 << 3)
|
||||
#define AMS_STATE_RESOLUTION_L2 (2 << 3)
|
||||
#define AMS_STATE_SELECTED (6 << 3)
|
||||
#define AMS_STATE_SECTOR2 (7 << 3)
|
||||
#define AMS_STATE_SECTORX_2 (0xf << 3)
|
||||
#define AMS_STATE_SELECTEDX (0xd << 3)
|
||||
#define AMS_STATE_SENSEX_L2 (0xa << 3)
|
||||
#define AMS_STATE_SENSEX (0xb << 3)
|
||||
#define AMS_STATE_SLEEP (0x9 << 3)
|
||||
// ... //
|
||||
#define AMS_REG_INT0 0x0a
|
||||
#define AMS_INT_XRF (1<<0)
|
||||
#define AMS_INT_TXE (1<<1)
|
||||
#define AMS_INT_RXE (1<<2)
|
||||
#define AMS_INT_EER_RF (1<<3)
|
||||
#define AMS_INT_EEW_RF (1<<4)
|
||||
#define AMS_INT_SLP (1<<5)
|
||||
#define AMS_INT_WU_A (1<<6)
|
||||
#define AMS_INT_INIT (1<<7)
|
||||
#define AMS_REG_INT1 0x0b
|
||||
#define AMS_INT_ACC_ERR (1<<0)
|
||||
#define AMS_INT_EEAC_ERR (1<<1)
|
||||
#define AMS_INT_IO_EEWR (1<<2)
|
||||
#define AMS_INT_BF_ERR (1<<3)
|
||||
#define AMS_INT_CRC_ERR (1<<4)
|
||||
#define AMS_INT_PAR_ERR (1<<5)
|
||||
#define AMS_INT_FRM_ERR (1<<6)
|
||||
#define AMS_INT_RXS (1<<7)
|
||||
#define AMS_REG_BUF2 0x0c
|
||||
#define AMS_BUF_LEN_MASK 0x1f
|
||||
#define AMS_BUF_INVALID 0x80
|
||||
|
||||
#define AMS_CONFIG_BLOCK0_ADDR 0x7e
|
||||
#define AMS_CONFIG_BLOCK1_ADDR 0x7f
|
||||
|
||||
#define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2)
|
||||
#define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2)
|
||||
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_50 0x02
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_25 0x03
|
||||
|
||||
#define AMS_CFG2_RFCFG_EN (1<<7)
|
||||
#define AMS_CFG2_TUN_MOD (1<<6)
|
||||
|
||||
#define AMS_CMD_DEFAULT 0x02
|
||||
#define AMS_CMD_CLEAR_BUFFER 0x04
|
||||
#define AMS_CMD_RESTART_TRANSCEIVER 0x06
|
||||
#define AMS_CMD_DIS_EN_TRANSCEIVER 0x07
|
||||
#define AMS_CMD_TRANSMIT_BUFFER 0x08
|
||||
#define AMS_CMD_TRANSMIT_ACK 0x09
|
||||
#define AMS_CMD_TRANSMIT_NACK0 0x0A
|
||||
#define AMS_CMD_TRANSMIT_NACK1 0x0B
|
||||
#define AMS_CMD_TRANSMIT_NACK4 0x0D
|
||||
#define AMS_CMD_TRANSMIT_NACK5 0x0C
|
||||
#define AMS_CMD_SLEEP 0x10
|
||||
#define AMS_CMD_SENSE 0x11
|
||||
#define AMS_CMD_SENSE_SLEEP 0x12
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -1,355 +1,50 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "stm32l4xx.h"
|
||||
#include "stm32l4xx_ll_gpio.h"
|
||||
#include "stm32l4xx_ll_spi.h"
|
||||
|
||||
#include "nfc.h"
|
||||
#include "ams.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include "device.h"
|
||||
|
||||
#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
||||
#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
||||
// Capability container
|
||||
|
||||
|
||||
const CAPABILITY_CONTAINER NFC_CC = {
|
||||
.cclen_hi = 0x00, .cclen_lo = 0x0f,
|
||||
.version = 0x01,
|
||||
.MLe_hi = 0x00, .MLe_lo = 0xff,
|
||||
.MLc_hi = 0x00, .MLc_lo = 0xff,
|
||||
.tlv = { 0x04,0x06,
|
||||
0x11,0x11,
|
||||
0x00,0xff,
|
||||
0x00,0xff }
|
||||
};
|
||||
|
||||
uint8_t NDEF_SAMPLE[] = "\x00\x13\xD1\x01\x0ET\x02enHello World";
|
||||
|
||||
static struct
|
||||
{
|
||||
uint8_t max_frame_size;
|
||||
uint8_t cid;
|
||||
uint8_t block_num;
|
||||
uint8_t selected_applet;
|
||||
} NFC_STATE;
|
||||
|
||||
|
||||
static void flush_rx()
|
||||
void nfc_state_init()
|
||||
{
|
||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0)
|
||||
{
|
||||
LL_SPI_ReceiveData8(SPI1);
|
||||
}
|
||||
memset(&NFC_STATE,0,sizeof(NFC_STATE));
|
||||
NFC_STATE.max_frame_size = 32;
|
||||
NFC_STATE.block_num = 1;
|
||||
}
|
||||
static void wait_for_tx()
|
||||
{
|
||||
// while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1)
|
||||
// ;
|
||||
while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY)
|
||||
;
|
||||
}
|
||||
static void wait_for_rx()
|
||||
{
|
||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
static void ams_print_device(AMS_DEVICE * dev)
|
||||
{
|
||||
printf1(TAG_NFC, "AMS_DEVICE:\r\n");
|
||||
printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf);
|
||||
printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0);
|
||||
printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1);
|
||||
printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2);
|
||||
printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status);
|
||||
printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status);
|
||||
printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0);
|
||||
printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1);
|
||||
printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0);
|
||||
printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1);
|
||||
printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2);
|
||||
printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1);
|
||||
printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr);
|
||||
printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type);
|
||||
printf1(TAG_NFC, " product_subtype:%02x\r\n",dev->regs.product_subtype);
|
||||
printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj);
|
||||
printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min);
|
||||
}
|
||||
|
||||
static uint8_t send_recv(uint8_t b)
|
||||
{
|
||||
wait_for_tx();
|
||||
LL_SPI_TransmitData8(SPI1, b);
|
||||
wait_for_rx();
|
||||
b = LL_SPI_ReceiveData8(SPI1);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
static void ams_write_reg(uint8_t addr, uint8_t tx)
|
||||
{
|
||||
send_recv(0x00| addr);
|
||||
send_recv(tx);
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
|
||||
uint8_t ams_read_reg(uint8_t addr)
|
||||
{
|
||||
send_recv(0x20| (addr & 0x1f));
|
||||
uint8_t data = send_recv(0);
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
return data;
|
||||
}
|
||||
|
||||
// data must be 14 bytes long
|
||||
void read_reg_block2(AMS_DEVICE * dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 0x20; i++)
|
||||
{
|
||||
dev->buf[i] = ams_read_reg(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// data must be 14 bytes long
|
||||
void read_reg_block(AMS_DEVICE * dev)
|
||||
{
|
||||
int i;
|
||||
uint8_t mode = 0x20 | (0 );
|
||||
flush_rx();
|
||||
|
||||
send_recv(mode);
|
||||
for (i = 0; i < 0x20; i++)
|
||||
{
|
||||
dev->buf[i] = send_recv(0);
|
||||
}
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
void ams_read_buffer(uint8_t * data, int len)
|
||||
{
|
||||
send_recv(0xa0);
|
||||
while(len--)
|
||||
{
|
||||
*data++ = send_recv(0x00);
|
||||
}
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
void ams_write_buffer(uint8_t * data, int len)
|
||||
{
|
||||
send_recv(0x80);
|
||||
while(len--)
|
||||
{
|
||||
send_recv(*data++);
|
||||
}
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
// data must be 4 bytes
|
||||
void ams_read_eeprom_block(uint8_t block, uint8_t * data)
|
||||
{
|
||||
send_recv(0x7f);
|
||||
send_recv(block << 1);
|
||||
|
||||
data[0] = send_recv(0);
|
||||
data[1] = send_recv(0);
|
||||
data[2] = send_recv(0);
|
||||
data[3] = send_recv(0);
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
|
||||
// data must be 4 bytes
|
||||
void ams_write_eeprom_block(uint8_t block, uint8_t * data)
|
||||
{
|
||||
send_recv(0x40);
|
||||
send_recv(block << 1);
|
||||
|
||||
send_recv(data[0]);
|
||||
send_recv(data[1]);
|
||||
send_recv(data[2]);
|
||||
send_recv(data[3]);
|
||||
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
void ams_write_command(uint8_t cmd)
|
||||
{
|
||||
send_recv(0xc0 | cmd);
|
||||
UNSELECT();
|
||||
SELECT();
|
||||
}
|
||||
|
||||
const char * ams_get_state_string(uint8_t regval)
|
||||
{
|
||||
if (regval & AMS_STATE_INVALID)
|
||||
{
|
||||
return "STATE_INVALID";
|
||||
}
|
||||
switch (regval & AMS_STATE_MASK)
|
||||
{
|
||||
case AMS_STATE_OFF:
|
||||
return "STATE_OFF";
|
||||
case AMS_STATE_SENSE:
|
||||
return "STATE_SENSE";
|
||||
case AMS_STATE_RESOLUTION:
|
||||
return "STATE_RESOLUTION";
|
||||
case AMS_STATE_RESOLUTION_L2:
|
||||
return "STATE_RESOLUTION_L2";
|
||||
case AMS_STATE_SELECTED:
|
||||
return "STATE_SELECTED";
|
||||
case AMS_STATE_SECTOR2:
|
||||
return "STATE_SECTOR2";
|
||||
case AMS_STATE_SECTORX_2:
|
||||
return "STATE_SECTORX_2";
|
||||
case AMS_STATE_SELECTEDX:
|
||||
return "STATE_SELECTEDX";
|
||||
case AMS_STATE_SENSEX_L2:
|
||||
return "STATE_SENSEX_L2";
|
||||
case AMS_STATE_SENSEX:
|
||||
return "STATE_SENSEX";
|
||||
case AMS_STATE_SLEEP:
|
||||
return "STATE_SLEEP";
|
||||
}
|
||||
return "STATE_WRONG";
|
||||
}
|
||||
|
||||
void ams_print_int0(uint8_t int0)
|
||||
{
|
||||
uint32_t tag = (TAG_NFC)|(TAG_NO_TAG);
|
||||
printf1(TAG_NFC," ");
|
||||
if (int0 & AMS_INT_XRF)
|
||||
printf1(tag," XRF");
|
||||
if (int0 & AMS_INT_TXE)
|
||||
printf1(tag," TXE");
|
||||
if (int0 & AMS_INT_RXE)
|
||||
printf1(tag," RXE");
|
||||
if (int0 & AMS_INT_EER_RF)
|
||||
printf1(tag," EER_RF");
|
||||
if (int0 & AMS_INT_EEW_RF)
|
||||
printf1(tag," EEW_RF");
|
||||
if (int0 & AMS_INT_SLP)
|
||||
printf1(tag," SLP");
|
||||
if (int0 & AMS_INT_WU_A)
|
||||
printf1(tag," WU_A");
|
||||
if (int0 & AMS_INT_INIT)
|
||||
printf1(tag," INIT");
|
||||
|
||||
printf1(tag,"\r\n");
|
||||
}
|
||||
|
||||
void ams_print_int1(uint8_t int0)
|
||||
{
|
||||
uint32_t tag = (TAG_NFC)|(TAG_NO_TAG);
|
||||
printf1(TAG_NFC," ");
|
||||
if (int0 & AMS_INT_ACC_ERR)
|
||||
printf1(tag," ACC_ERR");
|
||||
if (int0 & AMS_INT_EEAC_ERR)
|
||||
printf1(tag," EEAC_ERR");
|
||||
if (int0 & AMS_INT_IO_EEWR)
|
||||
printf1(tag," IO_EEWR");
|
||||
if (int0 & AMS_INT_BF_ERR)
|
||||
printf1(tag," BF_ERR");
|
||||
if (int0 & AMS_INT_CRC_ERR)
|
||||
printf1(tag," CRC_ERR");
|
||||
if (int0 & AMS_INT_PAR_ERR)
|
||||
printf1(tag," PAR_ERR");
|
||||
if (int0 & AMS_INT_FRM_ERR)
|
||||
printf1(tag," FRM_ERR");
|
||||
if (int0 & AMS_INT_RXS)
|
||||
printf1(tag," RXS");
|
||||
|
||||
printf1(tag,"\r\n");
|
||||
}
|
||||
|
||||
|
||||
void nfc_init()
|
||||
{
|
||||
uint8_t block[4];
|
||||
|
||||
memset(&NFC_STATE,0,sizeof(NFC_STATE));
|
||||
NFC_STATE.max_frame_size = 32;
|
||||
|
||||
LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN);
|
||||
|
||||
LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW);
|
||||
LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE);
|
||||
LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable(SPI1);
|
||||
|
||||
delay(10);
|
||||
SELECT();
|
||||
delay(10);
|
||||
|
||||
|
||||
ams_write_command(AMS_CMD_DEFAULT);
|
||||
ams_write_command(AMS_CMD_CLEAR_BUFFER);
|
||||
|
||||
// enable tunneling mode and RF configuration
|
||||
ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD);
|
||||
|
||||
ams_read_eeprom_block(0, block);
|
||||
printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
ams_read_eeprom_block(0, block);
|
||||
printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
|
||||
printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
uint8_t sense1 = 0x44;
|
||||
uint8_t sense2 = 0x00;
|
||||
uint8_t selr = 0x20; // SAK
|
||||
|
||||
if(block[0] != sense1 || block[1] != sense2 || block[2] != selr)
|
||||
{
|
||||
printf1(TAG_NFC,"Writing config block 0\r\n");
|
||||
block[0] = sense1;
|
||||
block[1] = sense2;
|
||||
block[2] = selr;
|
||||
block[3] = 0x00;
|
||||
|
||||
ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
|
||||
UNSELECT();
|
||||
delay(10);
|
||||
SELECT();
|
||||
delay(10);
|
||||
|
||||
ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
|
||||
printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4);
|
||||
}
|
||||
|
||||
ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block);
|
||||
printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4);
|
||||
|
||||
uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0;
|
||||
uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD;
|
||||
|
||||
if (block[0] != ic_cfg1 || block[1] != ic_cfg2)
|
||||
{
|
||||
printf1(TAG_NFC,"Writing config block 1\r\n");
|
||||
// set IC_CFG1
|
||||
block[0] = ic_cfg1;
|
||||
|
||||
// set IC_CFG2
|
||||
block[1] = ic_cfg2;
|
||||
|
||||
// mask interrupt bits
|
||||
block[2] = 0x80;
|
||||
block[3] = 0;
|
||||
|
||||
ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block);
|
||||
|
||||
UNSELECT();
|
||||
delay(10);
|
||||
SELECT();
|
||||
delay(10);
|
||||
|
||||
ams_read_eeprom_block(0x7F, block);
|
||||
printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4);
|
||||
}
|
||||
|
||||
nfc_state_init();
|
||||
ams_init();
|
||||
}
|
||||
|
||||
void nfc_write_frame(uint8_t * data, uint8_t len)
|
||||
@ -396,16 +91,183 @@ int answer_rats(uint8_t parameter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rblock_acknowledge()
|
||||
{
|
||||
uint8_t buf[32];
|
||||
NFC_STATE.block_num = !NFC_STATE.block_num;
|
||||
buf[0] = NFC_CMD_RBLOCK | NFC_STATE.block_num;
|
||||
nfc_write_frame(buf,1);
|
||||
}
|
||||
|
||||
// Selects application. Returns 1 if success, 0 otherwise
|
||||
int select_applet(uint8_t * aid, int len)
|
||||
{
|
||||
if (memcmp(aid,AID_NDEF_TYPE_4,sizeof(AID_NDEF_TYPE_4)) == 0)
|
||||
{
|
||||
NFC_STATE.selected_applet = APP_NDEF_TYPE_4;
|
||||
return 1;
|
||||
} else if (memcmp(aid,AID_NDEF_MIFARE_TYPE_4,sizeof(AID_NDEF_MIFARE_TYPE_4)) == 0)
|
||||
{
|
||||
NFC_STATE.selected_applet = APP_MIFARE_TYPE_4;
|
||||
return 1;
|
||||
} else if (memcmp(aid,AID_CAPABILITY_CONTAINER,sizeof(AID_CAPABILITY_CONTAINER)) == 0)
|
||||
{
|
||||
NFC_STATE.selected_applet = APP_CAPABILITY_CONTAINER;
|
||||
return 1;
|
||||
} else if (memcmp(aid,AID_NDEF_TAG,sizeof(AID_NDEF_TAG)) == 0)
|
||||
{
|
||||
NFC_STATE.selected_applet = APP_NDEF_TAG;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nfc_process_iblock(uint8_t * buf, int len)
|
||||
{
|
||||
APDU_HEADER * apdu = (APDU_HEADER *)(buf+1);
|
||||
uint8_t * payload = buf + 1 + 5;
|
||||
uint8_t plen = apdu->lc;
|
||||
int selected;
|
||||
uint8_t res[32];
|
||||
|
||||
printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC,buf,len);
|
||||
|
||||
|
||||
// TODO this needs to be organized better
|
||||
switch(apdu->ins)
|
||||
{
|
||||
case APDU_INS_SELECT:
|
||||
if (plen > len - 6)
|
||||
{
|
||||
printf1(TAG_ERR, "Truncating APDU length %d\r\n", apdu->lc);
|
||||
plen = len-6;
|
||||
}
|
||||
// if (apdu->p1 == 0 && apdu->p2 == 0x0c)
|
||||
// {
|
||||
// printf1(TAG_NFC,"Select NDEF\r\n");
|
||||
//
|
||||
// NFC_STATE.selected_applet = APP_NDEF_TAG;
|
||||
// // Select NDEF file!
|
||||
// res[0] = NFC_CMD_IBLOCK | (buf[0] & 1);
|
||||
// res[1] = APDU_STATUS_SUCCESS>>8;
|
||||
// res[2] = APDU_STATUS_SUCCESS & 0xff;
|
||||
// nfc_write_frame(res, 3);
|
||||
// printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3);
|
||||
// }
|
||||
// else
|
||||
{
|
||||
selected = select_applet(payload, plen);
|
||||
if (selected)
|
||||
{
|
||||
|
||||
// block = buf[0] & 1;
|
||||
// block = NFC_STATE.block_num;
|
||||
// block = !block;
|
||||
// NFC_STATE.block_num = block;
|
||||
res[0] = NFC_CMD_IBLOCK | (buf[0] & 1);
|
||||
res[1] = APDU_STATUS_SUCCESS>>8;
|
||||
res[2] = APDU_STATUS_SUCCESS & 0xff;
|
||||
nfc_write_frame(res, 3);
|
||||
printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_NFC, "NOT selected\r\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APDU_INS_READ_BINARY:
|
||||
|
||||
|
||||
switch(NFC_STATE.selected_applet)
|
||||
{
|
||||
case APP_CAPABILITY_CONTAINER:
|
||||
printf1(TAG_NFC,"APP_CAPABILITY_CONTAINER\r\n");
|
||||
if (plen > 15)
|
||||
{
|
||||
printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc);
|
||||
plen = 15;
|
||||
}
|
||||
memmove(res+1, &NFC_CC, plen);
|
||||
break;
|
||||
case APP_NDEF_TAG:
|
||||
printf1(TAG_NFC,"APP_NDEF_TAG\r\n");
|
||||
if (plen > (sizeof(NDEF_SAMPLE) - 1))
|
||||
{
|
||||
printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc);
|
||||
plen = sizeof(NDEF_SAMPLE) - 1;
|
||||
}
|
||||
memmove(res+1, NDEF_SAMPLE, plen);
|
||||
break;
|
||||
default:
|
||||
printf1(TAG_ERR, "No binary applet selected!\r\n");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
res[0] = NFC_CMD_IBLOCK | (buf[0] & 1);
|
||||
|
||||
res[1+plen] = APDU_STATUS_SUCCESS>>8;
|
||||
res[2+plen] = APDU_STATUS_SUCCESS & 0xff;
|
||||
nfc_write_frame(res, 3+plen);
|
||||
printf1(TAG_NFC,"APDU_INS_READ_BINARY\r\n");
|
||||
printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3+plen);
|
||||
break;
|
||||
default:
|
||||
printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu->ins);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void nfc_process_block(uint8_t * buf, int len)
|
||||
{
|
||||
if (IS_PPSS_CMD(buf[0]))
|
||||
{
|
||||
printf1(TAG_NFC, "NFC_CMD_PPSS\r\n");
|
||||
}
|
||||
else if (IS_IBLOCK(buf[0]))
|
||||
{
|
||||
nfc_process_iblock(buf,len);
|
||||
printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n");
|
||||
}
|
||||
else if (IS_RBLOCK(buf[0]))
|
||||
{
|
||||
rblock_acknowledge();
|
||||
printf1(TAG_NFC, "NFC_CMD_RBLOCK\r\n");
|
||||
}
|
||||
else if (IS_SBLOCK(buf[0]))
|
||||
{
|
||||
|
||||
if ((buf[0] & NFC_SBLOCK_DESELECT) == 0)
|
||||
{
|
||||
nfc_write_frame(buf, 1);
|
||||
printf1(TAG_NFC, "NFC_CMD_SBLOCK, DESELECTED\r\n");
|
||||
nfc_state_init();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_NFC, "NFC_CMD_SBLOCK, Unknown\r\n");
|
||||
}
|
||||
dump_hex1(TAG_NFC, buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_NFC, "unknown NFC request\r\n len[%d]:", len);
|
||||
dump_hex1(TAG_NFC, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_loop()
|
||||
{
|
||||
|
||||
const uint32_t interval = 200;
|
||||
static uint32_t t1 = 0;
|
||||
static uint32_t c = 0;
|
||||
uint8_t buf[32];
|
||||
AMS_DEVICE ams,ams2;
|
||||
AMS_DEVICE ams;
|
||||
int len = 0;
|
||||
uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00";
|
||||
// uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00";
|
||||
|
||||
|
||||
// if (millis() - t1 > interval)
|
||||
if (1)
|
||||
{
|
||||
@ -417,17 +279,14 @@ void nfc_loop()
|
||||
// }
|
||||
if (ams.regs.rfid_status)
|
||||
{
|
||||
uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status;
|
||||
// uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status;
|
||||
// if (state != AMS_STATE_SENSE)
|
||||
// printf1(TAG_NFC," %s %d\r\n", ams_get_state_string(ams.regs.rfid_status), millis());
|
||||
}
|
||||
if (ams.regs.int0)
|
||||
if (ams.regs.int0 & AMS_INT_INIT)
|
||||
{
|
||||
// ams_print_int0(ams.regs.int0);
|
||||
if (ams.regs.int0 & AMS_INT_XRF)
|
||||
{
|
||||
printf1(TAG_NFC," %d\r\n", millis());
|
||||
}
|
||||
// Initialize chip!
|
||||
nfc_state_init();
|
||||
}
|
||||
if (ams.regs.int1)
|
||||
{
|
||||
@ -443,15 +302,13 @@ void nfc_loop()
|
||||
{
|
||||
len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK;
|
||||
ams_read_buffer(buf, len);
|
||||
// printf1(TAG_NFC,"%d bytes in buffer\r\n", len);
|
||||
// dump_hex1(TAG_NFC, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
// printf1(TAG_NFC,"RATS %d\r\n",c++);
|
||||
// ams_write_command(AMS_CMD_TRANSMIT_ACK);
|
||||
|
||||
// ISO 14443-3
|
||||
switch(buf[0])
|
||||
{
|
||||
case NFC_CMD_REQA:
|
||||
@ -466,31 +323,14 @@ void nfc_loop()
|
||||
case NFC_CMD_RATS:
|
||||
t1 = millis();
|
||||
answer_rats(buf[1]);
|
||||
NFC_STATE.block_num = 1;
|
||||
printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1);
|
||||
break;
|
||||
default:
|
||||
|
||||
if (IS_PPSS_CMD(buf[0]))
|
||||
{
|
||||
printf1(TAG_NFC, "NFC_CMD_PPSS\r\n");
|
||||
}
|
||||
else if (IS_IBLOCK(buf[0]))
|
||||
{
|
||||
printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n");
|
||||
}
|
||||
else if (IS_RBLOCK(buf[0]))
|
||||
{
|
||||
printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n");
|
||||
}
|
||||
else if (IS_SBLOCK(buf[0]))
|
||||
{
|
||||
printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_NFC, "unknown NFC request\r\n len[%d]:", len);
|
||||
dump_hex1(TAG_NFC, buf, len);
|
||||
}
|
||||
// ISO 14443-4
|
||||
nfc_process_block(buf,len);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -6,109 +6,26 @@
|
||||
void nfc_loop();
|
||||
void nfc_init();
|
||||
|
||||
typedef union
|
||||
typedef struct
|
||||
{
|
||||
uint8_t buf[0x20];
|
||||
struct {
|
||||
uint8_t io_conf; // 0x00
|
||||
uint8_t ic_conf0; // 0x01
|
||||
uint8_t ic_conf1; // 0x02
|
||||
uint8_t ic_conf2; // 0x03
|
||||
uint8_t rfid_status; // 0x04
|
||||
uint8_t ic_status; // 0x05
|
||||
uint8_t _nc0[2]; // 0x06 - 0x07
|
||||
uint8_t mask_int0; // 0x08
|
||||
uint8_t mask_int1; // 0x09
|
||||
uint8_t int0; // 0x0a
|
||||
uint8_t int1; // 0x0b
|
||||
uint8_t buffer_status2; // 0x0c
|
||||
uint8_t buffer_status1; // 0x0d
|
||||
uint8_t last_nfc_addr; // 0x0e
|
||||
uint8_t _nc1[0x1b - 0x0f + 1]; // 0x0f - 0x1b
|
||||
uint8_t product_type; // 0x1c
|
||||
uint8_t product_subtype; // 0x1d
|
||||
uint8_t version_maj; // 0x1e
|
||||
uint8_t version_min; // 0x1f
|
||||
} regs;
|
||||
} __attribute__((packed)) AMS_DEVICE;
|
||||
uint8_t cclen_hi;
|
||||
uint8_t cclen_lo;
|
||||
uint8_t version;
|
||||
uint8_t MLe_hi;
|
||||
uint8_t MLe_lo;
|
||||
uint8_t MLc_hi;
|
||||
uint8_t MLc_lo;
|
||||
uint8_t tlv[8];
|
||||
} __attribute__((packed)) CAPABILITY_CONTAINER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t start;
|
||||
uint8_t parameter;
|
||||
} __attribute__((packed)) RATS_REQUEST;
|
||||
|
||||
#define AMS_REG_IO_CONF 0x00
|
||||
#define AMS_REG_IC_CONF0 0x01
|
||||
#define AMS_REG_IC_CONF1 0x02
|
||||
#define AMS_REG_IC_CONF2 0x03
|
||||
#define AMS_RFCFG_EN 0x80
|
||||
#define AMS_TUN_MOD 0x40
|
||||
#define AMS_REG_RFID_STATUS 0x04
|
||||
#define AMS_HF_PON 0x80
|
||||
#define AMS_STATE_MASK 0x78
|
||||
#define AMS_STATE_INVALID 0x04
|
||||
#define AMS_STATE_OFF (0 << 3)
|
||||
#define AMS_STATE_SENSE (1 << 3)
|
||||
#define AMS_STATE_RESOLUTION (3 << 3)
|
||||
#define AMS_STATE_RESOLUTION_L2 (2 << 3)
|
||||
#define AMS_STATE_SELECTED (6 << 3)
|
||||
#define AMS_STATE_SECTOR2 (7 << 3)
|
||||
#define AMS_STATE_SECTORX_2 (0xf << 3)
|
||||
#define AMS_STATE_SELECTEDX (0xd << 3)
|
||||
#define AMS_STATE_SENSEX_L2 (0xa << 3)
|
||||
#define AMS_STATE_SENSEX (0xb << 3)
|
||||
#define AMS_STATE_SLEEP (0x9 << 3)
|
||||
// ... //
|
||||
#define AMS_REG_INT0 0x0a
|
||||
#define AMS_INT_XRF (1<<0)
|
||||
#define AMS_INT_TXE (1<<1)
|
||||
#define AMS_INT_RXE (1<<2)
|
||||
#define AMS_INT_EER_RF (1<<3)
|
||||
#define AMS_INT_EEW_RF (1<<4)
|
||||
#define AMS_INT_SLP (1<<5)
|
||||
#define AMS_INT_WU_A (1<<6)
|
||||
#define AMS_INT_INIT (1<<7)
|
||||
#define AMS_REG_INT1 0x0b
|
||||
#define AMS_INT_ACC_ERR (1<<0)
|
||||
#define AMS_INT_EEAC_ERR (1<<1)
|
||||
#define AMS_INT_IO_EEWR (1<<2)
|
||||
#define AMS_INT_BF_ERR (1<<3)
|
||||
#define AMS_INT_CRC_ERR (1<<4)
|
||||
#define AMS_INT_PAR_ERR (1<<5)
|
||||
#define AMS_INT_FRM_ERR (1<<6)
|
||||
#define AMS_INT_RXS (1<<7)
|
||||
#define AMS_REG_BUF2 0x0c
|
||||
#define AMS_BUF_LEN_MASK 0x1f
|
||||
#define AMS_BUF_INVALID 0x80
|
||||
|
||||
#define AMS_CONFIG_BLOCK0_ADDR 0x7e
|
||||
#define AMS_CONFIG_BLOCK1_ADDR 0x7f
|
||||
|
||||
#define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2)
|
||||
#define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2)
|
||||
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_50 0x02
|
||||
#define AMS_CFG1_OUTPUT_RESISTANCE_25 0x03
|
||||
|
||||
#define AMS_CFG2_RFCFG_EN (1<<7)
|
||||
#define AMS_CFG2_TUN_MOD (1<<6)
|
||||
|
||||
#define AMS_CMD_DEFAULT 0x02
|
||||
#define AMS_CMD_CLEAR_BUFFER 0x04
|
||||
#define AMS_CMD_RESTART_TRANSCEIVER 0x06
|
||||
#define AMS_CMD_DIS_EN_TRANSCEIVER 0x07
|
||||
#define AMS_CMD_TRANSMIT_BUFFER 0x08
|
||||
#define AMS_CMD_TRANSMIT_ACK 0x09
|
||||
#define AMS_CMD_TRANSMIT_NACK0 0x0A
|
||||
#define AMS_CMD_TRANSMIT_NACK1 0x0B
|
||||
#define AMS_CMD_TRANSMIT_NACK4 0x0D
|
||||
#define AMS_CMD_TRANSMIT_NACK5 0x0C
|
||||
#define AMS_CMD_SLEEP 0x10
|
||||
#define AMS_CMD_SENSE 0x11
|
||||
#define AMS_CMD_SENSE_SLEEP 0x12
|
||||
uint8_t cla;
|
||||
uint8_t ins;
|
||||
uint8_t p1;
|
||||
uint8_t p2;
|
||||
uint8_t lc;
|
||||
} __attribute__((packed)) APDU_HEADER;
|
||||
|
||||
#define NFC_CMD_REQA 0x26
|
||||
#define NFC_CMD_WUPA 0x52
|
||||
@ -117,11 +34,31 @@ typedef struct
|
||||
|
||||
#define NFC_CMD_PPSS 0xd0
|
||||
#define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS)
|
||||
#define NFC_CMD_IBLOCK 0x00
|
||||
#define IS_IBLOCK(x) (((x) & 0xe0) == NFC_CMD_IBLOCK)
|
||||
#define NFC_CMD_RBLOCK 0xa0
|
||||
#define IS_RBLOCK(x) (((x) & 0xe0) == NFC_CMD_RBLOCK)
|
||||
#define NFC_CMD_SBLOCK 0xc0
|
||||
#define IS_SBLOCK(x) (((x) & 0xc0) == NFC_CMD_SBLOCK)
|
||||
#define NFC_CMD_IBLOCK 0x02
|
||||
#define IS_IBLOCK(x) (((x) & 0xe2) == NFC_CMD_IBLOCK)
|
||||
#define NFC_CMD_RBLOCK 0xa2
|
||||
#define IS_RBLOCK(x) (((x) & 0xe6) == NFC_CMD_RBLOCK)
|
||||
#define NFC_CMD_SBLOCK 0xc2
|
||||
#define IS_SBLOCK(x) (((x) & 0xc7) == NFC_CMD_SBLOCK)
|
||||
|
||||
#define NFC_SBLOCK_DESELECT 0x30
|
||||
|
||||
#define APDU_INS_SELECT 0xA4
|
||||
#define APDU_INS_READ_BINARY 0xB0
|
||||
|
||||
#define AID_NDEF_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x01"
|
||||
#define AID_NDEF_MIFARE_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x00"
|
||||
#define AID_CAPABILITY_CONTAINER "\xE1\x03"
|
||||
#define AID_NDEF_TAG "\x11\x11"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
APP_NDEF_TYPE_4 = 1,
|
||||
APP_MIFARE_TYPE_4,
|
||||
APP_CAPABILITY_CONTAINER,
|
||||
APP_NDEF_TAG,
|
||||
} APPLETS;
|
||||
|
||||
#define APDU_STATUS_SUCCESS 0x9000
|
||||
|
||||
#endif
|
||||
|
@ -53,7 +53,7 @@ int _write (int fd, const void *buf, long int len)
|
||||
// Send out UART serial
|
||||
while(len--)
|
||||
{
|
||||
_putchar(*data++);
|
||||
// _putchar(*data++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user