1 /*
2  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <osdep.h>
21 #include <wmi.h>
22 #include <wmi_unified_priv.h>
23 #include <wmi_unified_interop_issues_ap_api.h>
24 
25 /**
26  * extract_interop_issues_ap_ev_param_tlv() - extract info from event
27  * @wmi_handle: wmi handle
28  * @evt_buf: pointer to event buffer
29  * @data: Pointer to hold interop issues ap info
30  *
31  * Return: QDF_STATUS_SUCCESS for success or error code
32  */
33 static QDF_STATUS
extract_interop_issues_ap_ev_param_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct wlan_interop_issues_ap_event * data)34 extract_interop_issues_ap_ev_param_tlv(wmi_unified_t wmi_handle, void *evt_buf,
35 				     struct wlan_interop_issues_ap_event *data)
36 {
37 	wmi_pdev_rap_info_event_fixed_param *fixed_param;
38 	WMI_PDEV_RAP_INFO_EVENTID_param_tlvs *param_buf =
39 		(WMI_PDEV_RAP_INFO_EVENTID_param_tlvs *)evt_buf;
40 
41 	if (!param_buf) {
42 		wmi_err_rl("Invalid param_buf");
43 		return -EINVAL;
44 	}
45 
46 	fixed_param = param_buf->fixed_param;
47 	if (!fixed_param) {
48 		wmi_err_rl("Invalid fixed_praram");
49 		return -EINVAL;
50 	}
51 
52 	if (fixed_param->type != WMI_ROGUE_AP_ON_STA_PS) {
53 		wmi_err_rl("Invalid type");
54 		return -EINVAL;
55 	}
56 
57 	data->pdev_id = fixed_param->pdev_id;
58 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->bssid, data->rap_addr.bytes);
59 
60 	return QDF_STATUS_SUCCESS;
61 }
62 
63 /**
64  * send_set_rap_ps_cmd_tlv() - set interop issues ap mac address in fw
65  * @wmi_handle: wmi handle
66  * @rap: interop issues ap info
67  *
68  * Return: QDF_STATUS_SUCCESS for success or error code
69  */
70 static QDF_STATUS
send_set_rap_ps_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_interop_issues_ap_info * rap)71 send_set_rap_ps_cmd_tlv(wmi_unified_t wmi_handle,
72 			struct wlan_interop_issues_ap_info *rap)
73 {
74 	wmi_pdev_set_rap_config_fixed_param *cmd;
75 	wmi_pdev_set_rap_config_on_sta_ps_tlv_param *param;
76 	uint8_t *buf_ptr;
77 	wmi_buf_t buf;
78 	uint32_t ret;
79 	uint32_t len, count;
80 	qdf_size_t i;
81 
82 	count = rap->count;
83 	len  = sizeof(*cmd) + WMI_TLV_HDR_SIZE + sizeof(*param) * count;
84 	buf = wmi_buf_alloc(wmi_handle, len);
85 	if (!buf)
86 		return QDF_STATUS_E_FAILURE;
87 
88 	buf_ptr = wmi_buf_data(buf);
89 	cmd = (wmi_pdev_set_rap_config_fixed_param *)buf_ptr;
90 
91 	WMITLV_SET_HDR(&cmd->tlv_header,
92 		       WMITLV_TAG_STRUC_wmi_pdev_set_rap_config_fixed_param,
93 		       WMITLV_GET_STRUCT_TLVLEN
94 			       (wmi_pdev_set_rap_config_fixed_param));
95 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
96 						     wmi_handle,
97 						     WMI_HOST_PDEV_ID_SOC);
98 
99 	cmd->type = WMI_ROGUE_AP_ON_STA_PS;
100 	if (rap->detect_enable)
101 		cmd->sta_ps_detection_enabled = 1;
102 	else
103 		cmd->sta_ps_detection_enabled = 0;
104 
105 	buf_ptr += sizeof(*cmd);
106 
107 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
108 		  sizeof(wmi_pdev_set_rap_config_on_sta_ps_tlv_param) * count);
109 	buf_ptr += WMI_TLV_HDR_SIZE;
110 
111 	for (i = 0; i < count; i++) {
112 		param = (wmi_pdev_set_rap_config_on_sta_ps_tlv_param *)buf_ptr;
113 		WMITLV_SET_HDR(&param->tlv_header,
114 		  WMITLV_TAG_STRUC_wmi_pdev_set_rap_config_on_sta_ps_tlv_param,
115 		  WMITLV_GET_STRUCT_TLVLEN
116 				(wmi_pdev_set_rap_config_on_sta_ps_tlv_param));
117 		WMI_CHAR_ARRAY_TO_MAC_ADDR(rap->rap_items[i].bytes,
118 					   &param->bssid);
119 		buf_ptr += sizeof(*param);
120 	}
121 
122 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
123 				   WMI_PDEV_SET_RAP_CONFIG_CMDID);
124 	if (ret) {
125 		wmi_buf_free(buf);
126 		return QDF_STATUS_E_FAILURE;
127 	}
128 
129 	return QDF_STATUS_SUCCESS;
130 }
131 
wmi_interop_issues_ap_attach_tlv(wmi_unified_t wmi_handle)132 void wmi_interop_issues_ap_attach_tlv(wmi_unified_t wmi_handle)
133 {
134 	struct wmi_ops *ops = wmi_handle->ops;
135 
136 	ops->extract_interop_issues_ap_ev_param =
137 					extract_interop_issues_ap_ev_param_tlv;
138 	ops->send_set_rap_ps_cmd = send_set_rap_ps_cmd_tlv;
139 }
140