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  phFriNfc_LlcpTransport_Connectionless.c
     19  * \brief
     20  *
     21  * Project: NFC-FRI
     22  *
     23  */
     24 /*include files*/
     25 #include <phOsalNfc.h>
     26 #include <phLibNfcStatus.h>
     27 #include <phLibNfc.h>
     28 #include <phNfcLlcpTypes.h>
     29 #include <phFriNfc_LlcpTransport.h>
     30 #include <phFriNfc_Llcp.h>
     31 
     32 static void phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void*        pContext,
     33                                                             uint8_t      socketIndex,
     34                                                             NFCSTATUS    status);
     35 
     36 NFCSTATUS phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations(phFriNfc_LlcpTransport_Socket_t *pSocket)
     37 {
     38    NFCSTATUS status = NFCSTATUS_FAILED;
     39 
     40    /* Check if something is pending and if transport layer is ready to send */
     41    if ((pSocket->pfSocketSend_Cb != NULL) &&
     42        (pSocket->psTransport->bSendPending == FALSE))
     43    {
     44       /* Fill the psLlcpHeader stuture with the DSAP,PTYPE and the SSAP */
     45       pSocket->sLlcpHeader.dsap  = pSocket->socket_dSap;
     46       pSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_UI;
     47       pSocket->sLlcpHeader.ssap  = pSocket->socket_sSap;
     48 
     49       /* Send to data to the approiate socket */
     50       status =  phFriNfc_LlcpTransport_LinkSend(pSocket->psTransport,
     51                                    &pSocket->sLlcpHeader,
     52                                    NULL,
     53                                    &pSocket->sSocketSendBuffer,
     54                                    phFriNfc_LlcpTransport_Connectionless_SendTo_CB,
     55                                    pSocket->index,
     56                                    pSocket);
     57    }
     58    else
     59    {
     60       /* Cannot send now, retry later */
     61    }
     62 
     63    return status;
     64 }
     65 
     66 
     67 /* TODO: comment function Handle_Connectionless_IncommingFrame */
     68 void Handle_Connectionless_IncommingFrame(phFriNfc_LlcpTransport_t      *pLlcpTransport,
     69                                           phNfc_sData_t                 *psData,
     70                                           uint8_t                       dsap,
     71                                           uint8_t                       ssap)
     72 {
     73    phFriNfc_LlcpTransport_Socket_t * pSocket = NULL;
     74    uint8_t                           i       = 0;
     75    uint8_t                           writeIndex;
     76 
     77    /* Look through the socket table for a match */
     78    for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++)
     79    {
     80       if(pLlcpTransport->pSocketTable[i].socket_sSap == dsap)
     81       {
     82          /* Socket found ! */
     83          pSocket = &pLlcpTransport->pSocketTable[i];
     84 
     85          /* Forward directly to application if a read is pending */
     86          if (pSocket->bSocketRecvPending == TRUE)
     87          {
     88             /* Reset the RecvPending variable */
     89             pSocket->bSocketRecvPending = FALSE;
     90 
     91             /* Copy the received buffer into the receive buffer */
     92             memcpy(pSocket->sSocketRecvBuffer->buffer, psData->buffer, psData->length);
     93 
     94             /* Update the received length */
     95             *pSocket->receivedLength = psData->length;
     96 
     97             /* call the recv callback */
     98             pSocket->pfSocketRecvFrom_Cb(pSocket->pRecvContext, ssap, NFCSTATUS_SUCCESS);
     99             pSocket->pfSocketRecvFrom_Cb = NULL;
    100          }
    101          /* If no read is pending, try to bufferize for later reading */
    102          else
    103          {
    104             if((pSocket->indexRwWrite - pSocket->indexRwRead) < pSocket->localRW)
    105             {
    106                writeIndex = pSocket->indexRwWrite % pSocket->localRW;
    107                /* Save SSAP */
    108                pSocket->sSocketRwBufferTable[writeIndex].buffer[0] = ssap;
    109                /* Save UI frame payload */
    110                memcpy(pSocket->sSocketRwBufferTable[writeIndex].buffer + 1,
    111                       psData->buffer,
    112                       psData->length);
    113                pSocket->sSocketRwBufferTable[writeIndex].length = psData->length;
    114 
    115                /* Update the RW write index */
    116                pSocket->indexRwWrite++;
    117             }
    118             else
    119             {
    120                /* Unable to bufferize the packet, drop it */
    121             }
    122          }
    123          break;
    124       }
    125    }
    126 }
    127 
    128 /* TODO: comment function phFriNfc_LlcpTransport_Connectionless_SendTo_CB */
    129 static void phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void*        pContext,
    130                                                             uint8_t      socketIndex,
    131                                                             NFCSTATUS    status)
    132 {
    133    phFriNfc_LlcpTransport_Socket_t *         pLlcpSocket = (phFriNfc_LlcpTransport_Socket_t*)pContext;
    134    pphFriNfc_LlcpTransportSocketSendCb_t     pfSavedCallback;
    135    void *                                    pSavedContext;
    136 
    137    /* Call the send callback */
    138    pfSavedCallback = pLlcpSocket->pfSocketSend_Cb;
    139    if (pfSavedCallback != NULL)
    140    {
    141       pLlcpSocket->pfSocketSend_Cb = NULL;
    142       pfSavedCallback(pLlcpSocket->pSendContext, status);
    143    }
    144 }
    145 
    146 static void phFriNfc_LlcpTransport_Connectionless_Abort(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket)
    147 {
    148    if (pLlcpSocket->pfSocketSend_Cb != NULL)
    149    {
    150       pLlcpSocket->pfSocketSend_Cb(pLlcpSocket->pSendContext, NFCSTATUS_ABORTED);
    151       pLlcpSocket->pSendContext = NULL;
    152       pLlcpSocket->pfSocketSend_Cb = NULL;
    153    }
    154    if (pLlcpSocket->pfSocketRecvFrom_Cb != NULL)
    155    {
    156       pLlcpSocket->pfSocketRecvFrom_Cb(pLlcpSocket->pRecvContext, 0, NFCSTATUS_ABORTED);
    157       pLlcpSocket->pRecvContext = NULL;
    158       pLlcpSocket->pfSocketRecvFrom_Cb = NULL;
    159       pLlcpSocket->pfSocketRecv_Cb = NULL;
    160    }
    161    pLlcpSocket->pAcceptContext = NULL;
    162    pLlcpSocket->pfSocketAccept_Cb = NULL;
    163    pLlcpSocket->pListenContext = NULL;
    164    pLlcpSocket->pfSocketListen_Cb = NULL;
    165    pLlcpSocket->pConnectContext = NULL;
    166    pLlcpSocket->pfSocketConnect_Cb = NULL;
    167    pLlcpSocket->pDisconnectContext = NULL;
    168    pLlcpSocket->pfSocketDisconnect_Cb = NULL;
    169 }
    170 
    171 /**
    172 * \ingroup grp_fri_nfc
    173 * \brief <b>Close a socket on a LLCP-connectionless device</b>.
    174 *
    175 * This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket.
    176 *
    177 * \param[in]  pLlcpSocket                    A pointer to a phFriNfc_LlcpTransport_Socket_t.
    178 
    179 * \retval NFCSTATUS_SUCCESS                  Operation successful.
    180 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
    181 *                                            could not be properly interpreted.
    182 * \retval NFCSTATUS_FAILED                   Operation failed.
    183 */
    184 NFCSTATUS phFriNfc_LlcpTransport_Connectionless_Close(phFriNfc_LlcpTransport_Socket_t*   pLlcpSocket)
    185 {
    186    /* Reset the pointer to the socket closed */
    187    pLlcpSocket->eSocket_State                      = phFriNfc_LlcpTransportSocket_eSocketDefault;
    188    pLlcpSocket->eSocket_Type                       = phFriNfc_LlcpTransport_eDefaultType;
    189    pLlcpSocket->pContext                           = NULL;
    190    pLlcpSocket->pSocketErrCb                       = NULL;
    191    pLlcpSocket->socket_sSap                        = PHFRINFC_LLCP_SAP_DEFAULT;
    192    pLlcpSocket->socket_dSap                        = PHFRINFC_LLCP_SAP_DEFAULT;
    193    pLlcpSocket->bSocketRecvPending                 = FALSE;
    194    pLlcpSocket->bSocketSendPending                 = FALSE;
    195    pLlcpSocket->bSocketListenPending               = FALSE;
    196    pLlcpSocket->bSocketDiscPending                 = FALSE;
    197    pLlcpSocket->RemoteBusyConditionInfo            = FALSE;
    198    pLlcpSocket->ReceiverBusyCondition              = FALSE;
    199    pLlcpSocket->socket_VS                          = 0;
    200    pLlcpSocket->socket_VSA                         = 0;
    201    pLlcpSocket->socket_VR                          = 0;
    202    pLlcpSocket->socket_VRA                         = 0;
    203 
    204    phFriNfc_LlcpTransport_Connectionless_Abort(pLlcpSocket);
    205 
    206    memset(&pLlcpSocket->sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t));
    207 
    208    if (pLlcpSocket->sServiceName.buffer != NULL) {
    209        phOsalNfc_FreeMemory(pLlcpSocket->sServiceName.buffer);
    210    }
    211    pLlcpSocket->sServiceName.buffer = NULL;
    212    pLlcpSocket->sServiceName.length = 0;
    213 
    214    return NFCSTATUS_SUCCESS;
    215 }
    216 
    217 /**
    218 * \ingroup grp_fri_nfc
    219 * \brief <b>Send data on a socket to a given destination SAP</b>.
    220 *
    221 * This function is used to write data on a socket to a given destination SAP.
    222 * This function can only be called on a connectionless socket.
    223 *
    224 *
    225 * \param[in]  pLlcpSocket        A pointer to a LlcpSocket created.
    226 * \param[in]  nSap               The destination SAP.
    227 * \param[in]  psBuffer           The buffer containing the data to send.
    228 * \param[in]  pSend_RspCb        The callback to be called when the
    229 *                                operation is completed.
    230 * \param[in]  pContext           Upper layer context to be returned in
    231 *                                the callback.
    232 *
    233 * \retval NFCSTATUS_SUCCESS                  Operation successful.
    234 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
    235 *                                            could not be properly interpreted.
    236 * \retval NFCSTATUS_PENDING                  Reception operation is in progress,
    237 *                                            pSend_RspCb will be called upon completion.
    238 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
    239 *                                            a valid type to perform the requsted operation.
    240 * \retval NFCSTATUS_NOT_INITIALISED          Indicates stack is not yet initialized.
    241 * \retval NFCSTATUS_SHUTDOWN                 Shutdown in progress.
    242 * \retval NFCSTATUS_FAILED                   Operation failed.
    243 */
    244 NFCSTATUS phFriNfc_LlcpTransport_Connectionless_SendTo(phFriNfc_LlcpTransport_Socket_t             *pLlcpSocket,
    245                                                        uint8_t                                     nSap,
    246                                                        phNfc_sData_t*                              psBuffer,
    247                                                        pphFriNfc_LlcpTransportSocketSendCb_t       pSend_RspCb,
    248                                                        void*                                       pContext)
    249 {
    250    NFCSTATUS status = NFCSTATUS_FAILED;
    251 
    252    /* Store send callback  and context*/
    253    pLlcpSocket->pfSocketSend_Cb = pSend_RspCb;
    254    pLlcpSocket->pSendContext    = pContext;
    255 
    256    /* Test if a send is already pending at transport level */
    257    if(pLlcpSocket->psTransport->bSendPending == TRUE)
    258    {
    259       /* Save the request so it can be handled in phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations() */
    260       pLlcpSocket->sSocketSendBuffer = *psBuffer;
    261       pLlcpSocket->socket_dSap      = nSap;
    262       status = NFCSTATUS_PENDING;
    263    }
    264    else
    265    {
    266       /* Fill the psLlcpHeader stuture with the DSAP,PTYPE and the SSAP */
    267       pLlcpSocket->sLlcpHeader.dsap  = nSap;
    268       pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_UI;
    269       pLlcpSocket->sLlcpHeader.ssap  = pLlcpSocket->socket_sSap;
    270 
    271       /* Send to data to the approiate socket */
    272       status =  phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport,
    273                                    &pLlcpSocket->sLlcpHeader,
    274                                    NULL,
    275                                    psBuffer,
    276                                    phFriNfc_LlcpTransport_Connectionless_SendTo_CB,
    277                                    pLlcpSocket->index,
    278                                    pLlcpSocket);
    279    }
    280 
    281    return status;
    282 }
    283 
    284 
    285  /**
    286 * \ingroup grp_lib_nfc
    287 * \brief <b>Read data on a socket and get the source SAP</b>.
    288 *
    289 * This function is the same as phLibNfc_Llcp_Recv, except that the callback includes
    290 * the source SAP. This functions can only be called on a connectionless socket.
    291 *
    292 *
    293 * \param[in]  pLlcpSocket        A pointer to a LlcpSocket created.
    294 * \param[in]  psBuffer           The buffer receiving the data.
    295 * \param[in]  pRecv_RspCb        The callback to be called when the
    296 *                                operation is completed.
    297 * \param[in]  pContext           Upper layer context to be returned in
    298 *                                the callback.
    299 *
    300 * \retval NFCSTATUS_SUCCESS                  Operation successful.
    301 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
    302 *                                            could not be properly interpreted.
    303 * \retval NFCSTATUS_PENDING                  Reception operation is in progress,
    304 *                                            pRecv_RspCb will be called upon completion.
    305 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
    306 *                                            a valid type to perform the requsted operation.
    307 * \retval NFCSTATUS_NOT_INITIALISED          Indicates stack is not yet initialized.
    308 * \retval NFCSTATUS_SHUTDOWN                 Shutdown in progress.
    309 * \retval NFCSTATUS_FAILED                   Operation failed.
    310 */
    311 NFCSTATUS phLibNfc_LlcpTransport_Connectionless_RecvFrom(phFriNfc_LlcpTransport_Socket_t                   *pLlcpSocket,
    312                                                          phNfc_sData_t*                                    psBuffer,
    313                                                          pphFriNfc_LlcpTransportSocketRecvFromCb_t         pRecv_Cb,
    314                                                          void                                              *pContext)
    315 {
    316    NFCSTATUS   status = NFCSTATUS_PENDING;
    317    uint8_t     readIndex;
    318    uint8_t     ssap;
    319 
    320    if(pLlcpSocket->bSocketRecvPending)
    321    {
    322       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
    323    }
    324    else
    325    {
    326       /* Check if pending packets in RW */
    327       if(pLlcpSocket->indexRwRead != pLlcpSocket->indexRwWrite)
    328       {
    329          readIndex = pLlcpSocket->indexRwRead % pLlcpSocket->localRW;
    330 
    331          /* Extract ssap and buffer from RW buffer */
    332          ssap = pLlcpSocket->sSocketRwBufferTable[readIndex].buffer[0];
    333          memcpy(psBuffer->buffer,
    334                 pLlcpSocket->sSocketRwBufferTable[readIndex].buffer + 1,
    335                 pLlcpSocket->sSocketRwBufferTable[readIndex].length);
    336          psBuffer->length = pLlcpSocket->sSocketRwBufferTable[readIndex].length;
    337 
    338          /* Reset RW buffer length */
    339          pLlcpSocket->sSocketRwBufferTable[readIndex].length = 0;
    340 
    341          /* Update Value Rw Read Index */
    342          pLlcpSocket->indexRwRead++;
    343 
    344          /* call the recv callback */
    345          pRecv_Cb(pContext, ssap, NFCSTATUS_SUCCESS);
    346 
    347          status = NFCSTATUS_SUCCESS;
    348       }
    349       /* Otherwise, wait for a packet to come */
    350       else
    351       {
    352          /* Store the callback and context*/
    353          pLlcpSocket->pfSocketRecvFrom_Cb  = pRecv_Cb;
    354          pLlcpSocket->pRecvContext         = pContext;
    355 
    356          /* Store the pointer to the receive buffer */
    357          pLlcpSocket->sSocketRecvBuffer   =  psBuffer;
    358          pLlcpSocket->receivedLength      =  &psBuffer->length;
    359 
    360          /* Set RecvPending to TRUE */
    361          pLlcpSocket->bSocketRecvPending = TRUE;
    362       }
    363    }
    364    return status;
    365 }
    366