Home | History | Annotate | Download | only in src
      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