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