1 /* Copyright (c) 2015, 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 return WIFI_SUCCESS; 71 } 72 ALOGE ("%s: info or info->rssi_handlers NULL", __FUNCTION__); 73 return WIFI_ERROR_UNKNOWN; 74 } 75 76 void RSSIMonitorCommand::enableEventHandling() 77 { 78 pthread_mutex_lock(&rm_lock); 79 mEventHandlingEnabled = true; 80 pthread_mutex_unlock(&rm_lock); 81 } 82 83 void RSSIMonitorCommand::disableEventHandling() 84 { 85 pthread_mutex_lock(&rm_lock); 86 mEventHandlingEnabled = false; 87 pthread_mutex_unlock(&rm_lock); 88 } 89 90 bool RSSIMonitorCommand::isEventHandlingEnabled() 91 { 92 bool eventHandlingEnabled; 93 pthread_mutex_lock(&rm_lock); 94 eventHandlingEnabled = mEventHandlingEnabled; 95 pthread_mutex_unlock(&rm_lock); 96 97 return eventHandlingEnabled; 98 } 99 100 void RSSIMonitorCommand::setCallbackHandler(wifi_rssi_event_handler handler) 101 { 102 mHandler = handler; 103 } 104 105 RSSIMonitorCommand::RSSIMonitorCommand(wifi_handle handle, int id, 106 u32 vendor_id, u32 subcmd) 107 : WifiVendorCommand(handle, id, vendor_id, subcmd) 108 { 109 memset(&mHandler, 0, sizeof(mHandler)); 110 if (registerVendorHandler(vendor_id, subcmd)) { 111 /* Error case should not happen print log */ 112 ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u", 113 __FUNCTION__, vendor_id, subcmd); 114 } 115 pthread_mutex_init(&rm_lock, NULL); 116 disableEventHandling(); 117 } 118 119 RSSIMonitorCommand::~RSSIMonitorCommand() 120 { 121 unregisterVendorHandler(mVendor_id, mSubcmd); 122 pthread_mutex_destroy(&rm_lock); 123 } 124 125 void RSSIMonitorCommand::setReqId(wifi_request_id reqid) 126 { 127 mId = reqid; 128 } 129 130 RSSIMonitorCommand* RSSIMonitorCommand::instance(wifi_handle handle, 131 wifi_request_id id) 132 { 133 if (handle == NULL) { 134 ALOGE("Interface Handle is invalid"); 135 return NULL; 136 } 137 hal_info *info = getHalInfo(handle); 138 if (!info || !info->rssi_handlers) { 139 ALOGE("rssi_handlers is invalid"); 140 return NULL; 141 } 142 143 RSSIMonitorCommand* mRSSIMonitorCommandInstance = 144 info->rssi_handlers->mRSSIMonitorCommandInstance; 145 146 if (mRSSIMonitorCommandInstance == NULL) { 147 mRSSIMonitorCommandInstance = new RSSIMonitorCommand(handle, id, 148 OUI_QCA, 149 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI); 150 info->rssi_handlers->mRSSIMonitorCommandInstance = mRSSIMonitorCommandInstance; 151 return mRSSIMonitorCommandInstance; 152 } 153 else 154 { 155 if (handle != getWifiHandle(mRSSIMonitorCommandInstance->mInfo)) 156 { 157 /* upper layer must have cleaned up the handle and reinitialized, 158 so we need to update the same */ 159 ALOGV("Handle different, update the handle"); 160 mRSSIMonitorCommandInstance->mInfo = (hal_info *)handle; 161 } 162 mRSSIMonitorCommandInstance->setReqId(id); 163 } 164 return mRSSIMonitorCommandInstance; 165 } 166 167 /* This function will be the main handler for incoming event. 168 * Call the appropriate callback handler after parsing the vendor data. 169 */ 170 int RSSIMonitorCommand::handleEvent(WifiEvent &event) 171 { 172 int ret = WIFI_SUCCESS; 173 174 if (isEventHandlingEnabled() == false) { 175 ALOGE("%s: RSSI monitor isn't running or already stopped. " 176 "Nothing to do. Exit", __FUNCTION__); 177 return ret; 178 } 179 180 WifiVendorCommand::handleEvent(event); 181 182 /* Parse the vendordata and get the attribute */ 183 switch(mSubcmd) 184 { 185 case QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI: 186 { 187 mac_addr addr; 188 s8 rssi; 189 wifi_request_id reqId; 190 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX 191 + 1]; 192 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX, 193 (struct nlattr *)mVendorData, 194 mDataLen, NULL); 195 196 memset(addr, 0, sizeof(mac_addr)); 197 198 if (!tb_vendor[ 199 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID]) 200 { 201 ALOGE("%s: ATTR_RSSI_MONITORING_REQUEST_ID not found. Exit.", 202 __FUNCTION__); 203 ret = WIFI_ERROR_INVALID_ARGS; 204 break; 205 } 206 reqId = nla_get_u32( 207 tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID] 208 ); 209 /* If event has a different request_id, ignore that and use the 210 * request_id value which we're maintaining. 211 */ 212 if (reqId != id()) { 213 ALOGV("%s: Event has Req. ID:%d <> Ours:%d, continue...", 214 __FUNCTION__, reqId, id()); 215 reqId = id(); 216 } 217 ret = get_mac_addr(tb_vendor, 218 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID, 219 addr); 220 if (ret != WIFI_SUCCESS) { 221 return ret; 222 } 223 ALOGV(MAC_ADDR_STR, MAC_ADDR_ARRAY(addr)); 224 225 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI]) 226 { 227 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI" 228 " not found", __FUNCTION__); 229 return WIFI_ERROR_INVALID_ARGS; 230 } 231 rssi = get_s8(tb_vendor[ 232 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI]); 233 ALOGV("Current RSSI : %d ", rssi); 234 235 if (mHandler.on_rssi_threshold_breached) 236 (*mHandler.on_rssi_threshold_breached)(reqId, addr, rssi); 237 else 238 ALOGE("RSSI Monitoring: No Callback registered: "); 239 } 240 break; 241 242 default: 243 /* Error case should not happen print log */ 244 ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd); 245 } 246 247 return ret; 248 } 249 250 wifi_error wifi_start_rssi_monitoring(wifi_request_id id, 251 wifi_interface_handle iface, 252 s8 max_rssi, 253 s8 min_rssi, 254 wifi_rssi_event_handler eh) 255 { 256 int ret = WIFI_SUCCESS; 257 struct nlattr *nlData; 258 WifiVendorCommand *vCommand = NULL; 259 wifi_handle wifiHandle = getWifiHandle(iface); 260 RSSIMonitorCommand *rssiCommand; 261 262 ret = initialize_vendor_cmd(iface, id, 263 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI, 264 &vCommand); 265 if (ret != WIFI_SUCCESS) { 266 ALOGE("%s: Initialization failed", __FUNCTION__); 267 return (wifi_error)ret; 268 } 269 270 ALOGV("%s: Max RSSI:%d Min RSSI:%d", __FUNCTION__, 271 max_rssi, min_rssi); 272 /* Add the vendor specific attributes for the NL command. */ 273 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 274 if (!nlData) 275 goto cleanup; 276 277 if (vCommand->put_u32( 278 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, 279 QCA_WLAN_RSSI_MONITORING_START) || 280 vCommand->put_u32( 281 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, 282 id) || 283 vCommand->put_s8( 284 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI, 285 max_rssi) || 286 vCommand->put_s8( 287 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI, 288 min_rssi)) 289 { 290 goto cleanup; 291 } 292 293 vCommand->attr_end(nlData); 294 295 rssiCommand = RSSIMonitorCommand::instance(wifiHandle, id); 296 if (rssiCommand == NULL) { 297 ALOGE("%s: Error rssiCommand NULL", __FUNCTION__); 298 return WIFI_ERROR_OUT_OF_MEMORY; 299 } 300 301 rssiCommand->setCallbackHandler(eh); 302 303 ret = vCommand->requestResponse(); 304 if (ret < 0) 305 goto cleanup; 306 307 rssiCommand->enableEventHandling(); 308 309 cleanup: 310 delete vCommand; 311 return (wifi_error)ret; 312 } 313 314 wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, 315 wifi_interface_handle iface) 316 { 317 int ret = WIFI_SUCCESS; 318 struct nlattr *nlData; 319 WifiVendorCommand *vCommand = NULL; 320 wifi_handle wifiHandle = getWifiHandle(iface); 321 RSSIMonitorCommand *rssiCommand; 322 rssi_monitor_event_handlers* event_handlers; 323 hal_info *info = getHalInfo(wifiHandle); 324 325 event_handlers = (rssi_monitor_event_handlers*)info->rssi_handlers; 326 rssiCommand = event_handlers->mRSSIMonitorCommandInstance; 327 328 if (rssiCommand == NULL || 329 rssiCommand->isEventHandlingEnabled() == false) { 330 ALOGE("%s: RSSI monitor isn't running or already stopped. " 331 "Nothing to do. Exit", __FUNCTION__); 332 return WIFI_ERROR_NOT_AVAILABLE; 333 } 334 335 ret = initialize_vendor_cmd(iface, id, 336 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI, 337 &vCommand); 338 if (ret != WIFI_SUCCESS) { 339 ALOGE("%s: Initialization failed", __FUNCTION__); 340 return (wifi_error)ret; 341 } 342 343 /* Add the vendor specific attributes for the NL command. */ 344 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 345 if (!nlData) 346 goto cleanup; 347 348 if (vCommand->put_u32( 349 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, 350 QCA_WLAN_RSSI_MONITORING_STOP) || 351 vCommand->put_u32( 352 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, 353 id)) 354 { 355 goto cleanup; 356 } 357 358 vCommand->attr_end(nlData); 359 360 ret = vCommand->requestResponse(); 361 if (ret < 0) 362 goto cleanup; 363 364 rssiCommand->disableEventHandling(); 365 366 367 cleanup: 368 delete vCommand; 369 return (wifi_error)ret; 370 } 371