1 /*
2 * This code 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, or
5 * (at your option) any later version.
6 *
7 * This code is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include "config.h"
17 #include "spectool_container.h"
18 #include "wispy_hw_gen1.h"
19 #include "wispy_hw_24x.h"
20 #include "wispy_hw_dbx.h"
21 #include "ubertooth_hw_u1.h"
22
spectool_get_state(spectool_phy * phydev)23 int spectool_get_state(spectool_phy *phydev) {
24 return phydev->state;
25 }
26
spectool_get_error(spectool_phy * phydev)27 char *spectool_get_error(spectool_phy *phydev) {
28 return phydev->errstr;
29 }
30
spectool_phy_getname(spectool_phy * phydev)31 char *spectool_phy_getname(spectool_phy *phydev) {
32 if (phydev->device_spec == NULL)
33 return NULL;
34
35 return phydev->device_spec->device_name;
36 }
37
spectool_phy_getdevid(spectool_phy * phydev)38 int spectool_phy_getdevid(spectool_phy *phydev) {
39 if (phydev->device_spec == NULL)
40 return 0;
41
42 return phydev->device_spec->device_id;
43 }
44
spectool_phy_setname(spectool_phy * phydev,char * name)45 void spectool_phy_setname(spectool_phy *phydev, char *name) {
46 if (phydev->device_spec == NULL)
47 return;
48
49 snprintf(phydev->device_spec->device_name, SPECTOOL_PHY_NAME_MAX, "%s", name);
50 }
51
spectool_phy_open(spectool_phy * phydev)52 int spectool_phy_open(spectool_phy *phydev) {
53 if (phydev->open_func == NULL)
54 return 0;
55
56 return (*(phydev->open_func))(phydev);
57 }
58
spectool_phy_close(spectool_phy * phydev)59 int spectool_phy_close(spectool_phy *phydev) {
60 if (phydev->close_func == NULL)
61 return 0;
62
63 return (*(phydev->close_func))(phydev);
64 }
65
spectool_phy_poll(spectool_phy * phydev)66 int spectool_phy_poll(spectool_phy *phydev) {
67 if (phydev->poll_func == NULL)
68 return SPECTOOL_POLL_ERROR;
69
70 return (*(phydev->poll_func))(phydev);
71 }
72
spectool_phy_getpollfd(spectool_phy * phydev)73 int spectool_phy_getpollfd(spectool_phy *phydev) {
74 if (phydev == NULL)
75 return -1;
76
77 if (phydev->pollfd_func == NULL)
78 return -1;
79
80 return (*(phydev->pollfd_func))(phydev);
81 }
82
spectool_phy_setcalibration(spectool_phy * phydev,int enable)83 void spectool_phy_setcalibration(spectool_phy *phydev, int enable) {
84 if (phydev->setcalib_func != NULL)
85 return (*(phydev->setcalib_func))(phydev, enable);
86 }
87
spectool_phy_getflags(spectool_phy * phydev)88 int spectool_phy_getflags(spectool_phy *phydev) {
89 return phydev->device_spec->device_flags;
90 }
91
spectool_phy_setposition(spectool_phy * phydev,int in_profile,int start_khz,int res_hz)92 int spectool_phy_setposition(spectool_phy *phydev, int in_profile,
93 int start_khz, int res_hz) {
94 if (phydev->setposition_func != NULL)
95 return (*(phydev->setposition_func))(phydev, in_profile, start_khz, res_hz);
96
97 snprintf(phydev->errstr, SPECTOOL_ERROR_MAX, "Device does not support setting "
98 "scan position or resolution");
99 return -1;
100 }
101
spectool_phy_getsweep(spectool_phy * phydev)102 spectool_sample_sweep *spectool_phy_getsweep(spectool_phy *phydev) {
103 if (phydev->getsweep_func == NULL)
104 return NULL;
105
106 return (*(phydev->getsweep_func))(phydev);
107 }
108
spectool_cache_alloc(int nsweeps,int calc_peak,int calc_avg)109 spectool_sweep_cache *spectool_cache_alloc(int nsweeps, int calc_peak, int calc_avg) {
110 int x;
111 spectool_sweep_cache *c = (spectool_sweep_cache *) malloc(sizeof(spectool_sweep_cache));
112
113 c->sweeplist =
114 (spectool_sample_sweep **) malloc(sizeof(spectool_sample_sweep *) * nsweeps);
115 c->avg = NULL;
116 c->peak = NULL;
117 c->roll_peak = NULL;
118 c->latest = NULL;
119
120 for (x = 0; x < nsweeps; x++) {
121 c->sweeplist[x] = NULL;
122 }
123
124 c->num_alloc = nsweeps;
125 c->pos = -1;
126 c->looped = 0;
127 c->num_used = 0;
128
129 c->calc_peak = calc_peak;
130 c->calc_avg = calc_avg;
131
132 return c;
133 }
134
spectool_cache_free(spectool_sweep_cache * c)135 void spectool_cache_free(spectool_sweep_cache *c) {
136 if (c->avg != NULL)
137 free(c->avg);
138 if (c->peak != NULL)
139 free(c->peak);
140 free(c->sweeplist);
141 }
142
spectool_cache_clear(spectool_sweep_cache * c)143 void spectool_cache_clear(spectool_sweep_cache *c) {
144 if (c->avg != NULL)
145 free(c->avg);
146 c->avg = NULL;
147
148 if (c->peak != NULL)
149 free(c->peak);
150 c->peak = NULL;
151
152 if (c->roll_peak != NULL)
153 free(c->roll_peak);
154 c->roll_peak = NULL;
155
156 c->pos = 0;
157 c->looped = 0;
158 c->num_used = 0;
159 }
160
spectool_cache_append(spectool_sweep_cache * c,spectool_sample_sweep * s)161 void spectool_cache_append(spectool_sweep_cache *c, spectool_sample_sweep *s) {
162 int x, y, sum = 0;
163 int *avgdata, *avgsum;
164 int navg;
165 int nsampled;
166
167 /* Make sure we don't overflow and crash, should be sufficient
168 * to make sure that the new sweep is reasonable */
169 if (c->avg != NULL && c->avg->num_samples != s->num_samples)
170 return;
171
172 if (c->pos == (c->num_alloc - 1)) {
173 c->looped = 1;
174 c->pos = 0;
175 } else {
176 c->pos++;
177
178 if (c->num_used < c->num_alloc)
179 c->num_used++;
180 }
181
182 if (c->sweeplist[c->pos] != NULL) {
183 free(c->sweeplist[c->pos]);
184 }
185
186 if (c->looped)
187 nsampled = c->num_alloc;
188 else
189 nsampled = c->pos;
190
191 c->sweeplist[c->pos] =
192 (spectool_sample_sweep *) malloc(SPECTOOL_SWEEP_SIZE(s->num_samples));
193
194 memcpy(c->sweeplist[c->pos], s, SPECTOOL_SWEEP_SIZE(s->num_samples));
195
196 c->latest = c->sweeplist[c->pos];
197
198 if (c->avg == NULL && c->calc_avg) {
199 c->avg = (spectool_sample_sweep *) malloc(SPECTOOL_SWEEP_SIZE(s->num_samples));
200 memcpy(c->avg, s, SPECTOOL_SWEEP_SIZE(s->num_samples));
201 } else if (c->calc_avg) {
202 /* Reset average times */
203 c->avg->tm_start.tv_sec = 0;
204 c->avg->tm_start.tv_usec = 0;
205 c->avg->tm_end.tv_sec = 0;
206 c->avg->tm_end.tv_usec = 0;
207
208 /* Allocate a large int for summing */
209 avgdata = (int *) malloc(sizeof(int) * c->avg->num_samples);
210 avgsum = (int *) malloc(sizeof(int) * c->avg->num_samples);
211 for (x = 0; x < c->avg->num_samples; x++) {
212 avgdata[x] = 0;
213 avgsum[x] = 0;
214 }
215
216 /* Sum them up */
217
218 for (x = 0; x < nsampled; x++) {
219 if (c->sweeplist[x] == NULL)
220 continue;
221
222 for (y = 0; y < c->avg->num_samples; y++) {
223 avgdata[y] += c->sweeplist[x]->sample_data[y];
224 avgsum[y]++;
225 }
226
227 /* Update the time of the average network */
228 if (c->sweeplist[x]->tm_start.tv_sec > c->avg->tm_start.tv_sec) {
229 c->avg->tm_start.tv_sec = c->sweeplist[x]->tm_start.tv_sec;
230 c->avg->tm_start.tv_usec = c->sweeplist[x]->tm_start.tv_usec;
231 } else if (c->sweeplist[x]->tm_start.tv_sec == c->avg->tm_start.tv_sec &&
232 c->sweeplist[x]->tm_start.tv_usec > c->avg->tm_start.tv_usec) {
233 c->avg->tm_start.tv_usec = c->sweeplist[x]->tm_start.tv_usec;
234 }
235 if (c->sweeplist[x]->tm_end.tv_sec > c->avg->tm_end.tv_sec) {
236 c->avg->tm_end.tv_sec = c->sweeplist[x]->tm_end.tv_sec;
237 c->avg->tm_end.tv_usec = c->sweeplist[x]->tm_end.tv_usec;
238 } else if (c->sweeplist[x]->tm_end.tv_sec == c->avg->tm_end.tv_sec &&
239 c->sweeplist[x]->tm_end.tv_usec > c->avg->tm_end.tv_usec) {
240 c->avg->tm_end.tv_usec = c->sweeplist[x]->tm_end.tv_usec;
241 }
242
243 }
244
245 for (x = 0; x < c->avg->num_samples; x++) {
246 if (avgsum[x] == 0) {
247 c->avg->sample_data[x] = 0;
248 continue;
249 }
250
251 c->avg->sample_data[x] = (float) avgdata[x] / (float) avgsum[x];
252 }
253
254 free(avgdata);
255 free(avgsum);
256 }
257
258 /* Allocate or update the peak. We don't track peak timelines */
259 if (c->peak == NULL && c->calc_peak) {
260 c->peak = (spectool_sample_sweep *) malloc(SPECTOOL_SWEEP_SIZE(s->num_samples));
261 memcpy(c->peak, s, SPECTOOL_SWEEP_SIZE(s->num_samples));
262
263 /* This will never be allocated if peak is not */
264 c->roll_peak = (spectool_sample_sweep *) malloc(SPECTOOL_SWEEP_SIZE(s->num_samples));
265 memcpy(c->roll_peak, s, SPECTOOL_SWEEP_SIZE(s->num_samples));
266 } else if (c->calc_peak) {
267
268 for (x = 0; x < c->peak->num_samples; x++) {
269 if (c->peak->sample_data[x] < s->sample_data[x]) {
270 c->peak->sample_data[x] = s->sample_data[x];
271 }
272 }
273
274 memcpy(c->roll_peak, s, SPECTOOL_SWEEP_SIZE(s->num_samples));
275 for (x = 0; x < nsampled; x++) {
276 for (y = 0; y < c->roll_peak->num_samples; y++) {
277 // printf("debug - compare sampled %d pos %d loop %d set %d sample %d\n", nsampled, c->pos, c->looped, x, y);
278 if (c->roll_peak->sample_data[y] < c->sweeplist[x]->sample_data[y]) {
279 c->roll_peak->sample_data[y] = c->sweeplist[x]->sample_data[y];
280 }
281 }
282 }
283
284 }
285 }
286
spectool_cache_itr_init(spectool_sweep_cache * c,spectool_sweep_cache_itr * i)287 void spectool_cache_itr_init(spectool_sweep_cache *c, spectool_sweep_cache_itr *i) {
288 i->pos_start = c->pos;
289 i->pos_cur = c->pos + 1;
290 i->looped_start = 0;
291 }
292
spectool_cache_itr_next(spectool_sweep_cache * c,spectool_sweep_cache_itr * i)293 spectool_sample_sweep *spectool_cache_itr_next(spectool_sweep_cache *c, spectool_sweep_cache_itr *i) {
294 // if we've covered it all, punt
295 if (i->pos_cur == i->pos_start) {
296 if (i->looped_start == 0)
297 i->looped_start = 1;
298 else
299 return NULL;
300 }
301
302 // 'next' is actually backwards
303 i->pos_cur--;
304
305 // if we've hit the bottom but we're looped, go to the max filled slot
306 if (i->pos_cur < 0 && c->looped) i->pos_cur = c->num_used - 1;
307 // Or we're done
308 if (i->pos_cur < 0) return NULL;
309 // safety
310 if (i->pos_cur >= c->num_used) return NULL;
311
312 return c->sweeplist[i->pos_cur];
313 }
314
spectool_device_scan_init(spectool_device_list * list)315 void spectool_device_scan_init(spectool_device_list *list) {
316 list->list = (spectool_device_rec *) malloc(sizeof(spectool_device_rec) * MAX_SCAN_RESULT);
317 list->num_devs = 0;
318 list->max_devs = MAX_SCAN_RESULT;
319 }
320
spectool_device_scan(spectool_device_list * list)321 int spectool_device_scan(spectool_device_list *list) {
322 spectool_device_scan_init(list);
323
324 if (wispy1_usb_device_scan(list) < 0) {
325 return -1;
326 }
327
328 if (wispy24x_usb_device_scan(list) < 0) {
329 return -1;
330 }
331
332 if (wispydbx_usb_device_scan(list) < 0) {
333 return -1;
334 }
335
336 if (ubertooth_u1_device_scan(list) < 0) {
337 return -1;
338 }
339
340 return list->num_devs;
341 }
342
spectool_device_scan_free(spectool_device_list * list)343 void spectool_device_scan_free(spectool_device_list *list) {
344 int x;
345
346 for (x = 0; x < list->num_devs && x < list->max_devs; x++) {
347 if (list->list[x].hw_rec != NULL)
348 free(list->list[x].hw_rec);
349 }
350
351 list->num_devs = 0;
352 list->max_devs = 0;
353
354 if (list->list != NULL)
355 free(list->list);
356 }
357
spectool_device_init(spectool_phy * phydev,spectool_device_rec * rec)358 int spectool_device_init(spectool_phy *phydev, spectool_device_rec *rec) {
359 return (*(rec->init_func))(phydev, rec);
360 }
361
spectool_phy_getcurprofile(spectool_phy * phydev)362 spectool_sample_sweep *spectool_phy_getcurprofile(spectool_phy *phydev) {
363 if (phydev == NULL)
364 return NULL;
365
366 if (phydev->device_spec->cur_profile < 0 ||
367 phydev->device_spec->cur_profile > phydev->device_spec->num_sweep_ranges)
368 return NULL;
369
370 return &(phydev->device_spec->supported_ranges[phydev->device_spec->cur_profile]);
371 }
372
373