1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Changes from Qualcomm Innovation Center are provided under the following license:
17  *
18  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted (subject to the limitations in the
22  * disclaimer below) provided that the following conditions are met:
23  *
24  *   * Redistributions of source code must retain the above copyright
25  *     notice, this list of conditions and the following disclaimer.
26  *
27  *   * Redistributions in binary form must reproduce the above
28  *     copyright notice, this list of conditions and the following
29  *     disclaimer in the documentation and/or other materials provided
30  *     with the distribution.
31  *
32  *   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
33  *     contributors may be used to endorse or promote products derived
34  *     from this software without specific prior written permission.
35  *
36  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
37  * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
38  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
39  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
42  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
46  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
47  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
48  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49  */
50 
51 #include <stdint.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <sys/socket.h>
55 #include <netlink/genl/genl.h>
56 #include <netlink/genl/family.h>
57 #include <netlink/genl/ctrl.h>
58 #include <linux/rtnetlink.h>
59 #include <netpacket/packet.h>
60 #include <linux/filter.h>
61 #include <linux/errqueue.h>
62 #include <linux-private/linux/fib_rules.h>
63 #include <linux/pkt_sched.h>
64 #include <netlink/object-api.h>
65 #include <netlink/netlink.h>
66 #include <netlink/socket.h>
67 #if __has_include(<netlink-private/types.h>)
68 #include <netlink-private/object-api.h>
69 #include <netlink-private/types.h>
70 #else
71 #include <nl-priv-dynamic-core/nl-core.h>
72 #endif
73 
74 #include "nl80211_copy.h"
75 
76 #include <dirent.h>
77 #include <net/if.h>
78 #include <netinet/in.h>
79 #include <cld80211_lib.h>
80 
81 #include <sys/types.h>
82 #include "list.h"
83 #include <unistd.h>
84 
85 #include "sync.h"
86 
87 #define LOG_TAG  "WifiHAL"
88 
89 #include <hardware_legacy/wifi_hal.h>
90 #include "wifi_hal_ctrl.h"
91 #include "common.h"
92 #include "cpp_bindings.h"
93 #include "ifaceeventhandler.h"
94 #include "wifiloggercmd.h"
95 #include "tcp_params_update.h"
96 
97 /*
98  BUGBUG: normally, libnl allocates ports for all connections it makes; but
99  being a static library, it doesn't really know how many other netlink
100  connections are made by the same process, if connections come from different
101  shared libraries. These port assignments exist to solve that
102  problem - temporarily. We need to fix libnl to try and allocate ports across
103  the entire process.
104  */
105 
106 #define WIFI_HAL_CMD_SOCK_PORT       644
107 #define WIFI_HAL_EVENT_SOCK_PORT     645
108 
109 #define MAX_HW_VER_LENGTH 100
110 /*
111  * Defines for wifi_wait_for_driver_ready()
112  * Specify durations between polls and max wait time
113  */
114 #define POLL_DRIVER_DURATION_US (100000)
115 #define POLL_DRIVER_MAX_TIME_MS (10000)
116 
117 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
118 
119 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
120 
121 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach);
122 
123 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
124 
125 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock);
126 
127 static void internal_event_handler_app(wifi_handle handle, int events,
128                                        struct ctrl_sock *sock);
129 
130 static void internal_event_handler(wifi_handle handle, int events,
131                                    struct nl_sock *sock);
132 static int internal_valid_message_handler(nl_msg *msg, void *arg);
133 static int user_sock_message_handler(nl_msg *msg, void *arg);
134 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
135         const char *group);
136 static int wifi_add_membership(wifi_handle handle, const char *group);
137 static wifi_error wifi_init_interfaces(wifi_handle handle);
138 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
139                                          const u8 *program, u32 len);
140 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
141                                               u32 *version, u32 *max_len);
142 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
143                                    u32 src_offset, u8 *host_dst, u32 length);
144 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
145                                             u8 enable);
146 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
147                              WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
148 static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle handle);
149 
150 wifi_error
151     wifi_init_tcp_param_change_event_handler(wifi_interface_handle iface);
152 
153 wifi_error wifi_set_voip_mode(wifi_interface_handle iface, wifi_voip_mode mode);
154 
155 /* Initialize/Cleanup */
156 
wifi_get_iface_handle(wifi_handle handle,char * name)157 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
158 {
159     hal_info *info = (hal_info *)handle;
160     for (int i=0;i<info->num_interfaces;i++)
161     {
162         if (!strcmp(info->interfaces[i]->name, name))
163         {
164             return ((wifi_interface_handle )(info->interfaces)[i]);
165         }
166     }
167     return NULL;
168 }
169 
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)170 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
171 {
172     /* Release local port pool maintained by libnl and assign a own port
173      * identifier to the socket.
174      */
175     nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
176 }
177 
wifi_create_nl_socket(int port,int protocol)178 static nl_sock * wifi_create_nl_socket(int port, int protocol)
179 {
180     // ALOGI("Creating socket");
181     struct nl_sock *sock = nl_socket_alloc();
182     if (sock == NULL) {
183         ALOGE("Failed to create NL socket");
184         return NULL;
185     }
186 
187     wifi_socket_set_local_port(sock, port);
188 
189     if (nl_connect(sock, protocol)) {
190         ALOGE("Could not connect handle");
191         nl_socket_free(sock);
192         return NULL;
193     }
194 
195     return sock;
196 }
197 
wifi_create_ctrl_socket(hal_info * info)198 void wifi_create_ctrl_socket(hal_info *info)
199 {
200 #ifdef ANDROID
201    struct group *grp_wifi;
202    gid_t gid_wifi;
203    struct passwd *pwd_system;
204    uid_t uid_system;
205 #endif
206 
207     int flags;
208 
209     info->wifihal_ctrl_sock.s = socket(PF_UNIX, SOCK_DGRAM, 0);
210 
211     if (info->wifihal_ctrl_sock.s < 0) {
212         ALOGE("socket(PF_UNIX): %s", strerror(errno));
213         return;
214     }
215     memset(&info->wifihal_ctrl_sock.local, 0, sizeof(info->wifihal_ctrl_sock.local));
216 
217     info->wifihal_ctrl_sock.local.sun_family = AF_UNIX;
218 
219     snprintf(info->wifihal_ctrl_sock.local.sun_path,
220              sizeof(info->wifihal_ctrl_sock.local.sun_path), "%s", WIFI_HAL_CTRL_IFACE);
221 
222     if (bind(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
223              sizeof(info->wifihal_ctrl_sock.local)) < 0) {
224         ALOGD("ctrl_iface bind(PF_UNIX) failed: %s",
225                strerror(errno));
226         if (connect(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
227                     sizeof(info->wifihal_ctrl_sock.local)) < 0) {
228                 ALOGD("ctrl_iface exists, but does not"
229                       " allow connections - assuming it was left"
230                       "over from forced program termination");
231                 if (unlink(info->wifihal_ctrl_sock.local.sun_path) < 0) {
232                    ALOGE("Could not unlink existing ctrl_iface socket '%s': %s",
233                           info->wifihal_ctrl_sock.local.sun_path, strerror(errno));
234                    goto out;
235 
236                 }
237                 if (bind(info->wifihal_ctrl_sock.s ,
238                          (struct sockaddr *) &info->wifihal_ctrl_sock.local,
239                          sizeof(info->wifihal_ctrl_sock.local)) < 0) {
240                         ALOGE("wifihal-ctrl-iface-init: bind(PF_UNIX): %s",
241                                strerror(errno));
242                         goto out;
243                 }
244                 ALOGD("Successfully replaced leftover "
245                       "ctrl_iface socket '%s'", info->wifihal_ctrl_sock.local.sun_path);
246         } else {
247              ALOGI("ctrl_iface exists and seems to "
248                    "be in use - cannot override it");
249              ALOGI("Delete '%s' manually if it is "
250                    "not used anymore", info->wifihal_ctrl_sock.local.sun_path);
251              goto out;
252         }
253     }
254 
255     /*
256      * Make socket non-blocking so that we don't hang forever if
257      * target dies unexpectedly.
258      */
259 
260 #ifdef ANDROID
261     if (chmod(info->wifihal_ctrl_sock.local.sun_path, S_IRWXU | S_IRWXG) < 0)
262     {
263       ALOGE("Failed to give permissions: %s", strerror(errno));
264     }
265 
266     /* Set group even if we do not have privileges to change owner */
267     grp_wifi = getgrnam("wifi");
268     gid_wifi = grp_wifi ? grp_wifi->gr_gid : 0;
269     pwd_system = getpwnam("system");
270     uid_system = pwd_system ? pwd_system->pw_uid : 0;
271     if (!gid_wifi || !uid_system) {
272       ALOGE("Failed to get grp ids");
273       unlink(info->wifihal_ctrl_sock.local.sun_path);
274       goto out;
275     }
276     chown(info->wifihal_ctrl_sock.local.sun_path, -1, gid_wifi);
277     chown(info->wifihal_ctrl_sock.local.sun_path, uid_system, gid_wifi);
278 #endif
279 
280     flags = fcntl(info->wifihal_ctrl_sock.s, F_GETFL);
281     if (flags >= 0) {
282         flags |= O_NONBLOCK;
283         if (fcntl(info->wifihal_ctrl_sock.s, F_SETFL, flags) < 0) {
284             ALOGI("fcntl(ctrl, O_NONBLOCK): %s",
285                    strerror(errno));
286             /* Not fatal, continue on.*/
287         }
288     }
289   return;
290 
291 out:
292   close(info->wifihal_ctrl_sock.s);
293   info->wifihal_ctrl_sock.s = 0;
294   return;
295 }
296 
ack_handler(struct nl_msg * msg,void * arg)297 int ack_handler(struct nl_msg *msg, void *arg)
298 {
299     int *err = (int *)arg;
300     *err = 0;
301     return NL_STOP;
302 }
303 
finish_handler(struct nl_msg * msg,void * arg)304 int finish_handler(struct nl_msg *msg, void *arg)
305 {
306     int *ret = (int *)arg;
307     *ret = 0;
308     return NL_SKIP;
309 }
310 
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)311 int error_handler(struct sockaddr_nl *nla,
312                   struct nlmsgerr *err, void *arg)
313 {
314     int *ret = (int *)arg;
315     *ret = err->error;
316 
317     ALOGV("%s invoked with error: %d", __func__, err->error);
318     return NL_SKIP;
319 }
no_seq_check(struct nl_msg * msg,void * arg)320 static int no_seq_check(struct nl_msg *msg, void *arg)
321 {
322     return NL_OK;
323 }
324 
acquire_supported_features(wifi_interface_handle iface,feature_set * set)325 static wifi_error acquire_supported_features(wifi_interface_handle iface,
326         feature_set *set)
327 {
328     wifi_error ret;
329     interface_info *iinfo = getIfaceInfo(iface);
330     wifi_handle handle = getWifiHandle(iface);
331     *set = 0;
332 
333     WifihalGeneric supportedFeatures(handle, 0,
334             OUI_QCA,
335             QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
336 
337     /* create the message */
338     ret = supportedFeatures.create();
339     if (ret != WIFI_SUCCESS)
340         goto cleanup;
341 
342     ret = supportedFeatures.set_iface_id(iinfo->name);
343     if (ret != WIFI_SUCCESS)
344         goto cleanup;
345 
346     ret = supportedFeatures.requestResponse();
347     if (ret != WIFI_SUCCESS) {
348         ALOGE("%s: requestResponse Error:%d",__func__, ret);
349         goto cleanup;
350     }
351 
352     supportedFeatures.getResponseparams(set);
353 
354 cleanup:
355     return ret;
356 }
357 
acquire_driver_supported_features(wifi_interface_handle iface,features_info * driver_features)358 static wifi_error acquire_driver_supported_features(wifi_interface_handle iface,
359                                           features_info *driver_features)
360 {
361     wifi_error ret;
362     interface_info *iinfo = getIfaceInfo(iface);
363     wifi_handle handle = getWifiHandle(iface);
364 
365     WifihalGeneric driverFeatures(handle, 0,
366             OUI_QCA,
367             QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES);
368 
369     /* create the message */
370     ret = driverFeatures.create();
371     if (ret != WIFI_SUCCESS)
372         goto cleanup;
373 
374     ret = driverFeatures.set_iface_id(iinfo->name);
375     if (ret != WIFI_SUCCESS)
376         goto cleanup;
377 
378     ret = driverFeatures.requestResponse();
379     if (ret != WIFI_SUCCESS) {
380         ALOGE("%s: requestResponse Error:%d",__func__, ret);
381         goto cleanup;
382     }
383 
384     driverFeatures.getDriverFeatures(driver_features);
385 
386 cleanup:
387     return mapKernelErrortoWifiHalError(ret);
388 }
389 
wifi_get_capabilities(wifi_interface_handle handle)390 static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
391 {
392     wifi_error ret;
393     int requestId;
394     WifihalGeneric *wifihalGeneric;
395     wifi_handle wifiHandle = getWifiHandle(handle);
396     hal_info *info = getHalInfo(wifiHandle);
397 
398     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
399         ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
400         return WIFI_ERROR_NOT_SUPPORTED;
401     }
402 
403     /* No request id from caller, so generate one and pass it on to the driver.
404      * Generate it randomly.
405      */
406     requestId = get_requestid();
407 
408     wifihalGeneric = new WifihalGeneric(
409                             wifiHandle,
410                             requestId,
411                             OUI_QCA,
412                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
413     if (!wifihalGeneric) {
414         ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
415         return WIFI_ERROR_OUT_OF_MEMORY;
416     }
417 
418     ret = wifihalGeneric->wifiGetCapabilities(handle);
419 
420     delete wifihalGeneric;
421     return ret;
422 }
423 
wifi_get_sar_version(wifi_interface_handle handle)424 static wifi_error wifi_get_sar_version(wifi_interface_handle handle)
425 {
426     wifi_error ret;
427     wifi_handle wifiHandle = getWifiHandle(handle);
428 
429     WifihalGeneric *sarVersion = new WifihalGeneric(
430                             wifiHandle,
431                             0,
432                             OUI_QCA,
433                             QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY);
434     if (!sarVersion) {
435         ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
436         return WIFI_ERROR_OUT_OF_MEMORY;
437     }
438 
439 
440     ret = sarVersion->getSarVersion(handle);
441 
442     delete sarVersion;
443     return ret;
444 }
445 
get_firmware_bus_max_size_supported(wifi_interface_handle iface)446 static wifi_error get_firmware_bus_max_size_supported(
447                                                 wifi_interface_handle iface)
448 {
449     wifi_error ret;
450     interface_info *iinfo = getIfaceInfo(iface);
451     wifi_handle handle = getWifiHandle(iface);
452     hal_info *info = (hal_info *)handle;
453 
454     WifihalGeneric busSizeSupported(handle, 0,
455                                     OUI_QCA,
456                                     QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
457 
458     /* create the message */
459     ret = busSizeSupported.create();
460     if (ret != WIFI_SUCCESS)
461         goto cleanup;
462 
463     ret = busSizeSupported.set_iface_id(iinfo->name);
464     if (ret != WIFI_SUCCESS)
465         goto cleanup;
466 
467     ret = busSizeSupported.requestResponse();
468     if (ret != WIFI_SUCCESS) {
469         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
470         goto cleanup;
471     }
472     info->firmware_bus_max_size = busSizeSupported.getBusSize();
473 
474 cleanup:
475     return ret;
476 }
477 
wifi_init_user_sock(hal_info * info)478 static wifi_error wifi_init_user_sock(hal_info *info)
479 {
480     struct nl_sock *user_sock =
481         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
482     if (user_sock == NULL) {
483         ALOGE("Could not create diag sock");
484         return WIFI_ERROR_UNKNOWN;
485     }
486 
487     /* Set the socket buffer size */
488     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
489         ALOGE("Could not set size for user_sock: %s",
490                    strerror(errno));
491         /* continue anyway with the default (smaller) buffer */
492     }
493     else {
494         ALOGV("nl_socket_set_buffer_size successful for user_sock");
495     }
496 
497     struct nl_cb *cb = nl_socket_get_cb(user_sock);
498     if (cb == NULL) {
499         ALOGE("Could not get cb");
500         return WIFI_ERROR_UNKNOWN;
501     }
502 
503     info->user_sock_arg = 1;
504     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
505     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
506     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
507     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
508 
509     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
510     nl_cb_put(cb);
511 
512     int ret = nl_socket_add_membership(user_sock, 1);
513     if (ret < 0) {
514         ALOGE("Could not add membership");
515         return WIFI_ERROR_UNKNOWN;
516     }
517 
518     info->user_sock = user_sock;
519     ALOGV("Initiialized diag sock successfully");
520     return WIFI_SUCCESS;
521 }
522 
wifi_init_cld80211_sock_cb(hal_info * info)523 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
524 {
525     struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
526     if (cb == NULL) {
527         ALOGE("Could not get cb");
528         return WIFI_ERROR_UNKNOWN;
529     }
530 
531     info->user_sock_arg = 1;
532     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
533     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
534     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
535     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
536 
537     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
538     nl_cb_put(cb);
539 
540     return WIFI_SUCCESS;
541 }
542 
get_frequency_from_channel(uint32_t channel,wlan_mac_band band)543 static uint32_t get_frequency_from_channel(uint32_t channel, wlan_mac_band band)
544 {
545   uint32_t freq = 0;
546 
547   switch (band)
548   {
549     case WLAN_MAC_2_4_BAND:
550       if (!(channel >= 1 && channel <= 14))
551         goto failure;
552       //special handling for channel 14 by filling freq here
553       if (channel == 14)
554         freq = 2484;
555       else
556         freq = 2407 + (channel * 5);
557       break;
558     case WLAN_MAC_5_0_BAND:
559       if (!((channel >= 34 && channel < 65) ||
560           (channel > 99 && channel <= 196)))
561         goto failure;
562       freq = 5000 + (channel * 5);
563       break;
564     case WLAN_MAC_6_0_BAND:
565       if (!(channel >= 1 && channel <= 233))
566         goto failure;
567       freq = 5950 + (channel * 5);
568       break;
569     default:
570       break;
571   }
572 
573 failure:
574   return freq;
575 }
576 
get_nl_ifmask_from_coex_restriction_mask(u32 in_mask)577 static u32 get_nl_ifmask_from_coex_restriction_mask(u32 in_mask)
578 {
579     u32 op_mask = 0;
580 
581     if (!in_mask)
582        return op_mask;
583     if (in_mask & SOFTAP)
584          op_mask |= BIT(NL80211_IFTYPE_AP);
585     if (in_mask & WIFI_DIRECT)
586          op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
587     if (in_mask & WIFI_AWARE)
588          op_mask |= BIT(NL80211_IFTYPE_NAN);
589 
590     return op_mask;
591 }
592 
wifi_set_coex_unsafe_channels(wifi_handle handle,u32 num_channels,wifi_coex_unsafe_channel * unsafeChannels,u32 restrictions)593 wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle, u32 num_channels,
594                                          wifi_coex_unsafe_channel *unsafeChannels,
595                                          u32 restrictions)
596 {
597     wifi_error ret = WIFI_ERROR_UNKNOWN;
598     WifihalGeneric *cmd = NULL;
599     struct nlattr *nl_data = NULL;
600     struct nlattr *nl_attr_unsafe_chan = NULL;
601     struct nlattr *unsafe_channels_attr = NULL;
602     hal_info *info = NULL;
603     int freq_cnt = 0;
604     u32 *freq = (u32 *) malloc(sizeof(u32) * num_channels);
605     u32 *power_cap_dbm = (u32 *) malloc(sizeof(u32) * num_channels);
606 
607     if (!freq || !power_cap_dbm) {
608         ALOGE("%s: Failed to allocate memory", __FUNCTION__);
609         ret = WIFI_ERROR_OUT_OF_MEMORY;
610         goto cleanup;
611     }
612 
613     if (!handle) {
614          ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
615          goto cleanup;
616     }
617 
618     info = getHalInfo(handle);
619     if (!info || info->num_interfaces < 1) {
620          ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
621                __FUNCTION__);
622          goto cleanup;
623     }
624 
625     cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
626                              QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT);
627     if (cmd == NULL) {
628          ALOGE("%s: Error, created command NULL", __FUNCTION__);
629          ret = WIFI_ERROR_OUT_OF_MEMORY;
630          goto cleanup;
631     }
632 
633     /* Create the NL message. */
634     ret = cmd->create();
635     if (ret < 0) {
636          ALOGE("%s: failed to create NL msg due to error: (%d)",
637                __FUNCTION__, ret);
638          goto cleanup;
639     }
640 
641     /* Add the vendor specific attributes for the NL command. */
642     nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
643     if (!nl_data) {
644          ALOGE("%s: failed attr_start for NL80211_ATTR_VENDOR_DATA",
645                __FUNCTION__);
646          ret = WIFI_ERROR_OUT_OF_MEMORY;
647          goto cleanup;
648     }
649 
650     nl_attr_unsafe_chan = cmd->attr_start(
651         QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE);
652     if (!nl_attr_unsafe_chan) {
653          ALOGE("%s: failed attr_start for"
654                " QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE", __FUNCTION__);
655          ret = WIFI_ERROR_OUT_OF_MEMORY;
656          goto cleanup;
657     }
658     ALOGD("%s: num_channels:%d, restrictions:%x", __FUNCTION__, num_channels,
659           restrictions);
660     for (int i = 0; i < num_channels; i++)
661     {
662         u32 frequency = get_frequency_from_channel(unsafeChannels[i].channel,
663                 unsafeChannels[i].band);
664         if (frequency != 0)
665         {
666           freq[freq_cnt] = frequency;
667           power_cap_dbm[freq_cnt] = unsafeChannels[i].power_cap_dbm;
668           freq_cnt++;
669           ALOGV("%s: channel:%d, freq:%d, power_cap_dbm:%d, band:%d",
670                __FUNCTION__, unsafeChannels[i].channel, frequency,
671                unsafeChannels[i].power_cap_dbm, unsafeChannels[i].band);
672         }
673         else {
674             ALOGV("%s: Invalid channel found, channel:%d, power_cap_dbm:%d, band:%d",
675                __FUNCTION__, unsafeChannels[i].channel,
676                unsafeChannels[i].power_cap_dbm, unsafeChannels[i].band);
677         }
678     }
679     if (num_channels == 0) {
680          unsafe_channels_attr = cmd->attr_start(0);
681          if (!unsafe_channels_attr) {
682               ALOGE("%s: failed attr_start for unsafe_channels_attr when"
683                     " trying to clear usafe channels clear", __FUNCTION__);
684               ret = WIFI_ERROR_OUT_OF_MEMORY;
685               goto cleanup;
686          }
687          ret = cmd->put_u32(
688                QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, 0);
689          if (ret != WIFI_SUCCESS) {
690               ALOGE("%s: Failed to put frequency start, ret:%d",
691                     __FUNCTION__, ret);
692               goto cleanup;
693          }
694          ret = cmd->put_u32(
695                QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, 0);
696          if (ret != WIFI_SUCCESS) {
697               ALOGE("%s: Failed to put frequency end, ret:%d",
698                     __FUNCTION__, ret);
699               goto cleanup;
700          }
701          cmd->attr_end(unsafe_channels_attr);
702     }
703     else {
704         if (!unsafeChannels) {
705             ALOGE("%s: unsafe channels buffer should not be NULL when"
706                   " there are unsafe channels", __FUNCTION__);
707             ret = WIFI_ERROR_INVALID_ARGS;
708             goto cleanup;
709         }
710 
711         if(freq_cnt == 0)
712         {
713             ALOGE("%s: No valid frequency, ignore channel list", __FUNCTION__);
714             ret = WIFI_ERROR_INVALID_ARGS;
715             goto cleanup;
716         }
717         for (int i = 0; i < freq_cnt; i++) {
718             unsafe_channels_attr = cmd->attr_start(i);
719             if (!unsafe_channels_attr) {
720                 ALOGE("%s: failed attr_start for unsafe_channels_attr of"
721                     " index:%d", __FUNCTION__, i);
722                 ret = WIFI_ERROR_OUT_OF_MEMORY;
723                 goto cleanup;
724             }
725 
726             ret = cmd->put_u32(
727                   QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, freq[i]);
728             if (ret != WIFI_SUCCESS) {
729                 ALOGE("%s: Failed to put frequency start, ret:%d",
730                       __FUNCTION__, ret);
731                 goto cleanup;
732             }
733             ret = cmd->put_u32(
734                 QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, freq[i]);
735             if (ret != WIFI_SUCCESS) {
736                 ALOGE("%s: Failed to put frequency end, ret:%d",
737                     __FUNCTION__, ret);
738                 goto cleanup;
739             }
740             /**
741              * WIFI_COEX_NO_POWER_CAP (0x7FFFFFF) is specific to android
742              * framework, this value denotes that framework/wifihal is not
743              * providing any power cap and allow driver/firmware to operate on
744              * current power cap dbm. As driver is supposed to work on with
745              * LA/LE etc, we are skipping to send 0x7FFFFFF down to driver,
746              * hence driver will be operating as per current power cap calculated
747              * based on regulatory or other constraints.
748              */
749             if (power_cap_dbm[i] != WIFI_COEX_NO_POWER_CAP) {
750                 ret = cmd->put_s32(
751                       QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM,
752                       power_cap_dbm[i]);
753                 if (ret != WIFI_SUCCESS) {
754                     ALOGE("%s: Failed to put power_cap_dbm, ret:%d",
755                           __FUNCTION__, ret);
756                     goto cleanup;
757                 }
758             }
759             ALOGD("%s: freq:%d, power_cap_dbm:%d",
760                    __FUNCTION__, freq[i], power_cap_dbm[i]);
761             cmd->attr_end(unsafe_channels_attr);
762         }
763     }
764     cmd->attr_end(nl_attr_unsafe_chan);
765     if (num_channels > 0) {
766         ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK,
767                        get_nl_ifmask_from_coex_restriction_mask(restrictions));
768         if (ret != WIFI_SUCCESS) {
769             ALOGE("%s: Failed to put restrictions mask, ret:%d",
770                   __FUNCTION__, ret);
771             goto cleanup;
772         }
773     }
774     cmd->attr_end(nl_data);
775 
776     /* Send the msg and wait for a response. */
777     ret = cmd->requestResponse();
778     if (ret != WIFI_SUCCESS) {
779          ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
780          goto cleanup;
781     }
782 
783 cleanup:
784     if (cmd)
785         delete cmd;
786     if (freq)
787         free (freq);
788     if (power_cap_dbm)
789         free (power_cap_dbm);
790     return ret;
791 }
792 
wifi_set_dtim_config(wifi_interface_handle handle,u32 multiplier)793 wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier)
794 {
795     wifi_error ret = WIFI_ERROR_INVALID_ARGS;
796     WifihalGeneric *cmd = NULL;
797     struct nlattr *nlData = NULL;
798     interface_info *ifaceInfo = NULL;
799     wifi_handle wifiHandle = NULL;
800 
801     if (!handle) {
802          ALOGE("%s: Error, wifi_interface_handle NULL", __FUNCTION__);
803          goto cleanup;
804     }
805     ALOGD("%s: multiplier:%d", __FUNCTION__, multiplier);
806     wifiHandle = getWifiHandle(handle);
807     cmd = new WifihalGeneric(wifiHandle, get_requestid(), OUI_QCA,
808                              QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
809     if (cmd == NULL) {
810         ALOGE("%s: Error WifihalGeneric NULL", __FUNCTION__);
811         ret = WIFI_ERROR_OUT_OF_MEMORY;
812         goto cleanup;
813     }
814 
815     /* Create the NL message. */
816     ret = cmd->create();
817     if (ret != WIFI_SUCCESS) {
818         ALOGE("%s: failed to create NL msg. Error:%d", __FUNCTION__, ret);
819         goto cleanup;
820     }
821     ifaceInfo = getIfaceInfo(handle);
822     if (!ifaceInfo) {
823         ALOGE("%s: getIfaceInfo is NULL", __FUNCTION__);
824         ret = WIFI_ERROR_OUT_OF_MEMORY;
825         goto cleanup;
826     }
827 
828     /* Set the interface Id of the message. */
829     ret = cmd->set_iface_id(ifaceInfo->name);
830     if (ret != WIFI_SUCCESS) {
831         ALOGE("%s: failed to set iface id. Error:%d", __FUNCTION__, ret);
832         goto cleanup;
833     }
834 
835     /* Add the vendor specific attributes for the NL command. */
836     nlData = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
837     if (!nlData) {
838         ALOGE("%s: failed attr_start for VENDOR_DATA", __FUNCTION__);
839         ret = WIFI_ERROR_OUT_OF_MEMORY;
840         goto cleanup;
841     }
842 
843     ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM, multiplier);
844     if (ret != WIFI_SUCCESS) {
845         ALOGE("%s: failed to put vendor data. Error:%d", __FUNCTION__, ret);
846         goto cleanup;
847     }
848     cmd->attr_end(nlData);
849 
850     /* Send the NL msg. */
851     ret = cmd->requestResponse();
852     if (ret != WIFI_SUCCESS) {
853         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
854         goto cleanup;
855     }
856 
857 cleanup:
858     if (cmd)
859         delete cmd;
860     return ret;
861 }
862 
get_nl_band_mask(u32 in_mask)863 static u32 get_nl_band_mask(u32 in_mask)
864 {
865     u32 op_mask = 0;
866 
867     if (in_mask & WLAN_MAC_2_4_BAND)
868          op_mask |= BIT(NL80211_BAND_2GHZ);
869     if (in_mask & WLAN_MAC_5_0_BAND)
870          op_mask |= BIT(NL80211_BAND_5GHZ);
871     if (in_mask & WLAN_MAC_6_0_BAND)
872          op_mask |= BIT(NL80211_BAND_6GHZ);
873     if (in_mask & WLAN_MAC_60_0_BAND)
874          op_mask |= BIT(NL80211_BAND_60GHZ);
875 
876     return op_mask;
877 }
878 
get_nl_iftype_mode_masks(u32 in_mask)879 static u32 get_nl_iftype_mode_masks(u32 in_mask)
880 {
881     u32 op_mask = 0;
882 
883     if (in_mask & BIT(WIFI_INTERFACE_STA) ||
884         in_mask & BIT(WIFI_INTERFACE_TDLS))
885          op_mask |= BIT(NL80211_IFTYPE_STATION);
886     if (in_mask & BIT(WIFI_INTERFACE_SOFTAP))
887          op_mask |= BIT(NL80211_IFTYPE_AP);
888     if (in_mask & BIT(WIFI_INTERFACE_P2P_CLIENT))
889          op_mask |= BIT(NL80211_IFTYPE_P2P_CLIENT);
890     if (in_mask & BIT(WIFI_INTERFACE_P2P_GO))
891          op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
892     if (in_mask & BIT(WIFI_INTERFACE_NAN))
893          op_mask |= BIT(NL80211_IFTYPE_NAN);
894 
895     return op_mask;
896 }
897 
get_vendor_filter_mask(u32 in_mask)898 static u32 get_vendor_filter_mask(u32 in_mask)
899 {
900     u32 op_mask = 0;
901 
902     if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE)
903          op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX);
904     if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY)
905          op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY);
906 
907     return op_mask;
908 }
909 
wifi_get_usable_channels(wifi_handle handle,u32 band_mask,u32 iface_mode_mask,u32 filter_mask,u32 max_size,u32 * size,wifi_usable_channel * channels)910 wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask,
911                                     u32 iface_mode_mask, u32 filter_mask,
912                                     u32 max_size, u32* size,
913                                     wifi_usable_channel* channels)
914 {
915     wifi_error ret = WIFI_ERROR_UNKNOWN;
916     WifihalGeneric *cmd = NULL;
917     struct nlattr *nl_data = NULL;
918     hal_info *info = NULL;
919     u32 band = 0, iface_mask = 0, filter = 0;
920 
921     if (!handle) {
922          ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
923          goto cleanup;
924     }
925 
926     info = getHalInfo(handle);
927     if (!info || info->num_interfaces < 1) {
928          ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
929                __FUNCTION__);
930          goto cleanup;
931     }
932 
933     if (!max_size) {
934          ALOGE("%s: max channel size is zero", __FUNCTION__);
935          ret = WIFI_ERROR_INVALID_ARGS;
936          goto cleanup;
937     }
938 
939     if (!channels) {
940          ALOGE("%s: user input channel buffer NULL", __FUNCTION__);
941          ret = WIFI_ERROR_INVALID_ARGS;
942          goto cleanup;
943     }
944 
945     cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
946                              QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS);
947     if (cmd == NULL) {
948          ALOGE("%s: Error, created command NULL", __FUNCTION__);
949          ret = WIFI_ERROR_OUT_OF_MEMORY;
950          goto cleanup;
951     }
952 
953     /* Create the NL message. */
954     ret = cmd->create();
955     if (ret < 0) {
956          ALOGE("%s: failed to create NL msg due to error: (%d)",
957                __FUNCTION__, ret);
958          goto cleanup;
959     }
960 
961     /* Add the vendor specific attributes for the NL command. */
962     nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
963     if (!nl_data) {
964          ALOGE("%s: failed attr_start for VENDOR_DATA due to error",
965                __FUNCTION__);
966          ret = WIFI_ERROR_OUT_OF_MEMORY;
967          goto cleanup;
968     }
969 
970     band = get_nl_band_mask(band_mask);
971     ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK,
972                        band);
973     if (ret != WIFI_SUCCESS) {
974          ALOGE("%s: failed to put vendor data due to error:%d",
975                __FUNCTION__, ret);
976          goto cleanup;
977     }
978 
979     iface_mask = get_nl_iftype_mode_masks(iface_mode_mask);
980     ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK,
981                        iface_mask);
982     if (ret != WIFI_SUCCESS) {
983          ALOGE("%s: failed to put vendor data due to error:%d",
984                __FUNCTION__, ret);
985          goto cleanup;
986     }
987 
988     filter = get_vendor_filter_mask(filter_mask);
989     ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK,
990                        filter);
991     if (ret != WIFI_SUCCESS) {
992          ALOGE("%s: failed to put vendor data due to error:%d",
993                __FUNCTION__, ret);
994          goto cleanup;
995     }
996 
997     cmd->attr_end(nl_data);
998 
999     /* Populate the input received from caller/framework. */
1000     cmd->setMaxSetSize(max_size);
1001     cmd->set_channels_buff(channels);
1002 
1003     /* Send the msg and wait for a response. */
1004     ret = cmd->requestResponse();
1005     if (ret != WIFI_SUCCESS) {
1006          ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
1007          goto cleanup;
1008     }
1009 
1010     *size = cmd->get_results_size();
1011 
1012 cleanup:
1013     if (cmd)
1014         delete cmd;
1015     return ret;
1016 }
1017 
1018 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)1019 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
1020     if (fn == NULL) {
1021         return WIFI_ERROR_UNKNOWN;
1022     }
1023 
1024     fn->wifi_initialize = wifi_initialize;
1025     fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
1026     fn->wifi_cleanup = wifi_cleanup;
1027     fn->wifi_event_loop = wifi_event_loop;
1028     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
1029     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
1030     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
1031     fn->wifi_get_ifaces = wifi_get_ifaces;
1032     fn->wifi_get_iface_name = wifi_get_iface_name;
1033     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
1034     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
1035     fn->wifi_start_gscan = wifi_start_gscan;
1036     fn->wifi_stop_gscan = wifi_stop_gscan;
1037     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
1038     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
1039     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
1040     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
1041     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
1042     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
1043     fn->wifi_set_link_stats = wifi_set_link_stats;
1044     fn->wifi_get_link_stats = wifi_get_link_stats;
1045     fn->wifi_clear_link_stats = wifi_clear_link_stats;
1046     fn->wifi_get_valid_channels = wifi_get_valid_channels;
1047     fn->wifi_rtt_range_request = wifi_rtt_range_request;
1048     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
1049     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
1050     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
1051     fn->wifi_enable_responder = wifi_enable_responder;
1052     fn->wifi_disable_responder = wifi_disable_responder;
1053     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
1054     fn->wifi_start_logging = wifi_start_logging;
1055     fn->wifi_set_epno_list = wifi_set_epno_list;
1056     fn->wifi_reset_epno_list = wifi_reset_epno_list;
1057     fn->wifi_set_country_code = wifi_set_country_code;
1058     fn->wifi_enable_tdls = wifi_enable_tdls;
1059     fn->wifi_disable_tdls = wifi_disable_tdls;
1060     fn->wifi_get_tdls_status = wifi_get_tdls_status;
1061     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
1062     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
1063     fn->wifi_set_log_handler = wifi_set_log_handler;
1064     fn->wifi_reset_log_handler = wifi_reset_log_handler;
1065     fn->wifi_set_alert_handler = wifi_set_alert_handler;
1066     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
1067     fn->wifi_get_firmware_version = wifi_get_firmware_version;
1068     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
1069     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
1070     fn->wifi_get_ring_data = wifi_get_ring_data;
1071     fn->wifi_get_driver_version = wifi_get_driver_version;
1072     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
1073     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
1074     fn->wifi_set_lci = wifi_set_lci;
1075     fn->wifi_set_lcr = wifi_set_lcr;
1076     fn->wifi_start_sending_offloaded_packet =
1077             wifi_start_sending_offloaded_packet;
1078     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
1079     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
1080     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
1081     fn->wifi_nan_enable_request = nan_enable_request;
1082     fn->wifi_nan_disable_request = nan_disable_request;
1083     fn->wifi_nan_publish_request = nan_publish_request;
1084     fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
1085     fn->wifi_nan_subscribe_request = nan_subscribe_request;
1086     fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
1087     fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
1088     fn->wifi_nan_stats_request = nan_stats_request;
1089     fn->wifi_nan_config_request = nan_config_request;
1090     fn->wifi_nan_tca_request = nan_tca_request;
1091     fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
1092     fn->wifi_nan_register_handler = nan_register_handler;
1093     fn->wifi_nan_get_version = nan_get_version;
1094     fn->wifi_set_packet_filter = wifi_set_packet_filter;
1095     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
1096     fn->wifi_read_packet_filter = wifi_read_packet_filter;
1097     fn->wifi_nan_get_capabilities = nan_get_capabilities;
1098     fn->wifi_nan_data_interface_create = nan_data_interface_create;
1099     fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
1100     fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
1101     fn->wifi_nan_data_indication_response = nan_data_indication_response;
1102     fn->wifi_nan_data_end = nan_data_end;
1103     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
1104     fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
1105     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
1106     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
1107     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
1108     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
1109     fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
1110     fn->wifi_configure_roaming = wifi_configure_roaming;
1111     fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
1112     fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
1113     fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
1114     fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
1115     /* Customers will uncomment when they want to set qpower*/
1116     //fn->wifi_set_qpower = wifi_set_qpower;
1117     fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
1118     fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
1119     fn->wifi_set_latency_mode = wifi_set_latency_mode;
1120     fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
1121     fn->wifi_multi_sta_set_primary_connection = wifi_multi_sta_set_primary_connection;
1122     fn->wifi_multi_sta_set_use_case = wifi_multi_sta_set_use_case;
1123     fn->wifi_set_coex_unsafe_channels = wifi_set_coex_unsafe_channels;
1124     fn->wifi_set_dtim_config = wifi_set_dtim_config;
1125     fn->wifi_set_voip_mode = wifi_set_voip_mode;
1126     fn->wifi_get_usable_channels = wifi_get_usable_channels;
1127 
1128     return WIFI_SUCCESS;
1129 }
1130 
cld80211lib_cleanup(hal_info * info)1131 static void cld80211lib_cleanup(hal_info *info)
1132 {
1133     if (!info->cldctx)
1134         return;
1135     cld80211_remove_mcast_group(info->cldctx, "host_logs");
1136     cld80211_remove_mcast_group(info->cldctx, "fw_logs");
1137     cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
1138     cld80211_remove_mcast_group(info->cldctx, "diag_events");
1139     cld80211_remove_mcast_group(info->cldctx, "fatal_events");
1140     cld80211_remove_mcast_group(info->cldctx, "oem_msgs");
1141     exit_cld80211_recv(info->cldctx);
1142     cld80211_deinit(info->cldctx);
1143     info->cldctx = NULL;
1144 }
1145 
wifi_get_iface_id(hal_info * info,const char * iface)1146 static int wifi_get_iface_id(hal_info *info, const char *iface)
1147 {
1148     int i;
1149     for (i = 0; i < info->num_interfaces; i++)
1150         if (!strcmp(info->interfaces[i]->name, iface))
1151             return i;
1152     return -1;
1153 }
1154 
wifi_initialize(wifi_handle * handle)1155 wifi_error wifi_initialize(wifi_handle *handle)
1156 {
1157     wifi_error ret = WIFI_ERROR_UNKNOWN;
1158     wifi_interface_handle iface_handle;
1159     struct nl_sock *cmd_sock = NULL;
1160     struct nl_sock *event_sock = NULL;
1161     struct nl_cb *cb = NULL;
1162     int status = 0;
1163     int index;
1164     char hw_ver_type[MAX_HW_VER_LENGTH];
1165     char *hw_name = NULL;
1166 
1167     ALOGI("Initializing wifi");
1168     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
1169     if (info == NULL) {
1170         ALOGE("Could not allocate hal_info");
1171         return WIFI_ERROR_OUT_OF_MEMORY;
1172     }
1173 
1174     memset(info, 0, sizeof(*info));
1175 
1176     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
1177                                                      NETLINK_GENERIC);
1178     if (cmd_sock == NULL) {
1179         ALOGE("Failed to create command socket port");
1180         ret = WIFI_ERROR_UNKNOWN;
1181         goto unload;
1182     }
1183 
1184     /* Set the socket buffer size */
1185     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
1186         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
1187                    strerror(errno));
1188         /* continue anyway with the default (smaller) buffer */
1189     }
1190 
1191     event_sock =
1192         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
1193     if (event_sock == NULL) {
1194         ALOGE("Failed to create event socket port");
1195         ret = WIFI_ERROR_UNKNOWN;
1196         goto unload;
1197     }
1198 
1199     /* Set the socket buffer size */
1200     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
1201         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
1202                    strerror(errno));
1203         /* continue anyway with the default (smaller) buffer */
1204     }
1205 
1206     cb = nl_socket_get_cb(event_sock);
1207     if (cb == NULL) {
1208         ALOGE("Failed to get NL control block for event socket port");
1209         ret = WIFI_ERROR_UNKNOWN;
1210         goto unload;
1211     }
1212 
1213     info->event_sock_arg = 1;
1214     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
1215     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->event_sock_arg);
1216     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->event_sock_arg);
1217     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->event_sock_arg);
1218 
1219     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
1220             info);
1221     nl_cb_put(cb);
1222 
1223     info->cmd_sock = cmd_sock;
1224     info->event_sock = event_sock;
1225     info->clean_up = false;
1226     info->in_event_loop = false;
1227 
1228     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
1229     if (info->event_cb == NULL) {
1230         ALOGE("Could not allocate event_cb");
1231         ret = WIFI_ERROR_OUT_OF_MEMORY;
1232         goto unload;
1233     }
1234     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
1235     info->num_event_cb = 0;
1236 
1237     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
1238     if (info->nl80211_family_id < 0) {
1239         ALOGE("Could not resolve nl80211 familty id");
1240         ret = WIFI_ERROR_UNKNOWN;
1241         goto unload;
1242     }
1243 
1244     pthread_mutex_init(&info->cb_lock, NULL);
1245     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
1246 
1247     *handle = (wifi_handle) info;
1248 
1249     wifi_add_membership(*handle, "scan");
1250     wifi_add_membership(*handle, "mlme");
1251     wifi_add_membership(*handle, "regulatory");
1252     wifi_add_membership(*handle, "vendor");
1253 
1254     info->wifihal_ctrl_sock.s = 0;
1255 
1256     wifi_create_ctrl_socket(info);
1257 
1258     //! Initailise the monitoring clients list
1259     INITIALISE_LIST(&info->monitor_sockets);
1260 
1261     info->cldctx = cld80211_init();
1262     if (info->cldctx != NULL) {
1263         info->user_sock = info->cldctx->sock;
1264         ret = wifi_init_cld80211_sock_cb(info);
1265         if (ret != WIFI_SUCCESS) {
1266             ALOGE("Could not set cb for CLD80211 family");
1267             goto cld80211_cleanup;
1268         }
1269 
1270         status = cld80211_add_mcast_group(info->cldctx, "host_logs");
1271         if (status) {
1272             ALOGE("Failed to add mcast group host_logs :%d", status);
1273             goto cld80211_cleanup;
1274         }
1275         status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
1276         if (status) {
1277             ALOGE("Failed to add mcast group fw_logs :%d", status);
1278             goto cld80211_cleanup;
1279         }
1280         status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
1281         if (status) {
1282             ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
1283             goto cld80211_cleanup;
1284         }
1285         status = cld80211_add_mcast_group(info->cldctx, "diag_events");
1286         if (status) {
1287             ALOGE("Failed to add mcast group diag_events :%d", status);
1288             goto cld80211_cleanup;
1289         }
1290         status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
1291         if (status) {
1292             ALOGE("Failed to add mcast group fatal_events :%d", status);
1293             goto cld80211_cleanup;
1294         }
1295 
1296         if(info->wifihal_ctrl_sock.s > 0)
1297         {
1298           status = cld80211_add_mcast_group(info->cldctx, "oem_msgs");
1299           if (status) {
1300              ALOGE("Failed to add mcast group oem_msgs :%d", status);
1301              goto cld80211_cleanup;
1302           }
1303         }
1304     } else {
1305         ret = wifi_init_user_sock(info);
1306         if (ret != WIFI_SUCCESS) {
1307             ALOGE("Failed to alloc user socket");
1308             goto unload;
1309         }
1310     }
1311 
1312     ret = wifi_init_interfaces(*handle);
1313     if (ret != WIFI_SUCCESS) {
1314         ALOGE("Failed to init interfaces");
1315         goto unload;
1316     }
1317 
1318     if (info->num_interfaces == 0) {
1319         ALOGE("No interfaces found");
1320         ret = WIFI_ERROR_UNINITIALIZED;
1321         goto unload;
1322     }
1323 
1324     index = wifi_get_iface_id(info, "wlan0");
1325     if (index == -1) {
1326         int i;
1327         for (i = 0; i < info->num_interfaces; i++)
1328         {
1329             free(info->interfaces[i]);
1330         }
1331         ALOGE("%s no iface with wlan0", __func__);
1332         ret = WIFI_ERROR_UNKNOWN;
1333         goto unload;
1334     }
1335     iface_handle = (wifi_interface_handle)info->interfaces[index];
1336 
1337     ret = acquire_supported_features(iface_handle,
1338             &info->supported_feature_set);
1339     if (ret != WIFI_SUCCESS) {
1340         ALOGI("Failed to get supported feature set : %d", ret);
1341         //acquire_supported_features failure is acceptable condition as legacy
1342         //drivers might not support the required vendor command. So, do not
1343         //consider it as failure of wifi_initialize
1344         ret = WIFI_SUCCESS;
1345     }
1346 
1347     ret = acquire_driver_supported_features(iface_handle,
1348                                   &info->driver_supported_features);
1349     if (ret != WIFI_SUCCESS) {
1350         ALOGI("Failed to get vendor feature set : %d", ret);
1351         ret = WIFI_SUCCESS;
1352     }
1353 
1354     ret =  wifi_get_logger_supported_feature_set(iface_handle,
1355                          &info->supported_logger_feature_set);
1356     if (ret != WIFI_SUCCESS)
1357         ALOGE("Failed to get supported logger feature set: %d", ret);
1358 
1359     ret =  wifi_get_firmware_version(iface_handle, hw_ver_type,
1360                                      MAX_HW_VER_LENGTH);
1361     if (ret == WIFI_SUCCESS) {
1362         hw_name = strstr(hw_ver_type, "HW:");
1363         if (hw_name) {
1364             hw_name += strlen("HW:");
1365             if (strncmp(hw_name, "QCA6174", 7) == 0)
1366                info->pkt_log_ver = PKT_LOG_V1;
1367             else
1368                info->pkt_log_ver = PKT_LOG_V2;
1369         } else {
1370            info->pkt_log_ver = PKT_LOG_V0;
1371         }
1372         ALOGV("%s: hardware version type %d", __func__, info->pkt_log_ver);
1373     } else {
1374         ALOGE("Failed to get firmware version: %d", ret);
1375     }
1376 
1377     ret = get_firmware_bus_max_size_supported(iface_handle);
1378     if (ret != WIFI_SUCCESS) {
1379         ALOGE("Failed to get supported bus size, error : %d", ret);
1380         info->firmware_bus_max_size = 1520;
1381     }
1382 
1383     ret = wifi_logger_ring_buffers_init(info);
1384     if (ret != WIFI_SUCCESS)
1385         ALOGE("Wifi Logger Ring Initialization Failed");
1386 
1387     ret = wifi_get_capabilities(iface_handle);
1388     if (ret != WIFI_SUCCESS)
1389         ALOGE("Failed to get wifi Capabilities, error: %d", ret);
1390 
1391     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
1392     if (!info->pkt_stats) {
1393         ALOGE("%s: malloc Failed for size: %zu",
1394                 __FUNCTION__, sizeof(struct pkt_stats_s));
1395         ret = WIFI_ERROR_OUT_OF_MEMORY;
1396         goto unload;
1397     }
1398 
1399     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
1400                                   * PKT_STATS_BUF_SIZE;
1401 
1402     info->rx_aggr_pkts =
1403         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
1404     if (!info->rx_aggr_pkts) {
1405         ALOGE("%s: malloc Failed for size: %d",
1406                 __FUNCTION__, info->rx_buf_size_allocated);
1407         ret = WIFI_ERROR_OUT_OF_MEMORY;
1408         info->rx_buf_size_allocated = 0;
1409         goto unload;
1410     }
1411     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
1412 
1413     info->exit_sockets[0] = -1;
1414     info->exit_sockets[1] = -1;
1415 
1416     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
1417         ALOGE("Failed to create exit socket pair");
1418         ret = WIFI_ERROR_UNKNOWN;
1419         goto unload;
1420     }
1421 
1422     ALOGV("Initializing Gscan Event Handlers");
1423     ret = initializeGscanHandlers(info);
1424     if (ret != WIFI_SUCCESS) {
1425         ALOGE("Initializing Gscan Event Handlers Failed");
1426         goto unload;
1427     }
1428 
1429     ret = initializeRSSIMonitorHandler(info);
1430     if (ret != WIFI_SUCCESS) {
1431         ALOGE("Initializing RSSI Event Handler Failed");
1432         goto unload;
1433     }
1434 
1435     ret = initializeRadioHandler(info);
1436     if (ret != WIFI_SUCCESS) {
1437         ALOGE("Initializing Radio Event handler Failed");
1438         goto unload;
1439     }
1440 
1441     ret = wifi_init_tcp_param_change_event_handler(iface_handle);
1442     if (ret != WIFI_SUCCESS) {
1443         ALOGE("Initializing TCP param change event Handler Failed");
1444         goto unload;
1445     }
1446 
1447     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
1448             " features : %" PRIx64, NL80211_CMD_VENDOR, info->supported_feature_set);
1449 
1450     if (wifi_is_nan_ext_cmd_supported(iface_handle))
1451         info->support_nan_ext_cmd = true;
1452     else
1453         info->support_nan_ext_cmd = false;
1454 
1455     ALOGV("support_nan_ext_cmd is %d",
1456           info->support_nan_ext_cmd);
1457 
1458     ret = wifi_get_sar_version(iface_handle);
1459     if (ret != WIFI_SUCCESS) {
1460         ALOGE("Failed to  get  SAR Version, Setting it to default.");
1461         info->sar_version = QCA_WLAN_VENDOR_SAR_VERSION_1;
1462         ret = WIFI_SUCCESS;
1463     }
1464 
1465 cld80211_cleanup:
1466     if (status != 0 || ret != WIFI_SUCCESS) {
1467         ret = WIFI_ERROR_UNKNOWN;
1468         cld80211lib_cleanup(info);
1469     }
1470 unload:
1471     if (ret != WIFI_SUCCESS) {
1472         if (cmd_sock)
1473             nl_socket_free(cmd_sock);
1474         if (event_sock)
1475             nl_socket_free(event_sock);
1476         if (info) {
1477             if (info->cldctx) {
1478                 cld80211lib_cleanup(info);
1479             } else if (info->user_sock) {
1480                 nl_socket_free(info->user_sock);
1481             }
1482             if (info->pkt_stats) free(info->pkt_stats);
1483             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
1484             if (info->wifihal_ctrl_sock.s) close(info->wifihal_ctrl_sock.s);
1485             wifi_logger_ring_buffers_deinit(info);
1486             cleanupGscanHandlers(info);
1487             cleanupRSSIMonitorHandler(info);
1488             cleanupRadioHandler(info);
1489             cleanupTCPParamCommand(info);
1490             free(info->event_cb);
1491             if (info->driver_supported_features.flags) {
1492                 free(info->driver_supported_features.flags);
1493                 info->driver_supported_features.flags = NULL;
1494             }
1495             free(info);
1496         }
1497     }
1498 
1499     return ret;
1500 }
1501 
1502 #ifdef WIFI_DRIVER_STATE_CTRL_PARAM
wifi_update_driver_state(const char * state)1503 static int wifi_update_driver_state(const char *state) {
1504     struct timespec ts;
1505     int len, fd, ret = 0, count = 5;
1506     ts.tv_sec = 0;
1507     ts.tv_nsec = 200 * 1000000L;
1508     do {
1509         if (access(WIFI_DRIVER_STATE_CTRL_PARAM, W_OK) == 0)
1510             break;
1511         nanosleep(&ts, (struct timespec *)NULL);
1512     } while (--count > 0); /* wait at most 1 second for completion. */
1513     if (count == 0) {
1514         ALOGE("Failed to access driver state control param %s, %d at %s",
1515               strerror(errno), errno, WIFI_DRIVER_STATE_CTRL_PARAM);
1516         return -1;
1517     }
1518     fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
1519     if (fd < 0) {
1520         ALOGE("Failed to open driver state control param at %s",
1521               WIFI_DRIVER_STATE_CTRL_PARAM);
1522         close(fd);
1523         return -1;
1524     }
1525     len = strlen(state) + 1;
1526     if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
1527         ALOGE("Failed to write driver state control param at %s",
1528               WIFI_DRIVER_STATE_CTRL_PARAM);
1529         close(fd);
1530         ret = -1;
1531     }
1532     close(fd);
1533     return ret;
1534 }
1535 #endif
1536 
wifi_wait_for_driver_ready(void)1537 wifi_error wifi_wait_for_driver_ready(void)
1538 {
1539     // This function will wait to make sure basic client netdev is created
1540     // Function times out after 10 seconds
1541     int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
1542     FILE *fd;
1543 
1544 #if defined(WIFI_DRIVER_STATE_CTRL_PARAM) && defined(WIFI_DRIVER_STATE_ON)
1545     if (wifi_update_driver_state(WIFI_DRIVER_STATE_ON) < 0) {
1546         return WIFI_ERROR_UNKNOWN;
1547     }
1548 #endif
1549 
1550     do {
1551         if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
1552             fclose(fd);
1553             return WIFI_SUCCESS;
1554         }
1555         usleep(POLL_DRIVER_DURATION_US);
1556     } while(--count > 0);
1557 
1558     ALOGE("Timed out wating on Driver ready ... ");
1559     return WIFI_ERROR_TIMED_OUT;
1560 }
1561 
wifi_add_membership(wifi_handle handle,const char * group)1562 static int wifi_add_membership(wifi_handle handle, const char *group)
1563 {
1564     hal_info *info = getHalInfo(handle);
1565 
1566     int id = wifi_get_multicast_id(handle, "nl80211", group);
1567     if (id < 0) {
1568         ALOGE("Could not find group %s", group);
1569         return id;
1570     }
1571 
1572     int ret = nl_socket_add_membership(info->event_sock, id);
1573     if (ret < 0) {
1574         ALOGE("Could not add membership to group %s", group);
1575     }
1576 
1577     return ret;
1578 }
1579 
internal_cleaned_up_handler(wifi_handle handle)1580 static void internal_cleaned_up_handler(wifi_handle handle)
1581 {
1582     hal_info *info = getHalInfo(handle);
1583     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
1584     wifihal_mon_sock_t *reg, *tmp;
1585 
1586     if (info->cmd_sock != 0) {
1587         nl_socket_free(info->cmd_sock);
1588         nl_socket_free(info->event_sock);
1589         info->cmd_sock = NULL;
1590         info->event_sock = NULL;
1591     }
1592 
1593     if (info->wifihal_ctrl_sock.s != 0) {
1594         close(info->wifihal_ctrl_sock.s);
1595         unlink(info->wifihal_ctrl_sock.local.sun_path);
1596         info->wifihal_ctrl_sock.s = 0;
1597     }
1598 
1599    list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
1600         del_from_list(&reg->list);
1601         free(reg);
1602     }
1603 
1604     if (info->interfaces) {
1605         for (int i = 0; i < info->num_interfaces; i++)
1606             free(info->interfaces[i]);
1607         free(info->interfaces);
1608     }
1609 
1610     if (info->cldctx != NULL) {
1611         cld80211lib_cleanup(info);
1612     } else if (info->user_sock != 0) {
1613         nl_socket_free(info->user_sock);
1614         info->user_sock = NULL;
1615     }
1616 
1617     if (info->pkt_stats)
1618         free(info->pkt_stats);
1619     if (info->rx_aggr_pkts)
1620         free(info->rx_aggr_pkts);
1621     wifi_logger_ring_buffers_deinit(info);
1622     cleanupGscanHandlers(info);
1623     cleanupRSSIMonitorHandler(info);
1624     cleanupRadioHandler(info);
1625     cleanupTCPParamCommand(info);
1626 
1627     if (info->num_event_cb)
1628         ALOGE("%d events were leftover without being freed",
1629               info->num_event_cb);
1630     free(info->event_cb);
1631 
1632     if (info->exit_sockets[0] >= 0) {
1633         close(info->exit_sockets[0]);
1634         info->exit_sockets[0] = -1;
1635     }
1636 
1637     if (info->exit_sockets[1] >= 0) {
1638         close(info->exit_sockets[1]);
1639         info->exit_sockets[1] = -1;
1640     }
1641 
1642     if (info->pkt_fate_stats) {
1643         free(info->pkt_fate_stats);
1644         info->pkt_fate_stats = NULL;
1645     }
1646 
1647     if (info->driver_supported_features.flags) {
1648         free(info->driver_supported_features.flags);
1649         info->driver_supported_features.flags = NULL;
1650     }
1651 
1652     (*cleaned_up_handler)(handle);
1653     pthread_mutex_destroy(&info->cb_lock);
1654     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
1655     free(info);
1656 }
1657 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)1658 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
1659 {
1660     if (!handle) {
1661         ALOGE("Handle is null");
1662         return;
1663     }
1664 
1665     hal_info *info = getHalInfo(handle);
1666     info->cleaned_up_handler = handler;
1667     // Remove the dynamically created interface during wifi cleanup.
1668     wifi_cleanup_dynamic_ifaces(handle);
1669 
1670     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
1671 
1672     // Ensure wifi_event_loop() exits by setting clean_up to true.
1673     info->clean_up = true;
1674     ALOGI("Sent msg on exit sock to unblock poll()");
1675 }
1676 
1677 
1678 
validate_cld80211_msg(nlmsghdr * nlh,int family,int cmd)1679 static int validate_cld80211_msg(nlmsghdr *nlh, int family, int cmd)
1680 {
1681     //! Enhance this API
1682     struct genlmsghdr *hdr;
1683     hdr = (genlmsghdr *)nlmsg_data(nlh);
1684 
1685     if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1686     {
1687       ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1688       return -1;
1689     }
1690     if(hdr->cmd == WLAN_NL_MSG_OEM)
1691     {
1692       ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1693              nlh->nlmsg_type, hdr->cmd);
1694 
1695       //! Update pid with the wifihal pid
1696       nlh->nlmsg_pid = getpid();
1697       return 0;
1698     }
1699     else
1700     {
1701       ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1702       return -1;
1703     }
1704 }
1705 
1706 
validate_genl_msg(nlmsghdr * nlh,int family,int cmd)1707 static int validate_genl_msg(nlmsghdr *nlh, int family, int cmd)
1708 {
1709     //! Enhance this API
1710     struct genlmsghdr *hdr;
1711     hdr = (genlmsghdr *)nlmsg_data(nlh);
1712 
1713     if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1714     {
1715       ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1716       return -1;
1717     }
1718     if(hdr->cmd == NL80211_CMD_FRAME ||
1719        hdr->cmd == NL80211_CMD_REGISTER_ACTION)
1720     {
1721       ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1722              nlh->nlmsg_type, hdr->cmd);
1723       return 0;
1724     }
1725     else
1726     {
1727       ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1728       return -1;
1729     }
1730 }
1731 
send_nl_data(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1732 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1733 {
1734     hal_info *info = getHalInfo(handle);
1735     struct nl_msg *msg = NULL;
1736     int retval = -1;
1737 
1738     //! attach monitor socket if it was not it the list
1739     if(ctrl_msg->monsock_len)
1740     {
1741       retval = attach_monitor_sock(handle, ctrl_msg);
1742       if(retval)
1743         goto nl_out;
1744     }
1745 
1746     msg = nlmsg_alloc();
1747     if (!msg)
1748     {
1749        ALOGE("%s: Memory allocation failed \n", __FUNCTION__);
1750        goto nl_out;
1751     }
1752 
1753     if (ctrl_msg->data_len > nlmsg_get_max_size(msg))
1754     {
1755         ALOGE("%s: Invalid ctrl msg length \n", __FUNCTION__);
1756         retval = -1;
1757         goto nl_out;
1758     }
1759     memcpy((char *)msg->nm_nlh, (char *)ctrl_msg->data, ctrl_msg->data_len);
1760 
1761    if(ctrl_msg->family_name == GENERIC_NL_FAMILY)
1762    {
1763      //! Before sending the received gennlmsg to kernel,
1764      //! better to have checks for allowed commands
1765      retval = validate_genl_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1766      if (retval < 0)
1767          goto nl_out;
1768 
1769      retval = nl_send_auto_complete(info->event_sock, msg);    /* send message */
1770      if (retval < 0)
1771      {
1772        ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
1773        goto nl_out;
1774      }
1775      ALOGI("%s: sent gennl msg of len: %d to driver\n", __FUNCTION__, ctrl_msg->data_len);
1776      retval = internal_pollin_handler(handle, info->event_sock);
1777   }
1778   else if (ctrl_msg->family_name == CLD80211_FAMILY)
1779   {
1780     if (info->cldctx != NULL)
1781     {
1782       //! Before sending the received cld80211 msg to kernel,
1783       //! better to have checks for allowed commands
1784       retval = validate_cld80211_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1785       if (retval < 0)
1786          goto nl_out;
1787 
1788       retval = cld80211_send_msg(info->cldctx, msg);
1789       if (retval != 0)
1790       {
1791         ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
1792         goto nl_out;
1793       }
1794       ALOGI("%s: sent cld80211 msg of len: %d to driver\n", __FUNCTION__, ctrl_msg->data_len);
1795     }
1796     else
1797     {
1798       ALOGE("%s: cld80211 ctx not present \n", __FUNCTION__);
1799     }
1800   }
1801   else
1802   {
1803     ALOGE("%s: Unknown family name : %d \n", __FUNCTION__, ctrl_msg->family_name);
1804     retval = -1;
1805   }
1806 nl_out:
1807   if (msg)
1808   {
1809     nlmsg_free(msg);
1810   }
1811   return retval;
1812 }
1813 
register_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg,int attach)1814 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach)
1815 {
1816     hal_info *info = getHalInfo(handle);
1817 
1818     wifihal_mon_sock_t *reg, *nreg;
1819     char *match = NULL;
1820     unsigned int match_len = 0;
1821     unsigned int type;
1822 
1823     //! For Register Action frames, compare the match length and match buffer.
1824     //! For other registrations such as oem messages,
1825     //! diag messages check for respective commands
1826 
1827     if((ctrl_msg->family_name == GENERIC_NL_FAMILY) &&
1828        (ctrl_msg->cmd_id == NL80211_CMD_REGISTER_ACTION))
1829     {
1830        struct genlmsghdr *genlh;
1831        struct  nlmsghdr *nlh = (struct  nlmsghdr *)ctrl_msg->data;
1832        genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1833        struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1834 
1835        if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(*ctrl_msg))
1836        {
1837          ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1838          return -1;
1839        }
1840        if (nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1841                  genlmsg_attrlen(genlh, 0), NULL))
1842        {
1843          ALOGE("unable to parse nl attributes");
1844          return -1;
1845        }
1846        if (!nlattrs[NL80211_ATTR_FRAME_TYPE])
1847        {
1848          ALOGD("No Valid frame type");
1849        }
1850        else
1851        {
1852          type = nla_get_u16(nlattrs[NL80211_ATTR_FRAME_TYPE]);
1853        }
1854        if (!nlattrs[NL80211_ATTR_FRAME_MATCH])
1855        {
1856          ALOGE("No Frame Match");
1857          return -1;
1858        }
1859        else
1860        {
1861          match_len = nla_len(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1862          match = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1863 
1864          list_for_each_entry(reg, &info->monitor_sockets, list) {
1865 
1866            int mlen = min(match_len, reg->match_len);
1867 
1868            if (reg->match_len == 0)
1869                continue;
1870 
1871            if (memcmp(reg->match, match, mlen) == 0) {
1872 
1873               if((ctrl_msg->monsock_len == reg->monsock_len) &&
1874                  (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0))
1875               {
1876                 if(attach)
1877                 {
1878                   ALOGE(" %s :Action frame already registered for this client ", __FUNCTION__);
1879                   return -2;
1880                 }
1881                 else
1882                 {
1883                   del_from_list(&reg->list);
1884                   free(reg);
1885                   return 0;
1886                 }
1887               }
1888               else
1889               {
1890                 //! when action frame registered for other client,
1891                 //! you can't attach or dettach for new client
1892                 ALOGE(" %s :Action frame registered for other client ", __FUNCTION__);
1893                 return -2;
1894               }
1895            }
1896          }
1897        }
1898     }
1899     else
1900     {
1901       list_for_each_entry(reg, &info->monitor_sockets, list) {
1902 
1903          //! Checking for monitor sock in the list :
1904 
1905          //! For attach request :
1906          //! if sock is not present, then it is a new entry , so add to list.
1907          //! if sock is present,  and cmd_id does not match, add another entry to list.
1908          //! if sock is present, and cmd_id matches, return 0.
1909 
1910          //! For dettach req :
1911          //! if sock is not present, return error -2.
1912          //! if sock is present,  and cmd_id does not match, return error -2.
1913          //! if sock is present, and cmd_id matches, delete entry and return 0.
1914 
1915          if (ctrl_msg->monsock_len != reg->monsock_len)
1916              continue;
1917 
1918          if (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0) {
1919 
1920             if((reg->family_name == ctrl_msg->family_name) && (reg->cmd_id == ctrl_msg->cmd_id))
1921             {
1922                if(!attach)
1923                {
1924                  del_from_list(&reg->list);
1925                  free(reg);
1926                }
1927                return 0;
1928             }
1929          }
1930       }
1931     }
1932 
1933     if(attach)
1934     {
1935        if (ctrl_msg->monsock_len > sizeof(struct sockaddr_un))
1936        {
1937          ALOGE("%s: Invalid monitor socket length \n", __FUNCTION__);
1938          return -3;
1939        }
1940 
1941        nreg = (wifihal_mon_sock_t *)malloc(sizeof(*reg) + match_len);
1942         if (!nreg)
1943            return -1;
1944 
1945        memset((char *)nreg, 0, sizeof(*reg) + match_len);
1946        nreg->family_name = ctrl_msg->family_name;
1947        nreg->cmd_id = ctrl_msg->cmd_id;
1948        nreg->monsock_len = ctrl_msg->monsock_len;
1949        memcpy((char *)&nreg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len);
1950 
1951        if(match_len && match)
1952        {
1953          nreg->match_len = match_len;
1954          memcpy(nreg->match, match, match_len);
1955        }
1956        add_to_list(&nreg->list, &info->monitor_sockets);
1957     }
1958     else
1959     {
1960        //! Not attached, so cant be dettached
1961        ALOGE("%s: Dettaching the unregistered socket \n", __FUNCTION__);
1962        return -2;
1963     }
1964 
1965    return 0;
1966 }
1967 
attach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1968 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1969 {
1970    return register_monitor_sock(handle, ctrl_msg, 1);
1971 }
1972 
dettach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1973 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1974 {
1975    return register_monitor_sock(handle, ctrl_msg, 0);
1976 }
1977 
internal_pollin_handler_app(wifi_handle handle,struct ctrl_sock * sock)1978 static int internal_pollin_handler_app(wifi_handle handle,  struct ctrl_sock *sock)
1979 {
1980     int retval = -1;
1981     int res;
1982     struct sockaddr_un from;
1983     socklen_t fromlen = sizeof(from);
1984     wifihal_ctrl_req_t *ctrl_msg;
1985     wifihal_ctrl_sync_rsp_t ctrl_reply;
1986 
1987     ctrl_msg = (wifihal_ctrl_req_t *)malloc(DEFAULT_PAGE_SIZE);
1988     if(ctrl_msg == NULL)
1989     {
1990       ALOGE ("Memory allocation failure");
1991       return -1;
1992     }
1993 
1994     memset((char *)ctrl_msg, 0, DEFAULT_PAGE_SIZE);
1995 
1996     res = recvfrom(sock->s, (char *)ctrl_msg, DEFAULT_PAGE_SIZE, 0,
1997                    (struct sockaddr *)&from, &fromlen);
1998     if (res < 0) {
1999         ALOGE("recvfrom(ctrl_iface): %s",
2000                strerror(errno));
2001         if(ctrl_msg)
2002            free(ctrl_msg);
2003 
2004         return 0;
2005     }
2006     switch(ctrl_msg->ctrl_cmd)
2007     {
2008        case WIFIHAL_CTRL_MONITOR_ATTACH:
2009          retval = attach_monitor_sock(handle, ctrl_msg);
2010        break;
2011        case WIFIHAL_CTRL_MONITOR_DETTACH:
2012          retval = dettach_monitor_sock(handle, ctrl_msg);
2013        break;
2014        case WIFIHAL_CTRL_SEND_NL_DATA:
2015          retval = send_nl_data(handle, ctrl_msg);
2016        break;
2017        default:
2018        break;
2019     }
2020 
2021     ctrl_reply.ctrl_cmd = ctrl_msg->ctrl_cmd;
2022     ctrl_reply.family_name = ctrl_msg->family_name;
2023     ctrl_reply.cmd_id = ctrl_msg->cmd_id;
2024     ctrl_reply.status = retval;
2025 
2026     if(ctrl_msg)
2027        free(ctrl_msg);
2028 
2029     if (sendto(sock->s, (char *)&ctrl_reply, sizeof(ctrl_reply), 0, (struct sockaddr *)&from,
2030                fromlen) < 0) {
2031                   int _errno = errno;
2032                   ALOGE("socket send failed : %d",_errno);
2033 
2034        if (_errno == ENOBUFS || _errno == EAGAIN) {
2035            /*
2036             * The socket send buffer could be full. This
2037             * may happen if client programs are not
2038             * receiving their pending messages. Close and
2039             * reopen the socket as a workaround to avoid
2040             * getting stuck being unable to send any new
2041             * responses.
2042             */
2043           }
2044         }
2045       return res;
2046 }
2047 
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)2048 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
2049 {
2050     struct nl_cb *cb = nl_socket_get_cb(sock);
2051 
2052     int res = nl_recvmsgs(sock, cb);
2053     if(res)
2054         ALOGE("Error :%d while reading nl msg", res);
2055     nl_cb_put(cb);
2056     return res;
2057 }
2058 
internal_event_handler_app(wifi_handle handle,int events,struct ctrl_sock * sock)2059 static void internal_event_handler_app(wifi_handle handle, int events,
2060                                     struct ctrl_sock *sock)
2061 {
2062     if (events & POLLERR) {
2063         ALOGE("Error reading from wifi_hal ctrl socket");
2064         internal_pollin_handler_app(handle, sock);
2065     } else if (events & POLLHUP) {
2066         ALOGE("Remote side hung up");
2067     } else if (events & POLLIN) {
2068         //ALOGI("Found some events!!!");
2069         internal_pollin_handler_app(handle, sock);
2070     } else {
2071         ALOGE("Unknown event - %0x", events);
2072     }
2073 }
2074 
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)2075 static void internal_event_handler(wifi_handle handle, int events,
2076                                    struct nl_sock *sock)
2077 {
2078     if (events & POLLERR) {
2079         ALOGE("Error reading from socket");
2080         internal_pollin_handler(handle, sock);
2081     } else if (events & POLLHUP) {
2082         ALOGE("Remote side hung up");
2083     } else if (events & POLLIN) {
2084         //ALOGI("Found some events!!!");
2085         internal_pollin_handler(handle, sock);
2086     } else {
2087         ALOGE("Unknown event - %0x", events);
2088     }
2089 }
2090 
exit_event_handler(int fd)2091 static bool exit_event_handler(int fd) {
2092     char buf[4];
2093     memset(buf, 0, sizeof(buf));
2094 
2095     TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)));
2096     ALOGI("exit_event_handler, buf=%s", buf);
2097     if (strncmp(buf, "E", 1) == 0) {
2098        return true;
2099     }
2100 
2101     return false;
2102 }
2103 
2104 /* Run event handler */
wifi_event_loop(wifi_handle handle)2105 void wifi_event_loop(wifi_handle handle)
2106 {
2107     hal_info *info = getHalInfo(handle);
2108     if (info->in_event_loop) {
2109         return;
2110     } else {
2111         info->in_event_loop = true;
2112     }
2113 
2114     pollfd pfd[4];
2115     memset(&pfd, 0, 4*sizeof(pfd[0]));
2116 
2117     pfd[0].fd = nl_socket_get_fd(info->event_sock);
2118     pfd[0].events = POLLIN;
2119 
2120     pfd[1].fd = nl_socket_get_fd(info->user_sock);
2121     pfd[1].events = POLLIN;
2122 
2123     pfd[2].fd = info->exit_sockets[1];
2124     pfd[2].events = POLLIN;
2125 
2126     if(info->wifihal_ctrl_sock.s > 0) {
2127       pfd[3].fd = info->wifihal_ctrl_sock.s ;
2128       pfd[3].events = POLLIN;
2129     }
2130     /* TODO: Add support for timeouts */
2131 
2132     do {
2133         pfd[0].revents = 0;
2134         pfd[1].revents = 0;
2135         pfd[2].revents = 0;
2136         pfd[3].revents = 0;
2137         //ALOGI("Polling sockets");
2138         int result = poll(pfd, 4, -1);
2139         if (result < 0) {
2140             ALOGE("Error polling socket");
2141         } else {
2142             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
2143                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
2144             }
2145             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
2146                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
2147             }
2148             if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
2149                 internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
2150             }
2151             if (pfd[2].revents & POLLIN) {
2152                 if (exit_event_handler(pfd[2].fd)) {
2153                     break;
2154                 }
2155             }
2156         }
2157         rb_timerhandler(info);
2158     } while (!info->clean_up);
2159     internal_cleaned_up_handler(handle);
2160     ALOGI("wifi_event_loop() exits success");
2161 }
2162 
user_sock_message_handler(nl_msg * msg,void * arg)2163 static int user_sock_message_handler(nl_msg *msg, void *arg)
2164 {
2165     wifi_handle handle = (wifi_handle)arg;
2166     hal_info *info = getHalInfo(handle);
2167 
2168     diag_message_handler(info, msg);
2169 
2170     return NL_OK;
2171 }
2172 
internal_valid_message_handler(nl_msg * msg,void * arg)2173 static int internal_valid_message_handler(nl_msg *msg, void *arg)
2174 {
2175     wifi_handle handle = (wifi_handle)arg;
2176     hal_info *info = getHalInfo(handle);
2177 
2178     WifiEvent event(msg);
2179     int res = event.parse();
2180     if (res < 0) {
2181         ALOGE("Failed to parse event: %d", res);
2182         return NL_SKIP;
2183     }
2184 
2185     int cmd = event.get_cmd();
2186     uint32_t vendor_id = 0;
2187     int subcmd = 0;
2188 
2189     if (cmd == NL80211_CMD_VENDOR) {
2190         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
2191         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
2192         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
2193            of logs in bug report */
2194         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
2195             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
2196                   event.get_cmdString(), vendor_id, subcmd);
2197         }
2198     }
2199     else if((info->wifihal_ctrl_sock.s > 0) && (cmd == NL80211_CMD_FRAME))
2200     {
2201        struct genlmsghdr *genlh;
2202        struct  nlmsghdr *nlh = nlmsg_hdr(msg);
2203        genlh = (struct genlmsghdr *)nlmsg_data(nlh);
2204        struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
2205 
2206        wifihal_ctrl_event_t *ctrl_evt;
2207        char *buff;
2208        wifihal_mon_sock_t *reg;
2209 
2210        nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
2211                  genlmsg_attrlen(genlh, 0), NULL);
2212 
2213        if (!nlattrs[NL80211_ATTR_FRAME])
2214        {
2215          ALOGD("No Frame body");
2216          return WIFI_SUCCESS;
2217        }
2218        ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
2219        if(ctrl_evt == NULL)
2220        {
2221          ALOGE("Memory allocation failure");
2222          return -1;
2223        }
2224        memset((char *)ctrl_evt, 0, sizeof(*ctrl_evt) + nlh->nlmsg_len);
2225        ctrl_evt->family_name = GENERIC_NL_FAMILY;
2226        ctrl_evt->cmd_id = cmd;
2227        ctrl_evt->data_len = nlh->nlmsg_len;
2228        memcpy(ctrl_evt->data, (char *)nlh, ctrl_evt->data_len);
2229 
2230 
2231        buff = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME]) + 24; //! Size of Wlan80211FrameHeader
2232 
2233        list_for_each_entry(reg, &info->monitor_sockets, list) {
2234 
2235                  if (memcmp(reg->match, buff, reg->match_len))
2236                      continue;
2237 
2238                  /* found match! */
2239                  /* Indicate the received Action frame to respective client */
2240                  ALOGI("send gennl msg of len : %d to apps", ctrl_evt->data_len);
2241                  if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
2242                             sizeof(*ctrl_evt) + ctrl_evt->data_len,
2243                             0, (struct sockaddr *)&reg->monsock, reg->monsock_len) < 0)
2244                  {
2245                    int _errno = errno;
2246                    ALOGE("socket send failed : %d",_errno);
2247 
2248                    if (_errno == ENOBUFS || _errno == EAGAIN) {
2249                    }
2250                  }
2251 
2252         }
2253         free(ctrl_evt);
2254     }
2255 
2256     else {
2257         ALOGV("event received %s", event.get_cmdString());
2258     }
2259 
2260     // event.log();
2261 
2262     bool dispatched = false;
2263 
2264     pthread_mutex_lock(&info->cb_lock);
2265 
2266     for (int i = 0; i < info->num_event_cb; i++) {
2267         if (cmd == info->event_cb[i].nl_cmd) {
2268             if (cmd == NL80211_CMD_VENDOR
2269                 && ((vendor_id != info->event_cb[i].vendor_id)
2270                 || (subcmd != info->event_cb[i].vendor_subcmd)))
2271             {
2272                 /* event for a different vendor, ignore it */
2273                 continue;
2274             }
2275 
2276             cb_info *cbi = &(info->event_cb[i]);
2277             pthread_mutex_unlock(&info->cb_lock);
2278             if (cbi->cb_func) {
2279                 (*(cbi->cb_func))(msg, cbi->cb_arg);
2280                 dispatched = true;
2281             }
2282             return NL_OK;
2283         }
2284     }
2285 
2286 #ifdef QC_HAL_DEBUG
2287     if (!dispatched) {
2288         ALOGI("event ignored!!");
2289     }
2290 #endif
2291 
2292     pthread_mutex_unlock(&info->cb_lock);
2293     return NL_OK;
2294 }
2295 
2296 ////////////////////////////////////////////////////////////////////////////////
2297 
2298 class GetMulticastIdCommand : public WifiCommand
2299 {
2300 private:
2301     const char *mName;
2302     const char *mGroup;
2303     int   mId;
2304 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)2305     GetMulticastIdCommand(wifi_handle handle, const char *name,
2306             const char *group) : WifiCommand(handle, 0)
2307     {
2308         mName = name;
2309         mGroup = group;
2310         mId = -1;
2311     }
2312 
getId()2313     int getId() {
2314         return mId;
2315     }
2316 
create()2317     virtual wifi_error create() {
2318         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
2319         // ALOGI("ctrl family = %d", nlctrlFamily);
2320         wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
2321         if (ret != WIFI_SUCCESS)
2322             return ret;
2323 
2324         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
2325         return ret;
2326     }
2327 
handleResponse(WifiEvent & reply)2328     virtual int handleResponse(WifiEvent& reply) {
2329 
2330         // ALOGI("handling reponse in %s", __func__);
2331 
2332         struct nlattr **tb = reply.attributes();
2333         struct nlattr *mcgrp = NULL;
2334         int i;
2335 
2336         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
2337             ALOGI("No multicast groups found");
2338             return NL_SKIP;
2339         } else {
2340             // ALOGI("Multicast groups attr size = %d",
2341             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
2342         }
2343 
2344         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
2345 
2346             // ALOGI("Processing group");
2347             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
2348             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
2349                 nla_len(mcgrp), NULL);
2350             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
2351             {
2352                 continue;
2353             }
2354 
2355             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
2356             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
2357 
2358             // ALOGI("Found group name %s", grpName);
2359 
2360             if (strncmp(grpName, mGroup, grpNameLen) != 0)
2361                 continue;
2362 
2363             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
2364             break;
2365         }
2366 
2367         return NL_SKIP;
2368     }
2369 
2370 };
2371 
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)2372 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
2373         const char *group)
2374 {
2375     GetMulticastIdCommand cmd(handle, name, group);
2376     int res = cmd.requestResponse();
2377     if (res < 0)
2378         return res;
2379     else
2380         return cmd.getId();
2381 }
2382 
2383 /////////////////////////////////////////////////////////////////////////
2384 
is_wifi_interface(const char * name)2385 static bool is_wifi_interface(const char *name)
2386 {
2387     // filter out bridge interface
2388     if (strstr(name, "br") != NULL) {
2389         return false;
2390     }
2391 
2392     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0
2393         && strncmp(name, "wifi", 4) != 0
2394         && strncmp(name, "swlan", 5) != 0) {
2395         /* not a wifi interface; ignore it */
2396         return false;
2397     } else {
2398         return true;
2399     }
2400 }
2401 
get_interface(const char * name,interface_info * info)2402 static int get_interface(const char *name, interface_info *info)
2403 {
2404     strlcpy(info->name, name, (IFNAMSIZ + 1));
2405     info->id = if_nametoindex(name);
2406     // ALOGI("found an interface : %s, id = %d", name, info->id);
2407     return WIFI_SUCCESS;
2408 }
2409 
wifi_init_interfaces(wifi_handle handle)2410 wifi_error wifi_init_interfaces(wifi_handle handle)
2411 {
2412     hal_info *info = (hal_info *)handle;
2413 
2414     struct dirent *de;
2415 
2416     DIR *d = opendir("/sys/class/net");
2417     if (d == 0)
2418         return WIFI_ERROR_UNKNOWN;
2419 
2420     int n = 0;
2421     while ((de = readdir(d))) {
2422         if (de->d_name[0] == '.')
2423             continue;
2424         if (is_wifi_interface(de->d_name) ) {
2425             n++;
2426         }
2427     }
2428 
2429     closedir(d);
2430 
2431     d = opendir("/sys/class/net");
2432     if (d == 0)
2433         return WIFI_ERROR_UNKNOWN;
2434 
2435     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
2436     if (info->interfaces == NULL) {
2437         ALOGE("%s: Error info->interfaces NULL", __func__);
2438         return WIFI_ERROR_OUT_OF_MEMORY;
2439     }
2440 
2441     int i = 0;
2442     while ((de = readdir(d))) {
2443         if (de->d_name[0] == '.')
2444             continue;
2445         if (is_wifi_interface(de->d_name)) {
2446             interface_info *ifinfo
2447                 = (interface_info *)malloc(sizeof(interface_info));
2448             if (ifinfo == NULL) {
2449                 ALOGE("%s: Error ifinfo NULL", __func__);
2450                 while (i > 0) {
2451                     free(info->interfaces[i-1]);
2452                     i--;
2453                 }
2454                 free(info->interfaces);
2455                 return WIFI_ERROR_OUT_OF_MEMORY;
2456             }
2457             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
2458                 free(ifinfo);
2459                 continue;
2460             }
2461             ifinfo->handle = handle;
2462             info->interfaces[i] = ifinfo;
2463             i++;
2464         }
2465     }
2466 
2467     closedir(d);
2468 
2469     info->num_interfaces = n;
2470 
2471     return WIFI_SUCCESS;
2472 }
2473 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)2474 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
2475         wifi_interface_handle **interfaces)
2476 {
2477     hal_info *info = (hal_info *)handle;
2478 
2479     /* In case of dynamic interface add/remove, interface handles need to be
2480      * updated so that, interface specific APIs could be instantiated.
2481      * Reload here to get interfaces which are dynamically added. */
2482 
2483     if (info->num_interfaces > 0) {
2484         for (int i = 0; i < info->num_interfaces; i++)
2485             free(info->interfaces[i]);
2486         free(info->interfaces);
2487     }
2488 
2489     wifi_error ret = wifi_init_interfaces(handle);
2490     if (ret != WIFI_SUCCESS) {
2491         ALOGE("Failed to init interfaces while wifi_get_ifaces");
2492         return ret;
2493     }
2494 
2495     *interfaces = (wifi_interface_handle *)info->interfaces;
2496     *num = info->num_interfaces;
2497 
2498     return WIFI_SUCCESS;
2499 }
2500 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)2501 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
2502         size_t size)
2503 {
2504     interface_info *info = (interface_info *)handle;
2505     strlcpy(name, info->name, size);
2506     return WIFI_SUCCESS;
2507 }
2508 
2509 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)2510 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
2511         feature_set *set)
2512 {
2513     int ret = 0;
2514     wifi_handle handle = getWifiHandle(iface);
2515     *set = 0;
2516     hal_info *info = getHalInfo(handle);
2517 
2518     ret = acquire_supported_features(iface, set);
2519     if (ret != WIFI_SUCCESS) {
2520         *set = info->supported_feature_set;
2521         ALOGV("Supported feature set acquired at initialization : %" PRIx64, *set);
2522     } else {
2523         info->supported_feature_set = *set;
2524         ALOGV("Supported feature set acquired : %" PRIx64, *set);
2525     }
2526     return WIFI_SUCCESS;
2527 }
2528 
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)2529 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
2530                                        int set_size_max,
2531                                        feature_set set[], int *set_size)
2532 {
2533     wifi_error ret;
2534     struct nlattr *nlData;
2535     WifihalGeneric *vCommand = NULL;
2536     interface_info *ifaceInfo = getIfaceInfo(handle);
2537     wifi_handle wifiHandle = getWifiHandle(handle);
2538 
2539     if (set == NULL) {
2540         ALOGE("%s: NULL set pointer provided. Exit.",
2541             __func__);
2542         return WIFI_ERROR_INVALID_ARGS;
2543     }
2544 
2545     vCommand = new WifihalGeneric(wifiHandle, 0,
2546             OUI_QCA,
2547             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
2548     if (vCommand == NULL) {
2549         ALOGE("%s: Error vCommand NULL", __func__);
2550         return WIFI_ERROR_OUT_OF_MEMORY;
2551     }
2552 
2553     /* Create the message */
2554     ret = vCommand->create();
2555     if (ret != WIFI_SUCCESS)
2556         goto cleanup;
2557 
2558     ret = vCommand->set_iface_id(ifaceInfo->name);
2559     if (ret != WIFI_SUCCESS)
2560         goto cleanup;
2561 
2562     /* Add the vendor specific attributes for the NL command. */
2563     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2564     if (!nlData){
2565         ret = WIFI_ERROR_UNKNOWN;
2566         goto cleanup;
2567     }
2568 
2569     ret = vCommand->put_u32(
2570           QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
2571           set_size_max);
2572     if (ret != WIFI_SUCCESS)
2573         goto cleanup;
2574 
2575     vCommand->attr_end(nlData);
2576 
2577     /* Populate the input received from caller/framework. */
2578     vCommand->setMaxSetSize(set_size_max);
2579     vCommand->setSizePtr(set_size);
2580     vCommand->setConcurrencySet(set);
2581 
2582     ret = vCommand->requestResponse();
2583     if (ret != WIFI_SUCCESS)
2584         ALOGE("%s: requestResponse() error: %d", __func__, ret);
2585 
2586 cleanup:
2587     delete vCommand;
2588     if (ret)
2589         *set_size = 0;
2590     return ret;
2591 }
2592 
2593 
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)2594 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
2595 {
2596     wifi_error ret;
2597     struct nlattr *nlData;
2598     WifiVendorCommand *vCommand = NULL;
2599     interface_info *ifaceInfo = getIfaceInfo(handle);
2600     wifi_handle wifiHandle = getWifiHandle(handle);
2601 
2602     vCommand = new WifiVendorCommand(wifiHandle, 0,
2603             OUI_QCA,
2604             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
2605     if (vCommand == NULL) {
2606         ALOGE("%s: Error vCommand NULL", __func__);
2607         return WIFI_ERROR_OUT_OF_MEMORY;
2608     }
2609 
2610     /* Create the message */
2611     ret = vCommand->create();
2612     if (ret != WIFI_SUCCESS)
2613         goto cleanup;
2614 
2615     ret = vCommand->set_iface_id(ifaceInfo->name);
2616     if (ret != WIFI_SUCCESS)
2617         goto cleanup;
2618 
2619     /* Add the vendor specific attributes for the NL command. */
2620     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2621     if (!nlData){
2622         ret = WIFI_ERROR_UNKNOWN;
2623         goto cleanup;
2624     }
2625 
2626     /* Add the fixed part of the mac_oui to the nl command */
2627     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
2628     if (ret != WIFI_SUCCESS)
2629         goto cleanup;
2630 
2631     vCommand->attr_end(nlData);
2632 
2633     ret = vCommand->requestResponse();
2634     /* Don't check response since we aren't expecting one */
2635 
2636 cleanup:
2637     delete vCommand;
2638     return ret;
2639 }
2640 
wifi_start_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface,u16 ether_type,u8 * ip_packet,u16 ip_packet_len,u8 * src_mac_addr,u8 * dst_mac_addr,u32 period_msec)2641 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
2642                                                wifi_interface_handle iface,
2643                                                u16 ether_type,
2644                                                u8 *ip_packet,
2645                                                u16 ip_packet_len,
2646                                                u8 *src_mac_addr,
2647                                                u8 *dst_mac_addr,
2648                                                u32 period_msec)
2649 {
2650     wifi_error ret;
2651     struct nlattr *nlData;
2652     WifiVendorCommand *vCommand = NULL;
2653 
2654     ret = initialize_vendor_cmd(iface, id,
2655                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2656                                 &vCommand);
2657     if (ret != WIFI_SUCCESS) {
2658         ALOGE("%s: Initialization failed", __func__);
2659         return ret;
2660     }
2661 
2662     ALOGV("ether type 0x%04x\n", ether_type);
2663     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
2664     hexdump(ip_packet, ip_packet_len);
2665     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
2666           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
2667           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
2668 
2669     /* Add the vendor specific attributes for the NL command. */
2670     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2671     if (!nlData){
2672         ret = WIFI_ERROR_UNKNOWN;
2673         goto cleanup;
2674     }
2675 
2676     ret = vCommand->put_u32(
2677             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2678             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
2679     if (ret != WIFI_SUCCESS)
2680         goto cleanup;
2681 
2682     ret = vCommand->put_u32(
2683             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2684             id);
2685     if (ret != WIFI_SUCCESS)
2686         goto cleanup;
2687 
2688     ret = vCommand->put_u16(
2689             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE,
2690             ether_type);
2691     if (ret != WIFI_SUCCESS)
2692         goto cleanup;
2693 
2694     ret = vCommand->put_bytes(
2695             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
2696             (const char *)ip_packet, ip_packet_len);
2697     if (ret != WIFI_SUCCESS)
2698         goto cleanup;
2699 
2700     ret = vCommand->put_addr(
2701             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
2702             src_mac_addr);
2703     if (ret != WIFI_SUCCESS)
2704         goto cleanup;
2705 
2706     ret = vCommand->put_addr(
2707             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
2708             dst_mac_addr);
2709     if (ret != WIFI_SUCCESS)
2710         goto cleanup;
2711 
2712     ret = vCommand->put_u32(
2713             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
2714             period_msec);
2715     if (ret != WIFI_SUCCESS)
2716         goto cleanup;
2717 
2718     vCommand->attr_end(nlData);
2719 
2720     ret = vCommand->requestResponse();
2721     if (ret != WIFI_SUCCESS)
2722         goto cleanup;
2723 
2724 cleanup:
2725     delete vCommand;
2726     return ret;
2727 }
2728 
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)2729 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
2730                                               wifi_interface_handle iface)
2731 {
2732     wifi_error ret;
2733     struct nlattr *nlData;
2734     WifiVendorCommand *vCommand = NULL;
2735 
2736     ret = initialize_vendor_cmd(iface, id,
2737                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2738                                 &vCommand);
2739     if (ret != WIFI_SUCCESS) {
2740         ALOGE("%s: Initialization failed", __func__);
2741         return ret;
2742     }
2743 
2744     /* Add the vendor specific attributes for the NL command. */
2745     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2746     if (!nlData){
2747         ret = WIFI_ERROR_UNKNOWN;
2748         goto cleanup;
2749     }
2750 
2751     ret = vCommand->put_u32(
2752             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2753             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
2754     if (ret != WIFI_SUCCESS)
2755         goto cleanup;
2756 
2757     ret = vCommand->put_u32(
2758             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2759             id);
2760     if (ret != WIFI_SUCCESS)
2761         goto cleanup;
2762 
2763     vCommand->attr_end(nlData);
2764 
2765     ret = vCommand->requestResponse();
2766     if (ret != WIFI_SUCCESS)
2767         goto cleanup;
2768 
2769 cleanup:
2770     delete vCommand;
2771     return ret;
2772 }
2773 
2774 #define PACKET_FILTER_ID 0
2775 
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)2776 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
2777                                          const u8 *program, u32 len)
2778 {
2779     wifi_error ret;
2780     struct nlattr *nlData;
2781     WifiVendorCommand *vCommand = NULL;
2782     u32 current_offset = 0;
2783     wifi_handle wifiHandle = getWifiHandle(iface);
2784     hal_info *info = getHalInfo(wifiHandle);
2785 
2786     /* len=0 clears the filters in driver/firmware */
2787     if (len != 0 && program == NULL) {
2788         ALOGE("%s: No valid program provided. Exit.",
2789             __func__);
2790         return WIFI_ERROR_INVALID_ARGS;
2791     }
2792 
2793     do {
2794         ret = initialize_vendor_cmd(iface, get_requestid(),
2795                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2796                                     &vCommand);
2797         if (ret != WIFI_SUCCESS) {
2798             ALOGE("%s: Initialization failed", __FUNCTION__);
2799             return ret;
2800         }
2801 
2802         /* Add the vendor specific attributes for the NL command. */
2803         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2804         if (!nlData){
2805             ret = WIFI_ERROR_UNKNOWN;
2806             goto cleanup;
2807         }
2808 
2809         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2810                                 QCA_WLAN_SET_PACKET_FILTER);
2811         if (ret != WIFI_SUCCESS)
2812             goto cleanup;
2813         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2814                                 PACKET_FILTER_ID);
2815         if (ret != WIFI_SUCCESS)
2816             goto cleanup;
2817         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2818                                 len);
2819         if (ret != WIFI_SUCCESS)
2820             goto cleanup;
2821         ret = vCommand->put_u32(
2822                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2823                             current_offset);
2824         if (ret != WIFI_SUCCESS)
2825             goto cleanup;
2826 
2827         if (len) {
2828             ret = vCommand->put_bytes(
2829                                      QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2830                                      (char *)&program[current_offset],
2831                                      min(info->firmware_bus_max_size,
2832                                      len-current_offset));
2833             if (ret!= WIFI_SUCCESS) {
2834                 ALOGE("%s: failed to put program", __FUNCTION__);
2835                 goto cleanup;
2836             }
2837         }
2838 
2839         vCommand->attr_end(nlData);
2840 
2841         ret = vCommand->requestResponse();
2842         if (ret != WIFI_SUCCESS) {
2843             ALOGE("%s: requestResponse Error:%d",__func__, ret);
2844             goto cleanup;
2845         }
2846 
2847         /* destroy the object after sending each fragment to driver */
2848         delete vCommand;
2849         vCommand = NULL;
2850 
2851         current_offset += min(info->firmware_bus_max_size, len);
2852     } while (current_offset < len);
2853 
2854     info->apf_enabled = !!len;
2855 
2856 cleanup:
2857     if (vCommand)
2858         delete vCommand;
2859     return ret;
2860 }
2861 
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)2862 static wifi_error wifi_get_packet_filter_capabilities(
2863                 wifi_interface_handle handle, u32 *version, u32 *max_len)
2864 {
2865     wifi_error ret;
2866     struct nlattr *nlData;
2867     WifihalGeneric *vCommand = NULL;
2868     interface_info *ifaceInfo = getIfaceInfo(handle);
2869     wifi_handle wifiHandle = getWifiHandle(handle);
2870 
2871     if (version == NULL || max_len == NULL) {
2872         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
2873             __FUNCTION__);
2874         return WIFI_ERROR_INVALID_ARGS;
2875     }
2876 
2877     vCommand = new WifihalGeneric(wifiHandle, 0,
2878             OUI_QCA,
2879             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2880     if (vCommand == NULL) {
2881         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2882         return WIFI_ERROR_OUT_OF_MEMORY;
2883     }
2884 
2885     /* Create the message */
2886     ret = vCommand->create();
2887     if (ret != WIFI_SUCCESS)
2888         goto cleanup;
2889 
2890     ret = vCommand->set_iface_id(ifaceInfo->name);
2891     if (ret != WIFI_SUCCESS)
2892         goto cleanup;
2893 
2894     /* Add the vendor specific attributes for the NL command. */
2895     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2896     if (!nlData){
2897         ret = WIFI_ERROR_UNKNOWN;
2898         goto cleanup;
2899     }
2900 
2901     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2902                             QCA_WLAN_GET_PACKET_FILTER);
2903     if (ret != WIFI_SUCCESS)
2904         goto cleanup;
2905 
2906     vCommand->attr_end(nlData);
2907 
2908     ret = vCommand->requestResponse();
2909     if (ret != WIFI_SUCCESS) {
2910         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2911         if (ret == WIFI_ERROR_NOT_SUPPORTED) {
2912             /* Packet filtering is not supported currently, so return version
2913              * and length as 0
2914              */
2915             ALOGI("Packet filtering is not supprted");
2916             *version = 0;
2917             *max_len = 0;
2918             ret = WIFI_SUCCESS;
2919         }
2920         goto cleanup;
2921     }
2922 
2923     *version = vCommand->getFilterVersion();
2924     *max_len = vCommand->getFilterLength();
2925 cleanup:
2926     delete vCommand;
2927     return ret;
2928 }
2929 
2930 
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)2931 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
2932                                             u8 enable)
2933 {
2934     wifi_error ret;
2935     struct nlattr *nlData;
2936     WifiVendorCommand *vCommand = NULL;
2937 
2938     ret = initialize_vendor_cmd(iface, get_requestid(),
2939                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
2940                                 &vCommand);
2941     if (ret != WIFI_SUCCESS) {
2942         ALOGE("%s: Initialization failed", __func__);
2943         return ret;
2944     }
2945 
2946     ALOGV("ND offload : %s", enable?"Enable":"Disable");
2947 
2948     /* Add the vendor specific attributes for the NL command. */
2949     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2950     if (!nlData){
2951         ret = WIFI_ERROR_UNKNOWN;
2952         goto cleanup;
2953     }
2954 
2955     ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
2956     if (ret != WIFI_SUCCESS)
2957         goto cleanup;
2958 
2959     vCommand->attr_end(nlData);
2960 
2961     ret = vCommand->requestResponse();
2962 
2963 cleanup:
2964     delete vCommand;
2965     return ret;
2966 }
2967 
2968 /**
2969  * Copy 'len' bytes of raw data from host memory at source address 'program'
2970  * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
2971  * The size of the program lenght passed to the interpreter is set to
2972  * 'progaram_lenght'
2973  *
2974  * The implementation is allowed to tranlate this wrtie into a series of smaller
2975  * writes,but this function is not allowed to return untill all write operations
2976  * have been completed
2977  * additionally visible memory not targeted by this function must remain
2978  * unchanged
2979 
2980  * @param dst_offset write offset in bytes relative to the beginning of the APF
2981  * working memory with logical address 0X000. Must be a multiple of 4
2982  *
2983  * @param program host memory to copy bytes from. Must be 4B aligned
2984  *
2985  * @param len the number of bytes to copy from the bost into the APF working
2986  * memory
2987  *
2988  * @param program_length new length of the program instructions in bytes to pass
2989  * to the interpreter
2990  */
2991 
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)2992 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
2993                                          u32 dst_offset, const u8 *program,
2994                                          u32 len, u32 program_length)
2995 {
2996     wifi_error ret;
2997     struct nlattr *nlData;
2998     WifiVendorCommand *vCommand = NULL;
2999     u32 current_offset = 0;
3000     wifi_handle wifiHandle = getWifiHandle(iface);
3001     hal_info *info = getHalInfo(wifiHandle);
3002 
3003     /* len=0 clears the filters in driver/firmware */
3004     if (len != 0 && program == NULL) {
3005         ALOGE("%s: No valid program provided. Exit.",
3006             __func__);
3007         return WIFI_ERROR_INVALID_ARGS;
3008     }
3009 
3010     do {
3011         ret = initialize_vendor_cmd(iface, get_requestid(),
3012                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
3013                                     &vCommand);
3014         if (ret != WIFI_SUCCESS) {
3015             ALOGE("%s: Initialization failed", __FUNCTION__);
3016             return ret;
3017         }
3018 
3019         /* Add the vendor specific attributes for the NL command. */
3020         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3021         if (!nlData){
3022              ret = WIFI_ERROR_UNKNOWN;
3023              goto cleanup;
3024         }
3025 
3026         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
3027                                  QCA_WLAN_WRITE_PACKET_FILTER);
3028         if (ret != WIFI_SUCCESS)
3029             goto cleanup;
3030         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
3031                                 PACKET_FILTER_ID);
3032         if (ret != WIFI_SUCCESS)
3033             goto cleanup;
3034         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
3035                                 len);
3036         if (ret != WIFI_SUCCESS)
3037             goto cleanup;
3038         ret = vCommand->put_u32(
3039                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
3040                             dst_offset + current_offset);
3041         if (ret != WIFI_SUCCESS)
3042             goto cleanup;
3043         ret = vCommand->put_u32(
3044                            QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
3045                             program_length);
3046         if (ret != WIFI_SUCCESS)
3047             goto cleanup;
3048 
3049         ret = vCommand->put_bytes(
3050                                  QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
3051                                  (char *)&program[current_offset],
3052                                  min(info->firmware_bus_max_size,
3053                                  len - current_offset));
3054         if (ret!= WIFI_SUCCESS) {
3055             ALOGE("%s: failed to put program", __FUNCTION__);
3056             goto cleanup;
3057         }
3058 
3059         vCommand->attr_end(nlData);
3060 
3061         ret = vCommand->requestResponse();
3062         if (ret != WIFI_SUCCESS) {
3063             ALOGE("%s: requestResponse Error:%d",__func__, ret);
3064             goto cleanup;
3065         }
3066 
3067         /* destroy the object after sending each fragment to driver */
3068         delete vCommand;
3069         vCommand = NULL;
3070 
3071         current_offset += min(info->firmware_bus_max_size,
3072                                          len - current_offset);
3073     } while (current_offset < len);
3074 
3075 cleanup:
3076     if (vCommand)
3077         delete vCommand;
3078     return ret;
3079 }
3080 
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)3081 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
3082                                         u32 enable)
3083 {
3084     wifi_error ret;
3085     struct nlattr *nlData;
3086     WifiVendorCommand *vCommand = NULL;
3087     u32 subcmd;
3088     wifi_handle wifiHandle = getWifiHandle(handle);
3089     hal_info *info = getHalInfo(wifiHandle);
3090 
3091     ret = initialize_vendor_cmd(handle, get_requestid(),
3092                                 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
3093                                 &vCommand);
3094 
3095     if (ret != WIFI_SUCCESS) {
3096         ALOGE("%s: Initialization failed", __func__);
3097         return ret;
3098     }
3099     /* Add the vendor specific attributes for the NL command. */
3100     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3101     if (!nlData){
3102         ret = WIFI_ERROR_UNKNOWN;
3103         goto cleanup;
3104     }
3105 
3106     subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
3107                       QCA_WLAN_DISABLE_PACKET_FILTER;
3108     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
3109                             subcmd);
3110     if (ret != WIFI_SUCCESS)
3111             goto cleanup;
3112 
3113     vCommand->attr_end(nlData);
3114     ret = vCommand->requestResponse();
3115 
3116     if (ret != WIFI_SUCCESS) {
3117         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
3118         goto cleanup;
3119     }
3120 
3121     info->apf_enabled = !!enable;
3122 
3123 cleanup:
3124     delete vCommand;
3125     return ret;
3126 
3127 }
3128 
3129 /**
3130  * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
3131  * memory  to host memory starting at offset src_offset into host memory
3132  * pointed to by host_dst.
3133  * Memory can be text, data or some combination of the two. The implementiion is
3134  * allowed to translate this read into a series of smaller reads, but this
3135  * function is not allowed to return untill all the reads operations
3136  * into host_dst have been completed.
3137  *
3138  * @param src_offset offset in bytes of destination memory within APF working
3139  * memory
3140  *
3141  * @param host_dst host memory to copy into. Must be 4B aligned.
3142  *
3143  * @param length the number of bytes to copy from the APF working memory to the
3144  * host.
3145  */
3146 
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)3147 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
3148                                           u32 src_offset, u8 *host_dst, u32 length)
3149 {
3150     wifi_error ret = WIFI_ERROR_UNKNOWN;
3151     struct nlattr *nlData;
3152     WifihalGeneric *vCommand = NULL;
3153     interface_info *ifaceInfo = getIfaceInfo(handle);
3154     wifi_handle wifiHandle = getWifiHandle(handle);
3155     hal_info *info = getHalInfo(wifiHandle);
3156 
3157     /* Length to be passed to this function should be non-zero
3158      * Return invalid argument if length is passed as zero
3159      */
3160     if (length == 0)
3161         return  WIFI_ERROR_INVALID_ARGS;
3162 
3163     /*Temporary varibles to support the read complete length in chunks */
3164     u8 *temp_host_dst;
3165     u32 remainingLengthToBeRead, currentLength;
3166     u8 apf_locally_disabled = 0;
3167 
3168     /*Initializing the temporary variables*/
3169     temp_host_dst = host_dst;
3170     remainingLengthToBeRead = length;
3171 
3172     if (info->apf_enabled) {
3173         /* Disable APF only when not disabled by framework before calling
3174          * wifi_read_packet_filter()
3175          */
3176         ret = wifi_enable_packet_filter(handle, 0);
3177         if (ret != WIFI_SUCCESS) {
3178             ALOGE("%s: Failed to disable APF", __FUNCTION__);
3179             return ret;
3180         }
3181         apf_locally_disabled = 1;
3182     }
3183     /**
3184      * Read the complete length in chunks of size less or equal to firmware bus
3185      * max size
3186      */
3187     while (remainingLengthToBeRead)
3188     {
3189         vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
3190                                       QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
3191 
3192         if (vCommand == NULL) {
3193             ALOGE("%s: Error vCommand NULL", __FUNCTION__);
3194             ret = WIFI_ERROR_OUT_OF_MEMORY;
3195             break;
3196         }
3197 
3198         /* Create the message */
3199         ret = vCommand->create();
3200         if (ret != WIFI_SUCCESS)
3201             break;
3202         ret = vCommand->set_iface_id(ifaceInfo->name);
3203         if (ret != WIFI_SUCCESS)
3204             break;
3205         /* Add the vendor specific attributes for the NL command. */
3206         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3207         if (!nlData)
3208             break;
3209         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
3210                                 QCA_WLAN_READ_PACKET_FILTER);
3211         if (ret != WIFI_SUCCESS)
3212             break;
3213 
3214         currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
3215 
3216         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
3217                                 currentLength);
3218         if (ret != WIFI_SUCCESS)
3219             break;
3220         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
3221                                 src_offset);
3222         if (ret != WIFI_SUCCESS)
3223             break;
3224 
3225         vCommand->setPacketBufferParams(temp_host_dst, currentLength);
3226         vCommand->attr_end(nlData);
3227         ret = vCommand->requestResponse();
3228 
3229         if (ret != WIFI_SUCCESS) {
3230             ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
3231                   __FUNCTION__, ret, currentLength, src_offset);
3232             break;
3233         }
3234 
3235         remainingLengthToBeRead -= currentLength;
3236         temp_host_dst += currentLength;
3237         src_offset += currentLength;
3238         delete vCommand;
3239         vCommand = NULL;
3240     }
3241 
3242     /* Re enable APF only when disabled above within this API */
3243     if (apf_locally_disabled) {
3244         wifi_error status;
3245         status = wifi_enable_packet_filter(handle, 1);
3246         if (status != WIFI_SUCCESS)
3247             ALOGE("%s: Failed to enable APF", __FUNCTION__);
3248         /* Prefer to return read status if read fails */
3249         if (ret == WIFI_SUCCESS)
3250             ret = status;
3251     }
3252 
3253     delete vCommand;
3254     return ret;
3255 }
3256 
3257 class GetSupportedVendorCmd : public WifiCommand
3258 {
3259 private:
3260     u32 mVendorCmds[256];
3261     int mNumOfVendorCmds;
3262 
3263 public:
GetSupportedVendorCmd(wifi_handle handle)3264     GetSupportedVendorCmd(wifi_handle handle) : WifiCommand(handle, 0)
3265     {
3266         mNumOfVendorCmds = 0;
3267         memset(mVendorCmds, 0, 256);
3268     }
3269 
create()3270     virtual wifi_error create() {
3271         int nl80211_id = genl_ctrl_resolve(mInfo->cmd_sock, "nl80211");
3272         wifi_error ret = mMsg.create(nl80211_id, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, 0);
3273         mMsg.put_flag(NL80211_ATTR_SPLIT_WIPHY_DUMP);
3274 
3275         return ret;
3276     }
3277 
requestResponse()3278     virtual wifi_error requestResponse() {
3279         return WifiCommand::requestResponse(mMsg);
3280     }
set_iface_id(const char * name)3281     virtual wifi_error set_iface_id(const char* name) {
3282         unsigned ifindex = if_nametoindex(name);
3283         return mMsg.set_iface_id(ifindex);
3284     }
3285 
handleResponse(WifiEvent & reply)3286     virtual int handleResponse(WifiEvent& reply) {
3287         struct nlattr **tb = reply.attributes();
3288 
3289         if (tb[NL80211_ATTR_VENDOR_DATA]) {
3290             struct nlattr *nl;
3291             int rem, i = 0;
3292 
3293             for_each_attr(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
3294                 struct nl80211_vendor_cmd_info *vinfo;
3295                 if (nla_len(nl) != sizeof(*vinfo)) {
3296                     ALOGE("Unexpected vendor data info found in attribute");
3297                     continue;
3298                 }
3299                 vinfo = (struct nl80211_vendor_cmd_info *)nla_data(nl);
3300                 if (vinfo->vendor_id == OUI_QCA) {
3301                     mVendorCmds[i] = vinfo->subcmd;
3302                     i++;
3303                 }
3304             }
3305             mNumOfVendorCmds = i;
3306         }
3307         return NL_SKIP;
3308     }
3309 
isVendorCmdSupported(u32 cmdId)3310     int isVendorCmdSupported(u32 cmdId) {
3311         int i, ret;
3312 
3313         ret = 0;
3314         for (i = 0; i < mNumOfVendorCmds; i++) {
3315             if (cmdId == mVendorCmds[i]) {
3316                 ret = 1;
3317                 break;
3318             }
3319         }
3320 
3321         return ret;
3322     }
3323 };
3324 
wifi_is_nan_ext_cmd_supported(wifi_interface_handle iface_handle)3325 static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle iface_handle)
3326 {
3327     wifi_error ret;
3328     wifi_handle handle = getWifiHandle(iface_handle);
3329     interface_info *info = getIfaceInfo(iface_handle);
3330     GetSupportedVendorCmd cmd(handle);
3331 
3332     ret = cmd.create();
3333     if (ret != WIFI_SUCCESS) {
3334         ALOGE("%s: create command failed", __func__);
3335         return 0;
3336     }
3337 
3338     ret = cmd.set_iface_id(info->name);
3339     if (ret != WIFI_SUCCESS) {
3340         ALOGE("%s: set iface id failed", __func__);
3341         return 0;
3342     }
3343 
3344     ret = cmd.requestResponse();
3345     if (ret != WIFI_SUCCESS) {
3346         ALOGE("Failed to query nan_ext command support, ret=%d", ret);
3347         return 0;
3348     } else {
3349         return cmd.isVendorCmdSupported(QCA_NL80211_VENDOR_SUBCMD_NAN_EXT);
3350     }
3351 }
3352 
wifi_get_radar_history(wifi_interface_handle handle,radar_history_result * resultBuf,int resultBufSize,int * numResults)3353 wifi_error wifi_get_radar_history(wifi_interface_handle handle,
3354        radar_history_result *resultBuf, int resultBufSize, int *numResults)
3355 {
3356     wifi_error ret;
3357     struct nlattr *nlData;
3358     WifihalGeneric *vCommand = NULL;
3359     interface_info *ifaceInfo = NULL;
3360     wifi_handle wifiHandle = NULL;
3361 
3362     ALOGI("%s: enter", __FUNCTION__);
3363 
3364     if (!handle) {
3365         ALOGE("%s: Error, wifi_interface_handle NULL", __FUNCTION__);
3366         return WIFI_ERROR_UNKNOWN;
3367     }
3368 
3369     ifaceInfo = getIfaceInfo(handle);
3370     if (!ifaceInfo) {
3371         ALOGE("%s: Error, interface_info NULL", __FUNCTION__);
3372         return WIFI_ERROR_UNKNOWN;
3373     }
3374 
3375     wifiHandle = getWifiHandle(handle);
3376     if (!wifiHandle) {
3377         ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
3378         return WIFI_ERROR_UNKNOWN;
3379     }
3380 
3381     if (resultBuf == NULL || numResults == NULL) {
3382         ALOGE("%s: Error, resultsBuf/numResults NULL pointer", __FUNCTION__);
3383         return WIFI_ERROR_INVALID_ARGS;
3384     }
3385 
3386     vCommand = new WifihalGeneric(wifiHandle, 0,
3387             OUI_QCA,
3388             QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY);
3389     if (vCommand == NULL) {
3390         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
3391         return WIFI_ERROR_OUT_OF_MEMORY;
3392     }
3393 
3394     /* Create the message */
3395     ret = vCommand->create();
3396     if (ret != WIFI_SUCCESS)
3397         goto cleanup;
3398 
3399     ret = vCommand->set_iface_id(ifaceInfo->name);
3400     if (ret != WIFI_SUCCESS)
3401         goto cleanup;
3402 
3403     /* Add the vendor specific attributes for the NL command. */
3404     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3405     if (!nlData){
3406         ret = WIFI_ERROR_UNKNOWN;
3407         goto cleanup;
3408     }
3409 
3410     vCommand->attr_end(nlData);
3411 
3412     ret = vCommand->requestResponse();
3413     if (ret != WIFI_SUCCESS) {
3414         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
3415         goto cleanup;
3416     }
3417 
3418     /* No more data, copy the parsed results into the caller's results buffer */
3419     ret = vCommand->copyCachedRadarHistory(
3420             resultBuf, resultBufSize, numResults);
3421 
3422 cleanup:
3423     vCommand->freeCachedRadarHistory();
3424     delete vCommand;
3425     return ret;
3426 }
3427 
3428 #define SIZEOF_TLV_HDR 4
3429 #define OEM_DATA_TLV_TYPE_HEADER 1
3430 #define OEM_DATA_CMD_SET_SKIP_CAC   18
3431 
3432 struct oem_data_header {
3433     u16 cmd_id;
3434     u16 request_idx;
3435 };
3436 
wifi_add_oem_data_head(int cmd_id,u8 * oem_buf,size_t max)3437 static int wifi_add_oem_data_head(int cmd_id, u8* oem_buf, size_t max)
3438 {
3439     struct oem_data_header oem_hdr;
3440     oem_hdr.cmd_id = cmd_id;
3441     oem_hdr.request_idx = 0;
3442 
3443     if ((SIZEOF_TLV_HDR + sizeof(oem_hdr)) > max) {
3444         return 0;
3445     }
3446 
3447     wifi_put_le16(oem_buf, OEM_DATA_TLV_TYPE_HEADER);
3448     oem_buf += 2;
3449     wifi_put_le16(oem_buf, sizeof(oem_hdr));
3450     oem_buf += 2;
3451     memcpy(oem_buf, (u8 *)&oem_hdr, sizeof(oem_hdr));
3452     oem_buf += sizeof(oem_hdr);
3453 
3454     return (SIZEOF_TLV_HDR + sizeof(oem_hdr));
3455 }
3456 
3457 
3458 /**
3459  * This cmd takes effect on the interface the cmd is sent to.
3460  * This cmd loses effect when interface is down. (i.e. set mac addr)
3461  */
wifi_disable_next_cac(wifi_interface_handle handle)3462 wifi_error wifi_disable_next_cac(wifi_interface_handle handle) {
3463     wifi_error ret;
3464     interface_info *ifaceInfo = NULL;
3465     struct nlattr *nlData;
3466     WifiVendorCommand *vCommand = NULL;
3467     u8 oem_buf[16];
3468     int oem_buf_len = 0;
3469 
3470     if (!handle) {
3471         ALOGE("%s: Error, wifi_interface_handle NULL", __FUNCTION__);
3472         return WIFI_ERROR_UNKNOWN;
3473     }
3474 
3475     ifaceInfo = getIfaceInfo(handle);
3476     if (!ifaceInfo) {
3477         ALOGE("%s: Error, interface_info NULL", __FUNCTION__);
3478         return WIFI_ERROR_UNKNOWN;
3479     }
3480 
3481     ALOGI("%s: enter - iface=%s", __FUNCTION__, ifaceInfo->name);
3482     oem_buf_len = wifi_add_oem_data_head(
3483             OEM_DATA_CMD_SET_SKIP_CAC, oem_buf, sizeof(oem_buf));
3484     if (oem_buf_len <= 0) {
3485         ALOGE("%s: fill oem data head failed, cmd=%d", __func__,
3486                 OEM_DATA_CMD_SET_SKIP_CAC);
3487         return WIFI_ERROR_UNKNOWN;
3488     }
3489 
3490     ret = initialize_vendor_cmd(handle, get_requestid(),
3491                                 QCA_NL80211_VENDOR_SUBCMD_OEM_DATA,
3492                                 &vCommand);
3493 
3494     if (ret != WIFI_SUCCESS) {
3495         ALOGE("%s: Initialization failed", __func__);
3496         return ret;
3497     }
3498 
3499     /* Add the vendor specific attributes for the NL command. */
3500     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3501     if (!nlData) {
3502         ret = WIFI_ERROR_OUT_OF_MEMORY;
3503         goto cleanup;
3504     }
3505 
3506     ret = vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
3507                               (char *)oem_buf, oem_buf_len);
3508     if (ret != WIFI_SUCCESS)
3509         goto cleanup;
3510 
3511     vCommand->attr_end(nlData);
3512     ret = vCommand->requestResponse();
3513 
3514     if (ret != WIFI_SUCCESS) {
3515         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
3516         goto cleanup;
3517     }
3518 
3519 cleanup:
3520     delete vCommand;
3521     return ret;
3522 }
3523