/** * calls link establishment callback * * This function is called after P2P RF link establishment * or when a new link establishment is requested and the P2P RF link is already established */ static void static_PP2PCallLinkEstablishmentCallback( tContext * pContext, tP2PLink * pP2PLink, W_ERROR nError) { PDebugTrace("static_PP2PCallLinkEstablishmentCallback : hLink %08x - %p %s", pP2PLink->hLink, pP2PLink, PUtilTraceError(nError)); if (pP2PLink->bEstablishedCalled == W_FALSE) { /* mark the operation as completed */ if (pP2PLink->hEstablishOperation != W_NULL_HANDLE) { PBasicSetOperationCompleted(pContext, pP2PLink->hEstablishOperation); pP2PLink->hEstablishOperation = W_NULL_HANDLE; } if (nError == W_SUCCESS) { PDFCPostContext3(&pP2PLink->sEstablishmentCC, pP2PLink->hLink, W_SUCCESS); } else { PDFCPostContext3(&pP2PLink->sEstablishmentCC, W_NULL_HANDLE, nError); PDFCFlushCall(&pP2PLink->sReleaseCC); } pP2PLink->bEstablishedCalled = W_TRUE; } }
/* See header */ void PP2PCallSocketReadCallback( tContext * pContext, tP2PSocket * pP2PSocket, uint32_t nRecvLength, W_ERROR nError, uint8_t nSAP) { PDebugTrace("PP2PCallSocketReadCallback %08x - %p %s", pP2PSocket->sConfig.hSocket, pP2PSocket, PUtilTraceError(nError)); pP2PSocket->bRecvInProgress = W_FALSE; pP2PSocket->pRecvBuffer = null; pP2PSocket->nRecvBufferLength = 0; if (pP2PSocket->hRecvOperation != W_NULL_HANDLE) { PBasicSetOperationCompleted(pContext, pP2PSocket->hRecvOperation); pP2PSocket->hRecvOperation = W_NULL_HANDLE; } if (pP2PSocket->sConfig.nType == W_P2P_TYPE_CONNECTIONLESS) { PDFCPostContext4(&pP2PSocket->sRecvCC, nRecvLength, nError, nSAP); } else { PDFCPostContext3(&pP2PSocket->sRecvCC, nRecvLength, nError); } }
/** * Open a 7816 channel used to exchanged APDU * * @param[in] pContext The context * * @param[in] pNDEFConnection The NDEF connection */ static void static_PNDEFType4OpenChannel( tContext* pContext, tNDEFConnection* pNDEFConnection, tPBasicGenericDataCallbackFunction * pCallback, void * pCallbackParameter) { pNDEFConnection->sType.t4.pChannelCallback = pCallback; pNDEFConnection->sType.t4.pChannelCallbackParameter = pCallbackParameter; if (pNDEFConnection->sType.t4.h7816Channel == W_NULL_HANDLE) { /* Open a raw channel used to exchange APDU */ P7816OpenChannelInternal( pContext, pNDEFConnection->hConnection, static_PNDEFType4OpenChannelCompleted, pNDEFConnection, W_7816_CHANNEL_TYPE_RAW, (const uint8_t*)null, 0); } else { /* Channel is already opened. Send result */ tDFCCallbackContext sCallbackContext; PDFCFillCallbackContext(pContext, (tDFCCallback*)static_PNDEFType4OpenChannelCompleted, pNDEFConnection, &sCallbackContext); PDFCPostContext3(&sCallbackContext, pNDEFConnection->sType.t4.h7816Channel, W_SUCCESS); } }
/* See client API */ void PP2PURILookup( tContext * pContext, W_HANDLE hLink, tPP2PURILookupCompleted * pCallback, void * pCallbackParameter, const char16_t * pServiceURI) { tDFCCallbackContext * pCallbackContext = (tDFCCallbackContext *) CMemoryAlloc(sizeof(tDFCCallbackContext)); W_ERROR nError; if (pCallbackContext != null) { PDFCFillCallbackContext(pContext, (tDFCCallback *) pCallback, pCallbackParameter, pCallbackContext); if (pServiceURI != null) { PP2PURILookupDriver(pContext, hLink, static_PP2PURILookupCompleted, pCallbackContext, pServiceURI, PUtilStringLength(pServiceURI) * sizeof(char16_t)); } else { /* all errors are handled in the driver implementation */ PP2PURILookupDriver(pContext, hLink, static_PP2PURILookupCompleted, pCallbackContext, null, 0); } nError = PContextGetLastIoctlError(pContext); if (nError != W_SUCCESS) { tDFCCallbackContext sCallbackContext; PDFCFillCallbackContext(pContext, (tDFCCallback *) static_PP2PURILookupCompleted, pCallbackContext, &sCallbackContext); PDFCPostContext3(&sCallbackContext, 0, nError); } } else { tDFCCallbackContext sCallbackContext; PDFCFillCallbackContext(pContext, (tDFCCallback *) pCallback, pCallbackParameter, &sCallbackContext); PDFCPostContext3(&sCallbackContext, 0, W_ERROR_OUT_OF_RESOURCE); } }
static void static_PP2PURILookupCompleted( tContext* pContext, void * pCallbackParameter, uint8_t nDSAP, W_ERROR nError ) { tDFCCallbackContext * pCallbackContext = (tDFCCallbackContext *) pCallbackParameter; PDebugError("static_PP2PURILookupCompleted"); PDFCPostContext3(pCallbackContext, (uint32_t) nDSAP, nError); CMemoryFree(pCallbackContext); }
/* See tWBasicGenericDataCallbackFunction */ static void static_PBPrimeUserExchangeDataCompleted( tContext* pContext, void *pCallbackParameter, uint32_t nDataLength, W_ERROR nError) { tPBPrimeUserConnection* pBPrimeUserConnection = (tPBPrimeUserConnection*)pCallbackParameter; /* Check if the operation has been cancelled by the user */ if ( pBPrimeUserConnection->hCurrentOperation != W_NULL_HANDLE ) { /* Check the operation state */ if ( PBasicGetOperationState(pContext, pBPrimeUserConnection->hCurrentOperation) == P_OPERATION_STATE_CANCELLED) { PDebugError("static_PBPrimeUserExchangeDataCompleted: Operation is cancelled"); if(nError == W_SUCCESS) { nError = W_ERROR_CANCEL; } } else { PBasicSetOperationCompleted(pContext, pBPrimeUserConnection->hCurrentOperation); } PHandleClose(pContext, pBPrimeUserConnection->hCurrentOperation); pBPrimeUserConnection->hCurrentOperation = W_NULL_HANDLE; } PHandleClose(pContext, pBPrimeUserConnection->hCurrentDriverOperation); pBPrimeUserConnection->hCurrentDriverOperation = W_NULL_HANDLE; if(nError != W_SUCCESS) { PDebugError("static_PBPrimeUserExchangeDataCompleted: Returning %s", PUtilTraceError(nError)); nDataLength = 0; } /* Send the result */ PDFCPostContext3( &pBPrimeUserConnection->sCallbackContext, nDataLength, nError ); /* Release the reference after completion May destroy pBPrimeUserConnection */ PHandleDecrementReferenceCount(pContext, pBPrimeUserConnection); }
/* See WP2PEstablishLink */ W_HANDLE PP2PEstablishLinkDriver1Internal( tContext * pContext, tPBasicGenericHandleCallbackFunction* pEstablishmentCallback, void* pEstablishmentCallbackParameter ) { tDFCCallbackContext sCallbackContext; tP2PLink * pP2PLink = null; W_ERROR nError; PDFCFillCallbackContext( pContext, (tDFCCallback*)pEstablishmentCallback, pEstablishmentCallbackParameter, & sCallbackContext); if (PP2PCheckP2PSupport(pContext) == W_FALSE) { nError = W_ERROR_RF_PROTOCOL_NOT_SUPPORTED; goto error; } pP2PLink = CMemoryAlloc(sizeof(tP2PLink)); if (pP2PLink == null) { nError = W_ERROR_OUT_OF_RESOURCE; goto error; } CMemoryFill(pP2PLink, 0, sizeof(tP2PLink)); nError = PHandleRegister(pContext, pP2PLink, P_HANDLE_TYPE_P2P_LINK, &pP2PLink->hLink); if (nError != W_SUCCESS) { goto error; } pP2PLink->sEstablishmentCC = sCallbackContext; return pP2PLink->hLink; error: if (pP2PLink != null) { CMemoryFree(pP2PLink); } PDFCPostContext3(&sCallbackContext, W_NULL_HANDLE, nError); return W_NULL_HANDLE; }
/* See header */ void PP2PCallSocketReadAndWriteCallbacks( tContext * pContext, tP2PSocket * pP2PSocket, W_ERROR nError) { PDebugTrace("static_PP2PCallReadAndWriteCallbacks nError %d", nError); /* call the receive callback */ if (pP2PSocket->bRecvInProgress) { pP2PSocket->bRecvInProgress = W_FALSE; pP2PSocket->pRecvBuffer = null; if (pP2PSocket->hRecvOperation != W_NULL_HANDLE) { PBasicSetOperationCompleted(pContext, pP2PSocket->hRecvOperation); pP2PSocket->hRecvOperation = W_NULL_HANDLE; } PDFCPostContext3(&pP2PSocket->sRecvCC, 0, nError); } /* call the send callback */ if (pP2PSocket->bXmitInProgress) { pP2PSocket->bXmitInProgress = W_FALSE; pP2PSocket->pXmitBuffer = null; if (pP2PSocket->hXmitOperation != W_NULL_HANDLE) { PBasicSetOperationCompleted(pContext, pP2PSocket->hXmitOperation); pP2PSocket->hXmitOperation = W_NULL_HANDLE; } PDFCPostContext2(&pP2PSocket->sXmitCC, nError); } }
static void static_PBPrimeUserExchangeData( tContext* pContext, void* pObject, tPBasicGenericDataCallbackFunction* pCallback, void* pCallbackParameter, const uint8_t* pReaderToCardBuffer, uint32_t nReaderToCardBufferLength, uint8_t* pCardToReaderBuffer, uint32_t nCardToReaderBufferMaxLength, W_HANDLE* phOperation) { tPBPrimeUserConnection* pBPrimeUserConnection = (tPBPrimeUserConnection*)pObject; tDFCCallbackContext sCallbackContext; W_ERROR nError = W_SUCCESS; PDebugTrace("static_PBPrimeUserExchangeData"); PDFCFillCallbackContext( pContext, (tDFCCallback*)pCallback, pCallbackParameter, &sCallbackContext ); /* Check if an operation is still pending */ if ( pBPrimeUserConnection->hCurrentOperation != W_NULL_HANDLE ) { PDebugError("static_PBPrimeUserExchangeData: operation already pending"); nError = W_ERROR_BAD_STATE; goto return_error; } /* Check the card buffer size */ if ((nReaderToCardBufferLength == 0) || (pReaderToCardBuffer == null)) { PDebugError("static_PBPrimeUserExchangeData: nReaderToCardBufferLength / pReaderToCardBuffer can not be null"); nError = W_ERROR_BAD_PARAMETER; goto return_error; } if ( ((pCardToReaderBuffer == null) && (nCardToReaderBufferMaxLength != 0)) || ((pCardToReaderBuffer != null) && (nCardToReaderBufferMaxLength == 0)) ) { PDebugError("static_PBPrimeUserExchangeData: inconsistency between pCardToReaderBuffer and nCardToReaderBufferMaxLength"); nError = W_ERROR_BAD_PARAMETER; goto return_error; } /* Get an operation handle if needed */ if((pBPrimeUserConnection->hCurrentOperation = PBasicCreateOperation( pContext, static_PBPrimeUserExchangeDataCancel, pBPrimeUserConnection)) == W_NULL_HANDLE) { PDebugError("static_PBPrimeUserExchangeData: Cannot allocate the operation"); nError = W_ERROR_OUT_OF_RESOURCE; goto return_error; } if(phOperation != null) { /* Duplicate the handle to be referenced internally and in the returned handle */ nError = PHandleDuplicate(pContext, pBPrimeUserConnection->hCurrentOperation, phOperation ); if(nError != W_SUCCESS) { PDebugError("static_PBPrimeUserExchangeData: Error returned by PHandleDuplicate()"); PHandleClose(pContext, pBPrimeUserConnection->hCurrentOperation); pBPrimeUserConnection->hCurrentOperation = W_NULL_HANDLE; goto return_error; } } pBPrimeUserConnection->hCurrentDriverOperation = PBPrimeDriverExchangeData( pContext, pBPrimeUserConnection->hDriverConnection, static_PBPrimeUserExchangeDataCompleted, pBPrimeUserConnection, pReaderToCardBuffer, nReaderToCardBufferLength, pCardToReaderBuffer, nCardToReaderBufferMaxLength); nError = PContextGetLastIoctlError(pContext); if (nError != W_SUCCESS) { PDebugError("static_PBPrimeUserExchangeData: Error returned by PContextGetLastIoctlError()"); PHandleClose(pContext, pBPrimeUserConnection->hCurrentOperation); pBPrimeUserConnection->hCurrentOperation = W_NULL_HANDLE; goto return_error; } /* Store the callback context */ pBPrimeUserConnection->sCallbackContext = sCallbackContext; /* Increment the reference count to keep the connection object alive during the operation. The reference count is decreased in static_PBPrimeUserExchangeDataCompleted when the NFC HAL operation is completed */ PHandleIncrementReferenceCount(pBPrimeUserConnection); return; return_error: PDebugError("static_PBPrimeUserExchangeData: returning %s", PUtilTraceError(nError)); PDFCPostContext3( &sCallbackContext, 0, nError ); }
/** * Sends Select Application APDU * * @param[in] pContext The context * * @param[in] pNDEFConnection The NDEF connection */ static void static_PNDEFType4SelectApplication( tContext* pContext, tNDEFConnection* pNDEFConnection, tPBasicGenericDataCallbackFunction * pCallback, void * pCallbackParameter) { pNDEFConnection->sType.t4.pCCCache = PCacheConnectionGetBuffer(pContext, P_NDEF_4_CC_CACHE_ID, 0, &pNDEFConnection->sType.t4.nCCCacheLength); pNDEFConnection->sType.t4.pNDEFCache = PCacheConnectionGetBuffer(pContext, P_NDEF_4_NDEF_CACHE_ID, 0, &pNDEFConnection->sType.t4.nNDEFCacheLength); if ((pNDEFConnection->sType.t4.pCCCache == null) || (pNDEFConnection->sType.t4.pNDEFCache == null)) { /* NFC Type 4 Tag v2.0 specific commands (with optional Le byte) */ static const uint8_t aSelectApplicationv20[] = { P_7816SM_CLA, P_7816SM_INS_SELECT, P_7816SM_P1_SELECT_AID, P_7816SM_P2_SELECT_AID, 0x07, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01, 0x00 }; /* NFC Type 4 Tag v1.0 specific commands (with non-standard Le byte) */ static const uint8_t aSelectApplicationv10[] = { P_7816SM_CLA, P_7816SM_INS_SELECT, P_7816SM_P1_SELECT_AID, P_7816SM_P2_SELECT_AID, 0x07, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00, 0x00 }; const uint8_t * pSelectApplication; uint8_t nCommandLength = 0; PDebugTrace("static_PNDEFType4SelectApplication"); switch (pNDEFConnection->sType.t4.nVariant) { case P_NDEF_4_VERSION_20: pSelectApplication = aSelectApplicationv20; nCommandLength = sizeof(aSelectApplicationv20); break; case P_NDEF_4_VERSION_20_NON_STANDARD: pSelectApplication = aSelectApplicationv20; nCommandLength = sizeof(aSelectApplicationv20) - 1; break; case P_NDEF_4_VERSION_10: pSelectApplication = aSelectApplicationv10; nCommandLength = sizeof (aSelectApplicationv10) - 1; break; case P_NDEF_4_VERSION_10_NON_STANDARD: pSelectApplication = aSelectApplicationv10; nCommandLength = sizeof (aSelectApplicationv10); break; default: PDebugError("static_PNDEFType4SelectApplication : invalid tag type"); return; } /* Send the command */ P7816ExchangeApduInternal( pContext, pNDEFConnection->sType.t4.h7816Channel, pCallback, pCallbackParameter, pSelectApplication, nCommandLength, pNDEFConnection->pReceivedBuffer, pNDEFConnection->nBufferLength); } else { tDFCCallbackContext sCallbackContext; PDebugTrace("static_PNDEFType4SelectApplication : skipping select due to cache existence"); pNDEFConnection->pReceivedBuffer[0] = 0x90; pNDEFConnection->pReceivedBuffer[1] = 0x00; PDFCFillCallbackContext(pContext, (tDFCCallback *) pCallback, pCallbackParameter, &sCallbackContext); PDFCPostContext3(&sCallbackContext, 2, W_SUCCESS); } }