Merge changes 1093,1094 into donut

* changes:
  init.rc: Add Nexus to services (disabled for now)
  nexus: Initial checkin of Nexus - android native network management daemon.
This commit is contained in:
Android (Google) Code Review 2009-05-07 07:21:15 -07:00
commit 902905682d
29 changed files with 2153 additions and 0 deletions

47
nexus/Android.mk Normal file
View file

@ -0,0 +1,47 @@
BUILD_NEXUS := false
ifeq ($(BUILD_NEXUS),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
main.cpp \
NetworkManager.cpp \
CommandListener.cpp \
Controller.cpp \
WifiController.cpp \
LoopController.cpp \
NexusCommand.cpp \
TiwlanWifiController.cpp \
Supplicant.cpp \
SupplicantEvent.cpp \
SupplicantListener.cpp \
VpnController.cpp \
ScanResult.cpp \
LOCAL_MODULE:= nexus
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libsysutils libwpa_client libutils
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
nexctl.c \
LOCAL_MODULE:= nexctl
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libutils
include $(BUILD_EXECUTABLE)
endif # ifeq ($(BUILD_NEXUS),true)

124
nexus/CommandListener.cpp Normal file
View file

@ -0,0 +1,124 @@
/*
* 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 <errno.h>
#define LOG_TAG "CommandListener"
#include <cutils/log.h>
#include "CommandListener.h"
#include "Controller.h"
#include "NetworkManager.h"
#include "WifiController.h"
CommandListener::CommandListener(NetworkManager *netman) :
FrameworkListener("nexus") {
mNetman = netman;
registerCmd(new WifiEnableCmd(netman));
registerCmd(new WifiDisableCmd(netman));
registerCmd(new WifiScanCmd(netman));
registerCmd(new VpnEnableCmd(netman));
registerCmd(new VpnDisableCmd(netman));
}
/* -------------
* Wifi Commands
* ------------ */
CommandListener::WifiEnableCmd::WifiEnableCmd(NetworkManager *netman) :
NexusCommand("wifi_enable", netman) {
}
int CommandListener::WifiEnableCmd::runCommand(char *data) {
Controller *c = mNetman->findController("WIFI");
char buffer[32];
sprintf(buffer, "WIFI_ENABLE:%d", (c->enable() ? errno : 0));
mNetman->getFrameworkManager()->sendMsg(buffer);
return 0;
}
CommandListener::WifiDisableCmd::WifiDisableCmd(NetworkManager *netman) :
NexusCommand("wifi_disable", netman) {
}
int CommandListener::WifiDisableCmd::runCommand(char *data) {
Controller *c = mNetman->findController("WIFI");
char buffer[32];
sprintf(buffer, "WIFI_DISABLE:%d", (c->disable() ? errno : 0));
mNetman->getFrameworkManager()->sendMsg(buffer);
return 0;
}
CommandListener::WifiScanCmd::WifiScanCmd(NetworkManager *netman) :
NexusCommand("wifi_scan", netman) {
}
int CommandListener::WifiScanCmd::runCommand(char *data) {
LOGD("WifiScanCmd(%s)", data);
WifiController *wc = (WifiController *) mNetman->findController("WIFI");
char buffer[32];
int mode = 0;
char *bword, *last;
if (!(bword = strtok_r(data, ":", &last))) {
errno = EINVAL;
return -1;
}
if (!(bword = strtok_r(NULL, ":", &last))) {
errno = EINVAL;
return -1;
}
mode = atoi(bword);
sprintf(buffer, "WIFI_SCAN:%d", (wc->setScanMode(mode) ? errno : 0));
mNetman->getFrameworkManager()->sendMsg(buffer);
return 0;
}
/* ------------
* Vpn Commands
* ------------ */
CommandListener::VpnEnableCmd::VpnEnableCmd(NetworkManager *netman) :
NexusCommand("vpn_enable", netman) {
}
int CommandListener::VpnEnableCmd::runCommand(char *data) {
Controller *c = mNetman->findController("VPN");
char buffer[32];
sprintf(buffer, "VPN_ENABLE:%d", (c->enable() ? errno : 0));
mNetman->getFrameworkManager()->sendMsg(buffer);
return 0;
}
CommandListener::VpnDisableCmd::VpnDisableCmd(NetworkManager *netman) :
NexusCommand("vpn_disable", netman) {
}
int CommandListener::VpnDisableCmd::runCommand(char *data) {
Controller *c = mNetman->findController("VPN");
char buffer[32];
sprintf(buffer, "VPN_DISABLE:%d", (c->disable() ? errno : 0));
mNetman->getFrameworkManager()->sendMsg(buffer);
return 0;
}

70
nexus/CommandListener.h Normal file
View file

@ -0,0 +1,70 @@
/*
* 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.
*/
#ifndef _COMMANDLISTENER_H__
#define _COMMANDLISTENER_H__
#include <sysutils/FrameworkListener.h>
#include "NexusCommand.h"
class NetworkManager;
class CommandListener : public FrameworkListener {
protected:
NetworkManager *mNetman;
public:
CommandListener(NetworkManager *netman);
virtual ~CommandListener() {}
private:
class WifiEnableCmd : public NexusCommand {
public:
WifiEnableCmd(NetworkManager *);
virtual ~WifiEnableCmd() {}
int runCommand(char *data);
};
class WifiDisableCmd : public NexusCommand {
public:
WifiDisableCmd(NetworkManager *);
virtual ~WifiDisableCmd() {}
int runCommand(char *data);
};
class WifiScanCmd : public NexusCommand {
public:
WifiScanCmd(NetworkManager *);
virtual ~WifiScanCmd() {}
int runCommand(char *data);
};
class VpnEnableCmd : public NexusCommand {
public:
VpnEnableCmd(NetworkManager *);
virtual ~VpnEnableCmd() {}
int runCommand(char *data);
};
class VpnDisableCmd : public NexusCommand {
public:
VpnDisableCmd(NetworkManager *);
virtual ~VpnDisableCmd() {}
int runCommand(char *data);
};
};
#endif

144
nexus/Controller.cpp Normal file
View file

@ -0,0 +1,144 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define LOG_TAG "Controller"
#include <cutils/log.h>
#include "Controller.h"
extern "C" int init_module(void *, unsigned int, const char *);
extern "C" int delete_module(const char *, unsigned int);
Controller::Controller(const char *name) {
mName = name;
}
int Controller::start() {
return 0;
}
int Controller::stop() {
return 0;
}
int Controller::loadKernelModule(char *modpath, const char *args) {
void *module;
unsigned int size;
LOGD("loadKernelModule(%s, %s)", modpath, args);
module = loadFile(modpath, &size);
if (!module) {
errno = -EIO;
return -1;
}
int rc = init_module(module, size, args);
free (module);
return rc;
}
int Controller::unloadKernelModule(const char *modtag) {
int rc = -1;
int retries = 10;
LOGD("unloadKernelModule(%s)", modtag);
while (retries--) {
rc = delete_module(modtag, O_NONBLOCK | O_EXCL);
if (rc < 0 && errno == EAGAIN)
usleep(1000*500);
else
break;
}
if (rc != 0) {
LOGW("Unable to unload kernel driver '%s' (%s)", modtag,
strerror(errno));
}
return rc;
}
bool Controller::isKernelModuleLoaded(const char *modtag) {
FILE *fp = fopen("/proc/modules", "r");
if (!fp) {
LOGE("Unable to open /proc/modules (%s)", strerror(errno));
return false;
}
char line[255];
while(fgets(line, sizeof(line), fp)) {
char *endTag = strchr(line, ' ');
if (!endTag) {
LOGW("Unable to find tag for line '%s'", line);
continue;
}
if (!strncmp(line, modtag, (endTag - line))) {
fclose(fp);
return true;
}
}
fclose(fp);
return false;
}
void *Controller::loadFile(char *filename, unsigned int *_size)
{
int ret, fd;
struct stat sb;
ssize_t size;
void *buffer = NULL;
/* open the file */
fd = open(filename, O_RDONLY);
if (fd < 0)
return NULL;
/* find out how big it is */
if (fstat(fd, &sb) < 0)
goto bail;
size = sb.st_size;
/* allocate memory for it to be read into */
buffer = malloc(size);
if (!buffer)
goto bail;
/* slurp it into our buffer */
ret = read(fd, buffer, size);
if (ret != size)
goto bail;
/* let the caller know how big it is */
*_size = size;
bail:
close(fd);
return buffer;
}

47
nexus/Controller.h Normal file
View file

@ -0,0 +1,47 @@
/*
* 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.
*/
#ifndef _CONTROLLER_H
#define _CONTROLLER_H
#include "../../../frameworks/base/include/utils/List.h"
class Controller {
private:
const char *mName;
public:
Controller(const char *name);
virtual ~Controller() {}
virtual int start();
virtual int stop();
virtual int enable() = 0;
virtual int disable() = 0;
virtual const char *getName() { return mName; }
protected:
int loadKernelModule(char *modpath, const char *args);
bool isKernelModuleLoaded(const char *modtag);
int unloadKernelModule(const char *modtag);
private:
void *loadFile(char *filename, unsigned int *_size);
};
typedef android::List<Controller *> ControllerCollection;
#endif

32
nexus/LoopController.cpp Normal file
View file

@ -0,0 +1,32 @@
/*
* 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 <errno.h>
#include "LoopController.h"
LoopController::LoopController() :
Controller("LOOP") {
}
int LoopController::enable() {
errno = ENOSYS;
return -1;
}
int LoopController::disable() {
errno = ENOSYS;
return -1;
}

30
nexus/LoopController.h Normal file
View file

@ -0,0 +1,30 @@
/*
* 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.
*/
#ifndef _LOOP_CONTROLLER_H
#define _LOOP_CONTROLLER_H
#include "Controller.h"
class LoopController : public Controller {
public:
LoopController();
virtual ~LoopController() {}
int enable();
int disable();
};
#endif

100
nexus/NetworkManager.cpp Normal file
View file

@ -0,0 +1,100 @@
/*
* 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 <stdio.h>
#include <errno.h>
#define LOG_TAG "Nexus"
#include <cutils/log.h>
#include "NetworkManager.h"
#include "CommandListener.h"
#include "LoopController.h"
#include "VpnController.h"
#include "TiwlanWifiController.h"
NetworkManager::NetworkManager() {
mListener = new CommandListener(this);
mFm = new FrameworkManager(mListener);
mControllers = new ControllerCollection();
}
int NetworkManager::run() {
LOGD("NetworkManager::start()");
// XXX: Factory needed
addController(new LoopController());
addController(new TiwlanWifiController("/system/lib/modules/wlan.ko", "wlan", ""));
addController(new VpnController());
//addController(new GenericController("rmnet0"));
if (startControllers()) {
LOGW("Unable to start all controllers (%s)", strerror(errno));
}
mFm->run();
return 0;
}
void NetworkManager::addController(Controller *c) {
mControllers->push_back(c);
}
int NetworkManager::startControllers() {
int rc = 0;
ControllerCollection::iterator i;
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
int irc = (*i)->start();
LOGD("Controller '%s' start rc = %d", (*i)->getName(), irc);
if (irc && !rc)
rc = irc;
}
return rc;
}
int NetworkManager::stopControllers() {
int rc = 0;
ControllerCollection::iterator i;
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
int irc = (*i)->stop();
LOGD("Controller '%s' stop rc = %d", (*i)->getName(), irc);
if (irc && !rc)
rc = irc;
}
return rc;
}
Controller *NetworkManager::findController(const char *name) {
ControllerCollection::iterator i;
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
if (!strcmp((*i)->getName(), name))
return *i;
}
LOGW("Controller '%s' not found", name);
return NULL;
}
int NetworkManager::onInterfaceCreated(Controller *c, char *name) {
LOGD("Interface %s created by controller %s", name, c->getName());
return 0;
}
int NetworkManager::onInterfaceDestroyed(Controller *c, char *name) {
LOGD("Interface %s destroyed by controller %s", name, c->getName());
return 0;
}

51
nexus/NetworkManager.h Normal file
View file

@ -0,0 +1,51 @@
/*
* 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.
*/
#ifndef _NETWORKMANAGER_H
#define _NETWORKMANAGER_H
#include "Controller.h"
#include <sysutils/FrameworkManager.h>
class NetworkManager {
private:
FrameworkListener *mListener;
FrameworkManager *mFm;
ControllerCollection *mControllers;
public:
NetworkManager();
virtual ~NetworkManager() {}
int run();
private:
void addController(Controller *c);
int startControllers();
int stopControllers();
public:
Controller *findController(const char *name);
ControllerCollection *getControllers() { return mControllers; }
FrameworkManager *getFrameworkManager() { return mFm; }
public:
// XXX: Extract these into an interface
int onInterfaceCreated(Controller *c, char *name);
int onInterfaceDestroyed(Controller *c, char *name);
};
#endif

21
nexus/NexusCommand.cpp Normal file
View file

@ -0,0 +1,21 @@
/*
* 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 "NexusCommand.h"
NexusCommand::NexusCommand(const char *cmd, NetworkManager *netman) :
FrameworkCommand(cmd) {
mNetman = netman;
}

32
nexus/NexusCommand.h Normal file
View file

@ -0,0 +1,32 @@
/*
* 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.
*/
#ifndef _NEXUS_COMMAND_H
#define _NEXUS_COMMAND_H
#include <sysutils/FrameworkCommand.h>
class NetworkManager;
class NexusCommand : public FrameworkCommand {
protected:
NetworkManager *mNetman;
public:
NexusCommand(const char *cmd, NetworkManager *netman);
virtual ~NexusCommand() {}
};
#endif

74
nexus/ScanResult.cpp Normal file
View file

@ -0,0 +1,74 @@
/*
* 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>
#define LOG_TAG "ScanResult"
#include <cutils/log.h>
#include "ScanResult.h"
ScanResult::ScanResult() {
}
ScanResult::ScanResult(char *rawResult) {
char *tok, *next = NULL;
if (!(tok = strtok_r(rawResult, "\t", &next)))
goto out_bad;
mBssid = strdup(tok);
if (!(tok = strtok_r(NULL, "\t", &next)))
goto out_bad;
mFreq = atoi(tok);
if (!(tok = strtok_r(NULL, "\t", &next)))
goto out_bad;
mLevel = atoi(tok);
if (!(tok = strtok_r(rawResult, "\t", &next)))
goto out_bad;
mFlags = strdup(tok);
if (!(tok = strtok_r(rawResult, "\t", &next)))
goto out_bad;
mSsid = strdup(tok);
return;
out_bad:
LOGW("Malformatted scan result (%s)", rawResult);
}
ScanResult::~ScanResult() {
if (mBssid)
free(mBssid);
if (mFlags)
free(mFlags);
if (mSsid)
free(mSsid);
}
ScanResult *ScanResult::clone() {
ScanResult *r = new ScanResult();
r->mBssid = strdup(mBssid);
r->mFreq = mFreq;
r->mLevel = mLevel;
r->mFlags = strdup(mFlags);
r->mSsid = strdup(mSsid);
return r;
}

47
nexus/ScanResult.h Normal file
View file

@ -0,0 +1,47 @@
/*
* 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.
*/
#ifndef _SCAN_RESULT_H
#define _SCAN_RESULT_H
#include <sys/types.h>
#include "../../../frameworks/base/include/utils/List.h"
class ScanResult {
char *mBssid;
uint32_t mFreq;
int mLevel;
char *mFlags;
char *mSsid;
private:
ScanResult();
public:
ScanResult(char *rawResult);
virtual ~ScanResult();
ScanResult *clone();
const char *getBssid() { return mBssid; }
uint32_t getFreq() { return mFreq; }
const char *getFlags() { return mFlags; }
const char *getSsid() { return mSsid; }
};
typedef android::List<ScanResult *> ScanResultCollection;
#endif

377
nexus/Supplicant.cpp Normal file
View file

@ -0,0 +1,377 @@
/*
* 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 <errno.h>
#define LOG_TAG "Supplicant"
#include <cutils/log.h>
#include <cutils/properties.h>
#undef HAVE_LIBC_SYSTEM_PROPERTIES
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#endif
#include "Supplicant.h"
#include "SupplicantListener.h"
#include "SupplicantState.h"
#include "SupplicantEvent.h"
#include "ScanResult.h"
#include "libwpa_client/wpa_ctrl.h"
#define IFACE_DIR "/data/system/wpa_supplicant"
#define DRIVER_PROP_NAME "wlan.driver.status"
#define SUPPLICANT_NAME "wpa_supplicant"
#define SUPP_PROP_NAME "init.svc.wpa_supplicant"
Supplicant::Supplicant() {
mCtrl = NULL;
mMonitor = NULL;
mListener = NULL;
mState = SupplicantState::UNKNOWN;
mLatestScanResults = new ScanResultCollection();
pthread_mutex_init(&mLatestScanResultsLock, NULL);
}
int Supplicant::start() {
LOGD("start():");
// XXX: Validate supplicant config file
char status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 200;
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
const prop_info *pi;
unsigned int serial = 0;
#endif
if (property_get(SUPP_PROP_NAME, status, NULL) &&
strcmp(status, "running") == 0) {
return 0;
}
wpa_ctrl_cleanup();
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
pi = __system_property_find(SUPP_PROP_NAME);
if (pi != NULL)
serial = pi->serial;
#endif
property_set("ctl.start", SUPPLICANT_NAME);
sched_yield();
while (count--) {
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
if (!pi)
pi = __system_property_find(SUPP_PROP_NAME);
if (pi) {
__system_property_read(pi, NULL, status);
if (strcmp(status, "running") == 0)
return 0;
else if (pi->serial != serial &&
strcmp(status, "stopped") == 0) {
errno = EIO;
return -1;
}
}
#else
if (property_get(SUPP_PROP_NAME, status, NULL)) {
if (strcmp(status, "running") == 0)
break;
}
#endif
usleep(100000);
}
if (!count) {
errno = ETIMEDOUT;
return -1;
}
if (connectToSupplicant()) {
LOGE("Error connecting to supplicant (%s)\n", strerror(errno));
return -1;
}
return 0;
}
int Supplicant::stop() {
LOGD("stop()");
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 50;
if (mListener->stopListener()) {
LOGW("Unable to stop supplicant listener (%s)", strerror(errno));
return -1;
}
if (property_get(SUPP_PROP_NAME, supp_status, NULL)
&& strcmp(supp_status, "stopped") == 0) {
return 0;
}
property_set("ctl.stop", SUPPLICANT_NAME);
sched_yield();
while (count-- > 0) {
if (property_get(SUPP_PROP_NAME, supp_status, NULL)) {
if (strcmp(supp_status, "stopped") == 0)
break;
}
usleep(100000);
}
if (mCtrl) {
wpa_ctrl_close(mCtrl);
mCtrl = NULL;
}
if (mMonitor) {
wpa_ctrl_close(mMonitor);
mMonitor = NULL;
}
if (!count) {
LOGD("Timed out waiting for supplicant to stop");
errno = ETIMEDOUT;
return -1;
}
LOGD("Stopped OK");
return 0;
}
bool Supplicant::isStarted() {
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
if (!property_get(SUPP_PROP_NAME, supp_status, NULL) ||
!strcmp(supp_status, "running")) {
return false;
}
return true;
}
int Supplicant::connectToSupplicant() {
char ifname[256];
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
if (!property_get(SUPP_PROP_NAME, supp_status, NULL)
|| strcmp(supp_status, "running") != 0) {
LOGE("Supplicant not running, cannot connect");
return -1;
}
mCtrl = wpa_ctrl_open("tiwlan0");
if (mCtrl == NULL) {
LOGE("Unable to open connection to supplicant on \"%s\": %s",
"tiwlan0", strerror(errno));
return -1;
}
mMonitor = wpa_ctrl_open("tiwlan0");
if (mMonitor == NULL) {
wpa_ctrl_close(mCtrl);
mCtrl = NULL;
return -1;
}
if (wpa_ctrl_attach(mMonitor) != 0) {
wpa_ctrl_close(mMonitor);
wpa_ctrl_close(mCtrl);
mCtrl = mMonitor = NULL;
return -1;
}
mListener = new SupplicantListener(this, mMonitor);
if (mListener->startListener()) {
LOGE("Error - unable to start supplicant listener");
stop();
return -1;
}
return 0;
}
int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len)
{
if (!mCtrl) {
errno = ENOTCONN;
return -1;
}
LOGD("sendCommand(): -> '%s'", cmd);
int rc;
if ((rc = wpa_ctrl_request(mCtrl, cmd, strlen(cmd), reply, reply_len, NULL)) == -2) {
errno = ETIMEDOUT;
return -1;
} else if (rc < 0 || !strncmp(reply, "FAIL", 4)) {
errno = EIO;
return -1;
}
if (!strncmp(cmd, "PING", 4) ||
!strncmp(cmd, "SCAN_RESULTS", 12))
reply[*reply_len] = '\0';
LOGD("sendCommand(): <- '%s'", reply);
return 0;
}
int Supplicant::triggerScan(bool active) {
char reply[255];
size_t len = sizeof(reply);
if (sendCommand((active ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"),
reply, &len)) {
LOGW("triggerScan(%d): Error setting scan mode (%s)", active,
strerror(errno));
return -1;
}
len = sizeof(reply);
if (sendCommand("SCAN", reply, &len)) {
LOGW("triggerScan(%d): Error initiating scan", active);
return -1;
}
return 0;
}
int Supplicant::onConnectedEvent(SupplicantEvent *evt) {
LOGD("onConnectedEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onDisconnectedEvent(SupplicantEvent *evt) {
LOGD("onDisconnectedEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onTerminatingEvent(SupplicantEvent *evt) {
LOGD("onTerminatingEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onPasswordChangedEvent(SupplicantEvent *evt) {
LOGD("onPasswordChangedEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onEapNotificationEvent(SupplicantEvent *evt) {
LOGD("onEapNotificationEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onEapStartedEvent(SupplicantEvent *evt) {
LOGD("onEapStartedEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onEapMethodEvent(SupplicantEvent *evt) {
LOGD("onEapMethodEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onEapSuccessEvent(SupplicantEvent *evt) {
LOGD("onEapSuccessEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onEapFailureEvent(SupplicantEvent *evt) {
LOGD("onEapFailureEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onScanResultsEvent(SupplicantEvent *evt) {
LOGD("onScanResultsEvent(%s)", evt->getEvent());
if (!strcmp(evt->getEvent(), "Ready")) {
char *reply;
if (!(reply = (char *) malloc(4096))) {
errno = -ENOMEM;
return -1;
}
size_t len = 4096;
if (sendCommand("SCAN_RESULTS", reply, &len)) {
LOGW("onScanResultsEvent(%s): Error getting scan results (%s)",
evt->getEvent(), strerror(errno));
free(reply);
return -1;
}
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);
return 0;;
}
while((linep = strtok_r(NULL, "\n", &linep_next)))
mLatestScanResults->push_back(new ScanResult(linep));
pthread_mutex_unlock(&mLatestScanResultsLock);
free(reply);
} else {
LOGW("Unknown SCAN_RESULTS event (%s)", evt->getEvent());
}
return 0;
}
int Supplicant::onStateChangeEvent(SupplicantEvent *evt) {
LOGD("onStateChangeEvent(%s)", evt->getEvent());
// XXX: Update mState
return 0;
}
int Supplicant::onLinkSpeedEvent(SupplicantEvent *evt) {
LOGD("onLinkSpeedEvent(%s)", evt->getEvent());
return 0;
}
int Supplicant::onDriverStateEvent(SupplicantEvent *evt) {
LOGD("onDriverStateEvent(%s)", evt->getEvent());
return 0;
}
// XXX: Use a cursor + smartptr instead
const ScanResultCollection *Supplicant::getLatestScanResults() {
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;
};

72
nexus/Supplicant.h Normal file
View file

@ -0,0 +1,72 @@
/*
* 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.
*/
#ifndef _SUPPLICANT_H
#define _SUPPLICANT_H
struct wpa_ctrl;
class SupplicantListener;
class SupplicantEvent;
#include <pthread.h>
#include "ScanResult.h"
class Supplicant {
private:
struct wpa_ctrl *mCtrl;
struct wpa_ctrl *mMonitor;
SupplicantListener *mListener;
int mState;
ScanResultCollection *mLatestScanResults;
pthread_mutex_t mLatestScanResultsLock;
public:
Supplicant();
virtual ~Supplicant() {}
virtual int start();
virtual int stop();
virtual bool isStarted();
virtual int triggerScan(bool active);
int getState() { return mState; }
const ScanResultCollection *getLatestScanResults();
// XXX: Extract these into an interface
public:
virtual int onConnectedEvent(SupplicantEvent *evt);
virtual int onDisconnectedEvent(SupplicantEvent *evt);
virtual int onTerminatingEvent(SupplicantEvent *evt);
virtual int onPasswordChangedEvent(SupplicantEvent *evt);
virtual int onEapNotificationEvent(SupplicantEvent *evt);
virtual int onEapStartedEvent(SupplicantEvent *evt);
virtual int onEapMethodEvent(SupplicantEvent *evt);
virtual int onEapSuccessEvent(SupplicantEvent *evt);
virtual int onEapFailureEvent(SupplicantEvent *evt);
virtual int onScanResultsEvent(SupplicantEvent *evt);
virtual int onStateChangeEvent(SupplicantEvent *evt);
virtual int onLinkSpeedEvent(SupplicantEvent *evt);
virtual int onDriverStateEvent(SupplicantEvent *evt);
private:
int connectToSupplicant();
int sendCommand(const char *cmd, char *reply, size_t *reply_len);
};
#endif

95
nexus/SupplicantEvent.cpp Normal file
View file

@ -0,0 +1,95 @@
/*
* 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>
#define LOG_TAG "SupplicantEvent"
#include <cutils/log.h>
#include "SupplicantEvent.h"
#include "libwpa_client/wpa_ctrl.h"
SupplicantEvent::SupplicantEvent(char *event, size_t len) {
if (event[0] == '<') {
char *match = strchr(event, '>');
if (match) {
char tmp[16];
strncpy(tmp, &event[1], (match - event));
mLevel = atoi(tmp);
event += (match - event) + 1;
} else
LOGW("Unclosed level brace in event");
} else
LOGW("No level specified in event");
/*
* <N>CTRL-EVENT-XXX
* ^
* +---- event
*/
if (!strncmp(event, WPA_EVENT_CONNECTED, strlen(WPA_EVENT_CONNECTED)))
mType = SupplicantEvent::EVENT_CONNECTED;
else if (!strncmp(event, WPA_EVENT_DISCONNECTED, strlen(WPA_EVENT_DISCONNECTED)))
mType = SupplicantEvent::EVENT_DISCONNECTED;
else if (!strncmp(event, WPA_EVENT_TERMINATING, strlen(WPA_EVENT_TERMINATING)))
mType = SupplicantEvent::EVENT_TERMINATING;
else if (!strncmp(event, WPA_EVENT_PASSWORD_CHANGED, strlen(WPA_EVENT_PASSWORD_CHANGED)))
mType = SupplicantEvent::EVENT_PASSWORD_CHANGED;
else if (!strncmp(event, WPA_EVENT_EAP_NOTIFICATION, strlen(WPA_EVENT_EAP_NOTIFICATION)))
mType = SupplicantEvent::EVENT_EAP_NOTIFICATION;
else if (!strncmp(event, WPA_EVENT_EAP_STARTED, strlen(WPA_EVENT_EAP_STARTED)))
mType = SupplicantEvent::EVENT_EAP_STARTED;
else if (!strncmp(event, WPA_EVENT_EAP_METHOD, strlen(WPA_EVENT_EAP_METHOD)))
mType = SupplicantEvent::EVENT_EAP_METHOD;
else if (!strncmp(event, WPA_EVENT_EAP_SUCCESS, strlen(WPA_EVENT_EAP_SUCCESS)))
mType = SupplicantEvent::EVENT_EAP_SUCCESS;
else if (!strncmp(event, WPA_EVENT_EAP_FAILURE, strlen(WPA_EVENT_EAP_FAILURE)))
mType = SupplicantEvent::EVENT_EAP_FAILURE;
else if (!strncmp(event, WPA_EVENT_SCAN_RESULTS, strlen(WPA_EVENT_SCAN_RESULTS)))
mType = SupplicantEvent::EVENT_SCAN_RESULTS;
else if (!strncmp(event, WPA_EVENT_STATE_CHANGE, strlen(WPA_EVENT_STATE_CHANGE)))
mType = SupplicantEvent::EVENT_STATE_CHANGE;
else if (!strncmp(event, WPA_EVENT_LINK_SPEED, strlen(WPA_EVENT_LINK_SPEED)))
mType = SupplicantEvent::EVENT_LINK_SPEED;
else if (!strncmp(event, WPA_EVENT_DRIVER_STATE, strlen(WPA_EVENT_DRIVER_STATE)))
mType = SupplicantEvent::EVENT_DRIVER_STATE;
else {
LOGW("Unknown supplicant event '%s'", event);
mType = SupplicantEvent::EVENT_UNKNOWN;
}
for (event; *event != ' '; event++);
event++;
/*
* <N>CTRL-EVENT-XXX YYYY
* ^
* +---- event
*/
for (event; *event == ' '; event++);
mEvent = strdup(event);
mLen = len;
}
SupplicantEvent::~SupplicantEvent() {
if (mEvent)
free(mEvent);
}

