1 /*
2  * Generic spectrum tool container class for physical and logic devices,
3  * sample sweeps, and aggregations of sample sweeps
4  *
5  * This code is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This code is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16 
17 #ifndef __SPECTOOL_DEVCONTAINER_H__
18 #define __SPECTOOL_DEVCONTAINER_H__
19 
20 #include <time.h>
21 #include <sys/time.h>
22 
23 #ifdef HAVE_STDINT
24 #include <stdint.h>
25 #endif
26 
27 #ifdef HAVE_INTTYPES_H
28 #include <inttypes.h>
29 #endif
30 
31 /* A sweep record.  Because the sample array is allocated dynamically we
32  * re-use this same record as the definition of what sweep ranges a device
33  * can handle.
34  */
35 typedef struct _spectool_sample_sweep {
36 	/* Name of sweep (if used as a range marker */
37 	char *name;
38 
39 	/* Starting frequency of the sweep, in KHz */
40 	uint32_t start_khz;
41 	/* Ending frequency of the sweep, in KHz */
42 	uint32_t end_khz;
43 	/* Sample resolution, in KHz */
44 	uint32_t res_hz;
45 
46 	/* RSSI conversion information in mdbm
47 	 * db = (rssi * (amp_res_mdbm / 1000)) - (amp_offset_mdbm / 1000) */
48 	int amp_offset_mdbm;
49 	int amp_res_mdbm;
50 	unsigned int rssi_max;
51 
52 	/* Lowest RSSI seen by the device */
53 	unsigned int min_rssi_seen;
54 
55 	/* This could be derived from start, end, and resolution, but we include
56 	 * it here to save on math */
57 	unsigned int num_samples;
58 	/* Filter resolution in hz, hw config */
59 	unsigned int filter_bw_hz;
60 
61 	/* Samples per point (hw aggregation) */
62 	unsigned int samples_per_point;
63 
64 	/* Timestamp for when the sweep begins and ends */
65 	struct timeval tm_start;
66 	struct timeval tm_end;
67 
68 	/* Phy reference */
69 	void *phydev;
70 
71 	/* Actual sample data.  This is num_samples of uint8_t RSSI */
72 	uint8_t sample_data[0];
73 } spectool_sample_sweep;
74 
75 #define SPECTOOL_RSSI_CONVERT(O,R,D)	(int) ((D) * ((double) (R) / 1000.0f) + \
76 										   ((double) (O) / 1000.0f))
77 
78 #define SPECTOOL_SWEEP_SIZE(y)		(sizeof(spectool_sample_sweep) + (y))
79 
80 /* Sweep record for aggregating multiple sweep points */
81 typedef struct _spectool_sweep_cache {
82 	spectool_sample_sweep **sweeplist;
83 	spectool_sample_sweep *avg;
84 	spectool_sample_sweep *peak;
85 	spectool_sample_sweep *roll_peak;
86 	spectool_sample_sweep *latest;
87 	int num_alloc, pos, looped;
88 	int calc_peak, calc_avg;
89 	int num_used;
90 	uint32_t device_id;
91 } spectool_sweep_cache;
92 
93 typedef struct _spectool_sweep_cache_itr {
94 	int pos_start;
95 	int pos_cur;
96 	int looped_start;
97 } spectool_sweep_cache_itr;
98 
99 /* Allocate and manipulate sweep caches */
100 spectool_sweep_cache *spectool_cache_alloc(int nsweeps, int calc_peak, int calc_avg);
101 void spectool_cache_append(spectool_sweep_cache *c, spectool_sample_sweep *s);
102 void spectool_cache_clear(spectool_sweep_cache *c);
103 void spectool_cache_free(spectool_sweep_cache *c);
104 
105 void spectool_cache_itr_init(spectool_sweep_cache *c, spectool_sweep_cache_itr *i);
106 spectool_sample_sweep *spectool_cache_itr_next(spectool_sweep_cache *c, spectool_sweep_cache_itr *i);
107 
108 #define SPECTOOL_ERROR_MAX			512
109 #define SPECTOOL_PHY_NAME_MAX		256
110 typedef struct _spectool_dev_spec {
111 	/* A unique ID fetched from the firmware (in the future) or extracted from the
112 	 * USB bus (currently) */
113 	uint32_t device_id;
114 
115 	/* User-specified name */
116 	char device_name[SPECTOOL_PHY_NAME_MAX];
117 
118 	/* Version of the physical source device.
119 	 * 0x01 WiSPY generation 1 USB device
120 	 * 0x02 WiSPY generation 2 USB device
121 	 * 0x03 WiSPY generation 3 USB device
122 	 */
123 	uint8_t device_version;
124 
125 	/* Device flags */
126 	uint8_t device_flags;
127 
128 	spectool_sample_sweep *default_range;
129 
130 	/* Number of sweep ranges this device supports.
131 	 * Gen1 supports 1 range.
132 	 */
133 	unsigned int num_sweep_ranges;
134 
135 	/* Supported sweep ranges */
136 	spectool_sample_sweep *supported_ranges;
137 
138 	int cur_profile;
139 } spectool_dev_spec;
140 
141 /* Device flags */
142 #define SPECTOOL_DEV_FL_NONE			0
143 /* Variable sweep supported */
144 #define SPECTOOL_DEV_FL_VAR_SWEEP		1
145 
146 #define SPECTOOL_DEV_SIZE(y)		(sizeof(spectool_dev_spec))
147 
148 /* Central tracking structure for spectool device data and API callbacks */
149 typedef struct _spectool_phy {
150 	/* Phy capabilities */
151 	spectool_dev_spec *device_spec;
152 
153 	/* Running state */
154 	int state;
155 
156 	/* Min RSSI seen */
157 	unsigned int min_rssi_seen;
158 
159 	/* External phy-specific data */
160 	void *auxptr;
161 
162 	/* Function pointers to be filled in by the device init system */
163 	int (*open_func)(struct _spectool_phy *);
164 	int (*close_func)(struct _spectool_phy *);
165 	int (*poll_func)(struct _spectool_phy *);
166 	int (*pollfd_func)(struct _spectool_phy *);
167 	void (*setcalib_func)(struct _spectool_phy *, int);
168 	int (*setposition_func)(struct _spectool_phy *, int, int, int);
169 	spectool_sample_sweep *(*getsweep_func)(struct _spectool_phy *);
170 
171 	char errstr[SPECTOOL_ERROR_MAX];
172 
173 	/* Linked list elements incase we need them in our implementation */
174 	struct _spectool_phy *next;
175 
176 	/* Suggested delay for drawing */
177 	int draw_agg_suggestion;
178 } spectool_phy;
179 
180 #define SPECTOOL_PHY_SIZE		(sizeof(spectool_phy))
181 
182 int spectool_get_state(spectool_phy *phydev);
183 char *spectool_get_error(spectool_phy *phydev);
184 int spectool_phy_open(spectool_phy *phydev);
185 int spectool_phy_close(spectool_phy *phydev);
186 int spectool_phy_poll(spectool_phy *phydev);
187 int spectool_phy_getpollfd(spectool_phy *phydev);
188 spectool_sample_sweep *spectool_phy_getsweep(spectool_phy *phydev);
189 void spectool_phy_setcalibration(spectool_phy *phydev, int enable);
190 int spectool_phy_setposition(spectool_phy *phydev, int in_profile,
191 						  int start_khz, int res_hz);
192 char *spectool_phy_getname(spectool_phy *phydev);
193 void spectool_phy_setname(spectool_phy *phydev, char *name);
194 int spectool_phy_getdevid(spectool_phy *phydev);
195 int spectool_phy_get_flags(spectool_phy *phydev);
196 spectool_sample_sweep *spectool_phy_getcurprofile(spectool_phy *phydev);
197 
198 /* Running states */
199 #define SPECTOOL_STATE_CLOSED			0
200 #define SPECTOOL_STATE_CONFIGURING		1
201 #define SPECTOOL_STATE_CALIBRATING		2
202 #define SPECTOOL_STATE_RUNNING			3
203 #define SPECTOOL_STATE_ERROR			255
204 
205 /* Poll return states */
206 /* Failure */
207 #define SPECTOOL_POLL_ERROR			256
208 /* No state - partial poll, etc */
209 #define SPECTOOL_POLL_NONE				1
210 /* Sweep is complete, caller should pull data */
211 #define SPECTOOL_POLL_SWEEPCOMPLETE	2
212 /* Device has finished configuring */
213 #define SPECTOOL_POLL_CONFIGURED		4
214 /* Device has additional pending data and poll should be called again */
215 #define SPECTOOL_POLL_ADDITIONAL		8
216 
217 /* Device scan handling */
218 typedef struct _spectool_device_rec {
219 	/* Name of device */
220 	char name[SPECTOOL_PHY_NAME_MAX];
221 	/* ID of device */
222 	uint32_t device_id;
223 	/* Init function */
224 	int (*init_func)(struct _spectool_phy *, struct _spectool_device_rec *);
225 	/* Hardware record pointing to the aux handling */
226 	void *hw_rec;
227 
228 	/* Supported sweep ranges identified from hw type */
229 	unsigned int num_sweep_ranges;
230 	spectool_sample_sweep *supported_ranges;
231 } spectool_device_rec;
232 
233 typedef struct _spectool_device_list {
234 	int num_devs;
235 	int max_devs;
236 	spectool_device_rec *list;
237 } spectool_device_list;
238 
239 /* Hopefully this doesn't come back and bite us, but, really, 32 SAs on one system? */
240 #define MAX_SCAN_RESULT		32
241 
242 /* Scan for all attached devices we can handle */
243 void spectool_device_scan_init(spectool_device_list *list);
244 int spectool_device_scan(spectool_device_list *list);
245 void spectool_device_scan_free(spectool_device_list *list);
246 int spectool_device_init(spectool_phy *phydev, spectool_device_rec *rec);
247 
248 struct spectool_channels {
249 	/* Name of the channel set */
250 	char *name;
251 	/* Start and end khz for matching */
252 	int startkhz;
253 	int endkhz;
254 	/* Number of channels */
255 	int chan_num;
256 	/* Offsets in khz */
257 	int *chan_freqs;
258 	/* Width of channels in khz */
259 	int chan_width;
260 	/* Text of channel numbers */
261 	char **chan_text;
262 };
263 
264 /* Some channel lists */
265 static int chan_freqs_24[] = {
266 	2411000, 2416000, 2421000, 2426000, 2431000, 2436000, 2441000,
267 	2446000, 2451000, 2456000, 2461000, 2466000, 2471000, 2483000
268 };
269 
270 static char *chan_text_24[] = {
271 	"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"
272 };
273 
274 static int chan_freqs_5[] = {
275 	5180000, 5200000, 5220000, 5240000, 5260000, 5280000, 5300000, 5320000,
276 	5500000, 5520000, 5540000, 5560000, 5580000, 5600000, 5620000, 5640000,
277 	5660000, 5680000, 5700000, 5745000, 5765000, 5785000, 5805000, 5825000
278 };
279 
280 static char *chan_text_5[] = {
281 	"36", "40", "44", "48", "52", "56", "60", "64", "100", "104",
282 	"108", "112", "116", "120", "124", "128", "132", "136", "140",
283 	"149", "153", "157", "161", "165"
284 };
285 
286 static int chan_freqs_900[] = {
287 	905000, 910000, 915000, 920000, 925000
288 };
289 
290 static char *chan_text_900[] = {
291 	"905", "910", "915", "920", "925"
292 };
293 
294 /* Allocate all our channels in a big nasty array */
295 static struct spectool_channels channel_list[] = {
296 	{ "802.11b/g", 2400000, 2483000, 14, chan_freqs_24, 22000, chan_text_24 },
297 	{ "802.11b/g", 2402000, 2480000, 14, chan_freqs_24, 22000, chan_text_24 },
298 	{ "802.11a", 5100000, 5832000, 24, chan_freqs_5, 20000, chan_text_5 },
299 	{ "802.11a UN-II", 5100000, 5483000, 14, chan_freqs_5, 20000, chan_text_5 },
300 	{ "900 ISM", 902000, 927000, 5, chan_freqs_900, 5000, chan_text_900 },
301 	{ NULL, 0, 0, 0, NULL, 0, NULL }
302 };
303 
304 #endif
305 
306