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 s_packet_info; 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_llc_ctxt->phwinfo = pLinkInfo; 243 /* Call the internal frame initialise */ 244 phLlcNfc_H_Frame_Init(ps_llc_ctxt); 245 /* Call the internal LLC TL interface initialise */ 246 result = phLlcNfc_Interface_Init(ps_llc_ctxt); 247 if (NFCSTATUS_SUCCESS == result) 248 { 249 /* Call the internal LLC timer initialise */ 250 result = phLlcNfc_TimerInit(ps_llc_ctxt); 251 } 252 253 if (NFCSTATUS_SUCCESS == result) 254 { 255 /* Create the static timer */ 256 phLlcNfc_CreateTimers(); 257 258 /* Create a U frame */ 259 result = phLlcNfc_H_CreateUFramePayload(ps_llc_ctxt, 260 &s_packet_info, 261 &(s_packet_info.llcbuf_len), 262 phLlcNfc_e_rset); 263 } 264 if (NFCSTATUS_SUCCESS == result) 265 { 266 /* Call DAL write */ 267 result = phLlcNfc_Interface_Write(ps_llc_ctxt, 268 (uint8_t*)&(s_packet_info.s_llcbuf), 269 (uint32_t)s_packet_info.llcbuf_len); 270 } 271 if (NFCSTATUS_PENDING == result) 272 { 273 /* Start the timer */ 274 result = phLlcNfc_StartTimers(PH_LLCNFC_CONNECTIONTIMER, 0); 275 if (NFCSTATUS_SUCCESS == result) 276 { 277 ps_llc_ctxt->s_frameinfo.sent_frame_type = 278 init_u_rset_frame; 279 result = NFCSTATUS_PENDING; 280 } 281 } 282 283 if (NFCSTATUS_PENDING != result) 284 { 285 (void)phLlcNfc_Release(ps_llc_ctxt, pLinkInfo); 286 } 287 } 288 PH_LLCNFC_DEBUG("Llc Init result : 0x%x\n", result); 289 return result; 290 } 291 292 NFCSTATUS 293 phLlcNfc_Release( 294 void *pContext, 295 void *pLinkInfo 296 ) 297 { 298 NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, 299 NFCSTATUS_INVALID_PARAMETER); 300 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; 301 /* 302 1. Free all the memory allocated in initialise 303 */ 304 PH_LLCNFC_PRINT("Llc release called\n"); 305 306 if ((NULL != ps_llc_ctxt) && (NULL != pLinkInfo)) 307 { 308 result = NFCSTATUS_SUCCESS; 309 ps_llc_ctxt->phwinfo = pLinkInfo; 310 #ifdef INCLUDE_DALINIT_DEINIT 311 if (NULL != ps_llc_ctxt->lower_if.release) 312 { 313 result = ps_llc_ctxt->lower_if.release( 314 ps_llc_ctxt->lower_if.pcontext, 315 pLinkInfo); 316 } 317 #endif 318 if (NULL != ps_llc_ctxt->lower_if.transact_abort) 319 { 320 result = ps_llc_ctxt->lower_if.transact_abort( 321 ps_llc_ctxt->lower_if.pcontext, 322 pLinkInfo); 323 } 324 if (NULL != ps_llc_ctxt->lower_if.unregister) 325 { 326 result = ps_llc_ctxt->lower_if.unregister( 327 ps_llc_ctxt->lower_if.pcontext, 328 pLinkInfo); 329 } 330 331 /* Call the internal LLC timer un-initialise */ 332 phLlcNfc_TimerUnInit(ps_llc_ctxt); 333 phLlcNfc_H_Frame_DeInit(&ps_llc_ctxt->s_frameinfo); 334 (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t)); 335 phOsalNfc_FreeMemory(ps_llc_ctxt); 336 ps_llc_ctxt = NULL; 337 338 #ifdef LLC_RELEASE_FLAG 339 g_release_flag = TRUE; 340 #endif /* #ifdef LLC_RELEASE_FLAG */ 341 342 } 343 PH_LLCNFC_DEBUG("Llc release result : 0x%04X\n", result); 344 return result; 345 } 346 347 static 348 NFCSTATUS 349 phLlcNfc_Send ( 350 void *pContext, 351 void *pLinkInfo, 352 uint8_t *pLlcBuf, 353 uint16_t llcBufLength 354 ) 355 { 356 /* 357 1. Check the function parameters for valid values 358 2. Create the I frame llc payload using the upper layer buffer 359 3. Send the updated buffer to the below layer 360 4. Store the I frame in a list, till acknowledge is received 361 */ 362 NFCSTATUS result = NFCSTATUS_SUCCESS; 363 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; 364 phLlcNfc_Frame_t *ps_frame_info = NULL; 365 phLlcNfc_LlcPacket_t s_packet_info; 366 phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; 367 #if 0 368 uint8_t count = 1; 369 #endif /* #if 0 */ 370 371 PH_LLCNFC_PRINT ("Llc Send called\n"); 372 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) || 373 (NULL == pLlcBuf) || (0 == llcBufLength) || 374 (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN)) 375 { 376 /* Parameter check failed */ 377 result = PHNFCSTVAL(CID_NFC_LLC, 378 NFCSTATUS_INVALID_PARAMETER); 379 } 380 else if (ps_llc_ctxt->s_frameinfo.s_send_store.winsize_cnt >= 381 ps_llc_ctxt->s_frameinfo.window_size) 382 { 383 /* Window size check failed */ 384 result = PHNFCSTVAL(CID_NFC_LLC, 385 NFCSTATUS_NOT_ALLOWED); 386 } 387 else 388 { 389 ps_frame_info = &(ps_llc_ctxt->s_frameinfo); 390 ps_store_frame = &(ps_frame_info->s_send_store); 391 392 PH_LLCNFC_DEBUG ("Buffer length : 0x%04X\n", llcBufLength); 393 PH_LLCNFC_PRINT_BUFFER (pLlcBuf, llcBufLength); 394 395 /* Copy the hardware information */ 396 ps_llc_ctxt->phwinfo = pLinkInfo; 397 398 /* Create I frame with the user buffer */ 399 (void)phLlcNfc_H_CreateIFramePayload ( 400 &(ps_llc_ctxt->s_frameinfo), 401 &s_packet_info, 402 pLlcBuf, (uint8_t)llcBufLength); 403 404 405 /* Store the I frame in the send list */ 406 (void)phLlcNfc_H_StoreIFrame (ps_store_frame, s_packet_info); 407 result = NFCSTATUS_PENDING; 408 409 #ifdef CTRL_WIN_SIZE_COUNT 410 411 /* No check required */ 412 if ((TRUE != ps_frame_info->write_pending) && 413 (PH_LLCNFC_READPEND_REMAIN_BYTE != 414 ps_frame_info->read_pending)) 415 416 #else /* #ifdef CTRL_WIN_SIZE_COUNT */ 417 418 if (1 == ps_frame_info->s_send_store.winsize_cnt) 419 420 #endif /* #ifdef CTRL_WIN_SIZE_COUNT */ 421 { 422 /* Call write to the below layer, only if previous write 423 is completed */ 424 result = phLlcNfc_Interface_Write (ps_llc_ctxt, 425 (uint8_t *)&(s_packet_info.s_llcbuf), 426 (uint32_t)s_packet_info.llcbuf_len); 427 428 if ((NFCSTATUS_PENDING == result) || 429 (NFCSTATUS_BUSY == PHNFCSTATUS (result))) 430 { 431 ps_frame_info->write_status = result; 432 if (NFCSTATUS_BUSY == PHNFCSTATUS(result)) 433 { 434 result = NFCSTATUS_PENDING; 435 ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) 436 ((resend_i_frame == ps_frame_info->write_wait_call) ? 437 ps_frame_info->write_wait_call : user_i_frame); 438 } 439 else 440 { 441 /* Start the timer */ 442 (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, 443 ps_frame_info->n_s); 444 445 /* "sent_frame_type is updated" only if the data is 446 written to the lower layer */ 447 ps_frame_info->sent_frame_type = user_i_frame; 448 } 449 } 450 #if 0 451 /* Get the added frame array count */ 452 count = (uint8_t)((((ps_store_frame->start_pos + 453 ps_store_frame->winsize_cnt) - count)) % 454 PH_LLCNFC_MOD_NS_NR); 455 #endif /* #if 0 */ 456 } 457 else 458 { 459 ps_frame_info->write_status = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY); 460 ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) 461 ((resend_i_frame == ps_frame_info->write_wait_call) ? 462 ps_frame_info->write_wait_call : user_i_frame); 463 } 464 } 465 466 467 PH_LLCNFC_DEBUG ("Llc Send result : 0x%04X\n", result); 468 return result; 469 } 470 471 static 472 NFCSTATUS 473 phLlcNfc_Receive ( 474 void *pContext, 475 void *pLinkInfo, 476 uint8_t *pLlcBuf, 477 uint16_t llcBufLength 478 ) 479 { 480 NFCSTATUS result = NFCSTATUS_SUCCESS; 481 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; 482 phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; 483 484 PH_LLCNFC_PRINT("Llc Receive called\n"); 485 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) || 486 (NULL == pLlcBuf) || (0 == llcBufLength) || 487 (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN)) 488 { 489 result = PHNFCSTVAL(CID_NFC_LLC, 490 NFCSTATUS_INVALID_PARAMETER); 491 } 492 else 493 { 494 ps_llc_ctxt->phwinfo = pLinkInfo; 495 496 ps_recv_pkt = &(ps_llc_ctxt->s_frameinfo.s_recvpacket); 497 /* Always read the first byte to read the length, then 498 read the entire data later using the 1 byte buffer */ 499 llcBufLength = PH_LLCNFC_BYTES_INIT_READ; 500 /* Call write to the below layer */ 501 result = phLlcNfc_Interface_Read(ps_llc_ctxt, 502 PH_LLCNFC_READWAIT_OFF, 503 &(ps_recv_pkt->s_llcbuf.llc_length_byte), 504 llcBufLength); 505 506 ps_llc_ctxt->s_frameinfo.upper_recv_call = TRUE; 507 if (NFCSTATUS_PENDING != result) 508 { 509 ps_llc_ctxt->state = phLlcNfc_Initialised_State; 510 } 511 } 512 PH_LLCNFC_DEBUG("Llc Receive result : 0x%04X\n", result); 513 return result; 514 } 515