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