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