1 /* Copyright (c) 2015, 2018 The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions 5 * are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in 10 * the documentation and/or other materials provided with the 11 * distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "sync.h" 30 31 #define LOG_TAG "WifiHAL" 32 33 #include <utils/Log.h> 34 35 #include "wifi_hal.h" 36 #include "common.h" 37 #include "cpp_bindings.h" 38 #include "rssi_monitor.h" 39 #include "vendor_definitions.h" 40 41 /* Used to handle rssi command events from driver/firmware.*/ 42 typedef struct rssi_monitor_event_handler_s { 43 RSSIMonitorCommand* mRSSIMonitorCommandInstance; 44 } rssi_monitor_event_handlers; 45 46 wifi_error initializeRSSIMonitorHandler(hal_info *info) 47 { 48 info->rssi_handlers = (rssi_monitor_event_handlers *)malloc(sizeof( 49 rssi_monitor_event_handlers)); 50 if (info->rssi_handlers) { 51 memset(info->rssi_handlers, 0, sizeof(rssi_monitor_event_handlers)); 52 } 53 else { 54 ALOGE("%s: Allocation of RSSI event handlers failed", 55 __FUNCTION__); 56 return WIFI_ERROR_OUT_OF_MEMORY; 57 } 58 return WIFI_SUCCESS; 59 } 60 61 wifi_error cleanupRSSIMonitorHandler(hal_info *info) 62 { 63 rssi_monitor_event_handlers* event_handlers; 64 if (info && info->rssi_handlers) { 65 event_handlers = (rssi_monitor_event_handlers*) info->rssi_handlers; 66 if (event_handlers->mRSSIMonitorCommandInstance) { 67 delete event_handlers->mRSSIMonitorCommandInstance; 68 } 69 memset(event_handlers, 0, sizeof(rssi_monitor_event_handlers)); 70 free(info->rssi_handlers); 71 info->rssi_handlers = NULL; 72 return WIFI_SUCCESS; 73 } 74 ALOGE ("%s: info or info->rssi_handlers NULL", __FUNCTION__); 75 return WIFI_ERROR_UNKNOWN; 76 } 77 78 void RSSIMonitorCommand::enableEventHandling() 79 { 80 pthread_mutex_lock(&rm_lock); 81 mEventHandlingEnabled = true; 82 pthread_mutex_unlock(&rm_lock); 83 } 84 85 void RSSIMonitorCommand::disableEventHandling() 86 { 87 pthread_mutex_lock(&rm_lock); 88 mEventHandlingEnabled = false; 89 pthread_mutex_unlock(&rm_lock); 90 } 91 92 bool RSSIMonitorCommand::isEventHandlingEnabled() 93 { 94 bool eventHandlingEnabled; 95 pthread_mutex_lock(&rm_lock); 96 eventHandlingEnabled = mEventHandlingEnabled; 97 pthread_mutex_unlock(&rm_lock); 98 99 return eventHandlingEnabled; 100 } 101 102 void RSSIMonitorCommand::setCallbackHandler(wifi_rssi_event_handler handler) 103 { 104 mHandler = handler; 105 } 106 107 RSSIMonitorCommand::RSSIMonitorCommand(wifi_handle handle, int id, 108 u32 vendor_id, u32 subcmd) 109 : WifiVendorCommand(handle, id, vendor_id, subcmd) 110 { 111 memset(&mHandler, 0, sizeof(mHandler)); 112 if (registerVendorHandler(vendor_id, subcmd)) { 113 /* Error case should not happen print log */ 114 ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u", 115 __FUNCTION__, vendor_id, subcmd); 116 } 117 pthread_mutex_init(&rm_lock, NULL); 118 disableEventHandling(); 119 } 120 121 RSSIMonitorCommand::~RSSIMonitorCommand() 122 { 123 unregisterVendorHandler(mVendor_id, mSubcmd); 124 pthread_mutex_destroy(&rm_lock); 125 } 126 127 void RSSIMonitorCommand::setReqId(wifi_request_id reqid) 128 { 129 mId = reqid; 130 } 131 132 RSSIMonitorCommand* RSSIMonitorCommand::instance(wifi_handle handle, 133 wifi_request_id id) 134 { 135 if (handle == NULL) { 136 ALOGE("Interface Handle is invalid"); 137 return NULL; 138 } 139 hal_info *info = getHalInfo(handle); 140 if (!info || !info->rssi_handlers) { 141 ALOGE("rssi_handlers is invalid"); 142 return NULL; 143 } 144 145 RSSIMonitorCommand* mRSSIMonitorCommandInstance = 146 info->rssi_handlers->mRSSIMonitorCommandInstance; 147 148 if (mRSSIMonitorCommandInstance == NULL) { 149 mRSSIMonitorCommandInstance = new RSSIMonitorCommand(handle, id, 150 OUI_QCA, 151 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI); 152 info->rssi_handlers->mRSSIMonitorCommandInstance = mRSSIMonitorCommandInstance; 153 return mRSSIMonitorCommandInstance; 154 } 155 else 156 { 157 if (handle != getWifiHandle(mRSSIMonitorCommandInstance->mInfo)) 158 { 159 /* upper layer must have cleaned up the handle and reinitialized, 160 so we need to update the same */ 161 ALOGV("Handle different, update the handle"); 162 mRSSIMonitorCommandInstance->mInfo = (hal_info *)handle; 163 } 164 mRSSIMonitorCommandInstance->setReqId(id); 165 } 166 return mRSSIMonitorCommandInstance; 167 } 168 169 /* This function will be the main handler for incoming event. 170 * Call the appropriate callback handler after parsing the vendor data. 171 */ 172 int RSSIMonitorCommand::handleEvent(WifiEvent &event) 173 { 174 int ret = WIFI_SUCCESS; 175 176 if (isEventHandlingEnabled() == false) { 177 ALOGE("%s: RSSI monitor isn't running or already stopped. " 178 "Nothing to do. Exit", __FUNCTION__); 179 return ret; 180 } 181 182 WifiVendorCommand::handleEvent(event); 183 184 /* Parse the vendordata and get the attribute */ 185 switch(mSubcmd) 186 { 187 case QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI: 188 { 189 mac_addr addr; 190 s8 rssi; 191 wifi_request_id reqId; 192 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX 193 + 1]; 194 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX, 195 (struct nlattr *)mVendorData, 196 mDataLen, NULL); 197 198 memset(addr, 0, sizeof(mac_addr)); 199 200 if (!tb_vendor[ 201 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID]) 202 { 203 ALOGE("%s: ATTR_RSSI_MONITORING_REQUEST_ID not found. Exit.", 204 __FUNCTION__); 205 ret = WIFI_ERROR_INVALID_ARGS; 206 break; 207 } 208 reqId = nla_get_u32( 209 tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID] 210 ); 211 /* If event has a different request_id, ignore that and use the 212 * request_id value which we're maintaining. 213 */ 214 if (reqId != id()) { 215 ALOGV("%s: Event has Req. ID:%d <> Ours:%d, continue...", 216 __FUNCTION__, reqId, id()); 217 reqId = id(); 218 } 219 ret = get_mac_addr(tb_vendor, 220 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID, 221 addr); 222 if (ret != WIFI_SUCCESS) { 223 return ret; 224 } 225 ALOGV(MAC_ADDR_STR, MAC_ADDR_ARRAY(addr)); 226 227 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI]) 228 { 229 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI" 230 " not found", __FUNCTION__); 231 return WIFI_ERROR_INVALID_ARGS; 232 } 233 rssi = get_s8(tb_vendor[ 234 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI]); 235 ALOGV("Current RSSI : %d ", rssi); 236 237 if (mHandler.on_rssi_threshold_breached) 238 (*mHandler.on_rssi_threshold_breached)(reqId, addr, rssi); 239 else 240 ALOGE("RSSI Monitoring: No Callback registered: "); 241 } 242 break; 243 244 default: 245 /* Error case should not happen print log */ 246 ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd); 247 } 248 249 return ret; 250 } 251 252 wifi_error wifi_start_rssi_monitoring(wifi_request_id id, 253 wifi_interface_handle iface, 254 s8 max_rssi, 255 s8 min_rssi, 256 wifi_rssi_event_handler eh) 257 { 258 wifi_error ret; 259 struct nlattr *nlData; 260 WifiVendorCommand *vCommand = NULL; 261 wifi_handle wifiHandle = getWifiHandle(iface); 262 RSSIMonitorCommand *rssiCommand; 263 264 ret = initialize_vendor_cmd(iface, id, 265 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI, 266 &vCommand); 267 if (ret != WIFI_SUCCESS) { 268 ALOGE("%s: Initialization failed", __FUNCTION__); 269 return ret; 270 } 271 272 ALOGV("%s: Max RSSI:%d Min RSSI:%d", __FUNCTION__, 273 max_rssi, min_rssi); 274 /* Add the vendor specific attributes for the NL command. */ 275 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 276 if (!nlData) 277 goto cleanup; 278 279 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, 280 QCA_WLAN_RSSI_MONITORING_START); 281 if (ret != WIFI_SUCCESS) 282 goto cleanup; 283 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, 284 id); 285 if (ret != WIFI_SUCCESS) 286 goto cleanup; 287 ret = vCommand->put_s8(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI, 288 max_rssi); 289 if (ret != WIFI_SUCCESS) 290 goto cleanup; 291 ret = vCommand->put_s8(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI, 292 min_rssi); 293 if (ret != WIFI_SUCCESS) 294 goto cleanup; 295 296 vCommand->attr_end(nlData); 297 298 rssiCommand = RSSIMonitorCommand::instance(wifiHandle, id); 299 if (rssiCommand == NULL) { 300 ALOGE("%s: Error rssiCommand NULL", __FUNCTION__); 301 ret = WIFI_ERROR_OUT_OF_MEMORY; 302 goto cleanup; 303 } 304 305 rssiCommand->setCallbackHandler(eh); 306 307 ret = vCommand->requestResponse(); 308 if (ret != WIFI_SUCCESS) 309 goto cleanup; 310 311 rssiCommand->enableEventHandling(); 312 313 cleanup: 314 delete vCommand; 315 return ret; 316 } 317 318 wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, 319 wifi_interface_handle iface) 320 { 321 wifi_error ret; 322 struct nlattr *nlData; 323 WifiVendorCommand *vCommand = NULL; 324 wifi_handle wifiHandle = getWifiHandle(iface); 325 RSSIMonitorCommand *rssiCommand; 326 rssi_monitor_event_handlers* event_handlers; 327 hal_info *info = getHalInfo(wifiHandle); 328 329 event_handlers = info->rssi_handlers; 330 rssiCommand = event_handlers->mRSSIMonitorCommandInstance; 331 332 if (rssiCommand == NULL || 333 rssiCommand->isEventHandlingEnabled() == false) { 334 ALOGE("%s: RSSI monitor isn't running or already stopped. " 335 "Nothing to do. Exit", __FUNCTION__); 336 return WIFI_ERROR_NOT_AVAILABLE; 337 } 338 339 ret = initialize_vendor_cmd(iface, id, 340 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI, 341 &vCommand); 342 if (ret != WIFI_SUCCESS) { 343 ALOGE("%s: Initialization failed", __FUNCTION__); 344 return ret; 345 } 346 347 /* Add the vendor specific attributes for the NL command. */ 348 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 349 if (!nlData) 350 goto cleanup; 351 352 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, 353 QCA_WLAN_RSSI_MONITORING_STOP); 354 if (ret != WIFI_SUCCESS) 355 goto cleanup; 356 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, 357 id); 358 if (ret != WIFI_SUCCESS) 359 goto cleanup; 360 361 vCommand->attr_end(nlData); 362 363 ret = vCommand->requestResponse(); 364 if (ret != WIFI_SUCCESS) 365 goto cleanup; 366 367 rssiCommand->disableEventHandling(); 368 369 cleanup: 370 delete vCommand; 371 return ret; 372 } 373