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