2016-09-29 18:03:59 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
#include "failure_reason_util.h"
|
|
|
|
#include "wifi_legacy_hal.h"
|
|
|
|
|
|
|
|
#include <android-base/logging.h>
|
|
|
|
#include <cutils/properties.h>
|
2016-10-03 22:33:23 +02:00
|
|
|
#include <wifi_system/hal_tool.h>
|
|
|
|
#include <wifi_system/interface_tool.h>
|
2016-09-29 18:03:59 +02:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
std::string getWlanInterfaceName() {
|
|
|
|
char buffer[PROPERTY_VALUE_MAX];
|
|
|
|
property_get("wifi.interface", buffer, "wlan0");
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Legacy HAL functions accept "C" style function pointers, so use global
|
|
|
|
// functions to pass to the legacy HAL function and store the corresponding
|
|
|
|
// std::function methods to be invoked.
|
|
|
|
// Callback to be invoked once |stop| is complete.
|
|
|
|
std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
|
|
|
|
void onStopComplete(wifi_handle handle) {
|
|
|
|
if (on_stop_complete_internal_callback) {
|
|
|
|
on_stop_complete_internal_callback(handle);
|
|
|
|
}
|
|
|
|
}
|
2016-10-03 23:09:57 +02:00
|
|
|
|
|
|
|
// Callback to be invoked for driver dump.
|
|
|
|
std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
|
|
|
|
void onDriverMemoryDump(char* buffer, int buffer_size) {
|
|
|
|
if (on_driver_memory_dump_internal_callback) {
|
|
|
|
on_driver_memory_dump_internal_callback(buffer, buffer_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Callback to be invoked for firmware dump.
|
|
|
|
std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
|
|
|
|
void onFirmwareMemoryDump(char* buffer, int buffer_size) {
|
|
|
|
if (on_firmware_memory_dump_internal_callback) {
|
|
|
|
on_firmware_memory_dump_internal_callback(buffer, buffer_size);
|
|
|
|
}
|
|
|
|
}
|
2016-09-29 18:03:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace android {
|
|
|
|
namespace hardware {
|
|
|
|
namespace wifi {
|
|
|
|
namespace V1_0 {
|
|
|
|
namespace implementation {
|
|
|
|
|
2016-10-03 21:49:58 +02:00
|
|
|
const uint32_t WifiLegacyHal::kMaxVersionStringLength = 256;
|
|
|
|
|
2016-09-29 18:03:59 +02:00
|
|
|
WifiLegacyHal::WifiLegacyHal()
|
|
|
|
: global_handle_(nullptr),
|
|
|
|
wlan_interface_handle_(nullptr),
|
2016-10-03 22:33:23 +02:00
|
|
|
awaiting_event_loop_termination_(false) {}
|
2016-09-29 18:03:59 +02:00
|
|
|
|
|
|
|
wifi_error WifiLegacyHal::start() {
|
|
|
|
// Ensure that we're starting in a good state.
|
|
|
|
CHECK(!global_handle_ && !wlan_interface_handle_ &&
|
|
|
|
!awaiting_event_loop_termination_);
|
|
|
|
|
2016-10-03 22:33:23 +02:00
|
|
|
android::wifi_system::HalTool hal_tool;
|
|
|
|
android::wifi_system::InterfaceTool if_tool;
|
|
|
|
if (!hal_tool.InitFunctionTable(&global_func_table_)) {
|
|
|
|
LOG(ERROR) << "Failed to initialize legacy hal function table";
|
|
|
|
return WIFI_ERROR_UNKNOWN;
|
|
|
|
}
|
|
|
|
if (!if_tool.SetWifiUpState(true)) {
|
|
|
|
LOG(ERROR) << "Failed to set WiFi interface up";
|
|
|
|
return WIFI_ERROR_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2016-09-29 18:03:59 +02:00
|
|
|
LOG(INFO) << "Starting legacy HAL";
|
|
|
|
wifi_error status = global_func_table_.wifi_initialize(&global_handle_);
|
|
|
|
if (status != WIFI_SUCCESS || !global_handle_) {
|
|
|
|
LOG(ERROR) << "Failed to retrieve global handle";
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
event_loop_thread_ = std::thread(&WifiLegacyHal::runEventLoop, this);
|
|
|
|
status = retrieveWlanInterfaceHandle();
|
|
|
|
if (status != WIFI_SUCCESS || !wlan_interface_handle_) {
|
|
|
|
LOG(ERROR) << "Failed to retrieve wlan interface handle";
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
LOG(VERBOSE) << "Legacy HAL start complete";
|
|
|
|
return WIFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
wifi_error WifiLegacyHal::stop(
|
|
|
|
const std::function<void()>& on_stop_complete_user_callback) {
|
|
|
|
LOG(INFO) << "Stopping legacy HAL";
|
|
|
|
on_stop_complete_internal_callback = [&](wifi_handle handle) {
|
|
|
|
CHECK_EQ(global_handle_, handle) << "Handle mismatch";
|
|
|
|
on_stop_complete_user_callback();
|
|
|
|
global_handle_ = nullptr;
|
|
|
|
wlan_interface_handle_ = nullptr;
|
|
|
|
on_stop_complete_internal_callback = nullptr;
|
|
|
|
};
|
|
|
|
awaiting_event_loop_termination_ = true;
|
|
|
|
global_func_table_.wifi_cleanup(global_handle_, onStopComplete);
|
|
|
|
LOG(VERBOSE) << "Legacy HAL stop initiated";
|
|
|
|
return WIFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2016-10-03 21:49:58 +02:00
|
|
|
std::pair<wifi_error, std::string> WifiLegacyHal::getWlanDriverVersion() {
|
|
|
|
std::array<char, kMaxVersionStringLength> buffer;
|
|
|
|
buffer.fill(0);
|
|
|
|
wifi_error status = global_func_table_.wifi_get_driver_version(
|
|
|
|
wlan_interface_handle_, buffer.data(), buffer.size());
|
|
|
|
return std::make_pair(status, buffer.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<wifi_error, std::string> WifiLegacyHal::getWlanFirmwareVersion() {
|
|
|
|
std::array<char, kMaxVersionStringLength> buffer;
|
|
|
|
buffer.fill(0);
|
|
|
|
wifi_error status = global_func_table_.wifi_get_firmware_version(
|
|
|
|
wlan_interface_handle_, buffer.data(), buffer.size());
|
|
|
|
return std::make_pair(status, buffer.data());
|
|
|
|
}
|
|
|
|
|
2016-10-03 23:09:57 +02:00
|
|
|
std::pair<wifi_error, std::vector<char>>
|
|
|
|
WifiLegacyHal::requestWlanDriverMemoryDump() {
|
|
|
|
std::vector<char> driver_dump;
|
|
|
|
on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer,
|
|
|
|
int buffer_size) {
|
|
|
|
driver_dump.insert(driver_dump.end(), buffer, buffer + buffer_size);
|
|
|
|
};
|
|
|
|
wifi_error status = global_func_table_.wifi_get_driver_memory_dump(
|
|
|
|
wlan_interface_handle_, {onDriverMemoryDump});
|
|
|
|
on_driver_memory_dump_internal_callback = nullptr;
|
|
|
|
return std::make_pair(status, std::move(driver_dump));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<wifi_error, std::vector<char>>
|
|
|
|
WifiLegacyHal::requestWlanFirmwareMemoryDump() {
|
|
|
|
std::vector<char> firmware_dump;
|
|
|
|
on_firmware_memory_dump_internal_callback = [&firmware_dump](
|
|
|
|
char* buffer, int buffer_size) {
|
|
|
|
firmware_dump.insert(firmware_dump.end(), buffer, buffer + buffer_size);
|
|
|
|
};
|
|
|
|
wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
|
|
|
|
wlan_interface_handle_, {onFirmwareMemoryDump});
|
|
|
|
on_firmware_memory_dump_internal_callback = nullptr;
|
|
|
|
return std::make_pair(status, std::move(firmware_dump));
|
|
|
|
}
|
|
|
|
|
2016-09-29 18:03:59 +02:00
|
|
|
wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() {
|
|
|
|
const std::string& ifname_to_find = getWlanInterfaceName();
|
|
|
|
|
|
|
|
wifi_interface_handle* iface_handles = nullptr;
|
|
|
|
int num_iface_handles = 0;
|
|
|
|
wifi_error status = global_func_table_.wifi_get_ifaces(
|
|
|
|
global_handle_, &num_iface_handles, &iface_handles);
|
|
|
|
if (status != WIFI_SUCCESS) {
|
|
|
|
LOG(ERROR) << "Failed to enumerate interface handles: "
|
|
|
|
<< LegacyErrorToString(status);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < num_iface_handles; ++i) {
|
|
|
|
std::array<char, IFNAMSIZ> current_ifname;
|
|
|
|
current_ifname.fill(0);
|
|
|
|
status = global_func_table_.wifi_get_iface_name(
|
|
|
|
iface_handles[i], current_ifname.data(), current_ifname.size());
|
|
|
|
if (status != WIFI_SUCCESS) {
|
|
|
|
LOG(WARNING) << "Failed to get interface handle name: "
|
|
|
|
<< LegacyErrorToString(status);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (ifname_to_find == current_ifname.data()) {
|
|
|
|
wlan_interface_handle_ = iface_handles[i];
|
|
|
|
return WIFI_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return WIFI_ERROR_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WifiLegacyHal::runEventLoop() {
|
|
|
|
LOG(VERBOSE) << "Starting legacy HAL event loop";
|
|
|
|
global_func_table_.wifi_event_loop(global_handle_);
|
|
|
|
if (!awaiting_event_loop_termination_) {
|
|
|
|
LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
|
|
|
|
}
|
|
|
|
LOG(VERBOSE) << "Legacy HAL event loop terminated";
|
|
|
|
awaiting_event_loop_termination_ = false;
|
2016-10-03 22:33:23 +02:00
|
|
|
android::wifi_system::InterfaceTool if_tool;
|
|
|
|
if_tool.SetWifiUpState(false);
|
2016-09-29 18:03:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace implementation
|
|
|
|
} // namespace V1_0
|
|
|
|
} // namespace wifi
|
|
|
|
} // namespace hardware
|
|
|
|
} // namespace android
|