54
nexus/SupplicantEvent.h Normal file
View file

@ -0,0 +1,54 @@
/*
* 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.
*/
#ifndef _SUPPLICANT_EVENT_H
#define _SUPPLICANT_EVENT_H
#include <sys/types.h>
class SupplicantEvent {
private:
int mType;
char *mEvent;
size_t mLen;
int mLevel;
public:
static const int EVENT_UNKNOWN = 0;
static const int EVENT_CONNECTED = 1;
static const int EVENT_DISCONNECTED = 2;
static const int EVENT_TERMINATING = 3;
static const int EVENT_PASSWORD_CHANGED = 4;
static const int EVENT_EAP_NOTIFICATION = 5;
static const int EVENT_EAP_STARTED = 6;
static const int EVENT_EAP_METHOD = 7;
static const int EVENT_EAP_SUCCESS = 8;
static const int EVENT_EAP_FAILURE = 9;
static const int EVENT_SCAN_RESULTS = 10;
static const int EVENT_STATE_CHANGE = 11;
static const int EVENT_LINK_SPEED = 12;
static const int EVENT_DRIVER_STATE = 13;
public:
SupplicantEvent(char *event, size_t len);
virtual ~SupplicantEvent();
int getType() { return mType; }
const char *getEvent() { return mEvent; }
int getLen() { return mLen; }
int getLevel() { return mLevel; }
};
#endif

