2 * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
4 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
27 #include "ieee80211softmac_priv.h"
29 #include <net/iw_handler.h>
33 ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
34 struct iw_request_info *info,
35 union iwreq_data *data,
38 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
39 return ieee80211softmac_start_scan(sm);
41 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
44 /* if we're still scanning, return -EAGAIN so that userspace tools
45 * can get the complete scan results, otherwise return 0. */
47 ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
48 struct iw_request_info *info,
49 union iwreq_data *data,
53 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
55 spin_lock_irqsave(&sm->lock, flags);
57 spin_unlock_irqrestore(&sm->lock, flags);
60 spin_unlock_irqrestore(&sm->lock, flags);
61 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
63 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
66 ieee80211softmac_wx_set_essid(struct net_device *net_dev,
67 struct iw_request_info *info,
68 union iwreq_data *data,
71 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
75 spin_lock_irqsave(&sm->lock, flags);
77 sm->associnfo.static_essid = 0;
79 if (data->essid.flags && data->essid.length && extra /*required?*/) {
80 length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
82 memcpy(sm->associnfo.req_essid.data, extra, length);
83 sm->associnfo.static_essid = 1;
86 sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
88 /* set our requested ESSID length.
89 * If applicable, we have already copied the data in */
90 sm->associnfo.req_essid.len = length;
92 /* queue lower level code to do work (if necessary) */
93 schedule_work(&sm->associnfo.work);
95 spin_unlock_irqrestore(&sm->lock, flags);
98 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
101 ieee80211softmac_wx_get_essid(struct net_device *net_dev,
102 struct iw_request_info *info,
103 union iwreq_data *data,
106 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
109 /* avoid getting inconsistent information */
110 spin_lock_irqsave(&sm->lock, flags);
111 /* If all fails, return ANY (empty) */
112 data->essid.length = 0;
113 data->essid.flags = 0; /* active */
115 /* If we have a statically configured ESSID then return it */
116 if (sm->associnfo.static_essid) {
117 data->essid.length = sm->associnfo.req_essid.len;
118 data->essid.flags = 1; /* active */
119 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
122 /* If we're associating/associated, return that */
123 if (sm->associated || sm->associnfo.associating) {
124 data->essid.length = sm->associnfo.associate_essid.len;
125 data->essid.flags = 1; /* active */
126 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
128 spin_unlock_irqrestore(&sm->lock, flags);
131 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
134 ieee80211softmac_wx_set_rate(struct net_device *net_dev,
135 struct iw_request_info *info,
136 union iwreq_data *data,
139 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
140 struct ieee80211_device *ieee = mac->ieee;
142 s32 in_rate = data->bitrate.value;
148 /* FIXME: We don't correctly handle backing down to lower
149 rates, so 801.11g devices start off at 11M for now. People
150 can manually change it if they really need to, but 11M is
151 more reliable. Note similar logic in
152 ieee80211softmac_wx_set_rate() */
153 if (ieee->modulation & IEEE80211_CCK_MODULATION)
161 rate = IEEE80211_CCK_RATE_1MB;
164 rate = IEEE80211_CCK_RATE_2MB;
167 rate = IEEE80211_CCK_RATE_5MB;
170 rate = IEEE80211_CCK_RATE_11MB;
173 rate = IEEE80211_OFDM_RATE_6MB;
177 rate = IEEE80211_OFDM_RATE_9MB;
181 rate = IEEE80211_OFDM_RATE_12MB;
185 rate = IEEE80211_OFDM_RATE_18MB;
189 rate = IEEE80211_OFDM_RATE_24MB;
193 rate = IEEE80211_OFDM_RATE_36MB;
197 rate = IEEE80211_OFDM_RATE_48MB;
201 rate = IEEE80211_OFDM_RATE_54MB;
208 spin_lock_irqsave(&mac->lock, flags);
210 /* Check if correct modulation for this PHY. */
211 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
214 mac->txrates.default_rate = rate;
215 mac->txrates.default_fallback = lower_rate(mac, rate);
219 spin_unlock_irqrestore(&mac->lock, flags);
223 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
226 ieee80211softmac_wx_get_rate(struct net_device *net_dev,
227 struct iw_request_info *info,
228 union iwreq_data *data,
231 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
235 spin_lock_irqsave(&mac->lock, flags);
236 switch (mac->txrates.default_rate) {
237 case IEEE80211_CCK_RATE_1MB:
238 data->bitrate.value = 1000000;
240 case IEEE80211_CCK_RATE_2MB:
241 data->bitrate.value = 2000000;
243 case IEEE80211_CCK_RATE_5MB:
244 data->bitrate.value = 5500000;
246 case IEEE80211_CCK_RATE_11MB:
247 data->bitrate.value = 11000000;
249 case IEEE80211_OFDM_RATE_6MB:
250 data->bitrate.value = 6000000;
252 case IEEE80211_OFDM_RATE_9MB:
253 data->bitrate.value = 9000000;
255 case IEEE80211_OFDM_RATE_12MB:
256 data->bitrate.value = 12000000;
258 case IEEE80211_OFDM_RATE_18MB:
259 data->bitrate.value = 18000000;
261 case IEEE80211_OFDM_RATE_24MB:
262 data->bitrate.value = 24000000;
264 case IEEE80211_OFDM_RATE_36MB:
265 data->bitrate.value = 36000000;
267 case IEEE80211_OFDM_RATE_48MB:
268 data->bitrate.value = 48000000;
270 case IEEE80211_OFDM_RATE_54MB:
271 data->bitrate.value = 54000000;
279 spin_unlock_irqrestore(&mac->lock, flags);
283 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
286 ieee80211softmac_wx_get_wap(struct net_device *net_dev,
287 struct iw_request_info *info,
288 union iwreq_data *data,
291 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
295 spin_lock_irqsave(&mac->lock, flags);
296 if (mac->associnfo.bssvalid)
297 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
299 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
300 data->ap_addr.sa_family = ARPHRD_ETHER;
301 spin_unlock_irqrestore(&mac->lock, flags);
304 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
307 ieee80211softmac_wx_set_wap(struct net_device *net_dev,
308 struct iw_request_info *info,
309 union iwreq_data *data,
312 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
313 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
314 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
318 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
322 spin_lock_irqsave(&mac->lock, flags);
323 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
324 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
325 schedule_work(&mac->associnfo.work);
328 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
329 if (mac->associnfo.associating || mac->associated) {
330 /* bssid unchanged and associated or associating - just return */
334 /* copy new value in data->ap_addr.sa_data to bssid */
335 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
337 /* queue associate if new bssid or (old one again and not associated) */
338 schedule_work(&mac->associnfo.work);
342 spin_unlock_irqrestore(&mac->lock, flags);
345 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
348 ieee80211softmac_wx_set_genie(struct net_device *dev,
349 struct iw_request_info *info,
350 union iwreq_data *wrqu,
353 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
359 spin_lock_irqsave(&mac->lock, flags);
360 /* bleh. shouldn't be locked for that kmalloc... */
362 if (wrqu->data.length) {
363 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
364 /* this is an IE, so the length must be
365 * correct. Is it possible though that
366 * more than one IE is passed in?
371 if (mac->wpa.IEbuflen <= wrqu->data.length) {
372 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
379 mac->wpa.IEbuflen = wrqu->data.length;
381 memcpy(mac->wpa.IE, extra, wrqu->data.length);
382 dprintk(KERN_INFO PFX "generic IE set to ");
383 for (i=0;i<wrqu->data.length;i++)
384 dprintk("%.2x", mac->wpa.IE[i]);
386 mac->wpa.IElen = wrqu->data.length;
391 mac->wpa.IEbuflen = 0;
395 spin_unlock_irqrestore(&mac->lock, flags);
398 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
401 ieee80211softmac_wx_get_genie(struct net_device *dev,
402 struct iw_request_info *info,
403 union iwreq_data *wrqu,
406 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
409 int space = wrqu->data.length;
411 spin_lock_irqsave(&mac->lock, flags);
413 wrqu->data.length = 0;
415 if (mac->wpa.IE && mac->wpa.IElen) {
416 wrqu->data.length = mac->wpa.IElen;
417 if (mac->wpa.IElen <= space)
418 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
422 spin_unlock_irqrestore(&mac->lock, flags);
425 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);