1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Mifare Standard Format implementation 19 */ 20 21 #include <phFriNfc_MifStdFormat.h> 22 #include <phNfcCompId.h> 23 #include <phNxpExtns_MifareStd.h> 24 #include <phNxpLog.h> 25 26 #include <android-base/stringprintf.h> 27 #include <base/logging.h> 28 29 using android::base::StringPrintf; 30 31 /* Function prototype declarations */ 32 static void phFriNfc_MfStd_H_FillSendBuf( 33 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt, uint16_t BlockNo); 34 static NFCSTATUS phFriNfc_MfStd_H_Transceive( 35 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 36 static NFCSTATUS phFriNfc_MfStd_H_CallDisCon( 37 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt, NFCSTATUS Status); 38 static NFCSTATUS phFriNfc_MfStd_H_CallCon( 39 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 40 static NFCSTATUS phFriNfc_MfStd_H_ProCon( 41 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 42 static NFCSTATUS phFriNfc_MfStd_H_ProAuth( 43 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 44 static NFCSTATUS phFriNfc_MfStd_H_ProRdSectTr( 45 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 46 static NFCSTATUS phFriNfc_MfStd_H_ProWrSectTr( 47 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 48 static NFCSTATUS phFriNfc_MfStd_H_WrRdAuth( 49 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 50 static uint32_t phFriNfc_MfStd_H_ChkAcsBit(uint16_t BlockNo, 51 const uint8_t* RecvBuf, 52 const uint8_t AcsBits1[], 53 const uint8_t AcsBits2[]); 54 static void phFriNfc_MfStd_H_ChangeAuthSt( 55 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 56 static void phFriNfc_MfStd_H_NdefComplSect(uint8_t CardTypes, uint8_t Sector[]); 57 static NFCSTATUS phFriNfc_MfStd_H_ProWrMADBlk( 58 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 59 static NFCSTATUS phFriNfc_MfStd_H_ProErrAuth( 60 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 61 static NFCSTATUS phFriNfc_MfStd_H_ErrWrSectTr( 62 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 63 static NFCSTATUS phFriNfc_MfStd_H_ErrRdSectTr( 64 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 65 static NFCSTATUS phFriNfc_MfStd_H_ProUpdMADBlk( 66 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 67 static void phFriNfc_MfStd_H_StrNdefData( 68 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 69 static void phFriNfc_MfStd_H_BlkNoToWrTLV( 70 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt); 71 static int phFriNfc_MfStd_MemCompare(void* s1, void* s2, unsigned int n); 72 73 /* 74 * Enum definition contains format states 75 */ 76 typedef enum Mfc_format_state { 77 MFC_FORMAT_INIT = 0x00, 78 MFC_FORMAT_NFC_KEY, 79 MFC_FORMAT_DEF_KEY, 80 MFC_FORMAT_INVALID 81 } MFC_FORMAT_STATE; 82 83 /* format key status */ 84 static MFC_FORMAT_STATE FormatKeyState = MFC_FORMAT_INIT; 85 86 /******************************************************************************* 87 ** 88 ** Function phFriNfc_MfStd_Reset 89 ** 90 ** Description Resets the component instance to the initial state and 91 *initializes the 92 ** internal variables. 93 ** 94 ** Returns none 95 ** 96 *******************************************************************************/ 97 void phFriNfc_MfStd_Reset(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 98 uint8_t NfcForSectArray[] = PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT, 99 MADSectArray[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K; 100 101 /* Authentication state */ 102 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_VAL_1; 103 104 /* Set default key for A or B */ 105 memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.Default_KeyA_OR_B, 106 PH_FRINFC_MFSTD_FMT_DEFAULT_KEY, /* 0xFF */ 107 PH_FRINFC_MFSTD_FMT_VAL_6); 108 109 /* MAD sector key A */ 110 memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_KeyA, 111 MADSectArray, /*PH_FRINFC_MFSTD_FMT_VAL_0, */ 112 PH_FRINFC_MFSTD_FMT_VAL_6); 113 114 /* Copy access bits for MAD sectors */ 115 memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_AccessBits, 116 &MADSectArray[PH_FRINFC_MFSTD_FMT_VAL_6], PH_FRINFC_MFSTD_FMT_VAL_3); 117 118 /* NFC forum sector key A */ 119 (void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_KeyA, 120 NfcForSectArray, /*PH_FRINFC_MFSTD_FMT_VAL_0, */ 121 PH_FRINFC_MFSTD_FMT_VAL_6); 122 123 /* Copy access bits for NFC forum sectors */ 124 (void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_AccessBits, 125 &NfcForSectArray[PH_FRINFC_MFSTD_FMT_VAL_6], 126 PH_FRINFC_MFSTD_FMT_VAL_3); 127 128 /* Sector compliant array initialised to 0 */ 129 memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl, 130 PH_FRINFC_MFSTD_FMT_VAL_0, /* 0x00 */ 131 PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K); 132 133 NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = 134 (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_0; 135 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 136 (uint8_t)PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; 137 138 return; 139 } 140 141 /******************************************************************************* 142 ** 143 ** Function phFriNfc_MfStd_Format 144 ** 145 ** Description The function initiates and formats the Smart Card.After this 146 *formation, remote 147 ** card would be properly initialized and Ndef Compliant. 148 ** 149 ** Returns NFCSTATUS_PENDING if successful 150 ** Other values if an error has occurred 151 ** 152 *******************************************************************************/ 153 NFCSTATUS phFriNfc_MfStd_Format(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt, 154 const uint8_t* ScrtKeyB) { 155 NFCSTATUS Result = 156 PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER); 157 uint8_t index = PH_FRINFC_MFSTD_FMT_VAL_0; 158 159 if (ScrtKeyB != NULL) { 160 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 161 PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; 162 /* Store Key B in the context */ 163 while (index < PH_FRINFC_MFSTD_FMT_VAL_6) { 164 NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB[index] = ScrtKeyB[index]; 165 index++; 166 } 167 /* Set the state */ 168 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 169 /* Initialize current block to the first sector trailer */ 170 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = PH_FRINFC_MFSTD_FMT_VAL_3; 171 /* Set the authenticate state */ 172 if (MFC_FORMAT_DEF_KEY == FormatKeyState) { 173 FormatKeyState = MFC_FORMAT_INIT; 174 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = 175 PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; 176 } else { 177 FormatKeyState = MFC_FORMAT_NFC_KEY; 178 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = 179 PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY; /* Key Chnage for some cards */ 180 } 181 /* Start authentication */ 182 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 183 } 184 return Result; 185 } 186 187 /******************************************************************************* 188 ** 189 ** Function phFriNfc_MfStd_Process 190 ** 191 ** Description Completion Routine: This function is called by the lower 192 *layer (OVR HAL) 193 ** when an I/O operation has finished. The internal state 194 *machine decides 195 ** whether to call into the lower device again or to complete 196 *the process 197 ** by calling into the upper layer's completion routine, stored 198 *within this 199 ** component's context (phFriNfc_sNdefSmtCrdFmt_t). 200 ** 201 ** Returns none 202 ** 203 *******************************************************************************/ 204 void phFriNfc_MfStd_Process(void* Context, NFCSTATUS Status) { 205 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt = 206 (phFriNfc_sNdefSmtCrdFmt_t*)Context; 207 /* Copy the formatting status */ 208 NdefSmtCrdFmt->FmtProcStatus = Status; 209 210 if (Status == NFCSTATUS_SUCCESS) { 211 switch (NdefSmtCrdFmt->State) { 212 case PH_FRINFC_MFSTD_FMT_AUTH_SECT: 213 Status = phFriNfc_MfStd_H_ProAuth(NdefSmtCrdFmt); 214 break; 215 216 case PH_FRINFC_MFSTD_FMT_DIS_CON: 217 Status = phFriNfc_MfStd_H_CallCon(NdefSmtCrdFmt); 218 break; 219 220 case PH_FRINFC_MFSTD_FMT_CON: 221 if (MFC_FORMAT_DEF_KEY == FormatKeyState) { 222 /* retry the format with other key */ 223 Mfc_FormatNdef(current_key, 6); 224 return; 225 } 226 Status = phFriNfc_MfStd_H_ProCon(NdefSmtCrdFmt); 227 break; 228 229 case PH_FRINFC_MFSTD_FMT_RD_SECT_TR: 230 Status = phFriNfc_MfStd_H_ProRdSectTr(NdefSmtCrdFmt); 231 break; 232 233 case PH_FRINFC_MFSTD_FMT_WR_SECT_TR: 234 Status = phFriNfc_MfStd_H_ProWrSectTr(NdefSmtCrdFmt); 235 break; 236 237 case PH_FRINFC_MFSTD_FMT_WR_MAD_BLK: 238 Status = phFriNfc_MfStd_H_ProWrMADBlk(NdefSmtCrdFmt); 239 break; 240 241 case PH_FRINFC_MFSTD_FMT_WR_TLV: 242 break; 243 244 case PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK: 245 Status = phFriNfc_MfStd_H_ProUpdMADBlk(NdefSmtCrdFmt); 246 break; 247 248 default: 249 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, 250 NFCSTATUS_INVALID_DEVICE_REQUEST); 251 break; 252 } 253 } else { 254 switch (NdefSmtCrdFmt->State) { 255 case PH_FRINFC_MFSTD_FMT_AUTH_SECT: 256 if (MFC_FORMAT_NFC_KEY == FormatKeyState) { 257 FormatKeyState = MFC_FORMAT_DEF_KEY; 258 } 259 Status = phFriNfc_MfStd_H_ProErrAuth(NdefSmtCrdFmt); 260 break; 261 262 case PH_FRINFC_MFSTD_FMT_WR_SECT_TR: 263 Status = phFriNfc_MfStd_H_ErrWrSectTr(NdefSmtCrdFmt); 264 break; 265 266 case PH_FRINFC_MFSTD_FMT_RD_SECT_TR: 267 Status = phFriNfc_MfStd_H_ErrRdSectTr(NdefSmtCrdFmt); 268 break; 269 270 default: 271 Status = NdefSmtCrdFmt->FmtProcStatus; 272 break; 273 } 274 } 275 276 /* Status is not success then call completion routine */ 277 if (Status != NFCSTATUS_PENDING) { 278 phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status); 279 } 280 281 return; 282 } 283 284 /******************************************************************************* 285 ** 286 ** Function phFriNfc_MfStd_H_FillSendBuf 287 ** 288 ** Description This function fills the send buffer for transceive function 289 ** 290 ** Returns none 291 ** 292 *******************************************************************************/ 293 static void phFriNfc_MfStd_H_FillSendBuf( 294 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt, uint16_t BlockNo) { 295 // void *mem = NULL; 296 // /*commented to eliminate unused variable warning*/ 297 uint8_t MADSectTr1k[] = 298 PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K, /* MAD key A, 299 Access bits and GPB of MAD 300 sector */ 301 MADSectTr2k[] = 302 PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_2K, /* MAD key A, 303 Access bits and GPB 304 of MAD sector */ 305 MADSectTr4k[] = 306 PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_4K, /* MAD key A, 307 Access bits 308 and GPB of 309 MAD sector */ 310 NFCSectTr[] = 311 PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT, /* NFC forum key A, 312 Access bits and GPB of 313 NFC sector */ 314 NDEFMsgTLV[16] = 315 {0x03, 0x00, 0xFE, 0x00, 0x00, 0x00, /* NDEF message TLV 316 (INITIALISED state) */ 317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 318 MADBlk[16] = {0x0F, 0x00, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 319 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; 320 /* Block number in send buffer */ 321 NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_0] = (uint8_t)BlockNo; 322 /* Initialize send receive length */ 323 *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_MFSTD_FMT_MAX_RECV_LENGTH; 324 325 /* Depending on the different state, fill the send buffer */ 326 switch (NdefSmtCrdFmt->State) { 327 case PH_FRINFC_MFSTD_FMT_AUTH_SECT: 328 /* Depending on the authentication state, fill the send buffer */ 329 switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState) { 330 case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY: 331 case PH_FRINFC_MFSTD_FMT_AUTH_KEYB: 332 /* Fill send buffer with the default key */ 333 PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_DEF(mem); 334 break; 335 336 case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY: 337 /* Fill send buffer with NFC forum sector key */ 338 PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_NFCSECT_KEYA(mem); 339 break; 340 341 case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB: 342 /* Fill send buffer with NFC forum sector key */ 343 PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_SCRT_KEY(mem); 344 break; 345 346 case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY: 347 default: 348 /* Fill send buffer with MAD sector key */ 349 PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_MADSECT_KEYA(mem); 350 break; 351 } 352 break; 353 354 case PH_FRINFC_MFSTD_FMT_RD_SECT_TR: 355 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; 356 357 /* Send length is always one for read operation */ 358 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_1; 359 break; 360 361 case PH_FRINFC_MFSTD_FMT_WR_SECT_TR: 362 /* Fill send buffer for writing sector trailer */ 363 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; 364 /* Copy the relevant sector trailer value in the buffer */ 365 switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock) { 366 case PH_FRINFC_MFSTD_FMT_VAL_3: 367 if (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) { 368 memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 369 MADSectTr1k, sizeof(MADSectTr1k)); 370 } else if (NdefSmtCrdFmt->CardType == 371 PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD) { 372 memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 373 MADSectTr2k, sizeof(MADSectTr2k)); 374 } else { 375 memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 376 MADSectTr4k, sizeof(MADSectTr4k)); 377 } 378 break; 379 case 67: 380 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 381 MADSectTr4k, sizeof(MADSectTr4k)); 382 break; 383 default: 384 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 385 NFCSectTr, sizeof(NFCSectTr)); 386 break; 387 } 388 memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_11], 389 NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB, 390 sizeof(NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB)); 391 392 /* Send length is always 17 for write operation */ 393 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; 394 break; 395 396 case PH_FRINFC_MFSTD_FMT_WR_TLV: 397 /* Fill send buffer for writing TLV */ 398 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; 399 /* Copy the NDEF message TLV */ 400 memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], NDEFMsgTLV, 401 sizeof(NDEFMsgTLV)); 402 /* Send length is always 17 for write operation */ 403 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; 404 break; 405 406 case PH_FRINFC_MFSTD_FMT_WR_MAD_BLK: 407 /* Fill send buffer for writing MAD block */ 408 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; 409 if ((BlockNo == PH_FRINFC_MFSTD_FMT_VAL_2) || (BlockNo == 65) || 410 (BlockNo == 66)) { 411 /* MAD block number 2, 65 and 66 has 0x03, 0xE1 in the 412 * first two bytes 413 */ 414 MADBlk[PH_FRINFC_MFSTD_FMT_VAL_0] = 0x03; 415 MADBlk[PH_FRINFC_MFSTD_FMT_VAL_1] = 0xE1; 416 } 417 /* Copy the MAD Block values */ 418 memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], MADBlk, 419 sizeof(MADBlk)); 420 /* Send length is always 17 for write operation */ 421 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; 422 break; 423 424 case PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK: 425 default: 426 /* Fill send buffer for writing MAD block */ 427 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; 428 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; 429 switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk) { 430 case PH_FRINFC_MFSTD_FMT_MAD_BLK_1: 431 memcpy( 432 &NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 433 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk, 434 (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); 435 break; 436 437 case PH_FRINFC_MFSTD_FMT_MAD_BLK_2: 438 memcpy( 439 &NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 440 &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[16], 441 (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); 442 break; 443 444 case PH_FRINFC_MFSTD_FMT_MAD_BLK_64: 445 memcpy( 446 &NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 447 &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[32], 448 (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); 449 break; 450 451 case PH_FRINFC_MFSTD_FMT_MAD_BLK_65: 452 memcpy( 453 &NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 454 &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[48], 455 (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); 456 break; 457 458 case PH_FRINFC_MFSTD_FMT_MAD_BLK_66: 459 default: 460 memcpy( 461 &NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], 462 &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[64], 463 (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); 464 break; 465 } 466 break; 467 } 468 469 return; 470 } 471 472 /******************************************************************************* 473 ** 474 ** Function phFriNfc_MfStd_H_Transceive 475 ** 476 ** Description This function authenticates a block or a sector from the 477 *card. 478 ** 479 ** Returns NFCSTATUS_PENDING if successful 480 ** Other values if an error has occurred 481 ** 482 *******************************************************************************/ 483 static NFCSTATUS phFriNfc_MfStd_H_Transceive( 484 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 485 NFCSTATUS Result = NFCSTATUS_SUCCESS; 486 487 /*set the completion routines for the card operations*/ 488 NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = 489 phFriNfc_NdefSmtCrd_Process; 490 NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt; 491 492 *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE; 493 494 /* Call the Overlapped HAL Transceive function */ 495 Result = phFriNfc_ExtnsTransceive( 496 NdefSmtCrdFmt->pTransceiveInfo, NdefSmtCrdFmt->Cmd, 497 NdefSmtCrdFmt->SendRecvBuf, NdefSmtCrdFmt->SendLength, 498 NdefSmtCrdFmt->SendRecvLength); 499 return Result; 500 } 501 502 /******************************************************************************* 503 ** 504 ** Function phFriNfc_MfStd_H_CallDisCon 505 ** 506 ** Description This function calls disconnect. 507 ** 508 ** Returns NFCSTATUS_PENDING if successful 509 ** Other values if an error has occurred 510 ** 511 *******************************************************************************/ 512 static NFCSTATUS phFriNfc_MfStd_H_CallDisCon( 513 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt, NFCSTATUS Status) { 514 NFCSTATUS Result = Status; 515 516 /*Set Ndef State*/ 517 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_DIS_CON; 518 519 Result = phNxNciExtns_MifareStd_Reconnect(); 520 return Result; 521 } 522 523 /******************************************************************************* 524 ** 525 ** Function phFriNfc_MfStd_H_CallCon 526 ** 527 ** Description This function calls reconnect. 528 ** 529 ** Returns NFCSTATUS_PENDING if successful 530 ** Other values if an error has occurred 531 ** 532 *******************************************************************************/ 533 static NFCSTATUS phFriNfc_MfStd_H_CallCon( 534 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 535 NFCSTATUS Result = NFCSTATUS_SUCCESS; 536 /*Set Ndef State*/ 537 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_CON; 538 539 Result = phNxNciExtns_MifareStd_Reconnect(); 540 return Result; 541 } 542 543 /******************************************************************************* 544 ** 545 ** Function phFriNfc_MfStd_H_ProCon 546 ** 547 ** Description This function shall process the poll call. 548 ** 549 ** Returns NFCSTATUS_PENDING if successful 550 ** Other values if an error has occurred 551 ** 552 *******************************************************************************/ 553 static NFCSTATUS phFriNfc_MfStd_H_ProCon( 554 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 555 NFCSTATUS Result = NFCSTATUS_SUCCESS; 556 uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}; 557 uint8_t index = PH_FRINFC_MFSTD_FMT_VAL_1; 558 uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; 559 560 phFriNfc_MfStd_H_ChangeAuthSt(NdefSmtCrdFmt); 561 if (PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) { 562 PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); 563 } else { 564 /* Set the state */ 565 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 566 /* Start authentication */ 567 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 568 } 569 return Result; 570 } 571 572 /******************************************************************************* 573 ** 574 ** Function phFriNfc_MfStd_H_ProAuth 575 ** 576 ** Description This function shall process the authenticate call. 577 ** 578 ** Returns NFCSTATUS_PENDING if successful 579 ** Other values if an error has occurred 580 ** 581 *******************************************************************************/ 582 static NFCSTATUS phFriNfc_MfStd_H_ProAuth( 583 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 584 NFCSTATUS Result = NFCSTATUS_SUCCESS; 585 586 /* Depending on the authentication key check the */ 587 switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState) { 588 case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY: 589 if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 590 PH_FRINFC_MFSTD_FMT_VAL_3) && 591 (NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag == 592 PH_FRINFC_MFSTD_FMT_VAL_0)) { 593 /* Authenticate with default key for block 3 is successful, 594 * so fill the MAD block of sector 0 595 */ 596 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 597 PH_FRINFC_MFSTD_FMT_VAL_1; 598 /* Write the MAD block */ 599 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; 600 } else if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 67) && 601 (NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag == 602 PH_FRINFC_MFSTD_FMT_VAL_0)) { 603 /* Authenticate with default key for block 3 is successful, 604 * so fill the MAD block of sector 64 605 */ 606 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 64; 607 /* Write the MAD block */ 608 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; 609 } else { 610 /* Not a MAD sector */ 611 NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = 612 PH_FRINFC_MFSTD_FMT_VAL_0; 613 /* Write the MAD block */ 614 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; 615 } 616 break; 617 618 case PH_FRINFC_MFSTD_FMT_AUTH_KEYB: 619 if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 620 PH_FRINFC_MFSTD_FMT_MAD_BLK_1) || 621 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 622 PH_FRINFC_MFSTD_FMT_MAD_BLK_2) || 623 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 624 PH_FRINFC_MFSTD_FMT_MAD_BLK_64) || 625 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 626 PH_FRINFC_MFSTD_FMT_MAD_BLK_65) || 627 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 628 PH_FRINFC_MFSTD_FMT_MAD_BLK_66)) { 629 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 630 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk; 631 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK; 632 } else { 633 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 634 PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; 635 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; 636 } 637 638 break; 639 640 case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB: 641 if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 642 PH_FRINFC_MFSTD_FMT_MAD_BLK_1) || 643 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 644 PH_FRINFC_MFSTD_FMT_MAD_BLK_2) || 645 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 646 PH_FRINFC_MFSTD_FMT_MAD_BLK_64) || 647 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 648 PH_FRINFC_MFSTD_FMT_MAD_BLK_65) || 649 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 650 PH_FRINFC_MFSTD_FMT_MAD_BLK_66)) { 651 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 652 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk; 653 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK; 654 } else { 655 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 656 PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; 657 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; 658 } 659 break; 660 661 case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY: 662 case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY: 663 default: 664 if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 665 PH_FRINFC_MFSTD_FMT_MAD_BLK_66) || 666 (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == 667 PH_FRINFC_MFSTD_FMT_MAD_BLK_2)) { 668 /* Updating the MAD block is complete */ 669 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 670 PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; 671 /* If Mifare 4k card, write the TLV */ 672 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_TLV; 673 } else { 674 /* Depending on the sector trailer, check the access bit */ 675 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_RD_SECT_TR; 676 } 677 break; 678 } 679 /* Call read, write or authenticate */ 680 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 681 return Result; 682 } 683 684 /******************************************************************************* 685 ** 686 ** Function phFriNfc_MfStd_H_ErrWrSectTr 687 ** 688 ** Description This function shall process the error status of the writing 689 *sector trailer. 690 ** 691 ** Returns NFCSTATUS_PENDING if successful 692 ** Other values if an error has occurred 693 ** 694 *******************************************************************************/ 695 static NFCSTATUS phFriNfc_MfStd_H_ErrWrSectTr( 696 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 697 NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus; 698 /* If default key A is used for authentication and if write fails, then try to 699 * authenticate using key B 700 */ 701 if (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == 702 PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY) { 703 /* Change the state to authentication */ 704 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 705 /* internal authenticate state = key B */ 706 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_KEYB; 707 /* Now call authenticate */ 708 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 709 } else { 710 Result = phFriNfc_MfStd_H_ProWrSectTr(NdefSmtCrdFmt); 711 } 712 return Result; 713 } 714 715 /******************************************************************************* 716 ** 717 ** Function phFriNfc_MfStd_H_ProRdSectTr 718 ** 719 ** Description This function shall process the read access bit call. 720 ** 721 ** Returns NFCSTATUS_PENDING if successful 722 ** Other values if an error has occurred 723 ** 724 *******************************************************************************/ 725 static NFCSTATUS phFriNfc_MfStd_H_ProRdSectTr( 726 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 727 NFCSTATUS Result = NFCSTATUS_SUCCESS; 728 uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, 729 index = PH_FRINFC_MFSTD_FMT_VAL_1, 730 SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; 731 uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; 732 733 /* Calculate sector index */ 734 SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; 735 736 /* Depending on the sector trailer, check the access bit */ 737 memcompare = phFriNfc_MfStd_H_ChkAcsBit( 738 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock, NdefSmtCrdFmt->SendRecvBuf, 739 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_AccessBits, 740 NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_AccessBits); 741 742 /* Check the sector for ndef compliance */ 743 NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = 744 (uint8_t)((memcompare != PH_FRINFC_MFSTD_FMT_VAL_0) 745 ? PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL 746 : PH_FRINFC_MFSTD_FMT_NDEF_COMPL); 747 748 /* Increment the current block */ 749 PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); 750 SectIndex++; 751 if (PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) { 752 PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); 753 } else { 754 /* Set the state */ 755 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 756 /* Set the authenticate state */ 757 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = 758 PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; 759 /* Start authentication */ 760 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 761 } 762 return Result; 763 } 764 765 /******************************************************************************* 766 ** 767 ** Function phFriNfc_MfStd_H_ProWrSectTr 768 ** 769 ** Description This function shall process the write access bit call. 770 ** 771 ** Returns NFCSTATUS_PENDING if successful 772 ** Other values if an error has occurred 773 ** 774 *******************************************************************************/ 775 static NFCSTATUS phFriNfc_MfStd_H_ProWrSectTr( 776 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 777 NFCSTATUS Result = NFCSTATUS_SUCCESS; 778 uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, 779 index = PH_FRINFC_MFSTD_FMT_VAL_1, 780 SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; 781 uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; 782 783 /* Calculate sector index */ 784 SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; 785 786 /* Sector is ndef compliance */ 787 NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = 788 (uint8_t)((NdefSmtCrdFmt->FmtProcStatus != NFCSTATUS_SUCCESS) 789 ? PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL 790 : PH_FRINFC_MFSTD_FMT_NDEF_COMPL); 791 792 /* Increment the current block */ 793 PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); 794 SectIndex++; 795 if (PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) { 796 PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); 797 } else { 798 /* Set the state */ 799 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 800 /* Set the authenticate state */ 801 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = 802 PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; 803 /* Start authentication */ 804 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 805 } 806 return Result; 807 } 808 809 /******************************************************************************* 810 ** 811 ** Function phFriNfc_MfStd_H_ChkAcsBit 812 ** 813 ** Description This function checks access bits of each sector trailer. 814 ** 815 ** Returns compare value 816 ** 817 *******************************************************************************/ 818 static uint32_t phFriNfc_MfStd_H_ChkAcsBit(uint16_t BlockNo, 819 const uint8_t* RecvBuf, 820 const uint8_t AcsBits1[], 821 const uint8_t AcsBits2[]) { 822 uint32_t mem = PH_FRINFC_MFSTD_FMT_VAL_0; 823 824 /* Compare the access bits read from the sector trailer */ 825 mem = (uint32_t)(((BlockNo == PH_FRINFC_MFSTD_FMT_VAL_3) || (BlockNo == 67)) 826 ? phFriNfc_MfStd_MemCompare( 827 (void*)&RecvBuf[PH_FRINFC_MFSTD_FMT_VAL_6], 828 (void*)AcsBits1, PH_FRINFC_MFSTD_FMT_VAL_3) 829 : phFriNfc_MfStd_MemCompare( 830 (void*)&RecvBuf[PH_FRINFC_MFSTD_FMT_VAL_6], 831 (void*)AcsBits2, PH_FRINFC_MFSTD_FMT_VAL_3)); 832 833 return mem; 834 } 835 836 /******************************************************************************* 837 ** 838 ** Function phFriNfc_MfStd_H_WrRdAuth 839 ** 840 ** Description This function writes sector trailer using the block number. 841 ** 842 ** Returns NFCSTATUS_PENDING if successful 843 ** Other values if an error has occurred 844 ** 845 *******************************************************************************/ 846 static NFCSTATUS phFriNfc_MfStd_H_WrRdAuth( 847 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 848 NFCSTATUS Result = NFCSTATUS_SUCCESS; 849 /* Fill send buffer and send length */ 850 phFriNfc_MfStd_H_FillSendBuf(NdefSmtCrdFmt, 851 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock); 852 /* Call ovrhal transceive */ 853 Result = phFriNfc_MfStd_H_Transceive(NdefSmtCrdFmt); 854 855 return Result; 856 } 857 858 /******************************************************************************* 859 ** 860 ** Function phFriNfc_MfStd_H_ChangeAuthSt 861 ** 862 ** Description This function changes authentication state and change the 863 *block number if required. 864 ** 865 ** Returns none 866 ** 867 *******************************************************************************/ 868 static void phFriNfc_MfStd_H_ChangeAuthSt( 869 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 870 uint8_t SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; 871 872 if (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == 873 PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB) { 874 /* Calculate sector index */ 875 SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; 876 877 /* Check the sector for ndef compliance */ 878 NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = 879 PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL; 880 881 PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); 882 } 883 PH_FRINFC_MFSTD_FMT_NXT_AUTH_STATE(); 884 885 return; 886 } 887 888 /******************************************************************************* 889 ** 890 ** Function phFriNfc_MfStd_H_NdefComplSect 891 ** 892 ** Description This function finds contiguous ndef compliant blocks. 893 ** 894 ** Returns none 895 ** 896 *******************************************************************************/ 897 static void phFriNfc_MfStd_H_NdefComplSect(uint8_t CardTypes, 898 uint8_t Sector[]) { 899 uint8_t count = PH_FRINFC_MFSTD_FMT_VAL_0, 900 NdefComplSectMax = PH_FRINFC_MFSTD_FMT_VAL_0, 901 NdefComplSectTemp = PH_FRINFC_MFSTD_FMT_VAL_1, 902 SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0, 903 MaxCont = PH_FRINFC_MFSTD_FMT_VAL_0, 904 MaxSect = PH_FRINFC_MFSTD_FMT_VAL_0; 905 906 /* Get the maximum sector depending on the sector */ 907 MaxSect = ((CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) 908 ? PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K 909 : ((CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD) 910 ? PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K 911 : PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K)); 912 /* Sector index */ 913 NdefComplSectTemp = SectIndex = PH_FRINFC_MFSTD_FMT_VAL_1; 914 /* Check the sector index depending on the card type */ 915 while (((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && 916 (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) || 917 ((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) && 918 (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)) || 919 ((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K) && 920 (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD))) { 921 if (Sector[SectIndex] == PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL) { 922 if (MaxCont > count) { 923 /* Store the maximum contiguous */ 924 NdefComplSectMax = NdefComplSectTemp; 925 count = MaxCont; 926 } 927 MaxCont = PH_FRINFC_MFSTD_FMT_VAL_0; 928 /* Increment the sector index */ 929 PH_FRINFC_MFSTD_FMT_INCR_SECT; 930 /* Get the next compliant sector */ 931 NdefComplSectTemp = SectIndex; 932 } else { 933 /* Increment the sector index */ 934 PH_FRINFC_MFSTD_FMT_INCR_SECT; 935 } 936 MaxCont++; 937 } 938 if (MaxCont > count) { 939 /* Store the maximum contiguous */ 940 NdefComplSectMax = NdefComplSectTemp; 941 count = MaxCont; 942 } 943 /* Set the sector value has non ndef compliant which are not present with 944 * contiguous ndef compliant sectors 945 */ 946 if ((((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_1)) && 947 (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)) || 948 ((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2)) && 949 (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) || 950 ((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2)) && 951 (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD))) && 952 ((NdefComplSectMax > PH_FRINFC_MFSTD_FMT_VAL_0) && 953 (NdefComplSectMax < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2)))) { 954 memset(&Sector[PH_FRINFC_MFSTD_FMT_VAL_1], 955 PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, 956 (NdefComplSectMax - PH_FRINFC_MFSTD_FMT_VAL_1)); 957 958 memset(&Sector[(NdefComplSectMax + count)], 959 PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, 960 (MaxSect - (NdefComplSectMax + count))); 961 } 962 963 return; 964 } 965 966 /******************************************************************************* 967 ** 968 ** Function phFriNfc_MfStd_H_ProWrMADBlk 969 ** 970 ** Description This function writes the finds MAD block values. 971 ** 972 ** Returns NFCSTATUS_PENDING if successful 973 ** Other values if an error has occurred 974 ** 975 *******************************************************************************/ 976 static NFCSTATUS phFriNfc_MfStd_H_ProWrMADBlk( 977 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 978 NFCSTATUS Result = NFCSTATUS_SUCCESS; 979 980 switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock) { 981 case PH_FRINFC_MFSTD_FMT_VAL_1: 982 /* MAD blocks, still not completed */ 983 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; 984 /* MAD block number 2 */ 985 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = PH_FRINFC_MFSTD_FMT_VAL_2; 986 break; 987 988 case PH_FRINFC_MFSTD_FMT_VAL_2: 989 /* Now write to MAD block is completed */ 990 NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = PH_FRINFC_MFSTD_FMT_VAL_1; 991 /* Now write the sector trailer, so change the state */ 992 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; 993 /* MAD block number 3 = Sector trailer */ 994 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = PH_FRINFC_MFSTD_FMT_VAL_3; 995 break; 996 997 case 64: 998 /* MAD blocks, still not completed */ 999 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; 1000 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 65; 1001 break; 1002 1003 case 65: 1004 /* MAD blocks, still not completed */ 1005 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; 1006 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 66; 1007 break; 1008 1009 case 66: 1010 default: 1011 /* Now write to MAD block is completed */ 1012 NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = PH_FRINFC_MFSTD_FMT_VAL_1; 1013 /* Now write the sector trailer, so change the state */ 1014 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; 1015 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 67; 1016 break; 1017 } 1018 /* Write the block */ 1019 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 1020 1021 return Result; 1022 } 1023 1024 /******************************************************************************* 1025 ** 1026 ** Function phFriNfc_MfStd_H_ProErrAuth 1027 ** 1028 ** Description This function shall process the error status of the 1029 *authentication. 1030 ** 1031 ** Returns NFCSTATUS_PENDING if successful 1032 ** Other values if an error has occurred 1033 ** 1034 *******************************************************************************/ 1035 static NFCSTATUS phFriNfc_MfStd_H_ProErrAuth( 1036 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 1037 NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus; 1038 uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, 1039 index = PH_FRINFC_MFSTD_FMT_VAL_1; 1040 uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; 1041 1042 if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 67) && 1043 (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == 1044 PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB)) { 1045 /* Error in the MAD sector 16, so the remaining sector 1046 * information can't be updated 1047 */ 1048 memset(&NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[16], 1049 PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, 1050 (PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K - 16)); 1051 PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); 1052 } else if (((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock > 1053 PH_FRINFC_MFSTD_FMT_VAL_3) && 1054 (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState != 1055 PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB)) || 1056 ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 1057 PH_FRINFC_MFSTD_FMT_VAL_3) && 1058 (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState < 1059 PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB))) { 1060 /* Authenticate failed, so disconnect, poll and connect */ 1061 Result = phFriNfc_MfStd_H_CallDisCon(NdefSmtCrdFmt, Result); 1062 } else { 1063 if (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 1064 PH_FRINFC_MFSTD_FMT_VAL_3) { 1065 memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl, 1066 PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, 1067 PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K); 1068 } 1069 } 1070 1071 return Result; 1072 } 1073 1074 /******************************************************************************* 1075 ** 1076 ** Function phFriNfc_MfStd_H_ProUpdMADBlk 1077 ** 1078 ** Description This function shall process the error status of the writing 1079 *sector trailer. 1080 ** 1081 ** Returns NFCSTATUS_PENDING if successful 1082 ** Other values if an error has occurred 1083 ** 1084 *******************************************************************************/ 1085 static NFCSTATUS phFriNfc_MfStd_H_ProUpdMADBlk( 1086 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 1087 NFCSTATUS Result = NFCSTATUS_SUCCESS; 1088 switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk) { 1089 case PH_FRINFC_MFSTD_FMT_MAD_BLK_1: 1090 /* Write the next MAD Block */ 1091 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 1092 (uint8_t)PH_FRINFC_MFSTD_FMT_MAD_BLK_2; 1093 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 1094 PH_FRINFC_MFSTD_FMT_MAD_BLK_2; 1095 break; 1096 1097 case PH_FRINFC_MFSTD_FMT_MAD_BLK_2: 1098 case PH_FRINFC_MFSTD_FMT_MAD_BLK_66: 1099 if ((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) || 1100 (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 1101 PH_FRINFC_MFSTD_FMT_MAD_BLK_66)) { 1102 /* Get the block from where the TLV has to be written */ 1103 phFriNfc_MfStd_H_BlkNoToWrTLV(NdefSmtCrdFmt); 1104 1105 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 1106 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = 1107 PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY; 1108 } else { 1109 /* Write the next MAD Block */ 1110 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 1111 (uint8_t)PH_FRINFC_MFSTD_FMT_MAD_BLK_64; 1112 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 1113 PH_FRINFC_MFSTD_FMT_MAD_BLK_64; 1114 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 1115 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = 1116 PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB; 1117 } 1118 break; 1119 1120 case PH_FRINFC_MFSTD_FMT_MAD_BLK_64: 1121 /* Write the next MAD Block */ 1122 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 1123 (uint8_t)PH_FRINFC_MFSTD_FMT_MAD_BLK_65; 1124 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 1125 PH_FRINFC_MFSTD_FMT_MAD_BLK_65; 1126 break; 1127 1128 case PH_FRINFC_MFSTD_FMT_MAD_BLK_65: 1129 default: 1130 /* Write the next MAD Block */ 1131 NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = 1132 (uint8_t)PH_FRINFC_MFSTD_FMT_MAD_BLK_66; 1133 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 1134 PH_FRINFC_MFSTD_FMT_MAD_BLK_66; 1135 break; 1136 } 1137 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 1138 return Result; 1139 } 1140 1141 /******************************************************************************* 1142 ** 1143 ** Function phFriNfc_MfStd_H_StrNdefData 1144 ** 1145 ** Description This function shall store ndef compliant in the MAD array 1146 ** which will be later used for updating the MAD sector. 1147 ** 1148 ** Returns none 1149 ** 1150 *******************************************************************************/ 1151 static void phFriNfc_MfStd_H_StrNdefData( 1152 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 1153 uint8_t SectIndex = PH_FRINFC_MFSTD_FMT_VAL_1, 1154 index = PH_FRINFC_MFSTD_FMT_VAL_0; 1155 1156 memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk, 0x00, 1157 PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K); 1158 1159 /* Zeroth sector of the Mifare card is MAD sector, CRC is 0x14 */ 1160 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[PH_FRINFC_MFSTD_FMT_VAL_0] = 0x14; 1161 /* Info byte is 0x01, because the NDEF application is written and as per the 1162 * MAD spec, the value for miscellaneous application is 0x01 1163 */ 1164 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[PH_FRINFC_MFSTD_FMT_VAL_1] = 0x01; 1165 1166 if ((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD) || 1167 (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD)) { 1168 /* If 4k card then sector number 16 is MAD sector, CRC is 0xE8 */ 1169 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[32] = 0xE8; 1170 /* Info byte is 0x01, because the NDEF application is written and 1171 * as per the MAD spec, 1172 * the value for miscellaneous application is 0x01 1173 */ 1174 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[33] = 0x01; 1175 } 1176 /* NDEF information has to be updated from */ 1177 index = PH_FRINFC_MFSTD_FMT_VAL_2; 1178 /* Depending on the card type, check the sector index */ 1179 while (((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && 1180 (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) || 1181 ((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) && 1182 (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)) || 1183 ((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K) && 1184 (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD))) { 1185 /* Is the sector ndef compliant? */ 1186 if (NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] == 1187 PH_FRINFC_MFSTD_FMT_NDEF_COMPL) { 1188 /* Ndef compliant sector, update the MAD sector array 1189 * in the context with values 0x03 and 0xE1 1190 * 0x03 and 0xE1 is NDEF information in MAD sector 1191 */ 1192 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 1193 PH_FRINFC_MFSTD_FMT_NDEF_INFO1; 1194 index++; 1195 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 1196 PH_FRINFC_MFSTD_FMT_NDEF_INFO2; 1197 index++; 1198 } else { 1199 /* Not a Ndef compliant sector, update the MAD sector array 1200 * in the context with values 0x00 and 0x00 1201 * 0x00 and 0x00 is NDEF information in MAD sector 1202 */ 1203 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 0x00; 1204 index++; 1205 NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 0x00; 1206 index++; 1207 } 1208 /* Go to next sector */ 1209 SectIndex++; 1210 /* is the sector, a MAD sector 16? */ 1211 if (SectIndex == PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) { 1212 /* MAD sector number 16, so skip this sector */ 1213 SectIndex = SectIndex + PH_FRINFC_MFSTD_FMT_VAL_1; 1214 index = index + PH_FRINFC_MFSTD_FMT_VAL_2; 1215 } 1216 } 1217 1218 return; 1219 } 1220 1221 /******************************************************************************* 1222 ** 1223 ** Function phFriNfc_MfStd_H_BlkNoToWrTLV 1224 ** 1225 ** Description This function shall find the ndef compliant 1226 ** and calculate the block number to write the NDEF TLV. 1227 ** 1228 ** Returns none 1229 ** 1230 *******************************************************************************/ 1231 static void phFriNfc_MfStd_H_BlkNoToWrTLV( 1232 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 1233 uint8_t SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_1; 1234 while (((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && 1235 (NdefSmtCrdFmt->CardType == 1236 (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) || 1237 ((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) && 1238 (NdefSmtCrdFmt->CardType == 1239 (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)) || 1240 ((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K) && 1241 (NdefSmtCrdFmt->CardType == 1242 (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD))) { 1243 if (NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] == 1244 (uint8_t)PH_FRINFC_MFSTD_FMT_NDEF_COMPL) { 1245 /* Get the first NFC forum sector's block */ 1246 NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 1247 (uint16_t)(((SectIndex & 0xE0) >= 32) 1248 ? (128 + ((SectIndex % 32) * 16)) 1249 : (SectIndex * (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_4)); 1250 /* Break out of the loop */ 1251 SectIndex += (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K; 1252 } 1253 SectIndex++; 1254 } 1255 1256 return; 1257 } 1258 1259 /******************************************************************************* 1260 ** 1261 ** Function phFriNfc_MfStd_H_ErrRdSectTr 1262 ** 1263 ** Description This function shall process the error status of the reading 1264 *sector trailer. 1265 ** 1266 ** Returns NFCSTATUS_PENDING if successful 1267 ** Other values if an error has occurred 1268 ** 1269 *******************************************************************************/ 1270 static NFCSTATUS phFriNfc_MfStd_H_ErrRdSectTr( 1271 phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt) { 1272 NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus; 1273 uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, 1274 index = PH_FRINFC_MFSTD_FMT_VAL_1, 1275 SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; 1276 uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; 1277 /* If default key A is used for authentication and if write fails, then try to 1278 * authenticate using key B 1279 */ 1280 if (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == 1281 PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY) { 1282 /* Change the state to authentication */ 1283 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 1284 /* internal authenticate state = key B */ 1285 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_KEYB; 1286 /* Now call authenticate */ 1287 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 1288 } else { 1289 /* Calculate sector index */ 1290 SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; 1291 1292 /* Sector is ndef compliance */ 1293 NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = 1294 (uint8_t)((NdefSmtCrdFmt->FmtProcStatus != NFCSTATUS_SUCCESS) 1295 ? PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL 1296 : PH_FRINFC_MFSTD_FMT_NDEF_COMPL); 1297 1298 /* Increment the current block */ 1299 PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); 1300 SectIndex++; 1301 if (PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) { 1302 PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); 1303 } else { 1304 /* Set the state */ 1305 NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; 1306 /* Set the authenticate state */ 1307 NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = 1308 PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; 1309 /* Start authentication */ 1310 Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); 1311 } 1312 } 1313 return Result; 1314 } 1315 1316 /******************************************************************************* 1317 ** 1318 ** Function phFriNfc_MfStd_MemCompare 1319 ** 1320 ** Description This function shall process memory comparison. 1321 ** 1322 ** Returns 0 if memory is same 1323 ** Not 0 if different 1324 ** 1325 *******************************************************************************/ 1326 static int phFriNfc_MfStd_MemCompare(void* s1, void* s2, unsigned int n) { 1327 int8_t diff = 0; 1328 int8_t* char_1 = (int8_t*)s1; 1329 int8_t* char_2 = (int8_t*)s2; 1330 if (NULL == s1 || NULL == s2) { 1331 LOG(ERROR) << StringPrintf("NULL pointer passed to memcompare"); 1332 } else { 1333 for (; ((n > 0) && (diff == 0)); n--, char_1++, char_2++) { 1334 diff = *char_1 - *char_2; 1335 } 1336 } 1337 return (int)diff; 1338 } 1339