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 
17 #include <stdint.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <sys/socket.h>
21 #include <netlink/genl/genl.h>
22 #include <netlink/genl/family.h>
23 #include <netlink/genl/ctrl.h>
24 #include <linux/rtnetlink.h>
25 #include <netpacket/packet.h>
26 #include <linux/filter.h>
27 #include <linux/errqueue.h>
28 
29 #include <linux/pkt_sched.h>
30 #include <netlink/object-api.h>
31 #include <netlink/netlink.h>
32 #include <netlink/socket.h>
33 #include <netlink-private/object-api.h>
34 #include <netlink-private/types.h>
35 
36 #include "nl80211_copy.h"
37 
38 #include <dirent.h>
39 #include <net/if.h>
40 #include <netinet/in.h>
41 #include <cld80211_lib.h>
42 
43 #include <sys/types.h>
44 #include <unistd.h>
45 
46 #include "sync.h"
47 
48 #define LOG_TAG  "WifiHAL"
49 
50 #include "wifi_hal.h"
51 #include "common.h"
52 #include "cpp_bindings.h"
53 #include "ifaceeventhandler.h"
54 #include "wifiloggercmd.h"
55 #include "vendor_definitions.h"
56 
57 /*
58  BUGBUG: normally, libnl allocates ports for all connections it makes; but
59  being a static library, it doesn't really know how many other netlink
60  connections are made by the same process, if connections come from different
61  shared libraries. These port assignments exist to solve that
62  problem - temporarily. We need to fix libnl to try and allocate ports across
63  the entire process.
64  */
65 
66 #define WIFI_HAL_CMD_SOCK_PORT       644
67 #define WIFI_HAL_EVENT_SOCK_PORT     645
68 
69 /*
70  * Defines for wifi_wait_for_driver_ready()
71  * Specify durations between polls and max wait time
72  */
73 #define POLL_DRIVER_DURATION_US (100000)
74 #define POLL_DRIVER_MAX_TIME_MS (10000)
75 
76 static void internal_event_handler(wifi_handle handle, int events,
77                                    struct nl_sock *sock);
78 static int internal_valid_message_handler(nl_msg *msg, void *arg);
79 static int user_sock_message_handler(nl_msg *msg, void *arg);
80 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
81         const char *group);
82 static int wifi_add_membership(wifi_handle handle, const char *group);
83 static wifi_error wifi_init_interfaces(wifi_handle handle);
84 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
85                                          const u8 *program, u32 len);
86 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
87                                               u32 *version, u32 *max_len);
88 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
89                                    u32 src_offset, u8 *host_dst, u32 length);
90 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
91                                             u8 enable);
92 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
93                              WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
94 
95 /* Initialize/Cleanup */
96 
wifi_get_iface_handle(wifi_handle handle,char * name)97 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
98 {
99     hal_info *info = (hal_info *)handle;
100     for (int i=0;i<info->num_interfaces;i++)
101     {
102         if (!strcmp(info->interfaces[i]->name, name))
103         {
104             return ((wifi_interface_handle )(info->interfaces)[i]);
105         }
106     }
107     return NULL;
108 }
109 
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)110 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
111 {
112     /* Release local port pool maintained by libnl and assign a own port
113      * identifier to the socket.
114      */
115     nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
116 }
117 
wifi_create_nl_socket(int port,int protocol)118 static nl_sock * wifi_create_nl_socket(int port, int protocol)
119 {
120     // ALOGI("Creating socket");
121     struct nl_sock *sock = nl_socket_alloc();
122     if (sock == NULL) {
123         ALOGE("Failed to create NL socket");
124         return NULL;
125     }
126 
127     wifi_socket_set_local_port(sock, port);
128 
129     if (nl_connect(sock, protocol)) {
130         ALOGE("Could not connect handle");
131         nl_socket_free(sock);
132         return NULL;
133     }
134 
135     return sock;
136 }
137 
ack_handler(struct nl_msg * msg,void * arg)138 int ack_handler(struct nl_msg *msg, void *arg)
139 {
140     int *err = (int *)arg;
141     *err = 0;
142     return NL_STOP;
143 }
144 
finish_handler(struct nl_msg * msg,void * arg)145 int finish_handler(struct nl_msg *msg, void *arg)
146 {
147     int *ret = (int *)arg;
148     *ret = 0;
149     return NL_SKIP;
150 }
151 
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)152 int error_handler(struct sockaddr_nl *nla,
153                   struct nlmsgerr *err, void *arg)
154 {
155     int *ret = (int *)arg;
156     *ret = err->error;
157 
158     ALOGV("%s invoked with error: %d", __func__, err->error);
159     return NL_SKIP;
160 }
no_seq_check(struct nl_msg * msg,void * arg)161 static int no_seq_check(struct nl_msg *msg, void *arg)
162 {
163     return NL_OK;
164 }
165 
acquire_supported_features(wifi_interface_handle iface,feature_set * set)166 static wifi_error acquire_supported_features(wifi_interface_handle iface,
167         feature_set *set)
168 {
169     wifi_error ret;
170     interface_info *iinfo = getIfaceInfo(iface);
171     wifi_handle handle = getWifiHandle(iface);
172     *set = 0;
173 
174     WifihalGeneric supportedFeatures(handle, 0,
175             OUI_QCA,
176             QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
177 
178     /* create the message */
179     ret = supportedFeatures.create();
180     if (ret != WIFI_SUCCESS)
181         goto cleanup;
182 
183     ret = supportedFeatures.set_iface_id(iinfo->name);
184     if (ret != WIFI_SUCCESS)
185         goto cleanup;
186 
187     ret = supportedFeatures.requestResponse();
188     if (ret != WIFI_SUCCESS) {
189         ALOGE("%s: requestResponse Error:%d",__func__, ret);
190         goto cleanup;
191     }
192 
193     supportedFeatures.getResponseparams(set);
194 
195 cleanup:
196     return ret;
197 }
198 
wifi_get_capabilities(wifi_interface_handle handle)199 static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
200 {
201     wifi_error ret;
202     int requestId;
203     WifihalGeneric *wifihalGeneric;
204     wifi_handle wifiHandle = getWifiHandle(handle);
205     hal_info *info = getHalInfo(wifiHandle);
206 
207     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
208         ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
209         return WIFI_ERROR_NOT_SUPPORTED;
210     }
211 
212     /* No request id from caller, so generate one and pass it on to the driver.
213      * Generate it randomly.
214      */
215     requestId = get_requestid();
216 
217     wifihalGeneric = new WifihalGeneric(
218                             wifiHandle,
219                             requestId,
220                             OUI_QCA,
221                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
222     if (!wifihalGeneric) {
223         ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
224         return WIFI_ERROR_OUT_OF_MEMORY;
225     }
226 
227     ret = wifihalGeneric->wifiGetCapabilities(handle);
228 
229     delete wifihalGeneric;
230     return ret;
231 }
232 
get_firmware_bus_max_size_supported(wifi_interface_handle iface)233 static wifi_error get_firmware_bus_max_size_supported(
234                                                 wifi_interface_handle iface)
235 {
236     wifi_error ret;
237     interface_info *iinfo = getIfaceInfo(iface);
238     wifi_handle handle = getWifiHandle(iface);
239     hal_info *info = (hal_info *)handle;
240 
241     WifihalGeneric busSizeSupported(handle, 0,
242                                     OUI_QCA,
243                                     QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
244 
245     /* create the message */
246     ret = busSizeSupported.create();
247     if (ret != WIFI_SUCCESS)
248         goto cleanup;
249 
250     ret = busSizeSupported.set_iface_id(iinfo->name);
251     if (ret != WIFI_SUCCESS)
252         goto cleanup;
253 
254     ret = busSizeSupported.requestResponse();
255     if (ret != WIFI_SUCCESS) {
256         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
257         goto cleanup;
258     }
259     info->firmware_bus_max_size = busSizeSupported.getBusSize();
260 
261 cleanup:
262     return ret;
263 }
264 
wifi_init_user_sock(hal_info * info)265 static wifi_error wifi_init_user_sock(hal_info *info)
266 {
267     struct nl_sock *user_sock =
268         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
269     if (user_sock == NULL) {
270         ALOGE("Could not create diag sock");
271         return WIFI_ERROR_UNKNOWN;
272     }
273 
274     /* Set the socket buffer size */
275     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
276         ALOGE("Could not set size for user_sock: %s",
277                    strerror(errno));
278         /* continue anyway with the default (smaller) buffer */
279     }
280     else {
281         ALOGV("nl_socket_set_buffer_size successful for user_sock");
282     }
283 
284     struct nl_cb *cb = nl_socket_get_cb(user_sock);
285     if (cb == NULL) {
286         ALOGE("Could not get cb");
287         return WIFI_ERROR_UNKNOWN;
288     }
289 
290     info->user_sock_arg = 1;
291     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
292     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
293     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
294     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
295 
296     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
297     nl_cb_put(cb);
298 
299     int ret = nl_socket_add_membership(user_sock, 1);
300     if (ret < 0) {
301         ALOGE("Could not add membership");
302         return WIFI_ERROR_UNKNOWN;
303     }
304 
305     info->user_sock = user_sock;
306     ALOGV("Initiialized diag sock successfully");
307     return WIFI_SUCCESS;
308 }
309 
wifi_init_cld80211_sock_cb(hal_info * info)310 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
311 {
312     struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
313     if (cb == NULL) {
314         ALOGE("Could not get cb");
315         return WIFI_ERROR_UNKNOWN;
316     }
317 
318     info->user_sock_arg = 1;
319     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
320     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
321     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
322     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
323 
324     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
325     nl_cb_put(cb);
326 
327     return WIFI_SUCCESS;
328 }
329 
330 
331 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)332 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
333     if (fn == NULL) {
334         return WIFI_ERROR_UNKNOWN;
335     }
336 
337     fn->wifi_initialize = wifi_initialize;
338     fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
339     fn->wifi_cleanup = wifi_cleanup;
340     fn->wifi_event_loop = wifi_event_loop;
341     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
342     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
343     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
344     fn->wifi_get_ifaces = wifi_get_ifaces;
345     fn->wifi_get_iface_name = wifi_get_iface_name;
346     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
347     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
348     fn->wifi_start_gscan = wifi_start_gscan;
349     fn->wifi_stop_gscan = wifi_stop_gscan;
350     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
351     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
352     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
353     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
354     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
355     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
356     fn->wifi_set_link_stats = wifi_set_link_stats;
357     fn->wifi_get_link_stats = wifi_get_link_stats;
358     fn->wifi_clear_link_stats = wifi_clear_link_stats;
359     fn->wifi_get_valid_channels = wifi_get_valid_channels;
360     fn->wifi_rtt_range_request = wifi_rtt_range_request;
361     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
362     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
363     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
364     fn->wifi_enable_responder = wifi_enable_responder;
365     fn->wifi_disable_responder = wifi_disable_responder;
366     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
367     fn->wifi_start_logging = wifi_start_logging;
368     fn->wifi_set_epno_list = wifi_set_epno_list;
369     fn->wifi_reset_epno_list = wifi_reset_epno_list;
370     fn->wifi_set_country_code = wifi_set_country_code;
371     fn->wifi_enable_tdls = wifi_enable_tdls;
372     fn->wifi_disable_tdls = wifi_disable_tdls;
373     fn->wifi_get_tdls_status = wifi_get_tdls_status;
374     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
375     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
376     fn->wifi_set_log_handler = wifi_set_log_handler;
377     fn->wifi_reset_log_handler = wifi_reset_log_handler;
378     fn->wifi_set_alert_handler = wifi_set_alert_handler;
379     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
380     fn->wifi_get_firmware_version = wifi_get_firmware_version;
381     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
382     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
383     fn->wifi_get_ring_data = wifi_get_ring_data;
384     fn->wifi_get_driver_version = wifi_get_driver_version;
385     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
386     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
387     fn->wifi_set_lci = wifi_set_lci;
388     fn->wifi_set_lcr = wifi_set_lcr;
389     fn->wifi_start_sending_offloaded_packet =
390             wifi_start_sending_offloaded_packet;
391     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
392     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
393     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
394     fn->wifi_nan_enable_request = nan_enable_request;
395     fn->wifi_nan_disable_request = nan_disable_request;
396     fn->wifi_nan_publish_request = nan_publish_request;
397     fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
398     fn->wifi_nan_subscribe_request = nan_subscribe_request;
399     fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
400     fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
401     fn->wifi_nan_stats_request = nan_stats_request;
402     fn->wifi_nan_config_request = nan_config_request;
403     fn->wifi_nan_tca_request = nan_tca_request;
404     fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
405     fn->wifi_nan_register_handler = nan_register_handler;
406     fn->wifi_nan_get_version = nan_get_version;
407     fn->wifi_set_packet_filter = wifi_set_packet_filter;
408     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
409     fn->wifi_read_packet_filter = wifi_read_packet_filter;
410     fn->wifi_nan_get_capabilities = nan_get_capabilities;
411     fn->wifi_nan_data_interface_create = nan_data_interface_create;
412     fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
413     fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
414     fn->wifi_nan_data_indication_response = nan_data_indication_response;
415     fn->wifi_nan_data_end = nan_data_end;
416     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
417     fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
418     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
419     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
420     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
421     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
422     fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
423     fn->wifi_configure_roaming = wifi_configure_roaming;
424     fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
425     fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
426     fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
427     fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
428 
429     return WIFI_SUCCESS;
430 }
431 
cld80211lib_cleanup(hal_info * info)432 static void cld80211lib_cleanup(hal_info *info)
433 {
434     if (!info->cldctx)
435         return;
436     cld80211_remove_mcast_group(info->cldctx, "host_logs");
437     cld80211_remove_mcast_group(info->cldctx, "fw_logs");
438     cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
439     cld80211_remove_mcast_group(info->cldctx, "diag_events");
440     cld80211_remove_mcast_group(info->cldctx, "fatal_events");
441     exit_cld80211_recv(info->cldctx);
442     cld80211_deinit(info->cldctx);
443     info->cldctx = NULL;
444 }
445 
wifi_get_iface_id(hal_info * info,const char * iface)446 static int wifi_get_iface_id(hal_info *info, const char *iface)
447 {
448     int i;
449     for (i = 0; i < info->num_interfaces; i++)
450         if (!strcmp(info->interfaces[i]->name, iface))
451             return i;
452     return -1;
453 }
454 
wifi_initialize(wifi_handle * handle)455 wifi_error wifi_initialize(wifi_handle *handle)
456 {
457     int err = 0;
458     wifi_error ret = WIFI_SUCCESS;
459     wifi_interface_handle iface_handle;
460     struct nl_sock *cmd_sock = NULL;
461     struct nl_sock *event_sock = NULL;
462     struct nl_cb *cb = NULL;
463     int status = 0;
464     int index;
465 
466     ALOGI("Initializing wifi");
467     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
468     if (info == NULL) {
469         ALOGE("Could not allocate hal_info");
470         return WIFI_ERROR_OUT_OF_MEMORY;
471     }
472 
473     memset(info, 0, sizeof(*info));
474 
475     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
476                                                      NETLINK_GENERIC);
477     if (cmd_sock == NULL) {
478         ALOGE("Failed to create command socket port");
479         ret = WIFI_ERROR_UNKNOWN;
480         goto unload;
481     }
482 
483     /* Set the socket buffer size */
484     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
485         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
486                    strerror(errno));
487         /* continue anyway with the default (smaller) buffer */
488     }
489 
490     event_sock =
491         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
492     if (event_sock == NULL) {
493         ALOGE("Failed to create event socket port");
494         ret = WIFI_ERROR_UNKNOWN;
495         goto unload;
496     }
497 
498     /* Set the socket buffer size */
499     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
500         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
501                    strerror(errno));
502         /* continue anyway with the default (smaller) buffer */
503     }
504 
505     cb = nl_socket_get_cb(event_sock);
506     if (cb == NULL) {
507         ALOGE("Failed to get NL control block for event socket port");
508         ret = WIFI_ERROR_UNKNOWN;
509         goto unload;
510     }
511 
512     err = 1;
513     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
514     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
515     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
516     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
517 
518     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
519             info);
520     nl_cb_put(cb);
521 
522     info->cmd_sock = cmd_sock;
523     info->event_sock = event_sock;
524     info->clean_up = false;
525     info->in_event_loop = false;
526 
527     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
528     if (info->event_cb == NULL) {
529         ALOGE("Could not allocate event_cb");
530         ret = WIFI_ERROR_OUT_OF_MEMORY;
531         goto unload;
532     }
533     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
534     info->num_event_cb = 0;
535 
536     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
537     if (info->nl80211_family_id < 0) {
538         ALOGE("Could not resolve nl80211 familty id");
539         ret = WIFI_ERROR_UNKNOWN;
540         goto unload;
541     }
542 
543     pthread_mutex_init(&info->cb_lock, NULL);
544     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
545 
546     *handle = (wifi_handle) info;
547 
548     wifi_add_membership(*handle, "scan");
549     wifi_add_membership(*handle, "mlme");
550     wifi_add_membership(*handle, "regulatory");
551     wifi_add_membership(*handle, "vendor");
552 
553     info->cldctx = cld80211_init();
554     if (info->cldctx != NULL) {
555         info->user_sock = info->cldctx->sock;
556         ret = wifi_init_cld80211_sock_cb(info);
557         if (ret != WIFI_SUCCESS) {
558             ALOGE("Could not set cb for CLD80211 family");
559             goto cld80211_cleanup;
560         }
561 
562         status = cld80211_add_mcast_group(info->cldctx, "host_logs");
563         if (status) {
564             ALOGE("Failed to add mcast group host_logs :%d", status);
565             goto cld80211_cleanup;
566         }
567         status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
568         if (status) {
569             ALOGE("Failed to add mcast group fw_logs :%d", status);
570             goto cld80211_cleanup;
571         }
572         status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
573         if (status) {
574             ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
575             goto cld80211_cleanup;
576         }
577         status = cld80211_add_mcast_group(info->cldctx, "diag_events");
578         if (status) {
579             ALOGE("Failed to add mcast group diag_events :%d", status);
580             goto cld80211_cleanup;
581         }
582         status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
583         if (status) {
584             ALOGE("Failed to add mcast group fatal_events :%d", status);
585             goto cld80211_cleanup;
586         }
587     } else {
588         ret = wifi_init_user_sock(info);
589         if (ret != WIFI_SUCCESS) {
590             ALOGE("Failed to alloc user socket");
591             goto unload;
592         }
593     }
594 
595     ret = wifi_init_interfaces(*handle);
596     if (ret != WIFI_SUCCESS) {
597         ALOGE("Failed to init interfaces");
598         goto unload;
599     }
600 
601     if (info->num_interfaces == 0) {
602         ALOGE("No interfaces found");
603         ret = WIFI_ERROR_UNINITIALIZED;
604         goto unload;
605     }
606 
607     index = wifi_get_iface_id(info, "wlan0");
608     if (index == -1) {
609         int i;
610         for (i = 0; i < info->num_interfaces; i++)
611         {
612             free(info->interfaces[i]);
613         }
614         ALOGE("%s no iface with wlan0", __func__);
615         goto unload;
616     }
617     iface_handle = (wifi_interface_handle)info->interfaces[index];
618 
619     ret = acquire_supported_features(iface_handle,
620             &info->supported_feature_set);
621     if (ret != WIFI_SUCCESS) {
622         ALOGI("Failed to get supported feature set : %d", ret);
623         //acquire_supported_features failure is acceptable condition as legacy
624         //drivers might not support the required vendor command. So, do not
625         //consider it as failure of wifi_initialize
626         ret = WIFI_SUCCESS;
627     }
628 
629     ret =  wifi_get_logger_supported_feature_set(iface_handle,
630                          &info->supported_logger_feature_set);
631     if (ret != WIFI_SUCCESS)
632         ALOGE("Failed to get supported logger feature set: %d", ret);
633 
634     ret = get_firmware_bus_max_size_supported(iface_handle);
635     if (ret != WIFI_SUCCESS) {
636         ALOGE("Failed to get supported bus size, error : %d", ret);
637         info->firmware_bus_max_size = 1520;
638     }
639 
640     ret = wifi_logger_ring_buffers_init(info);
641     if (ret != WIFI_SUCCESS)
642         ALOGE("Wifi Logger Ring Initialization Failed");
643 
644     ret = wifi_get_capabilities(iface_handle);
645     if (ret != WIFI_SUCCESS)
646         ALOGE("Failed to get wifi Capabilities, error: %d", ret);
647 
648     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
649     if (!info->pkt_stats) {
650         ALOGE("%s: malloc Failed for size: %zu",
651                 __FUNCTION__, sizeof(struct pkt_stats_s));
652         ret = WIFI_ERROR_OUT_OF_MEMORY;
653         goto unload;
654     }
655 
656     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
657                                   * PKT_STATS_BUF_SIZE;
658 
659     info->rx_aggr_pkts =
660         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
661     if (!info->rx_aggr_pkts) {
662         ALOGE("%s: malloc Failed for size: %d",
663                 __FUNCTION__, info->rx_buf_size_allocated);
664         ret = WIFI_ERROR_OUT_OF_MEMORY;
665         info->rx_buf_size_allocated = 0;
666         goto unload;
667     }
668     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
669 
670     info->exit_sockets[0] = -1;
671     info->exit_sockets[1] = -1;
672 
673     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
674         ALOGE("Failed to create exit socket pair");
675         ret = WIFI_ERROR_UNKNOWN;
676         goto unload;
677     }
678 
679     ALOGV("Initializing Gscan Event Handlers");
680     ret = initializeGscanHandlers(info);
681     if (ret != WIFI_SUCCESS) {
682         ALOGE("Initializing Gscan Event Handlers Failed");
683         goto unload;
684     }
685 
686     ret = initializeRSSIMonitorHandler(info);
687     if (ret != WIFI_SUCCESS) {
688         ALOGE("Initializing RSSI Event Handler Failed");
689         goto unload;
690     }
691 
692     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
693             " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
694 
695 cld80211_cleanup:
696     if (status != 0 || ret != WIFI_SUCCESS) {
697         ret = WIFI_ERROR_UNKNOWN;
698         cld80211lib_cleanup(info);
699     }
700 unload:
701     if (ret != WIFI_SUCCESS) {
702         if (cmd_sock)
703             nl_socket_free(cmd_sock);
704         if (event_sock)
705             nl_socket_free(event_sock);
706         if (info) {
707             if (info->cldctx) {
708                 cld80211lib_cleanup(info);
709             } else if (info->user_sock) {
710                 nl_socket_free(info->user_sock);
711             }
712             if (info->pkt_stats) free(info->pkt_stats);
713             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
714             wifi_logger_ring_buffers_deinit(info);
715             cleanupGscanHandlers(info);
716             cleanupRSSIMonitorHandler(info);
717             free(info->event_cb);
718             free(info);
719         }
720     }
721 
722     return ret;
723 }
724 
wifi_wait_for_driver_ready(void)725 wifi_error wifi_wait_for_driver_ready(void)
726 {
727     // This function will wait to make sure basic client netdev is created
728     // Function times out after 10 seconds
729     int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
730     FILE *fd;
731 
732     do {
733         if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
734             fclose(fd);
735             return WIFI_SUCCESS;
736         }
737         usleep(POLL_DRIVER_DURATION_US);
738     } while(--count > 0);
739 
740     ALOGE("Timed out wating on Driver ready ... ");
741     return WIFI_ERROR_TIMED_OUT;
742 }
743 
wifi_add_membership(wifi_handle handle,const char * group)744 static int wifi_add_membership(wifi_handle handle, const char *group)
745 {
746     hal_info *info = getHalInfo(handle);
747 
748     int id = wifi_get_multicast_id(handle, "nl80211", group);
749     if (id < 0) {
750         ALOGE("Could not find group %s", group);
751         return id;
752     }
753 
754     int ret = nl_socket_add_membership(info->event_sock, id);
755     if (ret < 0) {
756         ALOGE("Could not add membership to group %s", group);
757     }
758 
759     return ret;
760 }
761 
internal_cleaned_up_handler(wifi_handle handle)762 static void internal_cleaned_up_handler(wifi_handle handle)
763 {
764     hal_info *info = getHalInfo(handle);
765     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
766 
767     if (info->cmd_sock != 0) {
768         nl_socket_free(info->cmd_sock);
769         nl_socket_free(info->event_sock);
770         info->cmd_sock = NULL;
771         info->event_sock = NULL;
772     }
773 
774     if (info->interfaces) {
775         for (int i = 0; i < info->num_interfaces; i++)
776             free(info->interfaces[i]);
777         free(info->interfaces);
778     }
779 
780     if (info->cldctx != NULL) {
781         cld80211lib_cleanup(info);
782     } else if (info->user_sock != 0) {
783         nl_socket_free(info->user_sock);
784         info->user_sock = NULL;
785     }
786 
787     if (info->pkt_stats)
788         free(info->pkt_stats);
789     if (info->rx_aggr_pkts)
790         free(info->rx_aggr_pkts);
791     wifi_logger_ring_buffers_deinit(info);
792     cleanupGscanHandlers(info);
793     cleanupRSSIMonitorHandler(info);
794 
795     if (info->num_event_cb)
796         ALOGE("%d events were leftover without being freed",
797               info->num_event_cb);
798     free(info->event_cb);
799 
800     if (info->exit_sockets[0] >= 0) {
801         close(info->exit_sockets[0]);
802         info->exit_sockets[0] = -1;
803     }
804 
805     if (info->exit_sockets[1] >= 0) {
806         close(info->exit_sockets[1]);
807         info->exit_sockets[1] = -1;
808     }
809 
810     if (info->pkt_fate_stats) {
811         free(info->pkt_fate_stats);
812         info->pkt_fate_stats = NULL;
813     }
814 
815     (*cleaned_up_handler)(handle);
816     pthread_mutex_destroy(&info->cb_lock);
817     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
818     free(info);
819 }
820 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)821 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
822 {
823     if (!handle) {
824         ALOGE("Handle is null");
825         return;
826     }
827 
828     hal_info *info = getHalInfo(handle);
829     info->cleaned_up_handler = handler;
830     info->clean_up = true;
831 
832     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
833     ALOGI("Sent msg on exit sock to unblock poll()");
834 }
835 
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)836 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
837 {
838     struct nl_cb *cb = nl_socket_get_cb(sock);
839 
840     int res = nl_recvmsgs(sock, cb);
841     if(res)
842         ALOGE("Error :%d while reading nl msg", res);
843     nl_cb_put(cb);
844     return res;
845 }
846 
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)847 static void internal_event_handler(wifi_handle handle, int events,
848                                    struct nl_sock *sock)
849 {
850     if (events & POLLERR) {
851         ALOGE("Error reading from socket");
852         internal_pollin_handler(handle, sock);
853     } else if (events & POLLHUP) {
854         ALOGE("Remote side hung up");
855     } else if (events & POLLIN) {
856         //ALOGI("Found some events!!!");
857         internal_pollin_handler(handle, sock);
858     } else {
859         ALOGE("Unknown event - %0x", events);
860     }
861 }
862 
863 /* Run event handler */
wifi_event_loop(wifi_handle handle)864 void wifi_event_loop(wifi_handle handle)
865 {
866     hal_info *info = getHalInfo(handle);
867     if (info->in_event_loop) {
868         return;
869     } else {
870         info->in_event_loop = true;
871     }
872 
873     pollfd pfd[3];
874     memset(&pfd, 0, 3*sizeof(pfd[0]));
875 
876     pfd[0].fd = nl_socket_get_fd(info->event_sock);
877     pfd[0].events = POLLIN;
878 
879     pfd[1].fd = nl_socket_get_fd(info->user_sock);
880     pfd[1].events = POLLIN;
881 
882     pfd[2].fd = info->exit_sockets[1];
883     pfd[2].events = POLLIN;
884 
885     /* TODO: Add support for timeouts */
886 
887     do {
888         pfd[0].revents = 0;
889         pfd[1].revents = 0;
890         pfd[2].revents = 0;
891         //ALOGI("Polling sockets");
892         int result = poll(pfd, 3, -1);
893         if (result < 0) {
894             ALOGE("Error polling socket");
895         } else {
896             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
897                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
898             }
899             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
900                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
901             }
902         }
903         rb_timerhandler(info);
904     } while (!info->clean_up);
905     internal_cleaned_up_handler(handle);
906 }
907 
user_sock_message_handler(nl_msg * msg,void * arg)908 static int user_sock_message_handler(nl_msg *msg, void *arg)
909 {
910     wifi_handle handle = (wifi_handle)arg;
911     hal_info *info = getHalInfo(handle);
912 
913     diag_message_handler(info, msg);
914 
915     return NL_OK;
916 }
917 
internal_valid_message_handler(nl_msg * msg,void * arg)918 static int internal_valid_message_handler(nl_msg *msg, void *arg)
919 {
920     wifi_handle handle = (wifi_handle)arg;
921     hal_info *info = getHalInfo(handle);
922 
923     WifiEvent event(msg);
924     int res = event.parse();
925     if (res < 0) {
926         ALOGE("Failed to parse event: %d", res);
927         return NL_SKIP;
928     }
929 
930     int cmd = event.get_cmd();
931     uint32_t vendor_id = 0;
932     int subcmd = 0;
933 
934     if (cmd == NL80211_CMD_VENDOR) {
935         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
936         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
937         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
938            of logs in bug report */
939         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
940             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
941                   event.get_cmdString(), vendor_id, subcmd);
942         }
943     } else {
944         ALOGV("event received %s", event.get_cmdString());
945     }
946 
947     // event.log();
948 
949     bool dispatched = false;
950 
951     pthread_mutex_lock(&info->cb_lock);
952 
953     for (int i = 0; i < info->num_event_cb; i++) {
954         if (cmd == info->event_cb[i].nl_cmd) {
955             if (cmd == NL80211_CMD_VENDOR
956                 && ((vendor_id != info->event_cb[i].vendor_id)
957                 || (subcmd != info->event_cb[i].vendor_subcmd)))
958             {
959                 /* event for a different vendor, ignore it */
960                 continue;
961             }
962 
963             cb_info *cbi = &(info->event_cb[i]);
964             pthread_mutex_unlock(&info->cb_lock);
965             if (cbi->cb_func) {
966                 (*(cbi->cb_func))(msg, cbi->cb_arg);
967                 dispatched = true;
968             }
969             return NL_OK;
970         }
971     }
972 
973 #ifdef QC_HAL_DEBUG
974     if (!dispatched) {
975         ALOGI("event ignored!!");
976     }
977 #endif
978 
979     pthread_mutex_unlock(&info->cb_lock);
980     return NL_OK;
981 }
982 
983 ////////////////////////////////////////////////////////////////////////////////
984 
985 class GetMulticastIdCommand : public WifiCommand
986 {
987 private:
988     const char *mName;
989     const char *mGroup;
990     int   mId;
991 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)992     GetMulticastIdCommand(wifi_handle handle, const char *name,
993             const char *group) : WifiCommand(handle, 0)
994     {
995         mName = name;
996         mGroup = group;
997         mId = -1;
998     }
999 
getId()1000     int getId() {
1001         return mId;
1002     }
1003 
create()1004     virtual wifi_error create() {
1005         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
1006         // ALOGI("ctrl family = %d", nlctrlFamily);
1007         wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
1008         if (ret != WIFI_SUCCESS)
1009             return ret;
1010 
1011         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
1012         return ret;
1013     }
1014 
handleResponse(WifiEvent & reply)1015     virtual int handleResponse(WifiEvent& reply) {
1016 
1017         // ALOGI("handling reponse in %s", __func__);
1018 
1019         struct nlattr **tb = reply.attributes();
1020         struct nlattr *mcgrp = NULL;
1021         int i;
1022 
1023         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
1024             ALOGI("No multicast groups found");
1025             return NL_SKIP;
1026         } else {
1027             // ALOGI("Multicast groups attr size = %d",
1028             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
1029         }
1030 
1031         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
1032 
1033             // ALOGI("Processing group");
1034             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
1035             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
1036                 nla_len(mcgrp), NULL);
1037             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
1038             {
1039                 continue;
1040             }
1041 
1042             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1043             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1044 
1045             // ALOGI("Found group name %s", grpName);
1046 
1047             if (strncmp(grpName, mGroup, grpNameLen) != 0)
1048                 continue;
1049 
1050             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
1051             break;
1052         }
1053 
1054         return NL_SKIP;
1055     }
1056 
1057 };
1058 
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)1059 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
1060         const char *group)
1061 {
1062     GetMulticastIdCommand cmd(handle, name, group);
1063     int res = cmd.requestResponse();
1064     if (res < 0)
1065         return res;
1066     else
1067         return cmd.getId();
1068 }
1069 
1070 /////////////////////////////////////////////////////////////////////////
1071 
is_wifi_interface(const char * name)1072 static bool is_wifi_interface(const char *name)
1073 {
1074     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1075         /* not a wifi interface; ignore it */
1076         return false;
1077     } else {
1078         return true;
1079     }
1080 }
1081 
get_interface(const char * name,interface_info * info)1082 static int get_interface(const char *name, interface_info *info)
1083 {
1084     strlcpy(info->name, name, (IFNAMSIZ + 1));
1085     info->id = if_nametoindex(name);
1086     // ALOGI("found an interface : %s, id = %d", name, info->id);
1087     return WIFI_SUCCESS;
1088 }
1089 
wifi_init_interfaces(wifi_handle handle)1090 wifi_error wifi_init_interfaces(wifi_handle handle)
1091 {
1092     hal_info *info = (hal_info *)handle;
1093 
1094     struct dirent *de;
1095 
1096     DIR *d = opendir("/sys/class/net");
1097     if (d == 0)
1098         return WIFI_ERROR_UNKNOWN;
1099 
1100     int n = 0;
1101     while ((de = readdir(d))) {
1102         if (de->d_name[0] == '.')
1103             continue;
1104         if (is_wifi_interface(de->d_name) ) {
1105             n++;
1106         }
1107     }
1108 
1109     closedir(d);
1110 
1111     d = opendir("/sys/class/net");
1112     if (d == 0)
1113         return WIFI_ERROR_UNKNOWN;
1114 
1115     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1116     if (info->interfaces == NULL) {
1117         ALOGE("%s: Error info->interfaces NULL", __func__);
1118         return WIFI_ERROR_OUT_OF_MEMORY;
1119     }
1120 
1121     int i = 0;
1122     while ((de = readdir(d))) {
1123         if (de->d_name[0] == '.')
1124             continue;
1125         if (is_wifi_interface(de->d_name)) {
1126             interface_info *ifinfo
1127                 = (interface_info *)malloc(sizeof(interface_info));
1128             if (ifinfo == NULL) {
1129                 ALOGE("%s: Error ifinfo NULL", __func__);
1130                 while (i > 0) {
1131                     free(info->interfaces[i-1]);
1132                     i--;
1133                 }
1134                 free(info->interfaces);
1135                 return WIFI_ERROR_OUT_OF_MEMORY;
1136             }
1137             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1138                 free(ifinfo);
1139                 continue;
1140             }
1141             ifinfo->handle = handle;
1142             info->interfaces[i] = ifinfo;
1143             i++;
1144         }
1145     }
1146 
1147     closedir(d);
1148 
1149     info->num_interfaces = n;
1150 
1151     return WIFI_SUCCESS;
1152 }
1153 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)1154 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
1155         wifi_interface_handle **interfaces)
1156 {
1157     hal_info *info = (hal_info *)handle;
1158 
1159     *interfaces = (wifi_interface_handle *)info->interfaces;
1160     *num = info->num_interfaces;
1161 
1162     return WIFI_SUCCESS;
1163 }
1164 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1165 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1166         size_t size)
1167 {
1168     interface_info *info = (interface_info *)handle;
1169     strlcpy(name, info->name, size);
1170     return WIFI_SUCCESS;
1171 }
1172 
1173 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1174 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1175         feature_set *set)
1176 {
1177     int ret = 0;
1178     wifi_handle handle = getWifiHandle(iface);
1179     *set = 0;
1180     hal_info *info = getHalInfo(handle);
1181 
1182     ret = acquire_supported_features(iface, set);
1183     if (ret != WIFI_SUCCESS) {
1184         *set = info->supported_feature_set;
1185         ALOGV("Supported feature set acquired at initialization : %x", *set);
1186     } else {
1187         info->supported_feature_set = *set;
1188         ALOGV("Supported feature set acquired : %x", *set);
1189     }
1190     return WIFI_SUCCESS;
1191 }
1192 
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1193 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1194                                        int set_size_max,
1195                                        feature_set set[], int *set_size)
1196 {
1197     wifi_error ret;
1198     struct nlattr *nlData;
1199     WifihalGeneric *vCommand = NULL;
1200     interface_info *ifaceInfo = getIfaceInfo(handle);
1201     wifi_handle wifiHandle = getWifiHandle(handle);
1202 
1203     if (set == NULL) {
1204         ALOGE("%s: NULL set pointer provided. Exit.",
1205             __func__);
1206         return WIFI_ERROR_INVALID_ARGS;
1207     }
1208 
1209     vCommand = new WifihalGeneric(wifiHandle, 0,
1210             OUI_QCA,
1211             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1212     if (vCommand == NULL) {
1213         ALOGE("%s: Error vCommand NULL", __func__);
1214         return WIFI_ERROR_OUT_OF_MEMORY;
1215     }
1216 
1217     /* Create the message */
1218     ret = vCommand->create();
1219     if (ret != WIFI_SUCCESS)
1220         goto cleanup;
1221 
1222     ret = vCommand->set_iface_id(ifaceInfo->name);
1223     if (ret != WIFI_SUCCESS)
1224         goto cleanup;
1225 
1226     /* Add the vendor specific attributes for the NL command. */
1227     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1228     if (!nlData)
1229         goto cleanup;
1230 
1231     ret = vCommand->put_u32(
1232           QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1233           set_size_max);
1234     if (ret != WIFI_SUCCESS)
1235         goto cleanup;
1236 
1237     vCommand->attr_end(nlData);
1238 
1239     /* Populate the input received from caller/framework. */
1240     vCommand->setMaxSetSize(set_size_max);
1241     vCommand->setSizePtr(set_size);
1242     vCommand->setConcurrencySet(set);
1243 
1244     ret = vCommand->requestResponse();
1245     if (ret != WIFI_SUCCESS)
1246         ALOGE("%s: requestResponse() error: %d", __func__, ret);
1247 
1248 cleanup:
1249     delete vCommand;
1250     if (ret)
1251         *set_size = 0;
1252     return ret;
1253 }
1254 
1255 
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1256 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1257 {
1258     wifi_error ret;
1259     struct nlattr *nlData;
1260     WifiVendorCommand *vCommand = NULL;
1261     interface_info *ifaceInfo = getIfaceInfo(handle);
1262     wifi_handle wifiHandle = getWifiHandle(handle);
1263 
1264     vCommand = new WifiVendorCommand(wifiHandle, 0,
1265             OUI_QCA,
1266             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
1267     if (vCommand == NULL) {
1268         ALOGE("%s: Error vCommand NULL", __func__);
1269         return WIFI_ERROR_OUT_OF_MEMORY;
1270     }
1271 
1272     /* Create the message */
1273     ret = vCommand->create();
1274     if (ret != WIFI_SUCCESS)
1275         goto cleanup;
1276 
1277     ret = vCommand->set_iface_id(ifaceInfo->name);
1278     if (ret != WIFI_SUCCESS)
1279         goto cleanup;
1280 
1281     /* Add the vendor specific attributes for the NL command. */
1282     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1283     if (!nlData)
1284         goto cleanup;
1285 
1286     /* Add the fixed part of the mac_oui to the nl command */
1287     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
1288     if (ret != WIFI_SUCCESS)
1289         goto cleanup;
1290 
1291     vCommand->attr_end(nlData);
1292 
1293     ret = vCommand->requestResponse();
1294     /* Don't check response since we aren't expecting one */
1295 
1296 cleanup:
1297     delete vCommand;
1298     return ret;
1299 }
1300 
wifi_start_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface,u8 * ip_packet,u16 ip_packet_len,u8 * src_mac_addr,u8 * dst_mac_addr,u32 period_msec)1301 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
1302                                                wifi_interface_handle iface,
1303                                                u8 *ip_packet,
1304                                                u16 ip_packet_len,
1305                                                u8 *src_mac_addr,
1306                                                u8 *dst_mac_addr,
1307                                                u32 period_msec)
1308 {
1309     wifi_error ret;
1310     struct nlattr *nlData;
1311     WifiVendorCommand *vCommand = NULL;
1312 
1313     ret = initialize_vendor_cmd(iface, id,
1314                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1315                                 &vCommand);
1316     if (ret != WIFI_SUCCESS) {
1317         ALOGE("%s: Initialization failed", __func__);
1318         return ret;
1319     }
1320 
1321     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
1322     hexdump(ip_packet, ip_packet_len);
1323     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
1324           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
1325           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
1326 
1327     /* Add the vendor specific attributes for the NL command. */
1328     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1329     if (!nlData)
1330         goto cleanup;
1331 
1332     ret = vCommand->put_u32(
1333             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1334             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
1335     if (ret != WIFI_SUCCESS)
1336         goto cleanup;
1337 
1338     ret = vCommand->put_u32(
1339             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1340             id);
1341     if (ret != WIFI_SUCCESS)
1342         goto cleanup;
1343 
1344     ret = vCommand->put_bytes(
1345             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
1346             (const char *)ip_packet, ip_packet_len);
1347     if (ret != WIFI_SUCCESS)
1348         goto cleanup;
1349 
1350     ret = vCommand->put_addr(
1351             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
1352             src_mac_addr);
1353     if (ret != WIFI_SUCCESS)
1354         goto cleanup;
1355 
1356     ret = vCommand->put_addr(
1357             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
1358             dst_mac_addr);
1359     if (ret != WIFI_SUCCESS)
1360         goto cleanup;
1361 
1362     ret = vCommand->put_u32(
1363             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
1364             period_msec);
1365     if (ret != WIFI_SUCCESS)
1366         goto cleanup;
1367 
1368     vCommand->attr_end(nlData);
1369 
1370     ret = vCommand->requestResponse();
1371     if (ret != WIFI_SUCCESS)
1372         goto cleanup;
1373 
1374 cleanup:
1375     delete vCommand;
1376     return ret;
1377 }
1378 
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)1379 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
1380                                               wifi_interface_handle iface)
1381 {
1382     wifi_error ret;
1383     struct nlattr *nlData;
1384     WifiVendorCommand *vCommand = NULL;
1385 
1386     ret = initialize_vendor_cmd(iface, id,
1387                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1388                                 &vCommand);
1389     if (ret != WIFI_SUCCESS) {
1390         ALOGE("%s: Initialization failed", __func__);
1391         return ret;
1392     }
1393 
1394     /* Add the vendor specific attributes for the NL command. */
1395     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1396     if (!nlData)
1397         goto cleanup;
1398 
1399     ret = vCommand->put_u32(
1400             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1401             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
1402     if (ret != WIFI_SUCCESS)
1403         goto cleanup;
1404 
1405     ret = vCommand->put_u32(
1406             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1407             id);
1408     if (ret != WIFI_SUCCESS)
1409         goto cleanup;
1410 
1411     vCommand->attr_end(nlData);
1412 
1413     ret = vCommand->requestResponse();
1414     if (ret != WIFI_SUCCESS)
1415         goto cleanup;
1416 
1417 cleanup:
1418     delete vCommand;
1419     return ret;
1420 }
1421 
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)1422 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
1423                                          const u8 *program, u32 len)
1424 {
1425     wifi_error ret;
1426     struct nlattr *nlData;
1427     WifiVendorCommand *vCommand = NULL;
1428     u32 current_offset = 0;
1429     wifi_handle wifiHandle = getWifiHandle(iface);
1430     hal_info *info = getHalInfo(wifiHandle);
1431 
1432     /* len=0 clears the filters in driver/firmware */
1433     if (len != 0 && program == NULL) {
1434         ALOGE("%s: No valid program provided. Exit.",
1435             __func__);
1436         return WIFI_ERROR_INVALID_ARGS;
1437     }
1438 
1439     do {
1440         ret = initialize_vendor_cmd(iface, get_requestid(),
1441                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1442                                     &vCommand);
1443         if (ret != WIFI_SUCCESS) {
1444             ALOGE("%s: Initialization failed", __FUNCTION__);
1445             return ret;
1446         }
1447 
1448         /* Add the vendor specific attributes for the NL command. */
1449         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1450         if (!nlData)
1451             goto cleanup;
1452 
1453         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1454                                 QCA_WLAN_SET_PACKET_FILTER);
1455         if (ret != WIFI_SUCCESS)
1456             goto cleanup;
1457         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
1458                                 PACKET_FILTER_ID);
1459         if (ret != WIFI_SUCCESS)
1460             goto cleanup;
1461         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1462                                 len);
1463         if (ret != WIFI_SUCCESS)
1464             goto cleanup;
1465         ret = vCommand->put_u32(
1466                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1467                             current_offset);
1468         if (ret != WIFI_SUCCESS)
1469             goto cleanup;
1470 
1471         if (len) {
1472             ret = vCommand->put_bytes(
1473                                      QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
1474                                      (char *)&program[current_offset],
1475                                      min(info->firmware_bus_max_size,
1476                                      len-current_offset));
1477             if (ret!= WIFI_SUCCESS) {
1478                 ALOGE("%s: failed to put program", __FUNCTION__);
1479                 goto cleanup;
1480             }
1481         }
1482 
1483         vCommand->attr_end(nlData);
1484 
1485         ret = vCommand->requestResponse();
1486         if (ret != WIFI_SUCCESS) {
1487             ALOGE("%s: requestResponse Error:%d",__func__, ret);
1488             goto cleanup;
1489         }
1490 
1491         /* destroy the object after sending each fragment to driver */
1492         delete vCommand;
1493         vCommand = NULL;
1494 
1495         current_offset += min(info->firmware_bus_max_size, len);
1496     } while (current_offset < len);
1497 
1498     info->apf_enabled = !!len;
1499 
1500 cleanup:
1501     if (vCommand)
1502         delete vCommand;
1503     return ret;
1504 }
1505 
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)1506 static wifi_error wifi_get_packet_filter_capabilities(
1507                 wifi_interface_handle handle, u32 *version, u32 *max_len)
1508 {
1509     wifi_error ret;
1510     struct nlattr *nlData;
1511     WifihalGeneric *vCommand = NULL;
1512     interface_info *ifaceInfo = getIfaceInfo(handle);
1513     wifi_handle wifiHandle = getWifiHandle(handle);
1514 
1515     if (version == NULL || max_len == NULL) {
1516         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
1517             __FUNCTION__);
1518         return WIFI_ERROR_INVALID_ARGS;
1519     }
1520 
1521     vCommand = new WifihalGeneric(wifiHandle, 0,
1522             OUI_QCA,
1523             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
1524     if (vCommand == NULL) {
1525         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1526         return WIFI_ERROR_OUT_OF_MEMORY;
1527     }
1528 
1529     /* Create the message */
1530     ret = vCommand->create();
1531     if (ret != WIFI_SUCCESS)
1532         goto cleanup;
1533 
1534     ret = vCommand->set_iface_id(ifaceInfo->name);
1535     if (ret != WIFI_SUCCESS)
1536         goto cleanup;
1537 
1538     /* Add the vendor specific attributes for the NL command. */
1539     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1540     if (!nlData)
1541         goto cleanup;
1542 
1543     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1544                             QCA_WLAN_GET_PACKET_FILTER_SIZE);
1545     if (ret != WIFI_SUCCESS)
1546         goto cleanup;
1547 
1548     vCommand->attr_end(nlData);
1549 
1550     ret = vCommand->requestResponse();
1551     if (ret != WIFI_SUCCESS) {
1552         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
1553         if (ret == WIFI_ERROR_NOT_SUPPORTED) {
1554             /* Packet filtering is not supported currently, so return version
1555              * and length as 0
1556              */
1557             ALOGI("Packet filtering is not supprted");
1558             *version = 0;
1559             *max_len = 0;
1560             ret = WIFI_SUCCESS;
1561         }
1562         goto cleanup;
1563     }
1564 
1565     *version = vCommand->getFilterVersion();
1566     *max_len = vCommand->getFilterLength();
1567 cleanup:
1568     delete vCommand;
1569     return ret;
1570 }
1571 
1572 
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)1573 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
1574                                             u8 enable)
1575 {
1576     wifi_error ret;
1577     struct nlattr *nlData;
1578     WifiVendorCommand *vCommand = NULL;
1579 
1580     ret = initialize_vendor_cmd(iface, get_requestid(),
1581                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
1582                                 &vCommand);
1583     if (ret != WIFI_SUCCESS) {
1584         ALOGE("%s: Initialization failed", __func__);
1585         return ret;
1586     }
1587 
1588     ALOGV("ND offload : %s", enable?"Enable":"Disable");
1589 
1590     /* Add the vendor specific attributes for the NL command. */
1591     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1592     if (!nlData)
1593         goto cleanup;
1594 
1595     ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
1596     if (ret != WIFI_SUCCESS)
1597         goto cleanup;
1598 
1599     vCommand->attr_end(nlData);
1600 
1601     ret = vCommand->requestResponse();
1602 
1603 cleanup:
1604     delete vCommand;
1605     return ret;
1606 }
1607 
1608 /**
1609  * Copy 'len' bytes of raw data from host memory at source address 'program'
1610  * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
1611  * The size of the program lenght passed to the interpreter is set to
1612  * 'progaram_lenght'
1613  *
1614  * The implementation is allowed to tranlate this wrtie into a series of smaller
1615  * writes,but this function is not allowed to return untill all write operations
1616  * have been completed
1617  * additionally visible memory not targeted by this function must remain
1618  * unchanged
1619 
1620  * @param dst_offset write offset in bytes relative to the beginning of the APF
1621  * working memory with logical address 0X000. Must be a multiple of 4
1622  *
1623  * @param program host memory to copy bytes from. Must be 4B aligned
1624  *
1625  * @param len the number of bytes to copy from the bost into the APF working
1626  * memory
1627  *
1628  * @param program_length new length of the program instructions in bytes to pass
1629  * to the interpreter
1630  */
1631 
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)1632 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
1633                                          u32 dst_offset, const u8 *program,
1634                                          u32 len, u32 program_length)
1635 {
1636     wifi_error ret;
1637     struct nlattr *nlData;
1638     WifiVendorCommand *vCommand = NULL;
1639     u32 current_offset = 0;
1640     wifi_handle wifiHandle = getWifiHandle(iface);
1641     hal_info *info = getHalInfo(wifiHandle);
1642 
1643     /* len=0 clears the filters in driver/firmware */
1644     if (len != 0 && program == NULL) {
1645         ALOGE("%s: No valid program provided. Exit.",
1646             __func__);
1647         return WIFI_ERROR_INVALID_ARGS;
1648     }
1649 
1650     do {
1651         ret = initialize_vendor_cmd(iface, get_requestid(),
1652                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1653                                     &vCommand);
1654         if (ret != WIFI_SUCCESS) {
1655             ALOGE("%s: Initialization failed", __FUNCTION__);
1656             return ret;
1657         }
1658 
1659         /* Add the vendor specific attributes for the NL command. */
1660         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1661         if (!nlData)
1662              goto cleanup;
1663 
1664         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1665                                  QCA_WLAN_WRITE_PACKET_FILTER);
1666         if (ret != WIFI_SUCCESS)
1667             goto cleanup;
1668         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
1669                                 PACKET_FILTER_ID);
1670         if (ret != WIFI_SUCCESS)
1671             goto cleanup;
1672         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1673                                 len);
1674         if (ret != WIFI_SUCCESS)
1675             goto cleanup;
1676         ret = vCommand->put_u32(
1677                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1678                             dst_offset + current_offset);
1679         if (ret != WIFI_SUCCESS)
1680             goto cleanup;
1681         ret = vCommand->put_u32(
1682                            QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
1683                             program_length);
1684         if (ret != WIFI_SUCCESS)
1685             goto cleanup;
1686 
1687         ret = vCommand->put_bytes(
1688                                  QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
1689                                  (char *)&program[current_offset],
1690                                  min(info->firmware_bus_max_size,
1691                                  len - current_offset));
1692         if (ret!= WIFI_SUCCESS) {
1693             ALOGE("%s: failed to put program", __FUNCTION__);
1694             goto cleanup;
1695         }
1696 
1697         vCommand->attr_end(nlData);
1698 
1699         ret = vCommand->requestResponse();
1700        if (ret != WIFI_SUCCESS) {
1701             ALOGE("%s: requestResponse Error:%d",__func__, ret);
1702             goto cleanup;
1703         }
1704 
1705         /* destroy the object after sending each fragment to driver */
1706         delete vCommand;
1707         vCommand = NULL;
1708 
1709         current_offset += min(info->firmware_bus_max_size,
1710                                          len - current_offset);
1711     } while (current_offset < len);
1712 
1713 cleanup:
1714     if (vCommand)
1715         delete vCommand;
1716     return ret;
1717 }
1718 
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)1719 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
1720                                         u32 enable)
1721 {
1722     wifi_error ret;
1723     struct nlattr *nlData;
1724     WifiVendorCommand *vCommand = NULL;
1725     u32 subcmd;
1726     wifi_handle wifiHandle = getWifiHandle(handle);
1727     hal_info *info = getHalInfo(wifiHandle);
1728 
1729     ret = initialize_vendor_cmd(handle, get_requestid(),
1730                                 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1731                                 &vCommand);
1732 
1733     if (ret != WIFI_SUCCESS) {
1734         ALOGE("%s: Initialization failed", __func__);
1735         return ret;
1736     }
1737     /* Add the vendor specific attributes for the NL command. */
1738     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1739     if (!nlData)
1740         goto cleanup;
1741 
1742     subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
1743                       QCA_WLAN_DISABLE_PACKET_FILTER;
1744     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1745                             subcmd);
1746     if (ret != WIFI_SUCCESS)
1747             goto cleanup;
1748 
1749     vCommand->attr_end(nlData);
1750     ret = vCommand->requestResponse();
1751 
1752     if (ret != WIFI_SUCCESS) {
1753         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
1754         goto cleanup;
1755     }
1756 
1757     info->apf_enabled = !!enable;
1758 
1759 cleanup:
1760     if (vCommand)
1761         delete vCommand;
1762     return ret;
1763 
1764 }
1765 
1766 /**
1767  * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
1768  * memory  to host memory starting at offset src_offset into host memory
1769  * pointed to by host_dst.
1770  * Memory can be text, data or some combination of the two. The implementiion is
1771  * allowed to translate this read into a series of smaller reads, but this
1772  * function is not allowed to return untill all the reads operations
1773  * into host_dst have been completed.
1774  *
1775  * @param src_offset offset in bytes of destination memory within APF working
1776  * memory
1777  *
1778  * @param host_dst host memory to copy into. Must be 4B aligned.
1779  *
1780  * @param length the number of bytes to copy from the APF working memory to the
1781  * host.
1782  */
1783 
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)1784 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
1785                                           u32 src_offset, u8 *host_dst, u32 length)
1786 {
1787     wifi_error ret;
1788     struct nlattr *nlData;
1789     WifihalGeneric *vCommand = NULL;
1790     interface_info *ifaceInfo = getIfaceInfo(handle);
1791     wifi_handle wifiHandle = getWifiHandle(handle);
1792     hal_info *info = getHalInfo(wifiHandle);
1793 
1794     /*Temporary varibles to support the read complete length in chunks */
1795     u8 *temp_host_dst;
1796     u32 remainingLengthToBeRead, currentLength;
1797     u8 apf_locally_disabled = 0;
1798 
1799     /*Initializing the temporary variables*/
1800     temp_host_dst = host_dst;
1801     remainingLengthToBeRead = length;
1802 
1803     if (info->apf_enabled) {
1804         /* Disable APF only when not disabled by framework before calling
1805          * wifi_read_packet_filter()
1806          */
1807         ret = wifi_enable_packet_filter(handle, 0);
1808         if (ret != WIFI_SUCCESS) {
1809             ALOGE("%s: Failed to disable APF", __FUNCTION__);
1810             return ret;
1811         }
1812         apf_locally_disabled = 1;
1813     }
1814     /**
1815      * Read the complete length in chunks of size less or equal to firmware bus
1816      * max size
1817      */
1818     while (remainingLengthToBeRead)
1819     {
1820         vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
1821                                       QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
1822 
1823         if (vCommand == NULL) {
1824             ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1825             ret = WIFI_ERROR_OUT_OF_MEMORY;
1826             break;
1827         }
1828 
1829         /* Create the message */
1830         ret = vCommand->create();
1831         if (ret != WIFI_SUCCESS)
1832             break;
1833         ret = vCommand->set_iface_id(ifaceInfo->name);
1834         if (ret != WIFI_SUCCESS)
1835             break;
1836         /* Add the vendor specific attributes for the NL command. */
1837         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1838         if (!nlData)
1839             break;
1840         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1841                                 QCA_WLAN_READ_PACKET_FILTER);
1842         if (ret != WIFI_SUCCESS)
1843             break;
1844 
1845         currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
1846 
1847         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1848                                 currentLength);
1849         if (ret != WIFI_SUCCESS)
1850             break;
1851         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1852                                 src_offset);
1853         if (ret != WIFI_SUCCESS)
1854             break;
1855 
1856         vCommand->setPacketBufferParams(temp_host_dst, currentLength);
1857         vCommand->attr_end(nlData);
1858         ret = vCommand->requestResponse();
1859 
1860         if (ret != WIFI_SUCCESS) {
1861             ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
1862                   __FUNCTION__, ret, currentLength, src_offset);
1863             break;
1864         }
1865 
1866         remainingLengthToBeRead -= currentLength;
1867         temp_host_dst += currentLength;
1868         src_offset += currentLength;
1869         delete vCommand;
1870         vCommand = NULL;
1871     }
1872 
1873     /* Re enable APF only when disabled above within this API */
1874     if (apf_locally_disabled) {
1875         wifi_error status;
1876         status = wifi_enable_packet_filter(handle, 1);
1877         if (status != WIFI_SUCCESS)
1878             ALOGE("%s: Failed to enable APF", __FUNCTION__);
1879         /* Prefer to return read status if read fails */
1880         if (ret == WIFI_SUCCESS)
1881             ret = status;
1882     }
1883 
1884     delete vCommand;
1885     return ret;
1886 }
1887