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