diff options
| author | Selvaraj, Sridhar <sselvara@codeaurora.org> | 2017-02-21 12:47:11 +0530 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2017-03-07 02:18:54 -0800 |
| commit | fcb39cb0b884428589faa7db56f81843e391b479 (patch) | |
| tree | 6edde0e21b14791d59d4002a082f717570e620d5 | |
| parent | d1b1a1ebbb0406295e2fc4d12140def0b632af0e (diff) | |
qcacld-3.0: Add support to use generic netlink sockets for userspace apps
Currently user space communication functions[cnss diag, PTT socket app]
in host driver uses netlink user sockets which is a security concern from
Linux Android SE policies.
Add support for to use netlink family cld80211 which uses generic
netlink sockets.
Change-Id: I4ea49ac6d7c9381212c93567fdc40f90e04dfba4
CRs-Fixed: 1112784
| -rw-r--r-- | Kbuild | 4 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 24 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_oemdata.c | 456 | ||||
| -rw-r--r-- | core/utils/fwlog/dbglog_host.c | 154 | ||||
| -rw-r--r-- | core/utils/logging/src/wlan_logging_sock_svc.c | 110 | ||||
| -rw-r--r-- | core/utils/nlink/inc/wlan_nlink_srv.h | 10 | ||||
| -rw-r--r-- | core/utils/nlink/src/wlan_nlink_srv.c | 197 | ||||
| -rw-r--r-- | core/utils/ptt/inc/wlan_ptt_sock_svc.h | 15 | ||||
| -rw-r--r-- | core/utils/ptt/src/wlan_ptt_sock_svc.c | 126 |
9 files changed, 901 insertions, 195 deletions
@@ -1243,6 +1243,10 @@ ifeq ($(CONFIG_QCACLD_WLAN_LFR3),y) CDEFINES += -DWLAN_FEATURE_ROAM_OFFLOAD endif +ifeq ($(CONFIG_CNSS_GENL), y) +CDEFINES += -DCNSS_GENL +endif + ifeq ($(CONFIG_QCACLD_WLAN_LFR2),y) CDEFINES += -DWLAN_FEATURE_HOST_ROAM endif diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 414f857f05ef..8a93f786a72a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -109,6 +109,10 @@ #include "cds_utils.h" #include "sir_api.h" +#ifdef CNSS_GENL +#include <net/cnss_nl.h> +#endif + #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) #else @@ -9072,6 +9076,24 @@ void wlan_hdd_enable_roaming(hdd_adapter_t *adapter) } } +/** + * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group + * @skb: sk buffer pointer + * + * Sends the bcast message to SVC multicast group with generic nl socket + * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. + * + * Return: None + */ +static void nl_srv_bcast_svc(struct sk_buff *skb) +{ +#ifdef CNSS_GENL + nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC); +#else + nl_srv_bcast(skb); +#endif +} + void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len) { struct sk_buff *skb; @@ -9156,7 +9178,7 @@ void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len) nlh->nlmsg_len += tlv_len; skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len)); - nl_srv_bcast(skb); + nl_srv_bcast_svc(skb); return; } diff --git a/core/hdd/src/wlan_hdd_oemdata.c b/core/hdd/src/wlan_hdd_oemdata.c index 6196b904ff57..01799882c9a8 100644 --- a/core/hdd/src/wlan_hdd_oemdata.c +++ b/core/hdd/src/wlan_hdd_oemdata.c @@ -46,6 +46,10 @@ #include "wma.h" #include "sme_api.h" +#ifdef CNSS_GENL +#include <net/cnss_nl.h> +#endif + static struct hdd_context_s *p_hdd_ctx; /** @@ -163,6 +167,27 @@ int iw_get_oem_data_cap(struct net_device *dev, } /** + * nl_srv_ucast_oem() - Wrapper function to send ucast msgs to OEM + * @skb: sk buffer pointer + * @dst_pid: Destination PID + * @flag: flags + * + * Sends the ucast message to OEM with generic nl socket if CNSS_GENL + * is enabled. Else, use the legacy netlink socket to send. + * + * Return: None + */ +static void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag) +{ +#ifdef CNSS_GENL + nl_srv_ucast(skb, dst_pid, flag, WLAN_NL_MSG_OEM, + CLD80211_MCGRP_OEM_MSGS); +#else + nl_srv_ucast(skb, dst_pid, flag); +#endif +} + +/** * send_oem_reg_rsp_nlink_msg() - send oem registration response * * This function sends oem message to registered application process @@ -240,7 +265,7 @@ static void send_oem_reg_rsp_nlink_msg(void) hdd_notice("sending App Reg Response length (%d) to process pid (%d)", aniHdr->length, p_hdd_ctx->oem_pid); - (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + (void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); return; } @@ -285,7 +310,7 @@ static void send_oem_err_rsp_nlink_msg(int32_t app_pid, uint8_t error_code) hdd_notice("sending oem error response to process pid (%d)", app_pid); - (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT); + (void)nl_srv_ucast_oem(skb, app_pid, MSG_DONTWAIT); return; } @@ -344,7 +369,7 @@ void hdd_send_oem_data_rsp_msg(struct oem_data_rsp *oem_data_rsp) hdd_notice("sending Oem Data Response of len (%d) to process pid (%d)", oem_data_rsp->rsp_len, p_hdd_ctx->oem_pid); - (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + (void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); return; } @@ -543,7 +568,7 @@ static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList) hdd_notice("sending channel info resp for num channels (%d) to pid (%d)", numOfChannels, p_hdd_ctx->oem_pid); - (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + (void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); return 0; } @@ -604,7 +629,7 @@ static int oem_process_set_cap_req_msg(int oem_cap_len, hdd_info("sending oem response to process pid %d", app_pid); - (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT); + (void)nl_srv_ucast_oem(skb, app_pid, MSG_DONTWAIT); return error_code; } @@ -670,7 +695,7 @@ static int oem_process_get_cap_req_msg(void) hdd_info("send rsp to oem-pid:%d for get_capability", p_hdd_ctx->oem_pid); - (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + (void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); return 0; } @@ -781,11 +806,288 @@ void hdd_send_peer_status_ind_to_oem_app(struct qdf_mac_addr *peerMac, pPeerInfo->peer_chan_info.reg_info_1, pPeerInfo->peer_chan_info.reg_info_2); - (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + (void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + + return; +} + +/** + * oem_app_reg_req_handler() - function to handle APP registration request + * from userspace + * @hdd_ctx: handle to HDD context + * @msg_hdr: pointer to ANI message header + * @pid: Process ID + * + * Return: 0 if success, error code otherwise + */ +static int oem_app_reg_req_handler(struct hdd_context_s *hdd_ctx, + tAniMsgHdr *msg_hdr, int pid) +{ + char *sign_str = NULL; + + /* Registration request is only allowed for Qualcomm Application */ + hdd_info("Received App Reg Req from App process pid(%d), len(%d)", + pid, msg_hdr->length); + + sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr)); + if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) && + (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR, + OEM_APP_SIGNATURE_LEN))) { + hdd_info("Valid App Reg Req from oem app process pid(%d)", pid); + + hdd_ctx->oem_app_registered = true; + hdd_ctx->oem_pid = pid; + send_oem_reg_rsp_nlink_msg(); + } else { + hdd_err("Invalid signature in App Reg Req from pid(%d)", pid); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_SIGNATURE); + return -EPERM; + } + + return 0; +} + +/** + * oem_data_req_handler() - function to handle data_req from userspace + * @hdd_ctx: handle to HDD context + * @msg_hdr: pointer to ANI message header + * @pid: Process ID + * + * Return: 0 if success, error code otherwise + */ +static int oem_data_req_handler(struct hdd_context_s *hdd_ctx, + tAniMsgHdr *msg_hdr, int pid) +{ + hdd_info("Received Oem Data Request length(%d) from pid: %d", + msg_hdr->length, pid); + + if ((!hdd_ctx->oem_app_registered) || + (pid != hdd_ctx->oem_pid)) { + /* either oem app is not registered yet or pid is different */ + hdd_err("OEM DataReq: app not registered(%d) or incorrect pid(%d)", + hdd_ctx->oem_app_registered, pid); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED); + return -EPERM; + } + + if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) { + hdd_err("Invalid length (%d) in Oem Data Request", + msg_hdr->length); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH); + return -EPERM; + } + + oem_process_data_req_msg(msg_hdr->length, + (char *) ((char *)msg_hdr + + sizeof(tAniMsgHdr))); + + return 0; +} + +/** + * oem_chan_info_req_handler() - function to handle chan_info_req from userspace + * @hdd_ctx: handle to HDD context + * @msg_hdr: pointer to ANI message header + * @pid: Process ID + * + * Return: 0 if success, error code otherwise + */ +static int oem_chan_info_req_handler(struct hdd_context_s *hdd_ctx, + tAniMsgHdr *msg_hdr, int pid) +{ + hdd_info("Received channel info request, num channel(%d) from pid: %d", + msg_hdr->length, pid); + + if ((!hdd_ctx->oem_app_registered) || + (pid != hdd_ctx->oem_pid)) { + /* either oem app is not registered yet or pid is different */ + hdd_err("Chan InfoReq: app not registered(%d) or incorrect pid(%d)", + hdd_ctx->oem_app_registered, pid); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED); + return -EPERM; + } + + /* message length contains list of channel ids */ + if ((!msg_hdr->length) || + (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) { + hdd_err("Invalid length (%d) in channel info request", + msg_hdr->length); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH); + return -EPERM; + } + oem_process_channel_info_req_msg(msg_hdr->length, + (char *)((char *)msg_hdr + sizeof(tAniMsgHdr))); + + return 0; +} + +/** + * oem_set_cap_req_handler() - function to handle set_cap_req from userspace + * @hdd_ctx: handle to HDD context + * @msg_hdr: pointer to ANI message header + * @pid: Process ID + * + * Return: 0 if success, error code otherwise + */ +static int oem_set_cap_req_handler(struct hdd_context_s *hdd_ctx, + tAniMsgHdr *msg_hdr, int pid) +{ + hdd_info("Received set oem cap req of length:%d from pid: %d", + msg_hdr->length, pid); + + if ((!hdd_ctx->oem_app_registered) || + (pid != hdd_ctx->oem_pid)) { + /* oem app is not registered yet or pid is different */ + hdd_err("set_oem_capability : app not registered(%d) or incorrect pid(%d)", + hdd_ctx->oem_app_registered, pid); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED); + return -EPERM; + } + + if ((!msg_hdr->length) || + (sizeof(struct sme_oem_capability) < msg_hdr->length)) { + hdd_err("Invalid length (%d) in set_oem_capability", + msg_hdr->length); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH); + return -EPERM; + } + + oem_process_set_cap_req_msg(msg_hdr->length, (char *) + ((char *)msg_hdr + sizeof(tAniMsgHdr)), + pid); + return 0; +} + +/** + * oem_get_cap_req_handler() - function to handle get_cap_req from userspace + * @hdd_ctx: handle to HDD context + * @msg_hdr: pointer to ANI message header + * @pid: Process ID + * + * Return: 0 if success, error code otherwise + */ +static int oem_get_cap_req_handler(struct hdd_context_s *hdd_ctx, + tAniMsgHdr *msg_hdr, int pid) +{ + hdd_info("Rcvd get oem capability req - length:%d from pid: %d", + msg_hdr->length, pid); + + if ((!hdd_ctx->oem_app_registered) || + (pid != hdd_ctx->oem_pid)) { + /* oem app is not registered yet or pid is different */ + hdd_err("get_oem_capability : app not registered(%d) or incorrect pid(%d)", + hdd_ctx->oem_app_registered, pid); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED); + return -EPERM; + } + + oem_process_get_cap_req_msg(); + return 0; +} + +/** + * oem_request_dispatcher() - OEM command dispatcher API + * @msg_hdr: ANI Message Header + * @pid: process id + * + * This API is used to dispatch the command from OEM depending + * on the type of the message received. + * + * Return: None + */ +static void oem_request_dispatcher(tAniMsgHdr *msg_hdr, int pid) +{ + switch (msg_hdr->type) { + case ANI_MSG_APP_REG_REQ: + oem_app_reg_req_handler(p_hdd_ctx, msg_hdr, pid); + break; + + case ANI_MSG_OEM_DATA_REQ: + oem_data_req_handler(p_hdd_ctx, msg_hdr, pid); + break; + + case ANI_MSG_CHANNEL_INFO_REQ: + oem_chan_info_req_handler(p_hdd_ctx, msg_hdr, pid); + break; + + case ANI_MSG_SET_OEM_CAP_REQ: + oem_set_cap_req_handler(p_hdd_ctx, msg_hdr, pid); + break; + + case ANI_MSG_GET_OEM_CAP_REQ: + oem_get_cap_req_handler(p_hdd_ctx, msg_hdr, pid); + break; + + default: + hdd_err("Received Invalid message type (%d), length (%d)", + msg_hdr->type, msg_hdr->length); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_TYPE); + } +} + +#ifdef CNSS_GENL +/** + * oem_cmd_handler() - API to handle OEM commands + * @data: Pointer to data + * @data_len: length of the received data + * @ctx: Pointer to the context + * @pid: Process id + * + * This API handles the command from OEM application from user space and + * send back event to user space if necessary. + * + * Return: None + */ +static void oem_cmd_handler(const void *data, int data_len, void *ctx, int pid) +{ + tAniMsgHdr *msg_hdr; + int ret; + struct nlattr *tb[CLD80211_ATTR_MAX + 1]; + + ret = wlan_hdd_validate_context(p_hdd_ctx); + if (ret) { + hdd_err("hdd ctx validate fails"); + return; + } + + if (nla_parse(tb, CLD80211_ATTR_MAX, data, data_len, NULL)) { + hdd_err("Invalid ATTR"); + return; + } + + if (!tb[CLD80211_ATTR_DATA]) { + hdd_err("attr ATTR_DATA failed"); + return; + } + + msg_hdr = (tAniMsgHdr *)nla_data(tb[CLD80211_ATTR_DATA]); + if (!msg_hdr) { + hdd_err("msg_hdr null"); + send_oem_err_rsp_nlink_msg(pid, OEM_ERR_NULL_MESSAGE_HEADER); + return; + } + oem_request_dispatcher(msg_hdr, pid); return; } +/** + * oem_activate_service() - API to register the oem command handler + * @hdd_ctx: Pointer to HDD Context + * + * This API is used to register the oem app command handler. Argument + * @pAdapter is given for prototype compatibility with legacy code. + * + * Return: 0 + */ +int oem_activate_service(struct hdd_context_s *hdd_ctx) +{ + p_hdd_ctx = hdd_ctx; + register_cld_cmd_cb(WLAN_NL_MSG_OEM, oem_cmd_handler, NULL); + return 0; +} +#else + /* * Callback function invoked by Netlink service for all netlink * messages (from user space) addressed to WLAN_NL_MSG_OEM @@ -806,7 +1108,6 @@ static int oem_msg_callback(struct sk_buff *skb) struct nlmsghdr *nlh; tAniMsgHdr *msg_hdr; int ret; - char *sign_str = NULL; nlh = (struct nlmsghdr *)skb->data; if (!nlh) { @@ -836,142 +1137,7 @@ static int oem_msg_callback(struct sk_buff *skb) return -EPERM; } - switch (msg_hdr->type) { - case ANI_MSG_APP_REG_REQ: - /* Registration request is only allowed for Qualcomm Application */ - hdd_notice("Received App Req Req from App process pid(%d), len(%d)", - nlh->nlmsg_pid, msg_hdr->length); - - sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr)); - if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) && - (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR, - OEM_APP_SIGNATURE_LEN))) { - hdd_notice("Valid App Req Req from oem app process pid(%d)", - nlh->nlmsg_pid); - - p_hdd_ctx->oem_app_registered = true; - p_hdd_ctx->oem_pid = nlh->nlmsg_pid; - send_oem_reg_rsp_nlink_msg(); - } else { - hdd_err("Invalid signature in App Reg Request from pid(%d)", - nlh->nlmsg_pid); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_INVALID_SIGNATURE); - return -EPERM; - } - break; - - case ANI_MSG_OEM_DATA_REQ: - hdd_notice("Received Oem Data Request length(%d) from pid: %d", - msg_hdr->length, nlh->nlmsg_pid); - - if ((!p_hdd_ctx->oem_app_registered) || - (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) { - /* either oem app is not registered yet or pid is different */ - hdd_err("OEM DataReq: app not registered(%d) or incorrect pid(%d)", - p_hdd_ctx->oem_app_registered, - nlh->nlmsg_pid); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_APP_NOT_REGISTERED); - return -EPERM; - } - - if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) { - hdd_err("Invalid length (%d) in Oem Data Request", - msg_hdr->length); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_INVALID_MESSAGE_LENGTH); - return -EPERM; - } - oem_process_data_req_msg(msg_hdr->length, - (char *)((char *)msg_hdr + - sizeof(tAniMsgHdr))); - break; - - case ANI_MSG_CHANNEL_INFO_REQ: - hdd_notice("Received channel info request, num channel(%d) from pid: %d", - msg_hdr->length, nlh->nlmsg_pid); - - if ((!p_hdd_ctx->oem_app_registered) || - (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) { - /* either oem app is not registered yet or pid is different */ - hdd_err("Chan InfoReq: app not registered(%d) or incorrect pid(%d)", - p_hdd_ctx->oem_app_registered, - nlh->nlmsg_pid); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_APP_NOT_REGISTERED); - return -EPERM; - } - - /* message length contains list of channel ids */ - if ((!msg_hdr->length) || - (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) { - hdd_err("Invalid length (%d) in channel info request", - msg_hdr->length); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_INVALID_MESSAGE_LENGTH); - return -EPERM; - } - oem_process_channel_info_req_msg(msg_hdr->length, - (char *)((char *)msg_hdr + - sizeof(tAniMsgHdr))); - break; - - case ANI_MSG_SET_OEM_CAP_REQ: - hdd_info("Received set oem capability req of length:%d from pid: %d", - msg_hdr->length, nlh->nlmsg_pid); - - if ((!p_hdd_ctx->oem_app_registered) || - (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) { - /* oem app is not registered yet or pid is different */ - hdd_err("set_oem_capability : app not registered(%d) or incorrect pid(%d)", - p_hdd_ctx->oem_app_registered, - nlh->nlmsg_pid); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_APP_NOT_REGISTERED); - return -EPERM; - } - - if ((!msg_hdr->length) || - (sizeof(struct sme_oem_capability) < msg_hdr->length)) { - hdd_err("Invalid length (%d) in set_oem_capability", - msg_hdr->length); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_INVALID_MESSAGE_LENGTH); - return -EPERM; - } - - oem_process_set_cap_req_msg(msg_hdr->length, - (char *)((char *)msg_hdr + - sizeof(tAniMsgHdr)), - nlh->nlmsg_pid); - break; - - case ANI_MSG_GET_OEM_CAP_REQ: - hdd_info("Rcvd get oem capability req of length:%d from pid: %d", - msg_hdr->length, nlh->nlmsg_pid); - - if ((!p_hdd_ctx->oem_app_registered) || - (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) { - /* oem app is not registered yet or pid is different */ - hdd_err("get_oem_capability : app not registered(%d) or incorrect pid(%d)", - p_hdd_ctx->oem_app_registered, - nlh->nlmsg_pid); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_APP_NOT_REGISTERED); - return -EPERM; - } - - oem_process_get_cap_req_msg(); - break; - - default: - hdd_err("Received Invalid message type (%d), length (%d)", - msg_hdr->type, msg_hdr->length); - send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, - OEM_ERR_INVALID_MESSAGE_TYPE); - return -EPERM; - } + oem_request_dispatcher(msg_hdr, nlh->nlmsg_pid); return 0; } @@ -1003,5 +1169,5 @@ int oem_activate_service(struct hdd_context_s *hdd_ctx) /* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */ return nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback); } - +#endif #endif diff --git a/core/utils/fwlog/dbglog_host.c b/core/utils/fwlog/dbglog_host.c index 11be14cb7faa..1654407fef26 100644 --- a/core/utils/fwlog/dbglog_host.c +++ b/core/utils/fwlog/dbglog_host.c @@ -46,6 +46,10 @@ #endif /* WLAN_OPEN_SOURCE */ #include "wmi_unified_priv.h" +#ifdef CNSS_GENL +#include <net/cnss_nl.h> +#endif + #ifdef MULTI_IF_NAME #define CLD_DEBUGFS_DIR "cld" MULTI_IF_NAME #else @@ -1598,6 +1602,24 @@ dbglog_debugfs_raw_data(wmi_unified_t wmi_handle, const uint8_t *buf, #endif /* WLAN_OPEN_SOURCE */ /** + * nl_srv_bcast_fw_logs() - Wrapper func to send bcast msgs to FW logs mcast grp + * @skb: sk buffer pointer + * + * Sends the bcast message to FW logs multicast group with generic nl socket + * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. + * + * Return: zero on success, error code otherwise + */ +static int nl_srv_bcast_fw_logs(struct sk_buff *skb) +{ +#ifdef CNSS_GENL + return nl_srv_bcast(skb, CLD80211_MCGRP_FW_LOGS, WLAN_NL_MSG_CNSS_DIAG); +#else + return nl_srv_bcast(skb); +#endif +} + +/** * send_fw_diag_nl_data - pack the data from fw diag event handler * @buffer: buffer of diag event * @len: length of the diag event @@ -1645,10 +1667,10 @@ static int send_fw_diag_nl_data(const uint8_t *buffer, A_UINT32 len, /* data buffer offset from nlmsg_hdr + sizeof(int) radio */ memcpy(nlmsg_data(nlh) + sizeof(radio), buffer, len); - res = nl_srv_bcast(skb_out); + res = nl_srv_bcast_fw_logs(skb_out); if ((res < 0) && (res != -ESRCH)) { AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, - ("%s: nl_srv_bcast failed 0x%x\n", + ("%s: nl_srv_bcast_fw_logs failed 0x%x\n", __func__, res)); return res; } @@ -1745,10 +1767,10 @@ send_diag_netlink_data(const uint8_t *buffer, A_UINT32 len, A_UINT32 cmd) slot->dropped = get_version; memcpy(slot->payload, buffer, len); - res = nl_srv_bcast(skb_out); + res = nl_srv_bcast_fw_logs(skb_out); if ((res < 0) && (res != -ESRCH)) { AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, - ("%s: nl_srv_bcast failed 0x%x\n", + ("%s: nl_srv_bcast_fw_logs failed 0x%x\n", __func__, res)); return res; } @@ -1805,10 +1827,10 @@ dbglog_process_netlink_data(wmi_unified_t wmi_handle, const uint8_t *buffer, slot->dropped = cpu_to_le32(dropped); memcpy(slot->payload, buffer, len); - res = nl_srv_bcast(skb_out); + res = nl_srv_bcast_fw_logs(skb_out); if ((res < 0) && (res != -ESRCH)) { AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, - ("%s: nl_srv_ucast failed 0x%x\n", + ("%s: nl_srv_bcast_fw_logs failed 0x%x\n", __func__, res)); return res; } @@ -4090,6 +4112,98 @@ static int dbglog_debugfs_remove(wmi_unified_t wmi_handle) } #endif /* WLAN_OPEN_SOURCE */ +/** + * cnss_diag_handle_crash_inject() - API to handle crash inject command + * @slot: pointer to struct dbglog_slot + * + * API to handle CNSS diag crash inject command + * + * Return: None + */ +static void cnss_diag_handle_crash_inject(struct dbglog_slot *slot) +{ + switch (slot->diag_type) { + case DIAG_TYPE_CRASH_INJECT: + if (slot->length != 2) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("crash_inject cmd error\n")); + return; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s : DIAG_TYPE_CRASH_INJECT: %d %d\n", __func__, + slot->payload[0], slot->payload[1])); + if (!tgt_assert_enable) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: tgt Assert Disabled\n", __func__)); + return; + } + wma_cli_set2_command(0, (int)GEN_PARAM_CRASH_INJECT, + slot->payload[0], + slot->payload[1], GEN_CMD); + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown cmd[%d] error\n", + slot->diag_type)); + break; + } +} + +#ifdef CNSS_GENL +/** + * cnss_diag_cmd_handler() - API to handle CNSS diag command + * @data: Data received + * @data_len: length of the data received + * @ctx: Pointer to stored context + * @pid: Process ID + * + * API to handle CNSS diag commands from user space + * + * Return: None + */ +static void cnss_diag_cmd_handler(const void *data, int data_len, + void *ctx, int pid) +{ + struct dbglog_slot *slot = NULL; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1]; + + if (nla_parse(tb, CLD80211_ATTR_MAX, data, data_len, NULL)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: nla parse fails \n", + __func__)); + return; + } + + if (!tb[CLD80211_ATTR_DATA]) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: attr VENDOR_DATA fails \n", + __func__)); + return; + } + slot = (struct dbglog_slot *)nla_data(tb[CLD80211_ATTR_DATA]); + + if (!slot) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: data NULL \n", __func__)); + return; + } + + cnss_diag_handle_crash_inject(slot); + return; +} + +/** + * cnss_diag_activate_service() - API to register CNSS diag cmd handler + * + * API to register the CNSS diag command handler using new genl infra. + * Return type is zero to match with legacy prototype + * + * Return: 0 + */ +int cnss_diag_activate_service(void) +{ + register_cld_cmd_cb(WLAN_NL_MSG_CNSS_DIAG, cnss_diag_cmd_handler, NULL); + return 0; +} + +#else + /**--------------------------------------------------------------------------- \brief cnss_diag_msg_callback() - Call back invoked by netlink service @@ -4104,7 +4218,6 @@ static int dbglog_debugfs_remove(wmi_unified_t wmi_handle) static int cnss_diag_msg_callback(struct sk_buff *skb) { struct nlmsghdr *nlh; - struct dbglog_slot *slot; A_UINT8 *msg; nlh = (struct nlmsghdr *)skb->data; @@ -4115,33 +4228,9 @@ static int cnss_diag_msg_callback(struct sk_buff *skb) } msg = NLMSG_DATA(nlh); + cnss_diag_handle_crash_inject((struct dbglog_slot *)msg); - slot = (struct dbglog_slot *)msg; - switch (slot->diag_type) { - case DIAG_TYPE_CRASH_INJECT: - if (slot->length == 2) { - AR_DEBUG_PRINTF(ATH_DEBUG_INFO, - ("%s : DIAG_TYPE_CRASH_INJECT: %d %d\n", - __func__, slot->payload[0], slot->payload[1])); - if (!tgt_assert_enable) { - AR_DEBUG_PRINTF(ATH_DEBUG_INFO, - ("%s: tgt Assert Disabled\n", - __func__)); - return 0; - } - wma_cli_set2_command(0, GEN_PARAM_CRASH_INJECT, - slot->payload[0], slot->payload[1], - GEN_CMD); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("crash_inject cmd error\n")); - } - break; - default: - break; - } return 0; - } /**--------------------------------------------------------------------------- @@ -4168,6 +4257,7 @@ int cnss_diag_activate_service(void) } return 0; } +#endif static A_BOOL dbglog_wow_print_handler(A_UINT32 mod_id, diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c index 79db19389782..dd43d7621e2e 100644 --- a/core/utils/logging/src/wlan_logging_sock_svc.c +++ b/core/utils/logging/src/wlan_logging_sock_svc.c @@ -46,6 +46,10 @@ #include "wlan_hdd_main.h" #include "pktlog_ac.h" +#ifdef CNSS_GENL +#include <net/cnss_nl.h> +#endif + #define MAX_NUM_PKT_LOG 32 /** @@ -78,7 +82,8 @@ static uint8_t grx_count; #define ANI_NL_MSG_LOG_TYPE 89 #define ANI_NL_MSG_READY_IND_TYPE 90 -#define MAX_LOGMSG_LENGTH 4096 +#define MAX_LOGMSG_LENGTH 2048 +#define MAX_SKBMSG_LENGTH 4096 #define MAX_PKTSTATS_LENGTH 2048 #define MAX_PKTSTATS_BUFF 16 @@ -172,6 +177,7 @@ static struct pkt_stats_msg *gpkt_stats_buffers; /* PID of the APP to log the message */ static int gapp_pid = INVALID_PID; +#ifndef CNSS_GENL /* Utility function to send a netlink message to an application * in user space */ @@ -223,6 +229,7 @@ static int wlan_send_sock_msg_to_app(tAniHdr *wmsg, int radio, __func__, wmsg->type, pid); return err; } +#endif /** * is_data_path_module() - To check for a Datapath module @@ -559,6 +566,42 @@ static int pkt_stats_fill_headers(struct sk_buff *skb) } /** + * nl_srv_bcast_diag() - Wrapper to send bcast msgs to diag events mcast grp + * @skb: sk buffer pointer + * + * Sends the bcast message to diag events multicast group with generic nl socket + * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. + * + * Return: zero on success, error code otherwise + */ +static int nl_srv_bcast_diag(struct sk_buff *skb) +{ +#ifdef CNSS_GENL + return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC); +#else + return nl_srv_bcast(skb); +#endif +} + +/** + * nl_srv_bcast_host_logs() - Wrapper to send bcast msgs to host logs mcast grp + * @skb: sk buffer pointer + * + * Sends the bcast message to host logs multicast group with generic nl socket + * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. + * + * Return: zero on success, error code otherwise + */ +static int nl_srv_bcast_host_logs(struct sk_buff *skb) +{ +#ifdef CNSS_GENL + return nl_srv_bcast(skb, CLD80211_MCGRP_HOST_LOGS, ANI_NL_MSG_LOG); +#else + return nl_srv_bcast(skb); +#endif +} + +/** * pktlog_send_per_pkt_stats_to_user() - This function is used to send the per * packet statistics to the user * @@ -577,11 +620,11 @@ int pktlog_send_per_pkt_stats_to_user(void) while (!list_empty(&gwlan_logging.pkt_stat_filled_list) && !gwlan_logging.exit) { - skb_new = dev_alloc_skb(MAX_PKTSTATS_LENGTH); + skb_new = dev_alloc_skb(MAX_SKBMSG_LENGTH); if (skb_new == NULL) { if (!rate_limit) { pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n", - __func__, MAX_LOGMSG_LENGTH, + __func__, MAX_SKBMSG_LENGTH, gwlan_logging.drop_count); } rate_limit = 1; @@ -602,7 +645,7 @@ int pktlog_send_per_pkt_stats_to_user(void) free_old_skb = true; goto err; } - ret = nl_srv_bcast(pstats_msg->skb); + ret = nl_srv_bcast_diag(pstats_msg->skb); if (ret < 0) { pr_info("%s: Send Failed %d drop_count = %u\n", __func__, ret, @@ -697,7 +740,7 @@ static int send_filled_buffers_to_user(void) list_add_tail(&plog_msg->node, &gwlan_logging.free_list); spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); - ret = nl_srv_bcast(skb); + ret = nl_srv_bcast_host_logs(skb); /* print every 64th drop count */ if (ret < 0 && (!(gwlan_logging.drop_count % 0x40))) { pr_err("%s: Send Failed %d drop_count = %u\n", @@ -858,6 +901,30 @@ static int wlan_logging_thread(void *Arg) return 0; } +#ifdef CNSS_GENL +/** + * register_logging_sock_handler() - Logging sock handler registration + * + * Dummy API to register the command handler for logger socket app. + * + * Return: None + */ +static void register_logging_sock_handler(void) +{ +} + +/** + * unregister_logging_sock_handler() - Logging sock handler unregistration + * + * Dummy API to unregister the command handler for logger socket app. + * + * Return: None + */ +static void unregister_logging_sock_handler(void) +{ +} +#else + /* * Process all the Netlink messages from Logger Socket app in user space */ @@ -924,6 +991,34 @@ static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb) return ret; } +/** + * register_logging_sock_handler() - Logging sock handler registration + * + * API to register the command handler for logger socket app. Registers + * legacy handler + * + * Return: None + */ +static void register_logging_sock_handler(void) +{ + nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg); +} + +/** + * unregister_logging_sock_handler() - Logging sock handler unregistration + * + * API to unregister the command handler for logger socket app. Unregisters + * legacy handler + * + * Return: None + */ +static void unregister_logging_sock_handler(void) +{ + nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg); +} +#endif + + int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf) { int i = 0, j, pkt_stats_size; @@ -1011,8 +1106,7 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf) gwlan_logging.is_active = true; gwlan_logging.is_flush_complete = false; - nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg); - + register_logging_sock_handler(); return 0; err3: @@ -1043,7 +1137,7 @@ int wlan_logging_sock_deactivate_svc(void) if (!gplog_msg) return 0; - nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg); + unregister_logging_sock_handler(); clear_default_logtoapp_log_level(); gapp_pid = INVALID_PID; diff --git a/core/utils/nlink/inc/wlan_nlink_srv.h b/core/utils/nlink/inc/wlan_nlink_srv.h index b455b64d583f..4f76a4171d01 100644 --- a/core/utils/nlink/inc/wlan_nlink_srv.h +++ b/core/utils/nlink/inc/wlan_nlink_srv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -54,7 +54,15 @@ void nl_srv_exit(void); int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler); int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler); + +#ifdef CNSS_GENL +int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag, + int app_id, int mcgroup_id); +int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id); +#else int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag); int nl_srv_bcast(struct sk_buff *skb); +#endif + int nl_srv_is_initialized(void); #endif diff --git a/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c index cef164515339..b8b8e2aab114 100644 --- a/core/utils/nlink/src/wlan_nlink_srv.c +++ b/core/utils/nlink/src/wlan_nlink_srv.c @@ -51,6 +51,13 @@ #include <wlan_nlink_srv.h> #include <qdf_trace.h> +#ifdef CNSS_GENL +#include <qdf_mem.h> +#include <wlan_nlink_common.h> +#include <net/genetlink.h> +#include <net/cnss_nl.h> +#endif + #if defined(CONFIG_CNSS_LOGGER) #include <net/cnss_logger.h> @@ -344,6 +351,195 @@ int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler) return retcode; } +#ifdef CNSS_GENL +/** + * nl80211hdr_put() - API to fill genlmsg header + * @skb: Sk buffer + * @portid: Port ID + * @seq: Sequence number + * @flags: Flags + * @cmd: Command id + * + * API to fill genl message header for brodcast events to user space + * + * Return: Pointer to user specific header/payload + */ +static inline void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid, + uint32_t seq, int flags, uint8_t cmd) +{ + struct genl_family *cld80211_fam = cld80211_get_genl_family(); + + return genlmsg_put(skb, portid, seq, cld80211_fam, flags, cmd); +} + +/** + * cld80211_fill_data() - API to fill payload to nl message + * @msg: Sk buffer + * @portid: Port ID + * @seq: Sequence number + * @flags: Flags + * @cmd: Command ID + * @buf: data buffer/payload to be filled + * @len: length of the payload ie. @buf + * + * API to fill the payload/data of the nl message to be sent + * + * Return: zero on success + */ +static int cld80211_fill_data(struct sk_buff *msg, uint32_t portid, + uint32_t seq, int flags, uint8_t cmd, + uint8_t *buf, int len) +{ + void *hdr; + struct nlattr *nest; + + hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); + if (!hdr) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "nl80211 hdr put failed"); + return -EPERM; + } + + nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA); + if (!nest) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "nla_nest_start failed"); + goto nla_put_failure; + } + + if (nla_put(msg, CLD80211_ATTR_DATA, len, buf)) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "nla_put failed"); + goto nla_put_failure; + } + + nla_nest_end(msg, nest); + genlmsg_end(msg, hdr); + + return 0; +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EPERM; +} + +/** + * send_msg_to_cld80211() - API to send message to user space Application + * @mcgroup_id: Multicast group ID + * @pid: Port ID + * @app_id: Application ID + * @buf: Data/payload buffer to be sent + * @len: Length of the data ie. @buf + * + * API to send the nl message to user space application. + * + * Return: zero on success + */ +static int send_msg_to_cld80211(int mcgroup_id, int pid, int app_id, + uint8_t *buf, int len) +{ + struct sk_buff *msg; + struct genl_family *cld80211_fam = cld80211_get_genl_family(); + int status; + int flags = GFP_KERNEL; + + if (in_interrupt() || irqs_disabled() || in_atomic()) + flags = GFP_ATOMIC; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags); + if (!msg) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "nlmsg malloc fails"); + return -EPERM; + } + + status = cld80211_fill_data(msg, pid, 0, 0, app_id, buf, len); + if (status) { + nlmsg_free(msg); + return -EPERM; + } + + genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0, + mcgroup_id, flags); + return 0; +} + +/** + * nl_srv_bcast() - wrapper function to do broadcast events to user space apps + * @skb: the socket buffer to send + * @mcgroup_id: multicast group id + * @app_id: application id + * + * This function is common wrapper to send broadcast events to different + * user space applications. + * + * return: none + */ +int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; + void *msg = NLMSG_DATA(nlh); + uint32_t msg_len = nlmsg_len(nlh); + uint8_t *tempbuf; + int status; + + tempbuf = (uint8_t *)qdf_mem_malloc(msg_len); + qdf_mem_copy(tempbuf, msg, msg_len); + status = send_msg_to_cld80211(mcgroup_id, 0, app_id, tempbuf, msg_len); + if (status) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "send msg to cld80211 fails for app id %d", app_id); + dev_kfree_skb(skb); + qdf_mem_free(tempbuf); + return -EPERM; + } + + dev_kfree_skb(skb); + qdf_mem_free(tempbuf); + return 0; +} + +/** + * nl_srv_ucast() - wrapper function to do unicast events to user space apps + * @skb: the socket buffer to send + * @dst_pid: destination process IF + * @flag: flags + * @app_id: application id + * @mcgroup_id: Multicast group ID + * + * This function is common wrapper to send unicast events to different + * user space applications. This internally used broadcast API with multicast + * group mcgrp_id. This wrapper serves as a common API in both + * new generic netlink infra and legacy implementation. + * + * return: zero on success, error code otherwise + */ +int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag, + int app_id, int mcgroup_id) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; + void *msg = NLMSG_DATA(nlh); + uint32_t msg_len = nlmsg_len(nlh); + uint8_t *tempbuf; + int status; + + tempbuf = (uint8_t *)qdf_mem_malloc(msg_len); + qdf_mem_copy(tempbuf, msg, msg_len); + status = send_msg_to_cld80211(mcgroup_id, dst_pid, app_id, + tempbuf, msg_len); + if (status) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "send msg to cld80211 fails for app id %d", app_id); + dev_kfree_skb(skb); + qdf_mem_free(tempbuf); + return -EPERM; + } + + dev_kfree_skb(skb); + qdf_mem_free(tempbuf); + return 0; +} +#else + /* * Unicast the message to the process in user space identfied * by the dst-pid @@ -391,6 +587,7 @@ int nl_srv_bcast(struct sk_buff *skb) } return err; } +#endif /* * Processes the Netlink socket input queue. diff --git a/core/utils/ptt/inc/wlan_ptt_sock_svc.h b/core/utils/ptt/inc/wlan_ptt_sock_svc.h index 44587480e7ac..c75f7e0cb9d4 100644 --- a/core/utils/ptt/inc/wlan_ptt_sock_svc.h +++ b/core/utils/ptt/inc/wlan_ptt_sock_svc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -119,6 +119,19 @@ typedef struct sAniAppRegReq { tAniNlModTypes type; /* module id */ int pid; /* process id */ } tAniNlAppRegReq; + +/** + * struct sptt_app_reg_req - PTT register request structure + * @radio: Radio ID + * @wmsg: ANI header + * + * payload structure received as nl data from PTT app/user space + */ +typedef struct sptt_app_reg_req { + int radio; + tAniHdr wmsg; +} ptt_app_reg_req; + typedef struct sAniNlAppRegRsp { tAniHdr wniHdr; /* Generic WNI msg header */ tAniNlAppRegReq regReq; /* The original request msg */ diff --git a/core/utils/ptt/src/wlan_ptt_sock_svc.c b/core/utils/ptt/src/wlan_ptt_sock_svc.c index 4efb50ffbc47..39a7afaf4342 100644 --- a/core/utils/ptt/src/wlan_ptt_sock_svc.c +++ b/core/utils/ptt/src/wlan_ptt_sock_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -39,6 +39,14 @@ #include <qdf_types.h> #include <qdf_trace.h> +#ifdef CNSS_GENL +#include <net/cnss_nl.h> +#else + +/** ptt Process ID */ +static int32_t ptt_pid = INVALID_PID; +#endif + #define PTT_SOCK_DEBUG #ifdef PTT_SOCK_DEBUG #define PTT_TRACE(level, args ...) QDF_TRACE(QDF_MODULE_ID_QDF, level, ## args) @@ -46,9 +54,6 @@ #define PTT_TRACE(level, args ...) #endif -/** ptt Process ID */ -static int32_t ptt_pid = INVALID_PID; - #ifdef PTT_SOCK_DEBUG_VERBOSE /* Utility function to perform a hex dump */ static void ptt_sock_dump_buf(const unsigned char *pbuf, int cnt) @@ -67,6 +72,45 @@ static void ptt_sock_dump_buf(const unsigned char *pbuf, int cnt) #endif /** + * nl_srv_ucast_ptt() - Wrapper function to send ucast msgs to PTT + * @skb: sk buffer pointer + * @dst_pid: Destination PID + * @flag: flags + * + * Sends the ucast message to PTT with generic nl socket if CNSS_GENL + * is enabled. Else, use the legacy netlink socket to send. + * + * Return: zero on success, error code otherwise + */ +static int nl_srv_ucast_ptt(struct sk_buff *skb, int dst_pid, int flag) +{ +#ifdef CNSS_GENL + return nl_srv_ucast(skb, dst_pid, flag, ANI_NL_MSG_PUMAC, + CLD80211_MCGRP_DIAG_EVENTS); +#else + return nl_srv_ucast(skb, dst_pid, flag); +#endif +} + +/** + * nl_srv_bcast_ptt() - Wrapper function to send bcast msgs to DIAG mcast group + * @skb: sk buffer pointer + * + * Sends the bcast message to DIAG multicast group with generic nl socket + * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. + * + * Return: zero on success, error code otherwise + */ +static int nl_srv_bcast_ptt(struct sk_buff *skb) +{ +#ifdef CNSS_GENL + return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC); +#else + return nl_srv_bcast(skb); +#endif +} + +/** * ptt_sock_send_msg_to_app() - Send nl message to user space * wmsg: Message header * radio: Unit number of the radio @@ -121,9 +165,9 @@ int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid) #endif if (pid != INVALID_PID) - err = nl_srv_ucast(skb, pid, MSG_DONTWAIT); + err = nl_srv_ucast_ptt(skb, pid, MSG_DONTWAIT); else - err = nl_srv_bcast(skb); + err = nl_srv_bcast_ptt(skb); if (err) PTT_TRACE(QDF_TRACE_LEVEL_INFO, @@ -132,6 +176,7 @@ int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid) return err; } +#ifndef CNSS_GENL /* * Process tregisteration request and send registration response messages * to the PTT Socket App in user space @@ -204,6 +249,73 @@ static int ptt_sock_rx_nlink_msg(struct sk_buff *skb) } return 0; } +#endif + +#ifdef CNSS_GENL +/** + * ptt_cmd_handler() - Handler function for PTT commands + * @data: Data to be parsed + * @data_len: Length of the data received + * @ctx: Registered context reference + * @pid: Process id of the user space application + * + * This function handles the command from PTT user space application + * + * Return: None + */ +static void ptt_cmd_handler(const void *data, int data_len, void *ctx, int pid) +{ + ptt_app_reg_req *payload; + struct nlattr *tb[CLD80211_ATTR_MAX + 1]; + + if (nla_parse(tb, CLD80211_ATTR_MAX, data, data_len, NULL)) { + PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "Invalid ATTR"); + return; + } + + if (!tb[CLD80211_ATTR_DATA]) { + PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "attr ATTR_DATA failed"); + return; + } + + payload = (ptt_app_reg_req *)(nla_data(tb[CLD80211_ATTR_DATA])); + switch (payload->wmsg.type) { + case ANI_MSG_APP_REG_REQ: + ptt_sock_send_msg_to_app(&payload->wmsg, payload->radio, + ANI_NL_MSG_PUMAC, pid); + break; + default: + PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "Unknown msg type %d", + payload->wmsg.type); + break; + } +} + +/** + * ptt_sock_activate_svc() - API to register PTT/PUMAC command handler + * + * API to register the PTT/PUMAC command handlers. Argument @pAdapter + * is sent for prototype compatibility between new genl and legacy + * implementation + * + * Return: 0 + */ +int ptt_sock_activate_svc(void) +{ + register_cld_cmd_cb(ANI_NL_MSG_PUMAC, ptt_cmd_handler, NULL); + register_cld_cmd_cb(ANI_NL_MSG_PTT, ptt_cmd_handler, NULL); + return 0; +} + +/** + * ptt_sock_deactivate_svc() - Dummy API to deactivate PTT service + * + * Return: Void + */ +void ptt_sock_deactivate_svc(void) +{ +} +#else /** * ptt_sock_activate_svc() - activate PTT service @@ -227,5 +339,5 @@ void ptt_sock_deactivate_svc(void) { ptt_pid = INVALID_PID; } - +#endif #endif /* PTT_SOCK_SVC_ENABLE */ |
