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