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);
45 ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
46 struct iw_request_info *info,
47 union iwreq_data *data,
50 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
51 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
53 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
56 ieee80211softmac_wx_set_essid(struct net_device *net_dev,
57 struct iw_request_info *info,
58 union iwreq_data *data,
61 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
65 spin_lock_irqsave(&sm->lock, flags);
67 sm->associnfo.static_essid = 0;
69 if (data->essid.flags && data->essid.length && extra /*required?*/) {
70 length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
72 memcpy(sm->associnfo.req_essid.data, extra, length);
73 sm->associnfo.static_essid = 1;
76 sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
78 /* set our requested ESSID length.
79 * If applicable, we have already copied the data in */
80 sm->associnfo.req_essid.len = length;
82 /* queue lower level code to do work (if necessary) */
83 schedule_work(&sm->associnfo.work);
85 spin_unlock_irqrestore(&sm->lock, flags);
88 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
91 ieee80211softmac_wx_get_essid(struct net_device *net_dev,
92 struct iw_request_info *info,
93 union iwreq_data *data,
96 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
99 /* avoid getting inconsistent information */
100 spin_lock_irqsave(&sm->lock, flags);
101 /* If all fails, return ANY (empty) */
102 data->essid.length = 0;
103 data->essid.flags = 0; /* active */
105 /* If we have a statically configured ESSID then return it */
106 if (sm->associnfo.static_essid) {
107 data->essid.length = sm->associnfo.req_essid.len;
108 data->essid.flags = 1; /* active */
109 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
112 /* If we're associating/associated, return that */
113 if (sm->associated || sm->associnfo.associating) {
114 data->essid.length = sm->associnfo.associate_essid.len;
115 data->essid.flags = 1; /* active */
116 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
118 spin_unlock_irqrestore(&sm->lock, flags);
121 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
124 ieee80211softmac_wx_set_rate(struct net_device *net_dev,
125 struct iw_request_info *info,
126 union iwreq_data *data,
129 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
130 struct ieee80211_device *ieee = mac->ieee;
132 s32 in_rate = data->bitrate.value;
138 /* automatic detect */
139 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
147 rate = IEEE80211_CCK_RATE_1MB;
150 rate = IEEE80211_CCK_RATE_2MB;
153 rate = IEEE80211_CCK_RATE_5MB;
156 rate = IEEE80211_CCK_RATE_11MB;
159 rate = IEEE80211_OFDM_RATE_6MB;
163 rate = IEEE80211_OFDM_RATE_9MB;
167 rate = IEEE80211_OFDM_RATE_12MB;
171 rate = IEEE80211_OFDM_RATE_18MB;
175 rate = IEEE80211_OFDM_RATE_24MB;
179 rate = IEEE80211_OFDM_RATE_36MB;
183 rate = IEEE80211_OFDM_RATE_48MB;
187 rate = IEEE80211_OFDM_RATE_54MB;
194 spin_lock_irqsave(&mac->lock, flags);
196 /* Check if correct modulation for this PHY. */
197 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
200 mac->txrates.default_rate = rate;
201 mac->txrates.default_fallback = lower_rate(mac, rate);
205 spin_unlock_irqrestore(&mac->lock, flags);
209 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
212 ieee80211softmac_wx_get_rate(struct net_device *net_dev,
213 struct iw_request_info *info,
214 union iwreq_data *data,
217 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
221 spin_lock_irqsave(&mac->lock, flags);
222 switch (mac->txrates.default_rate) {
223 case IEEE80211_CCK_RATE_1MB:
224 data->bitrate.value = 1000000;
226 case IEEE80211_CCK_RATE_2MB:
227 data->bitrate.value = 2000000;
229 case IEEE80211_CCK_RATE_5MB:
230 data->bitrate.value = 5500000;
232 case IEEE80211_CCK_RATE_11MB:
233 data->bitrate.value = 11000000;
235 case IEEE80211_OFDM_RATE_6MB:
236 data->bitrate.value = 6000000;
238 case IEEE80211_OFDM_RATE_9MB:
239 data->bitrate.value = 9000000;
241 case IEEE80211_OFDM_RATE_12MB:
242 data->bitrate.value = 12000000;
244 case IEEE80211_OFDM_RATE_18MB:
245 data->bitrate.value = 18000000;
247 case IEEE80211_OFDM_RATE_24MB:
248 data->bitrate.value = 24000000;
250 case IEEE80211_OFDM_RATE_36MB:
251 data->bitrate.value = 36000000;
253 case IEEE80211_OFDM_RATE_48MB:
254 data->bitrate.value = 48000000;
256 case IEEE80211_OFDM_RATE_54MB:
257 data->bitrate.value = 54000000;
265 spin_unlock_irqrestore(&mac->lock, flags);
269 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
272 ieee80211softmac_wx_get_wap(struct net_device *net_dev,
273 struct iw_request_info *info,
274 union iwreq_data *data,
277 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
281 spin_lock_irqsave(&mac->lock, flags);
282 if (mac->associnfo.bssvalid)
283 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
285 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
286 data->ap_addr.sa_family = ARPHRD_ETHER;
287 spin_unlock_irqrestore(&mac->lock, flags);
290 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
293 ieee80211softmac_wx_set_wap(struct net_device *net_dev,
294 struct iw_request_info *info,
295 union iwreq_data *data,
298 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
299 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
300 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
304 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
308 spin_lock_irqsave(&mac->lock, flags);
309 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
310 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
311 schedule_work(&mac->associnfo.work);
314 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
315 if (mac->associnfo.associating || mac->associated) {
316 /* bssid unchanged and associated or associating - just return */
320 /* copy new value in data->ap_addr.sa_data to bssid */
321 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
323 /* queue associate if new bssid or (old one again and not associated) */
324 schedule_work(&mac->associnfo.work);
328 spin_unlock_irqrestore(&mac->lock, flags);
331 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
334 ieee80211softmac_wx_set_genie(struct net_device *dev,
335 struct iw_request_info *info,
336 union iwreq_data *wrqu,
339 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
345 spin_lock_irqsave(&mac->lock, flags);
346 /* bleh. shouldn't be locked for that kmalloc... */
348 if (wrqu->data.length) {
349 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
350 /* this is an IE, so the length must be
351 * correct. Is it possible though that
352 * more than one IE is passed in?
357 if (mac->wpa.IEbuflen <= wrqu->data.length) {
358 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
365 mac->wpa.IEbuflen = wrqu->data.length;
367 memcpy(mac->wpa.IE, extra, wrqu->data.length);
368 dprintk(KERN_INFO PFX "generic IE set to ");
369 for (i=0;i<wrqu->data.length;i++)
370 dprintk("%.2x", mac->wpa.IE[i]);
372 mac->wpa.IElen = wrqu->data.length;
377 mac->wpa.IEbuflen = 0;
381 spin_unlock_irqrestore(&mac->lock, flags);
384 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
387 ieee80211softmac_wx_get_genie(struct net_device *dev,
388 struct iw_request_info *info,
389 union iwreq_data *wrqu,
392 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
395 int space = wrqu->data.length;
397 spin_lock_irqsave(&mac->lock, flags);
399 wrqu->data.length = 0;
401 if (mac->wpa.IE && mac->wpa.IElen) {
402 wrqu->data.length = mac->wpa.IElen;
403 if (mac->wpa.IElen <= space)
404 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
408 spin_unlock_irqrestore(&mac->lock, flags);
411 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);