1 /* 2 * Copyright (C) 2010 NXP Semiconductors 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 * \file phLlcNfc.c 19 * \brief Common LLC for the upper layer. 20 * 21 * Project: NFC-FRI-1.1 22 * 23 * $Date: Wed Apr 28 17:07:03 2010 $ 24 * $Author: ing02260 $ 25 * $Revision: 1.59 $ 26 * $Aliases: NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ 27 * 28 */ 29 30 /*************************** Includes *******************************/ 31 #include <phNfcTypes.h> 32 #include <phNfcStatus.h> 33 #include <phOsalNfc.h> 34 #include <phNfcInterface.h> 35 #include <phLlcNfc_DataTypes.h> 36 #include <phLlcNfc.h> 37 #include <phLlcNfc_Frame.h> 38 #include <phLlcNfc_Interface.h> 39 #include <phLlcNfc_Timer.h> 40 41 /*********************** End of includes ****************************/ 42 43 /***************************** Macros *******************************/ 44 45 /************************ End of macros *****************************/ 46 47 /***************************** Global variables *******************************/ 48 49 #ifdef LLC_RELEASE_FLAG 50 uint8_t g_release_flag; 51 #endif /* #ifdef LLC_RELEASE_FLAG */ 52 53 /************************ End of global variables *****************************/ 54 55 56 57 /*********************** Local functions ****************************/ 58 /** 59 * \ingroup grp_hal_nfc_llc 60 * 61 * \brief \b Init function 62 * 63 * \copydoc page_reg Initialise all variables of the LLC component (Asynchronous function). 64 * 65 * \param[in] pContext LLC context provided by the upper layer. The LLC 66 * context will be given to the upper layer through the 67 * \ref phLlcNfc_Register function 68 * \param[in] pLinkInfo Link information of the hardware 69 * 70 * \retval NFCSTATUS_PENDING If the command is yet to be processed. 71 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. 72 * \retval Other errors Errors related to the lower layers 73 * 74 */ 75 static 76 NFCSTATUS 77 phLlcNfc_Init ( 78 void *pContext, 79 void *pLinkInfo 80 ); 81 82 /** 83 * \ingroup grp_hal_nfc_llc 84 * 85 * \brief \b Send function 86 * 87 * \copydoc page_reg This asynchronous function gets the information from the upper layer and creates the 88 * proper LLC packet to send the information it to the hardware. The number of 89 * bytes written is obtained from the send response callback which has been 90 * registered in \ref phLlcNfc_Register function 91 * 92 * \param[in] pContext LLC context is provided by the upper layer. The LLC 93 * context earlier was given to the upper layer through the 94 * \ref phLlcNfc_Register function 95 * \param[in] pLinkInfo Link information of the hardware. 96 * \param[in] pLlc_Buf The information given by the upper layer to send it to 97 * the lower layer 98 * \param[in] llcBufLength the length of pLlc_Buf, that needs to be sent to the 99 * lower layer is given by the upper layer 100 * 101 * \retval NFCSTATUS_PENDING If the command is yet to be process. 102 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. 103 * \retval Other errors Errors related to the lower layers 104 * 105 */ 106 static 107 NFCSTATUS 108 phLlcNfc_Send ( 109 void *pContext, 110 void *pLinkInfo, 111 uint8_t *pLlcBuf, 112 uint16_t llcBufLength 113 ); 114 115 /** 116 * \ingroup grp_hal_nfc_llc 117 * 118 * \brief \b Receive function 119 * 120 * \copydoc page_reg This asynchronous function gets the length and the required buffer from 121 * the upper layer to receive the information from the the hardware. The 122 * received data will be given through the receive response callback 123 * which has been registered in the \b phLlcNfc_Register function 124 * 125 * \param[in] pContext LLC context is provided by the upper layer. The LLC 126 * context earlier was given to the upper layer through the 127 * \b phLlcNfc_Register function 128 * \param[in] pLinkInfo Link information of the hardware 129 * \param[in] pLlc_Buf The information given by the upper layer to receive data from 130 * the lower layer 131 * \param[in] llcBufLength The length of pLlc_Buf given by the upper layer 132 * 133 * \retval NFCSTATUS_PENDING If the command is yet to be process. 134 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. 135 * \retval Other errors Errors related to the lower layers 136 * 137 */ 138 static 139 NFCSTATUS 140 phLlcNfc_Receive ( 141 void *pContext, 142 void *pLinkInfo, 143 uint8_t *pLlcBuf, 144 uint16_t llcBufLength 145 ); 146 /******************** End of Local functions ************************/ 147 148 /********************** Global variables ****************************/ 149 150 /******************** End of Global Variables ***********************/ 151 152 NFCSTATUS 153 phLlcNfc_Register ( 154 phNfcIF_sReference_t *psReference, 155 phNfcIF_sCallBack_t if_callback, 156 void *psIFConfig 157 ) 158 { 159 NFCSTATUS result = NFCSTATUS_SUCCESS; 160 phLlcNfc_Context_t *ps_llc_ctxt = NULL; 161 phNfcLayer_sCfg_t *psconfig = (phNfcLayer_sCfg_t *)psIFConfig; 162 163 PH_LLCNFC_PRINT("Llc Register called\n"); 164 if ((NULL == psReference) || (NULL == psIFConfig) || 165 (NULL == psReference->plower_if) || 166 #if 0 167 (NULL == if_callback.pif_ctxt) || 168 #endif 169 (NULL == if_callback.notify) || 170 (NULL == if_callback.receive_complete) || 171 (NULL == if_callback.send_complete)) 172 { 173 result = PHNFCSTVAL(CID_NFC_LLC, 174 NFCSTATUS_INVALID_PARAMETER); 175 } 176 else 177 { 178 /* Now LLC is in RESET state */ 179 ps_llc_ctxt = (phLlcNfc_Context_t*)phOsalNfc_GetMemory( 180 sizeof(phLlcNfc_Context_t)); 181 if (NULL == ps_llc_ctxt) 182 { 183 /* Memory allocation failed */ 184 result = PHNFCSTVAL(CID_NFC_LLC, 185 NFCSTATUS_INSUFFICIENT_RESOURCES); 186 } 187 else 188 { 189 result = NFCSTATUS_SUCCESS; 190 191 (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t)); 192 193 /* Register the LLC functions to the upper layer */ 194 psReference->plower_if->init = (pphNfcIF_Interface_t)&phLlcNfc_Init; 195 psReference->plower_if->release = (pphNfcIF_Interface_t)&phLlcNfc_Release; 196 psReference->plower_if->send = (pphNfcIF_Transact_t)&phLlcNfc_Send; 197 psReference->plower_if->receive = (pphNfcIF_Transact_t)&phLlcNfc_Receive; 198 /* Copy the LLC context to the upper layer */ 199 psReference->plower_if->pcontext = ps_llc_ctxt; 200 201 /* Register the callback function from the upper layer */ 202 ps_llc_ctxt->cb_for_if.receive_complete = if_callback.receive_complete; 203 ps_llc_ctxt->cb_for_if.send_complete = if_callback.send_complete; 204 ps_llc_ctxt->cb_for_if.notify = if_callback.notify; 205 /* Get the upper layer context */ 206 ps_llc_ctxt->cb_for_if.pif_ctxt = if_callback.pif_ctxt; 207 208 result = phLlcNfc_Interface_Register(ps_llc_ctxt, psconfig); 209 210 if (NFCSTATUS_SUCCESS == result) 211 { 212 #ifdef LLC_RELEASE_FLAG 213 g_release_flag = FALSE; 214 #endif /* #ifdef LLC_RELEASE_FLAG */ 215 } 216 } 217 } 218 PH_LLCNFC_DEBUG("Llc Register result : 0x%x\n", result); 219 return result; 220 } 221 222 static 223 NFCSTATUS 224 phLlcNfc_Init ( 225 void *pContext, 226 void *pLinkInfo 227 ) 228 { 229 NFCSTATUS result = NFCSTATUS_SUCCESS; 230 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; 231 phLlcNfc_LlcPacket_t *ps_packet_info = NULL; 232 233 PH_LLCNFC_PRINT("Llc Init called\n"); 234 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo)) 235 { 236 result = PHNFCSTVAL(CID_NFC_LLC, 237 NFCSTATUS_INVALID_PARAMETER); 238 } 239 else 240 { 241 /* Initialisation */ 242 ps_packet_info = &(ps_llc_ctxt->s_frameinfo.s_llcpacket); 243 244 ps_llc_ctxt->phwinfo = pLinkInfo; 245 /* Call the internal frame initialise */ 246 phLlcNfc_H_Frame_Init(ps_llc_ctxt); 247 /* Call the internal LLC TL interface initialise */ 248 result = phLlcNfc_Interface_Init(ps_llc_ctxt); 249 if (NFCSTATUS_SUCCESS == result) 250 { 251 /* Call the internal LLC timer initialise */ 252 result = phLlcNfc_TimerInit(ps_llc_ctxt); 253 } 254 255 if (NFCSTATUS_SUCCESS == result) 256 { 257 /* Create the static timer */ 258 phLlcNfc_CreateTimers(); 259 260 /* Create a U frame */ 261 result = phLlcNfc_H_CreateUFramePayload(ps_llc_ctxt, 262 ps_packet_info, 263 &(ps_packet_info->llcbuf_len), 264 phLlcNfc_e_rset); 265 } 266 if (NFCSTATUS_SUCCESS == result) 267 { 268 /* Call DAL write */ 269 result = phLlcNfc_Interface_Write(ps_llc_ctxt, 270 (uint8_t*)&(ps_packet_info->s_llcbuf), 271 (uint32_t)ps_packet_info->llcbuf_len); 272 } 273 if (NFCSTATUS_PENDING == result) 274 { 275 /* Start the timer */ 276 result = phLlcNfc_StartTimers(PH_LLCNFC_CONNECTIONTIMER, 0); 277 if (NFCSTATUS_SUCCESS == result) 278 { 279 ps_llc_ctxt->s_frameinfo.sent_frame_type = 280 init_u_rset_frame; 281 result = NFCSTATUS_PENDING; 282 } 283 } 284 285 if (NFCSTATUS_PENDING != result) 286 { 287 (void)phLlcNfc_Release(ps_llc_ctxt, pLinkInfo); 288 } 289 } 290 PH_LLCNFC_DEBUG("Llc Init result : 0x%x\n", result); 291 return result; 292 } 293 294 NFCSTATUS 295 phLlcNfc_Release( 296 void *pContext, 297 void *pLinkInfo 298 ) 299 { 300 NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, 301 NFCSTATUS_INVALID_PARAMETER); 302 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; 303 /* 304 1. Free all the memory allocated in initialise 305 */ 306 PH_LLCNFC_PRINT("Llc release called\n"); 307 308 if ((NULL != ps_llc_ctxt) && (NULL != pLinkInfo)) 309 { 310 result = NFCSTATUS_SUCCESS; 311 ps_llc_ctxt->phwinfo = pLinkInfo; 312 #ifdef INCLUDE_DALINIT_DEINIT 313 if (NULL != ps_llc_ctxt->lower_if.release) 314 { 315 result = ps_llc_ctxt->lower_if.release( 316 ps_llc_ctxt->lower_if.pcontext, 317 pLinkInfo); 318 } 319 #endif 320 if (NULL != ps_llc_ctxt->lower_if.transact_abort) 321 { 322 result = ps_llc_ctxt->lower_if.transact_abort( 323 ps_llc_ctxt->lower_if.pcontext, 324 pLinkInfo); 325 } 326 if (NULL != ps_llc_ctxt->lower_if.unregister) 327 { 328 result = ps_llc_ctxt->lower_if.unregister( 329 ps_llc_ctxt->lower_if.pcontext, 330 pLinkInfo); 331 } 332 333 /* Call the internal LLC timer un-initialise */ 334 phLlcNfc_TimerUnInit(ps_llc_ctxt); 335 phLlcNfc_H_Frame_DeInit(&ps_llc_ctxt->s_frameinfo); 336 (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t)); 337 phOsalNfc_FreeMemory(ps_llc_ctxt); 338 ps_llc_ctxt = NULL; 339 340 #ifdef LLC_RELEASE_FLAG 341 g_release_flag = TRUE; 342 #endif /* #ifdef LLC_RELEASE_FLAG */ 343 344 } 345 PH_LLCNFC_DEBUG("Llc release result : 0x%04X\n", result); 346 return result; 347 } 348 349 static 350 NFCSTATUS 351 phLlcNfc_Send ( 352 void *pContext, 353 void *pLinkInfo, 354 uint8_t *pLlcBuf, 355 uint16_t llcBufLength 356 ) 357 { 358 /* 359 1. Check the function parameters for valid values 360 2. Create the I frame llc payload using the upper layer buffer 361 3. Send the updated buffer to the below layer 362 4. Store the I frame in a list, till acknowledge is received 363 */ 364 NFCSTATUS result = NFCSTATUS_SUCCESS; 365 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; 366 phLlcNfc_Frame_t *ps_frame_info = NULL; 367 phLlcNfc_LlcPacket_t *ps_packet_info = NULL, 368 s_packet_info; 369 phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; 370 #if 0 371 uint8_t count = 1; 372 #endif /* #if 0 */ 373 374 PH_LLCNFC_PRINT ("Llc Send called\n"); 375 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) || 376 (NULL == pLlcBuf) || (0 == llcBufLength) || 377 (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN)) 378 { 379 /* Parameter check failed */ 380 result = PHNFCSTVAL(CID_NFC_LLC, 381 NFCSTATUS_INVALID_PARAMETER); 382 } 383 else if (ps_llc_ctxt->s_frameinfo.s_send_store.winsize_cnt >= 384 ps_llc_ctxt->s_frameinfo.window_size) 385 { 386 /* Window size check failed */ 387 result = PHNFCSTVAL(CID_NFC_LLC, 388 NFCSTATUS_NOT_ALLOWED); 389 } 390 else 391 { 392 ps_frame_info = &(ps_llc_ctxt->s_frameinfo); 393 ps_store_frame = &(ps_frame_info->s_send_store); 394 395 PH_LLCNFC_DEBUG ("Buffer length : 0x%04X\n", llcBufLength); 396 PH_LLCNFC_PRINT_BUFFER (pLlcBuf, llcBufLength); 397 398 /* Copy the hardware information */ 399 ps_llc_ctxt->phwinfo = pLinkInfo; 400 401 /* Create I frame with the user buffer */ 402 (void)phLlcNfc_H_CreateIFramePayload ( 403 &(ps_llc_ctxt->s_frameinfo), 404 &s_packet_info, 405 pLlcBuf, (uint8_t)llcBufLength); 406 407 ps_packet_info = &(ps_frame_info->s_llcpacket); 408 409 /* Store the I frame in the send list */ 410 (void)phLlcNfc_H_StoreIFrame (ps_store_frame, s_packet_info); 411 result = NFCSTATUS_PENDING; 412 413 #ifdef CTRL_WIN_SIZE_COUNT 414 415 /* No check required */ 416 if ((TRUE != ps_frame_info->write_pending) && 417 (PH_LLCNFC_READPEND_REMAIN_BYTE != 418 ps_frame_info->read_pending)) 419 420 #else /* #ifdef CTRL_WIN_SIZE_COUNT */ 421 422 if (1 == ps_frame_info->s_send_store.winsize_cnt) 423 424 #endif /* #ifdef CTRL_WIN_SIZE_COUNT */ 425 { 426 (void)memcpy ((void *)ps_packet_info, (void *)&s_packet_info, 427 sizeof(phLlcNfc_LlcPacket_t)); 428 /* Call write to the below layer, only if previous write 429 is completed */ 430 result = phLlcNfc_Interface_Write (ps_llc_ctxt, 431 (uint8_t *)&(ps_packet_info->s_llcbuf), 432 (uint32_t)ps_packet_info->llcbuf_len); 433 434 if ((NFCSTATUS_PENDING == result) || 435 (NFCSTATUS_BUSY == PHNFCSTATUS (result))) 436 { 437 ps_frame_info->write_status = result; 438 if (NFCSTATUS_BUSY == PHNFCSTATUS(result)) 439 { 440 result = NFCSTATUS_PENDING; 441 ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) 442 ((resend_i_frame == ps_frame_info->write_wait_call) ? 443 ps_frame_info->write_wait_call : user_i_frame); 444 } 445 else 446 { 447 /* Start the timer */ 448 (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, 449 ps_frame_info->n_s); 450 451 /* "sent_frame_type is updated" only if the data is 452 written to the lower layer */ 453 ps_frame_info->sent_frame_type = user_i_frame; 454 } 455 } 456 #if 0 457 /* Get the added frame array count */ 458 count = (uint8_t)((((ps_store_frame->start_pos + 459 ps_store_frame->winsize_cnt) - count)) % 460 PH_LLCNFC_MOD_NS_NR); 461 #endif /* #if 0 */ 462 } 463 else 464 { 465 ps_frame_info->write_status = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY); 466 ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) 467 ((resend_i_frame == ps_frame_info->write_wait_call) ? 468 ps_frame_info->write_wait_call : user_i_frame); 469 } 470 } 471 472 473 PH_LLCNFC_DEBUG ("Llc Send result : 0x%04X\n", result); 474 return result; 475 } 476 477 static 478 NFCSTATUS 479 phLlcNfc_Receive ( 480 void *pContext, 481 void *pLinkInfo, 482 uint8_t *pLlcBuf, 483 uint16_t llcBufLength 484 ) 485 { 486 NFCSTATUS result = NFCSTATUS_SUCCESS; 487 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; 488 phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; 489 490 PH_LLCNFC_PRINT("Llc Receive called\n"); 491 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) || 492 (NULL == pLlcBuf) || (0 == llcBufLength) || 493 (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN)) 494 { 495 result = PHNFCSTVAL(CID_NFC_LLC, 496 NFCSTATUS_INVALID_PARAMETER); 497 } 498 else 499 { 500 ps_llc_ctxt->phwinfo = pLinkInfo; 501 502 ps_recv_pkt = &(ps_llc_ctxt->s_frameinfo.s_recvpacket); 503 /* Always read the first byte to read the length, then 504 read the entire data later using the 1 byte buffer */ 505 llcBufLength = PH_LLCNFC_BYTES_INIT_READ; 506 /* Call write to the below layer */ 507 result = phLlcNfc_Interface_Read(ps_llc_ctxt, 508 PH_LLCNFC_READWAIT_OFF, 509 &(ps_recv_pkt->s_llcbuf.llc_length_byte), 510 llcBufLength); 511 512 ps_llc_ctxt->s_frameinfo.upper_recv_call = TRUE; 513 if (NFCSTATUS_PENDING != result) 514 { 515 ps_llc_ctxt->state = phLlcNfc_Initialised_State; 516 } 517 } 518 PH_LLCNFC_DEBUG("Llc Receive result : 0x%04X\n", result); 519 return result; 520 } 521