View file

@ -0,0 +1,114 @@
/*
* 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 <errno.h>
#include <sys/types.h>
#include <pthread.h>
#define LOG_TAG "SupplicantListener"
#include <cutils/log.h>
#include "libwpa_client/wpa_ctrl.h"
#include "Supplicant.h"
#include "SupplicantListener.h"
#include "SupplicantEvent.h"
SupplicantListener::SupplicantListener(Supplicant *supplicant, struct wpa_ctrl *monitor) :
SocketListener(wpa_ctrl_get_fd(monitor), false) {
mSupplicant = supplicant;
mMonitor = monitor;
mThread = NULL;
}
int SupplicantListener::startListener() {
LOGD("startListener()");
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
return pthread_create(&mThread, &attr, &SupplicantListener::threadStart, this);
}
int SupplicantListener::stopListener() {
errno = -ENOSYS;
return -1;
}
void *SupplicantListener::threadStart(void *obj) {
LOGD("threadStart(): Worker thread started");
reinterpret_cast<SupplicantListener *>(obj)->run();
LOGD("threadStart(): Worker thread exited");
return NULL;
}
bool SupplicantListener::onDataAvailable(int socket) {
char buf[255];
size_t buflen = sizeof(buf);
int rc;
size_t nread = buflen - 1;
if ((rc = wpa_ctrl_recv(mMonitor, buf, &nread))) {
LOGE("wpa_ctrl_recv failed (%s)", strerror(errno));
return -errno;
}
buf[nread] = '\0';
if (!rc && !nread) {
LOGD("Received EOF on supplicant socket\n");
strncpy(buf, WPA_EVENT_TERMINATING " - signal 0 received", buflen-1);
buf[buflen-1] = '\0';
return false;
}
SupplicantEvent *evt = new SupplicantEvent(buf, nread);
// XXX: Make this a factory
// XXX: Instead of calling Supplicant directly
// extract an Interface and use that instead
if (evt->getType() == SupplicantEvent::EVENT_CONNECTED)
rc = mSupplicant->onConnectedEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_DISCONNECTED)
rc = mSupplicant->onDisconnectedEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_TERMINATING)
rc = mSupplicant->onTerminatingEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_PASSWORD_CHANGED)
rc = mSupplicant->onPasswordChangedEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_EAP_NOTIFICATION)
rc = mSupplicant->onEapNotificationEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_EAP_STARTED)
rc = mSupplicant->onEapStartedEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_EAP_SUCCESS)
rc = mSupplicant->onEapSuccessEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_EAP_FAILURE)
rc = mSupplicant->onEapFailureEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_SCAN_RESULTS)
rc = mSupplicant->onScanResultsEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_STATE_CHANGE)
rc = mSupplicant->onStateChangeEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_LINK_SPEED)
rc = mSupplicant->onLinkSpeedEvent(evt);
else if (evt->getType() == SupplicantEvent::EVENT_DRIVER_STATE)
rc = mSupplicant->onDriverStateEvent(evt);
else {
LOGW("Ignoring unknown event");
}
delete evt;
if (rc)
return false;
return true;
}

View file

@ -0,0 +1,48 @@
/*
* 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.
*/
#ifndef _SUPPLICANTLISTENER_H__
#define _SUPPLICANTLISTENER_H__
#include <pthread.h>
#include <sysutils/SocketListener.h>
struct wpa_ctrl;
class Supplicant;
class SupplicantListener: public SocketListener {
private:
struct wpa_ctrl *mMonitor;
Supplicant *mSupplicant;
pthread_t mThread;
public:
SupplicantListener(Supplicant *supplicant, struct wpa_ctrl *monitor);
virtual ~SupplicantListener() {}
int startListener();
int stopListener();
struct wpa_ctrl *getMonitor() { return mMonitor; }
Supplicant *getSupplicant() { return mSupplicant; }
protected:
virtual bool onDataAvailable(int socket);
private:
static void *threadStart(void *obj);
};
#endif

