OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [ieee80211/] [softmac/] [ieee80211softmac_scan.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Scanning routines.
3
 *
4
 * These are not exported because they're assigned to the function pointers.
5
 *
6
 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
7
 *                          Joseph Jezak <josejx@gentoo.org>
8
 *                          Larry Finger <Larry.Finger@lwfinger.net>
9
 *                          Danny van Dyk <kugelfang@gentoo.org>
10
 *                          Michael Buesch <mbuesch@freenet.de>
11
 *
12
 * This program is free software; you can redistribute it and/or modify it
13
 * under the terms of version 2 of the GNU General Public License as
14
 * published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
 * more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program; if not, write to the Free Software
23
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
24
 *
25
 * The full GNU General Public License is included in this distribution in the
26
 * file called COPYING.
27
 */
28
 
29
#include <linux/completion.h>
30
#include "ieee80211softmac_priv.h"
31
 
32
/* internal, use to trigger scanning if needed.
33
 * Returns -EBUSY if already scanning,
34
 * result of start_scan otherwise */
35
int
36
ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
37
{
38
        unsigned long flags;
39
        int ret;
40
 
41
        spin_lock_irqsave(&sm->lock, flags);
42
        if (sm->scanning)
43
        {
44
                spin_unlock_irqrestore(&sm->lock, flags);
45
                return -EINPROGRESS;
46
        }
47
        sm->scanning = 1;
48
        spin_unlock_irqrestore(&sm->lock, flags);
49
 
50
        ret = sm->start_scan(sm->dev);
51
        if (ret) {
52
                spin_lock_irqsave(&sm->lock, flags);
53
                sm->scanning = 0;
54
                spin_unlock_irqrestore(&sm->lock, flags);
55
        }
56
        return ret;
57
}
58
 
59
void
60
ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm)
61
{
62
        unsigned long flags;
63
 
64
        spin_lock_irqsave(&sm->lock, flags);
65
 
66
        if (!sm->scanning) {
67
                spin_unlock_irqrestore(&sm->lock, flags);
68
                return;
69
        }
70
 
71
        spin_unlock_irqrestore(&sm->lock, flags);
72
        sm->stop_scan(sm->dev);
73
}
74
 
75
void
76
ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm)
77
{
78
        unsigned long flags;
79
 
80
        spin_lock_irqsave(&sm->lock, flags);
81
 
82
        if (!sm->scanning) {
83
                spin_unlock_irqrestore(&sm->lock, flags);
84
                return;
85
        }
86
 
87
        spin_unlock_irqrestore(&sm->lock, flags);
88
        sm->wait_for_scan(sm->dev);
89
}
90
 
91
 
92
/* internal scanning implementation follows */
93
void ieee80211softmac_scan(struct work_struct *work)
94
{
95
        int invalid_channel;
96
        u8 current_channel_idx;
97
        struct ieee80211softmac_scaninfo *si =
98
                container_of(work, struct ieee80211softmac_scaninfo,
99
                             softmac_scan.work);
100
        struct ieee80211softmac_device *sm = si->mac;
101
        unsigned long flags;
102
 
103
        while (!(si->stop) && (si->current_channel_idx < si->number_channels)) {
104
                current_channel_idx = si->current_channel_idx;
105
                si->current_channel_idx++; /* go to the next channel */
106
 
107
                invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags);
108
 
109
                if (!invalid_channel) {
110
                        sm->set_channel(sm->dev, si->channels[current_channel_idx].channel);
111
                        // FIXME make this user configurable (active/passive)
112
                        if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0))
113
                                printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n");
114
 
115
                        /* also send directed management frame for the network we're looking for */
116
                        // TODO: is this if correct, or should we do this only if scanning from assoc request?
117
                        if (sm->associnfo.req_essid.len)
118
                                ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
119
 
120
                        spin_lock_irqsave(&sm->lock, flags);
121
                        if (unlikely(!sm->running)) {
122
                                /* Prevent reschedule on workqueue flush */
123
                                spin_unlock_irqrestore(&sm->lock, flags);
124
                                break;
125
                        }
126
                        queue_delayed_work(sm->wq, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
127
                        spin_unlock_irqrestore(&sm->lock, flags);
128
                        return;
129
                } else {
130
                        dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
131
                }
132
        }
133
 
134
        spin_lock_irqsave(&sm->lock, flags);
135
        cancel_delayed_work(&si->softmac_scan);
136
        si->started = 0;
137
        spin_unlock_irqrestore(&sm->lock, flags);
