diff options
author | Xin Li <delphij@google.com> | 2019-10-25 10:28:01 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2019-10-25 10:28:01 -0700 |
commit | 2dd444c395c7cceaae8fc9b681cbec1af67ce23b (patch) | |
tree | 09a382c89d58ac170687b86f24f3ebc3f80698b6 /qcwcn/wifi_hal/wifi_hal.cpp | |
parent | 180ce9e724d5a2097da24af214b2d4dc12a34f51 (diff) | |
parent | e66c67c549e9f29fafbe4d8e9098fc59cbd63ae8 (diff) | |
download | wlan-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.cpp | 586 |
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(®->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 *)®->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(®->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 *)®->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(®->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 *)®->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()); } |