• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations(phFriNfc_LlcpTransport_Socket_t * pSocket)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 */
Handle_Connectionless_IncommingFrame(phFriNfc_LlcpTransport_t * pLlcpTransport,phNfc_sData_t * psData,uint8_t dsap,uint8_t ssap)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 */
phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void * pContext,NFCSTATUS status)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 
phFriNfc_LlcpTransport_Connectionless_Abort(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket)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 */
phFriNfc_LlcpTransport_Connectionless_Close(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket)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 */
phFriNfc_LlcpTransport_Connectionless_SendTo(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb,void * pContext)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 */
phLibNfc_LlcpTransport_Connectionless_RecvFrom(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb,void * pContext)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