dfs_pri_detector.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * Copyright (c) 2012 Neratec Solutions AG
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/slab.h>
  17. #include "dfs_pattern_detector.h"
  18. #include "dfs_pri_detector.h"
  19. /**
  20. * struct pri_sequence - sequence of pulses matching one PRI
  21. * @head: list_head
  22. * @pri: pulse repetition interval (PRI) in usecs
  23. * @dur: duration of sequence in usecs
  24. * @count: number of pulses in this sequence
  25. * @count_falses: number of not matching pulses in this sequence
  26. * @first_ts: time stamp of first pulse in usecs
  27. * @last_ts: time stamp of last pulse in usecs
  28. * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
  29. */
  30. struct pri_sequence {
  31. struct list_head head;
  32. u32 pri;
  33. u32 dur;
  34. u32 count;
  35. u32 count_falses;
  36. u64 first_ts;
  37. u64 last_ts;
  38. u64 deadline_ts;
  39. };
  40. /**
  41. * struct pulse_elem - elements in pulse queue
  42. * @ts: time stamp in usecs
  43. */
  44. struct pulse_elem {
  45. struct list_head head;
  46. u64 ts;
  47. };
  48. /**
  49. * pde_get_multiple() - get number of multiples considering a given tolerance
  50. * @return factor if abs(val - factor*fraction) <= tolerance, 0 otherwise
  51. */
  52. static u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance)
  53. {
  54. u32 remainder;
  55. u32 factor;
  56. u32 delta;
  57. if (fraction == 0)
  58. return 0;
  59. delta = (val < fraction) ? (fraction - val) : (val - fraction);
  60. if (delta <= tolerance)
  61. /* val and fraction are within tolerance */
  62. return 1;
  63. factor = val / fraction;
  64. remainder = val % fraction;
  65. if (remainder > tolerance) {
  66. /* no exact match */
  67. if ((fraction - remainder) <= tolerance)
  68. /* remainder is within tolerance */
  69. factor++;
  70. else
  71. factor = 0;
  72. }
  73. return factor;
  74. }
  75. /**
  76. * DOC: Singleton Pulse and Sequence Pools
  77. *
  78. * Instances of pri_sequence and pulse_elem are kept in singleton pools to
  79. * reduce the number of dynamic allocations. They are shared between all
  80. * instances and grow up to the peak number of simultaneously used objects.
  81. *
  82. * Memory is freed after all references to the pools are released.
  83. */
  84. static u32 singleton_pool_references;
  85. static LIST_HEAD(pulse_pool);
  86. static LIST_HEAD(pseq_pool);
  87. static struct pulse_elem *pulse_queue_get_tail(struct pri_detector *pde)
  88. {
  89. struct list_head *l = &pde->pulses;
  90. if (list_empty(l))
  91. return NULL;
  92. return list_entry(l->prev, struct pulse_elem, head);
  93. }
  94. static bool pulse_queue_dequeue(struct pri_detector *pde)
  95. {
  96. struct pulse_elem *p = pulse_queue_get_tail(pde);
  97. if (p != NULL) {
  98. list_del_init(&p->head);
  99. pde->count--;
  100. /* give it back to pool */
  101. list_add(&p->head, &pulse_pool);
  102. }
  103. return (pde->count > 0);
  104. }
  105. /* remove pulses older than window */
  106. static void pulse_queue_check_window(struct pri_detector *pde)
  107. {
  108. u64 min_valid_ts;
  109. struct pulse_elem *p;
  110. /* there is no delta time with less than 2 pulses */
  111. if (pde->count < 2)
  112. return;
  113. if (pde->last_ts <= pde->window_size)
  114. return;
  115. min_valid_ts = pde->last_ts - pde->window_size;
  116. while ((p = pulse_queue_get_tail(pde)) != NULL) {
  117. if (p->ts >= min_valid_ts)
  118. return;
  119. pulse_queue_dequeue(pde);
  120. }
  121. }
  122. static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts)
  123. {
  124. struct pulse_elem *p;
  125. if (!list_empty(&pulse_pool)) {
  126. p = list_first_entry(&pulse_pool, struct pulse_elem, head);
  127. list_del(&p->head);
  128. } else {
  129. p = kmalloc(sizeof(*p), GFP_KERNEL);
  130. if (p == NULL) {
  131. pr_err("failed to allocate pulse_elem\n");
  132. return false;
  133. }
  134. }
  135. INIT_LIST_HEAD(&p->head);
  136. p->ts = ts;
  137. list_add(&p->head, &pde->pulses);
  138. pde->count++;
  139. pde->last_ts = ts;
  140. pulse_queue_check_window(pde);
  141. if (pde->count >= pde->max_count)
  142. pulse_queue_dequeue(pde);
  143. return true;
  144. }
  145. static bool pseq_handler_create_sequences(struct pri_detector *pde,
  146. u64 ts, u32 min_count)
  147. {
  148. struct pulse_elem *p;
  149. list_for_each_entry(p, &pde->pulses, head) {
  150. struct pri_sequence ps, *new_ps;
  151. struct pulse_elem *p2;
  152. u32 tmp_false_count;
  153. u64 min_valid_ts;
  154. u32 delta_ts = ts - p->ts;
  155. if (delta_ts < pde->rs->pri_min)
  156. /* ignore too small pri */
  157. continue;
  158. if (delta_ts > pde->rs->pri_max)
  159. /* stop on too large pri (sorted list) */
  160. break;
  161. /* build a new sequence with new potential pri */
  162. ps.count = 2;
  163. ps.count_falses = 0;
  164. ps.first_ts = p->ts;
  165. ps.last_ts = ts;
  166. ps.pri = ts - p->ts;
  167. ps.dur = ps.pri * (pde->rs->ppb - 1)
  168. + 2 * pde->rs->max_pri_tolerance;
  169. p2 = p;
  170. tmp_false_count = 0;
  171. min_valid_ts = ts - ps.dur;
  172. /* check which past pulses are candidates for new sequence */
  173. list_for_each_entry_continue(p2, &pde->pulses, head) {
  174. u32 factor;
  175. if (p2->ts < min_valid_ts)
  176. /* stop on crossing window border */
  177. break;
  178. /* check if pulse match (multi)PRI */
  179. factor = pde_get_multiple(ps.last_ts - p2->ts, ps.pri,
  180. pde->rs->max_pri_tolerance);
  181. if (factor > 0) {
  182. ps.count++;
  183. ps.first_ts = p2->ts;
  184. /*
  185. * on match, add the intermediate falses
  186. * and reset counter
  187. */
  188. ps.count_falses += tmp_false_count;
  189. tmp_false_count = 0;
  190. } else {
  191. /* this is a potential false one */
  192. tmp_false_count++;
  193. }
  194. }
  195. if (ps.count < min_count)
  196. /* did not reach minimum count, drop sequence */
  197. continue;
  198. /* this is a valid one, add it */
  199. ps.deadline_ts = ps.first_ts + ps.dur;
  200. if (!list_empty(&pseq_pool)) {
  201. new_ps = list_first_entry(&pseq_pool,
  202. struct pri_sequence, head);
  203. list_del(&new_ps->head);
  204. } else {
  205. new_ps = kmalloc(sizeof(*new_ps), GFP_KERNEL);
  206. if (new_ps == NULL)
  207. return false;
  208. }
  209. memcpy(new_ps, &ps, sizeof(ps));
  210. INIT_LIST_HEAD(&new_ps->head);
  211. list_add(&new_ps->head, &pde->sequences);
  212. }
  213. return true;
  214. }
  215. /* check new ts and add to all matching existing sequences */
  216. static u32
  217. pseq_handler_add_to_existing_seqs(struct pri_detector *pde, u64 ts)
  218. {
  219. u32 max_count = 0;
  220. struct pri_sequence *ps, *ps2;
  221. list_for_each_entry_safe(ps, ps2, &pde->sequences, head) {
  222. u32 delta_ts;
  223. u32 factor;
  224. /* first ensure that sequence is within window */
  225. if (ts > ps->deadline_ts) {
  226. list_del_init(&ps->head);
  227. list_add(&ps->head, &pseq_pool);
  228. continue;
  229. }
  230. delta_ts = ts - ps->last_ts;
  231. factor = pde_get_multiple(delta_ts, ps->pri,
  232. pde->rs->max_pri_tolerance);
  233. if (factor > 0) {
  234. ps->last_ts = ts;
  235. ps->count++;
  236. if (max_count < ps->count)
  237. max_count = ps->count;
  238. } else {
  239. ps->count_falses++;
  240. }
  241. }
  242. return max_count;
  243. }
  244. static struct pri_sequence *
  245. pseq_handler_check_detection(struct pri_detector *pde)
  246. {
  247. struct pri_sequence *ps;
  248. if (list_empty(&pde->sequences))
  249. return NULL;
  250. list_for_each_entry(ps, &pde->sequences, head) {
  251. /*
  252. * we assume to have enough matching confidence if we
  253. * 1) have enough pulses
  254. * 2) have more matching than false pulses
  255. */
  256. if ((ps->count >= pde->rs->ppb_thresh) &&
  257. (ps->count * pde->rs->num_pri >= ps->count_falses))
  258. return ps;
  259. }
  260. return NULL;
  261. }
  262. /* free pulse queue and sequences list and give objects back to pools */
  263. static void pri_detector_reset(struct pri_detector *pde, u64 ts)
  264. {
  265. struct pri_sequence *ps, *ps0;
  266. struct pulse_elem *p, *p0;
  267. list_for_each_entry_safe(ps, ps0, &pde->sequences, head) {
  268. list_del_init(&ps->head);
  269. list_add(&ps->head, &pseq_pool);
  270. }
  271. list_for_each_entry_safe(p, p0, &pde->pulses, head) {
  272. list_del_init(&p->head);
  273. list_add(&p->head, &pulse_pool);
  274. }
  275. pde->count = 0;
  276. pde->last_ts = ts;
  277. }
  278. static void pri_detector_exit(struct pri_detector *de)
  279. {
  280. pri_detector_reset(de, 0);
  281. singleton_pool_references--;
  282. if (singleton_pool_references == 0) {
  283. /* free singleton pools with no references left */
  284. struct pri_sequence *ps, *ps0;
  285. struct pulse_elem *p, *p0;
  286. list_for_each_entry_safe(p, p0, &pulse_pool, head) {
  287. list_del(&p->head);
  288. kfree(p);
  289. }
  290. list_for_each_entry_safe(ps, ps0, &pseq_pool, head) {
  291. list_del(&ps->head);
  292. kfree(ps);
  293. }
  294. }
  295. kfree(de);
  296. }
  297. static bool pri_detector_add_pulse(struct pri_detector *de,
  298. struct pulse_event *event)
  299. {
  300. u32 max_updated_seq;
  301. struct pri_sequence *ps;
  302. u64 ts = event->ts;
  303. const struct radar_detector_specs *rs = de->rs;
  304. /* ignore pulses not within width range */
  305. if ((rs->width_min > event->width) || (rs->width_max < event->width))
  306. return false;
  307. if ((ts - de->last_ts) < rs->max_pri_tolerance)
  308. /* if delta to last pulse is too short, don't use this pulse */
  309. return false;
  310. de->last_ts = ts;
  311. max_updated_seq = pseq_handler_add_to_existing_seqs(de, ts);
  312. if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) {
  313. pr_err("failed to create pulse sequences\n");
  314. pri_detector_reset(de, ts);
  315. return false;
  316. }
  317. ps = pseq_handler_check_detection(de);
  318. if (ps != NULL) {
  319. pr_info("DFS: radar found: pri=%d, count=%d, count_false=%d\n",
  320. ps->pri, ps->count, ps->count_falses);
  321. pri_detector_reset(de, ts);
  322. return true;
  323. }
  324. pulse_queue_enqueue(de, ts);
  325. return false;
  326. }
  327. struct pri_detector *
  328. pri_detector_init(const struct radar_detector_specs *rs)
  329. {
  330. struct pri_detector *de;
  331. de = kzalloc(sizeof(*de), GFP_KERNEL);
  332. if (de == NULL)
  333. return NULL;
  334. de->exit = pri_detector_exit;
  335. de->add_pulse = pri_detector_add_pulse;
  336. de->reset = pri_detector_reset;
  337. INIT_LIST_HEAD(&de->sequences);
  338. INIT_LIST_HEAD(&de->pulses);
  339. de->window_size = rs->pri_max * rs->ppb * rs->num_pri;
  340. de->max_count = rs->ppb * 2;
  341. de->rs = rs;
  342. singleton_pool_references++;
  343. return de;
  344. }