From fffcebf2e926a46534518e770b63d1ab6574e139 Mon Sep 17 00:00:00 2001 From: akosigi Date: Wed, 15 Nov 2017 18:29:32 +0530 Subject: [PATCH] qcacmn: Converge FTM feature Support for FTM to make it common between WIN and MCL. Change-Id: I4a65ca6d73d83e71f6a04405b5c41cdddb0a3c71 CRs-fixed: 2148283 --- ftm/core/src/wlan_ftm_svc.c | 166 ++++++++++++++++++ ftm/core/src/wlan_ftm_svc_i.h | 91 ++++++++++ ftm/dispatcher/inc/wlan_ftm_init_deinit_api.h | 59 +++++++ ftm/dispatcher/inc/wlan_ftm_ucfg_api.h | 125 +++++++++++++ ftm/dispatcher/src/wlan_ftm_init_deinit.c | 85 +++++++++ ftm/dispatcher/src/wlan_ftm_ucfg_api.c | 139 +++++++++++++++ .../dispatcher/src/dispatcher_init_deinit.c | 16 ++ os_if/linux/ftm/inc/wlan_cfg80211_ftm.h | 75 ++++++++ os_if/linux/ftm/inc/wlan_ioctl_ftm.h | 38 ++++ os_if/linux/ftm/src/wlan_cfg80211_ftm.c | 154 ++++++++++++++++ os_if/linux/ftm/src/wlan_ioctl_ftm.c | 115 ++++++++++++ qdf/inc/qdf_types.h | 2 + target_if/core/src/target_if_main.c | 9 + target_if/ftm/inc/target_if_ftm.h | 70 ++++++++ target_if/ftm/src/target_if_ftm.c | 158 +++++++++++++++++ umac/cmn_services/inc/wlan_cmn.h | 5 +- .../obj_mgr/inc/wlan_objmgr_cmn.h | 3 + .../lmac_if/inc/wlan_lmac_if_def.h | 34 ++++ .../lmac_if/src/wlan_lmac_if.c | 17 ++ 19 files changed, 1360 insertions(+), 1 deletion(-) create mode 100644 ftm/core/src/wlan_ftm_svc.c create mode 100644 ftm/core/src/wlan_ftm_svc_i.h create mode 100644 ftm/dispatcher/inc/wlan_ftm_init_deinit_api.h create mode 100644 ftm/dispatcher/inc/wlan_ftm_ucfg_api.h create mode 100644 ftm/dispatcher/src/wlan_ftm_init_deinit.c create mode 100644 ftm/dispatcher/src/wlan_ftm_ucfg_api.c create mode 100644 os_if/linux/ftm/inc/wlan_cfg80211_ftm.h create mode 100644 os_if/linux/ftm/inc/wlan_ioctl_ftm.h create mode 100644 os_if/linux/ftm/src/wlan_cfg80211_ftm.c create mode 100644 os_if/linux/ftm/src/wlan_ioctl_ftm.c create mode 100644 target_if/ftm/inc/target_if_ftm.h create mode 100644 target_if/ftm/src/target_if_ftm.c diff --git a/ftm/core/src/wlan_ftm_svc.c b/ftm/core/src/wlan_ftm_svc.c new file mode 100644 index 000000000000..a055642a1319 --- /dev/null +++ b/ftm/core/src/wlan_ftm_svc.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This implementation of init/deint functions for FTM services. + */ + +#include "wlan_ftm_svc_i.h" +#include +#include + +static inline struct wlan_lmac_if_ftm_tx_ops * +wlan_psoc_get_ftm_txops(struct wlan_objmgr_psoc *psoc) +{ + return &((psoc->soc_cb.tx_ops.ftm_tx_ops)); +} + +static QDF_STATUS +ftm_pdev_obj_init(struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj) +{ + ftm_pdev_obj->data = qdf_mem_malloc(FTM_CMD_MAX_BUF_LENGTH); + if (!ftm_pdev_obj->data) { + ftm_err("Memory alloc failed for ftm pdev obj data"); + return QDF_STATUS_E_NOMEM; + } + + ftm_pdev_obj->length = 0; + + ftm_pdev_obj->cmd_type = WIFI_FTM_CMD_UNKNOWN; + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_ftm_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev, + void *arg_list) +{ + QDF_STATUS status; + struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj; + + ftm_pdev_obj = qdf_mem_malloc(sizeof(*ftm_pdev_obj)); + + if (!ftm_pdev_obj) { + ftm_err("Memory alloc failed for ftm pdev obj"); + return QDF_STATUS_E_NOMEM; + } + + ftm_pdev_obj->pdev = pdev; + status = ftm_pdev_obj_init(ftm_pdev_obj); + + if (QDF_IS_STATUS_ERROR(status)) { + ftm_err("ftm pdev obj init failed"); + qdf_mem_free(ftm_pdev_obj); + return status; + } + + status = wlan_objmgr_pdev_component_obj_attach(pdev, + WLAN_UMAC_COMP_FTM, + ftm_pdev_obj, + QDF_STATUS_SUCCESS); + + if (QDF_IS_STATUS_ERROR(status)) { + ftm_err("ftm pdev obj attach failed"); + qdf_mem_free(ftm_pdev_obj); + return status; + } + + return status; +} + +static QDF_STATUS +ftm_pdev_obj_deinit(struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj) +{ + if (ftm_pdev_obj->data) { + qdf_mem_free(ftm_pdev_obj->data); + + ftm_pdev_obj->data = NULL; + ftm_pdev_obj->length = 0; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_ftm_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev, + void *arg_list) +{ + QDF_STATUS status; + struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj = + wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_FTM); + + if (NULL == ftm_pdev_obj) { + ftm_err("invalid wifi ftm obj"); + return QDF_STATUS_E_FAULT; + } + + status = wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_FTM, + ftm_pdev_obj); + + status = ftm_pdev_obj_deinit(ftm_pdev_obj); + ftm_pdev_obj->pdev = NULL; + + qdf_mem_free(ftm_pdev_obj); + + return status; +} + +QDF_STATUS +wlan_ftm_testmode_attach(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops; + + ftm_tx_ops = wlan_psoc_get_ftm_txops(psoc); + + if (ftm_tx_ops->ftm_attach) + return ftm_tx_ops->ftm_attach(psoc); + else + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_ftm_testmode_detach(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops; + + ftm_tx_ops = wlan_psoc_get_ftm_txops(psoc); + + if (ftm_tx_ops->ftm_detach) + return ftm_tx_ops->ftm_detach(psoc); + else + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_ftm_cmd_send(struct wlan_objmgr_pdev *pdev, uint8_t *buf, + uint32_t len, uint8_t pdev_id) +{ + struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) + return QDF_STATUS_E_NOENT; + + ftm_tx_ops = wlan_psoc_get_ftm_txops(psoc); + + if (ftm_tx_ops->ftm_cmd_send) + return ftm_tx_ops->ftm_cmd_send(pdev, buf, len, pdev_id); + + return QDF_STATUS_SUCCESS; +} diff --git a/ftm/core/src/wlan_ftm_svc_i.h b/ftm/core/src/wlan_ftm_svc_i.h new file mode 100644 index 000000000000..bd8be913e46e --- /dev/null +++ b/ftm/core/src/wlan_ftm_svc_i.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declare the ftm service data structure and apis + */ +#ifndef _WLAN_FTM_SVC_H_ +#define _WLAN_FTM_SVC_H_ + +#include +#include +#include + +/** + * struct ftm_seg_hdr_info - the segment header for the event from FW + * @len: length of the segment header + * @msgref: message reference + * @segment_info: segment information + * @pad: padding + * + */ +struct ftm_seg_hdr_info { + uint32_t len; + uint32_t msgref; + uint32_t segment_info; + uint32_t pad; +}; + +/** + * wlan_ftm_pdev_obj_create_notification() - ftm pdev create handler + * @pdev: pdev pointer + * @arg_list: argument list + * + * return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS wlan_ftm_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev, + void *arg_list); + +/** + * wlan_ftm_pdev_obj_destroy_notification() - ftm pdev destroy handler + * @pdev: pdev pointer + * @arg_list: argument list + * + * return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS wlan_ftm_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev, + void *arg_list); + +/** + * wlan_ftm_cmd_send() - send ftm command to target_if layer + * @pdev: pdev pointer + * @buf: data buffer + * @len: event length + * + * return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS wlan_ftm_cmd_send(struct wlan_objmgr_pdev *pdev, uint8_t *buf, + uint32_t len, uint8_t pdev_id); + +/** + * wlan_ftm_testmode_attach() - Attach FTM UTF handle + * @psoc: psoc pointer + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS wlan_ftm_testmode_attach(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_ftm_testmode_detach() - Attach FTM UTF handle + * @psoc: psoc pointer + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS wlan_ftm_testmode_detach(struct wlan_objmgr_psoc *psoc); +#endif /* _WLAN_FTM_SVC_H_ */ diff --git a/ftm/dispatcher/inc/wlan_ftm_init_deinit_api.h b/ftm/dispatcher/inc/wlan_ftm_init_deinit_api.h new file mode 100644 index 000000000000..0487af6478d1 --- /dev/null +++ b/ftm/dispatcher/inc/wlan_ftm_init_deinit_api.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declare the ftm service data structure and apis + */ +#ifndef _WLAN_FTM_UCFG_API_H_ +#define _WLAN_FTM_UCFG_API_H_ + +#include +#include +#include + +/** + * dispatcher_ftm_init() - FTM testmode initialization API + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS dispatcher_ftm_init(void); + +/** + * dispatcher_ftm_deinit() - FTM testmode deinitialization API + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS dispatcher_ftm_deinit(void); + +/** + * dispatcher_ftm_psoc_open() - FTM module open API + * @psoc: psoc object + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS dispatcher_ftm_psoc_open(struct wlan_objmgr_psoc *psoc); + +/** + * dispatcher_ftm_psoc_close() - FTM module close API + * @psoc: psoc object + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS dispatcher_ftm_psoc_close(struct wlan_objmgr_psoc *psoc); +#endif /* _WLAN_FTM_UCFG_API_H_ */ diff --git a/ftm/dispatcher/inc/wlan_ftm_ucfg_api.h b/ftm/dispatcher/inc/wlan_ftm_ucfg_api.h new file mode 100644 index 000000000000..34a6489c6d20 --- /dev/null +++ b/ftm/dispatcher/inc/wlan_ftm_ucfg_api.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declare the ftm service data structure and apis + */ +#ifndef _WLAN_FTM_UCFG_API_H_ +#define _WLAN_FTM_UCFG_API_H_ + +#include +#include +#include + +#define FTM_DEBUG 0 + +#if FTM_DEBUG +#define ftm_log(level, args...) \ + QDF_TRACE(QDF_MODULE_ID_FTM, level, ## args) +#define ftm_logfl(level, format, args...) \ + ftm_log(level, FL(format), ## args) + +#define ftm_alert(format, args...) \ + ftm_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args) +#define ftm_err(format, args...) \ + ftm_logfl(QDF_TRACE_LEVEL_ERROR, format, ## args) +#define ftm_warn(format, args...) \ + ftm_logfl(QDF_TRACE_LEVEL_WARN, format, ## args) +#define ftm_notice(format, args...) \ + ftm_logfl(QDF_TRACE_LEVEL_INFO, format, ## args) +#define ftm_debug(format, args...) \ + ftm_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args) +#else +#define ftm_alert(format, args...) +#define ftm_err(format, args...) +#define ftm_warn(format, args...) +#define ftm_notice(format, args...) +#define ftm_debug(format, args...) +#endif + +#define FTM_IOCTL_UNIFIED_UTF_CMD 0x1000 +#define FTM_IOCTL_UNIFIED_UTF_RSP 0x1001 +#define FTM_CMD_MAX_BUF_LENGTH 2048 + +/** + * enum wifi_ftm_cmd_type - the enumeration of the command source per pdev + * @WIFI_FTM_CMD_IOCTL: command from ioctl on the pdev + * @WIFI_FTM_CMD_NL80211: command from nl80211 on the pdev + * + */ +enum wifi_ftm_pdev_cmd_type { + WIFI_FTM_CMD_IOCTL = 1, + WIFI_FTM_CMD_NL80211, + + /* command should be added above */ + WIFI_FTM_CMD_UNKNOWN, +}; + +/** + * struct wifi_ftm_pdev_priv_obj - wifi ftm pdev utf event info + * @pdev: pointer to pdev + * @data: data ptr + * @current_seq: curent squence + * @expected_seq: expected sequence + * @length: length + * @offset: offset + * @cmd_type: command type from either ioctl or nl80211 + */ +struct wifi_ftm_pdev_priv_obj { + struct wlan_objmgr_pdev *pdev; + uint8_t *data; + uint8_t current_seq; + uint8_t expected_seq; + qdf_size_t length; + qdf_size_t offset; + enum wifi_ftm_pdev_cmd_type cmd_type; +}; + +/** + * wlan_ftm_testmode_cmd() - handle FTM testmode command + * @pdev: pdev pointer + * @data: data + * @len: data length + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS ucfg_wlan_ftm_testmode_cmd(struct wlan_objmgr_pdev *pdev, + uint8_t *data, uint32_t len); + +/** + * wlan_ftm_testmode_rsp() - handle FTM testmode command + * @pdev: pdev pointer + * @data: data + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS ucfg_wlan_ftm_testmode_rsp(struct wlan_objmgr_pdev *pdev, + uint8_t *data); + +/** + * wlan_ftm_process_utf_event() - process ftm UTF event + * @scn_handle: scn handle + * @event: event buffer + * @len: event length + * + * return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS wlan_ftm_process_utf_event(struct wlan_objmgr_pdev *pdev, + uint8_t *event_buf, uint32_t len); +#endif /* _WLAN_FTM_UCFG_API_H_ */ diff --git a/ftm/dispatcher/src/wlan_ftm_init_deinit.c b/ftm/dispatcher/src/wlan_ftm_init_deinit.c new file mode 100644 index 000000000000..47364e07284d --- /dev/null +++ b/ftm/dispatcher/src/wlan_ftm_init_deinit.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This implementation of init/deint functions for FTM services. + */ + +#include +#include +#include +#include "../../core/src/wlan_ftm_svc_i.h" +#include +#include + +QDF_STATUS dispatcher_ftm_init(void) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_FTM, + wlan_ftm_pdev_obj_create_notification, NULL); + + if (QDF_IS_STATUS_ERROR(status)) + goto err_pdev_create; + + status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_FTM, + wlan_ftm_pdev_obj_destroy_notification, NULL); + + if (QDF_IS_STATUS_ERROR(status)) + goto err_pdev_delete; + + return QDF_STATUS_SUCCESS; + +err_pdev_delete: + wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_FTM, + wlan_ftm_pdev_obj_create_notification, NULL); +err_pdev_create: + return status; +} + +QDF_STATUS dispatcher_ftm_deinit(void) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_FTM, + wlan_ftm_pdev_obj_create_notification, NULL); + + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_FTM, + wlan_ftm_pdev_obj_destroy_notification, NULL); + + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dispatcher_ftm_psoc_open(struct wlan_objmgr_psoc *psoc) +{ + /* calling the wmi event handler registration */ + return wlan_ftm_testmode_attach(psoc); +} + +QDF_STATUS dispatcher_ftm_psoc_close(struct wlan_objmgr_psoc *psoc) +{ + /* calling the wmi event handler de-registration */ + return wlan_ftm_testmode_detach(psoc); +} diff --git a/ftm/dispatcher/src/wlan_ftm_ucfg_api.c b/ftm/dispatcher/src/wlan_ftm_ucfg_api.c new file mode 100644 index 000000000000..8a737be1767f --- /dev/null +++ b/ftm/dispatcher/src/wlan_ftm_ucfg_api.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This implementation of init/deint functions for FTM services. + */ + +#include +#include +#include "../../core/src/wlan_ftm_svc_i.h" +#include +#include + +QDF_STATUS ucfg_wlan_ftm_testmode_cmd(struct wlan_objmgr_pdev *pdev, + uint8_t *data, uint32_t len) +{ + struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj; + uint8_t pdev_id; + + ftm_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_FTM); + if (!ftm_pdev_obj) { + ftm_err("Failed to get ftm pdev component"); + return QDF_STATUS_E_FAILURE; + } + + ftm_pdev_obj->length = 0; + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + return wlan_ftm_cmd_send(pdev, data, len, pdev_id); +} + +QDF_STATUS ucfg_wlan_ftm_testmode_rsp(struct wlan_objmgr_pdev *pdev, + uint8_t *data) +{ + struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj; + uint32_t *len; + + ftm_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_FTM); + if (!ftm_pdev_obj) { + ftm_err("Failed to get ftm pdev component"); + return QDF_STATUS_E_FAILURE; + } + + if (ftm_pdev_obj->length) { + len = (uint32_t *)data; + *len = ftm_pdev_obj->length; + qdf_mem_copy((data + 4), ftm_pdev_obj->data, + ftm_pdev_obj->length); + + ftm_pdev_obj->length = 0; + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS +wlan_ftm_process_utf_event(struct wlan_objmgr_pdev *pdev, + uint8_t *event_buf, uint32_t len) +{ + struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj; + u_int16_t utf_datalen; + uint8_t *utf_data; + struct ftm_seg_hdr_info seghdr_info; + u_int8_t total_segments, current_seq; + + ftm_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_FTM); + if (!ftm_pdev_obj) { + ftm_err("Failed to get ftm pdev component"); + return QDF_STATUS_E_FAILURE; + } + + utf_data = event_buf; + seghdr_info = *(struct ftm_seg_hdr_info *)(event_buf); + ftm_pdev_obj->current_seq = (seghdr_info.segment_info & 0xF); + + current_seq = (seghdr_info.segment_info & 0xF); + total_segments = (seghdr_info.segment_info >> 4) & 0xF; + + utf_datalen = len - sizeof(seghdr_info); + + if (current_seq == 0) { + ftm_pdev_obj->expected_seq = 0; + ftm_pdev_obj->offset = 0; + } else { + if (ftm_pdev_obj->expected_seq != current_seq) { + ftm_debug("seq mismatch exp Seq %d got seq %d\n", + ftm_pdev_obj->expected_seq, current_seq); + } + } + + qdf_mem_copy(&ftm_pdev_obj->data[ftm_pdev_obj->offset], + &utf_data[sizeof(seghdr_info)], utf_datalen); + + ftm_pdev_obj->offset = ftm_pdev_obj->offset + utf_datalen; + ftm_pdev_obj->expected_seq++; + + if (ftm_pdev_obj->expected_seq == total_segments) { + if (ftm_pdev_obj->offset != seghdr_info.len) { + ftm_debug("len mismatch len %zu total len %d\n", + ftm_pdev_obj->offset, seghdr_info.len); + } + + ftm_pdev_obj->length = ftm_pdev_obj->offset; + + /** + * If the repsonse is for a command from FTM daemon, + * send this repsonse data to cfg80211 + */ + if (ftm_pdev_obj->cmd_type == WIFI_FTM_CMD_NL80211) { + if (wlan_cfg80211_ftm_rx_event(pdev, ftm_pdev_obj->data, + ftm_pdev_obj->length) != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + ftm_pdev_obj->cmd_type = WIFI_FTM_CMD_UNKNOWN; + } + } + + return QDF_STATUS_SUCCESS; +} diff --git a/init_deinit/dispatcher/src/dispatcher_init_deinit.c b/init_deinit/dispatcher/src/dispatcher_init_deinit.c index 306239c9509e..258996b8e1bc 100644 --- a/init_deinit/dispatcher/src/dispatcher_init_deinit.c +++ b/init_deinit/dispatcher/src/dispatcher_init_deinit.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #ifdef WLAN_POLICY_MGR_ENABLE @@ -774,6 +775,9 @@ QDF_STATUS dispatcher_init(void) if (QDF_STATUS_SUCCESS != dispatcher_green_ap_init()) goto green_ap_init_fail; + if (QDF_STATUS_SUCCESS != dispatcher_ftm_init()) + goto ftm_init_fail; + /* * scheduler INIT has to be the last as each component's * initialization has to happen first and then at the end @@ -785,6 +789,8 @@ QDF_STATUS dispatcher_init(void) return QDF_STATUS_SUCCESS; scheduler_init_fail: + dispatcher_ftm_deinit(); +ftm_init_fail: dispatcher_green_ap_deinit(); green_ap_init_fail: dispatcher_spectral_deinit(); @@ -832,6 +838,8 @@ QDF_STATUS dispatcher_deinit(void) { QDF_BUG(QDF_STATUS_SUCCESS == scheduler_deinit()); + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_ftm_deinit()); + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_green_ap_deinit()); QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_spectral_deinit()); @@ -921,7 +929,13 @@ QDF_STATUS dispatcher_psoc_open(struct wlan_objmgr_psoc *psoc) if (QDF_STATUS_SUCCESS != son_psoc_open(psoc)) goto psoc_son_fail; + if (QDF_STATUS_SUCCESS != dispatcher_ftm_psoc_open(psoc)) + goto ftm_psoc_open_fail; + return QDF_STATUS_SUCCESS; + +ftm_psoc_open_fail: + son_psoc_close(psoc); psoc_son_fail: regulatory_psoc_close(psoc); regulatory_psoc_open_fail: @@ -946,6 +960,8 @@ EXPORT_SYMBOL(dispatcher_psoc_open); QDF_STATUS dispatcher_psoc_close(struct wlan_objmgr_psoc *psoc) { + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_ftm_psoc_close(psoc)); + QDF_BUG(QDF_STATUS_SUCCESS == son_psoc_close(psoc)); QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_regulatory_psoc_close(psoc)); diff --git a/os_if/linux/ftm/inc/wlan_cfg80211_ftm.h b/os_if/linux/ftm/inc/wlan_cfg80211_ftm.h new file mode 100644 index 000000000000..3bb497eb38de --- /dev/null +++ b/os_if/linux/ftm/inc/wlan_cfg80211_ftm.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declares driver FTM functions interfacing with linux kernel + */ + +#ifndef _WLAN_CFG80211_FTM_H_ +#define _WLAN_CFG80211_FTM_H_ + +/** + * enum wlan_cfg80211_ftm_attr - FTM Netlink attributes + * @WLAN_CFG80211_FTM_ATTR_INVALID: attribute is invalid + * @WLAN_CFG80211_FTM_ATTR_CMD: attribute type is FTM command + * @WLAN_CFG80211_FTM_ATTR_DATA: attribute type is data + * + * @WLAN_CFG80211_FTM_ATTR_MAX: Max number of attributes + */ +enum wlan_cfg80211_ftm_attr { + WLAN_CFG80211_FTM_ATTR_INVALID = 0, + WLAN_CFG80211_FTM_ATTR_CMD = 1, + WLAN_CFG80211_FTM_ATTR_DATA = 2, + + /* keep last */ + WLAN_CFG80211_FTM_ATTR_MAX, +}; + +/** + * enum wlan_cfg80211_ftm_cmd - FTM command types + * @WLAN_CFG80211_FTM_CMD_WLAN_FTM: command is of type FTM + */ +enum wlan_cfg80211_ftm_cmd { + WLAN_CFG80211_FTM_CMD_WLAN_FTM = 0, +}; + +#define WLAN_FTM_DATA_MAX_LEN 2048 + +/** + * wlan_cfg80211_ftm_testmode_cmd() - process cfg80211 testmode command + * @pdev: pdev object + * @data: ftm testmode command data of type void + * @len: length of the data + * + * Return: 0 on success or -Eerrno otherwise + */ +int wlan_cfg80211_ftm_testmode_cmd(struct wlan_objmgr_pdev *pdev, + void *data, uint32_t len); + +/** + * wlan_cfg80211_ftm_rx_event() - handle the received ftm event + * @pdev: pdev object + * @data: ftm event data + * @len: length of the data + * + * Return: QDF_STATUS_SUCCESS on success or QDF_STATUS_E errno otherwise + */ +QDF_STATUS wlan_cfg80211_ftm_rx_event(struct wlan_objmgr_pdev *pdev, + uint8_t *data, uint32_t len); + +#endif diff --git a/os_if/linux/ftm/inc/wlan_ioctl_ftm.h b/os_if/linux/ftm/inc/wlan_ioctl_ftm.h new file mode 100644 index 000000000000..7a94c3fa2c1a --- /dev/null +++ b/os_if/linux/ftm/inc/wlan_ioctl_ftm.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declares driver FTM functions interfacing with linux kernel + */ + +#ifndef _WLAN_IOCTL_FTM_H_ +#define _WLAN_IOCTL_FTM_H_ + +/** + * wlan_ioctl_ftm_testmode_cmd() - handle the ftm ioctl command + * @pdev: pdev object + * @cmd: ftm command + * @userdata: the content of the command + * @length: the length of the userdata + * + * Return: 0 on success, otherwise the error code. + */ +int wlan_ioctl_ftm_testmode_cmd(struct wlan_objmgr_pdev *pdev, int cmd, + uint8_t *userdata, uint32_t length); + +#endif diff --git a/os_if/linux/ftm/src/wlan_cfg80211_ftm.c b/os_if/linux/ftm/src/wlan_cfg80211_ftm.c new file mode 100644 index 000000000000..140100252d46 --- /dev/null +++ b/os_if/linux/ftm/src/wlan_cfg80211_ftm.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: implementation of the driver FTM functions interfacing with linux kernel + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct nla_policy +wlan_cfg80211_ftm_policy[WLAN_CFG80211_FTM_ATTR_MAX + 1] = { + [WLAN_CFG80211_FTM_ATTR_CMD] = {.type = NLA_U32}, + [WLAN_CFG80211_FTM_ATTR_DATA] = {.type = NLA_BINARY, + .len = WLAN_FTM_DATA_MAX_LEN}, +}; + +static int +wlan_cfg80211_process_ftm_cmd(struct wlan_objmgr_pdev *pdev, + struct nlattr *tb[]) +{ + int buf_len; + void *buf; + QDF_STATUS status; + + if (!tb[WLAN_CFG80211_FTM_ATTR_DATA]) { + ftm_err("WLAN_CFG80211_FTM_ATTR_DATA attribute is invalid"); + return -EINVAL; + } + + buf = nla_data(tb[WLAN_CFG80211_FTM_ATTR_DATA]); + buf_len = nla_len(tb[WLAN_CFG80211_FTM_ATTR_DATA]); + + if (buf_len > WLAN_FTM_DATA_MAX_LEN) + return -EINVAL; + + ftm_debug("****FTM Tx cmd len = %d*****", buf_len); + + status = ucfg_wlan_ftm_testmode_cmd(pdev, buf, buf_len); + + if (QDF_IS_STATUS_ERROR(status)) + status = QDF_STATUS_E_BUSY; + + return qdf_status_to_os_return(status); +} + +int +wlan_cfg80211_ftm_testmode_cmd(struct wlan_objmgr_pdev *pdev, + void *data, uint32_t len) +{ + struct nlattr *tb[WLAN_CFG80211_FTM_ATTR_MAX + 1]; + int err = 0, cmd; + struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj; + + ftm_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_FTM); + if (!ftm_pdev_obj) { + ftm_err("Failed to get ftm pdev component"); + return -EINVAL; + } + + ftm_pdev_obj->cmd_type = WIFI_FTM_CMD_NL80211; + + err = nla_parse(tb, WLAN_CFG80211_FTM_ATTR_MAX - 1, data, + len, wlan_cfg80211_ftm_policy); + if (err) { + ftm_err("Testmode INV ATTR"); + return err; + } + + if (!tb[WLAN_CFG80211_FTM_ATTR_CMD]) { + ftm_err("Testmode INV CMD"); + return -EINVAL; + } + cmd = nla_get_u32(tb[WLAN_CFG80211_FTM_ATTR_CMD]); + + switch (cmd) { + case WLAN_CFG80211_FTM_CMD_WLAN_FTM: + err = wlan_cfg80211_process_ftm_cmd(pdev, tb); + break; + + default: + ftm_err("unknown command: %d", cmd); + return -ENOENT; + } + + return err; +} + +qdf_export_symbol(wlan_cfg80211_ftm_testmode_cmd); + +QDF_STATUS +wlan_cfg80211_ftm_rx_event(struct wlan_objmgr_pdev *pdev, + uint8_t *data, uint32_t len) +{ + struct pdev_osif_priv *pdev_ospriv; + qdf_nbuf_t skb = NULL; + + if (!data || !len) { + ftm_err("Null data or invalid length"); + return QDF_STATUS_E_INVAL; + } + + pdev_ospriv = wlan_pdev_get_ospriv(pdev); + if (!pdev_ospriv) { + ftm_err("pdev_ospriv is NULL"); + return QDF_STATUS_E_INVAL; + } + + ftm_debug("Testmode response event generated"); + + skb = cfg80211_testmode_alloc_event_skb(pdev_ospriv->wiphy, + len, GFP_ATOMIC); + + if (!skb) + return QDF_STATUS_E_NOMEM; + + if (nla_put_u32(skb, WLAN_CFG80211_FTM_ATTR_CMD, + WLAN_CFG80211_FTM_CMD_WLAN_FTM) || + nla_put(skb, WLAN_CFG80211_FTM_ATTR_DATA, len, data)) { + goto nla_put_failure; + } + + cfg80211_testmode_event(skb, GFP_ATOMIC); + + return QDF_STATUS_SUCCESS; + +nla_put_failure: + qdf_nbuf_free(skb); + ftm_err("nla_put failed on testmode rx skb!"); + + return QDF_STATUS_E_INVAL; +} diff --git a/os_if/linux/ftm/src/wlan_ioctl_ftm.c b/os_if/linux/ftm/src/wlan_ioctl_ftm.c new file mode 100644 index 000000000000..952b9f7d5065 --- /dev/null +++ b/os_if/linux/ftm/src/wlan_ioctl_ftm.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: implementation of the driver FTM functions interfacing with linux kernel + */ + +#include +#include +#include +#include +#include +#include +#include + +static QDF_STATUS +wlan_process_ftm_ioctl_cmd(struct wlan_objmgr_pdev *pdev, + uint8_t *userdata, uint32_t length) +{ + uint8_t *buffer; + QDF_STATUS error; + + if (get_user(length, (uint32_t *)userdata) != 0) + return QDF_STATUS_E_FAILURE; + + if (length > WLAN_FTM_DATA_MAX_LEN) + return QDF_STATUS_E_FAILURE; + + buffer = qdf_mem_malloc(length); + if (!buffer) + return QDF_STATUS_E_NOMEM; + + if (copy_from_user(buffer, &userdata[sizeof(length)], length)) + error = QDF_STATUS_E_FAILURE; + else + error = ucfg_wlan_ftm_testmode_cmd(pdev, buffer, length); + + qdf_mem_free(buffer); + + return error; +} + +static QDF_STATUS +wlan_process_ftm_ioctl_rsp(struct wlan_objmgr_pdev *pdev, + uint8_t *userdata, uint32_t length) +{ + uint8_t *buffer; + QDF_STATUS error; + + length = WLAN_FTM_DATA_MAX_LEN + sizeof(u_int32_t); + + buffer = qdf_mem_malloc(length); + if (!buffer) + return QDF_STATUS_E_NOMEM; + + error = ucfg_wlan_ftm_testmode_rsp(pdev, buffer); + if (!error) + error = copy_to_user((userdata - sizeof(int)), buffer, length); + else + error = QDF_STATUS_E_AGAIN; + + qdf_mem_free(buffer); + + return error; +} + +int +wlan_ioctl_ftm_testmode_cmd(struct wlan_objmgr_pdev *pdev, int cmd, + uint8_t *userdata, uint32_t length) +{ + QDF_STATUS error; + struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj; + + ftm_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_FTM); + if (!ftm_pdev_obj) { + ftm_err("Failed to get ftm pdev component"); + return QDF_STATUS_E_FAILURE; + } + + ftm_pdev_obj->cmd_type = WIFI_FTM_CMD_IOCTL; + + switch (cmd) { + case FTM_IOCTL_UNIFIED_UTF_CMD: + error = wlan_process_ftm_ioctl_cmd(pdev, + userdata, length); + break; + case FTM_IOCTL_UNIFIED_UTF_RSP: + error = wlan_process_ftm_ioctl_rsp(pdev, + userdata, length); + break; + default: + ftm_err("FTM Unknown cmd - not supported"); + error = QDF_STATUS_E_NOSUPPORT; + } + + return qdf_status_to_os_return(error); +} + +qdf_export_symbol(wlan_ioctl_ftm_testmode_cmd); diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index 9a18c0d321f5..c5a65d686c19 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -325,6 +325,7 @@ typedef void (*qdf_timer_func_t)(void *); * @QDF_MODULE_ID_DIRECT_BUF_RX: Direct Buffer Receive module ID * @QDF_MODULE_ID_DISA: DISA (encryption test) module ID * @QDF_MODULE_ID_GREEN_AP: Green AP related logging + * @QDF_MODULE_ID_FTM: FTM module ID * @QDF_MODULE_ID_ANY: anything * @QDF_MODULE_ID_MAX: Max place holder module ID */ @@ -422,6 +423,7 @@ typedef enum { QDF_MODULE_ID_DIRECT_BUF_RX, QDF_MODULE_ID_DISA, QDF_MODULE_ID_GREEN_AP, + QDF_MODULE_ID_FTM, QDF_MODULE_ID_ANY, QDF_MODULE_ID_MAX, } QDF_MODULE_ID; diff --git a/target_if/core/src/target_if_main.c b/target_if/core/src/target_if_main.c index 92743eaa6a02..1f90f2d914a0 100644 --- a/target_if/core/src/target_if_main.c +++ b/target_if/core/src/target_if_main.c @@ -34,6 +34,7 @@ #endif #include #include +#include #ifdef DFS_COMPONENT_ENABLE #include #endif @@ -301,6 +302,12 @@ static void target_if_target_tx_ops_register( target_is_tgt_type_qca9888; } +static +void target_if_ftm_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ + target_if_ftm_register_tx_ops(tx_ops); +} + static QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { @@ -333,6 +340,8 @@ QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) target_if_green_ap_tx_ops_register(tx_ops); + target_if_ftm_tx_ops_register(tx_ops); + /* Converged UMAC components to register their TX-ops here */ return QDF_STATUS_SUCCESS; } diff --git a/target_if/ftm/inc/target_if_ftm.h b/target_if/ftm/inc/target_if_ftm.h new file mode 100644 index 000000000000..97ca6f5f84a5 --- /dev/null +++ b/target_if/ftm/inc/target_if_ftm.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declare the ftm service data structure and apis + */ +#ifndef _TARGET_IF_FTM_H_ +#define _TARGET_IF_FTM_H_ + +#include +#include +#include + +/** + * target_if_ftm_register_tx_ops() - register ftm tx ops + * @tx_ops: tx ops pointer + * + * Register ftm tx ops + * + * Return: QDF_STATUS + */ +QDF_STATUS target_if_ftm_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); + +/** + * target_if_ftm_attach() - Register FW event handler + * @psoc: psoc pointer + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +target_if_ftm_attach(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_ftm_detach() - De-Register FW event handler + * @psoc: psoc pointer + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +target_if_ftm_detach(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_ftm_cmd_send() - Send WMI command for FTM requests + * @pdev: pdev pointer + * buf: data to be sent to FW + * len: length of the data + * pdev_id: pdev id + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +target_if_ftm_cmd_send(struct wlan_objmgr_pdev *pdev, + uint8_t *buf, uint32_t len, uint8_t pdev_id); +#endif /* _TARGET_IF_FTM_H_ */ diff --git a/target_if/ftm/src/target_if_ftm.c b/target_if/ftm/src/target_if_ftm.c new file mode 100644 index 000000000000..6d02d6d49fa0 --- /dev/null +++ b/target_if/ftm/src/target_if_ftm.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: offload lmac interface APIs definitions for FTM + */ + +#include +#include +#include +#include +#include +#include +#include + +static inline struct wlan_lmac_if_ftm_rx_ops * +target_if_ftm_get_rx_ops(struct wlan_objmgr_psoc *psoc) +{ + return &psoc->soc_cb.rx_ops.ftm_rx_ops; +} + +static int +target_if_ftm_process_utf_event(ol_scn_t sc, uint8_t *event_buf, uint32_t len) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + struct wmi_host_pdev_utf_event event; + struct wlan_lmac_if_ftm_rx_ops *ftm_rx_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + psoc = target_if_get_psoc_from_scn_hdl(sc); + if (!psoc) { + ftm_err("null psoc"); + return QDF_STATUS_E_INVAL; + } + + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FTM_ID); + if (QDF_IS_STATUS_ERROR(status)) { + ftm_err("unable to get psoc reference"); + return QDF_STATUS_E_INVAL; + } + + event.datalen = len; + if (wmi_extract_pdev_utf_event(GET_WMI_HDL_FROM_PSOC(psoc), + event_buf, &event) != QDF_STATUS_SUCCESS) { + ftm_err("Extracting utf event failed"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); + return QDF_STATUS_E_INVAL; + } + + pdev = wlan_objmgr_get_pdev_by_id(psoc, event.pdev_id, WLAN_FTM_ID); + if (!pdev) { + ftm_err("null pdev"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); + return QDF_STATUS_E_INVAL; + } + + ftm_rx_ops = target_if_ftm_get_rx_ops(psoc); + + if (ftm_rx_ops->ftm_ev_handler) { + status = ftm_rx_ops->ftm_ev_handler(pdev, + event.data, event.datalen); + if (QDF_IS_STATUS_ERROR(status)) + status = QDF_STATUS_E_INVAL; + } else { + status = QDF_STATUS_E_INVAL; + } + + wlan_objmgr_pdev_release_ref(pdev, WLAN_FTM_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); + + return status; +} + +QDF_STATUS target_if_ftm_cmd_send(struct wlan_objmgr_pdev *pdev, + uint8_t *buf, uint32_t len, uint8_t pdev_id) +{ + QDF_STATUS ret; + wmi_unified_t handle = GET_WMI_HDL_FROM_PDEV(pdev); + struct pdev_utf_params param; + + param.utf_payload = buf; + param.len = len; + + ret = wmi_unified_pdev_utf_cmd_send(handle, ¶m, pdev_id); + if (ret) { + ftm_err("wmi utf cmd send failed, ret: %d", ret); + return QDF_STATUS_E_FAILURE; + } + + return ret; +} + +QDF_STATUS target_if_ftm_attach(struct wlan_objmgr_psoc *psoc) +{ + QDF_STATUS ret; + wmi_unified_t handle = GET_WMI_HDL_FROM_PSOC(psoc); + + ret = wmi_unified_register_event_handler(handle, wmi_pdev_utf_event_id, + target_if_ftm_process_utf_event, + WMI_RX_UMAC_CTX); + if (ret) { + ftm_err("wmi event registration failed, ret: %d", ret); + return QDF_STATUS_E_FAILURE; + } + + return ret; +} + +QDF_STATUS target_if_ftm_detach(struct wlan_objmgr_psoc *psoc) + +{ + int ret; + wmi_unified_t handle = GET_WMI_HDL_FROM_PSOC(psoc); + + ret = wmi_unified_unregister_event_handler(handle, + wmi_pdev_utf_event_id); + + if (ret) { + ftm_err("wmi event deregistration failed, ret: %d", ret); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_ftm_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops; + + if (!tx_ops) { + ftm_err("invalid tx_ops"); + return QDF_STATUS_E_FAILURE; + } + + ftm_tx_ops = &tx_ops->ftm_tx_ops; + ftm_tx_ops->ftm_attach = target_if_ftm_attach; + ftm_tx_ops->ftm_detach = target_if_ftm_detach; + ftm_tx_ops->ftm_cmd_send = target_if_ftm_cmd_send; + + return QDF_STATUS_SUCCESS; +} diff --git a/umac/cmn_services/inc/wlan_cmn.h b/umac/cmn_services/inc/wlan_cmn.h index 73d487aea2fa..062d9becf39a 100644 --- a/umac/cmn_services/inc/wlan_cmn.h +++ b/umac/cmn_services/inc/wlan_cmn.h @@ -118,11 +118,13 @@ * @WLAN_UMAC_COMP_NAN: Neighbor Aware Networking * @WLAN_UMAC_COMP_DFS: DFS * @WLAN_UMAC_COMP_SPECTRAL: Spectral - * @WLAN_UMAC_COMP_ID_MAX: Maximum components in UMAC * @WLAN_UMAC_COMP_OFFCHAN_TXRX: Offchan TxRx * @WLAN_UMAC_COMP_SPLITMAC: SplitMAC * @WLAN_UMAC_COMP_DISA: DISA encryption test * @WLAN_UMAC_COMP_GREEN_AP: Green AP + * @WLAN_UMAC_COMP_FTM: FTM component + * + * @WLAN_UMAC_COMP_ID_MAX: Maximum components in UMAC * * This id is static. * On Adding new component, new id has to be assigned @@ -151,6 +153,7 @@ enum wlan_umac_comp_id { WLAN_UMAC_COMP_SPLITMAC, WLAN_UMAC_COMP_DISA, WLAN_UMAC_COMP_GREEN_AP, + WLAN_UMAC_COMP_FTM, WLAN_UMAC_COMP_ID_MAX, }; diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h index 1fb88b56a173..3c3da3a89745 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h @@ -203,6 +203,7 @@ typedef void (*wlan_objmgr_peer_status_handler)( * @WLAN_DEBUG_ID: Debug operations * @WLAN_DIRECT_BUF_RX_ID: Direct Buffer Receive operations * @WLAN_DISA_ID: DISA (encryption test) operations + * @WLAN_FTM_ID: FTM module * @WLAN_REF_ID_MAX: Max id used to generate ref count tracking array */ /* New value added to the enum must also be reflected in function @@ -241,6 +242,7 @@ typedef enum { WLAN_DEBUG_ID = 29, WLAN_DIRECT_BUF_RX_ID = 30, WLAN_DISA_ID = 31, + WLAN_FTM_ID = 31, WLAN_REF_ID_MAX, } wlan_objmgr_ref_dbgid; @@ -286,6 +288,7 @@ static inline char *string_from_dbgid(wlan_objmgr_ref_dbgid id) "WLAN_DEBUG_ID", "WLAN_DIRECT_BUF_RX_ID", "WLAN_DISA_ID", + "WLAN_FTM_ID", "WLAN_REF_ID_MAX" }; return (char *)strings[id]; diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index f5d930501658..98ca15862bf4 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -112,6 +112,21 @@ struct wlan_lmac_if_scan_tx_ops { QDF_STATUS (*set_chan_list)(struct wlan_objmgr_pdev *pdev, void *arg); }; +/** + * struct wlan_lmac_if_ftm_tx_ops - south bound tx function pointers for ftm + * @ftm_attach: function to register event handlers with FW + * @ftm_detach: function to de-register event handlers with FW + * @ftm_cmd_send: function to send FTM commands to FW + * + * ftm module uses these functions to avail ol/da lmac services + */ +struct wlan_lmac_if_ftm_tx_ops { + QDF_STATUS (*ftm_attach)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*ftm_detach)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*ftm_cmd_send)(struct wlan_objmgr_pdev *pdev, + uint8_t *buf, uint32_t len, uint8_t mac_id); +}; + struct wlan_lmac_if_mlme_tx_ops { void (*scan_sta_power_events)(struct wlan_objmgr_pdev *pdev, @@ -419,6 +434,17 @@ struct wlan_lmac_if_nan_tx_ops { }; #endif +/** + * struct wlan_lmac_if_ftm_rx_ops - south bound rx function pointers for FTM + * @ftm_ev_handler: function to handle FTM event + * + * lmac modules uses this API to post FTM events to FTM module + */ +struct wlan_lmac_if_ftm_rx_ops { + QDF_STATUS (*ftm_ev_handler)(struct wlan_objmgr_pdev *pdev, + uint8_t *event_buf, uint32_t len); +}; + /** * struct wlan_lmac_reg_if_tx_ops - structure of tx function * pointers for regulatory component @@ -614,15 +640,20 @@ struct wlan_lmac_if_tx_ops { #endif struct wlan_lmac_if_mlme_tx_ops mops; struct wlan_lmac_if_target_tx_ops target_tx_ops; + #ifdef WLAN_OFFCHAN_TXRX_ENABLE struct wlan_lmac_if_offchan_txrx_ops offchan_txrx_ops; #endif + #ifdef DIRECT_BUF_RX_ENABLE struct wlan_lmac_if_direct_buf_rx_tx_ops dbr_tx_ops; #endif + #ifdef WLAN_SUPPORT_GREEN_AP struct wlan_lmac_if_green_ap_tx_ops green_ap_tx_ops; #endif + + struct wlan_lmac_if_ftm_tx_ops ftm_tx_ops; }; /** @@ -1066,9 +1097,12 @@ struct wlan_lmac_if_rx_ops { struct wlan_lmac_if_tdls_rx_ops tdls_rx_ops; #endif struct wlan_lmac_if_mlme_rx_ops mops; + #ifdef WLAN_SUPPORT_GREEN_AP struct wlan_lmac_if_green_ap_rx_ops green_ap_rx_ops; #endif + + struct wlan_lmac_if_ftm_rx_ops ftm_rx_ops; }; /* Function pointer to call legacy tx_ops registration in OL/WMA. diff --git a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c index 01bad7990717..b2670b8acc40 100644 --- a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c +++ b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c @@ -51,10 +51,12 @@ #include #include #endif + #ifdef WLAN_SUPPORT_GREEN_AP #include #include #endif +#include /* Function pointer for OL/WMA specific UMAC tx_ops * registration. @@ -324,6 +326,18 @@ wlan_lmac_if_umac_green_ap_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) } #endif +static QDF_STATUS +wlan_lmac_if_umac_ftm_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) +{ + struct wlan_lmac_if_ftm_rx_ops *ftm_rx_ops; + + ftm_rx_ops = &rx_ops->ftm_rx_ops; + + ftm_rx_ops->ftm_ev_handler = wlan_ftm_process_utf_event; + + return QDF_STATUS_SUCCESS; +} + /** * wlan_lmac_if_umac_rx_ops_register() - UMAC rx handler register * @rx_ops: Pointer to rx_ops structure to be populated @@ -389,6 +403,9 @@ wlan_lmac_if_umac_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) wlan_lmac_if_umac_green_ap_rx_ops_register(rx_ops); + /* FTM rx_ops */ + wlan_lmac_if_umac_ftm_rx_ops_register(rx_ops); + return QDF_STATUS_SUCCESS; }