1 /*
2  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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 /*
21  * This file lim_scan_result_utils.cc contains the utility functions
22  * LIM uses for maintaining and accessing scan results on STA.
23  * Author:        Chandra Modumudi
24  * Date:          02/13/02
25  * History:-
26  * Date           Modified by    Modification Information
27  * --------------------------------------------------------------------
28  */
29 
30 #include "lim_types.h"
31 #include "lim_utils.h"
32 #include "lim_ser_des_utils.h"
33 #include "lim_api.h"
34 #include "lim_ft_defs.h"
35 #include "lim_session.h"
36 #include "rrm_api.h"
37 #include "cds_utils.h"
38 
39 /**
40  * lim_collect_bss_description()
41  *
42  ***FUNCTION:
43  * This function is called during scan upon receiving
44  * Beacon/Probe Response frame to check if the received
45  * frame matches scan criteria, collect BSS description
46  * and add it to cached scan results.
47  *
48  ***LOGIC:
49  *
50  ***ASSUMPTIONS:
51  * NA
52  *
53  ***NOTE:
54  * NA
55  *
56  * @param  mac - Pointer to Global MAC structure
57  * @param  pBPR - Pointer to parsed Beacon/Probe Response structure
58  * @param  pRxPacketInfo  - Pointer to Received frame's BD
59  * @param  fScanning - flag to indicate if it is during scan.
60  * ---------------------------------------------
61  *
62  * @return None
63  */
64 void
lim_collect_bss_description(struct mac_context * mac,struct bss_description * pBssDescr,tpSirProbeRespBeacon pBPR,uint8_t * pRxPacketInfo,uint8_t fScanning)65 lim_collect_bss_description(struct mac_context *mac,
66 			    struct bss_description *pBssDescr,
67 			    tpSirProbeRespBeacon pBPR,
68 			    uint8_t *pRxPacketInfo, uint8_t fScanning)
69 {
70 	uint8_t *pBody;
71 	uint32_t ieLen = 0;
72 	tpSirMacMgmtHdr pHdr;
73 	uint32_t chan_freq;
74 	uint8_t rfBand = 0;
75 
76 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
77 
78 	if (SIR_MAC_B_PR_SSID_OFFSET > WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo)) {
79 		QDF_ASSERT(WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) >=
80 			   SIR_MAC_B_PR_SSID_OFFSET);
81 		return;
82 	}
83 	ieLen =
84 		WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) - SIR_MAC_B_PR_SSID_OFFSET;
85 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
86 	rfBand = WMA_GET_RX_RFBAND(pRxPacketInfo);
87 
88 	/**
89 	 * Length of BSS description is without length of
90 	 * length itself and length of pointer that holds ieFields.
91 	 *
92 	 * struct bss_description
93 	 * +--------+---------------------------------+---------------+
94 	 * | length | other fields                    | pointer to IEs|
95 	 * +--------+---------------------------------+---------------+
96 	 *                                            ^
97 	 *                                            ieFields
98 	 */
99 	pBssDescr->length =
100 		(uint16_t)(offsetof(struct bss_description, ieFields[0]) -
101 			   sizeof(pBssDescr->length) + ieLen);
102 
103 	/* Copy BSS Id */
104 	qdf_mem_copy((uint8_t *) &pBssDescr->bssId,
105 		     (uint8_t *) pHdr->bssId, sizeof(tSirMacAddr));
106 
107 	/* Copy Timestamp, Beacon Interval and Capability Info */
108 	pBssDescr->scansystimensec = qdf_get_bootbased_boottime_ns();
109 
110 	pBssDescr->timeStamp[0] = pBPR->timeStamp[0];
111 	pBssDescr->timeStamp[1] = pBPR->timeStamp[1];
112 	pBssDescr->beaconInterval = pBPR->beaconInterval;
113 	pBssDescr->capabilityInfo =
114 		lim_get_u16((uint8_t *) &pBPR->capabilityInfo);
115 
116 	if (!pBssDescr->beaconInterval) {
117 		pe_warn("Beacon Interval is ZERO, making it to default 100 "
118 			   QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(pHdr->bssId));
119 		pBssDescr->beaconInterval = 100;
120 	}
121 	/*
122 	 * There is a narrow window after Channel Switch msg is sent to HAL and before the AGC is shut
123 	 * down and beacons/Probe Rsps can trickle in and we may report the incorrect channel in 5Ghz
124 	 * band, so not relying on the 'last Scanned Channel' stored in LIM.
125 	 * Instead use the value returned by RXP in BD. This the the same value which HAL programs into
126 	 * RXP before every channel switch.
127 	 * Right now there is a problem in 5Ghz, where we are receiving beacons from a channel different from
128 	 * the currently scanned channel. so incorrect channel is reported to CSR and association does not happen.
129 	 * So for now we keep on looking for the channel info in the beacon (DSParamSet IE OR HT Info IE), and only if it
130 	 * is not present in the beacon, we go for the channel info present in RXP.
131 	 * This fix will work for 5Ghz 11n devices, but for 11a devices, we have to rely on RXP routing flag to get the correct channel.
132 	 * So The problem of incorrect channel reporting in 5Ghz will still remain for 11a devices.
133 	 */
134 	chan_freq = lim_get_channel_from_beacon(mac, pBPR);
135 	pBssDescr->chan_freq = chan_freq;
136 
137 	/* set the network type in bss description */
138 	pBssDescr->nwType =
139 		lim_get_nw_type(mac, chan_freq, SIR_MAC_MGMT_FRAME, pBPR);
140 
141 	/* Copy RSSI & SINR from BD */
142 	pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo);
143 	pBssDescr->rssi_raw = (int8_t) WMA_GET_RX_RSSI_RAW(pRxPacketInfo);
144 
145 	/* SINR no longer reported by HW */
146 	pBssDescr->sinr = 0;
147 	pe_debug(QDF_MAC_ADDR_FMT " rssi: normalized: %d, absolute: %d",
148 		QDF_MAC_ADDR_REF(pHdr->bssId), pBssDescr->rssi,
149 		pBssDescr->rssi_raw);
150 
151 	pBssDescr->received_time = (uint64_t)qdf_mc_timer_get_system_time();
152 	pBssDescr->tsf_delta = WMA_GET_RX_TSF_DELTA(pRxPacketInfo);
153 	pBssDescr->seq_ctrl = pHdr->seqControl;
154 
155 	pe_debug("Received %s from BSSID: " QDF_MAC_ADDR_FMT " tsf_delta = %u Seq Num: %x ssid:" QDF_SSID_FMT ", rssi: %d",
156 		 pBssDescr->fProbeRsp ? "Probe Rsp" : "Beacon",
157 		 QDF_MAC_ADDR_REF(pHdr->bssId),
158 		 pBssDescr->tsf_delta, ((pHdr->seqControl.seqNumHi <<
159 		 HIGH_SEQ_NUM_OFFSET) | pHdr->seqControl.seqNumLo),
160 		 QDF_SSID_REF(pBPR->ssId.length, pBPR->ssId.ssId),
161 		 pBssDescr->rssi_raw);
162 
163 	if (fScanning) {
164 		rrm_get_start_tsf(mac, pBssDescr->startTSF);
165 		pBssDescr->parentTSF = WMA_GET_RX_TIMESTAMP(pRxPacketInfo);
166 	}
167 
168 	/* MobilityDomain */
169 	pBssDescr->mdie[0] = 0;
170 	pBssDescr->mdie[1] = 0;
171 	pBssDescr->mdie[2] = 0;
172 	pBssDescr->mdiePresent = false;
173 	/* If mdie is present in the probe resp we */
174 	/* fill it in the bss description */
175 	if (pBPR->mdiePresent) {
176 		pBssDescr->mdiePresent = true;
177 		pBssDescr->mdie[0] = pBPR->mdie[0];
178 		pBssDescr->mdie[1] = pBPR->mdie[1];
179 		pBssDescr->mdie[2] = pBPR->mdie[2];
180 	}
181 
182 #ifdef FEATURE_WLAN_ESE
183 	pBssDescr->QBSSLoad_present = false;
184 	pBssDescr->QBSSLoad_avail = 0;
185 	if (pBPR->QBSSLoad.present) {
186 		pBssDescr->QBSSLoad_present = true;
187 		pBssDescr->QBSSLoad_avail = pBPR->QBSSLoad.avail;
188 	}
189 #endif
190 	/* Copy IE fields */
191 	qdf_mem_copy((uint8_t *) &pBssDescr->ieFields,
192 		     pBody + SIR_MAC_B_PR_SSID_OFFSET, ieLen);
193 
194 	/*set channel number in beacon in case it is not present */
195 	pBPR->chan_freq = chan_freq;
196 	mac->lim.beacon_probe_rsp_cnt_per_scan++;
197 
198 	return;
199 } /*** end lim_collect_bss_description() ***/
200