Merge "Merge Android 12"
diff --git a/bcmdhd/wifi_hal/Android.mk b/bcmdhd/wifi_hal/Android.mk
index 6b79524..580a730 100755
--- a/bcmdhd/wifi_hal/Android.mk
+++ b/bcmdhd/wifi_hal/Android.mk
@@ -41,6 +41,12 @@
LOCAL_HEADER_LIBRARIES := libutils_headers liblog_headers
+ifneq ($(wildcard vendor/google/libraries/GoogleWifiConfigLib),)
+LOCAL_SHARED_LIBRARIES += \
+ google_wifi_firmware_config_version_c_wrapper
+LOCAL_CFLAGS += -DGOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
+endif
+
LOCAL_SRC_FILES := \
wifi_hal.cpp \
rtt.cpp \
@@ -50,7 +56,8 @@
nan.cpp \
link_layer_stats.cpp \
wifi_logger.cpp \
- wifi_offload.cpp
+ wifi_offload.cpp \
+ twt.cpp
LOCAL_MODULE := libwifi-hal-bcm
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
diff --git a/bcmdhd/wifi_hal/brcm_version.h b/bcmdhd/wifi_hal/brcm_version.h
index 14efbee..184d5d5 100755
--- a/bcmdhd/wifi_hal/brcm_version.h
+++ b/bcmdhd/wifi_hal/brcm_version.h
@@ -1 +1 @@
-#define HAL_VERSION "Android-10-FRC2-SDK_29 59.0 (r854927) 2019-12-06 23:33:52 +0530 (Fri, 06 Dec 2019)"
+#define HAL_VERSION "BCMDHD vendor HAL"
diff --git a/bcmdhd/wifi_hal/common.cpp b/bcmdhd/wifi_hal/common.cpp
index c164ba4..887b530 100755
--- a/bcmdhd/wifi_hal/common.cpp
+++ b/bcmdhd/wifi_hal/common.cpp
@@ -105,14 +105,34 @@
wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
if (info->num_event_cb < info->alloc_event_cb) {
- info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR;
- info->event_cb[info->num_event_cb].vendor_id = id;
- info->event_cb[info->num_event_cb].vendor_subcmd = subcmd;
- info->event_cb[info->num_event_cb].cb_func = func;
- info->event_cb[info->num_event_cb].cb_arg = arg;
- ALOGV("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d",
- arg, func, id, subcmd, info->num_event_cb);
- info->num_event_cb++;
+ /* To avoid an unwanted duplication of the record, find first.
+ * Update it if the same record is already exist.
+ * KEY => [nl_cmd, vendor_id, vendor_subcmd]
+ */
+ int i = 0;
+ bool is_update = false;
+ for (i = 0; i < info->num_event_cb; i++) {
+ if ((info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR) &&
+ (info->event_cb[i].vendor_id == id) &&
+ (info->event_cb[i].vendor_subcmd == subcmd)) {
+ is_update = true;
+ break;
+ }
+ }
+
+ if (is_update) {
+ info->event_cb[i].cb_func = func;
+ info->event_cb[i].cb_arg = arg;
+ } else {
+ info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR;
+ info->event_cb[info->num_event_cb].vendor_id = id;
+ info->event_cb[info->num_event_cb].vendor_subcmd = subcmd;
+ info->event_cb[info->num_event_cb].cb_func = func;
+ info->event_cb[info->num_event_cb].cb_arg = arg;
+ info->num_event_cb++;
+ }
+ ALOGI("%s ""event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d",
+ is_update ? "Updated" : "Added", arg, func, id, subcmd, info->num_event_cb);
result = WIFI_SUCCESS;
}
@@ -157,7 +177,7 @@
if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
&& info->event_cb[i].vendor_id == id
&& info->event_cb[i].vendor_subcmd == subcmd) {
- ALOGV("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d",
+ ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d",
info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i);
memmove(&info->event_cb[i], &info->event_cb[i+1],
(info->num_event_cb - i - 1) * sizeof(cb_info));
@@ -263,6 +283,19 @@
return WIFI_ERROR_INVALID_ARGS;
}
+wifi_error wifi_get_cancel_cmd(wifi_request_id id, wifi_interface_handle iface)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ WifiCommand *cmd = wifi_get_cmd(handle, id);
+ ALOGV("Get Cancel WifiCommand = %p", cmd);
+ if (cmd) {
+ cmd->cancel();
+ cmd->releaseRef();
+ return WIFI_SUCCESS;
+ }
+
+ return WIFI_ERROR_INVALID_ARGS;
+}
void set_hautil_mode(bool util_mode)
{
halutil_mode = util_mode;
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index 98801b2..d5bc971 100755
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -44,6 +44,7 @@
*/
const uint32_t GOOGLE_OUI = 0x001A11;
+const uint32_t BRCM_OUI = 0x001018;
/* TODO: define vendor OUI here */
@@ -54,6 +55,7 @@
#define NMRSTR "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
#define NAN_MASTER_RANK_LEN 8
+#define SAR_CONFIG_SCENARIO_COUNT 100
/*
This enum defines ranges for various commands; commands themselves
@@ -102,8 +104,40 @@
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
/* define all tx power related commands between 0x1900 and 0x1910 */
- ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START = 0x1900,
- ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_END = 0x1910,
+ ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START = 0x1900,
+ ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_END = 0x1910,
+
+ /* define all thermal mode related commands between 0x1920 and 0x192F */
+ ANDROID_NL80211_SUBCMD_MITIGATION_RANGE_START = 0x1920,
+ ANDROID_NL80211_SUBCMD_MITIGATION_RANGE_END = 0x192F,
+
+ /* define all DSCP related commands between 0x2000 and 0x20FF */
+ ANDROID_NL80211_SUBCMD_DSCP_RANGE_START = 0x2000,
+ ANDROID_NL80211_SUBCMD_DSCP_RANGE_END = 0x20FF,
+
+ /* define all Channel Avoidance related commands between 0x2100 and 0x211F */
+ ANDROID_NL80211_SUBCMD_CHAVOID_RANGE_START = 0x2100,
+ ANDROID_NL80211_SUBCMD_CHAVOID_RANGE_END = 0x211F,
+
+ /* define all OTA Download related commands between 0x2120 and 0x212F */
+ ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_START = 0x2120,
+ ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_END = 0x212F,
+
+ /* define all VOIP mode config related commands between 0x2130 and 0x213F */
+ ANDROID_NL80211_SUBCMD_VIOP_MODE_START = 0x2130,
+ ANDROID_NL80211_SUBCMD_VIOP_MODE_END = 0x213F,
+
+ /* define all TWT related commands between 0x2140 and 0x214F */
+ ANDROID_NL80211_SUBCMD_TWT_START = 0x2140,
+ ANDROID_NL80211_SUBCMD_TWT_END = 0x214F,
+
+ /* define all Usable Channel related commands between 0x2150 and 0x215F */
+ ANDROID_NL80211_SUBCMD_USABLE_CHANNEL_START = 0x2150,
+ ANDROID_NL80211_SUBCMD_USABLE_CHANNEL_END = 0x215F,
+
+ /* define all init/deinit related commands between 0x2160 and 0x216F */
+ ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_START = 0x2160,
+ ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_END = 0x216F,
/* This is reserved for future usage */
@@ -147,6 +181,9 @@
WIFI_SUBCMD_FW_ROAM_POLICY, /* 0x1019 */
WIFI_SUBCMD_ROAM_CAPABILITY, /* 0x101a */
WIFI_SUBCMD_SET_LATENCY_MODE, /* 0x101b */
+ WIFI_SUBCMD_SET_MULTISTA_PRIMARY_CONNECTION, /* 0x101c */
+ WIFI_SUBCMD_SET_MULTISTA_USE_CASE, /* 0x101d */
+ WIFI_SUBCMD_SET_DTIM_CONFIG, /* 0x101e */
GSCAN_SUBCMD_MAX,
@@ -172,7 +209,27 @@
NAN_SUBCMD_ENABLE_MERGE, /* 0x1712 */
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
APF_SUBCMD_SET_FILTER,
+ APF_SUBCMD_READ_FILTER,
WIFI_SUBCMD_TX_POWER_SCENARIO = ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START,
+ WIFI_SUBCMD_THERMAL_MITIGATION = ANDROID_NL80211_SUBCMD_MITIGATION_RANGE_START,
+ DSCP_SUBCMD_SET_TABLE = ANDROID_NL80211_SUBCMD_DSCP_RANGE_START,
+ DSCP_SUBCMD_RESET_TABLE, /* 0x2001 */
+ CHAVOID_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_CHAVOID_RANGE_START,
+
+ TWT_SUBCMD_GETCAPABILITY = ANDROID_NL80211_SUBCMD_TWT_START,
+ TWT_SUBCMD_SETUP_REQUEST,
+ TWT_SUBCMD_TEAR_DOWN_REQUEST,
+ TWT_SUBCMD_INFO_FRAME_REQUEST,
+ TWT_SUBCMD_GETSTATS,
+ TWT_SUBCMD_CLR_STATS,
+
+ WIFI_SUBCMD_CONFIG_VOIP_MODE = ANDROID_NL80211_SUBCMD_VIOP_MODE_START,
+
+ WIFI_SUBCMD_GET_OTA_CURRUNT_INFO = ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_START,
+ WIFI_SUBCMD_OTA_UPDATE,
+ WIFI_SUBCMD_USABLE_CHANNEL = ANDROID_NL80211_SUBCMD_USABLE_CHANNEL_START,
+ WIFI_SUBCMD_TRIGGER_SSR = ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_START,
+
} WIFI_SUB_COMMAND;
typedef enum {
@@ -212,10 +269,14 @@
NAN_EVENT_SDF = 28,
NAN_EVENT_TCA = 29,
NAN_EVENT_SUBSCRIBE_UNMATCH = 30,
- NAN_EVENT_UNKNOWN,
+ NAN_EVENT_UNKNOWN = 31,
+ BRCM_VENDOR_EVENT_HANGED = 33,
ROAM_EVENT_START,
GOOGLE_FILE_DUMP_EVENT = 37,
- NAN_ASYNC_RESPONSE_DISABLED = 40
+ NAN_ASYNC_RESPONSE_DISABLED = 40,
+ BRCM_VENDOR_EVENT_TWT = 43,
+ BRCM_TPUT_DUMP_EVENT = 44,
+ NAN_EVENT_MATCH_EXPIRY = 45
} WIFI_EVENT;
typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
@@ -239,6 +300,7 @@
wifi_handle handle; // handle to wifi data
char name[IFNAMSIZ+1]; // interface name + trailing null
int id; // id to use when talking to driver
+ bool is_virtual; // mark each iface as virtual or static
} interface_info;
typedef struct {
@@ -265,6 +327,8 @@
interface_info **interfaces; // array of interfaces
int num_interfaces; // number of interfaces
+ int max_num_interfaces; // max number of interfaces
+ wifi_subsystem_restart_handler restart_handler; // trigger sub system handler
// add other details
@@ -302,6 +366,59 @@
u8 ie_data[1]; // IE data to follow
} wifi_gscan_full_result_t;
+void twt_deinit_handler();
+
+typedef enum {
+ TWT_EVENT_INVALID = 0,
+ TWT_SETUP_RESPONSE = 1,
+ TWT_TEARDOWN_COMPLETION = 2,
+ TWT_INFORM_FRAME = 3,
+ TWT_NOTIFY = 4,
+ TWT_EVENT_LAST
+} TwtEventType;
+
+typedef enum {
+ TWT_INVALID = 0,
+ TWT_SETUP_REQUEST = 1,
+ TWT_INFO_FRAME_REQUEST = 2,
+ TWT_TEAR_DOWN_REQUEST = 3,
+ TWT_LAST
+} TwtRequestType;
+
+typedef enum {
+ TWT_ATTRIBUTE_INVALID = 0,
+ TWT_ATTRIBUTE_CONFIG_ID = 1,
+ TWT_ATTRIBUTE_NEG_TYPE = 2,
+ TWT_ATTRIBUTE_TRIGGER_TYPE = 3,
+ TWT_ATTRIBUTE_WAKE_DUR_US = 4,
+ TWT_ATTRIBUTE_WAKE_INT_US = 5,
+ TWT_ATTRIBUTE_WAKE_INT_MIN_US = 6,
+ TWT_ATTRIBUTE_WAKE_INT_MAX_US = 7,
+ TWT_ATTRIBUTE_WAKE_DUR_MIN_US = 8,
+ TWT_ATTRIBUTE_WAKE_DUR_MAX_US = 9,
+ TWT_ATTRIBUTE_AVG_PKT_SIZE = 10,
+ TWT_ATTRIBUTE_AVG_PKT_NUM = 11,
+ TWT_ATTRIBUTE_WAKE_TIME_OFF_US = 12,
+ TWT_ATTRIBUTE_ALL_TWT = 13,
+ TWT_ATTRIBUTE_RESUME_TIME_US = 14,
+ TWT_ATTRIBUTE_AVG_EOSP_DUR = 15,
+ TWT_ATTRIBUTE_EOSP_COUNT = 16,
+ TWT_ATTRIBUTE_NUM_SP = 17,
+ TWT_ATTRIBUTE_DEVICE_CAP = 18,
+ TWT_ATTRIBUTE_PEER_CAP = 19,
+ TWT_ATTRIBUTE_STATUS = 20,
+ TWT_ATTRIBUTE_REASON_CODE = 21,
+ TWT_ATTRIBUTE_RESUMED = 22,
+ TWT_ATTRIBUTE_NOTIFICATION = 23,
+ TWT_ATTRIBUTE_SUB_EVENT = 24,
+ TWT_ATTRIBUTE_NUM_PEER_STATS = 25,
+ TWT_ATTRIBUTE_AVG_PKT_NUM_TX = 26,
+ TWT_ATTRIBUTE_AVG_PKT_SIZE_TX = 27,
+ TWT_ATTRIBUTE_AVG_PKT_NUM_RX = 28,
+ TWT_ATTRIBUTE_AVG_PKT_SIZE_RX = 29,
+ TWT_ATTRIBUTE_MAX
+} TWT_ATTRIBUTE;
+
wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg);
wifi_error wifi_register_vendor_handler(wifi_handle handle,
uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg);
@@ -321,18 +438,91 @@
wifi_handle getWifiHandle(hal_info *info);
wifi_interface_handle getIfaceHandle(interface_info *info);
wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface);
+wifi_error wifi_get_cancel_cmd(wifi_request_id id, wifi_interface_handle iface);
wifi_error nan_deinit_handler();
wifi_error wifi_start_hal(wifi_interface_handle iface);
wifi_error wifi_stop_hal(wifi_interface_handle iface);
wifi_interface_handle wifi_get_wlan_interface(wifi_handle info,
wifi_interface_handle *ifaceHandles, int numIfaceHandles);
+wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version);
wifi_error wifi_hal_preInit(wifi_interface_handle iface);
/* API to get wake reason statistics */
wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
+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);
+wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle, u32 num_channels,
+ wifi_coex_unsafe_channel channels[], u32 restrictions);
+wifi_error wifi_set_voip_mode(wifi_interface_handle handle, wifi_voip_mode mode);
+wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier);
void set_hautil_mode(bool halutil_mode);
bool get_halutil_mode();
+/* API's to support TWT */
+
+/**@brief twt_get_capability
+ * Request TWT capability
+ * @param wifi_interface_handle:
+ * @return Synchronous wifi_error and TwtCapabilitySet
+ */
+wifi_error twt_get_capability(wifi_interface_handle iface, TwtCapabilitySet* twt_cap_set);
+
+/**@brief twt_register_handler
+ * Request to register TWT callback
+ * @param wifi_interface_handle:
+ * @param TwtCallbackHandler:
+ * @return Synchronous wifi_error
+ */
+wifi_error twt_register_handler(wifi_interface_handle iface, TwtCallbackHandler handler);
+
+/**@brief twt_setup_request
+ * Request to send TWT setup frame
+ * @param wifi_interface_handle:
+ * @param TwtSetupRequest:
+ * @return Synchronous wifi_error
+ * @return Asynchronous EventTwtSetupResponse CB return TwtSetupResponse
+ */
+wifi_error twt_setup_request(wifi_interface_handle iface, TwtSetupRequest* msg);
+
+/**@brief twt_teardown_request
+ * Request to send TWT teardown frame
+ * @param wifi_interface_handle:
+ * @param TwtTeardownRequest:
+ * @return Synchronous wifi_error
+ * @return Asynchronous EventTwtTeardownCompletion CB return TwtTeardownCompletion
+ * TwtTeardownCompletion may also be received due to other events
+ * like CSA, BTCX, TWT scheduler, MultiConnection, peer-initiated teardown, etc.
+ */
+wifi_error twt_teardown_request(wifi_interface_handle iface, TwtTeardownRequest* msg);
+
+/**@brief twt_info_frame_request
+ * Request to send TWT info frame
+ * @param wifi_interface_handle:
+ * @param TwtInfoFrameRequest:
+ * @return Synchronous wifi_error
+ * @return Asynchronous EventTwtInfoFrameReceived CB return TwtInfoFrameReceived
+ * Driver may also receive Peer-initiated TwtInfoFrame
+ */
+wifi_error twt_info_frame_request(wifi_interface_handle iface, TwtInfoFrameRequest* msg);
+
+/**@brief twt_get_stats
+ * Request to get TWT stats
+ * @param wifi_interface_handle:
+ * @param config_id:
+ * @return Synchronous wifi_error and TwtStats
+ */
+wifi_error twt_get_stats(wifi_interface_handle iface, u8 config_id, TwtStats* stats);
+
+/**@brief twt_clear_stats
+ * Request to clear TWT stats
+ * @param wifi_interface_handle:
+ * @param config_id:
+ * @return Synchronous wifi_error
+ */
+wifi_error twt_clear_stats(wifi_interface_handle iface, u8 config_id);
+
+wifi_error wifi_trigger_subsystem_restart(wifi_handle handle);
// some common macros
#define min(x, y) ((x) < (y) ? (x) : (y))
diff --git a/bcmdhd/wifi_hal/cpp_bindings.cpp b/bcmdhd/wifi_hal/cpp_bindings.cpp
index 5ca6431..698789d 100755
--- a/bcmdhd/wifi_hal/cpp_bindings.cpp
+++ b/bcmdhd/wifi_hal/cpp_bindings.cpp
@@ -619,7 +619,7 @@
int WifiCommand::requestResponse(WifiRequest& request) {
pthread_mutex_lock(&ResponseMutex);
- int err = 0, res = 0;
+ int err = 0;
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb)
diff --git a/bcmdhd/wifi_hal/cpp_bindings.h b/bcmdhd/wifi_hal/cpp_bindings.h
index 8839a72..456f31c 100755
--- a/bcmdhd/wifi_hal/cpp_bindings.h
+++ b/bcmdhd/wifi_hal/cpp_bindings.h
@@ -126,7 +126,7 @@
return pos;
}
uint16_t get_type() {
- return pos->nla_type;
+ return nla_type(pos);
}
uint8_t get_u8() {
return nla_get_u8(pos);
@@ -278,7 +278,7 @@
virtual void addRef() {
int refs = __sync_add_and_fetch(&mRefs, 1);
- // ALOGD("addRef: WifiCommand %p has %d references", this, refs);
+ ALOGV("addRef: WifiCommand %p has %d references", this, refs);
}
virtual void releaseRef() {
diff --git a/bcmdhd/wifi_hal/gscan.cpp b/bcmdhd/wifi_hal/gscan.cpp
index f5722f2..f012423 100755
--- a/bcmdhd/wifi_hal/gscan.cpp
+++ b/bcmdhd/wifi_hal/gscan.cpp
@@ -235,7 +235,7 @@
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
- ALOGV("Id = %0x, subcmd = 0x%x, len = %d, expected len = %zd", id, subcmd, len,
+ ALOGV("Id = %0x, subcmd = 0x%x, len = %d, expected len = %d", id, subcmd, len,
mRequestsize);
memcpy(mCapabilities, data, min(len, mRequestsize));
@@ -252,6 +252,7 @@
return (wifi_error) command.requestResponse();
}
+/* Function to get chipset supported roaming capabilities */
wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle,
wifi_roaming_capabilities *capabilities)
{
@@ -345,48 +346,6 @@
/////////////////////////////////////////////////////////////////////////////
/* helper functions */
-
-static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
-{
- memset(results, 0, sizeof(wifi_scan_result) * num);
-
- int i = 0;
- for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
-
- int index = it.get_type();
- ALOGI("retrieved scan result %d", index);
- nlattr *sc_data = (nlattr *) it.get_data();
- wifi_scan_result *result = results + i;
-
- for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
- int type = it2.get_type();
- if (type == GSCAN_ATTRIBUTE_SSID) {
- strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
- result->ssid[it2.get_len()] = 0;
- } else if (type == GSCAN_ATTRIBUTE_BSSID) {
- memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
- } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
- result->ts = it2.get_u64();
- } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
- result->ts = it2.get_u16();
- } else if (type == GSCAN_ATTRIBUTE_RSSI) {
- result->rssi = it2.get_u8();
- } else if (type == GSCAN_ATTRIBUTE_RTT) {
- result->rtt = it2.get_u64();
- } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
- result->rtt_sd = it2.get_u64();
- }
- }
-
- }
-
- if (i >= num) {
- ALOGE("Got too many results; skipping some");
- }
-
- return i;
-}
-
int createFeatureRequest(WifiRequest& request, int subcmd, int enable) {
int result = request.create(GOOGLE_OUI, subcmd);
@@ -413,7 +372,7 @@
FullScanResultsCommand(wifi_interface_handle iface, int id, int *params,
wifi_scan_result_handler handler)
: WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler)
- { }
+ {*mParams = 0;}
int createRequest(WifiRequest& request, int subcmd, int enable) {
int result = request.create(GOOGLE_OUI, subcmd);
@@ -616,6 +575,10 @@
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
+
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
ALOGE("failed to configure setup; result = %d", result);
@@ -644,10 +607,6 @@
return result;
}
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
ALOGE("failed to start scan; result = %d", result);
@@ -744,7 +703,6 @@
if (id == -1) {
wifi_scan_result_handler handler;
wifi_scan_cmd_params dummy_params;
- wifi_handle handle = getWifiHandle(iface);
memset(&handler, 0, sizeof(handler));
ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
@@ -803,7 +761,7 @@
wifi_gscan_result_t *fixed = &drv_res->fixed;
if ((ie_len + offsetof(wifi_gscan_full_result_t, ie_data)) > len) {
- ALOGE("BAD event data, len %d ie_len %d fixed length %d!\n", len,
+ ALOGE("BAD event data, len %d ie_len %d fixed length %lu!\n", len,
ie_len, offsetof(wifi_gscan_full_result_t, ie_data));
return NL_SKIP;
}
@@ -818,7 +776,7 @@
if(handler.on_full_scan_result)
handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket);
- ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %lld %lld %lld %x %d\n",
+ ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %ld %lx %lx %x %d\n",
fixed->ssid, fixed->bssid[0], fixed->bssid[1], fixed->bssid[2], fixed->bssid[3],
fixed->bssid[4], fixed->bssid[5], fixed->rssi, fixed->channel, fixed->ts,
fixed->rtt, fixed->rtt_sd, drv_res->scan_ch_bucket, drv_res->ie_length);
@@ -830,11 +788,9 @@
wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
{
ALOGV("Disabling full scan results");
- wifi_handle handle = getWifiHandle(iface);
if(id == -1) {
wifi_scan_result_handler handler;
- wifi_handle handle = getWifiHandle(iface);
int params_dummy;
memset(&handler, 0, sizeof(handler));
@@ -1109,6 +1065,9 @@
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
+
result = requestResponse(request);
if (result < 0) {
ALOGI("Failed to execute hotlist setup request, result = %d", result);
@@ -1123,9 +1082,6 @@
return result;
}
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
-
result = requestResponse(request);
if (result < 0) {
unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
@@ -1329,6 +1285,7 @@
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
result = requestResponse(request);
if (result < 0) {
ALOGI("Failed to execute ePNO setup request, result = %d", result);
@@ -1337,7 +1294,6 @@
}
ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
ALOGI("successfully restarted the scan");
return result;
}
@@ -1368,7 +1324,6 @@
virtual int handleEvent(WifiEvent& event) {
ALOGI("ePNO event");
- int event_id = event.get_vendor_subcmd();
// event.log();
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -1537,6 +1492,8 @@
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
+
result = requestResponse(request);
if (result < 0) {
ALOGI("failed to set significant wifi change config %d", result);
@@ -1550,8 +1507,6 @@
return result;
}
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
-
result = requestResponse(request);
if (result < 0) {
unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
@@ -1661,7 +1616,6 @@
{
if (id == -1) {
wifi_epno_handler handler;
- wifi_handle handle = getWifiHandle(iface);
memset(&handler, 0, sizeof(handler));
ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
@@ -1677,6 +1631,9 @@
const wifi_epno_params *params, wifi_epno_handler handler)
{
wifi_handle handle = getWifiHandle(iface);
+ if (handler.on_network_found == NULL) {
+ return WIFI_ERROR_INVALID_ARGS;
+ }
ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -1761,8 +1718,6 @@
wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
wifi_bssid_params params)
{
- wifi_handle handle = getWifiHandle(iface);
-
BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, ¶ms);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = (wifi_error)cmd->start();
@@ -2004,11 +1959,11 @@
ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
- ALOGI("%d\t", mResult->rssi);
- ALOGI("%d\t", mResult->channel);
- ALOGI("%lld\t", mResult->ts);
- ALOGI("%lld\t", mResult->rtt);
- ALOGI("%lld\n", mResult->rtt_sd);
+ ALOGI("rssi:%d\t", mResult->rssi);
+ ALOGI("channel:%d\t", mResult->channel);
+ ALOGI("ts:0x%jx\t", mResult->ts);
+ ALOGI("rtt:0x%jx\t", mResult->rtt);
+ ALOGI("rtt_sd:0x%jx\n", mResult->rtt_sd);
if(*mHandler.on_passpoint_network_found)
(*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
diff --git a/bcmdhd/wifi_hal/link_layer_stats.cpp b/bcmdhd/wifi_hal/link_layer_stats.cpp
index 34226f4..a2aabe3 100644
--- a/bcmdhd/wifi_hal/link_layer_stats.cpp
+++ b/bcmdhd/wifi_hal/link_layer_stats.cpp
@@ -37,7 +37,7 @@
#define LOG_TAG "WifiHAL"
-#include <log/log.h>
+#include <utils/Log.h>
#include "wifi_hal.h"
#include "common.h"
@@ -93,13 +93,14 @@
return NL_SKIP;
}
- int id = reply.get_vendor_id();
- int subcmd = reply.get_vendor_subcmd();
-
- // ALOGI("Id = %0x, subcmd = %d", id, subcmd);
+ int id = reply.get_vendor_id();
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
+ if (!data || !len) {
+ ALOGE("Invalid vendor data received");
+ return NL_SKIP;
+ }
wifi_radio_stat *radio_stat =
convertToExternalRadioStatStructure((wifi_radio_stat_internal *)data);
if (!radio_stat) {
@@ -117,7 +118,9 @@
private:
wifi_radio_stat *convertToExternalRadioStatStructure(wifi_radio_stat_internal *internal_stat_ptr) {
wifi_radio_stat *external_stat_ptr = NULL;
- if (internal_stat_ptr) {
+ if (!internal_stat_ptr) {
+ ALOGE("Sta_ptr is null\n");
+ } else {
uint32_t channel_size = internal_stat_ptr->num_channels * sizeof(wifi_channel_stat);
uint32_t total_size = sizeof(wifi_radio_stat) + channel_size;
external_stat_ptr = (wifi_radio_stat *)malloc(total_size);
diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp
index cfabfa8..0805128 100755
--- a/bcmdhd/wifi_hal/nan.cpp
+++ b/bcmdhd/wifi_hal/nan.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2019 Broadcom Limited
+ * Portions copyright (C) 2017 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -286,7 +286,9 @@
NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL = 224,
NAN_ATTRIBUTE_NSS = 225,
NAN_ATTRIBUTE_ENABLE_RANGING = 226,
- NAN_ATTRIBUTE_DW_EARLY_TERM = 227
+ NAN_ATTRIBUTE_DW_EARLY_TERM = 227,
+ NAN_ATTRIBUTE_CHANNEL_INFO = 228,
+ NAN_ATTRIBUTE_NUM_CHANNELS = 229
} NAN_ATTRIBUTE;
typedef enum {
@@ -310,7 +312,6 @@
NAN_DATA_PATH_IFACE_UP = 17,
NAN_DATA_PATH_SEC_INFO = 18,
NAN_VERSION_INFO = 19,
- NAN_REQUEST_ENABLE_MERGE = 20,
NAN_REQUEST_LAST = 0xFFFF
} NanRequestType;
@@ -381,41 +382,7 @@
static int get_svc_hash(unsigned char *svc_name, u16 svc_name_len,
u8 *svc_hash, u16 svc_hash_len);
NanResponseType get_response_type(WIFI_SUB_COMMAND nan_subcmd);
-static NanStatusType nan_map_term_status(u32 vendor_reason);
static NanStatusType nan_map_response_status(int vendor_status);
-static int ioctl_sock = 0;
-
-static int setFlags(int s, struct ifreq *ifr, int set, int clr)
-{
- if(ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
- return WIFI_ERROR_UNKNOWN;
- }
-
- ifr->ifr_flags = (ifr->ifr_flags & (~clr)) | set;
- if (ioctl(s, SIOCSIFFLAGS, ifr) < 0) {
- return WIFI_ERROR_UNKNOWN;
- }
-
- return WIFI_SUCCESS;
-}
-
-static inline void init_sockaddr_in(struct sockaddr_in *sin, const char *addr)
-{
- sin->sin_family = AF_INET;
- sin->sin_port = 0;
- sin->sin_addr.s_addr = inet_addr(addr);
-}
-
-static int setAddr(int s, struct ifreq *ifr, const char *addr)
-{
- init_sockaddr_in((struct sockaddr_in *) &ifr->ifr_addr, addr);
-
- if (ioctl(s, SIOCSIFADDR, ifr) < 0) {
- return WIFI_ERROR_UNKNOWN;
- }
-
- return WIFI_SUCCESS;
-}
/* Function to separate the common events to NAN1.0 events */
static int is_de_event(int cmd) {
@@ -429,6 +396,7 @@
case NAN_EVENT_FOLLOWUP:
case NAN_EVENT_TRANSMIT_FOLLOWUP_IND:
case NAN_EVENT_PUBLISH_REPLIED_IND:
+ case NAN_EVENT_MATCH_EXPIRY:
is_de_evt = true;
break;
default:
@@ -574,6 +542,30 @@
};
+void HandleExpiryEvent(nan_hal_info_t info, nlattr *vendor_data) {
+ ALOGI("Received NAN_EVENT_MATCH_EXPIRY\n");
+ u16 attr_type;
+ NanMatchExpiredInd expired_event;
+ memset(&expired_event, 0, sizeof(NanMatchExpiredInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ expired_event.publish_subscribe_id = it.get_u16();
+ ALOGI("pub_sub id = %u\n",
+ expired_event.publish_subscribe_id);
+ } else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ expired_event.requestor_instance_id = it.get_u32();
+ ALOGI("req_inst id = %u\n", expired_event.requestor_instance_id);
+ }
+ }
+
+ if (expired_event.requestor_instance_id && expired_event.publish_subscribe_id) {
+ GET_NAN_HANDLE(info)->mHandlers.EventMatchExpired(&expired_event);
+ } else {
+ ALOGE("Invalid values for notifying the expired event, dropping the event\n");
+ }
+}
///////////////////////////////////////////////////////////////////////////////
class NanDiscEnginePrimitive : public WifiCommand
@@ -664,7 +656,7 @@
mInstId = mParams->publish_id;
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+ result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
if (result < 0) {
ALOGE("%s: Failed to fill pub id, result = %d\n", __func__, result);
return result;
@@ -967,7 +959,7 @@
}
ALOGI("%s: pub id = %d, inst_id = %d\n", __func__, mParams->publish_id, mInstId);
- result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+ result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
if (result < 0) {
ALOGE("%s: Failed to fill NAN_ATTRIBUTE_PUBLISH_ID, result = %d\n",
__func__, result);
@@ -1513,7 +1505,6 @@
int handleEvent(WifiEvent& event) {
int cmd = event.get_vendor_subcmd();
u16 attr_type;
- int result;
ALOGI("Received NanDiscEnginePrimitive event: %d\n", event.get_cmd());
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -1528,15 +1519,16 @@
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- pub_term_event.publish_id = it.get_u16();
+ pub_term_event.publish_id = it.get_u32();
ALOGI("pub id = %u", pub_term_event.publish_id);
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
pub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("pub termination status %u", pub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(pub_term_event.nan_reason, it.get_data(),
- sizeof(pub_term_event.nan_reason));
- ALOGI("pub termination reason: %s", pub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(pub_term_event.nan_reason));
+ memcpy(pub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("pub termination reason: %s, len = %d\n",
+ pub_term_event.nan_reason, len);
} else {
ALOGE("Unknown attr: %u\n", attr_type);
}
@@ -1560,7 +1552,7 @@
ALOGI("sub id: %u", it.get_u16());
subscribe_event.publish_subscribe_id = it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- ALOGI("pub id: %u", it.get_u16());
+ ALOGI("pub id: %u", it.get_u32());
subscribe_event.requestor_instance_id = it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
memcpy(subscribe_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
@@ -1656,9 +1648,10 @@
sub_term_event.reason = (NanStatusType)it.get_u16();
ALOGI("sub termination status %u", sub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(sub_term_event.nan_reason, it.get_data(),
- sizeof(sub_term_event.nan_reason));
- ALOGI("sub termination reason: %s", sub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(sub_term_event.nan_reason));
+ memcpy(sub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("sub termination nan reason: %s, len = %d\n",
+ sub_term_event.nan_reason, len);
} else {
ALOGI("Unknown attr: %d\n", attr_type);
}
@@ -1666,7 +1659,9 @@
GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
break;
-
+ case NAN_EVENT_MATCH_EXPIRY:
+ HandleExpiryEvent(info, vendor_data);
+ break;
case NAN_EVENT_FOLLOWUP:
NanFollowupInd followup_event;
memset(&followup_event, 0, sizeof(NanFollowupInd));
@@ -1705,9 +1700,10 @@
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
followup_ind.reason = (NanStatusType)it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(followup_ind.nan_reason, it.get_data(),
- sizeof(followup_ind.nan_reason));
- ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(followup_ind.nan_reason));
+ memcpy(followup_ind.nan_reason, it.get_data(), len);
+ ALOGI("nan transmit followup ind: reason: %s, len = %d\n",
+ followup_ind.nan_reason, len);
}
}
GET_NAN_HANDLE(info)->mHandlers.EventTransmitFollowup(&followup_ind);
@@ -1845,7 +1841,7 @@
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
+ result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
if (result < 0) {
ALOGE("%s: Failed to fill instance id = %d, result = %d\n",
__func__, mParams->requestor_instance_id, result);
@@ -2226,10 +2222,10 @@
case NAN_DP_INTERFACE_DELETE:
case NAN_DP_INITIATOR_RESPONSE:
case NAN_DP_RESPONDER_RESPONSE:
- case NAN_DP_END:
+ case NAN_DP_END:
valid = true;
break;
- default:
+ default:
ALOGE("NanDataPathPrmitive::Unknown cmd Response: %d\n", response_type);
break;
}
@@ -2304,8 +2300,8 @@
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- ALOGI("publish_id: %u", it.get_u16());
- ndp_request_event.service_instance_id = it.get_u16();
+ ALOGI("publish_id: %u", it.get_u32());
+ ndp_request_event.service_instance_id = it.get_u32();
} else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
memcpy(ndp_request_event.peer_disc_mac_addr,
@@ -2348,6 +2344,7 @@
NanDataPathConfirmInd ndp_create_confirmation_event;
memset(&ndp_create_confirmation_event, 0, sizeof(NanDataPathConfirmInd));
u16 ndp_conf_app_info_len = 0;
+ u8 chan_idx = 0;
counters.dp_confirm_evt++;
ALOGI("Received NAN_EVENT_DATA_CONFIRMATION\n");
@@ -2384,9 +2381,29 @@
ALOGI("reason code %u", (NanDataPathResponseCode)it.get_u8());
ndp_create_confirmation_event.rsp_code =
(NanDataPathResponseCode)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_NUM_CHANNELS) {
+ ALOGI("num channels %u", it.get_u32());
+ if (it.get_u32() <= NAN_MAX_CHANNEL_INFO_SUPPORTED) {
+ ndp_create_confirmation_event.num_channels = it.get_u32();
+ } else {
+ ndp_create_confirmation_event.num_channels =
+ NAN_MAX_CHANNEL_INFO_SUPPORTED;
+ ALOGE("num channels reset to max allowed %u",
+ ndp_create_confirmation_event.num_channels);
+ }
+ } else if (attr_type == NAN_ATTRIBUTE_CHANNEL_INFO) {
+ ALOGI("Channel info \n");
+ memcpy((u8 *)ndp_create_confirmation_event.channel_info, it.get_data(),
+ ndp_create_confirmation_event.num_channels * sizeof(NanChannelInfo));
+ while (chan_idx < ndp_create_confirmation_event.num_channels) {
+ ALOGI("channel: %u, Bandwidth: %u, nss: %u\n",
+ ndp_create_confirmation_event.channel_info[chan_idx].channel,
+ ndp_create_confirmation_event.channel_info[chan_idx].bandwidth,
+ ndp_create_confirmation_event.channel_info[chan_idx].nss);
+ chan_idx++;
+ }
}
}
-
GET_NAN_HANDLE(info)->mHandlers.EventDataConfirm(&ndp_create_confirmation_event);
break;
}
@@ -2484,10 +2501,6 @@
/* TODO: Not yet implemented */
} else if (mType == NAN_VERSION_INFO) {
return createVersionRequest(request);
-#ifdef NAN_CLUSTER_MERGE
- } else if (mType == NAN_REQUEST_ENABLE_MERGE) {
- return createEnableMergeRequest(request, (NanEnableMergeRequest *)mParams);
-#endif /* NAN_CLUSTER_MERGE */
} else {
ALOGE("Unknown Nan request\n");
}
@@ -2875,26 +2888,6 @@
return result;
}
-#ifdef NAN_CLUSTER_MERGE
- int createEnableMergeRequest(WifiRequest& request,
- NanEnableMergeRequest *mParams) {
- int result = request.create(GOOGLE_OUI, NAN_SUBCMD_ENABLE_MERGE);
- if (result < 0) {
- ALOGE("%s: Fail to create request\n", __func__);
- return result;
- }
- nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- result = request.put_u8(NAN_ATTRIBUTE_ENABLE_MERGE, mParams->enable);
- if (result < 0) {
- ALOGE("%s: Failing in enable merge, result = %d\n", __func__, result);
- return result;
- }
- request.attr_end(data);
- NAN_DBG_EXIT();
- return WIFI_SUCCESS;
- }
-#endif /* NAN_CLUSTER_MERGE */
-
int createConfigRequest(WifiRequest& request, NanConfigRequest *mParams) {
int result = request.create(GOOGLE_OUI, NAN_SUBCMD_CONFIG);
@@ -3282,7 +3275,7 @@
ndp_instance_id = it.get_u32();
ALOGI("handleEvent: ndp_instance_id = [%d]\n", ndp_instance_id);
} else if (attr_type == NAN_ATTRIBUTE_CMD_RESP_DATA) {
- ALOGI("sizeof cmd response data: %d, it.get_len() = %d\n",
+ ALOGI("sizeof cmd response data: %ld, it.get_len() = %d\n",
sizeof(nan_hal_resp_t), it.get_len());
if (it.get_len() == sizeof(nan_hal_resp_t)) {
rsp_vndr_data = (nan_hal_resp_t*)it.get_data();
@@ -3316,12 +3309,17 @@
ALOGE("%s: dp_primitive is no more available\n", __func__);
}
return NL_SKIP;
- } else {
- if (is_cmd_response(event_id)) {
- ALOGE("Handling cmd response asynchronously\n");
- handleAsyncResponse(rsp_vndr_data);
- }
- }
+ } else {
+ if (is_cmd_response(event_id)) {
+ ALOGE("Handling cmd response asynchronously\n");
+ if (rsp_vndr_data != NULL) {
+ handleAsyncResponse(rsp_vndr_data);
+ } else {
+ ALOGE("Wrong response data, rsp_vndr_data is NULL\n");
+ return NL_SKIP;
+ }
+ }
+ }
switch(event_id) {
case NAN_EVENT_DE_EVENT:
@@ -3395,9 +3393,10 @@
disabled_ind.reason = (NanStatusType)it.get_u8();
ALOGI("Nan Disable:status %u", disabled_ind.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(disabled_ind.nan_reason, it.get_data(),
- sizeof(disabled_ind.nan_reason));
- ALOGI("Disable nan reason: %s", disabled_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(disabled_ind.nan_reason));
+ memcpy(disabled_ind.nan_reason, it.get_data(), len);
+ ALOGI("Disabled nan reason: %s, len = %d\n",
+ disabled_ind.nan_reason, len);
}
}
@@ -3415,7 +3414,7 @@
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
- sdfInd.data.frame_len = it.get_u32();
+ sdfInd.data.frame_len = it.get_u16();
if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
}
@@ -3450,6 +3449,7 @@
unregisterVendorHandler(GOOGLE_OUI, i);
}
unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
void registerNanVendorEvents()
{
@@ -3458,6 +3458,7 @@
registerVendorHandler(GOOGLE_OUI, i);
}
registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ registerVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
};
@@ -3550,8 +3551,6 @@
C2S(NAN_DATA_PATH_IFACE_UP)
C2S(NAN_DATA_PATH_SEC_INFO)
C2S(NAN_VERSION_INFO)
- C2S(NAN_REQUEST_ENABLE_MERGE)
-
default:
return "UNKNOWN_NAN_CMD";
}
@@ -3902,7 +3901,6 @@
static int dump_NanPublishRequest(NanPublishRequest* msg)
{
ALOGI("%s: Dump NanPublishRequest msg:\n", __func__);
- u8 i = 0;
if (msg == NULL) {
ALOGE("Invalid msg\n");
return WIFI_ERROR_UNKNOWN;
@@ -4022,7 +4020,6 @@
static int dump_NanTransmitFollowupRequest(NanTransmitFollowupRequest* msg)
{
ALOGI("%s: Dump NanTransmitFollowupRequest msg:\n", __func__);
- u8 i = 0;
if (msg == NULL) {
ALOGE("Invalid msg\n");
return WIFI_ERROR_UNKNOWN;
@@ -4211,7 +4208,6 @@
{
wifi_error ret = WIFI_SUCCESS;
NanDiscEnginePrimitive *cmd;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_REQUEST_PUBLISH_CANCEL;
ALOGE("Cancellling publish request %d\n", msg->publish_id);
@@ -4258,7 +4254,6 @@
{
wifi_error ret = WIFI_SUCCESS;
NanDiscEnginePrimitive *cmd;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_REQUEST_SUBSCRIBE_CANCEL;
ALOGE("creating new instance + %d\n", msg->subscribe_id);
@@ -4274,36 +4269,11 @@
return ret;
}
-#ifdef NAN_CLUSTER_MERGE
-/* Function to send NAN cluster merge enable/disable request to the wifi driver.*/
-wifi_error nan_enable_cluster_merge_request(transaction_id id,
- wifi_interface_handle iface, NanEnableMergeRequest* msg)
-{
- wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
- NanRequestType cmdType = NAN_REQUEST_ENABLE_MERGE;
-
- NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
- NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
- cmd->setType(cmdType);
- cmd->setId(id);
- cmd->setMsg((void *)msg);
- ret = (wifi_error)cmd->start();
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s :enable nan cluster merge failed in start, error = %d\n", __func__, ret);
- }
- cmd->releaseRef();
-
- return ret;
-}
-#endif /* NAN_CLUSTER_MERGE */
-
/* Function to send nan transmit followup Request to the wifi driver.*/
wifi_error nan_transmit_followup_request(transaction_id id,
wifi_interface_handle iface, NanTransmitFollowupRequest* msg)
{
NanDiscEnginePrimitive *cmd = NULL;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_REQUEST_TRANSMIT_FOLLOWUP;
wifi_error ret = WIFI_SUCCESS;
@@ -4330,9 +4300,9 @@
wifi_handle handle = getWifiHandle(iface);
ALOGI("Nan Stats, halHandle = %p", handle);
- NanRequestType cmdType = NAN_REQUEST_STATS;
#ifdef NOT_SUPPORTED
+ NanRequestType cmdType = NAN_REQUEST_STATS;
wifi_error ret = WIFI_SUCCESS;
NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -4383,9 +4353,9 @@
wifi_handle handle = getWifiHandle(iface);
ALOGI("Nan TCA, halHandle = %p", handle);
- NanRequestType cmdType = NAN_REQUEST_TCA;
#ifdef NOT_SUPPORTED
+ NanRequestType cmdType = NAN_REQUEST_TCA;
wifi_error ret = WIFI_SUCCESS;
NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -4480,6 +4450,7 @@
delete GET_NAN_HANDLE(info);
NAN_HANDLE(info) = NULL;
}
+ ALOGI("wifi nan internal clean up done");
return WIFI_SUCCESS;
}
wifi_error nan_register_handler(wifi_interface_handle iface,
@@ -4552,6 +4523,7 @@
unregisterVendorHandler(GOOGLE_OUI, i);
}
unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
void registerNanVendorEvents()
{
@@ -4560,6 +4532,7 @@
registerVendorHandler(GOOGLE_OUI, i);
}
registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ registerVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
int handleEvent(WifiEvent& event) {
@@ -4623,9 +4596,10 @@
disabled_ind.reason = (NanStatusType)it.get_u8();
ALOGI("Nan Disable:status %u", disabled_ind.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(disabled_ind.nan_reason, it.get_data(),
- sizeof(disabled_ind.nan_reason));
- ALOGI("nan disable reason: %s", disabled_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(disabled_ind.nan_reason));
+ memcpy(disabled_ind.nan_reason, it.get_data(), len);
+ ALOGI("nan disabled reason: %s, len = %d\n",
+ disabled_ind.nan_reason, len);
}
}
@@ -4642,15 +4616,16 @@
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- pub_term_event.publish_id = it.get_u16();
+ pub_term_event.publish_id = it.get_u32();
ALOGI("pub id %u", pub_term_event.publish_id);
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
pub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("pub termination status %u", pub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(pub_term_event.nan_reason, it.get_data(),
- sizeof(pub_term_event.nan_reason));
- ALOGI("Pub termination nan reason: %s", pub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(pub_term_event.nan_reason));
+ memcpy(pub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("Pub termination nan reason: %s, len = %d\n",
+ pub_term_event.nan_reason, len);
} else {
ALOGE("Unknown attr\n");
}
@@ -4778,9 +4753,10 @@
sub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("sub termination status %u", sub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(sub_term_event.nan_reason, it.get_data(),
- sizeof(sub_term_event.nan_reason));
- ALOGI("sub termination nan reason: %s", sub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(sub_term_event.nan_reason));
+ memcpy(sub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("sub termination nan reason: %s, len = %d\n",
+ sub_term_event.nan_reason, len);
} else {
ALOGE("Unknown attr: %u\n", attr_type);
}
@@ -4789,6 +4765,9 @@
GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
break;
}
+ case NAN_EVENT_MATCH_EXPIRY:
+ HandleExpiryEvent(info, vendor_data);
+ break;
case NAN_EVENT_FOLLOWUP: {
NanFollowupInd followup_event;
memset(&followup_event, 0, sizeof(NanFollowupInd));
@@ -4837,7 +4816,7 @@
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
- sdfInd.data.frame_len = it.get_u32();
+ sdfInd.data.frame_len = it.get_u16();
if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
}
@@ -4893,8 +4872,8 @@
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- ALOGI("publish_id: %u\n", it.get_u16());
- ndp_request_event.service_instance_id = it.get_u16();
+ ALOGI("publish_id: %u\n", it.get_u32());
+ ndp_request_event.service_instance_id = it.get_u32();
} else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
memcpy(ndp_request_event.peer_disc_mac_addr,
@@ -5014,9 +4993,10 @@
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
followup_ind.reason = (NanStatusType)it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(followup_ind.nan_reason, it.get_data(),
- sizeof(followup_ind.nan_reason));
- ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(followup_ind.nan_reason));
+ memcpy(followup_ind.nan_reason, it.get_data(), len);
+ ALOGI("nan transmit followup ind: reason: %s, len = %d\n",
+ followup_ind.nan_reason, len);
}
}
@@ -5034,7 +5014,6 @@
/* To see event prints in console */
wifi_error nan_event_check_request(transaction_id id, wifi_interface_handle iface)
{
- wifi_handle handle = getWifiHandle(iface);
NanEventCap *cmd = new NanEventCap(iface, id);
if (cmd == NULL) {
return WIFI_ERROR_NOT_SUPPORTED;
@@ -5047,7 +5026,6 @@
wifi_interface_handle iface, char* iface_name)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType = NAN_DATA_PATH_IFACE_CREATE;
@@ -5070,7 +5048,6 @@
wifi_interface_handle iface, char* iface_name)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType = NAN_DATA_PATH_IFACE_DELETE;
@@ -5093,7 +5070,6 @@
wifi_interface_handle iface, NanDataPathInitiatorRequest* msg)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType;
@@ -5179,7 +5155,6 @@
wifi_interface_handle iface, NanDataPathIndicationResponse* msg)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType;
u8 pub_nmi[NAN_MAC_ADDR_LEN] = {0};
@@ -5275,7 +5250,6 @@
{
wifi_error ret = WIFI_SUCCESS;
NanDataPathPrimitive *cmd;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_DATA_PATH_END;
NAN_DBG_ENTER();
diff --git a/bcmdhd/wifi_hal/rtt.cpp b/bcmdhd/wifi_hal/rtt.cpp
index 81eb17f..43a49e8 100644
--- a/bcmdhd/wifi_hal/rtt.cpp
+++ b/bcmdhd/wifi_hal/rtt.cpp
@@ -60,26 +60,30 @@
} RTT_SUB_COMMAND;
typedef enum {
- RTT_ATTRIBUTE_TARGET_CNT = 0,
- RTT_ATTRIBUTE_TARGET_INFO,
- RTT_ATTRIBUTE_TARGET_MAC,
- RTT_ATTRIBUTE_TARGET_TYPE,
- RTT_ATTRIBUTE_TARGET_PEER,
- RTT_ATTRIBUTE_TARGET_CHAN,
- RTT_ATTRIBUTE_TARGET_PERIOD,
- RTT_ATTRIBUTE_TARGET_NUM_BURST,
- RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
- RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
- RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
- RTT_ATTRIBUTE_TARGET_LCI,
- RTT_ATTRIBUTE_TARGET_LCR,
- RTT_ATTRIBUTE_TARGET_BURST_DURATION,
- RTT_ATTRIBUTE_TARGET_PREAMBLE,
- RTT_ATTRIBUTE_TARGET_BW,
- RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
- RTT_ATTRIBUTE_RESULTS_PER_TARGET,
- RTT_ATTRIBUTE_RESULT_CNT,
- RTT_ATTRIBUTE_RESULT
+ RTT_ATTRIBUTE_TARGET_INVALID = 0,
+ RTT_ATTRIBUTE_TARGET_CNT = 1,
+ RTT_ATTRIBUTE_TARGET_INFO = 2,
+ RTT_ATTRIBUTE_TARGET_MAC = 3,
+ RTT_ATTRIBUTE_TARGET_TYPE = 4,
+ RTT_ATTRIBUTE_TARGET_PEER = 5,
+ RTT_ATTRIBUTE_TARGET_CHAN = 6,
+ RTT_ATTRIBUTE_TARGET_PERIOD = 7,
+ RTT_ATTRIBUTE_TARGET_NUM_BURST = 8,
+ RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST = 9,
+ RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM = 10,
+ RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR = 11,
+ RTT_ATTRIBUTE_TARGET_LCI = 12,
+ RTT_ATTRIBUTE_TARGET_LCR = 13,
+ RTT_ATTRIBUTE_TARGET_BURST_DURATION = 14,
+ RTT_ATTRIBUTE_TARGET_PREAMBLE = 15,
+ RTT_ATTRIBUTE_TARGET_BW = 16,
+ RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
+ RTT_ATTRIBUTE_RESULTS_PER_TARGET = 31,
+ RTT_ATTRIBUTE_RESULT_CNT = 32,
+ RTT_ATTRIBUTE_RESULT = 33,
+ RTT_ATTRIBUTE_RESUTL_DETAIL = 34,
+ /* Add any new RTT_ATTRIBUTE prior to RTT_ATTRIBUTE_MAX */
+ RTT_ATTRIBUTE_MAX
} RTT_ATTRIBUTE;
typedef struct strmap_entry {
int id;
@@ -96,6 +100,7 @@
#define DOT11_HDR_LEN 2
#define DOT11_RM_IE_LEN 5
#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementResponse */
#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */
#define DOT11_MEASURE_TYPE_CIVICLOC 11 /* d11 measurement location civic */
@@ -313,6 +318,7 @@
unsigned numRttParams;
int mCompleted;
int currentIdx;
+ int currDtlIdx;
int totalCnt;
static const int MAX_RESULTS = 1024;
wifi_rtt_result *rttResults[MAX_RESULTS];
@@ -328,6 +334,7 @@
currentIdx = 0;
mCompleted = 0;
totalCnt = 0;
+ currDtlIdx = 0;
}
RttCommand(wifi_interface_handle iface, int id)
@@ -336,7 +343,11 @@
currentIdx = 0;
mCompleted = 0;
totalCnt = 0;
+ currDtlIdx = 0;
numRttParams = 0;
+ memset(rttResults, 0, sizeof(rttResults));
+ rttParams = NULL;
+ rttHandler.on_rtt_results = NULL;
}
int createSetupRequest(WifiRequest& request) {
@@ -451,7 +462,11 @@
}
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
+ result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
+
+ if (result < 0) {
+ return result;
+ }
for(unsigned i = 0; i < num_devices; i++) {
result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
if (result < 0) {
@@ -470,13 +485,13 @@
return result;
}
+ registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
ALOGE("failed to configure RTT setup; result = %d", result);
return result;
}
- registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
ALOGI("Successfully started RTT operation");
return result;
}
@@ -528,6 +543,7 @@
int len = event.get_vendor_data_len();
if (vendor_data == NULL || len == 0) {
ALOGI("No rtt results found");
+ return NL_STOP;
}
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
@@ -561,19 +577,18 @@
memcpy(rtt_result, it2.get_data(), it2.get_len());
result_len -= sizeof(wifi_rtt_result);
if (result_len > 0) {
- result_len -= sizeof(wifi_rtt_result);
dot11_rm_ie_t *ele_1;
dot11_rm_ie_t *ele_2;
/* The result has LCI or LCR element */
ele_1 = (dot11_rm_ie_t *)(rtt_result + 1);
- if (ele_1->id == DOT11_MNG_MEASURE_REQUEST_ID) {
+ if (ele_1->id == DOT11_MNG_MEASURE_REPORT_ID) {
if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
rtt_result->LCI = (wifi_information_element *)ele_1;
result_len -= (ele_1->len + DOT11_HDR_LEN);
/* get a next rm ie */
if (result_len > 0) {
ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
- if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
+ if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
(ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
rtt_result->LCR = (wifi_information_element *)ele_2;
}
@@ -584,7 +599,7 @@
/* get a next rm ie */
if (result_len > 0) {
ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
- if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
+ if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
(ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
rtt_result->LCI = (wifi_information_element *)ele_2;
}
@@ -595,13 +610,14 @@
totalCnt++;
ALOGI("retrived rtt_result : \n\tburst_num :%d, measurement_number : %d, success_number : %d\n"
"\tnumber_per_burst_peer : %d, status : %s, retry_after_duration : %d s\n"
- "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %llu ns, rtt_sd : %llu\n"
- "\tdistance : %d, burst_duration : %d ms, negotiated_burst_num : %d\n",
+ "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %lu ns, rtt_sd : %lu\n"
+ "\tdistance : %d cm, burst_duration : %d ms, negotiated_burst_num : %d\n",
rtt_result->burst_num, rtt_result->measurement_number,
rtt_result->success_number, rtt_result->number_per_burst_peer,
get_err_info(rtt_result->status), rtt_result->retry_after_duration,
rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
- rtt_result->rtt/10, rtt_result->rtt_sd, rtt_result->distance_mm / 10,
+ (unsigned long)rtt_result->rtt/1000, (unsigned long)rtt_result->rtt_sd,
+ rtt_result->distance_mm / 10,
rtt_result->burst_duration, rtt_result->negotiated_burst_num);
currentIdx++;
}
@@ -611,7 +627,9 @@
}
if (mCompleted) {
unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
- (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
+ if (*rttHandler.on_rtt_results) {
+ (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
+ }
for (int i = 0; i < currentIdx; i++) {
free(rttResults[i]);
rttResults[i] = NULL;
@@ -630,7 +648,19 @@
wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
{
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_range_request: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
wifi_handle handle = getWifiHandle(iface);
+ if (handle == NULL) {
+ ALOGE("wifi_rtt_range_request: NULL handle pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = wifi_register_cmd(handle, id, cmd);
@@ -651,7 +681,19 @@
wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface,
unsigned num_devices, mac_addr addr[])
{
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
wifi_handle handle = getWifiHandle(iface);
+ if (handle == NULL) {
+ ALOGE("wifi_rtt_range_cancel: NULL handle pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
RttCommand *cmd = new RttCommand(iface, id);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
cmd->cancel_specific(num_devices, addr);
@@ -663,6 +705,18 @@
wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
wifi_rtt_capabilities *capabilities)
{
+ if (iface == NULL) {
+ ALOGE("wifi_get_rtt_capabilities: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (capabilities == NULL) {
+ ALOGE("wifi_get_rtt_capabilities: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
GetRttCapabilitiesCommand command(iface, capabilities);
return (wifi_error) command.requestResponse();
}
@@ -671,6 +725,12 @@
wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
wifi_rtt_responder* responderInfo)
{
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_get_responder_info: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
GetRttResponderInfoCommand command(iface, responderInfo);
return (wifi_error) command.requestResponse();
diff --git a/bcmdhd/wifi_hal/sync.h b/bcmdhd/wifi_hal/sync.h
index 64f8d39..1118c71 100644
--- a/bcmdhd/wifi_hal/sync.h
+++ b/bcmdhd/wifi_hal/sync.h
@@ -68,4 +68,4 @@
}
};
-#endif
\ No newline at end of file
+#endif
diff --git a/bcmdhd/wifi_hal/twt.cpp b/bcmdhd/wifi_hal/twt.cpp
new file mode 100755
index 0000000..15bb738
--- /dev/null
+++ b/bcmdhd/wifi_hal/twt.cpp
@@ -0,0 +1,947 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Portions copyright (C) 2020 Broadcom Limited
+ *
+ * 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 <stdint.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/handlers.h>
+
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+
+static const char *TwtCmdToString(int cmd);
+static void EventGetAttributeData(u8 sub_event_type, nlattr *vendor_data);
+typedef void *TwtRequest;
+
+#define C2S(x) case x: return #x;
+
+typedef struct _twt_hal_info {
+ void *twt_handle;
+ void *twt_feature_request;
+} twt_hal_info_t;
+
+twt_hal_info_t twt_info;
+
+#define TWT_HANDLE(twt_info) ((twt_info).twt_handle)
+#define GET_TWT_HANDLE(twt_info) ((TwtHandle *)twt_info.twt_handle)
+
+#define WL_TWT_CAP_FLAGS_REQ_SUPPORT (1u << 0u)
+#define WL_TWT_CAP_FLAGS_RESP_SUPPORT (1u << 1u)
+#define WL_TWT_CAP_FLAGS_BTWT_SUPPORT (1u << 2u)
+#define WL_TWT_CAP_FLAGS_FLEX_SUPPORT (1u << 3u)
+
+class TwtHandle
+{
+ public:
+ TwtCallbackHandler mHandlers;
+ TwtHandle(wifi_handle handle, TwtCallbackHandler handlers):mHandlers(handlers)
+ {}
+
+};
+
+
+static const char *TwtCmdToString(int cmd)
+{
+ switch (cmd) {
+ C2S(TWT_SETUP_REQUEST);
+ C2S(TWT_INFO_FRAME_REQUEST);
+ C2S(TWT_TEAR_DOWN_REQUEST);
+ default:
+ return "UNKNOWN_NAN_CMD";
+ }
+}
+
+static bool is_twt_sub_event(int sub_event_type)
+{
+ bool is_twt_event = false;
+ switch (sub_event_type) {
+ case TWT_SETUP_RESPONSE:
+ case TWT_TEARDOWN_COMPLETION:
+ case TWT_INFORM_FRAME:
+ case TWT_NOTIFY:
+ is_twt_event = true;
+ }
+ return is_twt_event;
+}
+
+void EventGetAttributeData(u8 sub_event_type, nlattr *vendor_data)
+{
+ u8 attr_type = 0;
+
+ switch (sub_event_type) {
+ case TWT_SETUP_RESPONSE:
+ TwtSetupResponse setup_response;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ ALOGI("config_id = %u\n", it.get_u8());
+ setup_response.config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_NEG_TYPE:
+ ALOGI("neg type = %u\n", it.get_u8());
+ setup_response.negotiation_type = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_REASON_CODE:
+ setup_response.reason_code = (TwtSetupReasonCode)it.get_u8();
+ ALOGI("reason code = %u\n", setup_response.reason_code);
+ break;
+ case TWT_ATTRIBUTE_STATUS:
+ setup_response.status = it.get_u8();
+ ALOGI("status = %u\n", setup_response.status);
+ break;
+ case TWT_ATTRIBUTE_TRIGGER_TYPE:
+ setup_response.trigger_type = it.get_u8();
+ ALOGI("trigger type = %u\n", setup_response.trigger_type);
+ break;
+ case TWT_ATTRIBUTE_WAKE_DUR_US:
+ setup_response.wake_dur_us = it.get_u32();
+ ALOGI("wake_dur_us = %d\n", setup_response.wake_dur_us);
+ break;
+ case TWT_ATTRIBUTE_WAKE_INT_US:
+ setup_response.wake_int_us = it.get_u32();
+ ALOGI("wake_int_us = %d\n", setup_response.wake_int_us);
+ break;
+ case TWT_ATTRIBUTE_WAKE_TIME_OFF_US:
+ setup_response.wake_time_off_us = it.get_u32();
+ ALOGI("wake_time_off_us = %d\n", setup_response.wake_time_off_us);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtSetupResponse(&setup_response);
+ break;
+ case TWT_TEARDOWN_COMPLETION:
+ TwtTeardownCompletion teardown_event;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ ALOGI("config_id = %u\n", it.get_u8());
+ teardown_event.config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_STATUS:
+ teardown_event.status = it.get_u8();
+ ALOGI("status = %u\n", teardown_event.status);
+ break;
+ case TWT_ATTRIBUTE_ALL_TWT:
+ teardown_event.all_twt = it.get_u8();
+ ALOGI("all_twt = %d\n", teardown_event.all_twt);
+ break;
+ case TWT_ATTRIBUTE_REASON_CODE:
+ teardown_event.reason = (TwtTeardownReason)it.get_u8();
+ ALOGI("reason = %u\n", teardown_event.reason);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtTeardownCompletion(&teardown_event);
+ break;
+ case TWT_INFORM_FRAME:
+ TwtInfoFrameReceived info_frame_event;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ ALOGI("config_id = %u\n", it.get_u8());
+ info_frame_event.config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_REASON_CODE:
+ info_frame_event.reason = (TwtInfoFrameReason)it.get_u8();
+ ALOGI("reason = %u\n", info_frame_event.reason);
+ break;
+ case TWT_ATTRIBUTE_STATUS:
+ info_frame_event.status = it.get_u8();
+ ALOGI("status = %u\n", info_frame_event.status);
+ break;
+ case TWT_ATTRIBUTE_ALL_TWT:
+ info_frame_event.all_twt = it.get_u8();
+ ALOGI("all_twt = %d\n", info_frame_event.all_twt);
+ break;
+ case TWT_ATTRIBUTE_RESUMED:
+ info_frame_event.twt_resumed = it.get_u8();
+ ALOGI("twt_resumed = %u\n", info_frame_event.twt_resumed);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtInfoFrameReceived(&info_frame_event);
+ break;
+ case TWT_NOTIFY:
+ TwtDeviceNotify notif_event;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_NOTIFICATION:
+ notif_event.notification = (TwtNotification)it.get_u8();
+ ALOGI("notification = %u\n", notif_event.notification);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtDeviceNotify(¬if_event);
+ break;
+ default:
+ ALOGE("Unknown event_type: %d\n", sub_event_type);
+ break;
+ }
+ return;
+}
+
+void HandleTwtEvent(nlattr *vendor_data) {
+ u8 sub_event_type = 0;
+ u8 event_type = 0;
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ event_type = it.get_type();
+ if (event_type == TWT_ATTRIBUTE_SUB_EVENT) {
+ sub_event_type = it.get_u8();
+ if (is_twt_sub_event(sub_event_type)) {
+ EventGetAttributeData(sub_event_type, vendor_data);
+ }
+ }
+ }
+ return;
+}
+
+class TwtEventCap : public WifiCommand
+{
+ public:
+ TwtEventCap(wifi_interface_handle iface, int id)
+ : WifiCommand("TwtCommand", iface, id)
+ {}
+
+ int start()
+ {
+ registerTwtVendorEvents();
+ return WIFI_SUCCESS;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ return NL_SKIP;
+ }
+
+ void registerTwtVendorEvents()
+ {
+ registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ void unregisterTwtVendorEvents()
+ {
+ unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ int handleEvent(WifiEvent& event) {
+ u16 attr_type;
+ TwtEventType twt_event;
+
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ int event_id = event.get_vendor_subcmd();
+
+ ALOGI("EventCapture: Received TWT event: %d\n", event_id);
+ if (!vendor_data || len == 0) {
+ ALOGE("No event data found");
+ return NL_SKIP;
+ }
+
+ switch (event_id) {
+ case BRCM_VENDOR_EVENT_TWT: {
+ ALOGE("Handle TWT event: %d\n", event_id);
+ HandleTwtEvent(vendor_data);
+ break;
+ }
+ default:
+ break;
+ }
+ return NL_SKIP;
+ }
+};
+
+/* To see event prints in console */
+wifi_error twt_event_check_request(transaction_id id, wifi_interface_handle iface)
+{
+ TwtEventCap *cmd = new TwtEventCap(iface, id);
+ if (cmd == NULL) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return (wifi_error)cmd->start();
+}
+
+//////////////////////////////////////////////////////////////////////////
+class GetTwtCapabilitiesCommand : public WifiCommand
+{
+ TwtCapabilitySet *mCapabilities;
+public:
+ GetTwtCapabilitiesCommand(wifi_interface_handle iface, TwtCapabilitySet *capabilities)
+ : WifiCommand("GetTwtCapabilitiesCommand", iface, 0), mCapabilities(capabilities)
+ {
+ memset(mCapabilities, 0, sizeof(*mCapabilities));
+ }
+
+ virtual int create() {
+ ALOGD("Creating message to get twt capabilities; iface\n");
+
+ int ret = mMsg.create(GOOGLE_OUI, TWT_SUBCMD_GETCAPABILITY);
+ if (ret < 0) {
+ ALOGE("Failed to send the twt cap cmd, err = %d\n", ret);
+ }
+ ALOGD("Success to send twt cap cmd, err = %d\n", ret);
+ return ret;
+ }
+
+private:
+ TwtCapability parseTwtCap(uint32_t twt_peer_cap) {
+ TwtCapability cap;
+ cap.requester_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_REQ_SUPPORT) ? 1 : 0;
+ cap.responder_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_RESP_SUPPORT) ? 1 : 0;
+ cap.broadcast_twt_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_BTWT_SUPPORT) ? 1 : 0;
+ cap.flexibile_twt_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_FLEX_SUPPORT) ? 1 : 0;
+ return cap;
+ }
+
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+
+ ALOGI("In GetTwtCapabilitiesCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+ uint32_t twt_device_cap, twt_peer_cap;
+
+ nlattr *data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len);
+ if (data == NULL || len == 0) {
+ ALOGE("no vendor data in GetTwtCapabilitiesCommand response; ignoring it\n");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case TWT_ATTRIBUTE_DEVICE_CAP:
+ twt_device_cap = it.get_u32();
+ mCapabilities->device_capability = parseTwtCap(twt_device_cap);
+ break;
+ case TWT_ATTRIBUTE_PEER_CAP:
+ twt_peer_cap = it.get_u32();
+ mCapabilities->peer_capability = parseTwtCap(twt_peer_cap);
+ break;
+ default:
+ ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ break;
+ }
+ }
+
+ ALOGE("Out GetTwtCapabilitiesCommand::handleResponse\n");
+ return NL_OK;
+ }
+};
+
+/* API to get TWT capability */
+wifi_error twt_get_capability(wifi_interface_handle iface,
+ TwtCapabilitySet *twt_cap_set)
+{
+ if (iface == NULL) {
+ ALOGE("twt_get_capability: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (twt_cap_set == NULL) {
+ ALOGE("twt_get_capability: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ GetTwtCapabilitiesCommand command(iface, twt_cap_set);
+ return (wifi_error) command.requestResponse();
+}
+
+//////////////////////////////////////////////////////////////////////////
+class GetTwtStatsCommand : public WifiCommand
+{
+ TwtStats* mStats;
+ u8 mConfig_id;
+public:
+ GetTwtStatsCommand(wifi_interface_handle iface, u8 config_id, TwtStats *stats)
+ : WifiCommand("GetTwtStatsCommand", iface, 0), mConfig_id(config_id), mStats(stats)
+ {
+ memset(mStats, 0, sizeof(*mStats));
+ }
+
+ virtual int create() {
+ ALOGD("Creating message to get twt stats; iface = %d", mIfaceInfo->id);
+
+ int ret = mMsg.create(GOOGLE_OUI, TWT_SUBCMD_GETSTATS);
+ if (ret < 0) {
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mConfig_id);
+ if (ret < 0) {
+ ALOGE("Failed to set mConfig_id %d\n", mConfig_id);
+ return ret;
+ }
+
+ ALOGI("Successfully configured config id %d\n", mConfig_id);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+
+ ALOGI("In GetTwtStatsCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+
+ nlattr *data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len);
+ if (data == NULL || len == 0) {
+ ALOGE("no vendor data in GetTwtStatsCommand response; ignoring it\n");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ mStats->config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_NUM_TX:
+ mStats->avg_pkt_num_tx = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_NUM_RX:
+ mStats->avg_pkt_num_rx = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_SIZE_TX:
+ mStats->avg_tx_pkt_size = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_SIZE_RX:
+ mStats->avg_rx_pkt_size = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_EOSP_DUR:
+ mStats->avg_eosp_dur_us = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_EOSP_COUNT:
+ mStats->eosp_count = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_NUM_SP:
+ mStats->num_sp = it.get_u32();
+ break;
+ default:
+ ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ break;
+ }
+ }
+
+ return NL_OK;
+ }
+};
+
+/* API to get TWT stats */
+wifi_error twt_get_stats(wifi_interface_handle iface, u8 config_id, TwtStats* stats)
+{
+ if (iface == NULL) {
+ ALOGE("twt_get_stats: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (stats == NULL) {
+ ALOGE("TwtCapabilitySet: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ GetTwtStatsCommand command(iface, config_id, stats);
+ return (wifi_error) command.requestResponse();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+class ClearTwtStatsCommand : public WifiCommand
+{
+ u8 mConfig_id;
+public:
+ ClearTwtStatsCommand(wifi_interface_handle iface, u8 config_id)
+ : WifiCommand("ClearTwtStatsCommand", iface, 0), mConfig_id(config_id)
+ {
+ }
+
+ virtual int create() {
+ ALOGD("Creating message to clear twt stats; config_id = %d\n", mConfig_id);
+
+ int ret = mMsg.create(GOOGLE_OUI, TWT_SUBCMD_CLR_STATS);
+ if (ret < 0) {
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mConfig_id);
+ if (ret < 0) {
+ ALOGE("Failed to set mConfig_id %d\n", mConfig_id);
+ return ret;
+ }
+
+ ALOGI("Successfully configured config id %d\n", mConfig_id);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In ClearTwtStatsCommand::handleResponse");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+/* API to clear TWT stats */
+wifi_error twt_clear_stats(wifi_interface_handle iface, u8 config_id)
+{
+ if (iface == NULL || !config_id) {
+ ALOGE("twt_clear_stats: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ ALOGE("twt_clear_stats: config id: %d\n", config_id);
+
+ ClearTwtStatsCommand command(iface, config_id);
+ return (wifi_error) command.requestResponse();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+class TwtFeatureRequest : public WifiCommand
+{
+ TwtRequest reqContext;
+ TwtRequestType mType;
+
+ public:
+ TwtFeatureRequest(wifi_interface_handle iface,
+ TwtRequest params, TwtRequestType cmdType)
+ : WifiCommand("TwtFeatureRequest", iface, 0), reqContext(params), mType(cmdType)
+ {
+ }
+
+ int createRequest(WifiRequest& request)
+ {
+ ALOGI("TWT CMD: %s\n", TwtCmdToString(mType));
+ if (mType == TWT_SETUP_REQUEST) {
+ return createTwtSetupRequest(request, (TwtSetupRequest *)reqContext);
+ } else if (mType == TWT_INFO_FRAME_REQUEST) {
+ return createInfoFrameRequest(request, (TwtInfoFrameRequest *)reqContext);
+ } else if (mType == TWT_TEAR_DOWN_REQUEST) {
+ return createTearDownRequest(request, (TwtTeardownRequest *)reqContext);
+ } else {
+ ALOGE("%s: Unknown TWT request: %d\n", __func__, mType);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ return WIFI_SUCCESS;
+ }
+
+ int createTwtSetupRequest(WifiRequest& request, TwtSetupRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, TWT_SUBCMD_SETUP_REQUEST);
+ if (result < 0) {
+ ALOGE("%s Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ /* If handle is 0xFFFF, then update instance_id in response of this request
+ * otherwise, update not needed
+ */
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (mParams->config_id) {
+ result = request.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mParams->config_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_id = %d, result = %d\n",
+ __func__, mParams->config_id, result);
+ return result;
+ }
+ }
+
+ if (mParams->negotiation_type) {
+ result = request.put_u8(TWT_ATTRIBUTE_NEG_TYPE, mParams->negotiation_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill negotiation_type = %d, result = %d\n",
+ __func__, mParams->negotiation_type, result);
+ return result;
+ }
+ }
+ if (mParams->trigger_type) {
+ result = request.put_u8(TWT_ATTRIBUTE_TRIGGER_TYPE, mParams->trigger_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill trigger_type = %d, result = %d\n",
+ __func__, mParams->trigger_type, result);
+ return result;
+ }
+ }
+ if (mParams->wake_dur_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_DUR_US, mParams->wake_dur_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_dur_us = %d, result = %d\n",
+ __func__, mParams->wake_dur_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_int_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_INT_US, mParams->wake_int_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_int_us = %d, result = %d\n",
+ __func__, mParams->wake_int_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_int_min_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_INT_MIN_US, mParams->wake_int_min_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_int_min_us = %d, result = %d\n",
+ __func__, mParams->wake_int_min_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_int_max_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_INT_MAX_US, mParams->wake_int_max_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_int_max_us = %d, result = %d\n",
+ __func__, mParams->wake_int_max_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_dur_min_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_DUR_MIN_US, mParams->wake_dur_min_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_dur_min_us = %d, result = %d\n",
+ __func__, mParams->wake_dur_min_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_dur_max_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_DUR_MAX_US, mParams->wake_dur_max_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_dur_max_us = %d, result = %d\n",
+ __func__, mParams->wake_dur_max_us, result);
+ return result;
+ }
+ }
+ if (mParams->avg_pkt_size) {
+ result = request.put_u32(TWT_ATTRIBUTE_AVG_PKT_SIZE, mParams->avg_pkt_size);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill avg_pkt_size = %d, result = %d\n",
+ __func__, mParams->avg_pkt_size, result);
+ return result;
+ }
+ }
+ if (mParams->avg_pkt_num) {
+ result = request.put_u32(TWT_ATTRIBUTE_AVG_PKT_NUM, mParams->avg_pkt_num);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill avg_pkt_num = %d, result = %d\n",
+ __func__, mParams->avg_pkt_num, result);
+ return result;
+ }
+ }
+ if (mParams->wake_time_off_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_TIME_OFF_US, mParams->wake_time_off_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_time_off_us = %d, result = %d\n",
+ __func__, mParams->wake_time_off_us, result);
+ return result;
+ }
+ }
+ request.attr_end(data);
+
+ ALOGI("Returning successfully\n");
+ return result;
+ }
+
+ int createInfoFrameRequest(WifiRequest& request, TwtInfoFrameRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, TWT_SUBCMD_INFO_FRAME_REQUEST);
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (mParams->config_id) {
+ result = request.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mParams->config_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_id = %d, result = %d\n",
+ __func__, mParams->config_id, result);
+ return result;
+ }
+ }
+ if (mParams->resume_time_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_RESUME_TIME_US, mParams->resume_time_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill resume_time_us = %d, result = %d\n",
+ __func__, mParams->resume_time_us, result);
+ return result;
+ }
+ }
+ if (mParams->all_twt) {
+ result = request.put_u8(TWT_ATTRIBUTE_ALL_TWT, mParams->all_twt);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill all_twt = %d, result = %d\n",
+ __func__, mParams->all_twt, result);
+ return result;
+ }
+ }
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int createTearDownRequest(WifiRequest& request, TwtTeardownRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, TWT_SUBCMD_TEAR_DOWN_REQUEST);
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (mParams->config_id) {
+ result = request.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mParams->config_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_id = %d, result = %d\n",
+ __func__, mParams->config_id, result);
+ return result;
+ }
+ }
+ if (mParams->negotiation_type) {
+ result = request.put_u8(TWT_ATTRIBUTE_NEG_TYPE, mParams->negotiation_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill negotiation_type = %d, result = %d\n",
+ __func__, mParams->negotiation_type, result);
+ return result;
+ }
+ }
+ if (mParams->all_twt) {
+ result = request.put_u8(TWT_ATTRIBUTE_ALL_TWT, mParams->all_twt);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill all_twt = %d, result = %d\n",
+ __func__, mParams->all_twt, result);
+ return result;
+ }
+ }
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int open()
+ {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: failed to create setup request; result = %d", __func__, result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: failed to configure setup; result = %d", __func__, result);
+ return result;
+ }
+
+ request.destroy();
+ return WIFI_SUCCESS;
+ }
+
+ void registerTwtVendorEvents()
+ {
+ registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ void unregisterTwtVendorEvents()
+ {
+ unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ u16 attr_type;
+ TwtEventType twt_event;
+
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ int event_id = event.get_vendor_subcmd();
+ ALOGI("Received TWT event: %d\n", event_id);
+
+ if (!vendor_data || len == 0) {
+ ALOGE("No event data found");
+ return NL_SKIP;
+ }
+
+ switch (event_id) {
+ case BRCM_VENDOR_EVENT_TWT: {
+ HandleTwtEvent(vendor_data);
+ break;
+ }
+ default:
+ ALOGE("Unknown event: %d\n", event_id);
+ break;
+ }
+ return NL_SKIP;
+ }
+
+};
+
+void twt_deinit_handler()
+{
+ if (twt_info.twt_feature_request) {
+ /* register for Twt vendor events with info mac class*/
+ TwtFeatureRequest *cmd_event = (TwtFeatureRequest*)(twt_info.twt_feature_request);
+ cmd_event->unregisterTwtVendorEvents();
+ delete (TwtFeatureRequest*)twt_info.twt_feature_request;
+ twt_info.twt_feature_request = NULL;
+ }
+ if (TWT_HANDLE(twt_info)) {
+ delete GET_TWT_HANDLE(twt_info);
+ TWT_HANDLE(twt_info) = NULL;
+ }
+ ALOGI("wifi twt internal clean up done");
+ return;
+}
+
+wifi_error twt_register_handler(wifi_interface_handle iface,
+ TwtCallbackHandler handlers)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ if (TWT_HANDLE(twt_info)) {
+ /* cleanup and re-register */
+ twt_deinit_handler();
+ }
+ memset(&twt_info, 0, sizeof(twt_info));
+ TWT_HANDLE(twt_info) = new TwtHandle(handle, handlers);
+ twt_info.twt_feature_request =
+ (void*)new TwtFeatureRequest(iface, NULL, TWT_LAST);
+ NULL_CHECK_RETURN(twt_info.twt_feature_request,
+ "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ TwtFeatureRequest *cmd_event = (TwtFeatureRequest*)(twt_info.twt_feature_request);
+ cmd_event->registerTwtVendorEvents();
+ return WIFI_SUCCESS;
+}
+
+wifi_error twt_setup_request(wifi_interface_handle iface, TwtSetupRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ TwtFeatureRequest *cmd;
+ TwtRequestType cmdType = TWT_SETUP_REQUEST;
+
+ cmd = new TwtFeatureRequest(iface, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+wifi_error twt_info_frame_request(wifi_interface_handle iface, TwtInfoFrameRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ TwtFeatureRequest *cmd;
+ TwtRequestType cmdType = TWT_INFO_FRAME_REQUEST;
+
+ cmd = new TwtFeatureRequest(iface, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+wifi_error twt_teardown_request(wifi_interface_handle iface, TwtTeardownRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ TwtFeatureRequest *cmd;
+ TwtRequestType cmdType = TWT_TEAR_DOWN_REQUEST;
+
+ cmd = new TwtFeatureRequest(iface, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index 258725c..0ba633b 100755
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -53,6 +53,8 @@
#include "rtt.h"
#include "brcm_version.h"
#include <stdio.h>
+#include <string>
+#include <vector>
/*
BUGBUG: normally, libnl allocates ports for all connections it makes; but
being a static library, it doesn't really know how many other netlink connections
@@ -63,6 +65,7 @@
#define WIFI_HAL_CMD_SOCK_PORT 644
#define WIFI_HAL_EVENT_SOCK_PORT 645
+#define MAX_VIRTUAL_IFACES 5
/*
* Defines for wifi_wait_for_driver_ready()
@@ -71,8 +74,8 @@
#define POLL_DRIVER_DURATION_US (100000)
#define POLL_DRIVER_MAX_TIME_MS (10000)
#define EVENT_BUF_SIZE 2048
+#define C2S(x) case x: return #x;
-static void internal_event_handler(wifi_handle handle, int events);
static int internal_no_seq_check(nl_msg *msg, void *arg);
static int internal_valid_message_handler(nl_msg *msg, void *arg);
static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
@@ -83,28 +86,42 @@
static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
const u8 *program, u32 len);
+static wifi_error wifi_read_packet_filter(wifi_interface_handle handle, u32 src_offset,
+ u8 *host_dst, u32 length);
static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
u32 *version, u32 *max_len);
static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable);
+static wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask, u32 iface_mode_mask,
+ u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels);
+static void wifi_cleanup_dynamic_ifaces(wifi_handle handle);
typedef enum wifi_attr {
- ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
- ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
- ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
- ANDR_WIFI_ATTRIBUTE_NODFS_SET,
- ANDR_WIFI_ATTRIBUTE_COUNTRY,
- ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE,
- ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE,
- ANDR_WIFI_ATTRIBUTE_LATENCY_MODE,
- ANDR_WIFI_ATTRIBUTE_RANDOM_MAC,
- ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO
- // Add more attribute here
+ ANDR_WIFI_ATTRIBUTE_INVALID = 0,
+ ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET = 1,
+ ANDR_WIFI_ATTRIBUTE_FEATURE_SET = 2,
+ ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI = 3,
+ ANDR_WIFI_ATTRIBUTE_NODFS_SET = 4,
+ ANDR_WIFI_ATTRIBUTE_COUNTRY = 5,
+ ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE = 6,
+ ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE = 7,
+ ANDR_WIFI_ATTRIBUTE_LATENCY_MODE = 8,
+ ANDR_WIFI_ATTRIBUTE_RANDOM_MAC = 9,
+ ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO = 10,
+ ANDR_WIFI_ATTRIBUTE_THERMAL_MITIGATION = 11,
+ ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW = 12,
+ ANDR_WIFI_ATTRIBUTE_VOIP_MODE = 13,
+ ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER = 14,
+ // Add more attribute here
+ ANDR_WIFI_ATTRIBUTE_MAX
} wifi_attr_t;
enum wifi_rssi_monitor_attr {
- RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
- RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
- RSSI_MONITOR_ATTRIBUTE_START,
+ RSSI_MONITOR_ATTRIBUTE_INVALID = 0,
+ RSSI_MONITOR_ATTRIBUTE_MAX_RSSI = 1,
+ RSSI_MONITOR_ATTRIBUTE_MIN_RSSI = 2,
+ RSSI_MONITOR_ATTRIBUTE_START = 3,
+ // Add more attribute here
+ RSSI_MONITOR_ATTRIBUTE_MAX
};
enum wifi_apf_attr {
@@ -116,7 +133,57 @@
enum apf_request_type {
GET_APF_CAPABILITIES,
- SET_APF_PROGRAM
+ SET_APF_PROGRAM,
+ READ_APF_PROGRAM
+};
+
+enum wifi_dscp_attr {
+ DSCP_ATTRIBUTE_INVALID = 0,
+ DSCP_ATTRIBUTE_START = 1,
+ DSCP_ATTRIBUTE_END = 2,
+ DSCP_ATTRIBUTE_AC = 3,
+ /* Add more attributes here */
+ DSCP_ATTRIBUTE_MAX
+};
+
+enum wifi_dscp_request_type {
+ SET_DSCP_TABLE,
+ RESET_DSCP_TABLE
+};
+
+enum wifi_chavoid_attr {
+ CHAVOID_ATTRIBUTE_INVALID = 0,
+ CHAVOID_ATTRIBUTE_CNT = 1,
+ CHAVOID_ATTRIBUTE_CONFIG = 2,
+ CHAVOID_ATTRIBUTE_BAND = 3,
+ CHAVOID_ATTRIBUTE_CHANNEL = 4,
+ CHAVOID_ATTRIBUTE_PWRCAP = 5,
+ CHAVOID_ATTRIBUTE_MANDATORY = 6,
+ /* Add more attributes here */
+ CHAVOID_ATTRIBUTE_MAX
+};
+
+enum wifi_usable_channel_attributes {
+ USABLECHAN_ATTRIBUTE_INVALID = 0,
+ USABLECHAN_ATTRIBUTE_BAND = 1,
+ USABLECHAN_ATTRIBUTE_IFACE = 2,
+ USABLECHAN_ATTRIBUTE_FILTER = 3,
+ USABLECHAN_ATTRIBUTE_MAX_SIZE = 4,
+ USABLECHAN_ATTRIBUTE_SIZE = 5,
+ USABLECHAN_ATTRIBUTE_CHANNELS = 6,
+ USABLECHAN_ATTRIBUTE_MAX
+};
+
+enum wifi_multista_attr {
+ MULTISTA_ATTRIBUTE_PRIM_CONN_IFACE,
+ MULTISTA_ATTRIBUTE_USE_CASE,
+ /* Add more attributes here */
+ MULTISTA_ATTRIBUTE_MAX
+};
+
+enum multista_request_type {
+ SET_PRIMARY_CONNECTION,
+ SET_USE_CASE
};
/* Initialize/Cleanup */
@@ -138,28 +205,26 @@
wifi_socket_set_local_port(sock, port);
- struct sockaddr *addr = NULL;
- // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
-
- // ALOGI("Connecting socket");
if (nl_connect(sock, NETLINK_GENERIC)) {
ALOGE("Could not connect handle");
nl_socket_free(sock);
return NULL;
}
-
- // ALOGI("Making socket nonblocking");
- /*
- if (nl_socket_set_nonblocking(sock)) {
- ALOGE("Could make socket non-blocking");
- nl_socket_free(sock);
- return NULL;
- }
- */
-
return sock;
}
+static const char *IfaceTypeToString(wifi_interface_type iface_type)
+{
+ switch (iface_type) {
+ C2S(WIFI_INTERFACE_TYPE_STA)
+ C2S(WIFI_INTERFACE_TYPE_AP)
+ C2S(WIFI_INTERFACE_TYPE_P2P)
+ C2S(WIFI_INTERFACE_TYPE_NAN)
+ default:
+ return "UNKNOWN_WIFI_INTERFACE_TYPE";
+ }
+}
+
/*initialize function pointer table with Broadcom HHAL API*/
wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
{
@@ -242,14 +307,56 @@
fn->wifi_nan_data_indication_response = nan_data_indication_response;
fn->wifi_nan_data_end = nan_data_end;
fn->wifi_set_latency_mode = wifi_set_latency_mode;
-#ifdef NAN_CLUSTER_MERGE
- fn->wifi_nan_enable_merge_request = nan_enable_cluster_merge_request;
-#endif /* NAN_CLUSTER_MERGE */
fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
+ fn->wifi_read_packet_filter = wifi_read_packet_filter;
+ fn->wifi_set_subsystem_restart_handler = wifi_set_subsystem_restart_handler;
+ fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
+ fn->wifi_map_dscp_access_category = wifi_map_dscp_access_category;
+ fn->wifi_reset_dscp_mapping = wifi_reset_dscp_mapping;
+ fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
+ fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
+ fn->wifi_set_coex_unsafe_channels = wifi_set_coex_unsafe_channels;
+ fn->wifi_twt_get_capability = twt_get_capability;
+ fn->wifi_twt_register_handler = twt_register_handler;
+ fn->wifi_twt_setup_request = twt_setup_request;
+ fn->wifi_twt_teardown_request = twt_teardown_request;
+ fn->wifi_twt_info_frame_request = twt_info_frame_request;
+ fn->wifi_twt_get_stats = twt_get_stats;
+ fn->wifi_twt_clear_stats = twt_clear_stats;
+ fn->wifi_multi_sta_set_primary_connection = wifi_multi_sta_set_primary_connection;
+ fn->wifi_multi_sta_set_use_case = wifi_multi_sta_set_use_case;
+ fn->wifi_set_voip_mode = wifi_set_voip_mode;
+ fn->wifi_set_dtim_config = wifi_set_dtim_config;
+ fn->wifi_get_usable_channels = wifi_get_usable_channels;
+ fn->wifi_trigger_subsystem_restart = wifi_trigger_subsystem_restart;
return WIFI_SUCCESS;
}
+#ifdef GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
+#include <google_wifi_firmware_config_version_info.h>
+
+static void
+wifi_check_valid_ota_version(wifi_interface_handle handle)
+{
+ bool valid = false;
+ int32_t default_ver = get_google_default_vendor_wifi_config_version();
+ int32_t ota_ver = get_google_ota_updated_wifi_config_version();
+ ALOGE("default_ver %d, ota_ver %d", default_ver, ota_ver);
+
+ if (ota_ver > default_ver) {
+ valid = verify_google_ota_updated_wifi_config_integrity();
+ }
+
+ if (valid) {
+ ALOGE("Valid config files of OTA.");
+ wifi_hal_ota_update(handle, ota_ver);
+ }
+ else {
+ ALOGE("Do not valid config files of OTA.");
+ }
+}
+#endif // GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
hal_info *halInfo = NULL;
wifi_error wifi_pre_initialize(void)
@@ -302,7 +409,7 @@
}
/* Set the socket buffer size */
- if (nl_socket_set_buffer_size(event_sock, (512*1024), 0) < 0) {
+ if (nl_socket_set_buffer_size(event_sock, (4*1024*1024), 0) < 0) {
ALOGE("Could not set size for event_sock: %s",
strerror(errno));
} else {
@@ -376,6 +483,9 @@
if (wlan0Handle != NULL) {
ALOGE("Calling preInit");
if (!get_halutil_mode()) {
+#ifdef GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
+ (void) wifi_check_valid_ota_version(wlan0Handle);
+#endif // GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
result = wifi_hal_preInit(wlan0Handle);
if (result != WIFI_SUCCESS) {
ALOGE("wifi_hal_preInit failed");
@@ -416,15 +526,6 @@
if (result != WIFI_SUCCESS) {
ALOGE("wifi_start_hal failed");
}
-#ifdef FILE_DUMP
- else {
- ALOGE("Calling start file dump");
- result = wifi_start_file_dump(wlan0Handle);
- if (result != WIFI_SUCCESS) {
- ALOGE("wifi_start_file_dump failed");
- }
- }
-#endif /* FILE_DUMP */
}
} else {
ALOGI("Not Calling set alert handler as global_iface is NULL");
@@ -500,13 +601,20 @@
ALOGI("Internal cleanup completed");
}
+
void wifi_internal_module_cleanup()
{
nan_deinit_handler();
+ twt_deinit_handler();
}
void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
{
+ if (!handle) {
+ ALOGE("Handle is null");
+ return;
+ }
+
hal_info *info = getHalInfo(handle);
char buf[64];
wifi_error result;
@@ -528,39 +636,12 @@
}
}
-#ifdef FILE_DUMP
- ALOGE("Calling stop file dump");
- result = wifi_stop_file_dump(wlan0Handle);
- if (result != WIFI_SUCCESS) {
- ALOGE("wifi_stop_file_dump failed");
- }
-#endif /* FILE_DUMP */
} else {
ALOGE("Not cleaning up hal as global_iface is NULL");
}
- if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) {
- // As a fallback set the cleanup flag to TRUE
- ALOGE("could not write to the cleanup socket");
- } else {
- // Listen to the response
- // Hopefully we dont get errors or get hung up
- // Not much can be done in that case, but assume that
- // it has rx'ed the Exit message to exit the thread.
- // As a fallback set the cleanup flag to TRUE
- memset(buf, 0, sizeof(buf));
- ssize_t result = TEMP_FAILURE_RETRY(read(info->cleanup_socks[0], buf, sizeof(buf)));
- ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
- result, errno, strerror(errno));
- if (strncmp(buf, "Done", 4) == 0) {
- ALOGE("Event processing terminated");
- } else {
- ALOGD("Rx'ed %s", buf);
- }
- }
- info->clean_up = true;
+ /* calling internal modules or cleanup */
wifi_internal_module_cleanup();
- ALOGI("wifi nan internal clean up done");
pthread_mutex_lock(&info->cb_lock);
int bad_commands = 0;
@@ -608,8 +689,17 @@
WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
ALOGE("Leaked command %p", cmd);
}
+ if (!get_halutil_mode()) {
+ wifi_cleanup_dynamic_ifaces(handle);
+ }
pthread_mutex_unlock(&info->cb_lock);
- internal_cleaned_up_handler(handle);
+
+ info->clean_up = true;
+
+ if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) {
+ // As a fallback set the cleanup flag to TRUE
+ ALOGE("could not write to the cleanup socket");
+ }
ALOGE("wifi_clean_up done");
}
@@ -660,28 +750,18 @@
} else if (pfd[0].revents & POLLHUP) {
ALOGE("Remote side hung up");
break;
- } else if (pfd[0].revents & POLLIN) {
+ } else if (pfd[0].revents & POLLIN && !info->clean_up) {
// ALOGI("Found some events!!!");
internal_pollin_handler(handle);
} else if (pfd[1].revents & POLLIN) {
- memset(buf, 0, sizeof(buf));
- ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[1].fd, buf, sizeof(buf)));
- ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
- result2, errno, strerror(errno));
- if (strncmp(buf, "Exit", 4) == 0) {
- ALOGD("Got a signal to exit!!!");
- if (TEMP_FAILURE_RETRY(write(pfd[1].fd, "Done", 4)) < 1) {
- ALOGE("could not write to the cleanup socket");
- }
- break;
- } else {
- ALOGD("Rx'ed %s on the cleanup socket\n", buf);
- }
+ ALOGI("Got a signal to exit!!!");
} else {
ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
}
} while (!info->clean_up);
- ALOGI("Exit %s", __FUNCTION__);
+
+ internal_cleaned_up_handler(handle);
+ ALOGE("Exit %s", __FUNCTION__);
}
///////////////////////////////////////////////////////////////////////////////////////
@@ -721,8 +801,6 @@
// ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
// event.log();
- bool dispatched = false;
-
pthread_mutex_lock(&info->cb_lock);
for (int i = 0; i < info->num_event_cb; i++) {
@@ -794,7 +872,6 @@
// ALOGI("handling reponse in %s", __func__);
struct nlattr **tb = reply.attributes();
- struct genlmsghdr *gnlh = reply.header();
struct nlattr *mcgrp = NULL;
int i;
@@ -989,27 +1066,27 @@
int start() {
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request, 1);
- if (result < 0) {
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to create request; result = %d", result);
return result;
}
+
+ registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ ALOGI("Register GOOGLE_RSSI_MONITOR_EVENT handler");
+
result = requestResponse(request);
- if (result < 0) {
- ALOGI("Failed to set RSSI Monitor, result = %d", result);
- return result;
- }
- ALOGI("Successfully set RSSI monitoring");
- result = registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
-
-
- if (result < 0) {
+ if (result != WIFI_SUCCESS) {
unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ ALOGE("Failed to set RSSI Monitor, result = %d", result);
return result;
}
- ALOGI("Done!");
+
+ ALOGI("Successfully set RSSI monitoring");
return result;
}
virtual int cancel() {
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request, 0);
@@ -1021,7 +1098,6 @@
ALOGE("failed to stop RSSI monitoring = %d", result);
}
}
- unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
return WIFI_SUCCESS;
}
@@ -1069,6 +1145,7 @@
class AndroidPktFilterCommand : public WifiCommand {
private:
const u8* mProgram;
+ u8* mReadProgram;
u32 mProgramLen;
u32* mVersion;
u32* mMaxLen;
@@ -1094,13 +1171,24 @@
mMaxLen = NULL;
}
+ AndroidPktFilterCommand(wifi_interface_handle handle,
+ u8* host_dst, u32 length)
+ : WifiCommand("AndroidPktFilterCommand", handle, 0),
+ mReadProgram(host_dst), mProgramLen(length),
+ mReqType(READ_APF_PROGRAM)
+ {
+ }
+
int createRequest(WifiRequest& request) {
if (mReqType == SET_APF_PROGRAM) {
ALOGI("\n%s: APF set program request\n", __FUNCTION__);
return createSetPktFilterRequest(request);
} else if (mReqType == GET_APF_CAPABILITIES) {
ALOGI("\n%s: APF get capabilities request\n", __FUNCTION__);
- return createGetPktFilterCapabilitesRequest(request);
+ return createGetPktFilterCapabilitesRequest(request);
+ } else if (mReqType == READ_APF_PROGRAM) {
+ ALOGI("\n%s: APF read packet filter request\n", __FUNCTION__);
+ return createReadPktFilterRequest(request);
} else {
ALOGE("\n%s Unknown APF request\n", __FUNCTION__);
return WIFI_ERROR_NOT_SUPPORTED;
@@ -1143,6 +1231,16 @@
return result;
}
+ int createReadPktFilterRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, APF_SUBCMD_READ_FILTER);
+ if (result < 0) {
+ return result;
+ }
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ request.attr_end(data);
+ return result;
+ }
+
int start() {
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request);
@@ -1182,11 +1280,11 @@
return NL_SKIP;
}
if( mReqType == SET_APF_PROGRAM) {
- ALOGD("Response recieved for set packet filter command\n");
+ ALOGD("Response received for set packet filter command\n");
} else if (mReqType == GET_APF_CAPABILITIES) {
*mVersion = 0;
*mMaxLen = 0;
- ALOGD("Response recieved for get packet filter capabilities command\n");
+ ALOGD("Response received for get packet filter capabilities command\n");
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
if (it.get_type() == APF_ATTRIBUTE_VERSION) {
*mVersion = it.get_u32();
@@ -1199,12 +1297,24 @@
it.get_type(), it.get_len());
}
}
+ } else if (mReqType == READ_APF_PROGRAM) {
+ ALOGD("Read packet filter, mProgramLen = %d\n", mProgramLen);
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ if (it.get_type() == APF_ATTRIBUTE_PROGRAM) {
+ u8 *buffer = NULL;
+ buffer = (u8 *)it.get_data();
+ memcpy(mReadProgram, buffer, mProgramLen);
+ } else if (it.get_type() == APF_ATTRIBUTE_PROGRAM_LEN) {
+ int apf_length = it.get_u32();
+ ALOGD("apf program length = %d\n", apf_length);
+ }
+ }
}
return NL_OK;
}
int handleEvent(WifiEvent& event) {
- /* No Event to recieve for APF commands */
+ /* No Event to receive for APF commands */
return NL_SKIP;
}
};
@@ -1385,7 +1495,8 @@
static bool is_wifi_interface(const char *name)
{
- if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "swlan", 5) != 0 && strncmp(name, "p2p", 3) != 0) {
+ if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "swlan", 5) != 0 &&
+ strncmp(name, "p2p", 3) != 0 && strncmp(name, "aware", 5) != 0) {
/* not a wifi interface; ignore it */
return false;
} else {
@@ -1395,7 +1506,11 @@
static int get_interface(const char *name, interface_info *info)
{
- strlcpy(info->name, name, sizeof(info->name));
+ int size = 0;
+ size = strlcpy(info->name, name, sizeof(info->name));
+ if (size >= sizeof(info->name)) {
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
info->id = if_nametoindex(name);
// ALOGI("found an interface : %s, id = %d", name, info->id);
return WIFI_SUCCESS;
@@ -1429,7 +1544,9 @@
if (d == 0)
return WIFI_ERROR_UNKNOWN;
- info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
+ /* Have place holder for 3 virtual interfaces */
+ n += MAX_VIRTUAL_IFACES;
+ info->interfaces = (interface_info **)calloc(n, sizeof(interface_info *) * n);
if (!info->interfaces) {
info->num_interfaces = 0;
closedir(d);
@@ -1448,10 +1565,12 @@
closedir(d);
return WIFI_ERROR_OUT_OF_MEMORY;
}
+ memset(ifinfo, 0, sizeof(interface_info));
if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
- free(ifinfo);
continue;
}
+ /* Mark as static iface */
+ ifinfo->is_virtual = false;
ifinfo->handle = handle;
info->interfaces[i] = ifinfo;
i++;
@@ -1460,7 +1579,8 @@
closedir(d);
- info->num_interfaces = n;
+ info->num_interfaces = i;
+ info->max_num_interfaces = n;
return WIFI_SUCCESS;
}
@@ -1474,6 +1594,74 @@
return WIFI_SUCCESS;
}
+wifi_error wifi_add_iface_hal_info(wifi_handle handle, const char* ifname)
+{
+ hal_info *info = NULL;
+ int i = 0;
+
+ info = (hal_info *)handle;
+ if (info == NULL) {
+ ALOGE("Could not find info\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGI("%s: add interface_info for iface: %s\n", __FUNCTION__, ifname);
+ if (info->num_interfaces == MAX_VIRTUAL_IFACES) {
+ ALOGE("No space. max limit reached for virtual interfaces %d\n", info->num_interfaces);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
+ if (!ifinfo) {
+ free(info->interfaces);
+ info->num_interfaces = 0;
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ ifinfo->handle = handle;
+ while (i < info->max_num_interfaces) {
+ if (info->interfaces[i] == NULL) {
+ if (get_interface(ifname, ifinfo) != WIFI_SUCCESS) {
+ continue;
+ }
+ ifinfo->is_virtual = true;
+ info->interfaces[i] = ifinfo;
+ info->num_interfaces++;
+ ALOGI("%s: Added iface: %s at the index %d\n", __FUNCTION__, ifname, i);
+ break;
+ }
+ i++;
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_clear_iface_hal_info(wifi_handle handle, const char* ifname)
+{
+ hal_info *info = (hal_info *)handle;
+ int i = 0;
+
+ ALOGI("%s: clear hal info for iface: %s\n", __FUNCTION__, ifname);
+ while (i < info->max_num_interfaces) {
+ if ((info->interfaces[i] != NULL) &&
+ strncmp(info->interfaces[i]->name, ifname,
+ sizeof(info->interfaces[i]->name)) == 0) {
+ free(info->interfaces[i]);
+ info->interfaces[i] = NULL;
+ info->num_interfaces--;
+ ALOGI("%s: Cleared the index = %d for iface: %s\n", __FUNCTION__, i, ifname);
+ break;
+ }
+ i++;
+ }
+ if (i < info->num_interfaces) {
+ for (int j = i; j < info->num_interfaces; j++) {
+ info->interfaces[j] = info->interfaces[j+1];
+ }
+ info->interfaces[info->num_interfaces] = NULL;
+ }
+ return WIFI_SUCCESS;
+}
+
wifi_interface_handle wifi_get_wlan_interface(wifi_handle info, wifi_interface_handle *ifaceHandles, int numIfaceHandles)
{
char buf[EVENT_BUF_SIZE];
@@ -1484,7 +1672,7 @@
}
for (int i = 0; i < numIfaceHandles; i++) {
if (wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
- if (strcmp(buf, "wlan0") == 0) {
+ if (strncmp(buf, "wlan0", 5) == 0) {
ALOGI("found interface %s\n", buf);
wlan0Handle = ifaceHandles[i];
return wlan0Handle;
@@ -1501,6 +1689,29 @@
return WIFI_SUCCESS;
}
+wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
+{
+ char buf[EVENT_BUF_SIZE];
+ wifi_interface_handle *ifaceHandles;
+ int numIfaceHandles;
+ wifi_interface_handle ifHandle;
+
+ wifi_error res = wifi_get_ifaces((wifi_handle)handle, &numIfaceHandles, &ifaceHandles);
+ if (res < 0) {
+ return NULL;
+ }
+ for (int i = 0; i < numIfaceHandles; i++) {
+ if (wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
+ if (strcmp(buf, name) == 0) {
+ ALOGI("found interface %s\n", buf);
+ ifHandle = ifaceHandles[i];
+ return ifHandle;
+ }
+ }
+ }
+ return NULL;
+}
+
wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
{
GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, set, NULL, NULL, 1);
@@ -1537,7 +1748,7 @@
static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
{
- ALOGD("Start RSSI monitor %d", id);
+ ALOGI("Starting RSSI monitor %d", id);
wifi_handle handle = getWifiHandle(iface);
SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -1557,12 +1768,11 @@
static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
{
- ALOGD("Stopping RSSI monitor");
+ ALOGI("Stopping RSSI monitor %d", id);
if(id == -1) {
wifi_rssi_event_handler handler;
s8 max_rssi = 0, min_rssi = 0;
- wifi_handle handle = getWifiHandle(iface);
memset(&handler, 0, sizeof(handler));
SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
max_rssi, min_rssi, handler);
@@ -1599,6 +1809,19 @@
return result;
}
+static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
+ u32 src_offset, u8 *host_dst, u32 length)
+{
+ ALOGD("Read APF program, halHandle = %p, length = %d\n", handle, length);
+ AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, host_dst, length);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Read APF program success\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
static wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable)
{
SetNdoffloadCommand command(handle, enable);
@@ -1636,7 +1859,7 @@
}
if ((mScenario <= WIFI_POWER_SCENARIO_INVALID) ||
- (mScenario > WIFI_POWER_SCENARIO_ON_BODY_BT)) {
+ (mScenario >= SAR_CONFIG_SCENARIO_COUNT)) {
ALOGE("Unsupported tx power value:%d\n", mScenario);
return WIFI_ERROR_NOT_SUPPORTED;
}
@@ -1690,3 +1913,934 @@
}
/////////////////////////////////////////////////////////////////////////////
+
+class ThermalMitigation : public WifiCommand {
+private:
+ wifi_thermal_mode mMitigation;
+ u32 mCompletionWindow;
+public:
+ // constructor for thermal mitigation setting
+ ThermalMitigation(wifi_interface_handle handle,
+ wifi_thermal_mode mitigation, u32 completion_window)
+ : WifiCommand("ThermalMitigation", handle, 0)
+ {
+ mMitigation = mitigation;
+ mCompletionWindow = completion_window;
+ }
+
+ int createRequest(WifiRequest& request, int subcmd,
+ wifi_thermal_mode mitigation, u32 completion_window) {
+ int result = request.create(GOOGLE_OUI, subcmd);
+ if (result < 0) {
+ return result;
+ }
+
+ if ((mitigation < WIFI_MITIGATION_NONE) ||
+ (mitigation > WIFI_MITIGATION_EMERGENCY)) {
+ ALOGE("Unsupported tx mitigation value:%d\n", mitigation);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_s8(ANDR_WIFI_ATTRIBUTE_THERMAL_MITIGATION, mitigation);
+ if (result < 0) {
+ ALOGE("Failed to put tx power scenario request; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW,
+ completion_window);
+ if (result < 0) {
+ ALOGE("Failed to put tx power scenario request; result = %d", result);
+ return result;
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request, WIFI_SUBCMD_THERMAL_MITIGATION, mMitigation,
+ mCompletionWindow);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create request; result = %d", result);
+ return result;
+ }
+
+ ALOGD("try to get resp; mitigation=%d, delay=%d", mMitigation, mCompletionWindow);
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to send thermal mitigation; result = %d", result);
+ }
+ return result;
+ }
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_set_thermal_mitigation_mode(wifi_handle handle,
+ wifi_thermal_mode mode,
+ u32 completion_window)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ ThermalMitigation command(wlan0Handle, mode, completion_window);
+ return (wifi_error)command.start();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+class ChAvoidCommand : public WifiCommand {
+ private:
+ u32 mNumParams;
+ wifi_coex_unsafe_channel *chavoidParams;
+ u32 mMandatory;
+
+ public:
+ ChAvoidCommand(wifi_interface_handle handle,
+ u32 num, wifi_coex_unsafe_channel channels[], u32 mandatory)
+ : WifiCommand("ChAvoidCommand", handle, 0),
+ mNumParams(num), chavoidParams(channels), mMandatory(mandatory)
+ {
+ }
+
+ int createRequest(WifiRequest& request) {
+ return createSetChAvoidRequest(request);
+ }
+
+ int createSetChAvoidRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, CHAVOID_SUBCMD_SET_CONFIG);
+ if (result < 0) {
+ ALOGE("%s : Failed to create SUBCMD\n", __func__);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(CHAVOID_ATTRIBUTE_CNT, mNumParams);
+ if (result < 0) {
+ ALOGE("%s : Failed to set cound\n", __func__);
+ return result;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_MANDATORY, mMandatory);
+ if (result < 0) {
+ ALOGE("%s : Failed to set mandatory cap\n", __func__);
+ return result;
+ }
+
+ nlattr *chavoid_config = request.attr_start(CHAVOID_ATTRIBUTE_CONFIG);
+ for (int i = 0; i< mNumParams; i++) {
+ nlattr *item = request.attr_start(i);
+ if (item == NULL) {
+ ALOGE("%s : Failed to alloc item\n", __func__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_BAND, chavoidParams[i].band);
+ if (result < 0) {
+ ALOGE("%s : Failed to set band\n", __func__);
+ return result;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_CHANNEL, chavoidParams[i].channel);
+ if (result < 0) {
+ ALOGE("%s : Failed to set channel\n", __func__);
+ return result;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_PWRCAP, chavoidParams[i].power_cap_dbm);
+ if (result < 0) {
+ ALOGE("%s : Failed to set power cap\n", __func__);
+ return result;
+ }
+ request.attr_end(item);
+ }
+ request.attr_end(chavoid_config);
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGI("Request Response failed for ChAvoid, result = %d", result);
+ return result;
+ }
+ return result;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ ALOGD("In ChAvoidCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in ChAvoidCommand response; ignoring it");
+ return NL_SKIP;
+ }
+ ALOGD("Response received for ChAvoid command\n");
+ return NL_OK;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ /* No Event to receive for ChAvoid commands */
+ ALOGD("ChAvoid command %s\n", __FUNCTION__);
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle,
+ u32 num, wifi_coex_unsafe_channel channels[], u32 mandatory)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ ChAvoidCommand *cmd = new ChAvoidCommand(wlan0Handle, num, channels, mandatory);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Setting Channel Avoidance success\n");
+ } else {
+ ALOGE("Setting Channel Avoidance failed\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+class DscpCommand : public WifiCommand {
+ private:
+ u32 mStart;
+ u32 mEnd;
+ u32 mAc;
+ int mReqType;
+ public:
+ DscpCommand(wifi_interface_handle handle,
+ u32 start, u32 end, u32 ac)
+ : WifiCommand("DscpCommand", handle, 0),
+ mStart(start), mEnd(end), mAc(ac),
+ mReqType(SET_DSCP_TABLE)
+ {
+ }
+
+ DscpCommand(wifi_interface_handle handle)
+ : WifiCommand("DscpCommand", handle, 0),
+ mReqType(RESET_DSCP_TABLE)
+ {
+ }
+
+ int createRequest(WifiRequest& request) {
+ if (mReqType == SET_DSCP_TABLE) {
+ ALOGI("\n%s: DSCP set table request\n", __FUNCTION__);
+ return createSetDscpRequest(request);
+ } else if (mReqType == RESET_DSCP_TABLE) {
+ ALOGI("\n%s: DSCP reset table request\n", __FUNCTION__);
+ return createResetDscpRequest(request);
+ } else {
+ ALOGE("\n%s Unknown DSCP request\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int createSetDscpRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, DSCP_SUBCMD_SET_TABLE);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(DSCP_ATTRIBUTE_START, mStart);
+ if (result < 0) {
+ goto exit;
+ }
+ result = request.put_u32(DSCP_ATTRIBUTE_END, mEnd);
+ if (result < 0) {
+ goto exit;
+ }
+ result = request.put_u32(DSCP_ATTRIBUTE_AC, mAc);
+ if (result < 0) {
+ goto exit;
+ }
+ request.attr_end(data);
+exit:
+ return result;
+ }
+
+ int createResetDscpRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, DSCP_SUBCMD_RESET_TABLE);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ request.attr_end(data);
+ return result;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGI("Request Response failed for DSCP, result = %d", result);
+ return result;
+ }
+ return result;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ ALOGD("In DscpCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in DscpCommand response; ignoring it");
+ return NL_SKIP;
+ }
+ if( mReqType == SET_DSCP_TABLE) {
+ ALOGD("Response received for Set DSCP command\n");
+ } else if (mReqType == RESET_DSCP_TABLE) {
+ ALOGD("Response received for Reset DSCP command\n");
+ }
+ return NL_OK;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ /* No Event to receive for DSCP commands */
+ ALOGD("DSCP command %s\n", __FUNCTION__);
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_map_dscp_access_category(wifi_handle handle,
+ u32 start, u32 end, u32 ac)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ DscpCommand *cmd = new DscpCommand(wlan0Handle, start, end, ac);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Mapping DSCP table success\n");
+ } else {
+ ALOGE("Mapping DSCP table fail\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
+
+wifi_error wifi_reset_dscp_mapping(wifi_handle handle)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ DscpCommand *cmd = new DscpCommand(wlan0Handle);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Resetting DSCP table success\n");
+ } else {
+ ALOGE("Resetting DSCP table fail\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
+
+class VirtualIfaceConfig : public WifiCommand {
+ const char *mIfname;
+ nl80211_iftype mType;
+ u32 mwlan0_id;
+
+public:
+ VirtualIfaceConfig(wifi_interface_handle handle, const char* ifname,
+ nl80211_iftype iface_type, u32 wlan0_id)
+ : WifiCommand("VirtualIfaceConfig", handle, 0), mIfname(ifname), mType(iface_type),
+ mwlan0_id(wlan0_id)
+ {
+ mIfname = ifname;
+ mType = iface_type;
+ mwlan0_id = wlan0_id;
+ }
+ int createRequest(WifiRequest& request, const char* ifname,
+ nl80211_iftype iface_type, u32 wlan0_id) {
+ ALOGD("add ifname = %s, iface_type = %d, wlan0_id = %d",
+ ifname, iface_type, wlan0_id);
+
+ int result = request.create(NL80211_CMD_NEW_INTERFACE);
+ if (result < 0) {
+ ALOGE("failed to create NL80211_CMD_NEW_INTERFACE; result = %d", result);
+ return result;
+ }
+
+ result = request.put_u32(NL80211_ATTR_IFINDEX, wlan0_id);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFINDEX; result = %d", result);
+ return result;
+ }
+
+ result = request.put_string(NL80211_ATTR_IFNAME, ifname);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFNAME = %s; result = %d", ifname, result);
+ return result;
+ }
+
+ result = request.put_u32(NL80211_ATTR_IFTYPE, iface_type);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFTYPE = %d; result = %d", iface_type, result);
+ return result;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int deleteRequest(WifiRequest& request, const char* ifname) {
+ ALOGD("delete ifname = %s\n", ifname);
+ int result = request.create(NL80211_CMD_DEL_INTERFACE);
+ if (result < 0) {
+ ALOGE("failed to create NL80211_CMD_DEL_INTERFACE; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFINDEX = %d; result = %d",
+ if_nametoindex(ifname), result);
+ return result;
+ }
+ result = request.put_string(NL80211_ATTR_IFNAME, ifname);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFNAME = %s; result = %d", ifname, result);
+ return result;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int createIface() {
+ ALOGE("Creating virtual interface");
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request, mIfname, mType, mwlan0_id);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create virtual iface request; result = %d\n", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to get the virtual iface create response; result = %d\n", result);
+ return result;
+ }
+ ALOGE("Created virtual interface");
+ return WIFI_SUCCESS;
+ }
+
+ int deleteIface() {
+ ALOGD("Deleting virtual interface");
+ WifiRequest request(familyId(), ifaceId());
+ int result = deleteRequest(request, mIfname);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create virtual iface delete request; result = %d\n", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to get response of delete virtual interface; result = %d\n", result);
+ return result;
+ }
+ return WIFI_SUCCESS;
+ }
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+static std::vector<std::string> added_ifaces;
+
+static 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();
+}
+
+wifi_error wifi_virtual_interface_create(wifi_handle handle, const char* ifname,
+ wifi_interface_type iface_type)
+{
+ int numIfaceHandles = 0;
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
+ u32 wlan0_id = if_nametoindex("wlan0");
+
+ if (!handle || !wlan0_id) {
+ ALOGE("%s: Error wifi_handle NULL or wlan0 not present\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Do not create interface if already exist. */
+ if (if_nametoindex(ifname)) {
+ ALOGD("%s: if_nametoindex(%s) = %d already exists, skip create \n",
+ __FUNCTION__, ifname, if_nametoindex(ifname));
+ return WIFI_SUCCESS;
+ }
+
+ ALOGD("%s: ifname name = %s, type = %s\n", __FUNCTION__, ifname,
+ IfaceTypeToString(iface_type));
+
+ switch (iface_type) {
+ case WIFI_INTERFACE_TYPE_STA:
+ type = NL80211_IFTYPE_STATION;
+ break;
+ case WIFI_INTERFACE_TYPE_AP:
+ type = NL80211_IFTYPE_AP;
+ break;
+ case WIFI_INTERFACE_TYPE_P2P:
+ type = NL80211_IFTYPE_P2P_DEVICE;
+ break;
+ case WIFI_INTERFACE_TYPE_NAN:
+ type = NL80211_IFTYPE_NAN;
+ break;
+ default:
+ ALOGE("%s: Wrong interface type %u\n", __FUNCTION__, iface_type);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ VirtualIfaceConfig command(wlan0Handle, ifname, type, wlan0_id);
+
+ ret = (wifi_error)command.createIface();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Iface add Error:%d", __FUNCTION__,ret);
+ return ret;
+ }
+ /* Update dynamic interface list */
+ added_ifaces.push_back(std::string(ifname));
+ ret = wifi_add_iface_hal_info((wifi_handle)handle, ifname);
+ return ret;
+}
+
+wifi_error wifi_virtual_interface_delete(wifi_handle handle, const char* ifname)
+{
+ int numIfaceHandles = 0;
+ int i = 0;
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ hal_info *info = (hal_info *)handle;
+ u32 wlan0_id = if_nametoindex("wlan0");
+
+ if (!handle || !wlan0_id) {
+ ALOGE("%s: Error wifi_handle NULL or wlan0 not present\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ while (i < info->max_num_interfaces) {
+ if (info->interfaces[i] != NULL &&
+ strncmp(info->interfaces[i]->name,
+ ifname, sizeof(info->interfaces[i]->name)) == 0) {
+ if (info->interfaces[i]->is_virtual == false) {
+ ALOGI("%s: %s is static iface, skip delete\n",
+ __FUNCTION__, ifname);
+ return WIFI_SUCCESS;
+ }
+ }
+ i++;
+ }
+
+ ALOGD("%s: iface name=%s\n", __FUNCTION__, ifname);
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ VirtualIfaceConfig command(wlan0Handle, ifname, (nl80211_iftype)0, 0);
+ ret = (wifi_error)command.deleteIface();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Iface delete Error:%d", __FUNCTION__,ret);
+ return ret;
+ }
+ /* Update dynamic interface list */
+ added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)),
+ added_ifaces.end());
+ ret = wifi_clear_iface_hal_info((wifi_handle)handle, ifname);
+ return ret;
+}
+/////////////////////////////////////////////////////////////////////////////
+
+class MultiStaConfig : public WifiCommand {
+ wifi_multi_sta_use_case mUseCase;
+ int mReqType;
+
+public:
+ MultiStaConfig(wifi_interface_handle handle)
+ : WifiCommand("MultiStaConfig", handle, 0), mReqType(SET_PRIMARY_CONNECTION)
+ {
+ }
+ MultiStaConfig(wifi_interface_handle handle, wifi_multi_sta_use_case use_case)
+ : WifiCommand("MultiStaConfig", handle, 0), mUseCase(use_case), mReqType(SET_USE_CASE)
+ {
+ mUseCase = use_case;
+ }
+
+ int createRequest(WifiRequest& request) {
+ if (mReqType == SET_PRIMARY_CONNECTION) {
+ ALOGI("\n%s: MultiSta set primary connection\n", __FUNCTION__);
+ return createSetPrimaryConnectionRequest(request);
+ } else if (mReqType == SET_USE_CASE) {
+ ALOGI("\n%s: MultiSta set use case\n", __FUNCTION__);
+ return createSetUsecaseRequest(request);
+ } else {
+ ALOGE("\n%s Unknown MultiSta request\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int createSetPrimaryConnectionRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_MULTISTA_PRIMARY_CONNECTION);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ request.attr_end(data);
+
+ return result;
+ }
+
+ int createSetUsecaseRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_MULTISTA_USE_CASE);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(MULTISTA_ATTRIBUTE_USE_CASE, mUseCase);
+ if (result < 0) {
+ ALOGE("failed to put MULTISTA_ATTRIBUTE_USE_CASE = %d; result = %d", mUseCase, result);
+ goto exit;
+ }
+
+exit: request.attr_end(data);
+ return result;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGI("Request Response failed for MultiSta, result = %d", result);
+ return result;
+ }
+ ALOGI("Done!");
+ return result;
+ }
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_multi_sta_set_primary_connection(wifi_handle handle, wifi_interface_handle iface)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ char buf[IFNAMSIZ];
+
+ if (!handle || !iface) {
+ ALOGE("%s: Error wifi_handle NULL or invalid wifi interface handle\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (wifi_get_iface_name(iface, buf, sizeof(buf)) != WIFI_SUCCESS) {
+ ALOGE("%s : Invalid interface handle\n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ ALOGD("Setting Multista primary connection for iface = %s\n", buf);
+
+ MultiStaConfig *cmd = new MultiStaConfig(iface);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->start();
+ cmd->releaseRef();
+ return ret;
+}
+
+wifi_error wifi_multi_sta_set_use_case(wifi_handle handle, wifi_multi_sta_use_case use_case)
+{
+ int numIfaceHandles = 0;
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ if (!handle) {
+ ALOGE("%s: Error wifi_handle NULL\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (!(use_case >= WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY &&
+ use_case <= WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED)) {
+ ALOGE("%s: Invalid multi_sta usecase %d\n", __FUNCTION__, use_case);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ ALOGD("Setting Multista usecase = %d\n", use_case);
+ MultiStaConfig *cmd = new MultiStaConfig(wlan0Handle, use_case);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->start();
+ cmd->releaseRef();
+ return ret;
+}
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SetVoipModeCommand : public WifiCommand {
+
+private:
+ wifi_voip_mode mMode;
+public:
+ SetVoipModeCommand(wifi_interface_handle handle, wifi_voip_mode mode)
+ : WifiCommand("SetVoipModeCommand", handle, 0) {
+ mMode = mode;
+ }
+ virtual int create() {
+ int ret;
+
+ ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_CONFIG_VOIP_MODE);
+ if (ret < 0) {
+ ALOGE("Can't create message to send to driver - %d", ret);
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_VOIP_MODE, mMode);
+ ALOGE("mMode - %d", mMode);
+ if (ret < 0) {
+ ALOGE("Failed to set voip mode %d\n", mMode);
+ return ret;
+ }
+
+ ALOGI("Successfully configured voip mode %d\n", mMode);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+};
+
+wifi_error wifi_set_voip_mode(wifi_interface_handle handle, wifi_voip_mode mode)
+{
+ ALOGD("Setting VOIP mode, halHandle = %p Mode = %d\n", handle, mode);
+ SetVoipModeCommand command(handle, mode);
+ return (wifi_error) command.requestResponse();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+class SetDtimConfigCommand : public WifiCommand {
+
+private:
+ uint32_t multiplier;
+public:
+ SetDtimConfigCommand(wifi_interface_handle handle, u32 dtim_multiplier)
+ : WifiCommand("SetDtimConfigCommand", handle, 0) {
+ multiplier = dtim_multiplier;
+ }
+ virtual int create() {
+ int ret;
+
+ ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_DTIM_CONFIG);
+ if (ret < 0) {
+ ALOGE("Can't create message to send to driver - %d", ret);
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER, multiplier);
+ if (ret < 0) {
+ ALOGE("Failed to set dtim mutiplier %d\n", multiplier);
+ return ret;
+ }
+
+ ALOGI("Successfully configured dtim multiplier %d\n", multiplier);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+};
+
+wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier)
+{
+ ALOGD("Setting DTIM config , halHandle = %p Multiplier = %d\n", handle, multiplier);
+ SetDtimConfigCommand command(handle, multiplier);
+ return (wifi_error) command.requestResponse();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+class UsableChannelCommand : public WifiCommand {
+
+private:
+ u32 mBandMask;
+ u32 mIfaceModeMask;
+ u32 mFilterMask;
+ u32 mMaxSize;
+ u32* mSize;
+ wifi_usable_channel* mChannels;
+
+public:
+ UsableChannelCommand(wifi_interface_handle handle, u32 band_mask, u32 iface_mode_mask,
+ u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels)
+ : WifiCommand("UsableChannelCommand", handle, 0),
+ mBandMask(band_mask), mIfaceModeMask(iface_mode_mask),
+ mFilterMask(filter_mask), mMaxSize(max_size),
+ mSize(size), mChannels(channels)
+ {
+ }
+
+ int createRequest(WifiRequest& request) {
+ createUsableChannelRequest(request);
+ return WIFI_SUCCESS;
+ }
+
+ int createUsableChannelRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_USABLE_CHANNEL);
+ if (result < 0) {
+ ALOGE("Failed to create UsableChannel request; result = %d", result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_BAND, mBandMask);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put log level; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_IFACE, mIfaceModeMask);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put ring flags; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_FILTER, mFilterMask);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put usablechan filter; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_MAX_SIZE, mMaxSize);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put usablechan max_size; result = %d", result);
+ return result;
+ }
+ request.attr_end(data);
+
+ return WIFI_SUCCESS;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create request; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to set scanning mac OUI; result = %d", result);
+ }
+
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In DebugCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+ wifi_usable_channel *channels(mChannels);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("No Debug data found");
+ return NL_SKIP;
+ }
+
+ nl_iterator it(vendor_data);
+ if (it.get_type() == USABLECHAN_ATTRIBUTE_SIZE) {
+ *mSize = it.get_u32();
+ } else {
+ ALOGE("Unknown attribute: %d expecting %d",
+ it.get_type(), USABLECHAN_ATTRIBUTE_SIZE);
+ return NL_SKIP;
+ }
+
+ it.next();
+ if (it.get_type() == USABLECHAN_ATTRIBUTE_CHANNELS) {
+ memcpy(channels, it.get_data(), sizeof(wifi_usable_channel) * *mSize);
+ } else {
+ ALOGE("Unknown attribute: %d expecting %d",
+ it.get_type(), USABLECHAN_ATTRIBUTE_SIZE);
+ return NL_SKIP;
+ }
+
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ /* NO events! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask, u32 iface_mode_mask,
+ u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ UsableChannelCommand command(wlan0Handle, band_mask, iface_mode_mask,
+ filter_mask, max_size, size, channels);
+ return (wifi_error)command.start();
+}
diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp
index e35bf9b..a9f9506 100755
--- a/bcmdhd/wifi_hal/wifi_logger.cpp
+++ b/bcmdhd/wifi_hal/wifi_logger.cpp
@@ -26,6 +26,7 @@
#include <netpacket/packet.h>
#include <linux/filter.h>
#include <linux/errqueue.h>
+#include <errno.h>
#include <linux/pkt_sched.h>
#include <netlink/object-api.h>
@@ -34,6 +35,7 @@
#include <netlink-private/object-api.h>
#include <netlink-private/types.h>
#include <unistd.h>
+#include <cutils/properties.h>
#include "nl80211_copy.h"
@@ -46,6 +48,7 @@
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
+#include <sys/stat.h>
#include "brcm_version.h"
#define WIFI_HAL_EVENT_SOCK_PORT 645
@@ -72,25 +75,51 @@
LOGGER_SET_HAL_PID
} DEBUG_SUB_COMMAND;
+#define MAX_NV_FILE 4
+#define MAX_SKU_NAME_LEN 5
+#define OTA_PATH "/data/vendor/firmware/wifi/"
+#define OTA_CLM_FILE "bcmdhd_clm.blob"
+#define OTA_NVRAM_FILE "bcmdhd.cal"
+#define HW_DEV_PROP "ro.revision"
+#define HW_SKU_PROP "ro.boot.hardware.sku"
+
typedef enum {
- LOGGER_ATTRIBUTE_DRIVER_VER,
- LOGGER_ATTRIBUTE_FW_VER,
- LOGGER_ATTRIBUTE_RING_ID,
- LOGGER_ATTRIBUTE_RING_NAME,
- LOGGER_ATTRIBUTE_RING_FLAGS,
- LOGGER_ATTRIBUTE_LOG_LEVEL,
- LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
- LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
- LOGGER_ATTRIBUTE_FW_DUMP_LEN,
- LOGGER_ATTRIBUTE_FW_DUMP_DATA,
- LOGGER_ATTRIBUTE_FW_ERR_CODE,
- LOGGER_ATTRIBUTE_RING_DATA,
- LOGGER_ATTRIBUTE_RING_STATUS,
- LOGGER_ATTRIBUTE_RING_NUM,
- LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
- LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
- LOGGER_ATTRIBUTE_PKT_FATE_NUM,
- LOGGER_ATTRIBUTE_PKT_FATE_DATA,
+ NVRAM,
+ CLM_BLOB
+} OTA_TYPE;
+
+char ota_nvram_ext[10];
+typedef struct ota_info_buf {
+ u32 ota_clm_len;
+ const void *ota_clm_buf[1];
+ u32 ota_nvram_len;
+ const void *ota_nvram_buf[1];
+} ota_info_buf_t;
+u32 applied_ota_version = 0;
+
+typedef enum {
+ LOGGER_ATTRIBUTE_INVALID = 0,
+ LOGGER_ATTRIBUTE_DRIVER_VER = 1,
+ LOGGER_ATTRIBUTE_FW_VER = 2,
+ LOGGER_ATTRIBUTE_RING_ID = 3,
+ LOGGER_ATTRIBUTE_RING_NAME = 4,
+ LOGGER_ATTRIBUTE_RING_FLAGS = 5,
+ LOGGER_ATTRIBUTE_LOG_LEVEL = 6,
+ LOGGER_ATTRIBUTE_LOG_TIME_INTVAL = 7,
+ LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE = 8,
+ LOGGER_ATTRIBUTE_FW_DUMP_LEN = 9,
+ LOGGER_ATTRIBUTE_FW_DUMP_DATA = 10,
+ LOGGER_ATTRIBUTE_FW_ERR_CODE = 11,
+ LOGGER_ATTRIBUTE_RING_DATA = 12,
+ LOGGER_ATTRIBUTE_RING_STATUS = 13,
+ LOGGER_ATTRIBUTE_RING_NUM = 14,
+ LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN = 15,
+ LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA = 16,
+ LOGGER_ATTRIBUTE_PKT_FATE_NUM = 17,
+ LOGGER_ATTRIBUTE_PKT_FATE_DATA = 18,
+ LOGGER_ATTRIBUTE_HANG_REASON = 19,
+ /* Add new attributes just above this */
+ LOGGER_ATTRIBUTE_MAX
} LOGGER_ATTRIBUTE;
typedef enum {
@@ -117,9 +146,10 @@
} PktFateReqType;
enum wake_stat_attributes {
- WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
- WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
- WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
+ WAKE_STAT_ATTRIBUTE_INVALID,
+ WAKE_STAT_ATTRIBUTE_TOTAL,
+ WAKE_STAT_ATTRIBUTE_WAKE,
+ WAKE_STAT_ATTRIBUTE_COUNT,
WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
@@ -136,8 +166,9 @@
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
- WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
- WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO
+ WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT,
+ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
+ WAKE_STAT_ATTRIBUTE_MAX
};
typedef enum {
@@ -146,8 +177,18 @@
SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
} SET_HAL_START_ATTRIBUTE;
-#define HAL_START_REQUEST_ID 2
+typedef enum {
+ OTA_DOWNLOAD_CLM_LENGTH_ATTR = 0x0001,
+ OTA_DOWNLOAD_CLM_ATTR = 0x0002,
+ OTA_DOWNLOAD_NVRAM_LENGTH_ATTR = 0x0003,
+ OTA_DOWNLOAD_NVRAM_ATTR = 0x0004,
+ OTA_SET_FORCE_REG_ON = 0x0005,
+ OTA_CUR_NVRAM_EXT_ATTR = 0x0006,
+} OTA_DOWNLOAD_ATTRIBUTE;
+#define HAL_START_REQUEST_ID 2
+#define HAL_RESTART_ID 3
+#define FILE_NAME_LEN 256
///////////////////////////////////////////////////////////////////////////////
class DebugCommand : public WifiCommand
{
@@ -465,7 +506,7 @@
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
- ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
+ ALOGD("len = %d, expected len = %lu", len, sizeof(unsigned int));
memcpy(mSupport, data, sizeof(unsigned int));
break;
}
@@ -624,6 +665,7 @@
/* unregister event handler */
unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
+ wifi_unregister_cmd(wifiHandle(), id());
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
@@ -729,7 +771,7 @@
return WIFI_SUCCESS;
}
- return wifi_cancel_cmd(id, iface);
+ return wifi_get_cancel_cmd(id, iface);
}
///////////////////////////////////////////////////////////////////////////////
@@ -795,7 +837,6 @@
}
virtual int handleEvent(WifiEvent& event) {
- wifi_ring_buffer_id ring_id;
char *buffer = NULL;
int buffer_size = 0;
bool is_err_alert = false;
@@ -827,7 +868,7 @@
}
}
- if(is_err_alert) {
+ if (is_err_alert) {
mBuffSize = sizeof(mErrCode);
if (mBuff) free(mBuff);
mBuff = (char *)malloc(mBuffSize);
@@ -896,6 +937,114 @@
}
};
+class SetRestartHandler : public WifiCommand
+{
+ wifi_subsystem_restart_handler mHandler;
+ char *mBuff;
+public:
+ SetRestartHandler(wifi_handle handle, wifi_request_id id, wifi_subsystem_restart_handler handler)
+ : WifiCommand("SetRestartHandler", handle, id), mHandler(handler), mBuff(NULL)
+ { }
+ int start() {
+ ALOGI("Start Restart Handler handler:%p", mHandler);
+ registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
+ return WIFI_SUCCESS;
+ }
+ virtual int cancel() {
+ ALOGI("Clear Restart Handler");
+
+ /* unregister alert handler */
+ unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
+ wifi_unregister_cmd(wifiHandle(), id());
+ ALOGI("Success to clear restarthandler");
+ return WIFI_SUCCESS;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ /* Nothing to do on response! */
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ int event_id = event.get_vendor_subcmd();
+ ALOGI("Got event: %d", event_id);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("No Debug data found");
+ return NL_SKIP;
+ }
+ if (event_id == BRCM_VENDOR_EVENT_HANGED) {
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ if (it.get_type() == LOGGER_ATTRIBUTE_HANG_REASON) {
+ mBuff = (char *)it.get_data();
+ } else {
+ ALOGI("Ignoring invalid attribute type = %d, size = %d",
+ it.get_type(), it.get_len());
+ }
+ }
+
+ if (*mHandler.on_subsystem_restart) {
+ (*mHandler.on_subsystem_restart)(mBuff);
+ ALOGI("Hang event received. Trigger SSR handler:%p",
+ mHandler.on_subsystem_restart);
+ } else {
+ ALOGI("No Restart handler registered");
+ }
+ }
+ return NL_OK;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+class SubSystemRestart : public WifiCommand
+{
+ public:
+ SubSystemRestart(wifi_interface_handle iface)
+ : WifiCommand("SubSystemRestart", iface, 0)
+ { }
+
+ int createRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_TRIGGER_SSR);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int create() {
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = createRequest(request);
+ if (result < 0) {
+ ALOGE("Failed to create ssr request result = %d\n", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register ssr response; result = %d\n", result);
+ }
+ return result;
+ }
+
+ protected:
+ int handleResponse(WifiEvent& reply) {
+ /* Nothing to do on response! */
+ return NL_OK;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ /* NO events to handle here! */
+ return NL_SKIP;
+ }
+
+};
///////////////////////////////////////////////////////////////////////////////
class HalInit : public WifiCommand
{
@@ -939,6 +1088,7 @@
ALOGE("Failed to register set hal start response; result = %d", result);
}
wifi_unregister_cmd(wifiHandle(), id());
+ ALOGV("Stop HAL Successfully Completed, mErrCode = %d\n", mErrCode);
return result;
}
@@ -1028,8 +1178,6 @@
wifi_error wifi_stop_hal(wifi_interface_handle iface)
{
- wifi_handle handle = getWifiHandle(iface);
-
HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
cmd->cancel();
@@ -1037,6 +1185,85 @@
return WIFI_SUCCESS;
}
+
+wifi_error wifi_set_subsystem_restart_handler(wifi_handle handle,
+ wifi_subsystem_restart_handler handler)
+{
+ hal_info *info = NULL;
+
+ info = (hal_info *)handle;
+ if (info == NULL) {
+ ALOGE("Could not find hal info\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ SetRestartHandler *cmd = new SetRestartHandler(handle, HAL_RESTART_ID, handler);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = wifi_register_cmd(handle, HAL_RESTART_ID, cmd);
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+
+ result = (wifi_error)cmd->start();
+ if (result != WIFI_SUCCESS) {
+ wifi_unregister_cmd(handle, HAL_RESTART_ID);
+ cmd->releaseRef();
+ return result;
+ }
+
+ /* Cache the handler to use it for trigger subsystem restart */
+ ALOGI("Register SSR handler:%p", handler);
+ info->restart_handler = handler;
+ return result;
+}
+
+wifi_error wifi_trigger_subsystem_restart(wifi_handle handle)
+{
+ wifi_error result = WIFI_SUCCESS;
+ hal_info *info = NULL;
+ char error_str[20];
+ SubSystemRestart *cmd = NULL;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ int numIfaceHandles = 0;
+
+ info = (hal_info *)handle;
+ if (handle == NULL || info == NULL) {
+ ALOGE("Could not find hal info\n");
+ result = WIFI_ERROR_UNKNOWN;
+ goto exit;
+ }
+
+ ALOGI("Trigger subsystem restart\n");
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ cmd = new SubSystemRestart(wlan0Handle);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ result = (wifi_error)cmd->create();
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ strncpy(error_str, "WIFI_ERROR_UNKNOWN", sizeof(error_str));
+ ALOGE("Failed to create SSR");
+ goto exit;
+ }
+
+ strncpy(error_str, "WIFI_SUCCESS", sizeof(error_str));
+
+exit:
+ if (info->restart_handler.on_subsystem_restart) {
+ ALOGI("Trigger ssr handler registered handler:%p",
+ info->restart_handler.on_subsystem_restart);
+ (info->restart_handler.on_subsystem_restart)(error_str);
+ } else {
+ ALOGI("No trigger ssr handler registered");
+ }
+
+ return result;
+}
+
wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
wifi_alert_handler handler)
{
@@ -1075,7 +1302,7 @@
return WIFI_SUCCESS;
}
- return wifi_cancel_cmd(id, iface);
+ return wifi_get_cancel_cmd(id, iface);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1345,7 +1572,7 @@
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
*mNoProvidedFates = it.get_u32();
- ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
+ ALOGI("No: of pkt fates provided is %zu\n", *mNoProvidedFates);
} else {
ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
it.get_type(), it.get_len());
@@ -1429,7 +1656,7 @@
mWakeReasonCnt->total_driver_fw_local_wake =
it.get_u32();
break;
- case WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT:
+ case WAKE_STAT_ATTRIBUTE_TOTAL:
mWakeReasonCnt->total_cmd_event_wake =
it.get_u32();
break;
@@ -1437,7 +1664,7 @@
mWakeReasonCnt->cmd_event_wake_cnt_used =
it.get_u32();
break;
- case WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE:
+ case WAKE_STAT_ATTRIBUTE_WAKE:
memcpy(mCmdEventWakeCount, it.get_data(),
(mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
break;
@@ -1485,7 +1712,7 @@
mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
it.get_u32();
break;
- case WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT:
+ case WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT:
mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
it.get_u32();
break;
@@ -1540,3 +1767,261 @@
cmd->releaseRef();
return result;
}
+
+///////////////////////////////////////////////////////////////////////////////
+class OtaUpdateCommand : public WifiCommand
+{
+ int mErrCode;
+
+ public:
+ OtaUpdateCommand(wifi_interface_handle iface)
+ : WifiCommand("OtaUpdateCommand", iface, 0), mErrCode(0)
+ { }
+
+ int start() {
+ ALOGE("Start OtaUpdateCommand");
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_GET_OTA_CURRUNT_INFO);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set hal start; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set hal start response; result = %d", result);
+ }
+ return result;
+ }
+
+ int otaDownload(ota_info_buf_t* buf, uint32_t ota_version) {
+ u32 force_reg_on = false;
+ WifiRequest request(familyId(), ifaceId());
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_OTA_UPDATE);
+
+ ALOGE("Download the OTA configuration");
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set Hal preInit; result = %d", result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(OTA_DOWNLOAD_CLM_LENGTH_ATTR, buf->ota_clm_len);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put(OTA_DOWNLOAD_CLM_ATTR, buf->ota_clm_buf, sizeof(*buf->ota_clm_buf));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put_u32(OTA_DOWNLOAD_NVRAM_LENGTH_ATTR, buf->ota_nvram_len);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put(OTA_DOWNLOAD_NVRAM_ATTR,
+ buf->ota_nvram_buf, sizeof(*buf->ota_nvram_buf));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ if (applied_ota_version != ota_version) {
+ force_reg_on = true;
+ applied_ota_version = ota_version;
+ }
+ result = request.put_u32(OTA_SET_FORCE_REG_ON, force_reg_on);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ request.attr_end(data);
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set otaDownload; result = %d", result);
+ }
+
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In OtaUpdateCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case OTA_CUR_NVRAM_EXT_ATTR:
+ strncpy(ota_nvram_ext, (char*)it.get_string(), it.get_len());
+ ALOGI("Current Nvram ext [%s]\n", ota_nvram_ext);
+ break;
+ default:
+ ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ break;
+ }
+ }
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ /* NO events! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error read_ota_file(char* file, char** buffer, uint32_t* size)
+{
+ FILE* fp = NULL;
+ int file_size, count;
+ char* buf;
+ fp = fopen(file, "r");
+
+ if (fp == NULL) {
+ ALOGI("File [%s] doesn't exist.", file);
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ file_size = ftell(fp);
+
+ buf = (char *)malloc(file_size + 1);
+ if (buf == NULL) {
+ fclose(fp);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ memset(buf, 0, file_size + 1);
+ fseek(fp, 0, SEEK_SET);
+ count = fread(buf, file_size, 1, fp);
+
+ *buffer = (char*) buf;
+ *size = file_size;
+ fclose(fp);
+ return WIFI_SUCCESS;
+}
+
+wifi_error check_multiple_nvram_clm(uint32_t type, char* hw_revision, char* hw_sku,
+ char** buffer, uint32_t* buffer_len)
+{
+ char file_name[MAX_NV_FILE][FILE_NAME_LEN];
+ char nvram_clmblob_default_file[FILE_NAME_LEN] = {0,};
+ wifi_error result = WIFI_SUCCESS;
+
+ if (type == CLM_BLOB) {
+ sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_CLM_FILE);
+ }
+ else if (type == NVRAM) {
+ sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_NVRAM_FILE);
+ }
+ for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
+ memset(file_name[i], 0, FILE_NAME_LEN);
+ }
+
+ sprintf(file_name[0], "%s_%s_%s", nvram_clmblob_default_file, hw_revision, hw_sku);
+ sprintf(file_name[1], "%s_%s", nvram_clmblob_default_file, hw_revision);
+ sprintf(file_name[2], "%s_%s", nvram_clmblob_default_file, hw_sku);
+ sprintf(file_name[3], "%s", nvram_clmblob_default_file);
+
+ for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
+ result = read_ota_file(file_name[i], buffer, buffer_len);
+ if (result == WIFI_SUCCESS) {
+ ALOGI("[OTA] %s PATH %s", type == NVRAM ? "NVRAM" : "CLM", file_name[i]);
+ break;
+ }
+ }
+ return result;
+}
+
+wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ wifi_error result = WIFI_SUCCESS;
+ ota_info_buf_t buf;
+ char *buffer_nvram = NULL;
+ char *buffer_clm = NULL;
+ char prop_revision_buf[PROPERTY_VALUE_MAX] = {0,};
+ char prop_sku_buf[PROPERTY_VALUE_MAX] = {0,};
+ char sku_name[MAX_SKU_NAME_LEN] = {0,};
+
+ OtaUpdateCommand *cmd = new OtaUpdateCommand(iface);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ALOGD("wifi_hal_ota_update, handle = %p, ota_version %d\n", handle, ota_version);
+
+ result = (wifi_error)cmd->start();
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+
+ property_get(HW_DEV_PROP, prop_revision_buf, NULL);
+ property_get(HW_SKU_PROP, prop_sku_buf, NULL);
+
+ if (strcmp(prop_sku_buf, "G9S9B") == 0 ||
+ strcmp(prop_sku_buf, "G8V0U") == 0 ||
+ strcmp(prop_sku_buf, "GFQM1") == 0) {
+ strncpy(sku_name, "MMW", MAX_SKU_NAME_LEN);
+ } else if (strcmp(prop_sku_buf, "GR1YH") == 0 ||
+ strcmp(prop_sku_buf, "GF5KQ") == 0 ||
+ strcmp(prop_sku_buf, "GPQ72") == 0) {
+ strncpy(sku_name, "JPN", MAX_SKU_NAME_LEN);
+ } else if (strcmp(prop_sku_buf, "GB7N6") == 0 ||
+ strcmp(prop_sku_buf, "GLU0G") == 0 ||
+ strcmp(prop_sku_buf, "GNA8F") == 0) {
+ strncpy(sku_name, "ROW", MAX_SKU_NAME_LEN);
+ } else {
+ strncpy(sku_name, "NA", MAX_SKU_NAME_LEN);
+ }
+
+ check_multiple_nvram_clm(CLM_BLOB, prop_revision_buf, sku_name, &buffer_clm, &buf.ota_clm_len);
+ if (buffer_clm == NULL) {
+ ALOGE("buffer_clm is null");
+ goto exit;
+ }
+ buf.ota_clm_buf[0] = buffer_clm;
+
+ check_multiple_nvram_clm(NVRAM, prop_revision_buf, sku_name,
+ &buffer_nvram, &buf.ota_nvram_len);
+ if (buffer_nvram == NULL) {
+ ALOGE("buffer_nvram is null");
+ goto exit;
+ }
+ buf.ota_nvram_buf[0] = buffer_nvram;
+ cmd->otaDownload(&buf, ota_version);
+
+exit:
+ if (buffer_clm != NULL) {
+ free(buffer_clm);
+ }
+ if (buffer_nvram != NULL) {
+ free(buffer_nvram);
+ }
+
+ cmd->releaseRef();
+
+ return result;
+}
diff --git a/bcmdhd/wifi_hal/wifi_offload.cpp b/bcmdhd/wifi_hal/wifi_offload.cpp
index 8054f49..1702ffd 100644
--- a/bcmdhd/wifi_hal/wifi_offload.cpp
+++ b/bcmdhd/wifi_hal/wifi_offload.cpp
@@ -52,13 +52,16 @@
} WIFI_OFFLOAD_SUB_COMMAND;
typedef enum {
- MKEEP_ALIVE_ATTRIBUTE_ID,
- MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
- MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
- MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
- MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
- MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
- MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE
+ MKEEP_ALIVE_ATTRIBUTE_INVALID = 0,
+ MKEEP_ALIVE_ATTRIBUTE_ID = 1,
+ MKEEP_ALIVE_ATTRIBUTE_IP_PKT = 2,
+ MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN = 3,
+ MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR = 4,
+ MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR = 5,
+ MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC = 6,
+ MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE = 7,
+ /* Add new attributes just above this */
+ MKEEP_ALIVE_ATTRIBUTE_MAX
} WIFI_MKEEP_ALIVE_ATTRIBUTE;
typedef enum {