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                                                            uint8_t      socketIndex,
34                                                            NFCSTATUS    status);
35
36NFCSTATUS 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 */
68void 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 */
129static 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
146static 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*/
184NFCSTATUS 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*/
244NFCSTATUS 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*/
311NFCSTATUS 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