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