Srinivas Dasari | dc48894 | 2018-01-24 19:35:19 +0530 | [diff] [blame] | 1 | /* Copyright (c) 2015, 2018 The Linux Foundation. All rights reserved. |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 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 |
| 9 | * copyright notice, this list of conditions and the following |
| 10 | * disclaimer in the documentation and/or other materials provided |
| 11 | * with the 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> |
Ajay Dudani | 65b8c55 | 2015-04-11 22:52:06 -0700 | [diff] [blame] | 33 | #include <errno.h> |
Amarnath Hullur Subramanyam | b131c77 | 2015-08-06 14:22:50 -0700 | [diff] [blame] | 34 | #include <stdlib.h> |
Srinivas Girigowda | 2bba36f | 2018-01-29 15:43:59 -0800 | [diff] [blame] | 35 | #include <unistd.h> |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 36 | #include <string> |
| 37 | #include <net/if.h> |
| 38 | #include <vector> |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 39 | #include "wificonfigcommand.h" |
| 40 | |
| 41 | /* Implementation of the API functions exposed in wifi_config.h */ |
| 42 | wifi_error wifi_extended_dtim_config_set(wifi_request_id id, |
| 43 | wifi_interface_handle iface, |
| 44 | int extended_dtim) |
| 45 | { |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 46 | wifi_error ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 47 | WiFiConfigCommand *wifiConfigCommand; |
| 48 | struct nlattr *nlData; |
| 49 | interface_info *ifaceInfo = getIfaceInfo(iface); |
| 50 | wifi_handle wifiHandle = getWifiHandle(iface); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 51 | |
Subhani Shaik | eb97b6e | 2016-03-29 11:33:25 +0530 | [diff] [blame] | 52 | ALOGV("%s: extended_dtim:%d", __FUNCTION__, extended_dtim); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 53 | |
| 54 | wifiConfigCommand = new WiFiConfigCommand( |
| 55 | wifiHandle, |
| 56 | id, |
| 57 | OUI_QCA, |
| 58 | QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION); |
| 59 | |
| 60 | if (wifiConfigCommand == NULL) { |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 61 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 62 | return WIFI_ERROR_UNKNOWN; |
| 63 | } |
| 64 | |
| 65 | /* Create the NL message. */ |
| 66 | ret = wifiConfigCommand->create(); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 67 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 68 | ALOGE("wifi_extended_dtim_config_set: failed to create NL msg. " |
| 69 | "Error:%d", ret); |
| 70 | goto cleanup; |
| 71 | } |
| 72 | |
| 73 | /* Set the interface Id of the message. */ |
| 74 | ret = wifiConfigCommand->set_iface_id(ifaceInfo->name); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 75 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 76 | ALOGE("wifi_extended_dtim_config_set: failed to set iface id. " |
| 77 | "Error:%d", ret); |
| 78 | goto cleanup; |
| 79 | } |
| 80 | |
| 81 | /* Add the vendor specific attributes for the NL command. */ |
| 82 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 83 | if (!nlData) { |
| 84 | ALOGE("wifi_extended_dtim_config_set: failed attr_start for " |
| 85 | "VENDOR_DATA. Error:%d", ret); |
| 86 | goto cleanup; |
| 87 | } |
| 88 | |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 89 | ret = wifiConfigCommand->put_u32( |
Srinivas Dasari | c0854c7 | 2018-06-14 16:55:55 +0530 | [diff] [blame] | 90 | QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM, extended_dtim); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 91 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 92 | ALOGE("wifi_extended_dtim_config_set(): failed to put vendor data. " |
| 93 | "Error:%d", ret); |
| 94 | goto cleanup; |
| 95 | } |
| 96 | wifiConfigCommand->attr_end(nlData); |
| 97 | |
| 98 | /* Send the NL msg. */ |
| 99 | wifiConfigCommand->waitForRsp(false); |
| 100 | ret = wifiConfigCommand->requestEvent(); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 101 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 102 | ALOGE("wifi_extended_dtim_config_set(): requestEvent Error:%d", ret); |
| 103 | goto cleanup; |
| 104 | } |
| 105 | |
| 106 | cleanup: |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 107 | delete wifiConfigCommand; |
Srinivas Dasari | dc48894 | 2018-01-24 19:35:19 +0530 | [diff] [blame] | 108 | return ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 109 | } |
| 110 | |
Peng Xu | 2eef57d | 2018-03-14 14:11:37 -0700 | [diff] [blame] | 111 | int check_feature(enum qca_wlan_vendor_features feature, features_info *info) |
| 112 | { |
| 113 | size_t idx = feature / 8; |
| 114 | |
| 115 | return (idx < info->flags_len) && |
| 116 | (info->flags[idx] & BIT(feature % 8)); |
| 117 | } |
| 118 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 119 | /* Set the country code to driver. */ |
| 120 | wifi_error wifi_set_country_code(wifi_interface_handle iface, |
| 121 | const char* country_code) |
| 122 | { |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 123 | int requestId; |
| 124 | wifi_error ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 125 | WiFiConfigCommand *wifiConfigCommand; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 126 | wifi_handle wifiHandle = getWifiHandle(iface); |
Peng Xu | 2eef57d | 2018-03-14 14:11:37 -0700 | [diff] [blame] | 127 | hal_info *info = getHalInfo(wifiHandle); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 128 | |
Subhani Shaik | eb97b6e | 2016-03-29 11:33:25 +0530 | [diff] [blame] | 129 | ALOGV("%s: %s", __FUNCTION__, country_code); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 130 | |
| 131 | /* No request id from caller, so generate one and pass it on to the driver. |
| 132 | * Generate it randomly. |
| 133 | */ |
Amarnath Hullur Subramanyam | b131c77 | 2015-08-06 14:22:50 -0700 | [diff] [blame] | 134 | requestId = get_requestid(); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 135 | |
| 136 | wifiConfigCommand = new WiFiConfigCommand( |
| 137 | wifiHandle, |
| 138 | requestId, |
| 139 | OUI_QCA, |
| 140 | QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION); |
| 141 | if (wifiConfigCommand == NULL) { |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 142 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 143 | return WIFI_ERROR_UNKNOWN; |
| 144 | } |
| 145 | |
| 146 | /* Create the NL message with NL80211_CMD_REQ_SET_REG NL cmd. */ |
| 147 | ret = wifiConfigCommand->create_generic(NL80211_CMD_REQ_SET_REG); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 148 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 149 | ALOGE("wifi_set_country_code: failed to create NL msg. Error:%d", ret); |
| 150 | goto cleanup; |
| 151 | } |
| 152 | |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 153 | ret = wifiConfigCommand->put_string(NL80211_ATTR_REG_ALPHA2, country_code); |
| 154 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 155 | ALOGE("wifi_set_country_code: put country code failed. Error:%d", ret); |
| 156 | goto cleanup; |
| 157 | } |
| 158 | |
Peng Xu | 2eef57d | 2018-03-14 14:11:37 -0700 | [diff] [blame] | 159 | if (check_feature(QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY, |
| 160 | &info->driver_supported_features)) { |
| 161 | ret = wifiConfigCommand->put_u32(NL80211_ATTR_USER_REG_HINT_TYPE, |
| 162 | NL80211_USER_REG_HINT_CELL_BASE); |
| 163 | if (ret != WIFI_SUCCESS) { |
| 164 | ALOGE("wifi_set_country_code: put reg hint type failed. Error:%d", |
| 165 | ret); |
| 166 | goto cleanup; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 171 | /* Send the NL msg. */ |
| 172 | wifiConfigCommand->waitForRsp(false); |
| 173 | ret = wifiConfigCommand->requestEvent(); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 174 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 175 | ALOGE("wifi_set_country_code(): requestEvent Error:%d", ret); |
| 176 | goto cleanup; |
| 177 | } |
Srinivas Dasari | 02d14ee | 2015-08-19 16:52:08 +0530 | [diff] [blame] | 178 | usleep(WAIT_TIME_FOR_SET_REG_DOMAIN); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 179 | |
| 180 | cleanup: |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 181 | delete wifiConfigCommand; |
Srinivas Dasari | dc48894 | 2018-01-24 19:35:19 +0530 | [diff] [blame] | 182 | return ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 183 | } |
| 184 | |
Jian Tang | 95979d7 | 2017-11-16 16:52:30 +0800 | [diff] [blame] | 185 | /* |
| 186 | * Set the powersave to driver. |
| 187 | */ |
| 188 | wifi_error wifi_set_qpower(wifi_interface_handle iface, |
| 189 | u8 powersave) |
| 190 | { |
| 191 | int requestId, ret = 0; |
| 192 | WiFiConfigCommand *wifiConfigCommand; |
| 193 | struct nlattr *nlData; |
| 194 | interface_info *ifaceInfo = getIfaceInfo(iface); |
| 195 | wifi_handle wifiHandle = getWifiHandle(iface); |
| 196 | //hal_info *info = getHalInfo(wifiHandle); |
| 197 | |
| 198 | ALOGD("%s: %d", __FUNCTION__, powersave); |
| 199 | |
| 200 | requestId = get_requestid(); |
| 201 | |
| 202 | wifiConfigCommand = new WiFiConfigCommand( |
| 203 | wifiHandle, |
| 204 | requestId, |
| 205 | OUI_QCA, |
| 206 | QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION); |
| 207 | |
| 208 | if (wifiConfigCommand == NULL) { |
| 209 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
| 210 | return WIFI_ERROR_UNKNOWN; |
| 211 | } |
| 212 | |
| 213 | /* Create the NL message. */ |
| 214 | ret = wifiConfigCommand->create(); |
| 215 | if (ret < 0) { |
| 216 | ALOGE("wifi_set_qpower: failed to create NL msg. " |
| 217 | "Error:%d", ret); |
| 218 | goto cleanup; |
| 219 | } |
| 220 | |
| 221 | /* Set the interface Id of the message. */ |
| 222 | ret = wifiConfigCommand->set_iface_id(ifaceInfo->name); |
| 223 | if (ret < 0) { |
| 224 | ALOGE("wifi_set_qpower: failed to set iface id. " |
| 225 | "Error:%d", ret); |
| 226 | goto cleanup; |
| 227 | } |
| 228 | |
| 229 | /* Add the vendor specific attributes for the NL command. */ |
| 230 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 231 | if (!nlData) { |
| 232 | ALOGE("wifi_set_qpower: failed attr_start for " |
| 233 | "VENDOR_DATA. Error:%d", ret); |
| 234 | goto cleanup; |
| 235 | } |
| 236 | |
| 237 | if (wifiConfigCommand->put_u8( |
Srinivas Dasari | c0854c7 | 2018-06-14 16:55:55 +0530 | [diff] [blame] | 238 | QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER, powersave)) { |
Jian Tang | 95979d7 | 2017-11-16 16:52:30 +0800 | [diff] [blame] | 239 | ALOGE("wifi_set_qpower(): failed to put vendor data. " |
| 240 | "Error:%d", ret); |
| 241 | goto cleanup; |
| 242 | } |
| 243 | wifiConfigCommand->attr_end(nlData); |
| 244 | |
| 245 | /* Send the NL msg. */ |
| 246 | wifiConfigCommand->waitForRsp(false); |
| 247 | ret = wifiConfigCommand->requestEvent(); |
| 248 | if (ret != 0) { |
| 249 | ALOGE("wifi_set_qpower(): requestEvent Error:%d", ret); |
| 250 | goto cleanup; |
| 251 | } |
| 252 | |
| 253 | cleanup: |
| 254 | delete wifiConfigCommand; |
| 255 | return (wifi_error)ret; |
| 256 | |
| 257 | } |
| 258 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 259 | wifi_error wifi_set_beacon_wifi_iface_stats_averaging_factor( |
| 260 | wifi_request_id id, |
| 261 | wifi_interface_handle iface, |
| 262 | u16 factor) |
| 263 | { |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 264 | wifi_error ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 265 | WiFiConfigCommand *wifiConfigCommand; |
| 266 | struct nlattr *nlData; |
| 267 | interface_info *ifaceInfo = getIfaceInfo(iface); |
| 268 | wifi_handle wifiHandle = getWifiHandle(iface); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 269 | |
Subhani Shaik | eb97b6e | 2016-03-29 11:33:25 +0530 | [diff] [blame] | 270 | ALOGV("%s factor:%u", __FUNCTION__, factor); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 271 | wifiConfigCommand = new WiFiConfigCommand( |
| 272 | wifiHandle, |
| 273 | id, |
| 274 | OUI_QCA, |
| 275 | QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION); |
| 276 | if (wifiConfigCommand == NULL) { |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 277 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 278 | return WIFI_ERROR_UNKNOWN; |
| 279 | } |
| 280 | |
| 281 | /* Create the NL message. */ |
| 282 | ret = wifiConfigCommand->create(); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 283 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 284 | ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed to " |
| 285 | "create NL msg. Error:%d", ret); |
| 286 | goto cleanup; |
| 287 | } |
| 288 | |
| 289 | /* Set the interface Id of the message. */ |
| 290 | ret = wifiConfigCommand->set_iface_id(ifaceInfo->name); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 291 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 292 | ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed to " |
| 293 | "set iface id. Error:%d", ret); |
| 294 | goto cleanup; |
| 295 | } |
| 296 | |
| 297 | /* Add the vendor specific attributes for the NL command. */ |
| 298 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 299 | if (!nlData) { |
| 300 | ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed " |
| 301 | "attr_start for VENDOR_DATA. Error:%d", ret); |
| 302 | goto cleanup; |
| 303 | } |
| 304 | |
| 305 | if (wifiConfigCommand->put_u32( |
Srinivas Dasari | c0854c7 | 2018-06-14 16:55:55 +0530 | [diff] [blame] | 306 | QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR, factor)) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 307 | ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor(): failed to " |
| 308 | "put vendor data. Error:%d", ret); |
| 309 | goto cleanup; |
| 310 | } |
| 311 | wifiConfigCommand->attr_end(nlData); |
| 312 | |
| 313 | /* Send the NL msg. */ |
| 314 | wifiConfigCommand->waitForRsp(false); |
| 315 | ret = wifiConfigCommand->requestEvent(); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 316 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 317 | ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor(): " |
| 318 | "requestEvent Error:%d", ret); |
| 319 | goto cleanup; |
| 320 | } |
| 321 | |
| 322 | cleanup: |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 323 | delete wifiConfigCommand; |
Srinivas Dasari | dc48894 | 2018-01-24 19:35:19 +0530 | [diff] [blame] | 324 | return ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | wifi_error wifi_set_guard_time(wifi_request_id id, |
| 328 | wifi_interface_handle iface, |
| 329 | u32 guard_time) |
| 330 | { |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 331 | wifi_error ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 332 | WiFiConfigCommand *wifiConfigCommand; |
| 333 | struct nlattr *nlData; |
| 334 | interface_info *ifaceInfo = getIfaceInfo(iface); |
| 335 | wifi_handle wifiHandle = getWifiHandle(iface); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 336 | |
Subhani Shaik | eb97b6e | 2016-03-29 11:33:25 +0530 | [diff] [blame] | 337 | ALOGV("%s : guard_time:%u", __FUNCTION__, guard_time); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 338 | |
| 339 | wifiConfigCommand = new WiFiConfigCommand( |
| 340 | wifiHandle, |
| 341 | id, |
| 342 | OUI_QCA, |
| 343 | QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION); |
| 344 | if (wifiConfigCommand == NULL) { |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 345 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 346 | return WIFI_ERROR_UNKNOWN; |
| 347 | } |
| 348 | |
| 349 | /* Create the NL message. */ |
| 350 | ret = wifiConfigCommand->create(); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 351 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 352 | ALOGE("wifi_set_guard_time: failed to create NL msg. Error:%d", ret); |
| 353 | goto cleanup; |
| 354 | } |
| 355 | |
| 356 | /* Set the interface Id of the message. */ |
| 357 | ret = wifiConfigCommand->set_iface_id(ifaceInfo->name); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 358 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 359 | ALOGE("wifi_set_guard_time: failed to set iface id. Error:%d", ret); |
| 360 | goto cleanup; |
| 361 | } |
| 362 | |
| 363 | /* Add the vendor specific attributes for the NL command. */ |
| 364 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 365 | if (!nlData) { |
| 366 | ALOGE("wifi_set_guard_time: failed attr_start for VENDOR_DATA. " |
| 367 | "Error:%d", ret); |
| 368 | goto cleanup; |
| 369 | } |
| 370 | |
| 371 | if (wifiConfigCommand->put_u32( |
Srinivas Dasari | c0854c7 | 2018-06-14 16:55:55 +0530 | [diff] [blame] | 372 | QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME, guard_time)) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 373 | ALOGE("wifi_set_guard_time: failed to add vendor data."); |
| 374 | goto cleanup; |
| 375 | } |
| 376 | wifiConfigCommand->attr_end(nlData); |
| 377 | |
| 378 | /* Send the NL msg. */ |
| 379 | wifiConfigCommand->waitForRsp(false); |
| 380 | ret = wifiConfigCommand->requestEvent(); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 381 | if (ret != WIFI_SUCCESS) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 382 | ALOGE("wifi_set_guard_time(): requestEvent Error:%d", ret); |
| 383 | goto cleanup; |
| 384 | } |
| 385 | |
| 386 | cleanup: |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 387 | delete wifiConfigCommand; |
Srinivas Dasari | dc48894 | 2018-01-24 19:35:19 +0530 | [diff] [blame] | 388 | return ret; |
Srinivas Girigowda | 2bba36f | 2018-01-29 15:43:59 -0800 | [diff] [blame] | 389 | } |
| 390 | |
| 391 | wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle, |
| 392 | wifi_power_scenario scenario) |
| 393 | { |
| 394 | wifi_error ret; |
| 395 | WiFiConfigCommand *wifiConfigCommand; |
| 396 | struct nlattr *nlData; |
| 397 | interface_info *ifaceInfo = getIfaceInfo(handle); |
| 398 | wifi_handle wifiHandle = getWifiHandle(handle); |
| 399 | u32 bdf_file = 0; |
| 400 | |
| 401 | ALOGV("%s : power scenario:%d", __FUNCTION__, scenario); |
| 402 | |
| 403 | wifiConfigCommand = new WiFiConfigCommand( |
| 404 | wifiHandle, |
| 405 | 1, |
| 406 | OUI_QCA, |
| 407 | QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS); |
| 408 | if (wifiConfigCommand == NULL) { |
| 409 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
| 410 | return WIFI_ERROR_UNKNOWN; |
| 411 | } |
| 412 | |
| 413 | /* Create the NL message. */ |
| 414 | ret = wifiConfigCommand->create(); |
| 415 | if (ret != WIFI_SUCCESS) { |
| 416 | ALOGE("wifi_select_tx_power_scenario: failed to create NL msg. Error:%d", ret); |
| 417 | goto cleanup; |
| 418 | } |
| 419 | |
| 420 | /* Set the interface Id of the message. */ |
| 421 | ret = wifiConfigCommand->set_iface_id(ifaceInfo->name); |
| 422 | if (ret != WIFI_SUCCESS) { |
| 423 | ALOGE("wifi_select_tx_power_scenario: failed to set iface id. Error:%d", ret); |
| 424 | goto cleanup; |
| 425 | } |
| 426 | |
| 427 | /* Add the vendor specific attributes for the NL command. */ |
| 428 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 429 | if (!nlData) { |
| 430 | ALOGE("wifi_select_tx_power_scenario: failed attr_start for VENDOR_DATA. " |
| 431 | "Error:%d", ret); |
| 432 | goto cleanup; |
| 433 | } |
| 434 | |
Srinivas Girigowda | 8e444fd | 2018-04-12 07:53:40 -0700 | [diff] [blame] | 435 | switch (scenario) { |
| 436 | case WIFI_POWER_SCENARIO_VOICE_CALL: |
| 437 | case WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF: |
| 438 | bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0; |
| 439 | break; |
| 440 | |
| 441 | case WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON: |
| 442 | bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1; |
| 443 | break; |
| 444 | |
| 445 | case WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF: |
| 446 | bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2; |
| 447 | break; |
| 448 | |
| 449 | case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON: |
| 450 | bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3; |
| 451 | break; |
| 452 | |
| 453 | default: |
| 454 | ALOGE("wifi_select_tx_power_scenario: invalid scenario %d", scenario); |
| 455 | ret = WIFI_ERROR_INVALID_ARGS; |
| 456 | goto cleanup; |
Srinivas Girigowda | 2bba36f | 2018-01-29 15:43:59 -0800 | [diff] [blame] | 457 | } |
Srinivas Girigowda | 8e444fd | 2018-04-12 07:53:40 -0700 | [diff] [blame] | 458 | |
Srinivas Girigowda | 2bba36f | 2018-01-29 15:43:59 -0800 | [diff] [blame] | 459 | if (wifiConfigCommand->put_u32( |
| 460 | QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE, |
| 461 | bdf_file)) { |
| 462 | ALOGE("failed to put SAR_ENABLE"); |
| 463 | goto cleanup; |
| 464 | } |
| 465 | wifiConfigCommand->attr_end(nlData); |
| 466 | |
| 467 | ret = wifiConfigCommand->requestEvent(); |
| 468 | if (ret != WIFI_SUCCESS) { |
| 469 | ALOGE("wifi_select_tx_power_scenario(): requestEvent Error:%d", ret); |
| 470 | goto cleanup; |
| 471 | } |
| 472 | |
| 473 | cleanup: |
| 474 | delete wifiConfigCommand; |
Srinivas Dasari | dc48894 | 2018-01-24 19:35:19 +0530 | [diff] [blame] | 475 | return ret; |
Srinivas Girigowda | 2bba36f | 2018-01-29 15:43:59 -0800 | [diff] [blame] | 476 | } |
| 477 | |
| 478 | wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle) |
| 479 | { |
| 480 | wifi_error ret; |
| 481 | WiFiConfigCommand *wifiConfigCommand; |
| 482 | struct nlattr *nlData; |
| 483 | interface_info *ifaceInfo = getIfaceInfo(handle); |
| 484 | wifi_handle wifiHandle = getWifiHandle(handle); |
| 485 | |
| 486 | wifiConfigCommand = new WiFiConfigCommand( |
| 487 | wifiHandle, |
| 488 | 1, |
| 489 | OUI_QCA, |
| 490 | QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS); |
| 491 | if (wifiConfigCommand == NULL) { |
| 492 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
| 493 | return WIFI_ERROR_UNKNOWN; |
| 494 | } |
| 495 | |
| 496 | /* Create the NL message. */ |
| 497 | ret = wifiConfigCommand->create(); |
| 498 | if (ret != WIFI_SUCCESS) { |
| 499 | ALOGE("wifi_reset_tx_power_scenario: failed to create NL msg. Error:%d", ret); |
| 500 | goto cleanup; |
| 501 | } |
| 502 | |
| 503 | /* Set the interface Id of the message. */ |
| 504 | ret = wifiConfigCommand->set_iface_id(ifaceInfo->name); |
| 505 | if (ret != WIFI_SUCCESS) { |
| 506 | ALOGE("wifi_reset_tx_power_scenario: failed to set iface id. Error:%d", ret); |
| 507 | goto cleanup; |
| 508 | } |
| 509 | |
| 510 | /* Add the vendor specific attributes for the NL command. */ |
| 511 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 512 | if (!nlData) { |
| 513 | ALOGE("wifi_reset_tx_power_scenario: failed attr_start for VENDOR_DATA. " |
| 514 | "Error:%d", ret); |
| 515 | goto cleanup; |
| 516 | } |
| 517 | |
| 518 | if (wifiConfigCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE, |
| 519 | QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE)) { |
| 520 | ALOGE("failed to put SAR_ENABLE or NUM_SPECS"); |
| 521 | goto cleanup; |
| 522 | } |
| 523 | wifiConfigCommand->attr_end(nlData); |
| 524 | |
| 525 | ret = wifiConfigCommand->requestEvent(); |
| 526 | if (ret != WIFI_SUCCESS) { |
| 527 | ALOGE("wifi_reset_tx_power_scenario(): requestEvent Error:%d", ret); |
| 528 | goto cleanup; |
| 529 | } |
| 530 | |
| 531 | cleanup: |
| 532 | delete wifiConfigCommand; |
Srinivas Dasari | dc48894 | 2018-01-24 19:35:19 +0530 | [diff] [blame] | 533 | return ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 534 | } |
| 535 | |
Vamsi Krishna | 4b90cd5 | 2020-02-03 10:11:34 +0530 | [diff] [blame^] | 536 | wifi_error wifi_set_thermal_mitigation_mode(wifi_handle handle, |
| 537 | wifi_thermal_mode mode, |
| 538 | u32 completion_window) |
| 539 | { |
| 540 | wifi_error ret; |
| 541 | WiFiConfigCommand *wifiConfigCommand; |
| 542 | struct nlattr *nlData; |
| 543 | u32 qca_vendor_thermal_level; |
| 544 | hal_info *info = getHalInfo(handle); |
| 545 | |
| 546 | if (!info || info->num_interfaces < 1) { |
| 547 | ALOGE("%s: Error wifi_handle NULL or base wlan interface not present", |
| 548 | __FUNCTION__); |
| 549 | return WIFI_ERROR_UNKNOWN; |
| 550 | } |
| 551 | |
| 552 | wifiConfigCommand = new WiFiConfigCommand( |
| 553 | handle, |
| 554 | 1, |
| 555 | OUI_QCA, |
| 556 | QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD); |
| 557 | if (wifiConfigCommand == NULL) { |
| 558 | ALOGE("%s: Error, Failed to create wifiConfigCommand", __FUNCTION__); |
| 559 | return WIFI_ERROR_UNKNOWN; |
| 560 | } |
| 561 | |
| 562 | /* Create the NL message. */ |
| 563 | ret = wifiConfigCommand->create(); |
| 564 | if (ret != WIFI_SUCCESS) { |
| 565 | ALOGE("Failed to create thermal vendor command, Error:%d", ret); |
| 566 | goto cleanup; |
| 567 | } |
| 568 | |
| 569 | /* Set the interface Id of the message. */ |
| 570 | if (wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, |
| 571 | info->interfaces[0]->id)) { |
| 572 | ALOGE("%s: Failed to put iface id", __FUNCTION__); |
| 573 | goto cleanup; |
| 574 | } |
| 575 | |
| 576 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 577 | if (!nlData) { |
| 578 | ALOGE("%s: Failed in attr_start for VENDOR_DATA, Error:%d", |
| 579 | __FUNCTION__, ret); |
| 580 | goto cleanup; |
| 581 | } |
| 582 | |
| 583 | if (wifiConfigCommand->put_u32(QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE, |
| 584 | QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL)) { |
| 585 | ALOGE("Failed to put THERMAL_LEVEL command type"); |
| 586 | goto cleanup; |
| 587 | } |
| 588 | |
| 589 | switch(mode) { |
| 590 | case WIFI_MITIGATION_NONE: |
| 591 | qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE; |
| 592 | break; |
| 593 | case WIFI_MITIGATION_LIGHT: |
| 594 | qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_LIGHT; |
| 595 | break; |
| 596 | case WIFI_MITIGATION_MODERATE: |
| 597 | qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_MODERATE; |
| 598 | break; |
| 599 | case WIFI_MITIGATION_SEVERE: |
| 600 | qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_SEVERE; |
| 601 | break; |
| 602 | case WIFI_MITIGATION_CRITICAL: |
| 603 | qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_CRITICAL; |
| 604 | break; |
| 605 | case WIFI_MITIGATION_EMERGENCY: |
| 606 | qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_EMERGENCY; |
| 607 | break; |
| 608 | default: |
| 609 | ALOGE("Unknown thermal mitigation level %d", mode); |
| 610 | ret = WIFI_ERROR_UNKNOWN; |
| 611 | goto cleanup; |
| 612 | } |
| 613 | |
| 614 | if (wifiConfigCommand->put_u32( |
| 615 | QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL, |
| 616 | qca_vendor_thermal_level)) { |
| 617 | ALOGE("Failed to put thermal level"); |
| 618 | goto cleanup; |
| 619 | } |
| 620 | |
| 621 | if (wifiConfigCommand->put_u32( |
| 622 | QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW, |
| 623 | completion_window)) { |
| 624 | ALOGE("Failed to put thermal completion window"); |
| 625 | goto cleanup; |
| 626 | } |
| 627 | wifiConfigCommand->attr_end(nlData); |
| 628 | |
| 629 | wifiConfigCommand->waitForRsp(false); |
| 630 | ret = wifiConfigCommand->requestEvent(); |
| 631 | if (ret != WIFI_SUCCESS) { |
| 632 | ALOGE("Failed to set thermal level with Error: %d", ret); |
| 633 | goto cleanup; |
| 634 | } |
| 635 | |
| 636 | cleanup: |
| 637 | delete wifiConfigCommand; |
| 638 | return ret; |
| 639 | } |
| 640 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 641 | WiFiConfigCommand::WiFiConfigCommand(wifi_handle handle, |
| 642 | int id, u32 vendor_id, |
| 643 | u32 subcmd) |
| 644 | : WifiVendorCommand(handle, id, vendor_id, subcmd) |
| 645 | { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 646 | /* Initialize the member data variables here */ |
| 647 | mWaitforRsp = false; |
| 648 | mRequestId = id; |
| 649 | } |
| 650 | |
| 651 | WiFiConfigCommand::~WiFiConfigCommand() |
| 652 | { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 653 | unregisterVendorHandler(mVendor_id, mSubcmd); |
| 654 | } |
| 655 | |
| 656 | /* This function implements creation of Vendor command */ |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 657 | wifi_error WiFiConfigCommand::create() |
| 658 | { |
| 659 | wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0); |
| 660 | if (ret != WIFI_SUCCESS) |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 661 | return ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 662 | |
| 663 | /* Insert the oui in the msg */ |
| 664 | ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 665 | if (ret != WIFI_SUCCESS) |
| 666 | return ret; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 667 | /* Insert the subcmd in the msg */ |
| 668 | ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 669 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 670 | return ret; |
| 671 | } |
| 672 | |
| 673 | /* This function implements creation of generic NL command */ |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 674 | wifi_error WiFiConfigCommand::create_generic(u8 cmdId) |
| 675 | { |
| 676 | wifi_error ret = mMsg.create(cmdId, 0, 0); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 677 | return ret; |
| 678 | } |
| 679 | |
| 680 | void WiFiConfigCommand::waitForRsp(bool wait) |
| 681 | { |
| 682 | mWaitforRsp = wait; |
| 683 | } |
| 684 | |
| 685 | /* Callback handlers registered for nl message send */ |
| 686 | static int error_handler_wifi_config(struct sockaddr_nl *nla, |
| 687 | struct nlmsgerr *err, |
| 688 | void *arg) |
| 689 | { |
| 690 | struct sockaddr_nl *tmp; |
| 691 | int *ret = (int *)arg; |
| 692 | tmp = nla; |
| 693 | *ret = err->error; |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 694 | ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret))); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 695 | return NL_STOP; |
| 696 | } |
| 697 | |
| 698 | /* Callback handlers registered for nl message send */ |
| 699 | static int ack_handler_wifi_config(struct nl_msg *msg, void *arg) |
| 700 | { |
| 701 | int *ret = (int *)arg; |
| 702 | struct nl_msg * a; |
| 703 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 704 | a = msg; |
| 705 | *ret = 0; |
| 706 | return NL_STOP; |
| 707 | } |
| 708 | |
| 709 | /* Callback handlers registered for nl message send */ |
| 710 | static int finish_handler_wifi_config(struct nl_msg *msg, void *arg) |
| 711 | { |
| 712 | int *ret = (int *)arg; |
| 713 | struct nl_msg * a; |
| 714 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 715 | a = msg; |
| 716 | *ret = 0; |
| 717 | return NL_SKIP; |
| 718 | } |
| 719 | |
| 720 | /* |
| 721 | * Override base class requestEvent and implement little differently here. |
| 722 | * This will send the request message. |
| 723 | * We don't wait for any response back in case of wificonfig, |
| 724 | * thus no wait for condition. |
| 725 | */ |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 726 | wifi_error WiFiConfigCommand::requestEvent() |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 727 | { |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 728 | int status; |
| 729 | wifi_error res = WIFI_SUCCESS; |
Hu Wang | c1a1901 | 2019-04-15 15:35:12 +0800 | [diff] [blame] | 730 | struct nl_cb *cb = NULL; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 731 | |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 732 | cb = nl_cb_alloc(NL_CB_DEFAULT); |
| 733 | if (!cb) { |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 734 | ALOGE("%s: Callback allocation failed",__FUNCTION__); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 735 | res = WIFI_ERROR_OUT_OF_MEMORY; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 736 | goto out; |
| 737 | } |
| 738 | |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 739 | status = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); |
| 740 | if (status < 0) { |
| 741 | res = mapKernelErrortoWifiHalError(status); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 742 | goto out; |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 743 | } |
| 744 | status = 1; |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 745 | |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 746 | nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_config, &status); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 747 | nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_config, |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 748 | &status); |
| 749 | nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_config, &status); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 750 | |
| 751 | /* Err is populated as part of finish_handler. */ |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 752 | while (status > 0) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 753 | nl_recvmsgs(mInfo->cmd_sock, cb); |
| 754 | } |
| 755 | |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 756 | if (status < 0) { |
| 757 | res = mapKernelErrortoWifiHalError(status); |
| 758 | goto out; |
| 759 | } |
| 760 | |
| 761 | if (mWaitforRsp == true) { |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 762 | struct timespec abstime; |
| 763 | abstime.tv_sec = 4; |
| 764 | abstime.tv_nsec = 0; |
| 765 | res = mCondition.wait(abstime); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 766 | if (res == WIFI_ERROR_TIMED_OUT) |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 767 | ALOGE("%s: Time out happened.", __FUNCTION__); |
Srinivas Dasari | 30b13c7 | 2017-08-08 15:44:23 +0530 | [diff] [blame] | 768 | |
Subhani Shaik | eb97b6e | 2016-03-29 11:33:25 +0530 | [diff] [blame] | 769 | ALOGV("%s: Command invoked return value:%d, mWaitForRsp=%d", |
Dasari Srinivas | 9b3d8d4 | 2015-09-10 11:16:45 +0530 | [diff] [blame] | 770 | __FUNCTION__, res, mWaitforRsp); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 771 | } |
| 772 | out: |
Hu Wang | c1a1901 | 2019-04-15 15:35:12 +0800 | [diff] [blame] | 773 | nl_cb_put(cb); |
Ahmad Kholaif | 159de4f | 2015-03-23 16:02:05 -0700 | [diff] [blame] | 774 | /* Cleanup the mMsg */ |
| 775 | mMsg.destroy(); |
| 776 | return res; |
| 777 | } |
| 778 | |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 779 | |
| 780 | |
| 781 | static std::vector<std::string> added_ifaces; |
| 782 | |
| 783 | static bool is_dynamic_interface(const char * ifname) |
| 784 | { |
| 785 | for (const auto& iface : added_ifaces) { |
| 786 | if (iface == std::string(ifname)) |
| 787 | return true; |
| 788 | } |
| 789 | return false; |
| 790 | } |
| 791 | |
| 792 | void wifi_cleanup_dynamic_ifaces(wifi_handle handle) |
| 793 | { |
| 794 | int len = added_ifaces.size(); |
| 795 | while (len--) { |
| 796 | wifi_virtual_interface_delete(handle, added_ifaces.front().c_str()); |
| 797 | } |
| 798 | added_ifaces.clear(); // could be redundent. But to be on safe side. |
| 799 | } |
| 800 | |
| 801 | wifi_error wifi_virtual_interface_create(wifi_handle handle, |
| 802 | const char* ifname, |
| 803 | wifi_interface_type iface_type) |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 804 | { |
| 805 | wifi_error ret; |
| 806 | WiFiConfigCommand *wifiConfigCommand; |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 807 | u32 wlan0_id = if_nametoindex("wlan0"); |
| 808 | if (!handle || !wlan0_id) { |
| 809 | ALOGE("%s: Error wifi_handle NULL or wlan0 not present", __FUNCTION__); |
| 810 | return WIFI_ERROR_UNKNOWN; |
| 811 | } |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 812 | |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 813 | ALOGD("%s: ifname=%s create", __FUNCTION__, ifname); |
| 814 | // Do not create interface if already exist. |
| 815 | if (if_nametoindex(ifname)) |
| 816 | return WIFI_SUCCESS; |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 817 | |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 818 | wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0); |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 819 | if (wifiConfigCommand == NULL) { |
| 820 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
| 821 | return WIFI_ERROR_UNKNOWN; |
| 822 | } |
| 823 | |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 824 | nl80211_iftype type; |
| 825 | switch(iface_type) { |
| 826 | case WIFI_INTERFACE_TYPE_STA: /* IfaceType:STA */ |
| 827 | type = NL80211_IFTYPE_STATION; |
| 828 | break; |
| 829 | case WIFI_INTERFACE_TYPE_AP: /* IfaceType:AP */ |
| 830 | type = NL80211_IFTYPE_AP; |
| 831 | break; |
| 832 | case WIFI_INTERFACE_TYPE_P2P: /* IfaceType:P2P */ |
| 833 | type = NL80211_IFTYPE_P2P_DEVICE; |
| 834 | break; |
Swarn Singh | c2c9bc8 | 2019-12-05 18:08:27 +0530 | [diff] [blame] | 835 | case WIFI_INTERFACE_TYPE_NAN: /* IfaceType:NAN */ |
| 836 | type = NL80211_IFTYPE_NAN; |
| 837 | break; |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 838 | default: |
| 839 | ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type); |
| 840 | ret = WIFI_ERROR_UNKNOWN; |
| 841 | goto done; |
| 842 | break; |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 843 | } |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 844 | wifiConfigCommand->create_generic(NL80211_CMD_NEW_INTERFACE); |
| 845 | wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, wlan0_id); |
| 846 | wifiConfigCommand->put_string(NL80211_ATTR_IFNAME, ifname); |
| 847 | wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type); |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 848 | /* Send the NL msg. */ |
| 849 | wifiConfigCommand->waitForRsp(false); |
| 850 | ret = wifiConfigCommand->requestEvent(); |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 851 | if (ret != WIFI_SUCCESS) { |
| 852 | ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret); |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 853 | } |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 854 | // Update dynamic interface list |
| 855 | added_ifaces.push_back(std::string(ifname)); |
Purushottam Kushwaha | e1cf8f9 | 2018-06-08 17:47:53 +0530 | [diff] [blame] | 856 | |
| 857 | done: |
| 858 | delete wifiConfigCommand; |
| 859 | return ret; |
| 860 | } |
Hu Wang | 38714b6 | 2018-11-08 19:57:21 +0800 | [diff] [blame] | 861 | |
Khanjan Desai | 80f7849 | 2020-03-03 00:04:51 +0530 | [diff] [blame] | 862 | wifi_error wifi_virtual_interface_delete(wifi_handle handle, |
| 863 | const char* ifname) |
| 864 | { |
| 865 | wifi_error ret; |
| 866 | WiFiConfigCommand *wifiConfigCommand; |
| 867 | u32 wlan0_id = if_nametoindex("wlan0"); |
| 868 | |
| 869 | if (!handle || !wlan0_id) { |
| 870 | ALOGE("%s: Error wifi_handle NULL or wlan0 not present", __FUNCTION__); |
| 871 | return WIFI_ERROR_UNKNOWN; |
| 872 | } |
| 873 | |
| 874 | ALOGD("%s: ifname=%s delete", __FUNCTION__, ifname); |
| 875 | if (if_nametoindex(ifname) && !is_dynamic_interface(ifname)) { |
| 876 | // Do not remove interface if it was not added dynamically. |
| 877 | return WIFI_SUCCESS; |
| 878 | } |
| 879 | wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0); |
| 880 | if (wifiConfigCommand == NULL) { |
| 881 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
| 882 | return WIFI_ERROR_UNKNOWN; |
| 883 | } |
| 884 | wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE); |
| 885 | wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname)); |
| 886 | /* Send the NL msg. */ |
| 887 | wifiConfigCommand->waitForRsp(false); |
| 888 | ret = wifiConfigCommand->requestEvent(); |
| 889 | if (ret != WIFI_SUCCESS) { |
| 890 | ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret); |
| 891 | } |
| 892 | // Update dynamic interface list |
| 893 | added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)), |
| 894 | added_ifaces.end()); |
| 895 | |
| 896 | delete wifiConfigCommand; |
| 897 | return ret; |
| 898 | } |
| 899 | |
| 900 | #ifdef WCNSS_QTI_AOSP |
Hu Wang | 38714b6 | 2018-11-08 19:57:21 +0800 | [diff] [blame] | 901 | /** |
| 902 | * Set latency level |
| 903 | */ |
| 904 | wifi_error wifi_set_latency_mode(wifi_interface_handle iface, |
| 905 | wifi_latency_mode mode) |
| 906 | { |
| 907 | int requestId, ret = 0; |
Hu Wang | c193635 | 2019-04-25 15:26:03 +0800 | [diff] [blame] | 908 | u16 level; |
Hu Wang | 38714b6 | 2018-11-08 19:57:21 +0800 | [diff] [blame] | 909 | WiFiConfigCommand *wifiConfigCommand; |
| 910 | struct nlattr *nlData; |
| 911 | interface_info *ifaceInfo = getIfaceInfo(iface); |
| 912 | wifi_handle wifiHandle = getWifiHandle(iface); |
| 913 | |
| 914 | ALOGD("%s: %d", __FUNCTION__, mode); |
| 915 | |
Hu Wang | c193635 | 2019-04-25 15:26:03 +0800 | [diff] [blame] | 916 | switch (mode) { |
| 917 | case WIFI_LATENCY_MODE_NORMAL: |
| 918 | level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL; |
| 919 | break; |
| 920 | case WIFI_LATENCY_MODE_LOW: |
| 921 | level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW; |
| 922 | break; |
| 923 | default: |
| 924 | ALOGI("%s: Unsupported latency mode=%d, resetting to NORMAL!", __FUNCTION__, mode); |
| 925 | level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL; |
| 926 | break; |
| 927 | } |
| 928 | |
Hu Wang | 38714b6 | 2018-11-08 19:57:21 +0800 | [diff] [blame] | 929 | requestId = get_requestid(); |
| 930 | |
| 931 | wifiConfigCommand = new WiFiConfigCommand( |
| 932 | wifiHandle, |
| 933 | requestId, |
| 934 | OUI_QCA, |
| 935 | QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION); |
| 936 | |
| 937 | if (wifiConfigCommand == NULL) { |
| 938 | ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__); |
| 939 | return WIFI_ERROR_UNKNOWN; |
| 940 | } |
| 941 | |
| 942 | /* Create the NL message. */ |
| 943 | ret = wifiConfigCommand->create(); |
| 944 | if (ret < 0) { |
| 945 | ALOGE("%s: failed to create NL msg. Error:%d", |
| 946 | __FUNCTION__, ret); |
| 947 | goto cleanup; |
| 948 | } |
| 949 | |
| 950 | /* Set the interface Id of the message. */ |
| 951 | ret = wifiConfigCommand->set_iface_id(ifaceInfo->name); |
| 952 | if (ret < 0) { |
| 953 | ALOGE("%s: failed to set iface id. Error:%d", |
| 954 | __FUNCTION__, ret); |
| 955 | goto cleanup; |
| 956 | } |
| 957 | |
| 958 | /* Add the vendor specific attributes for the NL command. */ |
| 959 | nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA); |
| 960 | if (!nlData) { |
| 961 | ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d", |
| 962 | __FUNCTION__, ret); |
| 963 | goto cleanup; |
| 964 | } |
| 965 | |
| 966 | if (wifiConfigCommand->put_u16( |
Hu Wang | c193635 | 2019-04-25 15:26:03 +0800 | [diff] [blame] | 967 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL, level)) { |
Hu Wang | 38714b6 | 2018-11-08 19:57:21 +0800 | [diff] [blame] | 968 | ALOGE("%s: failed to put vendor data. Error:%d", |
| 969 | __FUNCTION__, ret); |
| 970 | goto cleanup; |
| 971 | } |
| 972 | wifiConfigCommand->attr_end(nlData); |
| 973 | |
| 974 | /* Send the NL msg. */ |
| 975 | wifiConfigCommand->waitForRsp(false); |
| 976 | ret = wifiConfigCommand->requestEvent(); |
| 977 | if (ret != 0) { |
| 978 | ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret); |
| 979 | goto cleanup; |
| 980 | } |
| 981 | |
| 982 | cleanup: |
| 983 | delete wifiConfigCommand; |
| 984 | return (wifi_error)ret; |
| 985 | } |
Hans Chang | 04ada2a | 2018-08-28 14:53:31 -0700 | [diff] [blame] | 986 | #endif |