diff options
author | Etan Cohen <etancohen@google.com> | 2016-02-05 22:03:47 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-02-05 22:03:47 +0000 |
commit | a4c9b2f59fa6932a1fe25c073abcd668179d84db (patch) | |
tree | 12bacf29ac544f70e7c5f1353009fc30068b5838 | |
parent | c583100be95f4238b12270353c16f266adaa6ba6 (diff) | |
parent | fb4f4178cada2fabb3354f69009dc8a9bc2676a5 (diff) | |
download | connectivity-a4c9b2f59fa6932a1fe25c073abcd668179d84db.tar.gz |
Merge "Add Wi-Fi HAL facade to sl4n testing." into mm-wireless-dev
am: fb4f4178ca
* commit 'fb4f4178cada2fabb3354f69009dc8a9bc2676a5':
Add Wi-Fi HAL facade to sl4n testing.
-rw-r--r-- | sl4n/Android.mk | 25 | ||||
-rw-r--r-- | sl4n/facades/wifi/wifi_facade.cpp | 257 | ||||
-rw-r--r-- | sl4n/facades/wifi/wifi_facade.h | 50 | ||||
-rw-r--r-- | sl4n/utils/command_receiver.cpp | 34 | ||||
-rw-r--r-- | sl4n/utils/command_receiver.h | 4 |
5 files changed, 358 insertions, 12 deletions
diff --git a/sl4n/Android.mk b/sl4n/Android.mk index 6d2a239..c7c0e7f 100644 --- a/sl4n/Android.mk +++ b/sl4n/Android.mk @@ -22,12 +22,15 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE := sl4n LOCAL_C_INCLUDES += \ + frameworks/opt/net/wifi/service/jni \ + hardware/libhardware_legacy/include/hardware_legacy \ system/bt \ $(LOCAL_PATH)/rapidjson/include \ $(LOCAL_PATH)/facades LOCAL_SRC_FILES := \ facades/bluetooth/bluetooth_binder_facade.cpp \ + facades/wifi/wifi_facade.cpp \ main.cpp \ utils/command_receiver.cpp \ utils/common_utils.cpp @@ -46,6 +49,28 @@ LOCAL_STATIC_LIBRARIES += \ libosi \ libbluetooth-client +# set correct Wi-Fi HAL library path and add Wi-Fi related libraries +# ============================================================ +LIB_WIFI_HAL := libwifi-hal + +ifeq ($(BOARD_WLAN_DEVICE), bcmdhd) + LIB_WIFI_HAL := libwifi-hal-bcm +else ifeq ($(BOARD_WLAN_DEVICE), qcwcn) + LIB_WIFI_HAL := libwifi-hal-qcom +else ifeq ($(BOARD_WLAN_DEVICE), mrvl) + # this is commented because none of the nexus devices + # that sport Marvell's wifi have support for HAL + # LIB_WIFI_HAL := libwifi-hal-mrvl +else ifeq ($(BOARD_WLAN_DEVICE), MediaTek) + # support MTK WIFI HAL + LIB_WIFI_HAL := libwifi-hal-mt66xx +endif + +LOCAL_STATIC_LIBRARIES += \ + $(LIB_WIFI_HAL) \ + libnl \ + libwifi-hal-stub + LOCAL_CFLAGS += -std=c++11 -Wall -Wno-unused-parameter -Wno-missing-field-initializers diff --git a/sl4n/facades/wifi/wifi_facade.cpp b/sl4n/facades/wifi/wifi_facade.cpp new file mode 100644 index 0000000..80a3b8f --- /dev/null +++ b/sl4n/facades/wifi/wifi_facade.cpp @@ -0,0 +1,257 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// 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 <rapidjson/document.h> +#include <rapidjson/writer.h> +#include <rapidjson/stringbuffer.h> +#include <net/if.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <base.h> +#include <base/at_exit.h> +#include <base/command_line.h> +#include <base/logging.h> +#include <base/macros.h> +#include <base/strings/string_split.h> +#include <base/strings/string_util.h> +#include <utils/command_receiver.h> +#include <utils/common_utils.h> +#include <wifi_hal.h> +#include <wifi_hal_stub.h> + +#include "wifi_facade.h" + +const char kWlanInterface[] = "wlan0"; +const char kP2pInterface[] = "p2p0"; + +std::tuple<bool, int> WifiFacade::WifiInit() { + if (!WifiStartHal()) { + return std::make_tuple(false, sl4n_error_codes::kFailInt); + } + + if (!WifiGetInterfaces() || wlan0_index == -1) { + return std::make_tuple(false, sl4n_error_codes::kFailInt); + } + + return std::make_tuple(true, sl4n_error_codes::kPassInt); +} + +bool WifiFacade::WifiStartHal() { + if (wifi_hal_handle == NULL) { + if (init_wifi_stub_hal_func_table(&hal_fn) != 0) { + LOG(ERROR) << sl4n::kTagStr + << ": Can not initialize the basic function pointer table"; + return false; + } + + wifi_error res = init_wifi_vendor_hal_func_table(&hal_fn); + if (res != WIFI_SUCCESS) { + LOG(ERROR) << sl4n::kTagStr + << ": Can not initialize the vendor function pointer table"; + return false; + } + + int ret = BringInterfaceUpDown(kWlanInterface, 1); + if (ret != 0) { + return false; + } + + res = hal_fn.wifi_initialize(&wifi_hal_handle); + return res == WIFI_SUCCESS; + } else { + return BringInterfaceUpDown(kWlanInterface, 1) == 0; + } +} + +bool WifiFacade::WifiGetInterfaces() { + int num_ifaces; + int result = hal_fn.wifi_get_ifaces(wifi_hal_handle, &num_ifaces, + &wifi_iface_handles); + if (result < 0) { + LOG(ERROR) << sl4n::kTagStr << ": Can not get Wi-Fi interfaces"; + return false; + } + + if (num_ifaces < 0) { + LOG(ERROR) << sl4n::kTagStr << ": Negative number of interfaces"; + return false; + } + + if (wifi_iface_handles == NULL) { + LOG(ERROR) << sl4n::kTagStr + << "wifi_get_ifaces returned null interface array"; + return false; + } + + if (num_ifaces > 8) { + LOG(ERROR) << sl4n::kTagStr + << "wifi_get_ifaces returned too many interfaces"; + return false; + } + + char buf[128]; + for (int i = 0; i < num_ifaces; ++i) { + int result = hal_fn.wifi_get_iface_name(wifi_iface_handles[i], buf, + sizeof(buf)); + if (result < 0) { + LOG(ERROR) << sl4n::kTagStr + << "Can't obtain interface name for interface #" << i; + continue; + } + if (!strcmp(buf, kWlanInterface)) { + wlan0_index = i; + } else if (!strcmp(buf, kP2pInterface)) { + p2p0_index = i; + } + } + + return true; +} + +bool WifiFacade::SharedValidator() { + if (wifi_hal_handle == NULL) { + LOG(ERROR) << sl4n::kTagStr << "HAL handle not initialized"; + return false; + } + + if (wifi_iface_handles == NULL) { + LOG(ERROR) << sl4n::kTagStr << "HAL interfaces not initialized"; + return false; + } + + if (wlan0_index == -1) { + LOG(ERROR) << sl4n::kTagStr << kWlanInterface << " interface not found"; + return false; + } + + return true; +} + +std::tuple<int, int> WifiFacade::WifiGetSupportedFeatureSet() { + if (!SharedValidator()) { + return std::make_tuple(0, sl4n_error_codes::kFailInt); + } + + feature_set set = 0; + int result = hal_fn.wifi_get_supported_feature_set( + wifi_iface_handles[wlan0_index], &set); + if (result == WIFI_SUCCESS) { + return std::make_tuple(set, sl4n_error_codes::kPassInt); + } else { + return std::make_tuple(0, sl4n_error_codes::kFailInt); + } +} + +// TODO: copy of set_iface_flags from Wi-Fi JNI. Consolidate into a support +// library. +int WifiFacade::BringInterfaceUpDown(const char *ifname, int dev_up) { + struct ifreq ifr; + int ret; + int sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + LOG(ERROR) << "Bad socket: " << sock; + return -errno; + } + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + + if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { + ret = errno ? -errno : -999; + LOG(ERROR) << "Could not read interface " << ifname << " flags: " << errno; + close(sock); + return ret; + } + + if (dev_up) { + if (ifr.ifr_flags & IFF_UP) { + close(sock); + return 0; + } + ifr.ifr_flags |= IFF_UP; + } else { + if (!(ifr.ifr_flags & IFF_UP)) { + close(sock); + return 0; + } + ifr.ifr_flags &= ~IFF_UP; + } + + if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) { + LOG(ERROR) << "Could not set interface " << ifname << " flags: " << errno; + ret = errno ? -errno : -999; + close(sock); + return ret; + } + close(sock); + return 0; +} + +////////////////// +// wrappers +///////////////// + +static WifiFacade facade; // triggers registration with CommandReceiver + +void wifi_init_wrapper(rapidjson::Document &doc) { + int expected_param_size = 0; + if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) { + return; + } + bool result; + int error_code; + std::tie(result, error_code) = facade.WifiInit(); + if (error_code == sl4n_error_codes::kFailInt) { + doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator()); + doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator()); + } else { + doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator()); + doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator()); + } +} + +void wifi_get_supported_feature_set_wrapper(rapidjson::Document &doc) { + int expected_param_size = 0; + if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) { + return; + } + int result; + int error_code; + std::tie(result, error_code) = facade.WifiGetSupportedFeatureSet(); + if (error_code == sl4n_error_codes::kFailInt) { + doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator()); + doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator()); + } else { + doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator()); + doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator()); + } +} + +//////////////// +// constructor +//////////////// + +WifiFacade::WifiFacade() { + wifi_hal_handle = NULL; + wifi_iface_handles = NULL; + num_wifi_iface_handles = 0; + wlan0_index = -1; + p2p0_index = -1; + + CommandReceiver::RegisterCommand("WifiInit", &wifi_init_wrapper); + CommandReceiver::RegisterCommand("WifiGetSupportedFeatureSet", + &wifi_get_supported_feature_set_wrapper); +} diff --git a/sl4n/facades/wifi/wifi_facade.h b/sl4n/facades/wifi/wifi_facade.h new file mode 100644 index 0000000..d78ab66 --- /dev/null +++ b/sl4n/facades/wifi/wifi_facade.h @@ -0,0 +1,50 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// 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. +// + +#pragma once + +#include <rapidjson/document.h> +#include <tuple> + +// WifiFacade provides simple wrappers to call Wi-Fi HAL APIs. +// +// Each public function returns a tuple: <result, code>, where: +// result: result of HAL API or a dummy value (of the correct type) +// on failure. +// code: sl4n_error_codes::kPassInt or sl4n_error_codes::kFailInt on +// success or failure respectively. +// +// The wrapper must check whether or not it is possible to call the API. +// Note the function "SharedValidator()" should be used by wrapper to check +// whether or not the HAL is configured correctly. +class WifiFacade { + public: + WifiFacade(); + std::tuple<bool, int> WifiInit(); + std::tuple<int, int> WifiGetSupportedFeatureSet(); + private: + wifi_hal_fn hal_fn; + wifi_handle wifi_hal_handle; + wifi_interface_handle* wifi_iface_handles; + int num_wifi_iface_handles; + int wlan0_index; + int p2p0_index; + + bool SharedValidator(); + bool WifiStartHal(); + bool WifiGetInterfaces(); + int BringInterfaceUpDown(const char *ifname, int dev_up); +}; diff --git a/sl4n/utils/command_receiver.cpp b/sl4n/utils/command_receiver.cpp index 31493bf..a57c764 100644 --- a/sl4n/utils/command_receiver.cpp +++ b/sl4n/utils/command_receiver.cpp @@ -31,9 +31,8 @@ using android::sp; using ipc::binder::IBluetooth; -typedef void (*MFP)(rapidjson::Document&); typedef std::map<std::string, MFP> function_map; -function_map _funcMap; +function_map* _funcMap = NULL; BluetoothBinderFacade bt_binder; void _clean_result(rapidjson::Document &doc) { @@ -228,20 +227,23 @@ void bluetooth_binder_set_adv_settings_wrapper(rapidjson::Document &doc) { // End Wrappers ... I'm not a large water dwelling mammal... CommandReceiver::CommandReceiver() { - _funcMap.insert(std::make_pair("initiate", &initiate)); - _funcMap.insert(std::make_pair("BluetoothBinderInitInterface", + if (_funcMap == NULL) { + _funcMap = new function_map(); + } + _funcMap->insert(std::make_pair("initiate", &initiate)); + _funcMap->insert(std::make_pair("BluetoothBinderInitInterface", &bluetooth_binder_init_interface_wapper)); - _funcMap.insert(std::make_pair("BluetoothBinderGetName", + _funcMap->insert(std::make_pair("BluetoothBinderGetName", &bluetooth_binder_get_local_name_wrapper)); - _funcMap.insert(std::make_pair("BluetoothBinderSetName", + _funcMap->insert(std::make_pair("BluetoothBinderSetName", &bluetooth_binder_set_local_name_wrapper)); - _funcMap.insert(std::make_pair("BluetoothBinderGetAddress", + _funcMap->insert(std::make_pair("BluetoothBinderGetAddress", &bluetooth_binder_get_local_address_wrapper)); - _funcMap.insert(std::make_pair("BluetoothBinderEnable", + _funcMap->insert(std::make_pair("BluetoothBinderEnable", &bluetooth_binder_enable_wrapper)); - _funcMap.insert(std::make_pair("BluetoothBinderRegisterBLE", + _funcMap->insert(std::make_pair("BluetoothBinderRegisterBLE", &bluetooth_binder_register_ble_wrapper)); - _funcMap.insert(std::make_pair("BluetoothBinderSetAdvSettings", + _funcMap->insert(std::make_pair("BluetoothBinderSetAdvSettings", &bluetooth_binder_set_adv_settings_wrapper)); } @@ -253,9 +255,17 @@ void CommandReceiver::Call(rapidjson::Document& doc) { cmd = doc[sl4n::kMethodStr].GetString(); } - function_map::const_iterator iter = _funcMap.find(cmd); - if (iter != _funcMap.end()) { + function_map::const_iterator iter = _funcMap->find(cmd); + if (iter != _funcMap->end()) { iter->second(doc); } _clean_result(doc); } + +void CommandReceiver::RegisterCommand(std::string name, MFP command) { + if (_funcMap == NULL) { + _funcMap = new function_map(); + } + + _funcMap->insert(std::make_pair(name, command)); +} diff --git a/sl4n/utils/command_receiver.h b/sl4n/utils/command_receiver.h index b2e9531..c2af543 100644 --- a/sl4n/utils/command_receiver.h +++ b/sl4n/utils/command_receiver.h @@ -18,6 +18,8 @@ #include <rapidjson/document.h> +typedef void (*MFP)(rapidjson::Document&); + // This class defines the functions that interact with the input JSON and // correspondingly calls the facade associated with the input JSON doc. This // class also contains wrapper functions to the actual SL4N Facades and does @@ -30,6 +32,8 @@ class CommandReceiver { CommandReceiver(); ~CommandReceiver(); + static void RegisterCommand(std::string name, MFP command); + // Function that extracts the method/cmd parameter from the JSON doc and // passes the document to the corresponding wrapper function. void Call(rapidjson::Document& doc); |