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