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