summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qcwcn/wifi_hal/common.h4
-rw-r--r--qcwcn/wifi_hal/wifi_hal.cpp5
-rw-r--r--qcwcn/wifi_hal/wificonfig.cpp121
3 files changed, 130 insertions, 0 deletions
diff --git a/qcwcn/wifi_hal/common.h b/qcwcn/wifi_hal/common.h
index c545ca1..43b03ce 100644
--- a/qcwcn/wifi_hal/common.h
+++ b/qcwcn/wifi_hal/common.h
@@ -208,6 +208,10 @@ wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle i
wifi_error wifi_set_radio_mode_change_handler(wifi_request_id id, wifi_interface_handle
iface, wifi_radio_mode_change_handler eh);
wifi_error mapKernelErrortoWifiHalError(int kern_err);
+void wifi_cleanup_dynamic_ifaces(wifi_handle handle);
+wifi_error wifi_virtual_interface_create(wifi_handle handle, const char* ifname,
+ wifi_interface_type iface_type);
+wifi_error wifi_virtual_interface_delete(wifi_handle handle, const char* ifname);
// some common macros
#define min(x, y) ((x) < (y) ? (x) : (y))
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 2bf7937..7b85099 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -571,6 +571,8 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
+ fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
+ fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
fn->wifi_set_latency_mode = wifi_set_latency_mode;
fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
@@ -1042,6 +1044,9 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
hal_info *info = getHalInfo(handle);
info->cleaned_up_handler = handler;
info->clean_up = true;
+ // Remove the dynamically created interface during wifi cleanup.
+ wifi_cleanup_dynamic_ifaces(handle);
+
TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
ALOGI("Sent msg on exit sock to unblock poll()");
diff --git a/qcwcn/wifi_hal/wificonfig.cpp b/qcwcn/wifi_hal/wificonfig.cpp
index 7590f62..8ab296a 100644
--- a/qcwcn/wifi_hal/wificonfig.cpp
+++ b/qcwcn/wifi_hal/wificonfig.cpp
@@ -33,6 +33,9 @@
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string>
+#include <net/if.h>
+#include <vector>
#include "wificonfigcommand.h"
/* Implementation of the API functions exposed in wifi_config.h */
@@ -788,3 +791,121 @@ out:
return res;
}
+static std::vector<std::string> added_ifaces;
+
+static bool is_dynamic_interface(const char * ifname)
+{
+ for (const auto& iface : added_ifaces) {
+ if (iface == std::string(ifname))
+ return true;
+ }
+ return false;
+}
+
+void wifi_cleanup_dynamic_ifaces(wifi_handle handle)
+{
+ int len = added_ifaces.size();
+ while (len--) {
+ wifi_virtual_interface_delete(handle, added_ifaces.front().c_str());
+ }
+ added_ifaces.clear(); // could be redundent. But to be on safe side.
+}
+
+wifi_error wifi_virtual_interface_create(wifi_handle handle,
+ const char* ifname,
+ wifi_interface_type iface_type)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ u32 wlan0_id = if_nametoindex("wlan0");
+ if (!handle || !wlan0_id) {
+ ALOGE("%s: Error wifi_handle NULL or wlan0 not present", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGD("%s: ifname=%s create", __FUNCTION__, ifname);
+ // Do not create interface if already exist.
+ if (if_nametoindex(ifname))
+ return WIFI_SUCCESS;
+
+ wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nl80211_iftype type;
+ switch(iface_type) {
+ case WIFI_INTERFACE_TYPE_STA: /* IfaceType:STA */
+ type = NL80211_IFTYPE_STATION;
+ break;
+ case WIFI_INTERFACE_TYPE_AP: /* IfaceType:AP */
+ type = NL80211_IFTYPE_AP;
+ break;
+ case WIFI_INTERFACE_TYPE_P2P: /* IfaceType:P2P */
+ type = NL80211_IFTYPE_P2P_DEVICE;
+ break;
+ case WIFI_INTERFACE_TYPE_NAN: /* IfaceType:NAN */
+ type = NL80211_IFTYPE_NAN;
+ break;
+ default:
+ ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto done;
+ break;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_NEW_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, wlan0_id);
+ wifiConfigCommand->put_string(NL80211_ATTR_IFNAME, ifname);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type);
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
+ }
+ // Update dynamic interface list
+ added_ifaces.push_back(std::string(ifname));
+
+done:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+wifi_error wifi_virtual_interface_delete(wifi_handle handle,
+ const char* ifname)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ u32 wlan0_id = if_nametoindex("wlan0");
+
+ if (!handle || !wlan0_id) {
+ ALOGE("%s: Error wifi_handle NULL or wlan0 not present", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGD("%s: ifname=%s delete", __FUNCTION__, ifname);
+ if (if_nametoindex(ifname) && !is_dynamic_interface(ifname)) {
+ // Do not remove interface if it was not added dynamically.
+ return WIFI_SUCCESS;
+ }
+ wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
+ }
+ // Update dynamic interface list
+ added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)),
+ added_ifaces.end());
+
+ delete wifiConfigCommand;
+ return ret;
+}