33
nexus/SupplicantState.h Normal file
View file

@ -0,0 +1,33 @@
/*
* 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.
*/
#ifndef _SUPPLICANT_STATE_H
#define _SUPPLICANT_STATE_H
class SupplicantState {
public:
static const int UNKNOWN = 0;
static const int DISCONNECTED = 1;
static const int INACTIVE = 2;
static const int SCANNING = 3;
static const int ASSOCIATING = 4;
static const int ASSOCIATED = 5;
static const int FOURWAY_HANDSHAKE = 6;
static const int GROUP_HANDSHAKE = 7;
static const int COMPLETED = 8;
static const int IDLE = 9;
};
#endif

View file

@ -0,0 +1,67 @@
/*
* 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 <fcntl.h>
#include <errno.h>
#include <string.h>
#include <cutils/properties.h>
#define LOG_TAG "TiwlanWifiController"
#include <cutils/log.h>
#include "TiwlanWifiController.h"
#define DRIVER_PROP_NAME "wlan.driver.status"
extern "C" int sched_yield(void);
TiwlanWifiController::TiwlanWifiController(char *modpath, char *modname, char *modargs) :
WifiController(modpath, modname, modargs) {
}
int TiwlanWifiController::powerUp() {
return 0; // Powerup is currently done when the driver is loaded
}
int TiwlanWifiController::powerDown() {
return 0; // Powerdown is currently done when the driver is unloaded
}
bool TiwlanWifiController::isPoweredUp() {
return isKernelModuleLoaded(getModuleName());
}
int TiwlanWifiController::loadFirmware() {
char driver_status[PROPERTY_VALUE_MAX];
int count = 100;
LOGD("loadFirmware()");
property_set("ctl.start", "wlan_loader");
sched_yield();
// Wait for driver to be ready
while (count-- > 0) {
if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
if (strcmp(driver_status, "ok") == 0)
return 0;
else if (strcmp(DRIVER_PROP_NAME, "failed") == 0)
return -1;
}
usleep(200000);
}
property_set(DRIVER_PROP_NAME, "timeout");
return -1;
}

View file

@ -0,0 +1,31 @@
/*
* 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.
*/
#ifndef _TIWLAN_WIFI_CONTROLLER_H
#define _TIWLAN_WIFI_CONTROLLER_H
#include "WifiController.h"
class TiwlanWifiController : public WifiController {
public:
TiwlanWifiController(char *modpath, char *modname, char *modargs);
virtual ~TiwlanWifiController() {}
virtual int powerUp();
virtual int powerDown();
virtual bool isPoweredUp();
virtual int loadFirmware();
};
#endif

