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
|
# 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/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 += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||||
SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.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 <string.h>
|
||||||
|
|
||||||
#include "stm32l4xx.h"
|
#include "stm32l4xx.h"
|
||||||
#include "stm32l4xx_ll_gpio.h"
|
|
||||||
#include "stm32l4xx_ll_spi.h"
|
|
||||||
#include "nfc.h"
|
#include "nfc.h"
|
||||||
|
#include "ams.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
// Capability container
|
||||||
#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
|
||||||
|
|
||||||
|
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
|
static struct
|
||||||
{
|
{
|
||||||
uint8_t max_frame_size;
|
uint8_t max_frame_size;
|
||||||
uint8_t cid;
|
uint8_t cid;
|
||||||
|
uint8_t block_num;
|
||||||
|
uint8_t selected_applet;
|
||||||
} NFC_STATE;
|
} NFC_STATE;
|
||||||
|
|
||||||
|
void nfc_state_init()
|
||||||
static void flush_rx()
|
|
||||||
{
|
{
|
||||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0)
|
memset(&NFC_STATE,0,sizeof(NFC_STATE));
|
||||||
{
|
NFC_STATE.max_frame_size = 32;
|
||||||
LL_SPI_ReceiveData8(SPI1);
|
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()
|
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);
|
nfc_state_init();
|
||||||
ams_write_command(AMS_CMD_CLEAR_BUFFER);
|
ams_init();
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfc_write_frame(uint8_t * data, uint8_t len)
|
void nfc_write_frame(uint8_t * data, uint8_t len)
|
||||||
@ -396,16 +91,183 @@ int answer_rats(uint8_t parameter)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfc_loop()
|
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)
|
||||||
{
|
{
|
||||||
|
|
||||||
const uint32_t interval = 200;
|
// 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()
|
||||||
|
{
|
||||||
static uint32_t t1 = 0;
|
static uint32_t t1 = 0;
|
||||||
static uint32_t c = 0;
|
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
AMS_DEVICE ams,ams2;
|
AMS_DEVICE ams;
|
||||||
int len = 0;
|
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 (millis() - t1 > interval)
|
||||||
if (1)
|
if (1)
|
||||||
{
|
{
|
||||||
@ -417,17 +279,14 @@ void nfc_loop()
|
|||||||
// }
|
// }
|
||||||
if (ams.regs.rfid_status)
|
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)
|
// if (state != AMS_STATE_SENSE)
|
||||||
// printf1(TAG_NFC," %s %d\r\n", ams_get_state_string(ams.regs.rfid_status), millis());
|
// 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);
|
// Initialize chip!
|
||||||
if (ams.regs.int0 & AMS_INT_XRF)
|
nfc_state_init();
|
||||||
{
|
|
||||||
printf1(TAG_NFC," %d\r\n", millis());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ams.regs.int1)
|
if (ams.regs.int1)
|
||||||
{
|
{
|
||||||
@ -443,15 +302,13 @@ void nfc_loop()
|
|||||||
{
|
{
|
||||||
len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK;
|
len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK;
|
||||||
ams_read_buffer(buf, len);
|
ams_read_buffer(buf, len);
|
||||||
// printf1(TAG_NFC,"%d bytes in buffer\r\n", len);
|
|
||||||
// dump_hex1(TAG_NFC, buf, len);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
{
|
{
|
||||||
// printf1(TAG_NFC,"RATS %d\r\n",c++);
|
|
||||||
// ams_write_command(AMS_CMD_TRANSMIT_ACK);
|
// ISO 14443-3
|
||||||
switch(buf[0])
|
switch(buf[0])
|
||||||
{
|
{
|
||||||
case NFC_CMD_REQA:
|
case NFC_CMD_REQA:
|
||||||
@ -466,31 +323,14 @@ void nfc_loop()
|
|||||||
case NFC_CMD_RATS:
|
case NFC_CMD_RATS:
|
||||||
t1 = millis();
|
t1 = millis();
|
||||||
answer_rats(buf[1]);
|
answer_rats(buf[1]);
|
||||||
|
NFC_STATE.block_num = 1;
|
||||||
printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1);
|
printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
if (IS_PPSS_CMD(buf[0]))
|
// ISO 14443-4
|
||||||
{
|
nfc_process_block(buf,len);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6,109 +6,26 @@
|
|||||||
void nfc_loop();
|
void nfc_loop();
|
||||||
void nfc_init();
|
void nfc_init();
|
||||||
|
|
||||||
typedef union
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t buf[0x20];
|
uint8_t cclen_hi;
|
||||||
struct {
|
uint8_t cclen_lo;
|
||||||
uint8_t io_conf; // 0x00
|
uint8_t version;
|
||||||
uint8_t ic_conf0; // 0x01
|
uint8_t MLe_hi;
|
||||||
uint8_t ic_conf1; // 0x02
|
uint8_t MLe_lo;
|
||||||
uint8_t ic_conf2; // 0x03
|
uint8_t MLc_hi;
|
||||||
uint8_t rfid_status; // 0x04
|
uint8_t MLc_lo;
|
||||||
uint8_t ic_status; // 0x05
|
uint8_t tlv[8];
|
||||||
uint8_t _nc0[2]; // 0x06 - 0x07
|
} __attribute__((packed)) CAPABILITY_CONTAINER;
|
||||||
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;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t start;
|
uint8_t cla;
|
||||||
uint8_t parameter;
|
uint8_t ins;
|
||||||
} __attribute__((packed)) RATS_REQUEST;
|
uint8_t p1;
|
||||||
|
uint8_t p2;
|
||||||
#define AMS_REG_IO_CONF 0x00
|
uint8_t lc;
|
||||||
#define AMS_REG_IC_CONF0 0x01
|
} __attribute__((packed)) APDU_HEADER;
|
||||||
#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
|
|
||||||
|
|
||||||
#define NFC_CMD_REQA 0x26
|
#define NFC_CMD_REQA 0x26
|
||||||
#define NFC_CMD_WUPA 0x52
|
#define NFC_CMD_WUPA 0x52
|
||||||
@ -117,11 +34,31 @@ typedef struct
|
|||||||
|
|
||||||
#define NFC_CMD_PPSS 0xd0
|
#define NFC_CMD_PPSS 0xd0
|
||||||
#define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS)
|
#define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS)
|
||||||
#define NFC_CMD_IBLOCK 0x00
|
#define NFC_CMD_IBLOCK 0x02
|
||||||
#define IS_IBLOCK(x) (((x) & 0xe0) == NFC_CMD_IBLOCK)
|
#define IS_IBLOCK(x) (((x) & 0xe2) == NFC_CMD_IBLOCK)
|
||||||
#define NFC_CMD_RBLOCK 0xa0
|
#define NFC_CMD_RBLOCK 0xa2
|
||||||
#define IS_RBLOCK(x) (((x) & 0xe0) == NFC_CMD_RBLOCK)
|
#define IS_RBLOCK(x) (((x) & 0xe6) == NFC_CMD_RBLOCK)
|
||||||
#define NFC_CMD_SBLOCK 0xc0
|
#define NFC_CMD_SBLOCK 0xc2
|
||||||
#define IS_SBLOCK(x) (((x) & 0xc0) == NFC_CMD_SBLOCK)
|
#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
|
#endif
|
||||||
|
@ -53,7 +53,7 @@ int _write (int fd, const void *buf, long int len)
|
|||||||
// Send out UART serial
|
// Send out UART serial
|
||||||
while(len--)
|
while(len--)
|
||||||
{
|
{
|
||||||
_putchar(*data++);
|
// _putchar(*data++);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user