/* * Copyright (C) 2008 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. */ #include <stdlib.h> #include <string.h> #include <errno.h> #define LOG_TAG "WifiController" #include <cutils/log.h> #include "Supplicant.h" #include "WifiController.h" #include "NetworkManager.h" #include "ResponseCode.h" #include "WifiNetwork.h" #include "ISupplicantEventHandler.h" #include "SupplicantState.h" #include "SupplicantStatus.h" #include "SupplicantAssociatingEvent.h" #include "SupplicantAssociatedEvent.h" #include "SupplicantConnectedEvent.h" #include "SupplicantScanResultsEvent.h" #include "SupplicantStateChangeEvent.h" #include "SupplicantConnectionTimeoutEvent.h" #include "SupplicantDisconnectedEvent.h" #include "WifiStatusPoller.h" WifiController::WifiController(PropertyManager *mPropMngr, IControllerHandler *handlers, char *modpath, char *modname, char *modargs) : Controller("wifi", mPropMngr, handlers) { strncpy(mModulePath, modpath, sizeof(mModulePath)); strncpy(mModuleName, modname, sizeof(mModuleName)); strncpy(mModuleArgs, modargs, sizeof(mModuleArgs)); mLatestScanResults = new ScanResultCollection(); pthread_mutex_init(&mLatestScanResultsLock, NULL); pthread_mutex_init(&mLock, NULL); mSupplicant = new Supplicant(this, this); mActiveScan = false; mEnabled = false; mScanOnly = false; mPacketFilter = false; mBluetoothCoexScan = false; mBluetoothCoexMode = 0; mCurrentlyConnectedNetworkId = -1; mStatusPoller = new WifiStatusPoller(this); mRssiEventThreshold = 5; mLastLinkSpeed = 0; mSupplicantState = SupplicantState::UNKNOWN; mStaticProperties.propEnabled = new WifiEnabledProperty(this); mStaticProperties.propScanOnly = new WifiScanOnlyProperty(this); mStaticProperties.propAllowedChannels = new WifiAllowedChannelsProperty(this); mStaticProperties.propRssiEventThreshold = new IntegerPropertyHelper("RssiEventThreshold", false, &mRssiEventThreshold); mDynamicProperties.propSupplicantState = new WifiSupplicantStateProperty(this); mDynamicProperties.propActiveScan = new WifiActiveScanProperty(this); mDynamicProperties.propInterface = new WifiInterfaceProperty(this); mDynamicProperties.propSearching = new WifiSearchingProperty(this); mDynamicProperties.propPacketFilter = new WifiPacketFilterProperty(this); mDynamicProperties.propBluetoothCoexScan = new WifiBluetoothCoexScanProperty(this); mDynamicProperties.propBluetoothCoexMode = new WifiBluetoothCoexModeProperty(this); mDynamicProperties.propCurrentNetwork = new WifiCurrentNetworkProperty(this); mDynamicProperties.propRssi = new IntegerPropertyHelper("Rssi", true, &mLastRssi); mDynamicProperties.propLinkSpeed = new IntegerPropertyHelper("LinkSpeed", true, &mLastLinkSpeed); mDynamicProperties.propSuspended = new WifiSuspendedProperty(this); mDynamicProperties.propNetCount = new WifiNetCountProperty(this); mDynamicProperties.propTriggerScan = new WifiTriggerScanProperty(this); } int WifiController::start() { mPropMngr->attachProperty("wifi", mStaticProperties.propEnabled); mPropMngr->attachProperty("wifi", mStaticProperties.propScanOnly); mPropMngr->attachProperty("wifi", mStaticProperties.propAllowedChannels); mPropMngr->attachProperty("wifi", mStaticProperties.propRssiEventThreshold); return 0; } int WifiController::stop() { mPropMngr->detachProperty("wifi", mStaticProperties.propEnabled); mPropMngr->detachProperty("wifi", mStaticProperties.propScanOnly); mPropMngr->detachProperty("wifi", mStaticProperties.propAllowedChannels); mPropMngr->detachProperty("wifi", mStaticProperties.propRssiEventThreshold); return 0; } int WifiController::enable() { if (!isPoweredUp()) { LOGI("Powering up"); sendStatusBroadcast("Powering up WiFi hardware"); if (powerUp()) { LOGE("Powerup failed (%s)", strerror(errno)); return -1; } } if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) { LOGI("Loading driver"); sendStatusBroadcast("Loading WiFi driver"); if (loadKernelModule(mModulePath, mModuleArgs)) { LOGE("Kernel module load failed (%s)", strerror(errno)); goto out_powerdown; } } if (!isFirmwareLoaded()) { LOGI("Loading firmware"); sendStatusBroadcast("Loading WiFI firmware"); if (loadFirmware()) { LOGE("Firmware load failed (%s)", strerror(errno)); goto out_powerdown; } } if (!mSupplicant->isStarted()) { LOGI("Starting WPA Supplicant"); sendStatusBroadcast("Starting WPA Supplicant"); if (mSupplicant->start()) { LOGE("Supplicant start failed (%s)", strerror(errno)); goto out_unloadmodule; } } if (Controller::bindInterface(mSupplicant->getInterfaceName())) { LOGE("Error binding interface (%s)", strerror(errno)); goto out_unloadmodule; } if (mSupplicant->refreshNetworkList()) LOGW("Error getting list of networks (%s)", strerror(errno)); LOGW("TODO: Set # of allowed regulatory channels!"); mPropMngr->attachProperty("wifi", mDynamicProperties.propSupplicantState); mPropMngr->attachProperty("wifi", mDynamicProperties.propActiveScan); mPropMngr->attachProperty("wifi", mDynamicProperties.propInterface); mPropMngr->attachProperty("wifi", mDynamicProperties.propSearching); mPropMngr->attachProperty("wifi", mDynamicProperties.propPacketFilter); mPropMngr->attachProperty("wifi", mDynamicProperties.propBluetoothCoexScan); mPropMngr->attachProperty("wifi", mDynamicProperties.propBluetoothCoexMode); mPropMngr->attachProperty("wifi", mDynamicProperties.propCurrentNetwork); mPropMngr->attachProperty("wifi", mDynamicProperties.propRssi); mPropMngr->attachProperty("wifi", mDynamicProperties.propLinkSpeed); mPropMngr->attachProperty("wifi", mDynamicProperties.propSuspended); mPropMngr->attachProperty("wifi", mDynamicProperties.propNetCount); mPropMngr->attachProperty("wifi", mDynamicProperties.propTriggerScan); LOGI("Enabled successfully"); return 0; out_unloadmodule: if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) { if (unloadKernelModule(mModuleName)) { LOGE("Unable to unload module after failure!"); } } out_powerdown: if (powerDown()) { LOGE("Unable to powerdown after failure!"); } return -1; } bool WifiController::getSuspended() { pthread_mutex_lock(&mLock); bool r = mSuspended; pthread_mutex_unlock(&mLock); return r; } int WifiController::setSuspend(bool suspend) { pthread_mutex_lock(&mLock); if (suspend == mSuspended) { LOGW("Suspended state already = %d", suspend); pthread_mutex_unlock(&mLock); return 0; } if (suspend) { mHandlers->onControllerSuspending(this); char tmp[80]; LOGD("Suspending from supplicant state %s", SupplicantState::toString(mSupplicantState, tmp, sizeof(tmp))); if (mSupplicantState != SupplicantState::IDLE) { LOGD("Forcing Supplicant disconnect"); if (mSupplicant->disconnect()) { LOGW("Error disconnecting (%s)", strerror(errno)); } } LOGD("Stopping Supplicant driver"); if (mSupplicant->stopDriver()) { LOGE("Error stopping driver (%s)", strerror(errno)); pthread_mutex_unlock(&mLock); return -1; } } else { LOGD("Resuming"); if (mSupplicant->startDriver()) { LOGE("Error resuming driver (%s)", strerror(errno)); pthread_mutex_unlock(&mLock); return -1; } // XXX: set regulatory max channels if (mScanOnly) mSupplicant->triggerScan(); else mSupplicant->reconnect(); mHandlers->onControllerResumed(this); } mSuspended = suspend; pthread_mutex_unlock(&mLock); LOGD("Suspend / Resume completed"); return 0; } void WifiController::sendStatusBroadcast(const char *msg) { NetworkManager::Instance()-> getBroadcaster()-> sendBroadcast(ResponseCode::UnsolicitedInformational, msg, false); } int WifiController::disable() { mPropMngr->detachProperty("wifi", mDynamicProperties.propSupplicantState); mPropMngr->detachProperty("wifi", mDynamicProperties.propActiveScan); mPropMngr->detachProperty("wifi", mDynamicProperties.propInterface); mPropMngr->detachProperty("wifi", mDynamicProperties.propSearching); mPropMngr->detachProperty("wifi", mDynamicProperties.propPacketFilter); mPropMngr->detachProperty("wifi", mDynamicProperties.propBluetoothCoexScan); mPropMngr->detachProperty("wifi", mDynamicProperties.propBluetoothCoexMode); mPropMngr->detachProperty("wifi", mDynamicProperties.propCurrentNetwork); mPropMngr->detachProperty("wifi", mDynamicProperties.propRssi); mPropMngr->detachProperty("wifi", mDynamicProperties.propLinkSpeed); mPropMngr->detachProperty("wifi", mDynamicProperties.propSuspended); mPropMngr->detachProperty("wifi", mDynamicProperties.propNetCount); if (mSupplicant->isStarted()) { sendStatusBroadcast("Stopping WPA Supplicant"); if (mSupplicant->stop()) { LOGE("Supplicant stop failed (%s)", strerror(errno)); return -1; } } else LOGW("disable(): Supplicant not running?"); if (mModuleName[0] != '\0' && isKernelModuleLoaded(mModuleName)) { sendStatusBroadcast("Unloading WiFi driver"); if (unloadKernelModule(mModuleName)) { LOGE("Unable to unload module (%s)", strerror(errno)); return -1; } } if (isPoweredUp()) { sendStatusBroadcast("Powering down WiFi hardware"); if (powerDown()) { LOGE("Powerdown failed (%s)", strerror(errno)); return -1; } } return 0; } int WifiController::loadFirmware() { return 0; } int WifiController::triggerScan() { pthread_mutex_lock(&mLock); if (verifyNotSuspended()) { pthread_mutex_unlock(&mLock); return -1; } switch (mSupplicantState) { case SupplicantState::DISCONNECTED: case SupplicantState::INACTIVE: case SupplicantState::SCANNING: case SupplicantState::IDLE: break; default: // Switch to scan only mode mSupplicant->setApScanMode(2); break; } int rc = mSupplicant->triggerScan(); pthread_mutex_unlock(&mLock); return rc; } int WifiController::setActiveScan(bool active) { pthread_mutex_lock(&mLock); if (mActiveScan == active) { pthread_mutex_unlock(&mLock); return 0; } mActiveScan = active; int rc = mSupplicant->setScanMode(active); pthread_mutex_unlock(&mLock); return rc; } WifiNetwork *WifiController::createNetwork() { pthread_mutex_lock(&mLock); WifiNetwork *wn = mSupplicant->createNetwork(); pthread_mutex_unlock(&mLock); return wn; } int WifiController::removeNetwork(int networkId) { pthread_mutex_lock(&mLock); WifiNetwork *wn = mSupplicant->lookupNetwork(networkId); if (!wn) { pthread_mutex_unlock(&mLock); return -1; } int rc = mSupplicant->removeNetwork(wn); pthread_mutex_unlock(&mLock); return rc; } ScanResultCollection *WifiController::createScanResults() { ScanResultCollection *d = new ScanResultCollection(); ScanResultCollection::iterator i; pthread_mutex_lock(&mLatestScanResultsLock); for (i = mLatestScanResults->begin(); i != mLatestScanResults->end(); ++i) d->push_back((*i)->clone()); pthread_mutex_unlock(&mLatestScanResultsLock); return d; } WifiNetworkCollection *WifiController::createNetworkList() { return mSupplicant->createNetworkList(); } int WifiController::setPacketFilter(bool enable) { int rc; pthread_mutex_lock(&mLock); if (enable) rc = mSupplicant->enablePacketFilter(); else rc = mSupplicant->disablePacketFilter(); if (!rc) mPacketFilter = enable; pthread_mutex_unlock(&mLock); return rc; } int WifiController::setBluetoothCoexistenceScan(bool enable) { int rc; pthread_mutex_lock(&mLock); if (enable) rc = mSupplicant->enableBluetoothCoexistenceScan(); else rc = mSupplicant->disableBluetoothCoexistenceScan(); if (!rc) mBluetoothCoexScan = enable; pthread_mutex_unlock(&mLock); return rc; } int WifiController::setScanOnly(bool scanOnly) { pthread_mutex_lock(&mLock); int rc = mSupplicant->setApScanMode((scanOnly ? 2 : 1)); if (!rc) mScanOnly = scanOnly; if (!mSuspended) { if (scanOnly) mSupplicant->disconnect(); else mSupplicant->reconnect(); } pthread_mutex_unlock(&mLock); return rc; } int WifiController::setBluetoothCoexistenceMode(int mode) { pthread_mutex_lock(&mLock); int rc = mSupplicant->setBluetoothCoexistenceMode(mode); if (!rc) mBluetoothCoexMode = mode; pthread_mutex_unlock(&mLock); return rc; } void WifiController::onAssociatingEvent(SupplicantAssociatingEvent *evt) { LOGD("onAssociatingEvent(%s, %s, %d)", (evt->getBssid() ? evt->getBssid() : "n/a"), (evt->getSsid() ? evt->getSsid() : "n/a"), evt->getFreq()); } void WifiController::onAssociatedEvent(SupplicantAssociatedEvent *evt) { LOGD("onAssociatedEvent(%s)", evt->getBssid()); } void WifiController::onConnectedEvent(SupplicantConnectedEvent *evt) { LOGD("onConnectedEvent(%s, %d)", evt->getBssid(), evt->getReassociated()); SupplicantStatus *ss = mSupplicant->getStatus(); WifiNetwork *wn; if (ss->getWpaState() != SupplicantState::COMPLETED) { char tmp[32]; LOGW("onConnected() with SupplicantState = %s!", SupplicantState::toString(ss->getWpaState(), tmp, sizeof(tmp))); return; } if (ss->getId() == -1) { LOGW("onConnected() with id = -1!"); return; } mCurrentlyConnectedNetworkId = ss->getId(); if (!(wn = mSupplicant->lookupNetwork(ss->getId()))) { LOGW("Error looking up connected network id %d (%s)", ss->getId(), strerror(errno)); return; } delete ss; mHandlers->onInterfaceConnected(this); } void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) { char *reply; if (!(reply = (char *) malloc(4096))) { LOGE("Out of memory"); return; } mNumScanResultsSinceLastStateChange++; if (mNumScanResultsSinceLastStateChange >= 3) mIsSupplicantSearching = false; size_t len = 4096; if (mSupplicant->sendCommand("SCAN_RESULTS", reply, &len)) { LOGW("onScanResultsEvent: Error getting scan results (%s)", strerror(errno)); free(reply); return; } pthread_mutex_lock(&mLatestScanResultsLock); if (!mLatestScanResults->empty()) { ScanResultCollection::iterator i; for (i = mLatestScanResults->begin(); i !=mLatestScanResults->end(); ++i) { delete *i; } mLatestScanResults->clear(); } char *linep; char *linep_next = NULL; if (!strtok_r(reply, "\n", &linep_next)) { free(reply); pthread_mutex_unlock(&mLatestScanResultsLock); return; } while((linep = strtok_r(NULL, "\n", &linep_next))) mLatestScanResults->push_back(new ScanResult(linep)); // Switch handling of scan results back to normal mode mSupplicant->setApScanMode(1); char *tmp; asprintf(&tmp, "Scan results ready (%d)", mLatestScanResults->size()); NetworkManager::Instance()->getBroadcaster()-> sendBroadcast(ResponseCode::ScanResultsReady, tmp, false); free(tmp); pthread_mutex_unlock(&mLatestScanResultsLock); free(reply); } void WifiController::onStateChangeEvent(SupplicantStateChangeEvent *evt) { char tmp[32]; char tmp2[32]; if (evt->getState() == mSupplicantState) return; LOGD("onStateChangeEvent(%s -> %s)", SupplicantState::toString(mSupplicantState, tmp, sizeof(tmp)), SupplicantState::toString(evt->getState(), tmp2, sizeof(tmp2))); if (evt->getState() != SupplicantState::SCANNING) { mIsSupplicantSearching = true; mNumScanResultsSinceLastStateChange = 0; } char *tmp3; asprintf(&tmp3, "Supplicant state changed from %d (%s) -> %d (%s)", mSupplicantState, tmp, evt->getState(), tmp2); mSupplicantState = evt->getState(); if (mSupplicantState == SupplicantState::COMPLETED) { mStatusPoller->start(); } else if (mStatusPoller->isStarted()) { mStatusPoller->stop(); } NetworkManager::Instance()->getBroadcaster()-> sendBroadcast(ResponseCode::SupplicantStateChange, tmp3, false); free(tmp3); } void WifiController::onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) { LOGD("onConnectionTimeoutEvent(%s)", evt->getBssid()); } void WifiController::onDisconnectedEvent(SupplicantDisconnectedEvent *evt) { mCurrentlyConnectedNetworkId = -1; mHandlers->onInterfaceDisconnected(this); } #if 0 void WifiController::onTerminatingEvent(SupplicantEvent *evt) { LOGD("onTerminatingEvent(%s)", evt->getEvent()); } void WifiController::onPasswordChangedEvent(SupplicantEvent *evt) { LOGD("onPasswordChangedEvent(%s)", evt->getEvent()); } void WifiController::onEapNotificationEvent(SupplicantEvent *evt) { LOGD("onEapNotificationEvent(%s)", evt->getEvent()); } void WifiController::onEapStartedEvent(SupplicantEvent *evt) { LOGD("onEapStartedEvent(%s)", evt->getEvent()); } void WifiController::onEapMethodEvent(SupplicantEvent *evt) { LOGD("onEapMethodEvent(%s)", evt->getEvent()); } void WifiController::onEapSuccessEvent(SupplicantEvent *evt) { LOGD("onEapSuccessEvent(%s)", evt->getEvent()); } void WifiController::onEapFailureEvent(SupplicantEvent *evt) { LOGD("onEapFailureEvent(%s)", evt->getEvent()); } void WifiController::onLinkSpeedEvent(SupplicantEvent *evt) { LOGD("onLinkSpeedEvent(%s)", evt->getEvent()); } void WifiController::onDriverStateEvent(SupplicantEvent *evt) { LOGD("onDriverStateEvent(%s)", evt->getEvent()); } #endif void WifiController::onStatusPollInterval() { pthread_mutex_lock(&mLock); int rssi; if (mSupplicant->getRssi(&rssi)) { LOGE("Failed to get rssi (%s)", strerror(errno)); pthread_mutex_unlock(&mLock); return; } if (abs(mLastRssi - rssi) > mRssiEventThreshold) { char *tmp3; asprintf(&tmp3, "RSSI changed from %d -> %d", mLastRssi, rssi); mLastRssi = rssi; NetworkManager::Instance()->getBroadcaster()-> sendBroadcast(ResponseCode::RssiChange, tmp3, false); free(tmp3); } int linkspeed = mSupplicant->getLinkSpeed(); if (linkspeed != mLastLinkSpeed) { char *tmp3; asprintf(&tmp3, "Link speed changed from %d -> %d", mLastLinkSpeed, linkspeed); mLastLinkSpeed = linkspeed; NetworkManager::Instance()->getBroadcaster()-> sendBroadcast(ResponseCode::LinkSpeedChange, tmp3, false); free(tmp3); } pthread_mutex_unlock(&mLock); } int WifiController::verifyNotSuspended() { if (mSuspended) { errno = ESHUTDOWN; return -1; } return 0; } /* * Property inner classes */ WifiController::WifiIntegerProperty::WifiIntegerProperty(WifiController *c, const char *name, bool ro, int elements) : IntegerProperty(name, ro, elements) { mWc = c; } WifiController::WifiStringProperty::WifiStringProperty(WifiController *c, const char *name, bool ro, int elements) : StringProperty(name, ro, elements) { mWc = c; } WifiController::WifiEnabledProperty::WifiEnabledProperty(WifiController *c) : WifiIntegerProperty(c, "Enabled", false, 1) { } int WifiController::WifiEnabledProperty::get(int idx, int *buffer) { *buffer = mWc->mEnabled; return 0; } int WifiController::WifiEnabledProperty::set(int idx, int value) { int rc = (value ? mWc->enable() : mWc->disable()); if (!rc) mWc->mEnabled = value; return rc; } WifiController::WifiScanOnlyProperty::WifiScanOnlyProperty(WifiController *c) : WifiIntegerProperty(c, "ScanOnly", false, 1) { } int WifiController::WifiScanOnlyProperty::get(int idx, int *buffer) { *buffer = mWc->mScanOnly; return 0; } int WifiController::WifiScanOnlyProperty::set(int idx, int value) { return mWc->setScanOnly(value == 1); } WifiController::WifiAllowedChannelsProperty::WifiAllowedChannelsProperty(WifiController *c) : WifiIntegerProperty(c, "AllowedChannels", false, 1) { } int WifiController::WifiAllowedChannelsProperty::get(int idx, int *buffer) { *buffer = mWc->mNumAllowedChannels; return 0; } int WifiController::WifiAllowedChannelsProperty::set(int idx, int value) { // XXX: IMPL errno = ENOSYS; return -1; } WifiController::WifiSupplicantStateProperty::WifiSupplicantStateProperty(WifiController *c) : WifiStringProperty(c, "SupplicantState", true, 1) { } int WifiController::WifiSupplicantStateProperty::get(int idx, char *buffer, size_t max) { if (!SupplicantState::toString(mWc->mSupplicantState, buffer, max)) return -1; return 0; } WifiController::WifiActiveScanProperty::WifiActiveScanProperty(WifiController *c) : WifiIntegerProperty(c, "ActiveScan", false, 1) { } int WifiController::WifiActiveScanProperty::get(int idx, int *buffer) { *buffer = mWc->mActiveScan; return 0; } int WifiController::WifiActiveScanProperty::set(int idx, int value) { return mWc->setActiveScan(value); } WifiController::WifiInterfaceProperty::WifiInterfaceProperty(WifiController *c) : WifiStringProperty(c, "Interface", true, 1) { } int WifiController::WifiInterfaceProperty::get(int idx, char *buffer, size_t max) { strncpy(buffer, (mWc->getBoundInterface() ? mWc->getBoundInterface() : "none"), max); return 0; } WifiController::WifiSearchingProperty::WifiSearchingProperty(WifiController *c) : WifiIntegerProperty(c, "Searching", true, 1) { } int WifiController::WifiSearchingProperty::get(int idx, int *buffer) { *buffer = mWc->mIsSupplicantSearching; return 0; } WifiController::WifiPacketFilterProperty::WifiPacketFilterProperty(WifiController *c) : WifiIntegerProperty(c, "PacketFilter", false, 1) { } int WifiController::WifiPacketFilterProperty::get(int idx, int *buffer) { *buffer = mWc->mPacketFilter; return 0; } int WifiController::WifiPacketFilterProperty::set(int idx, int value) { return mWc->setPacketFilter(value); } WifiController::WifiBluetoothCoexScanProperty::WifiBluetoothCoexScanProperty(WifiController *c) : WifiIntegerProperty(c, "BluetoothCoexScan", false, 1) { } int WifiController::WifiBluetoothCoexScanProperty::get(int idx, int *buffer) { *buffer = mWc->mBluetoothCoexScan; return 0; } int WifiController::WifiBluetoothCoexScanProperty::set(int idx, int value) { return mWc->setBluetoothCoexistenceScan(value == 1); } WifiController::WifiBluetoothCoexModeProperty::WifiBluetoothCoexModeProperty(WifiController *c) : WifiIntegerProperty(c, "BluetoothCoexMode", false, 1) { } int WifiController::WifiBluetoothCoexModeProperty::get(int idx, int *buffer) { *buffer = mWc->mBluetoothCoexMode; return 0; } int WifiController::WifiBluetoothCoexModeProperty::set(int idx, int value) { return mWc->setBluetoothCoexistenceMode(value); } WifiController::WifiCurrentNetworkProperty::WifiCurrentNetworkProperty(WifiController *c) : WifiIntegerProperty(c, "CurrentlyConnectedNetworkId", true, 1) { } int WifiController::WifiCurrentNetworkProperty::get(int idx, int *buffer) { *buffer = mWc->mCurrentlyConnectedNetworkId; return 0; } WifiController::WifiSuspendedProperty::WifiSuspendedProperty(WifiController *c) : WifiIntegerProperty(c, "Suspended", false, 1) { } int WifiController::WifiSuspendedProperty::get(int idx, int *buffer) { *buffer = mWc->getSuspended(); return 0; } int WifiController::WifiSuspendedProperty::set(int idx, int value) { return mWc->setSuspend(value == 1); } WifiController::WifiNetCountProperty::WifiNetCountProperty(WifiController *c) : WifiIntegerProperty(c, "NetCount", true, 1) { } int WifiController::WifiNetCountProperty::get(int idx, int *buffer) { pthread_mutex_lock(&mWc->mLock); *buffer = mWc->mSupplicant->getNetworkCount(); pthread_mutex_unlock(&mWc->mLock); return 0; } WifiController::WifiTriggerScanProperty::WifiTriggerScanProperty(WifiController *c) : WifiIntegerProperty(c, "TriggerScan", false, 1) { } int WifiController::WifiTriggerScanProperty::get(int idx, int *buffer) { // XXX: Need action type *buffer = 0; return 0; } int WifiController::WifiTriggerScanProperty::set(int idx, int value) { return mWc->triggerScan(); }