44
nexus/VpnController.cpp Normal file
View file

@ -0,0 +1,44 @@
/*
* 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 <errno.h>
#include "VpnController.h"
VpnController::VpnController() :
Controller("VPN") {
}
int VpnController::start() {
errno = -ENOSYS;
return -1;
}
int VpnController::stop() {
errno = -ENOSYS;
return -1;
}
int VpnController::enable() {
// Load modules
// Start daemons
errno = -ENOSYS;
return -1;
}
int VpnController::disable() {
errno = -ENOSYS;
return -1;
}

38
nexus/VpnController.h Normal file
View file

@ -0,0 +1,38 @@
/*
* 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.
*/
#ifndef _VPN_CONTROLLER_H
#define _VPN_CONTROLLER_H
#include "Controller.h"
class VpnController : public Controller {
public:
VpnController();
virtual ~VpnController() {}
virtual int start();
virtual int stop();
virtual int enable();
virtual int disable();
protected:
private:
};
#endif

134
nexus/WifiController.cpp Normal file
View file

@ -0,0 +1,134 @@
/*
* 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 <string.h>
#include <errno.h>
#define LOG_TAG "WifiController"
#include <cutils/log.h>
#include "Supplicant.h"
#include "WifiController.h"
WifiController::WifiController(char *modpath, char *modname, char *modargs) :
Controller("WIFI") {
strncpy(mModulePath, modpath, sizeof(mModulePath));
strncpy(mModuleName, modname, sizeof(mModuleName));
strncpy(mModuleArgs, modargs, sizeof(mModuleArgs));
mSupplicant = new Supplicant();
mCurrentScanMode = 0;
}
int WifiController::start() {
return 0;
}
int WifiController::stop() {
errno = ENOSYS;
return -1;
}
int WifiController::enable() {
if (!isPoweredUp() && powerUp()) {
LOGE("Powerup failed (%s)", strerror(errno));
return -1;
}
if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) {
if (loadKernelModule(mModulePath, mModuleArgs)) {
LOGE("Kernel module load failed (%s)", strerror(errno));
goto out_powerdown;
}
}
if (loadFirmware()) {
LOGE("Firmware load failed (%s)", strerror(errno));
goto out_powerdown;
}
if (!mSupplicant->isStarted() && mSupplicant->start()) {
LOGE("Supplicant start failed (%s)", strerror(errno));
goto out_unloadmodule;
}
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;
}
int WifiController::disable() {
LOGD("disable()");
if (mSupplicant->isStarted() && mSupplicant->stop()) {
LOGE("Supplicant stop failed (%s)", strerror(errno));
return -1;
}
if (mModuleName[0] != '\0' && isKernelModuleLoaded(mModuleName)) {
if (unloadKernelModule(mModuleName)) {
LOGE("Unable to unload module (%s)", strerror(errno));
return -1;
}
}
if (isPoweredUp() && powerDown()) {
LOGE("Powerdown failed (%s)", strerror(errno));
return -1;
}
return 0;
}
int WifiController::loadFirmware() {
return 0;
}
int WifiController::setScanMode(int mode) {
int rc = 0;
if (mCurrentScanMode == mode)
return 0;
if (!(mode & SCAN_ENABLE_MASK)) {
if (mCurrentScanMode & SCAN_REPEAT_MASK)
stopPeriodicScan();
} else if (mode & SCAN_REPEAT_MASK)
rc = startPeriodicScan();
else
rc = mSupplicant->triggerScan(mode & SCAN_ACTIVE_MASK);
return rc;
}
int WifiController::startPeriodicScan() {
errno = -ENOSYS;
return -1;
}
int WifiController::stopPeriodicScan() {
errno = -ENOSYS;
return -1;
}

78
nexus/WifiController.h Normal file
View file

@ -0,0 +1,78 @@
/*
* 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.
*/
#ifndef _WIFI_CONTROLLER_H
#define _WIFI_CONTROLLER_H
#include <sys/types.h>
#include "Controller.h"
class NetInterface;
class Supplicant;
class WifiController : public Controller {
public:
static const uint32_t SCAN_ENABLE_MASK = 0x01;
static const uint32_t SCAN_ACTIVE_MASK = 0x02;
static const uint32_t SCAN_REPEAT_MASK = 0x04;
static const uint32_t SCANMODE_NONE = 0;
static const uint32_t SCANMODE_PASSIVE_ONESHOT = SCAN_ENABLE_MASK;
static const uint32_t SCANMODE_PASSIVE_CONTINUOUS = SCAN_ENABLE_MASK | SCAN_REPEAT_MASK;
static const uint32_t SCANMODE_ACTIVE_ONESHOT = SCAN_ENABLE_MASK | SCAN_ACTIVE_MASK;
static const uint32_t SCANMODE_ACTIVE_CONTINUOUS = SCAN_ENABLE_MASK | SCAN_ACTIVE_MASK | SCAN_REPEAT_MASK;
private:
Supplicant *mSupplicant;
char mModulePath[255];
char mModuleName[64];
char mModuleArgs[255];
int mCurrentScanMode;
public:
WifiController(char *modpath, char *modname, char *modargs);
virtual ~WifiController() {}
int start();
int stop();
int enable();
int disable();
int getType();
char *getModulePath() { return mModulePath; }
char *getModuleName() { return mModuleName; }
char *getModuleArgs() { return mModuleArgs; }
Supplicant *getSupplicant() { return mSupplicant; }
int getScanMode() { return mCurrentScanMode; }
int setScanMode(int mode);
protected:
virtual int powerUp() = 0;
virtual int powerDown() = 0;
virtual int loadFirmware();
virtual bool isPoweredUp() = 0;
private:
int startPeriodicScan();
int stopPeriodicScan();
};
#endif

