initial commit

This commit is contained in:
2021-10-11 11:30:39 +02:00
commit bb8deeb27d
56 changed files with 14201 additions and 0 deletions

23
LICENSE.md Normal file
View File

@@ -0,0 +1,23 @@
COPYRIGHT(c) 2017 STMicroelectronics
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of STMicroelectronics nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
README.md Normal file
View File

@@ -0,0 +1,22 @@
# X-NUCLEO-NFC03A1
The code has been designed for ST X-NUCLEO-NFC03A1 expansion board to show how to detect, read and write NFC tags.
The X-NUCLEO-NFC03A1 is an NFC card reader evaluation board based on CR95HF-VMD5T to enable expansion of the STM32 Nucleo boards.
The CR95HF manages frame coding and decoding in Reader mode for standard applications, such as NFC, proximity and vicinity standards.
The CR95HF embeds an analog front end to provide the 13.56 MHz air interface. The CR95HF supports ISO/IEC 14443 Type A and B, ISO/IEC 15693
(single or double subcarrier) and ISO/IEC 18092 communication protocols, besides being MIFARE® Classic compatible.
It also supports the detection, reading and writing of NFC Forum Type 1, 2, 3 and 4 tags.
## Examples
There is one example with the X-NUCLEO-NFC03A1 library:
* X_NUCLEO_NFC03A1_HelloWorld: This application is to show how to detect, read and write NFC Forum Type 1, 2, 3 and 4 tags.
## Documentation
You can find the source files at
https://github.com/stm32duino/X-NUCLEO-NFC03A1
The CR95HF datasheet is available at
http://www.st.com/content/st_com/en/products/nfc/st25-nfc-rfid-tags-readers/st25-nfc-rfid-readers/cr95hf.html

View File

@@ -0,0 +1,329 @@
/**
******************************************************************************
* @file X_NUCLEO_NFC03A1_HelloWorld.ino
* @author AST
* @version V1.0.0
* @date 6 December 2017
* @brief Arduino test application for the STMicrolectronics X-NUCLEO-NFC03A1
* NFC reader/writer expansion board.
* This application makes use of C++ classes obtained from the C
* components' drivers.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
#include "stdbool.h"
#include "string.h"
#include "lib_NDEF_URI.h"
#include "lib_NDEF_SMS.h"
#include "lib_NDEF_Text.h"
#include "lib_NDEF_Email.h"
#include "lib_NDEF_Geo.h"
#include "lib_95HFConfigManager.h"
#include "miscellaneous.h"
#include "lib_95HFConfigManager.h"
#include "lib_wrapper.h"
#include "lib_NDEF_URI.h"
#include "drv_spi.h"
#define SerialPort Serial
/* Exported define -----------------------------------------------------------*/
#define BULK_MAX_PACKET_SIZE 0x00000040
/* Regarding board antenna (and matching) appropriate
value may be modified to optimized RF performances */
/* Analogue configuration register
ARConfigB bits 7:4 MOD_INDEX Modulation index to modulator
3:0 RX_AMP_GAIN Defines receiver amplifier gain
For type A you can also adjust the Timer Window
*/
/****************** PICC ******************/
/* ISO14443A */
#define PICC_TYPEA_ACConfigA 0x27 /* backscaterring */
/* ISO14443B */
#define PICC_TYPEB_ARConfigD 0x0E /* card demodulation gain */
#define PICC_TYPEB_ACConfigA 0x17 /* backscaterring */
/* Felica */
#define PICC_TYPEF_ACConfigA 0x17 /* backscaterring */
/* Private variables ---------------------------------------------------------*/
/* TT1 (PCD only)*/
uint8_t TT1Tag[NFCT1_MAX_TAGMEMORY];
/* TT2 */
uint8_t TT2Tag[NFCT2_MAX_TAGMEMORY];
/* TT3 */
uint8_t TT3Tag[NFCT3_MAX_TAGMEMORY];
uint8_t *TT3AttribInfo = TT3Tag, *TT3NDEFfile = &TT3Tag[NFCT3_ATTRIB_INFO_SIZE];
/* TT4 */
uint8_t CardCCfile [NFCT4_MAX_CCMEMORY];
uint8_t CardNDEFfileT4A [NFCT4_MAX_NDEFMEMORY];
uint8_t CardNDEFfileT4B [NFCT4_MAX_NDEFMEMORY];
/* TT5 (PCD only)*/
uint8_t TT5Tag[NFCT5_MAX_TAGMEMORY];
sURI_Info url;
extern uint8_t NDEF_Buffer [];
extern DeviceMode_t devicemode;
sRecordInfo_uri RecordStruct;
int8_t TagType = TRACK_NOTHING;
bool TagDetected = false;
bool terminal_msg_flag = false ;
uint8_t status = ERRORCODE_GENERIC;
static char dataOut[256];
#define X_NUCLEO_NFC03A1_LED1 D7
#define X_NUCLEO_NFC03A1_LED2 D6
#define X_NUCLEO_NFC03A1_LED3 D5
#define X_NUCLEO_NFC03A1_LED4 D4
void setup() {
// 95HF HW Init
ConfigManager_HWInit();
// LED1
pinMode(X_NUCLEO_NFC03A1_LED1, OUTPUT);
// LED2
pinMode(X_NUCLEO_NFC03A1_LED2, OUTPUT);
// LED3
pinMode(X_NUCLEO_NFC03A1_LED3, OUTPUT);
// LED4
pinMode(X_NUCLEO_NFC03A1_LED4, OUTPUT);
// Configure USB serial interface
SerialPort.begin(115200);
SerialPort.print("\r\n\r\n---------------------------------------\r\n******Welcome to x-nucleo-nfc03a1 demo******\r\n----------------------------------------");
SerialPort.print("\r\n\r\nPlease bring an NFC tag to the board vicinity and Press User Button B1 on the board to start URI Writer/Reader demo on the tag");
terminal_msg_flag = true;
digitalWrite(X_NUCLEO_NFC03A1_LED1, HIGH);
}
/* Loop ----------------------------------------------------------------------*/
void loop()
{
devicemode = PCD;
/* Scan to find if there is a tag */
TagType = ConfigManager_TagHunting(TRACK_ALL);
switch(TagType)
{
case TRACK_NFCTYPE1:
{
TagDetected = true;
if(terminal_msg_flag == true )
{
terminal_msg_flag = false ;
/*---HT UI msg----------*/
SerialPort.print( "\r\n\r\nTRACK_NFCTYPE1 NFC tag detected nearby");
digitalWrite(X_NUCLEO_NFC03A1_LED2, HIGH);
}
}
break;
case TRACK_NFCTYPE2:
{
TagDetected = true;
if(terminal_msg_flag == true )
{
terminal_msg_flag = false ;
/*---HT UI msg----------*/
SerialPort.print( "\r\n\r\nTRACK_NFCTYPE2 NFC tag detected nearby");
digitalWrite(X_NUCLEO_NFC03A1_LED2, HIGH);
}
}
break;
case TRACK_NFCTYPE3:
{
TagDetected = true;
if(terminal_msg_flag == true )
{
terminal_msg_flag = false ;
/*---HT UI msg----------*/
SerialPort.print( "\r\n\r\nTRACK_NFCTYPE3 NFC tag detected nearby");
digitalWrite(X_NUCLEO_NFC03A1_LED2, HIGH);
}
}
break;
case TRACK_NFCTYPE4A:
{
TagDetected = true;
if(terminal_msg_flag == true )
{
terminal_msg_flag = false ;
/*---HT UI msg----------*/
SerialPort.print( "\r\n\r\nTRACK_NFCTYPE4A NFC tag detected nearby");
digitalWrite(X_NUCLEO_NFC03A1_LED2, HIGH);
}
}
break;
case TRACK_NFCTYPE4B:
{
TagDetected = true;
if(terminal_msg_flag == true )
{
terminal_msg_flag = false ;
/*---HT UI msg----------*/
SerialPort.print( "\r\n\r\nTRACK_NFCTYPE4B NFC tag detected nearby");
digitalWrite(X_NUCLEO_NFC03A1_LED2, HIGH);
}
}
break;
case TRACK_NFCTYPE5:
{
TagDetected = true;
if(terminal_msg_flag == true )
{
terminal_msg_flag = false ;
/*---HT UI msg----------*/
SerialPort.print( "\r\n\r\nTRACK_NFCTYPE5 NFC tag detected nearby");
digitalWrite(X_NUCLEO_NFC03A1_LED2, HIGH);
}
}
break;
default:
{
TagDetected = false;
if(terminal_msg_flag == false)
{
terminal_msg_flag = true ;
/*---HT UI msg----------*/
SerialPort.print( "\r\n\r\nCurrently there is no NFC tag in the vicinity");
digitalWrite(X_NUCLEO_NFC03A1_LED2, LOW);
digitalWrite(X_NUCLEO_NFC03A1_LED3, LOW);
digitalWrite(X_NUCLEO_NFC03A1_LED4, LOW);
}
}
break;
}
delay(300);
if (TagDetected == true)
{
TagDetected = false;
/* Fill the structure of the NDEF URI */
strcpy(url.Information,"ST website for near field communication");
strcpy(url.protocol,"http://");
strcpy(url.URI_Message,"st.com/st25");
status = NDEF_WriteURI(&url);
delay(500);
if(status == RESULTOK) /*---if URI write passed----------*/
{
status = ERRORCODE_GENERIC;
snprintf( dataOut, 256, "\r\n\r\n--------------------\r\n*****URI Writer*****\r\n--------------------\r\nURI Information written successfully on the tag: \r\n URI Information: [%s], \r\n URI Protocol: [%s] , \r\n URI Message: [%s]", (char *)url.Information, (char *)url.protocol, (char *)url.URI_Message );
SerialPort.print( dataOut );
digitalWrite(X_NUCLEO_NFC03A1_LED3, HIGH);
memset(url.Information,'\0',400); /*Clear url buffer before reading*/
if (TagType == TRACK_NFCTYPE1)
{
status = PCDNFCT1_ReadNDEF();
} else if (TagType == TRACK_NFCTYPE2)
{
status = PCDNFCT2_ReadNDEF();
} else if (TagType == TRACK_NFCTYPE3)
{
status = PCDNFCT3_ReadNDEF();
} else if (TagType == TRACK_NFCTYPE4A || TagType == TRACK_NFCTYPE4B)
{
status = PCDNFCT4_ReadNDEF();
} else if (TagType == TRACK_NFCTYPE5)
{
status = PCDNFCT5_ReadNDEF();
}
if ( status == RESULTOK )
{
status = ERRORCODE_GENERIC;
memset(NDEF_Buffer,'\0',20); /* Avoid printing useless characters */
status = NDEF_IdentifyNDEF( &RecordStruct, NDEF_Buffer);
if(status == RESULTOK && RecordStruct.TypeLength != 0)
{
if (NDEF_ReadURI(&RecordStruct, &url)==RESULTOK) /*---if URI read passed---*/
{
snprintf( dataOut, 256, "\r\n\r\n--------------------\r\n*****URI Reader*****\r\n--------------------\r\nURI Information read successfully from the tag: \r\n URI Information: [%s], \r\n URI Protocol: [%s] , \r\n URI Message: [%s]", (char *)url.Information, (char *)url.protocol, (char *)url.URI_Message );
SerialPort.print( dataOut );
digitalWrite(X_NUCLEO_NFC03A1_LED4, HIGH);
}
}
}
}
}
}

9
library.properties Normal file
View File

@@ -0,0 +1,9 @@
name=STM32duino X-NUCLEO-NFC03A1
version=1.0.2
author=STMicroelectronics
maintainer=stm32duino
sentence=Allows controlling the ST X-NUCLEO-NFC03A1 expansion board
paragraph=This library provides the drivers and a sample application to control ST X-NUCLEO-NFC03A1 expansion board
category=Communication
url=https://github.com/stm32duino/x-nucleo-nfc03a1
architectures=stm32

122
src/common.h Normal file
View File

@@ -0,0 +1,122 @@
/**
******************************************************************************
* @file common.h
* @author MMY Application Team
* @version $Revision: 1507 $
* @date $Date: 2016-01-08 09:48:35 +0100 (Fri, 08 Jan 2016) $
* @brief This file provides all the headers of the common functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _COMMON_H
#define _COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#define NFC_TAG_MEMORY 512
#include "miscellaneous.h"
#include "lib_95HFConfigManager.h"
#include "lib_wrapper.h"
#include "lib_NDEF_URI.h"
#include "drv_spi.h"
#define MAX_NDEF_MEM 0x50
/* Nfc Mandatory define ------------------------------------------------------*/
#define RESULTOK 0x00
#define ERRORCODE_GENERIC 1
#define ACTION_COMPLETED 0x9000
/* status and erroc code --------------------------------------------------- */
#define MAIN_SUCCESS_CODE RESULTOK
/* Enum for ST95 state aligned with new lib Ndef*/
typedef enum {UNDEFINED_MODE=0,PICC,PCD}DeviceMode_t;
typedef enum {UNDEFINED_TAG_TYPE=0,TT1,TT2,TT3,TT4A,TT4B,TT5}TagType_t;
/* external constants --------------------------------------------------------*/
extern bool HID_TRANSACTION;
/* Exported types ------------------------------------------------------------*/
typedef void (*pFunction)(void);
/* Exported constants --------------------------------------------------------*/
/* Constants used by Serial Command Line Mode */
#define CMD_STRING_SIZE 128
#define ApplicationAddress 0x8009000
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
/* Compute the FLASH upload image size */
#define FLASH_IMAGE_SIZE (uint32_t) (FLASH_SIZE - (ApplicationAddress - 0x08000000))
/* TT1 */
#define NFCT1_MAX_TAGMEMORY (120+2)
/* TT2 */
#define NFCT2_MAX_TAGMEMORY NFC_TAG_MEMORY /*(must be a multiple of 8) */
#define NFCT2_MAX_CC_SIZE 4
#define NFCT2_MAX_CONFIG 12
#define NFCT2_MAX_NDEFFILE (NFCT2_MAX_TAGMEMORY-NFCT2_MAX_CC_SIZE-NFCT2_MAX_CONFIG)
/* TT3 */
#define NFCT3_ATTRIB_INFO_SIZE 16
#define NFCT3_MAX_NDEFFILE NFC_TAG_MEMORY
#define NFCT3_MAX_TAGMEMORY (NFCT3_MAX_NDEFFILE+NFCT3_ATTRIB_INFO_SIZE)
#define NFCT3_NB_BLOC_MSB ((NFCT3_MAX_TAGMEMORY/16)>>8)
#define NFCT3_NB_BLOC_LSB ((NFCT3_MAX_TAGMEMORY/16)&0x00FF)
/* TT4 */
#define NFCT4_MAX_CCMEMORY 16
#define NFCT4A_MAX_NDEFMEMORY NFC_TAG_MEMORY
#define NFCT4B_MAX_NDEFMEMORY NFC_TAG_MEMORY
#define NFCT4_MAX_NDEFMEMORY NFCT4A_MAX_NDEFMEMORY
/* TT5 */
#define NFCT5_MAX_TAGMEMORY NFC_TAG_MEMORY
#define NFC_DEVICE_MAX_NDEFMEMORY NFCT4_MAX_NDEFMEMORY
/* Exported macro ------------------------------------------------------------*/
/* Common routines */
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* _COMMON_H */
/*******************(C)COPYRIGHT 2016 STMicroelectronics *****END OF FILE******/

248
src/drv_95HF.h Normal file
View File

@@ -0,0 +1,248 @@
/**
******************************************************************************
* @file drv_95HF.h
* @author MMY Application Team
* @version $Revision: 1347 $
* @date $Date: 2015-11-05 11:36:05 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of firmware functions to manage communication
* @brief between MCU and 95HF device (CR95HF)
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion ------------------------------------------------ */
#ifndef __DRV_95HF_H
#define __DRV_95HF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------------------- */
#include "drv_spi.h"
//#include "drv_uart.h"
/** @addtogroup BSP
* @{
*/
/** @addtogroup Components
* @{
*/
/** @defgroup XX95HF
* @{
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup XX95HF_Exported_Constants
* @{
*/
/* RFtransceiver HEADER command definition ---------------------------------------------- */
#define RFTRANS_95HF_COMMAND_SEND 0x00
#define RFTRANS_95HF_COMMAND_RESET 0x01
#define RFTRANS_95HF_COMMAND_RECEIVE 0x02
#define RFTRANS_95HF_COMMAND_POLLING 0x03
#define RFTRANS_95HF_COMMAND_IDLE 0x07
/* RFtransceiver mask and data to check the data (SPI polling)--------------------------- */
#define RFTRANS_95HF_FLAG_DATA_READY 0x08
#define RFTRANS_95HF_FLAG_DATA_READY_MASK 0x08
/* RF transceiver status --------------------------------------------------------------- */
#define RFTRANS_95HF_SUCCESS_CODE RESULTOK
#define RFTRANS_95HF_NOREPLY_CODE 0x01
#define RFTRANS_95HF_ERRORCODE_DEFAULT 0xFE
#define RFTRANS_95HF_ERRORCODE_TIMEOUT 0xFD
#define RFTRANS_95HF_ERRORCODE_POR 0x44
/* RF transceiver polling status ------------------------------------------------------- */
#define RFTRANS_95HF_POLLING_RFTRANS_95HF 0x00
#define RFTRANS_95HF_POLLING_TIMEOUT 0x01
/* RF transceiver number of byte of the buffers------------------------------------------ */
#define RFTRANS_95HF_RESPONSEBUFFER_SIZE 0xFF
#define RFTRANS_95HF_MAX_BUFFER_SIZE 0xFF
/* Max of 256 (for QJC) and 768 (for QJE. Should be 512 but bug Design) */
#define RFTRANS_95HF_MAX_ECHO 768
/* RF transceiver Offset of the command and the response -------------------------------- */
#define RFTRANS_95HF_COMMAND_OFFSET 0x00
#define RFTRANS_95HF_LENGTH_OFFSET 0x01
#define RFTRANS_95HF_DATA_OFFSET 0x02
/* ECHO response ------------------------------------------------------------------------ */
#define ECHORESPONSE 0x55
/* Sleep parameters --------------------------------------------------------------------- */
#define IDLE_SLEEP_MODE 0x00
#define IDLE_HIBERNATE_MODE 0x01
#define IDLE_CMD_LENTH 0x0E
#define WU_TIMEOUT 0x01
#define WU_TAG 0x02
#define WU_FIELD 0x04
#define WU_IRQ 0x08
#define WU_SPI 0x10
#define HIBERNATE_ENTER_CTRL 0x0400
#define SLEEP_ENTER_CTRL 0x0100
#define SLEEP_FIELD_ENTER_CTRL 0x0142
#define HIBERNATE_WU_CTRL 0x0400
#define SLEEP_WU_CTRL 0x3800
#define LEAVE_CTRL 0x1800
/* Calibration parameters---------------------------------------------------------------- */
#define WU_SOURCE_OFFSET 0x02
#define WU_PERIOD_OFFSET 0x09
#define DACDATAL_OFFSET 0x0C
#define DACDATAH_OFFSET 0x0D
#define NBTRIALS_OFFSET 0x0F
#define MAX_BUFFER_SIZE 256
#define ECHO 0x55
#define LISTEN 0x05
#define DUMMY_BYTE 0xFF
/* set state on IRQ in pin */
//#define RFTRANS_95HF_GET_INTERFACE() HAL_GPIO_ReadPin(INTERFACE_GPIO_PORT,INTERFACE_PIN)
#define READERREPLY_MAX_BUFFER_SIZE 0x40
/**
* @}
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup XX95HF_Exported_Types
* @{
*/
typedef enum {
RFTRANS_95HF_INTERFACE_UART = 0,
RFTRANS_95HF_INTERFACE_SPI,
RFTRANS_95HF_INTERFACE_TWI
}RFTRANS_95HF_INTERFACE;
/**
* @brief the different states of the RF transceiver
*/
typedef enum {
RFTRANS_95HF_STATE_UNKNOWN = 0,
RFTRANS_95HF_STATE_HIBERNATE ,
RFTRANS_95HF_STATE_SLEEP,
RFTRANS_95HF_STATE_POWERUP,
RFTRANS_95HF_STATE_TAGDETECTOR,
RFTRANS_95HF_STATE_READY,
RFTRANS_95HF_STATE_READER,
RFTRANS_95HF_STATE_TAGHUNTING,
}RFTRANS_95HF_STATE;
/**
* @brief the RF transceiver can be configured as either a reader or a card emulator
* @brief or as P2P device
*/
typedef enum {
RFTRANS_95HF_MODE_UNKNOWN = 0,
RFTRANS_95HF_MODE_READER ,
RFTRANS_95HF_MODE_CARDEMULATOR ,
RFTRANS_95HF_MODE_PASSIVEP2P ,
RFTRANS_95HF_MODE_ACTIVEP2P ,
}RFTRANS_95HF_MODE;
/**
* @brief the Rf transceiver supports the differrent protocols
*/
typedef enum {
RFTRANS_95HF_PROTOCOL_UNKNOWN = 0,
RFTRANS_95HF_PCD_14443A,
RFTRANS_95HF_PCD_14443B,
RFTRANS_95HF_PCD_15693,
RFTRANS_95HF_PCD_18092,
RFTRANS_95HF_PICC_14443A,
RFTRANS_95HF_PICC_14443B,
RFTRANS_95HF_PICC_15693,
RFTRANS_95HF_PICC_18092,
}RFTRANS_95HF_PROTOCOL;
/**
* @brief structure to store driver information
*/
typedef struct {
RFTRANS_95HF_INTERFACE uInterface;
RFTRANS_95HF_STATE uState;
RFTRANS_95HF_MODE uMode;
RFTRANS_95HF_PROTOCOL uCurrentProtocol;
}drv95HF_ConfigStruct;
/**
* @}
*/
/* External variables --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/** @defgroup XX95HF_Exported_Functions
* @{
*/
void drv95HF_ResetSPI(void);
//int8_t drv95HF_GetInterfacePinState(void);
uint8_t drv95HF_GetSerialInterface(void);
//int8_t drv95HF_GetIRQOutState(void);
void drv95HF_InitConfigStructure(void);
void drv95HF_InitilizeSerialInterface(void);
void drv95HF_ReceiveSPIResponse(uint8_t *pData);
void drv95HF_SendSPICommand(const uint8_t *pData );
int8_t drv95HF_SendReceive(const uint8_t *pCommand, uint8_t *pResponse);
void drv95HF_SendCmd(const uint8_t *pCommand);
int8_t drv95HF_PoolingReading(uint8_t *pResponse);
void drv95HF_Idle(const uint8_t WU_source, const uint8_t mode);
void drv95HF_SendIRQINPulse(void);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __DRV_95HF_H */
/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/

515
src/drv_95hf.cpp Normal file
View File

@@ -0,0 +1,515 @@
/**
******************************************************************************
* @file drv_95HF.c
* @author MMY Application Team
* @version $Revision: 1348 $
* @date $Date: 2015-11-05 11:36:33 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of driver functions to manage communication
* between MCU and xx95HF chip (CR95HF)
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "SPI.h"
#include "stdbool.h"
#include "drv_95HF.h"
#include "lib_pcd.h"
/** @addtogroup BSP
* @{
*/
/** @addtogroup Components
* @{
*/
/** @addtogroup XX95HF
* @{
*/
/* External variables --------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void drv95HF_InitializeSPI(void);
static void drv95HF_SendSPIResetByte(void);
static int8_t drv95HF_SPIPollingCommand(void);
/* Global variables ---------------------------------------------------------*/
/** @defgroup XX95HF_Global variables
* @{
*/
/**
* @brief buffer to exchange data with the RF tranceiver.
*/
uint8_t u95HFBuffer [RFTRANS_95HF_MAX_BUFFER_SIZE+3];
/**
* @brief This uTimeOut variable is used as a timeout duting the communication with the RF tranceiver
*/
extern volatile bool uDataReady;
bool EnableTimeOut = true;
/* ConfigStructure */
drv95HF_ConfigStruct drv95HFConfig;
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup XX95HF_Private_Functions
* @{
*/
/**
* @brief this functions initializes the SPI in order to communicate with the 95HF device
* @param None
* @retval void
*/
static void drv95HF_InitializeSPI(void)
{
RFTRANS_SPI_Init();
}
/**
* @brief This function sends a reset command over SPI bus
* @param None
* @retval None
*/
static void drv95HF_SendSPIResetByte(void)
{
/* Send reset control byte */
SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_RESET);
}
/**
* @brief This function polls 95HF chip until a response is ready or
* the counter of the timeout overflows
* @param None
* @retval PCD_POLLING_TIMEOUT : The time out was reached
* @retval PCD_SUCCESS_CODE : A response is available
*/
static int8_t drv95HF_SPIPollingCommand( void )
{
uint8_t Polling_Status = 0;
int timestamp_start = -1;
int timestamp_final = -1;
bool uTimeOut = false;
if(EnableTimeOut)
{
timestamp_start = millis();
}
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
do
{
/* Low level on NSS */
RFTRANS_95HF_NSS_LOW();
delay(2);
/* poll the 95HF transceiver until he's ready ! */
Polling_Status = SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_POLLING);
Polling_Status &= RFTRANS_95HF_FLAG_DATA_READY_MASK;
if(EnableTimeOut)
{
/* 3sec for LLCP can be improved to adjust it dynamically */
timestamp_final = millis();
if((timestamp_final - timestamp_start) > 3000)
{
uTimeOut = true;
}
}
}
while( Polling_Status != RFTRANS_95HF_FLAG_DATA_READY && uTimeOut != true );
/* High level on NSS */
RFTRANS_95HF_NSS_HIGH();
DEV_SPI.endTransaction();
if ( uTimeOut == true )
{
return RFTRANS_95HF_POLLING_TIMEOUT;
}
return RFTRANS_95HF_SUCCESS_CODE;
}
/**
* @}
*/
/** @defgroup drv_95HF_Public_Functions
* @{
*/
/**
* @brief Initilize the 95HF device config structure
* @param None
* @retval None
*/
void drv95HF_InitConfigStructure (void)
{
drv95HFConfig.uInterface = RFTRANS_95HF_INTERFACE_SPI;
drv95HFConfig.uState = RFTRANS_95HF_STATE_POWERUP;
drv95HFConfig.uCurrentProtocol = RFTRANS_95HF_PROTOCOL_UNKNOWN;
drv95HFConfig.uMode = RFTRANS_95HF_MODE_UNKNOWN;
}
/**
* @brief Send a reset sequence over SPI bus (Reset command ,wait ,negative pulse on IRQin).
* @param None
* @retval None
*/
void drv95HF_ResetSPI(void)
{
/* Deselect Rftransceiver over SPI */
RFTRANS_95HF_NSS_HIGH();
delay(1);
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
/* Select 95HF device over SPI */
RFTRANS_95HF_NSS_LOW();
/* Send reset control byte */
drv95HF_SendSPIResetByte();
/* Deselect 95HF device over SPI */
RFTRANS_95HF_NSS_HIGH();
DEV_SPI.endTransaction();
delay(3);
/* send a pulse on IRQ_in*/
drv95HF_SendIRQINPulse();
delay(10); /* mandatory before issuing a new command */
drv95HFConfig.uState = RFTRANS_95HF_STATE_READY;
}
/**
* @brief returns the value of interface pin.
* Low level means UART bus was choose.
* High level means SPI bus was choose.
* @param None
* @retval Bit_RESET : 0
* @retval Bit_SET : 1
*/
//int8_t drv95HF_GetInterfacePinState(void)
//{
// return RFTRANS_95HF_GET_INTERFACE();
//}
/**
* @brief This function returns the IRQout state
* @param None
* @retval Pin set : 1
* @retval Pin reset : 0
*/
//int8_t drv95HF_GetIRQOutState(void)
//{
// if (HAL_GPIO_ReadPin(IRQOUT_RFTRANS_95HF_PORT, IRQOUT_RFTRANS_95HF_PIN) != GPIO_PIN_RESET)
// {
// return 0x01;
// }
// else
// {
// return 0x00;
// }
//}
/**
* @brief This function initialize MCU serial interface peripheral (SPI or UART)
* @param None
* @retval None
*/
void drv95HF_InitilizeSerialInterface(void)
{
/* -- Get interface pin state to select UART or SPI mode -- */
//if (drv95HF_GetInterfacePinState() != RFTRANS_95HF_INTERFACE_UART)
//{
/* -- Set communication type -- */
drv95HFConfig.uInterface = RFTRANS_95HF_INTERFACE_SPI;
/* -- Initialize SPI Interface -- */
drv95HF_InitializeSPI( );
//}
}
/**
* @brief This function returns the Interface selected(UART or SPI)
* @param None
* @retval RFTRANS_INTERFACE_UART : the UART interface is selected
* @retval RFTRANS_INTERFACE_SPI : the SPI interface is selected
*/
uint8_t drv95HF_GetSerialInterface(void)
{
return drv95HFConfig.uInterface;
}
/**
* @brief This function sends a command over SPI bus
* @param *pData : pointer on data to send to the xx95HF
* @retval None
*/
void drv95HF_SendSPICommand(const uint8_t *pData)
{
uint8_t DummyBuffer[MAX_BUFFER_SIZE];
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
/* Select xx95HF over SPI */
RFTRANS_95HF_NSS_LOW();
/* Send a sending request to xx95HF */
SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_SEND);
if(*pData == ECHO)
{
/* Send a sending request to xx95HF */
SPI_SendReceiveByte(ECHO);
}
else
{
/* Transmit the buffer over SPI */
SPI_SendReceiveBuffer(pData, pData[RFTRANS_95HF_LENGTH_OFFSET]+RFTRANS_95HF_DATA_OFFSET, DummyBuffer);
}
/* Deselect xx95HF over SPI */
RFTRANS_95HF_NSS_HIGH();
DEV_SPI.endTransaction();
}
/**
* @brief This fucntion recovers a response from 95HF device
* @param *pData : pointer on data received from 95HF device
* @retval None
*/
void drv95HF_ReceiveSPIResponse(uint8_t *pData)
{
uint8_t DummyBuffer[MAX_BUFFER_SIZE];
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
/* Select 95HF transceiver over SPI */
RFTRANS_95HF_NSS_LOW();
/* Request a response from 95HF transceiver */
SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_RECEIVE);
/* Recover the "Command" byte */
pData[RFTRANS_95HF_COMMAND_OFFSET] = SPI_SendReceiveByte(DUMMY_BYTE);
if(pData[RFTRANS_95HF_COMMAND_OFFSET] == ECHO)
{
pData[RFTRANS_95HF_LENGTH_OFFSET] = 0x00;
/* In case we were in listen mode error code cancelled by user (0x85 0x00) must be retrieved */
pData[RFTRANS_95HF_LENGTH_OFFSET+1] = SPI_SendReceiveByte(DUMMY_BYTE);
pData[RFTRANS_95HF_LENGTH_OFFSET+2] = SPI_SendReceiveByte(DUMMY_BYTE);
}
else if(pData[RFTRANS_95HF_COMMAND_OFFSET] == 0xFF)
{
pData[RFTRANS_95HF_LENGTH_OFFSET] = 0x00;
pData[RFTRANS_95HF_LENGTH_OFFSET+1] = SPI_SendReceiveByte(DUMMY_BYTE);
pData[RFTRANS_95HF_LENGTH_OFFSET+2] = SPI_SendReceiveByte(DUMMY_BYTE);
}
else
{
/* Recover the "Length" byte */
pData[RFTRANS_95HF_LENGTH_OFFSET] = SPI_SendReceiveByte(DUMMY_BYTE);
/* Checks the data length */
if(pData[RFTRANS_95HF_LENGTH_OFFSET] != 0x00)
SPI_SendReceiveBuffer(DummyBuffer, pData[RFTRANS_95HF_LENGTH_OFFSET], &pData[RFTRANS_95HF_DATA_OFFSET]);
}
/* Deselect xx95HF over SPI */
RFTRANS_95HF_NSS_HIGH();
DEV_SPI.endTransaction();
}
/**
* @brief This function send a command to 95HF device over SPI or UART bus and receive its response
* @param *pCommand : pointer on the buffer to send to the 95HF device ( Command | Length | Data)
* @param *pResponse : pointer on the 95HF device response ( Command | Length | Data)
* @retval RFTRANS_95HF_SUCCESS_CODE : the function is succesful
*/
int8_t drv95HF_SendReceive(const uint8_t *pCommand, uint8_t *pResponse)
{
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
/* First step - Sending command */
drv95HF_SendSPICommand(pCommand);
/* Second step - Polling */
if (drv95HF_SPIPollingCommand( ) != RFTRANS_95HF_SUCCESS_CODE)
{
*pResponse = RFTRANS_95HF_ERRORCODE_TIMEOUT;
return RFTRANS_95HF_POLLING_TIMEOUT;
}
/* Third step - Receiving bytes */
drv95HF_ReceiveSPIResponse(pResponse);
}
return RFTRANS_95HF_SUCCESS_CODE;
}
/**
* @brief This function send a command to 95HF device over SPI or UART bus
* @param *pCommand : pointer on the buffer to send to the 95HF ( Command | Length | Data)
* @retval None
*/
void drv95HF_SendCmd(const uint8_t *pCommand)
{
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
/* First step - Sending command */
drv95HF_SendSPICommand(pCommand);
// else if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_UART)
/* First step - Sending command */
// drv95HF_SendUARTCommand(pCommand);
}
/**
* @brief This function is a specific command. It's made polling and reading sequence.
* @param *pResponse : pointer on the 95HF device response ( Command | Length | Data)
* @retval RFTRANS_95HF_SUCCESS_CODE : the function is succesful
* @retval RFTRANS_95HF_POLLING_RFTRANS_95HF : the polling sequence returns an error
*/
int8_t drv95HF_PoolingReading (uint8_t *pResponse)
{
*pResponse =RFTRANS_95HF_ERRORCODE_DEFAULT;
*(pResponse+1) = 0x00;
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
/* First step - Polling */
if (drv95HF_SPIPollingCommand( ) != RFTRANS_95HF_SUCCESS_CODE)
{ *pResponse = RFTRANS_95HF_ERRORCODE_TIMEOUT;
return RFTRANS_95HF_ERRORCODE_TIMEOUT;
}
/* Second step - Receiving bytes */
drv95HF_ReceiveSPIResponse(pResponse);
}
return RFTRANS_95HF_SUCCESS_CODE;
}
/**
* @brief Send a negative pulse on IRQin pin
* @param None
* @retval None
*/
void drv95HF_SendIRQINPulse(void)
{
if (drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
/* Send a pulse on IRQ_IN */
RFTRANS_95HF_IRQIN_HIGH() ;
delay(1);
RFTRANS_95HF_IRQIN_LOW() ;
delay(1);
RFTRANS_95HF_IRQIN_HIGH() ;
}
/* Need to wait 10ms after the pulse before to send the first command */
delay(10);
}
/**
* @brief this functions put the ST95HF in sleep/hibernate mode
* @param WU_source : Source selected to wake up the device (WU_TIMEOUT,WU_TAG,WU_FIELD,WU_IRQ,WU_SPI)
* @param mode : Can be IDLE_SLEEP_MODE or IDLE_HIBERNATE_MODE
* @retval None
*/
void drv95HF_Idle(const uint8_t WU_source, const uint8_t mode)
{
uint8_t pCommand[] = {RFTRANS_95HF_COMMAND_IDLE, IDLE_CMD_LENTH, 0, 0, 0, 0, 0 ,0x18 ,0x00 ,0x00 ,0x60 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00};
if (mode == IDLE_SLEEP_MODE) /* SLEEP */
{
/* Select the wake up source*/
pCommand[2] = WU_source;
/* Select SLEEP mode */
if (WU_source == WU_FIELD)
{
pCommand[3] = GETMSB(SLEEP_FIELD_ENTER_CTRL);
pCommand[4] = GETLSB(SLEEP_FIELD_ENTER_CTRL);
}
else
{
pCommand[3] = GETMSB(SLEEP_ENTER_CTRL);
pCommand[4] = GETLSB(SLEEP_ENTER_CTRL);
}
pCommand[5] = GETMSB(SLEEP_WU_CTRL);
pCommand[6] = GETLSB(SLEEP_WU_CTRL);
}
else /* HIBERNATE */
{
/* Select the wake up source, only IRQ is available for HIBERNATE mode*/
pCommand[2] = WU_IRQ;
/* Select HIBERNATE mode */
pCommand[3] = GETMSB(HIBERNATE_ENTER_CTRL);
pCommand[4] = GETLSB(HIBERNATE_ENTER_CTRL);
pCommand[5] = GETMSB(HIBERNATE_WU_CTRL);
pCommand[6] = GETLSB(HIBERNATE_WU_CTRL);
pCommand[10] = 0x00;
}
/* Send the command */
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
/* First step - Sending command */
drv95HF_SendSPICommand(pCommand);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/

123
src/drv_spi.cpp Normal file
View File

@@ -0,0 +1,123 @@
/**
******************************************************************************
* @file drv_spi.c
* @author MMY Application Team
* @version $Revision: 1508 $
* @date $Date: 2016-01-08 09:50:04 +0100 (Fri, 08 Jan 2016) $
* @brief This file provides a set of firmware functions to manages SPI communications
******************************************************************************
* @copyright
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under MMY-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "SPI.h"
#include "drv_spi.h"
/** @addtogroup BSP
* @{
*/
/** @addtogroup X_NUCLEO_NFC03A1_Spi
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
/* Public Functions ----------------------------------------------------------*/
/** @defgroup X_NUCLEO_NFC03A1_Spi_Public_Functions
* @{
*/
/**
* @brief Initialise HAL SPI for NFC03A1
* @param None
* @retval None
*/
void RFTRANS_SPI_Init(void)
{
// Configure NSS pin for CR95HF
pinMode(10, OUTPUT);
// Configure interface pin select for CR95HF
pinMode(9, OUTPUT);
// Configure interrupt input pin for CR95HF
pinMode(8, OUTPUT);
// Set the interface pin select high in order to configure the NFC reader to use the SPI interface
digitalWrite(9, HIGH);
/* SPI_NSS = High Level */
RFTRANS_95HF_NSS_HIGH();
/* Set signal to high */
RFTRANS_95HF_IRQIN_HIGH();
DEV_SPI.begin();
}
/**
* @brief Sends one byte over SPI and recovers a response
* @param data : data to send
* @retval data response from SPIx
*/
uint8_t SPI_SendReceiveByte(uint8_t data)
{
return DEV_SPI.transfer(data);
}
/**
* @brief reveive a byte array over SPI
* @param pCommand : pointer on the buffer to send
* @param length : length of the buffer to send
* @param pResponse : pointer on the buffer response
* @retval None
*/
void SPI_SendReceiveBuffer(const uint8_t *pCommand, uint8_t length, uint8_t *pResponse)
{
uint8_t i;
for(i=0; i<length; i++)
pResponse[i] = SPI_SendReceiveByte(pCommand[i]);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/

86
src/drv_spi.h Normal file
View File

@@ -0,0 +1,86 @@
/**
******************************************************************************
* @file drv_spi.h
* @author MMY Application Team
* @version $Revision: 1508 $
* @date $Date: 2016-01-08 09:50:04 +0100 (Fri, 08 Jan 2016) $
* @brief This file provides a set of firmware functions to manages SPI communications
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion ------------------------------------ */
#ifndef __DRV_SPI_H
#define __DRV_SPI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
/** @addtogroup BSP
* @{
*/
/** @defgroup X_NUCLEO_NFC03A1_Spi
* @{
*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#define DEV_SPI SPI
/* set state on SPI_NSS pin */
#define RFTRANS_95HF_NSS_LOW() digitalWrite(10, 0)
#define RFTRANS_95HF_NSS_HIGH() digitalWrite(10, 1)
/* set state on IRQ_In pin */
#define RFTRANS_95HF_IRQIN_LOW() digitalWrite(8, 0)
#define RFTRANS_95HF_IRQIN_HIGH() digitalWrite(8, 1)
/* Exported functions ------------------------------------------------------- */
/** @defgroup X_NUCLEO_NFC03A1_Spi_Exported_Functions
* @{
*/
void RFTRANS_SPI_Init(void);
void SPI_SendReceiveBuffer(const uint8_t *pCommand, uint8_t length, uint8_t *pResponse);
uint8_t SPI_SendReceiveByte(uint8_t data);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __DRV_SPI_H */
/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/

128
src/lib_95HF.h Normal file
View File

@@ -0,0 +1,128 @@
/**
******************************************************************************
* @file lib_95HF.h
* @author MMY Application Team
* @version $Revision: 1327 $
* @date $Date: 2015-11-05 10:28:31 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of xx95HF device.
* @brief The commands as defined in 95HF's family product datasheet.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LIB_95HF_H
#define _LIB_95HF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "drv_95HF.h"
#include "common.h"
#include "lib_nfctype1pcd.h"
#include "lib_nfctype2pcd.h"
#include "lib_nfctype3pcd.h"
#include "lib_nfctype4pcd.h"
#include "lib_nfctype5pcd.h"
/* Analogue configuration register for protocol initialization -------------------------------------------*/
#define TIMER_WINDOW_REG_ADD 0x3A
#define TIMER_WINDOW_UPDATE_CONFIRM_CMD 0x04
#define AFE_ANALOG_CONF_REG_SELECTION 0x68
#define AFE_ANALOG_CONF_REG_UPDATE 0x69
#define AFE_ACCONFIGA_OFFSET 0x04
/* ROM CODE Revision --------------------------------------------------------------*/
#define ROM_CODE_REVISION_OFFSET 13
/* RFtrans 95HF family command definition ---------------------------------------------------------------*/
#define IDN 0x01
#define PROTOCOL_SELECT 0x02
#define POLL_FIELD 0x03
#define SEND_RECEIVE 0x04
#define LISTEN 0x05
#define SEND 0x06
#define IDLE 0x07
#define READ_REGISTER 0x08
#define WRITE_REGISTER 0x09
#define BAUD_RATE 0x0A
#define SUB_FREQ_RES 0x0B
#define AC_FILTER 0x0D
#define TEST_MODE 0x0E
#define SLEEP_MODE 0x0F
#define ECHO 0x55
/* poll field status ------------------------------------------------------------------ */
#define POLLFIELD_RESULTSCODE_OK 0x00
// Send command field status
#define SEND_RESULTSCODE_OK 0x00
#define SEND_ERRORCODE_LENGTH 0x82
#define SEND_ERRORCODE_PROTOCOL 0x83
/* Idle command field status ----------------------------------------------------------------- */
#define IDLE_RESULTSCODE_OK 0x00
#define IDLE_ERRORCODE_LENGTH 0x82
/* read register command field status -------------------------------------------------------- */
#define READREG_RESULTSCODE_OK 0x00
#define READREG_ERRORCODE_LENGTH 0x82
/* write register command field status ------------------------------------------------------- */
#define WRITEREG_RESULTSCODE_OK 0x00
/* Baud rate command field status ------------------------------------------------------------ */
#define BAUDRATE_RESULTSCODE_OK 0x55
/* AC filter command field status ------------------------------------------------------------ */
#define ACFILTER_RESULTSCODE_OK 0x00
#define ACFILTER_ERRORCODE_LENGTH 0x82
/* sub freq command field status ------------------------------------------------------------- */
#define SUBFREQ_RESULTSCODE_OK 0x00
/* Test mode command field status ------------------------------------------------------------ */
#define TESTMODE_RESULTSCODE_OK 0x00
#define ASK_FOR_SESSION 0x0000
#define TAKE_SESSION 0xFFFF
#define XX95_ACTION_COMPLETED 0x9000
typedef enum {
QJA = 0x30,
QJB,
QJC,
QJD,
QJE
}IC_VERSION;
#ifdef __cplusplus
}
#endif
#endif /* _LIB_95HF_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,324 @@
/**
******************************************************************************
* @file lib_95HFConfigManager.c
* @author MMY Application Team
* @version $Revision: 1328 $
* @date $Date: 2015-11-05 10:30:08 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of firmware functions to manages device modes.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "Arduino.h"
#include "lib_95HFConfigManager.h"
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family ( CR95HF ) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup Config_Manager
* @{
* @brief This part of the library manage the configuration of the chip.
*/
/**
* @brief This buffer contains the data send/received by xx95HF
*/
extern uint8_t u95HFBuffer[RFTRANS_95HF_MAX_BUFFER_SIZE+3];
extern ISO14443A_CARD ISO14443A_Card;
/** @addtogroup Configuration_Manager
* @{
* @brief This file is used to select a configuration, PICC or PCD or Initiator/Target.
*/
/** @addtogroup lib_ConfigManager_Private_Functions
* @{
*/
static void ConfigManager_Init( void);
static int8_t ConfigManager_IDN(uint8_t *pResponse);
static void ConfigManager_Start(void );
static int8_t ConfigManager_PORsequence( void );
/* Variables for the different modes */
DeviceMode_t devicemode = UNDEFINED_MODE;
TagType_t nfc_tagtype = UNDEFINED_TAG_TYPE;
/* Variable to know IC version */
IC_VERSION IcVers = QJE; /* default set last IC version */
bool StopProcess = false;
bool TargetMode = true;
uint8_t TagUID[16];
/**
* @brief This function initialize the PICC
* @param None
* @retval None
*/
static void ConfigManager_Init( void)
{
/* initialize the structure of the Rf tranceiver */
drv95HF_InitConfigStructure ();
/* configure the Serial interface to communicate with the RF transceiver */
drv95HF_InitilizeSerialInterface ( );
}
/**
* @brief this function sends an IDN command to the PICC device
* @param pResponse : pointer on the PICC device reply
* @retval PICC_SUCCESSCODE : the function is succesful
*/
static int8_t ConfigManager_IDN(uint8_t *pResponse)
{
uint8_t DataToSend[] = {IDN ,0x00};
/* send the command to the PICC and retrieve its response */
drv95HF_SendReceive(DataToSend, pResponse);
return MANAGER_SUCCESSCODE;
}
/**
* @brief This function set a variable to inform Manager that a task is on going
* @param none
* @retval none
*/
static void ConfigManager_Start( void )
{
StopProcess = false;
devicemode = UNDEFINED_MODE;
nfc_tagtype = UNDEFINED_TAG_TYPE;
}
/**
* @brief This function sends POR sequence. It is used to initialize chip after a POR.
* @param none
* @retval MANAGER_ERRORCODE_PORERROR : the POR sequence doesn't succeded
* @retval MANAGER_SUCCESSCODE : chip is ready
*/
static int8_t ConfigManager_PORsequence( void )
{
uint16_t NthAttempt=0;
uint8_t command[]= {ECHO};
/* Power up sequence: Pulse on IRQ_IN to select UART or SPI mode */
drv95HF_SendIRQINPulse();
/* SPI Reset */
if(drv95HF_GetSerialInterface() == RFTRANS_95HF_INTERFACE_SPI)
{
drv95HF_ResetSPI();
}
do
{
/* send an ECHO command and checks response */
drv95HF_SendReceive(command, u95HFBuffer);
if (u95HFBuffer[0]==ECHORESPONSE)
return MANAGER_SUCCESSCODE;
/* if the SPI interface is selected then send a reset command*/
if(drv95HF_GetSerialInterface() == RFTRANS_95HF_INTERFACE_SPI)
{
drv95HF_ResetSPI();
}
/* if the UART interface is selected then send 255 ECHO commands*/
else if(drv95HF_GetSerialInterface() == RFTRANS_95HF_INTERFACE_UART)
{
do {
/* send an ECHO command and checks response */
drv95HF_SendReceive(command, u95HFBuffer);
if (u95HFBuffer[0] == ECHORESPONSE)
return MANAGER_SUCCESSCODE;
}while(NthAttempt++ < RFTRANS_95HF_MAX_ECHO);
}
} while (u95HFBuffer[0]!=ECHORESPONSE && NthAttempt++ <5);
return MANAGER_ERRORCODE_PORERROR;
}
/**
* @}
*/
/** @addtogroup lib_ConfigManager_Public_Functions
* @{
*/
/**
* @brief This interface function inform Manager that current task must be stopped
* @param none
* @retval none
*/
void ConfigManager_Stop(void )
{
StopProcess = true;
}
/**
* @brief This function initialize the NFC chip
* @brief Physical communication with chip enabled, RF communication not enabled
* @param None
* @retval None
*/
void ConfigManager_HWInit (void)
{
/* Initialize HW according to protocol to use */
ConfigManager_Init();
/* initilialize the RF transceiver */
if (ConfigManager_PORsequence( ) != MANAGER_SUCCESSCODE)
{
/* nothing to do, this is a trap for debug purpose you can use it to detect HW issue */
/* or GPIO config issue */
}
/* Retrieve the IC version of the chip */
ConfigManager_IDN(u95HFBuffer);
IcVers = (IC_VERSION) (u95HFBuffer[ROM_CODE_REVISION_OFFSET]);
}
/**
* @brief this function searches if a NFC or RFID tag is in the RF field.
* @brief The method used is this described by the NFC specification
* @param tagsToFind : Flags to select the different kinds of tag to track, same as return value
* @retval TRACK_NOTHING : No tag in the RF field
* @retval TRACK_NFCTYPE1 : A NFC type1 tag is present in the RF field
* @retval TRACK_NFCTYPE2 : A NFC type2 tag is present in the RF field
* @retval TRACK_NFCTYPE3 : A NFC type3 tag is present in the RF field
* @retval TRACK_NFCTYPE4A : A NFC type4A tag is present in the RF field
* @retval TRACK_NFCTYPE4B : A NFC type4B tag is present in the RF field
* @retval TRACK_NFCTYPE5 : A ISO/IEC 15693 type A tag is present in the RF field
*/
uint8_t ConfigManager_TagHunting ( uint8_t tagsToFind )
{
/* Start the config manager*/
ConfigManager_Start();
/******* NFC type 1 ********/
if (tagsToFind&TRACK_NFCTYPE1)
{
PCD_FieldOff();
delay(5);
ISO14443A_Init( );
if(ISO14443A_IsPresent() == RESULTOK)
{
if(TOPAZ_ID(TagUID) == RESULTOK)
return TRACK_NFCTYPE1;
}
}
/******* NFC type 2 and 4A ********/
if ((tagsToFind&TRACK_NFCTYPE2) || (tagsToFind&TRACK_NFCTYPE4A))
{
PCD_FieldOff();
delay(5);
ISO14443A_Init( );
if(ISO14443A_IsPresent() == RESULTOK)
{
if(ISO14443A_Anticollision() == RESULTOK)
{
if (((ISO14443A_Card.SAK&0x60) == 0x00) && (tagsToFind&TRACK_NFCTYPE2)) /* TT2 */
return TRACK_NFCTYPE2;
else if (((ISO14443A_Card.SAK&0x20) != 0x00) && (tagsToFind&TRACK_NFCTYPE4A))/* TT4A */
return TRACK_NFCTYPE4A;
}
}
}
/******* NFC type 3 ********/
if (tagsToFind&TRACK_NFCTYPE3)
{
PCD_FieldOff();
delay(5);
FELICA_Initialization();
if(FELICA_IsPresent() == RESULTOK )
return TRACK_NFCTYPE3;
}
/******* NFC type 4B ********/
if (tagsToFind&TRACK_NFCTYPE4B)
{
PCD_FieldOff();
delay(5);
if(ISO14443B_IsPresent() == RESULTOK )
{
if(ISO14443B_Anticollision() == RESULTOK)
{
return TRACK_NFCTYPE4B;
}
}
}
/******* ISO15693 ********/
if (tagsToFind&TRACK_NFCTYPE5)
{
PCD_FieldOff();
delay(5);
if(ISO15693_GetUID (TagUID) == RESULTOK)
return TRACK_NFCTYPE5;
}
/* Turn off the field if no tag has been detected*/
PCD_FieldOff();
/* No tag found */
return TRACK_NOTHING;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

112
src/lib_95HFConfigManager.h Normal file
View File

@@ -0,0 +1,112 @@
/**
******************************************************************************
* @file lib_95HFConfigManager.h
* @author MMY Application Team
* @version $Revision: 1327 $
* @date $Date: 2015-11-05 10:28:31 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of firmware functions to manage device modes.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion --------------------------------------------*/
#ifndef _LIB_95HFCONFIGMANAGER_H
#define _LIB_95HFCONFIGMANAGER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes -------------------------------------------------------------------------*/
#include "lib_iso15693pcd.h"
#include "lib_iso14443Apcd.h"
#include "lib_iso14443Bpcd.h"
#include "lib_iso18092pcd.h"
/* Manager status and erroc code ----------------------------------------------------*/
#define MANAGER_SUCCESSCODE RESULTOK
#define MANAGER_ERRORCODE_DEFAULT 0xF1
#define MANAGER_ERRORCODE_PORERROR 0xF2
#define MANAGER_ERRORCODE_COMMUNICATION_LOST 0xF3
/* Flags for PICC/PCD tracking ----------------------------------------------------------*/
#define TRACK_NOTHING 0x00
#define TRACK_NFCTYPE1 0x01 /* 0000 0001 */
#define TRACK_NFCTYPE2 0x02 /* 0000 0010 */
#define TRACK_NFCTYPE3 0x04 /* 0000 0100 */
#define TRACK_NFCTYPE4A 0x08 /* 0000 1000 */
#define TRACK_NFCTYPE4B 0x10 /* 0001 0000 */
#define TRACK_NFCTYPE5 0x20 /* 0010 0000 */
#define TRACK_ALL 0xFF /* 1111 1111 */
/* Flags for Initiator/Target tracking ------------------------------------------------------*/
#define P2P_NOTHING 0x00
#define INITIATOR_NFCA 0x01 /* 0000 0001 */
#define INITIATOR_NFCF 0x02 /* 0000 0010 */
#define TARGET_NFCA 0x04 /* 0000 0100 */
#define TARGET_NFCF 0x08 /* 0000 1000 */
#define TARGET_LLCPA 0x10 /* 0000 0100 */
#define TARGET_LLCPF 0x20 /* 0000 1000 */
#define INITIATOR_LLCPA 0x40 /* 0000 0100 */
#define INITIATOR_LLCPF 0x80 /* 0000 1000 */
#define P2P_ALL 0xFF /* 1111 1111 */
/* Flags for Proprietary P2P tracking ------------------------------------------------------*/
#define PP2P_NOTHING 0x00
#define PP2P_INITIATOR_NFCA 0x01 /* 0000 0001 */
#define PP2P_TARGET_NFCA 0x10 /* 0000 0100 */
#define PP2P_ALL 0xFF /* 1111 1111 */
/* Flags for SelectMode ----------------------------------------------------------*/
#define SELECT_NOTHING 0x00
#define SELECT_PCD 0x01 /* 0000 0001 */
#define SELECT_PICC 0x02 /* 0000 0010 */
#define SELECT_P2P 0x04 /* 0000 0100 */
#define SELECT_ALL 0xFF /* 1111 1111 */
/* structure of the manager state --------------------------------------------------*/
typedef struct {
uint8_t SelectedMode;
uint8_t PcdMode;
uint8_t PiccMode;
uint8_t P2pMode;
uint8_t Result;
uint16_t timeoutEmul;
uint16_t timeoutReadEmul;
}MANAGER_CONFIG;
//typedef enum PICCEMULATOR_SELECT_TAG_TYPE PICCEMULATOR_SELECT_TAG_TYPE;
/* public function ----------------------------------------------------------------*/
void ConfigManager_HWInit (void);
uint8_t ConfigManager_TagHunting ( uint8_t tagsToFind );
void ConfigManager_Stop(void);
#ifdef __cplusplus
}
#endif
#endif
/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/

401
src/lib_95HF_wrapper.cpp Normal file
View File

@@ -0,0 +1,401 @@
/**
******************************************************************************
* @file lib_95HF_wrapper.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief Interface for xx95HF in order to use NDEF lib
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_wrapper.h"
#include "lib_NDEF.h"
#include "lib_nfctype1pcd.h"
#include "lib_nfctype2pcd.h"
#include "lib_nfctype3pcd.h"
#include "lib_nfctype4pcd.h"
#include "lib_nfctype5pcd.h"
/* Variables for the different modes */
extern DeviceMode_t devicemode;
extern TagType_t nfc_tagtype;
bool updateFlash = false;
/* Tag type 1 */
extern uint8_t TT1Tag[];
/* Tag type 2 */
extern uint8_t TT2Tag[];
/* Tag type 3 */
extern uint8_t TT3Tag[];
extern uint8_t *TT3AttribInfo, *TT3NDEFfile;
/* Tag type 4 */
/* NDEF buffer */
extern uint8_t CardNDEFfileT4A [];
extern uint8_t CardNDEFfileT4B [];
/* CC buffer*/
extern uint8_t CardCCfile [];
/* Tag type 5 */
extern uint8_t TT5Tag[];
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/** @defgroup lib_95HF_Private_Functions
* @{
*/
/**
* @}
*/
/** @defgroup lib_95HF_Public_Functions
* @{
*/
/**
* @brief This fonction read the data stored in NDEF file at defined offset.
* @param Offset : Offset in the NDEF file.
* @param DataSize : Number of byte to read.
* @param pData : pointer on buffer to store read data.
* @retval ACTION_COMPLETED : The operation is completed.
*/
uint16_t ReadData( uint16_t Offset , uint16_t DataSize , uint8_t* pData )
{
uint16_t i;
switch( nfc_tagtype )
{
case TT1:
if( DataSize > NFCT1_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
for( i = Offset; i < (DataSize+Offset); i++ )
{
if( i == 0 ) // We need the size
{
/* 2 bytes length */
if( TT1Tag[17] == 0xFF )
{
pData[0] = TT1Tag[18];
pData[1] = TT1Tag[19];
}
/* 1 bytes length */
else
{
pData[0] = 0x00;
pData[1] = TT1Tag[17];
}
i++;
}
else // We need the NDEF message
{
/* 2 bytes length */
if( TT1Tag[17] == 0xFF )
pData[i-Offset] = TT1Tag[18+i];
/* 1 bytes length */
else
pData[i-Offset] = TT1Tag[16+i];
}
}
break;
case TT2:
if( DataSize > NFCT2_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
for( i = Offset; i < (DataSize+Offset); i++ )
{
if( i == 0 ) // We need the size
{
/* 2 bytes length */
if( TT2Tag[NFCT2_MAX_CONFIG+NFCT2_MAX_CC_SIZE+1] == 0xFF )
{
pData[0] = TT2Tag[NFCT2_MAX_CONFIG+NFCT2_MAX_CC_SIZE+2];
pData[1] = TT2Tag[NFCT2_MAX_CONFIG+NFCT2_MAX_CC_SIZE+3];
}
/* 1 bytes length */
else
{
pData[0] = 0x00;
pData[1] = TT2Tag[NFCT2_MAX_CONFIG+NFCT2_MAX_CC_SIZE+1];
}
i++;
}
else // We need the NDEF message
{
/* 2 bytes length */
if( TT2Tag[NFCT2_MAX_CONFIG+NFCT2_MAX_CC_SIZE+1] == 0xFF )
pData[i-Offset] = TT2Tag[NFCT2_MAX_CONFIG+NFCT2_MAX_CC_SIZE+2+i];
/* 1 bytes length */
else
pData[i-Offset] = TT2Tag[NFCT2_MAX_CONFIG+NFCT2_MAX_CC_SIZE+i];
}
}
break;
case TT3:
if( DataSize > NFCT3_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
for( i = Offset; i < (DataSize+Offset); i++ )
{
if( i == 0 ) // We need the size
{
pData[0] = TT3AttribInfo[12];
pData[1] = TT3AttribInfo[13];
i++;
}
else
{
pData[i-Offset] = *(TT3NDEFfile + i - 2);
}
}
break;
case TT4A:
if( DataSize > NFCT4A_MAX_NDEFMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
memcpy( pData, &CardNDEFfileT4A[Offset], DataSize );
break;
case TT4B:
if( DataSize > NFCT4B_MAX_NDEFMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
memcpy( pData, &CardNDEFfileT4B[Offset], DataSize );
break;
case TT5:
if( DataSize > NFCT5_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
for( i = Offset; i < (DataSize+Offset); i++ )
{
if( i == 0 ) // We need the size
{
/* 2 bytes length */
if( TT5Tag[5] == 0xFF )
{
pData[0] = TT5Tag[6];
pData[1] = TT5Tag[7];
}
/* 1 bytes length */
else
{
pData[0] = 0x00;
pData[1] = TT5Tag[5];
}
i++;
}
else // We need the NDEF message
{
/* 2 bytes length */
if( TT5Tag[5] == 0xFF )
pData[i-Offset] = TT5Tag[6+i];
/* 1 bytes length */
else
pData[i-Offset] = TT5Tag[4+i];
}
}
break;
default:
break;
}
return NDEF_OK;
}
/**
* @brief This fonction write data in NDEF file at defined offset.
* @param Offset : Offset in the NDEF file.
* @param DataSize : Number of byte to write.
* @param pData : pointer on buffer to copy.
* @retval ACTION_COMPLETED : The operation is completed.
*/
uint16_t WriteData( uint16_t Offset, uint32_t DataSize, uint8_t* pData )
{
uint16_t index = 0, i, sum = 0;
switch( nfc_tagtype )
{
case TT1:
if( DataSize > NFCT1_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
index = Offset + 14;
DataSize -= 2;
/* Write the NDEF TLV [0x03 length message] */
TT1Tag[index++] = 0x03;
/* Size can be stored in one byte or 3 bytes depending on the length */
if( DataSize < 255 )
{
TT1Tag[index++] = DataSize;
}
else
{
TT1Tag[index++] = 0xFF;
TT1Tag[index++] = ( DataSize&0x0000FF00 ) >> 8;
TT1Tag[index++] = DataSize & 0x000000FF;
}
memcpy( &(TT1Tag[index]), pData+2, DataSize );
/* Write the terminating TLV [0xFE] */
TT1Tag[index+DataSize] = 0xFE;
/* Update the phisical tag if needed */
if( devicemode == PCD )
return PCDNFCT1_WriteNDEF( );
break;
case TT2:
if( DataSize > NFCT2_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
index = Offset + NFCT2_MAX_CONFIG + NFCT2_MAX_CC_SIZE;
DataSize -= 2;
/* Write the NDEF TLV [0x03 length message] */
TT2Tag[index++] = 0x03;
/* Size can be stored in one byte or 3 bytes depending on the length */
if( DataSize < 255 )
{
TT2Tag[index++] = DataSize;
}
else
{
TT2Tag[index++] = 0xFF;
TT2Tag[index++] = ( DataSize&0x0000FF00 ) >> 8;
TT2Tag[index++] = DataSize & 0x000000FF;
}
memcpy( &(TT2Tag[index]), pData+2, DataSize );
/* Write the terminating TLV [0xFE] */
TT2Tag[index+DataSize] = 0xFE;
/* Update the phisical tag if needed */
if( devicemode == PCD )
return PCDNFCT2_WriteNDEF( );
else
updateFlash = true;
break;
case TT3:
if( DataSize > NFCT3_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
DataSize -= 2;
/* Write the ndef message first */
memcpy( TT3NDEFfile, pData+2, DataSize );
/* Update AttribInfo */
TT3AttribInfo[11] = ( DataSize&0x00FF0000 ) >> 16;
TT3AttribInfo[12] = ( DataSize&0x0000FF00 ) >> 8;
TT3AttribInfo[13] = DataSize & 0x000000FF;
/* Update checksum */
for( i = 0; i < 14; i++ )
sum += TT3AttribInfo[i];
TT3AttribInfo[14] = ( sum&0xFF00 ) >> 8;
TT3AttribInfo[15] = sum & 0x00FF;
/* Update the phisical tag if needed */
if( devicemode == PCD )
return PCDNFCT3_WriteNDEF( );
else
updateFlash = true;
break;
case TT4A:
if( DataSize > NFCT4A_MAX_NDEFMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
memcpy( &(CardNDEFfileT4A[Offset]), pData, DataSize );
/* Update the phisical tag if needed */
if( devicemode == PCD )
return PCDNFCT4_WriteNDEF( );
else
updateFlash = true;
break;
case TT4B:
if( DataSize > NFCT4_MAX_NDEFMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
memcpy( &(CardNDEFfileT4B[Offset]), pData, DataSize );
/* Update the phisical tag if needed */
if( devicemode == PCD )
return PCDNFCT4_WriteNDEF( );
else
updateFlash = true;
break;
case TT5:
if( DataSize > NFCT5_MAX_TAGMEMORY )
return NDEF_ERROR_MEMORY_INTERNAL;
index = 4;
DataSize -= 2;
/* Write the NDEF TLV [0x03 length message] */
TT5Tag[index++] = 0x03;
/* Size can be stored in one byte or 3 bytes depending on the length */
if( DataSize < 255 )
{
TT5Tag[index++] = DataSize;
}
else
{
TT5Tag[index++] = 0xFF;
TT5Tag[index++] = ( DataSize&0x0000FF00 ) >> 8;
TT5Tag[index++] = DataSize & 0x000000FF;
}
memcpy( &(TT5Tag[index]), pData + 2, DataSize );
/* Write the terminating TLV [0xFE] */
TT5Tag[index+DataSize] = 0xFE;
/* Update the phisical tag if needed */
if( devicemode == PCD )
return PCDNFCT5_WriteNDEF( );
break;
default:
break;
}
return NDEF_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

613
src/lib_NDEF.cpp Normal file
View File

@@ -0,0 +1,613 @@
/**
******************************************************************************
* @file lib_NDEF.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage NDEF file, to parse and identify them.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/** @defgroup libNDEF_Private_Functions
* @{
*/
static uint16_t NDEF_IsNDEFPresent( void );
static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct );
static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct );
static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct );
static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct );
static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct );
static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct );
static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload );
uint8_t NDEF_Buffer [NDEF_MAX_SIZE];
/* In case of smart Poster composed with different record, 2 records supported so far */
sRecordInfo_t SPRecordStruct1, SPRecordStruct2;
sRecordInfo_t *SPRecordStructAdd[SP_MAX_RECORD] = { &SPRecordStruct1, &SPRecordStruct2 };
/**
* @brief This function check that the tag contain a NDEF message.
* @retval NDEF_OK : There is a NDEF file stored in tag.
* @retval NDEF_ERROR : No NDEF in the tag.
*/
static uint16_t NDEF_IsNDEFPresent( void )
{
uint16_t FileSize;
uint8_t uNDEFHeader [0x2];
/* Check NDEF existence */
ReadData( NDEF_SIZE_OFFSET, 2, uNDEFHeader );
FileSize = (uint16_t)( (uNDEFHeader[0x00]<<8) | uNDEFHeader[0x01] );
if( FileSize != 0 )
return NDEF_OK;
else
return NDEF_ERROR;
}
/**
* @brief This function identify the type of record.
* @param pRecordStruct : pointer on the record structure to fill.
* @param pPayload : pointer on the payload.
* @retval Status : Status of the operation.
*/
static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload )
{
uint16_t status = NDEF_ERROR;
uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte;
/* Is ID length field present */
if( (*pPayload) & IL_Mask )
{
IDLengthField = ID_LENGTH_FIELD;
}
else
{
IDLengthField = 0;
}
/* it's a SR */
if( (*pPayload) & SR_Mask )
{
TypeNbByte = pPayload[1];
PayloadLengthField = 1;
if( IDLengthField == ID_LENGTH_FIELD )
IDNbByte = pPayload[3];
else
IDNbByte = 0;
}
else
{
TypeNbByte = pPayload[1];
PayloadLengthField = 4;
if( IDLengthField == ID_LENGTH_FIELD )
IDNbByte = pPayload[6];
else
IDNbByte = 0;
}
SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte;
/* it's a SR */
if( pPayload[0] & SR_Mask )
{
pRecordStruct->RecordFlags = pPayload[0];
pRecordStruct->TypeLength = TypeNbByte;
pRecordStruct->PayloadLength3 = 0;
pRecordStruct->PayloadLength2 = 0;
pRecordStruct->PayloadLength1 = 0;
pRecordStruct->PayloadLength0 = pPayload[2];
pRecordStruct->IDLength = IDNbByte;
memcpy( pRecordStruct->Type, &pPayload[3+IDNbByte], TypeNbByte );
memcpy( pRecordStruct->ID, &pPayload[3+IDNbByte+TypeNbByte], IDNbByte );
pRecordStruct->PayloadOffset = SizeOfRecordHeader;
}
else
{
pRecordStruct->RecordFlags = pPayload[0];
pRecordStruct->TypeLength = TypeNbByte;
pRecordStruct->PayloadLength3 = pPayload[2];
pRecordStruct->PayloadLength2 = pPayload[3];
pRecordStruct->PayloadLength1 = pPayload[4];
pRecordStruct->PayloadLength0 = pPayload[5];
pRecordStruct->IDLength = IDNbByte;
memcpy( pRecordStruct->Type, &pPayload[6+IDNbByte], TypeNbByte );
memcpy( pRecordStruct->ID, &pPayload[6+IDNbByte+TypeNbByte], IDNbByte );
pRecordStruct->PayloadOffset = SizeOfRecordHeader;
}
pRecordStruct->PayloadBufferAdd = (uint32_t)( pPayload + SizeOfRecordHeader );
status = NDEF_ParseRecordHeader( pRecordStruct );
return status;
}
/**
* @brief This function parse the record header and dispatch regarding TNF value.
* @param pRecordStruct : pointer on the record structure to fill.
* @retval NDEF_OK : record identified and structure filled.
* @retval NDEF_ERROR : Not supported.
*/
static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct )
{
uint16_t status = NDEF_OK;
switch( (pRecordStruct->RecordFlags & TNF_Mask) )
{
case TNF_WellKnown:
NDEF_ParseWellKnownType( pRecordStruct );
break;
case TNF_MediaType:
NDEF_ParseMediaType( pRecordStruct );
break;
case TNF_NFCForumExternal:
NDEF_ParseForumExternalType( pRecordStruct);
break;
default:
/* currently not supported or unknown*/
pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
status = NDEF_ERROR;
}
return status;
}
/**
* @brief This function parse the Well Known type record.
* @param pRecordStruct : pointer on the record structure to fill.
*/
static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct )
{
uint8_t* pPayload;
pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd );
if( !memcmp( &(pRecordStruct->Type), SMART_POSTER_TYPE_STRING, pRecordStruct->TypeLength ) )
{
/* special case where we have to parse others records */
pRecordStruct->NDEF_Type = SMARTPOSTER_TYPE;
NDEF_ParseSP( pRecordStruct );
}
else if( !memcmp( &(pRecordStruct->Type), URI_TYPE_STRING, pRecordStruct->TypeLength ) )
{
/* it's an URI Type check if it's an URL or SMS or ... */
/* check identifier */
if( *pPayload == URI_ID_0x00 )
{
NDEF_ParseURI( pRecordStruct );
}
else if( (*pPayload > URI_ID_0x00) && (*pPayload < URI_RFU) )
{
/* email special case */
if( *pPayload == (uint8_t) URI_ID_0x06 )
{
pRecordStruct->NDEF_Type = URI_EMAIL_TYPE;
}
else
{
pRecordStruct->NDEF_Type = WELL_KNOWN_ABRIDGED_URI_TYPE;
}
}
else
{
pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
}
}
else if( !memcmp( &(pRecordStruct->Type), TEXT_TYPE_STRING, pRecordStruct->TypeLength ) )
{
pRecordStruct->NDEF_Type = TEXT_TYPE;
}
else
pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
}
/**
* @brief This function parse the Media type record.
* @param pRecordStruct : pointer on the record structure to fill.
*/
static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct )
{
if( !memcmp( &(pRecordStruct->Type), VCARD_TYPE_STRING, pRecordStruct->TypeLength ) )
pRecordStruct->NDEF_Type = VCARD_TYPE;
else if( !memcmp( &(pRecordStruct->Type), XVCARD_TYPE_STRING, pRecordStruct->TypeLength ) )
pRecordStruct->NDEF_Type = VCARD_TYPE;
else if( !memcmp( &(pRecordStruct->Type), XVCARD2_TYPE_STRING, pRecordStruct->TypeLength ) )
pRecordStruct->NDEF_Type = VCARD_TYPE;
else
pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
}
/**
* @brief This function parse the Forum External type record.
* @param pRecordStruct : pointer on the record structure to fill.
*/
static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct )
{
if( !memcmp( &(pRecordStruct->Type), M24SR_DISCOVERY_APP_STRING, pRecordStruct->TypeLength ) )
pRecordStruct->NDEF_Type = M24SR_DISCOVERY_APP_TYPE;
else
pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
}
/**
* @brief This function parse the URI type record.
* @param pRecordStruct : pointer on the record structure to fill.
*/
static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct )
{
uint8_t* pPayload;
pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd );
pPayload++; /* to skip URI identifier first URI payload byte */
if( !memcmp( pPayload, SMS_TYPE_STRING, strlen(SMS_TYPE_STRING) ) )
{
pRecordStruct->NDEF_Type = URI_SMS_TYPE;
}
else if( !memcmp( pPayload, GEO_TYPE_STRING, strlen(GEO_TYPE_STRING) ) )
{
pRecordStruct->NDEF_Type = URI_GEO_TYPE;
}
else
pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
}
/**
* @brief This function parse the Smart Poster.
* @param pRecordStruct : pointer on the record structure to fill.
*/
static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct )
{
uint8_t* pPayload;
uint32_t PayloadSize = 0;
uint32_t SPPayloadSize = 0;
uint32_t OffsetInSPPayload = 0;
uint32_t RecordPosition = 0;
sRecordInfo_t *pSPRecordStruct;
/* initialize variable with size of the payload and poiter on data */
PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pRecordStruct->PayloadLength1) << 8) | pRecordStruct->PayloadLength0;
pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd );
pSPRecordStruct = SPRecordStructAdd[0];
/* Initailize the number of record find in the SP payload */
pRecordStruct->NbOfRecordInSPPayload = 0;
do
{
pSPRecordStruct = SPRecordStructAdd[RecordPosition];
/* identify the record in the SP payload */
if( NDEF_IdentifySPRecord( pSPRecordStruct, pPayload ) == NDEF_OK )
{
/* store add of structure that will contain the other record information */
pRecordStruct->NbOfRecordInSPPayload++;
pRecordStruct->SPRecordStructAdd[RecordPosition] = pSPRecordStruct;
/* After SPRecord + First Record check if we are at the end of NDEF file */
SPPayloadSize = ((uint32_t)(pSPRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pSPRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pSPRecordStruct->PayloadLength1) << 8) | pSPRecordStruct->PayloadLength0;
OffsetInSPPayload += pSPRecordStruct->PayloadOffset + SPPayloadSize;
pPayload += OffsetInSPPayload;
}
else /* Recommended Action Record for example */
{
SPPayloadSize = 0;
}
RecordPosition++;
}
while( (OffsetInSPPayload < PayloadSize) && RecordPosition<SP_MAX_RECORD); /* there is another record */
}
/**
* @}
*/
/** @defgroup libNDEF_Public_Functions
* @{
*/
/**
* @brief This function identify the NDEF message stored in tag.
* @param pRecordStruct : Structure to fill with record information.
* @param pNDEF : pointer on the NDEF message data.
* @retval NDEF_OK : record struct filled.
* @retval NDEF_ERROR : record struct not updated.
*/
uint16_t NDEF_IdentifyNDEF( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF )
{
uint16_t status = NDEF_ERROR;
uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte;
uint32_t PayloadSize;
/* check NDEF present */
if( NDEF_IsNDEFPresent() != NDEF_OK )
{
return NDEF_ERROR;
}
/* Analyse record layout */
ReadData( FIRST_RECORD_OFFSET, 1, pNDEF );
/* Is ID length field present */
if( (*pNDEF) & IL_Mask )
{
IDLengthField = ID_LENGTH_FIELD;
}
else
{
IDLengthField = 0;
}
/* it's a SR */
if( (*pNDEF) & SR_Mask )
{
/* Analyse short record layout */
ReadData( FIRST_RECORD_OFFSET, 4, pNDEF );
TypeNbByte = pNDEF[1];
PayloadLengthField = 1;
if( IDLengthField == ID_LENGTH_FIELD )
IDNbByte = pNDEF[3];
else
IDNbByte = 0;
}
else
{
/* Analyse normal record layout */
ReadData( FIRST_RECORD_OFFSET, 7, pNDEF );
TypeNbByte = pNDEF[1];
PayloadLengthField = 4;
if( IDLengthField == ID_LENGTH_FIELD )
IDNbByte = pNDEF[6];
else
IDNbByte = 0;
}
SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte;
/* Read record header */
ReadData( FIRST_RECORD_OFFSET, SizeOfRecordHeader, pNDEF );
/* it's a SR */
if( pNDEF[0] & SR_Mask )
{
pRecordStruct->RecordFlags = pNDEF[0];
pRecordStruct->TypeLength = TypeNbByte;
pRecordStruct->PayloadLength3 = 0;
pRecordStruct->PayloadLength2 = 0;
pRecordStruct->PayloadLength1 = 0;
pRecordStruct->PayloadLength0 = pNDEF[2];
pRecordStruct->IDLength = IDNbByte;
memcpy( pRecordStruct->Type, &pNDEF[3+IDNbByte], TypeNbByte );
memcpy( pRecordStruct->ID, &pNDEF[3+IDNbByte+TypeNbByte], IDNbByte );
pRecordStruct->PayloadOffset = SizeOfRecordHeader;
}
else
{
pRecordStruct->RecordFlags = pNDEF[0];
pRecordStruct->TypeLength = TypeNbByte;
pRecordStruct->PayloadLength3 = pNDEF[2];
pRecordStruct->PayloadLength2 = pNDEF[3];
pRecordStruct->PayloadLength1 = pNDEF[4];
pRecordStruct->PayloadLength0 = pNDEF[5];
pRecordStruct->IDLength = IDNbByte;
memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte );
memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte );
pRecordStruct->PayloadOffset = SizeOfRecordHeader;
}
PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pRecordStruct->PayloadLength1) << 8) | pRecordStruct->PayloadLength0;
/* read Payload */
status = ReadData( (uint16_t)((FIRST_RECORD_OFFSET) + pRecordStruct->PayloadOffset) , PayloadSize , pNDEF );
if( status != NDEF_OK )
return NDEF_ERROR;
else
pRecordStruct->PayloadBufferAdd = (uint32_t)(pNDEF);
NDEF_ParseRecordHeader( pRecordStruct );
return NDEF_OK;
}
/**
* @brief This function read the NDEF content of the TAG.
* @param pNDEF : pointer on the buffer to store NDEF data.
* @retval NDEF_OK : NDEF file data retrieve and store in the buffer.
* @retval NDEF_ERROR : not able to read NDEF from tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read.
*/
uint16_t NDEF_ReadNDEF( uint8_t* pNDEF )
{
uint16_t status = NDEF_ERROR;
uint16_t NDEF_Size = 0;
status = ReadData( 0, 2, pNDEF );
if( status == NDEF_OK )
{
NDEF_Size = (uint16_t)(*pNDEF << 8);
NDEF_Size = NDEF_Size | (uint16_t)(*++pNDEF );
status = ReadData( 0, NDEF_Size + 2, --pNDEF );
}
return status;
}
/**
* @brief This function write the NDEF in the TAG.
* @param pNDEF : pointer on the buffer containing the NDEF data.
* @retval NDEF_OK : NDEF file data written in the tag.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteNDEF( uint8_t *pNDEF )
{
uint16_t status = NDEF_ERROR;
uint16_t NDEF_Size = 0;
NDEF_Size = (uint16_t)(*pNDEF << 8);
NDEF_Size = NDEF_Size | (uint16_t)(*++pNDEF );
status = WriteData( 0, NDEF_Size + 2, --pNDEF );
return status;
}
/**
* @brief This function identify the NDEF message stored in tag.
* @param pRecordStruct : Structure to fill with record information.
* @param pNDEF : pointer on the NDEF message data.
* @retval NDEF_OK : record struct filled.
* @retval NDEF_ERROR : record struct not updated.
*/
uint16_t NDEF_IdentifyBuffer( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF )
{
uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte;
/* Is ID length field present */
if( (*pNDEF) & IL_Mask )
{
IDLengthField = ID_LENGTH_FIELD;
}
else
{
IDLengthField = 0;
}
/* it's a SR */
if( (*pNDEF) & SR_Mask )
{
/* Analyse short record layout */
TypeNbByte = pNDEF[1];
PayloadLengthField = 1;
if( IDLengthField == ID_LENGTH_FIELD )
IDNbByte = pNDEF[3];
else
IDNbByte = 0;
}
else
{
/* Analyse normal record layout */
TypeNbByte = pNDEF[1];
PayloadLengthField = 4;
if( IDLengthField == ID_LENGTH_FIELD )
IDNbByte = pNDEF[6];
else
IDNbByte = 0;
}
SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte;
/* it's a SR */
if( pNDEF[0] & SR_Mask )
{
pRecordStruct->RecordFlags = pNDEF[0];
pRecordStruct->TypeLength = TypeNbByte;
pRecordStruct->PayloadLength3 = 0;
pRecordStruct->PayloadLength2 = 0;
pRecordStruct->PayloadLength1 = 0;
pRecordStruct->PayloadLength0 = pNDEF[2];
pRecordStruct->IDLength = IDNbByte;
memcpy( pRecordStruct->Type, &pNDEF[3+IDNbByte], TypeNbByte );
memcpy( pRecordStruct->ID, &pNDEF[3+IDNbByte+TypeNbByte], IDNbByte );
pRecordStruct->PayloadOffset = SizeOfRecordHeader;
}
else
{
pRecordStruct->RecordFlags = pNDEF[0];
pRecordStruct->TypeLength = TypeNbByte;
pRecordStruct->PayloadLength3 = pNDEF[2];
pRecordStruct->PayloadLength2 = pNDEF[3];
pRecordStruct->PayloadLength1 = pNDEF[4];
pRecordStruct->PayloadLength0 = pNDEF[5];
pRecordStruct->IDLength = IDNbByte;
memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte );
memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte );
pRecordStruct->PayloadOffset = SizeOfRecordHeader;
}
pRecordStruct->PayloadBufferAdd = (uint32_t)(&pNDEF[pRecordStruct->PayloadOffset]);
NDEF_ParseRecordHeader( pRecordStruct );
return NDEF_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

259
src/lib_NDEF.h Normal file
View File

@@ -0,0 +1,259 @@
/**
******************************************************************************
* @file lib_NDEF.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_H
#define __LIB_NDEF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* include file which match the HW configuration */
#include "common.h"
#include "lib_wrapper.h"
#define NDEF_ACTION_COMPLETED 0x9000
#ifndef errorchk
#define errorchk(fCall) if (status = (fCall), status != NDEF_ACTION_COMPLETED) \
{goto Error;} else
#endif
/* Error codes for Higher level */
#define NDEF_OK RESULTOK
#define NDEF_ERROR ERRORCODE_GENERIC
#define NDEF_ERROR_MEMORY_TAG 2
#define NDEF_ERROR_MEMORY_INTERNAL 3
#define NDEF_ERROR_LOCKED 4
#define NDEF_ERROR_NOT_FORMATED 5
#define NDEF_MAX_SIZE NFC_DEVICE_MAX_NDEFMEMORY
#define NDEF_SIZE_OFFSET 0
#define FIRST_RECORD_OFFSET 2
#define RECORD_FLAG_FIELD 1
#define TYPE_LENGTH_FIELD 1
#define ID_LENGTH_FIELD 1
#define MB_Mask ((uint8_t)(0x80))
#define ME_Mask ((uint8_t)(0x40))
#define CF_Mask ((uint8_t)(0x20))
#define SR_Mask ((uint8_t)(0x10))
#define IL_Mask ((uint8_t)(0x08))
#define TNF_Mask ((uint8_t)(0x07))
#define TNF_Empty 0x00
#define TNF_WellKnown 0x01
#define TNF_MediaType 0x02
#define TNF_AbsoluteURI 0x03
#define TNF_NFCForumExternal 0x04
#define TNF_Unknown 0x05
#define TNF_Unchanged 0x06
#define TNF_Reserved 0x07
#define SP_MAX_RECORD 2
#define AAR_TYPE_STRING "android.com:pkg"
#define AAR_TYPE_STRING_LENGTH 15
#define M24SR_DISCOVERY_APP_STRING "st.com:m24sr_discovery_democtrl"
#define M24SR_DISCOVERY_APP_STRING_LENGTH 31
#define VCARD_TYPE_STRING "text/vcard"
#define VCARD_TYPE_STRING_LENGTH 10
#define XVCARD_TYPE_STRING "text/x-vCard"
#define XVCARD_TYPE_STRING_LENGTH 12
#define XVCARD2_TYPE_STRING "text/x-vcard"
#define XVCARD2_TYPE_STRING_LENGTH 12
#define SMART_POSTER_TYPE_STRING "Sp"
#define SMART_POSTER_TYPE_STRING_LENGTH 2
#define URI_TYPE_STRING "U"
#define URI_TYPE_STRING_LENGTH 1
#define SMS_TYPE_STRING "sms:"
#define SMS_TYPE_STRING_LENGTH 4
#define GEO_TYPE_STRING "geo:"
#define GEO_TYPE_STRING_LENGTH 4
#define URI_LATITUDE_END ","
#define URI_LATITUDE_END_LENGTH 1
#define EMAIL_TYPE_STRING "mailto:"
#define EMAIL_TYPE_STRING_LENGTH 7
#define URI_FIRST_DATA_END "?"
#define URI_FIRST_DATA_END_LENGTH 1
#define SUBJECT_BEGIN_STRING "subject="
#define SUBJECT_BEGIN_STRING_LENGTH 8
#define MESSAGE_BEGIN_STRING "body="
#define MESSAGE_BEGIN_STRING_LENGTH 5
#define URI_SECOND_DATA_END "&"
#define URI_SECOND_DATA_END_LENGTH 1
#define TEXT_TYPE_STRING "T"
#define TEXT_TYPE_STRING_LENGTH 1
#define ISO_ENGLISH_CODE_STRING "en"
#define ISO_ENGLISH_CODE_STRING_LENGTH 2
#define URI_ID_0x00 0x00
#define URI_ID_0x01 0x01
#define URI_ID_0x02 0x02
#define URI_ID_0x03 0x03
#define URI_ID_0x04 0x04
#define URI_ID_0x05 0x05
#define URI_ID_0x06 0x06
#define URI_ID_0x07 0x07
#define URI_ID_0x08 0x08
#define URI_ID_0x09 0x09
#define URI_ID_0x0A 0x0A
#define URI_ID_0x0B 0x0B
#define URI_ID_0x0C 0x0C
#define URI_ID_0x0D 0x0D
#define URI_ID_0x0E 0x0E
#define URI_ID_0x0F 0x0F
#define URI_ID_0x10 0x10
#define URI_ID_0x11 0x11
#define URI_ID_0x12 0x12
#define URI_ID_0x13 0x13
#define URI_ID_0x14 0x14
#define URI_ID_0x15 0x15
#define URI_ID_0x16 0x16
#define URI_ID_0x17 0x17
#define URI_ID_0x18 0x18
#define URI_ID_0x19 0x19
#define URI_ID_0x1A 0x1A
#define URI_ID_0x1B 0x1B
#define URI_ID_0x1C 0x1C
#define URI_ID_0x1D 0x1D
#define URI_ID_0x1E 0x1E
#define URI_ID_0x1F 0x1F
#define URI_ID_0x20 0x20
#define URI_ID_0x21 0x21
#define URI_ID_0x22 0x22
#define URI_ID_0x23 0x23
#define URI_RFU 0x24
#define URI_ID_0x01_STRING "http://www.\0"
#define URI_ID_0x02_STRING "https://www.\0"
#define URI_ID_0x03_STRING "http://\0"
#define URI_ID_0x04_STRING "https://\0"
#define URI_ID_0x05_STRING "tel:\0"
#define URI_ID_0x06_STRING "mailto:\0"
#define URI_ID_0x07_STRING "ftp://anonymous:anonymous@\0"
#define URI_ID_0x08_STRING "ftp://ftp.\0"
#define URI_ID_0x09_STRING "ftps://\0"
#define URI_ID_0x0A_STRING "sftp://\0"
#define URI_ID_0x0B_STRING "smb://\0"
#define URI_ID_0x0C_STRING "nfs://\0"
#define URI_ID_0x0D_STRING "ftp://\0"
#define URI_ID_0x0E_STRING "dav://\0"
#define URI_ID_0x0F_STRING "news:\0"
#define URI_ID_0x10_STRING "telnet://\0"
#define URI_ID_0x11_STRING "imap:\0"
#define URI_ID_0x12_STRING "rtsp://\0"
#define URI_ID_0x13_STRING "urn:\0"
#define URI_ID_0x14_STRING "pop:\0"
#define URI_ID_0x15_STRING "sip:\0"
#define URI_ID_0x16_STRING "sips:\0"
#define URI_ID_0x17_STRING "tftp:\0"
#define URI_ID_0x18_STRING "btspp://\0"
#define URI_ID_0x19_STRING "btl2cap://\0"
#define URI_ID_0x1A_STRING "btgoep://\0"
#define URI_ID_0x1B_STRING "tcpobex://\0"
#define URI_ID_0x1C_STRING "irdaobex://\0"
#define URI_ID_0x1D_STRING "file://\0"
#define URI_ID_0x1E_STRING "urn:epc:id:\0"
#define URI_ID_0x1F_STRING "urn:epc:tag\0"
#define URI_ID_0x20_STRING "urn:epc:pat:\0"
#define URI_ID_0x21_STRING "urn:epc:raw:\0"
#define URI_ID_0x22_STRING "urn:epc:\0"
#define URI_ID_0x23_STRING "urn:nfc:\0"
typedef enum
{
UNKNOWN_TYPE = 0,
VCARD_TYPE,
WELL_KNOWN_ABRIDGED_URI_TYPE,
URI_SMS_TYPE,
URI_GEO_TYPE,
URI_EMAIL_TYPE,
SMARTPOSTER_TYPE,
URL_TYPE,
TEXT_TYPE,
BT_TYPE,
/* list of "external type" known by this demo, other external type will be addressed as UNKNWON_TYPE */
M24SR_DISCOVERY_APP_TYPE
} NDEF_TypeDef;
typedef struct sRecordInfo sRecordInfo_t;
struct sRecordInfo
{
uint8_t RecordFlags;
uint8_t TypeLength;
uint8_t PayloadLength3;
uint8_t PayloadLength2;
uint8_t PayloadLength1;
uint8_t PayloadLength0;
uint8_t IDLength;
uint8_t Type[0xFF];
uint8_t ID[0xFF];
uint16_t PayloadOffset;
uint32_t PayloadBufferAdd; /* add where payload content has been stored */
NDEF_TypeDef NDEF_Type; /* to store identification ID for application */
sRecordInfo_t *SPRecordStructAdd[SP_MAX_RECORD]; /*in case of smart poster array to store add of other sRecordInfo struct */
uint8_t NbOfRecordInSPPayload;
};
uint16_t NDEF_IdentifyNDEF( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF );
uint16_t NDEF_IdentifyBuffer( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF );
uint16_t NDEF_ReadNDEF( uint8_t *pNDEF );
uint16_t NDEF_WriteNDEF( uint8_t *pNDEF );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

188
src/lib_NDEF_AAR.cpp Normal file
View File

@@ -0,0 +1,188 @@
/**
******************************************************************************
* @file lib_NDEF_AAR.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to add AAR to NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_AAR.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/** @defgroup libAAR_Private_Functions
* @{
*/
/**
* @}
*/
/** @defgroup libAAR_Public_Functions
* @{
* @brief This file is used to manage AAR (stored or loaded in tag)
*/
/**
* @brief This function add AAR (Android Application Record) in the tag.
* @param pAARStruct : pointer on structure that contain AAR information.
* @retval NDEF_OK : AAR added.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_AddAAR( sAARInfo *pAARStruct )
{
uint16_t status = NDEF_ERROR;
uint16_t DataSize = 0;
uint16_t Offset = 0;
uint32_t AAROffset = 0;
uint16_t NDEF_Size = 0;
uint8_t RecordFlag = 0;
uint8_t AARRecordFlag = 0;
/* AAR: External Type Record Header */
/************************************/
/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */
/*----------------------------------*/
/* MB ME CF SR IL TNF */ /* <---- IL=0, CF=0 and SR=1 TNF=4 NFC Forum external type*/
/*----------------------------------*/
/* TYPE LENGTH */
/*----------------------------------*/
/* PAYLOAD LENGTH 3 */ /* <---- Not Used */
/*----------------------------------*/
/* PAYLOAD LENGTH 2 */ /* <---- Not Used */
/*----------------------------------*/
/* PAYLOAD LENGTH 1 */ /* <---- Not Used */
/*----------------------------------*/
/* PAYLOAD LENGTH 0 */
/*----------------------------------*/
/* ID LENGTH */ /* <---- Not Used */
/*----------------------------------*/
/* TYPE */ /* android.com:pkg */
/*----------------------------------*/
/* ID */ /* <---- Not Used */
/************************************/
/* Do we have to add AAR to an existing NDEF message */
/* retrieve current NDEF size and current record flag*/
status = ReadData( 0, 3, NDEF_Buffer );
if( status == NDEF_OK )
{
NDEF_Size = (uint16_t)(NDEF_Buffer[0] << 8);
NDEF_Size = NDEF_Size | (uint16_t)(NDEF_Buffer[1]);
RecordFlag = NDEF_Buffer[2];
}
if( NDEF_Size != 0 )
{
AAROffset = NDEF_Size + 2;
RecordFlag &= 0xBF; /* remove ME flag on NDEF */
AARRecordFlag = 0x54; /* don't put MB flag */
}
else
{
AAROffset = 2;
AARRecordFlag = 0xD4; /* put MB and ME flag */
}
/* fill AAR record header */
Offset = 0;
NDEF_Buffer[Offset++] = AARRecordFlag; /* Record Flag */
NDEF_Buffer[Offset++] = AAR_TYPE_STRING_LENGTH;
NDEF_Buffer[Offset++] = 0x00; /* Will be filled at the end when payload size is known */
memcpy( &NDEF_Buffer[Offset], AAR_TYPE_STRING, AAR_TYPE_STRING_LENGTH );
/* fill AAR payload */
memcpy( &NDEF_Buffer[Offset + AAR_TYPE_STRING_LENGTH], pAARStruct->PakageName, strlen(pAARStruct->PakageName) );
NDEF_Buffer[2] = strlen( pAARStruct->PakageName );
DataSize = Offset + AAR_TYPE_STRING_LENGTH + strlen( pAARStruct->PakageName );
/* Write NDEF */
status = WriteData( AAROffset, DataSize, NDEF_Buffer );
/* Write NDEF size to complete*/
if( status == NDEF_OK )
{
DataSize = NDEF_Size + DataSize; /* Must add to the NDEF size the size of the AAR record*/
NDEF_Buffer[0] = (DataSize & 0xFF00) >> 8;
NDEF_Buffer[1] = DataSize & 0x00FF;
if( NDEF_Size != 0 )
{
NDEF_Buffer[2] = RecordFlag;
status = WriteData( 0x00, 3, NDEF_Buffer );
}
else
status = WriteData( 0x00, 2, NDEF_Buffer );
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

57
src/lib_NDEF_AAR.h Normal file
View File

@@ -0,0 +1,57 @@
/**
******************************************************************************
* @file lib_NDEF_AAR.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage AAR.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_AAR_H
#define __LIB_NDEF_AAR_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
typedef struct
{
char PakageName[80];
}sAARInfo;
/* Struct defined in lib_NDEF.h */
typedef struct sRecordInfo sRecordInfo_AAR;
uint16_t NDEF_AddAAR( sAARInfo *pAARStruct );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_AAR_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

413
src/lib_NDEF_Email.cpp Normal file
View File

@@ -0,0 +1,413 @@
/**
******************************************************************************
* @file lib_NDEF_Email.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage NDEF file that represent Email.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_Email.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/** @defgroup libEmail_Private_Functions
* @{
*/
static void NDEF_FillEmailStruct( uint8_t* pPayload, uint32_t PayloadSize, sEmailInfo *pEmailStruct );
static void NDEF_ReadURI_Email( sRecordInfo_email *pRecordStruct, sEmailInfo *pEmailStruct );
/**
* @brief This function fill Email structure with information of NDEF message
* @param pPayload : pointer on the payload data of the NDEF message
* @param PayloadSize : number of data in the payload
* @param pEmailStruct : pointer on the structure to fill
* @retval NONE
*/
static void NDEF_FillEmailStruct( uint8_t* pPayload, uint32_t PayloadSize, sEmailInfo *pEmailStruct )
{
uint8_t* pLastByteAdd, *pLook4Word, *pEndString;
uint32_t SizeOfKeyWord = 0;
pEndString = 0;
/* First character force to NULL in case not matching found */
*pEmailStruct->EmailAdd = 0;
*pEmailStruct->Subject = 0;
*pEmailStruct->Message = 0;
/* Interesting information are stored before picture if any */
/* Moreover picture is not used in this demonstration SW */
pLastByteAdd = (uint8_t*)(pPayload + PayloadSize);
/* first byte should be the "mailto:" well know URI type, skip it */
pLook4Word = ++pPayload;
/* Retrieve email add */
if( pLook4Word != pLastByteAdd )
{
pEndString = pLook4Word;
while( memcmp( pEndString, URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ) && (pEndString < pLastByteAdd) )
{
pEndString++;
}
if( ( !memcmp( pEndString, URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ) ) || (pEndString == pLastByteAdd) )
{
memcpy( pEmailStruct->EmailAdd, pLook4Word, pEndString-pLook4Word);
/* add end of string character */
pEmailStruct->EmailAdd[pEndString-pLook4Word] = 0;
}
}
pEndString += URI_FIRST_DATA_END_LENGTH;
pLook4Word = pEndString;
/* check if e-mail subject is present */
if( !memcmp( pLook4Word, SUBJECT_BEGIN_STRING, SUBJECT_BEGIN_STRING_LENGTH ) )
{
SizeOfKeyWord = SUBJECT_BEGIN_STRING_LENGTH;
/* Retrieve subject */
if( pLook4Word != pLastByteAdd )
{
pLook4Word += SizeOfKeyWord;
pEndString = pLook4Word;
while( memcmp( pEndString, URI_SECOND_DATA_END, URI_SECOND_DATA_END_LENGTH ) && (pEndString < pLastByteAdd) )
{
pEndString++;
}
if( ( !memcmp( pEndString, URI_SECOND_DATA_END, URI_SECOND_DATA_END_LENGTH ) ) || (pEndString == pLastByteAdd) )
{
memcpy( pEmailStruct->Subject, pLook4Word, pEndString-pLook4Word );
/* add end of string character */
pEmailStruct->Subject[pEndString-pLook4Word] = 0;
}
pEndString += URI_SECOND_DATA_END_LENGTH;
}
}
pLook4Word = pEndString;
/* check if e-mail message is present */
if( !memcmp( pLook4Word, MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH ) )
{
pEndString += MESSAGE_BEGIN_STRING_LENGTH;
/* Retrieve message */
memcpy( pEmailStruct->Message, pEndString, PayloadSize - (pEndString - pPayload + 1) );
/* add end of string character */
pEmailStruct->Message[PayloadSize-(pEndString-pPayload+1)] = 0;
}
}
/**
* @brief This function read the Email and store data in a structure.
* @param pRecordStruct : Pointer on the record structure.
* @param pEmailStruct : pointer on the structure to fill.
*/
static void NDEF_ReadURI_Email( sRecordInfo_email *pRecordStruct, sEmailInfo *pEmailStruct )
{
uint8_t* pPayload;
uint32_t PayloadSize;
PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pRecordStruct->PayloadLength1) << 8) | pRecordStruct->PayloadLength0;
/* Read record header */
pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd);
if( pRecordStruct->NDEF_Type == URI_EMAIL_TYPE )
NDEF_FillEmailStruct( pPayload , PayloadSize, pEmailStruct );
}
/**
* @}
*/
/** @defgroup libEmail_Public_Functions
* @{
* @brief This file is used to manage Email (stored or loaded in tag)
*/
/**
* @brief This function read NDEF and retrieve Eamil information if any.
* @param pRecordStruct : Pointer on the record structure.
* @param pEmailStruct : pointer on the structure to fill .
* @retval NDEF_OK : Email information from NDEF have been retrieved.
* @retval NDEF_ERROR : not able to read NDEF in tag.
*/
uint16_t NDEF_ReadEmail( sRecordInfo_email *pRecordStruct, sEmailInfo *pEmailStruct )
{
uint16_t status = NDEF_ERROR;
sRecordInfo_email *pSPRecordStruct;
uint32_t PayloadSize, RecordPosition;
uint8_t* pData;
if( pRecordStruct->NDEF_Type == URI_EMAIL_TYPE )
{
NDEF_ReadURI_Email( pRecordStruct, pEmailStruct );
status = NDEF_OK;
}
else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE )
{
for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ )
{
pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition];
if( pSPRecordStruct->NDEF_Type == URI_EMAIL_TYPE )
{
NDEF_ReadURI_Email( pSPRecordStruct, pEmailStruct );
status = NDEF_OK;
}
if( pSPRecordStruct->NDEF_Type == TEXT_TYPE )
{
PayloadSize = ((uint32_t)(pSPRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pSPRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pSPRecordStruct->PayloadLength1) << 8) | pSPRecordStruct->PayloadLength0;
/* The instruction content the UTF-8 language code that is not used here */
pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd;
PayloadSize -= *pData + 1; /* remove not usefull data */
pData += *pData + 1;
memcpy( pEmailStruct->Information, pData, PayloadSize );
}
}
}
return status;
}
/**
* @brief This function write the NDEF file with the Email data given in the structure.
* @param pEmailStruct : pointer on structure that contain the Email information.
* @retval NDEF_OK : the function is successful.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteEmail( sEmailInfo *pEmailStruct )
{
uint16_t status = NDEF_ERROR, Offset = 0;
NDEF_PrepareEmailMessage( pEmailStruct, &NDEF_Buffer[FIRST_RECORD_OFFSET], &Offset );
/* Write NDEF */
NDEF_Buffer[0] = (Offset & 0xFF00) >> 8;
NDEF_Buffer[1] = (Offset & 0x00FF);
status = WriteData( 0x00, Offset + FIRST_RECORD_OFFSET, NDEF_Buffer );
return status;
}
/**
* @brief This function write the NDEF file with the Email data given in the structure.
* @param pEmailStruct : pointer on structure that contain the Email information.
* @param pNDEFMessage : pointer on the NDEF message.
* @param size : to store the size of the NDEF message generated.
*/
void NDEF_PrepareEmailMessage( sEmailInfo *pEmailStruct, uint8_t *pNDEFMessage, uint16_t *size )
{
uint16_t Offset = 0;
uint32_t emailSize = 0;
uint32_t infoSize = 0;
uint32_t totalSize = 0;
/* Email is an URI but can be included in a smart poster to add text to give instruction to user for instance */
/* Email (smart poster) Record Header */
/************************************/
/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */
/*----------------------------------*/
/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/
/*----------------------------------*/
/* TYPE LENGTH */
/*----------------------------------*/
/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 0 */
/*----------------------------------*/
/* ID LENGTH */ /* <---- Not Used */
/*----------------------------------*/
/* TYPE */
/*----------------------------------*/
/* ID */ /* <---- Not Used */
/************************************/
/* Email : 1+@+1+subject+1+message */
emailSize = 1 + strlen( pEmailStruct->EmailAdd ) + URI_FIRST_DATA_END_LENGTH + SUBJECT_BEGIN_STRING_LENGTH +
strlen( pEmailStruct->Subject ) + URI_SECOND_DATA_END_LENGTH + MESSAGE_BEGIN_STRING_LENGTH + strlen( pEmailStruct->Message );
/* Check if a Smart poster is needed */
if( pEmailStruct->Information[0] != '\0' )
{
/* Info : 1+2+info */
infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen( pEmailStruct->Information );
/* Total */
totalSize = 4 + emailSize + 4 + infoSize;
if( emailSize > 255 ) totalSize += 3; /* Normal Email size */
if( infoSize > 255 ) totalSize += 3; /* Normal Info size */
/* SmartPoster header */
if( totalSize > 255 )
{
pNDEFMessage[Offset++] = 0xC1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = totalSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0xD1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)totalSize;
}
memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH );
Offset += SMART_POSTER_TYPE_STRING_LENGTH;
}
/* Email header */
pNDEFMessage[Offset] = 0x81;
if( emailSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit
if( pEmailStruct->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit
Offset++;
pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH;
if( emailSize > 255 )
{
pNDEFMessage[Offset++] = (emailSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (emailSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (emailSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = emailSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = (uint8_t)emailSize;
}
memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH );
Offset += URI_TYPE_STRING_LENGTH;
/* Email pay load */
pNDEFMessage[Offset++] = URI_ID_0x06;
memcpy( &pNDEFMessage[Offset], pEmailStruct->EmailAdd, strlen(pEmailStruct->EmailAdd) );
Offset += strlen( pEmailStruct->EmailAdd );
memcpy( &pNDEFMessage[Offset], URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH );
Offset += URI_FIRST_DATA_END_LENGTH;
memcpy( &pNDEFMessage[Offset], SUBJECT_BEGIN_STRING, SUBJECT_BEGIN_STRING_LENGTH );
Offset += SUBJECT_BEGIN_STRING_LENGTH;
memcpy( &pNDEFMessage[Offset], pEmailStruct->Subject, strlen(pEmailStruct->Subject) );
Offset += strlen( pEmailStruct->Subject );
memcpy( &pNDEFMessage[Offset], URI_SECOND_DATA_END, URI_SECOND_DATA_END_LENGTH );
Offset += URI_SECOND_DATA_END_LENGTH;
memcpy( &pNDEFMessage[Offset], MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH );
Offset += MESSAGE_BEGIN_STRING_LENGTH;
memcpy( &pNDEFMessage[Offset], pEmailStruct->Message, strlen(pEmailStruct->Message) );
Offset += strlen( pEmailStruct->Message );
/* Information header */
if( pEmailStruct->Information[0] != '\0' )
{
if( infoSize > 255 )
{
pNDEFMessage[Offset++] = 0x41;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = infoSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0x51;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)infoSize;
}
memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH );
Offset += TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */
memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH );
Offset += ISO_ENGLISH_CODE_STRING_LENGTH;
/* Information payload */
memcpy( &pNDEFMessage[Offset], pEmailStruct->Information, strlen(pEmailStruct->Information) );
Offset += strlen( pEmailStruct->Information );
}
*size = (uint16_t)(Offset);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

64
src/lib_NDEF_Email.h Normal file
View File

@@ -0,0 +1,64 @@
/**
******************************************************************************
* @file lib_NDEF_Email.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage Email NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_EMAIL_H
#define __LIB_NDEF_EMAIL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
/* "mailto:customer.service@st.com?subject=M24SR S/N 754FHFGJF46G329 WARRANTY&body=this is an auomatic warranty activation email" */
typedef struct
{
char EmailAdd[64];
char Subject[100];
char Message[2000];
char Information[400];
}sEmailInfo;
/* Struct defined in lib_NDEF.h */
typedef struct sRecordInfo sRecordInfo_email;
uint16_t NDEF_ReadEmail( sRecordInfo_email *pRecordStruct, sEmailInfo *pEmailStruct );
uint16_t NDEF_WriteEmail( sEmailInfo *pEmailStruct );
void NDEF_PrepareEmailMessage( sEmailInfo *pEmailStruct, uint8_t *pNDEFMessage, uint16_t *size );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_EMAIL_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

372
src/lib_NDEF_Geo.cpp Normal file
View File

@@ -0,0 +1,372 @@
/**
******************************************************************************
* @file lib_NDEF_Geo.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage NDEF file that represent geolocation.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_Geo.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/** @defgroup libGeo_Private_Functions
* @{
*/
static void NDEF_FillGeoStruct( uint8_t* pPayload, uint32_t PayloadSize, sGeoInfo *pGeoStruct );
static void NDEF_ReadURI_Geo( sRecordInfo_geo *pRecordStruct, sGeoInfo *pGeoStruct );
/**
* @brief This function fill Geo structure with information of NDEF message.
* @param pPayload : pointer on the payload data of the NDEF message.
* @param PayloadSize : number of data in the payload.
* @param pGeoStruct : pointer on the structure to fill.
*/
static void NDEF_FillGeoStruct( uint8_t* pPayload, uint32_t PayloadSize, sGeoInfo *pGeoStruct )
{
uint8_t* pLastByteAdd, *pLook4Word, *pEndString;
char* pKeyWord;
uint32_t SizeOfKeyWord;
pEndString = 0;
pKeyWord = GEO_TYPE_STRING;
SizeOfKeyWord = GEO_TYPE_STRING_LENGTH;
/* First character force to NULL in case not matching found */
*pGeoStruct->Latitude = 0;
*pGeoStruct->Longitude = 0;
/* Interresting information are stored before picture if any */
/* Moreover picture is not used in this demonstration SW */
pLastByteAdd = (uint8_t*)(pPayload + PayloadSize);
pLook4Word = pPayload;
while( memcmp( pLook4Word, pKeyWord, SizeOfKeyWord ) && (pLook4Word < pLastByteAdd) )
{
pLook4Word++;
}
/* Retrieve phone number */
if( pLook4Word != pLastByteAdd )
{
pLook4Word += SizeOfKeyWord;
pEndString = pLook4Word;
while( memcmp( pEndString, URI_LATITUDE_END, URI_LATITUDE_END_LENGTH ) && (pEndString < pLastByteAdd) )
{
pEndString++;
}
if( pEndString != pLastByteAdd )
{
memcpy( pGeoStruct->Latitude, pLook4Word, pEndString-pLook4Word );
/* add end of string character */
pGeoStruct->Latitude[pEndString-pLook4Word] = 0;
}
}
pEndString += URI_LATITUDE_END_LENGTH;
pLook4Word = pEndString;
memcpy( pGeoStruct->Longitude, pEndString, PayloadSize - (pEndString - pPayload) );
/* add end of string character */
pGeoStruct->Longitude[PayloadSize-(pEndString-pPayload)] = 0;
}
/**
* @brief This function read the geoloccation information and store data in a structure.
* @param pRecordStruct : Pointer on the record structure.
* @param pGeoStruct : pointer on the structure to fill.
*/
static void NDEF_ReadURI_Geo( sRecordInfo_geo *pRecordStruct, sGeoInfo *pGeoStruct )
{
uint8_t* pPayload;
uint32_t PayloadSize;
PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pRecordStruct->PayloadLength1) << 8) | pRecordStruct->PayloadLength0;
/* Read record header */
pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd);
if( pRecordStruct->NDEF_Type == URI_GEO_TYPE )
NDEF_FillGeoStruct( pPayload , PayloadSize, pGeoStruct );
}
/**
* @}
*/
/** @defgroup libGeo_Public_Functions
* @{
* @brief This file is used to manage geolocation (stored or loaded in tag)
*/
/**
* @brief This function read NDEF and retrieve Geo information if any.
* @param pRecordStruct : Pointer on the record structure.
* @param pGeoStruct : pointer on the structure to fill .
* @retval NDEF_OK : Geolocation information from NDEF have been retrieved.
* @retval NDEF_ERROR : not able to read NDEF from tag.
*/
uint16_t NDEF_ReadGeo( sRecordInfo_geo *pRecordStruct, sGeoInfo *pGeoStruct )
{
uint16_t status = NDEF_ERROR;
sRecordInfo_geo *pSPRecordStruct;
uint32_t PayloadSize, RecordPosition;
uint8_t* pData;
if( pRecordStruct->NDEF_Type == URI_GEO_TYPE )
{
NDEF_ReadURI_Geo( pRecordStruct, pGeoStruct );
status = NDEF_OK;
}
else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE )
{
for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ )
{
pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition];
if( pSPRecordStruct->NDEF_Type == URI_GEO_TYPE )
{
NDEF_ReadURI_Geo( pSPRecordStruct, pGeoStruct );
status = NDEF_OK;
}
if( pSPRecordStruct->NDEF_Type == TEXT_TYPE )
{
PayloadSize = ((uint32_t)(pSPRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pSPRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pSPRecordStruct->PayloadLength1) << 8) | pSPRecordStruct->PayloadLength0;
/* The instruction content the UTF-8 language code that is not used here */
pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd;
PayloadSize -= *pData + 1; /* remove not usefull data */
pData += *pData + 1; /* set pointer on usefull data */
memcpy( pGeoStruct->Information, pData, PayloadSize );
/* add end of string character */
pGeoStruct->Information[PayloadSize] = 0;
}
}
}
return status;
}
/**
* @brief This function write the NDEF file with the geolocation data given in the structure.
* @param pGeoStruct : pointer on structure that contain the geolocation information.
* @retval NDEF_OK : the function is succesful.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteGeo( sGeoInfo *pGeoStruct )
{
uint16_t status = NDEF_ERROR,Offset = 0;
NDEF_PrepareGeoMessage( pGeoStruct, &NDEF_Buffer[FIRST_RECORD_OFFSET], &Offset );
/* Write NDEF */
NDEF_Buffer[0] = (Offset & 0xFF00) >> 8;
NDEF_Buffer[1] = Offset & 0x00FF;
status = WriteData( 0x00, Offset+FIRST_RECORD_OFFSET, NDEF_Buffer );
return status;
}
/**
* @brief This function write the NDEF file with the geolocation data given in the structure.
* @param pGeoStruct : pointer on structure that contain the geolocation information.
* @param pNDEFMessage : pointer on the NDEF message.
* @param size : to store the size of the NDEF message generated.
*/
void NDEF_PrepareGeoMessage( sGeoInfo *pGeoStruct, uint8_t *pNDEFMessage, uint16_t *size )
{
uint16_t Offset = 0;
uint32_t geoSize = 0;
uint32_t infoSize = 0;
uint32_t totalSize = 0;
/* GEO is an URI but can be included in a smart poster to add text to give instruction to user for instance */
/* GEO (smart poster) Record Header */
/************************************/
/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */
/*----------------------------------*/
/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/
/*----------------------------------*/
/* TYPE LENGTH */
/*----------------------------------*/
/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 0 */
/*----------------------------------*/
/* ID LENGTH */ /* <---- Not Used */
/*----------------------------------*/
/* TYPE */
/*----------------------------------*/
/* ID */ /* <---- Not Used */
/************************************/
/* GEO : 1+geo:+latitude+1+longitude */
geoSize = 1 + GEO_TYPE_STRING_LENGTH + strlen(pGeoStruct->Latitude) + URI_LATITUDE_END_LENGTH + strlen(pGeoStruct->Longitude);
/* Check if a Smart poster is needed */
if( pGeoStruct->Information[0] != '\0' )
{
/* Info : 1+2+info */
infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen(pGeoStruct->Information);
/* Total */
totalSize = 4 + geoSize + 4 + infoSize;
if( geoSize > 255 ) totalSize += 3; /* Normal Geo size */
if( infoSize > 255 ) totalSize += 3; /* Normal Info size */
/* SmartPoster header */
if( totalSize > 255 )
{
pNDEFMessage[Offset++] = 0xC1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = totalSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0xD1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)totalSize;
}
memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH );
Offset += SMART_POSTER_TYPE_STRING_LENGTH;
}
/* GEO header */
pNDEFMessage[Offset] = 0x81;
if( geoSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit
if( pGeoStruct->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit
Offset++;
pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH;
if( geoSize > 255 )
{
pNDEFMessage[Offset++] = (geoSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (geoSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (geoSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = geoSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = (uint8_t)geoSize;
}
memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH );
Offset += URI_TYPE_STRING_LENGTH;
/* GEO payload */
pNDEFMessage[Offset++] = URI_ID_0x00; /* URI identifier no abbreviation */
memcpy( &pNDEFMessage[Offset], GEO_TYPE_STRING, GEO_TYPE_STRING_LENGTH );
Offset += GEO_TYPE_STRING_LENGTH;
memcpy( &pNDEFMessage[Offset], pGeoStruct->Latitude, strlen(pGeoStruct->Latitude) );
Offset += strlen( pGeoStruct->Latitude );
memcpy( &pNDEFMessage[Offset], URI_LATITUDE_END, URI_LATITUDE_END_LENGTH );
Offset += URI_LATITUDE_END_LENGTH;
memcpy( &pNDEFMessage[Offset], pGeoStruct->Longitude, strlen(pGeoStruct->Longitude) );
Offset += strlen( pGeoStruct->Longitude );
/* Information header */
if( pGeoStruct->Information[0] != '\0' )
{
if( infoSize > 255 )
{
pNDEFMessage[Offset++] = 0x41;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = infoSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0x51;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)infoSize;
}
memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH );
Offset += TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */
memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH );
Offset += ISO_ENGLISH_CODE_STRING_LENGTH;
/* Information payload */
memcpy( &pNDEFMessage[Offset], pGeoStruct->Information, strlen(pGeoStruct->Information) );
Offset += strlen( pGeoStruct->Information );
}
*size = (uint16_t)(Offset);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

61
src/lib_NDEF_Geo.h Normal file
View File

@@ -0,0 +1,61 @@
/**
******************************************************************************
* @file lib_NDEF_Geo.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage Geolocation NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_GEO_H
#define __LIB_NDEF_GEO_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
typedef struct
{
char Latitude[20];
char Longitude[20];
char Information[100];
}sGeoInfo;
/* Struct defined in lib_NDEF.h */
typedef struct sRecordInfo sRecordInfo_geo;
uint16_t NDEF_ReadGeo( sRecordInfo_geo *pRecordStruct, sGeoInfo *pGeoStruct );
uint16_t NDEF_WriteGeo( sGeoInfo *pGeoStruct );
void NDEF_PrepareGeoMessage( sGeoInfo *pGeoStruct, uint8_t *pNDEFMessage, uint16_t *size );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_GEO_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

297
src/lib_NDEF_MyApp.cpp Normal file
View File

@@ -0,0 +1,297 @@
/**
******************************************************************************
* @file lib_NDEF_MyApp.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage the NDEF file of a private application.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_MyApp.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpio... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/** @defgroup libMyApp_Private_Functions
* @{
*/
static void NDEF_Extract_M24SRDiscoveryApp_Input( sRecordInfo_myapp *pRecordStruct, sMyAppInfo *pMyAppStruct );
/**
* @brief This function read the NDEF file and store application data in a structure.
* @param pRecordStruct : Pointer on the record structure.
* @param pMyAppStruct : pointer on the structure to fill.
*/
static void NDEF_Extract_M24SRDiscoveryApp_Input( sRecordInfo_myapp *pRecordStruct, sMyAppInfo *pMyAppStruct )
{
uint8_t* pPayload;
uint8_t* pLook4Word;
uint16_t BackGroundColor, FontColor;
uint8_t i;
/* Read record header */
pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd);
/* initialize struct in case not matching found */
for( i = 0; i < 8; i++ )
{
/* Set the Back Color */
pMyAppStruct->LineX[i].BackGroundColor = 0xFFFF;
/* Set the Text Color */
pMyAppStruct->LineX[i].FontColor = 0x0000;
/* Set the line number */
pMyAppStruct->LineX[i].LineNb = i + 1;
/* Set the line content */
memcpy( pMyAppStruct->LineX[i].String, " ", 20 );
}
pLook4Word = pPayload;
for( i = 0; i < 4; i++ )
{
pMyAppStruct->LedBlinkConf.LedConf[i] = *pLook4Word;
pLook4Word++;
}
pMyAppStruct->LedBlinkConf.Speed = *pLook4Word;
pLook4Word++;
for( i = 0; i < 8; i++ )
{
/* Set the line number */
pMyAppStruct->LineX[i].LineNb = *pLook4Word;
pLook4Word++;
/* Set the Back Color */
BackGroundColor = (uint16_t)(*pLook4Word << 8);
BackGroundColor = BackGroundColor | (uint16_t)(*++pLook4Word );
pMyAppStruct->LineX[i].BackGroundColor = BackGroundColor;
pLook4Word++;
/* Set the Text Color */
FontColor = (uint16_t)(*pLook4Word << 8);
FontColor = FontColor | (uint16_t)(*++pLook4Word);
pMyAppStruct->LineX[i].FontColor = FontColor;
pLook4Word++;
/* Set the line content */
memcpy( pMyAppStruct->LineX[i].String, (char*)pLook4Word, 20 );
pLook4Word += 20;
}
}
/**
* @}
*/
/** @defgroup libMyApp_Public_Functions
* @{
* @brief This file is used to manage proprietary NDEF (stored or loaded in tag)
*/
/**
* @brief This function read NDEF and retrieve Application information if any.
* @param pRecordStruct : Pointer on the record structure.
* @param pMyAppStruct : pointer on the structure to fill.
* @retval NDEF_OK : NDEF file data read in the tag.
* @retval NDEF_ERROR : not able to read NDEF in tag.
*/
uint16_t NDEF_ReadMyApp( sRecordInfo_myapp *pRecordStruct, sMyAppInfo *pMyAppStruct )
{
uint16_t status = NDEF_ERROR;
if( pRecordStruct->NDEF_Type == M24SR_DISCOVERY_APP_TYPE )
{
NDEF_Extract_M24SRDiscoveryApp_Input( pRecordStruct, pMyAppStruct );
status = NDEF_OK;
}
else
{
status = NDEF_ERROR;
}
return status;
}
/**
* @brief This function write the NDEF file with the Application data given in the structure.
* @brief Only used for debug purpose in this firmware version.
* @param pMyAppStruct : pointer on structure that contain the application information.
* @retval NDEF_OK : NDEF file data written in the tag.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteMyApp( sMyAppInfo *pMyAppStruct )
{
uint16_t status = NDEF_ERROR;
uint16_t DataSize;
uint32_t PayloadSize;
uint8_t i;
uint8_t* pPayload;
/* External Type Record Header */
/************************************/
/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */
/*----------------------------------*/
/* MB ME CF SR IL TNF */ /* <---- IL=0, CF=0 and SR=1 TNF=4 NFC Forum external type*/
/*----------------------------------*/
/* TYPE LENGTH */
/*----------------------------------*/
/* PAYLOAD LENGTH 3 */ /* <---- Not Used */
/*----------------------------------*/
/* PAYLOAD LENGTH 2 */ /* <---- Not Used */
/*----------------------------------*/
/* PAYLOAD LENGTH 1 */ /* <---- Not Used */
/*----------------------------------*/
/* PAYLOAD LENGTH 0 */ /* The payload will always be 5 + 25*8=205 bytes for this application */
/*----------------------------------*/
/* ID LENGTH */ /* <---- Not Used */
/*----------------------------------*/
/* TYPE */ /* st.com:m24sr_discovery_democtrl */
/*----------------------------------*/
/* ID */ /* <---- Not Used */
/************************************/
/* NDEF file must be written in 2 phases, first phase NDEF size is Null */
NDEF_Buffer[NDEF_SIZE_OFFSET] = 0x00;
NDEF_Buffer[NDEF_SIZE_OFFSET+1] = 0x00;
/* fill URI record header */
NDEF_Buffer[FIRST_RECORD_OFFSET] = 0xD4; /* Record Flag */
NDEF_Buffer[FIRST_RECORD_OFFSET+1] = M24SR_DISCOVERY_APP_STRING_LENGTH;
NDEF_Buffer[FIRST_RECORD_OFFSET+2] = 0x00; /* Will be filled at the end when payload size is known */
memcpy( &NDEF_Buffer[FIRST_RECORD_OFFSET+3], M24SR_DISCOVERY_APP_STRING, M24SR_DISCOVERY_APP_STRING_LENGTH );
pPayload = &NDEF_Buffer[FIRST_RECORD_OFFSET + 3 + M24SR_DISCOVERY_APP_STRING_LENGTH];
PayloadSize = 0;
/**************************************************************/
/* BLINK CONFIG data */
/* led 1 blinking */
*pPayload = 0x03;
pPayload++;
/* led 2 blinking */
*pPayload = 0x02;
pPayload++;
/* led 3 blinking */
*pPayload = 0x02;
pPayload++;
/* led 4 blinking */
*pPayload = 0x03;
pPayload++;
/* speed */
*pPayload = 0x03;
pPayload++;
PayloadSize += 5;
/**************************************************************/
/**************************************************************/
/* SCREEN config data */
for( i = 0; i < 8; i++ )
{
/* Line number */
*pPayload = (uint8_t)(i + 1);
pPayload++;
/* Background color */
*pPayload = 0xFF;
pPayload++;
*pPayload = 0xFF;
pPayload++;
/* Font Color */
*pPayload = 0x00;
pPayload++;
*pPayload = 0x00;
pPayload++;
/* String */
memcpy( pPayload, "ABCDEFGHIJKLMNOPQRST", 20 );
pPayload += 20;
PayloadSize += 25;
}
NDEF_Buffer[FIRST_RECORD_OFFSET+2] = PayloadSize & 0x000000FF;
DataSize = PayloadSize + 5 + M24SR_DISCOVERY_APP_STRING_LENGTH;
/* Write NDEF */
status = WriteData( 0x00, DataSize, NDEF_Buffer );
/* Write NDEF size to complete*/
if( status == NDEF_OK )
{
DataSize -= 2; /* Must not count the 2 byte that represent the NDEF size */
NDEF_Buffer[0] = (DataSize & 0xFF00) >> 8;
NDEF_Buffer[1] = DataSize & 0x00FF;
status = WriteData( 0x00, 2, NDEF_Buffer );
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

89
src/lib_NDEF_MyApp.h Normal file
View File

@@ -0,0 +1,89 @@
/**
******************************************************************************
* @file lib_NDEF_MyApp.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file illustrate how to use M24SR with a proprietary protocol.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_MYAPP_H
#define __LIB_NDEF_MYAPP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
#define BLINK_CONFIG "<BLINK_CONFIG>"
#define BLINK_CONFIG_STRING_SIZE 14
#define BLINK_CONFIG_END "<\\BLINK_CONFIG>"
#define BLINK_CONFIG_END_STRING_SIZE 15
#define LINE_DESCR "<LINE_DESCR>"
#define LINE_DESCR_STRING_SIZE 12
#define LINE_DESCR_END "<\\LINE_DESCR>"
#define LINE_DESCR_END_STRING_SIZE 13
#define BLINKING_NONE 0x00
#define BLINKING_SLOW 0x01
#define BLINKING_MEDIUM 0x02
#define BLINKING_FAST 0x03
typedef struct
{
uint8_t LedConf[4];
uint8_t Speed;
}sLedBlinkConfig;
typedef struct
{
uint8_t LineNb;
uint16_t BackGroundColor;
uint16_t FontColor;
char String[20];
}sLineConfig;
typedef struct
{
sLedBlinkConfig LedBlinkConf;
sLineConfig LineX[8];
}sMyAppInfo;
/* Struct defined in lib_NDEF.h */
typedef struct sRecordInfo sRecordInfo_myapp;
uint16_t NDEF_ReadMyApp( sRecordInfo_myapp *pRecordStruct, sMyAppInfo *pMyAppStruct );
uint16_t NDEF_WriteMyApp( sMyAppInfo *pMyAppStruct );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_MYAPP_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

384
src/lib_NDEF_SMS.cpp Normal file
View File

@@ -0,0 +1,384 @@
/**
******************************************************************************
* @file lib_NDEF_SMS.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage NDEF file that represent SMS.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_SMS.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/** @defgroup libSMS_Private_Functions
* @{
*/
static void NDEF_FillSMSStruct( uint8_t* pPayload, uint32_t PayloadSize, sSMSInfo *pSMSStruct );
static void NDEF_ReadURI_SMS( sRecordInfo_sms *pRecordStruct, sSMSInfo *pSMSStruct );
/**
* @brief This function fill SMS structure with information of NDEF message.
* @param pPayload : pointer on the payload data of the NDEF message.
* @param PayloadSize : number of data in the payload.
* @param pSMSStruct : pointer on the structure to fill.
*/
static void NDEF_FillSMSStruct( uint8_t* pPayload, uint32_t PayloadSize, sSMSInfo *pSMSStruct )
{
uint8_t* pLastByteAdd, *pLook4Word, *pEndString ;
char* pKeyWord;
uint32_t SizeOfKeyWord;
pEndString = 0;
pKeyWord = SMS_TYPE_STRING;
SizeOfKeyWord = SMS_TYPE_STRING_LENGTH;
/* First character force to NULL in case not matching found */
*pSMSStruct->PhoneNumber = 0;
*pSMSStruct->Message = 0;
/* Interesting information are stored before picture if any */
/* Moreover picture is not used in this demonstration SW */
pLastByteAdd = (uint8_t*)(pPayload + PayloadSize);
pLook4Word = pPayload;
while( memcmp( pLook4Word, pKeyWord, SizeOfKeyWord ) && (pLook4Word < pLastByteAdd) )
{
pLook4Word++;
}
/* Retrieve phone number */
if( pLook4Word != pLastByteAdd )
{
pLook4Word += SizeOfKeyWord;
pEndString = pLook4Word;
while( memcmp( pEndString, URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ) && (pEndString < pLastByteAdd) )
{
pEndString++;
}
if( pEndString != pLastByteAdd )
{
memcpy( pSMSStruct->PhoneNumber, pLook4Word, pEndString-pLook4Word );
/* add end of string character */
pSMSStruct->PhoneNumber[pEndString-pLook4Word] = 0;
}
}
pEndString += URI_FIRST_DATA_END_LENGTH;
pLook4Word = pEndString;
/* check if e-mail subject is present */
if( !memcmp( pLook4Word, MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH ) )
{
pEndString += MESSAGE_BEGIN_STRING_LENGTH;
/* Retrieve message */
memcpy( pSMSStruct->Message, pEndString, PayloadSize - (pEndString - pPayload) );
/* add end of string character */
pSMSStruct->Message[PayloadSize-(pEndString-pPayload)] = 0;
}
}
/**
* @brief This function read the SMS and store data in a structure.
* @param pRecordStruct : Pointer on the record structure.
* @param pSMSStruct : pointer on the structure to fill.
*/
static void NDEF_ReadURI_SMS( sRecordInfo_sms *pRecordStruct, sSMSInfo *pSMSStruct )
{
uint8_t* pPayload;
uint32_t PayloadSize;
PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pRecordStruct->PayloadLength1) << 8) | pRecordStruct->PayloadLength0;
/* Read record header */
pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd);
if( pRecordStruct->NDEF_Type == URI_SMS_TYPE )
NDEF_FillSMSStruct( pPayload , PayloadSize, pSMSStruct );
}
/**
* @}
*/
/** @defgroup libSMS_Public_Functions
* @{
* @brief This file is used to manage SMS (stored or loaded in tag)
*/
/**
* @brief This function read NDEF and retrieve SMS information if any.
* @param pRecordStruct : Pointer on the record structure.
* @param pSMSStruct : pointer on the structure to fill.
* @retval NDEF_OK : SMS information from NDEF have been retrieve.
* @retval NDEF_ERROR : Not able to retrieve SMS information.
*/
uint16_t NDEF_ReadSMS( sRecordInfo_sms *pRecordStruct, sSMSInfo *pSMSStruct )
{
uint16_t status = NDEF_ERROR;
sRecordInfo_sms *pSPRecordStruct;
uint32_t PayloadSize, RecordPosition;
uint8_t* pData;
if( pRecordStruct->NDEF_Type == URI_SMS_TYPE )
{
NDEF_ReadURI_SMS( pRecordStruct, pSMSStruct );
status = NDEF_OK;
}
else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE )
{
for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ )
{
pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition];
if( pSPRecordStruct->NDEF_Type == URI_SMS_TYPE )
{
NDEF_ReadURI_SMS( pSPRecordStruct, pSMSStruct );
status = NDEF_OK;
}
if( pSPRecordStruct->NDEF_Type == TEXT_TYPE )
{
PayloadSize = ((uint32_t)(pSPRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pSPRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pSPRecordStruct->PayloadLength1) << 8) | pSPRecordStruct->PayloadLength0;
/* The instruction content the UTF-8 language code that is not used here */
pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd;
PayloadSize -= *pData + 1; /* remove not usefull data */
pData += *pData + 1; /* set pointer on usefull data */
memcpy( pSMSStruct->Information, pData, PayloadSize );
/* add end of string character */
pSMSStruct->Information[PayloadSize] = 0;
}
}
}
return status;
}
/**
* @brief This function write the NDEF file with the SMS data given in the structure.
* @param pSMSStruct : pointer on structure that contain the SMS information.
* @retval NDEF_OK : NDEF file data written in the tag.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteSMS( sSMSInfo *pSMSStruct )
{
uint16_t status = NDEF_ERROR, Offset = 0;
NDEF_PrepareSMSMessage( pSMSStruct, &NDEF_Buffer[FIRST_RECORD_OFFSET], &Offset );
/* Write NDEF */
NDEF_Buffer[0] = (Offset & 0xFF00) >> 8;
NDEF_Buffer[1] = Offset & 0x00FF;
status = WriteData( 0x00, Offset + FIRST_RECORD_OFFSET, NDEF_Buffer );
return status;
}
/**
* @brief This function write the NDEF file with the SMS data given in the structure.
* @param pSMSStruct : pointer on structure that contain the SMS information.
* @param pNDEFMessage : pointer on the NDEF message.
* @param size : to store the size of the NDEF message generated.
*/
void NDEF_PrepareSMSMessage( sSMSInfo *pSMSStruct, uint8_t *pNDEFMessage, uint16_t *size )
{
uint16_t Offset = 0;
uint32_t smsSize = 0;
uint32_t infoSize= 0;
uint32_t totalSize = 0;
/* SMS is an URI but can be included in a smart poster to add text to give instruction to user for instance */
/* SMS (smart poster) Record Header */
/************************************/
/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */
/*----------------------------------*/
/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/
/*----------------------------------*/
/* TYPE LENGTH */
/*----------------------------------*/
/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 0 */
/*----------------------------------*/
/* ID LENGTH */ /* <---- Not Used */
/*----------------------------------*/
/* TYPE */
/*----------------------------------*/
/* ID */ /* <---- Not Used */
/************************************/
/* SMS : 1+sms:+tel+1+body=+message */
smsSize = 1 + SMS_TYPE_STRING_LENGTH + strlen(pSMSStruct->PhoneNumber) + URI_FIRST_DATA_END_LENGTH +
MESSAGE_BEGIN_STRING_LENGTH + strlen(pSMSStruct->Message);
/* Check if a Smart poster is needed */
if( pSMSStruct->Information[0] != '\0' )
{
/* Info : 1+2+info */
infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen(pSMSStruct->Information);
/* Total */
totalSize = 4 + smsSize + 4 + infoSize;
if( smsSize > 255 ) totalSize += 3; /* Normal Email size */
if( infoSize > 255 ) totalSize += 3; /* Normal Info size */
/* SmartPoster header */
if( totalSize > 255 )
{
pNDEFMessage[Offset++] = 0xC1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = totalSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0xD1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)totalSize;
}
memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH );
Offset += SMART_POSTER_TYPE_STRING_LENGTH;
}
/* SMS header */
pNDEFMessage[Offset] = 0x81;
if( smsSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit
if( pSMSStruct->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit
Offset++;
pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH;
if( smsSize > 255 )
{
pNDEFMessage[Offset++] = (smsSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (smsSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (smsSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = smsSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = (uint8_t)smsSize;
}
memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH );
Offset += URI_TYPE_STRING_LENGTH;
/* SMS payload */
pNDEFMessage[Offset++] = URI_ID_0x00;
memcpy( &pNDEFMessage[Offset], SMS_TYPE_STRING, SMS_TYPE_STRING_LENGTH );
Offset += SMS_TYPE_STRING_LENGTH;
memcpy( &pNDEFMessage[Offset], pSMSStruct->PhoneNumber, strlen(pSMSStruct->PhoneNumber) );
Offset += strlen( pSMSStruct->PhoneNumber );
memcpy( &pNDEFMessage[Offset], URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH );
Offset += URI_FIRST_DATA_END_LENGTH;
memcpy( &pNDEFMessage[Offset], MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH );
Offset += MESSAGE_BEGIN_STRING_LENGTH;
memcpy( &pNDEFMessage[Offset], pSMSStruct->Message, strlen(pSMSStruct->Message) );
Offset += strlen( pSMSStruct->Message );
/* Information header */
if( pSMSStruct->Information[0] != '\0' )
{
if( infoSize > 255 )
{
pNDEFMessage[Offset++] = 0x41;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = infoSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0x51;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)infoSize;
}
memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH );
Offset += TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */
memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH );
Offset += ISO_ENGLISH_CODE_STRING_LENGTH;
/* Information payload */
memcpy( &pNDEFMessage[Offset], pSMSStruct->Information, strlen(pSMSStruct->Information) );
Offset += strlen( pSMSStruct->Information );
}
*size = (uint16_t)(Offset);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

62
src/lib_NDEF_SMS.h Normal file
View File

@@ -0,0 +1,62 @@
/**
******************************************************************************
* @file lib_NDEF_SMS.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage SMS NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_SMS_H
#define __LIB_NDEF_SMS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
typedef struct
{
char PhoneNumber[16];
char Message[400];
char Information[400];
}sSMSInfo;
/* Struct defined in lib_NDEF.h */
typedef struct sRecordInfo sRecordInfo_sms;
uint16_t NDEF_ReadSMS( sRecordInfo_sms *pRecordStruct, sSMSInfo *pSMSStruct );
uint16_t NDEF_WriteSMS( sSMSInfo *pSMSStruct );
void NDEF_PrepareSMSMessage( sSMSInfo *pSMSStruct, uint8_t *pNDEFMessage, uint16_t *size );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_SMS_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

141
src/lib_NDEF_Text.cpp Normal file
View File

@@ -0,0 +1,141 @@
/**
******************************************************************************
* @file lib_NDEF_Text.h
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage Text NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_Text.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/**
* @}
*/
/** @defgroup libEmail_Public_Functions
* @{
* @brief This file is used to manage Email (stored or loaded in tag)
*/
/**
* @brief This function write the text in the TAG.
* @param text : text to write.
* @retval NDEF_OK : NDEF file data written in the tag.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteText( char *text )
{
uint16_t status = NDEF_ERROR;
uint32_t textSize, Offset = 0;
NDEF_Buffer[0] = 0;
NDEF_Buffer[1] = 0;
Offset = FIRST_RECORD_OFFSET;
/* TEXT : 1+en+message */
textSize = 3 + strlen(text);
/* TEXT header */
NDEF_Buffer[Offset] = 0xD1;
if( textSize < 256 ) NDEF_Buffer[Offset] |= 0x10; // Set the SR bit
Offset++;
NDEF_Buffer[Offset++] = TEXT_TYPE_STRING_LENGTH;
if( textSize > 255 )
{
NDEF_Buffer[Offset++] = (textSize & 0xFF000000) >> 24;
NDEF_Buffer[Offset++] = (textSize & 0x00FF0000) >> 16;
NDEF_Buffer[Offset++] = (textSize & 0x0000FF00) >> 8;
NDEF_Buffer[Offset++] = textSize & 0x000000FF;
}
else
{
NDEF_Buffer[Offset++] = (uint8_t)textSize;
}
memcpy( &NDEF_Buffer[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH );
Offset += TEXT_TYPE_STRING_LENGTH;
/* TEXT payload */
NDEF_Buffer[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH;
memcpy( &NDEF_Buffer[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH );
Offset += ISO_ENGLISH_CODE_STRING_LENGTH;
memcpy( &NDEF_Buffer[Offset], text, strlen(text) );
Offset += strlen(text);
Offset -= 2; /* Must not count the 2 byte that represent the NDEF size */
NDEF_Buffer[0] = (Offset & 0xFF00) >> 8;
NDEF_Buffer[1] = Offset & 0x00FF;
status = WriteData( 0x00, Offset + 2, NDEF_Buffer );
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

49
src/lib_NDEF_Text.h Normal file
View File

@@ -0,0 +1,49 @@
/**
******************************************************************************
* @file lib_NDEF_Text.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage Text NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_TEXT_H
#define __LIB_NDEF_TEXT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
uint16_t NDEF_WriteText( char *text );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_TEXT_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

554
src/lib_NDEF_URI.cpp Normal file
View File

@@ -0,0 +1,554 @@
/**
******************************************************************************
* @file lib_NDEF_URI.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage NDEF file that represent URI.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_URI.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/** @defgroup libURI_Private_Functions
* @{
*/
static void NDEF_Parse_WellKnowType( sRecordInfo_uri *pRecordStruct, sURI_Info* pURI );
/**
* @brief This function read the URI information and store data in a structure.
* @param pRecordStruct : Pointer on the record structure.
* @param pURI : pointer on the structure to fill.
*/
static void NDEF_Parse_WellKnowType( sRecordInfo_uri *pRecordStruct, sURI_Info* pURI )
{
uint32_t PayloadSize;
uint8_t Offset;
uint8_t* pPayload;
pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd);
switch( *pPayload )
{
case URI_ID_0x01:
memcpy( pURI->protocol, URI_ID_0x01_STRING, strlen(URI_ID_0x01_STRING) );
Offset = strlen( URI_ID_0x01_STRING );
break;
case URI_ID_0x02:
memcpy( pURI->protocol, URI_ID_0x02_STRING, strlen(URI_ID_0x02_STRING) );
Offset = strlen( URI_ID_0x02_STRING );
break;
case URI_ID_0x03:
memcpy( pURI->protocol, URI_ID_0x03_STRING, strlen(URI_ID_0x03_STRING) );
Offset = strlen( URI_ID_0x03_STRING );
break;
case URI_ID_0x04:
memcpy( pURI->protocol, URI_ID_0x04_STRING, strlen(URI_ID_0x04_STRING) );
Offset = strlen( URI_ID_0x04_STRING );
break;
case URI_ID_0x05:
memcpy( pURI->protocol, URI_ID_0x05_STRING, strlen(URI_ID_0x05_STRING) );
Offset = strlen( URI_ID_0x05_STRING );
break;
case URI_ID_0x06:
memcpy( pURI->protocol, URI_ID_0x06_STRING, strlen(URI_ID_0x06_STRING) );
Offset = strlen( URI_ID_0x06_STRING );
break;
case URI_ID_0x07:
memcpy( pURI->protocol, URI_ID_0x07_STRING, strlen(URI_ID_0x07_STRING) );
Offset = strlen( URI_ID_0x07_STRING );
break;
case URI_ID_0x08:
memcpy( pURI->protocol, URI_ID_0x08_STRING, strlen(URI_ID_0x08_STRING) );
Offset = strlen( URI_ID_0x08_STRING );
break;
case URI_ID_0x09:
memcpy( pURI->protocol, URI_ID_0x09_STRING, strlen(URI_ID_0x09_STRING) );
Offset = strlen( URI_ID_0x09_STRING );
break;
case URI_ID_0x0A:
memcpy( pURI->protocol, URI_ID_0x0A_STRING, strlen(URI_ID_0x0A_STRING) );
Offset = strlen( URI_ID_0x0A_STRING );
break;
case URI_ID_0x0B:
memcpy( pURI->protocol, URI_ID_0x0B_STRING, strlen(URI_ID_0x0B_STRING) );
Offset = strlen( URI_ID_0x0B_STRING );
break;
case URI_ID_0x0C:
memcpy( pURI->protocol, URI_ID_0x0C_STRING, strlen(URI_ID_0x0C_STRING) );
Offset = strlen( URI_ID_0x0C_STRING );
break;
case URI_ID_0x0D:
memcpy( pURI->protocol, URI_ID_0x0D_STRING, strlen(URI_ID_0x0D_STRING) );
Offset = strlen( URI_ID_0x0D_STRING );
break;
case URI_ID_0x0E:
memcpy( pURI->protocol, URI_ID_0x0E_STRING, strlen(URI_ID_0x0E_STRING) );
Offset = strlen( URI_ID_0x0E_STRING );
break;
case URI_ID_0x0F:
memcpy( pURI->protocol, URI_ID_0x0F_STRING, strlen(URI_ID_0x0F_STRING) );
Offset = strlen( URI_ID_0x0F_STRING );
break;
case URI_ID_0x10:
memcpy( pURI->protocol, URI_ID_0x10_STRING, strlen(URI_ID_0x10_STRING) );
Offset = strlen( URI_ID_0x10_STRING );
break;
case URI_ID_0x11:
memcpy( pURI->protocol, URI_ID_0x11_STRING, strlen(URI_ID_0x11_STRING) );
Offset = strlen( URI_ID_0x11_STRING );
break;
case URI_ID_0x12:
memcpy( pURI->protocol, URI_ID_0x12_STRING, strlen(URI_ID_0x12_STRING) );
Offset = strlen( URI_ID_0x12_STRING );
break;
case URI_ID_0x13:
memcpy( pURI->protocol, URI_ID_0x13_STRING, strlen(URI_ID_0x13_STRING) );
Offset = strlen( URI_ID_0x13_STRING );
break;
case URI_ID_0x14:
memcpy( pURI->protocol, URI_ID_0x14_STRING, strlen(URI_ID_0x14_STRING) );
Offset = strlen( URI_ID_0x14_STRING );
break;
case URI_ID_0x15:
memcpy( pURI->protocol, URI_ID_0x15_STRING, strlen(URI_ID_0x15_STRING) );
Offset = strlen( URI_ID_0x15_STRING );
break;
case URI_ID_0x16:
memcpy( pURI->protocol, URI_ID_0x16_STRING, strlen(URI_ID_0x16_STRING) );
Offset = strlen( URI_ID_0x16_STRING );
break;
case URI_ID_0x17:
memcpy( pURI->protocol, URI_ID_0x17_STRING, strlen(URI_ID_0x17_STRING) );
Offset = strlen( URI_ID_0x17_STRING );
break;
case URI_ID_0x18:
memcpy( pURI->protocol, URI_ID_0x18_STRING, strlen(URI_ID_0x18_STRING) );
Offset = strlen( URI_ID_0x18_STRING );
break;
case URI_ID_0x19:
memcpy( pURI->protocol, URI_ID_0x19_STRING, strlen(URI_ID_0x19_STRING) );
Offset = strlen( URI_ID_0x19_STRING );
break;
case URI_ID_0x1A:
memcpy( pURI->protocol, URI_ID_0x1A_STRING, strlen(URI_ID_0x1A_STRING) );
Offset = strlen( URI_ID_0x1A_STRING );
break;
case URI_ID_0x1B:
memcpy( pURI->protocol, URI_ID_0x1B_STRING, strlen(URI_ID_0x1B_STRING) );
Offset = strlen( URI_ID_0x1B_STRING );
break;
case URI_ID_0x1C:
memcpy( pURI->protocol, URI_ID_0x1C_STRING, strlen(URI_ID_0x1C_STRING) );
Offset = strlen( URI_ID_0x1C_STRING );
break;
case URI_ID_0x1D:
memcpy( pURI->protocol, URI_ID_0x1D_STRING, strlen(URI_ID_0x1D_STRING) );
Offset = strlen( URI_ID_0x1D_STRING );
break;
case URI_ID_0x1E:
memcpy( pURI->protocol, URI_ID_0x1E_STRING, strlen(URI_ID_0x1E_STRING) );
Offset = strlen( URI_ID_0x1E_STRING );
break;
case URI_ID_0x1F:
memcpy( pURI->protocol, URI_ID_0x1F_STRING, strlen(URI_ID_0x1F_STRING) );
Offset = strlen( URI_ID_0x1F_STRING );
break;
case URI_ID_0x20:
memcpy( pURI->protocol, URI_ID_0x20_STRING, strlen(URI_ID_0x20_STRING) );
Offset = strlen( URI_ID_0x20_STRING );
break;
case URI_ID_0x21:
memcpy( pURI->protocol, URI_ID_0x21_STRING, strlen(URI_ID_0x21_STRING) );
Offset = strlen( URI_ID_0x21_STRING );
break;
case URI_ID_0x22:
memcpy( pURI->protocol, URI_ID_0x22_STRING, strlen(URI_ID_0x22_STRING) );
Offset = strlen( URI_ID_0x22_STRING );
break;
case URI_ID_0x23:
memcpy( pURI->protocol, URI_ID_0x23_STRING, strlen(URI_ID_0x23_STRING) );
Offset = strlen( URI_ID_0x23_STRING );
break;
default:
Offset = 0;
/* Should not happened */
break;
}
/* add end of string character */
pURI->protocol[Offset] = '\0';
pPayload++; /* go after well know byte */
PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pRecordStruct->PayloadLength1) << 8) | pRecordStruct->PayloadLength0;
PayloadSize = PayloadSize - 1; /* remove well know byte */
memcpy( pURI->URI_Message, pPayload, PayloadSize );
/* add end of string character */
pURI->URI_Message[PayloadSize] = '\0';
}
/**
* @}
*/
/** @defgroup libURI_Public_Functions
* @{
* @brief This file is used to manage URI (stored or loaded in tag)
*/
/**
* @brief This function read NDEF and retrieve URI information if any.
* @param pRecordStruct : Pointer on the record structure.
* @param pURI : pointer on the structure to fill.
* @retval NDEF_OK : URI information from NDEF have been retrieved.
* @retval NDEF_ERROR : Not able to retrieve URI information.
*/
uint16_t NDEF_ReadURI( sRecordInfo_uri *pRecordStruct, sURI_Info *pURI )
{
uint16_t status = NDEF_ERROR;
sRecordInfo_uri *pSPRecordStruct;
uint32_t PayloadSize, RecordPosition;
uint8_t* pData;
if( pRecordStruct->NDEF_Type == WELL_KNOWN_ABRIDGED_URI_TYPE )
{
NDEF_Parse_WellKnowType( pRecordStruct, pURI );
status = NDEF_OK;
}
else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE )
{
for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ )
{
pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition];
if( pSPRecordStruct->NDEF_Type == WELL_KNOWN_ABRIDGED_URI_TYPE )
{
NDEF_Parse_WellKnowType( pSPRecordStruct, pURI );
status = NDEF_OK;
}
if( pSPRecordStruct->NDEF_Type == TEXT_TYPE )
{
PayloadSize = ((uint32_t)(pSPRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pSPRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pSPRecordStruct->PayloadLength1) << 8) | pSPRecordStruct->PayloadLength0;
/* The instruction content the UTF-8 language code that is not used here */
pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd;
PayloadSize -= *pData + 1; /* remove not usefull data */
pData += *pData + 1;
memcpy( pURI->Information, pData, PayloadSize );
}
}
}
else
{
status = NDEF_ERROR;
}
return status;
}
/**
* @brief This function prepare the NDEF message with the URI data given in the structure.
* @param pURI : pointer on structure that contain the URI information.
* @param pNDEFMessage : pointer on the NDEF message.
* @param size : to store the size of the NDEF message generated.
*/
void NDEF_PrepareURIMessage( sURI_Info *pURI, uint8_t *pNDEFMessage, uint16_t *size )
{
uint32_t uriSize, totalSize, Offset = 0;
uint32_t infoSize = 0;
char type;
/* An URI can be included in a smart poster to add text to give instruction to user for instance */
/* URI (smart poster) Record Header */
/************************************/
/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */
/*----------------------------------*/
/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/
/*----------------------------------*/
/* TYPE LENGTH */
/*----------------------------------*/
/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */
/*----------------------------------*/
/* PAYLOAD LENGTH 0 */
/*----------------------------------*/
/* ID LENGTH */ /* <---- Not Used */
/*----------------------------------*/
/* TYPE */
/*----------------------------------*/
/* ID */ /* <---- Not Used */
/************************************/
/* We need to know the URI type in order to define if an abreviation is available */
type = getUriType( pURI->protocol );
/* URI : 1+URI for abreviate protocol*/
if( type != URI_ID_0x00 )
uriSize = 1 + strlen(pURI->URI_Message);
else /*: 1+protocol+URI else*/
uriSize = 1 + strlen(pURI->protocol) + strlen(pURI->URI_Message);
/* Check if a Smart poster is needed */
if( pURI->Information[0] != '\0' )
{
/* Info : 1+2+info */
infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen(pURI->Information);
/* Total */
totalSize = 4 + uriSize + 4 + infoSize;
if( uriSize > 255 ) totalSize += 3; /* Normal URI size */
if( infoSize > 255 ) totalSize += 3; /* Normal Info size */
/* SmartPoster header */
if( totalSize > 255 )
{
pNDEFMessage[Offset++] = 0xC1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = totalSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0xD1;
pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)totalSize;
}
memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH );
Offset += SMART_POSTER_TYPE_STRING_LENGTH;
}
/* URI header */
pNDEFMessage[Offset] = 0x81;
if( uriSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit
if( pURI->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit
Offset++;
pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH;
if( uriSize > 255 )
{
pNDEFMessage[Offset++] = (uriSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (uriSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (uriSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = uriSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = (uint8_t)uriSize;
}
memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH );
Offset += URI_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = type;
if( type == URI_ID_0x00 ) // No abreviation
{
memcpy( &pNDEFMessage[Offset], pURI->protocol, strlen(pURI->protocol) );
Offset += strlen(pURI->protocol);
}
memcpy( &pNDEFMessage[Offset], pURI->URI_Message, strlen(pURI->URI_Message) );
Offset += strlen(pURI->URI_Message);
/* Information header */
if( pURI->Information[0] != '\0' )
{
if( infoSize > 255 )
{
pNDEFMessage[Offset++] = 0x41;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24;
pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16;
pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8;
pNDEFMessage[Offset++] = infoSize & 0x000000FF;
}
else
{
pNDEFMessage[Offset++] = 0x51;
pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = (uint8_t)infoSize;
}
memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH );
Offset+=TEXT_TYPE_STRING_LENGTH;
pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */
memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH );
Offset += ISO_ENGLISH_CODE_STRING_LENGTH;
/* Information payload */
memcpy( &pNDEFMessage[Offset], pURI->Information, strlen(pURI->Information) );
Offset += strlen(pURI->Information);
}
*size = Offset;
}
/**
* @brief This function write the NDEF file with the URI data given in the structure.
* @param pURI : pointer on structure that contain the URI information.
* @retval NDEF_OK : NDEF file data written in the tag.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteURI( sURI_Info *pURI )
{
uint16_t status = NDEF_ERROR, Offset = 0;
NDEF_PrepareURIMessage( pURI, &NDEF_Buffer[FIRST_RECORD_OFFSET], &Offset );
/* Write NDEF */
NDEF_Buffer[0] = (Offset & 0xFF00) >> 8;
NDEF_Buffer[1] = Offset & 0x00FF;
status = WriteData( 0x00, Offset + FIRST_RECORD_OFFSET, NDEF_Buffer );
return status;
}
char getUriType( char *protocol )
{
if( !memcmp( protocol, URI_ID_0x01_STRING, strlen(URI_ID_0x01_STRING) ) ) return URI_ID_0x01;
else if( !memcmp( protocol, URI_ID_0x02_STRING, strlen(URI_ID_0x02_STRING) ) ) return URI_ID_0x02;
else if( !memcmp( protocol, URI_ID_0x03_STRING, strlen(URI_ID_0x03_STRING) ) ) return URI_ID_0x03;
else if( !memcmp( protocol, URI_ID_0x04_STRING, strlen(URI_ID_0x04_STRING) ) ) return URI_ID_0x04;
else if( !memcmp( protocol, URI_ID_0x05_STRING, strlen(URI_ID_0x05_STRING) ) ) return URI_ID_0x05;
else if( !memcmp( protocol, URI_ID_0x06_STRING, strlen(URI_ID_0x06_STRING) ) ) return URI_ID_0x06;
else if( !memcmp( protocol, URI_ID_0x07_STRING, strlen(URI_ID_0x07_STRING) ) ) return URI_ID_0x07;
else if( !memcmp( protocol, URI_ID_0x08_STRING, strlen(URI_ID_0x08_STRING) ) ) return URI_ID_0x08;
else if( !memcmp( protocol, URI_ID_0x09_STRING, strlen(URI_ID_0x09_STRING) ) ) return URI_ID_0x09;
else if( !memcmp( protocol, URI_ID_0x0A_STRING, strlen(URI_ID_0x0A_STRING) ) ) return URI_ID_0x0A;
else if( !memcmp( protocol, URI_ID_0x0B_STRING, strlen(URI_ID_0x0B_STRING) ) ) return URI_ID_0x0B;
else if( !memcmp( protocol, URI_ID_0x0C_STRING, strlen(URI_ID_0x0C_STRING) ) ) return URI_ID_0x0C;
else if( !memcmp( protocol, URI_ID_0x0D_STRING, strlen(URI_ID_0x0D_STRING) ) ) return URI_ID_0x0D;
else if( !memcmp( protocol, URI_ID_0x0E_STRING, strlen(URI_ID_0x0E_STRING) ) ) return URI_ID_0x0E;
else if( !memcmp( protocol, URI_ID_0x0F_STRING, strlen(URI_ID_0x0F_STRING) ) ) return URI_ID_0x0F;
else if( !memcmp( protocol, URI_ID_0x10_STRING, strlen(URI_ID_0x10_STRING) ) ) return URI_ID_0x10;
else if( !memcmp( protocol, URI_ID_0x11_STRING, strlen(URI_ID_0x11_STRING) ) ) return URI_ID_0x11;
else if( !memcmp( protocol, URI_ID_0x12_STRING, strlen(URI_ID_0x12_STRING) ) ) return URI_ID_0x12;
else if( !memcmp( protocol, URI_ID_0x13_STRING, strlen(URI_ID_0x13_STRING) ) ) return URI_ID_0x13;
else if( !memcmp( protocol, URI_ID_0x14_STRING, strlen(URI_ID_0x14_STRING) ) ) return URI_ID_0x14;
else if( !memcmp( protocol, URI_ID_0x15_STRING, strlen(URI_ID_0x15_STRING) ) ) return URI_ID_0x15;
else if( !memcmp( protocol, URI_ID_0x16_STRING, strlen(URI_ID_0x16_STRING) ) ) return URI_ID_0x16;
else if( !memcmp( protocol, URI_ID_0x17_STRING, strlen(URI_ID_0x17_STRING) ) ) return URI_ID_0x17;
else if( !memcmp( protocol, URI_ID_0x18_STRING, strlen(URI_ID_0x18_STRING) ) ) return URI_ID_0x18;
else if( !memcmp( protocol, URI_ID_0x19_STRING, strlen(URI_ID_0x19_STRING) ) ) return URI_ID_0x19;
else if( !memcmp( protocol, URI_ID_0x1A_STRING, strlen(URI_ID_0x1A_STRING) ) ) return URI_ID_0x1A;
else if( !memcmp( protocol, URI_ID_0x1B_STRING, strlen(URI_ID_0x1B_STRING) ) ) return URI_ID_0x1B;
else if( !memcmp( protocol, URI_ID_0x1C_STRING, strlen(URI_ID_0x1C_STRING) ) ) return URI_ID_0x1C;
else if( !memcmp( protocol, URI_ID_0x1D_STRING, strlen(URI_ID_0x1D_STRING) ) ) return URI_ID_0x1D;
else if( !memcmp( protocol, URI_ID_0x1E_STRING, strlen(URI_ID_0x1E_STRING) ) ) return URI_ID_0x1E;
else if( !memcmp( protocol, URI_ID_0x1F_STRING, strlen(URI_ID_0x1F_STRING) ) ) return URI_ID_0x1F;
else if( !memcmp( protocol, URI_ID_0x20_STRING, strlen(URI_ID_0x20_STRING) ) ) return URI_ID_0x20;
else if( !memcmp( protocol, URI_ID_0x21_STRING, strlen(URI_ID_0x21_STRING) ) ) return URI_ID_0x21;
else if( !memcmp( protocol, URI_ID_0x22_STRING, strlen(URI_ID_0x22_STRING) ) ) return URI_ID_0x22;
else if( !memcmp( protocol, URI_ID_0x23_STRING, strlen(URI_ID_0x23_STRING) ) ) return URI_ID_0x23;
else return URI_ID_0x00; // No abreviation for this protocol
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

62
src/lib_NDEF_URI.h Normal file
View File

@@ -0,0 +1,62 @@
/**
******************************************************************************
* @file lib_NDEF_URI.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage URI NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_URI_H
#define __LIB_NDEF_URI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
typedef struct
{
char protocol[80];
char URI_Message[400];
char Information[400];
}sURI_Info;
typedef struct sRecordInfo sRecordInfo_uri;
uint16_t NDEF_ReadURI(sRecordInfo_uri *pRecordStruct, sURI_Info *pURI);
uint16_t NDEF_WriteURI(sURI_Info *pURI);
void NDEF_PrepareURIMessage( sURI_Info *pURI, uint8_t *pNDEFMessage, uint16_t *size );
char getUriType( char *protocol );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_URI_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

389
src/lib_NDEF_Vcard.cpp Normal file
View File

@@ -0,0 +1,389 @@
/**
******************************************************************************
* @file lib_NDEF_Vcard.c
* @author MMY Application Team
* @version $Revision: 1330 $
* @date $Date: 2015-11-05 10:39:11 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage NDEF file that represent Vcard.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF_Vcard.h"
/** @addtogroup NFC_libraries
* @{
* @brief <b>This is the library used to manage the content of the TAG (data)
* But also the specific feature of the tag, for instance
* password, gpo... </b>
*/
/** @addtogroup libNFC_FORUM
* @{
* @brief This part of the library manage data which follow NFC forum organisation.
*/
/**
* @brief This buffer contains the data send/received by TAG
*/
extern uint8_t NDEF_Buffer [];
/** @defgroup libVcard_Private_Functions
* @{
*/
static void NDEF_FillVcardStruct( uint8_t* pPayload, uint32_t PayloadSize, char* pKeyWord, uint32_t SizeOfKeyWord, uint8_t* pString );
static void NDEF_ExtractVcard( sRecordInfo_vcard *pRecordStruct, sVcardInfo *pVcardStruct );
/**
* @brief This function fill Vcard structure with information of NDEF message.
* @param pPayload : pointer on the payload data of the NDEF message.
* @param PayloadSize : number of data in the payload.
* @param pKeyWord : pointer on the keyword to look for.
* @param SizeOfKeyWord : number of byte of the keyword we are looking for.
* @param pString : Pointer on the data string to fill.
*/
static void NDEF_FillVcardStruct( uint8_t* pPayload, uint32_t PayloadSize, char* pKeyWord, uint32_t SizeOfKeyWord, uint8_t* pString )
{
uint8_t* pLastByteAdd, *pLook4Word, *pEndString;
/* First character force to NULL in case not matching found */
*pString = 0;
/* Interresting information are stored before picture if any */
/* Moreover picture is not used in this demonstration SW */
pLastByteAdd = pPayload;
while( memcmp( pLastByteAdd, JPEG, JPEG_STRING_SIZE ) && (pLastByteAdd < (pPayload + PayloadSize)) )
{
pLastByteAdd++;
}
pLook4Word = pPayload;
while( memcmp( pLook4Word, pKeyWord, SizeOfKeyWord ) && (pLook4Word < pLastByteAdd) )
{
pLook4Word++;
}
/* Word found */
if( pLook4Word != pLastByteAdd )
{
pLook4Word += SizeOfKeyWord;
pEndString = pLook4Word;
while( memcmp( pEndString, LIMIT, LIMIT_STRING_SIZE ) && (pEndString < pLastByteAdd) )
{
pEndString++;
}
if( pEndString != pLastByteAdd )
{
memcpy( pString, pLook4Word, pEndString-pLook4Word );
/* add end of string character */
pString += pEndString - pLook4Word;
*pString = '\0';
}
}
}
/**
* @brief This function read the Vcard and store data in a structure.
* @param pRecordStruct : Pointer on the record structure.
* @param pSMSStruct : pointer on the structure to fill.
*/
static void NDEF_ExtractVcard( sRecordInfo_vcard *pRecordStruct, sVcardInfo *pVcardStruct )
{
uint32_t PayloadSize;
uint8_t* pPayload;
PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3) << 24) | ((uint32_t)(pRecordStruct->PayloadLength2) << 16) |
((uint32_t)(pRecordStruct->PayloadLength1) << 8) | pRecordStruct->PayloadLength0;
/* Read record header */
pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd);
NDEF_FillVcardStruct( pPayload, PayloadSize, VERSION, VERSION_STRING_SIZE, (uint8_t*)(pVcardStruct->Version) );
if( !memcmp( pVcardStruct->Version, VCARD_VERSION_2_1, VCARD_VERSION_2_1_SIZE ) )
{
NDEF_FillVcardStruct( pPayload, PayloadSize, FIRSTNAME, FIRSTNAME_STRING_SIZE, (uint8_t*)(pVcardStruct->FirstName) );
NDEF_FillVcardStruct( pPayload, PayloadSize, TITLE, TITLE_STRING_SIZE, (uint8_t*)(pVcardStruct->Title) );
NDEF_FillVcardStruct( pPayload, PayloadSize, ORG, ORG_STRING_SIZE, (uint8_t*)(pVcardStruct->Org) );
NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_ADDRESS, HOME_ADDRESS_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeAddress) );
NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_ADDRESS, WORK_ADDRESS_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkAddress) );
NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_TEL, HOME_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeTel) );
NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_TEL, WORK_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkTel) );
NDEF_FillVcardStruct( pPayload, PayloadSize, CELL_TEL, CELL_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->CellTel) );
NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_EMAIL, HOME_EMAIL_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeEmail) );
NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_EMAIL, WORK_EMAIL_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkEmail) );
}
else if( !memcmp( pVcardStruct->Version, VCARD_VERSION_3_0, VCARD_VERSION_3_0_SIZE ) )
{
/* need to be implemented */
}
else
{
/* maybe new version but not supported in this sw */
}
}
/**
* @}
*/
/** @defgroup libVcard_Public_Functions
* @{
* @brief This file is used to manage Vcard (stored or loaded in tag)
*/
/**
* @brief This function read NDEF and retrieve Vcard information if any.
* @param pRecordStruct : Pointer on the record structure.
* @param pVcardStruct : pointer on the structure to fill.
* @retval NDEF_OK : Vcard information from NDEF have been retrieved.
* @retval NDEF_ERROR : Not able to retrieve Vcard information.
*/
uint16_t NDEF_ReadVcard( sRecordInfo_vcard *pRecordStruct, sVcardInfo *pVcardStruct )
{
uint16_t status = NDEF_ERROR;
if( pRecordStruct->NDEF_Type == VCARD_TYPE )
{
NDEF_ExtractVcard( pRecordStruct, pVcardStruct );
status = NDEF_OK;
}
return status;
}
/**
* @brief This function write the NDEF file with the Vcard data given in the structure.
* @param pVcardStruct : pointer on structure that contain the Vcard information.
* @retval NDEF_OK : NDEF file data written in the tag.
* @retval NDEF_ERROR : not able to store NDEF in tag.
* @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
* @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
* @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
* @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
*/
uint16_t NDEF_WriteVcard( sVcardInfo *pVcardStruct )
{
uint16_t status = NDEF_ERROR, Offset = 0;
NDEF_PrepareVcardMessage( pVcardStruct, &NDEF_Buffer[FIRST_RECORD_OFFSET], &Offset );
/* Write NDEF */
NDEF_Buffer[0] = (Offset & 0xFF00) >> 8;
NDEF_Buffer[1] = Offset & 0x00FF;
status = WriteData( 0x00, Offset + FIRST_RECORD_OFFSET, NDEF_Buffer );
return status;
}
/**
* @brief This function write the NDEF file with the Vcard data given in the structure.
* @param pVcardStruct : pointer on structure that contain the Vcard information.
* @param pNDEFMessage : pointer on the NDEF message.
* @param size : to store the size of the NDEF message generated.
*/
void NDEF_PrepareVcardMessage( sVcardInfo *pVcardStruct, uint8_t *pNDEFMessage, uint16_t *size )
{
uint32_t PayloadSize = 0;
/* Vcard Record Header */
/************************************/
/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */
/*----------------------------------*/
/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=0 TNF=2 NFC Forum Media type*/
/*----------------------------------*/
/* TYPE LENGTH */
/*----------------------------------*/
/* PAYLOAD LENGTH 3 */
/*----------------------------------*/
/* PAYLOAD LENGTH 2 */
/*----------------------------------*/
/* PAYLOAD LENGTH 1 */
/*----------------------------------*/
/* PAYLOAD LENGTH 0 */
/*----------------------------------*/
/* ID LENGTH */ /* <---- Not Used */
/*----------------------------------*/
/* TYPE */
/*----------------------------------*/
/* ID */ /* <---- Not Used */
/************************************/
/* As we don't have embedded a jpeg encoder/decoder in this firmware */
/* We have made the choice to manage only string content of the vCard */
/* For demonstration purpose in order to fill the 8kB of the M24SR */
/* We have embedded a NDEF vCard in the STM32 to be able to fill M24SR */
/* fill record header */
pNDEFMessage[0] = 0xC2; /* Record Flag */
pNDEFMessage[1] = VCARD_TYPE_STRING_LENGTH;
pNDEFMessage[2] = 0x00; /* Will be filled at the end when payload size is known */
pNDEFMessage[3] = 0x00;
pNDEFMessage[4] = 0x00;
pNDEFMessage[5] = 0x00;
memcpy( &pNDEFMessage[6], VCARD_TYPE_STRING, VCARD_TYPE_STRING_LENGTH );
/* Payload is positionned in the NDEF after record header */
PayloadSize = 6 + VCARD_TYPE_STRING_LENGTH;
/* "BEGIN:VCARD\r\n" */
memcpy( &pNDEFMessage[PayloadSize], BEGIN, BEGIN_STRING_SIZE );
PayloadSize += BEGIN_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], VCARD,VCARD_STRING_SIZE );
PayloadSize += VCARD_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "VERSION:2.1\r\n" */
memcpy( &pNDEFMessage[PayloadSize], VERSION, VERSION_STRING_SIZE );
PayloadSize += VERSION_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], VCARD_VERSION_2_1, VCARD_VERSION_2_1_SIZE );
PayloadSize += VCARD_VERSION_2_1_SIZE;
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "FN:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], FIRSTNAME, FIRSTNAME_STRING_SIZE );
PayloadSize += FIRSTNAME_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->FirstName, strlen(pVcardStruct->FirstName) );
PayloadSize += strlen( pVcardStruct->FirstName );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "TITLE:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], TITLE, TITLE_STRING_SIZE );
PayloadSize += TITLE_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Title, strlen(pVcardStruct->Title) );
PayloadSize += strlen( pVcardStruct->Title );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "ORG:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], ORG, ORG_STRING_SIZE );
PayloadSize += ORG_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Org, strlen(pVcardStruct->Org) );
PayloadSize += strlen( pVcardStruct->Org );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "ADR;HOME:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], HOME_ADDRESS, HOME_ADDRESS_STRING_SIZE );
PayloadSize += HOME_ADDRESS_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeAddress, strlen(pVcardStruct->HomeAddress) );
PayloadSize += strlen( pVcardStruct->HomeAddress );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "ADR;WORK:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], WORK_ADDRESS, WORK_ADDRESS_STRING_SIZE );
PayloadSize += WORK_ADDRESS_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkAddress, strlen(pVcardStruct->WorkAddress) );
PayloadSize += strlen( pVcardStruct->WorkAddress );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "TEL;HOME:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], HOME_TEL, HOME_TEL_STRING_SIZE );
PayloadSize += HOME_TEL_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeTel, strlen(pVcardStruct->HomeTel) );
PayloadSize += strlen( pVcardStruct->HomeTel );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "TEL;WORK:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], WORK_TEL, WORK_TEL_STRING_SIZE );
PayloadSize += WORK_TEL_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkTel, strlen(pVcardStruct->WorkTel) );
PayloadSize += strlen( pVcardStruct->WorkTel );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "TEL;CELL:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], CELL_TEL, CELL_TEL_STRING_SIZE );
PayloadSize += CELL_TEL_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->CellTel, strlen(pVcardStruct->CellTel) );
PayloadSize += strlen( pVcardStruct->CellTel );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "EMAIL;HOME:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], HOME_EMAIL, HOME_EMAIL_STRING_SIZE );
PayloadSize += HOME_EMAIL_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeEmail, strlen(pVcardStruct->HomeEmail) );
PayloadSize += strlen( pVcardStruct->HomeEmail );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "EMAIL;WORK:\r\n" */
memcpy( &pNDEFMessage[PayloadSize], WORK_EMAIL, WORK_EMAIL_STRING_SIZE );
PayloadSize += WORK_EMAIL_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkEmail, strlen(pVcardStruct->WorkEmail) );
PayloadSize += strlen( pVcardStruct->WorkEmail );
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
/* "END:VCARD\r\n" */
memcpy( &pNDEFMessage[PayloadSize], END, END_STRING_SIZE );
PayloadSize += END_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], VCARD, VCARD_STRING_SIZE );
PayloadSize += VCARD_STRING_SIZE;
memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
PayloadSize += LIMIT_STRING_SIZE;
*size = (uint16_t)(PayloadSize); /* Must not count the 2 byte that represent the NDEF size */
PayloadSize -= 6 + VCARD_TYPE_STRING_LENGTH;
pNDEFMessage[2] = (PayloadSize & 0xFF000000) >> 24;
pNDEFMessage[3] = (PayloadSize & 0x00FF0000) >> 16;
pNDEFMessage[4] = (PayloadSize & 0x0000FF00) >> 8;
pNDEFMessage[5] = PayloadSize & 0x000000FF;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

114
src/lib_NDEF_Vcard.h Normal file
View File

@@ -0,0 +1,114 @@
/**
******************************************************************************
* @file lib_NDEF_Vcard.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to manage Vcard NDEF file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_NDEF_VCARD_H
#define __LIB_NDEF_VCARD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_NDEF.h"
#define VCARD_VERSION_2_1 "2.1"
#define VCARD_VERSION_2_1_SIZE 3
#define VCARD_VERSION_3_0 "3.0"
#define VCARD_VERSION_3_0_SIZE 3
#define BEGIN "BEGIN:"
#define VCARD "VCARD"
#define VERSION "VERSION:"
#define FIRSTNAME "FN:"
#define HOME_TEL "TEL;HOME:"
#define WORK_TEL "TEL;WORK:"
#define CELL_TEL "TEL;CELL:"
#define HOME_EMAIL "EMAIL;HOME:"
#define WORK_EMAIL "EMAIL;WORK:"
#define HOME_ADDRESS "ADR;HOME:"
#define WORK_ADDRESS "ADR;WORK:"
#define TITLE "TITLE:"
#define ORG "ORG:"
#define END "END:"
#define JPEG "JPEG"
#define LIMIT "\r\n"
#define BEGIN_STRING_SIZE 6
#define VCARD_STRING_SIZE 5
#define VERSION_STRING_SIZE 8
#define FIRSTNAME_STRING_SIZE 3
#define HOME_TEL_STRING_SIZE 9
#define WORK_TEL_STRING_SIZE 9
#define CELL_TEL_STRING_SIZE 9
#define HOME_EMAIL_STRING_SIZE 11
#define WORK_EMAIL_STRING_SIZE 11
#define HOME_ADDRESS_STRING_SIZE 9
#define WORK_ADDRESS_STRING_SIZE 9
#define TITLE_STRING_SIZE 6
#define ORG_STRING_SIZE 4
#define END_STRING_SIZE 4
#define JPEG_STRING_SIZE 4
#define LIMIT_STRING_SIZE 2
typedef struct
{
char Version [10];
char FirstName[80];
char Title[80];
char Org[80];
char HomeAddress[80];
char WorkAddress[80];
char HomeTel[40];
char WorkTel[40];
char CellTel[40];
char HomeEmail[80];
char WorkEmail[80];
}sVcardInfo;
/* Struct defined in lib_NDEF.h */
typedef struct sRecordInfo sRecordInfo_vcard;
uint16_t NDEF_ReadVcard( sRecordInfo_vcard *pRecordStruct, sVcardInfo *pVcardStruct );
uint16_t NDEF_WriteVcard( sVcardInfo *pVcardStruct );
void NDEF_PrepareVcardMessage( sVcardInfo *pVcardStruct, uint8_t *pNDEFMessage, uint16_t *size );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_NDEF_VCARD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

137
src/lib_iso14443A.h Normal file
View File

@@ -0,0 +1,137 @@
/**
******************************************************************************
* @file lib_iso14443A.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief ISO14443A common constants
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------------------------*/
#ifndef __ISO14443A_H
#define __ISO14443A_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
#include "stdbool.h"
/* status and error code ---------------------------------------------------------------------- */
#define ISO14443A_SUCCESSCODE RESULTOK
#define ISO14443A_ERRORCODE_DEFAULT 0x61
#define ISO14443A_ERRORCODE_CRC 0x62
/* Anticollison levels (commands) ------------------------------------------------------------- */
#define SEL_CASCADE_LVL_1 0x93
#define SEL_CASCADE_LVL_2 0x95
#define SEL_CASCADE_LVL_3 0x97
#define COMMAND_REQA 0x26
#define COMMAND_WUPA 0x52
#define COMMAND_SELECT_LV1 0x93
#define COMMAND_SELECT_LV2 0x95
#define COMMAND_SELECT_LV3 0x97
#define COMMAND_HLTA 0x50
#define COMMAND_RATS 0xE0
#define COMMAND_PPS 0xD0
#define COMMAND_DESELECT 0xC2
#define COMMAND_DESELECTCID 0xCA
/* Iblock ------------------------------------------------------------------------------------- */
#define COMMAND_IBLOCK02 0x02
#define COMMAND_IBLOCK03 0x03
#define COMMAND_SBLOCK 0xC2
#define COMMAND_NACKBLOCK_B2 0xB2
#define COMMAND_NACKBLOCK_B3 0xB3
#define COMMAND_ACKBLOCK 0xA2
/* numbr of the cascade level ----------------------------------------------------------------- */
#define CASCADE_LVL_1 1
#define CASCADE_LVL_2 2
#define CASCADE_LVL_3 3
#define ISO14443A_NVM_10 0x10
#define ISO14443A_NVM_20 0x20
#define ISO14443A_NVM_30 0x30
#define ISO14443A_NVM_40 0x40
#define ISO14443A_NVM_50 0x50
#define ISO14443A_NVM_60 0x60
#define ISO14443A_NVM_70 0x70
/* UID Sizes ---------------------------------------------------------------------------------- */
#define ISO14443A_UIDSIZE_UNDEFINED -1
#define ISO14443A_UID_PART 3
#define ISO14443A_UID_SINGLE_SIZE 4
#define ISO14443A_UID_DOUBLE_SIZE 7
#define ISO14443A_UID_TRIPLE_SIZE 10
/* Mask used for ATQA ------------------------------------------------------------------------ */
#define ISO14443A_UID_MASK 0xC0
#define ISO14443A_AC_BIT_FRAME_MASK 0x1F
#define ISO14443A_CID_MASK 0x0F
#define ISO14443A_FSDI_MASK 0xF0
/* Size for ISO14443A variables ------------------------------------------------------------- */
#define ISO14443A_MAX_NAME_SIZE 50
#define ISO14443A_MAX_UID_SIZE 10
#define ISO14443A_ATQA_SIZE 2
/* SAK FLAG --------------------------------------------------------------------------------- */
#define SAK_FLAG_ATS_SUPPORTED 0x20
#define SAK_FLAG_UID_NOT_COMPLETE 0x04
/* ATQ FLAG */
#define ATQ_FLAG_UID_SINGLE_SIZE 0
#define ATQ_FLAG_UID_DOUBLE_SIZE 1
#define ATQ_FLAG_UID_TRIPLE_SIZE 2
typedef struct{
/* ATQA answer to request of type A*/
uint8_t ATQA[ISO14443A_ATQA_SIZE];
uint8_t CascadeLevel;
/* UID : unique Identification*/
uint8_t UIDsize;
uint8_t UID[ISO14443A_MAX_UID_SIZE];
/* SAK : Select acknowledge*/
uint8_t SAK;
bool ATSSupported;
bool IsDetected;
char LogMsg[120];
uint8_t CID,
FSDI,
DRI,
NFC_DSI;
}ISO14443A_CARD;
#ifdef __cplusplus
}
#endif
#endif /* __ISO14443A_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

993
src/lib_iso14443Apcd.cpp Normal file
View File

@@ -0,0 +1,993 @@
/**
******************************************************************************
* @file lib_iso14443Apcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso14443A communication
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "Arduino.h"
#include "lib_iso14443Apcd.h"
extern PCD_PROTOCOL TechnoSelected;
extern IC_VERSION IcVers;
/* --------------------------------------------------
* code templates for ISO14443A protocol
* command = Command code | Length | data(Le)
* -------------------------------------------------- */
#define PCD_TYPEA_TIMERW 0x5A
/****************** PCD ******************/
/* ISO14443A */
#define PCD_TYPEA_ARConfigA 0x01
#define PCD_TYPEA_ARConfigB 0xDF
static const uint8_t TOPAZ[] = {SEND_RECEIVE, 0x08, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8};
static u8 MultiID[200] = {0};
static u8 MultiIDPart2[64] = {0};
static u8 RemainingID = 0;
uint16_t FSC = 32;
uint16_t FWI = 4; /* Default value */
ISO14443A_CARD ISO14443A_Card;
extern uint8_t u95HFBuffer [RFTRANS_95HF_MAX_BUFFER_SIZE+3];
uint8_t u95HFBufferAntiCol [RFTRANS_95HF_MAX_BUFFER_SIZE+3];
/* Variables for the different modes */
extern DeviceMode_t devicemode;
extern TagType_t nfc_tagtype;
static void ISO14443A_InitStructure( void );
static uint16_t FSCIToFSC(uint8_t FSCI);
static int8_t ISO14443A_REQA( uint8_t *pDataRead );
static int8_t ISO14443A_HLTA( uint8_t *pDataRead );
static int8_t ISO14443A_RATS( uint8_t *pDataRead );
#if 0
static int8_t ISO14443A_PPS( uint8_t *pDataRead );
#endif
static int8_t ISO14443A_AC( uint8_t *pDataRead, u8 CascadeLevel );
static int8_t ISO14443A_ACLevel1 ( uint8_t *pDataRead );
static int8_t ISO14443A_ACLevel2 ( uint8_t *pDataRead );
static int8_t ISO14443A_ACLevel3 ( uint8_t *pDataRead );
static void ISO14443A_CompleteStructure ( uint8_t *pATQA );
static int8_t ISO14443A_MultiAnticollision( void );
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup ISO14443A_pcd
* @{
* @brief This part of the library is used to follow ISO14443A.
*/
/** @addtogroup lib_iso14443Apcd_Private_Functions
* @{
*/
/**
* @brief Reset the ISO14443A data structure
* @param void
* @return void
*/
static void ISO14443A_InitStructure( void )
{
/* Initializes the data structure used to store results */
memset(ISO14443A_Card.ATQA, 0x00, ISO14443A_ATQA_SIZE);
memset(ISO14443A_Card.UID , 0x00, ISO14443A_MAX_UID_SIZE);
ISO14443A_Card.CascadeLevel = 0;
ISO14443A_Card.UIDsize = 0;
ISO14443A_Card.ATSSupported = false;
ISO14443A_Card.IsDetected = false;
}
/**
* @brief this functions convert FSCI to FSC
* @param FSCI : FSCI value
* @return FSC
*/
static uint16_t FSCIToFSC(uint8_t FSCI)
{
if (FSCI == 0) return 16;
else if (FSCI == 1) return 24;
else if (FSCI == 2) return 32;
else if (FSCI == 3) return 40;
else if (FSCI == 4) return 48;
else if (FSCI == 5) return 64;
else if (FSCI == 6) return 96;
else if (FSCI == 7) return 128;
else return 256;
}
/**
* @brief this functions sends the REQA command to the PCD device
* @param *pDataRead : Pointer to the PCD response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_REQA( uint8_t *pDataRead )
{
const uint8_t ReqA[] = { 0x26, 0x07};
int8_t status;
/* sends the command to the PCD device*/
errchk(PCD_SendRecv(0x02,ReqA,pDataRead));
/* retrieves the ATQA response */
memcpy(ISO14443A_Card.ATQA, &pDataRead[PCD_DATA_OFFSET], ISO14443A_ATQA_SIZE);
/* completes the strucure according to the ATQA response */
ISO14443A_CompleteStructure ( ISO14443A_Card.ATQA );
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief This functions manage the anticollision
* @param *pDataRead : Pointer to the PCD response
* @param CascadeLevel : information on the current cascade level
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_AC( uint8_t *pDataRead, u8 CascadeLevel )
{
u8 AnticolParameter [7] = {0x00, ISO14443A_NVM_20, 0x08,0x00,0x00,0x00,0x00};
u8 NbResponseByte = 0;
u8 NbResponseByteOrigin = 0;
u8 Collision = 0;
u8 ByteCollisionIndex = 0;
u8 BitCollisionIndex = 0;
u8 RemainingBit = 0;
u8 NewByteCollisionIndex = 0;
u8 NewBitCollisionIndex = 0;
u8 UID[4] = {0x00,0x00,0x00,0x00};
int8_t status;
/* prepare command regarding cascade level on-going */
AnticolParameter[0] = CascadeLevel;
/* sends the command to the PCD device*/
errchk(PCD_SendRecv(0x03,AnticolParameter,pDataRead));
NbResponseByte = pDataRead[1];
NbResponseByteOrigin = NbResponseByte;
Collision = (pDataRead[NbResponseByte-1] & 0x80);
ByteCollisionIndex = pDataRead[NbResponseByte];
BitCollisionIndex = pDataRead[NbResponseByte+1];
/* case that should not happend, as occurs because we have miss another collision */
if( BitCollisionIndex == 8)
{
return ISO14443A_ERRORCODE_DEFAULT;
}
/* check for collision (Tag of different UID length at the same time not managed so far) */
while( Collision == 0x80)
{
/* clear collision detection */
Collision = 0x00;
/* send the command to the PCD device*/
AnticolParameter[1] = ISO14443A_NVM_20 + ((ByteCollisionIndex) <<4) + (BitCollisionIndex+1);
if( ByteCollisionIndex == 0)
{
AnticolParameter[2] = pDataRead[2] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */
AnticolParameter[3] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */
UID [0] = AnticolParameter[2];
}
else if( ByteCollisionIndex == 1)
{
AnticolParameter[2] = pDataRead[2];
AnticolParameter[3] = pDataRead[3] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */
AnticolParameter[4] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */
UID [0] = AnticolParameter[2];
UID [1] = AnticolParameter[3];
}
else if( ByteCollisionIndex == 2)
{
AnticolParameter[2] = pDataRead[2];
AnticolParameter[3] = pDataRead[3];
AnticolParameter[4] = pDataRead[4] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */
AnticolParameter[5] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */;
UID [0] = AnticolParameter[2];
UID [1] = AnticolParameter[3];
UID [2] = AnticolParameter[4];
}
else if( ByteCollisionIndex == 3)
{
AnticolParameter[2] = pDataRead[2];
AnticolParameter[3] = pDataRead[3];
AnticolParameter[4] = pDataRead[4];
AnticolParameter[5] = pDataRead[5] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */
AnticolParameter[6] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */;
UID [0] = AnticolParameter[2];
UID [1] = AnticolParameter[3];
UID [2] = AnticolParameter[4];
UID [3] = AnticolParameter[5];
}
else
return ISO14443A_ERRORCODE_DEFAULT;
/* send part of the UID */
PCD_SendRecv((0x03+ByteCollisionIndex+1),AnticolParameter,pDataRead);
if(pDataRead[0] != 0x80)
return ISO14443A_ERRORCODE_DEFAULT;
/* check if there is another collision to take into account*/
NbResponseByte = pDataRead[1];
Collision = (pDataRead[NbResponseByte-1]) & 0x80;
if ( Collision == 0x80)
{
NewByteCollisionIndex = pDataRead[NbResponseByte];
NewBitCollisionIndex = pDataRead[NbResponseByte+1];
}
/* we can check that non-alignement is the one expected */
RemainingBit = 8 - (0x0F & (pDataRead[2+(NbResponseByte-2)-1]));
if( RemainingBit == BitCollisionIndex+1)
{
/* recreate the good UID */
if( ByteCollisionIndex == 0)
{
UID [0] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[2]) | pDataRead[2] ;
UID [1] = pDataRead[3];
UID [2] = pDataRead[4];
UID [3] = pDataRead[5];
}
else if( ByteCollisionIndex == 1)
{
UID [1] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[3]) | pDataRead[2] ;
UID [2] = pDataRead[3];
UID [3] = pDataRead[4];
}
else if( ByteCollisionIndex == 2)
{
UID [2] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[4]) | pDataRead[2] ;
UID [3] = pDataRead[3];
}
else if( ByteCollisionIndex == 3)
{
UID [3] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[5]) | pDataRead[2] ;
}
else
return ISO14443A_ERRORCODE_DEFAULT;
}
else
return ISO14443A_ERRORCODE_DEFAULT;
/* prepare the buffer expected by the caller */
pDataRead[0] = 0x80;
pDataRead[1] = NbResponseByteOrigin;
pDataRead[2] = UID [0];
pDataRead[3] = UID [1];
pDataRead[4] = UID [2];
pDataRead[5] = UID [3];
pDataRead[6] = UID[0]^UID[1]^UID[2]^UID[3];
/* if collision was detected restart anticol */
if ( Collision == 0x80)
{
if( ByteCollisionIndex != NewByteCollisionIndex )
{
ByteCollisionIndex += NewByteCollisionIndex;
BitCollisionIndex = NewBitCollisionIndex;
}
else
{
ByteCollisionIndex += NewByteCollisionIndex;
BitCollisionIndex += (NewBitCollisionIndex+1);
}
}
}
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief this function carries out the first level of the anticollision
* @param *pDataRead : Pointer to the PCD response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_ACLevel1( uint8_t *pDataRead )
{
uint8_t *pDataToSend = &(u95HFBuffer[PCD_DATA_OFFSET]),
Length = 0,
BccByte ;
int8_t status;
/* Perform anti-collision */
errchk(ISO14443A_AC(pDataRead, SEL_CASCADE_LVL_1));
/* Saves the UID in the structure */
if(ISO14443A_Card.UIDsize == ISO14443A_UID_SINGLE_SIZE)
{
memcpy( ISO14443A_Card.UID, &pDataRead[PCD_DATA_OFFSET], ISO14443A_UID_SINGLE_SIZE );
}
else
{
memcpy(ISO14443A_Card.UID, &pDataRead[PCD_DATA_OFFSET+1], ISO14443A_UID_PART);
}
/* copies the BCC byte of the card response*/
BccByte = pDataRead[PCD_DATA_OFFSET + ISO14443A_UID_SINGLE_SIZE ];
/* Preparing the buffer who contains the SELECT command */
pDataToSend[Length ++] = SEL_CASCADE_LVL_1;
pDataToSend[Length ++] = ISO14443A_NVM_70;
/* Inserts the previous reply in the next command */
if(ISO14443A_Card.UIDsize == ISO14443A_UID_SINGLE_SIZE)
{
memcpy(&pDataToSend[Length], ISO14443A_Card.UID, ISO14443A_UID_SINGLE_SIZE );
Length += ISO14443A_UID_SINGLE_SIZE ;
}
else
{
pDataToSend[Length ++] = 0x88;
memcpy(&pDataToSend[Length], ISO14443A_Card.UID, ISO14443A_UID_PART );
Length += ISO14443A_UID_PART ;
}
pDataToSend[Length ++] = BccByte;
/* Add the control byte : Append the CRC + 8 bits in first byte (standard frame)*/
pDataToSend[Length ++] = PCD_ISO14443A_APPENDCRC | PCD_ISO14443A_A8BITSINFIRSTBYTE;
errchk(PCD_SendRecv(Length,pDataToSend,pDataRead));
/* Recovering SAK byte */
ISO14443A_Card.SAK = pDataRead[PCD_DATA_OFFSET];
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief this function carries out the second level of the anticollision
* @param *pDataRead : Pointer to the PCD response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_ACLevel2( uint8_t *pDataRead )
{
uint8_t *pDataToSend = &(u95HFBuffer[PCD_DATA_OFFSET]),
Length = 0,
BccByte ;
int8_t status;
/* Perform anti-collision */
errchk(ISO14443A_AC(pDataRead, SEL_CASCADE_LVL_2));
//errchk(PCD_SendRecv(0x03,AnnticolParameter,pDataRead));
/* Copies the UID into the data structure */
if(ISO14443A_Card.UIDsize == ISO14443A_UID_DOUBLE_SIZE)
{
memcpy(&ISO14443A_Card.UID[ISO14443A_UID_PART], &pDataRead[PCD_DATA_OFFSET], ISO14443A_UID_SINGLE_SIZE);
}
else
{
memcpy(&ISO14443A_Card.UID[ISO14443A_UID_PART], &pDataRead[PCD_DATA_OFFSET+1], ISO14443A_UID_PART);
}
/* copies the BCC byte of the card response*/
BccByte = pDataRead[PCD_DATA_OFFSET + ISO14443A_UID_SINGLE_SIZE ];
/* Preparing the buffer who contains the SELECT command */
pDataToSend[Length ++] = SEL_CASCADE_LVL_2;
pDataToSend[Length ++] = ISO14443A_NVM_70;
/* Copies the UID into the data structure */
if(ISO14443A_Card.UIDsize == ISO14443A_UID_DOUBLE_SIZE)
{
memcpy(&(pDataToSend[Length]),&(ISO14443A_Card.UID[ISO14443A_UID_PART]) , ISO14443A_UID_SINGLE_SIZE);
Length += ISO14443A_UID_SINGLE_SIZE ;
}
else
{
pDataToSend[Length ++] = 0x88;
memcpy(&(pDataToSend[Length]),&(ISO14443A_Card.UID[ISO14443A_UID_PART]) , ISO14443A_UID_PART);
Length += ISO14443A_UID_PART ;
}
pDataToSend[Length ++] = BccByte;
/* Add the control byte : Append the CRC + 8 bits in first byte (standard frame)*/
pDataToSend[Length ++] = PCD_ISO14443A_APPENDCRC | PCD_ISO14443A_A8BITSINFIRSTBYTE;
/* emit the select command */
errchk(PCD_SendRecv(Length,pDataToSend,pDataRead));
/* Recovering SAK byte */
ISO14443A_Card.SAK = pDataRead[PCD_DATA_OFFSET];
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief this function carries out the second level of the anticollision
* @param *pDataRead : Pointer to the PCD response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_ACLevel3 ( uint8_t *pDataRead )
{
uint8_t *pDataToSend = &(u95HFBuffer[PCD_DATA_OFFSET]),
Length = 0,
BccByte ;
int8_t status;
/* Perform anti-collision */
errchk(ISO14443A_AC(pDataRead, SEL_CASCADE_LVL_3));
/* Copies the UID into the data structure */
memcpy(&ISO14443A_Card.UID[ISO14443A_UID_PART], &pDataRead[PCD_DATA_OFFSET], ISO14443A_UID_SINGLE_SIZE);
/* copies the BCC byte of the card response*/
BccByte = pDataRead[PCD_DATA_OFFSET + ISO14443A_UID_SINGLE_SIZE ];
/* Preparing the buffer who contains the SELECT command */
pDataToSend[Length ++] = SEL_CASCADE_LVL_3;
pDataToSend[Length ++] = ISO14443A_NVM_70;
/* Copies the UID into the data structure */
if(ISO14443A_Card.UIDsize == ISO14443A_UID_TRIPLE_SIZE)
{
memcpy(&(pDataToSend[Length]),&(ISO14443A_Card.UID[ISO14443A_UID_PART]) , ISO14443A_UID_SINGLE_SIZE);
Length += ISO14443A_UID_SINGLE_SIZE ;
}
pDataToSend[Length ++] = BccByte;
/* Add the control byte : Append the CRC + 8 bits in first byte (standard frame)*/
pDataToSend[Length ++] = PCD_ISO14443A_APPENDCRC | PCD_ISO14443A_A8BITSINFIRSTBYTE;
/* emitthe select command */
errchk(PCD_SendRecv(Length,pDataToSend,pDataRead));
/* Recovering SAK byte */
ISO14443A_Card.SAK = pDataRead[PCD_DATA_OFFSET];
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief this functions sends the HLTA command to the PCD device
* @param *pDataRead : Pointer to the PCD response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_HLTA( uint8_t *pDataRead )
{
const uint8_t pdata[]= { 0x50, 0x00, 0x28};
/* send the command to the PCD device*/
PCD_SendRecv(0x03,pdata,pDataRead);
return ISO14443A_SUCCESSCODE;
}
/**
* @brief this functions emits the RATS command to PICC device
* @param *pDataRead : Pointer to the response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_RATS( uint8_t *pDataRead )
{
int8_t status;
uint8_t FSCI;
const uint8_t pdata[]= { 0xE0, 0x80, 0x28};
/* send the command to the PCD device*/
errchk(PCD_SendRecv(0x03,pdata,pDataRead));
/* check the status byte of the PCD device */
errchk(PCD_IsReaderResultCodeOk (SEND_RECEIVE,pDataRead) );
/* check the CRC */
errchk(PCD_IsCRCOk (PCD_PROTOCOL_ISO14443A,pDataRead) );
FSCI = pDataRead[3]&0x0F;
FSC = FSCIToFSC(FSCI);
/* Check if FWI is present */
if( (pDataRead[3] & 0x20) == 0x20)
{
if( (pDataRead[3] & 0x10) == 0x10)
FWI = (pDataRead[5]&0xF0)>>4;
else
FWI = (pDataRead[4]&0xF0)>>4;
}
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
#if 0
/**
* @brief Handles the WAKE_UP command
* @param *pDataRead : Pointer to the response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443A_PPS( uint8_t *pDataRead )
{
const uint8_t pdata[]= { 0xD0, 0x11, 0x00, 0x28};
int8_t status;
/* sends the command to the PCD device*/
errchk(PCD_SendRecv(0x04,pdata,pDataRead));
/* checks the CRC */
errchk(PCD_IsCRCOk (PCD_PROTOCOL_ISO14443A,pDataRead) );
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
#endif
/**
* @brief this function completes the ISO144443 type A structure according to the ATQA response
*/
static void ISO14443A_CompleteStructure ( uint8_t *pATQA )
{
/* according to FSP ISO 11443-3 the b7&b8 bits of ATQA tag answer is UID size bit frame */
/* Recovering the UID size */
switch ((ISO14443A_Card.ATQA[0] & ISO14443A_UID_MASK)>>6)
{
case ATQ_FLAG_UID_SINGLE_SIZE:
ISO14443A_Card.UIDsize = ISO14443A_UID_SINGLE_SIZE;
ISO14443A_Card.CascadeLevel = CASCADE_LVL_1;
break;
case ATQ_FLAG_UID_DOUBLE_SIZE:
ISO14443A_Card.UIDsize = ISO14443A_UID_DOUBLE_SIZE;
ISO14443A_Card.CascadeLevel = CASCADE_LVL_2;
break;
case ATQ_FLAG_UID_TRIPLE_SIZE:
ISO14443A_Card.UIDsize = ISO14443A_UID_TRIPLE_SIZE;
ISO14443A_Card.CascadeLevel = CASCADE_LVL_3;
break;
}
}
/**
* @brief Checks if a card is in the field
* @param None
* @return ISO14443A_SUCCESSCODE (Anticollision done) / ISO14443A_ERRORCODE_DEFAULT (Communication issue)
*/
static int8_t ISO14443A_MultiAnticollision( void )
{
uint8_t *pDataRead = u95HFBufferAntiCol;
int8_t status;
/* Checks if an error occured and execute the Anti-collision level 1*/
errchk(ISO14443A_ACLevel1(pDataRead) );
/* UID Complete ? */
if(ISO14443A_Card.SAK & SAK_FLAG_UID_NOT_COMPLETE)
{
/* Checks if an error occured and execute the Anti-collision level 2*/
errchk(ISO14443A_ACLevel2(pDataRead) );
}
/* UID Complete ? */
if(ISO14443A_Card.SAK & SAK_FLAG_UID_NOT_COMPLETE)
{
/* Checks if an error occured and execute the Anti-collision level 3*/
errchk(ISO14443A_ACLevel3(pDataRead) );
}
/* Quiet the founded tag */
/* Send a HALT command */
errchk(ISO14443A_HLTA(pDataRead) );
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @}
*/
/** @addtogroup lib_iso14443Apcd_Public_Functions
* @{
*/
/**
* @brief this command initializes the PCD device for the IS014443A protocol
* @param none
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
int8_t ISO14443A_Init(void)
{
int8_t status;
ISO14443A_InitStructure( );
/* sends a protocol Select command to the pcd to configure it */
errchk(ISO14443A_ConfigFDTforAnticollision());
TechnoSelected = PCDPROTOCOL_14443A;
/* GT min time to respect before sending REQ_A */
delay(5);
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief Initializes the PCD device for the IS014443A protocol
* @param *pDataRead : Pointer to the PCD response
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
int8_t TOPAZ_ID( uint8_t *pDataRead)
{
uint8_t Tag_error_check;
if(PCD_CheckSendReceive(TOPAZ, pDataRead) != ISO14443A_SUCCESSCODE)
return ISO14443A_ERRORCODE_DEFAULT;
Tag_error_check = pDataRead[RFTRANS_95HF_LENGTH_OFFSET]-1;
if((pDataRead[Tag_error_check] & ISO14443A_CRCMASK) == ISO14443A_CRC_ERRORCODE_TYPEA)
return ISO14443A_ERRORCODE_CRC;
if(pDataRead[0] == SENDRECV_RESULTSCODE_OK && pDataRead[1] == 0x04)
return ISO14443A_ERRORCODE_DEFAULT;
devicemode = PCD;
if (pDataRead[0] == 0x80)
nfc_tagtype = TT1;
else
return ISO14443A_ERRORCODE_DEFAULT;
return ISO14443A_SUCCESSCODE;
}
/**
* @brief Checks if a ISO14443A card is in the field
* @return ISO14443A_SUCCESSCODE the function is succesful
* @return ISO14443A_ERRORCODE_DEFAULT : an error occured
*/
int8_t ISO14443A_IsPresent( void )
{
uint8_t *pDataRead = u95HFBuffer;
int8_t status;
errchk(ISO14443A_REQA(pDataRead));
/* checks the status byte of the PCD device */
errchk(PCD_IsReaderResultCodeOk (SEND_RECEIVE,pDataRead) );
ISO14443A_Card.IsDetected = true;
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief Checks if a card is in the field
* @param None
* @return ISO14443A_SUCCESSCODE (Anticollision done) / ISO14443A_ERRORCODE_DEFAULT (Communication issue)
*/
int8_t ISO14443A_Anticollision( void )
{
uint8_t *pDataRead = u95HFBuffer;
int8_t status;
/* Checks if an error occured and execute the Anti-collision level 1*/
errchk(ISO14443A_ACLevel1(pDataRead) );
/* UID Complete ? */
if(ISO14443A_Card.SAK & SAK_FLAG_UID_NOT_COMPLETE)
{
/* Checks if an error occured and execute the Anti-collision level 2*/
errchk(ISO14443A_ACLevel2(pDataRead) );
}
/* UID Complete ? */
if(ISO14443A_Card.SAK & SAK_FLAG_UID_NOT_COMPLETE)
{
/* Checks if an error occured and execute the Anti-collision level 2*/
errchk(ISO14443A_ACLevel3(pDataRead) );
}
/* Checks if the RATS command is supported by the card */
if(ISO14443A_Card.SAK & SAK_FLAG_ATS_SUPPORTED)
{
ISO14443A_ConfigFDTforRATS();
ISO14443A_Card.ATSSupported = true;
errchk(ISO14443A_RATS(pDataRead) );
}
/* Change the FDT to accept APDU */
ISO14443A_ConfigFDT(1);
devicemode = PCD;
/* Check the Tag type found */
if ((ISO14443A_Card.SAK&0x60) == 0x00) /* TT2 */
nfc_tagtype = TT2;
else if( (ISO14443A_Card.SAK & 0x20) == 0x20)
nfc_tagtype = TT4A;
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
int8_t ISO14443A_ConfigFDTforAnticollision( void)
{
u8 ProtocolSelectParameters [6] = {0x00, 0x00, 0x00, 0x00, 0x02, 0x02}; /* last 2 bytes since QJE version */
u8 WriteRegisterParameters [2] = {PCD_TYPEA_TIMERW, TIMER_WINDOW_UPDATE_CONFIRM_CMD};
u8 DemoGainParameters [2] = {PCD_TYPEA_ARConfigA, PCD_TYPEA_ARConfigB};
u8 NbParam = 0;
uint8_t *pDataRead = u95HFBuffer;
int8_t status;
if( IcVers >= QJE)
NbParam = 6;
else
NbParam = 4;
errchk(PCD_ProtocolSelect((NbParam+1),PCD_PROTOCOL_ISO14443A,ProtocolSelectParameters,pDataRead));
errchk(PCD_WriteRegister ( 0x04,TIMER_WINDOW_REG_ADD,0x00,WriteRegisterParameters,pDataRead));
/* in order to adjust the demoduation gain of the PCD which is reseted at each protocol select */
errchk(PCD_WriteRegister (0x04,AFE_ANALOG_CONF_REG_SELECTION,0x01,DemoGainParameters,u95HFBuffer));
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
int8_t ISO14443A_ConfigFDTforRATS( void)
{
u8 ProtocolSelectParameters [6] = {0x00, 0x00, 0x00, 0x00, 0x03, 0x03}; /* last 2 bytes since QJE version */
u8 WriteRegisterParameters [2] = {PCD_TYPEA_TIMERW, TIMER_WINDOW_UPDATE_CONFIRM_CMD};
u8 DemoGainParameters [2] = {PCD_TYPEA_ARConfigA, PCD_TYPEA_ARConfigB};
u8 NbParam = 0;
uint8_t *pDataRead = u95HFBuffer;
int8_t status;
if( IcVers >= QJE)
NbParam = 6;
else
NbParam = 4;
/* Change the PP:MM parameter to respect RATS timing TS-DP-1.1 13.8.1.1*/
/* min to respect */
/* FDT PCD = FWTt4at,activation = 71680 (1/fc) */
/* (2^PP)*(MM+1)*(DD+128)*32 = 71680 ==> PP = 4 MM=0 DD=12*/
/* max to respect not mandatory and as Tag has a FWT activation of 5.2us */
/* adding 16.4ms does not make sense ... */
/* FDT PCD = FWTt4at,activation + dela(t4at,poll) = 5286us + 16.4ms ~= 21.7ms */
/* (2^PP)*(MM+1)*(DD+128)*32 = 21,7 ==> PP = 4 MM=0 DD=12*/
ProtocolSelectParameters[1] = 4; // PP
ProtocolSelectParameters[2] = 0; // MM
ProtocolSelectParameters[3] = 12; // DD
errchk(PCD_ProtocolSelect((NbParam+1),PCD_PROTOCOL_ISO14443A,ProtocolSelectParameters,pDataRead));
errchk(PCD_WriteRegister ( 0x04,TIMER_WINDOW_REG_ADD,0x00,WriteRegisterParameters,pDataRead));
/* in order to adjust the demoduation gain of the PCD which is reseted at each protocol select */
errchk(PCD_WriteRegister (0x04,AFE_ANALOG_CONF_REG_SELECTION,0x01,DemoGainParameters,u95HFBuffer));
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
int8_t ISO14443A_ConfigFDT( uint8_t WTXM)
{
u8 ProtocolSelectParameters [6] = {0x00, 0x00, 0x00, 0x00, 0x03, 0x03}; /* last 2 bytes since QJE version */
u8 WriteRegisterParameters [2] = {PCD_TYPEA_TIMERW, TIMER_WINDOW_UPDATE_CONFIRM_CMD};
u8 DemoGainParameters [2] = {PCD_TYPEA_ARConfigA, PCD_TYPEA_ARConfigB};
u8 NbParam = 0;
uint8_t *pDataRead = u95HFBuffer;
int8_t status;
if( IcVers >= QJE)
NbParam = 6;
else
NbParam = 4;
/* FWI was updated thanks to ATS, if not the case use default value FWI = 4 TS-DP-1.1 13.6.2.11 */
/* FDT PCD = FWT PICC + deltaFWT(t4at) + "deltaT(t4at,poll)" TS-DP-1.1 13.8*/
/* If we perform some identification:
FDT = (2^PP)*(MM+1)*(DD+128)*32/13.56
FDT = (2^(PP))*(1)*(2*DD+256)*16/13.56 + (2^(PP))*(MM)*(2*DD+256)*16/13.56
FDT = (256*16/fc)*2^FWI + ((2^FWI) *256*16*1/fc)*MM with PP=FWI and DD=0
FDT = (2^FWI)*4096*1/fc + FWT*MM (EQUATION 1)
I_ With the choice to NOT add deltaT(t4at,poll) = 16,4ms
1) In the standard case (No extension time cmd received) we want
FDT = FWT + delta FWT(T4AT)
FDT = FWT + 49152 (1/fc)
If we take the rules that we will never set FWI to a value less than 4.
(EQUATION 1 comes)
FDT = FWT*MM + 65536*1/fc => delta FWT(T4AT) is respected
As a conclusion with
PP=FWI (with FWI>=4)
MM=1
DD=0
we are following the specification.
2) In the case of extension time request, M will take the WTXM value. */
if(FWI < 4 )
FWI = 4;
ProtocolSelectParameters[1] = FWI; // PP
ProtocolSelectParameters[2] = WTXM; // MM
ProtocolSelectParameters[3] = 0; // DD
errchk(PCD_ProtocolSelect((NbParam+1),PCD_PROTOCOL_ISO14443A,ProtocolSelectParameters,pDataRead));
errchk(PCD_WriteRegister ( 0x04,TIMER_WINDOW_REG_ADD,0x00,WriteRegisterParameters,pDataRead));
/* in order to adjust the demoduation gain of the PCD which is reseted at each protocol select */
errchk(PCD_WriteRegister (0x04,AFE_ANALOG_CONF_REG_SELECTION,0x01,DemoGainParameters,u95HFBuffer));
return ISO14443A_SUCCESSCODE;
Error:
return ISO14443A_ERRORCODE_DEFAULT;
}
/**
* @brief Checks if cards are in the field
* @param *pNbTag: Number of tag detected
* @param *pUIDout: UIDs of detected tags (11 bytes by tag, first byte indicate UID size)
* @return ISO14443A_SUCCESSCODE (Anticollision done) / ISO14443A_ERRORCODE_DEFAULT (Communication issue)
*/
void ISO14443A_MultiTagHunting ( uint8_t *pNbTag, uint8_t *pUIDout )
{
bool exit = false;
u8 loop = 0;
u8 i = 0;
RemainingID = 0;
*pNbTag = 0;
delay(5);
ISO14443A_InitStructure(); /* only initialize structure */
while( exit == false && loop<= ISO14443A_NB_TAG_MAX )
{
ISO14443A_InitStructure();
if(ISO14443A_IsPresent() == RESULTOK)
{
delayMicroseconds (50);
if(ISO14443A_MultiAnticollision() == RESULTOK)
{
MultiID[0+((*pNbTag)*11)] = ISO14443A_Card.UIDsize;
for(i=0; i<10; i++)
{
MultiID[(1+i)+((*pNbTag)*11)] = ISO14443A_Card.UID[i];
}
*pNbTag +=1;
}
}
else
{
/* no more tag */
exit = true;
}
loop++;
}
if( *pNbTag <= 5)
{
memcpy(pUIDout, &MultiID[0], (*pNbTag)*11 );
}
else
{
memcpy(pUIDout, &MultiID[0], 5*11 );
RemainingID = (*pNbTag-5);
memcpy(&MultiIDPart2[0], &MultiID[5*11] , RemainingID*11 );
}
}
void ISO14443A_MultiTagPart2 ( uint8_t *pNbTag, uint8_t *pUIDout )
{
memcpy(pUIDout, &MultiIDPart2[0], RemainingID*11);
*pNbTag = RemainingID;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

129
src/lib_iso14443Apcd.h Normal file
View File

@@ -0,0 +1,129 @@
/**
******************************************************************************
* @file lib_iso14443Apcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso14443A communication
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------------------------*/
#ifndef __ISO14443APCD_H
#define __ISO14443APCD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_pcd.h"
#include "lib_iso14443A.h"
/* status and error code ---------------------------------------------------------------------- */
#define ISO14443A_SUCCESSCODE RESULTOK
#define ISO14443A_ERRORCODE_DEFAULT 0x61
#define ISO14443A_ERRORCODE_CRC 0x62
/* Anticollison levels (commands) ------------------------------------------------------------- */
#define SEL_CASCADE_LVL_1 0x93
#define SEL_CASCADE_LVL_2 0x95
#define SEL_CASCADE_LVL_3 0x97
#define COMMAND_RATS 0xE0
#define COMMAND_PPS 0xD0
/* Iblock ------------------------------------------------------------------------------------- */
#define COMMAND_IBLOCK02 0x02
#define COMMAND_IBLOCK03 0x03
#define COMMAND_SBLOCK 0xC2
#define COMMAND_NACKBLOCK 0xB2
#define COMMAND_ACKBLOCK 0xA2
/* numbr of the cascade level ----------------------------------------------------------------- */
#define CASCADE_LVL_1 1
#define CASCADE_LVL_2 2
#define CASCADE_LVL_3 3
#define ISO14443A_NVM_10 0x10
#define ISO14443A_NVM_20 0x20
#define ISO14443A_NVM_30 0x30
#define ISO14443A_NVM_40 0x40
#define ISO14443A_NVM_50 0x50
#define ISO14443A_NVM_60 0x60
#define ISO14443A_NVM_70 0x70
/* UID Sizes ---------------------------------------------------------------------------------- */
#define ISO14443A_UIDSIZE_UNDEFINED -1
#define ISO14443A_UID_PART 3
#define ISO14443A_UID_SINGLE_SIZE 4
#define ISO14443A_UID_DOUBLE_SIZE 7
#define ISO14443A_UID_TRIPLE_SIZE 10
/* Mask used for ATQA ------------------------------------------------------------------------ */
#define ISO14443A_UID_MASK 0xC0
#define ISO14443A_AC_BIT_FRAME_MASK 0x1F
#define ISO14443A_CID_MASK 0x0F
#define ISO14443A_FSDI_MASK 0xF0
/* Size for ISO14443A variables ------------------------------------------------------------- */
#define ISO14443A_MAX_NAME_SIZE 50
#define ISO14443A_MAX_UID_SIZE 10
#define ISO14443A_ATQA_SIZE 2
/* SAK FLAG --------------------------------------------------------------------------------- */
#define SAK_FLAG_ATS_SUPPORTED 0x20
#define SAK_FLAG_UID_NOT_COMPLETE 0x04
/* ATQ FLAG */
#define ATQ_FLAG_UID_SINGLE_SIZE 0
#define ATQ_FLAG_UID_DOUBLE_SIZE 1
#define ATQ_FLAG_UID_TRIPLE_SIZE 2
/* MultiTag Huntig -------------------------------------------------------------------------- */
#define ISO14443A_NB_TAG_MAX 10
/* ---------------------------------------------------------------------------------
* --- Local Functions
* --------------------------------------------------------------------------------- */
void ISO14443A_Reset ( void );
int8_t ISO14443A_Init ( void );
int8_t ISO14443A_IsPresent ( void );
int8_t ISO14443A_Anticollision ( void );
int8_t TOPAZ_ID( uint8_t *pDataRead);
/* To manage dynamicaly FDT */
int8_t ISO14443A_ConfigFDTforAnticollision( void);
int8_t ISO14443A_ConfigFDTforRATS( void);
int8_t ISO14443A_ConfigFDT( uint8_t WTXM);
void ISO14443A_MultiTagHunting ( uint8_t* pNbTag, uint8_t *pUIDout );
void ISO14443A_MultiTagPart2 ( uint8_t *pNbTag, uint8_t *pUIDout );
#ifdef __cplusplus
}
#endif
#endif /* __ISO14443A_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

415
src/lib_iso14443Bpcd.cpp Normal file
View File

@@ -0,0 +1,415 @@
/**
******************************************************************************
* @file lib_iso14443Bpcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso14443B communication
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "Arduino.h"
#include "lib_iso14443Bpcd.h"
/* ISO14443B */
#define PCD_TYPEB_ARConfigA 0x01
#define PCD_TYPEB_ARConfigB 0x51
extern uint8_t u95HFBuffer [RFTRANS_95HF_MAX_BUFFER_SIZE+3];
extern IC_VERSION IcVers;
/* Variables for the different modes */
extern DeviceMode_t devicemode;
extern TagType_t nfc_tagtype;
extern PCD_PROTOCOL TechnoSelected;
/* private variables -----------------------------------------------------------------*/
ISO14443B_CARD ISO14443B_Card;
static void ISO14443B_InitStructure ( void );
static void ISO14443B_CompleteStruture ( uint8_t *pDataRead );
static int8_t ISO14443B_WriteARConfigB ( void );
static int8_t ISO14443B_WriteAndCheckARConfigB ( void );
static int8_t ISO14443BReadARConfigB ( uint8_t *pDataRead );
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup ISO14443B_pcd
* @{
* @brief This part of the library is used to follow ISO14443B.
*/
/** @addtogroup lib_iso14443Bpcd_Private_Functions
* @{
*/
/**
* @brief this functions intializes the ISO14443B data structure
*/
static void ISO14443B_InitStructure(void)
{
/* Initializes the data structure used to store results */
memset(ISO14443B_Card.ATQB , 0x00, ISO14443B_ATQB_SIZE);
memset(ISO14443B_Card.PUPI , 0x00, ISO14443B_MAX_PUPI_SIZE);
ISO14443B_Card.IsDetected = false;
memset(ISO14443B_Card.LogMsg, 0x00, ISO14443B_MAX_LOG_MSG);
}
/**
* @brief this function complete the ISO14443B structure according to the REQB response
* @param *pDataRead : Pointer to the PCD response
*/
static void ISO14443B_CompleteStruture ( uint8_t *pDataRead )
{
memcpy(ISO14443B_Card.ATQB, &pDataRead[PCD_DATA_OFFSET], ISO14443B_ATQB_SIZE);
/* retrieves the PUPI field */
memcpy (ISO14443B_Card.PUPI, &(pDataRead[PCD_DATA_OFFSET + 1]),ISO14443B_MAX_PUPI_SIZE);
/* retrieves the Application data field */
memcpy (ISO14443B_Card.ApplicationField,&(pDataRead[PCD_DATA_OFFSET + 1 + 0x04]),0x04);
/* retrieves the Application data field */
memcpy (ISO14443B_Card.ProtocolInfo, &(pDataRead[PCD_DATA_OFFSET + 1 + 0x04 + 0x04]),0x04);
}
/**
* @brief this function writes the configuration registers according to AFE_SET_ANALOG_CONFIG command
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443B_WriteARConfigB(void)
{
uint8_t SetAnalogConfigParameter [2] = { PCD_TYPEB_ARConfigA, PCD_TYPEB_ARConfigB };
int8_t status;
uint8_t *pDataRead = u95HFBuffer;
errchk(PCD_WriteRegister ( 0x04,AFE_ANALOG_CONF_REG_SELECTION,0x01,SetAnalogConfigParameter,pDataRead));
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @brief this function reads the configuration registers according to AFE_SET_ANALOG_CONFIG command
* @param *pDataRead : Pointer to the PCD response
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443BReadARConfigB (uint8_t *pDataRead )
{
int8_t status;
const uint8_t data = 0x01;
/* Select the register */
errchk(PCD_WriteRegister (0x03,AFE_ANALOG_CONF_REG_SELECTION,0x00,&data,pDataRead));
/* Read the ARConfigA and B register */
errchk(PCD_ReadRegister ( 0x03,AFE_ANALOG_CONF_REG_SELECTION,0x02,0x01,pDataRead));
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @brief this function reads ARConfigB registers and check if it matches the requested values(in AFE_SET_ANALOG_CONFIG command)
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
static int8_t ISO14443B_WriteAndCheckARConfigB(void)
{
uint8_t *pDataRead = u95HFBuffer;
int8_t status;
/* Set the Register index to ARConfigB index */
errchk(ISO14443B_WriteARConfigB( ));
/* Read the register value */
/* Set the Register index to ARConfigB index */
errchk(ISO14443BReadARConfigB( pDataRead ));
/* Check ARConfig value */
if((pDataRead[PCD_DATA_OFFSET]== PCD_TYPEB_ARConfigA) && (pDataRead[PCD_DATA_OFFSET + 1 ] == PCD_TYPEB_ARConfigB ) )
return ISO14443B_SUCCESSCODE;
else
return ISO14443B_ERRORCODE_DEFAULT;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @}
*/
/** @addtogroup lib_iso14443Bpcd_Public_Functions
* @{
*/
/**
* @brief Initializes the the PCD device for the IS014443B protocol
* @retval ISO14443B_SUCCESSCODE : the PCD device is well configured.
* @retval ISO14443B_ERRORCODE_DEFAULT : Communication issue.
*/
int8_t ISO14443B_Init( void )
{
uint8_t *pDataRead = u95HFBuffer;
int8_t status;
uint8_t * ProtocolSelectParameters;
const uint8_t ProtocolSelectParametersQJC[] = {
/* Parameters */
PCD_ISO14443B_TRANSMISSION_SPEED_106K |
PCD_ISO14443B_RECEPTION_SPEED_106K |
PCD_ISO14443B_APPEND_CRC,
/* Set FDT */
0x02 ,
0x00
};
const uint8_t ProtocolSelectParametersQJE[] = {
/* Parameters */
PCD_ISO14443B_TRANSMISSION_SPEED_106K |
PCD_ISO14443B_RECEPTION_SPEED_106K |
PCD_ISO14443B_APPEND_CRC,
/* PP MM bytes */
0x00,
0x1A
};
const uint8_t Length = 0x04;
if( IcVers < QJE)
{
ProtocolSelectParameters = (uint8_t*)(ProtocolSelectParametersQJC);
}
else
{
ProtocolSelectParameters = (uint8_t*)(ProtocolSelectParametersQJE);
}
ISO14443B_InitStructure( );
/* sends a protocol Select command to the pcd to configure it */
errchk(PCD_ProtocolSelect(Length,PCD_PROTOCOL_ISO14443B,ProtocolSelectParameters,pDataRead));
TechnoSelected = PCDPROTOCOL_14443B;
/* update the AR register */
errchk(ISO14443B_WriteAndCheckARConfigB ());
/* GT min time to respect before sending REQ_B */
delayMicroseconds(5100);
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @brief this function emits a REQB command to a PICC device
* @param *pDataRead : Pointer to the response
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
int8_t ISO14443B_ReqB ( uint8_t *pDataRead )
{
int8_t status;
const uint8_t ReqB[] = { /* APf */
ISO14443B_ANTICOLLISION_PREFIX_BYTE ,
/* AFI */
ISO14443B_AFI_ALL_FAMILIES ,
/* Parameters */
ISO14443B_EXTENDED_ATQB_NOT_SUPPORTED |
ISO14443B_REQB_ATTEMPT |
ISO14443B_SLOT_MARKER_1
};
/* sends the command to the PCD device*/
errchk(PCD_SendRecv(0x03,ReqB,pDataRead));
/* Filling of the data structure */
ISO14443B_Card.IsDetected = true;
/* complete the ISO 14443 type B strucure */
ISO14443B_CompleteStruture (pDataRead);
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @brief this function complete the ISO14443B structure according to the AttriB response
* @param *pDataRead : Pointer to the PCD response
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
int8_t ISO14443B_AttriB( uint8_t *pDataRead )
{
int8_t status;
uint8_t AttriB[ISO14443B_ATQB_SIZE] = {
/* Start byte */
ATTRIB_FIRST_BYTE ,
/* PUPI */
0x00 ,
/* PUPI */
0x00 ,
/* PUPI */
0x00 ,
/* PUPI */
0x00 ,
/* Parameter 1 */
TR0_64_FS |
TR1_64_FS |
EOF_REQUIRED |
SOF_REQUIRED ,
/* Parameter 2 */
MAX_FRAME_SIZE_256_BYTES |
PCD_TO_PICC_106K |
PICC_TO_PCD_106K ,
/* Parameter 3 */
TR2_32_FS |
PICC_COMPLIANT_ISO14443_4 ,
/* Parameter 4 */
CID_0
};
/* copies the PUPI field */
memcpy(&AttriB[1], ISO14443B_Card.PUPI, ISO14443B_MAX_PUPI_SIZE);
/* sends the command to the PCD device*/
errchk(PCD_SendRecv(0x09,AttriB,pDataRead));
/* checks the CRC */
errchk(PCD_IsCRCOk (PCD_PROTOCOL_ISO14443B,pDataRead) );
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @brief this function checks if a card is in the field
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
int8_t ISO14443B_IsPresent( void )
{
int8_t status;
uint8_t *pDataRead = u95HFBuffer;
/* Init the ISO14443 TypeB communication */
errchk(ISO14443B_Init( ));
/* WakeUp attempt */
errchk(ISO14443B_ReqB(pDataRead));
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @brief Anticolision state machine for ISO14443B cards
* @param void
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
int8_t ISO14443B_Anticollision(void)
{
int8_t status;
uint8_t *pDataRead = u95HFBuffer;
const uint8_t ProtocolSelectParameters[] = {PCD_ISO14443B_TRANSMISSION_SPEED_106K|PCD_ISO14443B_RECEPTION_SPEED_106K|PCD_ISO14443B_APPEND_CRC,0x04,0x3E};
/* ATTRIB attempt */
errchk(ISO14443B_AttriB(pDataRead));
/* Change the PP:MM parameter to accept longer APDU timeout (2^PP)*(MM+1)*(DD+128)*32/13.56 ~= 304ms*/
errchk(PCD_ProtocolSelect(0x04,PCD_PROTOCOL_ISO14443B,ProtocolSelectParameters,pDataRead));
devicemode = PCD;
nfc_tagtype = TT4B;
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @brief this function checks if a card is still in the field
* @retval ISO14443B_SUCCESSCODE : the function is successful.
* @retval ISO14443B_ERRORCODE_DEFAULT : an error occured
*/
int8_t ISO14443B_IsCardIntheField(void)
{
uint8_t *pDataRead = u95HFBuffer;
const uint8_t Parameter = 0xB2;
int8_t status;
/* sends the command to the PCD device*/
errchk(PCD_SendRecv(0x01,&Parameter,pDataRead));
return ISO14443B_SUCCESSCODE;
Error:
return ISO14443B_ERRORCODE_DEFAULT;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

195
src/lib_iso14443Bpcd.h Normal file
View File

@@ -0,0 +1,195 @@
/**
******************************************************************************
* @file lib_iso14443Bpcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso14443B communication
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_ISO14443B_H
#define __LIB_ISO14443B_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_pcd.h"
/* status and error code ---------------------------------------------------------------------- */
#define ISO14443B_SUCCESSCODE RESULTOK
#define ISO14443B_ERRORCODE_DEFAULT 0x71
#define ISO14443B_ERRORCODE_CRC 0x72
/* REQB/WUPB command
* ---------------------------------------------------
* 1st byte | 2nd byte | 3rd byte | 4th, 5th bytes
* ---------------------------------------------------
* APf | AFI | PARAM | CRC
* ---------------------------------------------------
*/
#define ISO14443B_ANTICOLLISION_PREFIX_BYTE 0x05
#define ISO14443B_REQB 0x05
#define ISO14443B_AFI_ALL_FAMILIES 0x00 /*Application Family Identifier(AFI)*/
/* REQB/WUPB PARAM (1 byte)
* -------------------------------------------------------------------------------------
* RFU(3 bits) | Extended ATQB supported(1 bit) | REQB/WUPB(1 bit) | SLOT MARKER(3 bits)
* -------------------------------------------------------------------------------------
*/
#define ISO14443B_EXTENDED_ATQB_SUPPORTED 1<<4
#define ISO14443B_EXTENDED_ATQB_NOT_SUPPORTED 0
#define ISO14443B_WUPB_ATTEMPT 1<<3
#define ISO14443B_REQB_ATTEMPT 0
#define ISO14443B_SLOT_MARKER_1 0
#define ISO14443B_SLOT_MARKER_2 0x01
#define ISO14443B_SLOT_MARKER_4 0x02
#define ISO14443B_SLOT_MARKER_8 3<<1
#define ISO14443B_SLOT_MARKER_16 0x04
/* ATTRIB command
* ---------------------------------------------------------------------------------------------------------------
* 1st byte | 2th to 5th bytes | 6th byte | 7th byte | 8th byte | 9th byte | 10th ... 'n'th bytes | (2 bytes)
* ---------------------------------------------------------------------------------------------------------------
* '1D' | Identifier(PUPI) | PARAM 1 | PARAM 2 | PARAM 3 | PARAM 4 | Higher Layer INF(opt) | CRC
* ---------------------------------------------------------------------------------------------------------------
*/
#define ATTRIB_FIRST_BYTE 0x1D
/* ATTRIB PARAM 1 (1 byte)
* ---------------------------------------------------------------------------------
* Minimum TR0(2 bits) | Minimum TR1(2 bits) | EOF(1 bit) | SOF(1 bit) | RFU(2 bits)
* ---------------------------------------------------------------------------------
*/
#define TR0_64_FS 0
#define TR0_32_FS 1<<6
#define TR0_16_FS 1<<7
#define TR1_64_FS 0
#define TR1_32_FS 1<<4
#define TR1_16_FS 1<<5
#define SOF_REQUIRED 0
#define SOF_NOT_REQUIRED 1<<2
#define EOF_REQUIRED 0
#define EOF_NOT_REQUIRED 1<<3
/* ATTRIB PARAM 2 (1 byte)
* -------------------------------------------------------------------------------
* PICC TO PCD SPEED(2 bits) | PCD TO PICC SPEED(2 bits) | MAX_FRAME_SIZE(2 bits)
* -------------------------------------------------------------------------------
*/
#define MAX_FRAME_SIZE_16_BYTES 0
#define MAX_FRAME_SIZE_24_BYTES 1
#define MAX_FRAME_SIZE_32_BYTES 2
#define MAX_FRAME_SIZE_40_BYTES 3
#define MAX_FRAME_SIZE_48_BYTES 4
#define MAX_FRAME_SIZE_64_BYTES 5
#define MAX_FRAME_SIZE_96_BYTES 6
#define MAX_FRAME_SIZE_128_BYTES 7
#define MAX_FRAME_SIZE_256_BYTES 8
#define PCD_TO_PICC_106K 0
#define PCD_TO_PICC_212K 1<<4
#define PCD_TO_PICC_424K 1<<5
#define PCD_TO_PICC_848K 3<<4
#define PICC_TO_PCD_106K 0
#define PICC_TO_PCD_212K 1<<6
#define PICC_TO_PCD_424K 1<<7
#define PICC_TO_PCD_848K 3<<6
/* ATTRIB PARAM 3 (1 byte)
* -------------------------------------------------------
* RFU(5 bits) | TR2 CODING(2 bits) | PROTOCOL TYPE(1 bit)
* -------------------------------------------------------
* The least significant byte is used for confirmation of
* the protocol type recovered in the ATQB
*/
#define TR2_32_FS 0
#define TR2_128_FS 1<<1
#define TR2_256_FS 1<<2
#define TR2_512_FS 3<<1
#define PICC_COMPLIANT_ISO14443_4 1
#define PICC_NOT_COMPLIANT_ISO14443_4 0
/* ATTRIB PARAM 4 (1 byte)
* --------------------------
* RFU(4 bits) | CID(4 bits)
* --------------------------
*/
#define CID_0 0
#define CID_1 1
#define CID_2 2
#define CID_3 3
#define CID_4 4
#define CID_5 5
#define CID_6 6
#define CID_7 7
#define CID_8 8
#define CID_9 9
#define CID_10 10
#define CID_11 11
#define CID_12 12
#define CID_13 13
#define CID_14 14
/* Sizes of ISO14443B variables */
#define ISO14443B_ATQB_SIZE 13
#define ISO14443B_MAX_PUPI_SIZE 0x04
#define ISO14443B_MAX_APPLI_SIZE 0x04
#define ISO14443B_MAX_PROTOCOL_SIZE 0x04
#define ISO14443B_MAX_LOG_MSG 60
typedef struct{
uint8_t ATQB[ISO14443B_ATQB_SIZE];
uint8_t PUPI[ISO14443B_MAX_PUPI_SIZE],
ApplicationField[ISO14443B_MAX_APPLI_SIZE],
ProtocolInfo[ISO14443B_MAX_PROTOCOL_SIZE];
bool IsDetected;
char LogMsg[ISO14443B_MAX_LOG_MSG];
}ISO14443B_CARD;
int8_t ISO14443B_Init ( void );
int8_t ISO14443B_ReqB ( uint8_t *pDataRead );
int8_t ISO14443B_AttriB ( uint8_t *pDataRead );
int8_t ISO14443B_IsPresent ( void );
int8_t ISO14443B_IsCardIntheField ( void );
int8_t ISO14443B_Anticollision ( void );
#ifdef __cplusplus
}
#endif
#endif /* __ISO14443B_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

1674
src/lib_iso15693pcd.cpp Normal file

File diff suppressed because it is too large Load Diff

318
src/lib_iso15693pcd.h Normal file
View File

@@ -0,0 +1,318 @@
/**
******************************************************************************
* @file lib_iso15693pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of function defined into ISO15693 specification
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_ISO15693_H
#define __LIB_ISO15693_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_pcd.h"
#define RFU 0
#define ISO15693_PROTOCOL 0x01
#define ISO15693_SELECTLENGTH 0x02
/* data rates constants fot select commands -------------------------------------------------- */
#define ISO15693_TRANSMISSION_26 0
#define ISO15693_TRANSMISSION_53 1
#define ISO15693_TRANSMISSION_6 2
#define ISO15693_TRANSMISSION_RFU 3
// constants fot select commands ------------------------------------------------------------- */
#define ISO15693_RESPECT_312 0
#define ISO15693_WAIT_FOR_SOF 1
/* modulation constants fot select commands -------------------------------------------------- */
#define ISO15693_MODULATION_100 0
#define ISO15693_MODULATION_10 1
/* sub carrier constants fot select commands -------------------------------------------------- */
#define ISO15693_SINGLE_SUBCARRIER 0
#define ISO15693_DUAL_SUBCARRIER 1
/* appendCrc constants fot select commands ---------------------------------------------------- */
#define ISO15693_APPENDCRC 1
#define ISO15693_DONTAPPENDCRC 0
#define ISO15693_M24LR64R 0x2C
#define ISO15693_M24LR64ER 0x5E
#define ISO15693_M24LR16ER 0x4E
#define ISO15693_M24LR04ER 0x5A
#define ISO15693_LRiS64K 0x44
#define ISO15693_LRiS2K 0x28
#define ISO15693_LRi2K 0x20
#define ISO15693_LRi1K 0x40
#define ISO15693_LOW_DENSITY 0x00
#define ISO15693_HIGH_DENSITY 0x01
#define ISO15693_NBBYTE_BLOCKLENGTH 4
/* mask of request flag ----------------------------------------------------------------------- */
#define ISO15693_MASK_SUBCARRIERFLAG 0x01
#define ISO15693_MASK_DATARATEFLAG 0x02
#define ISO15693_MASK_INVENTORYFLAG 0x04
#define ISO15693_MASK_PROTEXTFLAG 0x08
#define ISO15693_MASK_SELECTORAFIFLAG 0x10
#define ISO15693_MASK_ADDRORNBSLOTSFLAG 0x20
#define ISO15693_MASK_OPTIONFLAG 0x40
#define ISO15693_MASK_RFUFLAG 0x80
/* mask of response flag ---------------------------------------------------------------------- */
#define ISO15693_RESULTFLAG_STATUSOK 0x00
#define ISO15693_MASK_ERRORFLAG 0x01
/* memmory size information ------------------------------------------------------------------- */
#define ISO15693_MEMSIZEMASK_BLOCKSIZE 0x1F00
#define ISO15693_MEMSIZEMASK_NBBLOCK 0x00FF
#define ISO15693_MEMSIZEOFFSET_BLOCKSIZE 0x08
/* mask for information flags ----------------------------------------------------------------- */
#define ISO15693_MASK_DSFIDFLAG 0x01
#define ISO15693_MASK_AFIFLAG 0x02
#define ISO15693_MASK_MEMSIZEFLAG 0x04
#define ISO15693_MASK_ICREFFLAG 0x08
#define ISO15693_MASK_GETSYSINFOREPLY_MEMSIZE 0x1F
/* command code ------------------------------------------------------------------------------ */
#define ISO15693_CMDCODE_INVENTORY 0x01
#define ISO15693_CMDCODE_STAYQUIET 0x02
#define ISO15693_CMDCODE_READSINGLEBLOCK 0x20
#define ISO15693_CMDCODE_WRITESINGLEBLOCK 0x21
#define ISO15693_CMDCODE_LOCKBLOCK 0x22
#define ISO15693_CMDCODE_READMULBLOCKS 0x23
#define ISO15693_CMDCODE_WRITEMULBLOCKS 0x24
#define ISO15693_CMDCODE_SELECT 0x25
#define ISO15693_CMDCODE_RESETTOREADY 0x26
#define ISO15693_CMDCODE_WRITEAFI 0x27
#define ISO15693_CMDCODE_LOCKAFI 0x28
#define ISO15693_CMDCODE_WRITEDSFID 0x29
#define ISO15693_CMDCODE_LOCKDSFID 0x2A
#define ISO15693_CMDCODE_GETSYSINFO 0x2B
#define ISO15693_CMDCODE_GETSECURITYINFO 0x2C
// request flags ------------------------------------------------------------------------------ */
#define ISO15693_REQFLAG_SINGLESUBCARRIER 0
#define ISO15693_REQFLAG_TWOSUBCARRIER 1
#define ISO15693_REQFLAG_LOWDATARATE 0
#define ISO15693_REQFLAG_HIGHDATARATE 1
#define ISO15693_REQFLAG_INVENTORYFLAGNOTSET 0
#define ISO15693_REQFLAG_INVENTORYFLAGSET 1
#define ISO15693_REQFLAG_NOPROTOCOLEXTENSION 0
#define ISO15693_REQFLAG_PROTOCOLEXTENSION 1
// request flag 5 to 8 definition when inventory flag is not set ----------------------------- */
#define ISO15693_REQFLAG_NOTSELECTED 0
#define ISO15693_REQFLAG_SELECTED 1
#define ISO15693_REQFLAG_NOTADDRESSED 0
#define ISO15693_REQFLAG_ADDRESSED 1
#define ISO15693_REQFLAG_OPTIONFLAGNOTSET 0
#define ISO15693_REQFLAG_OPTIONFLAGSET 1
#define ISO15693_REQFLAG_RFUNOTSET 0
#define ISO15693_REQFLAG_RFUSET 1
// request flag 5 to 8 definition when inventory flag is set -------------------------------- */
#define ISO15693_REQFLAG_NOTAFI 0
#define ISO15693_REQFLAG_AFI 1
#define ISO15693_REQFLAG_16SLOTS 0
#define ISO15693_REQFLAG_1SLOT 1
// mask for parameter byte (select command) --------------------------------------------------- */
#define ISO15693_MASK_APPENDCRC 0x01
#define ISO15693_MASK_SUBCARRIER 0x02
#define ISO15693_MASK_MODULATION 0x04
#define ISO15693_MASK_WAITORSOF 0x08
#define ISO15693_MASK_DATARATE 0x30
#define ISO15693_MASK_RFU 0xC0
// bits offset for parameter byte (select command) -------------------------------------------- */
#define ISO15693_OFFSET_APPENDCRC 0x00
#define ISO15693_OFFSET_SUBCARRIER 0x01
#define ISO15693_OFFSET_MODULATION 0x02
#define ISO15693_OFFSET_WAITORSOF 0x03
#define ISO15693_OFFSET_DATARATE 0x04
#define ISO15693_OFFSET_RFU 0x06
// byte offset for tag responses -------------------------------------------------------------- */
#define ISO15693_OFFSET_FLAGS 0x00
#define ISO15693_OFFSET_ERRORCODE 0x01
#define ISO15693_OFFSET_GETSYSINFOREPLY_NBBLOCK 0x00
#define ISO15693_OFFSET_GETSYSINFOREPLY_MEMSIZE 0x01
#define ISO15693_OFFSET_UID PCD_DATA_OFFSET+0x02
#define ISO15693_INVENTORYOFFSET_DSFID 0x01
#define ISO15693_INVENTORYOFFSET_UID 0x02
#define ISO15693_INVENTORYOFFSET_CRC16 0x05
#define ISO15693_GETSYSINFOOFFSET_INFOFLAGS 0x01
#define ISO15693_GETSYSINFOOFFSET_UID 0x02
#define ISO15693_GETSYSINFOOFFSET_DSFID 0x0A
#define ISO15693_READSINGLEOFFSET_SECURITY 0x01
#define ISO15693_GETMULSECURITIOFFSET_SECURITY 0x01
/* number of byte of parameters ------------------------------------------------------------- */
#define ISO15693_NBBYTE_UID 0x08
#define ISO15693_NBBYTE_CRC16 0x02
#define ISO15693_NBBYTE_DSFID 0x01
#define ISO15693_NBBYTE_AFI 0x01
#define ISO15693_NBBYTE_BLOCKSECURITY 0x01
#define ISO15693_NBBYTE_REPLYFLAG 0x01
#define ISO15693_NBBYTE_INFOFLAG 0x01
#define ISO15693_NBBYTE_MEMORYSIZE 0x02
#define ISO15693_NBBYTE_ICREF 0x01
#define ISO15693_NBBYTE_REQUESTFLAG 0x01
#define ISO15693_NBBIT_INVENTORYSCANCHAIN 2+8+8+64
#define ISO15693_NBBYTE_INVENTORYSCANCHAIN 11 // =(2+8+8+64) /8 +1
#define ISO15693_NBBITS_MASKPARAMETER 64
/* success and error code --------------------------------------------------------------------- */
#define ISO15693_SUCCESSCODE RESULTOK
#define ISO15693_ERRORCODE_DEFAULT 0xF1
#define ISO15693_ERRORCODE_REQUESTFLAG 0xF2
#define ISO15693_ERRORCODE_PARAMETERLENGTH 0xF3
#define ISO15693_ERRORCODE_CRCRESIDUE 0xF4
#define ISO15693_ERRORCODE_NOTAGFOUND 0xF5
/* command length ----------------------------------------------------------------------------- */
#define ISO15693_MAXLENGTH_INVENTORY 13 // 8 + 8 + 8 + 64 + 16 = 104bits => 13 bytes
#define ISO15693_MAXLENGTH_STAYQUIET 12 // 8 + 8 + 64 + 16 = 96 => 12 bytes
#define ISO15693_MAXLENGTH_READSINGLEBLOCK 13 // 8 + 8 + 8 + 64 + 16 = 104bits => 13 bytes
#define ISO15693_MAXLENGTH_LOCKSINGLEBLOCK 13 // 8 + 8 + 8 + 64 + 16 = 104bits => 13 bytes
#define ISO15693_MAXLENGTH_READMULBLOCK 14 // 8 + 8 + 8 + 64 + 8 + 16 = 112 bits => 14 bytes
#define ISO15693_MAXLENGTH_SELECT 12 // 8 + 8 + 64 + 16 = 96 bits => 12 bytes
#define ISO15693_MAXLENGTH_RESETTOREADY 12 // 8 + 8 + 64 + 16 = 96 bits => 12 bytes
#define ISO15693_MAXLENGTH_WRTITEAFI 13 // 8 + 8 + 8 + 64 + 16 = 104bits => 13 bytes
#define ISO15693_MAXLENGTH_WRTITEDSFID 13 // 8 + 8 + 8 + 64 + 16 = 104bits => 13 bytes
#define ISO15693_MAXLENGTH_LOCKAFI 12 // 8 + 8 + 64 + 16 = 96 bits => 12 bytes
#define ISO15693_MAXLENGTH_LOCKDSFID 12 // 8 + 8 + 64 + 16 = 96 bits => 12 bytes
#define ISO15693_MAXLENGTH_GETMULSECURITY 14 // 8 + 8 + 8 + 64 + 8 + 16 = 112 bits => 14 bytes
#define ISO15693_MAXLENGTH_GETSYSTEMINFO 12 // 8 + 8 + 64 + 16 = 96 => 12 bytes
// reply length
#define ISO15693_MAXLENGTH_REPLYINVENTORY 12 // 8 + 8 + 64 + 16 = 96 => 12 bytes
#define ISO15693_MAXLENGTH_REPLYSTAYQUIET 4 // No reply
#define ISO15693_MAXLENGTH_REPLYREADSINGLEBLOCK MAX_BUFFER_SIZE // 8 + 8 + 8 + 64 + 16 = 104bits => 13 bytes
#define ISO15693_MAXLENGTH_REPLYWRITESINGLEBLOCK 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYLOCKSINGLEBLOCK 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYREADMULBLOCK MAX_BUFFER_SIZE
#define ISO15693_MAXLENGTH_REPLYSELECT 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYRESETTOREADY 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYWRTITEAFI 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYWRTITEDSFID 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYLOCKAFI 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYLOCKDSFID 4 // 8 + 8 + 16 = 32 bits => 4 bytes
#define ISO15693_MAXLENGTH_REPLYGETMULSECURITY MAX_BUFFER_SIZE
#define ISO15693_MAXLENGTH_REPLYGETSYSTEMINFO 15 // 8 + 8 + 64 + 8 + 8 + 8 + 16 = 112 bits => 15 bytes
/* CRC parameters ----------------------------------------------------------------------------- */
#define ISO15693_OFFSET_LENGTH PCD_LENGTH_OFFSET
#define ISO15693_CRC_MASK 0x02
#define ISO15693_CRC_ERROR_CODE 0x02
#define ISO15693_COLISION_MASK 0x01
#define ISO15693_COLISION_ERROR_CODE 0x01
#define ISO15693_CRC_MASK_TYPE_A 0x20
#define ISO15693_CRC_ERROR_CODE_TYPE_A 0x20
#define ISO15693_MAXLENGTH_BLOCKSIZE 0x32
typedef struct {
int8_t DataRate , // 0 => 26k 1 => 52 k 2 => 6k 3=>RFU
WaitOrSOF , // 0 => respect 312 <20>s 1=> wait for SOF
ModulationDepth , // 0 => 100% modulation 1=> 10% modulation
SubCarrier , // 0 => single 1=> Dual
AppendCRC ; // 1=> append 0=> don't append
}ISO15693ConfigStruct;
// CRC 16 constants
#define ISO15693_PRELOADCRC16 0xFFFF
#define ISO15693_POLYCRC16 0x8408
#define ISO15693_MASKCRC16 0x0001
#define ISO15693_RESIDUECRC16 0xF0B8
/* ---------------------------------------------------------------------------------
* --- Local Functions
* --------------------------------------------------------------------------------- */
/* ISO15693 functions --- */
/* configure the PCD --- */
int8_t ISO15693_Init(void);
/* ISO15693 commands --- */
int8_t ISO15693_RunInventory16slots(const uint8_t Flags , const uint8_t AFI,uint8_t *NbTag,uint8_t *pUIDout);
int8_t ISO15693_RunAntiCollision(const uint8_t Flags , const uint8_t AFI,uint8_t *NbTag,uint8_t *pUIDout);
// Get functions
int8_t ISO15693_GetUID(uint8_t *UIDout);
int8_t ISO15693_GetTagIdentification(uint16_t *Length_Memory_TAG, uint8_t *Tag_Density, uint8_t *IC_Ref_TAG);
int8_t ISO15693_GetSystemInfo(const uint8_t Flags, const uint8_t *UIDin ,uint8_t *pResponse);
// Tag functions
uint8_t ISO15693_ReadBytesTagData(uint8_t Tag_Density, uint8_t IC_Ref_Tag, uint8_t *Data_To_Read, uint16_t NbBytes_To_Read, uint16_t FirstBytes_To_Read);
uint8_t ISO15693_WriteBytes_TagData(uint8_t Tag_Density, uint8_t *Data_To_Write, uint16_t NbBytes_To_Write, uint16_t FirstBytes_To_Write);
#ifdef ISO15693_ALLCOMMANDS
int8_t ISO15693_LockSingleBlock(const uint8_t Flags, const uint8_t *UIDin, const uint8_t BlockNumber,uint8_t *pResponse);
int8_t ISO15693_Select(const uint8_t Flags, const uint8_t *UIDin, const uint8_t AppendCRC,const uint8_t *CRC16,uint8_t *pResponse);
int8_t ISO15693_WriteAFI(const uint8_t Flags, const uint8_t *UIDin,const uint8_t AFIToWrite,uint8_t *pResponse);
int8_t ISO15693_LockAFI(const uint8_t Flags, const uint8_t *UIDin, uint8_t *pResponse);
int8_t ISO15693_WriteDSFID(const uint8_t Flags, const uint8_t *UIDin,const uint8_t DSFIDToWrite,uint8_t *pResponse);
int8_t ISO15693_LockDSFID(const uint8_t Flags, const uint8_t *UIDin, uint8_t *pResponse);
int8_t ISO15693_GetMultipleBlockSecutityStatus(const uint8_t Flags, const uint8_t *UIDin, const uint8_t BlockNumber, const uint8_t NbBlocks,uint8_t *pResponse);
#endif /* ISO15693_ALLCOMMANDS*/
int8_t ISO15693_SplitInventoryResponse(const uint8_t *ReaderResponse,const uint8_t Length,uint8_t *Flags , uint8_t *DSFIDextract, uint8_t *UIDoutIndex);
#ifdef __cplusplus
}
#endif
#endif /* __ISO15693_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

221
src/lib_iso18092pcd.cpp Normal file
View File

@@ -0,0 +1,221 @@
/**
******************************************************************************
* @file lib_iso18092pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso18092 communication
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------------------ */
#include "Arduino.h"
#include "lib_iso18092pcd.h"
/* Felica */
#define PCD_TYPEF_ARConfigA 0x01
#define PCD_TYPEF_ARConfigB 0x51
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Variables for the different modes */
extern DeviceMode_t devicemode;
extern TagType_t nfc_tagtype;
extern PCD_PROTOCOL TechnoSelected;
FELICA_CARD FELICA_Card;
static const uint8_t REQC[] = {SEND_RECEIVE ,0x05,0x00,0x12,0xFC,0x01,0x03};
static int8_t FELICA_Init( uint8_t *pDataRead );
static int8_t FELICA_REQC( uint8_t *pDataRead );
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup ISO18092_pcd
* @{
* @brief This part of the library is used to follow ISO18092.
*/
/** @addtogroup lib_iso18092pcd_Private_Functions
* @{
*/
/**
* @brief Initializes the xx95HF for the FELICA protocol
* @param void
* @return TRUE (if well configured) / FALSE (Communication issue)
*/
static int8_t FELICA_Init( uint8_t *pDataRead )
{
int8_t status;
u8 ProtocolSelectParameters [4] = {0x51, 0x13, 0x01,0x0D};
u8 WriteAmpliGain [2] = {PCD_TYPEF_ARConfigA, PCD_TYPEF_ARConfigB};
u8 AutoFDet [2] = {0x02,0xA1};
/* sends a protocol Select command to the pcd to configure it */
errchk(PCD_ProtocolSelect(0x05,PCD_PROTOCOL_FELICA,ProtocolSelectParameters,pDataRead));
TechnoSelected = PCDPROTOCOL_18092;
/* in order to adjust the demodulation gain of the PCD*/
errchk(PCD_WriteRegister ( 0x04,AFE_ANALOG_CONF_REG_SELECTION,0x01,WriteAmpliGain,pDataRead));
/* in order to adjust the auto detect of the PCD*/
errchk(PCD_WriteRegister ( 0x04,0x0A,0x01,AutoFDet,pDataRead));
/* GT min time to respect before sending REQ_C */
delay(20);
delayMicroseconds(400);
return ISO18092_SUCCESSCODE;
Error:
return ISO18092_ERRORCODE_DEFAULT;
}
/**
* @brief Handles the REQC command
* @param *pDataRead : Pointer on the response
* @return TRUE (if CR95HF answered ATQB) / FALSE (No ISO14443B in Field)
*/
static int8_t FELICA_REQC( uint8_t *pDataRead )
{
if(PCD_CheckSendReceive(REQC, pDataRead)!= ISO18092_SUCCESSCODE)
return ISO18092_ERRORCODE_DEFAULT;
if (pDataRead[2] != 0x01) // If the answer is not an answer to REQC
return ISO18092_ERRORCODE_DEFAULT;
else
return ISO18092_SUCCESSCODE;
}
/**
* @}
*/
/** @addtogroup lib_iso18092pcd_Public_Functions
* @{
*/
void FELICA_Initialization( void )
{
uint8_t DataRead[MAX_BUFFER_SIZE];
/* Init the FeliCa communication */
FELICA_Init(DataRead);
}
/**
* @brief Checks if a FELICA card is in the field
* @param void
* @return ISO18092_SUCCESSCODE (A card is present) / ISO18092_ERRORCODE_DEFAULT (No card)
*/
int8_t FELICA_IsPresent( void )
{
uint8_t DataRead[MAX_BUFFER_SIZE];
/* Initializing buffer */
memset(DataRead,0,MAX_BUFFER_SIZE);
/* REQC attempt */
if(FELICA_REQC(DataRead) != ISO18092_SUCCESSCODE )
return ISO18092_ERRORCODE_DEFAULT;
/* Filling of the data structure */
FELICA_Card.IsDetected = true;
memcpy(FELICA_Card.ATQC, &DataRead[PCD_DATA_OFFSET], ATQC_SIZE);
memcpy(FELICA_Card.UID , &FELICA_Card.ATQC[1] , UID_SIZE_FELICA);
devicemode = PCD;
nfc_tagtype = TT3;
/* An ISO14443 card is in the field */
return ISO18092_SUCCESSCODE;
}
/**
* @brief Processing of the Anticolision for FELICA cards
* @param *message : contains message on the CR95HF replies
* @return ISO18092_SUCCESSCODE : the function is succesful
*/
int8_t FELICA_Anticollision( void )
{
/* Anticollision process done ! */
return ISO18092_SUCCESSCODE;
}
/**
* @brief Checks if a FELICA card is still in the field
* @param void
* @return ISO18092_SUCCESSCODE : the function is succesful
* @return ISO18092_ERRORCODE_DEFAULT : No card in the RF field
*/
int8_t FELICA_CardTest( void )
{
uint8_t DummyBuffer[MAX_BUFFER_SIZE];
if(PCD_CheckSendReceive(REQC, DummyBuffer)!= ISO18092_SUCCESSCODE)
return ISO18092_ERRORCODE_DEFAULT;
return ISO18092_SUCCESSCODE;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

77
src/lib_iso18092pcd.h Normal file
View File

@@ -0,0 +1,77 @@
/**
******************************************************************************
* @file lib_iso18092pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso18092 communication
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FELICA_H
#define __FELICA_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_pcd.h"
#include "stdbool.h"
/* -------------------------------------------------------------------------- */
#define ATQC_SIZE 0x20
#define UID_SIZE_FELICA 8
/* command code -------------------------------------------------------------- */
#define ISO18092_COMMAND_REQC 0x00
#define ISO18092_RESPONSE_REQC 0x01
/* code status -------------------------------------------------------------------------- */
#define ISO18092_SUCCESSCODE RESULTOK
#define ISO18092_ERRORCODE_DEFAULT 0xC1
typedef struct{
uint8_t ATQC[ATQC_SIZE];
uint8_t UID [UID_SIZE_FELICA];
bool IsDetected;
// char LogMsg[120];
}FELICA_CARD;
//extern FELICA_CARD FELICA_Card;
/* ---------------------------------------------------------------------------------
* --- Local Functions
* --------------------------------------------------------------------------------- */
void FELICA_Initialization( void );
int8_t FELICA_IsPresent ( void );
int8_t FELICA_CardTest ( void );
int8_t FELICA_Anticollision( void );
#ifdef __cplusplus
}
#endif
#endif /* __FELICA_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

275
src/lib_iso7816pcd.cpp Normal file
View File

@@ -0,0 +1,275 @@
/**
******************************************************************************
* @file lib_iso7816pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso 7816 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "lib_iso7816pcd.h"
extern TagType_t nfc_tagtype;
uint8_t bufferSend[MAX_BUFFER_SIZE+3],
bufferReceive[MAX_BUFFER_SIZE+3];
static APDU_Commands APDUcommand ;
static APDU_Responce APDUresponse;
static uint8_t BlockNumber = 0x02;
static int8_t ISO7816_SendReceiveAPDU ( uint8_t *pDataReceived );
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup ISO7816_pcd
* @{
* @brief This part of the library is used to follow ISO7816.
*/
/** @addtogroup lib_iso7816pcd_Private_Functions
* @{
*/
/**
* @brief this function sends the APDU command to the RF transceiver and returns its response
* @return ISO7816_SUCCESSCODE : the function is succesful
* @return ISO7816_ERRORCODE_RESPONSE : the function is not succesful. The tag returns an error code
* @return ISO7816_ERRORCODE_DEFAULT : the function is not succesful.
*/
static int8_t ISO7816_SendReceiveAPDU ( uint8_t *pDataReceived )
{
uint8_t NthByte=0;
int8_t status;
uint8_t bufferFWI[3];
bufferSend[NthByte++] = BlockNumber;
BlockNumber ^= 0x01;
// add the class byte
bufferSend[NthByte++] = APDUcommand.Header.CLA;
// add the command code
bufferSend[NthByte++] = APDUcommand.Header.INS;
// add the P1 and P2 fields
bufferSend[NthByte++] = APDUcommand.Header.P1;
bufferSend[NthByte++] = APDUcommand.Header.P2;
// add the LC field
if (APDUcommand.Body.LC)
bufferSend[NthByte++] = APDUcommand.Body.LC;
// add the datafield field
memcpy(&(bufferSend[NthByte]),APDUcommand.Body.pData,APDUcommand.Body.LC);
NthByte += APDUcommand.Body.LC;
// add the LE field
if (APDUcommand.Body.LE || (APDUcommand.Header.P1 == 0x04 && APDUcommand.Header.P2 == 0x00))
bufferSend[NthByte++] = APDUcommand.Body.LE;
// control byte append CRC + 8 bits
if( nfc_tagtype == TT4A )
bufferSend[NthByte++] = SEND_MASK_APPENDCRC | SEND_MASK_8BITSINFIRSTBYTE;
// send the command to the RF transceiver
errchk(PCD_SendRecv(NthByte,bufferSend,pDataReceived))
/* Test if a time extension is required */
if (pDataReceived[2] == 0xF2)
{
/* Modify temporarly FDT */
ISO14443A_ConfigFDT(pDataReceived[3]);
/* Send the same buffer in order to accept the time extension */
memcpy(bufferFWI,&pDataReceived[2],2);
if( nfc_tagtype == TT4A )
{
bufferFWI[2] = SEND_MASK_APPENDCRC | SEND_MASK_8BITSINFIRSTBYTE;
PCD_SendRecv(3,bufferFWI, pDataReceived);
}
else
PCD_SendRecv(2,bufferFWI, pDataReceived);
/* Setback FDT default value */
ISO14443A_ConfigFDT(1);
}
if( nfc_tagtype == TT4A )
{
APDUresponse.SW1 = pDataReceived[pDataReceived[PCD_LENGTH_OFFSET]-5];
APDUresponse.SW2 = pDataReceived[pDataReceived[PCD_LENGTH_OFFSET]-4];
}
else
{
APDUresponse.SW1 = pDataReceived[pDataReceived[PCD_LENGTH_OFFSET]-3];
APDUresponse.SW2 = pDataReceived[pDataReceived[PCD_LENGTH_OFFSET]-2];
}
if (APDUresponse.SW1 == 0x90 && APDUresponse.SW2 == 0x00)
return ISO7816_SUCCESSCODE;
else
return ISO7816_ERRORCODE_RESPONSE;
Error :
return ISO7816_ERRORCODE_DEFAULT;
}
/**
* @}
*/
/** @addtogroup lib_iso7816pcd_Public_Functions
* @{
*/
/**
* @brief this function sends the Select command
* @param P1byte : P1 value
* @param P2byte : P2 value
* @param LCbyte : LC value
* @param PData : pointer of the File ID
* @return ISO7816_SUCCESSCODE : the function is successful and the tag returns a success code
* @return ISO7816_ERRORCODE_DEFAULT : the function is not successful
*/
int8_t ISO7816_SelectFile(const uint8_t P1byte , const uint8_t P2byte , const uint8_t LCbyte ,uint8_t *pDataSel)
{
// add the class byte
APDUcommand.Header.CLA = ISO7816_CLASS_0X00;
// add the command code
APDUcommand.Header.INS = ISO7816_SELECT_FILE;
// add the P1 and P2 fields
APDUcommand.Header.P1 = P1byte;
APDUcommand.Header.P2 = P2byte;
// add the LC field
APDUcommand.Body.LC = LCbyte;
//add the FileId field
memcpy(APDUcommand.Body.pData, pDataSel, APDUcommand.Body.LC);
// the LE field is empty
APDUcommand.Body.LE = 0x00;
// Special case for the selectApplication
// The block number HAS TO be 0x02
if (APDUcommand.Header.P1 == 0x04 && APDUcommand.Header.P2 == 0x00)
BlockNumber = 0x02;
return ISO7816_SendReceiveAPDU ( bufferReceive );
}
/**
* @brief this function sends a ReadBinary command
* @param P1byte : P1 value
* @param P2byte : P2 value
* @param LEbyte : LE value
* @param *pDataRead : Pointer to the data read from the tag
* @return ISO7816_SUCCESSCODE : the function is successful and the tag returns a success code
* @return ISO7816_ERRORCODE_DEFAULT : the function is not successful
*/
int8_t ISO7816_ReadBinary(const uint8_t P1byte , const uint8_t P2byte , const uint8_t LEbyte , uint8_t *pDataRead)
{
// add the class byte
APDUcommand.Header.CLA = ISO7816_CLASS_0X00;
// add the command code
APDUcommand.Header.INS = ISO7816_READ_BINARY;
// add the P1 and P2 fields
APDUcommand.Header.P1 = P1byte;
APDUcommand.Header.P2 = P2byte;
// the LC field is empty
APDUcommand.Body.LC = 0x00;
APDUcommand.Body.LE = LEbyte;
return ISO7816_SendReceiveAPDU ( pDataRead );
}
/**
* @brief this function sends the UpdateBinary command.
* @param P1byte : P1 value
* @param P2byte : P2 value
* @param LCbyte : LC value
* @param *pData : Pointer to the data to write
* @return ISO7816_SUCCESSCODE : the function is successful and the tag returns a success code
* @return ISO7816_ERRORCODE_DEFAULT : the function is not successful
*/
int8_t ISO7816_UpdateBinary(const uint8_t P1byte , const uint8_t P2byte , const uint8_t LCbyte , uint8_t *pData)
{
// add the class byte
APDUcommand.Header.CLA = ISO7816_CLASS_0X00;
// add the command code
APDUcommand.Header.INS = ISO7816_UPDATE_BINARY;
// add the P1 and P2 fields
APDUcommand.Header.P1 = P1byte;
APDUcommand.Header.P2 = P2byte;
// add the datafield field
APDUcommand.Body.LC = LCbyte;
// add data to write
memcpy(APDUcommand.Body.pData,pData,APDUcommand.Body.LC);
// the LE field is empty
APDUcommand.Body.LE = 0x00;
return ISO7816_SendReceiveAPDU ( bufferReceive );
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

110
src/lib_iso7816pcd.h Normal file
View File

@@ -0,0 +1,110 @@
/**
******************************************************************************
* @file lib_iso7816pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Manage the iso 7816 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion --------------------------------------------------------*/
#ifndef __LIB_ISO7816_H
#define __LIB_ISO7816_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes -------------------------------------------------------------------------------------*/
#include "lib_iso14443Apcd.h"
#include "lib_pcd.h"
/* status and error code ---------------------------------------------------------------------- */
#define ISO7816_SUCCESSCODE RESULTOK
#define ISO7816_ERRORCODE_DEFAULT 0x71
#define ISO7816_ERRORCODE_RESPONSE 0x72
#define ISO7816_ERRORCODE_SENDERRORCODE 0x73
/* Iblock ------------------------------------------------------------------------------------- */
#define ISO7816_IBLOCK02 0x02
#define ISO7816_IBLOCK03 0x03
#define ISO7816_SELECT_FILE 0xA4
#define ISO7816_UPDATE_BINARY 0xD6
#define ISO7816_READ_BINARY 0xB0
#define ISO7816_CLASS_0X00 0x00
#define ISO7816_CLASS_STM 0xA2
// offset of the different field of the APDU
#define ISO7816_ADPUOFFSET_BLOCK 0x00
#define ISO7816_ADPUOFFSET_CLASS ISO7816_ADPUOFFSET_BLOCK + 1
#define ISO7816_ADPUOFFSET_INS ISO7816_ADPUOFFSET_BLOCK + 2
#define ISO7816_ADPUOFFSET_P1 ISO7816_ADPUOFFSET_BLOCK + 3
#define ISO7816_ADPUOFFSET_P2 ISO7816_ADPUOFFSET_BLOCK + 4
#define ISO7816_ADPUOFFSET_LC ISO7816_ADPUOFFSET_BLOCK + 5
#define ISO7816_ADPUOFFSET_DATA ISO7816_ADPUOFFSET_BLOCK + 6
/* ADPU-Header command structure ---------------------------------------------*/
typedef struct
{
uint8_t CLA; /* Command class */
uint8_t INS; /* Operation code */
uint8_t P1; /* Selection Mode */
uint8_t P2; /* Selection Option */
} Header;
/* ADPU-Body command structure -----------------------------------------------*/
typedef struct
{
uint8_t LC; /* Data field length */
uint8_t pData[256]; /* Command parameters */ // pointer on the transceiver buffer = *(ReaderRecBuf[CR95HF_DATA_OFFSET + ISO7816_ADPUOFFSET_DATA])
uint8_t LE; /* Expected length of data to be returned */
} Body;
/* ADPU Command structure ----------------------------------------------------*/
typedef struct
{
Header Header;
Body Body;
} APDU_Commands;
/* SC response structure -----------------------------------------------------*/
typedef struct
{
uint8_t SW1; /* Command Processing status */
uint8_t SW2; /* Command Processing qualification */
} APDU_Responce;
int8_t ISO7816_SelectFile(const uint8_t P1byte , const uint8_t P2byte , const uint8_t LCbyte , uint8_t *PData);
int8_t ISO7816_ReadBinary(const uint8_t P1byte , const uint8_t P2byte , const uint8_t LEbyte , uint8_t *pDataRead);
int8_t ISO7816_UpdateBinary(const uint8_t P1byte , const uint8_t P2byte , const uint8_t LCbyte , uint8_t *pData);
#ifdef __cplusplus
}
#endif
#endif /* __SMARTCARD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

248
src/lib_nfctype1pcd.cpp Normal file
View File

@@ -0,0 +1,248 @@
/**
******************************************************************************
* @file lib_nfctype1pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type1 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "lib_nfctype1pcd.h"
extern uint8_t TT1Tag[];
extern uint8_t TagUID[];
static uint8_t PCDNFCT1_ReadAll(uint8_t *pBufferRead);
static uint8_t PCDNFCT1_WriteErase(uint8_t address, uint8_t byte);
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup NFC_type1_pcd
* @{
* @brief This file is used to exchange with NFC FORUM Type1 Tag.
*/
/** @addtogroup lib_nfctype1pcd_Private_Functions
* @{
*/
/**
* @brief This function generates the ReadAll command
* @param pBufferRead : Pointer on the buffer which will contain the data read
* @retval PCDNFCT1_OK : Command success
* @retval PCDNFCT1_ERROR : Transmission error
*/
static uint8_t PCDNFCT1_ReadAll(uint8_t *pBufferRead)
{
uint8_t buffer[] = {PCDNFCT1_READALL,0x00,0x00,0,0,0,0,PCDNFCT1_TOPAZ_MODE};
memcpy(&buffer[3], &TagUID[4],4);
if (PCD_SendRecv(8,buffer, pBufferRead) == PCD_SUCCESSCODE)
return PCDNFCT1_OK;
else
return PCDNFCT1_ERROR;
}
/**
* @brief This function generates the WriteErase command
* @param address : The address of the byte to write
* @param byte : The byte to write
* @retval PCDNFCT1_OK : Command success
* @retval PCDNFCT1_ERROR : Transmission error
*/
static uint8_t PCDNFCT1_WriteErase(uint8_t address, uint8_t byte)
{
uint8_t buffer[] = {PCDNFCT1_WRITE_E,0,0,0,0,0,0,PCDNFCT1_TOPAZ_MODE};
uint8_t bufferRead[16];
/* Cannot write protected sector */
if (address < 13 || address > 102)
return PCDNFCT1_ERROR;
buffer[1] = address;
buffer[2] = byte;
memcpy(&buffer[3], &TagUID[4],4);
if (PCD_SendRecv(8,buffer, bufferRead) == PCD_SUCCESSCODE)
return PCDNFCT1_OK;
else
return PCDNFCT1_ERROR;
}
/**
* @}
*/
/** @addtogroup lib_nfctype1pcd_Public_Functions
* @{
*/
/**
* @brief This function reads the NDEF message from a tag type 1 and store result in the TT1Tag buffer
* @retval PCDNFCT1_OK : Command success
* @retval PCDNFCT1_ERROR : Transmission error
*/
uint8_t PCDNFCT1_ReadNDEF( void )
{
uint8_t status;
uint8_t buffer[NFCT1_MAX_TAGMEMORY+2];
uint16_t NDEFposition = 16, size;
errchk(PCDNFCT1_ReadAll(buffer));
if ((buffer[2] & PCDNFCT1_NDEF_CAPABLE_MSK) != 0x10) /* NDEF capable TT1 if H0 = 0x1X */
return PCDNFCT1_ERROR_NOT_FORMATED;
if (buffer[12] != PCDNFCT1_NDEF_MNB) /* CC file with NDEF info */
return PCDNFCT1_ERROR_NOT_FORMATED;
if (buffer[14] != 0x0E) /* Check the size (only static memory supported yet)*/
return PCDNFCT1_ERROR_MEMORY_INTERNAL;
// Searching for the first NDEF TLV
while (buffer[NDEFposition] != PCDNFCT1_TLV_NDEF)
{
if (buffer[NDEFposition] == PCDNFCT1_TLV_EMPTY) // Empty TLV
NDEFposition++;
else if (buffer[NDEFposition] == PCDNFCT1_TLV_LOCK || buffer[NDEFposition] == PCDNFCT1_TLV_MEM) // Lock CTRL TLV or Mem CTRL TLV
NDEFposition+=5;
else
return PCDNFCT1_ERROR; // Other TLV not supported yet (proprietary)
if (NDEFposition > NFCT1_MAX_TAGMEMORY)
return PCDNFCT1_ERROR; // EOF and no NDEF TLV found
}
// Get the length of the message and copy it
if (buffer[NDEFposition+1] == 0xFF) // Long message (cannot happen with static memory...)
{
size = buffer[NDEFposition+2]<<8|buffer[NDEFposition+3];
memcpy(&TT1Tag[16],&buffer[NDEFposition],size+5);
}
else // Short message
{
memcpy(&TT1Tag[16],&buffer[NDEFposition],buffer[NDEFposition+1]+3);
}
return PCDNFCT1_OK;
Error:
return PCDNFCT1_ERROR;
}
/**
* @brief This function writes the NDEF message to a tag type 1 from the TT1Tag buffer
* @retval PCDNFCT1_OK : Command success
* @retval PCDNFCT1_ERROR : Transmission error
* @retval PCDNFCT1_ERROR_MEMORY : Not enough memory available on the tag
*/
uint8_t PCDNFCT1_WriteNDEF( void )
{
uint8_t status;
uint8_t buffer[NFCT1_MAX_TAGMEMORY+2];
uint16_t NDEFposition = 16, size, i;
errchk(PCDNFCT1_ReadAll(buffer));
if ((buffer[2] & PCDNFCT1_NDEF_CAPABLE_MSK) != 0x10) /* NDEF capable TT1 if H0 = 0x1X */
return PCDNFCT1_ERROR_NOT_FORMATED;
if (buffer[12] != PCDNFCT1_NDEF_MNB) /* CC file with NDEF info */
return PCDNFCT1_ERROR_NOT_FORMATED;
if (buffer[14] != 0x0E) /* Check the size (only static memory supported yet)*/
return PCDNFCT1_ERROR;
// Searching for the first NDEF TLV
while (buffer[NDEFposition] != PCDNFCT1_TLV_NDEF)
{
if (buffer[NDEFposition] == PCDNFCT1_TLV_EMPTY) // Empty TLV
NDEFposition++;
else if (buffer[NDEFposition] == PCDNFCT1_TLV_LOCK || buffer[NDEFposition] == PCDNFCT1_TLV_MEM) // Lock CTRL TLV or Mem CTRL TLV
NDEFposition+=5;
else
return PCDNFCT1_ERROR; // Other TLV not supported yet (proprietary)
if (NDEFposition > NFCT1_MAX_TAGMEMORY)
return PCDNFCT1_ERROR; // EOF and no NDEF TLV found
}
if (TT1Tag[15] == 0xFF)
size = (((TT1Tag[16])<<8) | (TT1Tag[17])) + 4;
else
size = TT1Tag[15]+2;
if (size > NFCT1_MAX_TAGMEMORY-32)
return PCDNFCT1_ERROR_MEMORY_TAG;
// Invalidate the NDEF message
PCDNFCT1_WriteErase(8,PCDNFCT1_NDEF_DISABLE);
NDEFposition-=3;
for(i=15;i<15+size;i++,NDEFposition++)
{
errchk(PCDNFCT1_WriteErase(NDEFposition,TT1Tag[i]));
}
// Validate the NDEF message
PCDNFCT1_WriteErase(8,PCDNFCT1_NDEF_MNB);
return PCDNFCT1_OK;
Error:
return PCDNFCT1_ERROR;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

75
src/lib_nfctype1pcd.h Normal file
View File

@@ -0,0 +1,75 @@
/**
******************************************************************************
* @file lib_nfctype1pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type1 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LIB_NFCTYPE1PCD_H
#define _LIB_NFCTYPE1PCD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_pcd.h"
/* Error codes */
#define PCDNFCT1_OK PCDNFC_OK
#define PCDNFCT1_ERROR PCDNFC_ERROR
#define PCDNFCT1_ERROR_MEMORY_TAG PCDNFC_ERROR_MEMORY_TAG
#define PCDNFCT1_ERROR_MEMORY_INTERNAL PCDNFC_ERROR_MEMORY_INTERNAL
#define PCDNFCT1_ERROR_NOT_FORMATED PCDNFC_ERROR_NOT_FORMATED
/* Command List */
#define PCDNFCT1_READALL 0x00
#define PCDNFCT1_WRITE_E 0x53
/* Mask */
#define PCDNFCT1_NDEF_CAPABLE_MSK 0xF0
/* TLV */
#define PCDNFCT1_TLV_EMPTY 0x00
#define PCDNFCT1_TLV_LOCK 0x01
#define PCDNFCT1_TLV_MEM 0x02
#define PCDNFCT1_TLV_NDEF 0x03
#define PCDNFCT1_NDEF_MNB 0xE1
#define PCDNFCT1_NDEF_DISABLE 0x00
#define PCDNFCT1_TOPAZ_MODE 0xA8
/* Functions */
uint8_t PCDNFCT1_ReadNDEF( void );
uint8_t PCDNFCT1_WriteNDEF( void );
#ifdef __cplusplus
}
#endif
#endif /* _LIB_NFCTYPE1PCD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

344
src/lib_nfctype2pcd.cpp Normal file
View File

@@ -0,0 +1,344 @@
/**
******************************************************************************
* @file lib_nfctype2pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type2 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "Arduino.h"
#include "lib_nfctype2pcd.h"
extern uint8_t TT2Tag[];
static uint8_t PCDNFCT2_Read(uint8_t blocNbr, uint8_t *pBufferRead);
static uint8_t PCDNFCT2_Write(uint8_t blocNbr, uint8_t *pBufferWrite);
static uint8_t PCDNFCT2_SectorSelect(uint8_t sector);
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup NFC_type2_pcd
* @{
* @brief This file is used to exchange with NFC FORUM Type2 Tag.
*/
/** @addtogroup lib_nfctype2pcd_Private_Functions
* @{
*/
/**
* @brief This function generates the Read command
* @param blocNbr : First bloc number
* @param pBufferRead : Pointer on the buffer which will contain the data read
* @retval PCDNFCT2_OK : Command success
* @retval PCDNFCT2_ERROR : Transmission error
*/
static uint8_t PCDNFCT2_Read(uint8_t blocNbr, uint8_t *pBufferRead)
{
uint8_t buffer[] = {PCDNFCT2_READ,0,SEND_MASK_APPENDCRC|SEND_MASK_8BITSINFIRSTBYTE};
buffer[1] = blocNbr;
if (PCD_SendRecv(3,buffer, pBufferRead) == PCD_SUCCESSCODE)
return PCDNFCT2_OK;
else
return PCDNFCT2_ERROR;
}
/**
* @brief This function generates the Write command
* @param blocNbr : First bloc number
* @param pBufferWrite : Pointer on the buffer which contains the data to write
* @retval PCDNFCT2_OK : Command success
*/
static uint8_t PCDNFCT2_Write(uint8_t blocNbr, uint8_t *pBufferWrite)
{
uint8_t pBufferRead[32];
uint8_t buffer[] = {PCDNFCT2_WRITE,0,0,0,0,0,SEND_MASK_APPENDCRC|SEND_MASK_8BITSINFIRSTBYTE};
buffer[1] = blocNbr;
memcpy(&buffer[2], pBufferWrite,4);
PCD_SendRecv(7,buffer, pBufferRead);
return PCDNFCT2_OK;
}
/**
* @brief This function generates the SectorSelect command
* @param sector : Sector number (0/1)
* @retval PCDNFCT2_OK : Command success
* @retval PCDNFCT2_ERROR : Transmission error
*/
static uint8_t PCDNFCT2_SectorSelect(uint8_t sector)
{
uint8_t pBufferRead[32];
uint8_t buffer[] = {PCDNFCT2_SECTOR_SEL,0xFF,SEND_MASK_APPENDCRC|SEND_MASK_8BITSINFIRSTBYTE}; // First part
uint8_t buffer2[] = {0,0x00,0x00,0x00,SEND_MASK_APPENDCRC|SEND_MASK_8BITSINFIRSTBYTE}; // Second part
buffer2[0] = sector;
PCD_SendRecv(3,buffer, pBufferRead);
if (pBufferRead[0] == 0x90 && pBufferRead[1] == 0x04 && pBufferRead[2] == 0x0A) // ACK
{
PCD_SendRecv(5,buffer2, pBufferRead);
if (pBufferRead[0] == 0x87 && pBufferRead[1] == 0x00) // Passive ACK = no answer so ST95HF send a timeout
return PCDNFCT2_OK;
else
return PCDNFCT2_ERROR;
}
else
return PCDNFCT2_ERROR;
}
/**
* @}
*/
/** @addtogroup lib_nfctype2pcd_Public_Functions
* @{
*/
/**
* @brief This function reads the NDEF message from a tag type 2 and store result in the TT2Tag buffer
* @retval PCDNFCT2_OK : Command success
* @retval PCDNFCT2_ERROR : Transmission error
* @retval PCDNFCT2_ERROR_LOCKED : The tag cannot be read (CC lock)
*/
uint8_t PCDNFCT2_ReadNDEF( void )
{
uint8_t status;
uint8_t bufferRead[PCDNFCT2_READ_SIZE_BUFFER];
uint8_t buffer[NFCT2_MAX_TAGMEMORY];
uint16_t size, totalSize, i;
uint16_t NDEFposition = 16;
// Check if CC is present with NDEF capability
errchk(PCDNFCT2_Read(0,buffer));
if (buffer[14] != PCDNFCT2_NDEF_MNB)
return PCDNFCT2_ERROR_NOT_FORMATED;
// Check if the tag is not protected
if ((buffer[17]&PCDNFCT2_READ_MSK) != 0x00)
return PCDNFCT2_ERROR_LOCKED;
// Read the size from CC
totalSize = buffer[16]*8;
// Check if there is enough memory available to read the tag
if (totalSize > NFCT2_MAX_TAGMEMORY)
return PCDNFCT2_ERROR_MEMORY_INTERNAL;
if (totalSize > PCDNFCT2_SECTOR_SIZE)
size = PCDNFCT2_SECTOR_SIZE;
else
size = totalSize;
// Read the whole memory
for (i=0;i<size/4;i+=4)
{
errchk(PCDNFCT2_Read(i,bufferRead));
memcpy(&buffer[i*4],&bufferRead[2],PCDNFCT2_READ_SIZE);
}
// Second sector (if needed)
if (totalSize > PCDNFCT2_SECTOR_SIZE)
{
errchk(PCDNFCT2_SectorSelect(1));
size = totalSize-PCDNFCT2_SECTOR_SIZE;
for (i=4;i<size/4;i+=4)
{
errchk(PCDNFCT2_Read(i,bufferRead));
memcpy(&buffer[PCDNFCT2_SECTOR_SIZE+i*4],&bufferRead[2],PCDNFCT2_READ_SIZE);
}
}
// Searching for the first NDEF TLV
while (buffer[NDEFposition] != PCDNFCT2_TLV_NDEF)
{
if (buffer[NDEFposition] == PCDNFCT2_TLV_EMPTY) // Empty TLV
NDEFposition++;
else if (buffer[NDEFposition] == PCDNFCT2_TLV_LOCK || buffer[NDEFposition] == PCDNFCT2_TLV_MEM) // Lock CTRL TLV or Mem CTRL TLV
NDEFposition+=5;
else
return PCDNFCT2_ERROR; // Other TLV not supported yet (proprietary)
if (NDEFposition > totalSize)
return PCDNFCT2_ERROR; // EOF and no NDEF TLV found
}
// Get the length of the message and copy it
if (buffer[NDEFposition+1] == 0xFF) // Long message
{
size = buffer[NDEFposition+2]<<8|buffer[NDEFposition+3];
memcpy(&TT2Tag[16],&buffer[NDEFposition],size+5);
}
else // Short message
{
memcpy(&TT2Tag[16],&buffer[NDEFposition],buffer[NDEFposition+1]+3);
}
return PCDNFCT2_OK;
Error:
return PCDNFCT2_ERROR;
}
/**
* @brief This function writes the NDEF message to a tag type 2 from the TT2Tag buffer
* @retval PCDNFCT2_OK : Command success
* @retval PCDNFCT2_ERROR : Transmission error
* @retval PCDNFCT2_ERROR_LOCKED : The tag cannot be write or read (CC lock)
* @retval PCDNFCT2_ERROR_MEMORY : Not enough memory available on the tag
*/
uint8_t PCDNFCT2_WriteNDEF( void )
{
uint8_t status;
uint8_t bufferRead[PCDNFCT2_READ_SIZE_BUFFER];
uint8_t buffer[NFCT2_MAX_TAGMEMORY];
uint8_t byteSize;
uint16_t size, totalSize, i, firstBloc;
uint16_t NDEFposition = 16;
// Check if CC is present with NDEF capability
errchk(PCDNFCT2_Read(0,buffer));
if (buffer[14] != PCDNFCT2_NDEF_MNB)
return PCDNFCT2_ERROR_NOT_FORMATED;
// Check if the tag is not protected for read and write
if ((buffer[17]&(PCDNFCT2_READ_MSK|PCDNFCT2_WRITE_MSK)) != 0x00)
return PCDNFCT2_ERROR_LOCKED;
// Read the size from CC
totalSize = buffer[16]*8;
// Read the size of message
if (TT2Tag[17] == 0xFF) size = TT2Tag[18]<<8|TT2Tag[19];
else size = TT2Tag[17];
// Check if there is enough memory available
if (size > totalSize)
return PCDNFCT2_ERROR_MEMORY_TAG;
if (totalSize > PCDNFCT2_SECTOR_SIZE)
size = PCDNFCT2_SECTOR_SIZE;
else
size = totalSize;
// Read the whole memory
for (i=0;i<size/4;i+=4)
{
errchk(PCDNFCT2_Read(i,bufferRead));
memcpy(&buffer[i*4],&bufferRead[2],PCDNFCT2_READ_SIZE);
}
// Second sector (if needed)
if (totalSize > PCDNFCT2_SECTOR_SIZE)
{
PCDNFCT2_SectorSelect(1);
size = totalSize-PCDNFCT2_SECTOR_SIZE;
for (i=4;i<size/4;i+=4)
{
errchk(PCDNFCT2_Read(i,bufferRead));
memcpy(&buffer[PCDNFCT2_SECTOR_SIZE+i*4],&bufferRead[2],PCDNFCT2_READ_SIZE);
}
}
// Searching for the first NDEF TLV
while (buffer[NDEFposition] != PCDNFCT2_TLV_NDEF)
{
if (buffer[NDEFposition] == PCDNFCT2_TLV_EMPTY) // Empty TLV
NDEFposition++;
else if (buffer[NDEFposition] == PCDNFCT2_TLV_LOCK || buffer[NDEFposition] == PCDNFCT2_TLV_MEM) // Lock CTRL TLV or Mem CTRL TLV
NDEFposition+=5;
else
return PCDNFCT2_ERROR; // Other TLV not supported yet (proprietary)
if (NDEFposition > totalSize)
return PCDNFCT2_ERROR; // EOF and no NDEF TLV found
}
// Write the message
if (TT2Tag[17] == 0xFF)
size = ((TT2Tag[18]<<8) | (TT2Tag[19])) + 5;
else
size = TT2Tag[17] +3;
memcpy(&buffer[NDEFposition],&TT2Tag[16],size);
// The size has to be 0 for the first write
byteSize = TT2Tag[17];
buffer[NDEFposition+1] = 0;
firstBloc = NDEFposition>>2;
// To be sure to write the first sector
if (totalSize > PCDNFCT2_SECTOR_SIZE)
{
errchk(PCDNFCT2_SectorSelect(0));
}
// Write all the blocks
for (i=firstBloc;i<=(size>>2)+firstBloc;i++)
{
errchk(PCDNFCT2_Write(i, &buffer[i*4]));
// Tag from NXP needs this delay...
delay(5);
}
// Write the size (numBloc = (NDEFposition+1)>>2)
buffer[NDEFposition+1] = byteSize;
errchk(PCDNFCT2_Write(((NDEFposition+1)>>2), &buffer[((NDEFposition+1)>>2)*4]));
return PCDNFCT2_OK;
Error:
return PCDNFCT2_ERROR;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

85
src/lib_nfctype2pcd.h Normal file
View File

@@ -0,0 +1,85 @@
/**
******************************************************************************
* @file lib_nfctype2pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type2 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LIB_NFCTYPE2PCD_H
#define _LIB_NFCTYPE2PCD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_pcd.h"
/* Error codes */
#define PCDNFCT2_OK PCDNFC_OK
#define PCDNFCT2_ERROR PCDNFC_ERROR
#define PCDNFCT2_ERROR_MEMORY_TAG PCDNFC_ERROR_MEMORY_TAG
#define PCDNFCT2_ERROR_MEMORY_INTERNAL PCDNFC_ERROR_MEMORY_INTERNAL
#define PCDNFCT2_ERROR_LOCKED PCDNFC_ERROR_LOCKED
#define PCDNFCT2_ERROR_NOT_FORMATED PCDNFC_ERROR_NOT_FORMATED
/* Command List */
#define PCDNFCT2_READ 0x30
#define PCDNFCT2_WRITE 0xA2
#define PCDNFCT2_SECTOR_SEL 0xC2
/* Size */
#define PCDNFCT2_READ_SIZE 16
#define PCDNFCT2_READ_SIZE_BUFFER 18
#ifndef PCDNFCT2_SECTOR_SIZE
// if not defined at application level, let's use 1024 for wider compatibility
// it can be reduced to lower values, e.g. 256, but with restrictions :
// issue on second sector read
#define PCDNFCT2_SECTOR_SIZE 1024
#endif
/* Mask */
#define PCDNFCT2_READ_MSK 0xF0
#define PCDNFCT2_WRITE_MSK 0x0F
/* TLV */
#define PCDNFCT2_TLV_EMPTY 0x00
#define PCDNFCT2_TLV_LOCK 0x01
#define PCDNFCT2_TLV_MEM 0x02
#define PCDNFCT2_TLV_NDEF 0x03
#define PCDNFCT2_NDEF_MNB 0xE1
/* Functions */
uint8_t PCDNFCT2_ReadNDEF( void );
uint8_t PCDNFCT2_WriteNDEF( void );
#ifdef __cplusplus
}
#endif
#endif /* _LIB_NFCTYPE2PCD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

349
src/lib_nfctype3pcd.cpp Normal file
View File

@@ -0,0 +1,349 @@
/**
******************************************************************************
* @file lib_nfctype3pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type3 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "lib_nfctype3pcd.h"
extern FELICA_CARD FELICA_Card;
//extern uint8_t TT3Tag[];
extern uint8_t *TT3AttribInfo, *TT3NDEFfile;
static uint8_t PCDNFCT3_ReadAttribInfo(uint8_t *pBufferRead);
static uint8_t PCDNFCT3_WriteAttribInfo(uint8_t *pBufferWrite);
static uint8_t PCDNFCT3_ReadMessage(const uint32_t NbByteToRead, uint8_t *pBufferRead);
static uint8_t PCDNFCT3_WriteMessage(const uint32_t NbByteToWrite, uint8_t *pBufferWrite, uint8_t maxBlocWrite);
static void PCDNFCT3_UpdateCheckSum(uint8_t *bufferAttrib);
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup NFC_type3_pcd
* @{
* @brief This file is used to exchange with NFC FORUM Type3 Tag.
*/
/** @addtogroup lib_nfctype3pcd_Private_Functions
* @{
*/
/**
* @brief This function generates the Check command in order to read the AttribInfo field
* @param pBufferRead : Pointer on the buffer which will contain the data read
* @retval PCDNFCT3_OK : Command success
* @retval PCDNFCT3_ERROR : Transmission error
*/
static uint8_t PCDNFCT3_ReadAttribInfo(uint8_t *pBufferRead)
{
uint8_t buffer[] = {PCDNFCT3_CHECK,0,0,0,0,0,0,0,0,0x01,PCDNFCT3_CODE_READ_LSB,PCDNFCT3_CODE_READ_MSB,0x01,PCDNFCT3_FIRST_BLOC_MSB,PCDNFCT3_FIRST_BLOC_LSB};
/* Write UID */
memcpy(&buffer[1],FELICA_Card.UID,8);
if (PCD_SendRecv(15,buffer, pBufferRead) == PCD_SUCCESSCODE)
return PCDNFCT3_OK;
else
return PCDNFCT3_ERROR;
}
/**
* @brief This function generates the Update command in order to write the AttribInfo field
* @param pBufferWrite : Pointer on the buffer which contains the data to write
* @retval PCDNFCT3_OK : Command success
* @retval PCDNFCT3_ERROR : Transmission error
*/
static uint8_t PCDNFCT3_WriteAttribInfo(uint8_t *pBufferWrite)
{
uint8_t buffer[31] = {PCDNFCT3_UPDATE,0,0,0,0,0,0,0,0,0x01,PCDNFCT3_CODE_WRITE_LSB,PCDNFCT3_CODE_WRITE_MSB,0x01,PCDNFCT3_FIRST_BLOC_MSB,PCDNFCT3_FIRST_BLOC_LSB};
uint8_t bufferRead[PCDNFCT3_ATTR_SIZE];
/* Write UID */
memcpy(&buffer[1],FELICA_Card.UID,8);
/* Write AttribInfo */
memcpy(&buffer[15],pBufferWrite,PCDNFCT3_ATTR_SIZE);
if (PCD_SendRecv(31,buffer, bufferRead) == PCD_SUCCESSCODE)
{
if (bufferRead[11] == 0 && bufferRead[12] == 0)
return PCDNFCT3_OK;
else
return PCDNFCT3_ERROR; /* Error code in reception frame */
}
else
return PCDNFCT3_ERROR; /* Transmission error */
}
/**
* @brief This function generates check commands in order to read all the NDEF message
* @param NbByteToRead : Size of the NDEF message to read
* @param pBufferRead : Pointer on the buffer which will contain the data read
* @retval PCDNFCT3_OK : Command success
* @retval PCDNFCT3_ERROR : Transmission error
*/
static uint8_t PCDNFCT3_ReadMessage(const uint32_t NbByteToRead, uint8_t *pBufferRead)
{
uint8_t nbBloc,i,j=0,maxBlocRead;
uint8_t buffer[48] = {PCDNFCT3_CHECK,0,0,0,0,0,0,0,0,0x01,PCDNFCT3_CODE_READ_LSB,PCDNFCT3_CODE_READ_MSB};
uint8_t bufferRead[280];
memcpy(&buffer[1],FELICA_Card.UID,8);
/* Check the maximum number of bloc that can be read with one command */
maxBlocRead = TT3AttribInfo[1];
/* Check the total number of bloc to read */
nbBloc = (NbByteToRead>>4)+1;
/* Send as many commands as needed */
while (nbBloc > maxBlocRead)
{
nbBloc-=maxBlocRead;
buffer[12] = maxBlocRead;
for(i=0;i<maxBlocRead;i++) // 8001,8002,8003...
{
buffer[13+i*2] = PCDNFCT3_FIRST_BLOC_MSB;
buffer[14+i*2] = PCDNFCT3_FIRST_BLOC_LSB+i+1+j*maxBlocRead;
}
if (PCD_SendRecv(13+maxBlocRead*2,buffer, bufferRead) != PCD_SUCCESSCODE)
return PCDNFCT3_ERROR;
/* Append the result to the pBufferRead buffer */
memcpy(&pBufferRead[j*maxBlocRead*16],&bufferRead[14],maxBlocRead*16);
j++;
}
if (nbBloc != 0) /* If there are blocks remaining */
{
buffer[12] = nbBloc;
for(i=0;i<nbBloc;i++) // 8001,8002,8003...
{
buffer[13+i*2] = PCDNFCT3_FIRST_BLOC_MSB;
buffer[14+i*2] = PCDNFCT3_FIRST_BLOC_LSB+i+1+j*maxBlocRead;
}
if (PCD_SendRecv(13+nbBloc*2,buffer, bufferRead) != PCD_SUCCESSCODE)
return PCDNFCT3_ERROR;
/* Append the result to the pBufferRead buffer */
memcpy(&pBufferRead[j*maxBlocRead*16],&bufferRead[14],nbBloc*16);
}
return PCDNFCT3_OK;
}
/**
* @brief This function generates Update commands in order to write all the NDEF message
* @param NbByteToWrite : Size of the NDEF message to write
* @param pBufferWrite : Pointer on the buffer which contains the data to write
* @param maxBlocWrite : Maximum number of blocs that can be write in a single command
* @retval PCDNFCT3_OK : Command success
* @retval PCDNFCT3_ERROR : Transmission error
*/
static uint8_t PCDNFCT3_WriteMessage(const uint32_t NbByteToWrite, uint8_t *pBufferWrite, uint8_t maxBlocWrite)
{
uint8_t nbBloc,i,j=0;
uint8_t buffer[280] = {PCDNFCT3_UPDATE,0,0,0,0,0,0,0,0,0x01,PCDNFCT3_CODE_WRITE_LSB,PCDNFCT3_CODE_WRITE_MSB};
uint8_t bufferRead[16];
/* Write UID */
memcpy(&buffer[1],FELICA_Card.UID,8);
/* Check the total number of bloc to write */
nbBloc = (NbByteToWrite>>4)+1;
/* Send as many commands as needed */
while (nbBloc > maxBlocWrite)
{
nbBloc-=maxBlocWrite;
buffer[12] = maxBlocWrite;
for(i=0;i<maxBlocWrite;i++) // 8001,8002,8003...
{
buffer[13+i*2] = PCDNFCT3_FIRST_BLOC_MSB;
buffer[14+i*2] = PCDNFCT3_FIRST_BLOC_LSB+i+1+j*maxBlocWrite;
}
memcpy(&buffer[13+maxBlocWrite*2],&pBufferWrite[j*maxBlocWrite*16],maxBlocWrite*16);
if (PCD_SendRecv(13+maxBlocWrite*2+16*maxBlocWrite,buffer, bufferRead) != PCD_SUCCESSCODE)
return PCDNFCT3_ERROR;
if (bufferRead[11] != 0 || bufferRead[12] != 0)
return PCDNFCT3_ERROR; /* Error code in reception frame */
j++;
}
if (nbBloc != 0) /* If there are blocks remaining */
{
buffer[12] = nbBloc;
for(i=0;i<nbBloc;i++) // 8001,8002,8003...
{
buffer[13+i*2] = PCDNFCT3_FIRST_BLOC_MSB;
buffer[14+i*2] = PCDNFCT3_FIRST_BLOC_LSB+i+1+j*maxBlocWrite;
}
memcpy(&buffer[13+nbBloc*2],&pBufferWrite[j*maxBlocWrite*16],nbBloc*16);
if (PCD_SendRecv(13+nbBloc*2+16*nbBloc,buffer, bufferRead) != PCD_SUCCESSCODE)
return PCDNFCT3_ERROR;
if (bufferRead[11] != 0 || bufferRead[12] != 0)
return PCDNFCT3_ERROR; /* Error code in reception frame */
}
return PCDNFCT3_OK;
}
/**
* @brief This function updates the checksum of the AttribInfo field
* @param bufferAttrib : Pointer to the memory containing the AttribInfo field
*/
static void PCDNFCT3_UpdateCheckSum(uint8_t *bufferAttrib)
{
uint8_t i;
uint16_t checkSum = 0;
for(i=0;i<14;i++)
checkSum+=bufferAttrib[i];
bufferAttrib[14] = checkSum>>8;
bufferAttrib[15] = checkSum&0x00FF;
}
/**
* @}
*/
/** @addtogroup lib_nfctype3pcd_Public_Functions
* @{
*/
/**
* @brief This function reads the NDEF message from a tag type 3 and store result in the TT3Tag buffer
* @retval PCDNFCT3_OK : Command success
* @retval PCDNFCT3_ERROR : Transmission error
* @retval PCDNFCT3_ERROR_LOCKED : The tag cannot be read (AttribInfo lock)
*/
uint8_t PCDNFCT3_ReadNDEF( void )
{
uint8_t buffer[32];
uint8_t status;
uint32_t size;
/* Read AttribInfo field */
errchk(PCDNFCT3_ReadAttribInfo(buffer));
memcpy(TT3AttribInfo,&buffer[14],PCDNFCT3_ATTR_SIZE);
/* Calculate the size */
size = TT3AttribInfo[11]<<16|TT3AttribInfo[12]<<8|TT3AttribInfo[13];
// Check if there is enough memory available to read the tag
if (size > NFCT3_MAX_TAGMEMORY)
return PCDNFCT3_ERROR_MEMORY_INTERNAL;
/* Read the NDEF message */
errchk(PCDNFCT3_ReadMessage(size,TT3NDEFfile));
return PCDNFCT3_OK;
Error:
return PCDNFCT3_ERROR;
}
/**
* @brief This function writes the NDEF message to a tag type 3 from the TT3Tag buffer
* @retval PCDNFCT3_OK : Command success
* @retval PCDNFCT3_ERROR : Transmission error
* @retval PCDNFCT3_ERROR_LOCKED : The tag cannot be write (AttribInfo lock)
* @retval PCDNFCT3_ERROR_MEMORY : Not enough memory available on the tag
*/
uint8_t PCDNFCT3_WriteNDEF( void )
{
uint8_t buffer[32];
uint8_t bufferAttrib[16];
uint8_t status;
uint32_t size, memoryAvailable;
/* Read AttribInfo field */
errchk(PCDNFCT3_ReadAttribInfo(buffer));
memcpy(bufferAttrib,&buffer[14],PCDNFCT3_ATTR_SIZE);
/* Check if write is available */
if(bufferAttrib[10] != 0x01)
return PCDNFCT3_ERROR_LOCKED;
/* Check if there is enough memory */
memoryAvailable = ((bufferAttrib[3]<<8)|bufferAttrib[4]);
size = TT3AttribInfo[11]<<16|TT3AttribInfo[12]<<8|TT3AttribInfo[13];
if ((size>>4) > memoryAvailable)
return PCDNFCT3_ERROR_MEMORY_TAG;
/* Writing flag set to ON */
bufferAttrib[9] = PCDNFCT3_WRITE_ON;
/* Update CheckSum */
PCDNFCT3_UpdateCheckSum(bufferAttrib);
/* Write the AttribInfo */
errchk(PCDNFCT3_WriteAttribInfo(bufferAttrib));
/* Write the message */
errchk(PCDNFCT3_WriteMessage(size, TT3NDEFfile,bufferAttrib[2]));
/* Length */
memcpy(&bufferAttrib[11],&TT3AttribInfo[11],3);
/* Writing Flag OFF */
bufferAttrib[9] = PCDNFCT3_WRITE_OFF;
/* CheckSum */
PCDNFCT3_UpdateCheckSum(bufferAttrib);
/* Write the AttribInfo */
errchk(PCDNFCT3_WriteAttribInfo(bufferAttrib));
return PCDNFCT3_OK;
Error:
return PCDNFCT3_ERROR;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

75
src/lib_nfctype3pcd.h Normal file
View File

@@ -0,0 +1,75 @@
/**
******************************************************************************
* @file lib_nfctype3pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type3 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LIB_NFCTYPE3PCD_H
#define _LIB_NFCTYPE3PCD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_iso18092pcd.h"
#define PCDNFCT3_OK PCDNFC_OK
#define PCDNFCT3_ERROR PCDNFC_ERROR
#define PCDNFCT3_ERROR_MEMORY_TAG PCDNFC_ERROR_MEMORY_TAG
#define PCDNFCT3_ERROR_MEMORY_INTERNAL PCDNFC_ERROR_MEMORY_INTERNAL
#define PCDNFCT3_ERROR_LOCKED PCDNFC_ERROR_LOCKED
/* Command List */
#define PCDNFCT3_CHECK 0x06
#define PCDNFCT3_UPDATE 0x08
/* Service code */
#define PCDNFCT3_CODE_READ_MSB 0x00
#define PCDNFCT3_CODE_READ_LSB 0x0B
#define PCDNFCT3_CODE_WRITE_MSB 0x00
#define PCDNFCT3_CODE_WRITE_LSB 0x09
#define PCDNFCT3_FIRST_BLOC_MSB 0x80
#define PCDNFCT3_FIRST_BLOC_LSB 0x00
/* Flag */
#define PCDNFCT3_WRITE_ON 0x0F
#define PCDNFCT3_WRITE_OFF 0x00
/* Size */
#define PCDNFCT3_ATTR_SIZE 16
/* Functions */
uint8_t PCDNFCT3_ReadNDEF( void );
uint8_t PCDNFCT3_WriteNDEF( void );
#ifdef __cplusplus
}
#endif
#endif /* _LIB_NFCTYPE3PCD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

348
src/lib_nfctype4pcd.cpp Normal file
View File

@@ -0,0 +1,348 @@
/**
******************************************************************************
* @file lib_nfctype4pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type4 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "lib_nfctype4pcd.h"
extern uint8_t CardNDEFfileT4A[];
extern uint8_t CardNDEFfileT4B[];
/* Variables for the different modes */
//extern DeviceMode_t devicemode;
extern TagType_t nfc_tagtype;
extern uint16_t FSC;
static int8_t PCDNFCT4_SelectApplication(void);
static int8_t PCDNFCT4_SelectCCfile(void);
static int8_t PCDNFCT4_SelectNDEFfile(const uint8_t NDEF_ID_MSB, const uint8_t NDEF_ID_LSB);
static uint8_t PCDNFCT4_ReadBinary(const uint16_t Offset ,const uint8_t NbByteToRead , uint8_t *pBufferRead);
static uint8_t PCDNFCT4_UpdateBinary(const uint16_t Offset ,const uint8_t NbByteToWrite , uint8_t *pBufferWrite);
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup NFC_type4_pcd
* @{
* @brief This file is used to exchange with NFC FORUM Type4 Tag.
*/
/** @addtogroup lib_nfctype4pcd_Private_Functions
* @{
*/
/**
* @brief This function sends the SelectApplication command
* @retval PCDNFCT4_OK : Command success
* @retval PCDNFCT4_ERROR : Transmission error
*/
static int8_t PCDNFCT4_SelectApplication(void)
{
uint8_t P1byte = 0x04,
P2byte = 0x00,
LCbyte = 0x07,
NDEFaplicationField[] = PCDNFCT4_SELECT_APPLI;
if (ISO7816_SelectFile ( P1byte , P2byte , LCbyte ,NDEFaplicationField ) == ISO7816_SUCCESSCODE)
return PCDNFCT4_OK;
else
return PCDNFCT4_ERROR;
}
/**
* @brief This function sends the SelectCCfile command
* @retval PCDNFCT4_OK : Command success
* @retval PCDNFCT4_ERROR : Transmission error
*/
static int8_t PCDNFCT4_SelectCCfile(void)
{
uint8_t P1byte = 0x00,
P2byte = 0x0C,
LCbyte = 0x02,
FileId[] = PCDNFCT4_CC_ID;
if (ISO7816_SelectFile ( P1byte , P2byte , LCbyte ,FileId ) == ISO7816_SUCCESSCODE)
return PCDNFCT4_OK;
else
return PCDNFCT4_ERROR;
}
/**
* @brief This function sends the SelectNDEF command
* @param NDEF_ID_MSB : NDEF identifier most significant bit
* @param NDEF_ID_LSB : NDEF identifier least significant bit
* @retval PCDNFCT4_OK : Command success
* @retval PCDNFCT4_ERROR : Transmission error
*/
static int8_t PCDNFCT4_SelectNDEFfile(const uint8_t NDEF_ID_MSB, const uint8_t NDEF_ID_LSB)
{
uint8_t P1byte = 0x00,
P2byte = 0x0C,
LCbyte = 0x02,
FileId[2];
FileId[0] = NDEF_ID_MSB;
FileId[1] = NDEF_ID_LSB;
if (ISO7816_SelectFile ( P1byte , P2byte , LCbyte ,FileId ) == ISO7816_SUCCESSCODE)
return PCDNFCT4_OK;
else
return PCDNFCT4_ERROR;
}
/**
* @brief This function sends a read binary command
* @param Offset : first byte to read
* @param NbByteToRead : number of byte to read
* @param pBufferRead : pointer of the buffer read from the tag
* @retval PCDNFCT4_OK : Command success
* @retval PCDNFCT4_ERROR : Transmission error
*/
static uint8_t PCDNFCT4_ReadBinary(const uint16_t Offset ,const uint8_t NbByteToRead , uint8_t *pBufferRead)
{
uint8_t P1byte = GETMSB(Offset),
P2byte = GETLSB(Offset),
LEbyte = NbByteToRead;
if (ISO7816_ReadBinary ( P1byte , P2byte , LEbyte ,pBufferRead ) == ISO7816_SUCCESSCODE)
return PCDNFCT4_OK;
else
return PCDNFCT4_ERROR;
}
/**
* @brief This function sends a update binary command
* @param Offset : first byte to write
* @param NbByteToWrite : number of byte to write
* @param pBufferWrite : pointer of the buffer which contains data to write
* @retval PCDNFCT4_OK : Command success
* @retval PCDNFCT4_ERROR : Transmission error
*/
static uint8_t PCDNFCT4_UpdateBinary(const uint16_t Offset ,const uint8_t NbByteToWrite , uint8_t *pBufferWrite)
{
uint8_t P1byte = GETMSB(Offset),
P2byte = GETLSB(Offset),
LEbyte = NbByteToWrite;
if (ISO7816_UpdateBinary ( P1byte , P2byte , LEbyte ,pBufferWrite ) == ISO7816_SUCCESSCODE)
return PCDNFCT4_OK;
else
return PCDNFCT4_ERROR;
}
/**
* @}
*/
/** @addtogroup lib_nfctype4pcd_Public_Functions
* @{
*/
/**
* @brief This function reads the NDEF message from a tag type 4 and store result in the CardNDEFfile buffer
* @retval PCDNFCT4_OK : Command success
* @retval PCDNFCT4_ERROR : Transmission error
* @retval PCDNFCT4_ERROR_LOCKED : The tag cannot be read (CCfile lock)
*/
uint8_t PCDNFCT4_ReadNDEF( void )
{
uint8_t status, NDEF_ID_MSB, NDEF_ID_LSB;
uint8_t limit = 0;
uint16_t size, i = 0, MLe;
uint8_t buffer[PCDNFCT4_BUFFER_READ];
uint8_t *CardNDEFfile;
// Choose the correct buffer
if (nfc_tagtype == TT4A)
CardNDEFfile = CardNDEFfileT4A;
else
CardNDEFfile = CardNDEFfileT4B;
// SelectAppli
errchk(PCDNFCT4_SelectApplication());
// SelectCC
errchk(PCDNFCT4_SelectCCfile());
errchk(PCDNFCT4_ReadBinary(0x00, 0x0F, buffer));
NDEF_ID_MSB = buffer[12];
NDEF_ID_LSB = buffer[13];
MLe = MIN((buffer[6]<<8|buffer[7]),0xF6);
// Check if read access is allowed
if (buffer[16] != PCDNFCT4_ACCESS_ALLOWED)
return PCDNFCT4_ERROR_LOCKED;
// SelectNDEF
errchk(PCDNFCT4_SelectNDEFfile(NDEF_ID_MSB,NDEF_ID_LSB));
// Read length
errchk(PCDNFCT4_ReadBinary(0x00, 0x02, buffer));
size = (((buffer[3])<<8) | (buffer[4])) + 2;
// Check if there is enough memory available to read the tag
if (size > NFCT4_MAX_NDEFMEMORY)
return PCDNFCT4_ERROR_MEMORY_INTERNAL;
/* Mle have a good chance to be bigger than FSC but just in case */
/* FSC - PCB, SW1, SW2, CRC1, CRC2 */
limit = MIN(MLe,(FSC-5));
// Read data
while (size>limit)
{
errchk(PCDNFCT4_ReadBinary(i*limit, limit, buffer));
memcpy(&CardNDEFfile[i*limit],&buffer[PCD_DATA_OFFSET+1],limit);
size -= limit;
i++;
}
if (size > 0)
{
errchk(PCDNFCT4_ReadBinary(i*limit, size, buffer));
memcpy(&CardNDEFfile[i*limit],&buffer[PCD_DATA_OFFSET+1],size);
}
return PCDNFCT4_OK;
Error:
return PCDNFCT4_ERROR;
}
/**
* @brief This function writes the NDEF message to a tag type 4 from the CardNDEFfile buffer
* @retval PCDNFCT4_OK : Command success
* @retval PCDNFCT4_ERROR : Transmission error
* @retval PCDNFCT4_ERROR_LOCKED : The tag cannot be write (CCfile lock)
* @retval PCDNFCT4_ERROR_MEMORY : Not enough memory available on the tag
*/
uint8_t PCDNFCT4_WriteNDEF( void )
{
uint8_t status, NDEF_ID_MSB, NDEF_ID_LSB;
uint16_t size, i = 0, MLc, memoryAvailable;
uint8_t buffer[32], bufferSize[2];
uint8_t *CardNDEFfile;
// Choose the correct buffer
if (nfc_tagtype == TT4A)
CardNDEFfile = CardNDEFfileT4A;
else
CardNDEFfile = CardNDEFfileT4B;
// SelectAppli
errchk(PCDNFCT4_SelectApplication());
// SelectCC
errchk(PCDNFCT4_SelectCCfile());
errchk(PCDNFCT4_ReadBinary(0x00, 0x0F, buffer));
NDEF_ID_MSB = buffer[12];
NDEF_ID_LSB = buffer[13];
// Check if there is enough memory available on the tag
memoryAvailable = buffer[14]<<8|buffer[15];
size = (((CardNDEFfile[0])<<8) | (CardNDEFfile[1])) + 2;
if (size > memoryAvailable)
return PCDNFCT4_ERROR_MEMORY_TAG;
// Check if write access is allowed
if (buffer[17] != PCDNFCT4_ACCESS_ALLOWED)
return PCDNFCT4_ERROR_LOCKED;
// Chaining not supported yet... and the maximum for ST95HF is 0xF6
MLc = MIN((buffer[8]<<8|buffer[9]),0xF6);
// SelectNDEF
errchk(PCDNFCT4_SelectNDEFfile(NDEF_ID_MSB,NDEF_ID_LSB));
// Write NDEF
// The size must be 0
bufferSize[0] = CardNDEFfile[0]; bufferSize[1] = CardNDEFfile[1];
CardNDEFfile[0] = CardNDEFfile[1] = 0;
while (size>MLc)
{
status = PCDNFCT4_UpdateBinary(i*MLc, MLc, &CardNDEFfile[i*MLc]);
// If an error occur we have to write back the size to the NDEF buffer
if (status == PCDNFCT4_ERROR)
{
CardNDEFfile[0]=bufferSize[0];
CardNDEFfile[1]=bufferSize[1];
return PCDNFCT4_ERROR;
}
size -= MLc;
i++;
}
if (size > 0)
{
status = PCDNFCT4_UpdateBinary(i*MLc, size, &CardNDEFfile[i*MLc]);
// If an error occur we have to write back the size to the NDEF buffer
if (status == PCDNFCT4_ERROR)
{
CardNDEFfile[0]=bufferSize[0];
CardNDEFfile[1]=bufferSize[1];
return PCDNFCT4_ERROR;
}
}
// Write the size
errchk(PCDNFCT4_UpdateBinary(0,2,bufferSize));
return PCDNFCT4_OK;
Error:
return PCDNFCT4_ERROR;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

64
src/lib_nfctype4pcd.h Normal file
View File

@@ -0,0 +1,64 @@
/**
******************************************************************************
* @file lib_nfctype4pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type4 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LIB_NFCTYPE4PCD_H
#define _LIB_NFCTYPE4PCD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_iso7816pcd.h"
#define PCDNFCT4_OK PCDNFC_OK
#define PCDNFCT4_ERROR PCDNFC_ERROR
#define PCDNFCT4_ERROR_MEMORY_TAG PCDNFC_ERROR_MEMORY_TAG
#define PCDNFCT4_ERROR_MEMORY_INTERNAL PCDNFC_ERROR_MEMORY_INTERNAL
#define PCDNFCT4_ERROR_LOCKED PCDNFC_ERROR_LOCKED
/* Command List */
#define PCDNFCT4_SELECT_APPLI {0xD2,0x76,0x00,0x00,0x85,0x01,0x01,0x00}
#define PCDNFCT4_CC_ID {0xE1,0x03}
/* Size */
#define PCDNFCT4_BUFFER_READ 256
#define PCDNFCT4_ACCESS_ALLOWED 0x00
uint8_t PCDNFCT4_ReadNDEF(void);
uint8_t PCDNFCT4_WriteNDEF( void );
#ifdef __cplusplus
}
#endif
#endif /* _LIB_NFCTYPE4PCD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

234
src/lib_nfctype5pcd.cpp Normal file
View File

@@ -0,0 +1,234 @@
/**
******************************************************************************
* @file lib_nfctype5pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type2 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "lib_nfctype5pcd.h"
extern uint8_t TT5Tag[];
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup NFC_type5_pcd
* @{
* @brief This file is used to exchange with NFC FORUM Type5 Tag.
*/
/** @addtogroup lib_nfctype5pcd_Private_Functions
* @{
*/
/**
* @}
*/
/** @addtogroup lib_nfctype5pcd_Public_Functions
* @{
*/
/**
* @brief This function reads the NDEF message from a tag type V and store result in the TT5Tag buffer
* @retval PCDNFCT5_OK : Command success
* @retval PCDNFCT5_ERROR : Transmission error
* @retval PCDNFCT5_ERROR_LOCKED : The tag cannot be read (CC lock)
*/
uint8_t PCDNFCT5_ReadNDEF( void )
{
uint16_t size;
uint8_t tagDensity = ISO15693_HIGH_DENSITY;
// Try to determine the density by reading the first sector (128 bytes)
if (ISO15693_ReadBytesTagData(ISO15693_HIGH_DENSITY, ISO15693_LRiS64K, TT5Tag, 127, 0) != ISO15693_SUCCESSCODE)
{
if (ISO15693_ReadBytesTagData(ISO15693_LOW_DENSITY, ISO15693_LRiS64K, TT5Tag, 127, 0) != ISO15693_SUCCESSCODE)
return PCDNFCT5_ERROR;
tagDensity = ISO15693_LOW_DENSITY;
}
// NDEF capable ?
if (TT5Tag[0] != 0xE1)
return PCDNFCT5_ERROR_NOT_FORMATED;
// Check read access
if ((TT5Tag[1]&0x0C) != 0)
return PCDNFCT5_ERROR_LOCKED;
// Get the size of the message
if (TT5Tag[5] == 0xFF)
size = (TT5Tag[6]<<8)|TT5Tag[7];
else
size = 0x00FF&TT5Tag[5];
// Check if there is enough memory to read the tag
// If CC3 bit3 = 1 the size is higher than 2KB but we don't know the size...
if (size+7 > NFCT5_MAX_TAGMEMORY)
return PCDNFCT5_ERROR_MEMORY_INTERNAL;
// Read the rest of the tag if needed
if (size > 124)
{
if (ISO15693_ReadBytesTagData(tagDensity, ISO15693_LRiS64K, &TT5Tag[128], size-128, 128) != ISO15693_SUCCESSCODE)
{
return PCDNFCT5_ERROR;
}
}
return PCDNFCT5_OK;
}
/**
* @brief This function writes the NDEF message to a tag type V from the TT5Tag buffer
* @retval PCDNFCT5_OK : Command success
* @retval PCDNFCT5_ERROR : Transmission error
* @retval PCDNFCT5_ERROR_LOCKED : The tag cannot be write or read (CC lock)
* @retval PCDNFCT5_ERROR_MEMORY : Not enough memory available on the tag
*/
uint8_t PCDNFCT5_WriteNDEF( void )
{
uint8_t RepBuffer[30];
uint8_t firstSector[140], status;
uint16_t size, tagSize;
uint8_t tagDensity = ISO15693_HIGH_DENSITY;
// Try to determine the density by ready the first sector (128 bytes)
if (ISO15693_ReadBytesTagData(ISO15693_HIGH_DENSITY, ISO15693_LRiS64K, firstSector, 127, 0) != ISO15693_SUCCESSCODE)
{
if (ISO15693_ReadBytesTagData(ISO15693_LOW_DENSITY, ISO15693_LRiS64K, firstSector, 127, 0) != ISO15693_SUCCESSCODE)
return PCDNFCT5_ERROR;
tagDensity = ISO15693_LOW_DENSITY;
}
// NDEF capable ?
if (firstSector[0] != 0xE1)
{
/* Create the CC file */
// We need the size
if (tagDensity == ISO15693_HIGH_DENSITY)
ISO15693_GetSystemInfo (0x0A , 0x00, RepBuffer);
else
ISO15693_GetSystemInfo (0x02 , 0x00, RepBuffer);
if (RepBuffer[14] == 0xFF)
tagSize = (((RepBuffer[15]<<8)|RepBuffer[14])+1)*(RepBuffer[16]+1);
else
tagSize = (RepBuffer[14]+1)*(RepBuffer[15]+1);
// NDEF capable
TT5Tag[0] = 0xE1;
// Version + Read/Write allowed
TT5Tag[1] = 0x40;
// Size
if (tagSize > 2040)
{
// If the size is above 2040 (0xFF) then we have to set the bit3 of CC4
TT5Tag[2] = 0xFF;
TT5Tag[3] = 0x05;
}
else
{
TT5Tag[2] = tagSize/8;
TT5Tag[3] = 0x01;
}
}
else
{
// Copy the CC
memcpy(TT5Tag,firstSector,4);
// Check read and write access
if ((TT5Tag[1]&0x0F) != 0)
return PCDNFCT5_ERROR_LOCKED;
}
// Get the size of the message to write
if (TT5Tag[5] == 0xFF)
size = (TT5Tag[6]<<8)|TT5Tag[7];
else
size = 0x00FF&TT5Tag[5];
// Check if the memory available on the tag is enough
// If CC3 bit3 = 1 the size is higher than 2KB but we don't know the size...
if (TT5Tag[2]*8 < size+7 && (TT5Tag[3]&0x04) == 0)
return PCDNFCT5_ERROR_MEMORY_TAG;
if ((TT5Tag[3]&0x04) != 0) // So we use get system info command
{
if (tagDensity == ISO15693_HIGH_DENSITY)
ISO15693_GetSystemInfo (0x0A , 0x00, RepBuffer);
else
ISO15693_GetSystemInfo (0x02 , 0x00, RepBuffer);
if (RepBuffer[14] == 0xFF)
tagSize = (((RepBuffer[15]<<8)|RepBuffer[14])+1)*(RepBuffer[16]+1);
else
tagSize = (RepBuffer[14]+1)*(RepBuffer[15]+1);
if (tagSize < size+7)
return PCDNFCT5_ERROR_MEMORY_TAG;
}
// Write the tag
errchk(ISO15693_WriteBytes_TagData(tagDensity, TT5Tag, size+7, 0));
return PCDNFCT5_OK;
Error:
return PCDNFCT5_ERROR;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

59
src/lib_nfctype5pcd.h Normal file
View File

@@ -0,0 +1,59 @@
/**
******************************************************************************
* @file lib_nfctype5pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief Generates the NFC type5 commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LIB_NFCTYPE5PCD_H
#define _LIB_NFCTYPE5PCD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_pcd.h"
#include "lib_iso15693pcd.h"
/* Error codes */
#define PCDNFCT5_OK PCDNFC_OK
#define PCDNFCT5_ERROR PCDNFC_ERROR
#define PCDNFCT5_ERROR_MEMORY_TAG PCDNFC_ERROR_MEMORY_TAG
#define PCDNFCT5_ERROR_MEMORY_INTERNAL PCDNFC_ERROR_MEMORY_INTERNAL
#define PCDNFCT5_ERROR_LOCKED PCDNFC_ERROR_LOCKED
#define PCDNFCT5_ERROR_NOT_FORMATED PCDNFC_ERROR_NOT_FORMATED
/* Functions */
uint8_t PCDNFCT5_ReadNDEF( void );
uint8_t PCDNFCT5_WriteNDEF( void );
#ifdef __cplusplus
}
#endif
#endif /* _LIB_NFCTYPE5PCD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

769
src/lib_pcd.cpp Normal file
View File

@@ -0,0 +1,769 @@
/**
******************************************************************************
* @file lib_pcd.c
* @author MMY Application Team
* @version $Revision: 1334 $
* @date $Date: 2015-11-05 10:53:37 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of firmware functions to manages the PCD device device.
* @brief The commands as defined in the PCD device datasheet
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "lib_pcd.h"
extern drv95HF_ConfigStruct drv95HFConfig;
extern uint8_t u95HFBuffer [RFTRANS_95HF_MAX_BUFFER_SIZE+3];
/* Variables for the different modes */
//extern DeviceMode_t devicemode;
//extern TagType_t nfc_tagtype;
extern volatile bool EnableTimeOut;
static uint8_t IsAnAvailableProtocol (uint8_t Protocol);
PCD_PROTOCOL TechnoSelected = PCDPROTOCOL_UNKNOWN;
/** @addtogroup _95HF_Libraries
* @{
* @brief <b>This is the library used by the whole 95HF family (RX95HF, CR95HF, ST95HF) <br />
* You will find ISO libraries ( 14443A, 14443B, 15693, ...) for PICC and PCD <br />
* The libraries selected in the project will depend of the application targetted <br />
* and the product chosen (RX95HF emulate PICC, CR95HF emulate PCD, ST95HF can do both)</b>
*/
/** @addtogroup PCD
* @{
* @brief This part of the library enables PCD capabilities of CR95HF & ST95HF.
*/
/** @addtogroup PCD_Device
* @{
* @brief This set of function use the device commands to control both CR95HF & ST95HF <br />
* This layer is the bridge beetween the library and the 95HF driver.
*/
/** @addtogroup lib_PCD_Private_Functions
* @{
*/
static uint32_t PCD_ComputeUARTBaudRate(const uint8_t BaudRateCommandParameter);
/**
* @brief This function computes the UART baud rate according to Baudrate command parameter
* @param BaudRateCommandParameter : Baudrate command parameter (1 byte)
* @retval the UART baud rate value
*/
static uint32_t PCD_ComputeUARTBaudRate(const uint8_t BaudRateCommandParameter)
{
return ((uint32_t)13.56e6/ (2*BaudRateCommandParameter+2));
}
/**
* @brief this functions returns PCD_SUCCESSCODE if the protocol is available, otherwise PCD_ERRORCODE_PARAMETER
* @param Protocol : RF protocol (ISO 14443 A or 14443 B or 15 693 or Fellica)
* @return PCD_SUCCESSCODE : the protocol is available
* @return PCD_ERRORCODE_PARAMETER : the protocol isn't available
*/
static uint8_t IsAnAvailableProtocol (uint8_t Protocol)
{
switch(Protocol)
{
case PCD_PROTOCOL_FIELDOFF:
return PCD_SUCCESSCODE;
case PCD_PROTOCOL_ISO15693:
return PCD_SUCCESSCODE;
case PCD_PROTOCOL_ISO14443A:
return PCD_SUCCESSCODE;
case PCD_PROTOCOL_ISO14443B:
return PCD_SUCCESSCODE;
case PCD_PROTOCOL_FELICA:
return PCD_SUCCESSCODE;
default: return PCD_ERRORCODE_PARAMETER;
}
}
/**
* @}
*/
/** @addtogroup lib_PCD_Public_Functions
* @{
*/
/**
* @brief this function send an EOF pulse to a contacless tag
* @param pResponse : pointer on the PCD device reply
* @retval PCD_SUCCESSCODE : the function is succesful
*/
int8_t PCD_SendEOF(uint8_t *pResponse)
{
const uint8_t DataToSend[] = {SEND_RECEIVE ,0x00};
drv95HF_SendReceive(DataToSend, pResponse);
return PCD_SUCCESSCODE;
}
/**
* @brief this functions turns the field off
* @param none
* @retval PCD_SUCCESSCODE : the function is succesful
*/
void PCD_FieldOff( void )
{
uint8_t ParametersByte=0x00;
uint8_t pResponse[10];
PCD_ProtocolSelect(0x02, PCD_PROTOCOL_FIELDOFF, &ParametersByte,pResponse);
}
/**
* @brief this functions turns the field on
* @param none
* @return none
*/
void PCD_FieldOn(void)
{
uint8_t ParametersByte=0x00;
uint8_t pResponse[10];
PCD_ProtocolSelect(0x02, PCD_PROTOCOL_ISO15693, &ParametersByte,pResponse);
}
/**
* @brief this function send Echo command to the PCD device
* @param pResponse : pointer on the PCD device reply
* @return PCD_SUCCESSCODE
*/
int8_t PCD_Echo(uint8_t *pResponse)
{
const uint8_t command[]= {ECHO};
drv95HF_SendReceive(command, pResponse);
return PCD_SUCCESSCODE;
}
/**
* @brief this function send a ProtocolSeclect command to the PCD device
* @param Length : number of byte of protocol select command parameters
* @param Protocol : RF protocol (ISO 14443 A or B or 15 693 or Fellica)
* @param Parameters: prococol parameters (see reader datasheet)
* @param pResponse : pointer on the PCD device response
* @return PCD_SUCCESSCODE : the command was succedfully send
* @return PCD_ERRORCODE_PARAMETERLENGTH : the Length parameter is erroneous
* @return PCD_ERRORCODE_PARAMETER : a parameter is erroneous
*/
int8_t PCD_ProtocolSelect(const uint8_t Length,const uint8_t Protocol,const uint8_t *Parameters,uint8_t *pResponse)
{
uint8_t DataToSend[SELECT_BUFFER_SIZE];
int8_t status;
/* check ready to receive Protocol select command */
PCD_Echo(u95HFBuffer);
if (u95HFBuffer[0] != ECHORESPONSE)
{
/* reset the device */
PCD_PORsequence( );
}
/* initialize the result code to 0xFF and length to in case of error */
*pResponse = PCD_ERRORCODE_DEFAULT;
*(pResponse+1) = 0x00;
/* check the function parameters */
errchk(IsAnAvailableProtocol(Protocol));
DataToSend[PCD_COMMAND_OFFSET ] = PROTOCOL_SELECT;
DataToSend[PCD_LENGTH_OFFSET ] = Length;
DataToSend[PCD_DATA_OFFSET ] = Protocol;
/* DataToSend CodeCmd Length Data */
/* Parameters[0] first byte to emmit */
memcpy(&(DataToSend[PCD_DATA_OFFSET +1]),Parameters,Length-1);
/* Send the command the Rf transceiver */
drv95HF_SendReceive(DataToSend, pResponse);
return PCD_SUCCESSCODE;
Error:
return PCD_ERRORCODE_PARAMETER;
}
/**
* @brief this function send a SendRecv command to the PCD device. the command to contacless device is embeded in Parameters.
* @param Length : Number of bytes
* @param Parameters : data depenps on protocl selected
* @param pResponse : pointer on the PCD device response
* @return PCD_SUCCESSCODE : the command was succedfully send
* @return PCD_ERRORCODE_DEFAULT : the PCD device returned an error code
* @return PCD_ERRORCODE_PARAMETERLENGTH : Length parameter is erroneous
*/
int8_t PCD_SendRecv(const uint8_t Length,const uint8_t *Parameters,uint8_t *pResponse)
{
uint8_t DataToSend[SENDRECV_BUFFER_SIZE];
/* initialize the result code to 0xFF and length to 0 */
*pResponse = PCD_ERRORCODE_DEFAULT;
*(pResponse+1) = 0x00;
// /* check the function parameters */
// if (CHECKVAL (Length,1,255)==false)
// return PCD_ERRORCODE_PARAMETERLENGTH;
DataToSend[PCD_COMMAND_OFFSET ] = SEND_RECEIVE;
DataToSend[PCD_LENGTH_OFFSET ] = Length;
/* DataToSend CodeCmd Length Data*/
/* Parameters[0] first byte to emmit */
memcpy(&(DataToSend[PCD_DATA_OFFSET]),Parameters,Length);
/* Send the command the Rf transceiver */
drv95HF_SendReceive(DataToSend, pResponse);
if (PCD_IsReaderResultCodeOk (SEND_RECEIVE,pResponse) != PCD_SUCCESSCODE)
{
if(*pResponse == PCD_ERRORCODE_NOTAGFOUND)
return PCD_ERRORCODE_TIMEOUT;
else
return PCD_ERRORCODE_DEFAULT;
}
return PCD_SUCCESSCODE;
}
/**
* @brief this function send a Idle command to the PCD device
* @param Length : Number of bytes
* @param Data : pointer on data. Data depends on protocl selected
* @param pResponse : pointer on the PCD device response
* @return PCD_SUCCESSCODE : the command was succedfully send
* @return PCD_ERRORCODE_DEFAULT : the PCD device returned an error code
* @return PCD_ERRORCODE_PARAMETERLENGTH : Length parameter is erroneous
*/
int8_t PCD_Idle(const uint8_t Length, const uint8_t *Data )
{
uint8_t DataToSend[IDLE_BUFFER_SIZE];
/* check the function parameters */
if (Length != 0x0E)
return PCD_ERRORCODE_PARAMETERLENGTH;
DataToSend[PCD_COMMAND_OFFSET ] = IDLE;
DataToSend[PCD_LENGTH_OFFSET ] = Length;
memcpy(&(DataToSend[PCD_DATA_OFFSET]),Data,Length );
drv95HF_SendSPICommand(DataToSend);
return PCD_SUCCESSCODE;
}
/**
* @brief this function send a RdReg command to the PCD device
* @param Length : Number of bytes
* @param Address : address of first register to read
* @param RegCount : number of register to read
* @param Flags : whether to increment address after register read
* @param pResponse : pointer on the PCD device response
* @return PCD_SUCCESSCODE : the command was succedfully send
* @return PCD_ERRORCODE_DEFAULT : the PCD device returned an error code
* @return PCD_ERRORCODE_PARAMETERLENGTH : Length parameter is erroneous
*/
int8_t PCD_ReadRegister(const uint8_t Length,const uint8_t Address,const uint8_t RegCount,const uint8_t Flags,uint8_t *pResponse)
{
uint8_t DataToSend[RDREG_BUFFER_SIZE];
DataToSend[PCD_COMMAND_OFFSET ] = READ_REGISTER;
DataToSend[PCD_LENGTH_OFFSET ] = Length;
DataToSend[PCD_DATA_OFFSET ] = Address;
DataToSend[PCD_DATA_OFFSET +1 ] = RegCount;
DataToSend[PCD_DATA_OFFSET +2 ] = Flags;
/* Send the command the Rf transceiver */
drv95HF_SendReceive(DataToSend, pResponse);
if (PCD_IsReaderResultCodeOk (IDLE,pResponse) != PCD_SUCCESSCODE)
return PCD_ERRORCODE_DEFAULT;
return PCD_SUCCESSCODE;
}
/**
* @brief this function send a WriteRegister command to the PCD device
* @param Length : Number of bytes of WrReg parameters
* @param Address : address of first register to write
* @param pData : pointer data to be write
* @param Flags : whether to increment address after register read
* @param pResponse : pointer on the PCD device response
* @return PCD_SUCCESSCODE : the command was succedfully send
* @return PCD_ERRORCODE_PARAMETERLENGTH : Length parameter is erroneous
*/
int8_t PCD_WriteRegister(const uint8_t Length,const uint8_t Address,const uint8_t Flags,const uint8_t *pData,uint8_t *pResponse)
{
uint8_t DataToSend[WRREG_BUFFER_SIZE];
DataToSend[PCD_COMMAND_OFFSET ] = WRITE_REGISTER;
DataToSend[PCD_LENGTH_OFFSET ] = Length;
DataToSend[PCD_DATA_OFFSET ] = Address;
DataToSend[PCD_DATA_OFFSET +1 ] = Flags;
/* Parameters[0] first byte to emmit */
memcpy(&(DataToSend[PCD_DATA_OFFSET + 2]),pData,Length - 2 );
/* Send the command the Rf transceiver */
drv95HF_SendReceive(DataToSend, pResponse);
return PCD_SUCCESSCODE;
}
/**
* @brief This function sends POR sequence. It can be use to initialize the PCD device after a POR.
* @param none
* @return PCD_ERRORCODE_PORERROR : the POR sequence doesn't succeded
* @return PCD_SUCCESSCODE : the RF transceiver is ready
*/
int8_t PCD_PORsequence( void )
{
uint16_t NthAttempt=0;
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
drv95HF_ResetSPI();
}
do{
/* send an ECHO command and checks the PCD device response */
PCD_Echo(u95HFBuffer);
if (u95HFBuffer[0]==ECHORESPONSE)
return PCD_SUCCESSCODE;
/* if the SPI interface is selected then send a reset command*/
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
drv95HF_ResetSPI();
}
} while (u95HFBuffer[0]!=ECHORESPONSE && NthAttempt++ <5);
return PCD_ERRORCODE_PORERROR;
}
/**
* @brief this function send a command to the PCD device device over SPI or UART bus and receive its response.
* @brief the returned value is PCD_SUCCESSCODE
* @param *pCommand : pointer on the buffer to send to the the PCD device ( Command | Length | Data)
* @param *pResponse : pointer on the the PCD device response ( Command | Length | Data)
* @return PCD_SUCCESSCODE : the the PCD device returns an success code
* @return PCD_ERRORCODE_DEFAULT : the the PCD device returns an error code
*/
int8_t PCD_CheckSendReceive(const uint8_t *pCommand, uint8_t *pResponse)
{
drv95HF_SendReceive(pCommand, pResponse);
if (PCD_IsReaderResultCodeOk (SEND_RECEIVE,pResponse) != PCD_SUCCESSCODE)
return PCD_ERRORCODE_DEFAULT;
return PCD_SUCCESSCODE;
}
/**
* @brief this function returns PCD_SUCCESSCODE is the reader reply is a succesful code.
* @param CmdCode : code command send to the reader
* @param ReaderReply : pointer on the PCD device response
* @retval PCD_SUCCESSCODE : the CRC is Ok
* @retval PCD_NOREPLY_CODE : the CRC is erroenous
*/
int8_t PCD_IsCRCOk(const uint8_t Protocol ,const uint8_t *pReaderReply)
{
uint8_t NbByte = pReaderReply[PCD_LENGTH_OFFSET];
switch (Protocol)
{
case PCD_PROTOCOL_ISO15693:
if ( (pReaderReply [PCD_DATA_OFFSET + NbByte - CONTROL_15693_NBBYTE] & CONTROL_15693_CRCMASK) == CONTROL_15693_CRCMASK )
{
return PCD_ERRORCODE_DEFAULT;
}
else
{
return PCD_SUCCESSCODE;
}
case PCD_PROTOCOL_ISO14443A:
if ( (pReaderReply [PCD_DATA_OFFSET + NbByte - ISO14443A_NBBYTE] & ISO14443A_CRCMASK) == ISO14443A_CRCMASK )
{
return PCD_ERRORCODE_DEFAULT;
}
else
{
return PCD_SUCCESSCODE;
}
case PCD_PROTOCOL_ISO14443B:
if ( (pReaderReply [PCD_DATA_OFFSET + NbByte - CONTROL_14443B_NBBYTE] & CONTROL_14443B_CRCMASK) == CONTROL_14443B_CRCMASK )
{
return PCD_ERRORCODE_DEFAULT;
}
else
{
return PCD_SUCCESSCODE;
}
case PCD_PROTOCOL_FELICA:
if ( (pReaderReply [PCD_DATA_OFFSET + NbByte - CONTROL_FELICA_NBBYTE] & CONTROL_FELICA_CRCMASK) == CONTROL_FELICA_CRCMASK )
{
return PCD_ERRORCODE_DEFAULT;
}
else
{
return PCD_SUCCESSCODE;
}
default:
return ERRORCODE_GENERIC;
}
}
/**
* @brief this function returns PCD_SUCCESSCODE is the reader reply is a succesful code.
* @param CmdCode : code command send to the reader
* @param ReaderReply : pointer on the PCD device response
* @retval PCD_SUCCESSCODE : the PCD device returned a succesful code
* @retval PCD_ERRORCODE_DEFAULT : the PCD device didn't return a succesful code
* @retval PCD_NOREPLY_CODE : no the PCD device response
*/
int8_t PCD_IsReaderResultCodeOk(uint8_t CmdCode, const uint8_t *ReaderReply)
{
if (ReaderReply[READERREPLY_STATUSOFFSET] == PCD_ERRORCODE_DEFAULT)
return PCD_NOREPLY_CODE;
switch (CmdCode)
{
case ECHO:
if (ReaderReply[PSEUDOREPLY_OFFSET] == ECHO)
return PCD_SUCCESSCODE;
else
return PCD_ERRORCODE_DEFAULT;
case IDN:
if (ReaderReply[READERREPLY_STATUSOFFSET] == IDN_RESULTSCODE_OK)
return PCD_SUCCESSCODE;
else
return PCD_ERRORCODE_DEFAULT;
case PROTOCOL_SELECT:
switch (ReaderReply[READERREPLY_STATUSOFFSET])
{
case IDN_RESULTSCODE_OK :
return PCD_SUCCESSCODE;
case PROTOCOLSELECT_ERRORCODE_CMDLENGTH :
return PCD_ERRORCODE_DEFAULT;
case PROTOCOLSELECT_ERRORCODE_INVALID :
return PCD_ERRORCODE_DEFAULT;
default : return PCD_ERRORCODE_DEFAULT;
}
case SEND_RECEIVE:
switch (ReaderReply[READERREPLY_STATUSOFFSET])
{
case SENDRECV_RESULTSCODE_OK :
if (ReaderReply[READERREPLY_STATUSOFFSET+1] != 0)
return PCD_SUCCESSCODE;
else
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_RESULTSRESIDUAL :
return PCD_SUCCESSCODE;
case SENDRECV_ERRORCODE_COMERROR :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_FRAMEWAIT :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_SOF :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_OVERFLOW :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_FRAMING :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_EGT :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_LENGTH :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_CRC :
return PCD_ERRORCODE_DEFAULT;
case SENDRECV_ERRORCODE_RECEPTIONLOST :
return PCD_ERRORCODE_DEFAULT;
default :
return PCD_ERRORCODE_DEFAULT;
}
case IDLE:
switch (ReaderReply[READERREPLY_STATUSOFFSET])
{
case IDLE_RESULTSCODE_OK :
return PCD_SUCCESSCODE;
case IDLE_ERRORCODE_LENGTH :
return PCD_ERRORCODE_DEFAULT;
default : return PCD_ERRORCODE_DEFAULT;
}
case READ_REGISTER:
switch (ReaderReply[READERREPLY_STATUSOFFSET])
{
case READREG_RESULTSCODE_OK :
return PCD_SUCCESSCODE;
case READREG_ERRORCODE_LENGTH :
return PCD_ERRORCODE_DEFAULT;
default : return PCD_ERRORCODE_DEFAULT;
}
case WRITE_REGISTER:
switch (ReaderReply[READERREPLY_STATUSOFFSET])
{
case WRITEREG_RESULTSCODE_OK :
return PCD_SUCCESSCODE;
default : return PCD_ERRORCODE_DEFAULT;
}
case BAUD_RATE:
return PCD_ERRORCODE_DEFAULT;
default:
return ERRORCODE_GENERIC;
}
}
/**
* @brief this function perform the calibration to provide the parameter require for tag detection command
* @param WU Period : Time allow between 2 tag detections
* @param pDacDataH : Value computed for DacDataH (DacDataL = DacDataH <20> 0x10)
* @return PCD_SUCCESSCODE : the calibration was successfully performed (DacDataH value is significant)
*/
int8_t PCD_TagDetectCalibration(const uint8_t Wuperiod, uint8_t *pDacDataH)
{
uint8_t DataToSend[IDLE_CMD_LENTH+2] = { 0x00, 0x00, 0x03, 0xA1, 0x00, 0xF8, 0x01, 0x18,
0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x3F, 0x01};
uint8_t Response[3] = {0x00};
uint8_t AlgoStep[6] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04};
uint8_t i=0;
/* Insure no tag are present during calibration process */
/* During the calibration process, DacDataL is forced to 0x00 and the software successively
varies the DacDataH value from its maximum value (0xFE) to its minimum value (0x00) */
DataToSend[PCD_COMMAND_OFFSET ] = IDLE;
DataToSend[PCD_LENGTH_OFFSET ] = IDLE_CMD_LENTH;
/* modify WU Period according to user input */
DataToSend[WU_PERIOD_OFFSET] = Wuperiod;
/* Start 8-step calibration process */
/* Step 0: force wake-up event to Tag Detect (set DacDataH = 0x00)
With these conditions Wake-Up event must be Tag Detect */
DataToSend[DACDATAH_OFFSET] = 0x00;
drv95HF_SendReceive(DataToSend, Response);
if( (Response[0] == 0x00) && (Response[1] == 0x01) && (Response[2] == 0x02))
{
/* Step 1: force Wake-up event to Timeout set DacDataH = 0xFC
With these conditions, Wake-Up event must be Timeout */
DataToSend[DACDATAH_OFFSET] = 0xFC;
drv95HF_SendReceive(DataToSend, Response);
if( (Response[0] == 0x00) && (Response[1] == 0x01) && (Response[2] == 0x01))
{
/* Start loop
If previous Wake-up event was Timeout (0x01) we must decrease DacDataH,
If it was Tag Detect we must increase DacDataH */
for(i=0; i<6; i++)
{
switch(Response[2])
{
case 0x01:
DataToSend[DACDATAH_OFFSET] -= AlgoStep[i];
break;
case 0x02:
DataToSend[DACDATAH_OFFSET] += AlgoStep[i];
break;
default:
return PCD_ERRORCODE_DEFAULT;
}
drv95HF_SendReceive(DataToSend, Response);
}
/* If last Wake-up event = Tag Detect (0x02), search DacDataRef = last DacDataH value
If last Wake-up event = Timeout (0x01), search DacDataRef = last DacDataH value -4 */
/* We have founded DacDataRef, DacDataL= DacDataRef <20> Guard and DacDataH= DacDataRef+ Guard
where guard = 0x08 (2 DAC steps) */
if( (Response[0] == 0x00) && (Response[1] == 0x01) && (Response[2] == 0x01))
*pDacDataH = (DataToSend[DACDATAH_OFFSET] -0x04) + 0x08;
else
*pDacDataH = DataToSend[DACDATAH_OFFSET] + 0x08;
return PCD_SUCCESSCODE;
}
else
return PCD_ERRORCODE_DEFAULT;
}
else
return PCD_ERRORCODE_DEFAULT;
}
/**
* @brief This function wait for Tag detection to exit
* @param WU Source : Condition for exiting this function, Condition that was realized
* @param WU Period : Time allow between 2 tag detections
* @param DacDataH : value that must have been computed by calling PCD_TagDetectCalibration function
* @param NbTrials : number of trial to find tag before time out
* @return PCD_SUCCESSCODE : the calibration was succesfully performed (DacDataH value is significant)
*/
int8_t PCD_WaitforTagDetection(uint8_t *WuSource, const uint8_t WuPeriod, const uint8_t DacDataH, const uint8_t NbTrials)
{
uint8_t DataToSend[IDLE_CMD_LENTH+2] = { 0x00, 0x00, 0x00, 0x21, 0x00, 0x79, 0x01, 0x18,
0x00, 0x20, 0x60, 0x60, 0x00, 0x00, 0x3F, 0x01};
uint8_t Response[3] = {0x00};
DataToSend[PCD_COMMAND_OFFSET ] = IDLE;
DataToSend[PCD_LENGTH_OFFSET ] = IDLE_CMD_LENTH;
/* modify WU Period according to user input */
DataToSend[WU_SOURCE_OFFSET] = *WuSource;
DataToSend[WU_PERIOD_OFFSET] = WuPeriod;
DataToSend[DACDATAL_OFFSET] = DacDataH-0x10;
DataToSend[DACDATAH_OFFSET] = DacDataH;
DataToSend[NBTRIALS_OFFSET] = NbTrials;
/* In this case we need to desactivate the drv timeout */
EnableTimeOut = false;
drv95HF_SendReceive(DataToSend, Response);
/* Set back the drv timeout */
EnableTimeOut = true;
if( (Response[0] == 0x00) && (Response[1] == 0x01))
{
*WuSource = Response[2];
return PCD_SUCCESSCODE;
}
else
return PCD_ERRORCODE_DEFAULT;
}
/**
* @brief this function send a BaudRate command to the PCD device
* @param BaudRate : new baudrate
* @param pResponse : pseudo reply (shall be 0x55)
* @return PCD_SUCCESSCODE : the command was succedfully send
*/
int8_t PCD_BaudRate(const uint8_t BaudRate,uint8_t *pResponse)
{
uint8_t DataToSend[BAUDRATE_BUFFER_SIZE];
DataToSend[PCD_COMMAND_OFFSET ] = BAUD_RATE;
DataToSend[PCD_LENGTH_OFFSET ] = BAUDRATE_LENGTH;
DataToSend[PCD_DATA_OFFSET ] = BaudRate;
/* Send the command the Rf transceiver */
drv95HF_SendReceive(DataToSend, pResponse);
return PCD_SUCCESSCODE;
}
/**
* @brief This function run a process to change UARt baud rate. It'll check the baud rate is
* @brief compatible with this MCU and configurates MCU and the PCD device baud rate.
* @param *pCommand : pointer on the buffer to send to the the PCD device ( Command | Length | Data)
* @param *pResponse : pointer on the the PCD device response ( Command | Length | Data)
* @retval PCD_SUCCESSCODE : the UART baud rate has been succesfuly changed
* @retval PCD_ERRORCODE_UARTDATARATEUNCHANGED : the UART baud rate has not changed
* @retval PCD_ERRORCODE_UARTDATARATEPROCESS : command DaubRate was send to the PCD device but the MCU was not able to comunicatewith the PCD device
*/
int8_t PCD_ChangeUARTBaudRate(const uint8_t *pCommand, uint8_t *pResponse)
{
return PCD_ERRORCODE_UARTDATARATEUNCHANGED;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

269
src/lib_pcd.h Normal file
View File

@@ -0,0 +1,269 @@
/**
******************************************************************************
* @file lib_pcd.h
* @author MMY Application Team
* @version $Revision: 1333 $
* @date $Date: 2015-11-05 10:49:42 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of firmware functions to manages PCD device.
* @brief The commands as defined in CR95HF datasheet
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LIB_PCD_H
#define _LIB_PCD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lib_95HF.h"
#define PCD_SPI RFTRANS_95HF_SPI
/* customs command ------------------------------------------------------------------------*/
#define PCD_15693ANTICOL 0xA0
#define PCD_INVENTORY16SLOTS 0xA1
#define PCD_ISWAKEUP 0xA2
#define PCD_GOTOTAGDETECTINGSTATE 0xA3
#define PCD_CALIBRATETHETAGDETECTION 0xA4
#define PCD_READCUSTOMTAGMEMORY 0xB0
#define PCD_READMCUBUFFER 0xB1
#define PCD_GETHARDWAREVERSION 0xB2
#define PCD_DOWNLOADSTM32MEM 0xB5
#define PCD_READWHOLEMEMORY 0xB6
#define PCD_TRANSPARENT 0xB7
#define PCD_PULSE_POOLINGREADING 0xB8
#define PCD_PULSE_SPINSS 0xB9
#define PCD_GETINTERFACEPINSTATE 0xBA
#define PCD_SETUSBDISCONNECTSTATE 0xBB
#define PCD_GETMCUVERSION 0xBC
#define PCD_RESETSEQUENCE 0xBD
#define PCD_PULSE_IRQIN 0xBE
#ifdef USE_MSD_DRIVE
#define PCD_COPYTAGTOFILE 0xC1
#define PCD_COPYFILETOTAG 0xC2
#endif /*USE_MSD_DRIVE*/
#define PCD_POR 0xC3
#define PCD_TAG_TRAKING 0xC4
#define PCD_CRYPTO_GENERIC 0xC5
#define PCD_NDEF_MESSAGE 0xC6
#define PCD_MULTITAG 0xD0
#define PCD_MULTITAG_EXTENDED 0xD1
#define SUCCESFUL_SENDS 0x80
#define SUCCESFUL_COMMAND 0x00
#define SUCCESFUL_COMMAND_0x80 0x80
/* PCD status and erroc code------------------------------------------------------ */
#define PCD_SUCCESSCODE RESULTOK
#define PCD_ERRORCODE_DEFAULT 0x21
#define PCD_ERRORCODE_PARAMETER 0x22
#define PCD_NOREPLY_CODE 0x23
#define PCD_ERRORCODE_UARTDATARATEUNCHANGED 0x24
#define PCD_ERRORCODE_UARTDATARATEPROCESS 0x25
#define PCD_ERRORCODE_PORERROR 0x26
#define PCD_ERRORCODE_PARAMETERLENGTH 0x27
#define PCD_ERRORCODE_TIMEOUT 0x28
/* CR95HF polling status --------------------------------------------------------- */
#define PCD_IDLERES_LENGTH 0x01
#define PCD_WAKEUPSOURCE_TIMEOUT 0x01
#define PCD_WAKEUPSOURCE_TAGDETECTING 0x02
#define PCD_WAKEUPSOURCE_IRRQINN 0x08
/* Nb of bytes of reader commands --------------------------------------------------------- */
#define SELECT_BUFFER_SIZE 16
#define SENDRECV_BUFFER_SIZE 257
#define SEND_BUFFER_SIZE 257
#define IDLE_BUFFER_SIZE 16
#define RDREG_BUFFER_SIZE 5
#define WRREG_BUFFER_SIZE 257
#define BAUDRATE_BUFFER_SIZE 3
#define SUBFREQRES_BUFFER_SIZE 2
#define ACFILTER_BUFFER_SIZE 19
#define TESTMODE_BUFFER_SIZE 4
#define SLEEPMODE_BUFFER_SIZE 4
/* Nb of bytes of reader response --------------------------------------------------------- */
#define PCD_RESPONSEBUFFER_SIZE RFTRANS_95HF_MAX_BUFFER_SIZE
/* protocol allowed ----------------------------------------------------------------------- */
#define PCD_PROTOCOL_FIELDOFF 0x00
#define PCD_PROTOCOL_ISO15693 0x01
#define PCD_PROTOCOL_ISO14443A 0x02
#define PCD_PROTOCOL_ISO14443B 0x03
#define PCD_PROTOCOL_FELICA 0x04
#define PCD_PROTOCOL_ISO14443_SR 0x05
#define PCD_PROTOCOL_TOPAZ 0x06
/* RF transceiver Offset of the command and the response ---------------------------------- */
#define PCD_COMMAND_OFFSET RFTRANS_95HF_COMMAND_OFFSET
#define PCD_STATUS_OFFSET RFTRANS_95HF_COMMAND_OFFSET
#define PCD_LENGTH_OFFSET RFTRANS_95HF_LENGTH_OFFSET
#define PCD_DATA_OFFSET RFTRANS_95HF_DATA_OFFSET
/* Command parameter -------------------------------------------------------------------*/
#define SEND_MASK_APPENDCRC 0x20
#define SEND_MASK_DONTAPPENDCRC 0x00
#define SEND_MASK_8BITSINFIRSTBYTE 0x08
#define PCD_TRANSPARENTCOMMAND_OFFSET 0x01
#define ECHOREPLY_OFFSET 0x00
#define PSEUDOREPLY_OFFSET 0x00
#define PSEUDOREPLY_LENGTH 0x01
#define READERREPLY_STATUSOFFSET 0x00
#define IDN_RESULTSCODE_OK 0x00
/* protocol select status --------------------------------------------------------------------- */
#define PROTOCOLSELECT_LENGTH 0x02
#define PROTOCOLSELECT_RESULTSCODE_OK 0x00
#define PROTOCOLSELECT_ERRORCODE_CMDLENGTH 0x82
#define PROTOCOLSELECT_ERRORCODE_INVALID 0x83
/* baud rate command -------------------------------------------------------------------------- */
#define BAUDRATE_LENGTH 0x01
#define BAUDRATE_DATARATE_DEFAULT 57600
/* send receive field status ----------------------------------------------------------------- */
#define SENDRECV_RESULTSCODE_OK 0x80
#define SENDRECV_ERRORCODE_COMERROR 0x86
#define SENDRECV_ERRORCODE_FRAMEWAIT 0x87
#define SENDRECV_ERRORCODE_SOF 0x88
#define SENDRECV_ERRORCODE_OVERFLOW 0x89
#define SENDRECV_ERRORCODE_FRAMING 0x8A
#define SENDRECV_ERRORCODE_EGT 0x8B
#define SENDRECV_ERRORCODE_LENGTH 0x8C
#define SENDRECV_ERRORCODE_CRC 0x8D
#define SENDRECV_ERRORCODE_RECEPTIONLOST 0x8E
#define SENDRECV_RESULTSRESIDUAL 0x90
#define PCD_ERRORCODE_NOTAGFOUND 0x87
#define SENDRECV_ERRORCODE_SOFT 0xFF
/* control byte according to protocol -------------------------------------------------------- */
#define CONTROL_MAX_NBBYTE 0x03
#define CONTROL_15693_NBBYTE 0x01
#define CONTROL_15693_CRCMASK 0x02
#define CONTROL_15693_COLISIONMASK 0x01
#define ISO14443A_NBBYTE 0x03
#define ISO14443A_COLISIONMASK 0x80
#define ISO14443A_CRCMASK 0x20
#define ISO14443A_CRC_ERRORCODE_TYPEA 0x20
#define ISO14443A_PARITYMASK 0x10
#define ISO14443A_NBSIGNIFICANTBITMASK 0x0F
#define ISO14443A_FIRSTCOLISIONBITMASK 0x0F
#define CONTROL_14443B_NBBYTE 0x01
#define CONTROL_14443B_CRCMASK 0x02
#define CONTROL_14443B_ERRORCODE 0x02
#define CONTROL_14443B_COLISIONMASK 0x01
#define CONTROL_FELICA_NBBYTE 0x01
#define CONTROL_FELICA_CRCMASK 0x02
#define CONTROL_FELICA_COLISIONMASK 0x01
/* Command parameter -------------------------------------------------------------------*/
#define PCD_ISO14443A_APPENDCRC 0x20
#define PCD_ISO14443A_DONTAPPENDCRC 0x00
#define PCD_ISO14443A_A8BITSINFIRSTBYTE 0x08
/* Speed parameters commom to ISO14443B protocols --------------------------------------*/
#define PCD_ISO14443B_TRANSMISSION_SPEED_106K 0x00
#define PCD_ISO14443B_TRANSMISSION_SPEED_212K 0x40
#define PCD_ISO14443B_TRANSMISSION_SPEED_424K 0x80
#define PCD_ISO14443B_TRANSMISSION_SPEED_848K 0xC0
#define PCD_ISO14443B_RECEPTION_SPEED_106K 0x00
#define PCD_ISO14443B_RECEPTION_SPEED_212K 0x10
#define PCD_ISO14443B_RECEPTION_SPEED_424K 0x20
#define PCD_ISO14443B_RECEPTION_SPEED_848K 0x30
#define PCD_ISO14443B_APPEND_CRC 0x01
/* Error codes for Higher level */
#define PCDNFC_OK RESULTOK
#define PCDNFC_ERROR ERRORCODE_GENERIC
#define PCDNFC_ERROR_MEMORY_TAG 2
#define PCDNFC_ERROR_MEMORY_INTERNAL 3
#define PCDNFC_ERROR_LOCKED 4
#define PCDNFC_ERROR_NOT_FORMATED 5
/* protocol selected for the reader -----------------------------------------------*/
typedef enum {
PCDPROTOCOL_UNKNOWN = 0,
PCDPROTOCOL_14443A,
PCDPROTOCOL_14443B,
PCDPROTOCOL_18092,
PCDPROTOCOL_15693,
PCDPROTOCOL_NFCDEPA,
PCDPROTOCOL_NFCDEPF
}PCD_PROTOCOL;
/* Functions ---------------------------------------------------------------- */
int8_t PCD_IsReaderResultCodeOk(uint8_t CmdCode,const uint8_t *ReaderReply);
int8_t PCD_IsCRCOk(const uint8_t Protocol , const uint8_t *pReaderReply);
int8_t PCD_CheckSendReceive(const uint8_t *pCommand, uint8_t *pResponse);
void PCD_FieldOff(void);
void PCD_FieldOn(void);
int8_t PCD_IDN(uint8_t *pResponse);
int8_t PCD_Echo(uint8_t *pResponse);
int8_t PCD_SendEOF(uint8_t *pResponse);
int8_t PCD_ProtocolSelect(const uint8_t Length,const uint8_t Protocol, const uint8_t *Parameters, uint8_t *pResponse);
int8_t PCD_SendRecv(const uint8_t Length,const uint8_t *Parameters,uint8_t *pResponse);
int8_t PCD_Idle(const uint8_t Length,const uint8_t *Data);
int8_t PCD_ReadRegister(const uint8_t Length,const uint8_t Address,const uint8_t RegCount,const uint8_t Flags,uint8_t *pResponse);
int8_t PCD_WriteRegister(const uint8_t Length,const uint8_t Address,const uint8_t Flags,const uint8_t *pData,uint8_t *pResponse);
int8_t PCD_PORsequence(void);
void PCD_Receive_SPI_Response(uint8_t *pData);
int8_t PCD_TagDetectCalibration(const uint8_t Wuperiod,uint8_t *pDacDataH);
int8_t PCD_WaitforTagDetection(uint8_t *WuSource, const uint8_t WuPeriod, const uint8_t DacDataH, const uint8_t NbTrials);
int8_t PCD_BaudRate(const uint8_t BaudRate,uint8_t *pResponse);
int8_t PCD_ChangeUARTBaudRate(const uint8_t *pCommand, uint8_t *pResponse);
#ifdef __cplusplus
}
#endif
#endif /* _LIB_PCD_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

52
src/lib_wrapper.h Normal file
View File

@@ -0,0 +1,52 @@
/**
******************************************************************************
* @file lib_wrapper.h
* @author MMY Application Team
* @version $Revision: 1329 $
* @date $Date: 2015-11-05 10:34:25 +0100 (Thu, 05 Nov 2015) $
* @brief This file help to have upper layer independent from HW
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LIB_WRAPPER_H
#define __LIB_WRAPPER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "common.h"
uint16_t ReadData( uint16_t Offset, uint16_t DataSize, uint8_t* pData );
uint16_t WriteData( uint16_t Offset, uint32_t DataSize, uint8_t* pData );
#ifdef __cplusplus
}
#endif
#endif /* __LIB_WRAPPER_H */
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

76
src/miscellaneous.h Normal file
View File

@@ -0,0 +1,76 @@
/**
******************************************************************************
* @file miscellaneous.h
* @author MMY Application Team
* @version $Revision: 1507 $
* @date $Date: 2016-01-08 09:48:35 +0100 (Fri, 08 Jan 2016) $
* @brief miscellaneaous functions
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
#ifndef __MISCELLANEOUS_H
#define __MISCELLANEOUS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
#include "stdbool.h"
#include "string.h"
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef const uint32_t uc32; /*!< Read Only */
typedef const uint16_t uc16; /*!< Read Only */
typedef const uint8_t uc8; /*!< Read Only */
#define MAX(x,y) ((x > y)? x : y)
#define MIN(x,y) ((x < y)? x : y)
#define ABS(x) ((x)>0 ? (x) : -(x))
#define CHECKVAL(val, min,max) ((val < min || val > max) ? false : true)
#define GETMSB(val) ((val & 0xFF00 )>>8 )
#define GETLSB(val) ( val & 0x00FF )
#define RESULTOK 0x00
#define ERRORCODE_GENERIC 1
#ifndef errchk
#define errchk(fCall) if (status = (fCall), status != RESULTOK) \
{goto Error;} else
#endif
#ifdef __cplusplus
}
#endif
#endif /* __MISCELLANEOUS_H */
/**
* @}
*/
/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/