debugfs: Modified default dir of debugfs for debugging UHCI.
[linux/fpc-iii.git] / drivers / staging / wlan-ng / p80211wext.c
blob984e45d9f700b6de1c61475bd6fc9f3cf9a4c173
1 /* src/p80211/p80211wext.c
3 * Glue code to make linux-wlan-ng a happy wireless extension camper.
5 * original author: Reyk Floeter <reyk@synack.de>
6 * Completely re-written by Solomon Peachy <solomon@linux-wlan.com>
8 * Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.
9 * --------------------------------------------------------------------
11 * linux-wlan
13 * The contents of this file are subject to the Mozilla Public
14 * License Version 1.1 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.mozilla.org/MPL/
18 * Software distributed under the License is distributed on an "AS
19 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
20 * implied. See the License for the specific language governing
21 * rights and limitations under the License.
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU Public License version 2 (the "GPL"), in which
25 * case the provisions of the GPL are applicable instead of the
26 * above. If you wish to allow the use of your version of this file
27 * only under the terms of the GPL and not to allow others to use
28 * your version of this file under the MPL, indicate your decision
29 * by deleting the provisions above and replace them with the notice
30 * and other provisions required by the GPL. If you do not delete
31 * the provisions above, a recipient may use your version of this
32 * file under either the MPL or the GPL.
34 * --------------------------------------------------------------------
37 /*================================================================*/
38 /* System Includes */
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 #include <linux/types.h>
43 #include <linux/slab.h>
44 #include <linux/netdevice.h>
45 #include <linux/etherdevice.h>
46 #include <linux/wireless.h>
47 #include <net/iw_handler.h>
48 #include <linux/if_arp.h>
49 #include <asm/bitops.h>
50 #include <asm/uaccess.h>
51 #include <asm/byteorder.h>
52 #include <linux/if_ether.h>
53 #include <linux/bitops.h>
55 /*================================================================*/
56 /* Project Includes */
58 #include "p80211types.h"
59 #include "p80211hdr.h"
60 #include "p80211conv.h"
61 #include "p80211mgmt.h"
62 #include "p80211msg.h"
63 #include "p80211metastruct.h"
64 #include "p80211metadef.h"
65 #include "p80211netdev.h"
66 #include "p80211ioctl.h"
67 #include "p80211req.h"
69 static int p80211wext_giwrate(netdevice_t * dev,
70 struct iw_request_info *info,
71 struct iw_param *rrq, char *extra);
72 static int p80211wext_giwessid(netdevice_t * dev,
73 struct iw_request_info *info,
74 struct iw_point *data, char *essid);
76 static u8 p80211_mhz_to_channel(u16 mhz)
78 if (mhz >= 5000)
79 return (mhz - 5000) / 5;
81 if (mhz == 2482)
82 return 14;
84 if (mhz >= 2407)
85 return (mhz - 2407) / 5;
87 return 0;
90 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
93 if (ch == 0)
94 return 0;
95 if (ch > 200)
96 return 0;
98 /* 5G */
99 if (dot11a)
100 return 5000 + (5 * ch);
102 /* 2.4G */
103 if (ch == 14)
104 return 2484;
106 if ((ch < 14) && (ch > 0))
107 return 2407 + (5 * ch);
109 return 0;
112 /* taken from orinoco.c ;-) */
113 static const long p80211wext_channel_freq[] = {
114 2412, 2417, 2422, 2427, 2432, 2437, 2442,
115 2447, 2452, 2457, 2462, 2467, 2472, 2484
118 #define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq)
120 /* steal a spare bit to store the shared/opensystems state.
121 should default to open if not set */
122 #define HOSTWEP_SHAREDKEY BIT(3)
124 static int qual_as_percent(int snr)
126 if (snr <= 0)
127 return 0;
128 if (snr <= 40)
129 return snr * 5 / 2;
130 return 100;
133 static int p80211wext_dorequest(wlandevice_t * wlandev, u32 did, u32 data)
135 p80211msg_dot11req_mibset_t msg;
136 p80211item_uint32_t mibitem;
137 int result;
139 msg.msgcode = DIDmsg_dot11req_mibset;
140 mibitem.did = did;
141 mibitem.data = data;
142 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
143 result = p80211req_dorequest(wlandev, (u8 *) & msg);
145 return result;
148 static int p80211wext_autojoin(wlandevice_t * wlandev)
150 p80211msg_lnxreq_autojoin_t msg;
151 struct iw_point data;
152 char ssid[IW_ESSID_MAX_SIZE];
154 int result;
155 int err = 0;
157 /* Get ESSID */
158 result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
160 if (result) {
161 err = -EFAULT;
162 goto exit;
165 if (wlandev->hostwep & HOSTWEP_SHAREDKEY)
166 msg.authtype.data = P80211ENUM_authalg_sharedkey;
167 else
168 msg.authtype.data = P80211ENUM_authalg_opensystem;
170 msg.msgcode = DIDmsg_lnxreq_autojoin;
172 /* Trim the last '\0' to fit the SSID format */
174 if (data.length && ssid[data.length - 1] == '\0')
175 data.length = data.length - 1;
177 memcpy(msg.ssid.data.data, ssid, data.length);
178 msg.ssid.data.len = data.length;
180 result = p80211req_dorequest(wlandev, (u8 *) & msg);
182 if (result) {
183 err = -EFAULT;
184 goto exit;
187 exit:
189 return err;
193 /* called by /proc/net/wireless */
194 struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t * dev)
196 p80211msg_lnxreq_commsquality_t quality;
197 wlandevice_t *wlandev = dev->ml_priv;
198 struct iw_statistics *wstats = &wlandev->wstats;
199 int retval;
201 /* Check */
202 if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
203 return NULL;
205 /* XXX Only valid in station mode */
206 wstats->status = 0;
208 /* build request message */
209 quality.msgcode = DIDmsg_lnxreq_commsquality;
210 quality.dbm.data = P80211ENUM_truth_true;
211 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
213 /* send message to nsd */
214 if (wlandev->mlmerequest == NULL)
215 return NULL;
217 retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) & quality);
219 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
220 wstats->qual.level = quality.level.data; /* instant signal level */
221 wstats->qual.noise = quality.noise.data; /* instant noise level */
223 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
224 wstats->discard.code = wlandev->rx.decrypt_err;
225 wstats->discard.nwid = 0;
226 wstats->discard.misc = 0;
228 wstats->discard.fragment = 0; /* incomplete fragments */
229 wstats->discard.retries = 0; /* tx retries. */
230 wstats->miss.beacon = 0;
232 return wstats;
235 static int p80211wext_giwname(netdevice_t * dev,
236 struct iw_request_info *info,
237 char *name, char *extra)
239 struct iw_param rate;
240 int result;
241 int err = 0;
243 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
245 if (result) {
246 err = -EFAULT;
247 goto exit;
250 switch (rate.value) {
251 case 1000000:
252 case 2000000:
253 strcpy(name, "IEEE 802.11-DS");
254 break;
255 case 5500000:
256 case 11000000:
257 strcpy(name, "IEEE 802.11-b");
258 break;
260 exit:
261 return err;
264 static int p80211wext_giwfreq(netdevice_t * dev,
265 struct iw_request_info *info,
266 struct iw_freq *freq, char *extra)
268 wlandevice_t *wlandev = dev->ml_priv;
269 p80211item_uint32_t mibitem;
270 p80211msg_dot11req_mibset_t msg;
271 int result;
272 int err = 0;
274 msg.msgcode = DIDmsg_dot11req_mibget;
275 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
276 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
277 result = p80211req_dorequest(wlandev, (u8 *) & msg);
279 if (result) {
280 err = -EFAULT;
281 goto exit;
284 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
286 if (mibitem.data > NUM_CHANNELS) {
287 err = -EFAULT;
288 goto exit;
291 /* convert into frequency instead of a channel */
292 freq->e = 1;
293 freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
295 exit:
296 return err;
299 static int p80211wext_siwfreq(netdevice_t * dev,
300 struct iw_request_info *info,
301 struct iw_freq *freq, char *extra)
303 wlandevice_t *wlandev = dev->ml_priv;
304 p80211item_uint32_t mibitem;
305 p80211msg_dot11req_mibset_t msg;
306 int result;
307 int err = 0;
309 if (!wlan_wext_write) {
310 err = (-EOPNOTSUPP);
311 goto exit;
314 msg.msgcode = DIDmsg_dot11req_mibset;
315 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
316 mibitem.status = P80211ENUM_msgitem_status_data_ok;
318 if ((freq->e == 0) && (freq->m <= 1000))
319 mibitem.data = freq->m;
320 else
321 mibitem.data = p80211_mhz_to_channel(freq->m);
323 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
324 result = p80211req_dorequest(wlandev, (u8 *) & msg);
326 if (result) {
327 err = -EFAULT;
328 goto exit;
331 exit:
332 return err;
335 static int p80211wext_giwmode(netdevice_t * dev,
336 struct iw_request_info *info,
337 __u32 * mode, char *extra)
339 wlandevice_t *wlandev = dev->ml_priv;
341 switch (wlandev->macmode) {
342 case WLAN_MACMODE_IBSS_STA:
343 *mode = IW_MODE_ADHOC;
344 break;
345 case WLAN_MACMODE_ESS_STA:
346 *mode = IW_MODE_INFRA;
347 break;
348 case WLAN_MACMODE_ESS_AP:
349 *mode = IW_MODE_MASTER;
350 break;
351 default:
352 /* Not set yet. */
353 *mode = IW_MODE_AUTO;
356 return 0;
359 static int p80211wext_siwmode(netdevice_t * dev,
360 struct iw_request_info *info,
361 __u32 * mode, char *extra)
363 wlandevice_t *wlandev = dev->ml_priv;
364 p80211item_uint32_t mibitem;
365 p80211msg_dot11req_mibset_t msg;
366 int result;
367 int err = 0;
369 if (!wlan_wext_write) {
370 err = (-EOPNOTSUPP);
371 goto exit;
374 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
375 *mode != IW_MODE_MASTER) {
376 err = (-EOPNOTSUPP);
377 goto exit;
380 /* Operation mode is the same with current mode */
381 if (*mode == wlandev->macmode)
382 goto exit;
384 switch (*mode) {
385 case IW_MODE_ADHOC:
386 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
387 break;
388 case IW_MODE_INFRA:
389 wlandev->macmode = WLAN_MACMODE_ESS_STA;
390 break;
391 case IW_MODE_MASTER:
392 wlandev->macmode = WLAN_MACMODE_ESS_AP;
393 break;
394 default:
395 /* Not set yet. */
396 printk(KERN_INFO "Operation mode: %d not support\n", *mode);
397 return -EOPNOTSUPP;
400 /* Set Operation mode to the PORT TYPE RID */
401 msg.msgcode = DIDmsg_dot11req_mibset;
402 mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
403 mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
404 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
405 result = p80211req_dorequest(wlandev, (u8 *) & msg);
407 if (result)
408 err = -EFAULT;
410 exit:
411 return err;
414 static int p80211wext_giwrange(netdevice_t * dev,
415 struct iw_request_info *info,
416 struct iw_point *data, char *extra)
418 struct iw_range *range = (struct iw_range *)extra;
419 int i, val;
421 /* for backward compatability set size and zero everything we don't understand */
422 data->length = sizeof(*range);
423 memset(range, 0, sizeof(*range));
425 range->txpower_capa = IW_TXPOW_DBM;
426 /* XXX what about min/max_pmp, min/max_pmt, etc. */
428 range->we_version_compiled = WIRELESS_EXT;
429 range->we_version_source = 13;
431 range->retry_capa = IW_RETRY_LIMIT;
432 range->retry_flags = IW_RETRY_LIMIT;
433 range->min_retry = 0;
434 range->max_retry = 255;
436 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | /* mode/freq/ssid */
437 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
438 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
439 range->event_capa[1] = IW_EVENT_CAPA_K_1; /* encode */
440 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
441 IW_EVENT_CAPA_MASK(IWEVCUSTOM));
443 range->num_channels = NUM_CHANNELS;
445 /* XXX need to filter against the regulatory domain &| active set */
446 val = 0;
447 for (i = 0; i < NUM_CHANNELS; i++) {
448 range->freq[val].i = i + 1;
449 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
450 range->freq[val].e = 1;
451 val++;
454 range->num_frequency = val;
456 /* Max of /proc/net/wireless */
457 range->max_qual.qual = 100;
458 range->max_qual.level = 0;
459 range->max_qual.noise = 0;
460 range->sensitivity = 3;
461 /* XXX these need to be nsd-specific! */
463 range->min_rts = 0;
464 range->max_rts = 2347;
465 range->min_frag = 256;
466 range->max_frag = 2346;
468 range->max_encoding_tokens = NUM_WEPKEYS;
469 range->num_encoding_sizes = 2;
470 range->encoding_size[0] = 5;
471 range->encoding_size[1] = 13;
473 /* XXX what about num_bitrates/throughput? */
474 range->num_bitrates = 0;
476 /* estimated max throughput */
477 /* XXX need to cap it if we're running at ~2Mbps.. */
478 range->throughput = 5500000;
480 return 0;
483 static int p80211wext_giwap(netdevice_t * dev,
484 struct iw_request_info *info,
485 struct sockaddr *ap_addr, char *extra)
488 wlandevice_t *wlandev = dev->ml_priv;
490 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
491 ap_addr->sa_family = ARPHRD_ETHER;
493 return 0;
496 static int p80211wext_giwencode(netdevice_t * dev,
497 struct iw_request_info *info,
498 struct iw_point *erq, char *key)
500 wlandevice_t *wlandev = dev->ml_priv;
501 int err = 0;
502 int i;
504 i = (erq->flags & IW_ENCODE_INDEX) - 1;
505 erq->flags = 0;
507 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
508 erq->flags |= IW_ENCODE_ENABLED;
509 else
510 erq->flags |= IW_ENCODE_DISABLED;
512 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
513 erq->flags |= IW_ENCODE_RESTRICTED;
514 else
515 erq->flags |= IW_ENCODE_OPEN;
517 i = (erq->flags & IW_ENCODE_INDEX) - 1;
519 if (i == -1)
520 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
522 if ((i < 0) || (i >= NUM_WEPKEYS)) {
523 err = -EINVAL;
524 goto exit;
527 erq->flags |= i + 1;
529 /* copy the key from the driver cache as the keys are read-only MIBs */
530 erq->length = wlandev->wep_keylens[i];
531 memcpy(key, wlandev->wep_keys[i], erq->length);
533 exit:
534 return err;
537 static int p80211wext_siwencode(netdevice_t * dev,
538 struct iw_request_info *info,
539 struct iw_point *erq, char *key)
541 wlandevice_t *wlandev = dev->ml_priv;
542 p80211msg_dot11req_mibset_t msg;
543 p80211item_pstr32_t pstr;
545 int err = 0;
546 int result = 0;
547 int i;
549 if (!wlan_wext_write) {
550 err = (-EOPNOTSUPP);
551 goto exit;
554 /* Check the Key index first. */
555 if ((i = (erq->flags & IW_ENCODE_INDEX))) {
557 if ((i < 1) || (i > NUM_WEPKEYS)) {
558 err = -EINVAL;
559 goto exit;
560 } else
561 i--;
563 /* Set current key number only if no keys are given */
564 if (erq->flags & IW_ENCODE_NOKEY) {
565 result =
566 p80211wext_dorequest(wlandev,
567 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
570 if (result) {
571 err = -EFAULT;
572 goto exit;
576 } else {
577 /* Use defaultkey if no Key Index */
578 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
581 /* Check if there is no key information in the iwconfig request */
582 if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
584 /*------------------------------------------------------------
585 * If there is WEP Key for setting, check the Key Information
586 * and then set it to the firmware.
587 -------------------------------------------------------------*/
589 if (erq->length > 0) {
591 /* copy the key from the driver cache as the keys are read-only MIBs */
592 wlandev->wep_keylens[i] = erq->length;
593 memcpy(wlandev->wep_keys[i], key, erq->length);
595 /* Prepare data struture for p80211req_dorequest. */
596 memcpy(pstr.data.data, key, erq->length);
597 pstr.data.len = erq->length;
599 switch (i) {
600 case 0:
601 pstr.did =
602 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
603 break;
605 case 1:
606 pstr.did =
607 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
608 break;
610 case 2:
611 pstr.did =
612 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
613 break;
615 case 3:
616 pstr.did =
617 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
618 break;
620 default:
621 err = -EINVAL;
622 goto exit;
625 msg.msgcode = DIDmsg_dot11req_mibset;
626 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
627 result = p80211req_dorequest(wlandev, (u8 *) & msg);
629 if (result) {
630 err = -EFAULT;
631 goto exit;
637 /* Check the PrivacyInvoked flag */
638 if (erq->flags & IW_ENCODE_DISABLED) {
639 result =
640 p80211wext_dorequest(wlandev,
641 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
642 P80211ENUM_truth_false);
643 } else {
644 result =
645 p80211wext_dorequest(wlandev,
646 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
647 P80211ENUM_truth_true);
650 if (result) {
651 err = -EFAULT;
652 goto exit;
655 /* The security mode may be open or restricted, and its meaning
656 depends on the card used. With most cards, in open mode no
657 authentication is used and the card may also accept non-
658 encrypted sessions, whereas in restricted mode only encrypted
659 sessions are accepted and the card will use authentication if
660 available.
662 if (erq->flags & IW_ENCODE_RESTRICTED) {
663 result =
664 p80211wext_dorequest(wlandev,
665 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
666 P80211ENUM_truth_true);
667 } else if (erq->flags & IW_ENCODE_OPEN) {
668 result =
669 p80211wext_dorequest(wlandev,
670 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
671 P80211ENUM_truth_false);
674 if (result) {
675 err = -EFAULT;
676 goto exit;
679 exit:
681 return err;
684 static int p80211wext_giwessid(netdevice_t * dev,
685 struct iw_request_info *info,
686 struct iw_point *data, char *essid)
688 wlandevice_t *wlandev = dev->ml_priv;
690 if (wlandev->ssid.len) {
691 data->length = wlandev->ssid.len;
692 data->flags = 1;
693 memcpy(essid, wlandev->ssid.data, data->length);
694 essid[data->length] = 0;
695 #if (WIRELESS_EXT < 21)
696 data->length++;
697 #endif
698 } else {
699 memset(essid, 0, sizeof(wlandev->ssid.data));
700 data->length = 0;
701 data->flags = 0;
704 return 0;
707 static int p80211wext_siwessid(netdevice_t * dev,
708 struct iw_request_info *info,
709 struct iw_point *data, char *essid)
711 wlandevice_t *wlandev = dev->ml_priv;
712 p80211msg_lnxreq_autojoin_t msg;
714 int result;
715 int err = 0;
716 int length = data->length;
718 if (!wlan_wext_write) {
719 err = (-EOPNOTSUPP);
720 goto exit;
723 if (wlandev->hostwep & HOSTWEP_SHAREDKEY)
724 msg.authtype.data = P80211ENUM_authalg_sharedkey;
725 else
726 msg.authtype.data = P80211ENUM_authalg_opensystem;
728 msg.msgcode = DIDmsg_lnxreq_autojoin;
730 #if (WIRELESS_EXT < 21)
731 if (length)
732 length--;
733 #endif
735 /* Trim the last '\0' to fit the SSID format */
736 if (length && essid[length - 1] == '\0')
737 length--;
739 memcpy(msg.ssid.data.data, essid, length);
740 msg.ssid.data.len = length;
742 pr_debug("autojoin_ssid for %s \n", essid);
743 result = p80211req_dorequest(wlandev, (u8 *) & msg);
744 pr_debug("autojoin_ssid %d\n", result);
746 if (result) {
747 err = -EFAULT;
748 goto exit;
751 exit:
752 return err;
755 static int p80211wext_siwcommit(netdevice_t * dev,
756 struct iw_request_info *info,
757 struct iw_point *data, char *essid)
759 wlandevice_t *wlandev = dev->ml_priv;
760 int err = 0;
762 if (!wlan_wext_write) {
763 err = (-EOPNOTSUPP);
764 goto exit;
767 /* Auto Join */
768 err = p80211wext_autojoin(wlandev);
770 exit:
771 return err;
774 static int p80211wext_giwrate(netdevice_t * dev,
775 struct iw_request_info *info,
776 struct iw_param *rrq, char *extra)
778 wlandevice_t *wlandev = dev->ml_priv;
779 p80211item_uint32_t mibitem;
780 p80211msg_dot11req_mibset_t msg;
781 int result;
782 int err = 0;
784 msg.msgcode = DIDmsg_dot11req_mibget;
785 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
786 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
787 result = p80211req_dorequest(wlandev, (u8 *) & msg);
789 if (result) {
790 err = -EFAULT;
791 goto exit;
794 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
796 rrq->fixed = 0; /* can it change? */
797 rrq->disabled = 0;
798 rrq->value = 0;
800 #define HFA384x_RATEBIT_1 ((u16)1)
801 #define HFA384x_RATEBIT_2 ((u16)2)
802 #define HFA384x_RATEBIT_5dot5 ((u16)4)
803 #define HFA384x_RATEBIT_11 ((u16)8)
805 switch (mibitem.data) {
806 case HFA384x_RATEBIT_1:
807 rrq->value = 1000000;
808 break;
809 case HFA384x_RATEBIT_2:
810 rrq->value = 2000000;
811 break;
812 case HFA384x_RATEBIT_5dot5:
813 rrq->value = 5500000;
814 break;
815 case HFA384x_RATEBIT_11:
816 rrq->value = 11000000;
817 break;
818 default:
819 err = -EINVAL;
821 exit:
822 return err;
825 static int p80211wext_giwrts(netdevice_t * dev,
826 struct iw_request_info *info,
827 struct iw_param *rts, char *extra)
829 wlandevice_t *wlandev = dev->ml_priv;
830 p80211item_uint32_t mibitem;
831 p80211msg_dot11req_mibset_t msg;
832 int result;
833 int err = 0;
835 msg.msgcode = DIDmsg_dot11req_mibget;
836 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
837 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
838 result = p80211req_dorequest(wlandev, (u8 *) & msg);
840 if (result) {
841 err = -EFAULT;
842 goto exit;
845 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
847 rts->value = mibitem.data;
848 rts->disabled = (rts->value == 2347);
849 rts->fixed = 1;
851 exit:
852 return err;
855 static int p80211wext_siwrts(netdevice_t * dev,
856 struct iw_request_info *info,
857 struct iw_param *rts, char *extra)
859 wlandevice_t *wlandev = dev->ml_priv;
860 p80211item_uint32_t mibitem;
861 p80211msg_dot11req_mibset_t msg;
862 int result;
863 int err = 0;
865 if (!wlan_wext_write) {
866 err = (-EOPNOTSUPP);
867 goto exit;
870 msg.msgcode = DIDmsg_dot11req_mibget;
871 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
872 if (rts->disabled)
873 mibitem.data = 2347;
874 else
875 mibitem.data = rts->value;
877 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
878 result = p80211req_dorequest(wlandev, (u8 *) & msg);
880 if (result) {
881 err = -EFAULT;
882 goto exit;
885 exit:
886 return err;
889 static int p80211wext_giwfrag(netdevice_t * dev,
890 struct iw_request_info *info,
891 struct iw_param *frag, char *extra)
893 wlandevice_t *wlandev = dev->ml_priv;
894 p80211item_uint32_t mibitem;
895 p80211msg_dot11req_mibset_t msg;
896 int result;
897 int err = 0;
899 msg.msgcode = DIDmsg_dot11req_mibget;
900 mibitem.did =
901 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
902 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
903 result = p80211req_dorequest(wlandev, (u8 *) & msg);
905 if (result) {
906 err = -EFAULT;
907 goto exit;
910 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
912 frag->value = mibitem.data;
913 frag->disabled = (frag->value == 2346);
914 frag->fixed = 1;
916 exit:
917 return err;
920 static int p80211wext_siwfrag(netdevice_t * dev,
921 struct iw_request_info *info,
922 struct iw_param *frag, char *extra)
924 wlandevice_t *wlandev = dev->ml_priv;
925 p80211item_uint32_t mibitem;
926 p80211msg_dot11req_mibset_t msg;
927 int result;
928 int err = 0;
930 if (!wlan_wext_write) {
931 err = (-EOPNOTSUPP);
932 goto exit;
935 msg.msgcode = DIDmsg_dot11req_mibset;
936 mibitem.did =
937 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
939 if (frag->disabled)
940 mibitem.data = 2346;
941 else
942 mibitem.data = frag->value;
944 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
945 result = p80211req_dorequest(wlandev, (u8 *) & msg);
947 if (result) {
948 err = -EFAULT;
949 goto exit;
952 exit:
953 return err;
956 #ifndef IW_RETRY_LONG
957 #define IW_RETRY_LONG IW_RETRY_MAX
958 #endif
960 #ifndef IW_RETRY_SHORT
961 #define IW_RETRY_SHORT IW_RETRY_MIN
962 #endif
964 static int p80211wext_giwretry(netdevice_t * dev,
965 struct iw_request_info *info,
966 struct iw_param *rrq, char *extra)
968 wlandevice_t *wlandev = dev->ml_priv;
969 p80211item_uint32_t mibitem;
970 p80211msg_dot11req_mibset_t msg;
971 int result;
972 int err = 0;
973 u16 shortretry, longretry, lifetime;
975 msg.msgcode = DIDmsg_dot11req_mibget;
976 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
978 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
979 result = p80211req_dorequest(wlandev, (u8 *) & msg);
981 if (result) {
982 err = -EFAULT;
983 goto exit;
986 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
988 shortretry = mibitem.data;
990 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
992 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
993 result = p80211req_dorequest(wlandev, (u8 *) & msg);
995 if (result) {
996 err = -EFAULT;
997 goto exit;
1000 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1002 longretry = mibitem.data;
1004 mibitem.did =
1005 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1007 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1008 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1010 if (result) {
1011 err = -EFAULT;
1012 goto exit;
1015 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1017 lifetime = mibitem.data;
1019 rrq->disabled = 0;
1021 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1022 rrq->flags = IW_RETRY_LIFETIME;
1023 rrq->value = lifetime * 1024;
1024 } else {
1025 if (rrq->flags & IW_RETRY_LONG) {
1026 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1027 rrq->value = longretry;
1028 } else {
1029 rrq->flags = IW_RETRY_LIMIT;
1030 rrq->value = shortretry;
1031 if (shortretry != longretry)
1032 rrq->flags |= IW_RETRY_SHORT;
1036 exit:
1037 return err;
1041 static int p80211wext_siwretry(netdevice_t * dev,
1042 struct iw_request_info *info,
1043 struct iw_param *rrq, char *extra)
1045 wlandevice_t *wlandev = dev->ml_priv;
1046 p80211item_uint32_t mibitem;
1047 p80211msg_dot11req_mibset_t msg;
1048 int result;
1049 int err = 0;
1051 if (!wlan_wext_write) {
1052 err = (-EOPNOTSUPP);
1053 goto exit;
1056 if (rrq->disabled) {
1057 err = -EINVAL;
1058 goto exit;
1061 msg.msgcode = DIDmsg_dot11req_mibset;
1063 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1064 mibitem.did =
1065 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1066 mibitem.data = rrq->value /= 1024;
1068 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1069 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1071 if (result) {
1072 err = -EFAULT;
1073 goto exit;
1075 } else {
1076 if (rrq->flags & IW_RETRY_LONG) {
1077 mibitem.did =
1078 DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1079 mibitem.data = rrq->value;
1081 memcpy(&msg.mibattribute.data, &mibitem,
1082 sizeof(mibitem));
1083 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1085 if (result) {
1086 err = -EFAULT;
1087 goto exit;
1091 if (rrq->flags & IW_RETRY_SHORT) {
1092 mibitem.did =
1093 DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1094 mibitem.data = rrq->value;
1096 memcpy(&msg.mibattribute.data, &mibitem,
1097 sizeof(mibitem));
1098 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1100 if (result) {
1101 err = -EFAULT;
1102 goto exit;
1107 exit:
1108 return err;
1112 static int p80211wext_siwtxpow(netdevice_t * dev,
1113 struct iw_request_info *info,
1114 struct iw_param *rrq, char *extra)
1116 wlandevice_t *wlandev = dev->ml_priv;
1117 p80211item_uint32_t mibitem;
1118 p80211msg_dot11req_mibset_t msg;
1119 int result;
1120 int err = 0;
1122 if (!wlan_wext_write) {
1123 err = (-EOPNOTSUPP);
1124 goto exit;
1127 msg.msgcode = DIDmsg_dot11req_mibset;
1128 mibitem.did =
1129 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1130 if (rrq->fixed == 0)
1131 mibitem.data = 30;
1132 else
1133 mibitem.data = rrq->value;
1134 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1135 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1137 if (result) {
1138 err = -EFAULT;
1139 goto exit;
1142 exit:
1143 return err;
1146 static int p80211wext_giwtxpow(netdevice_t * dev,
1147 struct iw_request_info *info,
1148 struct iw_param *rrq, char *extra)
1150 wlandevice_t *wlandev = dev->ml_priv;
1151 p80211item_uint32_t mibitem;
1152 p80211msg_dot11req_mibset_t msg;
1153 int result;
1154 int err = 0;
1156 msg.msgcode = DIDmsg_dot11req_mibget;
1157 mibitem.did =
1158 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1160 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1161 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1163 if (result) {
1164 err = -EFAULT;
1165 goto exit;
1168 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1170 /* XXX handle OFF by setting disabled = 1; */
1172 rrq->flags = 0; /* IW_TXPOW_DBM; */
1173 rrq->disabled = 0;
1174 rrq->fixed = 0;
1175 rrq->value = mibitem.data;
1177 exit:
1178 return err;
1181 static int p80211wext_siwspy(netdevice_t * dev,
1182 struct iw_request_info *info,
1183 struct iw_point *srq, char *extra)
1185 wlandevice_t *wlandev = dev->ml_priv;
1186 struct sockaddr address[IW_MAX_SPY];
1187 int number = srq->length;
1188 int i;
1190 /* Copy the data from the input buffer */
1191 memcpy(address, extra, sizeof(struct sockaddr) * number);
1193 wlandev->spy_number = 0;
1195 if (number > 0) {
1197 /* extract the addresses */
1198 for (i = 0; i < number; i++) {
1200 memcpy(wlandev->spy_address[i], address[i].sa_data,
1201 ETH_ALEN);
1204 /* reset stats */
1205 memset(wlandev->spy_stat, 0,
1206 sizeof(struct iw_quality) * IW_MAX_SPY);
1208 /* set number of addresses */
1209 wlandev->spy_number = number;
1212 return 0;
1215 /* jkriegl: from orinoco, modified */
1216 static int p80211wext_giwspy(netdevice_t * dev,
1217 struct iw_request_info *info,
1218 struct iw_point *srq, char *extra)
1220 wlandevice_t *wlandev = dev->ml_priv;
1222 struct sockaddr address[IW_MAX_SPY];
1223 struct iw_quality spy_stat[IW_MAX_SPY];
1224 int number;
1225 int i;
1227 number = wlandev->spy_number;
1229 if (number > 0) {
1231 /* populate address and spy struct's */
1232 for (i = 0; i < number; i++) {
1233 memcpy(address[i].sa_data, wlandev->spy_address[i],
1234 ETH_ALEN);
1235 address[i].sa_family = AF_UNIX;
1236 memcpy(&spy_stat[i], &wlandev->spy_stat[i],
1237 sizeof(struct iw_quality));
1240 /* reset update flag */
1241 for (i = 0; i < number; i++)
1242 wlandev->spy_stat[i].updated = 0;
1245 /* push stuff to user space */
1246 srq->length = number;
1247 memcpy(extra, address, sizeof(struct sockaddr) * number);
1248 memcpy(extra + sizeof(struct sockaddr) * number, spy_stat,
1249 sizeof(struct iw_quality) * number);
1251 return 0;
1254 static int prism2_result2err(int prism2_result)
1256 int err = 0;
1258 switch (prism2_result) {
1259 case P80211ENUM_resultcode_invalid_parameters:
1260 err = -EINVAL;
1261 break;
1262 case P80211ENUM_resultcode_implementation_failure:
1263 err = -EIO;
1264 break;
1265 case P80211ENUM_resultcode_not_supported:
1266 err = -EOPNOTSUPP;
1267 break;
1268 default:
1269 err = 0;
1270 break;
1273 return err;
1276 static int p80211wext_siwscan(netdevice_t * dev,
1277 struct iw_request_info *info,
1278 struct iw_point *srq, char *extra)
1280 wlandevice_t *wlandev = dev->ml_priv;
1281 p80211msg_dot11req_scan_t msg;
1282 int result;
1283 int err = 0;
1284 int i = 0;
1286 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1287 printk(KERN_ERR "Can't scan in AP mode\n");
1288 err = (-EOPNOTSUPP);
1289 goto exit;
1292 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1293 msg.msgcode = DIDmsg_dot11req_scan;
1294 msg.bsstype.data = P80211ENUM_bsstype_any;
1296 memset(&(msg.bssid.data), 0xFF, sizeof(p80211item_pstr6_t));
1297 msg.bssid.data.len = 6;
1299 msg.scantype.data = P80211ENUM_scantype_active;
1300 msg.probedelay.data = 0;
1302 for (i = 1; i <= 14; i++)
1303 msg.channellist.data.data[i - 1] = i;
1304 msg.channellist.data.len = 14;
1306 msg.maxchanneltime.data = 250;
1307 msg.minchanneltime.data = 200;
1309 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1310 if (result)
1311 err = prism2_result2err(msg.resultcode.data);
1313 exit:
1314 return err;
1317 /* Helper to translate scan into Wireless Extensions scan results.
1318 * Inspired by the prism54 code, which was in turn inspired by the
1319 * airo driver code.
1321 static char *wext_translate_bss(struct iw_request_info *info, char *current_ev,
1322 char *end_buf,
1323 p80211msg_dot11req_scan_results_t * bss)
1325 struct iw_event iwe; /* Temporary buffer */
1327 /* The first entry must be the MAC address */
1328 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1329 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1330 iwe.cmd = SIOCGIWAP;
1331 current_ev =
1332 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1333 IW_EV_ADDR_LEN);
1335 /* The following entries will be displayed in the same order we give them */
1337 /* The ESSID. */
1338 if (bss->ssid.data.len > 0) {
1339 char essid[IW_ESSID_MAX_SIZE + 1];
1340 int size;
1342 size =
1343 min_t(unsigned short, IW_ESSID_MAX_SIZE,
1344 bss->ssid.data.len);
1345 memset(&essid, 0, sizeof(essid));
1346 memcpy(&essid, bss->ssid.data.data, size);
1347 pr_debug(" essid size = %d\n", size);
1348 iwe.u.data.length = size;
1349 iwe.u.data.flags = 1;
1350 iwe.cmd = SIOCGIWESSID;
1351 current_ev =
1352 iwe_stream_add_point(info, current_ev, end_buf, &iwe,
1353 &essid[0]);
1354 pr_debug(" essid size OK.\n");
1357 switch (bss->bsstype.data) {
1358 case P80211ENUM_bsstype_infrastructure:
1359 iwe.u.mode = IW_MODE_MASTER;
1360 break;
1362 case P80211ENUM_bsstype_independent:
1363 iwe.u.mode = IW_MODE_ADHOC;
1364 break;
1366 default:
1367 iwe.u.mode = 0;
1368 break;
1370 iwe.cmd = SIOCGIWMODE;
1371 if (iwe.u.mode)
1372 current_ev =
1373 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1374 IW_EV_UINT_LEN);
1376 /* Encryption capability */
1377 if (bss->privacy.data == P80211ENUM_truth_true)
1378 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1379 else
1380 iwe.u.data.flags = IW_ENCODE_DISABLED;
1381 iwe.u.data.length = 0;
1382 iwe.cmd = SIOCGIWENCODE;
1383 current_ev =
1384 iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1386 /* Add frequency. (short) bss->channel is the frequency in MHz */
1387 iwe.u.freq.m = bss->dschannel.data;
1388 iwe.u.freq.e = 0;
1389 iwe.cmd = SIOCGIWFREQ;
1390 current_ev =
1391 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1392 IW_EV_FREQ_LEN);
1394 /* Add quality statistics */
1395 iwe.u.qual.level = bss->signal.data;
1396 iwe.u.qual.noise = bss->noise.data;
1397 /* do a simple SNR for quality */
1398 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1399 iwe.cmd = IWEVQUAL;
1400 current_ev =
1401 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1402 IW_EV_QUAL_LEN);
1404 return current_ev;
1407 static int p80211wext_giwscan(netdevice_t * dev,
1408 struct iw_request_info *info,
1409 struct iw_point *srq, char *extra)
1411 wlandevice_t *wlandev = dev->ml_priv;
1412 p80211msg_dot11req_scan_results_t msg;
1413 int result = 0;
1414 int err = 0;
1415 int i = 0;
1416 int scan_good = 0;
1417 char *current_ev = extra;
1419 /* Since wireless tools doesn't really have a way of passing how
1420 * many scan results results there were back here, keep grabbing them
1421 * until we fail.
1423 do {
1424 memset(&msg, 0, sizeof(msg));
1425 msg.msgcode = DIDmsg_dot11req_scan_results;
1426 msg.bssindex.data = i;
1428 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1429 if ((result != 0) ||
1430 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1431 break;
1434 current_ev =
1435 wext_translate_bss(info, current_ev,
1436 extra + IW_SCAN_MAX_DATA, &msg);
1437 scan_good = 1;
1438 i++;
1439 } while (i < IW_MAX_AP);
1441 srq->length = (current_ev - extra);
1442 srq->flags = 0; /* todo */
1444 if (result && !scan_good)
1445 err = prism2_result2err(msg.resultcode.data);
1447 return err;
1450 /* extra wireless extensions stuff to support NetworkManager (I hope) */
1452 /* SIOCSIWENCODEEXT */
1453 static int p80211wext_set_encodeext(struct net_device *dev,
1454 struct iw_request_info *info,
1455 union iwreq_data *wrqu, char *extra)
1457 wlandevice_t *wlandev = dev->ml_priv;
1458 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1459 p80211msg_dot11req_mibset_t msg;
1460 p80211item_pstr32_t *pstr;
1462 int result = 0;
1463 struct iw_point *encoding = &wrqu->encoding;
1464 int idx = encoding->flags & IW_ENCODE_INDEX;
1466 pr_debug("set_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1467 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1469 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1470 /* set default key ? I'm not sure if this the the correct thing to do here */
1472 if (idx) {
1473 if (idx < 1 || idx > NUM_WEPKEYS)
1474 return -EINVAL;
1475 else
1476 idx--;
1478 pr_debug("setting default key (%d)\n", idx);
1479 result =
1480 p80211wext_dorequest(wlandev,
1481 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
1482 idx);
1483 if (result)
1484 return -EFAULT;
1487 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1488 if (ext->alg != IW_ENCODE_ALG_WEP) {
1489 pr_debug("asked to set a non wep key :(\n");
1490 return -EINVAL;
1492 if (idx) {
1493 if (idx < 1 || idx > NUM_WEPKEYS)
1494 return -EINVAL;
1495 else
1496 idx--;
1498 pr_debug("Set WEP key (%d)\n", idx);
1499 wlandev->wep_keylens[idx] = ext->key_len;
1500 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1502 memset(&msg, 0, sizeof(msg));
1503 pstr = (p80211item_pstr32_t *) & msg.mibattribute.data;
1504 memcpy(pstr->data.data, ext->key, ext->key_len);
1505 pstr->data.len = ext->key_len;
1506 switch (idx) {
1507 case 0:
1508 pstr->did =
1509 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1510 break;
1511 case 1:
1512 pstr->did =
1513 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1514 break;
1515 case 2:
1516 pstr->did =
1517 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1518 break;
1519 case 3:
1520 pstr->did =
1521 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1522 break;
1523 default:
1524 break;
1526 msg.msgcode = DIDmsg_dot11req_mibset;
1527 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1528 pr_debug("result (%d)\n", result);
1530 return result;
1533 /* SIOCGIWENCODEEXT */
1534 static int p80211wext_get_encodeext(struct net_device *dev,
1535 struct iw_request_info *info,
1536 union iwreq_data *wrqu, char *extra)
1538 wlandevice_t *wlandev = dev->ml_priv;
1539 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1541 struct iw_point *encoding = &wrqu->encoding;
1542 int result = 0;
1543 int max_len;
1544 int idx;
1546 pr_debug("get_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1547 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1549 max_len = encoding->length - sizeof(*ext);
1550 if (max_len <= 0) {
1551 pr_debug("get_encodeext max_len [%d] invalid\n", max_len);
1552 result = -EINVAL;
1553 goto exit;
1555 idx = encoding->flags & IW_ENCODE_INDEX;
1557 pr_debug("get_encode_ext index [%d]\n", idx);
1559 if (idx) {
1560 if (idx < 1 || idx > NUM_WEPKEYS) {
1561 pr_debug("get_encode_ext invalid key index [%d]\n",
1562 idx);
1563 result = -EINVAL;
1564 goto exit;
1566 idx--;
1567 } else {
1568 /* default key ? not sure what to do */
1569 /* will just use key[0] for now ! FIX ME */
1572 encoding->flags = idx + 1;
1573 memset(ext, 0, sizeof(*ext));
1575 ext->alg = IW_ENCODE_ALG_WEP;
1576 ext->key_len = wlandev->wep_keylens[idx];
1577 memcpy(ext->key, wlandev->wep_keys[idx], ext->key_len);
1579 encoding->flags |= IW_ENCODE_ENABLED;
1580 exit:
1581 return result;
1584 /* SIOCSIWAUTH */
1585 static int p80211_wext_set_iwauth(struct net_device *dev,
1586 struct iw_request_info *info,
1587 union iwreq_data *wrqu, char *extra)
1589 wlandevice_t *wlandev = dev->ml_priv;
1590 struct iw_param *param = &wrqu->param;
1591 int result = 0;
1593 pr_debug("set_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1595 switch (param->flags & IW_AUTH_INDEX) {
1596 case IW_AUTH_DROP_UNENCRYPTED:
1597 pr_debug("drop_unencrypted %d\n", param->value);
1598 if (param->value)
1599 result =
1600 p80211wext_dorequest(wlandev,
1601 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1602 P80211ENUM_truth_true);
1603 else
1604 result =
1605 p80211wext_dorequest(wlandev,
1606 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1607 P80211ENUM_truth_false);
1608 break;
1610 case IW_AUTH_PRIVACY_INVOKED:
1611 pr_debug("privacy invoked %d\n", param->value);
1612 if (param->value)
1613 result =
1614 p80211wext_dorequest(wlandev,
1615 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1616 P80211ENUM_truth_true);
1617 else
1618 result =
1619 p80211wext_dorequest(wlandev,
1620 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1621 P80211ENUM_truth_false);
1623 break;
1625 case IW_AUTH_80211_AUTH_ALG:
1626 if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1627 pr_debug("set open_system\n");
1628 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1629 } else if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1630 pr_debug("set shared key\n");
1631 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1632 } else {
1633 /* don't know what to do know */
1634 pr_debug("unknown AUTH_ALG (%d)\n", param->value);
1635 result = -EINVAL;
1637 break;
1639 default:
1640 break;
1643 return result;
1646 /* SIOCSIWAUTH */
1647 static int p80211_wext_get_iwauth(struct net_device *dev,
1648 struct iw_request_info *info,
1649 union iwreq_data *wrqu, char *extra)
1651 wlandevice_t *wlandev = dev->ml_priv;
1652 struct iw_param *param = &wrqu->param;
1653 int result = 0;
1655 pr_debug("get_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1657 switch (param->flags & IW_AUTH_INDEX) {
1658 case IW_AUTH_DROP_UNENCRYPTED:
1659 param->value =
1660 wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED ? 1 : 0;
1661 break;
1663 case IW_AUTH_PRIVACY_INVOKED:
1664 param->value =
1665 wlandev->hostwep & HOSTWEP_PRIVACYINVOKED ? 1 : 0;
1666 break;
1668 case IW_AUTH_80211_AUTH_ALG:
1669 param->value =
1670 wlandev->hostwep & HOSTWEP_SHAREDKEY ?
1671 IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM;
1672 break;
1674 default:
1675 break;
1678 return result;
1681 static iw_handler p80211wext_handlers[] = {
1682 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1683 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1684 (iw_handler) NULL, /* SIOCSIWNWID */
1685 (iw_handler) NULL, /* SIOCGIWNWID */
1686 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1687 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1688 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1689 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1690 (iw_handler) NULL, /* SIOCSIWSENS */
1691 (iw_handler) NULL, /* SIOCGIWSENS */
1692 (iw_handler) NULL, /* not used *//* SIOCSIWRANGE */
1693 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1694 (iw_handler) NULL, /* not used *//* SIOCSIWPRIV */
1695 (iw_handler) NULL, /* kernel code *//* SIOCGIWPRIV */
1696 (iw_handler) NULL, /* not used *//* SIOCSIWSTATS */
1697 (iw_handler) NULL, /* kernel code *//* SIOCGIWSTATS */
1698 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1699 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1700 (iw_handler) NULL, /* -- hole -- */
1701 (iw_handler) NULL, /* -- hole -- */
1702 (iw_handler) NULL, /* SIOCSIWAP */
1703 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1704 (iw_handler) NULL, /* -- hole -- */
1705 (iw_handler) NULL, /* SIOCGIWAPLIST */
1706 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1707 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1708 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1709 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1710 (iw_handler) NULL, /* SIOCSIWNICKN */
1711 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1712 (iw_handler) NULL, /* -- hole -- */
1713 (iw_handler) NULL, /* -- hole -- */
1714 (iw_handler) NULL, /* SIOCSIWRATE */
1715 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1716 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1717 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1718 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1719 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1720 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1721 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1722 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1723 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1724 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1725 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1726 (iw_handler) NULL, /* SIOCSIWPOWER */
1727 (iw_handler) NULL, /* SIOCGIWPOWER */
1728 /* WPA operations */
1729 (iw_handler) NULL, /* -- hole -- */
1730 (iw_handler) NULL, /* -- hole -- */
1731 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1732 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1733 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1734 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1736 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1737 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1738 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1741 struct iw_handler_def p80211wext_handler_def = {
1742 .num_standard = ARRAY_SIZE(p80211wext_handlers),
1743 .num_private = 0,
1744 .num_private_args = 0,
1745 .standard = p80211wext_handlers,
1746 .private = NULL,
1747 .private_args = NULL,
1748 .get_wireless_stats = p80211wext_get_wireless_stats
1751 int p80211wext_event_associated(wlandevice_t * wlandev, int assoc)
1753 union iwreq_data data;
1755 /* Send the association state first */
1756 data.ap_addr.sa_family = ARPHRD_ETHER;
1757 if (assoc)
1758 memcpy(data.ap_addr.sa_data, wlandev->bssid, ETH_ALEN);
1759 else
1760 memset(data.ap_addr.sa_data, 0, ETH_ALEN);
1762 if (wlan_wext_write)
1763 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1765 if (!assoc)
1766 goto done;
1768 /* XXX send association data, like IEs, etc etc. */
1770 done:
1771 return 0;