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