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