/*
*
* Copyright (C) 2010 NXP Semiconductors
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
/*!
* \file phFriNfc_ISO15693Format.c
* \brief This component encapsulates different format functinalities ,
* for the ISO-15693 card.
*
* Project: NFC-FRI
*
* $Date: $
* $Author: ing02260 $
* $Revision: 1.0 $
* $Aliases: $
*
*/
#ifndef PH_FRINFC_FMT_ISO15693_DISABLED
#include <phNfcTypes.h>
#include <phFriNfc_OvrHal.h>
#include <phFriNfc_SmtCrdFmt.h>
#include <phFriNfc_ISO15693Format.h>
/****************************** Macro definitions start ********************************/
/* State for the format */
#define ISO15693_FORMAT 0x01U
/* Bytes per block in the ISO-15693 */
#define ISO15693_BYTES_PER_BLOCK 0x04U
/* ISO-15693 Commands
GET SYSTEM INFORMATION COMMAND
*/
#define ISO15693_GET_SYSTEM_INFO_CMD 0x2BU
/* READ SINGLE BLOCK COMMAND */
#define ISO15693_RD_SINGLE_BLK_CMD 0x20U
/* WRITE SINGLE BLOCK COMMAND */
#define ISO15693_WR_SINGLE_BLK_CMD 0x21U
/* READ MULTIPLE BLOCK COMMAND */
#define ISO15693_RD_MULTIPLE_BLKS_CMD 0x23U
/* CC bytes
CC BYTE 0 - Magic Number - 0xE1
*/
#define ISO15693_CC_MAGIC_NUM 0xE1U
/* CC BYTE 1 - Mapping version and READ WRITE settings 0x40
*/
#define ISO15693_CC_VER_RW 0x40U
/* CC BYTE 2 - max size is calaculated using the byte 3 multiplied by 8 */
#define ISO15693_CC_MULTIPLE_FACTOR 0x08U
/* Inventory command support mask for the CC byte 4 */
#define ISO15693_INVENTORY_CMD_MASK 0x02U
/* Read MULTIPLE blocks support mask for CC byte 4 */
#define ISO15693_RDMULBLKS_CMD_MASK 0x01U
/* Flags for the command */
#define ISO15693_FMT_FLAGS 0x20U
/* Read two blocks */
#define ISO15693_RD_2_BLOCKS 0x02U
/* TYPE identifier of the NDEF TLV */
#define ISO15693_NDEF_TLV_TYPE_ID 0x03U
/* Terminator TLV identifier */
#define ISO15693_TERMINATOR_TLV_ID 0xFEU
/* UID 7th byte value shall be 0xE0 */
#define ISO15693_7TH_BYTE_UID_VALUE 0xE0U
#define ISO15693_BYTE_7_INDEX 0x07U
/* UID 6th byte value shall be 0x04 - NXP manufacturer */
#define ISO15693_6TH_BYTE_UID_VALUE 0x04U
#define ISO15693_BYTE_6_INDEX 0x06U
#define ISO15693_EXTRA_RESPONSE_FLAG 0x01U
#define ISO15693_GET_SYS_INFO_RESP_LEN 0x0EU
#define ISO15693_DSFID_MASK 0x01U
#define ISO15693_AFI_MASK 0x02U
#define ISO15693_MAX_SIZE_MASK 0x04U
#define ISO15693_ICREF_MASK 0x08U
#define ISO15693_SKIP_DFSID 0x01U
#define ISO15693_SKIP_AFI 0x01U
#define ISO15693_BLOCK_SIZE_IN_BYTES_MASK 0x1FU
/* MAXimum size of ICODE SLI/X */
#define ISO15693_SLI_X_MAX_SIZE 112U
/* MAXimum size of ICODE SLI/X - S */
#define ISO15693_SLI_X_S_MAX_SIZE 160U
/* MAXimum size of ICODE SLI/X - L */
#define ISO15693_SLI_X_L_MAX_SIZE 32U
/****************************** Macro definitions end ********************************/
/****************************** Data structures start ********************************/
typedef enum phFriNfc_ISO15693_FormatSeq
{
ISO15693_GET_SYS_INFO,
ISO15693_RD_SINGLE_BLK_CHECK,
ISO15693_WRITE_CC_FMT,
ISO15693_WRITE_NDEF_TLV
}phFriNfc_ISO15693_FormatSeq_t;
/****************************** Data structures end ********************************/
/*********************** Static function declarations start ***********************/
static
NFCSTATUS
phFriNfc_ISO15693_H_ProFormat (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt);
static
NFCSTATUS
phFriNfc_ISO15693_H_GetMaxDataSize (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
uint8_t *p_recv_buf,
uint8_t recv_length);
static
NFCSTATUS
phFriNfc_ISO15693_H_FmtReadWrite (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
uint8_t command,
uint8_t *p_data,
uint8_t data_length);
/*********************** Static function declarations end ***********************/
/*********************** Static function definitions start ***********************/
static
NFCSTATUS
phFriNfc_ISO15693_H_FmtReadWrite (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
uint8_t command,
uint8_t *p_data,
uint8_t data_length)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
uint8_t send_index = 0;
/* set the data for additional data exchange*/
psNdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
psNdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0;
psNdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0;
psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine =
phFriNfc_ISO15693_FmtProcess;
psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = psNdefSmtCrdFmt;
*psNdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;
psNdefSmtCrdFmt->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd;
*(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)ISO15693_FMT_FLAGS;
send_index = (uint8_t)(send_index + 1);
*(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)command;
send_index = (uint8_t)(send_index + 1);
(void)memcpy ((void *)(psNdefSmtCrdFmt->SendRecvBuf + send_index),
(void *)psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid,
psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
send_index = (uint8_t)(send_index +
psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
switch (command)
{
case ISO15693_WR_SINGLE_BLK_CMD:
case ISO15693_RD_MULTIPLE_BLKS_CMD:
{
*(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)
psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block;
send_index = (uint8_t)(send_index + 1);
if (data_length)
{
(void)memcpy ((void *)(psNdefSmtCrdFmt->SendRecvBuf + send_index),
(void *)p_data, data_length);
send_index = (uint8_t)(send_index + data_length);
}
else
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
}
break;
}
case ISO15693_RD_SINGLE_BLK_CMD:
{
*(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)
psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block;
send_index = (uint8_t)(send_index + 1);
break;
}
case ISO15693_GET_SYSTEM_INFO_CMD:
{
/* Dont do anything */
break;
}
default:
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
break;
}
}
psNdefSmtCrdFmt->SendLength = send_index;
if (!result)
{
result = phFriNfc_OvrHal_Transceive(psNdefSmtCrdFmt->LowerDevice,
&psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
psNdefSmtCrdFmt->psRemoteDevInfo,
psNdefSmtCrdFmt->Cmd,
&psNdefSmtCrdFmt->psDepAdditionalInfo,
psNdefSmtCrdFmt->SendRecvBuf,
psNdefSmtCrdFmt->SendLength,
psNdefSmtCrdFmt->SendRecvBuf,
psNdefSmtCrdFmt->SendRecvLength);
}
return result;
}
static
NFCSTATUS
phFriNfc_ISO15693_H_GetMaxDataSize (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
uint8_t *p_recv_buf,
uint8_t recv_length)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info =
&(psNdefSmtCrdFmt->AddInfo.s_iso15693_info);
phHal_sIso15693Info_t *ps_rem_iso_15693_info =
&(psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info);
uint8_t recv_index = 0;
if ((ISO15693_GET_SYS_INFO_RESP_LEN == recv_length)
&& (ISO15693_MAX_SIZE_MASK == (*p_recv_buf & ISO15693_MAX_SIZE_MASK)))
{
uint8_t information_flag = *p_recv_buf;
/* MAX size is present in the system information and
also response length is correct */
recv_index = (uint8_t)(recv_index + 1);
if (!phOsalNfc_MemCompare ((void *)ps_rem_iso_15693_info->Uid,
(void *)(p_recv_buf + recv_index),
ps_rem_iso_15693_info->UidLength))
{
/* UID comaparision successful */
uint8_t no_of_blocks = 0;
uint8_t blk_size_in_bytes = 0;
uint8_t ic_reference = 0;
/* So skip the UID size compared in the received buffer */
recv_index = (uint8_t)(recv_index +
ps_rem_iso_15693_info->UidLength);
if (information_flag & ISO15693_DSFID_MASK) {
/* Skip DFSID */
recv_index = (uint8_t)(recv_index + ISO15693_SKIP_DFSID);
}
if (information_flag & ISO15693_AFI_MASK) {
/* Skip AFI */
recv_index = (uint8_t)(recv_index + ISO15693_SKIP_AFI);
}
/* To get the number of blocks in the card */
no_of_blocks = (uint8_t)(*(p_recv_buf + recv_index) + 1);
recv_index = (uint8_t)(recv_index + 1);
/* To get the each block size in bytes */
blk_size_in_bytes = (uint8_t)((*(p_recv_buf + recv_index)
& ISO15693_BLOCK_SIZE_IN_BYTES_MASK) + 1);
recv_index = (uint8_t)(recv_index + 1);
if (information_flag & ISO15693_ICREF_MASK) {
/* Get the IC reference */
ic_reference = (uint8_t)(*(p_recv_buf + recv_index));
if (ic_reference == 0x03) {
no_of_blocks = 8;
}
}
/* calculate maximum data size in the card */
ps_iso15693_info->max_data_size = (uint16_t)
(no_of_blocks * blk_size_in_bytes);
}
else
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
}
}
else
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
}
return result;
}
static
NFCSTATUS
phFriNfc_ISO15693_H_ProFormat (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info =
&(psNdefSmtCrdFmt->AddInfo.s_iso15693_info);
phFriNfc_ISO15693_FormatSeq_t e_format_seq =
(phFriNfc_ISO15693_FormatSeq_t)
ps_iso15693_info->format_seq;
uint8_t command_type = 0;
uint8_t a_send_byte[ISO15693_BYTES_PER_BLOCK] = {0};
uint8_t send_length = 0;
uint8_t send_index = 0;
uint8_t format_complete = FALSE;
switch (e_format_seq)
{
case ISO15693_GET_SYS_INFO:
{
/* RESPONSE received for GET SYSTEM INFO */
if (!phFriNfc_ISO15693_H_GetMaxDataSize (psNdefSmtCrdFmt,
(psNdefSmtCrdFmt->SendRecvBuf + ISO15693_EXTRA_RESPONSE_FLAG),
(uint8_t)(*psNdefSmtCrdFmt->SendRecvLength -
ISO15693_EXTRA_RESPONSE_FLAG)))
{
/* Send the READ SINGLE BLOCK COMMAND */
command_type = ISO15693_RD_SINGLE_BLK_CMD;
e_format_seq = ISO15693_RD_SINGLE_BLK_CHECK;
/* Block number 0 to read */
psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block = 0x00;
}
else
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_RECEIVE_LENGTH);
}
break;
}
case ISO15693_RD_SINGLE_BLK_CHECK:
{
/* RESPONSE received for READ SINGLE BLOCK
received*/
/* Check if Card is really fresh
First 4 bytes must be 0 for fresh card */
if ((psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block == 0x00) &&
(psNdefSmtCrdFmt->SendRecvBuf[1] != 0x00 ||
psNdefSmtCrdFmt->SendRecvBuf[2] != 0x00 ||
psNdefSmtCrdFmt->SendRecvBuf[3] != 0x00 ||
psNdefSmtCrdFmt->SendRecvBuf[4] != 0x00))
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_FORMAT);
}
else
{
/* prepare data for writing CC bytes */
command_type = ISO15693_WR_SINGLE_BLK_CMD;
e_format_seq = ISO15693_WRITE_CC_FMT;
/* CC magic number */
*a_send_byte = (uint8_t)ISO15693_CC_MAGIC_NUM;
send_index = (uint8_t)(send_index + 1);
/* CC Version and read/write access */
*(a_send_byte + send_index) = (uint8_t) ISO15693_CC_VER_RW;
send_index = (uint8_t)(send_index + 1);
/* CC MAX data size, calculated during GET system information */
*(a_send_byte + send_index) = (uint8_t) (ps_iso15693_info->max_data_size / ISO15693_CC_MULTIPLE_FACTOR);
send_index = (uint8_t)(send_index + 1);
switch (ps_iso15693_info->max_data_size)
{
case ISO15693_SLI_X_MAX_SIZE:
{
/* For SLI tags : Inventory Page read not supported */
*(a_send_byte + send_index) = (uint8_t) ISO15693_RDMULBLKS_CMD_MASK;
break;
}
case ISO15693_SLI_X_S_MAX_SIZE:
{
/* For SLI - S tags : Read multiple blocks not supported */
*(a_send_byte + send_index) = (uint8_t) ISO15693_INVENTORY_CMD_MASK;
break;
}
case ISO15693_SLI_X_L_MAX_SIZE:
{
/* For SLI - L tags : Read multiple blocks not supported */
*(a_send_byte + send_index) = (uint8_t) ISO15693_INVENTORY_CMD_MASK;
break;
}
default:
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_DEVICE_REQUEST);
break;
}
}
send_index = (uint8_t)(send_index + 1);
send_length = sizeof (a_send_byte);
}
break;
}
case ISO15693_WRITE_CC_FMT:
{
/* CC byte write succcessful.
Prepare data for NDEF TLV writing */
command_type = ISO15693_WR_SINGLE_BLK_CMD;
e_format_seq = ISO15693_WRITE_NDEF_TLV;
ps_iso15693_info->current_block = (uint16_t)
(ps_iso15693_info->current_block + 1);
/* NDEF TLV - Type byte updated to 0x03 */
*a_send_byte = (uint8_t)ISO15693_NDEF_TLV_TYPE_ID;
send_index = (uint8_t)(send_index + 1);
/* NDEF TLV - Length byte updated to 0 */
*(a_send_byte + send_index) = 0;
send_index = (uint8_t)(send_index + 1);
/* Terminator TLV - value updated to 0xFEU */
*(a_send_byte + send_index) = (uint8_t)
ISO15693_TERMINATOR_TLV_ID;
send_index = (uint8_t)(send_index + 1);
send_length = sizeof (a_send_byte);
break;
}
case ISO15693_WRITE_NDEF_TLV:
{
/* SUCCESSFUL formatting complete */
format_complete = TRUE;
break;
}
default:
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
break;
}
}
if ((!format_complete) && (!result))
{
result = phFriNfc_ISO15693_H_FmtReadWrite (psNdefSmtCrdFmt,
command_type, a_send_byte, send_length);
}
ps_iso15693_info->format_seq = (uint8_t)e_format_seq;
return result;
}
/*********************** Static function definitions end ***********************/
/*********************** External function definitions start ***********************/
void
phFriNfc_ISO15693_FmtReset (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt)
{
/* reset to ISO15693 data structure */
(void)memset((void *)&(psNdefSmtCrdFmt->AddInfo.s_iso15693_info),
0x00, sizeof (phFriNfc_ISO15693_AddInfo_t));
psNdefSmtCrdFmt->FmtProcStatus = 0;
}
NFCSTATUS
phFriNfc_ISO15693_Format (
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
phHal_sIso15693Info_t *ps_rem_iso_15693_info =
&(psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info);
if ((ISO15693_7TH_BYTE_UID_VALUE ==
ps_rem_iso_15693_info->Uid[ISO15693_BYTE_7_INDEX])
&& (ISO15693_6TH_BYTE_UID_VALUE ==
ps_rem_iso_15693_info->Uid[ISO15693_BYTE_6_INDEX]))
{
/* Check if the card is manufactured by NXP (6th byte
index of UID value = 0x04 and the
last byte of UID is 0xE0, only then the card detected
is NDEF compliant */
psNdefSmtCrdFmt->State = ISO15693_FORMAT;
/* GET system information command to get the card size */
result = phFriNfc_ISO15693_H_FmtReadWrite (psNdefSmtCrdFmt,
ISO15693_GET_SYSTEM_INFO_CMD, NULL, 0);
}
else
{
result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
}
return result;
}
void
phFriNfc_ISO15693_FmtProcess (
void *pContext,
NFCSTATUS Status)
{
phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt =
(phFriNfc_sNdefSmtCrdFmt_t *)pContext;
phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info =
&(psNdefSmtCrdFmt->AddInfo.s_iso15693_info);
if((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER))
{
if (ISO15693_FORMAT == psNdefSmtCrdFmt->State)
{
/* Check for further formatting */
Status = phFriNfc_ISO15693_H_ProFormat (psNdefSmtCrdFmt);
}
else
{
Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
}
}
else
{
Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_FORMAT_ERROR);
}
/* Handle the all the error cases */
if ((NFCSTATUS_PENDING & PHNFCSTBLOWER) != (Status & PHNFCSTBLOWER))
{
/* call respective CR */
phFriNfc_SmtCrdFmt_HCrHandler (psNdefSmtCrdFmt, Status);
}
}
/*********************** External function definitions end ***********************/
#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */