• 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-types.h>
34 
35 #include "nl80211_copy.h"
36 
37 #include <dirent.h>
38 #include <net/if.h>
39 #include <netinet/in.h>
40 
41 #include "sync.h"
42 
43 #define LOG_TAG  "WifiHAL"
44 
45 #include "hardware_legacy/wifi.h"
46 
47 #include "wifi_hal.h"
48 #include "common.h"
49 #include "cpp_bindings.h"
50 #include "ifaceeventhandler.h"
51 #include "wifiloggercmd.h"
52 #include "vendor_definitions.h"
53 
54 /*
55  BUGBUG: normally, libnl allocates ports for all connections it makes; but
56  being a static library, it doesn't really know how many other netlink
57  connections are made by the same process, if connections come from different
58  shared libraries. These port assignments exist to solve that
59  problem - temporarily. We need to fix libnl to try and allocate ports across
60  the entire process.
61  */
62 
63 #define WIFI_HAL_CMD_SOCK_PORT       644
64 #define WIFI_HAL_EVENT_SOCK_PORT     645
65 
66 static void internal_event_handler(wifi_handle handle, int events,
67                                    struct nl_sock *sock);
68 static int internal_valid_message_handler(nl_msg *msg, void *arg);
69 static int user_sock_message_handler(nl_msg *msg, void *arg);
70 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
71         const char *group);
72 static int wifi_add_membership(wifi_handle handle, const char *group);
73 static wifi_error wifi_init_interfaces(wifi_handle handle);
74 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
75                                          const u8 *program, u32 len);
76 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
77                                               u32 *version, u32 *max_len);
78 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
79                                             u8 enable);
80 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
81                              WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
82 
83 /* Initialize/Cleanup */
84 
wifi_get_iface_handle(wifi_handle handle,char * name)85 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
86 {
87     hal_info *info = (hal_info *)handle;
88     for (int i=0;i<info->num_interfaces;i++)
89     {
90         if (!strcmp(info->interfaces[i]->name, name))
91         {
92             return ((wifi_interface_handle )(info->interfaces)[i]);
93         }
94     }
95     return NULL;
96 }
97 
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)98 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
99 {
100     uint32_t pid = getpid() & 0x3FFFFF;
101 
102     if (port == 0) {
103         sock->s_flags &= ~NL_OWN_PORT;
104     } else {
105         sock->s_flags |= NL_OWN_PORT;
106     }
107 
108     sock->s_local.nl_pid = pid + (port << 22);
109 }
110 
wifi_create_nl_socket(int port,int protocol)111 static nl_sock * wifi_create_nl_socket(int port, int protocol)
112 {
113     // ALOGI("Creating socket");
114     struct nl_sock *sock = nl_socket_alloc();
115     if (sock == NULL) {
116         ALOGE("Failed to create NL socket");
117         return NULL;
118     }
119 
120     wifi_socket_set_local_port(sock, port);
121 
122     struct sockaddr_nl *addr_nl = &(sock->s_local);
123     /* ALOGI("socket address is %d:%d:%d:%d",
124        addr_nl->nl_family, addr_nl->nl_pad, addr_nl->nl_pid,
125        addr_nl->nl_groups); */
126 
127     struct sockaddr *addr = NULL;
128     // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr),
129     // sizeof(*addr_nl));
130 
131     // ALOGI("Connecting socket");
132     if (nl_connect(sock, protocol)) {
133         ALOGE("Could not connect handle");
134         nl_socket_free(sock);
135         return NULL;
136     }
137 
138     return sock;
139 }
140 
ack_handler(struct nl_msg * msg,void * arg)141 int ack_handler(struct nl_msg *msg, void *arg)
142 {
143     int *err = (int *)arg;
144     *err = 0;
145     return NL_STOP;
146 }
147 
finish_handler(struct nl_msg * msg,void * arg)148 int finish_handler(struct nl_msg *msg, void *arg)
149 {
150     int *ret = (int *)arg;
151     *ret = 0;
152     return NL_SKIP;
153 }
154 
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)155 int error_handler(struct sockaddr_nl *nla,
156                   struct nlmsgerr *err, void *arg)
157 {
158     int *ret = (int *)arg;
159     *ret = err->error;
160 
161     ALOGV("%s invoked with error: %d", __func__, err->error);
162     return NL_SKIP;
163 }
no_seq_check(struct nl_msg * msg,void * arg)164 static int no_seq_check(struct nl_msg *msg, void *arg)
165 {
166     return NL_OK;
167 }
168 
acquire_supported_features(wifi_interface_handle iface,feature_set * set)169 static wifi_error acquire_supported_features(wifi_interface_handle iface,
170         feature_set *set)
171 {
172     int ret = 0;
173     interface_info *iinfo = getIfaceInfo(iface);
174     wifi_handle handle = getWifiHandle(iface);
175     *set = 0;
176 
177     WifihalGeneric supportedFeatures(handle, 0,
178             OUI_QCA,
179             QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
180 
181     /* create the message */
182     ret = supportedFeatures.create();
183     if (ret < 0)
184         goto cleanup;
185 
186     ret = supportedFeatures.set_iface_id(iinfo->name);
187     if (ret < 0)
188         goto cleanup;
189 
190     ret = supportedFeatures.requestResponse();
191     if (ret != 0) {
192         ALOGE("%s: requestResponse Error:%d",__func__, ret);
193         goto cleanup;
194     }
195 
196     supportedFeatures.getResponseparams(set);
197 
198 cleanup:
199     return (wifi_error)ret;
200 }
201 
get_firmware_bus_max_size_supported(wifi_interface_handle iface)202 static wifi_error get_firmware_bus_max_size_supported(
203                                                 wifi_interface_handle iface)
204 {
205     int ret = 0;
206     interface_info *iinfo = getIfaceInfo(iface);
207     wifi_handle handle = getWifiHandle(iface);
208     hal_info *info = (hal_info *)handle;
209 
210     WifihalGeneric busSizeSupported(handle, 0,
211                                     OUI_QCA,
212                                     QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
213 
214     /* create the message */
215     ret = busSizeSupported.create();
216     if (ret < 0)
217         goto cleanup;
218 
219     ret = busSizeSupported.set_iface_id(iinfo->name);
220     if (ret < 0)
221         goto cleanup;
222 
223     ret = busSizeSupported.requestResponse();
224     if (ret != 0) {
225         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
226         goto cleanup;
227     }
228     info->firmware_bus_max_size = busSizeSupported.getBusSize();
229 
230 cleanup:
231     return (wifi_error)ret;
232 }
233 
wifi_init_user_sock(hal_info * info)234 static wifi_error wifi_init_user_sock(hal_info *info)
235 {
236     struct nl_sock *user_sock =
237         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
238     if (user_sock == NULL) {
239         ALOGE("Could not create diag sock");
240         return WIFI_ERROR_UNKNOWN;
241     }
242 
243     /* Set the socket buffer size */
244     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
245         ALOGE("Could not set size for user_sock: %s",
246                    strerror(errno));
247         /* continue anyway with the default (smaller) buffer */
248     }
249     else {
250         ALOGV("nl_socket_set_buffer_size successful for user_sock");
251     }
252 
253     struct nl_cb *cb = nl_socket_get_cb(user_sock);
254     if (cb == NULL) {
255         ALOGE("Could not get cb");
256         return WIFI_ERROR_UNKNOWN;
257     }
258 
259     info->user_sock_arg = 1;
260     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
261     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
262     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
263     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
264 
265     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
266     nl_cb_put(cb);
267 
268     int ret = nl_socket_add_membership(user_sock, 1);
269     if (ret < 0) {
270         ALOGE("Could not add membership");
271         return WIFI_ERROR_UNKNOWN;
272     }
273 
274     info->user_sock = user_sock;
275     ALOGV("Initiialized diag sock successfully");
276     return WIFI_SUCCESS;
277 }
278 
279 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)280 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
281     if (fn == NULL) {
282         return WIFI_ERROR_UNKNOWN;
283     }
284 
285     fn->wifi_initialize = wifi_initialize;
286     fn->wifi_cleanup = wifi_cleanup;
287     fn->wifi_event_loop = wifi_event_loop;
288     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
289     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
290     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
291     fn->wifi_get_ifaces = wifi_get_ifaces;
292     fn->wifi_get_iface_name = wifi_get_iface_name;
293     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
294     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
295     fn->wifi_start_gscan = wifi_start_gscan;
296     fn->wifi_stop_gscan = wifi_stop_gscan;
297     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
298     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
299     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
300     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
301     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
302     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
303     fn->wifi_set_link_stats = wifi_set_link_stats;
304     fn->wifi_get_link_stats = wifi_get_link_stats;
305     fn->wifi_clear_link_stats = wifi_clear_link_stats;
306     fn->wifi_get_valid_channels = wifi_get_valid_channels;
307     fn->wifi_rtt_range_request = wifi_rtt_range_request;
308     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
309     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
310     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
311     fn->wifi_enable_responder = wifi_enable_responder;
312     fn->wifi_disable_responder = wifi_disable_responder;
313     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
314     fn->wifi_start_logging = wifi_start_logging;
315     fn->wifi_set_epno_list = wifi_set_epno_list;
316     fn->wifi_reset_epno_list = wifi_reset_epno_list;
317     fn->wifi_set_country_code = wifi_set_country_code;
318     fn->wifi_enable_tdls = wifi_enable_tdls;
319     fn->wifi_disable_tdls = wifi_disable_tdls;
320     fn->wifi_get_tdls_status = wifi_get_tdls_status;
321     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
322     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
323     fn->wifi_set_log_handler = wifi_set_log_handler;
324     fn->wifi_reset_log_handler = wifi_reset_log_handler;
325     fn->wifi_set_alert_handler = wifi_set_alert_handler;
326     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
327     fn->wifi_get_firmware_version = wifi_get_firmware_version;
328     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
329     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
330     fn->wifi_get_ring_data = wifi_get_ring_data;
331     fn->wifi_get_driver_version = wifi_get_driver_version;
332     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
333     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
334     fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
335     fn->wifi_set_lci = wifi_set_lci;
336     fn->wifi_set_lcr = wifi_set_lcr;
337     fn->wifi_start_sending_offloaded_packet =
338             wifi_start_sending_offloaded_packet;
339     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
340     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
341     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
342     fn->wifi_nan_enable_request = nan_enable_request;
343     fn->wifi_nan_disable_request = nan_disable_request;
344     fn->wifi_nan_publish_request = nan_publish_request;
345     fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
346     fn->wifi_nan_subscribe_request = nan_subscribe_request;
347     fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
348     fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
349     fn->wifi_nan_stats_request = nan_stats_request;
350     fn->wifi_nan_config_request = nan_config_request;
351     fn->wifi_nan_tca_request = nan_tca_request;
352     fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
353     fn->wifi_nan_register_handler = nan_register_handler;
354     fn->wifi_nan_get_version = nan_get_version;
355     fn->wifi_set_packet_filter = wifi_set_packet_filter;
356     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
357     fn->wifi_nan_get_capabilities = nan_get_capabilities;
358     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
359     fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
360     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
361     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
362     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
363     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
364 
365     return WIFI_SUCCESS;
366 }
367 
wifi_initialize(wifi_handle * handle)368 wifi_error wifi_initialize(wifi_handle *handle)
369 {
370     int err = 0;
371     bool driver_loaded = false;
372     wifi_error ret = WIFI_SUCCESS;
373     wifi_interface_handle iface_handle;
374     struct nl_sock *cmd_sock = NULL;
375     struct nl_sock *event_sock = NULL;
376     struct nl_cb *cb = NULL;
377 
378     ALOGI("Initializing wifi");
379     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
380     if (info == NULL) {
381         ALOGE("Could not allocate hal_info");
382         return WIFI_ERROR_OUT_OF_MEMORY;
383     }
384 
385     memset(info, 0, sizeof(*info));
386 
387     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
388                                                      NETLINK_GENERIC);
389     if (cmd_sock == NULL) {
390         ALOGE("Failed to create command socket port");
391         ret = WIFI_ERROR_UNKNOWN;
392         goto unload;
393     }
394 
395     /* Set the socket buffer size */
396     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
397         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
398                    strerror(errno));
399         /* continue anyway with the default (smaller) buffer */
400     }
401 
402     event_sock =
403         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
404     if (event_sock == NULL) {
405         ALOGE("Failed to create event socket port");
406         ret = WIFI_ERROR_UNKNOWN;
407         goto unload;
408     }
409 
410     /* Set the socket buffer size */
411     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
412         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
413                    strerror(errno));
414         /* continue anyway with the default (smaller) buffer */
415     }
416 
417     cb = nl_socket_get_cb(event_sock);
418     if (cb == NULL) {
419         ALOGE("Failed to get NL control block for event socket port");
420         ret = WIFI_ERROR_UNKNOWN;
421         goto unload;
422     }
423 
424     err = 1;
425     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
426     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
427     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
428     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
429 
430     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
431             info);
432     nl_cb_put(cb);
433 
434     info->cmd_sock = cmd_sock;
435     info->event_sock = event_sock;
436     info->clean_up = false;
437     info->in_event_loop = false;
438 
439     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
440     if (info->event_cb == NULL) {
441         ALOGE("Could not allocate event_cb");
442         ret = WIFI_ERROR_OUT_OF_MEMORY;
443         goto unload;
444     }
445     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
446     info->num_event_cb = 0;
447 
448     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
449     if (info->cmd == NULL) {
450         ALOGE("Could not allocate cmd info");
451         ret = WIFI_ERROR_OUT_OF_MEMORY;
452         goto unload;
453     }
454     info->alloc_cmd = DEFAULT_CMD_SIZE;
455     info->num_cmd = 0;
456 
457     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
458     if (info->nl80211_family_id < 0) {
459         ALOGE("Could not resolve nl80211 familty id");
460         ret = WIFI_ERROR_UNKNOWN;
461         goto unload;
462     }
463 
464     pthread_mutex_init(&info->cb_lock, NULL);
465     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
466 
467     *handle = (wifi_handle) info;
468 
469     wifi_add_membership(*handle, "scan");
470     wifi_add_membership(*handle, "mlme");
471     wifi_add_membership(*handle, "regulatory");
472     wifi_add_membership(*handle, "vendor");
473 
474     ret = wifi_init_user_sock(info);
475     if (ret != WIFI_SUCCESS) {
476         ALOGE("Failed to alloc user socket");
477         goto unload;
478     }
479 
480     if (!is_wifi_driver_loaded()) {
481         ret = (wifi_error)wifi_load_driver();
482         if(ret != WIFI_SUCCESS) {
483             ALOGE("%s Failed to load wifi driver : %d\n", __func__, ret);
484             goto unload;
485         }
486         driver_loaded = true;
487     }
488 
489     ret = wifi_init_interfaces(*handle);
490     if (ret != WIFI_SUCCESS) {
491         ALOGE("Failed to init interfaces");
492         goto unload;
493     }
494 
495     if (info->num_interfaces == 0) {
496         ALOGE("No interfaces found");
497         ret = WIFI_ERROR_UNINITIALIZED;
498         goto unload;
499     }
500 
501     iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle,
502             (info->interfaces[0])->name);
503     if (iface_handle == NULL) {
504         int i;
505         for (i = 0; i < info->num_interfaces; i++)
506         {
507             free(info->interfaces[i]);
508         }
509         ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name);
510         goto unload;
511     }
512 
513     ret = acquire_supported_features(iface_handle,
514             &info->supported_feature_set);
515     if (ret != WIFI_SUCCESS) {
516         ALOGI("Failed to get supported feature set : %d", ret);
517         //acquire_supported_features failure is acceptable condition as legacy
518         //drivers might not support the required vendor command. So, do not
519         //consider it as failure of wifi_initialize
520         ret = WIFI_SUCCESS;
521     }
522 
523     ret = get_firmware_bus_max_size_supported(iface_handle);
524     if (ret != WIFI_SUCCESS) {
525         ALOGE("Failed to get supported bus size, error : %d", ret);
526         info->firmware_bus_max_size = 1520;
527     }
528 
529     ret = wifi_logger_ring_buffers_init(info);
530     if (ret != WIFI_SUCCESS) {
531         ALOGE("Wifi Logger Ring Initialization Failed");
532         goto unload;
533     }
534 
535     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
536     if (!info->pkt_stats) {
537         ALOGE("%s: malloc Failed for size: %zu",
538                 __FUNCTION__, sizeof(struct pkt_stats_s));
539         ret = WIFI_ERROR_OUT_OF_MEMORY;
540         goto unload;
541     }
542 
543     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
544                                   * PKT_STATS_BUF_SIZE;
545 
546     info->rx_aggr_pkts =
547         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
548     if (!info->rx_aggr_pkts) {
549         ALOGE("%s: malloc Failed for size: %d",
550                 __FUNCTION__, info->rx_buf_size_allocated);
551         ret = WIFI_ERROR_OUT_OF_MEMORY;
552         info->rx_buf_size_allocated = 0;
553         goto unload;
554     }
555     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
556 
557     info->exit_sockets[0] = -1;
558     info->exit_sockets[1] = -1;
559 
560     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
561         ALOGE("Failed to create exit socket pair");
562         ret = WIFI_ERROR_UNKNOWN;
563         goto unload;
564     }
565 
566     ALOGV("Initializing Gscan Event Handlers");
567     ret = initializeGscanHandlers(info);
568     if (ret != WIFI_SUCCESS) {
569         ALOGE("Initializing Gscan Event Handlers Failed");
570         goto unload;
571     }
572 
573     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
574             " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
575 
576 unload:
577     if (ret != WIFI_SUCCESS) {
578         if (cmd_sock)
579             nl_socket_free(cmd_sock);
580         if (event_sock)
581             nl_socket_free(event_sock);
582         if (info) {
583             if (info->cmd) free(info->cmd);
584             if (info->event_cb) free(info->event_cb);
585             if (info->user_sock) nl_socket_free(info->user_sock);
586             if (info->pkt_stats) free(info->pkt_stats);
587             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
588             cleanupGscanHandlers(info);
589             free(info);
590         }
591     }
592 
593     if (driver_loaded)
594         wifi_unload_driver();
595     return ret;
596 }
597 
wifi_add_membership(wifi_handle handle,const char * group)598 static int wifi_add_membership(wifi_handle handle, const char *group)
599 {
600     hal_info *info = getHalInfo(handle);
601 
602     int id = wifi_get_multicast_id(handle, "nl80211", group);
603     if (id < 0) {
604         ALOGE("Could not find group %s", group);
605         return id;
606     }
607 
608     int ret = nl_socket_add_membership(info->event_sock, id);
609     if (ret < 0) {
610         ALOGE("Could not add membership to group %s", group);
611     }
612 
613     return ret;
614 }
615 
internal_cleaned_up_handler(wifi_handle handle)616 static void internal_cleaned_up_handler(wifi_handle handle)
617 {
618     hal_info *info = getHalInfo(handle);
619     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
620 
621     if (info->cmd_sock != 0) {
622         nl_socket_free(info->cmd_sock);
623         nl_socket_free(info->event_sock);
624         info->cmd_sock = NULL;
625         info->event_sock = NULL;
626     }
627 
628     if (info->user_sock != 0) {
629         nl_socket_free(info->user_sock);
630         info->user_sock = NULL;
631     }
632 
633     if (info->pkt_stats)
634         free(info->pkt_stats);
635     if (info->rx_aggr_pkts)
636         free(info->rx_aggr_pkts);
637     wifi_logger_ring_buffers_deinit(info);
638     cleanupGscanHandlers(info);
639 
640     if (info->exit_sockets[0] >= 0) {
641         close(info->exit_sockets[0]);
642         info->exit_sockets[0] = -1;
643     }
644 
645     if (info->exit_sockets[1] >= 0) {
646         close(info->exit_sockets[1]);
647         info->exit_sockets[1] = -1;
648     }
649 
650     if (info->pkt_fate_stats) {
651         free(info->pkt_fate_stats);
652         info->pkt_fate_stats = NULL;
653     }
654 
655     (*cleaned_up_handler)(handle);
656     pthread_mutex_destroy(&info->cb_lock);
657     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
658     free(info);
659 }
660 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)661 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
662 {
663     if (!handle) {
664         ALOGE("Handle is null");
665         return;
666     }
667 
668     hal_info *info = getHalInfo(handle);
669     info->cleaned_up_handler = handler;
670     info->clean_up = true;
671 
672     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
673     ALOGI("Sent msg on exit sock to unblock poll()");
674 }
675 
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)676 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
677 {
678     struct nl_cb *cb = nl_socket_get_cb(sock);
679 
680     int res = nl_recvmsgs(sock, cb);
681     if(res)
682         ALOGE("Error :%d while reading nl msg", res);
683     nl_cb_put(cb);
684     return res;
685 }
686 
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)687 static void internal_event_handler(wifi_handle handle, int events,
688                                    struct nl_sock *sock)
689 {
690     if (events & POLLERR) {
691         ALOGE("Error reading from socket");
692         internal_pollin_handler(handle, sock);
693     } else if (events & POLLHUP) {
694         ALOGE("Remote side hung up");
695     } else if (events & POLLIN) {
696         //ALOGI("Found some events!!!");
697         internal_pollin_handler(handle, sock);
698     } else {
699         ALOGE("Unknown event - %0x", events);
700     }
701 }
702 
703 /* Run event handler */
wifi_event_loop(wifi_handle handle)704 void wifi_event_loop(wifi_handle handle)
705 {
706     hal_info *info = getHalInfo(handle);
707     if (info->in_event_loop) {
708         return;
709     } else {
710         info->in_event_loop = true;
711     }
712 
713     pollfd pfd[3];
714     memset(&pfd, 0, 3*sizeof(pfd[0]));
715 
716     pfd[0].fd = nl_socket_get_fd(info->event_sock);
717     pfd[0].events = POLLIN;
718 
719     pfd[1].fd = nl_socket_get_fd(info->user_sock);
720     pfd[1].events = POLLIN;
721 
722     pfd[2].fd = info->exit_sockets[1];
723     pfd[2].events = POLLIN;
724 
725     /* TODO: Add support for timeouts */
726 
727     do {
728         int timeout = -1;                   /* Infinite timeout */
729         pfd[0].revents = 0;
730         pfd[1].revents = 0;
731         pfd[2].revents = 0;
732         //ALOGI("Polling sockets");
733         int result = poll(pfd, 3, -1);
734         if (result < 0) {
735             ALOGE("Error polling socket");
736         } else {
737             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
738                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
739             }
740             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
741                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
742             }
743         }
744         rb_timerhandler(info);
745     } while (!info->clean_up);
746     internal_cleaned_up_handler(handle);
747 }
748 
user_sock_message_handler(nl_msg * msg,void * arg)749 static int user_sock_message_handler(nl_msg *msg, void *arg)
750 {
751     wifi_handle handle = (wifi_handle)arg;
752     hal_info *info = getHalInfo(handle);
753 
754     diag_message_handler(info, msg);
755 
756     return NL_OK;
757 }
758 
internal_valid_message_handler(nl_msg * msg,void * arg)759 static int internal_valid_message_handler(nl_msg *msg, void *arg)
760 {
761     wifi_handle handle = (wifi_handle)arg;
762     hal_info *info = getHalInfo(handle);
763 
764     WifiEvent event(msg);
765     int res = event.parse();
766     if (res < 0) {
767         ALOGE("Failed to parse event: %d", res);
768         return NL_SKIP;
769     }
770 
771     int cmd = event.get_cmd();
772     uint32_t vendor_id = 0;
773     int subcmd = 0;
774 
775     if (cmd == NL80211_CMD_VENDOR) {
776         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
777         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
778         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
779            of logs in bug report */
780         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
781             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
782                   event.get_cmdString(), vendor_id, subcmd);
783         }
784     } else {
785         ALOGV("event received %s", event.get_cmdString());
786     }
787 
788     // event.log();
789 
790     bool dispatched = false;
791 
792     pthread_mutex_lock(&info->cb_lock);
793 
794     for (int i = 0; i < info->num_event_cb; i++) {
795         if (cmd == info->event_cb[i].nl_cmd) {
796             if (cmd == NL80211_CMD_VENDOR
797                 && ((vendor_id != info->event_cb[i].vendor_id)
798                 || (subcmd != info->event_cb[i].vendor_subcmd)))
799             {
800                 /* event for a different vendor, ignore it */
801                 continue;
802             }
803 
804             cb_info *cbi = &(info->event_cb[i]);
805             pthread_mutex_unlock(&info->cb_lock);
806             if (cbi->cb_func) {
807                 (*(cbi->cb_func))(msg, cbi->cb_arg);
808                 dispatched = true;
809             }
810             return NL_OK;
811         }
812     }
813 
814 #ifdef QC_HAL_DEBUG
815     if (!dispatched) {
816         ALOGI("event ignored!!");
817     }
818 #endif
819 
820     pthread_mutex_unlock(&info->cb_lock);
821     return NL_OK;
822 }
823 
824 ////////////////////////////////////////////////////////////////////////////////
825 
826 class GetMulticastIdCommand : public WifiCommand
827 {
828 private:
829     const char *mName;
830     const char *mGroup;
831     int   mId;
832 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)833     GetMulticastIdCommand(wifi_handle handle, const char *name,
834             const char *group) : WifiCommand(handle, 0)
835     {
836         mName = name;
837         mGroup = group;
838         mId = -1;
839     }
840 
getId()841     int getId() {
842         return mId;
843     }
844 
create()845     virtual int create() {
846         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
847         // ALOGI("ctrl family = %d", nlctrlFamily);
848         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
849         if (ret < 0) {
850             return ret;
851         }
852         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
853         return ret;
854     }
855 
handleResponse(WifiEvent & reply)856     virtual int handleResponse(WifiEvent& reply) {
857 
858         // ALOGI("handling reponse in %s", __func__);
859 
860         struct nlattr **tb = reply.attributes();
861         struct genlmsghdr *gnlh = reply.header();
862         struct nlattr *mcgrp = NULL;
863         int i;
864 
865         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
866             ALOGI("No multicast groups found");
867             return NL_SKIP;
868         } else {
869             // ALOGI("Multicast groups attr size = %d",
870             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
871         }
872 
873         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
874 
875             // ALOGI("Processing group");
876             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
877             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
878                 nla_len(mcgrp), NULL);
879             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
880             {
881                 continue;
882             }
883 
884             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
885             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
886 
887             // ALOGI("Found group name %s", grpName);
888 
889             if (strncmp(grpName, mGroup, grpNameLen) != 0)
890                 continue;
891 
892             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
893             break;
894         }
895 
896         return NL_SKIP;
897     }
898 
899 };
900 
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)901 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
902         const char *group)
903 {
904     GetMulticastIdCommand cmd(handle, name, group);
905     int res = cmd.requestResponse();
906     if (res < 0)
907         return res;
908     else
909         return cmd.getId();
910 }
911 
912 /////////////////////////////////////////////////////////////////////////
913 
is_wifi_interface(const char * name)914 static bool is_wifi_interface(const char *name)
915 {
916     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
917         /* not a wifi interface; ignore it */
918         return false;
919     } else {
920         return true;
921     }
922 }
923 
get_interface(const char * name,interface_info * info)924 static int get_interface(const char *name, interface_info *info)
925 {
926     strlcpy(info->name, name, (IFNAMSIZ + 1));
927     info->id = if_nametoindex(name);
928     // ALOGI("found an interface : %s, id = %d", name, info->id);
929     return WIFI_SUCCESS;
930 }
931 
wifi_init_interfaces(wifi_handle handle)932 wifi_error wifi_init_interfaces(wifi_handle handle)
933 {
934     hal_info *info = (hal_info *)handle;
935 
936     struct dirent *de;
937 
938     DIR *d = opendir("/sys/class/net");
939     if (d == 0)
940         return WIFI_ERROR_UNKNOWN;
941 
942     int n = 0;
943     while ((de = readdir(d))) {
944         if (de->d_name[0] == '.')
945             continue;
946         if (is_wifi_interface(de->d_name) ) {
947             n++;
948         }
949     }
950 
951     closedir(d);
952 
953     d = opendir("/sys/class/net");
954     if (d == 0)
955         return WIFI_ERROR_UNKNOWN;
956 
957     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
958     if (info->interfaces == NULL) {
959         ALOGE("%s: Error info->interfaces NULL", __func__);
960         return WIFI_ERROR_OUT_OF_MEMORY;
961     }
962 
963     int i = 0;
964     while ((de = readdir(d))) {
965         if (de->d_name[0] == '.')
966             continue;
967         if (is_wifi_interface(de->d_name)) {
968             interface_info *ifinfo
969                 = (interface_info *)malloc(sizeof(interface_info));
970             if (ifinfo == NULL) {
971                 ALOGE("%s: Error ifinfo NULL", __func__);
972                 while (i > 0) {
973                     free(info->interfaces[i-1]);
974                     i--;
975                 }
976                 free(info->interfaces);
977                 return WIFI_ERROR_OUT_OF_MEMORY;
978             }
979             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
980                 free(ifinfo);
981                 continue;
982             }
983             ifinfo->handle = handle;
984             info->interfaces[i] = ifinfo;
985             i++;
986         }
987     }
988 
989     closedir(d);
990 
991     info->num_interfaces = n;
992 
993     return WIFI_SUCCESS;
994 }
995 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)996 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
997         wifi_interface_handle **interfaces)
998 {
999     hal_info *info = (hal_info *)handle;
1000 
1001     *interfaces = (wifi_interface_handle *)info->interfaces;
1002     *num = info->num_interfaces;
1003 
1004     return WIFI_SUCCESS;
1005 }
1006 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1007 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1008         size_t size)
1009 {
1010     interface_info *info = (interface_info *)handle;
1011     strlcpy(name, info->name, size);
1012     return WIFI_SUCCESS;
1013 }
1014 
1015 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1016 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1017         feature_set *set)
1018 {
1019     int ret = 0;
1020     wifi_handle handle = getWifiHandle(iface);
1021     *set = 0;
1022     hal_info *info = getHalInfo(handle);
1023 
1024     ret = acquire_supported_features(iface, set);
1025     if (ret != WIFI_SUCCESS) {
1026         *set = info->supported_feature_set;
1027         ALOGV("Supported feature set acquired at initialization : %x", *set);
1028     } else {
1029         info->supported_feature_set = *set;
1030         ALOGV("Supported feature set acquired : %x", *set);
1031     }
1032     return WIFI_SUCCESS;
1033 }
1034 
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1035 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1036                                        int set_size_max,
1037                                        feature_set set[], int *set_size)
1038 {
1039     int ret = 0;
1040     struct nlattr *nlData;
1041     WifihalGeneric *vCommand = NULL;
1042     interface_info *ifaceInfo = getIfaceInfo(handle);
1043     wifi_handle wifiHandle = getWifiHandle(handle);
1044 
1045     if (set == NULL) {
1046         ALOGE("%s: NULL set pointer provided. Exit.",
1047             __func__);
1048         return WIFI_ERROR_INVALID_ARGS;
1049     }
1050 
1051     vCommand = new WifihalGeneric(wifiHandle, 0,
1052             OUI_QCA,
1053             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1054     if (vCommand == NULL) {
1055         ALOGE("%s: Error vCommand NULL", __func__);
1056         return WIFI_ERROR_OUT_OF_MEMORY;
1057     }
1058 
1059     /* Create the message */
1060     ret = vCommand->create();
1061     if (ret < 0)
1062         goto cleanup;
1063 
1064     ret = vCommand->set_iface_id(ifaceInfo->name);
1065     if (ret < 0)
1066         goto cleanup;
1067 
1068     /* Add the vendor specific attributes for the NL command. */
1069     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1070     if (!nlData)
1071         goto cleanup;
1072 
1073     if (vCommand->put_u32(
1074         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1075         set_size_max))
1076     {
1077         goto cleanup;
1078     }
1079     vCommand->attr_end(nlData);
1080 
1081     /* Populate the input received from caller/framework. */
1082     vCommand->setMaxSetSize(set_size_max);
1083     vCommand->setSizePtr(set_size);
1084     vCommand->setConcurrencySet(set);
1085 
1086     ret = vCommand->requestResponse();
1087     if (ret) {
1088         ALOGE("%s: requestResponse() error: %d", __func__, ret);
1089     }
1090 
1091 cleanup:
1092     delete vCommand;
1093     if (ret) {
1094         *set_size = 0;
1095     }
1096     return (wifi_error)ret;
1097 }
1098 
1099 
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1100 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1101 {
1102     int ret = 0;
1103     struct nlattr *nlData;
1104     WifiVendorCommand *vCommand = NULL;
1105     interface_info *ifaceInfo = getIfaceInfo(handle);
1106     wifi_handle wifiHandle = getWifiHandle(handle);
1107 
1108     vCommand = new WifiVendorCommand(wifiHandle, 0,
1109             OUI_QCA,
1110             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
1111     if (vCommand == NULL) {
1112         ALOGE("%s: Error vCommand NULL", __func__);
1113         return WIFI_ERROR_OUT_OF_MEMORY;
1114     }
1115 
1116     /* Create the message */
1117     ret = vCommand->create();
1118     if (ret < 0)
1119         goto cleanup;
1120 
1121     ret = vCommand->set_iface_id(ifaceInfo->name);
1122     if (ret < 0)
1123         goto cleanup;
1124 
1125     /* Add the vendor specific attributes for the NL command. */
1126     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1127     if (!nlData)
1128         goto cleanup;
1129 
1130     /* Add the fixed part of the mac_oui to the nl command */
1131     if (vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs)) {
1132         goto cleanup;
1133     }
1134 
1135     vCommand->attr_end(nlData);
1136 
1137     ret = vCommand->requestResponse();
1138     /* Don't check response since we aren't expecting one */
1139 
1140 cleanup:
1141     delete vCommand;
1142     return (wifi_error)ret;
1143 }
1144 
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)1145 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
1146                                                wifi_interface_handle iface,
1147                                                u8 *ip_packet,
1148                                                u16 ip_packet_len,
1149                                                u8 *src_mac_addr,
1150                                                u8 *dst_mac_addr,
1151                                                u32 period_msec)
1152 {
1153     int ret = WIFI_SUCCESS;
1154     struct nlattr *nlData;
1155     WifiVendorCommand *vCommand = NULL;
1156 
1157     ret = initialize_vendor_cmd(iface, id,
1158                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1159                                 &vCommand);
1160     if (ret != WIFI_SUCCESS) {
1161         ALOGE("%s: Initialization failed", __func__);
1162         return (wifi_error)ret;
1163     }
1164 
1165     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
1166     hexdump(ip_packet, ip_packet_len);
1167     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
1168           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
1169           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
1170 
1171     /* Add the vendor specific attributes for the NL command. */
1172     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1173     if (!nlData)
1174         goto cleanup;
1175 
1176     if (vCommand->put_u32(
1177             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1178             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START) ||
1179         vCommand->put_u32(
1180             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1181             id) ||
1182         vCommand->put_bytes(
1183             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
1184             (const char *)ip_packet, ip_packet_len) ||
1185         vCommand->put_addr(
1186             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
1187             src_mac_addr) ||
1188         vCommand->put_addr(
1189             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
1190             dst_mac_addr) ||
1191         vCommand->put_u32(
1192             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
1193             period_msec))
1194     {
1195         goto cleanup;
1196     }
1197 
1198     vCommand->attr_end(nlData);
1199 
1200     ret = vCommand->requestResponse();
1201     if (ret < 0)
1202         goto cleanup;
1203 
1204 cleanup:
1205     delete vCommand;
1206     return (wifi_error)ret;
1207 }
1208 
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)1209 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
1210                                               wifi_interface_handle iface)
1211 {
1212     int ret = WIFI_SUCCESS;
1213     struct nlattr *nlData;
1214     WifiVendorCommand *vCommand = NULL;
1215 
1216     ret = initialize_vendor_cmd(iface, id,
1217                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1218                                 &vCommand);
1219     if (ret != WIFI_SUCCESS) {
1220         ALOGE("%s: Initialization failed", __func__);
1221         return (wifi_error)ret;
1222     }
1223 
1224     /* Add the vendor specific attributes for the NL command. */
1225     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1226     if (!nlData)
1227         goto cleanup;
1228 
1229     if (vCommand->put_u32(
1230             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1231             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP) ||
1232         vCommand->put_u32(
1233             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1234             id))
1235     {
1236         goto cleanup;
1237     }
1238 
1239 
1240     vCommand->attr_end(nlData);
1241 
1242     ret = vCommand->requestResponse();
1243     if (ret < 0)
1244         goto cleanup;
1245 
1246 cleanup:
1247     delete vCommand;
1248     return (wifi_error)ret;
1249 }
1250 
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)1251 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
1252                                          const u8 *program, u32 len)
1253 {
1254     int ret = WIFI_SUCCESS;
1255     struct nlattr *nlData;
1256     WifiVendorCommand *vCommand = NULL;
1257     u32 current_offset = 0;
1258     wifi_handle wifiHandle = getWifiHandle(iface);
1259     hal_info *info = getHalInfo(wifiHandle);
1260 
1261     /* len=0 clears the filters in driver/firmware */
1262     if (len != 0 && program == NULL) {
1263         ALOGE("%s: No valid program provided. Exit.",
1264             __func__);
1265         return WIFI_ERROR_INVALID_ARGS;
1266     }
1267 
1268     do {
1269         ret = initialize_vendor_cmd(iface, get_requestid(),
1270                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1271                                     &vCommand);
1272         if (ret != WIFI_SUCCESS) {
1273             ALOGE("%s: Initialization failed", __FUNCTION__);
1274             return (wifi_error)ret;
1275         }
1276 
1277         /* Add the vendor specific attributes for the NL command. */
1278         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1279         if (!nlData)
1280             goto cleanup;
1281 
1282         if (vCommand->put_u32(
1283                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1284                 QCA_WLAN_SET_PACKET_FILTER) ||
1285             vCommand->put_u32(
1286                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
1287                 PACKET_FILTER_ID) ||
1288             vCommand->put_u32(
1289                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1290                 len) ||
1291             vCommand->put_u32(
1292                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1293                 current_offset)) {
1294             ALOGE("%s: failed to put subcmd/program", __FUNCTION__);
1295             goto cleanup;
1296         }
1297 
1298         if (len) {
1299             if(vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
1300                                    (char *)&program[current_offset],
1301                                    min(info->firmware_bus_max_size,
1302                                    len-current_offset))) {
1303                 ALOGE("%s: failed to put subcmd", __FUNCTION__);
1304                 goto cleanup;
1305             }
1306         }
1307 
1308         vCommand->attr_end(nlData);
1309 
1310         ret = vCommand->requestResponse();
1311         if (ret < 0) {
1312             ALOGE("%s: requestResponse Error:%d",__func__, ret);
1313             goto cleanup;
1314         }
1315 
1316         /* destroy the object after sending each fragment to driver */
1317         delete vCommand;
1318         vCommand = NULL;
1319 
1320         current_offset += min(info->firmware_bus_max_size, len);
1321     } while (current_offset < len);
1322 
1323 cleanup:
1324     if (vCommand)
1325         delete vCommand;
1326     return (wifi_error)ret;
1327 }
1328 
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)1329 static wifi_error wifi_get_packet_filter_capabilities(
1330                 wifi_interface_handle handle, u32 *version, u32 *max_len)
1331 {
1332     int ret = 0;
1333     struct nlattr *nlData;
1334     WifihalGeneric *vCommand = NULL;
1335     interface_info *ifaceInfo = getIfaceInfo(handle);
1336     wifi_handle wifiHandle = getWifiHandle(handle);
1337 
1338     if (version == NULL || max_len == NULL) {
1339         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
1340             __FUNCTION__);
1341         return WIFI_ERROR_INVALID_ARGS;
1342     }
1343 
1344     vCommand = new WifihalGeneric(wifiHandle, 0,
1345             OUI_QCA,
1346             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
1347     if (vCommand == NULL) {
1348         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1349         return WIFI_ERROR_OUT_OF_MEMORY;
1350     }
1351 
1352     /* Create the message */
1353     ret = vCommand->create();
1354     if (ret < 0)
1355         goto cleanup;
1356 
1357     ret = vCommand->set_iface_id(ifaceInfo->name);
1358     if (ret < 0)
1359         goto cleanup;
1360 
1361     /* Add the vendor specific attributes for the NL command. */
1362     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1363     if (!nlData)
1364         goto cleanup;
1365 
1366     if (vCommand->put_u32(
1367             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1368             QCA_WLAN_GET_PACKET_FILTER_SIZE))
1369     {
1370         goto cleanup;
1371     }
1372     vCommand->attr_end(nlData);
1373 
1374     ret = vCommand->requestResponse();
1375     if (ret) {
1376         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
1377         if (ret == -ENOTSUP) {
1378             /* Packet filtering is not supported currently, so return version
1379              * and length as 0
1380              */
1381             ALOGI("Packet filtering is not supprted");
1382             *version = 0;
1383             *max_len = 0;
1384             ret = WIFI_SUCCESS;
1385         }
1386         goto cleanup;
1387     }
1388 
1389     *version = vCommand->getFilterVersion();
1390     *max_len = vCommand->getFilterLength();
1391 cleanup:
1392     delete vCommand;
1393     return (wifi_error)ret;
1394 }
1395 
1396 
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)1397 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
1398                                             u8 enable)
1399 {
1400     int ret = WIFI_SUCCESS;
1401     struct nlattr *nlData;
1402     WifiVendorCommand *vCommand = NULL;
1403 
1404     ret = initialize_vendor_cmd(iface, get_requestid(),
1405                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
1406                                 &vCommand);
1407     if (ret != WIFI_SUCCESS) {
1408         ALOGE("%s: Initialization failed", __func__);
1409         return (wifi_error)ret;
1410     }
1411 
1412     ALOGV("ND offload : %s", enable?"Enable":"Disable");
1413 
1414     /* Add the vendor specific attributes for the NL command. */
1415     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1416     if (!nlData)
1417         goto cleanup;
1418 
1419     if (vCommand->put_u8(
1420             QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG,
1421             enable))
1422     {
1423         goto cleanup;
1424     }
1425 
1426     vCommand->attr_end(nlData);
1427 
1428     ret = vCommand->requestResponse();
1429 
1430 cleanup:
1431     delete vCommand;
1432     return (wifi_error)ret;
1433 }
1434