source: ReferenceDesigns/w3_802.11/c/wlan_mac_high_framework/wlan_mac_scan.c

Last change on this file was 6319, checked in by chunter, 5 years ago

1.8.0 release wlan-mac-se

File size: 12.9 KB
Line 
1/** @file wlan_mac_scan.c
2 *  @brief Scan FSM
3 *
4 *  This contains code for the active scan finite state machine.
5 *
6 *  @copyright Copyright 2014-2019, Mango Communications. All rights reserved.
7 *          Distributed under the Mango Communications Reference Design License
8 *              See LICENSE.txt included in the design archive or
9 *              at http://mangocomm.com/802.11/license
10 *
11 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
12 *
13 *
14 *   The scan process allows a node to search for a given BSS given an SSID.  The
15 * behavior of the scan is controlled with the global scan parameters
16 * (gl_scan_parameters).  The scan process follows a simple state machine:
17 *    - After initialization, the scan state is IDLE
18 *    - By calling wlan_mac_scan_start(), the scan transitions to RUNNING
19 *    - Once the scan is RUNNING, it can either be stopped (ie back to IDLE)
20 *      or PAUSED
21 *    - If a scan is PAUSED, it can either be stopped (ie back to IDLE) or
22 *      resumed (ie back to RUNNING)
23 *
24 * When a scan is paused, the node will stay on the current scan channel and the
25 * global scan variables will not be updated.
26 *
27 * When the scan is RUNNING, it will transition through each channel in the
28 * channel_vec array of the scan parameters.  Once it reaches the end of the
29 * channel_vec array, it will start over at the beginning and continue doing this
30 * until stopped or paused.  On a given channel, the scan will call the
31 * tx_probe_request_callback every probe_tx_interval_usec.  If the interval is
32 * zero, then the callback will never be called resulting in a passive scan.
33 *
34 * The fine scheduler is used to schedule both the probe request transmissions
35 * and the interval to change channels.  There is no error checking on the scan
36 * timing parameters.
37 *
38 */
39
40/***************************** Include Files *********************************/
41#include "wlan_mac_high_sw_config.h"
42
43// Xilinx SDK includes
44#include "xparameters.h"
45#include "stdio.h"
46#include "stdlib.h"
47#include "string.h"
48
49// WLAN includes
50#include "wlan_mac_high.h"
51#include "wlan_mac_packet_types.h"
52#include "wlan_mac_schedule.h"
53#include "wlan_mac_scan.h"
54#include "wlan_common_types.h"
55#include "wlan_mac_common.h"
56#include "wlan_platform_high.h"
57
58/*************************** Constant Definitions ****************************/
59
60
61/*********************** Global Variable Definitions *************************/
62
63
64/*************************** Variable Definitions ****************************/
65
66// Default Scan Channels
67//     These channels will be scanned by default at boot.  This uses the standard
68//     channel numbering scheme.
69//
70//const u8 default_channel_selections[] = {1,2,3,4,5,6,7,8,9,10,11};             // Scan only 2.4GHz channels
71const u8 default_channel_selections[] = {1,2,3,4,5,6,7,8,9,10,11,36,40,44,48}; // Scan 2.4GHz and 5GHz channels
72
73
74// Global scan parameters
75//     This variable needs to be treated as volatile since it is expected to be
76//     modified by other contexts after a call to wlan_mac_scan_get_parameters
77volatile scan_parameters_t gl_scan_parameters;
78
79
80// Scan state variables
81static s8 curr_scan_chan_idx;
82
83static u32 scan_sched_id;
84static u32 probe_sched_id;
85static scan_state_t scan_state;
86static int num_full_scans;
87
88
89// Callback Function
90//     Used to transmit probe requests during the scan process
91volatile function_ptr_t tx_probe_request_callback;
92volatile function_ptr_t scan_state_change_callback;
93
94
95
96/*************************** Functions Prototypes ****************************/
97
98void wlan_mac_scan_state_transition();
99
100
101/******************************** Functions **********************************/
102
103/*****************************************************************************/
104/**
105 * Initialize the scan state
106 *
107 * This function will initialize the scan state machine an set the scan
108 * parameters to the default values.
109 *
110 * @return  int              - Status: WLAN_SUCCESS or WLAN_FAILURE
111 *
112 *****************************************************************************/
113int wlan_mac_scan_init(){
114
115    // Initialize probe request callback
116    tx_probe_request_callback = (function_ptr_t)wlan_null_callback;
117    scan_state_change_callback = (function_ptr_t)wlan_null_callback;
118
119    // Set default scan parameters
120    gl_scan_parameters.channel_vec = wlan_mac_high_malloc(sizeof(default_channel_selections));
121
122    if (gl_scan_parameters.channel_vec != NULL) {
123        memcpy(gl_scan_parameters.channel_vec, default_channel_selections, sizeof(default_channel_selections));
124        gl_scan_parameters.channel_vec_len = sizeof(default_channel_selections)/sizeof(default_channel_selections[0]);
125    }
126
127    gl_scan_parameters.probe_tx_interval_usec   = DEFAULT_SCAN_PROBE_TX_INTERVAL_USEC;
128    gl_scan_parameters.time_per_channel_usec    = DEFAULT_SCAN_TIME_PER_CHANNEL_USEC;
129    gl_scan_parameters.ssid                     = strndup("", SSID_LEN_MAX);
130
131    // Set global scan parameters
132    //     - Other global variables will be initialized when wlan_mac_scan_start() is called
133    scan_sched_id  = SCHEDULE_ID_RESERVED_MAX;
134    probe_sched_id = SCHEDULE_ID_RESERVED_MAX;
135    scan_state     = SCAN_IDLE;
136
137    return WLAN_SUCCESS;
138}
139
140
141
142/*****************************************************************************/
143/**
144 * Set callbacks
145 *
146 *****************************************************************************/
147void wlan_mac_scan_set_tx_probe_request_callback(function_ptr_t callback){
148    tx_probe_request_callback = callback;
149}
150void wlan_mac_scan_set_state_change_callback(function_ptr_t callback){
151    scan_state_change_callback = callback;
152}
153
154
155
156/*****************************************************************************/
157/**
158 * Get global scan parameters structure
159 *
160 * This is in lieu of getter / setter methods for all of the scan parameters.
161 *
162 * @return  volatile scan_parameters_t*     - Pointer to scan parameters
163 *
164 *****************************************************************************/
165volatile scan_parameters_t* wlan_mac_scan_get_parameters(){
166    return &gl_scan_parameters;
167}
168
169
170
171/*****************************************************************************/
172/**
173 * Start scan
174 *
175 * This function will start a scan using the current scan parameters.
176 *
177 *****************************************************************************/
178void wlan_mac_scan_start(){
179
180    // Only start a scan if state machine is IDLE
181    if (scan_state == SCAN_IDLE) {
182
183        // Initialize a variable that tracks how many times the scanner
184        // as looped around the channel list.
185        num_full_scans = -1;
186
187        // Initialize scan variables
188        curr_scan_chan_idx = -1;
189        scan_state = SCAN_RUNNING;
190        scan_state_change_callback(scan_state);
191
192        // Start the scan
193        wlan_mac_scan_state_transition();
194    }
195}
196
197
198
199/*****************************************************************************/
200/**
201 * Stop scan
202 *
203 * This function will stop the current scan and return to the original channel
204 * that the node was on when wlan_mac_scan_start() was called.
205 *
206 *****************************************************************************/
207void wlan_mac_scan_stop() {
208    interrupt_state_t   prev_interrupt_state;
209
210    // Stop scan if it is running or paused
211    if ((scan_state == SCAN_RUNNING) || (scan_state == SCAN_PAUSED)) {
212
213        // Stop interrupts while removing scheduled events
214        prev_interrupt_state = wlan_platform_intc_stop();
215
216        // Remove any scheduled scan state transitions
217        if (scan_sched_id != SCHEDULE_ID_RESERVED_MAX) {
218            wlan_mac_schedule_remove_event(scan_sched_id);
219            scan_sched_id  = SCHEDULE_ID_RESERVED_MAX;
220        }
221
222        // Remove any scheduled probe requests
223        if (probe_sched_id != SCHEDULE_ID_RESERVED_MAX) {
224            wlan_mac_schedule_remove_event(probe_sched_id);
225            probe_sched_id = SCHEDULE_ID_RESERVED_MAX;
226        }
227
228        // Reset the number of full scans to an invalid number
229        num_full_scans = -1;
230
231        // Restore interrupt state
232        wlan_platform_intc_set_state(prev_interrupt_state);
233
234        // Update scan state variables
235        curr_scan_chan_idx = -1;
236        scan_state = SCAN_IDLE;
237        scan_state_change_callback(scan_state);
238    }
239}
240
241
242
243/*****************************************************************************/
244/**
245 * Pause scan
246 *
247 * This function will pause the current scan (ie it stops all scheduled events
248 * but does not revert the channel or update the scan state variables).
249 *
250 *****************************************************************************/
251void wlan_mac_scan_pause(){
252    interrupt_state_t   prev_interrupt_state;
253
254    // Can only pause when running
255    if (scan_state == SCAN_RUNNING) {
256
257        // Stop interrupts while removing scheduled events
258        prev_interrupt_state = wlan_platform_intc_stop();
259
260        // Remove any scheduled scan state transitions
261        if (scan_sched_id != SCHEDULE_ID_RESERVED_MAX) {
262            wlan_mac_schedule_remove_event(scan_sched_id);
263            scan_sched_id  = SCHEDULE_ID_RESERVED_MAX;
264        }
265
266        // Remove any scheduled probe requests
267        if (probe_sched_id != SCHEDULE_ID_RESERVED_MAX) {
268            wlan_mac_schedule_remove_event(probe_sched_id);
269            probe_sched_id = SCHEDULE_ID_RESERVED_MAX;
270        }
271
272        // Restore interrupt state
273        wlan_platform_intc_set_state(prev_interrupt_state);
274
275        // Update scan state variables
276        scan_state = SCAN_PAUSED;
277        scan_state_change_callback(scan_state);
278    }
279}
280
281
282
283/*****************************************************************************/
284/**
285 * Resume scan
286 *
287 * This function will resume a paused scan.  When a scan is resumed, it will
288 * immediately proceed to the next channel in the scan parameters.
289 *
290 *****************************************************************************/
291void wlan_mac_scan_resume(){
292
293    // Can only pause when running
294    if (scan_state == SCAN_PAUSED) {
295
296        // Update scan state variables
297        scan_state = SCAN_RUNNING;
298        scan_state_change_callback(scan_state);
299
300        // Resume scan
301        wlan_mac_scan_state_transition();
302    }
303}
304
305
306
307/*****************************************************************************/
308/**
309 * Is the node scanning?
310 *
311 * @return  u32              - Is Scanning?
312 *                                 1 - Currently scanning
313 *                                 0 - Not scanning
314 *
315 *****************************************************************************/
316u32 wlan_mac_scan_is_scanning(){
317    if ((scan_state == SCAN_RUNNING) || (scan_state == SCAN_PAUSED)) {
318        return 1;
319    } else {
320        return 0;
321    }
322}
323
324
325
326/*****************************************************************************/
327/**
328 * Scan state transition
329 *
330 * This internal function will stop any existing scheduled probe requests, change
331 * the channel and start sending probe requests on the new channel.  It will also
332 * schedule an event to execute the function again until scan is paused or
333 * stopped.
334 *
335 *****************************************************************************/
336void wlan_mac_scan_state_transition(){
337
338    // Remove existing scheduled probe requests
339    if (probe_sched_id != SCHEDULE_ID_RESERVED_MAX) {
340        wlan_mac_schedule_remove_event(probe_sched_id);
341        probe_sched_id = SCHEDULE_ID_RESERVED_MAX;
342    }
343
344    // Update the channel
345    curr_scan_chan_idx = (curr_scan_chan_idx + 1) % (gl_scan_parameters.channel_vec_len);
346    wlan_mac_high_set_radio_channel(gl_scan_parameters.channel_vec[(u8)curr_scan_chan_idx]);
347
348    // Update the number of full scan loops variable
349    if (curr_scan_chan_idx == 0) {
350        num_full_scans++;
351    }
352
353    // Send a probe request
354    //     - A probe interval of 0 results in a passive scan
355    if (gl_scan_parameters.probe_tx_interval_usec > 0) {
356        tx_probe_request_callback();
357
358        // Schedule future probe requests on this channel
359        //     - This will be stopped on the next call to wlan_mac_scan_state_transition()
360        //       when the channel is changed.
361        //
362        probe_sched_id = wlan_mac_schedule_add_event(SCHEDULE_ID_FINE, gl_scan_parameters.probe_tx_interval_usec, SCHEDULE_REPEAT_FOREVER, (void*)tx_probe_request_callback);
363    }
364
365    // Schedule the scan state transition
366    //     - This will only be executed when moving from IDLE to RUNNING
367    //     - The scheduled event will only be stopped when scan is paused or stopped
368    //
369    if (scan_sched_id == SCHEDULE_ID_RESERVED_MAX) {
370        scan_sched_id = wlan_mac_schedule_add_event(SCHEDULE_ID_FINE, gl_scan_parameters.time_per_channel_usec, SCHEDULE_REPEAT_FOREVER, (void*)wlan_mac_scan_state_transition);
371    }
372}
373
374int wlan_mac_scan_get_num_scans(){
375    return num_full_scans;
376}
Note: See TracBrowser for help on using the repository browser.