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 /* FIXME: We don't correctly handle backing down to lower
139 rates, so 801.11g devices start off at 11M for now. People
140 can manually change it if they really need to, but 11M is
141 more reliable. Note similar logic in
142 ieee80211softmac_wx_set_rate() */
143 if (ieee->modulation & IEEE80211_CCK_MODULATION)
151 rate = IEEE80211_CCK_RATE_1MB;
154 rate = IEEE80211_CCK_RATE_2MB;
157 rate = IEEE80211_CCK_RATE_5MB;
160 rate = IEEE80211_CCK_RATE_11MB;
163 rate = IEEE80211_OFDM_RATE_6MB;
167 rate = IEEE80211_OFDM_RATE_9MB;
171 rate = IEEE80211_OFDM_RATE_12MB;
175 rate = IEEE80211_OFDM_RATE_18MB;
179 rate = IEEE80211_OFDM_RATE_24MB;
183 rate = IEEE80211_OFDM_RATE_36MB;
187 rate = IEEE80211_OFDM_RATE_48MB;
191 rate = IEEE80211_OFDM_RATE_54MB;
198 spin_lock_irqsave(&mac->lock, flags);
200 /* Check if correct modulation for this PHY. */
201 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
204 mac->txrates.default_rate = rate;
205 mac->txrates.default_fallback = lower_rate(mac, rate);
209 spin_unlock_irqrestore(&mac->lock, flags);
213 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
216 ieee80211softmac_wx_get_rate(struct net_device *net_dev,
217 struct iw_request_info *info,
218 union iwreq_data *data,
221 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
225 spin_lock_irqsave(&mac->lock, flags);
226 switch (mac->txrates.default_rate) {
227 case IEEE80211_CCK_RATE_1MB:
228 data->bitrate.value = 1000000;
230 case IEEE80211_CCK_RATE_2MB:
231 data->bitrate.value = 2000000;
233 case IEEE80211_CCK_RATE_5MB:
234 data->bitrate.value = 5500000;
236 case IEEE80211_CCK_RATE_11MB:
237 data->bitrate.value = 11000000;
239 case IEEE80211_OFDM_RATE_6MB:
240 data->bitrate.value = 6000000;
242 case IEEE80211_OFDM_RATE_9MB:
243 data->bitrate.value = 9000000;
245 case IEEE80211_OFDM_RATE_12MB:
246 data->bitrate.value = 12000000;
248 case IEEE80211_OFDM_RATE_18MB:
249 data->bitrate.value = 18000000;
251 case IEEE80211_OFDM_RATE_24MB:
252 data->bitrate.value = 24000000;
254 case IEEE80211_OFDM_RATE_36MB:
255 data->bitrate.value = 36000000;
257 case IEEE80211_OFDM_RATE_48MB:
258 data->bitrate.value = 48000000;
260 case IEEE80211_OFDM_RATE_54MB:
261 data->bitrate.value = 54000000;
269 spin_unlock_irqrestore(&mac->lock, flags);
273 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
276 ieee80211softmac_wx_get_wap(struct net_device *net_dev,
277 struct iw_request_info *info,
278 union iwreq_data *data,
281 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
285 spin_lock_irqsave(&mac->lock, flags);
286 if (mac->associnfo.bssvalid)
287 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
289 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
290 data->ap_addr.sa_family = ARPHRD_ETHER;
291 spin_unlock_irqrestore(&mac->lock, flags);
294 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
297 ieee80211softmac_wx_set_wap(struct net_device *net_dev,
298 struct iw_request_info *info,
299 union iwreq_data *data,
302 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
303 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
304 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
308 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
312 spin_lock_irqsave(&mac->lock, flags);
313 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
314 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
315 schedule_work(&mac->associnfo.work);
318 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
319 if (mac->associnfo.associating || mac->associated) {
320 /* bssid unchanged and associated or associating - just return */
324 /* copy new value in data->ap_addr.sa_data to bssid */
325 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
327 /* queue associate if new bssid or (old one again and not associated) */
328 schedule_work(&mac->associnfo.work);
332 spin_unlock_irqrestore(&mac->lock, flags);
335 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
338 ieee80211softmac_wx_set_genie(struct net_device *dev,
339 struct iw_request_info *info,
340 union iwreq_data *wrqu,
343 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
349 spin_lock_irqsave(&mac->lock, flags);
350 /* bleh. shouldn't be locked for that kmalloc... */
352 if (wrqu->data.length) {
353 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
354 /* this is an IE, so the length must be
355 * correct. Is it possible though that
356 * more than one IE is passed in?
361 if (mac->wpa.IEbuflen <= wrqu->data.length) {
362 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
369 mac->wpa.IEbuflen = wrqu->data.length;
371 memcpy(mac->wpa.IE, extra, wrqu->data.length);
372 dprintk(KERN_INFO PFX "generic IE set to ");
373 for (i=0;i<wrqu->data.length;i++)
374 dprintk("%.2x", mac->wpa.IE[i]);
376 mac->wpa.IElen = wrqu->data.length;
381 mac->wpa.IEbuflen = 0;
385 spin_unlock_irqrestore(&mac->lock, flags);
388 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
391 ieee80211softmac_wx_get_genie(struct net_device *dev,
392 struct iw_request_info *info,
393 union iwreq_data *wrqu,
396 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
399 int space = wrqu->data.length;
401 spin_lock_irqsave(&mac->lock, flags);
403 wrqu->data.length = 0;
405 if (mac->wpa.IE && mac->wpa.IElen) {
406 wrqu->data.length = mac->wpa.IElen;
407 if (mac->wpa.IElen <= space)
408 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
412 spin_unlock_irqrestore(&mac->lock, flags);
415 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);