From a65debe705e17d510c0b3f5cbc07ebfa936d753e Mon Sep 17 00:00:00 2001 From: Sridhar Parasuram Date: Tue, 8 Dec 2009 11:55:31 -0800 Subject: Initial commit --- cnd/inc/cnd.h | 52 ++ cnd/inc/cnd_commands.h | 33 ++ cnd/inc/cnd_event.h | 53 ++ cnd/inc/cnd_iproute2.h | 186 ++++++ cnd/inc/cnd_unsol_messages.h | 29 + cnd/src/Android.mk | 39 ++ cnd/src/cnd.c | 46 ++ cnd/src/cnd_event.cpp | 256 ++++++++ cnd/src/cnd_iproute2.cpp | 1084 ++++++++++++++++++++++++++++++++++ cnd/src/cnd_process.cpp | 1123 ++++++++++++++++++++++++++++++++++++ include/cne/cne_svc.h | 492 ++++++++++++++++ reference-cne/inc/CRefCne.h | 128 ++++ reference-cne/inc/CRefCneRadio.h | 120 ++++ reference-cne/inc/RefCneDefs.h | 134 +++++ reference-cne/src/Android.mk | 46 ++ reference-cne/src/CRefCne.cpp | 402 +++++++++++++ reference-cne/src/CRefCneRadio.cpp | 280 +++++++++ reference-cne/src/CneSvc.cpp | 133 +++++ 18 files changed, 4636 insertions(+) create mode 100755 cnd/inc/cnd.h create mode 100755 cnd/inc/cnd_commands.h create mode 100755 cnd/inc/cnd_event.h create mode 100755 cnd/inc/cnd_iproute2.h create mode 100755 cnd/inc/cnd_unsol_messages.h create mode 100755 cnd/src/Android.mk create mode 100755 cnd/src/cnd.c create mode 100755 cnd/src/cnd_event.cpp create mode 100755 cnd/src/cnd_iproute2.cpp create mode 100755 cnd/src/cnd_process.cpp create mode 100755 include/cne/cne_svc.h create mode 100755 reference-cne/inc/CRefCne.h create mode 100755 reference-cne/inc/CRefCneRadio.h create mode 100755 reference-cne/inc/RefCneDefs.h create mode 100755 reference-cne/src/Android.mk create mode 100755 reference-cne/src/CRefCne.cpp create mode 100755 reference-cne/src/CRefCneRadio.cpp create mode 100755 reference-cne/src/CneSvc.cpp diff --git a/cnd/inc/cnd.h b/cnd/inc/cnd.h new file mode 100755 index 0000000..f6e9e65 --- /dev/null +++ b/cnd/inc/cnd.h @@ -0,0 +1,52 @@ +/* +** Copyright 2006, The Android Open Source Project +** Copyright (c) 2009, Code Aurora Forum. All rights reserved. +** +** 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 CND_H +#define CND_H + +#include +#include +#include "cne_svc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef void * CND_Token; + +typedef enum { + CND_E_SUCCESS = 0, + CND_E_RADIO_NOT_AVAILABLE = 1, /* If radio did not start or is resetting */ + CND_E_GENERIC_FAILURE = 2, + CND_E_INVALID_RESPONSE + +} CND_Errno; + + + + +void cnd_init(void); +void cnd_startEventLoop(void); + + + +#ifdef __cplusplus +} +#endif + +#endif /* CND_H */ + diff --git a/cnd/inc/cnd_commands.h b/cnd/inc/cnd_commands.h new file mode 100755 index 0000000..f5351df --- /dev/null +++ b/cnd/inc/cnd_commands.h @@ -0,0 +1,33 @@ +/* +** Copyright 2006, The Android Open Source Project +** Copyright (c) 2009, Code Aurora Forum. All rights reserved. +** +** 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. +*/ + {0, NULL, NULL}, //none + {CNE_REQUEST_INIT_CMD, dispatchVoid, responseVoid}, + {CNE_REQUEST_REG_ROLE_CMD, dispatchInts, responseInts}, + {CNE_REQUEST_GET_COMPATIBLE_NWS_CMD, dispatchInts, responseInts}, + {CNE_REQUEST_CONFIRM_NW_CMD, dispatchInts, responseInts}, + {CNE_REQUEST_DEREG_ROLE_CMD, dispatchInts, responseInts}, + {CNE_REQUEST_REG_NOTIFICATIONS_CMD, dispatchInts, responseInts}, + {CNE_REQUEST_UPDATE_BATTERY_INFO_CMD, dispatchInts, responseVoid}, + {CNE_REQUEST_UPDATE_WLAN_INFO_CMD, dispatchWlanInfo, responseVoid}, + {CNE_REQUEST_UPDATE_WWAN_INFO_CMD, dispatchInts, responseVoid}, + {CNE_NOTIFY_RAT_CONNECT_STATUS_CMD, dispatchInts, responseInts}, + {CNE_NOTIFY_DEFAULT_NW_PREF_CMD, dispatchInts, responseVoid}, + {CNE_REQUEST_UPDATE_WLAN_SCAN_RESULTS_CMD, dispatchWlanScanResults, responseVoid}, + {CNE_NOTIFY_SENSOR_EVENT_CMD, dispatchVoid, responseVoid}, + {CNE_REQUEST_CONFIG_IPROUTE2_CMD, dispatchStrings, responseVoid} + + diff --git a/cnd/inc/cnd_event.h b/cnd/inc/cnd_event.h new file mode 100755 index 0000000..fd05181 --- /dev/null +++ b/cnd/inc/cnd_event.h @@ -0,0 +1,53 @@ +/* +** Copyright 2006, The Android Open Source Project +** Copyright (c) 2009, Code Aurora Forum. All rights reserved. +** +** 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. +*/ + +// Max number of fd's we watch at any one time. Increase if necessary. +#define MAX_FD_EVENTS 8 + +typedef void (*cnd_event_cb)(int fd, void *userdata); + +struct cnd_event { + struct cnd_event *next; + struct cnd_event *prev; + + int fd; + int index; + int persist; + cnd_event_cb func; + void *param; +}; + +// Initialize internal data structs +void cnd_event_init(); + +// Initialize an event +void cnd_event_set(struct cnd_event * ev, int fd, int persist, cnd_event_cb func, void * param); + +// Add event to watch list +void cnd_event_add(struct cnd_event * ev); + + +// Remove event from watch list +void cnd_event_del(struct cnd_event * ev); + +// Event loop +void cnd_event_loop(); + + +// Dump watch table for debugging +void cnd_dump_watch_table(); + diff --git a/cnd/inc/cnd_iproute2.h b/cnd/inc/cnd_iproute2.h new file mode 100755 index 0000000..e12778d --- /dev/null +++ b/cnd/inc/cnd_iproute2.h @@ -0,0 +1,186 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CND_IPROUTE2_H +#define CND_IPROUTE2_H + +/**---------------------------------------------------------------------------- + @file cnd_iproute2.h + + cnd_iproute2 is an interface to make the necessary calls to iproute2 + in order to set up and take down routing tables. Defines APIS so that + a routing table associated with a RAT can be added or deleted. Also + allows the user to change the default routing table when a given + source address is not already associated with a RAT. +-----------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Class Definitions + * -------------------------------------------------------------------------*/ + +class cnd_iproute2 +{ + public: + /** + * @brief Returns an instance of the Cnd_iproute2 class. + + The user of this class will call this function to get an + instance of the class. All other public functions will be + called on this instance + + * @param None + * @see None + * @return An instance of the Cnd_iproute2 class is returned. + */ + static cnd_iproute2* getInstance + ( + void + ); + + /** + * @brief Create a routing table for a RAT using iproute2 + * + * The user of this function passes in the name of the RAT that + * matches the name already defined in the Android system. The + * user also needs to locate the gateway address and source + * prefix assocated with that RAT device. If a table is added + * when no another tables exist, it will automatically become the + * default table. + * + * @param deviceName The name of the device whose table + * will be added (Such as wlan or wwan) + * @param sourcePrefix The source network prefix or address + * that will be routed to the device + * (Such as 37.214.21/24 or 10.156.45.1) + * @param gatewayAddress The gateway address of the device. + * @return True if function is successful. False + * otherwise. + */ + bool addRoutingTable + ( + uint8_t *deviceName, + uint8_t *sourcePrefix, + uint8_t *gatewayAddress + ); + + /** + * @brief Change the default routing table that is associated + * with any source addresses not bound to another table. + * + * The user of this function passes in the name of the RAT that + * matches the name already defined in the Android system. That + * device will become the new default. If this RAT is already the + * default, this function simply returns true. + * + * @param deviceName The name of the device whose table + * will be added (Such as wlan or wwan) + * @return True if function is successful. False + * otherwise. + */ + bool changeDefaultTable + ( + uint8_t *deviceName + ); + + /** + * @brief Deletes a routing table from the system along with the + * rule corresponding to that table. + * + * @param deviceName The name of the device whose table will be + * deleted (Such as wlan or wwan) + * @return True if function is successful. False + * otherwise. + */ + bool deleteRoutingTable + ( + uint8_t *deviceName + ); + + /** + * Displays the contents of all routing tables for debugging + * purposes. + * + * @return True if function is successful. False + * otherwise. + */ + bool showAllRoutingTables + ( + void + ); + + /** + * Displays the contents of the routing table associated with + * the inputted device name. + * + * @param deviceName The name of the device to be displayed + * (Usually wlan or wwan) + * @return True if function is successful. False + * otherwise. + */ + bool showRoutingTable + ( + uint8_t *deviceName + ); + + /** + * Displays the rules associated with all tables for debugging + * purposes. + * + * @return True if function is successful. False + * otherwise. + */ + bool showRules + ( + void + ); + + private: + /* constructor */ + cnd_iproute2(){}; + /* destructor */ + ~cnd_iproute2(){}; + + static cnd_iproute2* instancePtr; +}; + + +#endif /* CND_IPROUTE2_H*/ diff --git a/cnd/inc/cnd_unsol_messages.h b/cnd/inc/cnd_unsol_messages.h new file mode 100755 index 0000000..f77d7f3 --- /dev/null +++ b/cnd/inc/cnd_unsol_messages.h @@ -0,0 +1,29 @@ +/* +** Copyright 2006, The Android Open Source Project +** Copyright (c) 2009, Code Aurora Forum. All rights reserved. +** +** 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. +*/ + + {0, NULL}, //none + {CNE_RESPONSE_REG_ROLE_MSG, responseInts}, + {CNE_RESPONSE_GET_COMPATIBLE_NWS_MSG, responseInts}, + {CNE_RESPONSE_CONFIRM_NW_MSG, responseInts}, + {CNE_RESPONSE_DEREG_ROLE_MSG, responseInts}, + {CNE_REQUEST_BRING_RAT_DOWN_MSG, eventRatChange}, + {CNE_REQUEST_BRING_RAT_UP_MSG, eventRatChange}, + {CNE_NOTIFY_MORE_PREFERED_RAT_AVAIL_MSG, responseInts}, + {CNE_NOTIFY_RAT_LOST_MSG, responseInts}, + {CNE_REQUEST_START_SCAN_WLAN_MSG, responseVoid}, + {CNE_NOTIFY_INFLIGHT_STATUS_MSG, responseInts} + diff --git a/cnd/src/Android.mk b/cnd/src/Android.mk new file mode 100755 index 0000000..50a28a1 --- /dev/null +++ b/cnd/src/Android.mk @@ -0,0 +1,39 @@ +# For cnd binary +# ======================= +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +#this is needed to make sure that the path for stlport is specified before stdc++ +LOCAL_NO_DEFAULT_COMPILER_FLAGS :=true + +LOCAL_SRC_FILES:= \ + cnd.c \ + cnd_event.cpp \ + cnd_process.cpp \ + cnd_iproute2.cpp + +LOCAL_MODULE:= cnd + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libhardware_legacy \ + libcne + +LOCAL_C_INCLUDES := \ + external/connectivity/cnd/inc \ + external/connectivity/include/cne \ + external/STLport-5.2.1/stlport \ + system/core/include \ + frameworks/base/include \ + bionic/libc/arch-arm/include \ + bionic/libc/include \ + bionic/libstdc++/include \ + bionic/libc/kernel/common \ + bionic/libc/kernel/arch-arm \ + bionic/libm/include + +LOCAL_CFLAGS+= -fno-exceptions -fno-short-enums -include system/core/include/arch/linux-arm/AndroidConfig.h -DANDROID + +include $(BUILD_EXECUTABLE) diff --git a/cnd/src/cnd.c b/cnd/src/cnd.c new file mode 100755 index 0000000..333ee96 --- /dev/null +++ b/cnd/src/cnd.c @@ -0,0 +1,46 @@ +/* +** Copyright 2006, The Android Open Source Project +** Copyright (c) 2009, Code Aurora Forum. All rights reserved. +** +** 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 +#include +#include +#include +#include +#include "cutils/properties.h" + +#define LOG_TAG "CND" + +int main (int argc, char **argv) +{ + char prop_value[PROPERTY_VALUE_MAX] = {'\0'}; + int len = property_get("persist.cne.UseCne", prop_value, "FALSE"); + prop_value[len] = '\0'; + if((strcmp(prop_value, "TRUE") == 0) || + (strcmp(prop_value, "true") == 0)) + { + cnd_init(); + cnd_startEventLoop(); + while(1) + { + // sleep(UINT32_MAX) seems to return immediately on bionic + sleep(0x00ffffff); + } + } + return 0; +} + + diff --git a/cnd/src/cnd_event.cpp b/cnd/src/cnd_event.cpp new file mode 100755 index 0000000..8185d9f --- /dev/null +++ b/cnd/src/cnd_event.cpp @@ -0,0 +1,256 @@ +/* +** Copyright 2006, The Android Open Source Project +** Copyright (c) 2009, Code Aurora Forum. All rights reserved. +** +** 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. +*/ + +#define LOG_TAG "CND_EVENT" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static pthread_mutex_t listMutex; +#define MUTEX_ACQUIRE() pthread_mutex_lock(&listMutex) +#define MUTEX_RELEASE() pthread_mutex_unlock(&listMutex) +#define MUTEX_INIT() pthread_mutex_init(&listMutex, NULL) +#define MUTEX_DESTROY() pthread_mutex_destroy(&listMutex) + +extern "C" void cne_svc_init(void); + +static fd_set readFds; +static int nfds = 0; + +static struct cnd_event * watch_table[MAX_FD_EVENTS]; +static struct cnd_event pending_list; + +static void init_list(struct cnd_event * list) +{ + memset(list, 0, sizeof(struct cnd_event)); + list->next = list; + list->prev = list; + list->fd = -1; +} + +static void addToList(struct cnd_event * ev, struct cnd_event * list) +{ + ev->next = list; + ev->prev = list->prev; + ev->prev->next = ev; + list->prev = ev; + +} + +static void removeFromList(struct cnd_event * ev) +{ + + ev->next->prev = ev->prev; + ev->prev->next = ev->next; + ev->next = NULL; + ev->prev = NULL; +} + + +static void removeWatch(struct cnd_event * ev, int index) +{ + + LOGD ("removeWatch: fd=%d, index=%d", ev->fd, index); + + watch_table[index] = NULL; + ev->index = -1; + + FD_CLR(ev->fd, &readFds); + + if (ev->fd+1 == nfds) { + int n = 0; + + for (int i = 0; i < MAX_FD_EVENTS; i++) { + struct cnd_event * rev = watch_table[i]; + + if ((rev != NULL) && (rev->fd > n)) { + n = rev->fd; + } + } + nfds = n + 1; + + } +} + +static void processReadReadyEvent(fd_set * rfds, int n) +{ + + LOGD ("processReadReadyEvent: n=%d, rfds0=%ld", n, rfds->fds_bits[0]); + MUTEX_ACQUIRE(); + + for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) { + + struct cnd_event * rev = watch_table[i]; + + if (rev != NULL) + LOGD ("processReadReadyEvent: i=%d, fd=%d, rfds0=%ld", i, rev->fd, rfds->fds_bits[0]); + else + LOGD ("processReadReadyEvent: i=%d, rev is NULL", i); + + if (rev != NULL && FD_ISSET(rev->fd, rfds)) { + addToList(rev, &pending_list); + LOGD ("processReadReadyEvent: add to pendingList fd=%d", rev->fd); + if (rev->persist == 0) { + removeWatch(rev, i); + } + n--; + } + } + + MUTEX_RELEASE(); + +} + +static void firePendingEvent(void) +{ + + struct cnd_event * ev = pending_list.next; + while (ev != &pending_list) { + struct cnd_event * next = ev->next; + removeFromList(ev); + ev->func(ev->fd, ev->param); + ev = next; + } + +} + +// Initialize internal data structs +void cnd_event_init() +{ + + MUTEX_INIT(); + FD_ZERO(&readFds); + init_list(&pending_list); + memset(watch_table, 0, sizeof(watch_table)); + cne_svc_init(); +} + +// Initialize an event +void cnd_event_set(struct cnd_event * ev, int fd, int persist, cnd_event_cb func, void * param) +{ + memset(ev, 0, sizeof(struct cnd_event)); + + ev->fd = fd; + ev->index = -1; + ev->persist = persist; + ev->func = func; + ev->param = param; + + fcntl(fd, F_SETFL, O_NONBLOCK); + +} + +// Add event to watch list +void cnd_event_add(struct cnd_event * ev) +{ + + MUTEX_ACQUIRE(); + + for (int i = 0; i < MAX_FD_EVENTS; i++) { + if (watch_table[i] == NULL) { + watch_table[i] = ev; + ev->index = i; + LOGD ("cnd_event_add-before: add at i=%d for fd=%d, readFds0=%ld", i, ev->fd, readFds.fds_bits[0]); + + FD_SET(ev->fd, &readFds); + + if (ev->fd >= nfds) + nfds = ev->fd+1; + LOGD ("cnd_event_add-after: add at i=%d for fd=%d, readFds0=%ld", i, ev->fd, readFds.fds_bits[0]); + + break; + } + } + MUTEX_RELEASE(); + + +} + + +// Remove event from watch or timer list +void cnd_event_del(struct cnd_event * ev) +{ + + + LOGD ("cnd_event_del: index=%d", ev->index); + MUTEX_ACQUIRE(); + + if (ev->index < 0 || ev->index >= MAX_FD_EVENTS) { + return; + } + + removeWatch(ev, ev->index); + + MUTEX_RELEASE(); + +} + + +void cnd_dump_watch_table(void) +{ + struct cnd_event * ev; + for (int i = 0; i < MAX_FD_EVENTS; i++) { + if (watch_table[i] != NULL) { + ev = watch_table[i]; + LOGD ("cnd_dump_watch_table: at i=%d , fd=%d", i, ev->fd); + } + } + + return; +} + +void cnd_event_loop(void) +{ + int n; + fd_set rfds; + int s_fdCommand; + + LOGD ("cnd_event_loop: started, nfds=%d",nfds); + + for (;;) { + // make local copy of read fd_set + memcpy(&rfds, &readFds, sizeof(fd_set)); + + LOGD ("cnd_event_loop: waiting for select nfds=%d, rfds0=%ld", nfds, rfds.fds_bits[0]); + + n = select(nfds, &rfds, NULL, NULL, NULL); + if (n < 0) { + if (errno == EINTR) + continue; + LOGE("cnd_event_loop: select error (%d)", errno); + return; + } + + if (n == 0) + LOGD ("cnd_event_loop: select timedout"); + else if (n > 0) + LOGD ("cnd_event_loop: select ok,n=%d, rfds0=%ld",n, rfds.fds_bits[0]); + + // Check for read-ready events + processReadReadyEvent(&rfds, n); + // Fire pending event + firePendingEvent(); + } +} diff --git a/cnd/src/cnd_iproute2.cpp b/cnd/src/cnd_iproute2.cpp new file mode 100755 index 0000000..3d8ec45 --- /dev/null +++ b/cnd/src/cnd_iproute2.cpp @@ -0,0 +1,1084 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/*============================================================================ + FILE: cnd_iproute2.cpp + + OVERVIEW: This program is an interface to make the necessary calls to + iproute2 in order to set up and take down routing tables. + These calls are made indirectly over the command line by using + a call to the C++ system() function. For each routing device + visible to the kernel, CneIproute2 allows one table. Each + table contains one entry, a path to the gateway address of the + routing device. A source address or network prefix is also + required in order to instantiate a table, so that packets from + that ip address are routed through the device. + + + DEPENDENCIES: None +============================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "cnd_iproute2.h" +#include +#include +#include +#include +#include + +using namespace std; + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#undef LOG_TAG +#define LOG_TAG "CNDIPROUTE2" + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +// List of all actions supported from iproute2. Should match defintions +// defined below prefixed with ACTIONS +enum Cmd_line_actions +{ + ACTIONS_ADD_ENUM, + ACTIONS_DELETE_ENUM, + ACTIONS_FLUSH_ENUM, + ACTIONS_SHOW_ENUM +}; + +/** Stores information needed to create a routing table and a rule. This +* allows the calling class to delete that table without needing to +* keep track of any characteristics of the device other than its name. +* Assumes that there can only be 1 rule associated with any defined +* table. +*/ +class DeviceInfo +{ + private: + // Variables relating to the routing table + int32_t tableNumber; + uint8_t *deviceName; + uint8_t *gatewayAddress; + + // Variables relating to the corresponding rule. + uint8_t *sourcePrefix; + int32_t priorityNumber; + + public: + DeviceInfo + ( + uint8_t *deviceName, + int32_t tableNumber, + uint8_t *gatewayAddress, + uint8_t *sourcePrefix, + int32_t priorityNumber + ) + { + DeviceInfo::deviceName = deviceName; + DeviceInfo::tableNumber = tableNumber; + DeviceInfo::gatewayAddress = gatewayAddress; + DeviceInfo::sourcePrefix = sourcePrefix; + DeviceInfo::priorityNumber = priorityNumber; + } + + ~DeviceInfo(); + + uint8_t* getDeviceName(void) + { + return deviceName; + } + + uint8_t* getGatewayAddress(void) + { + return gatewayAddress; + } + + int32_t getPriorityNumber(void) + { + return priorityNumber; + } + + uint8_t* getSourcePrefix(void) + { + return sourcePrefix; + } + + int32_t getTableNumber(void) + { + return tableNumber; + } +}; + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ +//Set of all table numbers currently being used. Cannot contain more than +//MAX_TABLE_SIZE - MIN_TABLE_SIZE elements +set tableNumberSet; + +// Maps the name of a device to its corresponding routing characteristics +map deviceMap; + +// If a packet does not have an associated rule, it will go to the main +// routing table and be routed to the following device by default +DeviceInfo *defaultDevice; + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ +// Commands to begin the command line string +static const uint8_t *ROUTING_CMD = (uint8_t *)"ip route"; +static const uint8_t *RULE_CMD = (uint8_t *)"ip rule"; + +// List of all actions supported from iproute2. These should match values in +// above enumeration 'Cnd_line_actions' +static const uint8_t *ACTIONS_ADD_STR = (uint8_t *)"add"; +static const uint8_t *ACTIONS_DELETE_STR = (uint8_t *)"delete"; +static const uint8_t *ACTIONS_FLUSH_STR = (uint8_t *)"flush"; +static const uint8_t *ACTIONS_SHOW_STR = (uint8_t *)"show"; + +// Keywords used to refine calls to iproute2 +static const uint8_t *CMD_LINE_DEVICE_NAME = (uint8_t *)"dev"; +static const uint8_t *CMD_LINE_GATEWAY_ADDRESS = (uint8_t *)"via"; +static const uint8_t *CMD_LINE_PRIORITY_NUMBER = (uint8_t *)"priority"; +static const uint8_t *CMD_LINE_SOURCE_PREFIX = (uint8_t *)"from"; +static const uint8_t *CMD_LINE_TABLE_NUMBER = (uint8_t *)"table"; + +// Keywords that refer to specific routes or tables +static const uint8_t *ALL_TABLES = (uint8_t *)"all"; +static const uint8_t *CACHED_ENTRIES = (uint8_t *)"cache"; +static const uint8_t *DEFAULT_ADDRESS = (uint8_t *)"default"; + +// Table #1 is the first usable routing table +static const int32_t MIN_TABLE_NUMBER = 1; + +// Table #253 is the 'defined' default routing table, which should not +// be overwritten +static const int32_t MAX_TABLE_NUMBER = 252; + +// Priority number 32766 diverts packets to the main table (Table #254) +static const int32_t MAX_PRIORITY_NUMBER = 32765; + +//Max number of digits in a table number is 3 +static const int32_t MAX_DIGITS_TABLE_NUMBER = 3; + +//Max number of digits in a priority number is 5 +static const int32_t MAX_DIGITS_PRIORITY_NUMBER = 5; + +cnd_iproute2* cnd_iproute2::instancePtr = NULL; + +/*------------------------------------------------------------------------- + * Declaration for a non-member method. + *-----------------------------------------------------------------------*/ +void flushCache +( + void +); + +uint8_t* cmdLineActionEnumToString +( + Cmd_line_actions commandAction +); + +bool modifyDefaultRoute +( + uint8_t *deviceName, + Cmd_line_actions commandAction +); + +bool modifyRoutingTable +( + uint8_t *deviceName, + uint8_t *sourcePrefix, + uint8_t *gatewayAddress, + Cmd_line_actions commandAction +); + +bool modifyRule +( + DeviceInfo *currentDevice, + Cmd_line_actions commandAction +); + +bool displayAllRoutingTables +( + void +); + +bool displayRoutingTable +( + uint8_t *deviceName +); + +bool displayRules +( + void +); + +bool cmdLineCaller +( + const uint8_t* cmdLineFirstWord, + ... +); + +/*---------------------------------------------------------------------------- + * FUNCTION getInstance + + DESCRIPTION Returns a pointer to an instance of the cnd_iproute2 such + that only 1 instance can be open at a time. + + * DEPENDENCIES None + + * RETURN VALUE cnd_iproute2* + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +cnd_iproute2* cnd_iproute2::getInstance +( + void +) +{ + if(NULL == instancePtr) + { + instancePtr = new cnd_iproute2; + } + + return instancePtr; +} + +/*---------------------------------------------------------------------------- + * FUNCTION cmdLineActionEnumToString + + * DESCRIPTION Helper function to converts values of Cmd_line_actions enum + to a string. + + * DEPENDENCIES None + + * RETURN VALUE uint8_t* + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +uint8_t* cmdLineActionEnumToString +( + Cmd_line_actions commandAction +) +{ + switch(commandAction) + { + case ACTIONS_ADD_ENUM: + return (uint8_t *)ACTIONS_ADD_STR; + break; + case ACTIONS_DELETE_ENUM: + return (uint8_t *)ACTIONS_DELETE_STR; + break; + case ACTIONS_FLUSH_ENUM: + return (uint8_t *)ACTIONS_FLUSH_STR; + break; + case ACTIONS_SHOW_ENUM: + return (uint8_t *)ACTIONS_SHOW_STR; + break; + default: + LOGE("Unsupported conversion of command action to string"); + return '\0'; + } +} +/*---------------------------------------------------------------------------- + * FUNCTION flushCache + + * DESCRIPTION Flushes the cache after routing table entries are changed + + * DEPENDENCIES None + + * RETURN VALUE None + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +void flushCache +( + void +) +{ + if (!cmdLineCaller(ROUTING_CMD, + cmdLineActionEnumToString(ACTIONS_FLUSH_ENUM), + CACHED_ENTRIES)) + { + LOGW("Attempt to flush the routing cache failed."); + } +} + +/*---------------------------------------------------------------------------- + * FUNCTION modifyDefaultRoute + + * DESCRIPTION Changes the default route given the name of the device that + will be either the new or old default. The default case + occurs if a packet is sent from some source address not + associated with a defined table. When this occurs, the main + table will route these undefined source addresses to the + gateway of the defined default device. This function will + add or delete that default route in the main table. + + * DEPENDENCIES commandAction should be either ADD OR DELETE + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool modifyDefaultRoute +( + uint8_t *deviceName, + Cmd_line_actions commandAction +) +{ + if ('\0' == deviceName) + { + LOGE("A null device name was passed while changing the default table. "); + return false; + } + + // If the upcoming command line call fails, revert to last default device + DeviceInfo *lastDefaultDevice = defaultDevice; + + uint8_t *gatewayAddress; + + switch(commandAction) + { + case ACTIONS_ADD_ENUM: + { + map::iterator deviceMapIter; + deviceMapIter = deviceMap.find(deviceName); + + if (deviceMapIter == deviceMap.end()) + { + LOGE("Cannot make the nonexistant table %s the default.", + deviceName); + return false; + } + + defaultDevice = deviceMapIter->second; + break; + } + + case ACTIONS_DELETE_ENUM: + { + // The following case should only be entered if the default table is + // being deleted when no tables exist + if ('\0' == defaultDevice) + { + LOGE("Cannot delete a default table when none exists."); + return false; + } + + break; + } + + default: + { + LOGE("Unsupported command action found while changing the default table"); + return false; + } + } + + gatewayAddress = defaultDevice->getGatewayAddress(); + + if (!cmdLineCaller(ROUTING_CMD, + cmdLineActionEnumToString(commandAction), + DEFAULT_ADDRESS, + CMD_LINE_GATEWAY_ADDRESS, + gatewayAddress, + CMD_LINE_DEVICE_NAME, + defaultDevice->getDeviceName())) + { + defaultDevice = lastDefaultDevice; + return false; + } + + if (ACTIONS_DELETE_ENUM == commandAction) + { + // After a deletion, there should be default device defined + // in the main routing table + defaultDevice = '\0'; + } + + return true; +} + +/*---------------------------------------------------------------------------- + * FUNCTION modifyRoutingTable + + * DESCRIPTION Adds or deletes a routing table given the name of the device + associated with that table. This routing table has one route, + which will route all packets to some gateway address from + some inputted source address. Once the table has been + modified, modifyRoutingTable will call another function to + create or delete a rule that maps some source address' + packets to this table. + + * DEPENDENCIES commandAction should be either ADD OR DELETE + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool modifyRoutingTable +( + uint8_t *deviceName, + uint8_t *sourcePrefix, + uint8_t *gatewayAddress, + Cmd_line_actions commandAction +) +{ + if ('\0' == deviceName) + { + LOGE("A null device name was passed while modifying a routing table"); + return false; + } + + int32_t tableNumber; + int32_t priorityNumber; + + DeviceInfo *currentDevice; + map::iterator deviceMapIter; + set::iterator tableNumberSetIter; + + switch(commandAction) + { + case ACTIONS_ADD_ENUM: + { + if ('\0' == sourcePrefix) + { + LOGE("A null source prefix was passed when adding the %s table", + deviceName); + return false; + } + + if ('\0' == gatewayAddress) + { + LOGE("A null gateway address was passed when adding the %s table", + deviceName); + return false; + } + + deviceMapIter = deviceMap.find(deviceName); + + // If a call to add a routing table overwrites an existing table, the + // new source and gateway addresses will overwrite the old ones. + // However, calls to add a duplicate table, where the source and + // gateway addresses do not change, are ignored and will not be + // considered a fatal error. + if (deviceMapIter != deviceMap.end()) + { + DeviceInfo *existingDevice = deviceMapIter->second; + + if ((0 != strcmp((char *)existingDevice->getGatewayAddress(), + (char *)gatewayAddress)) || + (0 != strcmp((char *)existingDevice->getSourcePrefix(), + (char *)sourcePrefix))) + { + //Delete existing device with the same name + modifyRoutingTable(deviceName, '\0', '\0', ACTIONS_DELETE_ENUM); + + //Delete default device that will be overwritten. New default will + //be added later + if (('\0' != defaultDevice) && (defaultDevice == existingDevice)) + { + modifyDefaultRoute('\0', ACTIONS_DELETE_ENUM); + } + } + + else { + LOGW("Adding a duplicate %s table with gateway %s and source %s", + deviceName, sourcePrefix, gatewayAddress); + return true; + } + } + + // Instantiating more than 252 tables simultaneously is an error + if (MAX_TABLE_NUMBER - MIN_TABLE_NUMBER < tableNumberSet.size()) + { + LOGE("Too many tables exist to add %s. %d tables are defined", + deviceName, tableNumberSet.size()); + return false; + } + + // Locate next available table number. If the previous check passed, + // there must be a table number available + for (int32_t nextTableNumber = MIN_TABLE_NUMBER; + nextTableNumber < MAX_TABLE_NUMBER; nextTableNumber++) + { + tableNumberSetIter = tableNumberSet.find(nextTableNumber); + if (tableNumberSetIter == tableNumberSet.end()) + { + tableNumber = nextTableNumber; + } + } + + // Always map the same rule to the same table number. This allows the + // reuse of priority numbers. + priorityNumber = MAX_PRIORITY_NUMBER - tableNumber; + + currentDevice = new DeviceInfo(deviceName, + tableNumber, + gatewayAddress, + sourcePrefix, + priorityNumber); + break; + } + + case ACTIONS_DELETE_ENUM: + { + if (deviceMap.empty()) + { + LOGE("Deleting a table when no table exists."); + return false; + } + + deviceMapIter = deviceMap.find(deviceName); + + if (deviceMapIter == deviceMap.end()) + { + LOGE("Cannot delete table %s that has not been created.", deviceName); + return false; + } + + currentDevice = deviceMapIter->second; + gatewayAddress = currentDevice->getGatewayAddress(); + tableNumber = currentDevice->getTableNumber(); + break; + } + + default: + { + LOGE("Unsupported command action found while modifying a table"); + return false; + } + } + + //Convert table number int to string, null-terminating the result + char tableNumberString[MAX_DIGITS_TABLE_NUMBER+1]; + int32_t numberOfDigits = snprintf(tableNumberString, + MAX_DIGITS_TABLE_NUMBER, + "%d", + tableNumber); + tableNumberString[numberOfDigits] = '\0'; + + if (!cmdLineCaller(ROUTING_CMD, + cmdLineActionEnumToString(commandAction), + DEFAULT_ADDRESS, + CMD_LINE_GATEWAY_ADDRESS, + gatewayAddress, + CMD_LINE_DEVICE_NAME, + deviceName, + CMD_LINE_TABLE_NUMBER, + (uint8_t *)tableNumberString)) + { + return false; + } + + switch(commandAction) + { + case ACTIONS_ADD_ENUM: + { + deviceMap.insert(make_pair(deviceName, currentDevice)); + tableNumberSet.insert(tableNumber); + + // If there is no default table, the new device should be the default. + if ('\0' == defaultDevice) + { + modifyDefaultRoute(deviceName, ACTIONS_ADD_ENUM); + } + + break; + } + + case ACTIONS_DELETE_ENUM: + { + deviceMap.erase(deviceName); + tableNumberSet.erase(tableNumber); + + // If there are no more tables, then there should be no default device. + if (0 == tableNumberSet.size()) + { + modifyDefaultRoute('\0', ACTIONS_DELETE_ENUM); + } + + // If the default table has been deleted and another device is available, + // set an arbitrary new device as the new default. + else if (defaultDevice == currentDevice) + { + uint8_t *newDefaultName = deviceMap.begin()->first; + + modifyDefaultRoute('\0', ACTIONS_DELETE_ENUM); + modifyDefaultRoute(newDefaultName, ACTIONS_ADD_ENUM); + } + + break; + } + + default: + break; + } + + return modifyRule(currentDevice, commandAction); +} + +/*---------------------------------------------------------------------------- + * FUNCTION modifyRule + + * DESCRIPTION Adds or deletes a rule given the actual device object of the + table associated with that rule. Every defined routing table + requires some rule to map packets from some given source + address to that routing table. This function takes an object + so that after a routing table has been removed, the source + prefix, table number, and priority number associated with that + table can still be accessed. This allows a call to be made to + iproute2 to delete the corresponding rule. + + * DEPENDENCIES commandAction should be either ADD OR DELETE + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool modifyRule +( + DeviceInfo *currentDevice, + Cmd_line_actions commandAction +) +{ + if ('\0' == currentDevice) + { + LOGE("A null device was passed while modifying a rule"); + return false; + } + + uint8_t* deviceName = currentDevice->getDeviceName(); + map::iterator deviceMapIter; + deviceMapIter = deviceMap.find(deviceName); + + // If a rule is being added, its corresponding table should exist in the map + // of all routing tables. + if ((ACTIONS_ADD_ENUM == commandAction) && + (deviceMapIter == deviceMap.end())) + { + LOGE("Cannot %s a rule for nonexistant table %s", + cmdLineActionEnumToString(commandAction), + deviceName); + return false; + } + + int32_t tableNumber = currentDevice->getTableNumber(); + int32_t priorityNumber = currentDevice->getPriorityNumber(); + uint8_t *sourcePrefix = currentDevice->getSourcePrefix(); + + //Convert table number & priority number ints to string, null-terminating + //the results + char tableNumberString[MAX_DIGITS_TABLE_NUMBER+1]; + char priorityNumberString[MAX_DIGITS_PRIORITY_NUMBER+1]; + + int32_t numberOfDigits = snprintf(tableNumberString, + MAX_DIGITS_TABLE_NUMBER, + "%d", + tableNumber); + tableNumberString[numberOfDigits] = '\0'; + + numberOfDigits = snprintf(priorityNumberString, + MAX_DIGITS_PRIORITY_NUMBER, + "%d", + priorityNumber); + priorityNumberString[numberOfDigits] = '\0'; + + if (!cmdLineCaller(RULE_CMD, + cmdLineActionEnumToString(commandAction), + CMD_LINE_SOURCE_PREFIX, + sourcePrefix, + CMD_LINE_TABLE_NUMBER, + (uint8_t *)tableNumberString, + CMD_LINE_PRIORITY_NUMBER, + (uint8_t *)priorityNumberString)) + { + return false; + } + + return true; +} + +/*---------------------------------------------------------------------------- + * FUNCTION displayAllRoutingTables + + * DESCRIPTION Displays contents of all routing tables + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool displayAllRoutingTables +( + void +) +{ + return cmdLineCaller(ROUTING_CMD, + cmdLineActionEnumToString(ACTIONS_SHOW_ENUM), + CMD_LINE_TABLE_NUMBER, + ALL_TABLES); +} + +/*---------------------------------------------------------------------------- + * FUNCTION displayRoutingTable + + * DESCRIPTION Displays contents of the inputted routing table + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool displayRoutingTable +( + uint8_t *deviceName +) +{ + if ('\0' == deviceName) + { + LOGE("A null argument was passed while displaying table %s.", + deviceName); + return false; + } + + return cmdLineCaller(ROUTING_CMD, + cmdLineActionEnumToString(ACTIONS_SHOW_ENUM), + CMD_LINE_TABLE_NUMBER, + deviceName); +} + +/*---------------------------------------------------------------------------- + * FUNCTION displayRules + + * DESCRIPTION Displays all rules currently entered in the system + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool displayRules +( + void +) +{ + return cmdLineCaller(RULE_CMD, + cmdLineActionEnumToString(ACTIONS_SHOW_ENUM)); +} + +/*---------------------------------------------------------------------------- + * FUNCTION cmdLineCaller + + * DESCRIPTION Sends a call to iproute2 over the command line. This function + takes in a list of an arbitrary number of words, which is + parsed together into one final string. This string is sent + over the command line using the C routine 'system'. Two + readers are instantiated to monitor any standard error and + standard output messages sent out by iproute2. These messages + are then passed to the Android log. + + * DEPENDENCIES Should not be any spaces in any inputted argument + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool cmdLineCaller +( + const uint8_t* cmdLineFirstWord, + ... +) +{ + size_t byteLength = 0; + size_t memLength; + va_list cmdLineWordList; + uint8_t *nextWord; + char *cmdLineString; + + if ('\0' == cmdLineFirstWord) + { + LOGE("No actual command passed to build a command line."); + return false; + } + + //Find length of overall command line string + byteLength = strlen((char *)cmdLineFirstWord); + va_start(cmdLineWordList, cmdLineFirstWord); + + while((nextWord = va_arg(cmdLineWordList,uint8_t*)) != '\0') + { + byteLength += strlen((char *)nextWord); + } + + va_end(cmdLineWordList); + + //Allocate command line string + cmdLineString = new (nothrow) char[byteLength]; + + if (cmdLineString == '\0') + { + LOGE("Could not allocate memory to build command line string."); + return false; + } + + + memLength = strlcpy(cmdLineString, + (char *)cmdLineFirstWord, + strlen((char *)cmdLineFirstWord)*sizeof(uint8_t)); + if (memLength > strlen((char *)cmdLineFirstWord) * sizeof(uint8_t)) + { + LOGE("Failure building first word of command line string."); + delete [] cmdLineString; + return false; + } + + //Build command line string containing each inputted word. + va_start(cmdLineWordList, cmdLineFirstWord); + + while((nextWord = va_arg(cmdLineWordList,uint8_t*)) != '\0') + { + //Add white space + memLength = strlcat(cmdLineString, + " ", + sizeof(uint8_t)); + if (memLength > sizeof(uint8_t)) + { + LOGE("Failure building command line string."); + delete [] cmdLineString; + return false; + } + + //Add next word + memLength = strlcat(cmdLineString, + (char *)nextWord, + strlen((char *)nextWord) * sizeof(uint8_t)); + if (memLength > strlen((char *)nextWord) * sizeof(uint8_t)) + { + LOGE("Failure building command line string."); + delete [] cmdLineString; + return false; + } + } + + LOGI("Iproute2 has been called with: %s", cmdLineString); + + int cmdLineExitValue = system(cmdLineString); + + if (0 != cmdLineExitValue) + { + LOGE("Command line call to iproute2 failed with exitvalue %d.", + cmdLineExitValue); + delete [] cmdLineString; + return false; + } + + delete [] cmdLineString; + return true; +} + +/*---------------------------------------------------------------------------- + * FUNCTION addRoutingTable + + * DESCRIPTION Adds a routing table to the system that contains a single + default entry, a route to the gateway address of a device. + It also adds a rule to route a given source network prefix or + address to the new table. + + The parameter deviceName refers to the name of the device + whose table will be added (Such as wlan or wwan) + The parameter sourcePrefix refers to the source network prefix + or address that will be routed to the device (Such as + 37.214.21/24 or 10.156.45.1) + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool cnd_iproute2::addRoutingTable +( + uint8_t *deviceName, + uint8_t *sourcePrefix, + uint8_t *gatewayAddress +) +{ + if (!modifyRoutingTable(deviceName, + sourcePrefix, + gatewayAddress, + ACTIONS_ADD_ENUM)) + { + return false; + } + + flushCache(); + return true; +} + +/*---------------------------------------------------------------------------- + * FUNCTION changeDefaultTable + + * DESCRIPTION Changes the default device where packets are routed to. If + some source address does not match an already defined rule, + packets from that source address will be routed through the + main table to some default device. This function replaces the + default route to direct traffic to an inputted, already + defined device. A routing table associated with this device + must have been added through addRoutingTable() before it can + be the default. + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool cnd_iproute2::changeDefaultTable +( + uint8_t *deviceName +) +{ + // No need to perform function if the default device will not change + if (('\0' != defaultDevice) && + (0 == strcmp((char *)defaultDevice->getDeviceName(), + (char *)deviceName))) + { + LOGW("The new default table %s is the same as the old.", + deviceName); + return true; + } + + if (!modifyDefaultRoute('\0', ACTIONS_DELETE_ENUM)) + { + return false; + } + + if (!modifyDefaultRoute(deviceName, ACTIONS_ADD_ENUM)) + { + return false; + } + + flushCache(); + return true; +} + +/*---------------------------------------------------------------------------- + * FUNCTION deleteRoutingTable + + * DESCRIPTION Deletes a routing table from the system along with the rule + corresponding to that table. + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool cnd_iproute2::deleteRoutingTable +( + uint8_t *deviceName +) +{ + if (!modifyRoutingTable(deviceName, '\0', '\0', ACTIONS_DELETE_ENUM)) + { + return false; + } + + flushCache(); + return true; +} + +/*---------------------------------------------------------------------------- + * FUNCTION showAllRoutingTables + + * DESCRIPTION Displays the contents of all routing tables for debugging + purposes. + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool cnd_iproute2::showAllRoutingTables +( + void +) +{ + return displayAllRoutingTables(); +} + +/*---------------------------------------------------------------------------- + * FUNCTION showRoutingTable + + * DESCRIPTION Displays the contents of the routing table associated with + the inputted device name. + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool cnd_iproute2::showRoutingTable +( + uint8_t *deviceName +) +{ + return displayRoutingTable(deviceName); +} + +/*---------------------------------------------------------------------------- + * FUNCTION showRoutingTable + + * DESCRIPTION Displays the rules associated with all tables for debugging + purposes. + + * DEPENDENCIES None + + * RETURN VALUE bool - True if function is successful. False otherwise. + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +bool cnd_iproute2::showRules +( + void +) +{ + return displayRules(); +} diff --git a/cnd/src/cnd_process.cpp b/cnd/src/cnd_process.cpp new file mode 100755 index 0000000..45f687f --- /dev/null +++ b/cnd/src/cnd_process.cpp @@ -0,0 +1,1123 @@ +/* +** Copyright 2006, The Android Open Source Project +** Copyright (c) 2009, Code Aurora Forum. All rights reserved. +** +** 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. +*/ +#define LOG_TAG "CND_PROCESS" + +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + + +namespace android { + +#define SOCKET_NAME_CND "cnd" + +// match with constant in .java +#define MAX_COMMAND_BYTES (8 * 1024) + +// Basically: memset buffers that the client library +// shouldn't be using anymore in an attempt to find +// memory usage issues sooner. +#define MEMSET_FREED 1 + +#define NUM_ELEMS(a) (sizeof (a) / sizeof (a)[0]) + +/* Constants for response types */ +#define SOLICITED_RESPONSE 0 +#define UNSOLICITED_MESSAGE 1 + +typedef struct { + int commandNumber; + void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI); + int(*responseFunction) (Parcel &p, void *response, size_t responselen); +} CommandInfo; + +typedef struct { + int messageNumber; + int (*responseFunction) (Parcel &p, void *response, size_t responselen); +} UnsolMessageInfo; + +typedef struct RequestInfo { + int32_t token; //this is not CND_Token + int fd; + CommandInfo *pCI; + struct RequestInfo *p_next; + char cancelled; + char local; // responses to local commands do not go back to command process +} RequestInfo; + + +/*******************************************************************/ + +static int s_registerCalled = 0; + +static pthread_t s_tid_dispatch; + +static int s_started = 0; + +static int s_fdListen = -1; +static int s_fdCommand = -1; + +static int cnmSvcFd = -1; + +static struct cnd_event s_commands_event[MAX_FD_EVENTS]; +static struct cnd_event s_listen_event; +static int command_index = 0; + +static pthread_mutex_t s_pendingRequestsMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t s_startupMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t s_startupCond = PTHREAD_COND_INITIALIZER; + +static pthread_mutex_t s_dispatchMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t s_dispatchCond = PTHREAD_COND_INITIALIZER; + +static RequestInfo *s_pendingRequests = NULL; + +static RequestInfo *s_toDispatchHead = NULL; +static RequestInfo *s_toDispatchTail = NULL; + + +/*******************************************************************/ +static void dispatchVoid (Parcel& p, RequestInfo *pRI); +static void dispatchString (Parcel& p, RequestInfo *pRI); +static void dispatchStrings (Parcel& p, RequestInfo *pRI); +static void dispatchInts (Parcel& p, RequestInfo *pRI); +static void dispatchWlanInfo(Parcel &p, RequestInfo *pRI); +static void dispatchWlanScanResults(Parcel &p, RequestInfo *pRI); +static void dispatchRaw(Parcel& p, RequestInfo *pRI); +static int responseInts(Parcel &p, void *response, size_t responselen); +static int responseStrings(Parcel &p, void *response, size_t responselen); +static int responseString(Parcel &p, void *response, size_t responselen); +static int responseVoid(Parcel &p, void *response, size_t responselen); +static int responseRaw(Parcel &p, void *response, size_t responselen); +static int responseStartTrans(Parcel &p, void *response, size_t responselen); +static int sendResponseRaw (const void *data, size_t dataSize, int fdCommand); +static int sendResponse (Parcel &p, int fd); +static int eventRatChange (Parcel &p, void *response, size_t responselen); +static char *strdupReadString(Parcel &p); +static void writeStringToParcel(Parcel &p, const char *s); +static void memsetString (char *s); +static int writeData(int fd, const void *buffer, size_t len); +static void unsolicitedMessage(int unsolMessage, void *data, size_t datalen, int fd); +static void processCommand (int command, void *data, size_t datalen, CND_Token t); +static int processCommandBuffer(void *buffer, size_t buflen, int fd); +static void invalidCommandBlock (RequestInfo *pRI); +static void onCommandsSocketClosed(void); +static void processCommandsCallback(int fd, void *param); +static void listenCallback (int fd, void *param); +static void *eventLoop(void *param); +static int checkAndDequeueRequestInfo(struct RequestInfo *pRI); +static void cnd_commandComplete(CND_Token t, CND_Errno e, void *response, size_t responselen); + +extern "C" const char * requestToString(int request); +extern "C" void cne_processCommand (int command, void *data, size_t datalen); +extern "C" void cne_regMessageCb(cne_messageCbType cbFn); + +/** Index == commandNumber */ +static CommandInfo s_commands[] = { +#include "cnd_commands.h" +}; + +static UnsolMessageInfo s_unsolMessages[] = { +#include "cnd_unsol_messages.h" +}; + +#define TEMP_BUFFER_SIZE (80) + + +void cnd_sendUnsolicitedMsg(int targetFd, int msgType, int dataLen, void *data) +{ + int fd; + + if (targetFd == 0) // TODO find the correct fd, who keeps track of it? + fd = cnmSvcFd; + else + fd = targetFd; + + LOGD ("cnd_sendUnsolicitedMsg: Fd=%d, msgType=%d, datalen=%d\n", + targetFd, msgType, dataLen); + + unsolicitedMessage(msgType, data, dataLen, fd); + + +} + +static void +processCommand (int command, void *data, size_t datalen, CND_Token t) +{ + + LOGD ("processCommand: command=%d, datalen=%d", command, datalen); + + /* Special handling for iproute2 command to setup iproute2 table */ + if (command == CNE_REQUEST_CONFIG_IPROUTE2_CMD) + { + char **pStrings; + *pStrings = (char *)data; + LOGD ("processCommand: str1=%s, str2=%s", pStrings[0], pStrings[1]); + // Call iproute2 API + + } + cne_processCommand(command, data, datalen); + cnd_commandComplete(t, CND_E_SUCCESS, NULL, 0); +} + +static char * +strdupReadString(Parcel &p) +{ + size_t stringlen; + const char16_t *s16; + + s16 = p.readString16Inplace(&stringlen); + + return strndup16to8(s16, stringlen); +} + +static void writeStringToParcel(Parcel &p, const char *s) +{ + char16_t *s16; + size_t s16_len; + s16 = strdup8to16(s, &s16_len); + p.writeString16(s16, s16_len); + free(s16); +} + + +static void +memsetString (char *s) +{ + if (s != NULL) { + memset (s, 0, strlen(s)); + } +} + + +static void +invalidCommandBlock (RequestInfo *pRI) +{ + //LOGE("invalid command block for token %d request %s", + // pRI->token, requestToString(pRI->pCI->commandNumber)); +} + +/** Callee expects NULL */ +static void +dispatchVoid (Parcel& p, RequestInfo *pRI) +{ + + processCommand(pRI->pCI->commandNumber, NULL, 0, pRI); +} + +/** Callee expects const char * */ +static void +dispatchString (Parcel& p, RequestInfo *pRI) +{ + status_t status; + size_t datalen; + size_t stringlen; + char *string8 = NULL; + + string8 = strdupReadString(p); + + processCommand(pRI->pCI->commandNumber, string8, + sizeof(char *), pRI); + +#ifdef MEMSET_FREED + memsetString(string8); +#endif + + free(string8); + return; +} + +/** Callee expects const char ** */ +static void +dispatchStrings (Parcel &p, RequestInfo *pRI) +{ + int32_t countStrings; + status_t status; + size_t datalen; + char **pStrings; + + status = p.readInt32 (&countStrings); + + if (status != NO_ERROR) { + goto invalid; + } + + + if (countStrings == 0) { + // just some non-null pointer + pStrings = (char **)alloca(sizeof(char *)); + datalen = 0; + } else if (((int)countStrings) == -1) { + pStrings = NULL; + datalen = 0; + } else { + datalen = sizeof(char *) * countStrings; + + pStrings = (char **)alloca(datalen); + + for (int i = 0 ; i < countStrings ; i++) { + pStrings[i] = strdupReadString(p); + + } + } + + processCommand(pRI->pCI->commandNumber, pStrings, datalen, pRI); + + if (pStrings != NULL) { + for (int i = 0 ; i < countStrings ; i++) { +#ifdef MEMSET_FREED + memsetString (pStrings[i]); +#endif + free(pStrings[i]); + } + +#ifdef MEMSET_FREED + memset(pStrings, 0, datalen); +#endif + } + + return; +invalid: + invalidCommandBlock(pRI); + return; +} + +/** Callee expects const int * */ +static void +dispatchInts (Parcel &p, RequestInfo *pRI) +{ + int32_t count; + status_t status; + size_t datalen; + int *pInts; + + status = p.readInt32 (&count); + + LOGD ("dispatchInts: status=%d, count=%d", status, count); + + if (status != NO_ERROR || count == 0) { + goto invalid; + } + + datalen = sizeof(int) * count; + pInts = (int *)alloca(datalen); + + + for (int i = 0 ; i < count ; i++) { + int32_t t; + + status = p.readInt32(&t); + pInts[i] = (int)t; + + + if (status != NO_ERROR) { + goto invalid; + } + } + + processCommand(pRI->pCI->commandNumber, const_cast(pInts), + datalen, pRI); + +#ifdef MEMSET_FREED + memset(pInts, 0, datalen); +#endif + + return; +invalid: + invalidCommandBlock(pRI); + return; +} + + +static void +dispatchWlanInfo(Parcel &p, RequestInfo *pRI) +{ + int32_t t; + status_t status; + CneWlanInfoType args; + + memset(&args, 0, sizeof(args)); + + status = p.readInt32 (&t); + args.status = (int)t; + status = p.readInt32 (&t); + args.rssi = (int)t; + args.ssid = strdupReadString(p); + + LOGD ("dispatchWlanInfo: status=%ld, rssi=%ld, ssid=%s", + args.status, args.rssi, args.ssid); + + + processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI); + + return; +} + +static void +dispatchWlanScanResults(Parcel &p, RequestInfo *pRI) +{ + int32_t t; + status_t status; + CneWlanScanResultsType args; + int32_t numItems; + + status = p.readInt32 (&t); + //args = (CneWlanScanResultsType *)malloc(sizeof(CneWlanScanResultsType)*numItems); + args.numItems = (int)t; + int max = (t < CNE_MAX_SCANLIST_SIZE)? t:CNE_MAX_SCANLIST_SIZE; + + for (int i = 0; i < max; i++) + { + //args->numItems = numItems; + status = p.readInt32 (&t); + args.scanList[i].level = (int)t; + status = p.readInt32 (&t); + args.scanList[i].frequency = (int)t; + args.scanList[i].ssid = strdupReadString(p); + args.scanList[i].bssid = strdupReadString(p); + args.scanList[i].capabilities = strdupReadString(p); + + LOGD ("dispatchWlanScanResults: max=%d, level=%ld, freq=%ld, ssid=%s, bssid=%s, cap=%s", + args.numItems, args.scanList[i].level, args.scanList[i].frequency, + args.scanList[i].ssid, args.scanList[i].bssid, args.scanList[i].capabilities); + + } + + + processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI); + + return; +} + +static void +dispatchRaw(Parcel &p, RequestInfo *pRI) +{ + int32_t len; + status_t status; + const void *data; + + status = p.readInt32(&len); + + if (status != NO_ERROR) { + goto invalid; + } + + // The java code writes -1 for null arrays + if (((int)len) == -1) { + data = NULL; + len = 0; + } + + data = p.readInplace(len); + + processCommand(pRI->pCI->commandNumber, const_cast(data), len, pRI); + + return; +invalid: + invalidCommandBlock(pRI); + return; +} + +static int +writeData(int fd, const void *buffer, size_t len) +{ + size_t writeOffset = 0; + const uint8_t *toWrite; + + toWrite = (const uint8_t *)buffer; + + LOGD ("writeData: len=%d",len); + while (writeOffset < len) { + ssize_t written; + do { + written = write (fd, toWrite + writeOffset, + len - writeOffset); + } while (written < 0 && errno == EINTR); + + if (written >= 0) { + writeOffset += written; + } else { // written < 0 + LOGE ("writeData: unexpected error on write errno:%d", errno); + close(fd); + return -1; + } + } + + return 0; +} + +static int +sendResponseRaw (const void *data, size_t dataSize, int fdCommand) +{ + int fd = fdCommand; + int ret; + uint32_t header; + + + LOGD ("sendResponseRaw: fdCommand=%d", fdCommand); + if (fdCommand < 0) { + return -1; + } + + if (dataSize > MAX_COMMAND_BYTES) { + LOGE("sendResponseRaw: packet larger than %u (%u)", + MAX_COMMAND_BYTES, (unsigned int )dataSize); + + return -1; + } + + pthread_mutex_lock(&s_writeMutex); + + header = htonl(dataSize); + + ret = writeData(fd, (void *)&header, sizeof(header)); + + if (ret < 0) { + return ret; + } + + writeData(fd, data, dataSize); + + if (ret < 0) { + pthread_mutex_unlock(&s_writeMutex); + return ret; + } + + pthread_mutex_unlock(&s_writeMutex); + + return 0; +} + +static int +sendResponse (Parcel &p, int fd) +{ + + return sendResponseRaw(p.data(), p.dataSize(), fd); +} + +static int +responseStartTrans(Parcel &p, void *response, size_t responselen) +{ + int numInts; + + + LOGD ("responseStartTrans: len=%d",responselen); + + if (response == NULL && responselen != 0) { + LOGE("invalid response: NULL"); + return CND_E_INVALID_RESPONSE; + } + + + int *p_int = (int *) response; + //bool tmp = p_int[1]; + char *p_char = (char *)response; + + p.writeInt32(p_int[0]); + //writeStringToParcel(p, (const char *)p_char[4]); + + + //p.write(&tmp, 1); + + LOGD ("responseStartTrans: int=%d, bool=%d",p_int[0], p_char[4]); + + return 0; +} + +/** response is an int* pointing to an array of ints*/ + +static int +responseInts(Parcel &p, void *response, size_t responselen) +{ + int numInts; + + + LOGD ("responseInts: len=%d",responselen); + + if (response == NULL && responselen != 0) { + LOGE("invalid response: NULL"); + return CND_E_INVALID_RESPONSE; + } + if (responselen % sizeof(int) != 0) { + LOGE("invalid response length %d expected multiple of %d\n", + (int)responselen, (int)sizeof(int)); + return CND_E_INVALID_RESPONSE; + } + + int *p_int = (int *) response; + + numInts = responselen / sizeof(int *); + p.writeInt32 (numInts); + + /* each int*/ + + for (int i = 0 ; i < numInts ; i++) { + + p.writeInt32(p_int[i]); + } + + + + return 0; +} + +/** response is a char **, pointing to an array of char *'s */ +static int responseStrings(Parcel &p, void *response, size_t responselen) +{ + int numStrings; + + if (response == NULL && responselen != 0) { + LOGE("invalid response: NULL"); + return CND_E_INVALID_RESPONSE; + } + if (responselen % sizeof(char *) != 0) { + LOGE("invalid response length %d expected multiple of %d\n", + (int)responselen, (int)sizeof(char *)); + return CND_E_INVALID_RESPONSE; + } + + if (response == NULL) { + p.writeInt32 (0); + } else { + char **p_cur = (char **) response; + + numStrings = responselen / sizeof(char *); + p.writeInt32 (numStrings); + + /* each string*/ + + for (int i = 0 ; i < numStrings ; i++) { + + writeStringToParcel (p, p_cur[i]); + } + + + } + return 0; +} + + +/** + * NULL strings are accepted + * FIXME currently ignores responselen + */ +static int responseString(Parcel &p, void *response, size_t responselen) +{ + + LOGD ("responseString called"); + /* one string only */ + writeStringToParcel(p, (const char *)response); + + return 0; +} + +static int responseVoid(Parcel &p, void *response, size_t responselen) +{ + return 0; +} + +static int responseRaw(Parcel &p, void *response, size_t responselen) +{ + if (response == NULL && responselen != 0) { + LOGE("invalid response: NULL with responselen != 0"); + return CND_E_INVALID_RESPONSE; + } + + // The java code reads -1 size as null byte array + if (response == NULL) { + p.writeInt32(-1); + } else { + p.writeInt32(responselen); + p.write(response, responselen); + } + + return 0; +} + +static int eventRatChange(Parcel &p, void *response, size_t responselen) +{ + if (response == NULL && responselen != 0) + { + LOGE("invalid response: NULL"); + return CND_E_INVALID_RESPONSE; + } + + CneRatInfoType *p_cur = ((CneRatInfoType *) response); + p.writeInt32((int)p_cur->rat); + + /* if ((p_cur->rat == CNE_RAT_WLAN_HOME) || + (p_cur->rat == CNE_RAT_WLAN_ENTERPRISE) || + (p_cur->rat == CNE_RAT_WLAN_OPERATOR) || + (p_cur->rat == CNE_RAT_WLAN_OTHER) || + (p_cur->rat == CNE_RAT_WLAN_ANY)) + { + writeStringToParcel (p, p_cur->wlan.ssid); + } + */ + if (p_cur->rat == CNE_RAT_WLAN) + { + writeStringToParcel (p, p_cur->wlan.ssid); + } + return 0; +} + +static int +checkAndDequeueRequestInfo(struct RequestInfo *pRI) +{ + int ret = 0; + + if (pRI == NULL) { + return 0; + } + + pthread_mutex_lock(&s_pendingRequestsMutex); + + for(RequestInfo **ppCur = &s_pendingRequests + ; *ppCur != NULL + ; ppCur = &((*ppCur)->p_next) + ) { + if (pRI == *ppCur) { + ret = 1; + + *ppCur = (*ppCur)->p_next; + break; + } + } + + pthread_mutex_unlock(&s_pendingRequestsMutex); + + return ret; +} + +static void onCommandsSocketClosed() +{ + int ret; + RequestInfo *p_cur; + + /* mark pending requests as "cancelled" so we dont report responses */ + + ret = pthread_mutex_lock(&s_pendingRequestsMutex); + assert (ret == 0); + + p_cur = s_pendingRequests; + + for (p_cur = s_pendingRequests + ; p_cur != NULL + ; p_cur = p_cur->p_next + ) { + p_cur->cancelled = 1; + } + + ret = pthread_mutex_unlock(&s_pendingRequestsMutex); + assert (ret == 0); +} + +static void unsolicitedMessage(int unsolMessage, void *data, size_t datalen, int fd) +{ + int unsolMessageIndex; + int ret; + + if (s_registerCalled == 0) { + // Ignore RIL_onUnsolicitedResponse before cnd_int + LOGW("unsolicitedMessage called before cnd_init"); + return; + } + + Parcel p; + + p.writeInt32 (UNSOLICITED_MESSAGE); + p.writeInt32 (unsolMessage); + + ret = s_unsolMessages[unsolMessage] + .responseFunction(p, data, datalen); + + if (ret != 0) { + // Problem with the response. Don't continue; + LOGE("unsolicitedMessage: problem with response"); + return; + } + + LOGD ("unsolicitedMessage: sending Response"); + ret = sendResponse(p, fd); + + return; + +} + +static int +processCommandBuffer(void *buffer, size_t buflen, int fd) +{ + Parcel p; + status_t status; + int32_t request; + int32_t token; + RequestInfo *pRI; + int ret; + + p.setData((uint8_t *) buffer, buflen); + + // status checked at end + status = p.readInt32(&request); + status = p.readInt32 (&token); + + LOGD ("processCommandBuffer: request=%d, token=%d, fd=%d", request, token, fd); + if (status != NO_ERROR) { + LOGE("invalid request block"); + return 0; + } + + if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) { + LOGE("unsupported request code %d token %d", request, token); + // TBD: this should return a response + return 0; + } + + + pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo)); + + pRI->token = token; + pRI->fd = fd; + pRI->pCI = &(s_commands[request]); + + ret = pthread_mutex_lock(&s_pendingRequestsMutex); + assert (ret == 0); + + pRI->p_next = s_pendingRequests; + s_pendingRequests = pRI; + + ret = pthread_mutex_unlock(&s_pendingRequestsMutex); + assert (ret == 0); + + pRI->pCI->dispatchFunction(p, pRI); + + return 0; +} + +static void processCommandsCallback(int fd, void *param) +{ + RecordStream *p_rs; + void *p_record; + size_t recordlen; + int ret; + + LOGD ("processCommandsCallback: fd=%d, s_fdCommand=%d", fd, s_fdCommand); + + p_rs = (RecordStream *)param; + + + for (;;) { + /* loop until EAGAIN/EINTR, end of stream, or other error */ + ret = record_stream_get_next(p_rs, &p_record, &recordlen); + + LOGD ("processCommandsCallback: len=%d, ret=%d", recordlen, ret); + if (ret == 0 && p_record == NULL) { + LOGD ("processCommandsCallback: end of stream"); + /* end-of-stream */ + break; + } else if (ret < 0) { + break; + } else if (ret == 0) { /* && p_record != NULL */ + processCommandBuffer(p_record, recordlen, fd); + + } + } + + //LOGD ("processCommandsCallback: errno=%d, ret=%d", errno, ret); + if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) { + /* fatal error or end-of-stream */ + if (ret != 0) { + LOGE("error on reading command socket errno:%d\n", errno); + } else { + LOGW("EOS. Closing command socket."); + } + + LOGD ("processCommandsCallback: Closing"); + close(s_fdCommand); + s_fdCommand = -1; + + // cnd_event_del(&s_commands_event); // TODO - need to clean up properly + + command_index = 0; + + record_stream_free(p_rs); + + /* start listening for new connections again */ + cnd_event_add(&s_listen_event); + + onCommandsSocketClosed(); + } + +} + +static void listenCallback (int fd, void *param) +{ + int ret; + int err; + int is_cnm_svc_socket; + RecordStream *p_rs; + int i; + char tmpBuf[10]; + int32_t pid, pid2, pid3, pid4; + + struct sockaddr_un peeraddr; + socklen_t socklen = sizeof (peeraddr); + + struct ucred creds; + socklen_t szCreds = sizeof(creds); + + + struct passwd *pwd = NULL; + + assert (s_fdCommand < 0); + assert (fd == s_fdListen); + + LOGD ("listenCallback: called"); + + + s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen); + + + if (s_fdCommand < 0 ) { + LOGE("Error on accept() errno:%d", errno); + /* start listening for new connections again */ + cnd_event_add(&s_listen_event); + return; + } + + errno = 0; + + err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); + + cnmSvcFd = s_fdCommand; // save command descriptor to be used for communication + + ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK); + + if (ret < 0) { + LOGE ("Error setting O_NONBLOCK errno = %d", errno); + } + + LOGI("listenCallback: accept new connection, fd=%d", s_fdCommand); + + p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES); + + + // note: persistent = 1, not removed from table + if (command_index >= MAX_FD_EVENTS) + { + LOGE ("Error: exceeding number of supported connection"); + return; + } + cnd_event_set (&s_commands_event[command_index], s_fdCommand, 1, processCommandsCallback, p_rs); + + cnd_event_add (&s_commands_event[command_index]); + + command_index++; + + return; + +} + + +static void * +eventLoop(void *param) +{ + int ret; + int filedes[2]; + + LOGD ("eventLoop: s_started=%d", s_started); + + pthread_mutex_lock(&s_startupMutex); + + s_started = 1; + pthread_cond_broadcast(&s_startupCond); + + pthread_mutex_unlock(&s_startupMutex); + + cnd_event_loop(); + + + return NULL; +} + +extern "C" void +cnd_startEventLoop(void) +{ + int ret; + pthread_attr_t attr; + + /* spin up eventLoop thread and wait for it to get started */ + s_started = 0; + pthread_mutex_lock(&s_startupMutex); + + pthread_attr_init (&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL); + + + while (s_started == 0) { + pthread_cond_wait(&s_startupCond, &s_startupMutex); + } + + + pthread_mutex_unlock(&s_startupMutex); + + if (ret < 0) { + LOGE("Failed to create dispatch thread errno:%d", errno); + return; + } +} + +extern "C" void +cnd_init (void) +{ + int ret; + + if (s_registerCalled > 0) { + LOGE("cnd_init has been called more than once. " + "Subsequent call ignored"); + return; + } + + s_registerCalled = 1; + + cnd_event_init(); + + cne_regMessageCb(cnd_sendUnsolicitedMsg); + + + s_fdListen = android_get_control_socket(SOCKET_NAME_CND); + if (s_fdListen < 0) { + LOGE("Failed to get socket '" SOCKET_NAME_CND "'"); + exit(-1); + } + + ret = listen(s_fdListen, 4); + + if (ret < 0) { + LOGE("Failed to listen on control socket '%d': %s", + s_fdListen, strerror(errno)); + exit(-1); + } + + + LOGD ("cnd_init: adding listenCallback event, fd=%d",s_fdListen); + + /* note: non-persistent to accept only one connection at a time */ + //cnd_event_set (&s_listen_event, s_fdListen, 0, listenCallback, NULL); + + // persistent to accept multiple connections at same time + cnd_event_set (&s_listen_event, s_fdListen, 1, listenCallback, NULL); + + cnd_event_add (&s_listen_event); + + +} + + +//extern "C" void - TBD -may want to change this function to extern "C" and +// be called from CneCet where Cne components (SRM/SPM/CDE) may send the +// response to Cne java +static void +cnd_commandComplete(CND_Token t, CND_Errno e, void *response, size_t responselen) +{ + RequestInfo *pRI; + int ret; + size_t errorOffset; + + pRI = (RequestInfo *)t; + + LOGD ("cnd_commandComplete: started"); + + if (!checkAndDequeueRequestInfo(pRI)) { + LOGE ("cnd_commandComplete: invalid CND_Token"); + return; + } + + if (pRI->local > 0) { + goto done; + } + + + if (pRI->cancelled == 0) { + Parcel p; + + p.writeInt32 (SOLICITED_RESPONSE); + p.writeInt32 (pRI->token); + errorOffset = p.dataPosition(); + + p.writeInt32 (e); + + + if (e == CND_E_SUCCESS) { + /* process response on success */ + ret = pRI->pCI->responseFunction(p, response, responselen); + LOGD ("cnd_commandComplete: ret = %d", ret); + /* if an error occurred, rewind and mark it */ + if (ret != 0) { + p.setDataPosition(errorOffset); + p.writeInt32 (ret); + } + } else { + LOGE ("cnd_commandComplete: Error"); + } + + if (pRI->fd < 0) { + LOGE ("cnd_commandComplete: Command channel closed"); + } + LOGD ("cnd_commandComplete: sending Response"); + sendResponse(p, pRI->fd); + } + +done: + free(pRI); +} + +} /* namespace android */ + + diff --git a/include/cne/cne_svc.h b/include/cne/cne_svc.h new file mode 100755 index 0000000..6093d35 --- /dev/null +++ b/include/cne/cne_svc.h @@ -0,0 +1,492 @@ +#ifndef CNE_SVC_H +#define CNE_SVC_H + +/**---------------------------------------------------------------------------- + @file cne_svc.h + + This file provides the CNE interface/Service for the clients. + It provides the info about all the commands that CNE can handle + and all the events that it can send to the clients. + +-----------------------------------------------------------------------------*/ + +/**---------------------------------------------------------------------------- + @mainpage Connectivity Engine Interface. + This documentation defines the interface for the Connectivity Engine(CNE). + + Connectivity Engine provides differenct services for its clients. + + Given the role the client wants to play, it will suggest the best network + that it can use for the best user experience. + + The suggestion are based of carrier profiles and user requirments. + + Clients can also specify its QOS requirments. + + Curently in this release clients can specify only band width requirements. + + Clients will get notified on loss of connectivity on their current rat. + + Clients can get notified if a better rat is availble based of its + requirments. + +-----------------------------------------------------------------------------*/ + +/*============================================================================= + Copyright (c) 2009 QUALCOMM Incorporated. + All Rights Reserved. + Qualcomm Confidential and Proprietary +============================================================================*/ + + + +/*============================================================================= + EDIT HISTORY FOR MODULE + + $Header: //depot/asic/sandbox/projects/cne/common/extern/inc/cne_svc.h#9 $ + $DateTime: 2009/12/03 19:27:03 $ + $Author: chinht $ + $Change: 1102974 $ + + when who what, where, why + ---------- --- ------------------------------------------------------- + 2009-07-15 ysk First revision. + +============================================================================*/ + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#ifndef TRUE +/** Boolean true value. */ + #define TRUE 1 +#endif /* TRUE */ + +#ifndef FALSE +/** Boolean false value. */ + #define FALSE 0 +#endif /* FALSE */ + +#ifndef NULL +/** NULL */ + #define NULL 0 +#endif /* NULL */ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +#define CNE_MAX_SSID_LEN 32 +#define CNE_MAX_SCANLIST_SIZE 20 + +/** + This is a type for representing the Requests, Notifications that could be + sent to the CNE. + */ +typedef enum +{ + CNE_REQUEST_INIT_CMD=1, + /**< Command to initialise the internal CNE modules.*/ + CNE_REQUEST_REG_ROLE_CMD, + /**< Command for registering a role that the clients wants to play. */ + CNE_REQUEST_GET_COMPATIBLE_NWS_CMD, + /**< Command to request a list of Nws for a registered role. */ + CNE_REQUEST_CONFIRM_NW_CMD, + /**< Command to confirm whether the given networks list is ok. */ + CNE_REQUEST_DEREG_ROLE_CMD, + /**< Command to deregister the role, once the client is done with it. */ + CNE_REQUEST_REG_NOTIFICATIONS_CMD, + /**< Command to register a notifications call back, if the client does + does not want to get notified via the default mechanism for that + platform + */ + CNE_REQUEST_UPDATE_BATTERY_INFO_CMD, + CNE_REQUEST_UPDATE_WLAN_INFO_CMD, + CNE_REQUEST_UPDATE_WWAN_INFO_CMD, + CNE_NOTIFY_RAT_CONNECT_STATUS_CMD, + CNE_NOTIFY_DEFAULT_NW_PREF_CMD, + /**< Command to notify CNE about the uppper layer default nw preference. */ + CNE_REQUEST_UPDATE_WLAN_SCAN_RESULTS_CMD, + + CNE_NOTIFY_SENSOR_EVENT_CMD, + CNE_REQUEST_CONFIG_IPROUTE2_CMD + + /* Add other commands here, note these should match with the ones in the + * java layer. + */ + +} cne_cmd_enum_type; + +/** + This is a type for representing the expected events/responses, requests that + the CNE can send to the clients and the upperlayer connectionManager. + */ +typedef enum +{ + + CNE_RESPONSE_REG_ROLE_MSG = 1, + /**< Response for the register role command. */ + CNE_RESPONSE_GET_COMPATIBLE_NWS_MSG, + /**< Response for the get compatible nws command. */ + CNE_RESPONSE_CONFIRM_NW_MSG, + /**< Response for the confirm Nw command. */ + CNE_RESPONSE_DEREG_ROLE_MSG, + /**< Response for the deregister role command. */ + CNE_REQUEST_BRING_RAT_DOWN_MSG, + CNE_REQUEST_BRING_RAT_UP_MSG, + CNE_NOTIFY_MORE_PREFERED_RAT_AVAIL_MSG, + /**< Notifications sent to the registered clients about a more prefered NW + availability. + */ + CNE_NOTIFY_RAT_LOST_MSG, + /**< Notification sent to clients when the RAT they are using is lost.*/ + CNE_REQUEST_START_SCAN_WLAN_MSG, + CNE_NOTIFY_INFLIGHT_STATUS_MSG + + +} cne_msg_enum_type; + +/** Unsigned 32 bit value */ +typedef unsigned long int uint32; +/** Unsigned 16 bit value */ +typedef unsigned short uint16; +/** Unsigned 8 bit value */ +typedef unsigned char uint8; +/** Unsigned 8 bit value */ +typedef unsigned char byte; + +/** boolean value can be TRUE or FALSE */ +typedef unsigned char boolean; + +/** Signed 32 bit value */ +typedef signed long int int32; +/** Signed 16 bit value */ +typedef signed short int16; +/** Signed 8 bit value */ +typedef signed char int8; + + +typedef enum // correspond to network State defined in NetworkInfo.java +{ + CNE_NETWORK_STATE_CONNECTING = 0, + CNE_NETWORK_STATE_CONNECTED, + CNE_NETWORK_SUSPENDED, + CNE_NETWORK_DISCONNECTING, + CNE_NETWORK_DISCONNECTED, + CNE_NETWORK_UNKNOWN + +} cne_network_state_enum_type; + + +/** Role Id Type. */ +typedef int32 cne_role_id_type; +/** Registration Id Type. */ +typedef int32 cne_reg_id_type; +/** BandWidth type */ +typedef uint32 cne_link_bw_type; + +/** + A call back funtion type that the clients would register with CNE if they + do not want to be notified via the default mechanisim used for that platform. + */ +typedef void (*cne_event_notif_cb_type) +( + cne_msg_enum_type event, + void *event_data_ptr, + void *cb_data_ptr +); + +/** +* A call back funtion type that cnd register with CNE to be +* called by CNE when it wants to send unsolicited message. + */ +typedef void (*cne_messageCbType) +( + int targetFd, + int msgType, + int dataLen, + void *data +); + +/** + This is a type representing the list of possible RATs + */ +typedef enum +{ + CNE_RAT_MIN = 0, //For tagging only + CNE_RAT_WWAN = CNE_RAT_MIN, + CNE_RAT_WLAN, + /* any new rats should be added here */ + CNE_RAT_ANY, + /**< Any of the above RATs */ + CNE_RAT_NONE, + /**< None of the abvoe RATs */ + CNE_RAT_MAX, //For tagging only + /** @internal */ + CNE_RAT_INVALID = CNE_RAT_MAX, + /**< INVALID RAT */ + +}cne_rat_type; + +/** + This is a type representing the list of possible subRATs + */ +typedef enum +{ + + CNE_NET_SUBTYPE_UNKNOWN = 0, + /* Sub type GPRS */ + CNE_NET_SUBTYPE_GPRS, + /* Sub type EDGE */ + CNE_NET_SUBTYPE_EDGE, + /* Sub type UMTS */ + CNE_NET_SUBTYPE_UMTS, + /* Sub type CDMA IS-95 */ + CNE_NET_SUBTYPE_CDMA, + /* Sub type EVDO Rev 0 */ + CNE_NET_SUBTYPE_EVDO_0, + /* Sub type EVDO Rev A */ + CNE_NET_SUBTYPE_EVDO_A, + /* Sub type 1x RTT */ + CNE_NET_SUBTYPE_1xRTT, + /* Sub type HSDPA */ + CNE_NET_SUBTYPE_HSDPA, + /* Sub type HSUPA */ + CNE_NET_SUBTYPE_HSUPA, + /* Sub type HSPA */ + CNE_NET_SUBTYPE_HSPA, + /* Sub type 802.11 B */ + CNE_NET_SUBTYPE_WLAN_B, + /* Sub type 802.11 G */ + CNE_NET_SUBTYPE_WLAN_G + +}cne_rat_subtype; + + +/* cmd handlers will pass the cmd data as raw bytes. + * the bytes specified below are for a 32 bit machine + */ +/** @note + BooleanNote: the daemon will receive the boolean as a 4 byte integer + cne may treat it as a 1 byte internally + */ +/** + Command data structure to be passed for the CNE_REQUEST_REG_ROLE_CMD + */ +typedef struct +{ + cne_role_id_type role_id; + /**< role Id 4 bytes */ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + cne_link_bw_type fwd_link_bw; + /**< forward link band width 4 bytes */ + cne_link_bw_type rev_link_bw; + /**< reverse link band width 4 bytes */ +} cne_reg_role_cmd_args_type; + +/** + Command data structure to be passed for the CNE_REQUEST_DEREG_ROLE_CMD + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ +} cne_dereg_role_cmd_args_type; + +/** + Command data structure to be passed for the CNE_REQUEST_GET_COMPATIBLE_NWS_CMD + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ +} cne_get_compatible_nws_cmd_args_type; + +/** + Command data structure to be passed for the CNE_REQUEST_REG_NOTIFICATIONS_CMD + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + cne_event_notif_cb_type cb_fn_ptr; + /**< notification call back function pointer 4 bytes */ + void* cb_data_ptr; + /**< call back data pointer 4 bytes */ +} cne_reg_notifs_cmd_args_type; + +/** + Command data structure to be passed for the CNE_REQUEST_CONFIRM_NW_CMD + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + cne_rat_type rat; + /**< rat to confirmed 4 bytes */ + boolean is_rat_ok; + /**< was the rat given ok TRUE if satisfied else FALSE 1 byte see BooleanNote + */ + boolean is_notif_if_better_rat_avail; + /**< TRUE if notifications be sent on better rat availability 1 bye + see BooleanNote + */ + cne_rat_type new_rat; + /**< if not satisfied with the given rat what is the new rat that you would + like. 4 bytes + */ +} cne_confirm_nw_cmd_args_type; + + + +/** + Response info structure returned for the response CNE_RESPONSE_REG_ROLE_MSG + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + boolean is_success; + /**< TRUE if the request was successful. 1 byte see BooleanNote */ +} cne_reg_role_rsp_evt_data_type; + + +/** + Response info structure returned for the response CNE_RESPONSE_GET_COMPATIBLE_NWS_MSG + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + boolean is_success; + /**< TRUE if the request was successful. 1 byte see BooleanNote */ + /* if success send the rat info */ + cne_rat_type best_rat; + /**< this is the best rat for this registration/role. 4 bytes */ + /* to do other ratInfo */ + cne_rat_type rat_pref_order[CNE_RAT_MAX]; + /**< Other Compatible RATs. CNE_RAT_MAX*4 bytes */ +} cne_get_compatible_nws_evt_rsp_data_type; + + +/** + Response info structure returned for the response CNE_RESPONSE_CONFIRM_NW_MSG + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + boolean is_success; + /**< TRUE if the request was successful. 1 byte see BooleanNote */ +} cne_confirm_nw_evt_rsp_data_type; + + +/** + Response info structure returned for the response CNE_RESPONSE_DEREG_ROLE_MSG + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + boolean is_success; + /**< TRUE if the request was successful. 1 byte see BooleanNote */ +} cne_dereg_role_evt_rsp_data_type; + + +/** + Response info structure returned for the event CNE_NOTIFY_RAT_LOST_MSG + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + cne_rat_type rat; + /**< Rat type which has lost the connectivity. 4 bytes */ +} cne_rat_lost_evt_data_type; + + +/** + Response info structure returned for the event + CNE_NOTIFY_MORE_PREFERED_RAT_AVAIL_MSG + */ +typedef struct +{ + cne_reg_id_type reg_id; + /**< regestration Id 4 bytes */ + cne_rat_type rat; + /**< Rat type which is better for this registration/role 4 bytes */ + /* to do other ratInfo */ +} cne_pref_rat_avail_evt_data_type; + +/** + Response info structure returned for the event + CNE_NOTIFY_INFLIGHT_STATUS_MSG + */ +typedef struct +{ + boolean is_flying; + /**< true if in flight else false */ +} cne_inflight_status_change_evt_data_type; + +typedef union { + cne_rat_type rat; + struct { + cne_rat_type rat; + char ssid[CNE_MAX_SSID_LEN]; + } wlan; + struct { + cne_rat_type rat; + } wwan; + +} CneRatInfoType; + + +typedef struct { + int32 status; + int32 rssi; + char *ssid; +} CneWlanInfoType; + +typedef struct { + int32 level; + int32 frequency; + char *ssid; + char *bssid; + char *capabilities; +}CneWlanScanListInfoType; + +typedef struct { + int numItems; + CneWlanScanListInfoType scanList[CNE_MAX_SCANLIST_SIZE]; +} CneWlanScanResultsType; + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/** + @brief cne_svc_init creates the internal cne sub modules. + This functions needs to be called only once at the power up. + @param None + @see None + @return None + +*/ +void cne_svc_init(); + + + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif /* CNE_SVC_H */ + diff --git a/reference-cne/inc/CRefCne.h b/reference-cne/inc/CRefCne.h new file mode 100755 index 0000000..bd04790 --- /dev/null +++ b/reference-cne/inc/CRefCne.h @@ -0,0 +1,128 @@ +#ifndef REF_CNE_H +#define REF_CNE_H + +/**---------------------------------------------------------------------------- + @file REF_CNE.h + + +-----------------------------------------------------------------------------*/ + +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + +#include "cne_svc.h" +#include "RefCneDefs.h" +#include "CRefCneRadio.h" + + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Class Definitions + * -------------------------------------------------------------------------*/ +class CRefCne +{ +public: + /** + @brief Returns an instance of the CneSpm class. + + The user of this class will call this function to get an + instance of the class. All other public functions will be + called on this instance + + @param None + @see None + @return An instance of the CneSpm class is returned. + */ + static CRefCne* getInstance (); + static void RefCneCmdHdlr + ( + int , + int , + void* + ); + +private: + /* Wlan notification command format */ + typedef struct _Wlan { + int status; + int rssi; + char ssid[32]; + } refCneWlanInfoCmdFmt; + + /* Wwan notification command format */ + typedef struct _Wwan { + int type; + int status; + int rssi; + int roaming; + } refCneWwanInfoCmdFmt; + + CRefCne(); + ~CRefCne(); + static CRefCne* m_sInstancePtr; + int m_iNumActiveNetworks; + static cne_rat_type m_siPrefNetwork; + CRefCneRadio* RefCneWifi; + CRefCneRadio* RefCneWwan; + + + ref_cne_ret_enum_type UpdateWlanInfoCmd + ( + void* + ); + + ref_cne_ret_enum_type UpdateWwanInfoCmd + ( + void* + ); + + ref_cne_ret_enum_type SetPrefNetCmd + ( + void * + ); + void SetPreferredNetwork + ( + cne_rat_type * + ); + cne_rat_type GetPreferredNetwork(); + void ProcessStateChange(); +}; + +#endif /* REF_CNE_H */ \ No newline at end of file diff --git a/reference-cne/inc/CRefCneRadio.h b/reference-cne/inc/CRefCneRadio.h new file mode 100755 index 0000000..e173c8e --- /dev/null +++ b/reference-cne/inc/CRefCneRadio.h @@ -0,0 +1,120 @@ +#ifndef REF_CNE_RADIO_H + #define REF_CNE_RADIO_H + +/**---------------------------------------------------------------------------- + @file REF_CNE_RADIO.h + + +-----------------------------------------------------------------------------*/ + +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + #include "cne_svc.h" + #include "RefCneDefs.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Class Definitions + * -------------------------------------------------------------------------*/ +class CRefCneRadio +{ +public: + /** + * @brief Returns an instance of the RefCneRadio class. + + The user of this class will call this function to get an + instance of the class. All other public functions will be + called on this instance + + @param None + @see None + *@return An instance of the RCneRadio class is returned. + **/ + + //Constructor + CRefCneRadio + ( + cne_rat_type + ); + + //Destructor + ~CRefCneRadio(){}; + + // returns if True if status is connected, else false + bool bIsDataConnected (); + + int iIsConActionPending (); + + void ClearPending (); + + bool bIsConStateChanged (); + + void UpdateStatus + ( + int + ); + + //Turn ON Radio + void TurnOn (); + + //Turn OFF Radio + void TurnOff (); + + void SetPending + ( + ref_cne_net_con_req_enum_type + ); + +private: + + //private member variables + cne_network_state_enum_type m_iNetState; + cne_rat_type m_iMyRatType; + ref_cne_net_con_req_enum_type m_iRequestState; + ref_cne_net_con_status_enum_type m_iPrevNetConState; + ref_cne_net_con_status_enum_type m_iNetConState; + + /* Impicit Contructor which cannot be explicitly called */ + CRefCneRadio(); + CRefCneRadio(const CRefCneRadio& radio); +}; +#endif /* REF_CNE_RADIO_H */ + + diff --git a/reference-cne/inc/RefCneDefs.h b/reference-cne/inc/RefCneDefs.h new file mode 100755 index 0000000..b189ddd --- /dev/null +++ b/reference-cne/inc/RefCneDefs.h @@ -0,0 +1,134 @@ +#ifndef REF_CNE_DEFS_H +#define REF_CNE_DEFS_H + +/**---------------------------------------------------------------------------- + @file REFCNE_Defs.h + + This file holds various definations that get used across, different CNE + modules. +-----------------------------------------------------------------------------*/ + + +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + #include + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + + #define RCNE_LOG_TAG "RefCnE" + + #define RCNE_MSG_WARN(...) LOG(LOG_WARN,RCNE_LOG_TAG,__VA_ARGS__) + #define RCNE_MSG_WARN1 RCNE_MSG_WARN + #define RCNE_MSG_WARN2 RCNE_MSG_WARN + #define RCNE_MSG_WARN3 RCNE_MSG_WARN + #define RCNE_MSG_WARN4 RCNE_MSG_WARN + #define RCNE_MSG_WARN5 RCNE_MSG_WARN + + #define RCNE_MSG_DEBUG(...) LOG(LOG_DEBUG,RCNE_LOG_TAG,__VA_ARGS__) + #define RCNE_MSG_DEBUG1 RCNE_MSG_DEBUG + #define RCNE_MSG_DEBUG2 RCNE_MSG_DEBUG + #define RCNE_MSG_DEBUG3 RCNE_MSG_DEBUG + #define RCNE_MSG_DEBUG4 RCNE_MSG_DEBUG + #define RCNE_MSG_DEBUG5 RCNE_MSG_DEBUG + + #define RCNE_MSG_ERROR(...) LOG(LOG_ERROR,RCNE_LOG_TAG,__VA_ARGS__) + #define RCNE_MSG_ERROR1 RCNE_MSG_ERROR + #define RCNE_MSG_ERROR2 RCNE_MSG_ERROR + #define RCNE_MSG_ERROR3 RCNE_MSG_ERROR + #define RCNE_MSG_ERROR4 RCNE_MSG_ERROR + #define RCNE_MSG_ERROR5 RCNE_MSG_ERROR + + #define RCNE_MSG_VERBOSE(...) LOG(LOG_VERBOSE,RCNE_LOG_TAG,__VA_ARGS__) + #define RCNE_MSG_VERBOSE1 RCNE_MSG_VERBOSE + #define RCNE_MSG_VERBOSE2 RCNE_MSG_VERBOSE + #define RCNE_MSG_VERBOSE3 RCNE_MSG_VERBOSE + #define RCNE_MSG_VERBOSE4 RCNE_MSG_VERBOSE + #define RCNE_MSG_VERBOSE5 RCNE_MSG_VERBOSE + + #define RCNE_MSG_INFO(...) LOG(LOG_INFO,RCNE_LOG_TAG,__VA_ARGS__) + #define RCNE_MSG_INFO1 RCNE_MSG_INFO + #define RCNE_MSG_INFO2 RCNE_MSG_INFO + #define RCNE_MSG_INFO3 RCNE_MSG_INFO + #define RCNE_MSG_INFO4 RCNE_MSG_INFO + #define RCNE_MSG_INFO5 RCNE_MSG_INFO + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/** Possible return codes */ +typedef enum +{ + /* ADD other new error codes here */ + REF_CNE_RET_ERROR = -1, + + REF_CNE_RET_OK = 1, +} ref_cne_ret_enum_type; + +typedef enum +{ + REF_CNE_NET_STATE_DISCONNECTED=0, + REF_CNE_NET_STATE_CONNECTED, + REF_CNE_NET_STATE_UNINITIALIZED, +} ref_cne_net_con_status_enum_type; + +typedef enum +{ + REF_CNE_NET_PENDING_CONNECT=0, + REF_CNE_NET_PENDING_DISCONNECT, + REF_CNE_NET_NOT_PENDING, +} ref_cne_net_con_req_enum_type; + +#ifndef TRUE + #define TRUE 1 /* Boolean true value. */ +#endif /* TRUE */ + +#ifndef FALSE + #define FALSE 0 /* Boolean false value. */ +#endif /* FALSE */ + +#ifndef NULL + #define NULL 0 +#endif /* NULL */ + +#ifndef MAX + #define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) ) +#endif /* MAX */ + +#ifndef MIN + #define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) ) +#endif /* MIN */ + +#endif /* REF_CNE_DEFS_H */ diff --git a/reference-cne/src/Android.mk b/reference-cne/src/Android.mk new file mode 100755 index 0000000..280264e --- /dev/null +++ b/reference-cne/src/Android.mk @@ -0,0 +1,46 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +# measurements show that the ARM version of ZLib is about x1.17 faster +# than the thumb one... +LOCAL_ARM_MODE := arm + +#this is needed to make sure that the path for stlport is specified first than stdc++ +LOCAL_NO_DEFAULT_COMPILER_FLAGS :=true + +LOCAL_SRC_FILES:= \ + CRefCne.cpp\ + CRefCneRadio.cpp\ + CneSvc.cpp\ + +LOCAL_MODULE:= librefcne + +LOCAL_C_INCLUDES := \ + external/connectivity/reference-cne/inc \ + external/connectivity/include/cne \ + bionic/libstdc++/include \ + system/core/include \ + hardware/libhardware/include \ + hardware/libhardware_legacy/include \ + hardware/ril/include \ + dalvik/libnativehelper/include \ + frameworks/base/include \ + external/skia/include \ + out/target/product/dream/obj/include \ + bionic/libc/arch-arm/include \ + bionic/libc/include \ + bionic/libstdc++/include \ + bionic/libc/kernel/common \ + bionic/libc/kernel/arch-arm \ + bionic/libm/include \ + bionic/libm/include/arch/arm \ + bionic/libthread_db/include \ + out/target/product/dream/obj/EXECUTABLES/cnetest_intermediates + +LOCAL_CFLAGS+= -fno-exceptions -Wno-multichar -msoft-float -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -march=armv5te -mtune=xscale -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5TE__ -include system/core/include/arch/linux-arm/AndroidConfig.h -I system/core/include/arch/linux-arm/ -mthumb-interwork -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -DSK_RELEASE -DNDEBUG -O2 -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -fvisibility-inlines-hidden -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300 -fno-rtti -DFEATURE_XMLLIB + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + diff --git a/reference-cne/src/CRefCne.cpp b/reference-cne/src/CRefCne.cpp new file mode 100755 index 0000000..5577a0a --- /dev/null +++ b/reference-cne/src/CRefCne.cpp @@ -0,0 +1,402 @@ +/**---------------------------------------------------------------------------- + @file CRefCne.cpp + + +-----------------------------------------------------------------------------*/ + +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define TWO_RADIOS_ARE_CONNECTED 2 +#define ONE_RADIO_IS_CONNECTED 1 +#define ALL_RADIOS_ARE_DISCONNECTED 0 + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "stdio.h" +#include "cne_svc.h" +#include "CRefCne.h" +#include "CRefCneRadio.h" +#include "RefCneDefs.h" + +/*---------------------------------------------------------------------------- + * Static Member declarations + * -------------------------------------------------------------------------*/ +CRefCne* CRefCne::m_sInstancePtr = NULL; +cne_rat_type CRefCne::m_siPrefNetwork = CNE_RAT_NONE; + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Class Definitions + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * FUNCTION getInstance + + * DESCRIPTION The user of this class will call this function to get an + instance of the class. All other public functions will be + called on this instance + + * DEPENDENCIES None + + * RETURN VALUE an instance of CRefCne class + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +CRefCne* CRefCne::getInstance +( +) +{ + if (m_sInstancePtr == NULL) + { + m_sInstancePtr = new CRefCne; + } + return(m_sInstancePtr); +} +/*---------------------------------------------------------------------------- + * FUNCTION Constructor + + * DESCRIPTION Creates the RefCne object & initializes members appropriately + + * DEPENDENCIES None + + * RETURN VALUE an instance of CRefCne class + + * SIDE EFFECTS RefCne object is created + *--------------------------------------------------------------------------*/ +CRefCne::CRefCne () +{ + m_iNumActiveNetworks = NULL; + RefCneWifi = new CRefCneRadio(CNE_RAT_WLAN); + RefCneWwan = new CRefCneRadio(CNE_RAT_WWAN); +} +/*---------------------------------------------------------------------------- + * FUNCTION RefCneCmdHdlr + + * DESCRIPTION This the master command handler which calls specific handler + to handle a particular command sent by the daemon + + * DEPENDENCIES None + + * RETURN VALUE None + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +void CRefCne::RefCneCmdHdlr +( + int cmd, + int cmd_len, + void* pCmdDataPtr +) +{ + cmd = (cne_cmd_enum_type) cmd; + CRefCne* myself = getInstance(); + switch (cmd) + { + case CNE_NOTIFY_DEFAULT_NW_PREF_CMD: + { + RCNE_MSG_INFO("Command hdlr: Notify default" + " network pref cmd called [%d]",cmd); + ref_cne_ret_enum_type ret = myself->SetPrefNetCmd(pCmdDataPtr); + if (ret != REF_CNE_RET_OK) + { + //ASSERT(0); + } + break; + } + case CNE_REQUEST_UPDATE_WLAN_INFO_CMD: + { + RCNE_MSG_INFO("Command hdlr: Update Wifi info cmd called [%d]",cmd); + ref_cne_ret_enum_type ret = myself->UpdateWlanInfoCmd(pCmdDataPtr); + if (ret != REF_CNE_RET_OK) + { + //ASSERT(0); + } + break; + } + case CNE_REQUEST_UPDATE_WWAN_INFO_CMD: + { + RCNE_MSG_INFO("Command hdlr: Update WWAN info cmd called [%d]",cmd); + ref_cne_ret_enum_type ret = myself->UpdateWwanInfoCmd(pCmdDataPtr); + if (ret != REF_CNE_RET_OK) + { + //assert(0); + } + break; + } + default: + { + RCNE_MSG_ERROR("Command hdlr: Unrecognized command recvd [%d]",cmd); + } + } + myself->ProcessStateChange(); +} +/*---------------------------------------------------------------------------- + * FUNCTION ProcessStateChange + + * DESCRIPTION Processess the change of state of the connectivity engine + after the command received from the daemon is processed + + * DEPENDENCIES None + + * RETURN VALUE None + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +void CRefCne::ProcessStateChange +( +) +{ + RCNE_MSG_INFO("PSC:BEGIN processing state change"); + m_iNumActiveNetworks = 0; + cne_rat_type myPrefNet = GetPreferredNetwork(); + /* Check if the preferred network is set, if not then phone is + * in boot up process, so do nothing */ + if (myPrefNet == NULL) + { + return; + } + + CRefCneRadio* pref; + CRefCneRadio* nonpref; + if (myPrefNet == CNE_RAT_WLAN ) + { + RCNE_MSG_DEBUG("PSC: Preferred RAT is Wifi, non-preferred RAT is WWAN"); + pref = RefCneWifi; + nonpref = RefCneWwan; + } else + { + RCNE_MSG_DEBUG("PSC: Preferred RAT is WWAN, non-preferred RAT is Wifi"); + pref = RefCneWwan; + nonpref = RefCneWifi; + } + if (RefCneWifi->bIsDataConnected() == TRUE ) + { + ++m_iNumActiveNetworks; + RCNE_MSG_INFO("PSC: Wifi is in connected state"); + } + if (RefCneWwan->bIsDataConnected() == TRUE ) + { + ++m_iNumActiveNetworks; + RCNE_MSG_INFO("PSC: WWAN is in connected state"); + } + switch (m_iNumActiveNetworks) + { + case TWO_RADIOS_ARE_CONNECTED: + /** + * If both Radios are up turn off the non-preferred network + */ + { + RCNE_MSG_DEBUG("PSC: both radios are up; disconnecting" + " non-preferred radio"); + nonpref->TurnOff(); + nonpref->SetPending(REF_CNE_NET_PENDING_DISCONNECT); + break; + } + case ONE_RADIO_IS_CONNECTED: + /** + * If only one radio is up check if it is the preferred one, + * if not then turn on the preferred network + */ + { + if (pref->bIsDataConnected() == FALSE) + { + RCNE_MSG_INFO("PSC: Non preferred radio is up; reconnecting" + " preferred radio"); + pref->TurnOn(); + pref->SetPending(REF_CNE_NET_PENDING_CONNECT); + } else + { + RCNE_MSG_INFO("PSC: Preferred radio is connected"); + } + break; + } + case ALL_RADIOS_ARE_DISCONNECTED: + /** + * If both networks are disconnected then try to bring up + * both networks + */ + { + RCNE_MSG_INFO("All radios are disconnected; trying to reconnect"); + pref->TurnOn(); + pref->SetPending(REF_CNE_NET_PENDING_CONNECT); + nonpref->TurnOn(); + nonpref->SetPending(REF_CNE_NET_PENDING_CONNECT); + break; + } + default: + { + RCNE_MSG_WARN("PSC: number of active networks is invalid"); + //ASSERT(0); + } + } +} +/*---------------------------------------------------------------------------- + * FUNCTION UpdateWlanInfoCmd + + * DESCRIPTION The command handler for UpdateWlanInfo notification + + * DEPENDENCIES None + + * RETURN VALUE ref_cne_ret_enum_type + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +ref_cne_ret_enum_type CRefCne::UpdateWlanInfoCmd +( + void* pWifiCmdData +) +{ + RCNE_MSG_DEBUG("UWLICH: Wlan update info cmd handler called"); + refCneWlanInfoCmdFmt *WlanInfoCmd; + WlanInfoCmd = (refCneWlanInfoCmdFmt *)pWifiCmdData; + if (WlanInfoCmd->status == NULL) + { + RCNE_MSG_ERROR("UWLICH: Invalid (==NULL) WLAN status received"); + return(REF_CNE_RET_ERROR); + } + RefCneWifi->UpdateStatus(WlanInfoCmd->status); + if ( (RefCneWifi->bIsDataConnected() + && (RefCneWifi->iIsConActionPending()== REF_CNE_NET_PENDING_CONNECT) ) + || (!RefCneWifi->bIsDataConnected() + && (RefCneWifi->iIsConActionPending()== REF_CNE_NET_PENDING_DISCONNECT) ) ) + { + RCNE_MSG_DEBUG("UWLICH: Was in connection action pending state; clearing it"); + RefCneWifi->ClearPending(); + } + RCNE_MSG_INFO("UWLICH: handled Wlan update info cmd"); + return(REF_CNE_RET_OK); +} +/*---------------------------------------------------------------------------- + * FUNCTION UpdateWwanInfoCmd + + * DESCRIPTION The command handler for UpdateWwanInfo notification + + * DEPENDENCIES None + + * RETURN VALUE ref_cne_ret_enum_type + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +ref_cne_ret_enum_type CRefCne::UpdateWwanInfoCmd +( + void* pWwanCmdData +) +{ + RCNE_MSG_DEBUG("UWWICH: Wwan update info cmd handler called"); + refCneWwanInfoCmdFmt *WwanInfoCmd; + WwanInfoCmd = (refCneWwanInfoCmdFmt *)pWwanCmdData; + if (WwanInfoCmd->status == NULL) + { + RCNE_MSG_ERROR("UWWICH: Invalid (==NULL) WWAN status received"); + return(REF_CNE_RET_ERROR); + } + RefCneWwan->UpdateStatus(WwanInfoCmd->status); + if ( (RefCneWwan->bIsDataConnected() + && (RefCneWwan->iIsConActionPending()== REF_CNE_NET_PENDING_CONNECT) ) + || (!RefCneWwan->bIsDataConnected() + && (RefCneWwan->iIsConActionPending()== REF_CNE_NET_PENDING_DISCONNECT) ) ) + { + RCNE_MSG_DEBUG("UWWICH: Was in connection action pending state; clearing it"); + RefCneWwan->ClearPending(); + } + RCNE_MSG_INFO("UWWICH: handled Wwan update info cmd"); + return(REF_CNE_RET_OK); +} +/*---------------------------------------------------------------------------- + * FUNCTION SetPrefNetCmd + + * DESCRIPTION The command handler for set preferred network notification + + * DEPENDENCIES None + + * RETURN VALUE ref_cne_ret_enum_type + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +ref_cne_ret_enum_type CRefCne::SetPrefNetCmd +( + void* pPrefNetCmdData +) +{ + RCNE_MSG_DEBUG("SPNCH: Set preferred network command handler called"); + cne_rat_type *pPrefNetwork; + pPrefNetwork = (cne_rat_type *)pPrefNetCmdData; + if ( (*pPrefNetwork != CNE_RAT_WLAN)&&(*pPrefNetwork != CNE_RAT_WWAN) ) + { + RCNE_MSG_ERROR("SPNCH: Invalid Network ID [%d] received",*pPrefNetwork); + return(REF_CNE_RET_ERROR); + } + SetPreferredNetwork(pPrefNetwork); + RCNE_MSG_DEBUG("SPNCH: handled set preferred network cmd"); + return(REF_CNE_RET_OK); +} +/*---------------------------------------------------------------------------- + * FUNCTION SetPreferredNetwork + + * DESCRIPTION Sets the desired network as the preferred network + + * DEPENDENCIES None + + * RETURN VALUE None + + * SIDE EFFECTS The default network for the system is changed + *--------------------------------------------------------------------------*/ +void CRefCne::SetPreferredNetwork +( + cne_rat_type* pNetId +) +{ + m_siPrefNetwork = *pNetId; + return; +} +/*---------------------------------------------------------------------------- + * FUNCTION GetPreferredNetwork + + * DESCRIPTION Informs the caller about which network is used as default + + * DEPENDENCIES None + + * RETURN VALUE cne_rat_type + + * SIDE EFFECTS None + *--------------------------------------------------------------------------*/ +cne_rat_type CRefCne::GetPreferredNetwork +( +) +{ + return(m_siPrefNetwork); +} + diff --git a/reference-cne/src/CRefCneRadio.cpp b/reference-cne/src/CRefCneRadio.cpp new file mode 100755 index 0000000..48a4738 --- /dev/null +++ b/reference-cne/src/CRefCneRadio.cpp @@ -0,0 +1,280 @@ +/*============================================================================ + FILE: CRefCneRadio.cpp + + OVERVIEW: The CRefCneRadio class provides means to control an air + interface upon creation of its object. Some of the methods + such as bIsDataConnected, bIsConStateChanged, provide means to + find out the current connectivity state of the radio + + DEPENDENCIES: The CRefCneRadio class is constructed for a unique air interface + denoted by its RAT type. Once constructed, all other methods + can be called on this object. +============================================================================*/ + +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/*--------------------------------------------------------------------------- + * Extern Declarations + *-------------------------------------------------------------------------*/ +extern "C" void cnd_sendUnsolicitedMsg + ( + int targetFd, + int msgType, + int dataLen, + void *data + ); + +/*---------------------------------------------------------------------------- + * Includes + * -------------------------------------------------------------------------*/ +#include "CRefCneRadio.h" +#include "RefCneDefs.h" +#include "cne_svc.h" + +/*============================================================================= + FUNCTION CRefCneRadio + + DESCRIPTION Class constructor initializes class member variables + + DEPENDENCIES None + + RETURN VALUE CRefCneRadio instance + + SIDE EFFECTS None + ============================================================================*/ +CRefCneRadio::CRefCneRadio +( + cne_rat_type myRadio +):m_iRequestState(REF_CNE_NET_NOT_PENDING), + m_iNetConState(REF_CNE_NET_STATE_UNINITIALIZED), + m_iPrevNetConState(REF_CNE_NET_STATE_UNINITIALIZED) +{ + //Print to logcat: RefCne Radio constructor called + /* set the command handlers */ + + m_iMyRatType = myRadio; + + //Print to logcat: RefCne Radio constructed +} +/*============================================================================= + FUNCTION CRefCneRadio + + DESCRIPTION Copy constructor, not allowed. + + DEPENDENCIES None + + RETURN VALUE None + + SIDE EFFECTS None + ============================================================================*/ +CRefCneRadio::CRefCneRadio(const CRefCneRadio& radio) +{ +} +/*============================================================================= + FUNCTION bIsDataConnected + + DESCRIPTION Querrys the Radio to see if it is connected + + DEPENDENCIES None + + RETURN VALUE TRUE, FALSE + + SIDE EFFECTS None + ============================================================================*/ +bool CRefCneRadio::bIsDataConnected () +{ + if(m_iNetConState == REF_CNE_NET_STATE_CONNECTED) + { + return TRUE; + } + else + { + return FALSE; + } +} +/*============================================================================= + FUNCTION iIsConActionPending + + DESCRIPTION Querrys the Radio for a pending request + + DEPENDENCIES None + + RETURN VALUE TRUE, FALSE + + SIDE EFFECTS None + ============================================================================*/ +int CRefCneRadio::iIsConActionPending +( +) +{ + return m_iRequestState; +} +/*============================================================================= + FUNCTION ClearPending + + DESCRIPTION Clears the request pending flag + + DEPENDENCIES None + + RETURN VALUE None + + SIDE EFFECTS None + ============================================================================*/ +void CRefCneRadio::ClearPending +( +) +{ + m_iRequestState = REF_CNE_NET_NOT_PENDING; +} +/*============================================================================= + FUNCTION bIsConStateChanged + + DESCRIPTION Querry the radio to see if the new status is different from + previous + + DEPENDENCIES None + + RETURN VALUE None + + SIDE EFFECTS None + ============================================================================*/ +bool CRefCneRadio::bIsConStateChanged +( +) +{ + if(m_iNetConState != m_iPrevNetConState) + { + return TRUE; + } + else + { + return FALSE; + } +} +/*============================================================================= + FUNCTION UpdateStatus + + DESCRIPTION Maintains the previous and current state of the radio + + DEPENDENCIES None + + RETURN VALUE None + + SIDE EFFECTS None + ============================================================================*/ +void CRefCneRadio::UpdateStatus + ( + int myNetStatus + ) +{ + m_iNetState = (cne_network_state_enum_type )myNetStatus; + m_iPrevNetConState = m_iNetConState; + switch(myNetStatus) + { + case CNE_NETWORK_STATE_CONNECTED: + { + m_iNetConState = REF_CNE_NET_STATE_CONNECTED; + break; + } + default: + { + m_iNetConState = REF_CNE_NET_STATE_DISCONNECTED; + } + } + return; +} +/*============================================================================= + FUNCTION TurnOn + + DESCRIPTION Turns the radio on + + DEPENDENCIES None + + RETURN VALUE None + + SIDE EFFECTS None + ============================================================================*/ +void CRefCneRadio::TurnOn +( +) +{ + //Send Turn On command to Connectivity daemon + cnd_sendUnsolicitedMsg + (0, CNE_REQUEST_BRING_RAT_UP_MSG, sizeof(m_iMyRatType), &m_iMyRatType); + return; +} +/*============================================================================= + FUNCTION TurnOff + + DESCRIPTION Turns the radio off + + DEPENDENCIES None + + RETURN VALUE None + + SIDE EFFECTS None + ============================================================================*/ +void CRefCneRadio::TurnOff +( +) +{ + //Send Turn Off command to Connectivity daemon + cnd_sendUnsolicitedMsg + (0, CNE_REQUEST_BRING_RAT_DOWN_MSG, sizeof(m_iMyRatType), &m_iMyRatType); + return; +} +/*============================================================================= + FUNCTION SetPending + + DESCRIPTION Sets the pending flag appropriately when radio is turned on + or off + + DEPENDENCIES None + + RETURN VALUE None + + SIDE EFFECTS None + ============================================================================*/ +void CRefCneRadio::SetPending +( + ref_cne_net_con_req_enum_type flag +) +{ + m_iRequestState = flag; +} + +//Implicit constructor +CRefCneRadio::CRefCneRadio +( +) +{ +} + + diff --git a/reference-cne/src/CneSvc.cpp b/reference-cne/src/CneSvc.cpp new file mode 100755 index 0000000..9c91ed4 --- /dev/null +++ b/reference-cne/src/CneSvc.cpp @@ -0,0 +1,133 @@ +/*============================================================================ + FILE: CneSvc.cpp + + OVERVIEW: Provide an overview of the implementation contained in this + file. Do not rehash the user-level documentation from the + header file. Maintainers, not users of this code will be + reading this. Describe anything of interest about the + algorithms or design, and call attention to anything tricky + or potentially confusing. + + DEPENDENCIES: If the code in this file has any notable dependencies, + describe them here. Any initialization and sequencing + requirements, or assumptions about the overall state of + the system belong here. +============================================================================*/ + +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "cne_svc.h" +#include "CRefCne.h" +#include "RefCneDefs.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +extern void cnd_regCommandsNotificationCb +( + int, + void (*)(int,int,void*), + int +); + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static/Class member Function Declarations and Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Externalized Function Definitions + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * FUNCTION Function Name + + * DESCRIPTION Function Description + + * DEPENDENCIES + + * RETURN VALUE + + * SIDE EFFECTS + *--------------------------------------------------------------------------*/ +extern "C" void +cne_processCommand +( + int cmd, + int cmd_len, + void *cmd_data /* event data depends on the type of event */ +) +{ + //CRefCne::getInstance()->RefCneCmdHdlr(cmd, cmd_len, cmd_data); + CRefCne::RefCneCmdHdlr(cmd, cmd_len, cmd_data); + return; +} + +/*---------------------------------------------------------------------------- + * FUNCTION Function Name + + * DESCRIPTION Function Description + + * DEPENDENCIES + + * RETURN VALUE + + * SIDE EFFECTS + *--------------------------------------------------------------------------*/ +void cne_svc_init +( + void +) +{ + /* create the RefCne obj */ + (void) CRefCne::getInstance(); +} + + -- cgit v1.2.3