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