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
32static void phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void*        pContext,
33                                                            NFCSTATUS    status);
34
35NFCSTATUS 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 */
66void 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 */
127static 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
143static 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*/
181NFCSTATUS 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*/
241NFCSTATUS 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*/
307NFCSTATUS 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