summaryrefslogtreecommitdiffstats
path: root/bcmdhd/wifi_hal/wifi_hal.cpp
diff options
context:
space:
mode:
authorAshwin <ashwin.bhat@broadcom.com>2015-06-12 13:08:45 -0700
committerVinit Deshpande <vinitd@google.com>2015-06-24 10:55:57 -0700
commitfef13c11034313585be68c32322b9a53c43a37b2 (patch)
tree6f54b84d47b7cf8ab895decec6805393a9ce9d7e /bcmdhd/wifi_hal/wifi_hal.cpp
parent6a4c420bc727655771343331e02850f683f00bbb (diff)
downloadhardware_broadcom_wlan-fef13c11034313585be68c32322b9a53c43a37b2.tar.gz
hardware_broadcom_wlan-fef13c11034313585be68c32322b9a53c43a37b2.tar.bz2
hardware_broadcom_wlan-fef13c11034313585be68c32322b9a53c43a37b2.zip
RSSI monitor changes
RSSI monitor is used to set RSSI thresholds to driver and rx events when thresholds are crossed. also includes some code cleanup Change-Id: Ia55ded489ed5d4232e6fea0ffdcfc824522613b1 Signed-off-by: Ashwin <ashwin.bhat@broadcom.com>
Diffstat (limited to 'bcmdhd/wifi_hal/wifi_hal.cpp')
-rw-r--r--bcmdhd/wifi_hal/wifi_hal.cpp155
1 files changed, 155 insertions, 0 deletions
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index 6f14a66..22912f9 100644
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -53,6 +53,9 @@ 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);
static int wifi_add_membership(wifi_handle handle, const char *group);
static wifi_error wifi_init_interfaces(wifi_handle handle);
+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);
+static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
typedef enum wifi_attr {
ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
@@ -60,6 +63,12 @@ typedef enum wifi_attr {
ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI
} wifi_attr_t;
+enum wifi_rssi_monitor_attr {
+ RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
+ RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
+ RSSI_MONITOR_ATTRIBUTE_START,
+};
+
/* Initialize/Cleanup */
void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
@@ -145,6 +154,8 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
fn->wifi_set_bssid_preference = wifi_set_bssid_preference;
fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam;
+ fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
+ fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
return WIFI_SUCCESS;
}
@@ -624,6 +635,121 @@ public:
}
};
+class SetRSSIMonitorCommand : public WifiCommand {
+private:
+ s8 mMax_rssi;
+ s8 mMin_rssi;
+ wifi_rssi_event_handler mHandler;
+public:
+ SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
+ s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
+ : WifiCommand(handle, id), mMax_rssi(max_rssi), mMin_rssi(min_rssi), mHandler(eh)
+ {
+ }
+ int createRequest(WifiRequest& request, int enable) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
+ if (result < 0) {
+ return result;
+ }
+ ALOGD("create request");
+ result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
+ if (result < 0) {
+ return result;
+ }
+ result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
+ if (result < 0) {
+ return result;
+ }
+ request.attr_end(data);
+ return result;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request, 1);
+ if (result < 0) {
+ return result;
+ }
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGI("Failed to set RSSI Monitor, result = %d", result);
+ return result;
+ }
+ ALOGI("Successfully set RSSI monitoring");
+ registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+
+
+ if (result < 0) {
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ return result;
+ }
+ ALOGI("Done!");
+ return result;
+ }
+
+ virtual int cancel() {
+
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request, 0);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create request; result = %d", result);
+ } else {
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to stop RSSI monitoring = %d", result);
+ }
+ }
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ return WIFI_SUCCESS;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ ALOGI("Got a RSSI monitor event");
+
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGI("RSSI monitor: No data");
+ return NL_SKIP;
+ }
+ /* driver<->HAL event structure */
+ #define RSSI_MONITOR_EVT_VERSION 1
+ typedef struct {
+ u8 version;
+ s8 cur_rssi;
+ mac_addr BSSID;
+ } rssi_monitor_evt;
+
+ rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
+
+ if (data->version != RSSI_MONITOR_EVT_VERSION) {
+ ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
+ return NL_SKIP;
+ }
+
+ if (*mHandler.on_rssi_threshold_breached) {
+ (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
+ } else {
+ ALOGW("No RSSI monitor handler registered");
+ }
+
+ return NL_SKIP;
+ }
+
+};
+
class GetFeatureSetCommand : public WifiCommand {
private:
@@ -851,4 +977,33 @@ wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *count
return (wifi_error) command.requestResponse();
}
+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);
+ wifi_handle handle = getWifiHandle(iface);
+ SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
+ wifi_register_cmd(handle, id, cmd);
+ return (wifi_error)cmd->start();
+}
+
+
+static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
+{
+ ALOGD("Stopping RSSI monitor");
+
+ 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);
+ cmd->cancel();
+ cmd->releaseRef();
+ return WIFI_SUCCESS;
+ }
+ return wifi_cancel_cmd(id, iface);
+}
+
/////////////////////////////////////////////////////////////////////////////