summaryrefslogtreecommitdiff
path: root/qcwcn/wifi_hal/wifi_hal.cpp
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2019-10-25 10:28:01 -0700
committerXin Li <delphij@google.com>2019-10-25 10:28:01 -0700
commit2dd444c395c7cceaae8fc9b681cbec1af67ce23b (patch)
tree09a382c89d58ac170687b86f24f3ebc3f80698b6 /qcwcn/wifi_hal/wifi_hal.cpp
parent180ce9e724d5a2097da24af214b2d4dc12a34f51 (diff)
parente66c67c549e9f29fafbe4d8e9098fc59cbd63ae8 (diff)
downloadwlan-2dd444c395c7cceaae8fc9b681cbec1af67ce23b.tar.gz
Merge Coral/Flame into AOSP master
Bug: 141248619 Change-Id: I9976a12048a8be199082a2200540f4a899fd3e4f Merged-In: I911b1a53ec46f39cc7597c2a31f59669db4f0699
Diffstat (limited to 'qcwcn/wifi_hal/wifi_hal.cpp')
-rw-r--r--qcwcn/wifi_hal/wifi_hal.cpp586
1 files changed, 581 insertions, 5 deletions
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 198ab01..cb82885 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -41,6 +41,7 @@
#include <cld80211_lib.h>
#include <sys/types.h>
+#include "list.h"
#include <unistd.h>
#include "sync.h"
@@ -48,6 +49,7 @@
#define LOG_TAG "WifiHAL"
#include "wifi_hal.h"
+#include "wifi_hal_ctrl.h"
#include "common.h"
#include "cpp_bindings.h"
#include "ifaceeventhandler.h"
@@ -73,6 +75,19 @@
#define POLL_DRIVER_DURATION_US (100000)
#define POLL_DRIVER_MAX_TIME_MS (10000)
+static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
+
+static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
+
+static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach);
+
+static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
+
+static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock);
+
+static void internal_event_handler_app(wifi_handle handle, int events,
+ struct ctrl_sock *sock);
+
static void internal_event_handler(wifi_handle handle, int events,
struct nl_sock *sock);
static int internal_valid_message_handler(nl_msg *msg, void *arg);
@@ -135,6 +150,105 @@ static nl_sock * wifi_create_nl_socket(int port, int protocol)
return sock;
}
+void wifi_create_ctrl_socket(hal_info *info)
+{
+#ifdef ANDROID
+ struct group *grp_wifi;
+ gid_t gid_wifi;
+ struct passwd *pwd_system;
+ uid_t uid_system;
+#endif
+
+ int flags;
+
+ info->wifihal_ctrl_sock.s = socket(PF_UNIX, SOCK_DGRAM, 0);
+
+ if (info->wifihal_ctrl_sock.s < 0) {
+ ALOGE("socket(PF_UNIX): %s", strerror(errno));
+ return;
+ }
+ memset(&info->wifihal_ctrl_sock.local, 0, sizeof(info->wifihal_ctrl_sock.local));
+
+ info->wifihal_ctrl_sock.local.sun_family = AF_UNIX;
+
+ snprintf(info->wifihal_ctrl_sock.local.sun_path,
+ sizeof(info->wifihal_ctrl_sock.local.sun_path), "%s", WIFI_HAL_CTRL_IFACE);
+
+ if (bind(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
+ sizeof(info->wifihal_ctrl_sock.local)) < 0) {
+ ALOGD("ctrl_iface bind(PF_UNIX) failed: %s",
+ strerror(errno));
+ if (connect(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
+ sizeof(info->wifihal_ctrl_sock.local)) < 0) {
+ ALOGD("ctrl_iface exists, but does not"
+ " allow connections - assuming it was left"
+ "over from forced program termination");
+ if (unlink(info->wifihal_ctrl_sock.local.sun_path) < 0) {
+ ALOGE("Could not unlink existing ctrl_iface socket '%s': %s",
+ info->wifihal_ctrl_sock.local.sun_path, strerror(errno));
+ goto out;
+
+ }
+ if (bind(info->wifihal_ctrl_sock.s ,
+ (struct sockaddr *) &info->wifihal_ctrl_sock.local,
+ sizeof(info->wifihal_ctrl_sock.local)) < 0) {
+ ALOGE("wifihal-ctrl-iface-init: bind(PF_UNIX): %s",
+ strerror(errno));
+ goto out;
+ }
+ ALOGD("Successfully replaced leftover "
+ "ctrl_iface socket '%s'", info->wifihal_ctrl_sock.local.sun_path);
+ } else {
+ ALOGI("ctrl_iface exists and seems to "
+ "be in use - cannot override it");
+ ALOGI("Delete '%s' manually if it is "
+ "not used anymore", info->wifihal_ctrl_sock.local.sun_path);
+ goto out;
+ }
+ }
+
+ /*
+ * Make socket non-blocking so that we don't hang forever if
+ * target dies unexpectedly.
+ */
+
+#ifdef ANDROID
+ if (chmod(info->wifihal_ctrl_sock.local.sun_path, S_IRWXU | S_IRWXG) < 0)
+ {
+ ALOGE("Failed to give permissions: %s", strerror(errno));
+ }
+
+ /* Set group even if we do not have privileges to change owner */
+ grp_wifi = getgrnam("wifi");
+ gid_wifi = grp_wifi ? grp_wifi->gr_gid : 0;
+ pwd_system = getpwnam("system");
+ uid_system = pwd_system ? pwd_system->pw_uid : 0;
+ if (!gid_wifi || !uid_system) {
+ ALOGE("Failed to get grp ids");
+ unlink(info->wifihal_ctrl_sock.local.sun_path);
+ goto out;
+ }
+ chown(info->wifihal_ctrl_sock.local.sun_path, -1, gid_wifi);
+ chown(info->wifihal_ctrl_sock.local.sun_path, uid_system, gid_wifi);
+#endif
+
+ flags = fcntl(info->wifihal_ctrl_sock.s, F_GETFL);
+ if (flags >= 0) {
+ flags |= O_NONBLOCK;
+ if (fcntl(info->wifihal_ctrl_sock.s, F_SETFL, flags) < 0) {
+ ALOGI("fcntl(ctrl, O_NONBLOCK): %s",
+ strerror(errno));
+ /* Not fatal, continue on.*/
+ }
+ }
+ return;
+
+out:
+ close(info->wifihal_ctrl_sock.s);
+ info->wifihal_ctrl_sock.s = 0;
+ return;
+}
+
int ack_handler(struct nl_msg *msg, void *arg)
{
int *err = (int *)arg;
@@ -471,6 +585,7 @@ static void cld80211lib_cleanup(hal_info *info)
cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
cld80211_remove_mcast_group(info->cldctx, "diag_events");
cld80211_remove_mcast_group(info->cldctx, "fatal_events");
+ cld80211_remove_mcast_group(info->cldctx, "oem_msgs");
exit_cld80211_recv(info->cldctx);
cld80211_deinit(info->cldctx);
info->cldctx = NULL;
@@ -584,6 +699,13 @@ wifi_error wifi_initialize(wifi_handle *handle)
wifi_add_membership(*handle, "regulatory");
wifi_add_membership(*handle, "vendor");
+ info->wifihal_ctrl_sock.s = 0;
+
+ wifi_create_ctrl_socket(info);
+
+ //! Initailise the monitoring clients list
+ INITIALISE_LIST(&info->monitor_sockets);
+
info->cldctx = cld80211_init();
if (info->cldctx != NULL) {
info->user_sock = info->cldctx->sock;
@@ -618,6 +740,15 @@ wifi_error wifi_initialize(wifi_handle *handle)
ALOGE("Failed to add mcast group fatal_events :%d", status);
goto cld80211_cleanup;
}
+
+ if(info->wifihal_ctrl_sock.s > 0)
+ {
+ status = cld80211_add_mcast_group(info->cldctx, "oem_msgs");
+ if (status) {
+ ALOGE("Failed to add mcast group oem_msgs :%d", status);
+ goto cld80211_cleanup;
+ }
+ }
} else {
ret = wifi_init_user_sock(info);
if (ret != WIFI_SUCCESS) {
@@ -687,7 +818,7 @@ wifi_error wifi_initialize(wifi_handle *handle)
}
ALOGV("%s: hardware version type %d", __func__, info->pkt_log_ver);
} else {
- ALOGE("Failed to get supported logger feature set: %d", ret);
+ ALOGE("Failed to get firmware version: %d", ret);
}
ret = get_firmware_bus_max_size_supported(iface_handle);
@@ -826,6 +957,7 @@ static void internal_cleaned_up_handler(wifi_handle handle)
{
hal_info *info = getHalInfo(handle);
wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
+ wifihal_mon_sock_t *reg, *tmp;
if (info->cmd_sock != 0) {
nl_socket_free(info->cmd_sock);
@@ -834,6 +966,19 @@ static void internal_cleaned_up_handler(wifi_handle handle)
info->event_sock = NULL;
}
+ if (info->wifihal_ctrl_sock.s != 0) {
+ close(info->wifihal_ctrl_sock.s);
+ unlink(info->wifihal_ctrl_sock.local.sun_path);
+ info->wifihal_ctrl_sock.s = 0;
+ }
+
+ list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
+ del_from_list(&reg->list);
+ if(reg) {
+ free(reg);
+ }
+ }
+
if (info->interfaces) {
for (int i = 0; i < info->num_interfaces; i++)
free(info->interfaces[i]);
@@ -901,6 +1046,352 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
ALOGI("Sent msg on exit sock to unblock poll()");
}
+
+
+static int validate_cld80211_msg(nlmsghdr *nlh, int family, int cmd)
+{
+ //! Enhance this API
+ struct genlmsghdr *hdr;
+ hdr = (genlmsghdr *)nlmsg_data(nlh);
+
+ if(hdr->cmd == WLAN_NL_MSG_OEM)
+ {
+ ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
+ nlh->nlmsg_type, hdr->cmd);
+
+ //! Update pid with the wifihal pid
+ nlh->nlmsg_pid = getpid();
+ return 0;
+ }
+ else
+ {
+ ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
+ return -1;
+ }
+}
+
+
+static int validate_genl_msg(nlmsghdr *nlh, int family, int cmd)
+{
+ //! Enhance this API
+ struct genlmsghdr *hdr;
+ hdr = (genlmsghdr *)nlmsg_data(nlh);
+
+ if(hdr->cmd == NL80211_CMD_FRAME ||
+ hdr->cmd == NL80211_CMD_REGISTER_ACTION)
+ {
+ ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
+ nlh->nlmsg_type, hdr->cmd);
+ return 0;
+ }
+ else
+ {
+ ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
+ return -1;
+ }
+}
+
+static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
+{
+ hal_info *info = getHalInfo(handle);
+ struct nl_msg *msg = NULL;
+ int retval = -1;
+
+ //! attach monitor socket if it was not it the list
+ if(ctrl_msg->monsock_len)
+ {
+ retval = attach_monitor_sock(handle, ctrl_msg);
+ if(retval)
+ goto nl_out;
+ }
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ {
+ ALOGE("%s: Memory allocation failed \n", __FUNCTION__);
+ goto nl_out;
+ }
+
+ memcpy((char *)msg->nm_nlh, (char *)ctrl_msg->data, ctrl_msg->data_len);
+
+ if(ctrl_msg->family_name == GENERIC_NL_FAMILY)
+ {
+ //! Before sending the received gennlmsg to kernel,
+ //! better to have checks for allowed commands
+ retval = validate_genl_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
+ if (retval < 0)
+ goto nl_out;
+
+ retval = nl_send_auto_complete(info->event_sock, msg); /* send message */
+ if (retval < 0)
+ {
+ ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
+ goto nl_out;
+ }
+
+ retval = internal_pollin_handler(handle, info->event_sock);
+ }
+ else if (ctrl_msg->family_name == CLD80211_FAMILY)
+ {
+ if (info->cldctx != NULL)
+ {
+ //! Before sending the received cld80211 msg to kernel,
+ //! better to have checks for allowed commands
+ retval = validate_cld80211_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
+ if (retval < 0)
+ goto nl_out;
+
+ retval = cld80211_send_msg(info->cldctx, msg);
+ if (retval != 0)
+ {
+ ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
+ goto nl_out;
+ }
+ ALOGD("%s: sent cld80211 message for pid %d\n", __FUNCTION__, getpid());
+ }
+ else
+ {
+ ALOGE("%s: cld80211 ctx not present \n", __FUNCTION__);
+ }
+ }
+ else
+ {
+ ALOGE("%s: Unknown family name : %d \n", __FUNCTION__, ctrl_msg->family_name);
+ retval = -1;
+ }
+nl_out:
+ if (msg)
+ {
+ nlmsg_free(msg);
+ }
+ return retval;
+}
+
+static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach)
+{
+ hal_info *info = getHalInfo(handle);
+
+ wifihal_mon_sock_t *reg, *nreg;
+ char *match = NULL;
+ unsigned int match_len = 0;
+ unsigned int type;
+
+ //! For Register Action frames, compare the match length and match buffer.
+ //! For other registrations such as oem messages,
+ //! diag messages check for respective commands
+
+ if((ctrl_msg->family_name == GENERIC_NL_FAMILY) &&
+ (ctrl_msg->cmd_id == NL80211_CMD_REGISTER_ACTION))
+ {
+ struct genlmsghdr *genlh;
+ struct nlmsghdr *nlh = (struct nlmsghdr *)ctrl_msg->data;
+ genlh = (struct genlmsghdr *)nlmsg_data(nlh);
+ struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
+
+ nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
+ genlmsg_attrlen(genlh, 0), NULL);
+
+ if (!nlattrs[NL80211_ATTR_FRAME_TYPE])
+ {
+ ALOGD("No Valid frame type");
+ }
+ else
+ {
+ type = nla_get_u16(nlattrs[NL80211_ATTR_FRAME_TYPE]);
+ }
+ if (!nlattrs[NL80211_ATTR_FRAME_MATCH])
+ {
+ ALOGE("No Frame Match");
+ return -1;
+ }
+ else
+ {
+ match_len = nla_len(nlattrs[NL80211_ATTR_FRAME_MATCH]);
+ match = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME_MATCH]);
+
+ list_for_each_entry(reg, &info->monitor_sockets, list) {
+
+ if(reg == NULL)
+ break;
+
+ int mlen = min(match_len, reg->match_len);
+
+ if (reg->match_len == 0)
+ continue;
+
+ if (memcmp(reg->match, match, mlen) == 0) {
+
+ if((ctrl_msg->monsock_len == reg->monsock_len) &&
+ (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0))
+ {
+ if(attach)
+ {
+ ALOGE(" %s :Action frame already registered for this client ", __FUNCTION__);
+ return -2;
+ }
+ else
+ {
+ del_from_list(&reg->list);
+ free(reg);
+ return 0;
+ }
+ }
+ else
+ {
+ //! when action frame registered for other client,
+ //! you can't attach or dettach for new client
+ ALOGE(" %s :Action frame registered for other client ", __FUNCTION__);
+ return -2;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ list_for_each_entry(reg, &info->monitor_sockets, list) {
+
+ //! Checking for monitor sock in the list :
+
+ //! For attach request :
+ //! if sock is not present, then it is a new entry , so add to list.
+ //! if sock is present, and cmd_id does not match, add another entry to list.
+ //! if sock is present, and cmd_id matches, return 0.
+
+ //! For dettach req :
+ //! if sock is not present, return error -2.
+ //! if sock is present, and cmd_id does not match, return error -2.
+ //! if sock is present, and cmd_id matches, delete entry and return 0.
+ if(reg == NULL)
+ break;
+
+ if (ctrl_msg->monsock_len != reg->monsock_len)
+ continue;
+
+ if (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0) {
+
+ if((reg->family_name == ctrl_msg->family_name) && (reg->cmd_id == ctrl_msg->cmd_id))
+ {
+ if(!attach)
+ {
+ del_from_list(&reg->list);
+ free(reg);
+ }
+ return 0;
+ }
+ }
+ }
+ }
+
+ if(attach)
+ {
+ nreg = (wifihal_mon_sock_t *)malloc(sizeof(*reg) + match_len);
+ if (!nreg)
+ return -1;
+
+ memset((char *)nreg, 0, sizeof(*reg) + match_len);
+ nreg->family_name = ctrl_msg->family_name;
+ nreg->cmd_id = ctrl_msg->cmd_id;
+ nreg->monsock_len = ctrl_msg->monsock_len;
+ memcpy((char *)&nreg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len);
+
+ if(match_len && match)
+ {
+ nreg->match_len = match_len;
+ memcpy(nreg->match, match, match_len);
+ }
+ add_to_list(&nreg->list, &info->monitor_sockets);
+ }
+ else
+ {
+ //! Not attached, so cant be dettached
+ ALOGE("%s: Dettaching the unregistered socket \n", __FUNCTION__);
+ return -2;
+ }
+
+ return 0;
+}
+
+static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
+{
+ return register_monitor_sock(handle, ctrl_msg, 1);
+}
+
+static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
+{
+ return register_monitor_sock(handle, ctrl_msg, 0);
+}
+
+static int internal_pollin_handler_app(wifi_handle handle, struct ctrl_sock *sock)
+{
+ int retval = -1;
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+ wifihal_ctrl_req_t *ctrl_msg;
+ wifihal_ctrl_sync_rsp_t ctrl_reply;
+
+ ctrl_msg = (wifihal_ctrl_req_t *)malloc(DEFAULT_PAGE_SIZE);
+ if(ctrl_msg == NULL)
+ {
+ ALOGE ("Memory allocation failure");
+ return -1;
+ }
+
+ memset((char *)ctrl_msg, 0, DEFAULT_PAGE_SIZE);
+
+ res = recvfrom(sock->s, (char *)ctrl_msg, DEFAULT_PAGE_SIZE, 0,
+ (struct sockaddr *)&from, &fromlen);
+ if (res < 0) {
+ ALOGE("recvfrom(ctrl_iface): %s",
+ strerror(errno));
+ if(ctrl_msg)
+ free(ctrl_msg);
+
+ return 0;
+ }
+ switch(ctrl_msg->ctrl_cmd)
+ {
+ case WIFIHAL_CTRL_MONITOR_ATTACH:
+ retval = attach_monitor_sock(handle, ctrl_msg);
+ break;
+ case WIFIHAL_CTRL_MONITOR_DETTACH:
+ retval = dettach_monitor_sock(handle, ctrl_msg);
+ break;
+ case WIFIHAL_CTRL_SEND_NL_DATA:
+ retval = send_nl_data(handle, ctrl_msg);
+ break;
+ default:
+ break;
+ }
+
+ ctrl_reply.ctrl_cmd = ctrl_msg->ctrl_cmd;
+ ctrl_reply.family_name = ctrl_msg->family_name;
+ ctrl_reply.cmd_id = ctrl_msg->cmd_id;
+ ctrl_reply.status = retval;
+
+ if(ctrl_msg)
+ free(ctrl_msg);
+
+ if (sendto(sock->s, (char *)&ctrl_reply, sizeof(ctrl_reply), 0, (struct sockaddr *)&from,
+ fromlen) < 0) {
+ int _errno = errno;
+ ALOGE("socket send failed : %d",_errno);
+
+ if (_errno == ENOBUFS || _errno == EAGAIN) {
+ /*
+ * The socket send buffer could be full. This
+ * may happen if client programs are not
+ * receiving their pending messages. Close and
+ * reopen the socket as a workaround to avoid
+ * getting stuck being unable to send any new
+ * responses.
+ */
+ }
+ }
+ return res;
+}
+
static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
{
struct nl_cb *cb = nl_socket_get_cb(sock);
@@ -912,6 +1403,22 @@ static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
return res;
}
+static void internal_event_handler_app(wifi_handle handle, int events,
+ struct ctrl_sock *sock)
+{
+ if (events & POLLERR) {
+ ALOGE("Error reading from wifi_hal ctrl socket");
+ internal_pollin_handler_app(handle, sock);
+ } else if (events & POLLHUP) {
+ ALOGE("Remote side hung up");
+ } else if (events & POLLIN) {
+ //ALOGI("Found some events!!!");
+ internal_pollin_handler_app(handle, sock);
+ } else {
+ ALOGE("Unknown event - %0x", events);
+ }
+}
+
static void internal_event_handler(wifi_handle handle, int events,
struct nl_sock *sock)
{
@@ -938,8 +1445,8 @@ void wifi_event_loop(wifi_handle handle)
info->in_event_loop = true;
}
- pollfd pfd[3];
- memset(&pfd, 0, 3*sizeof(pfd[0]));
+ pollfd pfd[4];
+ memset(&pfd, 0, 4*sizeof(pfd[0]));
pfd[0].fd = nl_socket_get_fd(info->event_sock);
pfd[0].events = POLLIN;
@@ -950,14 +1457,19 @@ void wifi_event_loop(wifi_handle handle)
pfd[2].fd = info->exit_sockets[1];
pfd[2].events = POLLIN;
+ if(info->wifihal_ctrl_sock.s > 0) {
+ pfd[3].fd = info->wifihal_ctrl_sock.s ;
+ pfd[3].events = POLLIN;
+ }
/* TODO: Add support for timeouts */
do {
pfd[0].revents = 0;
pfd[1].revents = 0;
pfd[2].revents = 0;
+ pfd[3].revents = 0;
//ALOGI("Polling sockets");
- int result = poll(pfd, 3, -1);
+ int result = poll(pfd, 4, -1);
if (result < 0) {
ALOGE("Error polling socket");
} else {
@@ -967,6 +1479,9 @@ void wifi_event_loop(wifi_handle handle)
if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
internal_event_handler(handle, pfd[1].revents, info->user_sock);
}
+ if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
+ internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
+ }
}
rb_timerhandler(info);
} while (!info->clean_up);
@@ -1008,7 +1523,68 @@ static int internal_valid_message_handler(nl_msg *msg, void *arg)
ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
event.get_cmdString(), vendor_id, subcmd);
}
- } else {
+ }
+ else if((info->wifihal_ctrl_sock.s > 0) && (cmd == NL80211_CMD_FRAME))
+ {
+ struct genlmsghdr *genlh;
+ struct nlmsghdr *nlh = nlmsg_hdr(msg);
+ genlh = (struct genlmsghdr *)nlmsg_data(nlh);
+ struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
+
+ wifihal_ctrl_event_t *ctrl_evt;
+ char *buff;
+ wifihal_mon_sock_t *reg;
+
+ nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
+ genlmsg_attrlen(genlh, 0), NULL);
+
+ if (!nlattrs[NL80211_ATTR_FRAME])
+ {
+ ALOGD("No Frame body");
+ return WIFI_SUCCESS;
+ }
+
+ ctrl_evt = (wifihal_ctrl_event_t *)malloc(DEFAULT_PAGE_SIZE);
+ if(ctrl_evt == NULL)
+ {
+ ALOGE("Memory allocation failure");
+ return -1;
+ }
+ memset((char *)ctrl_evt, 0, DEFAULT_PAGE_SIZE);
+ ctrl_evt->family_name = GENERIC_NL_FAMILY;
+ ctrl_evt->cmd_id = cmd;
+ ctrl_evt->data_len = msg->nm_nlh->nlmsg_len;
+ memcpy(ctrl_evt->data, (char *)msg->nm_nlh, ctrl_evt->data_len);
+
+
+ buff = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME]) + 24; //! Size of Wlan80211FrameHeader
+
+ list_for_each_entry(reg, &info->monitor_sockets, list) {
+
+ if(reg == NULL)
+ break;
+
+ if (memcmp(reg->match, buff, reg->match_len))
+ continue;
+
+ /* found match! */
+ /* Indicate the received Action frame to respective client */
+ if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
+ sizeof(*ctrl_evt) + ctrl_evt->data_len,
+ 0, (struct sockaddr *)&reg->monsock, reg->monsock_len) < 0)
+ {
+ int _errno = errno;
+ ALOGE("socket send failed : %d",_errno);
+
+ if (_errno == ENOBUFS || _errno == EAGAIN) {
+ }
+ }
+
+ }
+ free(ctrl_evt);
+ }
+
+ else {
ALOGV("event received %s", event.get_cmdString());
}