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 */ 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 */ 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 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