diff --git a/targets/stm32l432/application.mk b/targets/stm32l432/application.mk index 70bbc3f..110c069 100644 --- a/targets/stm32l432/application.mk +++ b/targets/stm32l432/application.mk @@ -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) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c new file mode 100644 index 0000000..1b2c87a --- /dev/null +++ b/targets/stm32l432/src/ams.c @@ -0,0 +1,340 @@ +#include + +#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); + } + +} diff --git a/targets/stm32l432/src/ams.h b/targets/stm32l432/src/ams.h new file mode 100644 index 0000000..361cb0d --- /dev/null +++ b/targets/stm32l432/src/ams.h @@ -0,0 +1,127 @@ +#ifndef _AMS_H_ +#define _AMS_H_ + +#include +#include +#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 diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 133f4c2..ed3e9d8 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -1,355 +1,50 @@ #include #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; } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 7cc9556..8a91803 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -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 diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index 431bc18..d3d5e5d 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -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; }