summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-16 21:27:29 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-10-16 21:27:29 +0000
commiteae62b98409be855ff25142bafea5468fcd0d35c (patch)
treee85a39a8d72b962035b725bf8e947c6119c82cac
parent9ad696cade24229e8c541f20e6ae853e75b0067c (diff)
parentcf585f68ac0121f807c642b3757f37873fd4f88b (diff)
downloadwlan-eae62b98409be855ff25142bafea5468fcd0d35c.tar.gz
Merge "Snap for 10957012 from 2ae324a109af6109c9e832604b1b1d3a099fd02a to simpleperf-release" into simpleperf-release
-rw-r--r--OWNERS1
-rw-r--r--bcmdhd/wifi_hal/Android.bp1
-rw-r--r--[-rwxr-xr-x]bcmdhd/wifi_hal/common.h6
-rw-r--r--bcmdhd/wifi_hal/link_layer_stats.cpp20
-rwxr-xr-xbcmdhd/wifi_hal/nan.cpp30
-rw-r--r--bcmdhd/wifi_hal/rtt.cpp173
-rw-r--r--bcmdhd/wifi_hal/scan.cpp166
-rwxr-xr-xbcmdhd/wifi_hal/twt.cpp4
-rw-r--r--[-rwxr-xr-x]bcmdhd/wifi_hal/wifi_hal.cpp52
9 files changed, 395 insertions, 58 deletions
diff --git a/OWNERS b/OWNERS
index d8c95cc..dd590d3 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
arabawy@google.com
etancohen@google.com
kumachang@google.com
+wangroger@google.com
diff --git a/bcmdhd/wifi_hal/Android.bp b/bcmdhd/wifi_hal/Android.bp
index 92498f3..4994828 100644
--- a/bcmdhd/wifi_hal/Android.bp
+++ b/bcmdhd/wifi_hal/Android.bp
@@ -84,6 +84,7 @@ cc_library_static {
"wifi_logger.cpp",
"wifi_offload.cpp",
"twt.cpp",
+ "scan.cpp",
],
proprietary: true,
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index 4c7973b..b54fbb1 100755..100644
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -33,6 +33,7 @@
#define DEFAULT_CMD_SIZE (64)
#define DOT11_OUI_LEN 3
#define DOT11_MAX_SSID_LEN 32
+#define MAX_CACHED_SCAN_RESULT 32
#define ETHERTYPE_IP 0x0800 /* IP */
#define ETHERTYPE_IPV6 0x86dd /* IP protocol version 6 */
@@ -142,6 +143,9 @@ typedef enum {
ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_START = 0x2160,
ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_END = 0x216F,
+ /* define scan related commands between 0x2170 and 0x2175 */
+ ANDROID_NL80211_SUBCMD_SCAN_START = 0x2170,
+ ANDROID_NL80211_SUBCMD_SCAN_END = 0x2175,
/* This is reserved for future usage */
} ANDROID_VENDOR_SUB_COMMAND;
@@ -187,6 +191,7 @@ typedef enum {
WIFI_SUBCMD_SET_MULTISTA_PRIMARY_CONNECTION, /* 0x101c */
WIFI_SUBCMD_SET_MULTISTA_USE_CASE, /* 0x101d */
WIFI_SUBCMD_SET_DTIM_CONFIG, /* 0x101e */
+ WIFI_SUBCMD_CHANNEL_POLICY, /* 0x101f */
GSCAN_SUBCMD_MAX,
@@ -234,6 +239,7 @@ typedef enum {
WIFI_SUBCMD_TRIGGER_SSR = ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_START,
WIFI_SUBCMD_GET_RADIO_COMBO_MATRIX,
WIFI_SUBCMD_ENABLE_TX_POWER_LIMIT,
+ WIFI_SUBCMD_GET_CACHED_SCAN_RESULTS = ANDROID_NL80211_SUBCMD_SCAN_START,
} WIFI_SUB_COMMAND;
typedef enum {
diff --git a/bcmdhd/wifi_hal/link_layer_stats.cpp b/bcmdhd/wifi_hal/link_layer_stats.cpp
index 04b89b5..05ab438 100644
--- a/bcmdhd/wifi_hal/link_layer_stats.cpp
+++ b/bcmdhd/wifi_hal/link_layer_stats.cpp
@@ -131,6 +131,11 @@ protected:
}
if (num_radios) {
+ if (!data || !data_len) {
+ ALOGE("%s: null data\n", __func__);
+ return NL_SKIP;
+ }
+
rem_len = MAX_CMD_RESP_BUF_LEN;
radioStatsBuf = (u8 *)malloc(MAX_CMD_RESP_BUF_LEN);
if (!radioStatsBuf) {
@@ -140,11 +145,6 @@ protected:
memset(radioStatsBuf, 0, MAX_CMD_RESP_BUF_LEN);
output = radioStatsBuf;
- if (!data || !data_len) {
- ALOGE("%s: null data\n", __func__);
- return NL_SKIP;
- }
-
data_ptr = (u8*)data;
for (int i = 0; i < num_radios; i++) {
rem_len -= per_radio_size;
@@ -161,12 +161,18 @@ protected:
convertToExternalRadioStatStructure((wifi_radio_stat*)data_ptr,
&per_radio_size);
if (!radio_stat_ptr || !per_radio_size) {
+ if (radio_stat_ptr) {
+ free(radio_stat_ptr);
+ radio_stat_ptr = NULL;
+ }
ALOGE("No data for radio %d\n", i);
continue;
}
memcpy(output, radio_stat_ptr, per_radio_size);
output += per_radio_size;
total_size += per_radio_size;
+ free(radio_stat_ptr);
+ radio_stat_ptr = NULL;
}
iface_stat = ((u8*)data + total_size);
@@ -179,10 +185,6 @@ protected:
num_radios, (wifi_radio_stat *)radioStatsBuf);
}
exit:
- if (radio_stat_ptr) {
- free(radio_stat_ptr);
- radio_stat_ptr = NULL;
- }
if (radioStatsBuf) {
free(radioStatsBuf);
radioStatsBuf = NULL;
diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp
index a2d2d47..4dd4dd9 100755
--- a/bcmdhd/wifi_hal/nan.cpp
+++ b/bcmdhd/wifi_hal/nan.cpp
@@ -1390,8 +1390,6 @@ class NanDiscEnginePrimitive : public WifiCommand
}
if (mParams->service_specific_info_len > 0) {
- u16 len = min(mParams->service_specific_info_len,
- sizeof(mParams->service_specific_info) - 1);
result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
mParams->service_specific_info_len);
if (result < 0) {
@@ -1406,7 +1404,7 @@ class NanDiscEnginePrimitive : public WifiCommand
ALOGE("%s: Failed to put svc info, result = %d", __func__, result);
return result;
}
- mParams->service_specific_info[len] = '\0';
+ mParams->service_specific_info[mParams->service_specific_info_len] = '\0';
ALOGI("Transmit service info string is %s\n", mParams->service_specific_info);
}
@@ -1510,11 +1508,13 @@ class NanDiscEnginePrimitive : public WifiCommand
{
nan_hal_resp_t *rsp_vndr_data = NULL;
NanResponseMsg rsp_data;
+ u32 len;
if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
return NL_SKIP;
}
rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
+ len = reply.get_vendor_data_len();
ALOGI("NanDiscEnginePrmitive::handle response\n");
memset(&rsp_data, 0, sizeof(NanResponseMsg));
rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
@@ -1543,8 +1543,28 @@ class NanDiscEnginePrimitive : public WifiCommand
} else if (rsp_data.response_type == NAN_RESPONSE_SUBSCRIBE) {
rsp_data.body.subscribe_response.subscribe_id = mInstId;
} else if (rsp_data.response_type == NAN_GET_CAPABILITIES) {
- memcpy((void *)&rsp_data.body.nan_capabilities, (void *)&rsp_vndr_data->capabilities,
- sizeof(rsp_data.body.nan_capabilities));
+ /* avoid memcpy to keep backward compatibility */
+ NanCapabilities *desc = &rsp_data.body.nan_capabilities;
+ NanCapabilities *src = &rsp_vndr_data->capabilities;
+
+ desc->max_publishes = src->max_publishes;
+ desc->max_subscribes = src->max_subscribes;
+ desc->max_ndi_interfaces = src->max_ndi_interfaces;
+ desc->max_ndp_sessions = src->max_ndp_sessions;
+ desc->max_concurrent_nan_clusters = src->max_concurrent_nan_clusters;
+ desc->max_service_name_len = src->max_service_name_len;
+ desc->max_match_filter_len = src->max_match_filter_len;
+ desc->max_total_match_filter_len = src->max_total_match_filter_len;
+ desc->max_service_specific_info_len = src->max_service_specific_info_len;
+ desc->max_app_info_len = src->max_app_info_len;
+ desc->max_sdea_service_specific_info_len = src->max_sdea_service_specific_info_len;
+ desc->max_queued_transmit_followup_msgs = src->max_queued_transmit_followup_msgs;
+ desc->max_subscribe_address = src->max_subscribe_address;
+ desc->is_ndp_security_supported = src->is_ndp_security_supported;
+ desc->ndp_supported_bands = src->ndp_supported_bands;
+ desc->cipher_suites_supported = src->cipher_suites_supported;
+ desc->is_instant_mode_supported = src->is_instant_mode_supported;
+ desc->ndpe_attr_supported = src->ndpe_attr_supported;
}
GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
diff --git a/bcmdhd/wifi_hal/rtt.cpp b/bcmdhd/wifi_hal/rtt.cpp
index 603caf3..2197c81 100644
--- a/bcmdhd/wifi_hal/rtt.cpp
+++ b/bcmdhd/wifi_hal/rtt.cpp
@@ -48,7 +48,8 @@
#include "cpp_bindings.h"
using namespace android;
-#define RTT_RESULT_SIZE (sizeof(wifi_rtt_result));
+#define RTT_RESULT_V2_SIZE (sizeof(wifi_rtt_result_v2))
+#define RTT_RESULT_V1_SIZE (sizeof(wifi_rtt_result))
typedef enum {
RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
@@ -82,6 +83,8 @@ typedef enum {
RTT_ATTRIBUTE_RESULT_CNT = 32,
RTT_ATTRIBUTE_RESULT = 33,
RTT_ATTRIBUTE_RESUTL_DETAIL = 34,
+ RTT_ATTRIBUTE_RESULT_FREQ = 35,
+ RTT_ATTRIBUTE_RESULT_BW = 36,
/* Add any new RTT_ATTRIBUTE prior to RTT_ATTRIBUTE_MAX */
RTT_ATTRIBUTE_MAX
} RTT_ATTRIBUTE;
@@ -131,7 +134,7 @@ get_err_info(int status)
for (i = 0; i < (int) num_entries; i++)
{
if (p_entry->id == status)
- return p_entry->text;
+ return p_entry->text.c_str();
p_entry++; /* next entry */
}
return "unknown error"; /* not found */
@@ -321,9 +324,15 @@ class RttCommand : public WifiCommand
int currDtlIdx;
int totalCnt;
static const int MAX_RESULTS = 1024;
- wifi_rtt_result *rttResults[MAX_RESULTS];
+ wifi_rtt_result_v2 *rttResults[MAX_RESULTS];
wifi_rtt_config *rttParams;
wifi_rtt_event_handler rttHandler;
+ int nextidx = 0;
+ wifi_rtt_result *rttResultsV1[MAX_RESULTS];
+ wifi_channel channel;
+ wifi_rtt_bw bw = WIFI_RTT_BW_UNSPECIFIED;
+ int result_size;
+ int opt_result_size;
public:
RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
@@ -331,6 +340,7 @@ public:
rttHandler(handler)
{
memset(rttResults, 0, sizeof(rttResults));
+ memset(rttResultsV1, 0, sizeof(rttResultsV1));
currentIdx = 0;
mCompleted = 0;
totalCnt = 0;
@@ -345,9 +355,10 @@ public:
totalCnt = 0;
currDtlIdx = 0;
numRttParams = 0;
- memset(rttResults, 0, sizeof(rttResults));
- rttParams = NULL;
- rttHandler.on_rtt_results = NULL;
+ memset(rttResults, 0, sizeof(rttResults));
+ memset(rttResultsV1, 0, sizeof(rttResultsV1));
+ rttParams = NULL;
+ rttHandler.on_rtt_results_v2 = NULL;
}
int createSetupRequest(WifiRequest& request) {
@@ -563,79 +574,159 @@ public:
bssid[3],
bssid[4],
bssid[5]);
+ } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_FREQ) {
+ channel = it2.get_u32();
+ if (rttResults[currentIdx] == NULL) {
+ ALOGE("Not allocated, currentIdx %d\n", currentIdx);
+ break;
+ }
+ if (!channel) {
+ rttResults[currentIdx]->frequency = UNSPECIFIED;
+ } else {
+ rttResults[currentIdx]->frequency = channel;
+ }
+ ALOGI("retrieved rtt_result : \n\tchannel :%d",
+ rttResults[currentIdx]->frequency);
+ } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_BW) {
+ bw = (wifi_rtt_bw)it2.get_u32();
+ if (rttResults[currentIdx] == NULL) {
+ ALOGE("Not allocated, currentIdx %d\n", currentIdx);
+ break;
+ }
+ rttResults[currentIdx]->packet_bw = bw;
+ ALOGI("retrieved rtt_result : \n\tpacket_bw :%d",
+ rttResults[currentIdx]->packet_bw);
} else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) {
result_cnt = it2.get_u32();
ALOGI("retrieved result_cnt : %d\n", result_cnt);
} else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) {
+ currentIdx = nextidx;
int result_len = it2.get_len();
- rttResults[currentIdx] = (wifi_rtt_result *)malloc(it2.get_len());
- wifi_rtt_result *rtt_result = rttResults[currentIdx];
- if (rtt_result == NULL) {
+ rttResultsV1[currentIdx] =
+ (wifi_rtt_result *)malloc(it2.get_len());
+ wifi_rtt_result *rtt_results_v1 = rttResultsV1[currentIdx];
+ if (rtt_results_v1 == NULL) {
mCompleted = 1;
- ALOGE("failed to allocate the wifi_rtt_result\n");
+ ALOGE("failed to allocate the wifi_result_v1\n");
break;
}
- memcpy(rtt_result, it2.get_data(), it2.get_len());
- result_len -= sizeof(wifi_rtt_result);
+
+ /* Populate to the rtt_results_v1 struct */
+ memcpy(rtt_results_v1, it2.get_data(), it2.get_len());
+
+ /* handle the optional data */
+ result_len -= RTT_RESULT_V1_SIZE;
if (result_len > 0) {
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);
+ ele_1 = (dot11_rm_ie_t *)(rtt_results_v1 + 1);
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;
+ rtt_results_v1->LCI = (wifi_information_element *)ele_1;
result_len -= (ele_1->len + DOT11_HDR_LEN);
+ opt_result_size += (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));
+ ele_2 = (dot11_rm_ie_t *)((char *)ele_1 +
+ (ele_1->len + DOT11_HDR_LEN));
if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
(ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
- rtt_result->LCR = (wifi_information_element *)ele_2;
+ rtt_results_v1->LCR = (wifi_information_element *)ele_2;
}
}
} else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC){
- rtt_result->LCR = (wifi_information_element *)ele_1;
+ rtt_results_v1->LCR = (wifi_information_element *)ele_1;
result_len -= (ele_1->len + DOT11_HDR_LEN);
+ opt_result_size += (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));
+ ele_2 = (dot11_rm_ie_t *)((char *)ele_1 +
+ (ele_1->len + DOT11_HDR_LEN));
if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
(ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
- rtt_result->LCI = (wifi_information_element *)ele_2;
+ rtt_results_v1->LCI = (wifi_information_element *)ele_2;
}
}
}
}
}
+
+ /* Alloc new struct including new elements, reserve for new elements */
+ rttResults[currentIdx] =
+ (wifi_rtt_result_v2 *)malloc(RTT_RESULT_V2_SIZE + opt_result_size);
+ wifi_rtt_result_v2 *rtt_result_v2 = rttResults[currentIdx];
+ if (rtt_result_v2 == NULL) {
+ ALOGE("failed to allocate the rtt_result\n");
+ break;
+ }
+
+ /* Populate the new struct as per the legacy struct elements */
+ memcpy(&rtt_result_v2->rtt_result,
+ (wifi_rtt_result *)rtt_results_v1, RTT_RESULT_V1_SIZE);
+ if (!channel) {
+ rtt_result_v2->frequency = UNSPECIFIED;
+ }
+
+ /* Copy the optional data to new struct */
+ if (opt_result_size &&
+ (opt_result_size == (it2.get_len() - RTT_RESULT_V1_SIZE))) {
+
+ wifi_rtt_result_v2 *opt_rtt_result = NULL;
+ /* Intersect the optional data from legacy rtt result struct */
+ wifi_rtt_result *opt_legacy_rtt_result =
+ (wifi_rtt_result *)(rtt_results_v1 + RTT_RESULT_V1_SIZE);
+
+ /* shift dest buf by size of new rtt result struct */
+ opt_rtt_result =
+ (wifi_rtt_result_v2 *)rtt_result_v2 + RTT_RESULT_V2_SIZE;
+
+ /* Append optional rtt_result_v1 data to rtt_result_v2 */
+ memcpy(opt_rtt_result, opt_legacy_rtt_result,
+ (it2.get_len() - RTT_RESULT_V1_SIZE));
+ } else {
+ ALOGI("Optional rtt result elements missing, skip processing\n");
+ }
+
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 : %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,
- (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++;
+ ALOGI("retrieved rtt_result : \n\tburst_num :%d, measurement_number : %d"
+ ", success_number : %d \tnumber_per_burst_peer : %d, status : %s,"
+ " retry_after_duration : %d s\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_results_v1->burst_num, rtt_results_v1->measurement_number,
+ rtt_results_v1->success_number,
+ rtt_results_v1->number_per_burst_peer,
+ get_err_info(rtt_results_v1->status),
+ rtt_results_v1->retry_after_duration,
+ rtt_results_v1->rssi, rtt_results_v1->rx_rate.bitrate * 100,
+ (unsigned long)rtt_results_v1->rtt/1000,
+ (unsigned long)rtt_results_v1->rtt_sd,
+ rtt_results_v1->distance_mm / 10,
+ rtt_results_v1->burst_duration,
+ rtt_results_v1->negotiated_burst_num);
+ nextidx = currentIdx;
+ nextidx++;
}
}
}
-
}
if (mCompleted) {
unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
- if (*rttHandler.on_rtt_results) {
- (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
+ {
+ if (*rttHandler.on_rtt_results_v2) {
+ (*rttHandler.on_rtt_results_v2)(id(), totalCnt, rttResults);
+ }
}
for (int i = 0; i < currentIdx; i++) {
free(rttResults[i]);
rttResults[i] = NULL;
+
+ free(rttResultsV1[i]);
+ rttResultsV1[i] = NULL;
}
- totalCnt = currentIdx = 0;
+ totalCnt = currentIdx = nextidx = 0;
WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id());
if (cmd)
cmd->releaseRef();
@@ -650,16 +741,16 @@ wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle ifac
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;
+ 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;
+ ALOGE("wifi_rtt_range_request: NULL handle pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
}
ALOGI("Rtt range_request; id = %d", id);
diff --git a/bcmdhd/wifi_hal/scan.cpp b/bcmdhd/wifi_hal/scan.cpp
new file mode 100644
index 0000000..d8ab4e0
--- /dev/null
+++ b/bcmdhd/wifi_hal/scan.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Portions copyright (C) 2022 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 <hardware_legacy/wifi_hal.h>
+#include "common.h"
+#include "cpp_bindings.h"
+
+#define CACHE_SCAN_RESULT_SIZE sizeof(wifi_cached_scan_result)
+#define MAX_CACHE_SCAN_RESULT_SIZE (MAX_CACHED_SCAN_RESULT*CACHE_SCAN_RESULT_SIZE)
+typedef enum {
+ WIFI_ATTRIBUTE_CACHED_SCAN_INVALID = 0,
+ WIFI_ATTRIBUTE_CACHED_SCAN_BOOT_TIMESTAMP = 1,
+ WIFI_ATTRIBUTE_CACHED_SCANNED_FREQ_NUM = 2,
+ WIFI_ATTRIBUTE_CACHED_SCANNED_FREQ_LIST = 3,
+ WIFI_ATTRIBUTE_CACHED_SCAN_RESULT_CNT = 4,
+ WIFI_ATTRIBUTE_CACHED_SCAN_RESULTS = 5,
+ WIFI_ATTRIBUTE_CACHED_SCAN_MAX
+} SCAN_ATTRIBUTE;
+/////////////////////////////////////////////////////////////////////////////
+
+class GetCachedScanResultsCommand : public WifiCommand {
+ wifi_cached_scan_result_handler mHandler;
+ wifi_cached_scan_report *mReport;
+
+public:
+ GetCachedScanResultsCommand(wifi_interface_handle iface, int id,
+ wifi_cached_scan_result_handler handler)
+ : WifiCommand("GetCachedScanResultsCommand", iface, id), mHandler(handler)
+ {
+ mReport = NULL;
+ }
+
+ virtual int create() {
+ ALOGE("Creating message to get cached scan results");
+
+ int ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_CACHED_SCAN_RESULTS);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return ret;
+ }
+
+ protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGI("In GetCachedScanResultsCommand::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();
+ int valid_entries = 0;
+ int result_size = 0;
+ wifi_timestamp timestamp = 0;
+ int size = 0;
+
+ ALOGV("Id = %0x, subcmd = %d", id, subcmd);
+
+ 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 GetCachedScanResults response; ignoring it");
+ return NL_SKIP;
+ }
+
+ mReport = (wifi_cached_scan_report *)malloc(sizeof(wifi_cached_scan_report));
+ if (mReport == NULL) {
+ ALOGE("Failed to allocate!!\n");
+ return NL_SKIP;
+ }
+ memset(mReport, 0, sizeof(wifi_cached_scan_report));
+
+ ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ if (it.get_type() == WIFI_ATTRIBUTE_CACHED_SCAN_BOOT_TIMESTAMP) {
+ timestamp = it.get_u32();
+ ALOGV("Time since boot_ms: %ld\n", timestamp);
+ } else if (it.get_type() == WIFI_ATTRIBUTE_CACHED_SCAN_RESULT_CNT) {
+ valid_entries = min(it.get_u16(), MAX_CACHED_SCAN_RESULT);
+ ALOGV("cached scan result cnt: %d", valid_entries);
+ } else if ((it.get_type() == WIFI_ATTRIBUTE_CACHED_SCAN_RESULTS) &&
+ valid_entries && timestamp) {
+ size = min(it.get_len(), MAX_CACHE_SCAN_RESULT_SIZE);
+ if (size > (valid_entries*CACHE_SCAN_RESULT_SIZE)) {
+ ALOGE("Not enough space to copy!!\n");
+ return NL_SKIP;
+ }
+ result_size = valid_entries * CACHE_SCAN_RESULT_SIZE;
+ mReport->results = (wifi_cached_scan_result *)malloc(result_size);
+ if (mReport->results == NULL) {
+ ALOGE("Failed to allocate!!\n");
+ return NL_SKIP;
+ }
+ memcpy((void *)mReport->results, (void *)it.get_data(), size);
+ } else {
+ ALOGW("Ignoring invalid attribute type = %d, size = %d",
+ it.get_type(), it.get_len());
+ }
+ }
+
+ mReport->ts = timestamp;
+ mReport->result_cnt = valid_entries;
+
+ if (*mHandler.on_cached_scan_results && mReport) {
+ (*mHandler.on_cached_scan_results)(mReport);
+ ALOGV("Notified cache scan report!!");
+ }
+
+ if (mReport) {
+ if (mReport->results) {
+ free((void *)mReport->results);
+ }
+ free(mReport);
+ }
+ return NL_OK;
+ }
+};
+
+wifi_error wifi_get_cached_scan_results(wifi_interface_handle iface,
+ wifi_cached_scan_result_handler handler)
+{
+ ALOGI("Getting cached scan results, iface handle = %p", iface);
+ GetCachedScanResultsCommand command(iface, 0, handler);
+ return (wifi_error) command.requestResponse();
+}
diff --git a/bcmdhd/wifi_hal/twt.cpp b/bcmdhd/wifi_hal/twt.cpp
index e3dd5bd..63cd002 100755
--- a/bcmdhd/wifi_hal/twt.cpp
+++ b/bcmdhd/wifi_hal/twt.cpp
@@ -367,7 +367,7 @@ protected:
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);
+ ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
if (data == NULL || len == 0) {
ALOGE("no vendor data in GetTwtCapabilitiesCommand response; ignoring it\n");
return NL_SKIP;
@@ -463,7 +463,7 @@ protected:
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);
+ ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
if (data == NULL || len == 0) {
ALOGE("no vendor data in GetTwtStatsCommand response; ignoring it\n");
return NL_SKIP;
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index e6a14e7..f746f09 100755..100644
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -100,6 +100,10 @@ static wifi_error wifi_get_supported_radio_combinations_matrix(wifi_handle handl
static void wifi_cleanup_dynamic_ifaces(wifi_handle handle);
static wifi_error wifi_enable_tx_power_limits(wifi_interface_handle iface,
bool isEnable);
+wifi_error wifi_get_cached_scan_results(wifi_interface_handle iface,
+ wifi_cached_scan_result_handler handler);
+wifi_error wifi_enable_sta_channel_for_peer_network(wifi_handle handle,
+ u32 channelCategoryEnableFlag);
typedef enum wifi_attr {
ANDR_WIFI_ATTRIBUTE_INVALID = 0,
@@ -117,6 +121,7 @@ typedef enum wifi_attr {
ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW = 12,
ANDR_WIFI_ATTRIBUTE_VOIP_MODE = 13,
ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER = 14,
+ ANDR_WIFI_ATTRIBUTE_CHAN_POLICY = 15,
// Add more attribute here
ANDR_WIFI_ATTRIBUTE_MAX
} wifi_attr_t;
@@ -355,7 +360,8 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
fn->wifi_nan_rtt_chre_disable_request = nan_chre_disable_request;
fn->wifi_chre_register_handler = nan_chre_register_handler;
fn->wifi_enable_tx_power_limits = wifi_enable_tx_power_limits;
-
+ fn->wifi_get_cached_scan_results = wifi_get_cached_scan_results;
+ fn->wifi_enable_sta_channel_for_peer_network = wifi_enable_sta_channel_for_peer_network;
return WIFI_SUCCESS;
}
#ifdef GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
@@ -3056,3 +3062,47 @@ wifi_error wifi_enable_tx_power_limits(wifi_interface_handle handle, bool isEnab
EnableTxPowerLimit command(handle, isEnable);
return (wifi_error) command.requestResponse();
}
+
+//////////////////////////////////////////////////////
+class EnableStaChannel : public WifiCommand {
+
+private:
+ u32 mChannelCatEnabFlag;
+public:
+ EnableStaChannel(wifi_interface_handle handle, u32 channelCategoryEnableFlag)
+ : WifiCommand("EnableStaChannel", handle, 0) {
+ mChannelCatEnabFlag = channelCategoryEnableFlag;
+ }
+ virtual int create() {
+ int ret;
+
+ ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_CHANNEL_POLICY);
+ 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_CHAN_POLICY, mChannelCatEnabFlag);
+ if (ret < 0) {
+ return ret;
+ }
+
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+};
+
+/* enable or disable the feature of allowing current STA-connected
+ * channel for WFA GO, SAP and Wi-Fi Aware when the regulatory allows.
+ */
+wifi_error wifi_enable_sta_channel_for_peer_network(wifi_handle handle,
+ u32 channelCategoryEnableFlag) {
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ EnableStaChannel command(wlan0Handle, channelCategoryEnableFlag);
+ return (wifi_error) command.requestResponse();
+}