138
 
139
        dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n",
140
                     sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel);
141
        ieee80211softmac_scan_finished(sm);
142
        complete_all(&sm->scaninfo->finished);
143
}
144
 
145
static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac)
146
{
147
        /* ugh. can we call this without having the spinlock held? */
148
        struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC);
149
        if (unlikely(!info))
150
                return NULL;
151
        INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan);
152
        info->mac = mac;
153
        init_completion(&info->finished);
154
        return info;
155
}
156
 
157
int ieee80211softmac_start_scan_implementation(struct net_device *dev)
158
{
159
        struct ieee80211softmac_device *sm = ieee80211_priv(dev);
160
        unsigned long flags;
161
 
162
        if (!(dev->flags & IFF_UP))
163
                return -ENODEV;
164
 
165
        assert(ieee80211softmac_scan_handlers_check_self(sm));
166
        if (!ieee80211softmac_scan_handlers_check_self(sm))
167
                return -EINVAL;
168
 
169
        spin_lock_irqsave(&sm->lock, flags);
170
        /* it looks like we need to hold the lock here
171
         * to make sure we don't allocate two of these... */
172
        if (unlikely(!sm->scaninfo))
173
                sm->scaninfo = allocate_scaninfo(sm);
174
        if (unlikely(!sm->scaninfo)) {
175
                spin_unlock_irqrestore(&sm->lock, flags);
176
                return -ENOMEM;
177
        }
178
 
179
        sm->scaninfo->skip_flags = IEEE80211_CH_INVALID;
180
        if (0 /* not scanning in IEEE802.11b */)//TODO
181
                sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY;
182
        if (0 /* IEEE802.11a */) {//TODO
183
                sm->scaninfo->channels = sm->ieee->geo.a;
184
                sm->scaninfo->number_channels = sm->ieee->geo.a_channels;
185
        } else {
186
                sm->scaninfo->channels = sm->ieee->geo.bg;
187
                sm->scaninfo->number_channels = sm->ieee->geo.bg_channels;
188
        }
189
        sm->scaninfo->current_channel_idx = 0;
190
        sm->scaninfo->started = 1;
191
        sm->scaninfo->stop = 0;
192
        INIT_COMPLETION(sm->scaninfo->finished);
193
        queue_delayed_work(sm->wq, &sm->scaninfo->softmac_scan, 0);
194
        spin_unlock_irqrestore(&sm->lock, flags);
195
        return 0;
196
}
197
 
198
void ieee80211softmac_stop_scan_implementation(struct net_device *dev)
199
{
200
        struct ieee80211softmac_device *sm = ieee80211_priv(dev);
201
        unsigned long flags;
202
 
203
        assert(ieee80211softmac_scan_handlers_check_self(sm));
204
        if (!ieee80211softmac_scan_handlers_check_self(sm))
205
                return;
206
 
207
        spin_lock_irqsave(&sm->lock, flags);
208
        assert(sm->scaninfo != NULL);
209
        if (sm->scaninfo) {
210
                if (sm->scaninfo->started)
211
                        sm->scaninfo->stop = 1;
212
                else
213
                        complete_all(&sm->scaninfo->finished);
214
        }
215
        spin_unlock_irqrestore(&sm->lock, flags);
216
}
217
 
218
void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev)
219
{
220
        struct ieee80211softmac_device *sm = ieee80211_priv(dev);
221
        unsigned long flags;
222
 
223
        assert(ieee80211softmac_scan_handlers_check_self(sm));
224
        if (!ieee80211softmac_scan_handlers_check_self(sm))
225
                return;
226
 
227
        spin_lock_irqsave(&sm->lock, flags);
228
        if (!sm->scaninfo->started) {
229
                spin_unlock_irqrestore(&sm->lock, flags);
230
                return;
231
        }
232
        spin_unlock_irqrestore(&sm->lock, flags);
233
        wait_for_completion(&sm->scaninfo->finished);
234
}
235
 
236
/* this is what drivers (that do scanning) call when they're done */
237
void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
238
{
239
        unsigned long flags;
240
 
241
        spin_lock_irqsave(&sm->lock, flags);
242
        sm->scanning = 0;
243
        spin_unlock_irqrestore(&sm->lock, flags);
244
 
245
        if (sm->associnfo.bssvalid) {
246
                struct ieee80211softmac_network *net;
247
 
248
                net = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
249
                if (net)
250
                        sm->set_channel(sm->dev, net->channel);
251
        }
252
        ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
253
}
254
EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.