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