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