platform_system_core/nexus/WifiController.cpp
San Mehat c4a895b709 nexus: Rollup update for nexus
nexus: Change field separator from : to ' '

Signed-off-by: San Mehat <san@google.com>

nexus: Add some prototypes for stuff to come

Signed-off-by: San Mehat <san@google.com>

nexus: Add some TODOs

Signed-off-by: San Mehat <san@google.com>

libsysutils: Put a proper token parser into the FrameworkListener which
supports minimal \ escapes and quotes

Signed-off-by: San Mehat <san@google.com>

nexus: Fix a lot of bugs

Signed-off-by: San Mehat <san@google.com>

libsysutils: Remove some debugging
Signed-off-by: San Mehat <san@google.com>

nexus: Send broadcasts for supplicant state changes

Signed-off-by: San Mehat <san@google.com>

nexus: Plumb DHCP listener state changes to NetworkManager

Signed-off-by: San Mehat <san@google.com>

nexus: Make the SupplicantState strings more parsable

Signed-off-by: San Mehat <san@google.com>

nexus: Broadcast a message when dhcp state changes.

Signed-off-by: San Mehat <san@google.com>

nexus: Add a few new response codes

Signed-off-by: San Mehat <san@google.com>

nexus: Rename ErrorCode -> ResponseCode

Signed-off-by: San Mehat <san@google.com>

nexus: Add DHCP event broadcasting. Also adds the framework for
tracking supplicant 'searching-for-AP' state

Signed-off-by: San Mehat <san@google.com>

nexus: REmove WifiScanner

Signed-off-by: San Mehat <san@google.com>

nexus: Change the way scanning works. scanmode can now be selected
independantly of triggering a scan. Also adds rxfilter support

Signed-off-by: San Mehat <san@google.com>

nexus: Add support for configuring bluetooth coexistence scanning and modes

Signed-off-by: San Mehat <san@google.com>

nexus: use case insensitive match for property names

Signed-off-by: San Mehat <san@google.com>

nexus: Rollup of a bunch of stuff:
    - 'list' command now takes an argument to match against
    - InterfaceConfig has been moved into the Controller base (for now)
    - DhcpClient now has some rudimentry locking
    - process 'ADDRINFO' messages from dhcpcd
    - Drop tertiary dns

Signed-off-by: San Mehat <san@google.com>

nexus: Clean up some of the supplicant variable parsing and add 'wifi.current'

Signed-off-by: San Mehat <san@google.com>

nexus: Add driver-stop/start, initial suspend support

Signed-off-by: San Mehat <san@google.com>

nexus: Add Controller suspend/resume callbacks, as well as locking

Signed-off-by: San Mehat <san@google.com>

nexus: Make ARP probing configurable for DhcpClient

Signed-off-by: San Mehat <san@google.com>

nexus: Add linkspeed / rssi retrieval

Signed-off-by: San Mehat <san@google.com>

nexus: Add WifiStatusPoller to track RSSI/linkspeed when associated

Signed-off-by: San Mehat <san@google.com>

nexus: Disable some debugging and add 'wifi.netcount' property

Signed-off-by: San Mehat <san@google.com>

nexus: Replace the hackish property system with something more flexible with namespaces

Signed-off-by: San Mehat <san@google.com>

libsysutils: Fix a few bugs in SocketListener

Signed-off-by: San Mehat <san@google.com>

nexus: PropertyManager: Add array support

Signed-off-by: San Mehat <san@google.com>

nexus: Clean up properties
Signed-off-by: San Mehat <san@google.com>

nexus: WifiController: Change name of 'CurrentNetwork' property

Signed-off-by: San Mehat <san@google.com>
2009-07-10 14:23:51 -07:00

819 lines
26 KiB
C++

/*
* 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();
}