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.c
19 * \brief
20 *
21 * Project: NFC-FRI
22 *
23 */
24
25 /*include files*/
26 #include <phOsalNfc.h>
27 #include <phLibNfcStatus.h>
28 #include <phLibNfc.h>
29 #include <phNfcLlcpTypes.h>
30 #include <phFriNfc_Llcp.h>
31 #include <phFriNfc_LlcpTransport.h>
32 #include <phFriNfc_LlcpTransport_Connectionless.h>
33 #include <phFriNfc_LlcpTransport_Connection.h>
34
35 /* local macros */
36
37 /* Check if (a <= x < b) */
38 #define IS_BETWEEN(x, a, b) (((x)>=(a)) && ((x)<(b)))
39
40
phFriNfc_LlcpTransport_AutoBind(phFriNfc_LlcpTransport_Socket_t * pSocket)41 static NFCSTATUS phFriNfc_LlcpTransport_AutoBind(phFriNfc_LlcpTransport_Socket_t *pSocket)
42 {
43 uint8_t i;
44 uint8_t sap;
45 phFriNfc_LlcpTransport_Socket_t* pSocketTable = pSocket->psTransport->pSocketTable;
46
47 /* Try all possible SAPs */
48 for(sap=PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST ; sap<PHFRINFC_LLCP_SAP_NUMBER ; sap++)
49 {
50 /* Go through socket list to check if current SAP is in use */
51 for(i=0 ; i<PHFRINFC_LLCP_NB_SOCKET_MAX ; i++)
52 {
53 if((pSocketTable[i].eSocket_State >= phFriNfc_LlcpTransportSocket_eSocketBound) &&
54 (pSocketTable[i].socket_sSap == sap))
55 {
56 /* SAP is already in use */
57 break;
58 }
59 }
60
61 if (i >= PHFRINFC_LLCP_NB_SOCKET_MAX)
62 {
63 /* No socket is using current SAP, proceed with binding */
64 pSocket->socket_sSap = sap;
65 pSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketBound;
66 return NFCSTATUS_SUCCESS;
67 }
68 }
69
70 /* If we reach this point, it means that no SAP is free */
71 return NFCSTATUS_INSUFFICIENT_RESOURCES;
72 }
73
74 /* TODO: comment function Transport recv CB */
phFriNfc_LlcpTransport__Recv_CB(void * pContext,phNfc_sData_t * psData,NFCSTATUS status)75 static void phFriNfc_LlcpTransport__Recv_CB(void *pContext,
76 phNfc_sData_t *psData,
77 NFCSTATUS status)
78 {
79 phFriNfc_Llcp_sPacketHeader_t sLlcpLocalHeader;
80 uint8_t dsap;
81 uint8_t ptype;
82 uint8_t ssap;
83
84 phFriNfc_LlcpTransport_t* pLlcpTransport = (phFriNfc_LlcpTransport_t*)pContext;
85
86 if(status != NFCSTATUS_SUCCESS)
87 {
88 pLlcpTransport->LinkStatusError = TRUE;
89 }
90 else
91 {
92 phFriNfc_Llcp_Buffer2Header( psData->buffer,0x00, &sLlcpLocalHeader);
93
94 dsap = (uint8_t)sLlcpLocalHeader.dsap;
95 ptype = (uint8_t)sLlcpLocalHeader.ptype;
96 ssap = (uint8_t)sLlcpLocalHeader.ssap;
97
98 /* Update the length value (without the header length) */
99 psData->length = psData->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE;
100
101 /* Update the buffer pointer */
102 psData->buffer = psData->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE;
103
104 switch(ptype)
105 {
106 /* Connectionless */
107 case PHFRINFC_LLCP_PTYPE_UI:
108 {
109 Handle_Connectionless_IncommingFrame(pLlcpTransport,
110 psData,
111 dsap,
112 ssap);
113 }break;
114
115 /* Connection oriented */
116 /* NOTE: forward reserved PTYPE to enable FRMR sending */
117 case PHFRINFC_LLCP_PTYPE_CONNECT:
118 case PHFRINFC_LLCP_PTYPE_CC:
119 case PHFRINFC_LLCP_PTYPE_DISC:
120 case PHFRINFC_LLCP_PTYPE_DM:
121 case PHFRINFC_LLCP_PTYPE_I:
122 case PHFRINFC_LLCP_PTYPE_RR:
123 case PHFRINFC_LLCP_PTYPE_RNR:
124 case PHFRINFC_LLCP_PTYPE_FRMR:
125 case PHFRINFC_LLCP_PTYPE_RESERVED1:
126 case PHFRINFC_LLCP_PTYPE_RESERVED2:
127 case PHFRINFC_LLCP_PTYPE_RESERVED3:
128 case PHFRINFC_LLCP_PTYPE_RESERVED4:
129 {
130 Handle_ConnectionOriented_IncommingFrame(pLlcpTransport,
131 psData,
132 dsap,
133 ptype,
134 ssap);
135 }break;
136 default:
137 {
138
139 }break;
140 }
141
142 /*Restart the Receive Loop */
143 status = phFriNfc_Llcp_Recv(pLlcpTransport->pLlcp,
144 phFriNfc_LlcpTransport__Recv_CB,
145 pLlcpTransport);
146 }
147 }
148
149
150 /* TODO: comment function Transport reset */
phFriNfc_LlcpTransport_Reset(phFriNfc_LlcpTransport_t * pLlcpTransport,phFriNfc_Llcp_t * pLlcp)151 NFCSTATUS phFriNfc_LlcpTransport_Reset (phFriNfc_LlcpTransport_t *pLlcpTransport,
152 phFriNfc_Llcp_t *pLlcp)
153 {
154 NFCSTATUS status = NFCSTATUS_SUCCESS;
155 uint8_t i;
156
157 /* Check for NULL pointers */
158 if(pLlcpTransport == NULL || pLlcp == NULL)
159 {
160 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
161 }
162 else
163 {
164 /* Reset Transport structure */
165 pLlcpTransport->pLlcp = pLlcp;
166 pLlcpTransport->LinkStatusError = FALSE;
167 pLlcpTransport->bSendPending = FALSE;
168 pLlcpTransport->bRecvPending = FALSE;
169 pLlcpTransport->bDmPending = FALSE;
170 pLlcpTransport->bFrmrPending = FALSE;
171 pLlcpTransport->socketIndex = FALSE;
172 pLlcpTransport->LinkStatusError = 0;
173
174
175 /* Reset all the socket info in the table */
176 for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++)
177 {
178 pLlcpTransport->pSocketTable[i].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault;
179 pLlcpTransport->pSocketTable[i].eSocket_Type = phFriNfc_LlcpTransport_eDefaultType;
180 pLlcpTransport->pSocketTable[i].index = i;
181 pLlcpTransport->pSocketTable[i].pContext = NULL;
182 pLlcpTransport->pSocketTable[i].pListenContext = NULL;
183 pLlcpTransport->pSocketTable[i].pAcceptContext = NULL;
184 pLlcpTransport->pSocketTable[i].pRejectContext = NULL;
185 pLlcpTransport->pSocketTable[i].pConnectContext = NULL;
186 pLlcpTransport->pSocketTable[i].pDisonnectContext = NULL;
187 pLlcpTransport->pSocketTable[i].pSendContext = NULL;
188 pLlcpTransport->pSocketTable[i].pRecvContext = NULL;
189 pLlcpTransport->pSocketTable[i].pSocketErrCb = NULL;
190 pLlcpTransport->pSocketTable[i].bufferLinearLength = 0;
191 pLlcpTransport->pSocketTable[i].bufferSendMaxLength = 0;
192 pLlcpTransport->pSocketTable[i].bufferRwMaxLength = 0;
193 pLlcpTransport->pSocketTable[i].ReceiverBusyCondition = FALSE;
194 pLlcpTransport->pSocketTable[i].RemoteBusyConditionInfo = FALSE;
195 pLlcpTransport->pSocketTable[i].socket_sSap = PHFRINFC_LLCP_SAP_DEFAULT;
196 pLlcpTransport->pSocketTable[i].socket_dSap = PHFRINFC_LLCP_SAP_DEFAULT;
197 pLlcpTransport->pSocketTable[i].bSocketRecvPending = FALSE;
198 pLlcpTransport->pSocketTable[i].bSocketSendPending = FALSE;
199 pLlcpTransport->pSocketTable[i].bSocketListenPending = FALSE;
200 pLlcpTransport->pSocketTable[i].bSocketDiscPending = FALSE;
201 pLlcpTransport->pSocketTable[i].bSocketConnectPending = FALSE;
202 pLlcpTransport->pSocketTable[i].bSocketAcceptPending = FALSE;
203 pLlcpTransport->pSocketTable[i].bSocketRRPending = FALSE;
204 pLlcpTransport->pSocketTable[i].bSocketRNRPending = FALSE;
205 pLlcpTransport->pSocketTable[i].psTransport = pLlcpTransport;
206 pLlcpTransport->pSocketTable[i].pfSocketSend_Cb = NULL;
207 pLlcpTransport->pSocketTable[i].pfSocketRecv_Cb = NULL;
208 pLlcpTransport->pSocketTable[i].pfSocketRecvFrom_Cb = NULL;
209 pLlcpTransport->pSocketTable[i].pfSocketListen_Cb = NULL;
210 pLlcpTransport->pSocketTable[i].pfSocketConnect_Cb = NULL;
211 pLlcpTransport->pSocketTable[i].pfSocketDisconnect_Cb = NULL;
212 pLlcpTransport->pSocketTable[i].socket_VS = 0;
213 pLlcpTransport->pSocketTable[i].socket_VSA = 0;
214 pLlcpTransport->pSocketTable[i].socket_VR = 0;
215 pLlcpTransport->pSocketTable[i].socket_VRA = 0;
216 pLlcpTransport->pSocketTable[i].remoteRW = 0;
217 pLlcpTransport->pSocketTable[i].localRW = 0;
218 pLlcpTransport->pSocketTable[i].remoteMIU = 0;
219 pLlcpTransport->pSocketTable[i].localMIUX = 0;
220 pLlcpTransport->pSocketTable[i].index = 0;
221 pLlcpTransport->pSocketTable[i].indexRwRead = 0;
222 pLlcpTransport->pSocketTable[i].indexRwWrite = 0;
223
224 memset(&pLlcpTransport->pSocketTable[i].sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t));
225
226 if (pLlcpTransport->pSocketTable[i].sServiceName.buffer != NULL) {
227 phOsalNfc_FreeMemory(pLlcpTransport->pSocketTable[i].sServiceName.buffer);
228 }
229 pLlcpTransport->pSocketTable[i].sServiceName.buffer = NULL;
230 pLlcpTransport->pSocketTable[i].sServiceName.length = 0;
231 }
232
233 /* Start The Receive Loop */
234 status = phFriNfc_Llcp_Recv(pLlcpTransport->pLlcp,
235 phFriNfc_LlcpTransport__Recv_CB,
236 pLlcpTransport);
237 }
238 return status;
239 }
240
241 /* TODO: comment function Transport CloseAll */
phFriNfc_LlcpTransport_CloseAll(phFriNfc_LlcpTransport_t * pLlcpTransport)242 NFCSTATUS phFriNfc_LlcpTransport_CloseAll (phFriNfc_LlcpTransport_t *pLlcpTransport)
243 {
244 NFCSTATUS status = NFCSTATUS_SUCCESS;
245 uint8_t i;
246
247 /* Check for NULL pointers */
248 if(pLlcpTransport == NULL)
249 {
250 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
251 }
252
253 /* Close all sockets */
254 for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++)
255 {
256 if(pLlcpTransport->pSocketTable[i].eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented)
257 {
258 switch(pLlcpTransport->pSocketTable[i].eSocket_State)
259 {
260 case phFriNfc_LlcpTransportSocket_eSocketConnected:
261 case phFriNfc_LlcpTransportSocket_eSocketConnecting:
262 case phFriNfc_LlcpTransportSocket_eSocketAccepted:
263 case phFriNfc_LlcpTransportSocket_eSocketDisconnected:
264 case phFriNfc_LlcpTransportSocket_eSocketDisconnecting:
265 case phFriNfc_LlcpTransportSocket_eSocketRejected:
266 phFriNfc_LlcpTransport_Close(&pLlcpTransport->pSocketTable[i]);
267 break;
268 default: break;
269 }
270 }
271 else
272 {
273 phFriNfc_LlcpTransport_Close(&pLlcpTransport->pSocketTable[i]);
274 }
275 }
276 return status;
277 }
278
279
280 /**
281 * \ingroup grp_lib_nfc
282 * \brief <b>Get the local options of a socket</b>.
283 *
284 * This function returns the local options (maximum packet size and receive window size) used
285 * for a given connection-oriented socket. This function shall not be used with connectionless
286 * sockets.
287 *
288 * \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
289 * \param[in] psLocalOptions A pointer to be filled with the local options of the socket.
290 *
291 * \retval NFCSTATUS_SUCCESS Operation successful.
292 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
293 * could not be properly interpreted.
294 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
295 * a valid type to perform the requsted operation.
296 * \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized.
297 * \retval NFCSTATUS_SHUTDOWN Shutdown in progress.
298 * \retval NFCSTATUS_FAILED Operation failed.
299 */
phFriNfc_LlcpTransport_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phLibNfc_Llcp_sSocketOptions_t * psLocalOptions)300 NFCSTATUS phFriNfc_LlcpTransport_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket,
301 phLibNfc_Llcp_sSocketOptions_t *psLocalOptions)
302 {
303 NFCSTATUS status = NFCSTATUS_SUCCESS;
304
305 /* Check for NULL pointers */
306 if (pLlcpSocket == NULL || psLocalOptions == NULL)
307 {
308 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
309 }
310 /* Test the socket type */
311 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
312 {
313 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
314 }
315 /* Test the socket state */
316 else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault)
317 {
318 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
319 }
320 else
321 {
322 status = phFriNfc_LlcpTransport_ConnectionOriented_SocketGetLocalOptions(pLlcpSocket,
323 psLocalOptions);
324 }
325
326 return status;
327 }
328
329
330 /**
331 * \ingroup grp_lib_nfc
332 * \brief <b>Get the local options of a socket</b>.
333 *
334 * This function returns the remote options (maximum packet size and receive window size) used
335 * for a given connection-oriented socket. This function shall not be used with connectionless
336 * sockets.
337 *
338 * \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
339 * \param[in] psRemoteOptions A pointer to be filled with the remote options of the socket.
340 *
341 * \retval NFCSTATUS_SUCCESS Operation successful.
342 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
343 * could not be properly interpreted.
344 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
345 * a valid type to perform the requsted operation.
346 * \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized.
347 * \retval NFCSTATUS_SHUTDOWN Shutdown in progress.
348 * \retval NFCSTATUS_FAILED Operation failed.
349 */
phFriNfc_LlcpTransport_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phLibNfc_Llcp_sSocketOptions_t * psRemoteOptions)350 NFCSTATUS phFriNfc_LlcpTransport_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
351 phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions)
352 {
353 NFCSTATUS status = NFCSTATUS_SUCCESS;
354
355 /* Check for NULL pointers */
356 if (pLlcpSocket == NULL || psRemoteOptions == NULL)
357 {
358 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
359 }
360 /* Test the socket type */
361 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
362 {
363 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
364 }
365 /* Test the socket state */
366 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected)
367 {
368 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
369 }
370 else
371 {
372 status = phFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(pLlcpSocket,
373 psRemoteOptions);
374 }
375
376 return status;
377 }
378
379 /**
380 * \ingroup grp_fri_nfc
381 * \brief <b>Create a socket on a LLCP-connected device</b>.
382 *
383 * This function creates a socket for a given LLCP link. Sockets can be of two types :
384 * connection-oriented and connectionless. If the socket is connection-oriented, the caller
385 * must provide a working buffer to the socket in order to handle incoming data. This buffer
386 * must be large enough to fit the receive window (RW * MIU), the remaining space being
387 * used as a linear buffer to store incoming data as a stream. Data will be readable later
388 * using the phLibNfc_LlcpTransport_Recv function.
389 * The options and working buffer are not required if the socket is used as a listening socket,
390 * since it cannot be directly used for communication.
391 *
392 * \param[in] pLlcpSocketTable A pointer to a table of PHFRINFC_LLCP_NB_SOCKET_DEFAULT sockets.
393 * \param[in] eType The socket type.
394 * \param[in] psOptions The options to be used with the socket.
395 * \param[in] psWorkingBuffer A working buffer to be used by the library.
396 * \param[out] pLlcpSocket A pointer on the socket to be filled with a
397 socket found on the socket table.
398 * \param[in] pErr_Cb The callback to be called each time the socket
399 * is in error.
400 * \param[in] pContext Upper layer context to be returned in the callback.
401 *
402 * \retval NFCSTATUS_SUCCESS Operation successful.
403 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
404 * could not be properly interpreted.
405 * \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW
406 * declared in the options.
407 * \retval NFCSTATUS_INSUFFICIENT_RESOURCES No more socket handle available.
408 * \retval NFCSTATUS_FAILED Operation failed.
409 * */
phFriNfc_LlcpTransport_Socket(phFriNfc_LlcpTransport_t * pLlcpTransport,phFriNfc_LlcpTransport_eSocketType_t eType,phFriNfc_LlcpTransport_sSocketOptions_t * psOptions,phNfc_sData_t * psWorkingBuffer,phFriNfc_LlcpTransport_Socket_t ** pLlcpSocket,pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb,void * pContext)410 NFCSTATUS phFriNfc_LlcpTransport_Socket(phFriNfc_LlcpTransport_t *pLlcpTransport,
411 phFriNfc_LlcpTransport_eSocketType_t eType,
412 phFriNfc_LlcpTransport_sSocketOptions_t *psOptions,
413 phNfc_sData_t *psWorkingBuffer,
414 phFriNfc_LlcpTransport_Socket_t **pLlcpSocket,
415 pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb,
416 void *pContext)
417 {
418 NFCSTATUS status = NFCSTATUS_SUCCESS;
419 phFriNfc_Llcp_sLinkParameters_t LlcpLinkParamInfo;
420 uint8_t index=0;
421 uint8_t cpt;
422
423 /* Check for NULL pointers */
424 if (((NULL == psOptions) && (eType != phFriNfc_LlcpTransport_eConnectionLess)) || ((psWorkingBuffer == NULL) && (eType != phFriNfc_LlcpTransport_eConnectionLess)) || pLlcpSocket == NULL || pErr_Cb == NULL || pContext == NULL || pLlcpTransport == NULL)
425 {
426 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
427 return status;
428 }
429 /* Test the socket type*/
430 else if(eType != phFriNfc_LlcpTransport_eConnectionOriented && eType != phFriNfc_LlcpTransport_eConnectionLess)
431 {
432 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
433 return status;
434 }
435
436 /* Get the local parameters of the LLCP Link */
437 status = phFriNfc_Llcp_GetLocalInfo(pLlcpTransport->pLlcp,&LlcpLinkParamInfo);
438 if(status != NFCSTATUS_SUCCESS)
439 {
440 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED);
441 }
442 else
443 {
444 /* Search a socket free in the Socket Table*/
445 do
446 {
447 if(pLlcpTransport->pSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault)
448 {
449 /* Set the socket pointer to socket of the table */
450 *pLlcpSocket = &pLlcpTransport->pSocketTable[index];
451
452 /* Store the socket info in the socket pointer */
453 pLlcpTransport->pSocketTable[index].eSocket_Type = eType;
454 pLlcpTransport->pSocketTable[index].pSocketErrCb = pErr_Cb;
455
456 /* Store the context of the upper layer */
457 pLlcpTransport->pSocketTable[index].pContext = pContext;
458
459 /* Set the pointers to the different working buffers */
460 if(pLlcpTransport->pSocketTable[index].eSocket_Type != phFriNfc_LlcpTransport_eConnectionLess)
461 {
462 /* Test the socket options */
463 if((psOptions->rw > PHFRINFC_LLCP_RW_MAX) && (eType == phFriNfc_LlcpTransport_eConnectionOriented))
464 {
465 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
466 }
467 /* Set socket options */
468 memcpy(&pLlcpTransport->pSocketTable[index].sSocketOption, psOptions, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t));
469
470 /* Set socket local params (MIUX & RW) */
471 pLlcpTransport->pSocketTable[index].localMIUX = (pLlcpTransport->pSocketTable[index].sSocketOption.miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK;
472 pLlcpTransport->pSocketTable[index].localRW = pLlcpTransport->pSocketTable[index].sSocketOption.rw & PHFRINFC_LLCP_TLV_RW_MASK;
473
474 /* Set the Max length for the Send and Receive Window Buffer */
475 pLlcpTransport->pSocketTable[index].bufferSendMaxLength = pLlcpTransport->pSocketTable[index].sSocketOption.miu;
476 pLlcpTransport->pSocketTable[index].bufferRwMaxLength = pLlcpTransport->pSocketTable[index].sSocketOption.miu * ((pLlcpTransport->pSocketTable[index].sSocketOption.rw & PHFRINFC_LLCP_TLV_RW_MASK));
477 pLlcpTransport->pSocketTable[index].bufferLinearLength = psWorkingBuffer->length - pLlcpTransport->pSocketTable[index].bufferSendMaxLength - pLlcpTransport->pSocketTable[index].bufferRwMaxLength;
478
479 /* Test the connection oriented buffers length */
480 if((pLlcpTransport->pSocketTable[index].bufferSendMaxLength + pLlcpTransport->pSocketTable[index].bufferRwMaxLength) > psWorkingBuffer->length
481 || ((pLlcpTransport->pSocketTable[index].bufferLinearLength < PHFRINFC_LLCP_MIU_DEFAULT) && (pLlcpTransport->pSocketTable[index].bufferLinearLength != 0)))
482 {
483 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_BUFFER_TOO_SMALL);
484 return status;
485 }
486
487 /* Set the pointer and the length for the Receive Window Buffer */
488 for(cpt=0;cpt<pLlcpTransport->pSocketTable[index].localRW;cpt++)
489 {
490 pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].buffer = psWorkingBuffer->buffer + (cpt*pLlcpTransport->pSocketTable[index].sSocketOption.miu);
491 pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].length = 0;
492 }
493
494 /* Set the pointer and the length for the Send Buffer */
495 pLlcpTransport->pSocketTable[index].sSocketSendBuffer.buffer = psWorkingBuffer->buffer + pLlcpTransport->pSocketTable[index].bufferRwMaxLength;
496 pLlcpTransport->pSocketTable[index].sSocketSendBuffer.length = pLlcpTransport->pSocketTable[index].bufferSendMaxLength;
497
498 /** Set the pointer and the length for the Linear Buffer */
499 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.buffer = psWorkingBuffer->buffer + pLlcpTransport->pSocketTable[index].bufferRwMaxLength + pLlcpTransport->pSocketTable[index].bufferSendMaxLength;
500 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length = pLlcpTransport->pSocketTable[index].bufferLinearLength;
501
502 if(pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length != 0)
503 {
504 /* Init Cyclic Fifo */
505 phFriNfc_Llcp_CyclicFifoInit(&pLlcpTransport->pSocketTable[index].sCyclicFifoBuffer,
506 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.buffer,
507 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length);
508 }
509 }
510 /* Store index of the socket */
511 pLlcpTransport->pSocketTable[index].index = index;
512
513 /* Set the socket into created state */
514 pLlcpTransport->pSocketTable[index].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketCreated;
515 return status;
516 }
517 else
518 {
519 index++;
520 }
521 }while(index<PHFRINFC_LLCP_NB_SOCKET_MAX);
522
523 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INSUFFICIENT_RESOURCES);
524 }
525 return status;
526 }
527
528 /**
529 * \ingroup grp_fri_nfc
530 * \brief <b>Close a socket on a LLCP-connected device</b>.
531 *
532 * This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket.
533 * If the socket was connected, it is first disconnected, and then closed.
534 *
535 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
536
537 * \retval NFCSTATUS_SUCCESS Operation successful.
538 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
539 * could not be properly interpreted.
540 * \retval NFCSTATUS_FAILED Operation failed.
541 */
phFriNfc_LlcpTransport_Close(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket)542 NFCSTATUS phFriNfc_LlcpTransport_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket)
543 {
544 NFCSTATUS status = NFCSTATUS_SUCCESS;
545
546 /* Check for NULL pointers */
547 if( pLlcpSocket == NULL)
548 {
549 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
550 }
551 else if(pLlcpSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented)
552 {
553 status = phFriNfc_LlcpTransport_ConnectionOriented_Close(pLlcpSocket);
554 }
555 else if(pLlcpSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionLess)
556 {
557 status = phFriNfc_LlcpTransport_Connectionless_Close(pLlcpSocket);
558 }
559 else
560 {
561 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
562 }
563
564 return status;
565 }
566
567 /**
568 * \ingroup grp_fri_nfc
569 * \brief <b>Bind a socket to a local SAP</b>.
570 *
571 * This function binds the socket to a local Service Access Point.
572 *
573 * \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
574 * \param[in] pConfigInfo A port number for a specific socket
575 *
576 * \retval NFCSTATUS_SUCCESS Operation successful.
577 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
578 * could not be properly interpreted.
579 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
580 * a valid type to perform the requsted operation.
581 * \retval NFCSTATUS_ALREADY_REGISTERED The selected SAP is already bound to another
582 socket.
583 * \retval NFCSTATUS_FAILED Operation failed.
584 */
585
phFriNfc_LlcpTransport_Bind(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap)586 NFCSTATUS phFriNfc_LlcpTransport_Bind(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket,
587 uint8_t nSap)
588 {
589 NFCSTATUS status = NFCSTATUS_SUCCESS;
590 uint8_t i;
591
592 /* Check for NULL pointers */
593 if(pLlcpSocket == NULL)
594 {
595 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
596 }
597 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketCreated)
598 {
599 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
600 }
601 else if(nSap<2 || nSap>63)
602 {
603 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
604 }
605 else
606 {
607 /* Test if the nSap it is useb by another socket */
608 for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++)
609 {
610 if((pLlcpSocket->psTransport->pSocketTable[i].socket_sSap == nSap)
611 && (pLlcpSocket->psTransport->pSocketTable[i].eSocket_Type == pLlcpSocket->eSocket_Type))
612 {
613 return status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_ALREADY_REGISTERED);
614 }
615 }
616 /* Set the nSap value of the socket */
617 pLlcpSocket->socket_sSap = nSap;
618 /* Set the socket state */
619 pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketBound;
620 }
621 return status;
622 }
623
624 /*********************************************/
625 /* ConnectionOriented */
626 /*********************************************/
627
628 /**
629 * \ingroup grp_fri_nfc
630 * \brief <b>Listen for incoming connection requests on a socket</b>.
631 *
632 * This function switches a socket into a listening state and registers a callback on
633 * incoming connection requests. In this state, the socket is not able to communicate
634 * directly. The listening state is only available for connection-oriented sockets
635 * which are still not connected. The socket keeps listening until it is closed, and
636 * thus can trigger several times the pListen_Cb callback.
637 *
638 *
639 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
640 * \param[in] psServiceName A pointer to Service Name
641 * \param[in] pListen_Cb The callback to be called each time the
642 * socket receive a connection request.
643 * \param[in] pContext Upper layer context to be returned in
644 * the callback.
645 *
646 * \retval NFCSTATUS_SUCCESS Operation successful.
647 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
648 * could not be properly interpreted.
649 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state to switch
650 * to listening state.
651 * \retval NFCSTATUS_FAILED Operation failed.
652 */
phFriNfc_LlcpTransport_Listen(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psServiceName,pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb,void * pContext)653 NFCSTATUS phFriNfc_LlcpTransport_Listen(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
654 phNfc_sData_t *psServiceName,
655 pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb,
656 void* pContext)
657 {
658 NFCSTATUS status = NFCSTATUS_SUCCESS;
659
660 /* Check for NULL pointers */
661 if(pLlcpSocket == NULL || pListen_Cb == NULL|| pContext == NULL || psServiceName == NULL)
662 {
663 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
664 }
665 /* Check for socket state */
666 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
667 {
668 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
669 }
670 /* Check for socket type */
671 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
672 {
673 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
674 }
675 /* Test if a listen is not pending with this socket */
676 else if(pLlcpSocket->bSocketListenPending)
677 {
678 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
679 }
680 /* Test the length of the SN */
681 else if(psServiceName->length > PHFRINFC_LLCP_SN_MAX_LENGTH)
682 {
683 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
684 }
685 /* Test the SAP range for SDP-advertised services */
686 else if((psServiceName->length > 0) &&
687 (!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST)) &&
688 (!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_WKS_FIRST, PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST)))
689 {
690 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
691 }
692 /* Test the SAP range for non SDP-advertised services */
693 else if((psServiceName->length == 0) &&
694 (!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST, PHFRINFC_LLCP_SAP_NUMBER)) &&
695 (!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_WKS_FIRST, PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST)))
696 {
697 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
698 }
699 else
700 {
701 status = phFriNfc_LlcpTransport_ConnectionOriented_Listen(pLlcpSocket,
702 psServiceName,
703 pListen_Cb,
704 pContext);
705 }
706 return status;
707 }
708
709 /**
710 * \ingroup grp_fri_nfc
711 * \brief <b>Accept an incoming connection request for a socket</b>.
712 *
713 * This functions allows the client to accept an incoming connection request.
714 * It must be used with the socket provided within the listen callback. The socket
715 * is implicitly switched to the connected state when the function is called.
716 *
717 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
718 * \param[in] psOptions The options to be used with the socket.
719 * \param[in] psWorkingBuffer A working buffer to be used by the library.
720 * \param[in] pErr_Cb The callback to be called each time the accepted socket
721 * is in error.
722 * \param[in] pContext Upper layer context to be returned in the callback.
723 *
724 * \retval NFCSTATUS_SUCCESS Operation successful.
725 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
726 * could not be properly interpreted.
727 * \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW
728 * declared in the options.
729 * \retval NFCSTATUS_FAILED Operation failed.
730 */
phFriNfc_LlcpTransport_Accept(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phFriNfc_LlcpTransport_sSocketOptions_t * psOptions,phNfc_sData_t * psWorkingBuffer,pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb,pphFriNfc_LlcpTransportSocketAcceptCb_t pAccept_RspCb,void * pContext)731 NFCSTATUS phFriNfc_LlcpTransport_Accept(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
732 phFriNfc_LlcpTransport_sSocketOptions_t* psOptions,
733 phNfc_sData_t* psWorkingBuffer,
734 pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb,
735 pphFriNfc_LlcpTransportSocketAcceptCb_t pAccept_RspCb,
736 void* pContext)
737 {
738 NFCSTATUS status = NFCSTATUS_SUCCESS;
739
740 /* Check for NULL pointers */
741 if(pLlcpSocket == NULL || psOptions == NULL || psWorkingBuffer == NULL || pErr_Cb == NULL || pContext == NULL)
742 {
743 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
744 }
745 /* Check for socket state */
746 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
747 {
748 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
749 }
750 /* Check for socket type */
751 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
752 {
753 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
754 }
755 /* Test the socket options */
756 else if(psOptions->rw > PHFRINFC_LLCP_RW_MAX)
757 {
758 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
759 }
760 else
761 {
762 /* Set the Max length for the Send and Receive Window Buffer */
763 pLlcpSocket->bufferSendMaxLength = psOptions->miu;
764 pLlcpSocket->bufferRwMaxLength = psOptions->miu * ((psOptions->rw & PHFRINFC_LLCP_TLV_RW_MASK));
765 pLlcpSocket->bufferLinearLength = psWorkingBuffer->length - pLlcpSocket->bufferSendMaxLength - pLlcpSocket->bufferRwMaxLength;
766
767 /* Test the buffers length */
768 if((pLlcpSocket->bufferSendMaxLength + pLlcpSocket->bufferRwMaxLength) > psWorkingBuffer->length
769 || ((pLlcpSocket->bufferLinearLength < PHFRINFC_LLCP_MIU_DEFAULT) && (pLlcpSocket->bufferLinearLength != 0)))
770 {
771 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_BUFFER_TOO_SMALL);
772 }
773 else
774 {
775 pLlcpSocket->psTransport->socketIndex = pLlcpSocket->index;
776
777 status = phFriNfc_LlcpTransport_ConnectionOriented_Accept(pLlcpSocket,
778 psOptions,
779 psWorkingBuffer,
780 pErr_Cb,
781 pAccept_RspCb,
782 pContext);
783 }
784 }
785 return status;
786 }
787
788 /**
789 * \ingroup grp_fri_nfc
790 * \brief <b>Reject an incoming connection request for a socket</b>.
791 *
792 * This functions allows the client to reject an incoming connection request.
793 * It must be used with the socket provided within the listen callback. The socket
794 * is implicitly closed when the function is called.
795 *
796 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
797 * \param[in] pReject_RspCb The callback to be call when the Reject operation is completed
798 * \param[in] pContext Upper layer context to be returned in the callback.
799 *
800 * \retval NFCSTATUS_SUCCESS Operation successful.
801 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
802 * could not be properly interpreted.
803 * \retval NFCSTATUS_FAILED Operation failed.
804 */
phFriNfc_LlcpTransport_Reject(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,pphFriNfc_LlcpTransportSocketRejectCb_t pReject_RspCb,void * pContext)805 NFCSTATUS phFriNfc_LlcpTransport_Reject( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
806 pphFriNfc_LlcpTransportSocketRejectCb_t pReject_RspCb,
807 void *pContext)
808 {
809 NFCSTATUS status = NFCSTATUS_SUCCESS;
810
811 /* Check for NULL pointers */
812 if(pLlcpSocket == NULL)
813 {
814 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
815 }
816 /* Check for socket state */
817 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
818 {
819 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
820 }
821 /* Check for socket type */
822 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
823 {
824 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
825 }
826 else
827 {
828 status = phLibNfc_LlcpTransport_ConnectionOriented_Reject(pLlcpSocket,
829 pReject_RspCb,
830 pContext);
831 }
832
833 return status;
834 }
835
836 /**
837 * \ingroup grp_fri_nfc
838 * \brief <b>Try to establish connection with a socket on a remote SAP</b>.
839 *
840 * This function tries to connect to a given SAP on the remote peer. If the
841 * socket is not bound to a local SAP, it is implicitly bound to a free SAP.
842 *
843 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
844 * \param[in] nSap The destination SAP to connect to.
845 * \param[in] pConnect_RspCb The callback to be called when the connection
846 * operation is completed.
847 * \param[in] pContext Upper layer context to be returned in
848 * the callback.
849 *
850 * \retval NFCSTATUS_SUCCESS Operation successful.
851 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
852 * could not be properly interpreted.
853 * \retval NFCSTATUS_PENDING Connection operation is in progress,
854 * pConnect_RspCb will be called upon completion.
855 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
856 * a valid type to perform the requsted operation.
857 * \retval NFCSTATUS_FAILED Operation failed.
858 */
phFriNfc_LlcpTransport_Connect(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap,pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb,void * pContext)859 NFCSTATUS phFriNfc_LlcpTransport_Connect( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
860 uint8_t nSap,
861 pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb,
862 void* pContext)
863 {
864 NFCSTATUS status = NFCSTATUS_SUCCESS;
865 uint8_t i;
866
867 /* Check for NULL pointers */
868 if(pLlcpSocket == NULL || pConnect_RspCb == NULL || pContext == NULL)
869 {
870 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
871 }
872 /* Test the port number value */
873 else if(nSap<02 || nSap>63)
874 {
875 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
876 }
877 /* Test if the socket is a connectionOriented socket */
878 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
879 {
880 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
881 }
882
883 /* Test if the socket is not in connecting or connected state*/
884 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketCreated && pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
885 {
886 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
887 }
888 else
889 {
890 /* Implicit bind if socket is not already bound */
891 if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
892 {
893 status = phFriNfc_LlcpTransport_AutoBind(pLlcpSocket);
894 if (status != NFCSTATUS_SUCCESS)
895 {
896 return status;
897 }
898 }
899
900 /* Test the SAP range for non SDP-advertised services */
901 if(!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST, PHFRINFC_LLCP_SAP_NUMBER))
902 {
903 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
904 }
905 else
906 {
907 status = phFriNfc_LlcpTransport_ConnectionOriented_Connect(pLlcpSocket,
908 nSap,
909 NULL,
910 pConnect_RspCb,
911 pContext);
912 }
913 }
914
915 return status;
916 }
917
918 /**
919 * \ingroup grp_fri_nfc
920 * \brief <b>Try to establish connection with a socket on a remote service, given its URI</b>.
921 *
922 * This function tries to connect to a SAP designated by an URI. If the
923 * socket is not bound to a local SAP, it is implicitly bound to a free SAP.
924 *
925 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
926 * \param[in] psUri The URI corresponding to the destination SAP to connect to.
927 * \param[in] pConnect_RspCb The callback to be called when the connection
928 * operation is completed.
929 * \param[in] pContext Upper layer context to be returned in
930 * the callback.
931 *
932 * \retval NFCSTATUS_SUCCESS Operation successful.
933 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
934 * could not be properly interpreted.
935 * \retval NFCSTATUS_PENDING Connection operation is in progress,
936 * pConnect_RspCb will be called upon completion.
937 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
938 * a valid type to perform the requsted operation.
939 * \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized.
940 * \retval NFCSTATUS_SHUTDOWN Shutdown in progress.
941 * \retval NFCSTATUS_FAILED Operation failed.
942 */
phFriNfc_LlcpTransport_ConnectByUri(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psUri,pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb,void * pContext)943 NFCSTATUS phFriNfc_LlcpTransport_ConnectByUri(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
944 phNfc_sData_t* psUri,
945 pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb,
946 void* pContext)
947 {
948 NFCSTATUS status = NFCSTATUS_SUCCESS;
949 uint8_t i;
950
951 /* Check for NULL pointers */
952 if(pLlcpSocket == NULL || pConnect_RspCb == NULL || pContext == NULL)
953 {
954 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
955 }
956 /* Test if the socket is a connectionOriented socket */
957 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
958 {
959 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
960 }
961 /* Test if the socket is not in connect pending or connected state*/
962 else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnecting || pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected)
963 {
964 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
965 }
966 /* Test the length of the SN */
967 else if(psUri->length > PHFRINFC_LLCP_SN_MAX_LENGTH)
968 {
969 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
970 }
971 else
972 {
973 /* Implicit bind if socket is not already bound */
974 if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
975 {
976 status = phFriNfc_LlcpTransport_AutoBind(pLlcpSocket);
977 if (status != NFCSTATUS_SUCCESS)
978 {
979 return status;
980 }
981 }
982
983 /* Test the SAP range for non SDP-advertised services */
984 if(!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST, PHFRINFC_LLCP_SAP_NUMBER))
985 {
986 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
987 }
988 else
989 {
990 status = phFriNfc_LlcpTransport_ConnectionOriented_Connect(pLlcpSocket,
991 PHFRINFC_LLCP_SAP_DEFAULT,
992 psUri,
993 pConnect_RspCb,
994 pContext);
995 }
996 }
997
998 return status;
999 }
1000
1001 /**
1002 * \ingroup grp_lib_nfc
1003 * \brief <b>Disconnect a currently connected socket</b>.
1004 *
1005 * This function initiates the disconnection of a previously connected socket.
1006 *
1007 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
1008 * \param[in] pDisconnect_RspCb The callback to be called when the
1009 * operation is completed.
1010 * \param[in] pContext Upper layer context to be returned in
1011 * the callback.
1012 *
1013 * \retval NFCSTATUS_SUCCESS Operation successful.
1014 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
1015 * could not be properly interpreted.
1016 * \retval NFCSTATUS_PENDING Disconnection operation is in progress,
1017 * pDisconnect_RspCb will be called upon completion.
1018 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
1019 * a valid type to perform the requsted operation.
1020 * \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized.
1021 * \retval NFCSTATUS_SHUTDOWN Shutdown in progress.
1022 * \retval NFCSTATUS_FAILED Operation failed.
1023 */
phFriNfc_LlcpTransport_Disconnect(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb,void * pContext)1024 NFCSTATUS phFriNfc_LlcpTransport_Disconnect(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
1025 pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb,
1026 void* pContext)
1027 {
1028 NFCSTATUS status = NFCSTATUS_SUCCESS;
1029
1030 /* Check for NULL pointers */
1031 if(pLlcpSocket == NULL || pDisconnect_RspCb == NULL || pContext == NULL)
1032 {
1033 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1034 }
1035 /* Test if the socket is a connectionOriented socket */
1036 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
1037 {
1038 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1039 }
1040 /* Test if the socket is connected state*/
1041 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected)
1042 {
1043 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1044 }
1045 else
1046 {
1047 status = phLibNfc_LlcpTransport_ConnectionOriented_Disconnect(pLlcpSocket,
1048 pDisconnect_RspCb,
1049 pContext);
1050 }
1051
1052 return status;
1053 }
1054
1055 /**
1056 * \ingroup grp_fri_nfc
1057 * \brief <b>Send data on a socket</b>.
1058 *
1059 * This function is used to write data on a socket. This function
1060 * can only be called on a connection-oriented socket which is already
1061 * in a connected state.
1062 *
1063 *
1064 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
1065 * \param[in] psBuffer The buffer containing the data to send.
1066 * \param[in] pSend_RspCb The callback to be called when the
1067 * operation is completed.
1068 * \param[in] pContext Upper layer context to be returned in
1069 * the callback.
1070 *
1071 * \retval NFCSTATUS_SUCCESS Operation successful.
1072 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
1073 * could not be properly interpreted.
1074 * \retval NFCSTATUS_PENDING Reception operation is in progress,
1075 * pSend_RspCb will be called upon completion.
1076 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
1077 * a valid type to perform the requsted operation.
1078 * \retval NFCSTATUS_FAILED Operation failed.
1079 */
phFriNfc_LlcpTransport_Send(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb,void * pContext)1080 NFCSTATUS phFriNfc_LlcpTransport_Send(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
1081 phNfc_sData_t* psBuffer,
1082 pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb,
1083 void* pContext)
1084 {
1085 NFCSTATUS status = NFCSTATUS_SUCCESS;
1086
1087 /* Check for NULL pointers */
1088 if(pLlcpSocket == NULL || psBuffer == NULL || pSend_RspCb == NULL || pContext == NULL)
1089 {
1090 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1091 }
1092 /* Test if the socket is a connectionOriented socket */
1093 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
1094 {
1095 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1096 }
1097 /* Test if the socket is in connected state */
1098 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected)
1099 {
1100 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
1101 }
1102 /* Test the length of the buffer */
1103 else if(psBuffer->length > pLlcpSocket->remoteMIU )
1104 {
1105 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1106 }
1107 /* Test if a send is pending */
1108 else if(pLlcpSocket->pfSocketSend_Cb != NULL)
1109 {
1110 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
1111 }
1112 else
1113 {
1114 status = phFriNfc_LlcpTransport_ConnectionOriented_Send(pLlcpSocket,
1115 psBuffer,
1116 pSend_RspCb,
1117 pContext);
1118 }
1119
1120 return status;
1121 }
1122
1123 /**
1124 * \ingroup grp_fri_nfc
1125 * \brief <b>Read data on a socket</b>.
1126 *
1127 * This function is used to read data from a socket. It reads at most the
1128 * size of the reception buffer, but can also return less bytes if less bytes
1129 * are available. If no data is available, the function will be pending until
1130 * more data comes, and the response will be sent by the callback. This function
1131 * can only be called on a connection-oriented socket.
1132 *
1133 *
1134 * \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t.
1135 * \param[in] psBuffer The buffer receiving the data.
1136 * \param[in] pRecv_RspCb The callback to be called when the
1137 * operation is completed.
1138 * \param[in] pContext Upper layer context to be returned in
1139 * the callback.
1140 *
1141 * \retval NFCSTATUS_SUCCESS Operation successful.
1142 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
1143 * could not be properly interpreted.
1144 * \retval NFCSTATUS_PENDING Reception operation is in progress,
1145 * pRecv_RspCb will be called upon completion.
1146 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
1147 * a valid type to perform the requsted operation.
1148 * \retval NFCSTATUS_FAILED Operation failed.
1149 */
phFriNfc_LlcpTransport_Recv(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketRecvCb_t pRecv_RspCb,void * pContext)1150 NFCSTATUS phFriNfc_LlcpTransport_Recv( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,
1151 phNfc_sData_t* psBuffer,
1152 pphFriNfc_LlcpTransportSocketRecvCb_t pRecv_RspCb,
1153 void* pContext)
1154 {
1155 NFCSTATUS status = NFCSTATUS_SUCCESS;
1156
1157 /* Check for NULL pointers */
1158 if(pLlcpSocket == NULL || psBuffer == NULL || pRecv_RspCb == NULL || pContext == NULL)
1159 {
1160 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1161 }
1162 /* Test if the socket is a connectionOriented socket */
1163 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
1164 {
1165 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1166 }
1167 /* Test if the socket is in connected state */
1168 else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault)
1169 {
1170 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1171 }
1172 /* Test if a receive is pending */
1173 else if(pLlcpSocket->bSocketRecvPending == TRUE)
1174 {
1175 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
1176 }
1177 else
1178 {
1179 status = phFriNfc_LlcpTransport_ConnectionOriented_Recv(pLlcpSocket,
1180 psBuffer,
1181 pRecv_RspCb,
1182 pContext);
1183 }
1184
1185 return status;
1186 }
1187
1188 /*****************************************/
1189 /* ConnectionLess */
1190 /*****************************************/
1191
1192 /**
1193 * \ingroup grp_fri_nfc
1194 * \brief <b>Send data on a socket to a given destination SAP</b>.
1195 *
1196 * This function is used to write data on a socket to a given destination SAP.
1197 * This function can only be called on a connectionless socket.
1198 *
1199 *
1200 * \param[in] pLlcpSocket A pointer to a LlcpSocket created.
1201 * \param[in] nSap The destination SAP.
1202 * \param[in] psBuffer The buffer containing the data to send.
1203 * \param[in] pSend_RspCb The callback to be called when the
1204 * operation is completed.
1205 * \param[in] pContext Upper layer context to be returned in
1206 * the callback.
1207 *
1208 * \retval NFCSTATUS_SUCCESS Operation successful.
1209 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
1210 * could not be properly interpreted.
1211 * \retval NFCSTATUS_PENDING Reception operation is in progress,
1212 * pSend_RspCb will be called upon completion.
1213 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
1214 * a valid type to perform the requsted operation.
1215 * \retval NFCSTATUS_FAILED Operation failed.
1216 */
phFriNfc_LlcpTransport_SendTo(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb,void * pContext)1217 NFCSTATUS phFriNfc_LlcpTransport_SendTo( phFriNfc_LlcpTransport_Socket_t *pLlcpSocket,
1218 uint8_t nSap,
1219 phNfc_sData_t *psBuffer,
1220 pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb,
1221 void* pContext)
1222 {
1223 NFCSTATUS status = NFCSTATUS_SUCCESS;
1224 phFriNfc_Llcp_sLinkParameters_t LlcpRemoteLinkParamInfo;
1225
1226 if(pLlcpSocket == NULL || psBuffer == NULL || pSend_RspCb == NULL || pContext == NULL)
1227 {
1228 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1229 }
1230 /* Test the port number value */
1231 else if(nSap<2 || nSap>63)
1232 {
1233 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1234 }
1235 /* Test if the socket is a connectionless socket */
1236 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionLess)
1237 {
1238 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1239 }
1240 /* Test if the socket is in an updated state */
1241 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
1242 {
1243 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
1244 }
1245 else
1246 {
1247 /* Get the local parameters of the LLCP Link */
1248 status = phFriNfc_Llcp_GetRemoteInfo(pLlcpSocket->psTransport->pLlcp,&LlcpRemoteLinkParamInfo);
1249 if(status != NFCSTATUS_SUCCESS)
1250 {
1251 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED);
1252 }
1253 /* Test the length of the socket buffer for ConnectionLess mode*/
1254 else if(psBuffer->length > LlcpRemoteLinkParamInfo.miu)
1255 {
1256 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1257 }
1258 /* Test if the link is in error state */
1259 else if(pLlcpSocket->psTransport->LinkStatusError)
1260 {
1261 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
1262 }
1263 else
1264 {
1265 status = phFriNfc_LlcpTransport_Connectionless_SendTo(pLlcpSocket,
1266 nSap,
1267 psBuffer,
1268 pSend_RspCb,
1269 pContext);
1270 }
1271 }
1272
1273 return status;
1274 }
1275
1276
1277 /**
1278 * \ingroup grp_lib_nfc
1279 * \brief <b>Read data on a socket and get the source SAP</b>.
1280 *
1281 * This function is the same as phLibNfc_Llcp_Recv, except that the callback includes
1282 * the source SAP. This functions can only be called on a connectionless socket.
1283 *
1284 *
1285 * \param[in] pLlcpSocket A pointer to a LlcpSocket created.
1286 * \param[in] psBuffer The buffer receiving the data.
1287 * \param[in] pRecv_RspCb The callback to be called when the
1288 * operation is completed.
1289 * \param[in] pContext Upper layer context to be returned in
1290 * the callback.
1291 *
1292 * \retval NFCSTATUS_SUCCESS Operation successful.
1293 * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
1294 * could not be properly interpreted.
1295 * \retval NFCSTATUS_PENDING Reception operation is in progress,
1296 * pRecv_RspCb will be called upon completion.
1297 * \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of
1298 * a valid type to perform the requsted operation.
1299 * \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized.
1300 * \retval NFCSTATUS_SHUTDOWN Shutdown in progress.
1301 * \retval NFCSTATUS_FAILED Operation failed.
1302 */
phFriNfc_LlcpTransport_RecvFrom(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb,void * pContext)1303 NFCSTATUS phFriNfc_LlcpTransport_RecvFrom( phFriNfc_LlcpTransport_Socket_t *pLlcpSocket,
1304 phNfc_sData_t* psBuffer,
1305 pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb,
1306 void* pContext)
1307 {
1308 NFCSTATUS status = NFCSTATUS_SUCCESS;
1309 if(pLlcpSocket == NULL || psBuffer == NULL || pRecv_Cb == NULL || pContext == NULL)
1310 {
1311 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1312 }
1313 /* Test if the socket is a connectionless socket */
1314 else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionLess)
1315 {
1316 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
1317 }
1318 /* Test if the socket is in an updated state */
1319 else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
1320 {
1321 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
1322 }
1323 else
1324 {
1325 if(pLlcpSocket->bSocketRecvPending)
1326 {
1327 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
1328 }
1329 else
1330 {
1331 status = phLibNfc_LlcpTransport_Connectionless_RecvFrom(pLlcpSocket,
1332 psBuffer,
1333 pRecv_Cb,
1334 pContext);
1335 }
1336 }
1337
1338 return status;
1339 }
1340