[7885] wlbt : Handle APF in HAL
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / wifi_hal.cpp
CommitLineData
7753f181
DD
1#include <errno.h>
2#include <stdint.h>
c0b490a2 3#include <string.h>
7753f181
DD
4#include <fcntl.h>
5#include <sys/socket.h>
6#include <netlink/genl/genl.h>
7#include <netlink/genl/family.h>
8#include <netlink/genl/ctrl.h>
9#include <linux/rtnetlink.h>
10#include <netpacket/packet.h>
11#include <linux/filter.h>
12#include <linux/errqueue.h>
13
14#include <linux/pkt_sched.h>
15#include <netlink/object-api.h>
16#include <netlink/netlink.h>
17#include <netlink/socket.h>
18#include <netlink/attr.h>
19#include <netlink/handlers.h>
20#include <netlink/msg.h>
21
22#include <dirent.h>
23#include <net/if.h>
24
25#include "sync.h"
26
27#define LOG_TAG "WifiHAL"
28
29#include <utils/Log.h>
7753f181
DD
30#include "wifi_hal.h"
31#include "common.h"
32#include "cpp_bindings.h"
02b2b8ab 33#include "roam.h"
7753f181
DD
34
35
36#define WIFI_HAL_CMD_SOCK_PORT 644
37#define WIFI_HAL_EVENT_SOCK_PORT 645
38
39#define FEATURE_SET 0
40#define FEATURE_SET_MATRIX 1
41#define ATTR_NODFS_VALUE 3
1fdbd4c1 42#define ATTR_COUNTRY_CODE 4
7753f181
DD
43
44static void internal_event_handler(wifi_handle handle, int events);
45static int internal_no_seq_check(nl_msg *msg, void *arg);
46static int internal_valid_message_handler(nl_msg *msg, void *arg);
47static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
48static int wifi_add_membership(wifi_handle handle, const char *group);
49static wifi_error wifi_init_interfaces(wifi_handle handle);
50
51typedef enum wifi_attr {
de14a5c9 52 ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_CONFIG,
7753f181
DD
53 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI
54} wifi_attr_t;
55
f425b4a8
PG
56enum wifi_rssi_monitor_attr {
57 RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
58 RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
59 RSSI_MONITOR_ATTRIBUTE_START,
60};
61
62static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
63 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
64static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
65
7753f181
DD
66/* Initialize/Cleanup */
67
68void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
69{
70 uint32_t pid = getpid() & 0x3FFFFF;
71 nl_socket_set_local_port(sock, pid + (port << 22));
72}
73
74static nl_sock * wifi_create_nl_socket(int port)
75{
7753f181
DD
76 struct nl_sock *sock = nl_socket_alloc();
77 if (sock == NULL) {
78 ALOGE("Could not create handle");
79 return NULL;
80 }
81
82 wifi_socket_set_local_port(sock, port);
83
7753f181
DD
84 if (nl_connect(sock, NETLINK_GENERIC)) {
85 ALOGE("Could not connect handle");
86 nl_socket_free(sock);
87 return NULL;
88 }
89
7753f181
DD
90 return sock;
91}
92
d59e4b54 93/* Initialize HAL function pointer table */
7753f181
DD
94wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
95{
96 if (fn == NULL) {
97 return WIFI_ERROR_UNKNOWN;
98 }
99 fn->wifi_initialize = wifi_initialize;
100 fn->wifi_cleanup = wifi_cleanup;
101 fn->wifi_event_loop = wifi_event_loop;
102 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
103 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
104 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
105 fn->wifi_get_ifaces = wifi_get_ifaces;
106 fn->wifi_get_iface_name = wifi_get_iface_name;
107 fn->wifi_start_gscan = wifi_start_gscan;
108 fn->wifi_stop_gscan = wifi_stop_gscan;
109 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
110 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
111 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
112 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
113 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
114 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
7753f181
DD
115 fn->wifi_get_valid_channels = wifi_get_valid_channels;
116 fn->wifi_rtt_range_request = wifi_rtt_range_request;
117 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
118 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
119 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
3c0c6ab1
PG
120 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
121 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
6ff2d683 122 fn->wifi_set_epno_list = wifi_set_epno_list;
c15187c1 123 fn->wifi_reset_epno_list = wifi_reset_epno_list;
6ff2d683
JPS
124 fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
125 fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
f425b4a8
PG
126 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
127 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
d583845d 128 fn->wifi_set_link_stats = wifi_set_link_stats;
058cae5f 129 fn->wifi_get_link_stats = wifi_get_link_stats;
d583845d 130 fn->wifi_clear_link_stats = wifi_clear_link_stats;
1fdbd4c1 131 fn->wifi_set_country_code = wifi_set_country_code;
02b2b8ab 132 fn->wifi_configure_roaming = wifi_configure_roaming;
de14a5c9 133 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
114ef2d7 134 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
d1c19a13 135
7753f181
DD
136 return WIFI_SUCCESS;
137}
138
139wifi_error wifi_initialize(wifi_handle *handle)
140{
141 srand(getpid());
142
143 ALOGI("Initializing wifi");
144 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
145 if (info == NULL) {
146 ALOGE("Could not allocate hal_info");
147 return WIFI_ERROR_UNKNOWN;
148 }
149
150 memset(info, 0, sizeof(*info));
151
7753f181
DD
152 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
153 ALOGE("Could not create cleanup sockets");
154 free(info);
155 return WIFI_ERROR_UNKNOWN;
156 }
157
158 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
159 if (cmd_sock == NULL) {
160 ALOGE("Could not create handle");
161 free(info);
162 return WIFI_ERROR_UNKNOWN;
163 }
164
165 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
166 if (event_sock == NULL) {
167 ALOGE("Could not create handle");
168 nl_socket_free(cmd_sock);
169 free(info);
170 return WIFI_ERROR_UNKNOWN;
171 }
172
173 struct nl_cb *cb = nl_socket_get_cb(event_sock);
174 if (cb == NULL) {
175 ALOGE("Could not create handle");
176 nl_socket_free(cmd_sock);
177 nl_socket_free(event_sock);
178 free(info);
179 return WIFI_ERROR_UNKNOWN;
180 }
181
182// ALOGI("cb->refcnt = %d", cb->cb_refcnt);
183 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
184 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
185 nl_cb_put(cb);
186
187 info->cmd_sock = cmd_sock;
188 info->event_sock = event_sock;
189 info->clean_up = false;
190 info->in_event_loop = false;
191
192 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
193 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
194 info->num_event_cb = 0;
195
196 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
197 info->alloc_cmd = DEFAULT_CMD_SIZE;
198 info->num_cmd = 0;
199
200 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
201 if (info->nl80211_family_id < 0) {
202 ALOGE("Could not resolve nl80211 familty id");
203 nl_socket_free(cmd_sock);
204 nl_socket_free(event_sock);
205 free(info);
206 return WIFI_ERROR_UNKNOWN;
207 }
208
209 pthread_mutex_init(&info->cb_lock, NULL);
210
211 *handle = (wifi_handle) info;
c0b490a2 212
7753f181
DD
213 wifi_add_membership(*handle, "scan");
214 wifi_add_membership(*handle, "mlme");
215 wifi_add_membership(*handle, "regulatory");
216 wifi_add_membership(*handle, "vendor");
217
218 wifi_init_interfaces(*handle);
c0b490a2
JPS
219 char intf_name_buff[10 * 10 + 4]; /* Randomly choosen max interface 10. each interface name max 9 + 1(for space) */
220 char *pos = intf_name_buff;
221 for (int i = 0; i < (info->num_interfaces < 10 ? info->num_interfaces : 10); i++) {
222 strncpy(pos, info->interfaces[i]->name, sizeof(intf_name_buff) - (pos - intf_name_buff));
223 pos += strlen(pos);
224 }
225 if (info->num_interfaces > 10) {
226 strncpy(pos, "...", 3);
227 }
7753f181 228
c0b490a2 229 ALOGD("Found %d interfaces[%s]. Initialized Wifi HAL Successfully", info->num_interfaces, intf_name_buff);
7753f181 230
7753f181
DD
231 return WIFI_SUCCESS;
232}
233
234static int wifi_add_membership(wifi_handle handle, const char *group)
235{
236 hal_info *info = getHalInfo(handle);
237
238 int id = wifi_get_multicast_id(handle, "nl80211", group);
239 if (id < 0) {
240 ALOGE("Could not find group %s", group);
241 return id;
242 }
243
244 int ret = nl_socket_add_membership(info->event_sock, id);
245 if (ret < 0) {
246 ALOGE("Could not add membership to group %s", group);
247 }
7753f181
DD
248 return ret;
249}
250
251static void internal_cleaned_up_handler(wifi_handle handle)
252{
253 hal_info *info = getHalInfo(handle);
254 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
255
256 if (info->cmd_sock != 0) {
257 close(info->cleanup_socks[0]);
258 close(info->cleanup_socks[1]);
259 nl_socket_free(info->cmd_sock);
260 nl_socket_free(info->event_sock);
261 info->cmd_sock = NULL;
262 info->event_sock = NULL;
263 }
264
265 (*cleaned_up_handler)(handle);
266 pthread_mutex_destroy(&info->cb_lock);
267 free(info);
7753f181
DD
268}
269
270void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
271{
272 hal_info *info = getHalInfo(handle);
273 char buf[64];
274
275 info->cleaned_up_handler = handler;
276 if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
277 ALOGE("could not write to the cleanup socket");
278 } else {
279 // Listen to the response
280 // Hopefully we dont get errors or get hung up
281 // Not much can be done in that case, but assume that
282 // it has rx'ed the Exit message to exit the thread.
283 // As a fallback set the cleanup flag to TRUE
284 memset(buf, 0, sizeof(buf));
285 int result = read(info->cleanup_socks[0], buf, sizeof(buf));
286 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
c0b490a2 287 if (strncmp(buf, "Done", 4) != 0) {
7753f181
DD
288 ALOGD("Rx'ed %s", buf);
289 }
290 }
291 info->clean_up = true;
292 pthread_mutex_lock(&info->cb_lock);
293
294 int bad_commands = 0;
295
7753f181
DD
296 while (info->num_cmd > bad_commands) {
297 int num_cmd = info->num_cmd;
298 cmd_info *cmdi = &(info->cmd[bad_commands]);
299 WifiCommand *cmd = cmdi->cmd;
300 if (cmd != NULL) {
301 pthread_mutex_unlock(&info->cb_lock);
302 cmd->cancel();
303 pthread_mutex_lock(&info->cb_lock);
304 /* release reference added when command is saved */
305 cmd->releaseRef();
306 if (num_cmd == info->num_cmd) {
307 bad_commands++;
308 }
309 }
310 }
311
312 for (int i = 0; i < info->num_event_cb; i++) {
313 cb_info *cbi = &(info->event_cb[i]);
314 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
315 ALOGE("Leaked command %p", cmd);
316 }
317 pthread_mutex_unlock(&info->cb_lock);
318 internal_cleaned_up_handler(handle);
319}
320
321static int internal_pollin_handler(wifi_handle handle)
322{
323 hal_info *info = getHalInfo(handle);
7753f181
DD
324 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
325 int res = nl_recvmsgs(info->event_sock, cb);
7753f181
DD
326 nl_cb_put(cb);
327 return res;
328}
329
330/* Run event handler */
331void wifi_event_loop(wifi_handle handle)
332{
333 hal_info *info = getHalInfo(handle);
7753f181
DD
334 if (info->in_event_loop) {
335 return;
336 } else {
337 info->in_event_loop = true;
338 }
339
340 pollfd pfd[2];
341 memset(&pfd[0], 0, sizeof(pollfd) * 2);
342
343 pfd[0].fd = nl_socket_get_fd(info->event_sock);
344 pfd[0].events = POLLIN;
345 pfd[1].fd = info->cleanup_socks[1];
346 pfd[1].events = POLLIN;
347
348 char buf[2048];
349
350 do {
351 int timeout = -1; /* Infinite timeout */
352 pfd[0].revents = 0;
353 pfd[1].revents = 0;
354 int result = poll(pfd, 2, timeout);
355 if (result < 0) {
356 } else if (pfd[0].revents & POLLERR) {
c0b490a2 357 int prev_err = (int)errno;
7753f181 358 int result2 = read(pfd[0].fd, buf, sizeof(buf));
c0b490a2 359 ALOGE("Poll err:%d | Read after POLL returned %d, error no = %d", prev_err, result2, errno);
7753f181
DD
360 } else if (pfd[0].revents & POLLHUP) {
361 ALOGE("Remote side hung up");
362 break;
363 } else if (pfd[0].revents & POLLIN) {
364 internal_pollin_handler(handle);
365 } else if (pfd[1].revents & POLLIN) {
366 memset(buf, 0, sizeof(buf));
367 int result2 = read(pfd[1].fd, buf, sizeof(buf));
368 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
369 if (strncmp(buf, "Exit", 4) == 0) {
370 ALOGD("Got a signal to exit!!!");
371 if (write(pfd[1].fd, "Done", 4) < 1) {
372 ALOGE("could not write to the cleanup socket");
373 }
374 break;
375 } else {
376 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
377 }
378 } else {
379 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
380 }
381 } while (!info->clean_up);
7753f181
DD
382}
383
384///////////////////////////////////////////////////////////////////////////////////////
385
386static int internal_no_seq_check(struct nl_msg *msg, void *arg)
387{
388 return NL_OK;
389}
390
391static int internal_valid_message_handler(nl_msg *msg, void *arg)
392{
393 wifi_handle handle = (wifi_handle)arg;
394 hal_info *info = getHalInfo(handle);
7753f181
DD
395
396 WifiEvent event(msg);
397 int res = event.parse();
398 if (res < 0) {
399 ALOGE("Failed to parse event: %d", res);
400 return NL_SKIP;
401 }
402
403 int cmd = event.get_cmd();
404 uint32_t vendor_id = 0;
405 int subcmd = 0;
406
407 if (cmd == NL80211_CMD_VENDOR) {
408 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
409 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
d20effd2 410 /*
7753f181 411 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
d20effd2 412 event.get_cmdString(), vendor_id, subcmd);*/
7753f181
DD
413 }
414
415 //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
416 //event.log();
417
7753f181 418 pthread_mutex_lock(&info->cb_lock);
3c0c6ab1 419
7753f181
DD
420 for (int i = 0; i < info->num_event_cb; i++) {
421 if (cmd == info->event_cb[i].nl_cmd) {
422 if (cmd == NL80211_CMD_VENDOR
423 && ((vendor_id != info->event_cb[i].vendor_id)
424 || (subcmd != info->event_cb[i].vendor_subcmd)))
425 {
426 /* event for a different vendor, ignore it */
427 continue;
428 }
429
430 cb_info *cbi = &(info->event_cb[i]);
431 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
432 void *cb_arg = cbi->cb_arg;
433 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
434 if (cmd != NULL) {
435 cmd->addRef();
436 }
437
438 pthread_mutex_unlock(&info->cb_lock);
439 if (cb_func)
440 (*cb_func)(msg, cb_arg);
441 if (cmd != NULL) {
442 cmd->releaseRef();
443 }
444
445 return NL_OK;
446 }
447 }
448
449 pthread_mutex_unlock(&info->cb_lock);
450 return NL_OK;
451}
452
453///////////////////////////////////////////////////////////////////////////////////////
454
455class GetMulticastIdCommand : public WifiCommand
456{
457private:
458 const char *mName;
459 const char *mGroup;
460 int mId;
461public:
462 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
463 : WifiCommand(handle, 0)
464 {
465 mName = name;
466 mGroup = group;
467 mId = -1;
468 }
469
470 int getId() {
471 return mId;
472 }
473
474 virtual int create() {
475 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
7753f181
DD
476 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
477 if (ret < 0) {
478 return ret;
479 }
480 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
481 return ret;
482 }
483
484 virtual int handleResponse(WifiEvent& reply) {
7753f181 485 struct nlattr **tb = reply.attributes();
7753f181
DD
486 struct nlattr *mcgrp = NULL;
487 int i;
488
489 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
490 ALOGE("No multicast groups found");
491 return NL_SKIP;
7753f181
DD
492 }
493
494 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
495
7753f181
DD
496 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
497 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
498 nla_len(mcgrp), NULL);
499 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
500 continue;
501 }
502
503 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
504 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
505
7753f181
DD
506 if (strncmp(grpName, mGroup, grpNameLen) != 0)
507 continue;
508
509 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
510 break;
511 }
512
513 return NL_SKIP;
514 }
515
516};
517
518class SetPnoMacAddrOuiCommand : public WifiCommand {
519
520private:
521 byte *mOui;
522 feature_set *fset;
523 feature_set *feature_matrix;
524 int *fm_size;
525 int set_size_max;
526public:
527 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
528 : WifiCommand(handle, 0)
529 {
530 mOui = scan_oui;
ec386ae4
HG
531 fset = NULL;
532 feature_matrix = NULL;
533 fm_size = NULL;
534 set_size_max = 0;
7753f181
DD
535 }
536
537 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
538 int result = request.create(GOOGLE_OUI, subcmd);
539 if (result < 0) {
540 return result;
541 }
542
543 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
544 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
545 if (result < 0) {
546 return result;
547 }
548
549 request.attr_end(data);
550 return WIFI_SUCCESS;
551
552 }
553
554 int start() {
7753f181
DD
555 WifiRequest request(familyId(), ifaceId());
556 int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui);
557 if (result != WIFI_SUCCESS) {
558 ALOGE("failed to create request; result = %d", result);
559 return result;
560 }
561
562 result = requestResponse(request);
563 if (result != WIFI_SUCCESS) {
564 ALOGE("failed to set scanning mac OUI; result = %d", result);
565 }
566
567 return result;
568 }
569protected:
570 virtual int handleResponse(WifiEvent& reply) {
7753f181
DD
571 /* Nothing to do on response! */
572 return NL_SKIP;
573 }
574};
575
576class SetNodfsCommand : public WifiCommand {
577
578private:
579 u32 mNoDfs;
580public:
581 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
582 : WifiCommand(handle, 0) {
583 mNoDfs = nodfs;
584 }
585 virtual int create() {
586 int ret;
587
588 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS);
589 if (ret < 0) {
590 ALOGE("Can't create message to send to driver - %d", ret);
591 return ret;
592 }
593
594 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
595 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
596 if (ret < 0) {
597 return ret;
598 }
599
600 mMsg.attr_end(data);
601 return WIFI_SUCCESS;
602 }
603};
604
f425b4a8
PG
605class SetRSSIMonitorCommand : public WifiCommand {
606private:
607 s8 mMax_rssi;
608 s8 mMin_rssi;
609 wifi_rssi_event_handler mHandler;
610public:
611 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
612 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
613 : WifiCommand(handle, id), mMax_rssi(max_rssi), mMin_rssi
614 (min_rssi), mHandler(eh)
615 {
616 }
617 int createRequest(WifiRequest& request, int enable) {
618 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_RSSI_MONITOR);
619 if (result < 0) {
620 return result;
621 }
622
623 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
624 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
625 if (result < 0) {
626 return result;
627 }
c0b490a2 628
f425b4a8
PG
629 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
630 if (result < 0) {
631 return result;
632 }
633 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_START, enable);
634 if (result < 0) {
635 return result;
636 }
637 request.attr_end(data);
638 return result;
639 }
640
641 int start() {
642 WifiRequest request(familyId(), ifaceId());
643 int result = createRequest(request, 1);
644 if (result < 0) {
645 return result;
646 }
647 result = requestResponse(request);
648 if (result < 0) {
649 ALOGI("Failed to set RSSI Monitor, result = %d", result);
650 return result;
651 }
652 ALOGI("Successfully set RSSI monitoring");
653 registerVendorHandler(GOOGLE_OUI, WIFI_RSSI_REPORT_EVENT);
654
f425b4a8
PG
655 return result;
656 }
657
658 virtual int cancel() {
659
660 WifiRequest request(familyId(), ifaceId());
661 int result = createRequest(request, 0);
662 if (result != WIFI_SUCCESS) {
663 ALOGE("failed to create request; result = %d", result);
664 } else {
665 result = requestResponse(request);
666 if (result != WIFI_SUCCESS) {
667 ALOGE("failed to stop RSSI monitoring = %d", result);
668 }
669 }
670 unregisterVendorHandler(GOOGLE_OUI, WIFI_RSSI_REPORT_EVENT);
671 return WIFI_SUCCESS;
672 }
673
674 virtual int handleResponse(WifiEvent& reply) {
675 /* Nothing to do on response! */
676 return NL_SKIP;
677 }
678
679 virtual int handleEvent(WifiEvent& event) {
f425b4a8
PG
680
681 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
682 int len = event.get_vendor_data_len();
683
684 if (vendor_data == NULL || len == 0) {
685 ALOGI("RSSI monitor: No data");
686 return NL_SKIP;
687 }
688
689 typedef struct {
690 s8 cur_rssi;
691 mac_addr BSSID;
692 } rssi_monitor_evt;
693
694 rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
695
696 if (*mHandler.on_rssi_threshold_breached) {
697 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
698 } else {
699 ALOGW("No RSSI monitor handler registered");
700 }
701
702 return NL_SKIP;
703 }
704
705};
706
1fdbd4c1
MG
707class SetCountryCodeCommand : public WifiCommand {
708private:
709 const char *mCountryCode;
710public:
711 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
712 : WifiCommand(handle, 0) {
713 mCountryCode = country_code;
714 }
715 virtual int create() {
716 int ret;
717
718 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_COUNTRY_CODE);
719 if (ret < 0) {
720 ALOGE("Can't create message to send to driver - %d", ret);
721 return ret;
722 }
723
724 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
725 ret = mMsg.put_string(ATTR_COUNTRY_CODE, mCountryCode);
726 if (ret < 0) {
727 return ret;
728 }
729
730 mMsg.attr_end(data);
731 return WIFI_SUCCESS;
732
733 }
734};
735
0318783f 736class GetFeatureSetCommand : public WifiCommand {
f425b4a8 737
0318783f 738private:
0fe9bfaf 739
0318783f 740 feature_set *fset;
0fe9bfaf 741
0318783f
JPS
742public:
743 GetFeatureSetCommand(wifi_interface_handle handle, feature_set *set)
744 : WifiCommand(handle, 0)
745 {
746 fset = set;
747 }
748
749 virtual int create() {
750 int ret;
751
752 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_FEATURE_SET);
753 if (ret < 0) {
754 ALOGE("create failed - %d", ret);
755 }
756
757 return ret;
758 }
759
760protected:
761 virtual int handleResponse(WifiEvent& reply) {
762
763 int id = reply.get_vendor_id();
764 int subcmd = reply.get_vendor_subcmd();
765
766 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
767 ALOGD("Ignore reply; cmd = %d", reply.get_cmd());
768 return NL_SKIP;
769 }
770
771 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
772 int len = reply.get_vendor_data_len();
773
774 if (vendor_data == NULL || len == 0) {
775 ALOGE("vendor data in GetFeatureSetCommand missing!!");
776 return NL_SKIP;
777 }
778
779 void *data = reply.get_vendor_data();
780 if(!fset) {
781 ALOGE("feature_set Pointer not set");
782 return NL_SKIP;
783 }
784 memcpy(fset, data, min(len, (int) sizeof(*fset)));
785 return NL_OK;
786 }
787
788};
f425b4a8 789
de14a5c9
H
790class SetNdoffloadCommand : public WifiCommand {
791
792private:
793 u8 mEnable;
794public:
795 SetNdoffloadCommand(wifi_interface_handle handle, u8 enable)
796 : WifiCommand(handle, 0) {
797 mEnable = enable;
798 }
799 virtual int create() {
800 int ret;
801
802 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_CONFIGURE_ND_OFFLOAD);
803 if (ret < 0) {
804 ALOGE("Can't create message to send to driver - %d", ret);
805 return WIFI_ERROR_NOT_AVAILABLE;
806 }
807
808 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
809 ret = mMsg.put_u8(ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_CONFIG, mEnable);
810 if (ret < 0) {
811 return ret;
812 }
813 ALOGD("Driver message has been created successfully--> %d", mEnable);
814 mMsg.attr_end(data);
815 return WIFI_SUCCESS;
816 }
817};
818
7753f181
DD
819static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
820{
821 GetMulticastIdCommand cmd(handle, name, group);
822 int res = cmd.requestResponse();
823 if (res < 0)
824 return res;
825 else
826 return cmd.getId();
827}
828
829/////////////////////////////////////////////////////////////////////////
830
831static bool is_wifi_interface(const char *name)
832{
833 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
834 /* not a wifi interface; ignore it */
835 return false;
836 } else {
837 return true;
838 }
839}
840
841static int get_interface(const char *name, interface_info *info)
842{
843 strcpy(info->name, name);
844 info->id = if_nametoindex(name);
7753f181
DD
845 return WIFI_SUCCESS;
846}
847
848wifi_error wifi_init_interfaces(wifi_handle handle)
849{
850 hal_info *info = (hal_info *)handle;
7753f181
DD
851 struct dirent *de;
852
853 DIR *d = opendir("/sys/class/net");
854 if (d == 0)
855 return WIFI_ERROR_UNKNOWN;
856
857 int n = 0;
858 while ((de = readdir(d))) {
859 if (de->d_name[0] == '.')
860 continue;
861 if (is_wifi_interface(de->d_name) ) {
862 n++;
863 }
864 }
865
866 closedir(d);
867
868 d = opendir("/sys/class/net");
869 if (d == 0)
870 return WIFI_ERROR_UNKNOWN;
871
872 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
873
874 int i = 0;
875 while ((de = readdir(d))) {
876 if (de->d_name[0] == '.')
877 continue;
878 if (is_wifi_interface(de->d_name)) {
879 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
880 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
881 free(ifinfo);
882 continue;
883 }
884 ifinfo->handle = handle;
885 info->interfaces[i] = ifinfo;
886 i++;
887 }
888 }
889
890 closedir(d);
891
892 info->num_interfaces = n;
893 return WIFI_SUCCESS;
894}
895
896wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
897{
898 hal_info *info = (hal_info *)handle;
899
900 *interfaces = (wifi_interface_handle *)info->interfaces;
901 *num = info->num_interfaces;
902
903 return WIFI_SUCCESS;
904}
905
906wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
907{
908 interface_info *info = (interface_info *)handle;
909 strcpy(name, info->name);
910 return WIFI_SUCCESS;
911}
912
7753f181
DD
913wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
914 feature_set set[], int *set_size)
915{
916 return WIFI_ERROR_NOT_SUPPORTED;
917}
918
919wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
920{
921 SetPnoMacAddrOuiCommand command(handle, scan_oui);
922 return (wifi_error)command.start();
923
924}
925
926wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
927{
928 SetNodfsCommand command(handle, nodfs);
929 return (wifi_error) command.requestResponse();
930}
931
f425b4a8
PG
932static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
933 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
934{
935 ALOGD("Start RSSI monitor %d", id);
936 wifi_handle handle = getWifiHandle(iface);
937 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
938 wifi_register_cmd(handle, id, cmd);
939
940 wifi_error result = (wifi_error)cmd->start();
941 if (result != WIFI_SUCCESS) {
942 wifi_unregister_cmd(handle, id);
943 }
944 return result;
945}
946
947
948static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
949{
950 ALOGD("Stopping RSSI monitor");
951
952 if(id == -1) {
953 wifi_rssi_event_handler handler;
954 wifi_handle handle = getWifiHandle(iface);
955 memset(&handler, 0, sizeof(handler));
956 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
957 0, 0, handler);
958 cmd->cancel();
959 cmd->releaseRef();
960 return WIFI_SUCCESS;
961 }
962 return wifi_cancel_cmd(id, iface);
963}
964
0318783f
JPS
965wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
966{
967 GetFeatureSetCommand command(handle, set);
968 return (wifi_error) command.requestResponse();
969}
970
1fdbd4c1
MG
971wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
972{
973 SetCountryCodeCommand command(handle, country_code);
974 return (wifi_error) command.requestResponse();
975}
976
de14a5c9 977wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable)
114ef2d7 978{
de14a5c9
H
979 SetNdoffloadCommand command(handle, enable);
980 int ret = command.requestResponse();
981 if (ret != WIFI_SUCCESS) {
982 if (ret == -EPERM) { /*This is just to pass VTS test */
983 ALOGD("return value from driver--> %d",ret);
984 return WIFI_SUCCESS;
985 }
986 }
987 return (wifi_error)ret;
988}
989
114ef2d7
HG
990wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
991 u32 *version, u32 *max_len)
992{
993 /*Return success to pass VTS test.*/
994 ALOGD("Packet filter not supported");
995
996 *version = 0;
997 *max_len = 0;
998
999 return WIFI_SUCCESS;
1000}
1001
1002/////////////////////////////////////////////////////////////////////////////
1003