| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /****************************************************************************** |
| * |
| * The original Work has been changed by NXP. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Copyright 2019 NXP |
| * |
| ******************************************************************************/ |
| /* |
| * Communicate with a peer using NFC-DEP, LLCP, SNEP. |
| */ |
| #include "PeerToPeer.h" |
| |
| #include <android-base/stringprintf.h> |
| #include <base/logging.h> |
| #include <nativehelper/ScopedLocalRef.h> |
| |
| #include "JavaClassConstants.h" |
| #include "NfcJniUtil.h" |
| #include "llcp_defs.h" |
| #include "nfc_config.h" |
| #if (NXP_EXTNS == TRUE) |
| #include "NativeJniExtns.h" |
| #endif |
| |
| using android::base::StringPrintf; |
| |
| /* Some older PN544-based solutions would only send the first SYMM back |
| * (as an initiator) after the full LTO (750ms). But our connect timer |
| * starts immediately, and hence we may timeout if the timer is set to |
| * 1000 ms. Worse, this causes us to immediately connect to the NPP |
| * socket, causing concurrency issues in that stack. Increase the default |
| * timeout to 2000 ms, giving us enough time to complete the first connect. |
| */ |
| #define LLCP_DATA_LINK_TIMEOUT 2000 |
| |
| using namespace android; |
| |
| namespace android { |
| extern void nativeNfcTag_registerNdefTypeHandler(); |
| extern void nativeNfcTag_deregisterNdefTypeHandler(); |
| extern void startRfDiscovery(bool isStart); |
| extern bool isDiscoveryStarted(); |
| } // namespace android |
| |
| PeerToPeer PeerToPeer::sP2p; |
| const std::string P2pServer::sSnepServiceName("urn:nfc:sn:snep"); |
| |
| extern bool nfc_debug_enabled; |
| |
| /******************************************************************************* |
| ** |
| ** Function: PeerToPeer |
| ** |
| ** Description: Initialize member variables. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| PeerToPeer::PeerToPeer() |
| : mRemoteWKS(0), |
| mIsP2pListening(false), |
| mP2pListenTechMask(NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F | |
| NFA_TECHNOLOGY_MASK_A_ACTIVE | |
| NFA_TECHNOLOGY_MASK_F_ACTIVE), |
| mNextJniHandle(1) { |
| memset(mServers, 0, sizeof(mServers)); |
| memset(mClients, 0, sizeof(mClients)); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: ~PeerToPeer |
| ** |
| ** Description: Free all resources. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| PeerToPeer::~PeerToPeer() {} |
| |
| /******************************************************************************* |
| ** |
| ** Function: getInstance |
| ** |
| ** Description: Get the singleton PeerToPeer object. |
| ** |
| ** Returns: Singleton PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| PeerToPeer& PeerToPeer::getInstance() { return sP2p; } |
| |
| /******************************************************************************* |
| ** |
| ** Function: initialize |
| ** |
| ** Description: Initialize member variables. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::initialize() { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("PeerToPeer::initialize"); |
| |
| if (NfcConfig::hasKey(NAME_P2P_LISTEN_TECH_MASK)) |
| mP2pListenTechMask = NfcConfig::getUnsigned(NAME_P2P_LISTEN_TECH_MASK); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findServerLocked |
| ** |
| ** Description: Find a PeerToPeer object by connection handle. |
| ** Assumes mMutex is already held |
| ** nfaP2pServerHandle: Connectin handle. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<P2pServer> PeerToPeer::findServerLocked(tNFA_HANDLE nfaP2pServerHandle) { |
| for (int i = 0; i < sMax; i++) { |
| if ((mServers[i] != NULL) && |
| (mServers[i]->mNfaP2pServerHandle == nfaP2pServerHandle)) { |
| return (mServers[i]); |
| } |
| } |
| |
| // If here, not found |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findServerLocked |
| ** |
| ** Description: Find a PeerToPeer object by connection handle. |
| ** Assumes mMutex is already held |
| ** serviceName: service name. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<P2pServer> PeerToPeer::findServerLocked(tJNI_HANDLE jniHandle) { |
| for (int i = 0; i < sMax; i++) { |
| if ((mServers[i] != NULL) && (mServers[i]->mJniHandle == jniHandle)) { |
| return (mServers[i]); |
| } |
| } |
| |
| // If here, not found |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findServerLocked |
| ** |
| ** Description: Find a PeerToPeer object by service name |
| ** Assumes mMutex is already heldf |
| ** serviceName: service name. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<P2pServer> PeerToPeer::findServerLocked(const char* serviceName) { |
| for (int i = 0; i < sMax; i++) { |
| if ((mServers[i] != NULL) && |
| (mServers[i]->mServiceName.compare(serviceName) == 0)) |
| return (mServers[i]); |
| } |
| |
| // If here, not found |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: registerServer |
| ** |
| ** Description: Let a server start listening for peer's connection request. |
| ** jniHandle: Connection handle. |
| ** serviceName: Server's service name. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::registerServer(tJNI_HANDLE jniHandle, |
| const char* serviceName) { |
| static const char fn[] = "PeerToPeer::registerServer"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; service name: %s JNI handle: %u", fn, |
| serviceName, jniHandle); |
| sp<P2pServer> pSrv = NULL; |
| |
| mMutex.lock(); |
| // Check if already registered |
| if ((pSrv = findServerLocked(serviceName)) != NULL) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: service name=%s already registered, handle: 0x%04x", fn, |
| serviceName, pSrv->mNfaP2pServerHandle); |
| |
| // Update JNI handle |
| pSrv->mJniHandle = jniHandle; |
| mMutex.unlock(); |
| return (true); |
| } |
| |
| for (int ii = 0; ii < sMax; ii++) { |
| if (mServers[ii] == NULL) { |
| pSrv = mServers[ii] = new P2pServer(jniHandle, serviceName); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: added new p2p server index: %d handle: %u name: %s", fn, ii, |
| jniHandle, serviceName); |
| break; |
| } |
| } |
| mMutex.unlock(); |
| |
| if (pSrv == NULL) { |
| LOG(ERROR) << StringPrintf("%s: service name=%s no free entry", fn, |
| serviceName); |
| return (false); |
| } |
| |
| if (pSrv->registerWithStack()) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: got new p2p server h=0x%X", fn, pSrv->mNfaP2pServerHandle); |
| return (true); |
| } else { |
| LOG(ERROR) << StringPrintf("%s: invalid server handle", fn); |
| removeServer(jniHandle); |
| return (false); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: removeServer |
| ** |
| ** Description: Free resources related to a server. |
| ** jniHandle: Connection handle. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::removeServer(tJNI_HANDLE jniHandle) { |
| static const char fn[] = "PeerToPeer::removeServer"; |
| |
| AutoMutex mutex(mMutex); |
| |
| for (int i = 0; i < sMax; i++) { |
| if ((mServers[i] != NULL) && (mServers[i]->mJniHandle == jniHandle)) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: server jni_handle: %u; nfa_handle: 0x%04x; name: %s; index=%d", |
| fn, jniHandle, mServers[i]->mNfaP2pServerHandle, |
| mServers[i]->mServiceName.c_str(), i); |
| |
| mServers[i] = NULL; |
| return; |
| } |
| } |
| LOG(ERROR) << StringPrintf("%s: unknown server jni handle: %u", fn, |
| jniHandle); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: llcpActivatedHandler |
| ** |
| ** Description: Receive LLLCP-activated event from stack. |
| ** nat: JVM-related data. |
| ** activated: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::llcpActivatedHandler(nfc_jni_native_data* nat, |
| tNFA_LLCP_ACTIVATED& activated) { |
| static const char fn[] = "PeerToPeer::llcpActivatedHandler"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| |
| // no longer need to receive NDEF message from a tag |
| android::nativeNfcTag_deregisterNdefTypeHandler(); |
| |
| mRemoteWKS = activated.remote_wks; |
| |
| JNIEnv* e = NULL; |
| ScopedAttach attach(nat->vm, &e); |
| if (e == NULL) { |
| LOG(ERROR) << StringPrintf("%s: jni env is null", fn); |
| return; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: get object class", fn); |
| ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_P2pDevice)); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail get p2p device", fn); |
| return; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: instantiate", fn); |
| /* New target instance */ |
| jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V"); |
| ScopedLocalRef<jobject> tag(e, e->NewObject(tag_cls.get(), ctor)); |
| |
| /* Set P2P Target mode */ |
| jfieldID f = e->GetFieldID(tag_cls.get(), "mMode", "I"); |
| |
| if (activated.is_initiator == TRUE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: p2p initiator", fn); |
| e->SetIntField(tag.get(), f, (jint)MODE_P2P_INITIATOR); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: p2p target", fn); |
| e->SetIntField(tag.get(), f, (jint)MODE_P2P_TARGET); |
| } |
| /* Set LLCP version */ |
| f = e->GetFieldID(tag_cls.get(), "mLlcpVersion", "B"); |
| e->SetByteField(tag.get(), f, (jbyte)activated.remote_version); |
| |
| /* Set tag handle */ |
| f = e->GetFieldID(tag_cls.get(), "mHandle", "I"); |
| e->SetIntField(tag.get(), f, |
| (jint)0x1234); // ?? This handle is not used for anything |
| |
| if (nat->tag != NULL) { |
| e->DeleteGlobalRef(nat->tag); |
| } |
| nat->tag = e->NewGlobalRef(tag.get()); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: notify nfc service", fn); |
| |
| /* Notify manager that new a P2P device was found */ |
| e->CallVoidMethod(nat->manager, |
| android::gCachedNfcManagerNotifyLlcpLinkActivation, |
| tag.get()); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail notify", fn); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: llcpDeactivatedHandler |
| ** |
| ** Description: Receive LLLCP-deactivated event from stack. |
| ** nat: JVM-related data. |
| ** deactivated: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::llcpDeactivatedHandler( |
| nfc_jni_native_data* nat, tNFA_LLCP_DEACTIVATED& /*deactivated*/) { |
| static const char fn[] = "PeerToPeer::llcpDeactivatedHandler"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| |
| JNIEnv* e = NULL; |
| ScopedAttach attach(nat->vm, &e); |
| if (e == NULL) { |
| LOG(ERROR) << StringPrintf("%s: jni env is null", fn); |
| return; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: notify nfc service", fn); |
| /* Notify manager that the LLCP is lost or deactivated */ |
| e->CallVoidMethod(nat->manager, |
| android::gCachedNfcManagerNotifyLlcpLinkDeactivated, |
| nat->tag); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail notify", fn); |
| } |
| |
| // let the tag-reading code handle NDEF data event |
| android::nativeNfcTag_registerNdefTypeHandler(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| void PeerToPeer::llcpFirstPacketHandler(nfc_jni_native_data* nat) { |
| static const char fn[] = "PeerToPeer::llcpFirstPacketHandler"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| |
| JNIEnv* e = NULL; |
| ScopedAttach attach(nat->vm, &e); |
| if (e == NULL) { |
| LOG(ERROR) << StringPrintf("%s: jni env is null", fn); |
| return; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: notify nfc service", fn); |
| /* Notify manager that the LLCP is lost or deactivated */ |
| e->CallVoidMethod(nat->manager, |
| android::gCachedNfcManagerNotifyLlcpFirstPacketReceived, |
| nat->tag); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail notify", fn); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| /******************************************************************************* |
| ** |
| ** Function: accept |
| ** |
| ** Description: Accept a peer's request to connect. |
| ** serverJniHandle: Server's handle. |
| ** connJniHandle: Connection handle. |
| ** maxInfoUnit: Maximum information unit. |
| ** recvWindow: Receive window size. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::accept(tJNI_HANDLE serverJniHandle, tJNI_HANDLE connJniHandle, |
| int maxInfoUnit, int recvWindow) { |
| static const char fn[] = "PeerToPeer::accept"; |
| sp<P2pServer> pSrv = NULL; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; server jni handle: %u; conn jni handle: %u; maxInfoUnit: %d; " |
| "recvWindow: %d", |
| fn, serverJniHandle, connJniHandle, maxInfoUnit, recvWindow); |
| |
| mMutex.lock(); |
| if ((pSrv = findServerLocked(serverJniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: unknown server jni handle: %u", fn, |
| serverJniHandle); |
| mMutex.unlock(); |
| return (false); |
| } |
| mMutex.unlock(); |
| |
| return pSrv->accept(serverJniHandle, connJniHandle, maxInfoUnit, recvWindow); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: deregisterServer |
| ** |
| ** Description: Stop a P2pServer from listening for peer. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::deregisterServer(tJNI_HANDLE jniHandle) { |
| static const char fn[] = "PeerToPeer::deregisterServer"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; JNI handle: %u", fn, jniHandle); |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| sp<P2pServer> pSrv = NULL; |
| bool isPollingTempStopped = false; |
| |
| mMutex.lock(); |
| if ((pSrv = findServerLocked(jniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: unknown service handle: %u", fn, jniHandle); |
| mMutex.unlock(); |
| return (false); |
| } |
| mMutex.unlock(); |
| if (isDiscoveryStarted()) { |
| isPollingTempStopped = true; |
| startRfDiscovery(false); |
| } |
| |
| { |
| // Server does not call NFA_P2pDisconnect(), so unblock the accept() |
| SyncEventGuard guard(pSrv->mConnRequestEvent); |
| pSrv->mConnRequestEvent.notifyOne(); |
| } |
| |
| nfaStat = NFA_P2pDeregister(pSrv->mNfaP2pServerHandle); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: deregister error=0x%X", fn, nfaStat); |
| } |
| |
| removeServer(jniHandle); |
| #if (NXP_EXTNS == FALSE) |
| if (isPollingTempStopped) { |
| startRfDiscovery(true); |
| } |
| #endif |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| return true; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: createClient |
| ** |
| ** Description: Create a P2pClient object for a new out-bound connection. |
| ** jniHandle: Connection handle. |
| ** miu: Maximum information unit. |
| ** rw: Receive window size. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::createClient(tJNI_HANDLE jniHandle, uint16_t miu, uint8_t rw) { |
| static const char fn[] = "PeerToPeer::createClient"; |
| int i = 0; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter: jni h: %u miu: %u rw: %u", fn, jniHandle, miu, rw); |
| |
| mMutex.lock(); |
| sp<P2pClient> client = NULL; |
| for (i = 0; i < sMax; i++) { |
| if (mClients[i] == NULL) { |
| mClients[i] = client = new P2pClient(); |
| |
| mClients[i]->mClientConn->mJniHandle = jniHandle; |
| mClients[i]->mClientConn->mMaxInfoUnit = miu; |
| mClients[i]->mClientConn->mRecvWindow = rw; |
| break; |
| } |
| } |
| mMutex.unlock(); |
| |
| if (client == NULL) { |
| LOG(ERROR) << StringPrintf("%s: fail", fn); |
| return (false); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: pClient: 0x%p assigned for client jniHandle: %u", |
| fn, client.get(), jniHandle); |
| |
| { |
| SyncEventGuard guard(mClients[i]->mRegisteringEvent); |
| NFA_P2pRegisterClient(NFA_P2P_DLINK_TYPE, nfaClientCallback); |
| mClients[i]->mRegisteringEvent.wait(); // wait for NFA_P2P_REG_CLIENT_EVT |
| } |
| |
| if (mClients[i]->mNfaP2pClientHandle != NFA_HANDLE_INVALID) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: exit; new client jniHandle: %u NFA Handle: 0x%04x", fn, |
| jniHandle, client->mClientConn->mNfaConnHandle); |
| return (true); |
| } else { |
| LOG(ERROR) << StringPrintf( |
| "%s: FAILED; new client jniHandle: %u NFA Handle: 0x%04x", fn, |
| jniHandle, client->mClientConn->mNfaConnHandle); |
| removeConn(jniHandle); |
| return (false); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: removeConn |
| ** |
| ** Description: Free resources related to a connection. |
| ** jniHandle: Connection handle. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::removeConn(tJNI_HANDLE jniHandle) { |
| static const char fn[] = "PeerToPeer::removeConn"; |
| |
| AutoMutex mutex(mMutex); |
| // If the connection is a for a client, delete the client itself |
| for (int ii = 0; ii < sMax; ii++) { |
| if ((mClients[ii] != NULL) && |
| (mClients[ii]->mClientConn->mJniHandle == jniHandle)) { |
| if (mClients[ii]->mNfaP2pClientHandle != NFA_HANDLE_INVALID) |
| NFA_P2pDeregister(mClients[ii]->mNfaP2pClientHandle); |
| |
| mClients[ii] = NULL; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: deleted client handle: %u index: %u", fn, jniHandle, ii); |
| return; |
| } |
| } |
| |
| // If the connection is for a server, just delete the connection |
| for (int ii = 0; ii < sMax; ii++) { |
| if (mServers[ii] != NULL) { |
| if (mServers[ii]->removeServerConnection(jniHandle)) { |
| return; |
| } |
| } |
| } |
| |
| LOG(ERROR) << StringPrintf("%s: could not find handle: %u", fn, jniHandle); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: connectConnOriented |
| ** |
| ** Description: Establish a connection-oriented connection to a peer. |
| ** jniHandle: Connection handle. |
| ** serviceName: Peer's service name. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::connectConnOriented(tJNI_HANDLE jniHandle, |
| const char* serviceName) { |
| static const char fn[] = "PeerToPeer::connectConnOriented"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; h: %u service name=%s", fn, jniHandle, serviceName); |
| bool stat = createDataLinkConn(jniHandle, serviceName, 0); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; h: %u stat: %u", fn, jniHandle, stat); |
| return stat; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: connectConnOriented |
| ** |
| ** Description: Establish a connection-oriented connection to a peer. |
| ** jniHandle: Connection handle. |
| ** destinationSap: Peer's service access point. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::connectConnOriented(tJNI_HANDLE jniHandle, |
| uint8_t destinationSap) { |
| static const char fn[] = "PeerToPeer::connectConnOriented"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; h: %u dest sap: 0x%X", fn, jniHandle, destinationSap); |
| bool stat = createDataLinkConn(jniHandle, NULL, destinationSap); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; h: %u stat: %u", fn, jniHandle, stat); |
| return stat; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: createDataLinkConn |
| ** |
| ** Description: Establish a connection-oriented connection to a peer. |
| ** jniHandle: Connection handle. |
| ** serviceName: Peer's service name. |
| ** destinationSap: Peer's service access point. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::createDataLinkConn(tJNI_HANDLE jniHandle, |
| const char* serviceName, |
| uint8_t destinationSap) { |
| static const char fn[] = "PeerToPeer::createDataLinkConn"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| sp<P2pClient> pClient = NULL; |
| |
| if ((pClient = findClient(jniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: can't find client, JNI handle: %u", fn, |
| jniHandle); |
| #if (NXP_EXTNS == TRUE) |
| NativeJniExtns::getInstance().notifyNfcEvent("nfaClientCallback"); |
| #endif |
| return (false); |
| } |
| |
| { |
| SyncEventGuard guard(pClient->mConnectingEvent); |
| pClient->mIsConnecting = true; |
| |
| if (serviceName) |
| nfaStat = NFA_P2pConnectByName(pClient->mNfaP2pClientHandle, |
| const_cast<char*>(serviceName), |
| pClient->mClientConn->mMaxInfoUnit, |
| pClient->mClientConn->mRecvWindow); |
| else if (destinationSap) |
| nfaStat = |
| NFA_P2pConnectBySap(pClient->mNfaP2pClientHandle, destinationSap, |
| pClient->mClientConn->mMaxInfoUnit, |
| pClient->mClientConn->mRecvWindow); |
| if (nfaStat == NFA_STATUS_OK) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: wait for connected event mConnectingEvent: 0x%p", fn, |
| pClient.get()); |
| pClient->mConnectingEvent.wait(); |
| } |
| } |
| |
| if (nfaStat == NFA_STATUS_OK) { |
| if (pClient->mClientConn->mNfaConnHandle == NFA_HANDLE_INVALID) { |
| removeConn(jniHandle); |
| nfaStat = NFA_STATUS_FAILED; |
| } else |
| pClient->mIsConnecting = false; |
| } else { |
| removeConn(jniHandle); |
| LOG(ERROR) << StringPrintf("%s: fail; error=0x%X", fn, nfaStat); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| return nfaStat == NFA_STATUS_OK; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findClient |
| ** |
| ** Description: Find a PeerToPeer object with a client connection handle. |
| ** nfaConnHandle: Connection handle. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<P2pClient> PeerToPeer::findClient(tNFA_HANDLE nfaConnHandle) { |
| AutoMutex mutex(mMutex); |
| for (int i = 0; i < sMax; i++) { |
| if ((mClients[i] != NULL) && |
| (mClients[i]->mNfaP2pClientHandle == nfaConnHandle)) |
| return (mClients[i]); |
| } |
| return (NULL); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findClient |
| ** |
| ** Description: Find a PeerToPeer object with a client connection handle. |
| ** jniHandle: Connection handle. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<P2pClient> PeerToPeer::findClient(tJNI_HANDLE jniHandle) { |
| AutoMutex mutex(mMutex); |
| for (int i = 0; i < sMax; i++) { |
| if ((mClients[i] != NULL) && |
| (mClients[i]->mClientConn->mJniHandle == jniHandle)) |
| return (mClients[i]); |
| } |
| return (NULL); |
| } |
| /******************************************************************************* |
| ** |
| ** Function: checkClientHandle |
| ** |
| ** Description: Check a PeerToPeer object with a client connection handle. |
| ** jniHandle: Connection handle. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<P2pClient> PeerToPeer::checkClientHandle(tJNI_HANDLE jniHandle) { |
| return findClient(jniHandle); |
| } |
| /******************************************************************************* |
| ** |
| ** Function: findClientCon |
| ** |
| ** Description: Find a PeerToPeer object with a client connection handle. |
| ** nfaConnHandle: Connection handle. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<P2pClient> PeerToPeer::findClientCon(tNFA_HANDLE nfaConnHandle) { |
| AutoMutex mutex(mMutex); |
| for (int i = 0; i < sMax; i++) { |
| if ((mClients[i] != NULL) && |
| (mClients[i]->mClientConn->mNfaConnHandle == nfaConnHandle)) |
| return (mClients[i]); |
| } |
| return (NULL); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findConnection |
| ** |
| ** Description: Find a PeerToPeer object with a connection handle. |
| ** nfaConnHandle: Connection handle. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<NfaConn> PeerToPeer::findConnection(tNFA_HANDLE nfaConnHandle) { |
| AutoMutex mutex(mMutex); |
| // First, look through all the client control blocks |
| for (int ii = 0; ii < sMax; ii++) { |
| if ((mClients[ii] != NULL) && |
| (mClients[ii]->mClientConn->mNfaConnHandle == nfaConnHandle)) { |
| return mClients[ii]->mClientConn; |
| } |
| } |
| |
| // Not found yet. Look through all the server control blocks |
| for (int ii = 0; ii < sMax; ii++) { |
| if (mServers[ii] != NULL) { |
| sp<NfaConn> conn = mServers[ii]->findServerConnection(nfaConnHandle); |
| if (conn != NULL) { |
| return conn; |
| } |
| } |
| } |
| |
| // Not found... |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findConnection |
| ** |
| ** Description: Find a PeerToPeer object with a connection handle. |
| ** jniHandle: Connection handle. |
| ** |
| ** Returns: PeerToPeer object. |
| ** |
| *******************************************************************************/ |
| sp<NfaConn> PeerToPeer::findConnection(tJNI_HANDLE jniHandle) { |
| AutoMutex mutex(mMutex); |
| // First, look through all the client control blocks |
| for (int ii = 0; ii < sMax; ii++) { |
| if ((mClients[ii] != NULL) && |
| (mClients[ii]->mClientConn->mJniHandle == jniHandle)) { |
| return mClients[ii]->mClientConn; |
| } |
| } |
| |
| // Not found yet. Look through all the server control blocks |
| for (int ii = 0; ii < sMax; ii++) { |
| if (mServers[ii] != NULL) { |
| sp<NfaConn> conn = mServers[ii]->findServerConnection(jniHandle); |
| if (conn != NULL) { |
| return conn; |
| } |
| } |
| } |
| |
| // Not found... |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: send |
| ** |
| ** Description: Send data to peer. |
| ** jniHandle: Handle of connection. |
| ** buffer: Buffer of data. |
| ** bufferLen: Length of data. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::send(tJNI_HANDLE jniHandle, uint8_t* buffer, |
| uint16_t bufferLen) { |
| static const char fn[] = "PeerToPeer::send"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| sp<NfaConn> pConn = NULL; |
| |
| if ((pConn = findConnection(jniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: can't find connection handle: %u", fn, |
| jniHandle); |
| return (false); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: send data; jniHandle: %u nfaHandle: 0x%04X", fn, |
| pConn->mJniHandle, pConn->mNfaConnHandle); |
| |
| while (true) { |
| SyncEventGuard guard(pConn->mCongEvent); |
| nfaStat = NFA_P2pSendData(pConn->mNfaConnHandle, bufferLen, buffer); |
| if (nfaStat == NFA_STATUS_CONGESTED) |
| pConn->mCongEvent.wait(); // wait for NFA_P2P_CONGEST_EVT |
| else |
| break; |
| |
| if (pConn->mNfaConnHandle == |
| NFA_HANDLE_INVALID) // peer already disconnected |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: peer disconnected", fn); |
| return (false); |
| } |
| } |
| |
| if (nfaStat == NFA_STATUS_OK) |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit OK; JNI handle: %u NFA Handle: 0x%04x", fn, |
| jniHandle, pConn->mNfaConnHandle); |
| else |
| LOG(ERROR) << StringPrintf( |
| "%s: Data not sent; JNI handle: %u NFA Handle: 0x%04x error: 0x%04x", |
| fn, jniHandle, pConn->mNfaConnHandle, nfaStat); |
| |
| return nfaStat == NFA_STATUS_OK; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: receive |
| ** |
| ** Description: Receive data from peer. |
| ** jniHandle: Handle of connection. |
| ** buffer: Buffer to store data. |
| ** bufferLen: Max length of buffer. |
| ** actualLen: Actual length received. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::receive(tJNI_HANDLE jniHandle, uint8_t* buffer, |
| uint16_t bufferLen, uint16_t& actualLen) { |
| static const char fn[] = "PeerToPeer::receive"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; jniHandle: %u bufferLen: %u", fn, jniHandle, bufferLen); |
| sp<NfaConn> pConn = NULL; |
| tNFA_STATUS stat = NFA_STATUS_FAILED; |
| uint32_t actualDataLen2 = 0; |
| bool isMoreData = TRUE; |
| bool retVal = false; |
| |
| if ((pConn = findConnection(jniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: can't find connection handle: %u", fn, |
| jniHandle); |
| return (false); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: jniHandle: %u nfaHandle: 0x%04X buf len=%u", fn, |
| pConn->mJniHandle, pConn->mNfaConnHandle, bufferLen); |
| |
| while (pConn->mNfaConnHandle != NFA_HANDLE_INVALID) { |
| // NFA_P2pReadData() is synchronous |
| stat = NFA_P2pReadData(pConn->mNfaConnHandle, bufferLen, &actualDataLen2, |
| buffer, &isMoreData); |
| if ((stat == NFA_STATUS_OK) && (actualDataLen2 > 0)) // received some data |
| { |
| actualLen = (uint16_t)actualDataLen2; |
| retVal = true; |
| break; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: waiting for data...", fn); |
| { |
| SyncEventGuard guard(pConn->mReadEvent); |
| pConn->mReadEvent.wait(); |
| } |
| } // while |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; nfa h: 0x%X ok: %u actual len: %u", fn, |
| pConn->mNfaConnHandle, retVal, actualLen); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: disconnectConnOriented |
| ** |
| ** Description: Disconnect a connection-oriented connection with peer. |
| ** jniHandle: Handle of connection. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool PeerToPeer::disconnectConnOriented(tJNI_HANDLE jniHandle) { |
| static const char fn[] = "PeerToPeer::disconnectConnOriented"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| sp<P2pClient> pClient = NULL; |
| sp<NfaConn> pConn = NULL; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; jni handle: %u", fn, jniHandle); |
| |
| if ((pConn = findConnection(jniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: can't find connection handle: %u", fn, |
| jniHandle); |
| return (false); |
| } |
| |
| // If this is a client, he may not be connected yet, so unblock him just in |
| // case |
| if (((pClient = findClient(jniHandle)) != NULL) && (pClient->mIsConnecting)) { |
| SyncEventGuard guard(pClient->mConnectingEvent); |
| pClient->mConnectingEvent.notifyOne(); |
| return (true); |
| } |
| |
| { |
| SyncEventGuard guard1(pConn->mCongEvent); |
| pConn->mCongEvent.notifyOne(); // unblock send() if congested |
| } |
| { |
| SyncEventGuard guard2(pConn->mReadEvent); |
| pConn->mReadEvent.notifyOne(); // unblock receive() |
| } |
| |
| if (pConn->mNfaConnHandle != NFA_HANDLE_INVALID) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: try disconn nfa h=0x%04X", fn, pConn->mNfaConnHandle); |
| SyncEventGuard guard(pConn->mDisconnectingEvent); |
| nfaStat = NFA_P2pDisconnect(pConn->mNfaConnHandle, FALSE); |
| |
| if (nfaStat != NFA_STATUS_OK) |
| LOG(ERROR) << StringPrintf("%s: fail p2p disconnect", fn); |
| else |
| pConn->mDisconnectingEvent.wait(); |
| } |
| |
| mDisconnectMutex.lock(); |
| removeConn(jniHandle); |
| mDisconnectMutex.unlock(); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; jni handle: %u", fn, jniHandle); |
| return nfaStat == NFA_STATUS_OK; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getRemoteMaxInfoUnit |
| ** |
| ** Description: Get peer's max information unit. |
| ** jniHandle: Handle of the connection. |
| ** |
| ** Returns: Peer's max information unit. |
| ** |
| *******************************************************************************/ |
| uint16_t PeerToPeer::getRemoteMaxInfoUnit(tJNI_HANDLE jniHandle) { |
| static const char fn[] = "PeerToPeer::getRemoteMaxInfoUnit"; |
| sp<NfaConn> pConn = NULL; |
| |
| if ((pConn = findConnection(jniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: can't find client jniHandle: %u", fn, |
| jniHandle); |
| return 0; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: jniHandle: %u MIU: %u", fn, jniHandle, pConn->mRemoteMaxInfoUnit); |
| return (pConn->mRemoteMaxInfoUnit); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getRemoteRecvWindow |
| ** |
| ** Description: Get peer's receive window size. |
| ** jniHandle: Handle of the connection. |
| ** |
| ** Returns: Peer's receive window size. |
| ** |
| *******************************************************************************/ |
| uint8_t PeerToPeer::getRemoteRecvWindow(tJNI_HANDLE jniHandle) { |
| static const char fn[] = "PeerToPeer::getRemoteRecvWindow"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: client jni handle: %u", fn, jniHandle); |
| sp<NfaConn> pConn = NULL; |
| |
| if ((pConn = findConnection(jniHandle)) == NULL) { |
| LOG(ERROR) << StringPrintf("%s: can't find client", fn); |
| return 0; |
| } |
| return pConn->mRemoteRecvWindow; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: setP2pListenMask |
| ** |
| ** Description: Sets the p2p listen technology mask. |
| ** p2pListenMask: the p2p listen mask to be set? |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::setP2pListenMask(tNFA_TECHNOLOGY_MASK p2pListenMask) { |
| mP2pListenTechMask = p2pListenMask; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getP2pListenMask |
| ** |
| ** Description: Get the set of technologies that P2P is listening. |
| ** |
| ** Returns: Set of technologies. |
| ** |
| *******************************************************************************/ |
| tNFA_TECHNOLOGY_MASK PeerToPeer::getP2pListenMask() { |
| return mP2pListenTechMask; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: resetP2pListenMask |
| ** |
| ** Description: Reset the p2p listen technology mask to initial value. |
| ** |
| ** Returns: None. |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::resetP2pListenMask() { |
| mP2pListenTechMask = NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F | |
| NFA_TECHNOLOGY_MASK_A_ACTIVE | |
| NFA_TECHNOLOGY_MASK_F_ACTIVE; |
| #if (NXP_EXTNS == TRUE) |
| if (NfcConfig::hasKey(NAME_P2P_LISTEN_TECH_MASK)) |
| mP2pListenTechMask = NfcConfig::getUnsigned(NAME_P2P_LISTEN_TECH_MASK); |
| #else |
| if (NfcConfig::hasKey("P2P_LISTEN_TECH_MASK")) |
| mP2pListenTechMask = NfcConfig::getUnsigned("P2P_LISTEN_TECH_MASK"); |
| #endif |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: enableP2pListening |
| ** |
| ** Description: Start/stop polling/listening to peer that supports P2P. |
| ** isEnable: Is enable polling/listening? |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::enableP2pListening(bool isEnable) { |
| static const char fn[] = "PeerToPeer::enableP2pListening"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter isEnable: %u mIsP2pListening: %u", fn, |
| isEnable, mIsP2pListening); |
| |
| // If request to enable P2P listening, and we were not already listening |
| if ((isEnable == true) && (mIsP2pListening == false) && |
| (mP2pListenTechMask != 0)) { |
| SyncEventGuard guard(mSetTechEvent); |
| if ((nfaStat = NFA_SetP2pListenTech(mP2pListenTechMask)) == NFA_STATUS_OK) { |
| mSetTechEvent.wait(); |
| mIsP2pListening = true; |
| } else |
| LOG(ERROR) << StringPrintf("%s: fail enable listen; error=0x%X", fn, |
| nfaStat); |
| } else if ((isEnable == false) && (mIsP2pListening == true)) { |
| SyncEventGuard guard(mSetTechEvent); |
| // Request to disable P2P listening, check if it was enabled |
| if ((nfaStat = NFA_SetP2pListenTech(0)) == NFA_STATUS_OK) { |
| mSetTechEvent.wait(); |
| mIsP2pListening = false; |
| } else |
| LOG(ERROR) << StringPrintf("%s: fail disable listen; error=0x%X", fn, |
| nfaStat); |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; mIsP2pListening: %u", fn, mIsP2pListening); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: handleNfcOnOff |
| ** |
| ** Description: Handle events related to turning NFC on/off by the user. |
| ** isOn: Is NFC turning on? |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::handleNfcOnOff(bool isOn) { |
| static const char fn[] = "PeerToPeer::handleNfcOnOff"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; is on=%u", fn, isOn); |
| |
| mIsP2pListening = false; // In both cases, P2P will not be listening |
| |
| AutoMutex mutex(mMutex); |
| if (isOn) { |
| // Start with no clients or servers |
| memset(mServers, 0, sizeof(mServers)); |
| memset(mClients, 0, sizeof(mClients)); |
| } else { |
| // Disconnect through all the clients |
| for (int ii = 0; ii < sMax; ii++) { |
| if (mClients[ii] != NULL) { |
| if (mClients[ii]->mClientConn->mNfaConnHandle == NFA_HANDLE_INVALID) { |
| SyncEventGuard guard(mClients[ii]->mConnectingEvent); |
| mClients[ii]->mConnectingEvent.notifyOne(); |
| } else { |
| mClients[ii]->mClientConn->mNfaConnHandle = NFA_HANDLE_INVALID; |
| { |
| SyncEventGuard guard1(mClients[ii]->mClientConn->mCongEvent); |
| mClients[ii] |
| ->mClientConn->mCongEvent.notifyOne(); // unblock send() |
| } |
| { |
| SyncEventGuard guard2(mClients[ii]->mClientConn->mReadEvent); |
| mClients[ii] |
| ->mClientConn->mReadEvent.notifyOne(); // unblock receive() |
| } |
| } |
| } |
| } // loop |
| |
| // Now look through all the server control blocks |
| for (int ii = 0; ii < sMax; ii++) { |
| if (mServers[ii] != NULL) { |
| mServers[ii]->unblockAll(); |
| } |
| } // loop |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: nfaServerCallback |
| ** |
| ** Description: Receive LLCP-related events from the stack. |
| ** p2pEvent: Event code. |
| ** eventData: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::nfaServerCallback(tNFA_P2P_EVT p2pEvent, |
| tNFA_P2P_EVT_DATA* eventData) { |
| static const char fn[] = "PeerToPeer::nfaServerCallback"; |
| sp<P2pServer> pSrv = NULL; |
| sp<NfaConn> pConn = NULL; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; event=0x%X", fn, p2pEvent); |
| |
| #if (NXP_EXTNS == TRUE) |
| NativeJniExtns::getInstance().notifyNfcEvent( |
| "nfaClientCallback", (void*)&p2pEvent, (void*)&eventData); |
| #endif |
| switch (p2pEvent) { |
| case NFA_P2P_REG_SERVER_EVT: // NFA_P2pRegisterServer() has started to |
| // listen |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_REG_SERVER_EVT; handle: 0x%04x; service sap=0x%02x " |
| "name: " |
| "%s", |
| fn, eventData->reg_server.server_handle, |
| eventData->reg_server.server_sap, eventData->reg_server.service_name); |
| |
| sP2p.mMutex.lock(); |
| pSrv = sP2p.findServerLocked(eventData->reg_server.service_name); |
| sP2p.mMutex.unlock(); |
| if (pSrv == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_REG_SERVER_EVT for unknown service: %s", fn, |
| eventData->reg_server.service_name); |
| } else { |
| SyncEventGuard guard(pSrv->mRegServerEvent); |
| pSrv->mNfaP2pServerHandle = eventData->reg_server.server_handle; |
| pSrv->mRegServerEvent.notifyOne(); // unblock registerServer() |
| } |
| break; |
| |
| case NFA_P2P_ACTIVATED_EVT: // remote device has activated |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_ACTIVATED_EVT; handle: 0x%04x", fn, |
| eventData->activated.handle); |
| break; |
| |
| case NFA_P2P_DEACTIVATED_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DEACTIVATED_EVT; handle: 0x%04x", fn, |
| eventData->activated.handle); |
| break; |
| |
| case NFA_P2P_CONN_REQ_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_CONN_REQ_EVT; nfa server h=0x%04x; nfa conn h=0x%04x; " |
| "remote sap=0x%02x", |
| fn, eventData->conn_req.server_handle, |
| eventData->conn_req.conn_handle, eventData->conn_req.remote_sap); |
| |
| sP2p.mMutex.lock(); |
| pSrv = sP2p.findServerLocked(eventData->conn_req.server_handle); |
| sP2p.mMutex.unlock(); |
| if (pSrv == NULL) { |
| LOG(ERROR) << StringPrintf("%s: NFA_P2P_CONN_REQ_EVT; unknown server h", |
| fn); |
| return; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_CONN_REQ_EVT; server jni h=%u", fn, pSrv->mJniHandle); |
| |
| // Look for a connection block that is waiting (handle invalid) |
| if ((pConn = pSrv->findServerConnection( |
| (tNFA_HANDLE)NFA_HANDLE_INVALID)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_CONN_REQ_EVT; server not listening", fn); |
| } else { |
| SyncEventGuard guard(pSrv->mConnRequestEvent); |
| pConn->mNfaConnHandle = eventData->conn_req.conn_handle; |
| pConn->mRemoteMaxInfoUnit = eventData->conn_req.remote_miu; |
| pConn->mRemoteRecvWindow = eventData->conn_req.remote_rw; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_CONN_REQ_EVT; server jni h=%u; conn jni " |
| "h=%u; notify conn req", |
| fn, pSrv->mJniHandle, pConn->mJniHandle); |
| pSrv->mConnRequestEvent.notifyOne(); // unblock accept() |
| } |
| break; |
| |
| case NFA_P2P_CONNECTED_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_CONNECTED_EVT; h=0x%x remote sap=0x%X", fn, |
| eventData->connected.client_handle, eventData->connected.remote_sap); |
| break; |
| |
| case NFA_P2P_DISC_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DISC_EVT; h=0x%04x; reason=0x%X", fn, |
| eventData->disc.handle, eventData->disc.reason); |
| // Look for the connection block |
| if ((pConn = sP2p.findConnection(eventData->disc.handle)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT: can't find conn for NFA handle: 0x%04x", fn, |
| eventData->disc.handle); |
| } else { |
| sP2p.mDisconnectMutex.lock(); |
| pConn->mNfaConnHandle = NFA_HANDLE_INVALID; |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; try guard disconn event", fn); |
| SyncEventGuard guard3(pConn->mDisconnectingEvent); |
| pConn->mDisconnectingEvent.notifyOne(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; notified disconn event", fn); |
| } |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; try guard congest event", fn); |
| SyncEventGuard guard1(pConn->mCongEvent); |
| pConn->mCongEvent.notifyOne(); // unblock write (if congested) |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; notified congest event", fn); |
| } |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DISC_EVT; try guard read event", fn); |
| SyncEventGuard guard2(pConn->mReadEvent); |
| pConn->mReadEvent.notifyOne(); // unblock receive() |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DISC_EVT; notified read event", fn); |
| } |
| sP2p.mDisconnectMutex.unlock(); |
| } |
| break; |
| |
| case NFA_P2P_DATA_EVT: |
| // Look for the connection block |
| if ((pConn = sP2p.findConnection(eventData->data.handle)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_DATA_EVT: can't find conn for NFA handle: 0x%04x", fn, |
| eventData->data.handle); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DATA_EVT; h=0x%X; remote sap=0x%X", fn, |
| eventData->data.handle, eventData->data.remote_sap); |
| SyncEventGuard guard(pConn->mReadEvent); |
| pConn->mReadEvent.notifyOne(); |
| } |
| break; |
| |
| case NFA_P2P_CONGEST_EVT: |
| // Look for the connection block |
| if ((pConn = sP2p.findConnection(eventData->congest.handle)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_CONGEST_EVT: can't find conn for NFA handle: 0x%04x", |
| fn, eventData->congest.handle); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_CONGEST_EVT; nfa handle: 0x%04x congested: %u", fn, |
| eventData->congest.handle, eventData->congest.is_congested); |
| if (eventData->congest.is_congested == FALSE) { |
| SyncEventGuard guard(pConn->mCongEvent); |
| pConn->mCongEvent.notifyOne(); |
| } |
| } |
| break; |
| |
| default: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: unknown event 0x%X ????", fn, p2pEvent); |
| break; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: nfaClientCallback |
| ** |
| ** Description: Receive LLCP-related events from the stack. |
| ** p2pEvent: Event code. |
| ** eventData: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::nfaClientCallback(tNFA_P2P_EVT p2pEvent, |
| tNFA_P2P_EVT_DATA* eventData) { |
| static const char fn[] = "PeerToPeer::nfaClientCallback"; |
| sp<NfaConn> pConn = NULL; |
| sp<P2pClient> pClient = NULL; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; event=%u", fn, p2pEvent); |
| #if (NXP_EXTNS == TRUE) |
| NativeJniExtns::getInstance().notifyNfcEvent( |
| "nfaClientCallback", (void*)&p2pEvent, (void*)&eventData); |
| #endif |
| switch (p2pEvent) { |
| case NFA_P2P_REG_CLIENT_EVT: |
| // Look for a client that is trying to register |
| if ((pClient = sP2p.findClient((tNFA_HANDLE)NFA_HANDLE_INVALID)) == |
| NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_REG_CLIENT_EVT: can't find waiting client", fn); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_REG_CLIENT_EVT; Conn Handle: 0x%04x, pClient: 0x%p", |
| fn, eventData->reg_client.client_handle, pClient.get()); |
| |
| SyncEventGuard guard(pClient->mRegisteringEvent); |
| pClient->mNfaP2pClientHandle = eventData->reg_client.client_handle; |
| pClient->mRegisteringEvent.notifyOne(); |
| } |
| break; |
| |
| case NFA_P2P_ACTIVATED_EVT: |
| // Look for a client that is trying to register |
| if ((pClient = sP2p.findClient(eventData->activated.handle)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_ACTIVATED_EVT: can't find client", fn); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_ACTIVATED_EVT; Conn Handle: 0x%04x, pClient: 0x%p", fn, |
| eventData->activated.handle, pClient.get()); |
| } |
| break; |
| |
| case NFA_P2P_DEACTIVATED_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DEACTIVATED_EVT: conn handle: 0x%X", fn, |
| eventData->deactivated.handle); |
| break; |
| |
| case NFA_P2P_CONNECTED_EVT: |
| // Look for the client that is trying to connect |
| if ((pClient = sP2p.findClient(eventData->connected.client_handle)) == |
| NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_CONNECTED_EVT: can't find client: 0x%04x", fn, |
| eventData->connected.client_handle); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_CONNECTED_EVT; client_handle=0x%04x " |
| "conn_handle: 0x%04x remote sap=0x%X pClient: 0x%p", |
| fn, eventData->connected.client_handle, |
| eventData->connected.conn_handle, eventData->connected.remote_sap, |
| pClient.get()); |
| |
| SyncEventGuard guard(pClient->mConnectingEvent); |
| pClient->mClientConn->mNfaConnHandle = eventData->connected.conn_handle; |
| pClient->mClientConn->mRemoteMaxInfoUnit = |
| eventData->connected.remote_miu; |
| pClient->mClientConn->mRemoteRecvWindow = |
| eventData->connected.remote_rw; |
| pClient->mConnectingEvent.notifyOne(); // unblock createDataLinkConn() |
| } |
| break; |
| |
| case NFA_P2P_DISC_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DISC_EVT; h=0x%04x; reason=0x%X", fn, |
| eventData->disc.handle, eventData->disc.reason); |
| // Look for the connection block |
| if ((pConn = sP2p.findConnection(eventData->disc.handle)) == NULL) { |
| // If no connection, may be a client that is trying to connect |
| if ((pClient = sP2p.findClient(eventData->disc.handle)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT: can't find client for NFA handle: 0x%04x", |
| fn, eventData->disc.handle); |
| return; |
| } |
| // Unblock createDataLinkConn() |
| SyncEventGuard guard(pClient->mConnectingEvent); |
| pClient->mConnectingEvent.notifyOne(); |
| } else { |
| sP2p.mDisconnectMutex.lock(); |
| pConn->mNfaConnHandle = NFA_HANDLE_INVALID; |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; try guard disconn event", fn); |
| SyncEventGuard guard3(pConn->mDisconnectingEvent); |
| pConn->mDisconnectingEvent.notifyOne(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; notified disconn event", fn); |
| } |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; try guard congest event", fn); |
| SyncEventGuard guard1(pConn->mCongEvent); |
| pConn->mCongEvent.notifyOne(); // unblock write (if congested) |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_DISC_EVT; notified congest event", fn); |
| } |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DISC_EVT; try guard read event", fn); |
| SyncEventGuard guard2(pConn->mReadEvent); |
| pConn->mReadEvent.notifyOne(); // unblock receive() |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DISC_EVT; notified read event", fn); |
| } |
| sP2p.mDisconnectMutex.unlock(); |
| } |
| break; |
| |
| case NFA_P2P_DATA_EVT: |
| // Look for the connection block |
| if ((pConn = sP2p.findConnection(eventData->data.handle)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_DATA_EVT: can't find conn for NFA handle: 0x%04x", fn, |
| eventData->data.handle); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_P2P_DATA_EVT; h=0x%X; remote sap=0x%X", fn, |
| eventData->data.handle, eventData->data.remote_sap); |
| SyncEventGuard guard(pConn->mReadEvent); |
| pConn->mReadEvent.notifyOne(); |
| } |
| break; |
| |
| case NFA_P2P_CONGEST_EVT: |
| // Look for the connection block |
| if ((pConn = sP2p.findConnection(eventData->congest.handle)) == NULL) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_P2P_CONGEST_EVT: can't find conn for NFA handle: 0x%04x", |
| fn, eventData->congest.handle); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_P2P_CONGEST_EVT; nfa handle: 0x%04x congested: %u", fn, |
| eventData->congest.handle, eventData->congest.is_congested); |
| |
| SyncEventGuard guard(pConn->mCongEvent); |
| pConn->mCongEvent.notifyOne(); |
| } |
| break; |
| |
| default: |
| LOG(ERROR) << StringPrintf("%s: unknown event 0x%X ????", fn, p2pEvent); |
| break; |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: connectionEventHandler |
| ** |
| ** Description: Receive events from the stack. |
| ** event: Event code. |
| ** eventData: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void PeerToPeer::connectionEventHandler(uint8_t event, |
| tNFA_CONN_EVT_DATA* /*eventData*/) { |
| switch (event) { |
| case NFA_SET_P2P_LISTEN_TECH_EVT: { |
| SyncEventGuard guard(mSetTechEvent); |
| mSetTechEvent.notifyOne(); // unblock NFA_SetP2pListenTech() |
| break; |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getNextJniHandle |
| ** |
| ** Description: Get a new JNI handle. |
| ** |
| ** Returns: A new JNI handle. |
| ** |
| *******************************************************************************/ |
| PeerToPeer::tJNI_HANDLE PeerToPeer::getNewJniHandle() { |
| tJNI_HANDLE newHandle = 0; |
| |
| mNewJniHandleMutex.lock(); |
| newHandle = mNextJniHandle++; |
| mNewJniHandleMutex.unlock(); |
| return newHandle; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| ///////////////////////////////////////////////////////////////////////// |
| |
| /******************************************************************************* |
| ** |
| ** Function: P2pServer |
| ** |
| ** Description: Initialize member variables. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| P2pServer::P2pServer(PeerToPeer::tJNI_HANDLE jniHandle, const char* serviceName) |
| : mNfaP2pServerHandle(NFA_HANDLE_INVALID), mJniHandle(jniHandle) { |
| mServiceName.assign(serviceName); |
| |
| memset(mServerConn, 0, sizeof(mServerConn)); |
| } |
| |
| bool P2pServer::registerWithStack() { |
| static const char fn[] = "P2pServer::registerWithStack"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; service name: %s JNI handle: %u", fn, |
| mServiceName.c_str(), mJniHandle); |
| tNFA_STATUS stat = NFA_STATUS_OK; |
| uint8_t serverSap = NFA_P2P_ANY_SAP; |
| |
| /********************** |
| default values for all LLCP parameters: |
| - Local Link MIU (LLCP_MIU) |
| - Option parameter (LLCP_OPT_VALUE) |
| - Response Waiting Time Index (LLCP_WAITING_TIME) |
| - Local Link Timeout (LLCP_LTO_VALUE) |
| - Inactivity Timeout as initiator role (LLCP_INIT_INACTIVITY_TIMEOUT) |
| - Inactivity Timeout as target role (LLCP_TARGET_INACTIVITY_TIMEOUT) |
| - Delay SYMM response (LLCP_DELAY_RESP_TIME) |
| - Data link connection timeout (LLCP_DATA_LINK_CONNECTION_TOUT) |
| - Delay timeout to send first PDU as initiator |
| (LLCP_DELAY_TIME_TO_SEND_FIRST_PDU) |
| ************************/ |
| stat = NFA_P2pSetLLCPConfig(LLCP_MAX_MIU, LLCP_OPT_VALUE, LLCP_WAITING_TIME, |
| LLCP_LTO_VALUE, |
| 0, // use 0 for infinite timeout for symmetry |
| // procedure when acting as initiator |
| 0, // use 0 for infinite timeout for symmetry |
| // procedure when acting as target |
| LLCP_DELAY_RESP_TIME, LLCP_DATA_LINK_TIMEOUT, |
| LLCP_DELAY_TIME_TO_SEND_FIRST_PDU); |
| if (stat != NFA_STATUS_OK) |
| LOG(ERROR) << StringPrintf("%s: fail set LLCP config; error=0x%X", fn, |
| stat); |
| |
| if (sSnepServiceName.compare(mServiceName) == 0) |
| serverSap = 4; // LLCP_SAP_SNEP == 4 |
| |
| { |
| SyncEventGuard guard(mRegServerEvent); |
| stat = NFA_P2pRegisterServer(serverSap, NFA_P2P_DLINK_TYPE, |
| const_cast<char*>(mServiceName.c_str()), |
| PeerToPeer::nfaServerCallback); |
| if (stat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail register p2p server; error=0x%X", fn, |
| stat); |
| return (false); |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: wait for listen-completion event", fn); |
| // Wait for NFA_P2P_REG_SERVER_EVT |
| mRegServerEvent.wait(); |
| } |
| |
| return (mNfaP2pServerHandle != NFA_HANDLE_INVALID); |
| } |
| |
| bool P2pServer::accept(PeerToPeer::tJNI_HANDLE serverJniHandle, |
| PeerToPeer::tJNI_HANDLE connJniHandle, int maxInfoUnit, |
| int recvWindow) { |
| static const char fn[] = "P2pServer::accept"; |
| tNFA_STATUS nfaStat = NFA_STATUS_OK; |
| |
| sp<NfaConn> connection = allocateConnection(connJniHandle); |
| if (connection == NULL) { |
| LOG(ERROR) << StringPrintf("%s: failed to allocate new server connection", |
| fn); |
| return false; |
| } |
| |
| { |
| // Wait for NFA_P2P_CONN_REQ_EVT or NFA_NDEF_DATA_EVT when remote device |
| // requests connection |
| SyncEventGuard guard(mConnRequestEvent); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: serverJniHandle: %u; connJniHandle: %u; wait for " |
| "incoming connection", |
| fn, serverJniHandle, connJniHandle); |
| mConnRequestEvent.wait(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: serverJniHandle: %u; connJniHandle: %u; nfa conn h: 0x%X; got " |
| "incoming connection", |
| fn, serverJniHandle, connJniHandle, connection->mNfaConnHandle); |
| } |
| |
| if (connection->mNfaConnHandle == NFA_HANDLE_INVALID) { |
| removeServerConnection(connJniHandle); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: no handle assigned", fn); |
| return (false); |
| } |
| |
| if (maxInfoUnit > (int)LLCP_MIU) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: overriding the miu passed by the app(%d) with stack miu(%zu)", fn, |
| maxInfoUnit, LLCP_MIU); |
| maxInfoUnit = LLCP_MIU; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: serverJniHandle: %u; connJniHandle: %u; nfa conn h: 0x%X; try " |
| "accept", |
| fn, serverJniHandle, connJniHandle, connection->mNfaConnHandle); |
| nfaStat = |
| NFA_P2pAcceptConn(connection->mNfaConnHandle, maxInfoUnit, recvWindow); |
| |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail to accept remote; error=0x%X", fn, |
| nfaStat); |
| return (false); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: exit; serverJniHandle: %u; connJniHandle: %u; nfa conn h: 0x%X", fn, |
| serverJniHandle, connJniHandle, connection->mNfaConnHandle); |
| return (true); |
| } |
| |
| void P2pServer::unblockAll() { |
| AutoMutex mutex(mMutex); |
| for (int jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) { |
| if (mServerConn[jj] != NULL) { |
| mServerConn[jj]->mNfaConnHandle = NFA_HANDLE_INVALID; |
| { |
| SyncEventGuard guard1(mServerConn[jj]->mCongEvent); |
| mServerConn[jj] |
| ->mCongEvent.notifyOne(); // unblock write (if congested) |
| } |
| { |
| SyncEventGuard guard2(mServerConn[jj]->mReadEvent); |
| mServerConn[jj]->mReadEvent.notifyOne(); // unblock receive() |
| } |
| } |
| } |
| } |
| |
| sp<NfaConn> P2pServer::allocateConnection(PeerToPeer::tJNI_HANDLE jniHandle) { |
| AutoMutex mutex(mMutex); |
| // First, find a free connection block to handle the connection |
| for (int ii = 0; ii < MAX_NFA_CONNS_PER_SERVER; ii++) { |
| if (mServerConn[ii] == NULL) { |
| mServerConn[ii] = new NfaConn; |
| mServerConn[ii]->mJniHandle = jniHandle; |
| return mServerConn[ii]; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findServerConnection |
| ** |
| ** Description: Find a P2pServer that has the handle. |
| ** nfaConnHandle: NFA connection handle. |
| ** |
| ** Returns: P2pServer object. |
| ** |
| *******************************************************************************/ |
| sp<NfaConn> P2pServer::findServerConnection(tNFA_HANDLE nfaConnHandle) { |
| int jj = 0; |
| |
| AutoMutex mutex(mMutex); |
| for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) { |
| if ((mServerConn[jj] != NULL) && |
| (mServerConn[jj]->mNfaConnHandle == nfaConnHandle)) |
| return (mServerConn[jj]); |
| } |
| |
| // If here, not found |
| return (NULL); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findServerConnection |
| ** |
| ** Description: Find a P2pServer that has the handle. |
| ** nfaConnHandle: NFA connection handle. |
| ** |
| ** Returns: P2pServer object. |
| ** |
| *******************************************************************************/ |
| sp<NfaConn> P2pServer::findServerConnection(PeerToPeer::tJNI_HANDLE jniHandle) { |
| int jj = 0; |
| |
| AutoMutex mutex(mMutex); |
| for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) { |
| if ((mServerConn[jj] != NULL) && (mServerConn[jj]->mJniHandle == jniHandle)) |
| return (mServerConn[jj]); |
| } |
| |
| // If here, not found |
| return (NULL); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: removeServerConnection |
| ** |
| ** Description: Find a P2pServer that has the handle. |
| ** nfaConnHandle: NFA connection handle. |
| ** |
| ** Returns: P2pServer object. |
| ** |
| *******************************************************************************/ |
| bool P2pServer::removeServerConnection(PeerToPeer::tJNI_HANDLE jniHandle) { |
| int jj = 0; |
| |
| AutoMutex mutex(mMutex); |
| for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) { |
| if ((mServerConn[jj] != NULL) && |
| (mServerConn[jj]->mJniHandle == jniHandle)) { |
| mServerConn[jj] = NULL; |
| return true; |
| } |
| } |
| |
| // If here, not found |
| return false; |
| } |
| ///////////////////////////////////////////////////////////////////////// |
| ///////////////////////////////////////////////////////////////////////// |
| |
| /******************************************************************************* |
| ** |
| ** Function: P2pClient |
| ** |
| ** Description: Initialize member variables. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| P2pClient::P2pClient() |
| : mNfaP2pClientHandle(NFA_HANDLE_INVALID), mIsConnecting(false) { |
| mClientConn = new NfaConn(); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: ~P2pClient |
| ** |
| ** Description: Free all resources. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| P2pClient::~P2pClient() {} |
| |
| ///////////////////////////////////////////////////////////////////////// |
| ///////////////////////////////////////////////////////////////////////// |
| |
| /******************************************************************************* |
| ** |
| ** Function: NfaConn |
| ** |
| ** Description: Initialize member variables. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| NfaConn::NfaConn() |
| : mNfaConnHandle(NFA_HANDLE_INVALID), |
| mJniHandle(0), |
| mMaxInfoUnit(0), |
| mRecvWindow(0), |
| mRemoteMaxInfoUnit(0), |
| mRemoteRecvWindow(0) {} |