1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <string.h>
19#include <errno.h>
20
21#define LOG_TAG "WifiController"
22#include <cutils/log.h>
23
24#include "Supplicant.h"
25#include "WifiController.h"
26#include "NetworkManager.h"
27#include "ResponseCode.h"
28#include "WifiNetwork.h"
29#include "ISupplicantEventHandler.h"
30#include "SupplicantState.h"
31#include "SupplicantStatus.h"
32#include "SupplicantAssociatingEvent.h"
33#include "SupplicantAssociatedEvent.h"
34#include "SupplicantConnectedEvent.h"
35#include "SupplicantScanResultsEvent.h"
36#include "SupplicantStateChangeEvent.h"
37#include "SupplicantConnectionTimeoutEvent.h"
38#include "SupplicantDisconnectedEvent.h"
39#include "WifiStatusPoller.h"
40
41WifiController::WifiController(PropertyManager *mPropMngr,
42                               IControllerHandler *handlers,
43                               char *modpath, char *modname, char *modargs) :
44                Controller("wifi", mPropMngr, handlers) {
45    strncpy(mModulePath, modpath, sizeof(mModulePath));
46    strncpy(mModuleName, modname, sizeof(mModuleName));
47    strncpy(mModuleArgs, modargs, sizeof(mModuleArgs));
48
49    mLatestScanResults = new ScanResultCollection();
50    pthread_mutex_init(&mLatestScanResultsLock, NULL);
51
52    pthread_mutex_init(&mLock, NULL);
53
54    mSupplicant = new Supplicant(this, this);
55    mActiveScan = false;
56    mEnabled = false;
57    mScanOnly = false;
58    mPacketFilter = false;
59    mBluetoothCoexScan = false;
60    mBluetoothCoexMode = 0;
61    mCurrentlyConnectedNetworkId = -1;
62    mStatusPoller = new WifiStatusPoller(this);
63    mRssiEventThreshold = 5;
64    mLastLinkSpeed = 0;
65
66    mSupplicantState = SupplicantState::UNKNOWN;
67
68    mStaticProperties.propEnabled = new WifiEnabledProperty(this);
69    mStaticProperties.propScanOnly = new WifiScanOnlyProperty(this);
70    mStaticProperties.propAllowedChannels = new WifiAllowedChannelsProperty(this);
71
72    mStaticProperties.propRssiEventThreshold =
73            new IntegerPropertyHelper("RssiEventThreshold", false, &mRssiEventThreshold);
74
75    mDynamicProperties.propSupplicantState = new WifiSupplicantStateProperty(this);
76    mDynamicProperties.propActiveScan = new WifiActiveScanProperty(this);
77    mDynamicProperties.propInterface = new WifiInterfaceProperty(this);
78    mDynamicProperties.propSearching = new WifiSearchingProperty(this);
79    mDynamicProperties.propPacketFilter = new WifiPacketFilterProperty(this);
80    mDynamicProperties.propBluetoothCoexScan = new WifiBluetoothCoexScanProperty(this);
81    mDynamicProperties.propBluetoothCoexMode = new WifiBluetoothCoexModeProperty(this);
82    mDynamicProperties.propCurrentNetwork = new WifiCurrentNetworkProperty(this);
83
84    mDynamicProperties.propRssi = new IntegerPropertyHelper("Rssi", true, &mLastRssi);
85    mDynamicProperties.propLinkSpeed = new IntegerPropertyHelper("LinkSpeed", true, &mLastLinkSpeed);
86
87    mDynamicProperties.propSuspended = new WifiSuspendedProperty(this);
88    mDynamicProperties.propNetCount = new WifiNetCountProperty(this);
89    mDynamicProperties.propTriggerScan = new WifiTriggerScanProperty(this);
90}
91
92int WifiController::start() {
93    mPropMngr->attachProperty("wifi", mStaticProperties.propEnabled);
94    mPropMngr->attachProperty("wifi", mStaticProperties.propScanOnly);
95    mPropMngr->attachProperty("wifi", mStaticProperties.propAllowedChannels);
96    mPropMngr->attachProperty("wifi", mStaticProperties.propRssiEventThreshold);
97    return 0;
98}
99
100int WifiController::stop() {
101    mPropMngr->detachProperty("wifi", mStaticProperties.propEnabled);
102    mPropMngr->detachProperty("wifi", mStaticProperties.propScanOnly);
103    mPropMngr->detachProperty("wifi", mStaticProperties.propAllowedChannels);
104    mPropMngr->detachProperty("wifi", mStaticProperties.propRssiEventThreshold);
105    return 0;
106}
107
108int WifiController::enable() {
109
110    if (!isPoweredUp()) {
111        LOGI("Powering up");
112        sendStatusBroadcast("Powering up WiFi hardware");
113        if (powerUp()) {
114            LOGE("Powerup failed (%s)", strerror(errno));
115            return -1;
116        }
117    }
118
119    if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) {
120        LOGI("Loading driver");
121        sendStatusBroadcast("Loading WiFi driver");
122        if (loadKernelModule(mModulePath, mModuleArgs)) {
123            LOGE("Kernel module load failed (%s)", strerror(errno));
124            goto out_powerdown;
125        }
126    }
127
128    if (!isFirmwareLoaded()) {
129        LOGI("Loading firmware");
130        sendStatusBroadcast("Loading WiFI firmware");
131        if (loadFirmware()) {
132            LOGE("Firmware load failed (%s)", strerror(errno));
133            goto out_powerdown;
134        }
135    }
136
137    if (!mSupplicant->isStarted()) {
138        LOGI("Starting WPA Supplicant");
139        sendStatusBroadcast("Starting WPA Supplicant");
140        if (mSupplicant->start()) {
141            LOGE("Supplicant start failed (%s)", strerror(errno));
142            goto out_unloadmodule;
143        }
144    }
145
146    if (Controller::bindInterface(mSupplicant->getInterfaceName())) {
147        LOGE("Error binding interface (%s)", strerror(errno));
148        goto out_unloadmodule;
149    }
150
151    if (mSupplicant->refreshNetworkList())
152        LOGW("Error getting list of networks (%s)", strerror(errno));
153
154    LOGW("TODO: Set # of allowed regulatory channels!");
155
156    mPropMngr->attachProperty("wifi", mDynamicProperties.propSupplicantState);
157    mPropMngr->attachProperty("wifi", mDynamicProperties.propActiveScan);
158    mPropMngr->attachProperty("wifi", mDynamicProperties.propInterface);
159    mPropMngr->attachProperty("wifi", mDynamicProperties.propSearching);
160    mPropMngr->attachProperty("wifi", mDynamicProperties.propPacketFilter);
161    mPropMngr->attachProperty("wifi", mDynamicProperties.propBluetoothCoexScan);
162    mPropMngr->attachProperty("wifi", mDynamicProperties.propBluetoothCoexMode);
163    mPropMngr->attachProperty("wifi", mDynamicProperties.propCurrentNetwork);
164    mPropMngr->attachProperty("wifi", mDynamicProperties.propRssi);
165    mPropMngr->attachProperty("wifi", mDynamicProperties.propLinkSpeed);
166    mPropMngr->attachProperty("wifi", mDynamicProperties.propSuspended);
167    mPropMngr->attachProperty("wifi", mDynamicProperties.propNetCount);
168    mPropMngr->attachProperty("wifi", mDynamicProperties.propTriggerScan);
169
170    LOGI("Enabled successfully");
171    return 0;
172
173out_unloadmodule:
174    if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) {
175        if (unloadKernelModule(mModuleName)) {
176            LOGE("Unable to unload module after failure!");
177        }
178    }
179
180out_powerdown:
181    if (powerDown()) {
182        LOGE("Unable to powerdown after failure!");
183    }
184    return -1;
185}
186
187bool WifiController::getSuspended() {
188    pthread_mutex_lock(&mLock);
189    bool r = mSuspended;
190    pthread_mutex_unlock(&mLock);
191    return r;
192}
193
194int WifiController::setSuspend(bool suspend) {
195
196    pthread_mutex_lock(&mLock);
197    if (suspend == mSuspended) {
198        LOGW("Suspended state already = %d", suspend);
199        pthread_mutex_unlock(&mLock);
200        return 0;
201    }
202
203    if (suspend) {
204        mHandlers->onControllerSuspending(this);
205
206        char tmp[80];
207        LOGD("Suspending from supplicant state %s",
208             SupplicantState::toString(mSupplicantState,
209                                       tmp,
210                                       sizeof(tmp)));
211
212        if (mSupplicantState != SupplicantState::IDLE) {
213            LOGD("Forcing Supplicant disconnect");
214            if (mSupplicant->disconnect()) {
215                LOGW("Error disconnecting (%s)", strerror(errno));
216            }
217        }
218
219        LOGD("Stopping Supplicant driver");
220        if (mSupplicant->stopDriver()) {
221            LOGE("Error stopping driver (%s)", strerror(errno));
222            pthread_mutex_unlock(&mLock);
223            return -1;
224        }
225    } else {
226        LOGD("Resuming");
227
228        if (mSupplicant->startDriver()) {
229            LOGE("Error resuming driver (%s)", strerror(errno));
230            pthread_mutex_unlock(&mLock);
231            return -1;
232        }
233        // XXX: set regulatory max channels
234        if (mScanOnly)
235            mSupplicant->triggerScan();
236        else
237            mSupplicant->reconnect();
238
239        mHandlers->onControllerResumed(this);
240    }
241
242    mSuspended = suspend;
243    pthread_mutex_unlock(&mLock);
244    LOGD("Suspend / Resume completed");
245    return 0;
246}
247
248void WifiController::sendStatusBroadcast(const char *msg) {
249    NetworkManager::Instance()->
250                    getBroadcaster()->
251                    sendBroadcast(ResponseCode::UnsolicitedInformational, msg, false);
252}
253
254int WifiController::disable() {
255
256    mPropMngr->detachProperty("wifi", mDynamicProperties.propSupplicantState);
257    mPropMngr->detachProperty("wifi", mDynamicProperties.propActiveScan);
258    mPropMngr->detachProperty("wifi", mDynamicProperties.propInterface);
259    mPropMngr->detachProperty("wifi", mDynamicProperties.propSearching);
260    mPropMngr->detachProperty("wifi", mDynamicProperties.propPacketFilter);
261    mPropMngr->detachProperty("wifi", mDynamicProperties.propBluetoothCoexScan);
262    mPropMngr->detachProperty("wifi", mDynamicProperties.propBluetoothCoexMode);
263    mPropMngr->detachProperty("wifi", mDynamicProperties.propCurrentNetwork);
264    mPropMngr->detachProperty("wifi", mDynamicProperties.propRssi);
265    mPropMngr->detachProperty("wifi", mDynamicProperties.propLinkSpeed);
266    mPropMngr->detachProperty("wifi", mDynamicProperties.propSuspended);
267    mPropMngr->detachProperty("wifi", mDynamicProperties.propNetCount);
268
269    if (mSupplicant->isStarted()) {
270        sendStatusBroadcast("Stopping WPA Supplicant");
271        if (mSupplicant->stop()) {
272            LOGE("Supplicant stop failed (%s)", strerror(errno));
273            return -1;
274        }
275    } else
276        LOGW("disable(): Supplicant not running?");
277
278    if (mModuleName[0] != '\0' && isKernelModuleLoaded(mModuleName)) {
279        sendStatusBroadcast("Unloading WiFi driver");
280        if (unloadKernelModule(mModuleName)) {
281            LOGE("Unable to unload module (%s)", strerror(errno));
282            return -1;
283        }
284    }
285
286    if (isPoweredUp()) {
287        sendStatusBroadcast("Powering down WiFi hardware");
288        if (powerDown()) {
289            LOGE("Powerdown failed (%s)", strerror(errno));
290            return -1;
291        }
292    }
293    return 0;
294}
295
296int WifiController::loadFirmware() {
297    return 0;
298}
299
300int WifiController::triggerScan() {
301    pthread_mutex_lock(&mLock);
302    if (verifyNotSuspended()) {
303        pthread_mutex_unlock(&mLock);
304        return -1;
305    }
306
307    switch (mSupplicantState) {
308        case SupplicantState::DISCONNECTED:
309        case SupplicantState::INACTIVE:
310        case SupplicantState::SCANNING:
311        case SupplicantState::IDLE:
312            break;
313        default:
314            // Switch to scan only mode
315            mSupplicant->setApScanMode(2);
316            break;
317    }
318
319    int rc = mSupplicant->triggerScan();
320    pthread_mutex_unlock(&mLock);
321    return rc;
322}
323
324int WifiController::setActiveScan(bool active) {
325    pthread_mutex_lock(&mLock);
326    if (mActiveScan == active) {
327        pthread_mutex_unlock(&mLock);
328        return 0;
329    }
330    mActiveScan = active;
331
332    int rc = mSupplicant->setScanMode(active);
333    pthread_mutex_unlock(&mLock);
334    return rc;
335}
336
337WifiNetwork *WifiController::createNetwork() {
338    pthread_mutex_lock(&mLock);
339    WifiNetwork *wn = mSupplicant->createNetwork();
340    pthread_mutex_unlock(&mLock);
341    return wn;
342}
343
344int WifiController::removeNetwork(int networkId) {
345    pthread_mutex_lock(&mLock);
346    WifiNetwork *wn = mSupplicant->lookupNetwork(networkId);
347
348    if (!wn) {
349        pthread_mutex_unlock(&mLock);
350        return -1;
351    }
352    int rc = mSupplicant->removeNetwork(wn);
353    pthread_mutex_unlock(&mLock);
354    return rc;
355}
356
357ScanResultCollection *WifiController::createScanResults() {
358    ScanResultCollection *d = new ScanResultCollection();
359    ScanResultCollection::iterator i;
360
361    pthread_mutex_lock(&mLatestScanResultsLock);
362    for (i = mLatestScanResults->begin(); i != mLatestScanResults->end(); ++i)
363        d->push_back((*i)->clone());
364
365    pthread_mutex_unlock(&mLatestScanResultsLock);
366    return d;
367}
368
369WifiNetworkCollection *WifiController::createNetworkList() {
370    return mSupplicant->createNetworkList();
371}
372
373int WifiController::setPacketFilter(bool enable) {
374    int rc;
375
376    pthread_mutex_lock(&mLock);
377    if (enable)
378        rc = mSupplicant->enablePacketFilter();
379    else
380        rc = mSupplicant->disablePacketFilter();
381
382    if (!rc)
383        mPacketFilter = enable;
384    pthread_mutex_unlock(&mLock);
385    return rc;
386}
387
388int WifiController::setBluetoothCoexistenceScan(bool enable) {
389    int rc;
390
391    pthread_mutex_lock(&mLock);
392
393    if (enable)
394        rc = mSupplicant->enableBluetoothCoexistenceScan();
395    else
396        rc = mSupplicant->disableBluetoothCoexistenceScan();
397
398    if (!rc)
399        mBluetoothCoexScan = enable;
400    pthread_mutex_unlock(&mLock);
401    return rc;
402}
403
404int WifiController::setScanOnly(bool scanOnly) {
405    pthread_mutex_lock(&mLock);
406    int rc = mSupplicant->setApScanMode((scanOnly ? 2 : 1));
407    if (!rc)
408        mScanOnly = scanOnly;
409    if (!mSuspended) {
410        if (scanOnly)
411            mSupplicant->disconnect();
412        else
413            mSupplicant->reconnect();
414    }
415    pthread_mutex_unlock(&mLock);
416    return rc;
417}
418
419int WifiController::setBluetoothCoexistenceMode(int mode) {
420    pthread_mutex_lock(&mLock);
421    int rc = mSupplicant->setBluetoothCoexistenceMode(mode);
422    if (!rc)
423        mBluetoothCoexMode = mode;
424    pthread_mutex_unlock(&mLock);
425    return rc;
426}
427
428void WifiController::onAssociatingEvent(SupplicantAssociatingEvent *evt) {
429    LOGD("onAssociatingEvent(%s, %s, %d)",
430         (evt->getBssid() ? evt->getBssid() : "n/a"),
431         (evt->getSsid() ? evt->getSsid() : "n/a"),
432         evt->getFreq());
433}
434
435void WifiController::onAssociatedEvent(SupplicantAssociatedEvent *evt) {
436    LOGD("onAssociatedEvent(%s)", evt->getBssid());
437}
438
439void WifiController::onConnectedEvent(SupplicantConnectedEvent *evt) {
440    LOGD("onConnectedEvent(%s, %d)", evt->getBssid(), evt->getReassociated());
441    SupplicantStatus *ss = mSupplicant->getStatus();
442    WifiNetwork *wn;
443
444    if (ss->getWpaState() != SupplicantState::COMPLETED) {
445        char tmp[32];
446
447        LOGW("onConnected() with SupplicantState = %s!",
448             SupplicantState::toString(ss->getWpaState(), tmp,
449             sizeof(tmp)));
450        return;
451    }
452
453    if (ss->getId() == -1) {
454        LOGW("onConnected() with id = -1!");
455        return;
456    }
457
458    mCurrentlyConnectedNetworkId = ss->getId();
459    if (!(wn = mSupplicant->lookupNetwork(ss->getId()))) {
460        LOGW("Error looking up connected network id %d (%s)",
461             ss->getId(), strerror(errno));
462        return;
463    }
464
465    delete ss;
466    mHandlers->onInterfaceConnected(this);
467}
468
469void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) {
470    char *reply;
471
472    if (!(reply = (char *) malloc(4096))) {
473        LOGE("Out of memory");
474        return;
475    }
476
477    mNumScanResultsSinceLastStateChange++;
478    if (mNumScanResultsSinceLastStateChange >= 3)
479        mIsSupplicantSearching = false;
480
481    size_t len = 4096;
482
483    if (mSupplicant->sendCommand("SCAN_RESULTS", reply, &len)) {
484        LOGW("onScanResultsEvent: Error getting scan results (%s)",
485             strerror(errno));
486        free(reply);
487        return;
488    }
489
490    pthread_mutex_lock(&mLatestScanResultsLock);
491    if (!mLatestScanResults->empty()) {
492        ScanResultCollection::iterator i;
493
494        for (i = mLatestScanResults->begin();
495             i !=mLatestScanResults->end(); ++i) {
496            delete *i;
497        }
498        mLatestScanResults->clear();
499    }
500
501    char *linep;
502    char *linep_next = NULL;
503
504    if (!strtok_r(reply, "\n", &linep_next)) {
505        free(reply);
506        pthread_mutex_unlock(&mLatestScanResultsLock);
507        return;
508    }
509
510    while((linep = strtok_r(NULL, "\n", &linep_next)))
511        mLatestScanResults->push_back(new ScanResult(linep));
512
513    // Switch handling of scan results back to normal mode
514    mSupplicant->setApScanMode(1);
515
516    char *tmp;
517    asprintf(&tmp, "Scan results ready (%d)", mLatestScanResults->size());
518    NetworkManager::Instance()->getBroadcaster()->
519                                sendBroadcast(ResponseCode::ScanResultsReady,
520                                              tmp, false);
521    free(tmp);
522    pthread_mutex_unlock(&mLatestScanResultsLock);
523    free(reply);
524}
525
526void WifiController::onStateChangeEvent(SupplicantStateChangeEvent *evt) {
527    char tmp[32];
528    char tmp2[32];
529
530    if (evt->getState() == mSupplicantState)
531        return;
532
533    LOGD("onStateChangeEvent(%s -> %s)",
534         SupplicantState::toString(mSupplicantState, tmp, sizeof(tmp)),
535         SupplicantState::toString(evt->getState(), tmp2, sizeof(tmp2)));
536
537    if (evt->getState() != SupplicantState::SCANNING) {
538        mIsSupplicantSearching = true;
539        mNumScanResultsSinceLastStateChange = 0;
540    }
541
542    char *tmp3;
543    asprintf(&tmp3,
544             "Supplicant state changed from %d (%s) -> %d (%s)",
545             mSupplicantState, tmp, evt->getState(), tmp2);
546
547    mSupplicantState = evt->getState();
548
549    if (mSupplicantState == SupplicantState::COMPLETED) {
550        mStatusPoller->start();
551    } else if (mStatusPoller->isStarted()) {
552        mStatusPoller->stop();
553    }
554
555    NetworkManager::Instance()->getBroadcaster()->
556                                sendBroadcast(ResponseCode::SupplicantStateChange,
557                                              tmp3, false);
558    free(tmp3);
559}
560
561void WifiController::onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) {
562    LOGD("onConnectionTimeoutEvent(%s)", evt->getBssid());
563}
564
565void WifiController::onDisconnectedEvent(SupplicantDisconnectedEvent *evt) {
566    mCurrentlyConnectedNetworkId = -1;
567    mHandlers->onInterfaceDisconnected(this);
568}
569
570#if 0
571void WifiController::onTerminatingEvent(SupplicantEvent *evt) {
572    LOGD("onTerminatingEvent(%s)", evt->getEvent());
573}
574
575void WifiController::onPasswordChangedEvent(SupplicantEvent *evt) {
576    LOGD("onPasswordChangedEvent(%s)", evt->getEvent());
577}
578
579void WifiController::onEapNotificationEvent(SupplicantEvent *evt) {
580    LOGD("onEapNotificationEvent(%s)", evt->getEvent());
581}
582
583void WifiController::onEapStartedEvent(SupplicantEvent *evt) {
584    LOGD("onEapStartedEvent(%s)", evt->getEvent());
585}
586
587void WifiController::onEapMethodEvent(SupplicantEvent *evt) {
588    LOGD("onEapMethodEvent(%s)", evt->getEvent());
589}
590
591void WifiController::onEapSuccessEvent(SupplicantEvent *evt) {
592    LOGD("onEapSuccessEvent(%s)", evt->getEvent());
593}
594
595void WifiController::onEapFailureEvent(SupplicantEvent *evt) {
596    LOGD("onEapFailureEvent(%s)", evt->getEvent());
597}
598
599void WifiController::onLinkSpeedEvent(SupplicantEvent *evt) {
600    LOGD("onLinkSpeedEvent(%s)", evt->getEvent());
601}
602
603void WifiController::onDriverStateEvent(SupplicantEvent *evt) {
604    LOGD("onDriverStateEvent(%s)", evt->getEvent());
605}
606#endif
607
608void WifiController::onStatusPollInterval() {
609    pthread_mutex_lock(&mLock);
610    int rssi;
611    if (mSupplicant->getRssi(&rssi)) {
612        LOGE("Failed to get rssi (%s)", strerror(errno));
613        pthread_mutex_unlock(&mLock);
614        return;
615    }
616
617    if (abs(mLastRssi - rssi) > mRssiEventThreshold) {
618        char *tmp3;
619        asprintf(&tmp3, "RSSI changed from %d -> %d",
620                 mLastRssi, rssi);
621        mLastRssi = rssi;
622        NetworkManager::Instance()->getBroadcaster()->
623                               sendBroadcast(ResponseCode::RssiChange,
624                                             tmp3, false);
625        free(tmp3);
626    }
627
628    int linkspeed = mSupplicant->getLinkSpeed();
629    if (linkspeed != mLastLinkSpeed) {
630        char *tmp3;
631        asprintf(&tmp3, "Link speed changed from %d -> %d",
632                 mLastLinkSpeed, linkspeed);
633        mLastLinkSpeed = linkspeed;
634        NetworkManager::Instance()->getBroadcaster()->
635                               sendBroadcast(ResponseCode::LinkSpeedChange,
636                                             tmp3, false);
637        free(tmp3);
638
639    }
640    pthread_mutex_unlock(&mLock);
641}
642
643int WifiController::verifyNotSuspended() {
644    if (mSuspended) {
645        errno = ESHUTDOWN;
646        return -1;
647    }
648    return 0;
649}
650
651/*
652 * Property inner classes
653 */
654
655WifiController::WifiIntegerProperty::WifiIntegerProperty(WifiController *c,
656                                                         const char *name,
657                                                         bool ro,
658                                                         int elements) :
659                IntegerProperty(name, ro, elements) {
660    mWc = c;
661}
662
663WifiController::WifiStringProperty::WifiStringProperty(WifiController *c,
664                                                       const char *name,
665                                                       bool ro, int elements) :
666                StringProperty(name, ro, elements) {
667    mWc = c;
668}
669
670WifiController::WifiEnabledProperty::WifiEnabledProperty(WifiController *c) :
671                WifiIntegerProperty(c, "Enabled", false, 1) {
672}
673
674int WifiController::WifiEnabledProperty::get(int idx, int *buffer) {
675    *buffer = mWc->mEnabled;
676    return 0;
677}
678int WifiController::WifiEnabledProperty::set(int idx, int value) {
679    int rc = (value ? mWc->enable() : mWc->disable());
680    if (!rc)
681        mWc->mEnabled = value;
682    return rc;
683}
684
685WifiController::WifiScanOnlyProperty::WifiScanOnlyProperty(WifiController *c) :
686                WifiIntegerProperty(c, "ScanOnly", false, 1) {
687}
688int WifiController::WifiScanOnlyProperty::get(int idx, int *buffer) {
689    *buffer = mWc->mScanOnly;
690    return 0;
691}
692int WifiController::WifiScanOnlyProperty::set(int idx, int value) {
693    return mWc->setScanOnly(value == 1);
694}
695
696WifiController::WifiAllowedChannelsProperty::WifiAllowedChannelsProperty(WifiController *c) :
697                WifiIntegerProperty(c, "AllowedChannels", false, 1) {
698}
699int WifiController::WifiAllowedChannelsProperty::get(int idx, int *buffer) {
700    *buffer = mWc->mNumAllowedChannels;
701    return 0;
702}
703int WifiController::WifiAllowedChannelsProperty::set(int idx, int value) {
704    // XXX: IMPL
705    errno = ENOSYS;
706    return -1;
707}
708
709WifiController::WifiSupplicantStateProperty::WifiSupplicantStateProperty(WifiController *c) :
710                WifiStringProperty(c, "SupplicantState", true, 1) {
711}
712int WifiController::WifiSupplicantStateProperty::get(int idx, char *buffer, size_t max) {
713    if (!SupplicantState::toString(mWc->mSupplicantState, buffer, max))
714        return -1;
715    return 0;
716}
717
718WifiController::WifiActiveScanProperty::WifiActiveScanProperty(WifiController *c) :
719                WifiIntegerProperty(c, "ActiveScan", false, 1) {
720}
721int WifiController::WifiActiveScanProperty::get(int idx, int *buffer) {
722    *buffer = mWc->mActiveScan;
723    return 0;
724}
725int WifiController::WifiActiveScanProperty::set(int idx, int value) {
726    return mWc->setActiveScan(value);
727}
728
729WifiController::WifiInterfaceProperty::WifiInterfaceProperty(WifiController *c) :
730                WifiStringProperty(c, "Interface", true, 1) {
731}
732int WifiController::WifiInterfaceProperty::get(int idx, char *buffer, size_t max) {
733    strncpy(buffer, (mWc->getBoundInterface() ? mWc->getBoundInterface() : "none"), max);
734    return 0;
735}
736
737WifiController::WifiSearchingProperty::WifiSearchingProperty(WifiController *c) :
738                WifiIntegerProperty(c, "Searching", true, 1) {
739}
740int WifiController::WifiSearchingProperty::get(int idx, int *buffer) {
741    *buffer = mWc->mIsSupplicantSearching;
742    return 0;
743}
744
745WifiController::WifiPacketFilterProperty::WifiPacketFilterProperty(WifiController *c) :
746                WifiIntegerProperty(c, "PacketFilter", false, 1) {
747}
748int WifiController::WifiPacketFilterProperty::get(int idx, int *buffer) {
749    *buffer = mWc->mPacketFilter;
750    return 0;
751}
752int WifiController::WifiPacketFilterProperty::set(int idx, int value) {
753    return mWc->setPacketFilter(value);
754}
755
756WifiController::WifiBluetoothCoexScanProperty::WifiBluetoothCoexScanProperty(WifiController *c) :
757                WifiIntegerProperty(c, "BluetoothCoexScan", false, 1) {
758}
759int WifiController::WifiBluetoothCoexScanProperty::get(int idx, int *buffer) {
760    *buffer = mWc->mBluetoothCoexScan;
761    return 0;
762}
763int WifiController::WifiBluetoothCoexScanProperty::set(int idx, int value) {
764    return mWc->setBluetoothCoexistenceScan(value == 1);
765}
766
767WifiController::WifiBluetoothCoexModeProperty::WifiBluetoothCoexModeProperty(WifiController *c) :
768                WifiIntegerProperty(c, "BluetoothCoexMode", false, 1) {
769}
770int WifiController::WifiBluetoothCoexModeProperty::get(int idx, int *buffer) {
771    *buffer = mWc->mBluetoothCoexMode;
772    return 0;
773}
774int WifiController::WifiBluetoothCoexModeProperty::set(int idx, int value) {
775    return mWc->setBluetoothCoexistenceMode(value);
776}
777
778WifiController::WifiCurrentNetworkProperty::WifiCurrentNetworkProperty(WifiController *c) :
779                WifiIntegerProperty(c, "CurrentlyConnectedNetworkId", true, 1) {
780}
781int WifiController::WifiCurrentNetworkProperty::get(int idx, int *buffer) {
782    *buffer = mWc->mCurrentlyConnectedNetworkId;
783    return 0;
784}
785
786WifiController::WifiSuspendedProperty::WifiSuspendedProperty(WifiController *c) :
787                WifiIntegerProperty(c, "Suspended", false, 1) {
788}
789int WifiController::WifiSuspendedProperty::get(int idx, int *buffer) {
790    *buffer = mWc->getSuspended();
791    return 0;
792}
793int WifiController::WifiSuspendedProperty::set(int idx, int value) {
794    return mWc->setSuspend(value == 1);
795}
796
797WifiController::WifiNetCountProperty::WifiNetCountProperty(WifiController *c) :
798                WifiIntegerProperty(c, "NetCount", true, 1) {
799}
800int WifiController::WifiNetCountProperty::get(int idx, int *buffer) {
801    pthread_mutex_lock(&mWc->mLock);
802    *buffer = mWc->mSupplicant->getNetworkCount();
803    pthread_mutex_unlock(&mWc->mLock);
804    return 0;
805}
806
807WifiController::WifiTriggerScanProperty::WifiTriggerScanProperty(WifiController *c) :
808                WifiIntegerProperty(c, "TriggerScan", false, 1) {
809}
810int WifiController::WifiTriggerScanProperty::get(int idx, int *buffer) {
811    // XXX: Need action type
812    *buffer = 0;
813    return 0;
814}
815
816int WifiController::WifiTriggerScanProperty::set(int idx, int value) {
817    return mWc->triggerScan();
818}
819
820