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