1/* 2 * Copyright (C) 2010 NXP Semiconductors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/** 18 * \file phFriNfc_LlcpTransport_Connectionless.c 19 * \brief 20 * 21 * Project: NFC-FRI 22 * 23 */ 24/*include files*/ 25#include <phOsalNfc.h> 26#include <phLibNfcStatus.h> 27#include <phLibNfc.h> 28#include <phNfcLlcpTypes.h> 29#include <phFriNfc_LlcpTransport.h> 30#include <phFriNfc_Llcp.h> 31 32static void phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void* pContext, 33 NFCSTATUS status); 34 35NFCSTATUS phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations(phFriNfc_LlcpTransport_Socket_t *pSocket) 36{ 37 NFCSTATUS status = NFCSTATUS_FAILED; 38 39 /* Check if something is pending and if transport layer is ready to send */ 40 if ((pSocket->pfSocketSend_Cb != NULL) && 41 (pSocket->psTransport->bSendPending == FALSE)) 42 { 43 /* Fill the psLlcpHeader stuture with the DSAP,PTYPE and the SSAP */ 44 pSocket->sLlcpHeader.dsap = pSocket->socket_dSap; 45 pSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_UI; 46 pSocket->sLlcpHeader.ssap = pSocket->socket_sSap; 47 48 /* Send to data to the approiate socket */ 49 status = phFriNfc_LlcpTransport_LinkSend(pSocket->psTransport, 50 &pSocket->sLlcpHeader, 51 NULL, 52 &pSocket->sSocketSendBuffer, 53 phFriNfc_LlcpTransport_Connectionless_SendTo_CB, 54 pSocket); 55 } 56 else 57 { 58 /* Cannot send now, retry later */ 59 } 60 61 return status; 62} 63 64 65/* TODO: comment function Handle_Connectionless_IncommingFrame */ 66void Handle_Connectionless_IncommingFrame(phFriNfc_LlcpTransport_t *pLlcpTransport, 67 phNfc_sData_t *psData, 68 uint8_t dsap, 69 uint8_t ssap) 70{ 71 phFriNfc_LlcpTransport_Socket_t * pSocket = NULL; 72 uint8_t i = 0; 73 uint8_t writeIndex; 74 75 /* Look through the socket table for a match */ 76 for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++) 77 { 78 if(pLlcpTransport->pSocketTable[i].socket_sSap == dsap) 79 { 80 /* Socket found ! */ 81 pSocket = &pLlcpTransport->pSocketTable[i]; 82 83 /* Forward directly to application if a read is pending */ 84 if (pSocket->bSocketRecvPending == TRUE) 85 { 86 /* Reset the RecvPending variable */ 87 pSocket->bSocketRecvPending = FALSE; 88 89 /* Copy the received buffer into the receive buffer */ 90 memcpy(pSocket->sSocketRecvBuffer->buffer, psData->buffer, psData->length); 91 92 /* Update the received length */ 93 *pSocket->receivedLength = psData->length; 94 95 /* call the recv callback */ 96 pSocket->pfSocketRecvFrom_Cb(pSocket->pRecvContext, ssap, NFCSTATUS_SUCCESS); 97 pSocket->pfSocketRecvFrom_Cb = NULL; 98 } 99 /* If no read is pending, try to bufferize for later reading */ 100 else 101 { 102 if((pSocket->indexRwWrite - pSocket->indexRwRead) < pSocket->localRW) 103 { 104 writeIndex = pSocket->indexRwWrite % pSocket->localRW; 105 /* Save SSAP */ 106 pSocket->sSocketRwBufferTable[writeIndex].buffer[0] = ssap; 107 /* Save UI frame payload */ 108 memcpy(pSocket->sSocketRwBufferTable[writeIndex].buffer + 1, 109 psData->buffer, 110 psData->length); 111 pSocket->sSocketRwBufferTable[writeIndex].length = psData->length; 112 113 /* Update the RW write index */ 114 pSocket->indexRwWrite++; 115 } 116 else 117 { 118 /* Unable to bufferize the packet, drop it */ 119 } 120 } 121 break; 122 } 123 } 124} 125 126/* TODO: comment function phFriNfc_LlcpTransport_Connectionless_SendTo_CB */ 127static void phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void* pContext, 128 NFCSTATUS status) 129{ 130 phFriNfc_LlcpTransport_Socket_t * pLlcpSocket = (phFriNfc_LlcpTransport_Socket_t*)pContext; 131 pphFriNfc_LlcpTransportSocketSendCb_t pfSavedCallback; 132 void * pSavedContext; 133 134 /* Call the send callback */ 135 pfSavedCallback = pLlcpSocket->pfSocketSend_Cb; 136 if (pfSavedCallback != NULL) 137 { 138 pLlcpSocket->pfSocketSend_Cb = NULL; 139 pfSavedCallback(pLlcpSocket->pSendContext, status); 140 } 141} 142 143static void phFriNfc_LlcpTransport_Connectionless_Abort(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) 144{ 145 if (pLlcpSocket->pfSocketSend_Cb != NULL) 146 { 147 pLlcpSocket->pfSocketSend_Cb(pLlcpSocket->pSendContext, NFCSTATUS_ABORTED); 148 pLlcpSocket->pSendContext = NULL; 149 pLlcpSocket->pfSocketSend_Cb = NULL; 150 } 151 if (pLlcpSocket->pfSocketRecvFrom_Cb != NULL) 152 { 153 pLlcpSocket->pfSocketRecvFrom_Cb(pLlcpSocket->pRecvContext, 0, NFCSTATUS_ABORTED); 154 pLlcpSocket->pRecvContext = NULL; 155 pLlcpSocket->pfSocketRecvFrom_Cb = NULL; 156 pLlcpSocket->pfSocketRecv_Cb = NULL; 157 } 158 pLlcpSocket->pAcceptContext = NULL; 159 pLlcpSocket->pfSocketAccept_Cb = NULL; 160 pLlcpSocket->pListenContext = NULL; 161 pLlcpSocket->pfSocketListen_Cb = NULL; 162 pLlcpSocket->pConnectContext = NULL; 163 pLlcpSocket->pfSocketConnect_Cb = NULL; 164 pLlcpSocket->pDisonnectContext = NULL; 165 pLlcpSocket->pfSocketDisconnect_Cb = NULL; 166} 167 168/** 169* \ingroup grp_fri_nfc 170* \brief <b>Close a socket on a LLCP-connectionless device</b>. 171* 172* This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket. 173* 174* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. 175 176* \retval NFCSTATUS_SUCCESS Operation successful. 177* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters 178* could not be properly interpreted. 179* \retval NFCSTATUS_FAILED Operation failed. 180*/ 181NFCSTATUS phFriNfc_LlcpTransport_Connectionless_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) 182{ 183 /* Reset the pointer to the socket closed */ 184 pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault; 185 pLlcpSocket->eSocket_Type = phFriNfc_LlcpTransport_eDefaultType; 186 pLlcpSocket->pContext = NULL; 187 pLlcpSocket->pSocketErrCb = NULL; 188 pLlcpSocket->socket_sSap = PHFRINFC_LLCP_SAP_DEFAULT; 189 pLlcpSocket->socket_dSap = PHFRINFC_LLCP_SAP_DEFAULT; 190 pLlcpSocket->bSocketRecvPending = FALSE; 191 pLlcpSocket->bSocketSendPending = FALSE; 192 pLlcpSocket->bSocketListenPending = FALSE; 193 pLlcpSocket->bSocketDiscPending = FALSE; 194 pLlcpSocket->RemoteBusyConditionInfo = FALSE; 195 pLlcpSocket->ReceiverBusyCondition = FALSE; 196 pLlcpSocket->socket_VS = 0; 197 pLlcpSocket->socket_VSA = 0; 198 pLlcpSocket->socket_VR = 0; 199 pLlcpSocket->socket_VRA = 0; 200 201 phFriNfc_LlcpTransport_Connectionless_Abort(pLlcpSocket); 202 203 memset(&pLlcpSocket->sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t)); 204 205 if (pLlcpSocket->sServiceName.buffer != NULL) { 206 phOsalNfc_FreeMemory(pLlcpSocket->sServiceName.buffer); 207 } 208 pLlcpSocket->sServiceName.buffer = NULL; 209 pLlcpSocket->sServiceName.length = 0; 210 211 return NFCSTATUS_SUCCESS; 212} 213 214/** 215* \ingroup grp_fri_nfc 216* \brief <b>Send data on a socket to a given destination SAP</b>. 217* 218* This function is used to write data on a socket to a given destination SAP. 219* This function can only be called on a connectionless socket. 220* 221* 222* \param[in] pLlcpSocket A pointer to a LlcpSocket created. 223* \param[in] nSap The destination SAP. 224* \param[in] psBuffer The buffer containing the data to send. 225* \param[in] pSend_RspCb The callback to be called when the 226* operation is completed. 227* \param[in] pContext Upper layer context to be returned in 228* the callback. 229* 230* \retval NFCSTATUS_SUCCESS Operation successful. 231* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters 232* could not be properly interpreted. 233* \retval NFCSTATUS_PENDING Reception operation is in progress, 234* pSend_RspCb will be called upon completion. 235* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of 236* a valid type to perform the requsted operation. 237* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. 238* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. 239* \retval NFCSTATUS_FAILED Operation failed. 240*/ 241NFCSTATUS phFriNfc_LlcpTransport_Connectionless_SendTo(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, 242 uint8_t nSap, 243 phNfc_sData_t* psBuffer, 244 pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, 245 void* pContext) 246{ 247 NFCSTATUS status = NFCSTATUS_FAILED; 248 249 /* Store send callback and context*/ 250 pLlcpSocket->pfSocketSend_Cb = pSend_RspCb; 251 pLlcpSocket->pSendContext = pContext; 252 253 /* Test if a send is already pending at transport level */ 254 if(pLlcpSocket->psTransport->bSendPending == TRUE) 255 { 256 /* Save the request so it can be handled in phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations() */ 257 pLlcpSocket->sSocketSendBuffer = *psBuffer; 258 pLlcpSocket->socket_dSap = nSap; 259 status = NFCSTATUS_PENDING; 260 } 261 else 262 { 263 /* Fill the psLlcpHeader stuture with the DSAP,PTYPE and the SSAP */ 264 pLlcpSocket->sLlcpHeader.dsap = nSap; 265 pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_UI; 266 pLlcpSocket->sLlcpHeader.ssap = pLlcpSocket->socket_sSap; 267 268 /* Send to data to the approiate socket */ 269 status = phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport, 270 &pLlcpSocket->sLlcpHeader, 271 NULL, 272 psBuffer, 273 phFriNfc_LlcpTransport_Connectionless_SendTo_CB, 274 pLlcpSocket); 275 } 276 277 return status; 278} 279 280 281 /** 282* \ingroup grp_lib_nfc 283* \brief <b>Read data on a socket and get the source SAP</b>. 284* 285* This function is the same as phLibNfc_Llcp_Recv, except that the callback includes 286* the source SAP. This functions can only be called on a connectionless socket. 287* 288* 289* \param[in] pLlcpSocket A pointer to a LlcpSocket created. 290* \param[in] psBuffer The buffer receiving the data. 291* \param[in] pRecv_RspCb The callback to be called when the 292* operation is completed. 293* \param[in] pContext Upper layer context to be returned in 294* the callback. 295* 296* \retval NFCSTATUS_SUCCESS Operation successful. 297* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters 298* could not be properly interpreted. 299* \retval NFCSTATUS_PENDING Reception operation is in progress, 300* pRecv_RspCb will be called upon completion. 301* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of 302* a valid type to perform the requsted operation. 303* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. 304* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. 305* \retval NFCSTATUS_FAILED Operation failed. 306*/ 307NFCSTATUS phLibNfc_LlcpTransport_Connectionless_RecvFrom(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, 308 phNfc_sData_t* psBuffer, 309 pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb, 310 void *pContext) 311{ 312 NFCSTATUS status = NFCSTATUS_PENDING; 313 uint8_t readIndex; 314 uint8_t ssap; 315 316 if(pLlcpSocket->bSocketRecvPending) 317 { 318 status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED); 319 } 320 else 321 { 322 /* Check if pending packets in RW */ 323 if(pLlcpSocket->indexRwRead != pLlcpSocket->indexRwWrite) 324 { 325 readIndex = pLlcpSocket->indexRwRead % pLlcpSocket->localRW; 326 327 /* Extract ssap and buffer from RW buffer */ 328 ssap = pLlcpSocket->sSocketRwBufferTable[readIndex].buffer[0]; 329 memcpy(psBuffer->buffer, 330 pLlcpSocket->sSocketRwBufferTable[readIndex].buffer + 1, 331 pLlcpSocket->sSocketRwBufferTable[readIndex].length); 332 psBuffer->length = pLlcpSocket->sSocketRwBufferTable[readIndex].length; 333 334 /* Reset RW buffer length */ 335 pLlcpSocket->sSocketRwBufferTable[readIndex].length = 0; 336 337 /* Update Value Rw Read Index */ 338 pLlcpSocket->indexRwRead++; 339 340 /* call the recv callback */ 341 pRecv_Cb(pContext, ssap, NFCSTATUS_SUCCESS); 342 343 status = NFCSTATUS_SUCCESS; 344 } 345 /* Otherwise, wait for a packet to come */ 346 else 347 { 348 /* Store the callback and context*/ 349 pLlcpSocket->pfSocketRecvFrom_Cb = pRecv_Cb; 350 pLlcpSocket->pRecvContext = pContext; 351 352 /* Store the pointer to the receive buffer */ 353 pLlcpSocket->sSocketRecvBuffer = psBuffer; 354 pLlcpSocket->receivedLength = &psBuffer->length; 355 356 /* Set RecvPending to TRUE */ 357 pLlcpSocket->bSocketRecvPending = TRUE; 358 } 359 } 360 return status; 361} 362