remote: close file on usteer_init_local_id fread fail
[project/usteer.git] / measurement.c
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
14 *
15 * Copyright (C) 2021 David Bauer <mail@david-bauer.net>
16 */
17
18 #include "usteer.h"
19
20 LIST_HEAD(measurements);
21 static struct usteer_timeout_queue tq;
22
23 int
24 usteer_measurement_get_rssi(struct usteer_measurement_report *report)
25 {
26 /* Apple devices always set the RSNI to 0, while
27 * it should be set to 255 in case RSNI is unavailable.
28 *
29 * For them, RCPI seems to be calculated as RCPI = 255 + (RSSI)
30 */
31
32 if (!report->rsni)
33 return report->rcpi - 255;
34
35 return (report->rcpi / 2) - 110;
36 }
37
38 void
39 usteer_measurement_report_node_cleanup(struct usteer_node *node)
40 {
41 struct usteer_measurement_report *mr, *tmp;
42
43 list_for_each_entry_safe(mr, tmp, &node->measurements, node_list)
44 usteer_measurement_report_del(mr);
45 }
46
47 void
48 usteer_measurement_report_sta_cleanup(struct sta *sta)
49 {
50 struct usteer_measurement_report *mr, *tmp;
51
52 list_for_each_entry_safe(mr, tmp, &sta->measurements, sta_list)
53 usteer_measurement_report_del(mr);
54 }
55
56 struct usteer_measurement_report *
57 usteer_measurement_report_get(struct sta *sta, struct usteer_node *node, bool create)
58 {
59 struct usteer_measurement_report *mr;
60
61 list_for_each_entry(mr, &sta->measurements, sta_list) {
62 if (mr->node == node)
63 return mr;
64 }
65
66 if (!create)
67 return NULL;
68
69 mr = calloc(1, sizeof(*mr));
70 if (!mr)
71 return NULL;
72
73 /* Set node & add to nodes list */
74 mr->node = node;
75 list_add(&mr->node_list, &node->measurements);
76
77 /* Set sta & add to STAs list */
78 mr->sta = sta;
79 list_add(&mr->sta_list, &sta->measurements);
80
81 /* Add to Measurement list */
82 list_add(&mr->list, &measurements);
83
84 /* Set measurement expiration */
85 usteer_timeout_set(&tq, &mr->timeout, config.measurement_report_timeout);
86
87 return mr;
88 }
89
90 struct usteer_measurement_report *
91 usteer_measurement_report_add(struct sta *sta, struct usteer_node *node,
92 uint8_t rcpi, uint8_t rsni, uint64_t timestamp)
93 {
94 struct usteer_measurement_report *mr = usteer_measurement_report_get(sta, node, true);
95
96 if (!mr)
97 return NULL;
98
99 mr->timestamp = timestamp;
100 mr->rsni = rsni;
101 mr->rcpi = rcpi;
102
103 /* Reset timeout */
104 usteer_timeout_set(&tq, &mr->timeout, config.measurement_report_timeout);
105
106 return mr;
107 }
108
109 void
110 usteer_measurement_report_del(struct usteer_measurement_report *mr)
111 {
112 usteer_timeout_cancel(&tq, &mr->timeout);
113 list_del(&mr->node_list);
114 list_del(&mr->sta_list);
115 list_del(&mr->list);
116 free(mr);
117 }
118
119 static void
120 usteer_measurement_timeout(struct usteer_timeout_queue *q, struct usteer_timeout *t)
121 {
122 struct usteer_measurement_report *mr = container_of(t, struct usteer_measurement_report, timeout);
123
124 usteer_measurement_report_del(mr);
125 }
126
127 static void __usteer_init usteer_measurement_init(void)
128 {
129 usteer_timeout_init(&tq);
130 tq.cb = usteer_measurement_timeout;
131 }