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 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 */ 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 */ 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 */ 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 */ 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 */ 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 * */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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