41
nexus/main.cpp Normal file
View file

@ -0,0 +1,41 @@
/*
* 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 <errno.h>
#define LOG_TAG "Nexus"
#include "cutils/log.h"
#include "NetworkManager.h"
int main() {
NetworkManager *nm;
LOGI("Nexus version 0.1 firing up");
if (!(nm = new NetworkManager())) {
LOGE("Unable to create NetworkManager");
exit (-1);
};
if (nm->run()) {
LOGE("Unable to Run NetworkManager (%s)", strerror(errno));
exit (1);
}
LOGI("Nexus exiting");
exit(0);
}

104
nexus/nexctl.c Normal file
View file

@ -0,0 +1,104 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
static void signal_handler(int sig) {
fprintf(stdout, "{ interrupt! }\n");
}
int main(int argc, char **argv) {
int sock;
if ((sock = socket_local_client("nexus",
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM)) < 0) {
fprintf(stderr, "Error connecting (%s)\n", strerror(errno));
exit(1);
}
printf("Connected to nexus\n");
while(1) {
fd_set read_fds;
struct timeval to;
int rc = 0;
signal(SIGINT, SIG_DFL);
printf("-> ");
fflush(stdout);
char buffer[255];
if (!fgets(buffer, sizeof(buffer) -1, stdin)) {
printf("Exiting...\n");
exit(0);
}
buffer[strlen(buffer) -1] = 0;
printf("sending '%s'\n", buffer);
if (write(sock, buffer, strlen(buffer) +1) < 0) {
fprintf(stderr, "Error writing data (%s)\n", strerror(errno));
exit(2);
}
wait:
to.tv_sec = 5;
to.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(sock, &read_fds);
signal(SIGINT, signal_handler);
if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {
if (errno == EINTR)
continue;
fprintf(stderr, "Error in select (%s)\n", strerror(errno));
exit(2);
} else if (!rc) {
printf("{response timeout}\n");
continue;
} else if (FD_ISSET(sock, &read_fds)) {
printf("got data!\n");
if ((rc = read(sock, buffer, sizeof(buffer)-1)) < 0) {
fprintf(stderr, "Error reading response (%s)\n", strerror(errno));
exit(2);
}
printf(" |%s|\n", buffer);
goto wait;
}
}
exit(0);
}

View file

@ -217,6 +217,10 @@ service servicemanager /system/bin/servicemanager
service vold /system/bin/vold
socket vold stream 0660 root mount
service nexus /system/bin/nexus
socket nexus stream 0660 root system
disabled
#service mountd /system/bin/mountd
# socket mountd stream 0660 root mount