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