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
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 * Changes from Qualcomm Innovation Center are provided under the following license:
29
30 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
31 * SPDX-License-Identifier: BSD-3-Clause-Clear
32 */
33
34 #include "sync.h"
35 #define LOG_TAG "WifiHAL"
36 #include <utils/Log.h>
37 #include <time.h>
38 #include <errno.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <string>
42 #include <net/if.h>
43 #include <vector>
44 #include <sys/ioctl.h>
45 #include <net/if.h>
46 #include <net/if_arp.h>
47 #include <sys/socket.h>
48 #include "wificonfigcommand.h"
49 #include "ifaceeventhandler.h"
50
51 #define NUM_OF_SAR_LIMITS_SPECS 2
52 #define NUM_OF_SPEC_CHAINS 2
53
54 /* Implementation of the API functions exposed in wifi_config.h */
wifi_extended_dtim_config_set(wifi_request_id id,wifi_interface_handle iface,int extended_dtim)55 wifi_error wifi_extended_dtim_config_set(wifi_request_id id,
56 wifi_interface_handle iface,
57 int extended_dtim)
58 {
59 wifi_error ret;
60 WiFiConfigCommand *wifiConfigCommand;
61 struct nlattr *nlData;
62 interface_info *ifaceInfo = getIfaceInfo(iface);
63 wifi_handle wifiHandle = getWifiHandle(iface);
64
65 ALOGV("%s: extended_dtim:%d", __FUNCTION__, extended_dtim);
66
67 wifiConfigCommand = new WiFiConfigCommand(
68 wifiHandle,
69 id,
70 OUI_QCA,
71 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
72
73 if (wifiConfigCommand == NULL) {
74 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
75 return WIFI_ERROR_UNKNOWN;
76 }
77
78 /* Create the NL message. */
79 ret = wifiConfigCommand->create();
80 if (ret != WIFI_SUCCESS) {
81 ALOGE("wifi_extended_dtim_config_set: failed to create NL msg. "
82 "Error:%d", ret);
83 goto cleanup;
84 }
85
86 /* Set the interface Id of the message. */
87 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
88 if (ret != WIFI_SUCCESS) {
89 ALOGE("wifi_extended_dtim_config_set: failed to set iface id. "
90 "Error:%d", ret);
91 goto cleanup;
92 }
93
94 /* Add the vendor specific attributes for the NL command. */
95 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
96 if (!nlData) {
97 ret = WIFI_ERROR_UNKNOWN;
98 ALOGE("wifi_extended_dtim_config_set: failed attr_start for "
99 "VENDOR_DATA. Error:%d", ret);
100 goto cleanup;
101 }
102
103 ret = wifiConfigCommand->put_u32(
104 QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM, extended_dtim);
105 if (ret != WIFI_SUCCESS) {
106 ALOGE("wifi_extended_dtim_config_set(): failed to put vendor data. "
107 "Error:%d", ret);
108 goto cleanup;
109 }
110 wifiConfigCommand->attr_end(nlData);
111
112 /* Send the NL msg. */
113 wifiConfigCommand->waitForRsp(false);
114 ret = wifiConfigCommand->requestEvent();
115 if (ret != WIFI_SUCCESS) {
116 ALOGE("wifi_extended_dtim_config_set(): requestEvent Error:%d", ret);
117 goto cleanup;
118 }
119
120 cleanup:
121 delete wifiConfigCommand;
122 return ret;
123 }
124
check_feature(enum qca_wlan_vendor_features feature,features_info * info)125 int check_feature(enum qca_wlan_vendor_features feature, features_info *info)
126 {
127 size_t idx = feature / 8;
128
129 return (idx < info->flags_len) &&
130 (info->flags[idx] & BIT(feature % 8));
131 }
132
133 /* Set the country code to driver. */
wifi_set_country_code(wifi_interface_handle iface,const char * country_code)134 wifi_error wifi_set_country_code(wifi_interface_handle iface,
135 const char* country_code)
136 {
137 int requestId;
138 wifi_error ret;
139 WiFiConfigCommand *wifiConfigCommand;
140 wifi_handle wifiHandle = getWifiHandle(iface);
141 hal_info *info = getHalInfo(wifiHandle);
142
143 ALOGV("%s: %s", __FUNCTION__, country_code);
144
145 /* No request id from caller, so generate one and pass it on to the driver.
146 * Generate it randomly.
147 */
148 requestId = get_requestid();
149
150 wifiConfigCommand = new WiFiConfigCommand(
151 wifiHandle,
152 requestId,
153 OUI_QCA,
154 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
155 if (wifiConfigCommand == NULL) {
156 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
157 return WIFI_ERROR_UNKNOWN;
158 }
159
160 /* Create the NL message with NL80211_CMD_REQ_SET_REG NL cmd. */
161 ret = wifiConfigCommand->create_generic(NL80211_CMD_REQ_SET_REG);
162 if (ret != WIFI_SUCCESS) {
163 ALOGE("wifi_set_country_code: failed to create NL msg. Error:%d", ret);
164 goto cleanup;
165 }
166
167 ret = wifiConfigCommand->put_string(NL80211_ATTR_REG_ALPHA2, country_code);
168 if (ret != WIFI_SUCCESS) {
169 ALOGE("wifi_set_country_code: put country code failed. Error:%d", ret);
170 goto cleanup;
171 }
172
173 if (check_feature(QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY,
174 &info->driver_supported_features)) {
175 ret = wifiConfigCommand->put_u32(NL80211_ATTR_USER_REG_HINT_TYPE,
176 NL80211_USER_REG_HINT_CELL_BASE);
177 if (ret != WIFI_SUCCESS) {
178 ALOGE("wifi_set_country_code: put reg hint type failed. Error:%d",
179 ret);
180 goto cleanup;
181 }
182 }
183
184
185 /* Send the NL msg. */
186 wifiConfigCommand->waitForRsp(false);
187 ret = wifiConfigCommand->requestEvent();
188 if (ret != WIFI_SUCCESS) {
189 ALOGE("wifi_set_country_code(): requestEvent Error:%d", ret);
190 goto cleanup;
191 }
192 usleep(WAIT_TIME_FOR_SET_REG_DOMAIN);
193
194 cleanup:
195 delete wifiConfigCommand;
196 return ret;
197 }
198
199 /*
200 * Set the powersave to driver.
201 */
wifi_set_qpower(wifi_interface_handle iface,u8 powersave)202 wifi_error wifi_set_qpower(wifi_interface_handle iface,
203 u8 powersave)
204 {
205 int requestId, ret = 0;
206 WiFiConfigCommand *wifiConfigCommand;
207 struct nlattr *nlData;
208 interface_info *ifaceInfo = getIfaceInfo(iface);
209 wifi_handle wifiHandle = getWifiHandle(iface);
210 //hal_info *info = getHalInfo(wifiHandle);
211
212 ALOGD("%s: %d", __FUNCTION__, powersave);
213
214 requestId = get_requestid();
215
216 wifiConfigCommand = new WiFiConfigCommand(
217 wifiHandle,
218 requestId,
219 OUI_QCA,
220 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
221
222 if (wifiConfigCommand == NULL) {
223 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
224 return WIFI_ERROR_UNKNOWN;
225 }
226
227 /* Create the NL message. */
228 ret = wifiConfigCommand->create();
229 if (ret < 0) {
230 ALOGE("wifi_set_qpower: failed to create NL msg. "
231 "Error:%d", ret);
232 goto cleanup;
233 }
234
235 /* Set the interface Id of the message. */
236 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
237 if (ret < 0) {
238 ALOGE("wifi_set_qpower: failed to set iface id. "
239 "Error:%d", ret);
240 goto cleanup;
241 }
242
243 /* Add the vendor specific attributes for the NL command. */
244 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
245 if (!nlData) {
246 ret = WIFI_ERROR_UNKNOWN;
247 ALOGE("wifi_set_qpower: failed attr_start for "
248 "VENDOR_DATA. Error:%d", ret);
249 goto cleanup;
250 }
251
252 if (wifiConfigCommand->put_u8(
253 QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER, powersave)) {
254 ret = WIFI_ERROR_UNKNOWN;
255 ALOGE("wifi_set_qpower(): failed to put vendor data. "
256 "Error:%d", ret);
257 goto cleanup;
258 }
259 wifiConfigCommand->attr_end(nlData);
260
261 /* Send the NL msg. */
262 wifiConfigCommand->waitForRsp(false);
263 ret = wifiConfigCommand->requestEvent();
264 if (ret != 0) {
265 ALOGE("wifi_set_qpower(): requestEvent Error:%d", ret);
266 goto cleanup;
267 }
268
269 cleanup:
270 delete wifiConfigCommand;
271 return (wifi_error)ret;
272
273 }
274
wifi_set_beacon_wifi_iface_stats_averaging_factor(wifi_request_id id,wifi_interface_handle iface,u16 factor)275 wifi_error wifi_set_beacon_wifi_iface_stats_averaging_factor(
276 wifi_request_id id,
277 wifi_interface_handle iface,
278 u16 factor)
279 {
280 wifi_error ret;
281 WiFiConfigCommand *wifiConfigCommand;
282 struct nlattr *nlData;
283 interface_info *ifaceInfo = getIfaceInfo(iface);
284 wifi_handle wifiHandle = getWifiHandle(iface);
285
286 ALOGV("%s factor:%u", __FUNCTION__, factor);
287 wifiConfigCommand = new WiFiConfigCommand(
288 wifiHandle,
289 id,
290 OUI_QCA,
291 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
292 if (wifiConfigCommand == NULL) {
293 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
294 return WIFI_ERROR_UNKNOWN;
295 }
296
297 /* Create the NL message. */
298 ret = wifiConfigCommand->create();
299 if (ret != WIFI_SUCCESS) {
300 ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed to "
301 "create NL msg. Error:%d", ret);
302 goto cleanup;
303 }
304
305 /* Set the interface Id of the message. */
306 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
307 if (ret != WIFI_SUCCESS) {
308 ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed to "
309 "set iface id. Error:%d", ret);
310 goto cleanup;
311 }
312
313 /* Add the vendor specific attributes for the NL command. */
314 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
315 if (!nlData) {
316 ret = WIFI_ERROR_UNKNOWN;
317 ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed "
318 "attr_start for VENDOR_DATA. Error:%d", ret);
319 goto cleanup;
320 }
321
322 if (wifiConfigCommand->put_u32(
323 QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR, factor)) {
324 ret = WIFI_ERROR_UNKNOWN;
325 ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor(): failed to "
326 "put vendor data. Error:%d", ret);
327 goto cleanup;
328 }
329 wifiConfigCommand->attr_end(nlData);
330
331 /* Send the NL msg. */
332 wifiConfigCommand->waitForRsp(false);
333 ret = wifiConfigCommand->requestEvent();
334 if (ret != WIFI_SUCCESS) {
335 ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor(): "
336 "requestEvent Error:%d", ret);
337 goto cleanup;
338 }
339
340 cleanup:
341 delete wifiConfigCommand;
342 return ret;
343 }
344
wifi_set_guard_time(wifi_request_id id,wifi_interface_handle iface,u32 guard_time)345 wifi_error wifi_set_guard_time(wifi_request_id id,
346 wifi_interface_handle iface,
347 u32 guard_time)
348 {
349 wifi_error ret;
350 WiFiConfigCommand *wifiConfigCommand;
351 struct nlattr *nlData;
352 interface_info *ifaceInfo = getIfaceInfo(iface);
353 wifi_handle wifiHandle = getWifiHandle(iface);
354
355 ALOGV("%s : guard_time:%u", __FUNCTION__, guard_time);
356
357 wifiConfigCommand = new WiFiConfigCommand(
358 wifiHandle,
359 id,
360 OUI_QCA,
361 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
362 if (wifiConfigCommand == NULL) {
363 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
364 return WIFI_ERROR_UNKNOWN;
365 }
366
367 /* Create the NL message. */
368 ret = wifiConfigCommand->create();
369 if (ret != WIFI_SUCCESS) {
370 ALOGE("wifi_set_guard_time: failed to create NL msg. Error:%d", ret);
371 goto cleanup;
372 }
373
374 /* Set the interface Id of the message. */
375 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
376 if (ret != WIFI_SUCCESS) {
377 ALOGE("wifi_set_guard_time: failed to set iface id. Error:%d", ret);
378 goto cleanup;
379 }
380
381 /* Add the vendor specific attributes for the NL command. */
382 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
383 if (!nlData) {
384 ret = WIFI_ERROR_UNKNOWN;
385 ALOGE("wifi_set_guard_time: failed attr_start for VENDOR_DATA. "
386 "Error:%d", ret);
387 goto cleanup;
388 }
389
390 if (wifiConfigCommand->put_u32(
391 QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME, guard_time)) {
392 ret = WIFI_ERROR_UNKNOWN;
393 ALOGE("wifi_set_guard_time: failed to add vendor data.");
394 goto cleanup;
395 }
396 wifiConfigCommand->attr_end(nlData);
397
398 /* Send the NL msg. */
399 wifiConfigCommand->waitForRsp(false);
400 ret = wifiConfigCommand->requestEvent();
401 if (ret != WIFI_SUCCESS) {
402 ALOGE("wifi_set_guard_time(): requestEvent Error:%d", ret);
403 goto cleanup;
404 }
405
406 cleanup:
407 delete wifiConfigCommand;
408 return ret;
409 }
410
wifi_select_SARv01_tx_power_scenario(wifi_interface_handle handle,wifi_power_scenario scenario)411 wifi_error wifi_select_SARv01_tx_power_scenario(wifi_interface_handle handle,
412 wifi_power_scenario scenario)
413 {
414 wifi_error ret;
415 WiFiConfigCommand *wifiConfigCommand;
416 struct nlattr *nlData;
417 interface_info *ifaceInfo = getIfaceInfo(handle);
418 wifi_handle wifiHandle = getWifiHandle(handle);
419 u32 bdf_file = 0;
420
421 ALOGV("%s : power scenario:%d", __FUNCTION__, scenario);
422
423 wifiConfigCommand = new WiFiConfigCommand(
424 wifiHandle,
425 1,
426 OUI_QCA,
427 QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS);
428 if (wifiConfigCommand == NULL) {
429 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
430 return WIFI_ERROR_UNKNOWN;
431 }
432
433 /* Create the NL message. */
434 ret = wifiConfigCommand->create();
435 if (ret != WIFI_SUCCESS) {
436 ALOGE("wifi_select_tx_power_scenario: failed to create NL msg. Error:%d", ret);
437 goto cleanup;
438 }
439
440 /* Set the interface Id of the message. */
441 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
442 if (ret != WIFI_SUCCESS) {
443 ALOGE("wifi_select_tx_power_scenario: failed to set iface id. Error:%d", ret);
444 goto cleanup;
445 }
446
447 /* Add the vendor specific attributes for the NL command. */
448 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
449 if (!nlData) {
450 ret = WIFI_ERROR_UNKNOWN;
451 ALOGE("wifi_select_tx_power_scenario: failed attr_start for VENDOR_DATA. "
452 "Error:%d", ret);
453 goto cleanup;
454 }
455
456 switch (scenario) {
457 /* WIFI_POWER_SCENARIO_VOICE_CALL is used by VTS test to check this API.
458 * We should not remove this scenario even we don't use it in new projects.
459 */
460 case WIFI_POWER_SCENARIO_VOICE_CALL:
461 case WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON:
462 case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT:
463 case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW:
464 bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
465 break;
466
467 case WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF:
468 bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1;
469 break;
470
471 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT:
472 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT:
473 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW:
474 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW:
475 bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2;
476 break;
477
478 case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON:
479 bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3;
480 break;
481
482 case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT:
483 bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
484 break;
485
486 case WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF:
487 case WIFI_POWER_SCENARIO_ON_BODY_BT:
488 bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
489 break;
490
491 default:
492 ALOGE("wifi_select_tx_power_scenario: invalid scenario %d", scenario);
493 ret = WIFI_ERROR_INVALID_ARGS;
494 goto cleanup;
495 }
496
497 if (wifiConfigCommand->put_u32(
498 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE,
499 bdf_file)) {
500 ret = WIFI_ERROR_UNKNOWN;
501 ALOGE("failed to put SAR_ENABLE");
502 goto cleanup;
503 }
504 wifiConfigCommand->attr_end(nlData);
505
506 ret = wifiConfigCommand->requestEvent();
507 if (ret != WIFI_SUCCESS) {
508 ALOGE("wifi_select_tx_power_scenario(): requestEvent Error:%d", ret);
509 goto cleanup;
510 }
511
512 cleanup:
513 delete wifiConfigCommand;
514 return ret;
515 }
516
wifi_select_SARv02_tx_power_scenario(wifi_interface_handle handle,wifi_power_scenario scenario)517 wifi_error wifi_select_SARv02_tx_power_scenario(wifi_interface_handle handle,
518 wifi_power_scenario scenario)
519 {
520 wifi_error ret;
521 WiFiConfigCommand *wifiConfigCommand;
522 struct nlattr *nlData, *nlSpecList, *nlSpec;
523 interface_info *ifaceInfo = getIfaceInfo(handle);
524 wifi_handle wifiHandle = getWifiHandle(handle);
525 u32 power_lim_idx = 0;
526
527 ALOGV("%s : power scenario SARV2:%d", __FUNCTION__, scenario);
528
529 wifiConfigCommand = new WiFiConfigCommand(
530 wifiHandle,
531 1,
532 OUI_QCA,
533 QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS);
534 if (wifiConfigCommand == NULL) {
535 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
536 return WIFI_ERROR_UNKNOWN;
537 }
538
539 /* Create the NL message. */
540 ret = wifiConfigCommand->create();
541 if (ret != WIFI_SUCCESS) {
542 ALOGE("wifi_select_tx_power_scenario: failed to create NL msg. Error:%d", ret);
543 goto cleanup;
544 }
545
546 /* Set the interface Id of the message. */
547 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
548 if (ret != WIFI_SUCCESS) {
549 ALOGE("wifi_select_tx_power_scenario: failed to set iface id. Error:%d", ret);
550 goto cleanup;
551 }
552
553 /* Add the vendor specific attributes for the NL command. */
554 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
555 if (!nlData) {
556 ret = WIFI_ERROR_UNKNOWN;
557 ALOGE("wifi_select_tx_power_scenario: failed attr_start for VENDOR_DATA.");
558 goto cleanup;
559 }
560
561 if (wifiConfigCommand->put_u32(
562 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE,
563 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0)) {
564 ret = WIFI_ERROR_UNKNOWN;
565 ALOGE("failed to put SAR_ENABLE");
566 goto cleanup;
567 }
568
569 if (wifiConfigCommand->put_u32(
570 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS,
571 NUM_OF_SAR_LIMITS_SPECS)) {
572 ret = WIFI_ERROR_UNKNOWN;
573 ALOGE("failed to put SAR_LIMITS_NUM_SPECS");
574 goto cleanup;
575 }
576
577 switch (scenario) {
578 case WIFI_POWER_SCENARIO_VOICE_CALL:
579 case WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON:
580 case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT:
581 case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW:
582
583 power_lim_idx = 0;
584 break;
585
586 case WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF:
587 power_lim_idx = 1;
588 break;
589
590 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT:
591 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT:
592 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW:
593 case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW:
594 power_lim_idx = 2;
595 break;
596
597 case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON:
598 power_lim_idx = 3;
599 break;
600
601 case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT:
602 power_lim_idx = 4;
603 break;
604
605 case WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF:
606 case WIFI_POWER_SCENARIO_ON_BODY_BT:
607 power_lim_idx = 5;
608 break;
609 default:
610 ALOGE("wifi_select_tx_power_scenario: invalid scenario %d", scenario);
611 ret = WIFI_ERROR_INVALID_ARGS;
612 goto cleanup;
613 }
614
615
616 nlSpecList = wifiConfigCommand->attr_start(QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC);
617 if (!nlSpecList)
618 {
619 ALOGE("Cannot create spec list");
620 ret = WIFI_ERROR_UNKNOWN;
621 goto cleanup;
622 }
623
624
625 for (int i = 0; i < NUM_OF_SPEC_CHAINS; i++) {
626 nlSpec = wifiConfigCommand->attr_start(0);
627 if (!nlSpec) {
628 ret = WIFI_ERROR_UNKNOWN;
629 goto cleanup;
630 }
631 if (wifiConfigCommand->put_u32(
632 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN,
633 i))
634 {
635 ALOGE("Failed to put: QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN");
636 ret = WIFI_ERROR_UNKNOWN;
637 goto cleanup;
638 }
639
640 if (wifiConfigCommand->put_u32(
641 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX,
642 power_lim_idx))
643 {
644 ALOGE("Failed to put: QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX");
645 ret = WIFI_ERROR_UNKNOWN;
646 goto cleanup;
647 }
648
649 wifiConfigCommand->attr_end(nlSpec);
650 }
651
652
653
654 wifiConfigCommand->attr_end(nlSpecList);
655
656 wifiConfigCommand->attr_end(nlData);
657 ALOGV("wifi_select_tx_power_scenario %u selected", power_lim_idx);
658 ret = wifiConfigCommand->requestEvent();
659 if (ret != WIFI_SUCCESS) {
660 ALOGE("wifi_select_tx_power_scenario(): requestEvent Error:%d", ret);
661 goto cleanup;
662 }
663
664 cleanup:
665 delete wifiConfigCommand;
666 return ret;
667 }
668
669
wifi_select_tx_power_scenario(wifi_interface_handle handle,wifi_power_scenario scenario)670 wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle,
671 wifi_power_scenario scenario)
672 {
673
674 wifi_handle wifiHandle = getWifiHandle(handle);
675 hal_info *info = getHalInfo(wifiHandle);
676 if (info == NULL) {
677 ALOGE("%s: Error hal_info NULL", __FUNCTION__);
678 return WIFI_ERROR_UNKNOWN;
679 }
680 ALOGV("wifi_select_tx_power_scenario: sarVer%u", (u32)info->sar_version);
681 if (info->sar_version == QCA_WLAN_VENDOR_SAR_VERSION_1)
682 return wifi_select_SARv01_tx_power_scenario(handle,scenario);
683 else if (info->sar_version == QCA_WLAN_VENDOR_SAR_VERSION_2)
684 return wifi_select_SARv02_tx_power_scenario(handle,scenario);
685 else {
686 ALOGE("wifi_select_tx_power_scenario %u invalid or not supported", (u32)info->sar_version);
687 return WIFI_ERROR_UNKNOWN;
688 }
689 }
690
691
wifi_reset_tx_power_scenario(wifi_interface_handle handle)692 wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
693 {
694 wifi_error ret;
695 WiFiConfigCommand *wifiConfigCommand;
696 struct nlattr *nlData;
697 interface_info *ifaceInfo = getIfaceInfo(handle);
698 wifi_handle wifiHandle = getWifiHandle(handle);
699
700 wifiConfigCommand = new WiFiConfigCommand(
701 wifiHandle,
702 1,
703 OUI_QCA,
704 QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS);
705 if (wifiConfigCommand == NULL) {
706 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
707 return WIFI_ERROR_UNKNOWN;
708 }
709
710 /* Create the NL message. */
711 ret = wifiConfigCommand->create();
712 if (ret != WIFI_SUCCESS) {
713 ALOGE("wifi_reset_tx_power_scenario: failed to create NL msg. Error:%d", ret);
714 goto cleanup;
715 }
716
717 /* Set the interface Id of the message. */
718 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
719 if (ret != WIFI_SUCCESS) {
720 ALOGE("wifi_reset_tx_power_scenario: failed to set iface id. Error:%d", ret);
721 goto cleanup;
722 }
723
724 /* Add the vendor specific attributes for the NL command. */
725 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
726 if (!nlData) {
727 ret = WIFI_ERROR_UNKNOWN;
728 ALOGE("wifi_reset_tx_power_scenario: failed attr_start for VENDOR_DATA. "
729 "Error:%d", ret);
730 goto cleanup;
731 }
732
733 if (wifiConfigCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE,
734 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE)) {
735 ret = WIFI_ERROR_UNKNOWN;
736 ALOGE("failed to put SAR_ENABLE or NUM_SPECS");
737 goto cleanup;
738 }
739 wifiConfigCommand->attr_end(nlData);
740
741 ret = wifiConfigCommand->requestEvent();
742 if (ret != WIFI_SUCCESS) {
743 ALOGE("wifi_reset_tx_power_scenario(): requestEvent Error:%d", ret);
744 goto cleanup;
745 }
746
747 cleanup:
748 delete wifiConfigCommand;
749 return ret;
750 }
751
wifi_set_thermal_mitigation_mode(wifi_handle handle,wifi_thermal_mode mode,u32 completion_window)752 wifi_error wifi_set_thermal_mitigation_mode(wifi_handle handle,
753 wifi_thermal_mode mode,
754 u32 completion_window)
755 {
756 wifi_error ret;
757 WiFiConfigCommand *wifiConfigCommand;
758 struct nlattr *nlData;
759 u32 qca_vendor_thermal_level;
760 hal_info *info = getHalInfo(handle);
761
762 if (!info || info->num_interfaces < 1) {
763 ALOGE("%s: Error wifi_handle NULL or base wlan interface not present",
764 __FUNCTION__);
765 return WIFI_ERROR_UNKNOWN;
766 }
767
768 wifiConfigCommand = new WiFiConfigCommand(
769 handle,
770 1,
771 OUI_QCA,
772 QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD);
773 if (wifiConfigCommand == NULL) {
774 ALOGE("%s: Error, Failed to create wifiConfigCommand", __FUNCTION__);
775 return WIFI_ERROR_UNKNOWN;
776 }
777
778 /* Create the NL message. */
779 ret = wifiConfigCommand->create();
780 if (ret != WIFI_SUCCESS) {
781 ALOGE("Failed to create thermal vendor command, Error:%d", ret);
782 goto cleanup;
783 }
784
785 /* Set the interface Id of the message. */
786 if (wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
787 info->interfaces[0]->id)) {
788 ret = WIFI_ERROR_UNKNOWN;
789 ALOGE("%s: Failed to put iface id", __FUNCTION__);
790 goto cleanup;
791 }
792
793 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
794 if (!nlData) {
795 ret = WIFI_ERROR_UNKNOWN;
796 ALOGE("%s: Failed in attr_start for VENDOR_DATA, Error:%d",
797 __FUNCTION__, ret);
798 goto cleanup;
799 }
800
801 if (wifiConfigCommand->put_u32(QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE,
802 QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL)) {
803 ret = WIFI_ERROR_UNKNOWN;
804 ALOGE("Failed to put THERMAL_LEVEL command type");
805 goto cleanup;
806 }
807
808 switch(mode) {
809 case WIFI_MITIGATION_NONE:
810 qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE;
811 break;
812 case WIFI_MITIGATION_LIGHT:
813 qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_LIGHT;
814 break;
815 case WIFI_MITIGATION_MODERATE:
816 qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_MODERATE;
817 break;
818 case WIFI_MITIGATION_SEVERE:
819 qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_SEVERE;
820 break;
821 case WIFI_MITIGATION_CRITICAL:
822 qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_CRITICAL;
823 break;
824 case WIFI_MITIGATION_EMERGENCY:
825 qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_EMERGENCY;
826 break;
827 default:
828 ALOGE("Unknown thermal mitigation level %d", mode);
829 ret = WIFI_ERROR_UNKNOWN;
830 goto cleanup;
831 }
832
833 if (wifiConfigCommand->put_u32(
834 QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL,
835 qca_vendor_thermal_level)) {
836 ret = WIFI_ERROR_UNKNOWN;
837 ALOGE("Failed to put thermal level");
838 goto cleanup;
839 }
840
841 if (wifiConfigCommand->put_u32(
842 QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW,
843 completion_window)) {
844 ret = WIFI_ERROR_UNKNOWN;
845 ALOGE("Failed to put thermal completion window");
846 goto cleanup;
847 }
848 wifiConfigCommand->attr_end(nlData);
849
850 wifiConfigCommand->waitForRsp(false);
851 ret = wifiConfigCommand->requestEvent();
852 if (ret != WIFI_SUCCESS) {
853 ALOGE("Failed to set thermal level with Error: %d", ret);
854 goto cleanup;
855 }
856
857 cleanup:
858 delete wifiConfigCommand;
859 return ret;
860 }
861
WiFiConfigCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)862 WiFiConfigCommand::WiFiConfigCommand(wifi_handle handle,
863 int id, u32 vendor_id,
864 u32 subcmd)
865 : WifiVendorCommand(handle, id, vendor_id, subcmd)
866 {
867 /* Initialize the member data variables here */
868 mWaitforRsp = false;
869 mRequestId = id;
870 }
871
~WiFiConfigCommand()872 WiFiConfigCommand::~WiFiConfigCommand()
873 {
874 unregisterVendorHandler(mVendor_id, mSubcmd);
875 }
876
877 /* This function implements creation of Vendor command */
create()878 wifi_error WiFiConfigCommand::create()
879 {
880 wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
881 if (ret != WIFI_SUCCESS)
882 return ret;
883
884 /* Insert the oui in the msg */
885 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
886 if (ret != WIFI_SUCCESS)
887 return ret;
888 /* Insert the subcmd in the msg */
889 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
890
891 return ret;
892 }
893
894 /* This function implements creation of generic NL command */
create_generic(u8 cmdId)895 wifi_error WiFiConfigCommand::create_generic(u8 cmdId)
896 {
897 wifi_error ret = mMsg.create(cmdId, 0, 0);
898 return ret;
899 }
900
waitForRsp(bool wait)901 void WiFiConfigCommand::waitForRsp(bool wait)
902 {
903 mWaitforRsp = wait;
904 }
905
906 /* Callback handlers registered for nl message send */
error_handler_wifi_config(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)907 static int error_handler_wifi_config(struct sockaddr_nl *nla,
908 struct nlmsgerr *err,
909 void *arg)
910 {
911 struct sockaddr_nl *tmp;
912 int *ret = (int *)arg;
913 tmp = nla;
914 *ret = err->error;
915 ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
916 return NL_STOP;
917 }
918
919 /* Callback handlers registered for nl message send */
ack_handler_wifi_config(struct nl_msg * msg,void * arg)920 static int ack_handler_wifi_config(struct nl_msg *msg, void *arg)
921 {
922 int *ret = (int *)arg;
923 struct nl_msg * a;
924
925 a = msg;
926 *ret = 0;
927 return NL_STOP;
928 }
929
930 /* Callback handlers registered for nl message send */
finish_handler_wifi_config(struct nl_msg * msg,void * arg)931 static int finish_handler_wifi_config(struct nl_msg *msg, void *arg)
932 {
933 int *ret = (int *)arg;
934 struct nl_msg * a;
935
936 a = msg;
937 *ret = 0;
938 return NL_SKIP;
939 }
940
941 /*
942 * Override base class requestEvent and implement little differently here.
943 * This will send the request message.
944 * We don't wait for any response back in case of wificonfig,
945 * thus no wait for condition.
946 */
requestEvent()947 wifi_error WiFiConfigCommand::requestEvent()
948 {
949 int status;
950 wifi_error res = WIFI_SUCCESS;
951 struct nl_cb *cb = NULL;
952
953 cb = nl_cb_alloc(NL_CB_DEFAULT);
954 if (!cb) {
955 ALOGE("%s: Callback allocation failed",__FUNCTION__);
956 res = WIFI_ERROR_OUT_OF_MEMORY;
957 goto out;
958 }
959 if (mInfo == NULL || mInfo->cmd_sock == NULL) {
960 ALOGE("%s: Wifi is turned of or socket is Null",__FUNCTION__);
961 res = WIFI_ERROR_UNKNOWN;
962 goto out;
963 }
964
965 status = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
966 if (status < 0) {
967 res = mapKernelErrortoWifiHalError(status);
968 goto out;
969 }
970 status = 1;
971
972 nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_config, &status);
973 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_config,
974 &status);
975 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_config, &status);
976
977 /* Err is populated as part of finish_handler. */
978 while (status > 0) {
979 nl_recvmsgs(mInfo->cmd_sock, cb);
980 }
981
982 if (status < 0) {
983 res = mapKernelErrortoWifiHalError(status);
984 goto out;
985 }
986
987 if (mWaitforRsp == true) {
988 struct timespec abstime;
989 abstime.tv_sec = 4;
990 abstime.tv_nsec = 0;
991 res = mCondition.wait(abstime);
992 if (res == WIFI_ERROR_TIMED_OUT)
993 ALOGE("%s: Time out happened.", __FUNCTION__);
994
995 ALOGV("%s: Command invoked return value:%d, mWaitForRsp=%d",
996 __FUNCTION__, res, mWaitforRsp);
997 }
998 out:
999 nl_cb_put(cb);
1000 /* Cleanup the mMsg */
1001 mMsg.destroy();
1002 return res;
1003 }
1004
1005
1006
1007 static std::vector<std::string> added_ifaces;
1008
is_dynamic_interface(const char * ifname)1009 static bool is_dynamic_interface(const char * ifname)
1010 {
1011 for (const auto& iface : added_ifaces) {
1012 if (iface == std::string(ifname))
1013 return true;
1014 }
1015 return false;
1016 }
1017
wifi_cleanup_dynamic_ifaces(wifi_handle handle)1018 void wifi_cleanup_dynamic_ifaces(wifi_handle handle)
1019 {
1020 int len = added_ifaces.size();
1021 while (len--) {
1022 wifi_virtual_interface_delete(handle, added_ifaces.front().c_str());
1023 }
1024 added_ifaces.clear(); // could be redundent. But to be on safe side.
1025 }
1026
wifi_set_interface_mode(wifi_handle handle,const char * ifname,u32 iface_type)1027 static wifi_error wifi_set_interface_mode(wifi_handle handle,
1028 const char* ifname,
1029 u32 iface_type)
1030 {
1031 wifi_error ret;
1032 WiFiConfigCommand *wifiConfigCommand;
1033
1034 ALOGD("%s: ifname=%s iface_type=%u", __FUNCTION__, ifname, iface_type);
1035
1036 wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
1037 if (wifiConfigCommand == NULL) {
1038 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
1039 return WIFI_ERROR_UNKNOWN;
1040 }
1041
1042 nl80211_iftype type;
1043 switch(iface_type) {
1044 case WIFI_INTERFACE_TYPE_STA: /* IfaceType:STA */
1045 type = NL80211_IFTYPE_STATION;
1046 break;
1047 case WIFI_INTERFACE_TYPE_AP: /* IfaceType:AP */
1048 type = NL80211_IFTYPE_AP;
1049 break;
1050 case WIFI_INTERFACE_TYPE_P2P: /* IfaceType:P2P */
1051 type = NL80211_IFTYPE_P2P_DEVICE;
1052 break;
1053 case WIFI_INTERFACE_TYPE_NAN: /* IfaceType:NAN */
1054 type = NL80211_IFTYPE_NAN;
1055 break;
1056 default:
1057 ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type);
1058 ret = WIFI_ERROR_UNKNOWN;
1059 goto done;
1060 break;
1061 }
1062 wifiConfigCommand->create_generic(NL80211_CMD_SET_INTERFACE);
1063 wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
1064 wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type);
1065
1066 /* Send the NL msg. */
1067 wifiConfigCommand->waitForRsp(false);
1068 ret = wifiConfigCommand->requestEvent();
1069 if (ret != WIFI_SUCCESS) {
1070 ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
1071 }
1072
1073 done:
1074 delete wifiConfigCommand;
1075 return ret;
1076 }
1077
wifi_virtual_interface_create(wifi_handle handle,const char * ifname,wifi_interface_type iface_type)1078 wifi_error wifi_virtual_interface_create(wifi_handle handle,
1079 const char* ifname,
1080 wifi_interface_type iface_type)
1081 {
1082 wifi_error ret;
1083 WiFiConfigCommand *wifiConfigCommand;
1084 hal_info *info = getHalInfo(handle);
1085 if (!info || info->num_interfaces < 1) {
1086 ALOGE("%s: Error wifi_handle NULL or base wlan interface not present", __FUNCTION__);
1087 return WIFI_ERROR_UNKNOWN;
1088 }
1089
1090 // Already exists and set interface mode only
1091 if (if_nametoindex(ifname) != 0) {
1092 return wifi_set_interface_mode(handle, ifname, iface_type);
1093 }
1094
1095 ALOGD("%s: ifname=%s create", __FUNCTION__, ifname);
1096
1097 wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
1098 if (wifiConfigCommand == NULL) {
1099 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
1100 return WIFI_ERROR_UNKNOWN;
1101 }
1102
1103 nl80211_iftype type;
1104 switch(iface_type) {
1105 case WIFI_INTERFACE_TYPE_STA: /* IfaceType:STA */
1106 type = NL80211_IFTYPE_STATION;
1107 break;
1108 case WIFI_INTERFACE_TYPE_AP: /* IfaceType:AP */
1109 type = NL80211_IFTYPE_AP;
1110 break;
1111 case WIFI_INTERFACE_TYPE_P2P: /* IfaceType:P2P */
1112 type = NL80211_IFTYPE_P2P_DEVICE;
1113 break;
1114 case WIFI_INTERFACE_TYPE_NAN: /* IfaceType:NAN */
1115 type = NL80211_IFTYPE_NAN;
1116 break;
1117 default:
1118 ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type);
1119 ret = WIFI_ERROR_UNKNOWN;
1120 goto done;
1121 break;
1122 }
1123 wifiConfigCommand->create_generic(NL80211_CMD_NEW_INTERFACE);
1124 wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,info->interfaces[0]->id);
1125 wifiConfigCommand->put_string(NL80211_ATTR_IFNAME, ifname);
1126 wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type);
1127 /* Send the NL msg. */
1128 wifiConfigCommand->waitForRsp(false);
1129 ret = wifiConfigCommand->requestEvent();
1130 if (ret != WIFI_SUCCESS) {
1131 ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
1132 }
1133 // Update dynamic interface list
1134 added_ifaces.push_back(std::string(ifname));
1135 if (iface_type == WIFI_INTERFACE_TYPE_STA) {
1136 int sock = socket(AF_INET, SOCK_DGRAM, 0);
1137 if(sock < 0) {
1138 ret = WIFI_ERROR_UNKNOWN;
1139 ALOGE("%s :socket error, Failed to bring up iface \n", __func__);
1140 goto done;
1141 }
1142 struct ifreq ifr;
1143 memset(&ifr, 0, sizeof(ifr));
1144 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1145 if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
1146 ret = WIFI_ERROR_UNKNOWN;
1147 ALOGE("%s :Could not read interface %s flags \n", __func__, ifname);
1148 goto done;
1149 }
1150 ifr.ifr_flags |= IFF_UP;
1151 if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
1152 ret = WIFI_ERROR_UNKNOWN;
1153 ALOGE("%s :Could not bring iface %s up \n", __func__, ifname);
1154 }
1155 }
1156
1157 done:
1158 delete wifiConfigCommand;
1159 return ret;
1160 }
1161
wifi_virtual_interface_delete(wifi_handle handle,const char * ifname)1162 wifi_error wifi_virtual_interface_delete(wifi_handle handle,
1163 const char* ifname)
1164 {
1165 wifi_error ret;
1166 WiFiConfigCommand *wifiConfigCommand;
1167 if (!handle) {
1168 ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
1169 return WIFI_ERROR_UNKNOWN;
1170 }
1171
1172 ALOGD("%s: ifname=%s delete", __FUNCTION__, ifname);
1173 if (if_nametoindex(ifname) && !is_dynamic_interface(ifname)) {
1174 // Do not remove interface if it was not added dynamically.
1175 return WIFI_SUCCESS;
1176 }
1177 wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
1178 if (wifiConfigCommand == NULL) {
1179 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
1180 return WIFI_ERROR_UNKNOWN;
1181 }
1182 wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
1183 wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
1184 /* Send the NL msg. */
1185 wifiConfigCommand->waitForRsp(false);
1186 ret = wifiConfigCommand->requestEvent();
1187 if (ret != WIFI_SUCCESS) {
1188 ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
1189 }
1190 // Update dynamic interface list
1191 added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)),
1192 added_ifaces.end());
1193
1194 delete wifiConfigCommand;
1195 return ret;
1196 }
1197
1198 /**
1199 * Set latency level
1200 */
wifi_set_latency_mode(wifi_interface_handle iface,wifi_latency_mode mode)1201 wifi_error wifi_set_latency_mode(wifi_interface_handle iface,
1202 wifi_latency_mode mode)
1203 {
1204 int requestId, ret = 0;
1205 u16 level;
1206 WiFiConfigCommand *wifiConfigCommand;
1207 struct nlattr *nlData;
1208 interface_info *ifaceInfo = getIfaceInfo(iface);
1209 wifi_handle wifiHandle = getWifiHandle(iface);
1210 hal_info *info = getHalInfo(wifiHandle);
1211
1212 ALOGD("%s: %d", __FUNCTION__, mode);
1213
1214 if (!(info->supported_feature_set & WIFI_FEATURE_SET_LATENCY_MODE)) {
1215 ALOGE("%s: Latency Mode is not supported by driver", __FUNCTION__);
1216 return WIFI_ERROR_NOT_SUPPORTED;
1217 };
1218
1219 switch (mode) {
1220 case WIFI_LATENCY_MODE_NORMAL:
1221 level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL;
1222 break;
1223 case WIFI_LATENCY_MODE_LOW:
1224 level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW;
1225 break;
1226 default:
1227 ALOGI("%s: Unsupported latency mode=%d, resetting to NORMAL!", __FUNCTION__, mode);
1228 level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL;
1229 break;
1230 }
1231
1232 requestId = get_requestid();
1233
1234 wifiConfigCommand = new WiFiConfigCommand(
1235 wifiHandle,
1236 requestId,
1237 OUI_QCA,
1238 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
1239
1240 if (wifiConfigCommand == NULL) {
1241 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
1242 return WIFI_ERROR_UNKNOWN;
1243 }
1244
1245 /* Create the NL message. */
1246 ret = wifiConfigCommand->create();
1247 if (ret < 0) {
1248 ALOGE("%s: failed to create NL msg. Error:%d",
1249 __FUNCTION__, ret);
1250 goto cleanup;
1251 }
1252
1253 /* Set the interface Id of the message. */
1254 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
1255 if (ret < 0) {
1256 ALOGE("%s: failed to set iface id. Error:%d",
1257 __FUNCTION__, ret);
1258 goto cleanup;
1259 }
1260
1261 /* Add the vendor specific attributes for the NL command. */
1262 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1263 if (!nlData) {
1264 ret = WIFI_ERROR_UNKNOWN;
1265 ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
1266 __FUNCTION__, ret);
1267 goto cleanup;
1268 }
1269
1270 if (wifiConfigCommand->put_u16(
1271 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL, level)) {
1272 ret = WIFI_ERROR_UNKNOWN;
1273 ALOGE("%s: failed to put vendor data. Error:%d",
1274 __FUNCTION__, ret);
1275 goto cleanup;
1276 }
1277 wifiConfigCommand->attr_end(nlData);
1278
1279 /* Send the NL msg. */
1280 wifiConfigCommand->waitForRsp(false);
1281 ret = wifiConfigCommand->requestEvent();
1282 if (ret != 0) {
1283 ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
1284 goto cleanup;
1285 }
1286
1287 cleanup:
1288 delete wifiConfigCommand;
1289 return (wifi_error)ret;
1290 }
1291
1292 /**
1293 * Set STA + STA primary iface connection
1294 */
wifi_multi_sta_set_primary_connection(wifi_handle handle,wifi_interface_handle iface)1295 wifi_error wifi_multi_sta_set_primary_connection(wifi_handle handle,
1296 wifi_interface_handle iface)
1297 {
1298 int requestId, ret = 0;
1299 WiFiConfigCommand *wifiConfigCommand;
1300 if (!handle) {
1301 ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
1302 return WIFI_ERROR_UNKNOWN;
1303 }
1304 struct nlattr *nlData;
1305 interface_info *ifaceInfo = getIfaceInfo(iface);
1306
1307 requestId = get_requestid();
1308
1309 wifiConfigCommand = new WiFiConfigCommand(
1310 handle,
1311 requestId,
1312 OUI_QCA,
1313 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
1314
1315 if (wifiConfigCommand == NULL) {
1316 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
1317 return WIFI_ERROR_UNKNOWN;
1318 }
1319
1320 /* Create the NL message. */
1321 ret = wifiConfigCommand->create();
1322 if (ret < 0) {
1323 ALOGE("%s: failed to create NL msg. Error:%d",
1324 __FUNCTION__, ret);
1325 goto cleanup;
1326 }
1327
1328 /* Set the interface Id of the message. */
1329 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
1330 if (ret < 0) {
1331 ALOGE("%s: failed to set iface id. Error:%d",
1332 __FUNCTION__, ret);
1333 goto cleanup;
1334 }
1335
1336 /* Add the vendor specific attributes for the NL command. */
1337 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1338 if (!nlData) {
1339 ret = WIFI_ERROR_UNKNOWN;
1340 ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
1341 __FUNCTION__, ret);
1342 goto cleanup;
1343 }
1344
1345 if (wifiConfigCommand->put_u8(
1346 QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY, 1)) {
1347 ret = WIFI_ERROR_UNKNOWN;
1348 ALOGE("%s: failed to put vendor data. Error:%d",
1349 __FUNCTION__, ret);
1350 goto cleanup;
1351 }
1352 wifiConfigCommand->attr_end(nlData);
1353
1354 /* Send the NL msg. */
1355 wifiConfigCommand->waitForRsp(false);
1356 ret = wifiConfigCommand->requestEvent();
1357 if (ret != 0) {
1358 ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
1359 goto cleanup;
1360 }
1361
1362 cleanup:
1363 delete wifiConfigCommand;
1364 return (wifi_error)ret;
1365 }
1366
1367 /**
1368 * Set STA + STA use case
1369 */
wifi_multi_sta_set_use_case(wifi_handle handle,wifi_multi_sta_use_case case_info)1370 wifi_error wifi_multi_sta_set_use_case(wifi_handle handle,
1371 wifi_multi_sta_use_case case_info)
1372 {
1373 int requestId, ret = 0;
1374 u8 use_case;
1375 WiFiConfigCommand *wifiConfigCommand;
1376 if (!handle) {
1377 ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
1378 return WIFI_ERROR_UNKNOWN;
1379 }
1380 struct nlattr *nlData;
1381 hal_info *info = getHalInfo(handle);
1382 if (!info || info->num_interfaces < 1) {
1383 ALOGE("%s: Error wifi_handle NULL or base wlan interface not present", __FUNCTION__);
1384 return WIFI_ERROR_UNKNOWN;
1385 }
1386
1387 ALOGD("%s: %d", __FUNCTION__, case_info);
1388
1389 switch (case_info) {
1390 case WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY:
1391 use_case = QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY;
1392 break;
1393 case WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED:
1394 use_case = QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED;
1395 break;
1396 default:
1397 ALOGE("%s: Unknown use case %d", __FUNCTION__, case_info);
1398 ret = WIFI_ERROR_UNKNOWN;
1399 goto cleanup;;
1400 }
1401
1402 requestId = get_requestid();
1403
1404 wifiConfigCommand = new WiFiConfigCommand(
1405 handle,
1406 requestId,
1407 OUI_QCA,
1408 QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY);
1409
1410 if (wifiConfigCommand == NULL) {
1411 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
1412 return WIFI_ERROR_UNKNOWN;
1413 }
1414
1415 /* Create the NL message. */
1416 ret = wifiConfigCommand->create();
1417 if (ret < 0) {
1418 ALOGE("%s: failed to create NL msg. Error:%d",
1419 __FUNCTION__, ret);
1420 goto cleanup;
1421 }
1422
1423 /* Set the interface Id of the message. */
1424 if (wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
1425 info->interfaces[0]->id)) {
1426 ret = WIFI_ERROR_UNKNOWN;
1427 ALOGE("%s: Failed to put iface id", __FUNCTION__);
1428 goto cleanup;
1429 }
1430
1431 /* Add the vendor specific attributes for the NL command. */
1432 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1433 if (!nlData) {
1434 ret = WIFI_ERROR_UNKNOWN;
1435 ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
1436 __FUNCTION__, ret);
1437 goto cleanup;
1438 }
1439
1440 if (wifiConfigCommand->put_u8(
1441 QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG, use_case)) {
1442 ret = WIFI_ERROR_UNKNOWN;
1443 ALOGE("%s: failed to put use_case. Error:%d",
1444 __FUNCTION__, ret);
1445 goto cleanup;
1446 }
1447 wifiConfigCommand->attr_end(nlData);
1448
1449 /* Send the NL msg. */
1450 wifiConfigCommand->waitForRsp(false);
1451 ret = wifiConfigCommand->requestEvent();
1452 if (ret != 0) {
1453 ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
1454 goto cleanup;
1455 }
1456
1457 cleanup:
1458 delete wifiConfigCommand;
1459 return (wifi_error)ret;
1460 }
1461
1462 /**
1463 * Invoked to set voip optimization mode for the provided STA iface
1464 */
wifi_set_voip_mode(wifi_interface_handle iface,wifi_voip_mode mode)1465 wifi_error wifi_set_voip_mode(wifi_interface_handle iface, wifi_voip_mode mode)
1466 {
1467 int requestId, ret = 0;
1468 WiFiConfigCommand *wifiConfigCommand;
1469
1470 struct nlattr *nlData;
1471 interface_info *ifaceInfo = getIfaceInfo(iface);
1472
1473 wifi_handle wifiHandle = getWifiHandle(iface);
1474 if (!wifiHandle) {
1475 ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
1476 return WIFI_ERROR_UNKNOWN;
1477 }
1478
1479 requestId = get_requestid();
1480 ALOGV("%s: voip mode=%d", __FUNCTION__, mode);
1481 wifiConfigCommand = new WiFiConfigCommand(
1482 wifiHandle,
1483 requestId,
1484 OUI_QCA,
1485 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
1486
1487 if (wifiConfigCommand == NULL) {
1488 ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
1489 return WIFI_ERROR_UNKNOWN;
1490 }
1491
1492 /* Create the NL message. */
1493 ret = wifiConfigCommand->create();
1494 if (ret < 0) {
1495 ALOGE("%s: failed to create NL msg. Error:%d",
1496 __FUNCTION__, ret);
1497 goto cleanup;
1498 }
1499
1500 /* Set the interface Id of the message. */
1501 ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
1502 if (ret < 0) {
1503 ALOGE("%s: failed to set iface id. Error:%d",
1504 __FUNCTION__, ret);
1505 goto cleanup;
1506 }
1507
1508 /* Add the vendor specific attributes for the NL command. */
1509 nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1510 if (!nlData) {
1511 ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
1512 __FUNCTION__, ret);
1513 goto cleanup;
1514 }
1515
1516 if (wifiConfigCommand->put_u8(
1517 QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE, (u8)mode)) {
1518 ALOGE("%s: failed to put vendor data. Error:%d",
1519 __FUNCTION__, ret);
1520 goto cleanup;
1521 }
1522 wifiConfigCommand->attr_end(nlData);
1523
1524 /* Send the NL msg. */
1525 wifiConfigCommand->waitForRsp(false);
1526 ret = wifiConfigCommand->requestEvent();
1527 if (ret != 0) {
1528 ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
1529 goto cleanup;
1530 }
1531
1532 cleanup:
1533 delete wifiConfigCommand;
1534 return (wifi_error)ret;
1535 }
1536