Add preliminary background scan and roaming module design
[mech_eap.git] / wpa_supplicant / bgscan_simple.c
1 /*
2  * WPA Supplicant - background scan and roaming module: simple
3  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eloop.h"
19 #include "drivers/driver.h"
20 #include "config_ssid.h"
21 #include "wpa_supplicant_i.h"
22 #include "bgscan.h"
23
24 struct bgscan_simple_data {
25         struct wpa_supplicant *wpa_s;
26         const struct wpa_ssid *ssid;
27         int scan_interval;
28 };
29
30
31 static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
32 {
33         struct bgscan_simple_data *data = eloop_ctx;
34         struct wpa_supplicant *wpa_s = data->wpa_s;
35         struct wpa_driver_scan_params params;
36
37         os_memset(&params, 0, sizeof(params));
38         params.num_ssids = 1;
39         params.ssids[0].ssid = data->ssid->ssid;
40         params.ssids[0].ssid_len = data->ssid->ssid_len;
41         params.freqs = data->ssid->scan_freq;
42
43         /*
44          * A more advanced bgscan module would learn about most like channels
45          * over time and request scans only for some channels (probing others
46          * every now and then) to reduce effect on the data connection.
47          */
48
49         wpa_printf(MSG_DEBUG, "bgscan simple: Request a background scan");
50         if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
51                 wpa_printf(MSG_DEBUG, "bgscan simple: Failed to trigger scan");
52                 eloop_register_timeout(data->scan_interval, 0,
53                                        bgscan_simple_timeout, data, NULL);
54         }
55 }
56
57
58 static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
59                                  const char *params,
60                                  const struct wpa_ssid *ssid)
61 {
62         struct bgscan_simple_data *data;
63
64         data = os_zalloc(sizeof(*data));
65         if (data == NULL)
66                 return NULL;
67         data->wpa_s = wpa_s;
68         data->ssid = ssid;
69         if (params)
70                 data->scan_interval = atoi(params);
71         if (data->scan_interval <= 0)
72                 data->scan_interval = 30;
73         eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
74                                data, NULL);
75         return data;
76 }
77
78
79 static void bgscan_simple_deinit(void *priv)
80 {
81         struct bgscan_simple_data *data = priv;
82         eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
83         os_free(data);
84 }
85
86
87 static int bgscan_simple_notify_scan(void *priv)
88 {
89         struct bgscan_simple_data *data = priv;
90
91         wpa_printf(MSG_DEBUG, "bgscan simple: scan result notification");
92
93         eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
94         eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
95                                data, NULL);
96
97         /*
98          * A more advanced bgscan could process scan results internally, select
99          * the BSS and request roam if needed. This sample uses the existing
100          * BSS/ESS selection routine. Change this to return 1 if selection is
101          * done inside the bgscan module.
102          */
103
104         return 0;
105 }
106
107
108 static void bgscan_simple_notify_beacon_loss(void *priv)
109 {
110         wpa_printf(MSG_DEBUG, "bgscan simple: beacon loss");
111         /* TODO: speed up background scanning */
112 }
113
114
115 static void bgscan_simple_notify_signal_change(void *priv)
116 {
117         wpa_printf(MSG_DEBUG, "bgscan simple: signal level changed");
118         /* TODO: if signal strength dropped enough, speed up background
119          * scanning */
120 }
121
122
123 const struct bgscan_ops bgscan_simple_ops = {
124         .name = "simple",
125         .init = bgscan_simple_init,
126         .deinit = bgscan_simple_deinit,
127         .notify_scan = bgscan_simple_notify_scan,
128         .notify_beacon_loss = bgscan_simple_notify_beacon_loss,
129         .notify_signal_change = bgscan_simple_notify_signal_change,
130 };