1 /* Copyright (c) 2014, 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 #define LOG_TAG "WifiHAL" 31 #include <utils/Log.h> 32 #include <time.h> 33 34 #include "ifaceeventhandler.h" 35 36 /* Used to handle NL command events from driver/firmware. */ 37 IfaceEventHandlerCommand *mwifiEventHandler = NULL; 38 39 /* Set the interface event monitor handler*/ 40 wifi_error wifi_set_iface_event_handler(wifi_request_id id, 41 wifi_interface_handle iface, 42 wifi_event_handler eh) 43 { 44 int ret = 0; 45 wifi_handle wifiHandle = getWifiHandle(iface); 46 47 /* Check if a similar request to set iface event handler was made earlier. 48 * Right now we don't differentiate between the case where (i) the new 49 * Request Id is different from the current one vs (ii) both new and 50 * Request Ids are the same. 51 */ 52 if (mwifiEventHandler) 53 { 54 if (id == mwifiEventHandler->get_request_id()) { 55 ALOGE("%s: Iface Event Handler Set for request Id %d is still" 56 "running. Exit", __func__, id); 57 return WIFI_ERROR_TOO_MANY_REQUESTS; 58 } else { 59 ALOGE("%s: Iface Event Handler Set for a different Request " 60 "Id:%d is requested. Not supported. Exit", __func__, id); 61 return WIFI_ERROR_NOT_SUPPORTED; 62 } 63 } 64 65 mwifiEventHandler = new IfaceEventHandlerCommand( 66 wifiHandle, 67 id, 68 NL80211_CMD_REG_CHANGE); 69 if (mwifiEventHandler == NULL) { 70 ALOGE("%s: Error mwifiEventHandler NULL", __func__); 71 return WIFI_ERROR_UNKNOWN; 72 } 73 mwifiEventHandler->setCallbackHandler(eh); 74 75 return (wifi_error)ret; 76 } 77 78 /* Reset monitoring for the NL event*/ 79 wifi_error wifi_reset_iface_event_handler(wifi_request_id id, 80 wifi_interface_handle iface) 81 { 82 int ret = 0; 83 84 if (mwifiEventHandler) 85 { 86 if (id == mwifiEventHandler->get_request_id()) { 87 ALOGV("Delete Object mwifiEventHandler for id = %d", id); 88 delete mwifiEventHandler; 89 mwifiEventHandler = NULL; 90 } else { 91 ALOGE("%s: Iface Event Handler Set for a different Request " 92 "Id:%d is requested. Not supported. Exit", __func__, id); 93 return WIFI_ERROR_NOT_SUPPORTED; 94 } 95 } else { 96 ALOGV("Object mwifiEventHandler for id = %d already Deleted", id); 97 } 98 99 return (wifi_error)ret; 100 } 101 102 /* This function will be the main handler for the registered incoming 103 * (from driver) Commads. Calls the appropriate callback handler after 104 * parsing the vendor data. 105 */ 106 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event) 107 { 108 wifiEventHandler::handleEvent(event); 109 110 switch(mSubcmd) 111 { 112 case NL80211_CMD_REG_CHANGE: 113 { 114 char code[2]; 115 memset(&code[0], 0, 2); 116 if(tb[NL80211_ATTR_REG_ALPHA2]) 117 { 118 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2); 119 } else { 120 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__); 121 } 122 ALOGV("Country : %c%c", code[0], code[1]); 123 if(mHandler.on_country_code_changed) 124 { 125 mHandler.on_country_code_changed(code); 126 } 127 } 128 break; 129 default: 130 ALOGV("NL Event : %d Not supported", mSubcmd); 131 } 132 133 return NL_SKIP; 134 } 135 136 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd) 137 : wifiEventHandler(handle, id, subcmd) 138 { 139 ALOGV("wifiEventHandler %p constructed", this); 140 registerHandler(mSubcmd); 141 memset(&mHandler, 0, sizeof(wifi_event_handler)); 142 mEventData = NULL; 143 mDataLen = 0; 144 } 145 146 IfaceEventHandlerCommand::~IfaceEventHandlerCommand() 147 { 148 ALOGV("IfaceEventHandlerCommand %p destructor", this); 149 unregisterHandler(mSubcmd); 150 } 151 152 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler) 153 { 154 mHandler = nHandler; 155 } 156 157 int wifiEventHandler::get_request_id() 158 { 159 return mRequestId; 160 } 161 162 int IfaceEventHandlerCommand::get_request_id() 163 { 164 return wifiEventHandler::get_request_id(); 165 } 166 167 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd) 168 : WifiCommand(handle, id) 169 { 170 mRequestId = id; 171 mSubcmd = subcmd; 172 registerHandler(mSubcmd); 173 ALOGV("wifiEventHandler %p constructed", this); 174 } 175 176 wifiEventHandler::~wifiEventHandler() 177 { 178 ALOGV("wifiEventHandler %p destructor", this); 179 unregisterHandler(mSubcmd); 180 } 181 182 int wifiEventHandler::handleEvent(WifiEvent &event) 183 { 184 struct genlmsghdr *gnlh = event.header(); 185 mSubcmd = gnlh->cmd; 186 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 187 genlmsg_attrlen(gnlh, 0), NULL); 188 ALOGV("Got NL Event : %d from the Driver.", gnlh->cmd); 189 190 return NL_SKIP; 191 } 192 193 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id, 194 u32 subcmd) 195 : WifiVendorCommand(handle, id, vendor_id, subcmd) 196 { 197 /* Initialize the member data variables here */ 198 mSet = 0; 199 mSetSizeMax = 0; 200 mSetSizePtr = NULL; 201 mConcurrencySet = 0; 202 filterVersion = 0; 203 filterLength = 0; 204 firmware_bus_max_size = 0; 205 } 206 207 WifihalGeneric::~WifihalGeneric() 208 { 209 } 210 211 int WifihalGeneric::requestResponse() 212 { 213 return WifiCommand::requestResponse(mMsg); 214 } 215 216 int WifihalGeneric::handleResponse(WifiEvent &reply) 217 { 218 ALOGV("Got a Wi-Fi HAL module message from Driver"); 219 int i = 0; 220 WifiVendorCommand::handleResponse(reply); 221 222 // Parse the vendordata and get the attribute 223 switch(mSubcmd) 224 { 225 case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES: 226 { 227 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1]; 228 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX, 229 (struct nlattr *)mVendorData, 230 mDataLen, NULL); 231 232 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]) 233 { 234 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__); 235 return WIFI_ERROR_INVALID_ARGS; 236 } 237 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]); 238 ALOGV("Supported feature set : %x", mSet); 239 240 break; 241 } 242 case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX: 243 { 244 struct nlattr *tb_vendor[ 245 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1]; 246 nla_parse(tb_vendor, 247 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX, 248 (struct nlattr *)mVendorData,mDataLen, NULL); 249 250 if (tb_vendor[ 251 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) { 252 u32 val; 253 val = nla_get_u32( 254 tb_vendor[ 255 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]); 256 257 ALOGV("%s: Num of concurrency combinations: %d", 258 __func__, val); 259 val = val > (unsigned int)mSetSizeMax ? 260 (unsigned int)mSetSizeMax : val; 261 *mSetSizePtr = val; 262 263 /* Extract the list of channels. */ 264 if (*mSetSizePtr > 0 && 265 tb_vendor[ 266 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) { 267 nla_memcpy(mConcurrencySet, 268 tb_vendor[ 269 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET], 270 sizeof(feature_set) * (*mSetSizePtr)); 271 } 272 273 ALOGV("%s: Get concurrency matrix response received.", 274 __func__); 275 ALOGV("%s: Num of concurrency combinations : %d", 276 __func__, *mSetSizePtr); 277 ALOGV("%s: List of valid concurrency combinations is: ", 278 __func__); 279 for(i = 0; i < *mSetSizePtr; i++) 280 { 281 ALOGV("%x", *(mConcurrencySet + i)); 282 } 283 } 284 } 285 break; 286 case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER: 287 { 288 struct nlattr *tb_vendor[ 289 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1]; 290 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX, 291 (struct nlattr *)mVendorData, 292 mDataLen, NULL); 293 294 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]) 295 { 296 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION" 297 " not found", __FUNCTION__); 298 return WIFI_ERROR_INVALID_ARGS; 299 } 300 filterVersion = nla_get_u32( 301 tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]); 302 ALOGV("Current version : %u", filterVersion); 303 304 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]) 305 { 306 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH" 307 " not found", __FUNCTION__); 308 return WIFI_ERROR_INVALID_ARGS; 309 } 310 filterLength = nla_get_u32( 311 tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]); 312 ALOGV("Max filter length Supported : %u", filterLength); 313 314 } 315 break; 316 case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE: 317 { 318 struct nlattr *tb_vendor[ 319 QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1]; 320 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX, 321 (struct nlattr *)mVendorData, mDataLen, NULL); 322 323 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]) 324 { 325 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE" 326 " not found", __FUNCTION__); 327 return WIFI_ERROR_INVALID_ARGS; 328 } 329 firmware_bus_max_size = nla_get_u32( 330 tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]); 331 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size); 332 } 333 break; 334 default : 335 ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd); 336 } 337 return NL_SKIP; 338 } 339 340 void WifihalGeneric::getResponseparams(feature_set *pset) 341 { 342 *pset = mSet; 343 } 344 345 void WifihalGeneric::setMaxSetSize(int set_size_max) { 346 mSetSizeMax = set_size_max; 347 } 348 349 void WifihalGeneric::setConcurrencySet(feature_set set[]) { 350 mConcurrencySet = set; 351 } 352 353 void WifihalGeneric::setSizePtr(int *set_size) { 354 mSetSizePtr = set_size; 355 } 356 357 int WifihalGeneric::getFilterVersion() { 358 return filterVersion; 359 } 360 361 int WifihalGeneric::getFilterLength() { 362 return filterLength; 363 } 364 365 int WifihalGeneric::getBusSize() { 366 return firmware_bus_max_size; 367 } 368