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    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