summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-05-07 07:21:15 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2009-05-07 07:21:15 -0700
commit902905682da7247aac3a73a71057e87f9758f0b1 (patch)
tree49bc54a6f8cf4fa222a40172e1105590853e505b
parent747baadddb37737b0ecf83f6147a5e3252a34b12 (diff)
parent269946c09faaff88403289bcfa2519e994f75c21 (diff)
downloadsystem_core-902905682da7247aac3a73a71057e87f9758f0b1.zip
system_core-902905682da7247aac3a73a71057e87f9758f0b1.tar.gz
system_core-902905682da7247aac3a73a71057e87f9758f0b1.tar.bz2
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.
-rw-r--r--nexus/Android.mk47
-rw-r--r--nexus/CommandListener.cpp124
-rw-r--r--nexus/CommandListener.h70
-rw-r--r--nexus/Controller.cpp144
-rw-r--r--nexus/Controller.h47
-rw-r--r--nexus/LoopController.cpp32
-rw-r--r--nexus/LoopController.h30
-rw-r--r--nexus/NetworkManager.cpp100
-rw-r--r--nexus/NetworkManager.h51
-rw-r--r--nexus/NexusCommand.cpp21
-rw-r--r--nexus/NexusCommand.h32
-rw-r--r--nexus/ScanResult.cpp74
-rw-r--r--nexus/ScanResult.h47
-rw-r--r--nexus/Supplicant.cpp377
-rw-r--r--nexus/Supplicant.h72
-rw-r--r--nexus/SupplicantEvent.cpp95
-rw-r--r--nexus/SupplicantEvent.h54
-rw-r--r--nexus/SupplicantListener.cpp114
-rw-r--r--nexus/SupplicantListener.h48
-rw-r--r--nexus/SupplicantState.h33
-rw-r--r--nexus/TiwlanWifiController.cpp67
-rw-r--r--nexus/TiwlanWifiController.h31
-rw-r--r--nexus/VpnController.cpp44
-rw-r--r--nexus/VpnController.h38
-rw-r--r--nexus/WifiController.cpp134
-rw-r--r--nexus/WifiController.h78
-rw-r--r--nexus/main.cpp41
-rw-r--r--nexus/nexctl.c104
-rw-r--r--rootdir/init.rc4
29 files changed, 2153 insertions, 0 deletions
diff --git a/nexus/Android.mk b/nexus/Android.mk
new file mode 100644
index 0000000..e76cb27
--- /dev/null
+++ b/nexus/Android.mk
@@ -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)
diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp
new file mode 100644
index 0000000..cdb1db5
--- /dev/null
+++ b/nexus/CommandListener.cpp
@@ -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;
+}
diff --git a/nexus/CommandListener.h b/nexus/CommandListener.h
new file mode 100644
index 0000000..261c093
--- /dev/null
+++ b/nexus/CommandListener.h
@@ -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
diff --git a/nexus/Controller.cpp b/nexus/Controller.cpp
new file mode 100644
index 0000000..cc1a187
--- /dev/null
+++ b/nexus/Controller.cpp
@@ -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;
+}
diff --git a/nexus/Controller.h b/nexus/Controller.h
new file mode 100644
index 0000000..8e69978
--- /dev/null
+++ b/nexus/Controller.h
@@ -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
diff --git a/nexus/LoopController.cpp b/nexus/LoopController.cpp
new file mode 100644
index 0000000..38037ac
--- /dev/null
+++ b/nexus/LoopController.cpp
@@ -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;
+}
diff --git a/nexus/LoopController.h b/nexus/LoopController.h
new file mode 100644
index 0000000..8b89977
--- /dev/null
+++ b/nexus/LoopController.h
@@ -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
diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp
new file mode 100644
index 0000000..9c64945
--- /dev/null
+++ b/nexus/NetworkManager.cpp
@@ -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;
+}
diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h
new file mode 100644
index 0000000..8f362a9
--- /dev/null
+++ b/nexus/NetworkManager.h
@@ -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
diff --git a/nexus/NexusCommand.cpp b/nexus/NexusCommand.cpp
new file mode 100644
index 0000000..090113c
--- /dev/null
+++ b/nexus/NexusCommand.cpp
@@ -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;
+}
diff --git a/nexus/NexusCommand.h b/nexus/NexusCommand.h
new file mode 100644
index 0000000..204541c
--- /dev/null
+++ b/nexus/NexusCommand.h
@@ -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
diff --git a/nexus/ScanResult.cpp b/nexus/ScanResult.cpp
new file mode 100644
index 0000000..b7237b5
--- /dev/null
+++ b/nexus/ScanResult.cpp
@@ -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;
+}
diff --git a/nexus/ScanResult.h b/nexus/ScanResult.h
new file mode 100644
index 0000000..79b2b65
--- /dev/null
+++ b/nexus/ScanResult.h
@@ -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
diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp
new file mode 100644
index 0000000..215a8b3
--- /dev/null
+++ b/nexus/Supplicant.cpp
@@ -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;
+};
diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h
new file mode 100644
index 0000000..46a9e86
--- /dev/null
+++ b/nexus/Supplicant.h
@@ -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
diff --git a/nexus/SupplicantEvent.cpp b/nexus/SupplicantEvent.cpp
new file mode 100644
index 0000000..5c0944a
--- /dev/null
+++ b/nexus/SupplicantEvent.cpp
@@ -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);
+}
diff --git a/nexus/SupplicantEvent.h b/nexus/SupplicantEvent.h
new file mode 100644
index 0000000..86ce8cb
--- /dev/null
+++ b/nexus/SupplicantEvent.h
@@ -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
diff --git a/nexus/SupplicantListener.cpp b/nexus/SupplicantListener.cpp
new file mode 100644
index 0000000..16306b5
--- /dev/null
+++ b/nexus/SupplicantListener.cpp
@@ -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;
+}
diff --git a/nexus/SupplicantListener.h b/nexus/SupplicantListener.h
new file mode 100644
index 0000000..3d27a68
--- /dev/null
+++ b/nexus/SupplicantListener.h
@@ -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
diff --git a/nexus/SupplicantState.h b/nexus/SupplicantState.h
new file mode 100644
index 0000000..f2cf603
--- /dev/null
+++ b/nexus/SupplicantState.h
@@ -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
diff --git a/nexus/TiwlanWifiController.cpp b/nexus/TiwlanWifiController.cpp
new file mode 100644
index 0000000..ec83825
--- /dev/null
+++ b/nexus/TiwlanWifiController.cpp
@@ -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;
+}
diff --git a/nexus/TiwlanWifiController.h b/nexus/TiwlanWifiController.h
new file mode 100644
index 0000000..a93d610
--- /dev/null
+++ b/nexus/TiwlanWifiController.h
@@ -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
diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp
new file mode 100644
index 0000000..2d3db85
--- /dev/null
+++ b/nexus/VpnController.cpp
@@ -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;
+}
diff --git a/nexus/VpnController.h b/nexus/VpnController.h
new file mode 100644
index 0000000..f792ce3
--- /dev/null
+++ b/nexus/VpnController.h
@@ -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
diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp
new file mode 100644
index 0000000..8a7e33f
--- /dev/null
+++ b/nexus/WifiController.cpp
@@ -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;
+}
diff --git a/nexus/WifiController.h b/nexus/WifiController.h
new file mode 100644
index 0000000..6d00513
--- /dev/null
+++ b/nexus/WifiController.h
@@ -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
diff --git a/nexus/main.cpp b/nexus/main.cpp
new file mode 100644
index 0000000..a26a14d
--- /dev/null
+++ b/nexus/main.cpp
@@ -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);
+}
diff --git a/nexus/nexctl.c b/nexus/nexctl.c
new file mode 100644
index 0000000..6d117c7
--- /dev/null
+++ b/nexus/nexctl.c
@@ -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);
+
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index e1f1e8a..c20eeaa 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -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