3 * Copyright (C) 2010 NXP Semiconductors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 * \file phFriNfc_ISO15693Format.c
20 * \brief This component encapsulates different format functinalities ,
21 * for the ISO-15693 card.
32 #ifndef PH_FRINFC_FMT_ISO15693_DISABLED
34 #include <phNfcTypes.h>
35 #include <phFriNfc_OvrHal.h>
36 #include <phFriNfc_SmtCrdFmt.h>
37 #include <phFriNfc_ISO15693Format.h>
40 /****************************** Macro definitions start ********************************/
41 /* State for the format */
42 #define ISO15693_FORMAT 0x01U
44 /* Bytes per block in the ISO-15693 */
45 #define ISO15693_BYTES_PER_BLOCK 0x04U
48 GET SYSTEM INFORMATION COMMAND
50 #define ISO15693_GET_SYSTEM_INFO_CMD 0x2BU
51 /* READ SINGLE BLOCK COMMAND */
52 #define ISO15693_RD_SINGLE_BLK_CMD 0x20U
53 /* WRITE SINGLE BLOCK COMMAND */
54 #define ISO15693_WR_SINGLE_BLK_CMD 0x21U
55 /* READ MULTIPLE BLOCK COMMAND */
56 #define ISO15693_RD_MULTIPLE_BLKS_CMD 0x23U
59 CC BYTE 0 - Magic Number - 0xE1
61 #define ISO15693_CC_MAGIC_NUM 0xE1U
62 /* CC BYTE 1 - Mapping version and READ WRITE settings 0x40
64 #define ISO15693_CC_VER_RW 0x40U
65 /* CC BYTE 2 - max size is calaculated using the byte 3 multiplied by 8 */
66 #define ISO15693_CC_MULTIPLE_FACTOR 0x08U
68 /* Inventory command support mask for the CC byte 4 */
69 #define ISO15693_INVENTORY_CMD_MASK 0x02U
70 /* Read MULTIPLE blocks support mask for CC byte 4 */
71 #define ISO15693_RDMULBLKS_CMD_MASK 0x01U
72 /* Flags for the command */
73 #define ISO15693_FMT_FLAGS 0x20U
76 #define ISO15693_RD_2_BLOCKS 0x02U
78 /* TYPE identifier of the NDEF TLV */
79 #define ISO15693_NDEF_TLV_TYPE_ID 0x03U
80 /* Terminator TLV identifier */
81 #define ISO15693_TERMINATOR_TLV_ID 0xFEU
83 /* UID 7th byte value shall be 0xE0 */
84 #define ISO15693_7TH_BYTE_UID_VALUE 0xE0U
85 #define ISO15693_BYTE_7_INDEX 0x07U
87 /* UID 6th byte value shall be 0x04 - NXP manufacturer */
88 #define ISO15693_6TH_BYTE_UID_VALUE 0x04U
89 #define ISO15693_BYTE_6_INDEX 0x06U
91 #define ISO15693_EXTRA_RESPONSE_FLAG 0x01U
93 #define ISO15693_GET_SYS_INFO_RESP_LEN 0x0EU
94 #define ISO15693_DSFID_MASK 0x01U
95 #define ISO15693_AFI_MASK 0x02U
96 #define ISO15693_MAX_SIZE_MASK 0x04U
97 #define ISO15693_ICREF_MASK 0x08U
98 #define ISO15693_SKIP_DFSID 0x01U
99 #define ISO15693_SKIP_AFI 0x01U
100 #define ISO15693_BLOCK_SIZE_IN_BYTES_MASK 0x1FU
103 /* MAXimum size of ICODE SLI/X */
104 #define ISO15693_SLI_X_MAX_SIZE 112U
105 /* MAXimum size of ICODE SLI/X - S */
106 #define ISO15693_SLI_X_S_MAX_SIZE 160U
107 /* MAXimum size of ICODE SLI/X - L */
108 #define ISO15693_SLI_X_L_MAX_SIZE 32U
109 /****************************** Macro definitions end ********************************/
111 /****************************** Data structures start ********************************/
112 typedef enum phFriNfc_ISO15693_FormatSeq
114 ISO15693_GET_SYS_INFO,
115 ISO15693_RD_SINGLE_BLK_CHECK,
116 ISO15693_WRITE_CC_FMT,
117 ISO15693_WRITE_NDEF_TLV
118 }phFriNfc_ISO15693_FormatSeq_t;
119 /****************************** Data structures end ********************************/
121 /*********************** Static function declarations start ***********************/
124 phFriNfc_ISO15693_H_ProFormat (
125 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt);
129 phFriNfc_ISO15693_H_GetMaxDataSize (
130 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
132 uint8_t recv_length);
136 phFriNfc_ISO15693_H_FmtReadWrite (
137 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
140 uint8_t data_length);
141 /*********************** Static function declarations end ***********************/
143 /*********************** Static function definitions start ***********************/
147 phFriNfc_ISO15693_H_FmtReadWrite (
148 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
153 NFCSTATUS result = NFCSTATUS_SUCCESS;
154 uint8_t send_index = 0;
156 /* set the data for additional data exchange*/
157 psNdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
158 psNdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0;
159 psNdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0;
161 psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine =
162 phFriNfc_ISO15693_FmtProcess;
163 psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = psNdefSmtCrdFmt;
165 *psNdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;
167 psNdefSmtCrdFmt->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd;
169 *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)ISO15693_FMT_FLAGS;
170 send_index = (uint8_t)(send_index + 1);
172 *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)command;
173 send_index = (uint8_t)(send_index + 1);
175 (void)memcpy ((void *)(psNdefSmtCrdFmt->SendRecvBuf + send_index),
176 (void *)psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid,
177 psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
178 send_index = (uint8_t)(send_index +
179 psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
183 case ISO15693_WR_SINGLE_BLK_CMD:
184 case ISO15693_RD_MULTIPLE_BLKS_CMD:
186 *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)
187 psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block;
188 send_index = (uint8_t)(send_index + 1);
192 (void)memcpy ((void *)(psNdefSmtCrdFmt->SendRecvBuf + send_index),
193 (void *)p_data, data_length);
194 send_index = (uint8_t)(send_index + data_length);
198 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
199 NFCSTATUS_INVALID_DEVICE_REQUEST);
204 case ISO15693_RD_SINGLE_BLK_CMD:
206 *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)
207 psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block;
208 send_index = (uint8_t)(send_index + 1);
212 case ISO15693_GET_SYSTEM_INFO_CMD:
214 /* Dont do anything */
220 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
221 NFCSTATUS_INVALID_DEVICE_REQUEST);
226 psNdefSmtCrdFmt->SendLength = send_index;
230 result = phFriNfc_OvrHal_Transceive(psNdefSmtCrdFmt->LowerDevice,
231 &psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
232 psNdefSmtCrdFmt->psRemoteDevInfo,
233 psNdefSmtCrdFmt->Cmd,
234 &psNdefSmtCrdFmt->psDepAdditionalInfo,
235 psNdefSmtCrdFmt->SendRecvBuf,
236 psNdefSmtCrdFmt->SendLength,
237 psNdefSmtCrdFmt->SendRecvBuf,
238 psNdefSmtCrdFmt->SendRecvLength);
246 phFriNfc_ISO15693_H_GetMaxDataSize (
247 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt,
251 NFCSTATUS result = NFCSTATUS_SUCCESS;
252 phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info =
253 &(psNdefSmtCrdFmt->AddInfo.s_iso15693_info);
254 phHal_sIso15693Info_t *ps_rem_iso_15693_info =
255 &(psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info);
256 uint8_t recv_index = 0;
258 if ((ISO15693_GET_SYS_INFO_RESP_LEN == recv_length)
259 && (ISO15693_MAX_SIZE_MASK == (*p_recv_buf & ISO15693_MAX_SIZE_MASK)))
261 uint8_t information_flag = *p_recv_buf;
262 /* MAX size is present in the system information and
263 also response length is correct */
264 recv_index = (uint8_t)(recv_index + 1);
266 if (!phOsalNfc_MemCompare ((void *)ps_rem_iso_15693_info->Uid,
267 (void *)(p_recv_buf + recv_index),
268 ps_rem_iso_15693_info->UidLength))
270 /* UID comaparision successful */
271 uint8_t no_of_blocks = 0;
272 uint8_t blk_size_in_bytes = 0;
273 uint8_t ic_reference = 0;
275 /* So skip the UID size compared in the received buffer */
276 recv_index = (uint8_t)(recv_index +
277 ps_rem_iso_15693_info->UidLength);
279 if (information_flag & ISO15693_DSFID_MASK) {
281 recv_index = (uint8_t)(recv_index + ISO15693_SKIP_DFSID);
283 if (information_flag & ISO15693_AFI_MASK) {
285 recv_index = (uint8_t)(recv_index + ISO15693_SKIP_AFI);
288 /* To get the number of blocks in the card */
289 no_of_blocks = (uint8_t)(*(p_recv_buf + recv_index) + 1);
290 recv_index = (uint8_t)(recv_index + 1);
292 /* To get the each block size in bytes */
293 blk_size_in_bytes = (uint8_t)((*(p_recv_buf + recv_index)
294 & ISO15693_BLOCK_SIZE_IN_BYTES_MASK) + 1);
295 recv_index = (uint8_t)(recv_index + 1);
297 if (information_flag & ISO15693_ICREF_MASK) {
298 /* Get the IC reference */
299 ic_reference = (uint8_t)(*(p_recv_buf + recv_index));
300 if (ic_reference == 0x03) {
305 /* calculate maximum data size in the card */
306 ps_iso15693_info->max_data_size = (uint16_t)
307 (no_of_blocks * blk_size_in_bytes);
312 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
313 NFCSTATUS_INVALID_DEVICE_REQUEST);
318 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
319 NFCSTATUS_INVALID_DEVICE_REQUEST);
328 phFriNfc_ISO15693_H_ProFormat (
329 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt)
331 NFCSTATUS result = NFCSTATUS_SUCCESS;
332 phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info =
333 &(psNdefSmtCrdFmt->AddInfo.s_iso15693_info);
334 phFriNfc_ISO15693_FormatSeq_t e_format_seq =
335 (phFriNfc_ISO15693_FormatSeq_t)
336 ps_iso15693_info->format_seq;
337 uint8_t command_type = 0;
338 uint8_t a_send_byte[ISO15693_BYTES_PER_BLOCK] = {0};
339 uint8_t send_length = 0;
340 uint8_t send_index = 0;
341 uint8_t format_complete = FALSE;
343 switch (e_format_seq)
345 case ISO15693_GET_SYS_INFO:
347 /* RESPONSE received for GET SYSTEM INFO */
349 if (!phFriNfc_ISO15693_H_GetMaxDataSize (psNdefSmtCrdFmt,
350 (psNdefSmtCrdFmt->SendRecvBuf + ISO15693_EXTRA_RESPONSE_FLAG),
351 (uint8_t)(*psNdefSmtCrdFmt->SendRecvLength -
352 ISO15693_EXTRA_RESPONSE_FLAG)))
354 /* Send the READ SINGLE BLOCK COMMAND */
355 command_type = ISO15693_RD_SINGLE_BLK_CMD;
356 e_format_seq = ISO15693_RD_SINGLE_BLK_CHECK;
358 /* Block number 0 to read */
359 psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block = 0x00;
363 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
364 NFCSTATUS_INVALID_RECEIVE_LENGTH);
369 case ISO15693_RD_SINGLE_BLK_CHECK:
371 /* RESPONSE received for READ SINGLE BLOCK
374 /* Check if Card is really fresh
375 First 4 bytes must be 0 for fresh card */
377 if ((psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block == 0x00) &&
378 (psNdefSmtCrdFmt->SendRecvBuf[1] != 0x00 ||
379 psNdefSmtCrdFmt->SendRecvBuf[2] != 0x00 ||
380 psNdefSmtCrdFmt->SendRecvBuf[3] != 0x00 ||
381 psNdefSmtCrdFmt->SendRecvBuf[4] != 0x00))
383 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_FORMAT);
387 /* prepare data for writing CC bytes */
389 command_type = ISO15693_WR_SINGLE_BLK_CMD;
390 e_format_seq = ISO15693_WRITE_CC_FMT;
392 /* CC magic number */
393 *a_send_byte = (uint8_t)ISO15693_CC_MAGIC_NUM;
394 send_index = (uint8_t)(send_index + 1);
396 /* CC Version and read/write access */
397 *(a_send_byte + send_index) = (uint8_t) ISO15693_CC_VER_RW;
398 send_index = (uint8_t)(send_index + 1);
400 /* CC MAX data size, calculated during GET system information */
401 *(a_send_byte + send_index) = (uint8_t) (ps_iso15693_info->max_data_size / ISO15693_CC_MULTIPLE_FACTOR);
402 send_index = (uint8_t)(send_index + 1);
404 switch (ps_iso15693_info->max_data_size)
406 case ISO15693_SLI_X_MAX_SIZE:
408 /* For SLI tags : Inventory Page read not supported */
409 *(a_send_byte + send_index) = (uint8_t) ISO15693_RDMULBLKS_CMD_MASK;
413 case ISO15693_SLI_X_S_MAX_SIZE:
415 /* For SLI - S tags : Read multiple blocks not supported */
416 *(a_send_byte + send_index) = (uint8_t) ISO15693_INVENTORY_CMD_MASK;
420 case ISO15693_SLI_X_L_MAX_SIZE:
422 /* For SLI - L tags : Read multiple blocks not supported */
423 *(a_send_byte + send_index) = (uint8_t) ISO15693_INVENTORY_CMD_MASK;
429 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_DEVICE_REQUEST);
434 send_index = (uint8_t)(send_index + 1);
436 send_length = sizeof (a_send_byte);
442 case ISO15693_WRITE_CC_FMT:
444 /* CC byte write succcessful.
445 Prepare data for NDEF TLV writing */
446 command_type = ISO15693_WR_SINGLE_BLK_CMD;
447 e_format_seq = ISO15693_WRITE_NDEF_TLV;
449 ps_iso15693_info->current_block = (uint16_t)
450 (ps_iso15693_info->current_block + 1);
452 /* NDEF TLV - Type byte updated to 0x03 */
453 *a_send_byte = (uint8_t)ISO15693_NDEF_TLV_TYPE_ID;
454 send_index = (uint8_t)(send_index + 1);
456 /* NDEF TLV - Length byte updated to 0 */
457 *(a_send_byte + send_index) = 0;
458 send_index = (uint8_t)(send_index + 1);
460 /* Terminator TLV - value updated to 0xFEU */
461 *(a_send_byte + send_index) = (uint8_t)
462 ISO15693_TERMINATOR_TLV_ID;
463 send_index = (uint8_t)(send_index + 1);
465 send_length = sizeof (a_send_byte);
469 case ISO15693_WRITE_NDEF_TLV:
471 /* SUCCESSFUL formatting complete */
472 format_complete = TRUE;
478 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
479 NFCSTATUS_INVALID_DEVICE_REQUEST);
484 if ((!format_complete) && (!result))
486 result = phFriNfc_ISO15693_H_FmtReadWrite (psNdefSmtCrdFmt,
487 command_type, a_send_byte, send_length);
490 ps_iso15693_info->format_seq = (uint8_t)e_format_seq;
494 /*********************** Static function definitions end ***********************/
496 /*********************** External function definitions start ***********************/
498 phFriNfc_ISO15693_FmtReset (
499 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt)
501 /* reset to ISO15693 data structure */
502 (void)memset((void *)&(psNdefSmtCrdFmt->AddInfo.s_iso15693_info),
503 0x00, sizeof (phFriNfc_ISO15693_AddInfo_t));
504 psNdefSmtCrdFmt->FmtProcStatus = 0;
508 phFriNfc_ISO15693_Format (
509 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt)
511 NFCSTATUS result = NFCSTATUS_SUCCESS;
512 phHal_sIso15693Info_t *ps_rem_iso_15693_info =
513 &(psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info);
516 if ((ISO15693_7TH_BYTE_UID_VALUE ==
517 ps_rem_iso_15693_info->Uid[ISO15693_BYTE_7_INDEX])
518 && (ISO15693_6TH_BYTE_UID_VALUE ==
519 ps_rem_iso_15693_info->Uid[ISO15693_BYTE_6_INDEX]))
521 /* Check if the card is manufactured by NXP (6th byte
522 index of UID value = 0x04 and the
523 last byte of UID is 0xE0, only then the card detected
525 psNdefSmtCrdFmt->State = ISO15693_FORMAT;
527 /* GET system information command to get the card size */
528 result = phFriNfc_ISO15693_H_FmtReadWrite (psNdefSmtCrdFmt,
529 ISO15693_GET_SYSTEM_INFO_CMD, NULL, 0);
533 result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
534 NFCSTATUS_INVALID_DEVICE_REQUEST);
541 phFriNfc_ISO15693_FmtProcess (
545 phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt =
546 (phFriNfc_sNdefSmtCrdFmt_t *)pContext;
547 phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info =
548 &(psNdefSmtCrdFmt->AddInfo.s_iso15693_info);
550 if((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER))
552 if (ISO15693_FORMAT == psNdefSmtCrdFmt->State)
554 /* Check for further formatting */
555 Status = phFriNfc_ISO15693_H_ProFormat (psNdefSmtCrdFmt);
559 Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
560 NFCSTATUS_INVALID_DEVICE_REQUEST);
565 Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT,
566 NFCSTATUS_FORMAT_ERROR);
569 /* Handle the all the error cases */
570 if ((NFCSTATUS_PENDING & PHNFCSTBLOWER) != (Status & PHNFCSTBLOWER))
572 /* call respective CR */
573 phFriNfc_SmtCrdFmt_HCrHandler (psNdefSmtCrdFmt, Status);
576 /*********************** External function definitions end ***********************/
579 #endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */