blob: a21d9c868f4fd78b06601cbc8fa4107f10632a31 [file] [log] [blame]
Martijn Coenena6e012a2011-01-13 23:24:24 +01001/*
Nick Pelly34ff48f2011-06-27 09:01:51 -07002 *
Martijn Coenena6e012a2011-01-13 23:24:24 +01003 * Copyright (C) 2010 NXP Semiconductors
4 *
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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 */
17
18/*!
19* \file phFriNfc_ISO15693Map.c
20* \brief This component encapsulates read/write/check ndef/process functionalities,
21* for the ISO-15693 Card.
22*
23* Project: NFC-FRI
24*
25* $Date: $
26* $Author: ing02260 $
27* $Revision: $
28* $Aliases: $
29*
30*/
31
32#ifndef PH_FRINFC_MAP_ISO15693_DISABLED
33
34#include <phNfcTypes.h>
35#include <phNfcConfig.h>
36#include <phNfcInterface.h>
37#include <phNfcHalTypes.h>
38#include <phFriNfc.h>
39#include <phFriNfc_NdefMap.h>
40#include <phFriNfc_OvrHal.h>
41#include <phFriNfc_MapTools.h>
42#include <phFriNfc_ISO15693Map.h>
43
44/************************** START DATA STRUCTURE *********************/
45
46typedef enum phFriNfc_eChkNdefSeq
47{
48 ISO15693_NDEF_TLV_T,
49 ISO15693_NDEF_TLV_L,
50 ISO15693_NDEF_TLV_V,
51 ISO15693_PROP_TLV_L,
52 ISO15693_PROP_TLV_V
53
54}phFriNfc_eChkNdefSeq_t;
55
56typedef enum phFriNfc_eWrNdefSeq
57{
58 ISO15693_RD_BEFORE_WR_NDEF_L_0,
59 ISO15693_WRITE_DATA,
60 ISO15693_RD_BEFORE_WR_NDEF_L,
61 ISO15693_WRITE_NDEF_TLV_L
62
63}phFriNfc_eWrNdefSeq_t;
64
65#ifdef FRINFC_READONLY_NDEF
66
67typedef enum phFriNfc_eRONdefSeq
68{
69 ISO15693_RD_BEFORE_WR_CC,
70 ISO15693_WRITE_CC,
71 ISO15693_LOCK_BLOCK
72
73}phFriNfc_eRONdefSeq_t;
74
75#endif /* #ifdef FRINFC_READONLY_NDEF */
76
77/************************** END DATA STRUCTURE *********************/
78
79/************************** START MACROS definition *********************/
80
81
82
83
84/* UID bytes to differentiate ICODE cards */
85#define ISO15693_UID_BYTE_4 0x04U
86#define ISO15693_UID_BYTE_5 0x05U
Martijn Coenen4f3ef022011-01-20 01:27:17 +010087#define ISO15693_UID_BYTE_6 0x06U
88#define ISO15693_UID_BYTE_7 0x07U
89
90/* UID 7th byte value shall be 0xE0 */
91#define ISO15693_UIDBYTE_7_VALUE 0xE0U
92/* UID 6th byte value shall be 0x04 - NXP manufacturer */
93#define ISO15693_UIDBYTE_6_VALUE 0x04U
94
Martijn Coenena6e012a2011-01-13 23:24:24 +010095
96/* UID value for
97 SL2 ICS20
98 SL2S2002
99 */
100#define ISO15693_UIDBYTE_5_VALUE_SLI_X 0x01U
101/* Card size SL2 ICS20 / SL2S2002 */
102#define ISO15693_SL2_S2002_ICS20 112U
103
104/* UID value for
105 SL2 ICS53,
106 SL2 ICS54
107 SL2S5302
108*/
109#define ISO15693_UIDBYTE_5_VALUE_SLI_X_S 0x02U
110#define ISO15693_UIDBYTE_4_VALUE_SLI_X_S 0x00U
111#define ISO15693_UIDBYTE_4_VALUE_SLI_X_SHC 0x80U
112#define ISO15693_UIDBYTE_4_VALUE_SLI_X_SY 0x40U
113/* SL2 ICS53, SL2 ICS54 and SL2S5302 */
114#define ISO15693_SL2_S5302_ICS53_ICS54 160U
115
116/* UID value for
117 SL2 ICS50
118 SL2 ICS51
119 SL2S5002
120*/
121#define ISO15693_UIDBYTE_5_VALUE_SLI_X_L 0x03U
122#define ISO15693_UIDBYTE_4_VALUE_SLI_X_L 0x00U
123#define ISO15693_UIDBYTE_4_VALUE_SLI_X_LHC 0x80U
124/* SL2 ICS50, SL2 ICS51 and SL2S5002 */
125#define ISO15693_SL2_S5002_ICS50_ICS51 32U
126
127
128/* State Machine declaration
129CHECK NDEF state */
130#define ISO15693_CHECK_NDEF 0x01U
131/* READ NDEF state */
132#define ISO15693_READ_NDEF 0x02U
133/* WRITE NDEF state */
134#define ISO15693_WRITE_NDEF 0x03U
135#ifdef FRINFC_READONLY_NDEF
136
137 /* READ ONLY NDEF state */
138 #define ISO15693_READ_ONLY_NDEF 0x04U
139
140 /* READ ONLY MASK byte for CC */
141 #define ISO15693_CC_READ_ONLY_MASK 0x03U
142
143 /* CC READ WRITE index */
144 #define ISO15693_RW_BTYE_INDEX 0x01U
145
146 /* LOCK BLOCK command */
147 #define ISO15693_LOCK_BLOCK_CMD 0x22U
148
149#endif /* #ifdef FRINFC_READONLY_NDEF */
150
151/* CC Bytes
152Magic number */
153#define ISO15693_CC_MAGIC_BYTE 0xE1U
154/* Expected mapping version */
155#define ISO15693_MAPPING_VERSION 0x01U
156/* Major version is in upper 2 bits */
157#define ISO15693_MAJOR_VERSION_MASK 0xC0U
158
159/* CC indicating tag is capable of multi-block read */
160#define ISO15693_CC_USE_MBR 0x01U
161/* CC indicating tag is capable of inventory page read */
162#define ISO15693_CC_USE_IPR 0x02U
163/* EXTRA byte in the response */
164#define ISO15693_EXTRA_RESP_BYTE 0x01U
165
166/* Maximum card size multiplication factor */
167#define ISO15693_MULT_FACTOR 0x08U
168/* NIBBLE mask for READ WRITE access */
169#define ISO15693_LSB_NIBBLE_MASK 0x0FU
Martijn Coenena6e012a2011-01-13 23:24:24 +0100170#define ISO15693_RD_WR_PERMISSION 0x00U
171#define ISO15693_RD_ONLY_PERMISSION 0x03U
172
173/* READ command identifier */
174#define ISO15693_READ_COMMAND 0x20U
175
176/* READ multiple command identifier */
177#define ISO15693_READ_MULTIPLE_COMMAND 0x23U
178
179/* INVENTORY pageread command identifier */
180#define ICODE_INVENTORY_PAGEREAD_COMMAND 0xB0U
181#define INVENTORY_PAGEREAD_FLAGS 0x24U
182#define NXP_MANUFACTURING_CODE 0x04U
183
184/* WRITE command identifier */
185#define ISO15693_WRITE_COMMAND 0x21U
186/* FLAG option */
187#define ISO15693_FLAGS 0x20U
188
189/* RESPONSE length expected for single block READ */
190#define ISO15693_SINGLE_BLK_RD_RESP_LEN 0x04U
191/* NULL TLV identifier */
192#define ISO15693_NULL_TLV_ID 0x00U
193/* NDEF TLV, TYPE identifier */
194#define ISO15693_NDEF_TLV_TYPE_ID 0x03U
195
196/* 8 BIT shift */
197#define ISO15693_BTYE_SHIFT 0x08U
198
199/* Proprietary TLV TYPE identifier */
200#define ISO15693_PROP_TLV_ID 0xFDU
201
202/* CC SIZE in BYTES */
203#define ISO15693_CC_SIZE 0x04U
204
205/* To get the remaining size in the card.
206Inputs are
2071. maximum data size
2082. block number
2093. index of the block number */
210#define ISO15693_GET_REMAINING_SIZE(max_data_size, blk, index) \
211 (max_data_size - ((blk * ISO15693_BYTES_PER_BLOCK) + index))
212
213#define ISO15693_GET_LEN_FIELD_BLOCK_NO(blk, byte_addr, ndef_size) \
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100214 (((byte_addr + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) > \
Martijn Coenena6e012a2011-01-13 23:24:24 +0100215 (ISO15693_BYTES_PER_BLOCK - 1)) ? (blk + 1) : blk)
216
217#define ISO15693_GET_LEN_FIELD_BYTE_NO(blk, byte_addr, ndef_size) \
218 (((byte_addr + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) % \
219 ISO15693_BYTES_PER_BLOCK))
220
221
222
223/************************** END MACROS definition *********************/
224
225/************************** START static functions declaration *********************/
226static
227NFCSTATUS
228phFriNfc_ISO15693_H_ProcessReadOnly (
229 phFriNfc_NdefMap_t *psNdefMap);
230
231static
232NFCSTATUS
233phFriNfc_ISO15693_H_ProcessWriteNdef (
234 phFriNfc_NdefMap_t *psNdefMap);
235
236static
237NFCSTATUS
238phFriNfc_ISO15693_H_ProcessReadNdef (
239 phFriNfc_NdefMap_t *psNdefMap);
240
241static
242NFCSTATUS
243phFriNfc_ISO15693_H_ProcessCheckNdef (
244 phFriNfc_NdefMap_t *psNdefMap);
245
246static
247void
248phFriNfc_ISO15693_H_Complete (
249 phFriNfc_NdefMap_t *psNdefMap,
250 NFCSTATUS Status);
251
252static
253NFCSTATUS
254phFriNfc_ISO15693_H_ReadWrite (
255 phFriNfc_NdefMap_t *psNdefMap,
256 uint8_t command,
257 uint8_t *p_data,
258 uint8_t data_length);
259
260static
261NFCSTATUS
262phFriNfc_ReadRemainingInMultiple (
263 phFriNfc_NdefMap_t *psNdefMap,
264 uint32_t startBlock);
265
266/************************** END static functions declaration *********************/
267
268/************************** START static functions definition *********************/
269
270static
271NFCSTATUS
272phFriNfc_ISO15693_H_ProcessWriteNdef (
273 phFriNfc_NdefMap_t *psNdefMap)
274{
275 NFCSTATUS result = NFCSTATUS_SUCCESS;
276 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
277 &(psNdefMap->ISO15693Container);
278 phFriNfc_eWrNdefSeq_t e_wr_ndef_seq = (phFriNfc_eWrNdefSeq_t)
279 psNdefMap->ISO15693Container.ndef_seq;
280 uint8_t *p_recv_buf = NULL;
281 uint8_t recv_length = 0;
282 uint8_t write_flag = FALSE;
283 uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0};
284 uint8_t remaining_size = 0;
285
286 switch (e_wr_ndef_seq)
287 {
288 case ISO15693_RD_BEFORE_WR_NDEF_L_0:
289 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100290 /* L byte is read */
291 p_recv_buf = (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE);
Martijn Coenena6e012a2011-01-13 23:24:24 +0100292 recv_length = (uint8_t)
293 (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE);
294
295 if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length)
296 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100297 /* Response length is correct */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100298 uint8_t byte_index = 0;
299
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100300 /* Copy the recevied buffer */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100301 (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf,
302 recv_length);
303
304 byte_index = ISO15693_GET_LEN_FIELD_BYTE_NO(
305 ps_iso_15693_con->ndef_tlv_type_blk,
306 ps_iso_15693_con->ndef_tlv_type_byte,
307 psNdefMap->ApduBufferSize);
308
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100309 /* Writing length field to 0, Update length field to 0 */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100310 *(a_write_buf + byte_index) = 0x00;
311
312 if ((ISO15693_BYTES_PER_BLOCK - 1) != byte_index)
313 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100314 /* User data is updated in the buffer */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100315 byte_index = (uint8_t)(byte_index + 1);
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100316 /* Block number shall be udate */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100317 remaining_size = (ISO15693_BYTES_PER_BLOCK - byte_index);
318
319 if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)
320 < remaining_size)
321 {
322 remaining_size = (uint8_t)(psNdefMap->ApduBufferSize -
323 psNdefMap->ApduBuffIndex);
324 }
325
326 /* Go to next byte to fill the write buffer */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100327 (void)memcpy ((void *)(a_write_buf + byte_index),
328 (void *)(psNdefMap->ApduBuffer +
329 psNdefMap->ApduBuffIndex), remaining_size);
330
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100331 /* Write index updated */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100332 psNdefMap->ApduBuffIndex = (uint8_t)(psNdefMap->ApduBuffIndex +
333 remaining_size);
334 }
335
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100336 /* After this write, user data can be written.
337 Update the sequence accordingly */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100338 e_wr_ndef_seq = ISO15693_WRITE_DATA;
339 write_flag = TRUE;
340 } /* if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) */
341 else
342 {
343 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
344 NFCSTATUS_INVALID_RECEIVE_LENGTH);
345 }
346 break;
347 } /* case ISO15693_RD_BEFORE_WR_NDEF_L_0: */
348
349 case ISO15693_RD_BEFORE_WR_NDEF_L:
350 {
351 p_recv_buf = (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE);
352 recv_length = (uint8_t)(*psNdefMap->SendRecvLength -
353 ISO15693_EXTRA_RESP_BYTE);
354
355 if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length)
356 {
357 uint8_t byte_index = 0;
358
359 (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf,
360 recv_length);
361
362 byte_index = ISO15693_GET_LEN_FIELD_BYTE_NO(
363 ps_iso_15693_con->ndef_tlv_type_blk,
364 ps_iso_15693_con->ndef_tlv_type_byte,
365 psNdefMap->ApduBuffIndex);
366
367 *(a_write_buf + byte_index) = (uint8_t)psNdefMap->ApduBuffIndex;
368 e_wr_ndef_seq = ISO15693_WRITE_NDEF_TLV_L;
369 write_flag = TRUE;
370 }
371 else
372 {
373 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
374 NFCSTATUS_INVALID_RECEIVE_LENGTH);
375 }
376 break;
377 }
378
379 case ISO15693_WRITE_DATA:
380 {
381 if ((psNdefMap->ApduBufferSize == psNdefMap->ApduBuffIndex)
382 || (ps_iso_15693_con->current_block ==
383 (ps_iso_15693_con->max_data_size / ISO15693_BYTES_PER_BLOCK)))
384 {
385 ps_iso_15693_con->current_block =
386 ISO15693_GET_LEN_FIELD_BLOCK_NO(
387 ps_iso_15693_con->ndef_tlv_type_blk,
388 ps_iso_15693_con->ndef_tlv_type_byte,
389 psNdefMap->ApduBuffIndex);
390 e_wr_ndef_seq = ISO15693_RD_BEFORE_WR_NDEF_L;
391 }
392 else
393 {
394 remaining_size = ISO15693_BYTES_PER_BLOCK;
395
396 ps_iso_15693_con->current_block = (uint16_t)
397 (ps_iso_15693_con->current_block + 1);
398
399 if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)
400 < remaining_size)
401 {
402 remaining_size = (uint8_t)(psNdefMap->ApduBufferSize -
403 psNdefMap->ApduBuffIndex);
404 }
405
406 (void)memcpy ((void *)a_write_buf, (void *)
407 (psNdefMap->ApduBuffer +
408 psNdefMap->ApduBuffIndex), remaining_size);
409
410 psNdefMap->ApduBuffIndex = (uint8_t)(psNdefMap->ApduBuffIndex +
411 remaining_size);
412 write_flag = TRUE;
413 }
414 break;
415 } /* case ISO15693_WRITE_DATA: */
416
417 case ISO15693_WRITE_NDEF_TLV_L:
418 {
419 *psNdefMap->WrNdefPacketLength = psNdefMap->ApduBuffIndex;
420 ps_iso_15693_con->actual_ndef_size = psNdefMap->ApduBuffIndex;
421 break;
422 }
423
424 default:
425 {
426 break;
427 }
428 } /* switch (e_wr_ndef_seq) */
429
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100430 if (((0 == psNdefMap->ApduBuffIndex)
431 || (*psNdefMap->WrNdefPacketLength != psNdefMap->ApduBuffIndex))
432 && (!result))
Martijn Coenena6e012a2011-01-13 23:24:24 +0100433 {
434 if (FALSE == write_flag)
435 {
436 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
437 ISO15693_READ_COMMAND, NULL, 0);
438 }
439 else
440 {
441 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
442 ISO15693_WRITE_COMMAND,
443 a_write_buf, sizeof (a_write_buf));
444 }
445 }
446
447 psNdefMap->ISO15693Container.ndef_seq = (uint8_t)e_wr_ndef_seq;
448 return result;
449}
450
451static
452NFCSTATUS
453phFriNfc_ISO15693_H_ReadWrite (
454 phFriNfc_NdefMap_t *psNdefMap,
455 uint8_t command,
456 uint8_t *p_data,
457 uint8_t data_length)
458{
459 NFCSTATUS result = NFCSTATUS_SUCCESS;
460 uint8_t send_index = 0;
461
462 /* set the data for additional data exchange*/
463 psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
464 psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0;
465 psNdefMap->psDepAdditionalInfo.NAD = 0;
466
467 psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_ISO15693_Process;
468 psNdefMap->MapCompletionInfo.Context = psNdefMap;
469
470 *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength;
471
472 psNdefMap->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd;
473
474 *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)ISO15693_FLAGS;
475 send_index = (uint8_t)(send_index + 1);
476
477 *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)command;
478 send_index = (uint8_t)(send_index + 1);
479
480 (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
481 (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid,
482 psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
483 send_index = (uint8_t)(send_index +
484 psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
485
486 *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)
487 psNdefMap->ISO15693Container.current_block;
488 send_index = (uint8_t)(send_index + 1);
489
490 if ((ISO15693_WRITE_COMMAND == command) ||
491 (ISO15693_READ_MULTIPLE_COMMAND == command))
492 {
493 (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
494 (void *)p_data, data_length);
495 send_index = (uint8_t)(send_index + data_length);
496 }
497
498 psNdefMap->SendLength = send_index;
499 result = phFriNfc_OvrHal_Transceive(psNdefMap->LowerDevice,
500 &psNdefMap->MapCompletionInfo,
501 psNdefMap->psRemoteDevInfo,
502 psNdefMap->Cmd,
503 &psNdefMap->psDepAdditionalInfo,
504 psNdefMap->SendRecvBuf,
505 psNdefMap->SendLength,
506 psNdefMap->SendRecvBuf,
507 psNdefMap->SendRecvLength);
508
509 return result;
510}
511
512static
513NFCSTATUS
514phFriNfc_ISO15693_H_Inventory_Page_Read (
515 phFriNfc_NdefMap_t *psNdefMap,
516 uint8_t command,
517 uint8_t page,
518 uint8_t numPages)
519{
520 NFCSTATUS result = NFCSTATUS_SUCCESS;
521 uint8_t send_index = 0;
522
523 /* set the data for additional data exchange*/
524 psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
525 psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0;
526 psNdefMap->psDepAdditionalInfo.NAD = 0;
527
528 psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_ISO15693_Process;
529 psNdefMap->MapCompletionInfo.Context = psNdefMap;
530
531 *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength;
532
533 psNdefMap->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd;
534
535 *(psNdefMap->SendRecvBuf + send_index) = INVENTORY_PAGEREAD_FLAGS;
536 send_index = (uint8_t)(send_index + 1);
537
538 *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)command;
539 send_index = (uint8_t)(send_index + 1);
540
541 *(psNdefMap->SendRecvBuf + send_index) = NXP_MANUFACTURING_CODE;
542 send_index = (uint8_t)(send_index + 1);
543
544 *(psNdefMap->SendRecvBuf + send_index) = 0x40;
545 send_index = (uint8_t)(send_index + 1);
546
547 (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
548 (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid,
549 psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
550 send_index = (uint8_t)(send_index +
551 psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength);
552
553 *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)
554 page;
555 send_index = (uint8_t)(send_index + 1);
556
557 *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)
558 numPages;
559 send_index = (uint8_t)(send_index + 1);
560
561 psNdefMap->SendLength = send_index;
562
563 result = phFriNfc_OvrHal_Transceive(psNdefMap->LowerDevice,
564 &psNdefMap->MapCompletionInfo,
565 psNdefMap->psRemoteDevInfo,
566 psNdefMap->Cmd,
567 &psNdefMap->psDepAdditionalInfo,
568 psNdefMap->SendRecvBuf,
569 psNdefMap->SendLength,
570 psNdefMap->SendRecvBuf,
571 psNdefMap->SendRecvLength);
572
573 return result;
574}
575
576static
577NFCSTATUS
578phFriNfc_ISO15693_Reformat_Pageread_Buffer (
579 uint8_t *p_recv_buf,
580 uint8_t recv_length,
581 uint8_t *p_dst_buf,
582 uint8_t dst_length)
583{
584 // Inventory page reads return an extra security byte per page
585 // So we need to reformat the returned buffer in memory
586 uint32_t i = 0;
587 uint32_t reformatted_index = 0;
588 while (i < recv_length) {
589 // Going for another page of 16 bytes, check for space in dst buffer
590 if (reformatted_index + 16 > dst_length) {
591 break;
592 }
593 if (p_recv_buf[i] == 0x0F) {
594 // Security, insert 16 0 bytes
595 memset(&(p_dst_buf[reformatted_index]), 0, 16);
596 reformatted_index += 16;
597 i++;
598 } else {
599 // Skip security byte
600 i++;
601 if (i + 16 <= recv_length) {
602 memcpy(&(p_dst_buf[reformatted_index]), &(p_recv_buf[i]), 16);
603 reformatted_index += 16;
604 } else {
605 break;
606 }
607 i+=16;
608 }
609 }
610 return reformatted_index;
611}
612
613static
614NFCSTATUS
615phFriNfc_ISO15693_H_ProcessReadNdef (
616 phFriNfc_NdefMap_t *psNdefMap)
617{
618 NFCSTATUS result = NFCSTATUS_SUCCESS;
619 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
620 &(psNdefMap->ISO15693Container);
621 uint16_t remaining_data_size = 0;
622 uint8_t *p_recv_buf =
623 (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE);
624 uint8_t recv_length = (uint8_t)
625 (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE);
626
627 uint8_t *reformatted_buf = (uint8_t*) phOsalNfc_GetMemory(ps_iso_15693_con->max_data_size);
628
629 if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)
630 {
631 uint8_t reformatted_size = phFriNfc_ISO15693_Reformat_Pageread_Buffer(p_recv_buf, recv_length,
632 reformatted_buf, ps_iso_15693_con->max_data_size);
633 p_recv_buf = reformatted_buf + (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK);
634 recv_length = reformatted_size - (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK);
635 }
636 if (ps_iso_15693_con->store_length)
637 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100638 /* Continue Offset option selected
Martijn Coenena6e012a2011-01-13 23:24:24 +0100639 So stored data already existing,
640 copy the information to the user buffer
641 */
642 if (ps_iso_15693_con->store_length
643 <= (psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex))
644 {
645 /* Stored data length is less than or equal
646 to the user expected size */
647 (void)memcpy ((void *)(psNdefMap->ApduBuffer +
648 psNdefMap->ApduBuffIndex),
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100649 (void *)ps_iso_15693_con->store_read_data,
Martijn Coenena6e012a2011-01-13 23:24:24 +0100650 ps_iso_15693_con->store_length);
651
652 psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
653 ps_iso_15693_con->store_length);
654
655 remaining_data_size = ps_iso_15693_con->store_length;
656
657 ps_iso_15693_con->store_length = 0;
658 }
659 else
660 {
661 /* stored length is more than the user expected size */
662 remaining_data_size = (uint16_t)(ps_iso_15693_con->store_length -
663 (psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex));
664
665 (void)memcpy ((void *)(psNdefMap->ApduBuffer +
666 psNdefMap->ApduBuffIndex),
667 (void *)ps_iso_15693_con->store_read_data,
668 remaining_data_size);
669
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100670 /* As stored data is more than the user expected data. So store
671 the remaining bytes again into the data structure */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100672 (void)memcpy ((void *)ps_iso_15693_con->store_read_data,
673 (void *)(ps_iso_15693_con->store_read_data +
674 remaining_data_size),
675 (ps_iso_15693_con->store_length - remaining_data_size));
676
677 psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
678 remaining_data_size);
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100679
680 ps_iso_15693_con->store_length = (uint8_t)
681 (ps_iso_15693_con->store_length - remaining_data_size);
Martijn Coenena6e012a2011-01-13 23:24:24 +0100682 }
683 } /* if (ps_iso_15693_con->store_length) */
684 else
685 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100686 /* Data is read from the card. */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100687 uint8_t byte_index = 0;
688
689 remaining_data_size = ps_iso_15693_con->remaining_size_to_read;
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100690
691 /* Check if the block number is to read the first VALUE field */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100692 if (ISO15693_GET_VALUE_FIELD_BLOCK_NO(ps_iso_15693_con->ndef_tlv_type_blk,
693 ps_iso_15693_con->ndef_tlv_type_byte,
694 ps_iso_15693_con->actual_ndef_size)
695 == ps_iso_15693_con->current_block)
696 {
697 /* Read from the beginning option selected,
698 BYTE number may start from the middle */
699 byte_index = (uint8_t)ISO15693_GET_VALUE_FIELD_BYTE_NO(
700 ps_iso_15693_con->ndef_tlv_type_blk,
701 ps_iso_15693_con->ndef_tlv_type_byte,
702 ps_iso_15693_con->actual_ndef_size);
703 }
704
705 if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)
706 < remaining_data_size)
707 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100708 remaining_data_size = (uint8_t)
709 (recv_length - byte_index);
710 /* user input is less than the remaining card size */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100711 if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100712 < (uint16_t)remaining_data_size)
Martijn Coenena6e012a2011-01-13 23:24:24 +0100713 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100714 /* user data required is less than the data read */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100715 remaining_data_size = (uint8_t)(psNdefMap->ApduBufferSize -
716 psNdefMap->ApduBuffIndex);
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100717
718 if (0 != (recv_length - (byte_index +
719 remaining_data_size)))
720 {
Martijn Coenena6e012a2011-01-13 23:24:24 +0100721 /* Store the data for the continue read option */
722 (void)memcpy ((void *)ps_iso_15693_con->store_read_data,
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100723 (void *)(p_recv_buf + (byte_index +
724 remaining_data_size)),
725 (recv_length - (byte_index +
726 remaining_data_size)));
Martijn Coenena6e012a2011-01-13 23:24:24 +0100727
728 ps_iso_15693_con->store_length = (uint8_t)
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100729 (recv_length - (byte_index +
730 remaining_data_size));
Martijn Coenena6e012a2011-01-13 23:24:24 +0100731 }
Martijn Coenena6e012a2011-01-13 23:24:24 +0100732 }
733 }
734 else
735 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100736 /* user data required is equal or greater than the data read */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100737 if (remaining_data_size > (recv_length - byte_index))
738 {
739 remaining_data_size = (uint8_t)
740 (recv_length - byte_index);
741 }
742 }
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100743
744 /* Copy data in the user buffer */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100745 (void)memcpy ((void *)(psNdefMap->ApduBuffer +
746 psNdefMap->ApduBuffIndex),
747 (void *)(p_recv_buf + byte_index),
748 remaining_data_size);
749
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100750 /* Update the read index */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100751 psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
752 remaining_data_size);
753
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100754 } /* else part of if (ps_iso_15693_con->store_length) */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100755
756 /* Remaining size is decremented */
757 ps_iso_15693_con->remaining_size_to_read = (uint8_t)
758 (ps_iso_15693_con->remaining_size_to_read -
759 remaining_data_size);
760
761 if ((psNdefMap->ApduBuffIndex != psNdefMap->ApduBufferSize)
762 && (0 != ps_iso_15693_con->remaining_size_to_read))
763 {
764 ps_iso_15693_con->current_block = (uint16_t)
765 (ps_iso_15693_con->current_block + 1);
766 /* READ again */
767 if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) ||
768 (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) {
769 result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block);
770 }
771 else {
772 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND,
773 NULL, 0);
774 }
775 }
776 else
777 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100778 /* Read completed, EITHER index has reached to the user size
779 OR end of the card is reached
780 update the user data structure with read data size */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100781 *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex;
782 }
783 if (reformatted_buf != NULL) {
784 phOsalNfc_FreeMemory(reformatted_buf);
785 }
786 return result;
787}
788
789static
790NFCSTATUS
791phFriNfc_ISO15693_H_CheckCCBytes (
792 phFriNfc_NdefMap_t *psNdefMap)
793{
794 NFCSTATUS result = NFCSTATUS_SUCCESS;
795 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
796 &(psNdefMap->ISO15693Container);
797 uint8_t recv_index = 0;
798 uint8_t *p_recv_buf = (psNdefMap->SendRecvBuf + 1);
799
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100800 /* expected CC byte : E1 40 "MAX SIZE depends on tag" */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100801 if (ISO15693_CC_MAGIC_BYTE == *p_recv_buf)
802 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100803 /* 0xE1 magic byte found*/
Martijn Coenena6e012a2011-01-13 23:24:24 +0100804 recv_index = (uint8_t)(recv_index + 1);
805 uint8_t tag_major_version = (*(p_recv_buf + recv_index) & ISO15693_MAJOR_VERSION_MASK) >> 6;
806 if (ISO15693_MAPPING_VERSION >= tag_major_version)
807 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100808 /* Correct mapping version found */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100809 switch (*(p_recv_buf + recv_index) & ISO15693_LSB_NIBBLE_MASK)
810 {
811 case ISO15693_RD_WR_PERMISSION:
812 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100813 /* READ/WRITE possible */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100814 psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE;
815 break;
816 }
817
818 case ISO15693_RD_ONLY_PERMISSION:
819 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100820 /* ONLY READ possible, WRITE NOT possible */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100821 psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY;
822 break;
823 }
824
825 default:
826 {
827 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
828 NFCSTATUS_NO_NDEF_SUPPORT);
829 break;
830 }
831 }
832 recv_index = (uint8_t)(recv_index + 1);
833
834 if (!result)
835 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100836 /* Update MAX SIZE */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100837 ps_iso_15693_con->max_data_size = (uint16_t)
838 (*(p_recv_buf + recv_index) *
839 ISO15693_MULT_FACTOR);
840 recv_index = (uint8_t)(recv_index + 1);
841 ps_iso_15693_con->read_capabilities = (*(p_recv_buf + recv_index));
842
843
844 }
845 }
846 else
847 {
848 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
849 NFCSTATUS_NO_NDEF_SUPPORT);
850 }
851 }
852 else
853 {
854 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
855 NFCSTATUS_NO_NDEF_SUPPORT);
856 }
857 return result;
858}
859
860static
861NFCSTATUS
862phFriNfc_ISO15693_H_ProcessCheckNdef (
863 phFriNfc_NdefMap_t *psNdefMap)
864{
865 NFCSTATUS result = NFCSTATUS_SUCCESS;
866 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
867 &(psNdefMap->ISO15693Container);
868 phFriNfc_eChkNdefSeq_t e_chk_ndef_seq = (phFriNfc_eChkNdefSeq_t)
869 psNdefMap->ISO15693Container.ndef_seq;
870
871 uint8_t *p_recv_buf =
872 (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE);
873 uint8_t recv_length = (uint8_t)
874 (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE);
875 uint8_t parse_index = 0;
876 static uint16_t prop_ndef_index = 0;
877 uint8_t *reformatted_buf = (uint8_t*) phOsalNfc_GetMemory(ps_iso_15693_con->max_data_size);
878
879 if (0 == ps_iso_15693_con->current_block)
880 {
881 /* Check CC byte */
882 result = phFriNfc_ISO15693_H_CheckCCBytes (psNdefMap);
883 parse_index = (uint8_t)(parse_index + recv_length);
884 }
885 else if (1 == ps_iso_15693_con->current_block &&
886 (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR))
887 {
888
889 uint8_t reformatted_size = phFriNfc_ISO15693_Reformat_Pageread_Buffer(p_recv_buf, recv_length,
890 reformatted_buf, ps_iso_15693_con->max_data_size);
891 // Skip initial CC bytes
892 p_recv_buf = reformatted_buf + (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK);
893 recv_length = reformatted_size - (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK);
894 }
895 else
896 {
897 /* Propreitary TLVs VALUE can end in between a block,
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100898 so when that block is read, update the parse_index
899 with byte address value */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100900 if (ISO15693_PROP_TLV_V == e_chk_ndef_seq)
901 {
902 parse_index = ps_iso_15693_con->ndef_tlv_type_byte;
903 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
904 }
905 }
906
907 while ((parse_index < recv_length)
908 && (NFCSTATUS_SUCCESS == result)
909 && (ISO15693_NDEF_TLV_V != e_chk_ndef_seq))
910 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100911 /* Parse
912 1. till the received length of the block
913 2. till there is no error during parse
914 3. till LENGTH field of NDEF TLV is found
915 */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100916 switch (e_chk_ndef_seq)
917 {
918 case ISO15693_NDEF_TLV_T:
919 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100920 /* Expected value is 0x03 TYPE identifier
921 of the NDEF TLV */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100922 prop_ndef_index = 0;
923 switch (*(p_recv_buf + parse_index))
924 {
925 case ISO15693_NDEF_TLV_TYPE_ID:
926 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100927 /* Update the data structure with the byte address and
928 the block number */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100929 ps_iso_15693_con->ndef_tlv_type_byte = parse_index;
930 ps_iso_15693_con->ndef_tlv_type_blk =
931 ps_iso_15693_con->current_block;
932 e_chk_ndef_seq = ISO15693_NDEF_TLV_L;
Martijn Coenena6e012a2011-01-13 23:24:24 +0100933
934 break;
935 }
936
937 case ISO15693_NULL_TLV_ID:
938 {
939 /* Dont do any thing, go to next byte */
940 break;
941 }
942
943 case ISO15693_PROP_TLV_ID:
944 {
945 /* Move the sequence to find the length
946 of the proprietary TLV */
947 e_chk_ndef_seq = ISO15693_PROP_TLV_L;
948 break;
949 }
950
951 default:
952 {
953 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
954 NFCSTATUS_NO_NDEF_SUPPORT);
955 break;
956 }
957 } /* switch (*(p_recv_buf + parse_index)) */
958 break;
959 }
960
961 case ISO15693_PROP_TLV_L:
962 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100963 /* Length field of the proprietary TLV */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100964 switch (prop_ndef_index)
965 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100966 /* Length field can have 1 or 3 bytes depending
967 on the data size, so check for each index byte */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100968 case 0:
969 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100970 /* 1st index of the length field of the TLV */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100971 if (0 == *(p_recv_buf + parse_index))
972 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100973 /* LENGTH is 0, not possible, so error */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100974 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
975 NFCSTATUS_NO_NDEF_SUPPORT);
976 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
977 }
978 else
979 {
Martijn Coenena6e012a2011-01-13 23:24:24 +0100980 if (ISO15693_THREE_BYTE_LENGTH_ID ==
981 *(p_recv_buf + parse_index))
982 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100983 /* 3 byte LENGTH field identified, so increment the
984 index, so next time 2nd byte is parsed */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100985 prop_ndef_index = (uint8_t)(prop_ndef_index + 1);
986 }
987 else
988 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +0100989 /* 1 byte LENGTH field identified, so "static"
990 index is set to 0 and actual ndef size is
991 copied to the data structure
992 */
Martijn Coenena6e012a2011-01-13 23:24:24 +0100993 ps_iso_15693_con->actual_ndef_size =
994 *(p_recv_buf + parse_index);
995 e_chk_ndef_seq = ISO15693_PROP_TLV_V;
996 prop_ndef_index = 0;
997 }
998 }
999 break;
1000 }
1001
1002 case 1:
1003 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001004 /* 2nd index of the LENGTH field that is MSB of the length,
1005 so the length is left shifted by 8 */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001006 ps_iso_15693_con->actual_ndef_size = (uint16_t)
1007 (*(p_recv_buf + parse_index) <<
1008 ISO15693_BTYE_SHIFT);
1009 prop_ndef_index = (uint8_t)(prop_ndef_index + 1);
1010 break;
1011 }
1012
1013 case 2:
1014 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001015 /* 3rd index of the LENGTH field that is LSB of the length,
1016 so the length ORed with the previously stored size */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001017 ps_iso_15693_con->actual_ndef_size = (uint16_t)
1018 (ps_iso_15693_con->actual_ndef_size |
1019 *(p_recv_buf + parse_index));
1020
1021 e_chk_ndef_seq = ISO15693_PROP_TLV_V;
1022 prop_ndef_index = 0;
1023 break;
1024 }
1025
1026 default:
1027 {
1028 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1029 NFCSTATUS_INVALID_DEVICE_REQUEST);
1030 break;
1031 }
1032 } /* switch (prop_ndef_index) */
1033
1034 if ((ISO15693_PROP_TLV_V == e_chk_ndef_seq)
1035 && (ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size,
1036 ps_iso_15693_con->current_block, parse_index)
1037 <= ps_iso_15693_con->actual_ndef_size))
1038 {
1039 /* Check for the length field value has not exceeded the card size,
1040 if size is exceeded or then return error */
1041 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
1042 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1043 NFCSTATUS_NO_NDEF_SUPPORT);
1044 }
1045 else
1046 {
1047 uint16_t prop_byte_addr = 0;
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001048
Martijn Coenena6e012a2011-01-13 23:24:24 +01001049 /* skip the proprietary TLVs value field */
1050 prop_byte_addr = (uint16_t)
1051 ((ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK) +
1052 parse_index + ps_iso_15693_con->actual_ndef_size);
1053
1054 ps_iso_15693_con->ndef_tlv_type_byte = (uint8_t)(prop_byte_addr %
1055 ISO15693_BYTES_PER_BLOCK);
1056 ps_iso_15693_con->ndef_tlv_type_blk = (uint16_t)(prop_byte_addr /
1057 ISO15693_BYTES_PER_BLOCK);
1058 if (parse_index + ps_iso_15693_con->actual_ndef_size >=
1059 recv_length)
1060 {
1061 parse_index = (uint8_t)recv_length;
1062 }
1063 else
1064 {
1065 parse_index = (uint8_t)(parse_index +
1066 ps_iso_15693_con->actual_ndef_size);
1067 }
1068
1069 }
1070 break;
1071 } /* case ISO15693_PROP_TLV_L: */
1072
1073 case ISO15693_PROP_TLV_V:
1074 {
1075 uint8_t remaining_length = (uint8_t)(recv_length -
1076 parse_index);
1077
1078 if ((ps_iso_15693_con->actual_ndef_size - prop_ndef_index)
1079 > remaining_length)
1080 {
1081 parse_index = (uint8_t)(parse_index + remaining_length);
1082 prop_ndef_index = (uint8_t)(prop_ndef_index + remaining_length);
1083 }
1084 else if ((ps_iso_15693_con->actual_ndef_size - prop_ndef_index)
1085 == remaining_length)
1086 {
1087 parse_index = (uint8_t)(parse_index + remaining_length);
1088 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
1089 prop_ndef_index = 0;
1090 }
1091 else
1092 {
1093 parse_index = (uint8_t)(parse_index +
1094 (ps_iso_15693_con->actual_ndef_size -
1095 prop_ndef_index));
1096 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
1097 prop_ndef_index = 0;
1098 }
1099 break;
1100 } /* case ISO15693_PROP_TLV_V: */
1101
1102 case ISO15693_NDEF_TLV_L:
1103 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001104 /* Length field of the NDEF TLV */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001105 switch (prop_ndef_index)
1106 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001107 /* Length field can have 1 or 3 bytes depending
1108 on the data size, so check for each index byte */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001109 case 0:
1110 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001111 /* 1st index of the length field of the TLV */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001112 if (0 == *(p_recv_buf + parse_index))
1113 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001114 /* LENGTH is 0, card is in INITILIASED STATE */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001115 e_chk_ndef_seq = ISO15693_NDEF_TLV_V;
1116 ps_iso_15693_con->actual_ndef_size = 0;
1117 }
1118 else
1119 {
1120 prop_ndef_index = (uint8_t)(prop_ndef_index + 1);
1121
1122 if (ISO15693_THREE_BYTE_LENGTH_ID ==
1123 *(p_recv_buf + parse_index))
1124 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001125 /* At present no CARD supports more than 255 bytes,
1126 so error is returned */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001127 prop_ndef_index = (uint8_t)(prop_ndef_index + 1);
1128 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1129 NFCSTATUS_NO_NDEF_SUPPORT);
1130 prop_ndef_index = 0;
1131 }
1132 else
1133 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001134 /* 1 byte LENGTH field identified, so "static"
1135 index is set to 0 and actual ndef size is
1136 copied to the data structure
1137 */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001138 ps_iso_15693_con->actual_ndef_size =
1139 *(p_recv_buf + parse_index);
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001140 /* next values are the DATA field of the NDEF TLV */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001141 e_chk_ndef_seq = ISO15693_NDEF_TLV_V;
1142 prop_ndef_index = 0;
1143 }
1144 }
1145 break;
1146 }
1147
1148 case 1:
1149 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001150 /* 2nd index of the LENGTH field that is MSB of the length,
1151 so the length is left shifted by 8 */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001152 ps_iso_15693_con->actual_ndef_size = (uint16_t)
1153 (*(p_recv_buf + parse_index) <<
1154 ISO15693_BTYE_SHIFT);
1155 prop_ndef_index = (uint8_t)(prop_ndef_index + 1);
1156 break;
1157 }
1158
1159 case 2:
1160 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001161 /* 3rd index of the LENGTH field that is LSB of the length,
1162 so the length ORed with the previously stored size */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001163 ps_iso_15693_con->actual_ndef_size = (uint16_t)
1164 (ps_iso_15693_con->actual_ndef_size |
1165 *(p_recv_buf + parse_index));
1166
1167 e_chk_ndef_seq = ISO15693_NDEF_TLV_V;
1168 prop_ndef_index = 0;
1169 break;
1170 }
1171
1172 default:
1173 {
1174 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1175 NFCSTATUS_INVALID_DEVICE_REQUEST);
1176 break;
1177 }
1178 } /* switch (prop_ndef_index) */
1179
1180 if ((ISO15693_NDEF_TLV_V == e_chk_ndef_seq)
1181 && (ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size,
1182 /* parse_index + 1 is done because the data starts from the next index.
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001183 "MOD" operation is used to know that parse_index >
Martijn Coenena6e012a2011-01-13 23:24:24 +01001184 ISO15693_BYTES_PER_BLOCK, then block shall be incremented
1185 */
1186 (((parse_index + 1) % ISO15693_BYTES_PER_BLOCK) ?
1187 ps_iso_15693_con->current_block :
1188 ps_iso_15693_con->current_block + 1), ((parse_index + 1) %
1189 ISO15693_BYTES_PER_BLOCK))
1190 < ps_iso_15693_con->actual_ndef_size))
1191 {
1192 /* Check for the length field value has not exceeded the card size */
1193 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
1194 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1195 NFCSTATUS_NO_NDEF_SUPPORT);
1196 }
1197 else
1198 {
1199 psNdefMap->CardState = (uint8_t)
1200 ((PH_NDEFMAP_CARD_STATE_READ_ONLY
1201 == psNdefMap->CardState) ?
1202 PH_NDEFMAP_CARD_STATE_READ_ONLY :
1203 ((ps_iso_15693_con->actual_ndef_size) ?
1204 PH_NDEFMAP_CARD_STATE_READ_WRITE :
1205 PH_NDEFMAP_CARD_STATE_INITIALIZED));
1206 }
1207 break;
1208 } /* case ISO15693_NDEF_TLV_L: */
1209
1210 case ISO15693_NDEF_TLV_V:
1211 {
1212 break;
1213 }
1214
1215 default:
1216 {
1217 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1218 NFCSTATUS_INVALID_DEVICE_REQUEST);
1219 break;
1220 }
1221 } /* switch (e_chk_ndef_seq) */
1222 parse_index = (uint8_t)(parse_index + 1);
1223 } /* while ((parse_index < recv_length)
1224 && (NFCSTATUS_SUCCESS == result)
1225 && (ISO15693_NDEF_TLV_V != e_chk_ndef_seq)) */
1226
1227 if (result)
1228 {
1229 /* Error returned while parsing, so STOP read */
1230 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
1231 prop_ndef_index = 0;
1232 }
1233 else if (ISO15693_NDEF_TLV_V != e_chk_ndef_seq)
1234 {
1235 /* READ again */
1236 if (ISO15693_PROP_TLV_V != e_chk_ndef_seq)
1237 {
1238 ps_iso_15693_con->current_block = (uint16_t)
1239 (ps_iso_15693_con->current_block + 1);
1240 }
1241 else
1242 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001243 /* Proprietary TLV detected, so skip the proprietary blocks */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001244 ps_iso_15693_con->current_block = ps_iso_15693_con->ndef_tlv_type_blk;
1245 }
1246
1247 uint32_t remaining_size = ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size,
1248 ps_iso_15693_con->current_block, 0);
1249 if (remaining_size > 0)
1250 {
1251 if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) ||
1252 (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) {
1253 result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block);
1254 } else {
1255 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND,
1256 NULL, 0);
1257 }
1258 }
1259 else
1260 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001261 /* End of card reached, error no NDEF information found */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001262 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
1263 prop_ndef_index = 0;
1264 /* Error, no size to parse */
1265 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1266 NFCSTATUS_NO_NDEF_SUPPORT);
1267 }
1268
1269 }
1270 else
1271 {
1272 /* Successful read with proper NDEF information updated */
1273 prop_ndef_index = 0;
1274 e_chk_ndef_seq = ISO15693_NDEF_TLV_T;
1275 psNdefMap->CardType = (uint8_t)PH_FRINFC_NDEFMAP_ISO15693_CARD;
1276 }
1277
1278 psNdefMap->ISO15693Container.ndef_seq = (uint8_t)e_chk_ndef_seq;
1279
1280 if (reformatted_buf != NULL) {
1281 phOsalNfc_FreeMemory(reformatted_buf);
1282 }
1283 return result;
1284}
1285
1286static
1287void
1288phFriNfc_ISO15693_H_Complete (
1289 phFriNfc_NdefMap_t *psNdefMap,
1290 NFCSTATUS Status)
1291{
1292 /* set the state back to the RESET_INIT state*/
1293 psNdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT;
1294
1295 /* set the completion routine*/
1296 psNdefMap->CompletionRoutine[psNdefMap->ISO15693Container.cr_index].
1297 CompletionRoutine (psNdefMap->CompletionRoutine->Context, Status);
1298}
1299
1300#ifdef FRINFC_READONLY_NDEF
1301
1302static
1303NFCSTATUS
1304phFriNfc_ISO15693_H_ProcessReadOnly (
1305 phFriNfc_NdefMap_t *psNdefMap)
1306{
1307 NFCSTATUS result = NFCSTATUS_SUCCESS;
1308 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
1309 &(psNdefMap->ISO15693Container);
1310 phFriNfc_eRONdefSeq_t e_ro_ndef_seq = (phFriNfc_eRONdefSeq_t)
1311 ps_iso_15693_con->ndef_seq;
1312 uint8_t *p_recv_buf = (psNdefMap->SendRecvBuf +
1313 ISO15693_EXTRA_RESP_BYTE);
1314 uint8_t recv_length = (uint8_t)(*psNdefMap->SendRecvLength -
1315 ISO15693_EXTRA_RESP_BYTE);
1316 uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0};
1317
1318 switch (e_ro_ndef_seq)
1319 {
1320 case ISO15693_RD_BEFORE_WR_CC:
1321 {
1322 if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length)
1323 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001324 result = phFriNfc_ISO15693_H_CheckCCBytes (psNdefMap);
1325 /* Check CC bytes and also the card state for READ ONLY,
1326 if the card is already read only, then dont continue with
1327 next operation */
1328 if ((PH_NDEFMAP_CARD_STATE_READ_ONLY != psNdefMap->CardState)
1329 && (!result))
1330 {
1331 /* CC byte read successful */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001332 (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf,
1333 sizeof (a_write_buf));
1334
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001335 /* Change the read write access to read only */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001336 *(a_write_buf + ISO15693_RW_BTYE_INDEX) = (uint8_t)
1337 (*(a_write_buf + ISO15693_RW_BTYE_INDEX) |
1338 ISO15693_CC_READ_ONLY_MASK);
1339
1340 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001341 ISO15693_WRITE_COMMAND, a_write_buf,
Martijn Coenena6e012a2011-01-13 23:24:24 +01001342 sizeof (a_write_buf));
1343
1344 e_ro_ndef_seq = ISO15693_WRITE_CC;
1345 }
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001346 }
Martijn Coenena6e012a2011-01-13 23:24:24 +01001347 break;
1348 }
1349
1350 case ISO15693_WRITE_CC:
1351 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001352 /* Write to CC is successful. */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001353 e_ro_ndef_seq = ISO15693_LOCK_BLOCK;
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001354 /* Start the lock block command to lock the blocks */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001355 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
1356 ISO15693_LOCK_BLOCK_CMD, NULL, 0);
1357 break;
1358 }
1359
1360 case ISO15693_LOCK_BLOCK:
1361 {
1362 if (ps_iso_15693_con->current_block ==
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001363 ((ps_iso_15693_con->max_data_size / ISO15693_BYTES_PER_BLOCK) -
1364 1))
Martijn Coenena6e012a2011-01-13 23:24:24 +01001365 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001366 /* End of card reached, READ ONLY successful */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001367 }
1368 else
1369 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001370 /* current block is incremented */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001371 ps_iso_15693_con->current_block = (uint16_t)
1372 (ps_iso_15693_con->current_block + 1);
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001373 /* Lock the current block */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001374 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
1375 ISO15693_LOCK_BLOCK_CMD, NULL, 0);
1376 }
1377 break;
1378 }
1379
1380 default:
1381 {
1382 break;
1383 }
1384 }
1385
1386 ps_iso_15693_con->ndef_seq = (uint8_t)e_ro_ndef_seq;
1387 return result;
1388}
1389
1390#endif /* #ifdef FRINFC_READONLY_NDEF */
1391/************************** END static functions definition *********************/
1392
1393/************************** START external functions *********************/
1394
1395NFCSTATUS
1396phFriNfc_ISO15693_ChkNdef (
1397 phFriNfc_NdefMap_t *psNdefMap)
1398{
1399 NFCSTATUS result = NFCSTATUS_SUCCESS;
1400 phHal_sIso15693Info_t *ps_iso_15693_info =
1401 &(psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info);
1402
1403 /* Update the previous operation with current operation.
1404 This becomes the previous operation after this execution */
1405 psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE;
1406 /* Update the CR index to know from which operation completion
1407 routine has to be called */
1408 psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_CHK_NDEF;
1409 /* State update */
1410 psNdefMap->State = ISO15693_CHECK_NDEF;
1411 /* Reset the NDEF sequence */
1412 psNdefMap->ISO15693Container.ndef_seq = 0;
1413 psNdefMap->ISO15693Container.current_block = 0;
1414 psNdefMap->ISO15693Container.actual_ndef_size = 0;
1415 psNdefMap->ISO15693Container.ndef_tlv_type_blk = 0;
1416 psNdefMap->ISO15693Container.ndef_tlv_type_byte = 0;
1417 psNdefMap->ISO15693Container.store_length = 0;
1418 psNdefMap->ISO15693Container.remaining_size_to_read = 0;
1419 psNdefMap->ISO15693Container.read_capabilities = 0;
1420
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001421 if ((ISO15693_UIDBYTE_6_VALUE ==
1422 ps_iso_15693_info->Uid[ISO15693_UID_BYTE_6])
1423 && (ISO15693_UIDBYTE_7_VALUE ==
1424 ps_iso_15693_info->Uid[ISO15693_UID_BYTE_7]))
1425 {
1426 /* Check if the card is manufactured by NXP (6th byte
1427 index of UID value = 0x04 and the
1428 last byte i.e., 7th byte of UID is 0xE0, only then the card detected
1429 is NDEF compliant */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001430 switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_5])
1431 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001432 /* Check for supported tags, by checking the 5th byte index of UID */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001433 case ISO15693_UIDBYTE_5_VALUE_SLI_X:
1434 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001435 /* ISO 15693 card type is ICODE SLI
1436 so maximum size is 112 */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001437 psNdefMap->ISO15693Container.max_data_size =
1438 ISO15693_SL2_S2002_ICS20;
1439 break;
1440 }
1441
1442 case ISO15693_UIDBYTE_5_VALUE_SLI_X_S:
1443 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001444 /* ISO 15693 card type is ICODE SLI/X S
1445 so maximum size depends on the 4th UID byte index */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001446 switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_4])
1447 {
1448 case ISO15693_UIDBYTE_4_VALUE_SLI_X_S:
1449 case ISO15693_UIDBYTE_4_VALUE_SLI_X_SHC:
1450 case ISO15693_UIDBYTE_4_VALUE_SLI_X_SY:
1451 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001452 /* Supported tags are with value (4th byte UID index)
1453 of 0x00, 0x80 and 0x40
1454 For these cards max size is 160 bytes */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001455 psNdefMap->ISO15693Container.max_data_size =
1456 ISO15693_SL2_S5302_ICS53_ICS54;
1457 break;
1458 }
1459
1460 default:
1461 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001462 /* Tag not supported */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001463 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1464 NFCSTATUS_INVALID_DEVICE_REQUEST);
1465 break;
1466 }
1467 }
1468 break;
1469 }
1470
1471 case ISO15693_UIDBYTE_5_VALUE_SLI_X_L:
1472 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001473 /* ISO 15693 card type is ICODE SLI/X L
1474 so maximum size depends on the 4th UID byte index */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001475 switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_4])
1476 {
1477 case ISO15693_UIDBYTE_4_VALUE_SLI_X_L:
1478 case ISO15693_UIDBYTE_4_VALUE_SLI_X_LHC:
1479 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001480 /* Supported tags are with value (4th byte UID index)
1481 of 0x00 and 0x80
1482 For these cards max size is 32 bytes */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001483 psNdefMap->ISO15693Container.max_data_size =
1484 ISO15693_SL2_S5002_ICS50_ICS51;
1485 break;
1486 }
1487
1488 default:
1489 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001490 /* Tag not supported */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001491 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1492 NFCSTATUS_INVALID_DEVICE_REQUEST);
1493 break;
1494 }
1495 }
1496 break;
1497 }
1498
1499 default:
1500 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001501 /* Tag not supported */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001502 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1503 NFCSTATUS_INVALID_DEVICE_REQUEST);
1504 break;
1505 }
1506 }
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001507 }
1508 else
1509 {
1510 /* Tag not supported */
1511 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1512 NFCSTATUS_INVALID_DEVICE_REQUEST);
1513 }
Martijn Coenena6e012a2011-01-13 23:24:24 +01001514
1515 if (!result)
1516 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001517 /* Start reading the data */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001518 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND,
1519 NULL, 0);
1520 }
1521
1522
1523 return result;
1524}
1525
1526NFCSTATUS
1527phFriNfc_ISO15693_RdNdef (
1528 phFriNfc_NdefMap_t *psNdefMap,
1529 uint8_t *pPacketData,
1530 uint32_t *pPacketDataLength,
1531 uint8_t Offset)
1532{
1533 NFCSTATUS result = NFCSTATUS_SUCCESS;
1534 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
1535 &(psNdefMap->ISO15693Container);
1536
1537 /* Update the previous operation with current operation.
1538 This becomes the previous operation after this execution */
1539 psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE;
1540 /* Update the CR index to know from which operation completion
1541 routine has to be called */
1542 psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_RD_NDEF;
1543 /* State update */
1544 psNdefMap->State = ISO15693_READ_NDEF;
1545 /* Copy user buffer to the context */
1546 psNdefMap->ApduBuffer = pPacketData;
1547 /* Copy user length to the context */
1548 psNdefMap->ApduBufferSize = *pPacketDataLength;
1549 /* Update the user memory size to a context variable */
1550 psNdefMap->NumOfBytesRead = pPacketDataLength;
1551 /* Number of bytes read from the card is zero.
1552 This variable returns the number of bytes read
1553 from the card. */
1554 *psNdefMap->NumOfBytesRead = 0;
1555 /* Index to know the length read */
1556 psNdefMap->ApduBuffIndex = 0;
1557 /* Store the offset in the context */
1558 psNdefMap->Offset = Offset;
1559
1560 if ((!ps_iso_15693_con->remaining_size_to_read)
1561 && (!psNdefMap->Offset))
1562 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001563 /* Entire data is already read from the card.
1564 There is no data to give */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001565 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1566 NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
1567 }
1568 else if (0 == ps_iso_15693_con->actual_ndef_size)
1569 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001570 /* Card is NDEF, but no data in the card. */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001571 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1572 NFCSTATUS_READ_FAILED);
1573 }
1574 else if (PH_NDEFMAP_CARD_STATE_INITIALIZED == psNdefMap->CardState)
1575 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001576 /* Card is NDEF, but no data in the card. */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001577 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1578 NFCSTATUS_READ_FAILED);
1579 }
1580 else if (psNdefMap->Offset)
1581 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001582 /* BEGIN offset, so reset the remaining read size and
1583 also the curretn block */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001584 ps_iso_15693_con->remaining_size_to_read =
1585 ps_iso_15693_con->actual_ndef_size;
1586 ps_iso_15693_con->current_block =
1587 ISO15693_GET_VALUE_FIELD_BLOCK_NO(
1588 ps_iso_15693_con->ndef_tlv_type_blk,
1589 ps_iso_15693_con->ndef_tlv_type_byte,
1590 ps_iso_15693_con->actual_ndef_size);
1591
1592 // Check capabilities
1593 if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) ||
1594 (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) {
1595 result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block);
1596 } else {
1597 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND,
1598 NULL, 0);
1599 }
1600 }
1601 else
1602 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001603 /* CONTINUE offset */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001604 if (ps_iso_15693_con->store_length > 0)
1605 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001606 /* Previous read had extra bytes, so data is stored, so give that take
1607 that data from store. If more data is required, then read remaining bytes */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001608 result = phFriNfc_ISO15693_H_ProcessReadNdef (psNdefMap);
1609 }
1610 else
1611 {
1612 ps_iso_15693_con->current_block = (uint16_t)
1613 (ps_iso_15693_con->current_block + 1);
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001614 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
1615 ISO15693_READ_COMMAND, NULL, 0);
Martijn Coenena6e012a2011-01-13 23:24:24 +01001616 }
1617 }
1618
1619 return result;
1620}
1621
1622static
1623NFCSTATUS
1624phFriNfc_ReadRemainingInMultiple (
1625 phFriNfc_NdefMap_t *psNdefMap,
1626 uint32_t startBlock)
1627{
1628 NFCSTATUS result = NFCSTATUS_FAILED;
1629 phFriNfc_ISO15693Cont_t *ps_iso_15693_con = &(psNdefMap->ISO15693Container);
1630
1631 uint32_t remaining_size = ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size,
1632 startBlock, 0);
1633 // Check capabilities
1634 if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) {
1635 // Multi-page read command
1636 uint8_t mbread[1];
1637 mbread[0] = (remaining_size / ISO15693_BYTES_PER_BLOCK) - 1;
1638 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_MULTIPLE_COMMAND,
1639 mbread, 1);
1640 } else if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR) {
1641 uint32_t page = 0;
1642 uint32_t pagesToRead = (remaining_size / ISO15693_BYTES_PER_BLOCK / 4) - 1;
1643 if ((remaining_size % (ISO15693_BYTES_PER_BLOCK * ISO15693_BLOCKS_PER_PAGE)) != 0) {
1644 pagesToRead++;
1645 }
1646 result = phFriNfc_ISO15693_H_Inventory_Page_Read (psNdefMap, ICODE_INVENTORY_PAGEREAD_COMMAND,
1647 page, pagesToRead);
1648 // Inventory
1649 } else {
1650 result = NFCSTATUS_FAILED;
1651 }
1652 return result;
1653}
1654
1655NFCSTATUS
1656phFriNfc_ISO15693_WrNdef (
1657 phFriNfc_NdefMap_t *psNdefMap,
1658 uint8_t *pPacketData,
1659 uint32_t *pPacketDataLength,
1660 uint8_t Offset)
1661{
1662 NFCSTATUS result = NFCSTATUS_SUCCESS;
1663 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
1664 &(psNdefMap->ISO15693Container);
1665 uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0};
1666
1667 /* Update the previous operation with current operation.
1668 This becomes the previous operation after this execution */
1669 psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE;
1670 /* Update the CR index to know from which operation completion
1671 routine has to be called */
1672 psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_WR_NDEF;
1673 /* State update */
1674 psNdefMap->State = ISO15693_WRITE_NDEF;
1675 /* Copy user buffer to the context */
1676 psNdefMap->ApduBuffer = pPacketData;
1677 /* Copy user length to the context */
1678 psNdefMap->ApduBufferSize = *pPacketDataLength;
1679 /* Update the user memory size to a context variable */
1680 psNdefMap->NumOfBytesRead = pPacketDataLength;
1681 /* Number of bytes written to the card is zero.
1682 This variable returns the number of bytes written
1683 to the card. */
1684 *psNdefMap->WrNdefPacketLength = 0;
1685 /* Index to know the length read */
1686 psNdefMap->ApduBuffIndex = 0;
1687 /* Store the offset in the context */
1688 psNdefMap->Offset = Offset;
1689
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001690 /* Set the current block correctly to write the length field to 0 */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001691 ps_iso_15693_con->current_block =
1692 ISO15693_GET_LEN_FIELD_BLOCK_NO(
1693 ps_iso_15693_con->ndef_tlv_type_blk,
1694 ps_iso_15693_con->ndef_tlv_type_byte,
1695 *pPacketDataLength);
1696
1697 if (ISO15693_GET_LEN_FIELD_BYTE_NO(
1698 ps_iso_15693_con->ndef_tlv_type_blk,
1699 ps_iso_15693_con->ndef_tlv_type_byte,
1700 *pPacketDataLength))
1701 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001702 /* Check the byte address to write. If length byte address is in between or
1703 is the last byte of the block, then READ before write
1704 reason, write should not corrupt other data
1705 */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001706 ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_RD_BEFORE_WR_NDEF_L_0;
1707 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
1708 ISO15693_READ_COMMAND, NULL, 0);
1709 }
1710 else
1711 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001712 /* If length byte address is at the beginning of the block then WRITE
1713 length field to 0 and as also write user DATA */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001714 ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_WRITE_DATA;
1715
1716 /* Length is made 0x00 */
1717 *a_write_buf = 0x00;
1718
1719 /* Write remaining data */
1720 (void)memcpy ((void *)(a_write_buf + 1),
1721 (void *)psNdefMap->ApduBuffer,
1722 (ISO15693_BYTES_PER_BLOCK - 1));
1723
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001724 /* Write data */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001725 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
1726 ISO15693_WRITE_COMMAND,
1727 a_write_buf, ISO15693_BYTES_PER_BLOCK);
1728
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001729 /* Increment the index to keep track of bytes sent for write */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001730 psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex
1731 + (ISO15693_BYTES_PER_BLOCK - 1));
1732 }
1733
1734 return result;
1735}
1736
1737#ifdef FRINFC_READONLY_NDEF
1738
1739NFCSTATUS
1740phFriNfc_ISO15693_ConvertToReadOnly (
1741 phFriNfc_NdefMap_t *psNdefMap)
1742{
1743 NFCSTATUS result = NFCSTATUS_SUCCESS;
1744 phFriNfc_ISO15693Cont_t *ps_iso_15693_con =
1745 &(psNdefMap->ISO15693Container);
1746
1747 psNdefMap->State = ISO15693_READ_ONLY_NDEF;
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001748 /* READ CC bytes */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001749 ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_RD_BEFORE_WR_CC;
1750 ps_iso_15693_con->current_block = 0;
1751
1752 result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap,
1753 ISO15693_READ_COMMAND, NULL, 0);
1754
1755 return result;
1756}
1757
1758#endif /* #ifdef FRINFC_READONLY_NDEF */
1759
1760
1761void
1762phFriNfc_ISO15693_Process (
1763 void *pContext,
1764 NFCSTATUS Status)
1765{
1766 phFriNfc_NdefMap_t *psNdefMap =
1767 (phFriNfc_NdefMap_t *)pContext;
1768
1769 if ((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER))
1770 {
1771 switch (psNdefMap->State)
1772 {
1773 case ISO15693_CHECK_NDEF:
1774 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001775 /* State = CHECK NDEF in progress */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001776 Status = phFriNfc_ISO15693_H_ProcessCheckNdef (psNdefMap);
1777 break;
1778 }
1779
1780 case ISO15693_READ_NDEF:
1781 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001782 /* State = READ NDEF in progress */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001783 Status = phFriNfc_ISO15693_H_ProcessReadNdef (psNdefMap);
1784 break;
1785 }
1786
1787 case ISO15693_WRITE_NDEF:
1788 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001789 /* State = WRITE NDEF in progress */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001790 Status = phFriNfc_ISO15693_H_ProcessWriteNdef (psNdefMap);
1791 break;
1792 }
1793
1794#ifdef FRINFC_READONLY_NDEF
1795 case ISO15693_READ_ONLY_NDEF:
1796 {
Martijn Coenen4f3ef022011-01-20 01:27:17 +01001797 /* State = RAD ONLY NDEF in progress */
Martijn Coenena6e012a2011-01-13 23:24:24 +01001798 Status = phFriNfc_ISO15693_H_ProcessReadOnly (psNdefMap);
1799 break;
1800 }
1801#endif /* #ifdef FRINFC_READONLY_NDEF */
1802
1803 default:
1804 {
1805 break;
1806 }
1807 }
1808 }
1809
1810 /* Call for the Completion Routine*/
1811 if (NFCSTATUS_PENDING != Status)
1812 {
1813 phFriNfc_ISO15693_H_Complete(psNdefMap, Status);
1814 }
1815}
1816
1817/************************** END external functions *********************/
1818
1819#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */