Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1 | /* |
Nick Pelly | 34ff48f | 2011-06-27 09:01:51 -0700 | [diff] [blame] | 2 | * |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 3 | * 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 | |
| 46 | typedef 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 | |
| 56 | typedef 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 | |
| 67 | typedef 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 87 | #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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 95 | |
| 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 |
| 129 | CHECK 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 |
| 152 | Magic 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 170 | #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. |
| 206 | Inputs are |
| 207 | 1. maximum data size |
| 208 | 2. block number |
| 209 | 3. 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 214 | (((byte_addr + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) > \ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 215 | (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 *********************/ |
| 226 | static |
| 227 | NFCSTATUS |
| 228 | phFriNfc_ISO15693_H_ProcessReadOnly ( |
| 229 | phFriNfc_NdefMap_t *psNdefMap); |
| 230 | |
| 231 | static |
| 232 | NFCSTATUS |
| 233 | phFriNfc_ISO15693_H_ProcessWriteNdef ( |
| 234 | phFriNfc_NdefMap_t *psNdefMap); |
| 235 | |
| 236 | static |
| 237 | NFCSTATUS |
| 238 | phFriNfc_ISO15693_H_ProcessReadNdef ( |
| 239 | phFriNfc_NdefMap_t *psNdefMap); |
| 240 | |
| 241 | static |
| 242 | NFCSTATUS |
| 243 | phFriNfc_ISO15693_H_ProcessCheckNdef ( |
| 244 | phFriNfc_NdefMap_t *psNdefMap); |
| 245 | |
| 246 | static |
| 247 | void |
| 248 | phFriNfc_ISO15693_H_Complete ( |
| 249 | phFriNfc_NdefMap_t *psNdefMap, |
| 250 | NFCSTATUS Status); |
| 251 | |
| 252 | static |
| 253 | NFCSTATUS |
| 254 | phFriNfc_ISO15693_H_ReadWrite ( |
| 255 | phFriNfc_NdefMap_t *psNdefMap, |
| 256 | uint8_t command, |
| 257 | uint8_t *p_data, |
| 258 | uint8_t data_length); |
| 259 | |
| 260 | static |
| 261 | NFCSTATUS |
| 262 | phFriNfc_ReadRemainingInMultiple ( |
| 263 | phFriNfc_NdefMap_t *psNdefMap, |
| 264 | uint32_t startBlock); |
| 265 | |
| 266 | /************************** END static functions declaration *********************/ |
| 267 | |
| 268 | /************************** START static functions definition *********************/ |
| 269 | |
| 270 | static |
| 271 | NFCSTATUS |
| 272 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 290 | /* L byte is read */ |
| 291 | p_recv_buf = (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 292 | recv_length = (uint8_t) |
| 293 | (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE); |
| 294 | |
| 295 | if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) |
| 296 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 297 | /* Response length is correct */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 298 | uint8_t byte_index = 0; |
| 299 | |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 300 | /* Copy the recevied buffer */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 301 | (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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 309 | /* Writing length field to 0, Update length field to 0 */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 310 | *(a_write_buf + byte_index) = 0x00; |
| 311 | |
| 312 | if ((ISO15693_BYTES_PER_BLOCK - 1) != byte_index) |
| 313 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 314 | /* User data is updated in the buffer */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 315 | byte_index = (uint8_t)(byte_index + 1); |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 316 | /* Block number shall be udate */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 317 | 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 327 | (void)memcpy ((void *)(a_write_buf + byte_index), |
| 328 | (void *)(psNdefMap->ApduBuffer + |
| 329 | psNdefMap->ApduBuffIndex), remaining_size); |
| 330 | |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 331 | /* Write index updated */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 332 | psNdefMap->ApduBuffIndex = (uint8_t)(psNdefMap->ApduBuffIndex + |
| 333 | remaining_size); |
| 334 | } |
| 335 | |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 336 | /* After this write, user data can be written. |
| 337 | Update the sequence accordingly */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 338 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 430 | if (((0 == psNdefMap->ApduBuffIndex) |
| 431 | || (*psNdefMap->WrNdefPacketLength != psNdefMap->ApduBuffIndex)) |
| 432 | && (!result)) |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 433 | { |
| 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 | |
| 451 | static |
| 452 | NFCSTATUS |
| 453 | phFriNfc_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 | |
| 512 | static |
| 513 | NFCSTATUS |
| 514 | phFriNfc_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 | |
| 576 | static |
| 577 | NFCSTATUS |
| 578 | phFriNfc_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 | |
| 613 | static |
| 614 | NFCSTATUS |
| 615 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 638 | /* Continue Offset option selected |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 639 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 649 | (void *)ps_iso_15693_con->store_read_data, |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 650 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 670 | /* As stored data is more than the user expected data. So store |
| 671 | the remaining bytes again into the data structure */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 672 | (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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 679 | |
| 680 | ps_iso_15693_con->store_length = (uint8_t) |
| 681 | (ps_iso_15693_con->store_length - remaining_data_size); |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 682 | } |
| 683 | } /* if (ps_iso_15693_con->store_length) */ |
| 684 | else |
| 685 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 686 | /* Data is read from the card. */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 687 | uint8_t byte_index = 0; |
| 688 | |
| 689 | remaining_data_size = ps_iso_15693_con->remaining_size_to_read; |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 690 | |
| 691 | /* Check if the block number is to read the first VALUE field */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 692 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 708 | remaining_data_size = (uint8_t) |
| 709 | (recv_length - byte_index); |
| 710 | /* user input is less than the remaining card size */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 711 | if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 712 | < (uint16_t)remaining_data_size) |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 713 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 714 | /* user data required is less than the data read */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 715 | remaining_data_size = (uint8_t)(psNdefMap->ApduBufferSize - |
| 716 | psNdefMap->ApduBuffIndex); |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 717 | |
| 718 | if (0 != (recv_length - (byte_index + |
| 719 | remaining_data_size))) |
| 720 | { |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 721 | /* Store the data for the continue read option */ |
| 722 | (void)memcpy ((void *)ps_iso_15693_con->store_read_data, |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 723 | (void *)(p_recv_buf + (byte_index + |
| 724 | remaining_data_size)), |
| 725 | (recv_length - (byte_index + |
| 726 | remaining_data_size))); |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 727 | |
| 728 | ps_iso_15693_con->store_length = (uint8_t) |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 729 | (recv_length - (byte_index + |
| 730 | remaining_data_size)); |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 731 | } |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 732 | } |
| 733 | } |
| 734 | else |
| 735 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 736 | /* user data required is equal or greater than the data read */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 737 | if (remaining_data_size > (recv_length - byte_index)) |
| 738 | { |
| 739 | remaining_data_size = (uint8_t) |
| 740 | (recv_length - byte_index); |
| 741 | } |
| 742 | } |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 743 | |
| 744 | /* Copy data in the user buffer */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 745 | (void)memcpy ((void *)(psNdefMap->ApduBuffer + |
| 746 | psNdefMap->ApduBuffIndex), |
| 747 | (void *)(p_recv_buf + byte_index), |
| 748 | remaining_data_size); |
| 749 | |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 750 | /* Update the read index */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 751 | psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + |
| 752 | remaining_data_size); |
| 753 | |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 754 | } /* else part of if (ps_iso_15693_con->store_length) */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 755 | |
| 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 778 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 781 | *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex; |
| 782 | } |
| 783 | if (reformatted_buf != NULL) { |
| 784 | phOsalNfc_FreeMemory(reformatted_buf); |
| 785 | } |
| 786 | return result; |
| 787 | } |
| 788 | |
| 789 | static |
| 790 | NFCSTATUS |
| 791 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 800 | /* expected CC byte : E1 40 "MAX SIZE depends on tag" */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 801 | if (ISO15693_CC_MAGIC_BYTE == *p_recv_buf) |
| 802 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 803 | /* 0xE1 magic byte found*/ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 804 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 808 | /* Correct mapping version found */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 809 | switch (*(p_recv_buf + recv_index) & ISO15693_LSB_NIBBLE_MASK) |
| 810 | { |
| 811 | case ISO15693_RD_WR_PERMISSION: |
| 812 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 813 | /* READ/WRITE possible */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 814 | psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; |
| 815 | break; |
| 816 | } |
| 817 | |
| 818 | case ISO15693_RD_ONLY_PERMISSION: |
| 819 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 820 | /* ONLY READ possible, WRITE NOT possible */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 821 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 836 | /* Update MAX SIZE */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 837 | 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 | |
| 860 | static |
| 861 | NFCSTATUS |
| 862 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 898 | so when that block is read, update the parse_index |
| 899 | with byte address value */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 900 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 911 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 916 | switch (e_chk_ndef_seq) |
| 917 | { |
| 918 | case ISO15693_NDEF_TLV_T: |
| 919 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 920 | /* Expected value is 0x03 TYPE identifier |
| 921 | of the NDEF TLV */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 922 | prop_ndef_index = 0; |
| 923 | switch (*(p_recv_buf + parse_index)) |
| 924 | { |
| 925 | case ISO15693_NDEF_TLV_TYPE_ID: |
| 926 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 927 | /* Update the data structure with the byte address and |
| 928 | the block number */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 929 | 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 933 | |
| 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 963 | /* Length field of the proprietary TLV */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 964 | switch (prop_ndef_index) |
| 965 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 966 | /* Length field can have 1 or 3 bytes depending |
| 967 | on the data size, so check for each index byte */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 968 | case 0: |
| 969 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 970 | /* 1st index of the length field of the TLV */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 971 | if (0 == *(p_recv_buf + parse_index)) |
| 972 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 973 | /* LENGTH is 0, not possible, so error */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 974 | 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 980 | if (ISO15693_THREE_BYTE_LENGTH_ID == |
| 981 | *(p_recv_buf + parse_index)) |
| 982 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 983 | /* 3 byte LENGTH field identified, so increment the |
| 984 | index, so next time 2nd byte is parsed */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 985 | prop_ndef_index = (uint8_t)(prop_ndef_index + 1); |
| 986 | } |
| 987 | else |
| 988 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 989 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 993 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1004 | /* 2nd index of the LENGTH field that is MSB of the length, |
| 1005 | so the length is left shifted by 8 */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1006 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1015 | /* 3rd index of the LENGTH field that is LSB of the length, |
| 1016 | so the length ORed with the previously stored size */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1017 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1048 | |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1049 | /* 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1104 | /* Length field of the NDEF TLV */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1105 | switch (prop_ndef_index) |
| 1106 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1107 | /* Length field can have 1 or 3 bytes depending |
| 1108 | on the data size, so check for each index byte */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1109 | case 0: |
| 1110 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1111 | /* 1st index of the length field of the TLV */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1112 | if (0 == *(p_recv_buf + parse_index)) |
| 1113 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1114 | /* LENGTH is 0, card is in INITILIASED STATE */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1115 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1125 | /* At present no CARD supports more than 255 bytes, |
| 1126 | so error is returned */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1127 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1134 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1138 | ps_iso_15693_con->actual_ndef_size = |
| 1139 | *(p_recv_buf + parse_index); |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1140 | /* next values are the DATA field of the NDEF TLV */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1141 | e_chk_ndef_seq = ISO15693_NDEF_TLV_V; |
| 1142 | prop_ndef_index = 0; |
| 1143 | } |
| 1144 | } |
| 1145 | break; |
| 1146 | } |
| 1147 | |
| 1148 | case 1: |
| 1149 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1150 | /* 2nd index of the LENGTH field that is MSB of the length, |
| 1151 | so the length is left shifted by 8 */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1152 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1161 | /* 3rd index of the LENGTH field that is LSB of the length, |
| 1162 | so the length ORed with the previously stored size */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1163 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1183 | "MOD" operation is used to know that parse_index > |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1184 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1243 | /* Proprietary TLV detected, so skip the proprietary blocks */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1244 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1261 | /* End of card reached, error no NDEF information found */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1262 | 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 | |
| 1286 | static |
| 1287 | void |
| 1288 | phFriNfc_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 | |
| 1302 | static |
| 1303 | NFCSTATUS |
| 1304 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1324 | 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1332 | (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf, |
| 1333 | sizeof (a_write_buf)); |
| 1334 | |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1335 | /* Change the read write access to read only */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1336 | *(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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1341 | ISO15693_WRITE_COMMAND, a_write_buf, |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1342 | sizeof (a_write_buf)); |
| 1343 | |
| 1344 | e_ro_ndef_seq = ISO15693_WRITE_CC; |
| 1345 | } |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1346 | } |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1347 | break; |
| 1348 | } |
| 1349 | |
| 1350 | case ISO15693_WRITE_CC: |
| 1351 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1352 | /* Write to CC is successful. */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1353 | e_ro_ndef_seq = ISO15693_LOCK_BLOCK; |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1354 | /* Start the lock block command to lock the blocks */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1355 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1363 | ((ps_iso_15693_con->max_data_size / ISO15693_BYTES_PER_BLOCK) - |
| 1364 | 1)) |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1365 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1366 | /* End of card reached, READ ONLY successful */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1367 | } |
| 1368 | else |
| 1369 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1370 | /* current block is incremented */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1371 | ps_iso_15693_con->current_block = (uint16_t) |
| 1372 | (ps_iso_15693_con->current_block + 1); |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1373 | /* Lock the current block */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1374 | 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 | |
| 1395 | NFCSTATUS |
| 1396 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1421 | 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1430 | switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_5]) |
| 1431 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1432 | /* Check for supported tags, by checking the 5th byte index of UID */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1433 | case ISO15693_UIDBYTE_5_VALUE_SLI_X: |
| 1434 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1435 | /* ISO 15693 card type is ICODE SLI |
| 1436 | so maximum size is 112 */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1437 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1444 | /* ISO 15693 card type is ICODE SLI/X S |
| 1445 | so maximum size depends on the 4th UID byte index */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1446 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1452 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1455 | psNdefMap->ISO15693Container.max_data_size = |
| 1456 | ISO15693_SL2_S5302_ICS53_ICS54; |
| 1457 | break; |
| 1458 | } |
| 1459 | |
| 1460 | default: |
| 1461 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1462 | /* Tag not supported */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1463 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1473 | /* ISO 15693 card type is ICODE SLI/X L |
| 1474 | so maximum size depends on the 4th UID byte index */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1475 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1480 | /* Supported tags are with value (4th byte UID index) |
| 1481 | of 0x00 and 0x80 |
| 1482 | For these cards max size is 32 bytes */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1483 | psNdefMap->ISO15693Container.max_data_size = |
| 1484 | ISO15693_SL2_S5002_ICS50_ICS51; |
| 1485 | break; |
| 1486 | } |
| 1487 | |
| 1488 | default: |
| 1489 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1490 | /* Tag not supported */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1491 | result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| 1492 | NFCSTATUS_INVALID_DEVICE_REQUEST); |
| 1493 | break; |
| 1494 | } |
| 1495 | } |
| 1496 | break; |
| 1497 | } |
| 1498 | |
| 1499 | default: |
| 1500 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1501 | /* Tag not supported */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1502 | result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| 1503 | NFCSTATUS_INVALID_DEVICE_REQUEST); |
| 1504 | break; |
| 1505 | } |
| 1506 | } |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1507 | } |
| 1508 | else |
| 1509 | { |
| 1510 | /* Tag not supported */ |
| 1511 | result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| 1512 | NFCSTATUS_INVALID_DEVICE_REQUEST); |
| 1513 | } |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1514 | |
| 1515 | if (!result) |
| 1516 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1517 | /* Start reading the data */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1518 | result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, |
| 1519 | NULL, 0); |
| 1520 | } |
| 1521 | |
| 1522 | |
| 1523 | return result; |
| 1524 | } |
| 1525 | |
| 1526 | NFCSTATUS |
| 1527 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1563 | /* Entire data is already read from the card. |
| 1564 | There is no data to give */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1565 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1570 | /* Card is NDEF, but no data in the card. */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1571 | result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| 1572 | NFCSTATUS_READ_FAILED); |
| 1573 | } |
| 1574 | else if (PH_NDEFMAP_CARD_STATE_INITIALIZED == psNdefMap->CardState) |
| 1575 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1576 | /* Card is NDEF, but no data in the card. */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1577 | result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| 1578 | NFCSTATUS_READ_FAILED); |
| 1579 | } |
| 1580 | else if (psNdefMap->Offset) |
| 1581 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1582 | /* BEGIN offset, so reset the remaining read size and |
| 1583 | also the curretn block */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1584 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1603 | /* CONTINUE offset */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1604 | if (ps_iso_15693_con->store_length > 0) |
| 1605 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1606 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1608 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1614 | result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, |
| 1615 | ISO15693_READ_COMMAND, NULL, 0); |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1616 | } |
| 1617 | } |
| 1618 | |
| 1619 | return result; |
| 1620 | } |
| 1621 | |
| 1622 | static |
| 1623 | NFCSTATUS |
| 1624 | phFriNfc_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 | |
| 1655 | NFCSTATUS |
| 1656 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1690 | /* Set the current block correctly to write the length field to 0 */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1691 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1702 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1706 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1712 | /* 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 Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1714 | 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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1724 | /* Write data */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1725 | result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, |
| 1726 | ISO15693_WRITE_COMMAND, |
| 1727 | a_write_buf, ISO15693_BYTES_PER_BLOCK); |
| 1728 | |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1729 | /* Increment the index to keep track of bytes sent for write */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1730 | 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 | |
| 1739 | NFCSTATUS |
| 1740 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1748 | /* READ CC bytes */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1749 | 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 | |
| 1761 | void |
| 1762 | phFriNfc_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 Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1775 | /* State = CHECK NDEF in progress */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1776 | Status = phFriNfc_ISO15693_H_ProcessCheckNdef (psNdefMap); |
| 1777 | break; |
| 1778 | } |
| 1779 | |
| 1780 | case ISO15693_READ_NDEF: |
| 1781 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1782 | /* State = READ NDEF in progress */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1783 | Status = phFriNfc_ISO15693_H_ProcessReadNdef (psNdefMap); |
| 1784 | break; |
| 1785 | } |
| 1786 | |
| 1787 | case ISO15693_WRITE_NDEF: |
| 1788 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1789 | /* State = WRITE NDEF in progress */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1790 | Status = phFriNfc_ISO15693_H_ProcessWriteNdef (psNdefMap); |
| 1791 | break; |
| 1792 | } |
| 1793 | |
| 1794 | #ifdef FRINFC_READONLY_NDEF |
| 1795 | case ISO15693_READ_ONLY_NDEF: |
| 1796 | { |
Martijn Coenen | 4f3ef02 | 2011-01-20 01:27:17 +0100 | [diff] [blame] | 1797 | /* State = RAD ONLY NDEF in progress */ |
Martijn Coenen | a6e012a | 2011-01-13 23:24:24 +0100 | [diff] [blame] | 1798 | 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 */ |