1 /*
2 * Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2002-2010, Atheros Communications Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: ETSI 1.5.1 introduced new waveforms which use staggered PRIs within
20 * the same waveform. This file contains the detection implementation for
21 * these specific types of radars. This logic is different from the other
22 * detection because it must detect waveforms that may have 2 or more
23 * different PRIs (pulse repetition intervals).
24 */
25
26 #include "../dfs.h"
27 #include "../dfs_process_radar_found_ind.h"
28
29 /**
30 * dfs_is_pri_multiple() - Is PRI is multiple.
31 * @sample_pri: Sample PRI.
32 * @refpri: Reference PRI.
33 */
dfs_is_pri_multiple(uint32_t sample_pri,uint32_t refpri)34 static int dfs_is_pri_multiple(uint32_t sample_pri, uint32_t refpri)
35 {
36 #define MAX_ALLOWED_MISSED 3
37 int i;
38
39 if (sample_pri < refpri || (!refpri))
40 return 0;
41
42 for (i = 1; i <= MAX_ALLOWED_MISSED; i++) {
43 if ((sample_pri%(i*refpri) <= 5))
44 return 1;
45 }
46
47 return 0;
48 #undef MAX_ALLOWED_MISSED
49 }
50
51 /**
52 * dfs_is_unique_pri() - Check for the unique PRI.
53 * @highestpri: Highest PRI.
54 * @midpri: MID PRI.
55 * @lowestpri: Lowest PRI.
56 * @refpri: Reference PRI.
57 */
dfs_is_unique_pri(uint32_t highestpri,uint32_t midpri,uint32_t lowestpri,uint32_t refpri)58 static int dfs_is_unique_pri(uint32_t highestpri, uint32_t midpri,
59 uint32_t lowestpri, uint32_t refpri)
60 {
61 #define DFS_STAGGERED_PRI_MARGIN_MIN 20
62 #define DFS_STAGGERED_PRI_MARGIN_MAX 400
63 if ((DFS_DIFF(lowestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
64 (DFS_DIFF(midpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
65 (DFS_DIFF(highestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN)
66 )
67 return 1;
68
69 if ((dfs_is_pri_multiple(refpri, highestpri)) ||
70 (dfs_is_pri_multiple(refpri, lowestpri)) ||
71 (dfs_is_pri_multiple(refpri, midpri)))
72 return 0;
73 #undef DFS_STAGGERED_PRI_MARGIN_MIN
74 #undef DFS_STAGGERED_PRI_MARGIN_MAX
75
76 return 0;
77 }
78
dfs_staggered_check(struct wlan_dfs * dfs,struct dfs_filter * rf,uint32_t deltaT,uint32_t width)79 int dfs_staggered_check(struct wlan_dfs *dfs, struct dfs_filter *rf,
80 uint32_t deltaT, uint32_t width)
81 {
82 uint32_t refpri, refdur, searchpri = 0, deltapri;
83 uint32_t n, i, primargin, durmargin;
84 int score[DFS_MAX_DL_SIZE], delayindex, dindex, found = 0;
85 struct dfs_delayline *dl;
86 uint32_t scoreindex, lowpriindex = 0, lowpri = 0xffff;
87 int higherthan, lowerthan, numscores;
88 int numpulseshigh = 0, numpulsesmid = 0, numpulsestemp = 0;
89 uint32_t lowestscore = 0, lowestscoreindex = 0, lowestpri = 0;
90 uint32_t midscore = 0, midscoreindex = 0, midpri = 0;
91 uint32_t highestscore = 0, highestscoreindex = 0, highestpri = 0;
92
93 dl = &rf->rf_dl;
94 if (dl->dl_numelems < (rf->rf_threshold-1)) {
95 dfs_debug(dfs, WLAN_DEBUG_DFS2,
96 "numelems %d < threshold for filter %d",
97 dl->dl_numelems,
98 rf->rf_pulseid);
99 return 0;
100 }
101 if (deltaT > rf->rf_filterlen) {
102 dfs_debug(dfs, WLAN_DEBUG_DFS2,
103 "numelems %d < threshold for filter %d",
104 dl->dl_numelems,
105 rf->rf_pulseid);
106 return 0;
107 }
108 primargin = 6;
109 if (rf->rf_maxdur < 10)
110 durmargin = 4;
111 else
112 durmargin = 6;
113
114 qdf_mem_zero(score, sizeof(int)*DFS_MAX_DL_SIZE);
115 /* Find out the lowest pri */
116 for (n = 0; n < dl->dl_numelems; n++) {
117 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
118 refpri = dl->dl_elems[delayindex].de_time;
119 if (refpri == 0) {
120 continue;
121 } else if (refpri < lowpri) {
122 lowpri = dl->dl_elems[delayindex].de_time;
123 lowpriindex = n;
124 }
125 }
126
127 /* Find out the each delay element's pri score */
128 for (n = 0; n < dl->dl_numelems; n++) {
129 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
130 refpri = dl->dl_elems[delayindex].de_time;
131 if (refpri == 0)
132 continue;
133
134 if ((refpri > rf->rf_maxpri) || (refpri < rf->rf_minpri)) {
135 score[n] = 0;
136 continue;
137 }
138
139 for (i = 0; i < dl->dl_numelems; i++) {
140 dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
141 searchpri = dl->dl_elems[dindex].de_time;
142 deltapri = DFS_DIFF(searchpri, refpri);
143 if (deltapri < primargin)
144 score[n]++;
145 }
146 }
147
148 dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET(
149 (dl->dl_min_sidx + dl->dl_max_sidx) / 2);
150
151 for (n = 0; n < dl->dl_numelems; n++) {
152 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
153 refdur = dl->dl_elems[delayindex].de_time;
154 dfs_debug(dfs, WLAN_DEBUG_DFS2,
155 "score[%d]=%d pri=%d",
156 n, score[n], refdur);
157 }
158
159 /* Find out the 2 or 3 highest scorers */
160 scoreindex = 0;
161 highestscore = 0;
162 highestscoreindex = 0;
163 highestpri = 0; numscores = 0; lowestscore = 0;
164
165 for (n = 0; n < dl->dl_numelems; n++) {
166 higherthan = 0;
167 lowerthan = 0;
168 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
169 refpri = dl->dl_elems[delayindex].de_time;
170
171 if (!dfs_is_unique_pri(highestpri,
172 midpri,
173 lowestpri,
174 refpri))
175 continue;
176
177 if (score[n] >= highestscore) {
178 lowestscore = midscore;
179 lowestpri = midpri;
180 lowestscoreindex = midscoreindex;
181 midscore = highestscore;
182 midpri = highestpri;
183 midscoreindex = highestscoreindex;
184 highestscore = score[n];
185 highestpri = refpri;
186 highestscoreindex = n;
187 } else if (score[n] >= midscore) {
188 lowestscore = midscore;
189 lowestpri = midpri;
190 lowestscoreindex = midscoreindex;
191 midscore = score[n];
192 midpri = refpri;
193 midscoreindex = n;
194 } else if (score[n] >= lowestscore) {
195 lowestscore = score[n];
196 lowestpri = refpri;
197 lowestscoreindex = n;
198 }
199 }
200
201 if (midscore == 0)
202 return 0;
203
204 dfs_debug(dfs, WLAN_DEBUG_DFS1,
205 "FINAL highestscore=%d highestscoreindex = %d highestpri = %d",
206 highestscore, highestscoreindex, highestpri);
207
208 dfs_debug(dfs, WLAN_DEBUG_DFS1,
209 "FINAL lowestscore=%d lowestscoreindex=%d lowpri=%d",
210 lowestscore, lowestscoreindex, lowestpri);
211
212 dfs_debug(dfs, WLAN_DEBUG_DFS1,
213 "FINAL midscore=%d midscoreindex=%d midpri=%d",
214 midscore, midscoreindex, midpri);
215
216 delayindex = (dl->dl_firstelem + highestscoreindex) & DFS_MAX_DL_MASK;
217 refdur = dl->dl_elems[delayindex].de_dur;
218 refpri = dl->dl_elems[delayindex].de_time;
219
220 dfs_debug(dfs, WLAN_DEBUG_DFS1,
221 "highscoreindex=%d refdur=%d refpri=%d",
222 highestscoreindex, refdur, refpri);
223
224 numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri,
225 refdur, 0, highestpri);
226 numpulseshigh = numpulsestemp;
227 numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri,
228 refdur, 0, highestpri + midpri);
229 if (numpulsestemp > numpulseshigh)
230 numpulseshigh = numpulsestemp;
231
232 numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri,
233 refdur, 0, highestpri + midpri + lowestpri);
234 if (numpulsestemp > numpulseshigh)
235 numpulseshigh = numpulsestemp;
236
237 delayindex = (dl->dl_firstelem + midscoreindex) & DFS_MAX_DL_MASK;
238 refdur = dl->dl_elems[delayindex].de_dur;
239 refpri = dl->dl_elems[delayindex].de_time;
240 dfs_debug(dfs, WLAN_DEBUG_DFS1,
241 "midscoreindex=%d refdur=%d refpri=%d",
242 midscoreindex, refdur, refpri);
243
244 numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,
245 0, midpri);
246 numpulsesmid = numpulsestemp;
247 numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,
248 0, highestpri + midpri);
249 if (numpulsestemp > numpulsesmid)
250 numpulsesmid = numpulsestemp;
251 numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,
252 0, highestpri + midpri + lowestpri);
253 if (numpulsestemp > numpulsesmid)
254 numpulsesmid = numpulsestemp;
255
256 dfs_debug(dfs, WLAN_DEBUG_DFS2,
257 "numpulseshigh=%d, numpulsesmid=%d",
258 numpulseshigh, numpulsesmid);
259
260 if ((numpulseshigh >= rf->rf_threshold) &&
261 (numpulsesmid >= rf->rf_threshold)) {
262 found = 1;
263 dfs_debug(dfs, WLAN_DEBUG_DFS2,
264 "MATCH filter=%u numpulseshigh=%u numpulsesmid= %u thresh=%u",
265 rf->rf_pulseid, numpulseshigh,
266 numpulsesmid, rf->rf_threshold);
267 }
268
269 return found;
270 }
271