x86/amd-iommu: Add per IOMMU reference counting
[linux/fpc-iii.git] / drivers / staging / wlan-ng / p80211wext.c
blob74d8022adb24ae5a6b82de7a44f9c06608da0a46
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 #include "p80211types.h"
56 #include "p80211hdr.h"
57 #include "p80211conv.h"
58 #include "p80211mgmt.h"
59 #include "p80211msg.h"
60 #include "p80211metastruct.h"
61 #include "p80211metadef.h"
62 #include "p80211netdev.h"
63 #include "p80211ioctl.h"
64 #include "p80211req.h"
66 static int p80211wext_giwrate(netdevice_t *dev,
67 struct iw_request_info *info,
68 struct iw_param *rrq, char *extra);
69 static int p80211wext_giwessid(netdevice_t *dev,
70 struct iw_request_info *info,
71 struct iw_point *data, char *essid);
73 static u8 p80211_mhz_to_channel(u16 mhz)
75 if (mhz >= 5000)
76 return (mhz - 5000) / 5;
78 if (mhz == 2482)
79 return 14;
81 if (mhz >= 2407)
82 return (mhz - 2407) / 5;
84 return 0;
87 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
90 if (ch == 0)
91 return 0;
92 if (ch > 200)
93 return 0;
95 /* 5G */
96 if (dot11a)
97 return 5000 + (5 * ch);
99 /* 2.4G */
100 if (ch == 14)
101 return 2484;
103 if ((ch < 14) && (ch > 0))
104 return 2407 + (5 * ch);
106 return 0;
109 /* taken from orinoco.c ;-) */
110 static const long p80211wext_channel_freq[] = {
111 2412, 2417, 2422, 2427, 2432, 2437, 2442,
112 2447, 2452, 2457, 2462, 2467, 2472, 2484
115 #define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq)
117 /* steal a spare bit to store the shared/opensystems state.
118 should default to open if not set */
119 #define HOSTWEP_SHAREDKEY BIT(3)
121 static int qual_as_percent(int snr)
123 if (snr <= 0)
124 return 0;
125 if (snr <= 40)
126 return snr * 5 / 2;
127 return 100;
130 static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data)
132 p80211msg_dot11req_mibset_t msg;
133 p80211item_uint32_t mibitem;
134 int result;
136 msg.msgcode = DIDmsg_dot11req_mibset;
137 mibitem.did = did;
138 mibitem.data = data;
139 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
140 result = p80211req_dorequest(wlandev, (u8 *) & msg);
142 return result;
145 static int p80211wext_autojoin(wlandevice_t *wlandev)
147 p80211msg_lnxreq_autojoin_t msg;
148 struct iw_point data;
149 char ssid[IW_ESSID_MAX_SIZE];
151 int result;
152 int err = 0;
154 /* Get ESSID */
155 result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
157 if (result) {
158 err = -EFAULT;
159 goto exit;
162 if (wlandev->hostwep & HOSTWEP_SHAREDKEY)
163 msg.authtype.data = P80211ENUM_authalg_sharedkey;
164 else
165 msg.authtype.data = P80211ENUM_authalg_opensystem;
167 msg.msgcode = DIDmsg_lnxreq_autojoin;
169 /* Trim the last '\0' to fit the SSID format */
171 if (data.length && ssid[data.length - 1] == '\0')
172 data.length = data.length - 1;
174 memcpy(msg.ssid.data.data, ssid, data.length);
175 msg.ssid.data.len = data.length;
177 result = p80211req_dorequest(wlandev, (u8 *) & msg);
179 if (result) {
180 err = -EFAULT;
181 goto exit;
184 exit:
186 return err;
190 /* called by /proc/net/wireless */
191 struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev)
193 p80211msg_lnxreq_commsquality_t quality;
194 wlandevice_t *wlandev = dev->ml_priv;
195 struct iw_statistics *wstats = &wlandev->wstats;
196 int retval;
198 /* Check */
199 if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
200 return NULL;
202 /* XXX Only valid in station mode */
203 wstats->status = 0;
205 /* build request message */
206 quality.msgcode = DIDmsg_lnxreq_commsquality;
207 quality.dbm.data = P80211ENUM_truth_true;
208 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
210 /* send message to nsd */
211 if (wlandev->mlmerequest == NULL)
212 return NULL;
214 retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) & quality);
216 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
217 wstats->qual.level = quality.level.data; /* instant signal level */
218 wstats->qual.noise = quality.noise.data; /* instant noise level */
220 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
221 wstats->discard.code = wlandev->rx.decrypt_err;
222 wstats->discard.nwid = 0;
223 wstats->discard.misc = 0;
225 wstats->discard.fragment = 0; /* incomplete fragments */
226 wstats->discard.retries = 0; /* tx retries. */
227 wstats->miss.beacon = 0;
229 return wstats;
232 static int p80211wext_giwname(netdevice_t *dev,
233 struct iw_request_info *info,
234 char *name, char *extra)
236 struct iw_param rate;
237 int result;
238 int err = 0;
240 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
242 if (result) {
243 err = -EFAULT;
244 goto exit;
247 switch (rate.value) {
248 case 1000000:
249 case 2000000:
250 strcpy(name, "IEEE 802.11-DS");
251 break;
252 case 5500000:
253 case 11000000:
254 strcpy(name, "IEEE 802.11-b");
255 break;
257 exit:
258 return err;
261 static int p80211wext_giwfreq(netdevice_t *dev,
262 struct iw_request_info *info,
263 struct iw_freq *freq, char *extra)
265 wlandevice_t *wlandev = dev->ml_priv;
266 p80211item_uint32_t mibitem;
267 p80211msg_dot11req_mibset_t msg;
268 int result;
269 int err = 0;
271 msg.msgcode = DIDmsg_dot11req_mibget;
272 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
273 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
274 result = p80211req_dorequest(wlandev, (u8 *) & msg);
276 if (result) {
277 err = -EFAULT;
278 goto exit;
281 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
283 if (mibitem.data > NUM_CHANNELS) {
284 err = -EFAULT;
285 goto exit;
288 /* convert into frequency instead of a channel */
289 freq->e = 1;
290 freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
292 exit:
293 return err;
296 static int p80211wext_siwfreq(netdevice_t *dev,
297 struct iw_request_info *info,
298 struct iw_freq *freq, char *extra)
300 wlandevice_t *wlandev = dev->ml_priv;
301 p80211item_uint32_t mibitem;
302 p80211msg_dot11req_mibset_t msg;
303 int result;
304 int err = 0;
306 if (!wlan_wext_write) {
307 err = (-EOPNOTSUPP);
308 goto exit;
311 msg.msgcode = DIDmsg_dot11req_mibset;
312 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
313 mibitem.status = P80211ENUM_msgitem_status_data_ok;
315 if ((freq->e == 0) && (freq->m <= 1000))
316 mibitem.data = freq->m;
317 else
318 mibitem.data = p80211_mhz_to_channel(freq->m);
320 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
321 result = p80211req_dorequest(wlandev, (u8 *) & msg);
323 if (result) {
324 err = -EFAULT;
325 goto exit;
328 exit:
329 return err;
332 static int p80211wext_giwmode(netdevice_t *dev,
333 struct iw_request_info *info,
334 __u32 *mode, char *extra)
336 wlandevice_t *wlandev = dev->ml_priv;
338 switch (wlandev->macmode) {
339 case WLAN_MACMODE_IBSS_STA:
340 *mode = IW_MODE_ADHOC;
341 break;
342 case WLAN_MACMODE_ESS_STA:
343 *mode = IW_MODE_INFRA;
344 break;
345 case WLAN_MACMODE_ESS_AP:
346 *mode = IW_MODE_MASTER;
347 break;
348 default:
349 /* Not set yet. */
350 *mode = IW_MODE_AUTO;
353 return 0;
356 static int p80211wext_siwmode(netdevice_t *dev,
357 struct iw_request_info *info,
358 __u32 *mode, char *extra)
360 wlandevice_t *wlandev = dev->ml_priv;
361 p80211item_uint32_t mibitem;
362 p80211msg_dot11req_mibset_t msg;
363 int result;
364 int err = 0;
366 if (!wlan_wext_write) {
367 err = (-EOPNOTSUPP);
368 goto exit;
371 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
372 *mode != IW_MODE_MASTER) {
373 err = (-EOPNOTSUPP);
374 goto exit;
377 /* Operation mode is the same with current mode */
378 if (*mode == wlandev->macmode)
379 goto exit;
381 switch (*mode) {
382 case IW_MODE_ADHOC:
383 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
384 break;
385 case IW_MODE_INFRA:
386 wlandev->macmode = WLAN_MACMODE_ESS_STA;
387 break;
388 case IW_MODE_MASTER:
389 wlandev->macmode = WLAN_MACMODE_ESS_AP;
390 break;
391 default:
392 /* Not set yet. */
393 printk(KERN_INFO "Operation mode: %d not support\n", *mode);
394 return -EOPNOTSUPP;
397 /* Set Operation mode to the PORT TYPE RID */
398 msg.msgcode = DIDmsg_dot11req_mibset;
399 mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
400 mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
401 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
402 result = p80211req_dorequest(wlandev, (u8 *) & msg);
404 if (result)
405 err = -EFAULT;
407 exit:
408 return err;
411 static int p80211wext_giwrange(netdevice_t *dev,
412 struct iw_request_info *info,
413 struct iw_point *data, char *extra)
415 struct iw_range *range = (struct iw_range *)extra;
416 int i, val;
418 /* for backward compatability set size and zero everything we don't understand */
419 data->length = sizeof(*range);
420 memset(range, 0, sizeof(*range));
422 range->txpower_capa = IW_TXPOW_DBM;
423 /* XXX what about min/max_pmp, min/max_pmt, etc. */
425 range->we_version_compiled = WIRELESS_EXT;
426 range->we_version_source = 13;
428 range->retry_capa = IW_RETRY_LIMIT;
429 range->retry_flags = IW_RETRY_LIMIT;
430 range->min_retry = 0;
431 range->max_retry = 255;
433 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | /* mode/freq/ssid */
434 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
435 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
436 range->event_capa[1] = IW_EVENT_CAPA_K_1; /* encode */
437 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
438 IW_EVENT_CAPA_MASK(IWEVCUSTOM));
440 range->num_channels = NUM_CHANNELS;
442 /* XXX need to filter against the regulatory domain &| active set */
443 val = 0;
444 for (i = 0; i < NUM_CHANNELS; i++) {
445 range->freq[val].i = i + 1;
446 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
447 range->freq[val].e = 1;
448 val++;
451 range->num_frequency = val;
453 /* Max of /proc/net/wireless */
454 range->max_qual.qual = 100;
455 range->max_qual.level = 0;
456 range->max_qual.noise = 0;
457 range->sensitivity = 3;
458 /* XXX these need to be nsd-specific! */
460 range->min_rts = 0;
461 range->max_rts = 2347;
462 range->min_frag = 256;
463 range->max_frag = 2346;
465 range->max_encoding_tokens = NUM_WEPKEYS;
466 range->num_encoding_sizes = 2;
467 range->encoding_size[0] = 5;
468 range->encoding_size[1] = 13;
470 /* XXX what about num_bitrates/throughput? */
471 range->num_bitrates = 0;
473 /* estimated max throughput */
474 /* XXX need to cap it if we're running at ~2Mbps.. */
475 range->throughput = 5500000;
477 return 0;
480 static int p80211wext_giwap(netdevice_t *dev,
481 struct iw_request_info *info,
482 struct sockaddr *ap_addr, char *extra)
485 wlandevice_t *wlandev = dev->ml_priv;
487 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
488 ap_addr->sa_family = ARPHRD_ETHER;
490 return 0;
493 static int p80211wext_giwencode(netdevice_t *dev,
494 struct iw_request_info *info,
495 struct iw_point *erq, char *key)
497 wlandevice_t *wlandev = dev->ml_priv;
498 int err = 0;
499 int i;
501 i = (erq->flags & IW_ENCODE_INDEX) - 1;
502 erq->flags = 0;
504 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
505 erq->flags |= IW_ENCODE_ENABLED;
506 else
507 erq->flags |= IW_ENCODE_DISABLED;
509 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
510 erq->flags |= IW_ENCODE_RESTRICTED;
511 else
512 erq->flags |= IW_ENCODE_OPEN;
514 i = (erq->flags & IW_ENCODE_INDEX) - 1;
516 if (i == -1)
517 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
519 if ((i < 0) || (i >= NUM_WEPKEYS)) {
520 err = -EINVAL;
521 goto exit;
524 erq->flags |= i + 1;
526 /* copy the key from the driver cache as the keys are read-only MIBs */
527 erq->length = wlandev->wep_keylens[i];
528 memcpy(key, wlandev->wep_keys[i], erq->length);
530 exit:
531 return err;
534 static int p80211wext_siwencode(netdevice_t *dev,
535 struct iw_request_info *info,
536 struct iw_point *erq, char *key)
538 wlandevice_t *wlandev = dev->ml_priv;
539 p80211msg_dot11req_mibset_t msg;
540 p80211item_pstr32_t pstr;
542 int err = 0;
543 int result = 0;
544 int i;
546 if (!wlan_wext_write) {
547 err = (-EOPNOTSUPP);
548 goto exit;
551 /* Check the Key index first. */
552 if ((i = (erq->flags & IW_ENCODE_INDEX))) {
554 if ((i < 1) || (i > NUM_WEPKEYS)) {
555 err = -EINVAL;
556 goto exit;
557 } else
558 i--;
560 /* Set current key number only if no keys are given */
561 if (erq->flags & IW_ENCODE_NOKEY) {
562 result =
563 p80211wext_dorequest(wlandev,
564 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
567 if (result) {
568 err = -EFAULT;
569 goto exit;
573 } else {
574 /* Use defaultkey if no Key Index */
575 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
578 /* Check if there is no key information in the iwconfig request */
579 if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
581 /*------------------------------------------------------------
582 * If there is WEP Key for setting, check the Key Information
583 * and then set it to the firmware.
584 -------------------------------------------------------------*/
586 if (erq->length > 0) {
588 /* copy the key from the driver cache as the keys are read-only MIBs */
589 wlandev->wep_keylens[i] = erq->length;
590 memcpy(wlandev->wep_keys[i], key, erq->length);
592 /* Prepare data struture for p80211req_dorequest. */
593 memcpy(pstr.data.data, key, erq->length);
594 pstr.data.len = erq->length;
596 switch (i) {
597 case 0:
598 pstr.did =
599 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
600 break;
602 case 1:
603 pstr.did =
604 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
605 break;
607 case 2:
608 pstr.did =
609 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
610 break;
612 case 3:
613 pstr.did =
614 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
615 break;
617 default:
618 err = -EINVAL;
619 goto exit;
622 msg.msgcode = DIDmsg_dot11req_mibset;
623 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
624 result = p80211req_dorequest(wlandev, (u8 *) & msg);
626 if (result) {
627 err = -EFAULT;
628 goto exit;
634 /* Check the PrivacyInvoked flag */
635 if (erq->flags & IW_ENCODE_DISABLED) {
636 result =
637 p80211wext_dorequest(wlandev,
638 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
639 P80211ENUM_truth_false);
640 } else {
641 result =
642 p80211wext_dorequest(wlandev,
643 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
644 P80211ENUM_truth_true);
647 if (result) {
648 err = -EFAULT;
649 goto exit;
652 /* The security mode may be open or restricted, and its meaning
653 depends on the card used. With most cards, in open mode no
654 authentication is used and the card may also accept non-
655 encrypted sessions, whereas in restricted mode only encrypted
656 sessions are accepted and the card will use authentication if
657 available.
659 if (erq->flags & IW_ENCODE_RESTRICTED) {
660 result =
661 p80211wext_dorequest(wlandev,
662 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
663 P80211ENUM_truth_true);
664 } else if (erq->flags & IW_ENCODE_OPEN) {
665 result =
666 p80211wext_dorequest(wlandev,
667 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
668 P80211ENUM_truth_false);
671 if (result) {
672 err = -EFAULT;
673 goto exit;
676 exit:
678 return err;
681 static int p80211wext_giwessid(netdevice_t *dev,
682 struct iw_request_info *info,
683 struct iw_point *data, char *essid)
685 wlandevice_t *wlandev = dev->ml_priv;
687 if (wlandev->ssid.len) {
688 data->length = wlandev->ssid.len;
689 data->flags = 1;
690 memcpy(essid, wlandev->ssid.data, data->length);
691 essid[data->length] = 0;
692 } else {
693 memset(essid, 0, sizeof(wlandev->ssid.data));
694 data->length = 0;
695 data->flags = 0;
698 return 0;
701 static int p80211wext_siwessid(netdevice_t *dev,
702 struct iw_request_info *info,
703 struct iw_point *data, char *essid)
705 wlandevice_t *wlandev = dev->ml_priv;
706 p80211msg_lnxreq_autojoin_t msg;
708 int result;
709 int err = 0;
710 int length = data->length;
712 if (!wlan_wext_write) {
713 err = (-EOPNOTSUPP);
714 goto exit;
717 if (wlandev->hostwep & HOSTWEP_SHAREDKEY)
718 msg.authtype.data = P80211ENUM_authalg_sharedkey;
719 else
720 msg.authtype.data = P80211ENUM_authalg_opensystem;
722 msg.msgcode = DIDmsg_lnxreq_autojoin;
724 /* Trim the last '\0' to fit the SSID format */
725 if (length && essid[length - 1] == '\0')
726 length--;
728 memcpy(msg.ssid.data.data, essid, length);
729 msg.ssid.data.len = length;
731 pr_debug("autojoin_ssid for %s \n", essid);
732 result = p80211req_dorequest(wlandev, (u8 *) & msg);
733 pr_debug("autojoin_ssid %d\n", result);
735 if (result) {
736 err = -EFAULT;
737 goto exit;
740 exit:
741 return err;
744 static int p80211wext_siwcommit(netdevice_t *dev,
745 struct iw_request_info *info,
746 struct iw_point *data, char *essid)
748 wlandevice_t *wlandev = dev->ml_priv;
749 int err = 0;
751 if (!wlan_wext_write) {
752 err = (-EOPNOTSUPP);
753 goto exit;
756 /* Auto Join */
757 err = p80211wext_autojoin(wlandev);
759 exit:
760 return err;
763 static int p80211wext_giwrate(netdevice_t *dev,
764 struct iw_request_info *info,
765 struct iw_param *rrq, char *extra)
767 wlandevice_t *wlandev = dev->ml_priv;
768 p80211item_uint32_t mibitem;
769 p80211msg_dot11req_mibset_t msg;
770 int result;
771 int err = 0;
773 msg.msgcode = DIDmsg_dot11req_mibget;
774 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
775 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
776 result = p80211req_dorequest(wlandev, (u8 *) & msg);
778 if (result) {
779 err = -EFAULT;
780 goto exit;
783 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
785 rrq->fixed = 0; /* can it change? */
786 rrq->disabled = 0;
787 rrq->value = 0;
789 #define HFA384x_RATEBIT_1 ((u16)1)
790 #define HFA384x_RATEBIT_2 ((u16)2)
791 #define HFA384x_RATEBIT_5dot5 ((u16)4)
792 #define HFA384x_RATEBIT_11 ((u16)8)
794 switch (mibitem.data) {
795 case HFA384x_RATEBIT_1:
796 rrq->value = 1000000;
797 break;
798 case HFA384x_RATEBIT_2:
799 rrq->value = 2000000;
800 break;
801 case HFA384x_RATEBIT_5dot5:
802 rrq->value = 5500000;
803 break;
804 case HFA384x_RATEBIT_11:
805 rrq->value = 11000000;
806 break;
807 default:
808 err = -EINVAL;
810 exit:
811 return err;
814 static int p80211wext_giwrts(netdevice_t *dev,
815 struct iw_request_info *info,
816 struct iw_param *rts, char *extra)
818 wlandevice_t *wlandev = dev->ml_priv;
819 p80211item_uint32_t mibitem;
820 p80211msg_dot11req_mibset_t msg;
821 int result;
822 int err = 0;
824 msg.msgcode = DIDmsg_dot11req_mibget;
825 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
826 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
827 result = p80211req_dorequest(wlandev, (u8 *) & msg);
829 if (result) {
830 err = -EFAULT;
831 goto exit;
834 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
836 rts->value = mibitem.data;
837 rts->disabled = (rts->value == 2347);
838 rts->fixed = 1;
840 exit:
841 return err;
844 static int p80211wext_siwrts(netdevice_t *dev,
845 struct iw_request_info *info,
846 struct iw_param *rts, char *extra)
848 wlandevice_t *wlandev = dev->ml_priv;
849 p80211item_uint32_t mibitem;
850 p80211msg_dot11req_mibset_t msg;
851 int result;
852 int err = 0;
854 if (!wlan_wext_write) {
855 err = (-EOPNOTSUPP);
856 goto exit;
859 msg.msgcode = DIDmsg_dot11req_mibget;
860 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
861 if (rts->disabled)
862 mibitem.data = 2347;
863 else
864 mibitem.data = rts->value;
866 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
867 result = p80211req_dorequest(wlandev, (u8 *) & msg);
869 if (result) {
870 err = -EFAULT;
871 goto exit;
874 exit:
875 return err;
878 static int p80211wext_giwfrag(netdevice_t *dev,
879 struct iw_request_info *info,
880 struct iw_param *frag, char *extra)
882 wlandevice_t *wlandev = dev->ml_priv;
883 p80211item_uint32_t mibitem;
884 p80211msg_dot11req_mibset_t msg;
885 int result;
886 int err = 0;
888 msg.msgcode = DIDmsg_dot11req_mibget;
889 mibitem.did =
890 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
891 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
892 result = p80211req_dorequest(wlandev, (u8 *) & msg);
894 if (result) {
895 err = -EFAULT;
896 goto exit;
899 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
901 frag->value = mibitem.data;
902 frag->disabled = (frag->value == 2346);
903 frag->fixed = 1;
905 exit:
906 return err;
909 static int p80211wext_siwfrag(netdevice_t *dev,
910 struct iw_request_info *info,
911 struct iw_param *frag, char *extra)
913 wlandevice_t *wlandev = dev->ml_priv;
914 p80211item_uint32_t mibitem;
915 p80211msg_dot11req_mibset_t msg;
916 int result;
917 int err = 0;
919 if (!wlan_wext_write) {
920 err = (-EOPNOTSUPP);
921 goto exit;
924 msg.msgcode = DIDmsg_dot11req_mibset;
925 mibitem.did =
926 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
928 if (frag->disabled)
929 mibitem.data = 2346;
930 else
931 mibitem.data = frag->value;
933 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
934 result = p80211req_dorequest(wlandev, (u8 *) & msg);
936 if (result) {
937 err = -EFAULT;
938 goto exit;
941 exit:
942 return err;
945 #ifndef IW_RETRY_LONG
946 #define IW_RETRY_LONG IW_RETRY_MAX
947 #endif
949 #ifndef IW_RETRY_SHORT
950 #define IW_RETRY_SHORT IW_RETRY_MIN
951 #endif
953 static int p80211wext_giwretry(netdevice_t *dev,
954 struct iw_request_info *info,
955 struct iw_param *rrq, char *extra)
957 wlandevice_t *wlandev = dev->ml_priv;
958 p80211item_uint32_t mibitem;
959 p80211msg_dot11req_mibset_t msg;
960 int result;
961 int err = 0;
962 u16 shortretry, longretry, lifetime;
964 msg.msgcode = DIDmsg_dot11req_mibget;
965 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
967 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
968 result = p80211req_dorequest(wlandev, (u8 *) & msg);
970 if (result) {
971 err = -EFAULT;
972 goto exit;
975 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
977 shortretry = mibitem.data;
979 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
981 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
982 result = p80211req_dorequest(wlandev, (u8 *) & msg);
984 if (result) {
985 err = -EFAULT;
986 goto exit;
989 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
991 longretry = mibitem.data;
993 mibitem.did =
994 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
996 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
997 result = p80211req_dorequest(wlandev, (u8 *) & msg);
999 if (result) {
1000 err = -EFAULT;
1001 goto exit;
1004 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1006 lifetime = mibitem.data;
1008 rrq->disabled = 0;
1010 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1011 rrq->flags = IW_RETRY_LIFETIME;
1012 rrq->value = lifetime * 1024;
1013 } else {
1014 if (rrq->flags & IW_RETRY_LONG) {
1015 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1016 rrq->value = longretry;
1017 } else {
1018 rrq->flags = IW_RETRY_LIMIT;
1019 rrq->value = shortretry;
1020 if (shortretry != longretry)
1021 rrq->flags |= IW_RETRY_SHORT;
1025 exit:
1026 return err;
1030 static int p80211wext_siwretry(netdevice_t *dev,
1031 struct iw_request_info *info,
1032 struct iw_param *rrq, char *extra)
1034 wlandevice_t *wlandev = dev->ml_priv;
1035 p80211item_uint32_t mibitem;
1036 p80211msg_dot11req_mibset_t msg;
1037 int result;
1038 int err = 0;
1040 if (!wlan_wext_write) {
1041 err = (-EOPNOTSUPP);
1042 goto exit;
1045 if (rrq->disabled) {
1046 err = -EINVAL;
1047 goto exit;
1050 msg.msgcode = DIDmsg_dot11req_mibset;
1052 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1053 mibitem.did =
1054 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1055 mibitem.data = rrq->value /= 1024;
1057 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1058 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1060 if (result) {
1061 err = -EFAULT;
1062 goto exit;
1064 } else {
1065 if (rrq->flags & IW_RETRY_LONG) {
1066 mibitem.did =
1067 DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1068 mibitem.data = rrq->value;
1070 memcpy(&msg.mibattribute.data, &mibitem,
1071 sizeof(mibitem));
1072 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1074 if (result) {
1075 err = -EFAULT;
1076 goto exit;
1080 if (rrq->flags & IW_RETRY_SHORT) {
1081 mibitem.did =
1082 DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1083 mibitem.data = rrq->value;
1085 memcpy(&msg.mibattribute.data, &mibitem,
1086 sizeof(mibitem));
1087 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1089 if (result) {
1090 err = -EFAULT;
1091 goto exit;
1096 exit:
1097 return err;
1101 static int p80211wext_siwtxpow(netdevice_t *dev,
1102 struct iw_request_info *info,
1103 struct iw_param *rrq, char *extra)
1105 wlandevice_t *wlandev = dev->ml_priv;
1106 p80211item_uint32_t mibitem;
1107 p80211msg_dot11req_mibset_t msg;
1108 int result;
1109 int err = 0;
1111 if (!wlan_wext_write) {
1112 err = (-EOPNOTSUPP);
1113 goto exit;
1116 msg.msgcode = DIDmsg_dot11req_mibset;
1117 mibitem.did =
1118 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1119 if (rrq->fixed == 0)
1120 mibitem.data = 30;
1121 else
1122 mibitem.data = rrq->value;
1123 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1124 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1126 if (result) {
1127 err = -EFAULT;
1128 goto exit;
1131 exit:
1132 return err;
1135 static int p80211wext_giwtxpow(netdevice_t *dev,
1136 struct iw_request_info *info,
1137 struct iw_param *rrq, char *extra)
1139 wlandevice_t *wlandev = dev->ml_priv;
1140 p80211item_uint32_t mibitem;
1141 p80211msg_dot11req_mibset_t msg;
1142 int result;
1143 int err = 0;
1145 msg.msgcode = DIDmsg_dot11req_mibget;
1146 mibitem.did =
1147 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1149 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1150 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1152 if (result) {
1153 err = -EFAULT;
1154 goto exit;
1157 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1159 /* XXX handle OFF by setting disabled = 1; */
1161 rrq->flags = 0; /* IW_TXPOW_DBM; */
1162 rrq->disabled = 0;
1163 rrq->fixed = 0;
1164 rrq->value = mibitem.data;
1166 exit:
1167 return err;
1170 static int p80211wext_siwspy(netdevice_t *dev,
1171 struct iw_request_info *info,
1172 struct iw_point *srq, char *extra)
1174 wlandevice_t *wlandev = dev->ml_priv;
1175 struct sockaddr address[IW_MAX_SPY];
1176 int number = srq->length;
1177 int i;
1179 /* Copy the data from the input buffer */
1180 memcpy(address, extra, sizeof(struct sockaddr) * number);
1182 wlandev->spy_number = 0;
1184 if (number > 0) {
1186 /* extract the addresses */
1187 for (i = 0; i < number; i++) {
1189 memcpy(wlandev->spy_address[i], address[i].sa_data,
1190 ETH_ALEN);
1193 /* reset stats */
1194 memset(wlandev->spy_stat, 0,
1195 sizeof(struct iw_quality) * IW_MAX_SPY);
1197 /* set number of addresses */
1198 wlandev->spy_number = number;
1201 return 0;
1204 /* jkriegl: from orinoco, modified */
1205 static int p80211wext_giwspy(netdevice_t *dev,
1206 struct iw_request_info *info,
1207 struct iw_point *srq, char *extra)
1209 wlandevice_t *wlandev = dev->ml_priv;
1211 struct sockaddr address[IW_MAX_SPY];
1212 struct iw_quality spy_stat[IW_MAX_SPY];
1213 int number;
1214 int i;
1216 number = wlandev->spy_number;
1218 if (number > 0) {
1220 /* populate address and spy struct's */
1221 for (i = 0; i < number; i++) {
1222 memcpy(address[i].sa_data, wlandev->spy_address[i],
1223 ETH_ALEN);
1224 address[i].sa_family = AF_UNIX;
1225 memcpy(&spy_stat[i], &wlandev->spy_stat[i],
1226 sizeof(struct iw_quality));
1229 /* reset update flag */
1230 for (i = 0; i < number; i++)
1231 wlandev->spy_stat[i].updated = 0;
1234 /* push stuff to user space */
1235 srq->length = number;
1236 memcpy(extra, address, sizeof(struct sockaddr) * number);
1237 memcpy(extra + sizeof(struct sockaddr) * number, spy_stat,
1238 sizeof(struct iw_quality) * number);
1240 return 0;
1243 static int prism2_result2err(int prism2_result)
1245 int err = 0;
1247 switch (prism2_result) {
1248 case P80211ENUM_resultcode_invalid_parameters:
1249 err = -EINVAL;
1250 break;
1251 case P80211ENUM_resultcode_implementation_failure:
1252 err = -EIO;
1253 break;
1254 case P80211ENUM_resultcode_not_supported:
1255 err = -EOPNOTSUPP;
1256 break;
1257 default:
1258 err = 0;
1259 break;
1262 return err;
1265 static int p80211wext_siwscan(netdevice_t *dev,
1266 struct iw_request_info *info,
1267 struct iw_point *srq, char *extra)
1269 wlandevice_t *wlandev = dev->ml_priv;
1270 p80211msg_dot11req_scan_t msg;
1271 int result;
1272 int err = 0;
1273 int i = 0;
1275 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1276 printk(KERN_ERR "Can't scan in AP mode\n");
1277 err = (-EOPNOTSUPP);
1278 goto exit;
1281 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1282 msg.msgcode = DIDmsg_dot11req_scan;
1283 msg.bsstype.data = P80211ENUM_bsstype_any;
1285 memset(&(msg.bssid.data), 0xFF, sizeof(p80211item_pstr6_t));
1286 msg.bssid.data.len = 6;
1288 msg.scantype.data = P80211ENUM_scantype_active;
1289 msg.probedelay.data = 0;
1291 for (i = 1; i <= 14; i++)
1292 msg.channellist.data.data[i - 1] = i;
1293 msg.channellist.data.len = 14;
1295 msg.maxchanneltime.data = 250;
1296 msg.minchanneltime.data = 200;
1298 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1299 if (result)
1300 err = prism2_result2err(msg.resultcode.data);
1302 exit:
1303 return err;
1306 /* Helper to translate scan into Wireless Extensions scan results.
1307 * Inspired by the prism54 code, which was in turn inspired by the
1308 * airo driver code.
1310 static char *wext_translate_bss(struct iw_request_info *info, char *current_ev,
1311 char *end_buf,
1312 p80211msg_dot11req_scan_results_t *bss)
1314 struct iw_event iwe; /* Temporary buffer */
1316 /* The first entry must be the MAC address */
1317 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1318 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1319 iwe.cmd = SIOCGIWAP;
1320 current_ev =
1321 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1322 IW_EV_ADDR_LEN);
1324 /* The following entries will be displayed in the same order we give them */
1326 /* The ESSID. */
1327 if (bss->ssid.data.len > 0) {
1328 char essid[IW_ESSID_MAX_SIZE + 1];
1329 int size;
1331 size =
1332 min_t(unsigned short, IW_ESSID_MAX_SIZE,
1333 bss->ssid.data.len);
1334 memset(&essid, 0, sizeof(essid));
1335 memcpy(&essid, bss->ssid.data.data, size);
1336 pr_debug(" essid size = %d\n", size);
1337 iwe.u.data.length = size;
1338 iwe.u.data.flags = 1;
1339 iwe.cmd = SIOCGIWESSID;
1340 current_ev =
1341 iwe_stream_add_point(info, current_ev, end_buf, &iwe,
1342 &essid[0]);
1343 pr_debug(" essid size OK.\n");
1346 switch (bss->bsstype.data) {
1347 case P80211ENUM_bsstype_infrastructure:
1348 iwe.u.mode = IW_MODE_MASTER;
1349 break;
1351 case P80211ENUM_bsstype_independent:
1352 iwe.u.mode = IW_MODE_ADHOC;
1353 break;
1355 default:
1356 iwe.u.mode = 0;
1357 break;
1359 iwe.cmd = SIOCGIWMODE;
1360 if (iwe.u.mode)
1361 current_ev =
1362 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1363 IW_EV_UINT_LEN);
1365 /* Encryption capability */
1366 if (bss->privacy.data == P80211ENUM_truth_true)
1367 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1368 else
1369 iwe.u.data.flags = IW_ENCODE_DISABLED;
1370 iwe.u.data.length = 0;
1371 iwe.cmd = SIOCGIWENCODE;
1372 current_ev =
1373 iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1375 /* Add frequency. (short) bss->channel is the frequency in MHz */
1376 iwe.u.freq.m = bss->dschannel.data;
1377 iwe.u.freq.e = 0;
1378 iwe.cmd = SIOCGIWFREQ;
1379 current_ev =
1380 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1381 IW_EV_FREQ_LEN);
1383 /* Add quality statistics */
1384 iwe.u.qual.level = bss->signal.data;
1385 iwe.u.qual.noise = bss->noise.data;
1386 /* do a simple SNR for quality */
1387 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1388 iwe.cmd = IWEVQUAL;
1389 current_ev =
1390 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1391 IW_EV_QUAL_LEN);
1393 return current_ev;
1396 static int p80211wext_giwscan(netdevice_t *dev,
1397 struct iw_request_info *info,
1398 struct iw_point *srq, char *extra)
1400 wlandevice_t *wlandev = dev->ml_priv;
1401 p80211msg_dot11req_scan_results_t msg;
1402 int result = 0;
1403 int err = 0;
1404 int i = 0;
1405 int scan_good = 0;
1406 char *current_ev = extra;
1408 /* Since wireless tools doesn't really have a way of passing how
1409 * many scan results results there were back here, keep grabbing them
1410 * until we fail.
1412 do {
1413 memset(&msg, 0, sizeof(msg));
1414 msg.msgcode = DIDmsg_dot11req_scan_results;
1415 msg.bssindex.data = i;
1417 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1418 if ((result != 0) ||
1419 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1420 break;
1423 current_ev =
1424 wext_translate_bss(info, current_ev,
1425 extra + IW_SCAN_MAX_DATA, &msg);
1426 scan_good = 1;
1427 i++;
1428 } while (i < IW_MAX_AP);
1430 srq->length = (current_ev - extra);
1431 srq->flags = 0; /* todo */
1433 if (result && !scan_good)
1434 err = prism2_result2err(msg.resultcode.data);
1436 return err;
1439 /* extra wireless extensions stuff to support NetworkManager (I hope) */
1441 /* SIOCSIWENCODEEXT */
1442 static int p80211wext_set_encodeext(struct net_device *dev,
1443 struct iw_request_info *info,
1444 union iwreq_data *wrqu, char *extra)
1446 wlandevice_t *wlandev = dev->ml_priv;
1447 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1448 p80211msg_dot11req_mibset_t msg;
1449 p80211item_pstr32_t *pstr;
1451 int result = 0;
1452 struct iw_point *encoding = &wrqu->encoding;
1453 int idx = encoding->flags & IW_ENCODE_INDEX;
1455 pr_debug("set_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1456 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1458 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1459 /* set default key ? I'm not sure if this the the correct thing to do here */
1461 if (idx) {
1462 if (idx < 1 || idx > NUM_WEPKEYS)
1463 return -EINVAL;
1464 else
1465 idx--;
1467 pr_debug("setting default key (%d)\n", idx);
1468 result =
1469 p80211wext_dorequest(wlandev,
1470 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
1471 idx);
1472 if (result)
1473 return -EFAULT;
1476 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1477 if (ext->alg != IW_ENCODE_ALG_WEP) {
1478 pr_debug("asked to set a non wep key :(\n");
1479 return -EINVAL;
1481 if (idx) {
1482 if (idx < 1 || idx > NUM_WEPKEYS)
1483 return -EINVAL;
1484 else
1485 idx--;
1487 pr_debug("Set WEP key (%d)\n", idx);
1488 wlandev->wep_keylens[idx] = ext->key_len;
1489 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1491 memset(&msg, 0, sizeof(msg));
1492 pstr = (p80211item_pstr32_t *) & msg.mibattribute.data;
1493 memcpy(pstr->data.data, ext->key, ext->key_len);
1494 pstr->data.len = ext->key_len;
1495 switch (idx) {
1496 case 0:
1497 pstr->did =
1498 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1499 break;
1500 case 1:
1501 pstr->did =
1502 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1503 break;
1504 case 2:
1505 pstr->did =
1506 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1507 break;
1508 case 3:
1509 pstr->did =
1510 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1511 break;
1512 default:
1513 break;
1515 msg.msgcode = DIDmsg_dot11req_mibset;
1516 result = p80211req_dorequest(wlandev, (u8 *) & msg);
1517 pr_debug("result (%d)\n", result);
1519 return result;
1522 /* SIOCGIWENCODEEXT */
1523 static int p80211wext_get_encodeext(struct net_device *dev,
1524 struct iw_request_info *info,
1525 union iwreq_data *wrqu, char *extra)
1527 wlandevice_t *wlandev = dev->ml_priv;
1528 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1530 struct iw_point *encoding = &wrqu->encoding;
1531 int result = 0;
1532 int max_len;
1533 int idx;
1535 pr_debug("get_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1536 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1538 max_len = encoding->length - sizeof(*ext);
1539 if (max_len <= 0) {
1540 pr_debug("get_encodeext max_len [%d] invalid\n", max_len);
1541 result = -EINVAL;
1542 goto exit;
1544 idx = encoding->flags & IW_ENCODE_INDEX;
1546 pr_debug("get_encode_ext index [%d]\n", idx);
1548 if (idx) {
1549 if (idx < 1 || idx > NUM_WEPKEYS) {
1550 pr_debug("get_encode_ext invalid key index [%d]\n",
1551 idx);
1552 result = -EINVAL;
1553 goto exit;
1555 idx--;
1556 } else {
1557 /* default key ? not sure what to do */
1558 /* will just use key[0] for now ! FIX ME */
1561 encoding->flags = idx + 1;
1562 memset(ext, 0, sizeof(*ext));
1564 ext->alg = IW_ENCODE_ALG_WEP;
1565 ext->key_len = wlandev->wep_keylens[idx];
1566 memcpy(ext->key, wlandev->wep_keys[idx], ext->key_len);
1568 encoding->flags |= IW_ENCODE_ENABLED;
1569 exit:
1570 return result;
1573 /* SIOCSIWAUTH */
1574 static int p80211_wext_set_iwauth(struct net_device *dev,
1575 struct iw_request_info *info,
1576 union iwreq_data *wrqu, char *extra)
1578 wlandevice_t *wlandev = dev->ml_priv;
1579 struct iw_param *param = &wrqu->param;
1580 int result = 0;
1582 pr_debug("set_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1584 switch (param->flags & IW_AUTH_INDEX) {
1585 case IW_AUTH_DROP_UNENCRYPTED:
1586 pr_debug("drop_unencrypted %d\n", param->value);
1587 if (param->value)
1588 result =
1589 p80211wext_dorequest(wlandev,
1590 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1591 P80211ENUM_truth_true);
1592 else
1593 result =
1594 p80211wext_dorequest(wlandev,
1595 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1596 P80211ENUM_truth_false);
1597 break;
1599 case IW_AUTH_PRIVACY_INVOKED:
1600 pr_debug("privacy invoked %d\n", param->value);
1601 if (param->value)
1602 result =
1603 p80211wext_dorequest(wlandev,
1604 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1605 P80211ENUM_truth_true);
1606 else
1607 result =
1608 p80211wext_dorequest(wlandev,
1609 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1610 P80211ENUM_truth_false);
1612 break;
1614 case IW_AUTH_80211_AUTH_ALG:
1615 if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1616 pr_debug("set open_system\n");
1617 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1618 } else if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1619 pr_debug("set shared key\n");
1620 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1621 } else {
1622 /* don't know what to do know */
1623 pr_debug("unknown AUTH_ALG (%d)\n", param->value);
1624 result = -EINVAL;
1626 break;
1628 default:
1629 break;
1632 return result;
1635 /* SIOCSIWAUTH */
1636 static int p80211_wext_get_iwauth(struct net_device *dev,
1637 struct iw_request_info *info,
1638 union iwreq_data *wrqu, char *extra)
1640 wlandevice_t *wlandev = dev->ml_priv;
1641 struct iw_param *param = &wrqu->param;
1642 int result = 0;
1644 pr_debug("get_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1646 switch (param->flags & IW_AUTH_INDEX) {
1647 case IW_AUTH_DROP_UNENCRYPTED:
1648 param->value =
1649 wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED ? 1 : 0;
1650 break;
1652 case IW_AUTH_PRIVACY_INVOKED:
1653 param->value =
1654 wlandev->hostwep & HOSTWEP_PRIVACYINVOKED ? 1 : 0;
1655 break;
1657 case IW_AUTH_80211_AUTH_ALG:
1658 param->value =
1659 wlandev->hostwep & HOSTWEP_SHAREDKEY ?
1660 IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM;
1661 break;
1663 default:
1664 break;
1667 return result;
1670 static iw_handler p80211wext_handlers[] = {
1671 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1672 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1673 (iw_handler) NULL, /* SIOCSIWNWID */
1674 (iw_handler) NULL, /* SIOCGIWNWID */
1675 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1676 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1677 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1678 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1679 (iw_handler) NULL, /* SIOCSIWSENS */
1680 (iw_handler) NULL, /* SIOCGIWSENS */
1681 (iw_handler) NULL, /* not used *//* SIOCSIWRANGE */
1682 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1683 (iw_handler) NULL, /* not used *//* SIOCSIWPRIV */
1684 (iw_handler) NULL, /* kernel code *//* SIOCGIWPRIV */
1685 (iw_handler) NULL, /* not used *//* SIOCSIWSTATS */
1686 (iw_handler) NULL, /* kernel code *//* SIOCGIWSTATS */
1687 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1688 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1689 (iw_handler) NULL, /* -- hole -- */
1690 (iw_handler) NULL, /* -- hole -- */
1691 (iw_handler) NULL, /* SIOCSIWAP */
1692 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1693 (iw_handler) NULL, /* -- hole -- */
1694 (iw_handler) NULL, /* SIOCGIWAPLIST */
1695 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1696 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1697 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1698 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1699 (iw_handler) NULL, /* SIOCSIWNICKN */
1700 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1701 (iw_handler) NULL, /* -- hole -- */
1702 (iw_handler) NULL, /* -- hole -- */
1703 (iw_handler) NULL, /* SIOCSIWRATE */
1704 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1705 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1706 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1707 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1708 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1709 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1710 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1711 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1712 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1713 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1714 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1715 (iw_handler) NULL, /* SIOCSIWPOWER */
1716 (iw_handler) NULL, /* SIOCGIWPOWER */
1717 /* WPA operations */
1718 (iw_handler) NULL, /* -- hole -- */
1719 (iw_handler) NULL, /* -- hole -- */
1720 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1721 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1722 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1723 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1725 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1726 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1727 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1730 struct iw_handler_def p80211wext_handler_def = {
1731 .num_standard = ARRAY_SIZE(p80211wext_handlers),
1732 .num_private = 0,
1733 .num_private_args = 0,
1734 .standard = p80211wext_handlers,
1735 .private = NULL,
1736 .private_args = NULL,
1737 .get_wireless_stats = p80211wext_get_wireless_stats
1740 int p80211wext_event_associated(wlandevice_t * wlandev, int assoc)
1742 union iwreq_data data;
1744 /* Send the association state first */
1745 data.ap_addr.sa_family = ARPHRD_ETHER;
1746 if (assoc)
1747 memcpy(data.ap_addr.sa_data, wlandev->bssid, ETH_ALEN);
1748 else
1749 memset(data.ap_addr.sa_data, 0, ETH_ALEN);
1751 if (wlan_wext_write)
1752 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1754 if (!assoc)
1755 goto done;
1757 /* XXX send association data, like IEs, etc etc. */
1759 done:
1760 return 0;