Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
[linux-2.6.git] / drivers / staging / wlags49_h2 / wl_wext.c
blobc731ff2a6aa16301400199baed40bc3cc226a2b4
1 /*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
14 * SOFTWARE LICENSE
16 * This software is provided subject to the following terms and conditions,
17 * which you should read carefully before using the software. Using this
18 * software indicates your acceptance of these terms and conditions. If you do
19 * not agree with these terms and conditions, do not use the software.
21 * Copyright © 2003 Agere Systems Inc.
22 * All rights reserved.
24 * Redistribution and use in source or binary forms, with or without
25 * modifications, are permitted provided that the following conditions are met:
27 * . Redistributions of source code must retain the above copyright notice, this
28 * list of conditions and the following Disclaimer as comments in the code as
29 * well as in the documentation and/or other materials provided with the
30 * distribution.
32 * . Redistributions in binary form must reproduce the above copyright notice,
33 * this list of conditions and the following Disclaimer in the documentation
34 * and/or other materials provided with the distribution.
36 * . Neither the name of Agere Systems Inc. nor the names of the contributors
37 * may be used to endorse or promote products derived from this software
38 * without specific prior written permission.
40 * Disclaimer
42 * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
43 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
45 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
46 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53 * DAMAGE.
55 ******************************************************************************/
57 /*******************************************************************************
58 * include files
59 ******************************************************************************/
60 #include <wl_version.h>
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <linux/etherdevice.h>
66 #include <asm/uaccess.h>
68 #include <debug.h>
69 #include <hcf.h>
70 #include <hcfdef.h>
72 #include <wl_if.h>
73 #include <wl_internal.h>
74 #include <wl_util.h>
75 #include <wl_main.h>
76 #include <wl_wext.h>
77 #include <wl_priv.h>
79 /*******************************************************************************
80 * global definitions
81 ******************************************************************************/
82 #if DBG
83 extern dbg_info_t *DbgInfo;
84 #endif // DBG
87 /* Set up the LTV to program the appropriate key */
88 static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr,
89 int set_tx, u8 *seq, u8 *key, size_t key_len)
91 int ret = -EINVAL;
92 int buf_idx = 0;
93 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
94 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
96 DBG_ENTER(DbgInfo);
99 * Check the key index here; if 0, load as Pairwise Key, otherwise,
100 * load as a group key. Note that for the Hermes, the RIDs for
101 * group/pairwise keys are different from each other and different
102 * than the default WEP keys as well.
104 switch (key_idx) {
105 case 0:
106 ltv->len = 28;
107 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
109 /* Load the BSSID */
110 memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
111 buf_idx += ETH_ALEN;
113 /* Load the TKIP key */
114 memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
115 buf_idx += 16;
117 /* Load the TSC */
118 memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
119 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
121 /* Load the RSC */
122 memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
123 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
125 /* Load the TxMIC key */
126 memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
127 buf_idx += 8;
129 /* Load the RxMIC key */
130 memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
132 ret = 0;
133 break;
134 case 1:
135 case 2:
136 case 3:
137 ltv->len = 26;
138 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
140 /* Load the key Index */
142 /* If this is a Tx Key, set bit 8000 */
143 if (set_tx)
144 key_idx |= 0x8000;
145 ltv->u.u16[buf_idx] = cpu_to_le16(key_idx);
146 buf_idx += 2;
148 /* Load the RSC */
149 memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
150 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
152 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
153 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
154 memcpy(&ltv->u.u8[buf_idx], key, key_len);
155 buf_idx += key_len;
157 /* Load the TSC */
158 memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
160 ret = 0;
161 break;
162 default:
163 break;
166 DBG_LEAVE(DbgInfo);
167 return ret;
170 /* Set up the LTV to clear the appropriate key */
171 static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr)
173 int ret;
175 switch (key_idx) {
176 case 0:
177 if (!is_broadcast_ether_addr(addr)) {
178 ltv->len = 7;
179 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
180 memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
181 ret = 0;
183 break;
184 case 1:
185 case 2:
186 case 3:
187 /* Clear the Group TKIP keys by index */
188 ltv->len = 2;
189 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
190 ltv->u.u16[0] = cpu_to_le16(key_idx);
192 ret = 0;
193 break;
194 default:
195 break;
198 return ret;
201 /* Set the WEP keys in the wl_private structure */
202 static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
203 u8 *key, size_t key_len,
204 bool enable, bool set_tx)
206 hcf_8 encryption_state = lp->EnableEncryption;
207 int tk = lp->TransmitKeyID - 1; /* current key */
208 int ret = 0;
210 /* Is encryption supported? */
211 if (!wl_has_wep(&(lp->hcfCtx))) {
212 DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
213 ret = -EOPNOTSUPP;
214 goto out;
217 DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
218 key, key_len);
220 /* Check the size of the key */
221 switch (key_len) {
222 case MIN_KEY_SIZE:
223 case MAX_KEY_SIZE:
225 /* Check the index */
226 if ((key_idx < 0) || (key_idx >= MAX_KEYS))
227 key_idx = tk;
229 /* Cleanup */
230 memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
232 /* Copy the key in the driver */
233 memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
235 /* Set the length */
236 lp->DefaultKeys.key[key_idx].len = key_len;
238 DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
239 DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
240 lp->DefaultKeys.key[key_idx].key,
241 lp->DefaultKeys.key[key_idx].len, key_idx);
243 /* Enable WEP (if possible) */
244 if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
245 lp->EnableEncryption = 1;
247 break;
249 case 0:
250 /* Do we want to just set the current transmit key? */
251 if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
252 DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
253 lp->DefaultKeys.key[key_idx].len);
255 if (lp->DefaultKeys.key[key_idx].len > 0) {
256 lp->TransmitKeyID = key_idx + 1;
257 lp->EnableEncryption = 1;
258 } else {
259 DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
260 ret = -EINVAL;
263 break;
265 default:
266 DBG_WARNING(DbgInfo, "Invalid Key length\n");
267 ret = -EINVAL;
268 goto out;
271 /* Read the flags */
272 if (enable) {
273 lp->EnableEncryption = 1;
274 lp->wext_enc = IW_ENCODE_ALG_WEP;
275 } else {
276 lp->EnableEncryption = 0; /* disable encryption */
277 lp->wext_enc = IW_ENCODE_ALG_NONE;
280 DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
281 DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
282 DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
284 /* Write the changes to the card */
285 if (ret == 0) {
286 DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
287 lp->TransmitKeyID);
289 if (lp->EnableEncryption == encryption_state) {
290 if (key_len != 0) {
291 /* Dynamic WEP key update */
292 wl_set_wep_keys(lp);
294 } else {
295 /* To switch encryption on/off, soft reset is
296 * required */
297 wl_apply(lp);
301 out:
302 return ret;
305 /*******************************************************************************
306 * wireless_commit()
307 *******************************************************************************
309 * DESCRIPTION:
311 * Commit
312 * protocol used.
314 * PARAMETERS:
316 * wrq - the wireless request buffer
318 * RETURNS:
320 * N/A
322 ******************************************************************************/
323 static int wireless_commit(struct net_device *dev,
324 struct iw_request_info *info,
325 union iwreq_data *rqu, char *extra)
327 struct wl_private *lp = wl_priv(dev);
328 unsigned long flags;
329 int ret = 0;
330 /*------------------------------------------------------------------------*/
332 DBG_FUNC( "wireless_commit" );
333 DBG_ENTER(DbgInfo);
335 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
336 ret = -EBUSY;
337 goto out;
340 wl_lock( lp, &flags );
342 wl_act_int_off( lp );
344 wl_apply(lp);
346 wl_act_int_on( lp );
348 wl_unlock(lp, &flags);
350 out:
351 DBG_LEAVE( DbgInfo );
352 return ret;
353 } // wireless_commit
354 /*============================================================================*/
359 /*******************************************************************************
360 * wireless_get_protocol()
361 *******************************************************************************
363 * DESCRIPTION:
365 * Returns a vendor-defined string that should identify the wireless
366 * protocol used.
368 * PARAMETERS:
370 * wrq - the wireless request buffer
372 * RETURNS:
374 * N/A
376 ******************************************************************************/
377 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
379 DBG_FUNC( "wireless_get_protocol" );
380 DBG_ENTER( DbgInfo );
382 /* Originally, the driver was placing the string "Wireless" here. However,
383 the wireless extensions (/linux/wireless.h) indicate this string should
384 describe the wireless protocol. */
386 strcpy(name, "IEEE 802.11b");
388 DBG_LEAVE(DbgInfo);
389 return 0;
390 } // wireless_get_protocol
391 /*============================================================================*/
396 /*******************************************************************************
397 * wireless_set_frequency()
398 *******************************************************************************
400 * DESCRIPTION:
402 * Sets the frequency (channel) on which the card should Tx/Rx.
404 * PARAMETERS:
406 * wrq - the wireless request buffer
407 * lp - the device's private adapter structure
409 * RETURNS:
411 * 0 on success
412 * errno value otherwise
414 ******************************************************************************/
415 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
417 struct wl_private *lp = wl_priv(dev);
418 unsigned long flags;
419 int channel = 0;
420 int ret = 0;
421 /*------------------------------------------------------------------------*/
424 DBG_FUNC( "wireless_set_frequency" );
425 DBG_ENTER( DbgInfo );
427 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
428 ret = -EBUSY;
429 goto out;
432 if( !capable( CAP_NET_ADMIN )) {
433 ret = -EPERM;
434 DBG_LEAVE( DbgInfo );
435 return ret;
439 /* If frequency specified, look up channel */
440 if( freq->e == 1 ) {
441 int f = freq->m / 100000;
442 channel = wl_get_chan_from_freq( f );
446 /* Channel specified */
447 if( freq->e == 0 ) {
448 channel = freq->m;
452 /* If the channel is an 802.11a channel, set Bit 8 */
453 if( channel > 14 ) {
454 channel = channel | 0x100;
458 wl_lock( lp, &flags );
460 wl_act_int_off( lp );
462 lp->Channel = channel;
465 /* Commit the adapter parameters */
466 wl_apply( lp );
468 /* Send an event that channel/freq has been set */
469 wl_wext_event_freq( lp->dev );
471 wl_act_int_on( lp );
473 wl_unlock(lp, &flags);
475 out:
476 DBG_LEAVE( DbgInfo );
477 return ret;
478 } // wireless_set_frequency
479 /*============================================================================*/
484 /*******************************************************************************
485 * wireless_get_frequency()
486 *******************************************************************************
488 * DESCRIPTION:
490 * Gets the frequency (channel) on which the card is Tx/Rx.
492 * PARAMETERS:
494 * wrq - the wireless request buffer
495 * lp - the device's private adapter structure
497 * RETURNS:
499 * N/A
501 ******************************************************************************/
502 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
505 struct wl_private *lp = wl_priv(dev);
506 unsigned long flags;
507 int ret = -1;
508 /*------------------------------------------------------------------------*/
511 DBG_FUNC( "wireless_get_frequency" );
512 DBG_ENTER( DbgInfo );
514 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
515 ret = -EBUSY;
516 goto out;
519 wl_lock( lp, &flags );
521 wl_act_int_off( lp );
523 lp->ltvRecord.len = 2;
524 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
526 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
527 if( ret == HCF_SUCCESS ) {
528 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
530 freq->m = wl_get_freq_from_chan( channel ) * 100000;
531 freq->e = 1;
534 wl_act_int_on( lp );
536 wl_unlock(lp, &flags);
538 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
540 out:
541 DBG_LEAVE( DbgInfo );
542 return ret;
543 } // wireless_get_frequency
544 /*============================================================================*/
549 /*******************************************************************************
550 * wireless_get_range()
551 *******************************************************************************
553 * DESCRIPTION:
555 * This function is used to provide misc info and statistics about the
556 * wireless device.
558 * PARAMETERS:
560 * wrq - the wireless request buffer
561 * lp - the device's private adapter structure
563 * RETURNS:
565 * 0 on success
566 * errno value otherwise
568 ******************************************************************************/
569 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
571 struct wl_private *lp = wl_priv(dev);
572 unsigned long flags;
573 struct iw_range *range = (struct iw_range *) extra;
574 int ret = 0;
575 int status = -1;
576 int count;
577 __u16 *pTxRate;
578 int retries = 0;
579 /*------------------------------------------------------------------------*/
582 DBG_FUNC( "wireless_get_range" );
583 DBG_ENTER( DbgInfo );
585 /* Set range information */
586 data->length = sizeof(struct iw_range);
587 memset(range, 0, sizeof(struct iw_range));
589 wl_lock( lp, &flags );
591 wl_act_int_off( lp );
593 /* Set range information */
594 memset( range, 0, sizeof( struct iw_range ));
596 retry:
597 /* Get the current transmit rate from the adapter */
598 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
599 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
601 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
602 if( status != HCF_SUCCESS ) {
603 /* Recovery action: reset and retry up to 10 times */
604 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
606 if (retries < 10) {
607 retries++;
609 /* Holding the lock too long, makes a gap to allow other processes */
610 wl_unlock(lp, &flags);
611 wl_lock( lp, &flags );
613 status = wl_reset( dev );
614 if ( status != HCF_SUCCESS ) {
615 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
617 ret = -EFAULT;
618 goto out_unlock;
621 /* Holding the lock too long, makes a gap to allow other processes */
622 wl_unlock(lp, &flags);
623 wl_lock( lp, &flags );
625 goto retry;
627 } else {
628 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
629 ret = -EFAULT;
630 goto out_unlock;
634 /* Holding the lock too long, makes a gap to allow other processes */
635 wl_unlock(lp, &flags);
636 wl_lock( lp, &flags );
638 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
640 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
642 if (retries > 0) {
643 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
646 // NWID - NOT SUPPORTED
649 /* Channel/Frequency Info */
650 range->num_channels = RADIO_CHANNELS;
653 /* Signal Level Thresholds */
654 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
657 /* Link quality */
658 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
660 /* If the value returned in /proc/net/wireless is greater than the maximum range,
661 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
662 it requires a bit of contorsion... */
664 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
665 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
668 /* Set available rates */
669 range->num_bitrates = 0;
671 lp->ltvRecord.len = 6;
672 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
674 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
675 if( status == HCF_SUCCESS ) {
676 for( count = 0; count < MAX_RATES; count++ )
677 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
678 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
679 range->num_bitrates++;
681 } else {
682 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
683 ret = -EFAULT;
684 goto out_unlock;
687 /* RTS Threshold info */
688 range->min_rts = MIN_RTS_BYTES;
689 range->max_rts = MAX_RTS_BYTES;
691 // Frag Threshold info - NOT SUPPORTED
693 // Power Management info - NOT SUPPORTED
695 /* Encryption */
697 /* Holding the lock too long, makes a gap to allow other processes */
698 wl_unlock(lp, &flags);
699 wl_lock( lp, &flags );
701 /* Is WEP supported? */
703 if( wl_has_wep( &( lp->hcfCtx ))) {
704 /* WEP: RC4 40 bits */
705 range->encoding_size[0] = MIN_KEY_SIZE;
707 /* RC4 ~128 bits */
708 range->encoding_size[1] = MAX_KEY_SIZE;
709 range->num_encoding_sizes = 2;
710 range->max_encoding_tokens = MAX_KEYS;
713 /* Tx Power Info */
714 range->txpower_capa = IW_TXPOW_MWATT;
715 range->num_txpower = 1;
716 range->txpower[0] = RADIO_TX_POWER_MWATT;
718 /* Wireless Extension Info */
719 range->we_version_compiled = WIRELESS_EXT;
720 range->we_version_source = WIRELESS_SUPPORT;
722 // Retry Limits and Lifetime - NOT SUPPORTED
724 /* Holding the lock too long, makes a gap to allow other processes */
725 wl_unlock(lp, &flags);
726 wl_lock( lp, &flags );
728 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
729 wl_wireless_stats( lp->dev );
730 range->avg_qual = lp->wstats.qual;
731 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
733 /* Event capability (kernel + driver) */
734 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
735 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
736 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
737 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
738 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
739 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
740 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
741 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
743 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
744 range->scan_capa = IW_SCAN_CAPA_NONE;
746 out_unlock:
747 wl_act_int_on( lp );
749 wl_unlock(lp, &flags);
751 DBG_LEAVE(DbgInfo);
752 return ret;
753 } // wireless_get_range
754 /*============================================================================*/
757 /*******************************************************************************
758 * wireless_get_bssid()
759 *******************************************************************************
761 * DESCRIPTION:
763 * Gets the BSSID the wireless device is currently associated with.
765 * PARAMETERS:
767 * wrq - the wireless request buffer
768 * lp - the device's private adapter structure
770 * RETURNS:
772 * 0 on success
773 * errno value otherwise
775 ******************************************************************************/
776 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
778 struct wl_private *lp = wl_priv(dev);
779 unsigned long flags;
780 int ret = 0;
781 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
782 int status = -1;
783 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
784 /*------------------------------------------------------------------------*/
787 DBG_FUNC( "wireless_get_bssid" );
788 DBG_ENTER( DbgInfo );
790 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
791 ret = -EBUSY;
792 goto out;
795 wl_lock( lp, &flags );
797 wl_act_int_off( lp );
799 ap_addr->sa_family = ARPHRD_ETHER;
801 /* Assume AP mode here, which means the BSSID is our own MAC address. In
802 STA mode, this address will be overwritten with the actual BSSID using
803 the code below. */
804 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
807 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
808 //;?should we return an error status in AP mode
810 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
811 /* Get Current BSSID */
812 lp->ltvRecord.typ = CFG_CUR_BSSID;
813 lp->ltvRecord.len = 4;
814 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
816 if( status == HCF_SUCCESS ) {
817 /* Copy info into sockaddr struct */
818 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
819 } else {
820 ret = -EFAULT;
824 #endif // (HCF_TYPE) & HCF_TYPE_STA
826 wl_act_int_on( lp );
828 wl_unlock(lp, &flags);
830 out:
831 DBG_LEAVE(DbgInfo);
832 return ret;
833 } // wireless_get_bssid
834 /*============================================================================*/
839 /*******************************************************************************
840 * wireless_get_ap_list()
841 *******************************************************************************
843 * DESCRIPTION:
845 * Gets the results of a network scan.
847 * PARAMETERS:
849 * wrq - the wireless request buffer
850 * lp - the device's private adapter structure
852 * RETURNS:
854 * 0 on success
855 * errno value otherwise
857 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
858 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
859 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
861 ******************************************************************************/
862 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
864 struct wl_private *lp = wl_priv(dev);
865 unsigned long flags;
866 int ret;
867 int num_aps = -1;
868 int sec_count = 0;
869 hcf_32 count;
870 struct sockaddr *hwa = NULL;
871 struct iw_quality *qual = NULL;
872 #ifdef WARP
873 ScanResult *p = &lp->scan_results;
874 #else
875 ProbeResult *p = &lp->probe_results;
876 #endif // WARP
877 /*------------------------------------------------------------------------*/
879 DBG_FUNC( "wireless_get_ap_list" );
880 DBG_ENTER( DbgInfo );
882 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
883 ret = -EBUSY;
884 goto out;
887 wl_lock( lp, &flags );
889 wl_act_int_off( lp );
891 /* Set the completion state to FALSE */
892 lp->scan_results.scan_complete = FALSE;
893 lp->probe_results.scan_complete = FALSE;
894 /* Channels to scan */
895 lp->ltvRecord.len = 2;
896 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
897 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
898 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
899 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
901 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
902 disassociate from the network we are currently on */
903 lp->ltvRecord.len = 2;
904 lp->ltvRecord.typ = CFG_SCAN_SSID;
905 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
906 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
907 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
909 /* Initiate the scan */
910 #ifdef WARP
911 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
912 #else
913 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
914 #endif // WARP
916 wl_act_int_on( lp );
918 //;? unlock? what about the access to lp below? is it broken?
919 wl_unlock(lp, &flags);
921 if( ret == HCF_SUCCESS ) {
922 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
923 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
924 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
925 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
926 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
927 ret = -EIO;
928 } else {
929 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
930 other things in the meantime, This prevents system lockups by
931 giving some time back to the kernel */
932 for( count = 0; count < 100; count ++ ) {
933 mdelay( 10 );
934 schedule( );
939 rmb();
941 if ( ret != HCF_SUCCESS ) {
942 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
943 } else {
944 num_aps = (*p)/*lp->probe_results*/.num_aps;
945 if (num_aps > IW_MAX_AP) {
946 num_aps = IW_MAX_AP;
948 data->length = num_aps;
949 hwa = (struct sockaddr *)extra;
950 qual = (struct iw_quality *) extra +
951 ( sizeof( struct sockaddr ) * num_aps );
953 /* This flag is used to tell the user if we provide quality
954 information. Since we provide signal/noise levels but no
955 quality info on a scan, this is set to 0. Setting to 1 and
956 providing a quality of 0 produces weird results. If we ever
957 provide quality (or can calculate it), this can be changed */
958 data->flags = 0;
960 for( count = 0; count < num_aps; count++ ) {
961 #ifdef WARP
962 memcpy( hwa[count].sa_data,
963 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
964 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
965 DBG_PRINT("BSSID: %pM\n",
966 (*p).ProbeTable[count].BSSID);
967 memcpy( hwa[count].sa_data,
968 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
969 #endif // WARP
971 /* Once the data is copied to the wireless struct, invalidate the
972 scan result to initiate a rescan on the next request */
973 (*p)/*lp->probe_results*/.scan_complete = FALSE;
974 /* Send the wireless event that the scan has completed, just in case
975 it's needed */
976 wl_wext_event_scan_complete( lp->dev );
979 out:
980 DBG_LEAVE( DbgInfo );
981 return ret;
982 } // wireless_get_ap_list
983 /*============================================================================*/
988 /*******************************************************************************
989 * wireless_set_sensitivity()
990 *******************************************************************************
992 * DESCRIPTION:
994 * Sets the sensitivity (distance between APs) of the wireless card.
996 * PARAMETERS:
998 * wrq - the wireless request buffer
999 * lp - the device's private adapter structure
1001 * RETURNS:
1003 * 0 on success
1004 * errno value otherwise
1006 ******************************************************************************/
1007 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1009 struct wl_private *lp = wl_priv(dev);
1010 unsigned long flags;
1011 int ret = 0;
1012 int dens = sens->value;
1013 /*------------------------------------------------------------------------*/
1016 DBG_FUNC( "wireless_set_sensitivity" );
1017 DBG_ENTER( DbgInfo );
1019 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1020 ret = -EBUSY;
1021 goto out;
1024 if(( dens < 1 ) || ( dens > 3 )) {
1025 ret = -EINVAL;
1026 goto out;
1029 wl_lock( lp, &flags );
1031 wl_act_int_off( lp );
1033 lp->DistanceBetweenAPs = dens;
1034 wl_apply( lp );
1036 wl_act_int_on( lp );
1038 wl_unlock(lp, &flags);
1040 out:
1041 DBG_LEAVE( DbgInfo );
1042 return ret;
1043 } // wireless_set_sensitivity
1044 /*============================================================================*/
1049 /*******************************************************************************
1050 * wireless_get_sensitivity()
1051 *******************************************************************************
1053 * DESCRIPTION:
1055 * Gets the sensitivity (distance between APs) of the wireless card.
1057 * PARAMETERS:
1059 * wrq - the wireless request buffer
1060 * lp - the device's private adapter structure
1062 * RETURNS:
1064 * 0 on success
1065 * errno value otherwise
1067 ******************************************************************************/
1068 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1070 struct wl_private *lp = wl_priv(dev);
1071 int ret = 0;
1072 /*------------------------------------------------------------------------*/
1073 /*------------------------------------------------------------------------*/
1076 DBG_FUNC( "wireless_get_sensitivity" );
1077 DBG_ENTER( DbgInfo );
1079 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1080 ret = -EBUSY;
1081 goto out;
1084 /* not worth locking ... */
1085 sens->value = lp->DistanceBetweenAPs;
1086 sens->fixed = 0; /* auto */
1087 out:
1088 DBG_LEAVE( DbgInfo );
1089 return ret;
1090 } // wireless_get_sensitivity
1091 /*============================================================================*/
1096 /*******************************************************************************
1097 * wireless_set_essid()
1098 *******************************************************************************
1100 * DESCRIPTION:
1102 * Sets the ESSID (network name) that the wireless device should associate
1103 * with.
1105 * PARAMETERS:
1107 * wrq - the wireless request buffer
1108 * lp - the device's private adapter structure
1110 * RETURNS:
1112 * 0 on success
1113 * errno value otherwise
1115 ******************************************************************************/
1116 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
1118 struct wl_private *lp = wl_priv(dev);
1119 unsigned long flags;
1120 int ret = 0;
1122 DBG_FUNC( "wireless_set_essid" );
1123 DBG_ENTER( DbgInfo );
1125 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1126 ret = -EBUSY;
1127 goto out;
1130 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
1131 ret = -EINVAL;
1132 goto out;
1135 wl_lock( lp, &flags );
1137 wl_act_int_off( lp );
1139 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
1141 /* data->flags is zero to ask for "any" */
1142 if( data->flags == 0 ) {
1143 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
1144 * ;?but there ain't no STAP anymore*/
1145 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
1146 strcpy( lp->NetworkName, "ANY" );
1147 } else {
1148 //strcpy( lp->NetworkName, "ANY" );
1149 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
1151 } else {
1152 memcpy( lp->NetworkName, ssid, data->length );
1155 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1157 /* Commit the adapter parameters */
1158 wl_apply( lp );
1160 /* Send an event that ESSID has been set */
1161 wl_wext_event_essid( lp->dev );
1163 wl_act_int_on( lp );
1165 wl_unlock(lp, &flags);
1167 out:
1168 DBG_LEAVE( DbgInfo );
1169 return ret;
1170 } // wireless_set_essid
1171 /*============================================================================*/
1176 /*******************************************************************************
1177 * wireless_get_essid()
1178 *******************************************************************************
1180 * DESCRIPTION:
1182 * Gets the ESSID (network name) that the wireless device is associated
1183 * with.
1185 * PARAMETERS:
1187 * wrq - the wireless request buffer
1188 * lp - the device's private adapter structure
1190 * RETURNS:
1192 * 0 on success
1193 * errno value otherwise
1195 ******************************************************************************/
1196 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1199 struct wl_private *lp = wl_priv(dev);
1200 unsigned long flags;
1201 int ret = 0;
1202 int status = -1;
1203 wvName_t *pName;
1204 /*------------------------------------------------------------------------*/
1207 DBG_FUNC( "wireless_get_essid" );
1208 DBG_ENTER( DbgInfo );
1210 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1211 ret = -EBUSY;
1212 goto out;
1215 wl_lock( lp, &flags );
1217 wl_act_int_off( lp );
1219 /* Get the desired network name */
1220 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1223 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1224 //;?should we return an error status in AP mode
1226 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1228 #endif
1231 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1232 //;?should we restore this to allow smaller memory footprint
1234 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1235 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1238 #endif // HCF_AP
1241 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1242 if( status == HCF_SUCCESS ) {
1243 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1245 /* Endian translate the string length */
1246 pName->length = CNV_LITTLE_TO_INT( pName->length );
1248 /* Copy the information into the user buffer */
1249 data->length = pName->length;
1251 if( pName->length < HCF_MAX_NAME_LEN ) {
1252 pName->name[pName->length] = '\0';
1255 data->flags = 1;
1258 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1259 //;?should we return an error status in AP mode
1261 /* if desired is null ("any"), return current or "any" */
1262 if( pName->name[0] == '\0' ) {
1263 /* Get the current network name */
1264 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1265 lp->ltvRecord.typ = CFG_CUR_SSID;
1267 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1269 if( status == HCF_SUCCESS ) {
1270 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1272 /* Endian translate the string length */
1273 pName->length = CNV_LITTLE_TO_INT( pName->length );
1275 /* Copy the information into the user buffer */
1276 data->length = pName->length;
1277 data->flags = 1;
1278 } else {
1279 ret = -EFAULT;
1280 goto out_unlock;
1284 #endif // HCF_STA
1286 if (pName->length > IW_ESSID_MAX_SIZE) {
1287 ret = -EFAULT;
1288 goto out_unlock;
1291 memcpy(essid, pName->name, pName->length);
1292 } else {
1293 ret = -EFAULT;
1294 goto out_unlock;
1297 out_unlock:
1298 wl_act_int_on( lp );
1300 wl_unlock(lp, &flags);
1302 out:
1303 DBG_LEAVE( DbgInfo );
1304 return ret;
1305 } // wireless_get_essid
1306 /*============================================================================*/
1311 /*******************************************************************************
1312 * wireless_set_encode()
1313 *******************************************************************************
1315 * DESCRIPTION:
1317 * Sets the encryption keys and status (enable or disable).
1319 * PARAMETERS:
1321 * wrq - the wireless request buffer
1322 * lp - the device's private adapter structure
1324 * RETURNS:
1326 * 0 on success
1327 * errno value otherwise
1329 ******************************************************************************/
1330 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1332 struct wl_private *lp = wl_priv(dev);
1333 unsigned long flags;
1334 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1335 int ret = 0;
1336 bool enable = true;
1338 DBG_ENTER(DbgInfo);
1340 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
1341 ret = -EBUSY;
1342 goto out;
1345 if (erq->flags & IW_ENCODE_DISABLED)
1346 enable = false;
1348 wl_lock(lp, &flags);
1350 wl_act_int_off(lp);
1352 ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1353 enable, true);
1355 /* Send an event that Encryption has been set */
1356 if (ret == 0)
1357 wl_wext_event_encode(dev);
1359 wl_act_int_on(lp);
1361 wl_unlock(lp, &flags);
1363 out:
1364 DBG_LEAVE(DbgInfo);
1365 return ret;
1368 /*******************************************************************************
1369 * wireless_get_encode()
1370 *******************************************************************************
1372 * DESCRIPTION:
1374 * Gets the encryption keys and status.
1376 * PARAMETERS:
1378 * wrq - the wireless request buffer
1379 * lp - the device's private adapter structure
1381 * RETURNS:
1383 * 0 on success
1384 * errno value otherwise
1386 ******************************************************************************/
1387 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1390 struct wl_private *lp = wl_priv(dev);
1391 unsigned long flags;
1392 int ret = 0;
1393 int index;
1394 /*------------------------------------------------------------------------*/
1397 DBG_FUNC( "wireless_get_encode" );
1398 DBG_ENTER( DbgInfo );
1399 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1401 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1402 ret = -EBUSY;
1403 goto out;
1406 /* Only super-user can see WEP key */
1407 if( !capable( CAP_NET_ADMIN )) {
1408 ret = -EPERM;
1409 DBG_LEAVE( DbgInfo );
1410 return ret;
1413 wl_lock( lp, &flags );
1415 wl_act_int_off( lp );
1417 /* Is it supported? */
1418 if( !wl_has_wep( &( lp->hcfCtx ))) {
1419 ret = -EOPNOTSUPP;
1420 goto out_unlock;
1423 /* Basic checking */
1424 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1427 /* Set the flags */
1428 erq->flags = 0;
1430 if( lp->EnableEncryption == 0 ) {
1431 erq->flags |= IW_ENCODE_DISABLED;
1434 /* Which key do we want */
1435 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1436 index = lp->TransmitKeyID - 1;
1439 erq->flags |= index + 1;
1441 /* Copy the key to the user buffer */
1442 erq->length = lp->DefaultKeys.key[index].len;
1444 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1446 out_unlock:
1448 wl_act_int_on( lp );
1450 wl_unlock(lp, &flags);
1452 out:
1453 DBG_LEAVE( DbgInfo );
1454 return ret;
1455 } // wireless_get_encode
1456 /*============================================================================*/
1461 /*******************************************************************************
1462 * wireless_set_nickname()
1463 *******************************************************************************
1465 * DESCRIPTION:
1467 * Sets the nickname, or station name, of the wireless device.
1469 * PARAMETERS:
1471 * wrq - the wireless request buffer
1472 * lp - the device's private adapter structure
1474 * RETURNS:
1476 * 0 on success
1477 * errno value otherwise
1479 ******************************************************************************/
1480 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1482 struct wl_private *lp = wl_priv(dev);
1483 unsigned long flags;
1484 int ret = 0;
1485 /*------------------------------------------------------------------------*/
1488 DBG_FUNC( "wireless_set_nickname" );
1489 DBG_ENTER( DbgInfo );
1491 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1492 ret = -EBUSY;
1493 goto out;
1496 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1497 if( !capable(CAP_NET_ADMIN )) {
1498 ret = -EPERM;
1499 DBG_LEAVE( DbgInfo );
1500 return ret;
1502 #endif
1504 /* Validate the new value */
1505 if(data->length > HCF_MAX_NAME_LEN) {
1506 ret = -EINVAL;
1507 goto out;
1510 wl_lock( lp, &flags );
1512 wl_act_int_off( lp );
1514 memset( lp->StationName, 0, sizeof( lp->StationName ));
1516 memcpy( lp->StationName, nickname, data->length );
1518 /* Commit the adapter parameters */
1519 wl_apply( lp );
1521 wl_act_int_on( lp );
1523 wl_unlock(lp, &flags);
1525 out:
1526 DBG_LEAVE( DbgInfo );
1527 return ret;
1528 } // wireless_set_nickname
1529 /*============================================================================*/
1534 /*******************************************************************************
1535 * wireless_get_nickname()
1536 *******************************************************************************
1538 * DESCRIPTION:
1540 * Gets the nickname, or station name, of the wireless device.
1542 * PARAMETERS:
1544 * wrq - the wireless request buffer
1545 * lp - the device's private adapter structure
1547 * RETURNS:
1549 * 0 on success
1550 * errno value otherwise
1552 ******************************************************************************/
1553 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1555 struct wl_private *lp = wl_priv(dev);
1556 unsigned long flags;
1557 int ret = 0;
1558 int status = -1;
1559 wvName_t *pName;
1560 /*------------------------------------------------------------------------*/
1563 DBG_FUNC( "wireless_get_nickname" );
1564 DBG_ENTER( DbgInfo );
1566 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1567 ret = -EBUSY;
1568 goto out;
1571 wl_lock( lp, &flags );
1573 wl_act_int_off( lp );
1575 /* Get the current station name */
1576 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1577 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1579 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1581 if( status == HCF_SUCCESS ) {
1582 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1584 /* Endian translate the length */
1585 pName->length = CNV_LITTLE_TO_INT( pName->length );
1587 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1588 ret = -EFAULT;
1589 } else {
1590 /* Copy the information into the user buffer */
1591 data->length = pName->length;
1592 memcpy(nickname, pName->name, pName->length);
1594 } else {
1595 ret = -EFAULT;
1598 wl_act_int_on( lp );
1600 wl_unlock(lp, &flags);
1602 out:
1603 DBG_LEAVE(DbgInfo);
1604 return ret;
1605 } // wireless_get_nickname
1606 /*============================================================================*/
1611 /*******************************************************************************
1612 * wireless_set_porttype()
1613 *******************************************************************************
1615 * DESCRIPTION:
1617 * Sets the port type of the wireless device.
1619 * PARAMETERS:
1621 * wrq - the wireless request buffer
1622 * lp - the device's private adapter structure
1624 * RETURNS:
1626 * 0 on success
1627 * errno value otherwise
1629 ******************************************************************************/
1630 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1632 struct wl_private *lp = wl_priv(dev);
1633 unsigned long flags;
1634 int ret = 0;
1635 hcf_16 portType;
1636 hcf_16 createIBSS;
1637 /*------------------------------------------------------------------------*/
1639 DBG_FUNC( "wireless_set_porttype" );
1640 DBG_ENTER( DbgInfo );
1642 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1643 ret = -EBUSY;
1644 goto out;
1647 wl_lock( lp, &flags );
1649 wl_act_int_off( lp );
1651 /* Validate the new value */
1652 switch( *mode ) {
1653 case IW_MODE_ADHOC:
1655 /* When user requests ad-hoc, set IBSS mode! */
1656 portType = 1;
1657 createIBSS = 1;
1659 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1661 break;
1664 case IW_MODE_AUTO:
1665 case IW_MODE_INFRA:
1667 /* Both automatic and infrastructure set port to BSS/STA mode */
1668 portType = 1;
1669 createIBSS = 0;
1671 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1673 break;
1676 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1678 case IW_MODE_MASTER:
1680 /* Set BSS/AP mode */
1681 portType = 1;
1683 lp->CreateIBSS = 0;
1684 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1686 break;
1688 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1691 default:
1693 portType = 0;
1694 createIBSS = 0;
1695 ret = -EINVAL;
1698 if( portType != 0 ) {
1699 /* Only do something if there is a mode change */
1700 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1701 lp->PortType = portType;
1702 lp->CreateIBSS = createIBSS;
1704 /* Commit the adapter parameters */
1705 wl_go( lp );
1707 /* Send an event that mode has been set */
1708 wl_wext_event_mode( lp->dev );
1712 wl_act_int_on( lp );
1714 wl_unlock(lp, &flags);
1716 out:
1717 DBG_LEAVE( DbgInfo );
1718 return ret;
1719 } // wireless_set_porttype
1720 /*============================================================================*/
1725 /*******************************************************************************
1726 * wireless_get_porttype()
1727 *******************************************************************************
1729 * DESCRIPTION:
1731 * Gets the port type of the wireless device.
1733 * PARAMETERS:
1735 * wrq - the wireless request buffer
1736 * lp - the device's private adapter structure
1738 * RETURNS:
1740 * 0 on success
1741 * errno value otherwise
1743 ******************************************************************************/
1744 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1747 struct wl_private *lp = wl_priv(dev);
1748 unsigned long flags;
1749 int ret = 0;
1750 int status = -1;
1751 hcf_16 *pPortType;
1752 /*------------------------------------------------------------------------*/
1755 DBG_FUNC( "wireless_get_porttype" );
1756 DBG_ENTER( DbgInfo );
1758 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1759 ret = -EBUSY;
1760 goto out;
1763 wl_lock( lp, &flags );
1765 wl_act_int_off( lp );
1767 /* Get the current port type */
1768 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1769 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1771 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1773 if( status == HCF_SUCCESS ) {
1774 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1776 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1778 switch( *pPortType ) {
1779 case 1:
1781 #if 0
1782 #if (HCF_TYPE) & HCF_TYPE_AP
1784 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1785 *mode = IW_MODE_MASTER;
1786 } else {
1787 *mode = IW_MODE_INFRA;
1790 #else
1792 *mode = IW_MODE_INFRA;
1794 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1795 #endif
1797 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1798 *mode = IW_MODE_MASTER;
1799 } else {
1800 if( lp->CreateIBSS ) {
1801 *mode = IW_MODE_ADHOC;
1802 } else {
1803 *mode = IW_MODE_INFRA;
1807 break;
1810 case 3:
1811 *mode = IW_MODE_ADHOC;
1812 break;
1814 default:
1815 ret = -EFAULT;
1816 break;
1818 } else {
1819 ret = -EFAULT;
1822 wl_act_int_on( lp );
1824 wl_unlock(lp, &flags);
1826 out:
1827 DBG_LEAVE( DbgInfo );
1828 return ret;
1829 } // wireless_get_porttype
1830 /*============================================================================*/
1835 /*******************************************************************************
1836 * wireless_set_power()
1837 *******************************************************************************
1839 * DESCRIPTION:
1841 * Sets the power management settings of the wireless device.
1843 * PARAMETERS:
1845 * wrq - the wireless request buffer
1846 * lp - the device's private adapter structure
1848 * RETURNS:
1850 * 0 on success
1851 * errno value otherwise
1853 ******************************************************************************/
1854 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1856 struct wl_private *lp = wl_priv(dev);
1857 unsigned long flags;
1858 int ret = 0;
1859 /*------------------------------------------------------------------------*/
1862 DBG_FUNC( "wireless_set_power" );
1863 DBG_ENTER( DbgInfo );
1865 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1866 ret = -EBUSY;
1867 goto out;
1870 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1872 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1873 if( !capable( CAP_NET_ADMIN )) {
1874 ret = -EPERM;
1876 DBG_LEAVE( DbgInfo );
1877 return ret;
1879 #endif
1881 wl_lock( lp, &flags );
1883 wl_act_int_off( lp );
1885 /* Set the power management state based on the 'disabled' value */
1886 if( wrq->disabled ) {
1887 lp->PMEnabled = 0;
1888 } else {
1889 lp->PMEnabled = 1;
1892 /* Commit the adapter parameters */
1893 wl_apply( lp );
1895 wl_act_int_on( lp );
1897 wl_unlock(lp, &flags);
1899 out:
1900 DBG_LEAVE( DbgInfo );
1901 return ret;
1902 } // wireless_set_power
1903 /*============================================================================*/
1908 /*******************************************************************************
1909 * wireless_get_power()
1910 *******************************************************************************
1912 * DESCRIPTION:
1914 * Gets the power management settings of the wireless device.
1916 * PARAMETERS:
1918 * wrq - the wireless request buffer
1919 * lp - the device's private adapter structure
1921 * RETURNS:
1923 * 0 on success
1924 * errno value otherwise
1926 ******************************************************************************/
1927 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1930 struct wl_private *lp = wl_priv(dev);
1931 unsigned long flags;
1932 int ret = 0;
1933 /*------------------------------------------------------------------------*/
1934 DBG_FUNC( "wireless_get_power" );
1935 DBG_ENTER( DbgInfo );
1937 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1938 ret = -EBUSY;
1939 goto out;
1942 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1944 wl_lock( lp, &flags );
1946 wl_act_int_off( lp );
1948 rrq->flags = 0;
1949 rrq->value = 0;
1951 if( lp->PMEnabled ) {
1952 rrq->disabled = 0;
1953 } else {
1954 rrq->disabled = 1;
1957 wl_act_int_on( lp );
1959 wl_unlock(lp, &flags);
1961 out:
1962 DBG_LEAVE( DbgInfo );
1963 return ret;
1964 } // wireless_get_power
1965 /*============================================================================*/
1970 /*******************************************************************************
1971 * wireless_get_tx_power()
1972 *******************************************************************************
1974 * DESCRIPTION:
1976 * Gets the transmit power of the wireless device's radio.
1978 * PARAMETERS:
1980 * wrq - the wireless request buffer
1981 * lp - the device's private adapter structure
1983 * RETURNS:
1985 * 0 on success
1986 * errno value otherwise
1988 ******************************************************************************/
1989 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1991 struct wl_private *lp = wl_priv(dev);
1992 unsigned long flags;
1993 int ret = 0;
1994 /*------------------------------------------------------------------------*/
1995 DBG_FUNC( "wireless_get_tx_power" );
1996 DBG_ENTER( DbgInfo );
1998 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1999 ret = -EBUSY;
2000 goto out;
2003 wl_lock( lp, &flags );
2005 wl_act_int_off( lp );
2007 #ifdef USE_POWER_DBM
2008 rrq->value = RADIO_TX_POWER_DBM;
2009 rrq->flags = IW_TXPOW_DBM;
2010 #else
2011 rrq->value = RADIO_TX_POWER_MWATT;
2012 rrq->flags = IW_TXPOW_MWATT;
2013 #endif
2014 rrq->fixed = 1;
2015 rrq->disabled = 0;
2017 wl_act_int_on( lp );
2019 wl_unlock(lp, &flags);
2021 out:
2022 DBG_LEAVE( DbgInfo );
2023 return ret;
2024 } // wireless_get_tx_power
2025 /*============================================================================*/
2030 /*******************************************************************************
2031 * wireless_set_rts_threshold()
2032 *******************************************************************************
2034 * DESCRIPTION:
2036 * Sets the RTS threshold for the wireless card.
2038 * PARAMETERS:
2040 * wrq - the wireless request buffer
2041 * lp - the device's private adapter structure
2043 * RETURNS:
2045 * 0 on success
2046 * errno value otherwise
2048 ******************************************************************************/
2049 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2051 int ret = 0;
2052 struct wl_private *lp = wl_priv(dev);
2053 unsigned long flags;
2054 int rthr = rts->value;
2055 /*------------------------------------------------------------------------*/
2058 DBG_FUNC( "wireless_set_rts_threshold" );
2059 DBG_ENTER( DbgInfo );
2061 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2062 ret = -EBUSY;
2063 goto out;
2066 if(rts->fixed == 0) {
2067 ret = -EINVAL;
2068 goto out;
2071 if( rts->disabled ) {
2072 rthr = 2347;
2075 if(( rthr < 256 ) || ( rthr > 2347 )) {
2076 ret = -EINVAL;
2077 goto out;
2080 wl_lock( lp, &flags );
2082 wl_act_int_off( lp );
2084 lp->RTSThreshold = rthr;
2086 wl_apply( lp );
2088 wl_act_int_on( lp );
2090 wl_unlock(lp, &flags);
2092 out:
2093 DBG_LEAVE( DbgInfo );
2094 return ret;
2095 } // wireless_set_rts_threshold
2096 /*============================================================================*/
2101 /*******************************************************************************
2102 * wireless_get_rts_threshold()
2103 *******************************************************************************
2105 * DESCRIPTION:
2107 * Gets the RTS threshold for the wireless card.
2109 * PARAMETERS:
2111 * wrq - the wireless request buffer
2112 * lp - the device's private adapter structure
2114 * RETURNS:
2116 * 0 on success
2117 * errno value otherwise
2119 ******************************************************************************/
2120 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2122 int ret = 0;
2123 struct wl_private *lp = wl_priv(dev);
2124 unsigned long flags;
2125 /*------------------------------------------------------------------------*/
2127 DBG_FUNC( "wireless_get_rts_threshold" );
2128 DBG_ENTER( DbgInfo );
2130 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2131 ret = -EBUSY;
2132 goto out;
2135 wl_lock( lp, &flags );
2137 wl_act_int_off( lp );
2139 rts->value = lp->RTSThreshold;
2141 rts->disabled = ( rts->value == 2347 );
2143 rts->fixed = 1;
2145 wl_act_int_on( lp );
2147 wl_unlock(lp, &flags);
2149 out:
2150 DBG_LEAVE( DbgInfo );
2151 return ret;
2152 } // wireless_get_rts_threshold
2153 /*============================================================================*/
2159 /*******************************************************************************
2160 * wireless_set_rate()
2161 *******************************************************************************
2163 * DESCRIPTION:
2165 * Set the default data rate setting used by the wireless device.
2167 * PARAMETERS:
2169 * wrq - the wireless request buffer
2170 * lp - the device's private adapter structure
2172 * RETURNS:
2174 * 0 on success
2175 * errno value otherwise
2177 ******************************************************************************/
2178 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2180 struct wl_private *lp = wl_priv(dev);
2181 unsigned long flags;
2182 int ret = 0;
2183 #ifdef WARP
2184 int status = -1;
2185 int index = 0;
2186 #endif // WARP
2187 /*------------------------------------------------------------------------*/
2190 DBG_FUNC( "wireless_set_rate" );
2191 DBG_ENTER( DbgInfo );
2193 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2194 ret = -EBUSY;
2195 goto out;
2198 wl_lock( lp, &flags );
2200 wl_act_int_off( lp );
2202 #ifdef WARP
2204 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2205 if Bit 9 is set in the current channel RID */
2206 lp->ltvRecord.len = 2;
2207 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2209 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2211 if( status == HCF_SUCCESS ) {
2212 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2214 DBG_PRINT( "Index: %d\n", index );
2215 } else {
2216 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2217 DBG_LEAVE( DbgInfo );
2218 ret = -EINVAL;
2219 goto out_unlock;
2222 if( rrq->value > 0 &&
2223 rrq->value <= 1 * MEGABIT ) {
2224 lp->TxRateControl[index] = 0x0001;
2226 else if( rrq->value > 1 * MEGABIT &&
2227 rrq->value <= 2 * MEGABIT ) {
2228 if( rrq->fixed == 1 ) {
2229 lp->TxRateControl[index] = 0x0002;
2230 } else {
2231 lp->TxRateControl[index] = 0x0003;
2234 else if( rrq->value > 2 * MEGABIT &&
2235 rrq->value <= 5 * MEGABIT ) {
2236 if( rrq->fixed == 1 ) {
2237 lp->TxRateControl[index] = 0x0004;
2238 } else {
2239 lp->TxRateControl[index] = 0x0007;
2242 else if( rrq->value > 5 * MEGABIT &&
2243 rrq->value <= 6 * MEGABIT ) {
2244 if( rrq->fixed == 1 ) {
2245 lp->TxRateControl[index] = 0x0010;
2246 } else {
2247 lp->TxRateControl[index] = 0x0017;
2250 else if( rrq->value > 6 * MEGABIT &&
2251 rrq->value <= 9 * MEGABIT ) {
2252 if( rrq->fixed == 1 ) {
2253 lp->TxRateControl[index] = 0x0020;
2254 } else {
2255 lp->TxRateControl[index] = 0x0037;
2258 else if( rrq->value > 9 * MEGABIT &&
2259 rrq->value <= 11 * MEGABIT ) {
2260 if( rrq->fixed == 1 ) {
2261 lp->TxRateControl[index] = 0x0008;
2262 } else {
2263 lp->TxRateControl[index] = 0x003F;
2266 else if( rrq->value > 11 * MEGABIT &&
2267 rrq->value <= 12 * MEGABIT ) {
2268 if( rrq->fixed == 1 ) {
2269 lp->TxRateControl[index] = 0x0040;
2270 } else {
2271 lp->TxRateControl[index] = 0x007F;
2274 else if( rrq->value > 12 * MEGABIT &&
2275 rrq->value <= 18 * MEGABIT ) {
2276 if( rrq->fixed == 1 ) {
2277 lp->TxRateControl[index] = 0x0080;
2278 } else {
2279 lp->TxRateControl[index] = 0x00FF;
2282 else if( rrq->value > 18 * MEGABIT &&
2283 rrq->value <= 24 * MEGABIT ) {
2284 if( rrq->fixed == 1 ) {
2285 lp->TxRateControl[index] = 0x0100;
2286 } else {
2287 lp->TxRateControl[index] = 0x01FF;
2290 else if( rrq->value > 24 * MEGABIT &&
2291 rrq->value <= 36 * MEGABIT ) {
2292 if( rrq->fixed == 1 ) {
2293 lp->TxRateControl[index] = 0x0200;
2294 } else {
2295 lp->TxRateControl[index] = 0x03FF;
2298 else if( rrq->value > 36 * MEGABIT &&
2299 rrq->value <= 48 * MEGABIT ) {
2300 if( rrq->fixed == 1 ) {
2301 lp->TxRateControl[index] = 0x0400;
2302 } else {
2303 lp->TxRateControl[index] = 0x07FF;
2306 else if( rrq->value > 48 * MEGABIT &&
2307 rrq->value <= 54 * MEGABIT ) {
2308 if( rrq->fixed == 1 ) {
2309 lp->TxRateControl[index] = 0x0800;
2310 } else {
2311 lp->TxRateControl[index] = 0x0FFF;
2314 else if( rrq->fixed == 0 ) {
2315 /* In this case, the user has not specified a bitrate, only the "auto"
2316 moniker. So, set to all supported rates */
2317 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2318 } else {
2319 rrq->value = 0;
2320 ret = -EINVAL;
2321 goto out_unlock;
2325 #else
2327 if( rrq->value > 0 &&
2328 rrq->value <= 1 * MEGABIT ) {
2329 lp->TxRateControl[0] = 1;
2331 else if( rrq->value > 1 * MEGABIT &&
2332 rrq->value <= 2 * MEGABIT ) {
2333 if( rrq->fixed ) {
2334 lp->TxRateControl[0] = 2;
2335 } else {
2336 lp->TxRateControl[0] = 6;
2339 else if( rrq->value > 2 * MEGABIT &&
2340 rrq->value <= 5 * MEGABIT ) {
2341 if( rrq->fixed ) {
2342 lp->TxRateControl[0] = 4;
2343 } else {
2344 lp->TxRateControl[0] = 7;
2347 else if( rrq->value > 5 * MEGABIT &&
2348 rrq->value <= 11 * MEGABIT ) {
2349 if( rrq->fixed) {
2350 lp->TxRateControl[0] = 5;
2351 } else {
2352 lp->TxRateControl[0] = 3;
2355 else if( rrq->fixed == 0 ) {
2356 /* In this case, the user has not specified a bitrate, only the "auto"
2357 moniker. So, set the rate to 11Mb auto */
2358 lp->TxRateControl[0] = 3;
2359 } else {
2360 rrq->value = 0;
2361 ret = -EINVAL;
2362 goto out_unlock;
2365 #endif // WARP
2368 /* Commit the adapter parameters */
2369 wl_apply( lp );
2371 out_unlock:
2373 wl_act_int_on( lp );
2375 wl_unlock(lp, &flags);
2377 out:
2378 DBG_LEAVE( DbgInfo );
2379 return ret;
2380 } // wireless_set_rate
2381 /*============================================================================*/
2386 /*******************************************************************************
2387 * wireless_get_rate()
2388 *******************************************************************************
2390 * DESCRIPTION:
2392 * Get the default data rate setting used by the wireless device.
2394 * PARAMETERS:
2396 * wrq - the wireless request buffer
2397 * lp - the device's private adapter structure
2399 * RETURNS:
2401 * 0 on success
2402 * errno value otherwise
2404 ******************************************************************************/
2405 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2408 struct wl_private *lp = wl_priv(dev);
2409 unsigned long flags;
2410 int ret = 0;
2411 int status = -1;
2412 hcf_16 txRate;
2413 /*------------------------------------------------------------------------*/
2416 DBG_FUNC( "wireless_get_rate" );
2417 DBG_ENTER( DbgInfo );
2419 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2420 ret = -EBUSY;
2421 goto out;
2424 wl_lock( lp, &flags );
2426 wl_act_int_off( lp );
2428 /* Get the current transmit rate from the adapter */
2429 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2430 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2432 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2434 if( status == HCF_SUCCESS ) {
2435 #ifdef WARP
2437 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2439 if( txRate & 0x0001 ) {
2440 txRate = 1;
2442 else if( txRate & 0x0002 ) {
2443 txRate = 2;
2445 else if( txRate & 0x0004 ) {
2446 txRate = 5;
2448 else if( txRate & 0x0008 ) {
2449 txRate = 11;
2451 else if( txRate & 0x00010 ) {
2452 txRate = 6;
2454 else if( txRate & 0x00020 ) {
2455 txRate = 9;
2457 else if( txRate & 0x00040 ) {
2458 txRate = 12;
2460 else if( txRate & 0x00080 ) {
2461 txRate = 18;
2463 else if( txRate & 0x00100 ) {
2464 txRate = 24;
2466 else if( txRate & 0x00200 ) {
2467 txRate = 36;
2469 else if( txRate & 0x00400 ) {
2470 txRate = 48;
2472 else if( txRate & 0x00800 ) {
2473 txRate = 54;
2476 #else
2478 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2480 #endif // WARP
2482 rrq->value = txRate * MEGABIT;
2483 } else {
2484 rrq->value = 0;
2485 ret = -EFAULT;
2488 wl_act_int_on( lp );
2490 wl_unlock(lp, &flags);
2492 out:
2493 DBG_LEAVE( DbgInfo );
2494 return ret;
2495 } // wireless_get_rate
2496 /*============================================================================*/
2501 #if 0 //;? Not used anymore
2502 /*******************************************************************************
2503 * wireless_get_private_interface()
2504 *******************************************************************************
2506 * DESCRIPTION:
2508 * Returns the Linux Wireless Extensions' compatible private interface of
2509 * the driver.
2511 * PARAMETERS:
2513 * wrq - the wireless request buffer
2514 * lp - the device's private adapter structure
2516 * RETURNS:
2518 * 0 on success
2519 * errno value otherwise
2521 ******************************************************************************/
2522 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2524 int ret = 0;
2525 /*------------------------------------------------------------------------*/
2528 DBG_FUNC( "wireless_get_private_interface" );
2529 DBG_ENTER( DbgInfo );
2531 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2532 ret = -EBUSY;
2533 goto out;
2536 if( wrq->u.data.pointer != NULL ) {
2537 struct iw_priv_args priv[] =
2539 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2540 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2541 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2542 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2543 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2544 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2547 /* Verify the user buffer */
2548 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2550 if( ret != 0 ) {
2551 DBG_LEAVE( DbgInfo );
2552 return ret;
2555 /* Copy the data into the user's buffer */
2556 wrq->u.data.length = NELEM( priv );
2557 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2560 out:
2561 DBG_LEAVE( DbgInfo );
2562 return ret;
2563 } // wireless_get_private_interface
2564 /*============================================================================*/
2565 #endif
2569 /*******************************************************************************
2570 * wireless_set_scan()
2571 *******************************************************************************
2573 * DESCRIPTION:
2575 * Instructs the driver to initiate a network scan.
2577 * PARAMETERS:
2579 * wrq - the wireless request buffer
2580 * lp - the device's private adapter structure
2582 * RETURNS:
2584 * 0 on success
2585 * errno value otherwise
2587 ******************************************************************************/
2588 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2590 struct wl_private *lp = wl_priv(dev);
2591 unsigned long flags;
2592 int ret = 0;
2593 int status = -1;
2594 int retries = 0;
2595 /*------------------------------------------------------------------------*/
2597 //;? Note: shows results as trace, returns always 0 unless BUSY
2599 DBG_FUNC( "wireless_set_scan" );
2600 DBG_ENTER( DbgInfo );
2602 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2603 ret = -EBUSY;
2604 goto out;
2607 wl_lock( lp, &flags );
2609 wl_act_int_off( lp );
2612 * This looks like a nice place to test if the HCF is still
2613 * communicating with the card. It seems that sometimes BAP_1
2614 * gets corrupted. By looking at the comments in HCF the
2615 * cause is still a mystery. Okay, the communication to the
2616 * card is dead, reset the card to revive.
2618 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2620 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2621 wl_reset( dev );
2624 retry:
2625 /* Set the completion state to FALSE */
2626 lp->probe_results.scan_complete = FALSE;
2629 /* Channels to scan */
2630 #ifdef WARP
2631 lp->ltvRecord.len = 5;
2632 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2633 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2634 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2635 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2636 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2637 #else
2638 lp->ltvRecord.len = 2;
2639 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2640 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2641 #endif // WARP
2643 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2645 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2647 // Holding the lock too long, makes a gap to allow other processes
2648 wl_unlock(lp, &flags);
2649 wl_lock( lp, &flags );
2651 if( status != HCF_SUCCESS ) {
2652 //Recovery
2653 retries++;
2654 if(retries <= 10) {
2655 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2656 wl_reset( dev );
2658 // Holding the lock too long, makes a gap to allow other processes
2659 wl_unlock(lp, &flags);
2660 wl_lock( lp, &flags );
2662 goto retry;
2666 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2667 disassociate from the network we are currently on */
2668 lp->ltvRecord.len = 18;
2669 lp->ltvRecord.typ = CFG_SCAN_SSID;
2670 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2671 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2673 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2675 // Holding the lock too long, makes a gap to allow other processes
2676 wl_unlock(lp, &flags);
2677 wl_lock( lp, &flags );
2679 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2681 /* Initiate the scan */
2682 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2683 retrieve probe response must always be used to support WPA */
2684 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2686 if( status == HCF_SUCCESS ) {
2687 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2688 } else {
2689 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2692 wl_act_int_on( lp );
2694 wl_unlock(lp, &flags);
2696 out:
2697 DBG_LEAVE(DbgInfo);
2698 return ret;
2699 } // wireless_set_scan
2700 /*============================================================================*/
2705 /*******************************************************************************
2706 * wireless_get_scan()
2707 *******************************************************************************
2709 * DESCRIPTION:
2711 * Instructs the driver to gather and return the results of a network scan.
2713 * PARAMETERS:
2715 * wrq - the wireless request buffer
2716 * lp - the device's private adapter structure
2718 * RETURNS:
2720 * 0 on success
2721 * errno value otherwise
2723 ******************************************************************************/
2724 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2726 struct wl_private *lp = wl_priv(dev);
2727 unsigned long flags;
2728 int ret = 0;
2729 int count;
2730 char *buf;
2731 char *buf_end;
2732 struct iw_event iwe;
2733 PROBE_RESP *probe_resp;
2734 hcf_8 msg[512];
2735 hcf_8 *wpa_ie;
2736 hcf_16 wpa_ie_len;
2737 /*------------------------------------------------------------------------*/
2740 DBG_FUNC( "wireless_get_scan" );
2741 DBG_ENTER( DbgInfo );
2743 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2744 ret = -EBUSY;
2745 goto out;
2748 wl_lock( lp, &flags );
2750 wl_act_int_off( lp );
2752 /* If the scan is not done, tell the calling process to try again later */
2753 if( !lp->probe_results.scan_complete ) {
2754 ret = -EAGAIN;
2755 goto out_unlock;
2758 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2759 lp->probe_results.num_aps );
2761 buf = extra;
2762 buf_end = extra + IW_SCAN_MAX_DATA;
2764 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2765 /* Reference the probe response from the table */
2766 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2769 /* First entry MUST be the MAC address */
2770 memset( &iwe, 0, sizeof( iwe ));
2772 iwe.cmd = SIOCGIWAP;
2773 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2774 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2775 iwe.len = IW_EV_ADDR_LEN;
2777 buf = iwe_stream_add_event(info, buf, buf_end,
2778 &iwe, IW_EV_ADDR_LEN);
2780 /* Use the mode to indicate if it's a station or AP */
2781 /* Won't always be an AP if in IBSS mode */
2782 memset( &iwe, 0, sizeof( iwe ));
2784 iwe.cmd = SIOCGIWMODE;
2786 if( probe_resp->capability & CAPABILITY_IBSS ) {
2787 iwe.u.mode = IW_MODE_INFRA;
2788 } else {
2789 iwe.u.mode = IW_MODE_MASTER;
2792 iwe.len = IW_EV_UINT_LEN;
2794 buf = iwe_stream_add_event(info, buf, buf_end,
2795 &iwe, IW_EV_UINT_LEN);
2797 /* Any quality information */
2798 memset(&iwe, 0, sizeof(iwe));
2800 iwe.cmd = IWEVQUAL;
2801 iwe.u.qual.level = dbm(probe_resp->signal);
2802 iwe.u.qual.noise = dbm(probe_resp->silence);
2803 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2804 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2805 iwe.len = IW_EV_QUAL_LEN;
2807 buf = iwe_stream_add_event(info, buf, buf_end,
2808 &iwe, IW_EV_QUAL_LEN);
2811 /* ESSID information */
2812 if( probe_resp->rawData[1] > 0 ) {
2813 memset( &iwe, 0, sizeof( iwe ));
2815 iwe.cmd = SIOCGIWESSID;
2816 iwe.u.data.length = probe_resp->rawData[1];
2817 iwe.u.data.flags = 1;
2819 buf = iwe_stream_add_point(info, buf, buf_end,
2820 &iwe, &probe_resp->rawData[2]);
2824 /* Encryption Information */
2825 memset( &iwe, 0, sizeof( iwe ));
2827 iwe.cmd = SIOCGIWENCODE;
2828 iwe.u.data.length = 0;
2830 /* Check the capabilities field of the Probe Response to see if
2831 'privacy' is supported on the AP in question */
2832 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2833 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2834 } else {
2835 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2838 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
2841 /* Frequency Info */
2842 memset( &iwe, 0, sizeof( iwe ));
2844 iwe.cmd = SIOCGIWFREQ;
2845 iwe.len = IW_EV_FREQ_LEN;
2846 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2847 iwe.u.freq.e = 0;
2849 buf = iwe_stream_add_event(info, buf, buf_end,
2850 &iwe, IW_EV_FREQ_LEN);
2853 /* Custom info (Beacon Interval) */
2854 memset( &iwe, 0, sizeof( iwe ));
2855 memset( msg, 0, sizeof( msg ));
2857 iwe.cmd = IWEVCUSTOM;
2858 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2859 iwe.u.data.length = strlen( msg );
2861 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
2864 /* WPA-IE */
2865 wpa_ie = NULL;
2866 wpa_ie_len = 0;
2868 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2869 if( wpa_ie != NULL ) {
2870 memset(&iwe, 0, sizeof(iwe));
2872 iwe.cmd = IWEVGENIE;
2873 iwe.u.data.length = wpa_ie_len;
2875 buf = iwe_stream_add_point(info, buf, buf_end,
2876 &iwe, wpa_ie);
2879 /* Add other custom info in formatted string format as needed... */
2882 data->length = buf - extra;
2884 out_unlock:
2886 wl_act_int_on( lp );
2888 wl_unlock(lp, &flags);
2890 out:
2891 DBG_LEAVE( DbgInfo );
2892 return ret;
2893 } // wireless_get_scan
2894 /*============================================================================*/
2896 #if DBG
2897 static const char * const auth_names[] = {
2898 "IW_AUTH_WPA_VERSION",
2899 "IW_AUTH_CIPHER_PAIRWISE",
2900 "IW_AUTH_CIPHER_GROUP",
2901 "IW_AUTH_KEY_MGMT",
2902 "IW_AUTH_TKIP_COUNTERMEASURES",
2903 "IW_AUTH_DROP_UNENCRYPTED",
2904 "IW_AUTH_80211_AUTH_ALG",
2905 "IW_AUTH_WPA_ENABLED",
2906 "IW_AUTH_RX_UNENCRYPTED_EAPOL",
2907 "IW_AUTH_ROAMING_CONTROL",
2908 "IW_AUTH_PRIVACY_INVOKED",
2909 "IW_AUTH_CIPHER_GROUP_MGMT",
2910 "IW_AUTH_MFP",
2911 "Unsupported"
2913 #endif
2915 static int wireless_set_auth(struct net_device *dev,
2916 struct iw_request_info *info,
2917 struct iw_param *data, char *extra)
2919 struct wl_private *lp = wl_priv(dev);
2920 unsigned long flags;
2921 ltv_t ltv;
2922 int ret;
2923 int iwa_idx = data->flags & IW_AUTH_INDEX;
2924 int iwa_val = data->value;
2926 DBG_FUNC( "wireless_set_auth" );
2927 DBG_ENTER( DbgInfo );
2929 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2930 ret = -EBUSY;
2931 goto out;
2934 wl_lock( lp, &flags );
2936 wl_act_int_off( lp );
2938 if (iwa_idx > IW_AUTH_MFP)
2939 iwa_idx = IW_AUTH_MFP + 1;
2940 DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
2941 switch (iwa_idx) {
2942 case IW_AUTH_WPA_VERSION:
2943 /* We do support WPA */
2944 if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
2945 (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
2946 ret = 0;
2947 else
2948 ret = -EINVAL;
2949 break;
2951 case IW_AUTH_WPA_ENABLED:
2952 DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
2953 if (iwa_val)
2954 lp->EnableEncryption = 2;
2955 else
2956 lp->EnableEncryption = 0;
2958 /* Write straight to the card */
2959 ltv.len = 2;
2960 ltv.typ = CFG_CNF_ENCRYPTION;
2961 ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
2962 ret = hcf_put_info(&lp->hcfCtx, (LTVP)&ltv);
2964 break;
2966 case IW_AUTH_TKIP_COUNTERMEASURES:
2968 /* Immediately disable card */
2969 lp->driverEnable = !iwa_val;
2970 if (lp->driverEnable)
2971 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2972 else
2973 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2974 ret = 0;
2975 break;
2977 case IW_AUTH_MFP:
2978 /* Management Frame Protection not supported.
2979 * Only fail if set to required.
2981 if (iwa_val == IW_AUTH_MFP_REQUIRED)
2982 ret = -EINVAL;
2983 else
2984 ret = 0;
2985 break;
2987 case IW_AUTH_KEY_MGMT:
2989 /* Record required management suite.
2990 * Will take effect on next commit */
2991 if (iwa_val != 0)
2992 lp->AuthKeyMgmtSuite = 4;
2993 else
2994 lp->AuthKeyMgmtSuite = 0;
2996 ret = -EINPROGRESS;
2997 break;
2999 case IW_AUTH_80211_AUTH_ALG:
3001 /* Just record whether open or shared is required.
3002 * Will take effect on next commit */
3003 ret = -EINPROGRESS;
3005 if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
3006 lp->authentication = 1;
3007 else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
3008 lp->authentication = 0;
3009 else
3010 ret = -EINVAL;
3011 break;
3013 case IW_AUTH_DROP_UNENCRYPTED:
3014 /* Only needed for AP */
3015 lp->ExcludeUnencrypted = iwa_val;
3016 ret = -EINPROGRESS;
3017 break;
3019 case IW_AUTH_CIPHER_PAIRWISE:
3020 case IW_AUTH_CIPHER_GROUP:
3021 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3022 case IW_AUTH_ROAMING_CONTROL:
3023 case IW_AUTH_PRIVACY_INVOKED:
3024 /* Not used. May need to do something with
3025 * CIPHER_PAIRWISE and CIPHER_GROUP*/
3026 ret = -EINPROGRESS;
3027 break;
3029 default:
3030 DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
3031 /* return an error */
3032 ret = -EOPNOTSUPP;
3033 break;
3036 wl_act_int_on( lp );
3038 wl_unlock(lp, &flags);
3040 out:
3041 DBG_LEAVE( DbgInfo );
3042 return ret;
3043 } // wireless_set_auth
3044 /*============================================================================*/
3047 static void flush_tx(struct wl_private *lp)
3049 ltv_t ltv;
3050 int count;
3053 * Make sure that there is no data queued up in the firmware
3054 * before setting the TKIP keys. If this check is not
3055 * performed, some data may be sent out with incorrect MIC
3056 * and cause synchronization errors with the AP
3058 /* Check every 1ms for 100ms */
3059 for (count = 0; count < 100; count++) {
3060 udelay(1000);
3062 ltv.len = 2;
3063 ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
3064 ltv.u.u16[0] = 0;
3066 hcf_get_info(&(lp->hcfCtx), (LTVP)&ltv);
3068 if (ltv.u.u16[0] == 0)
3069 break;
3072 if (count >= 100)
3073 DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
3077 static int wireless_set_encodeext(struct net_device *dev,
3078 struct iw_request_info *info,
3079 struct iw_point *erq, char *keybuf)
3081 struct wl_private *lp = wl_priv(dev);
3082 unsigned long flags;
3083 int ret;
3084 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
3085 ltv_t ltv;
3086 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3087 bool enable = true;
3088 bool set_tx = false;
3090 DBG_ENTER(DbgInfo);
3092 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
3093 ret = -EBUSY;
3094 goto out;
3097 if (erq->flags & IW_ENCODE_DISABLED) {
3098 ext->alg = IW_ENCODE_ALG_NONE;
3099 enable = false;
3102 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
3103 set_tx = true;
3105 wl_lock(lp, &flags);
3107 wl_act_int_off(lp);
3109 memset(&ltv, 0, sizeof(ltv));
3111 switch (ext->alg) {
3112 case IW_ENCODE_ALG_TKIP:
3113 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3115 if (sizeof(ext->rx_seq) != 8) {
3116 DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
3117 DBG_LEAVE(DbgInfo);
3118 ret = -EINVAL;
3119 goto out_unlock;
3122 ret = hermes_set_tkip_keys(&ltv, key_idx, ext->addr.sa_data,
3123 set_tx,
3124 ext->rx_seq, ext->key, ext->key_len);
3126 if (ret != 0) {
3127 DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
3128 goto out_unlock;
3131 flush_tx(lp);
3133 lp->wext_enc = IW_ENCODE_ALG_TKIP;
3135 /* Write the key */
3136 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3137 break;
3139 case IW_ENCODE_ALG_WEP:
3140 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3142 if (erq->flags & IW_ENCODE_RESTRICTED) {
3143 DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
3144 ret = -EINVAL;
3145 goto out_unlock;
3148 ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
3149 enable, set_tx);
3151 break;
3153 case IW_ENCODE_ALG_CCMP:
3154 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3155 ret = -EOPNOTSUPP;
3156 break;
3158 case IW_ENCODE_ALG_NONE:
3159 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3161 if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
3162 ret = hermes_clear_tkip_keys(&ltv, key_idx,
3163 ext->addr.sa_data);
3164 flush_tx(lp);
3165 lp->wext_enc = IW_ENCODE_ALG_NONE;
3166 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3168 } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
3169 ret = hermes_set_wep_keys(lp, key_idx,
3170 ext->key, ext->key_len,
3171 false, false);
3172 } else {
3173 ret = 0;
3176 break;
3178 default:
3179 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3180 ret = -EOPNOTSUPP;
3181 break;
3184 out_unlock:
3186 wl_act_int_on(lp);
3188 wl_unlock(lp, &flags);
3190 out:
3191 DBG_LEAVE(DbgInfo);
3192 return ret;
3194 /*============================================================================*/
3198 static int wireless_set_genie(struct net_device *dev,
3199 struct iw_request_info *info,
3200 struct iw_point *data, char *extra)
3203 int ret = 0;
3205 DBG_ENTER(DbgInfo);
3207 /* We can't write this to the card, but apparently this
3208 * operation needs to succeed */
3209 ret = 0;
3211 DBG_LEAVE(DbgInfo);
3212 return ret;
3214 /*============================================================================*/
3217 /*******************************************************************************
3218 * wl_wireless_stats()
3219 *******************************************************************************
3221 * DESCRIPTION:
3223 * Return the current device wireless statistics.
3225 * PARAMETERS:
3227 * wrq - the wireless request buffer
3228 * lp - the device's private adapter structure
3230 * RETURNS:
3232 * 0 on success
3233 * errno value otherwise
3235 ******************************************************************************/
3236 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3238 struct iw_statistics *pStats;
3239 struct wl_private *lp = wl_priv(dev);
3240 /*------------------------------------------------------------------------*/
3243 DBG_FUNC( "wl_wireless_stats" );
3244 DBG_ENTER(DbgInfo);
3245 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3247 pStats = NULL;
3249 /* Initialize the statistics */
3250 pStats = &( lp->wstats );
3251 pStats->qual.updated = 0x00;
3253 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3255 CFG_COMMS_QUALITY_STRCT *pQual;
3256 CFG_HERMES_TALLIES_STRCT tallies;
3257 int status;
3259 /* Update driver status */
3260 pStats->status = 0;
3262 /* Get the current link quality information */
3263 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3264 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3265 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3267 if( status == HCF_SUCCESS ) {
3268 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3270 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3271 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3272 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3274 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3275 IW_QUAL_LEVEL_UPDATED |
3276 IW_QUAL_NOISE_UPDATED |
3277 IW_QUAL_DBM);
3278 } else {
3279 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3282 /* Get the current tallies from the adapter */
3283 /* Only possible when the device is open */
3284 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3285 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3286 /* No endian translation is needed here, as CFG_TALLIES is an
3287 MSF RID; all processing is done on the host, not the card! */
3288 pStats->discard.nwid = 0L;
3289 pStats->discard.code = tallies.RxWEPUndecryptable;
3290 pStats->discard.misc = tallies.TxDiscards +
3291 tallies.RxFCSErrors +
3292 //tallies.RxDiscardsNoBuffer +
3293 tallies.TxDiscardsWrongSA;
3294 //;? Extra taken over from Linux driver based on 7.18 version
3295 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3296 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3297 } else {
3298 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3300 } else {
3301 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3305 DBG_LEAVE( DbgInfo );
3306 return pStats;
3307 } // wl_wireless_stats
3308 /*============================================================================*/
3313 /*******************************************************************************
3314 * wl_get_wireless_stats()
3315 *******************************************************************************
3317 * DESCRIPTION:
3319 * Return the current device wireless statistics. This function calls
3320 * wl_wireless_stats, but acquires spinlocks first as it can be called
3321 * directly by the network layer.
3323 * PARAMETERS:
3325 * wrq - the wireless request buffer
3326 * lp - the device's private adapter structure
3328 * RETURNS:
3330 * 0 on success
3331 * errno value otherwise
3333 ******************************************************************************/
3334 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3336 unsigned long flags;
3337 struct wl_private *lp = wl_priv(dev);
3338 struct iw_statistics *pStats = NULL;
3339 /*------------------------------------------------------------------------*/
3341 DBG_FUNC( "wl_get_wireless_stats" );
3342 DBG_ENTER(DbgInfo);
3344 wl_lock( lp, &flags );
3346 wl_act_int_off( lp );
3348 #ifdef USE_RTS
3349 if( lp->useRTS == 1 ) {
3350 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3351 } else
3352 #endif
3354 pStats = wl_wireless_stats( dev );
3356 wl_act_int_on( lp );
3358 wl_unlock(lp, &flags);
3360 DBG_LEAVE( DbgInfo );
3361 return pStats;
3362 } // wl_get_wireless_stats
3365 /*******************************************************************************
3366 * wl_spy_gather()
3367 *******************************************************************************
3369 * DESCRIPTION:
3371 * Gather wireless spy statistics.
3373 * PARAMETERS:
3375 * wrq - the wireless request buffer
3376 * lp - the device's private adapter structure
3378 * RETURNS:
3380 * 0 on success
3381 * errno value otherwise
3383 ******************************************************************************/
3384 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3386 struct iw_quality wstats;
3387 int status;
3388 u_char stats[2];
3389 DESC_STRCT desc[1];
3390 struct wl_private *lp = wl_priv(dev);
3391 /*------------------------------------------------------------------------*/
3393 /* shortcut */
3394 if (!lp->spy_data.spy_number) {
3395 return;
3398 /* Gather wireless spy statistics: for each packet, compare the source
3399 address with out list, and if match, get the stats. */
3400 memset( stats, 0, sizeof(stats));
3401 memset( desc, 0, sizeof(DESC_STRCT));
3403 desc[0].buf_addr = stats;
3404 desc[0].BUF_SIZE = sizeof(stats);
3405 desc[0].next_desc_addr = 0; // terminate list
3407 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3409 if( status == HCF_SUCCESS ) {
3410 wstats.level = (u_char) dbm(stats[1]);
3411 wstats.noise = (u_char) dbm(stats[0]);
3412 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3414 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3415 IW_QUAL_LEVEL_UPDATED |
3416 IW_QUAL_NOISE_UPDATED |
3417 IW_QUAL_DBM);
3419 wireless_spy_update( dev, mac, &wstats );
3421 } // wl_spy_gather
3422 /*============================================================================*/
3427 /*******************************************************************************
3428 * wl_wext_event_freq()
3429 *******************************************************************************
3431 * DESCRIPTION:
3433 * This function is used to send an event that the channel/freq
3434 * configuration for a specific device has changed.
3437 * PARAMETERS:
3439 * dev - the network device for which this event is to be issued
3441 * RETURNS:
3443 * N/A
3445 ******************************************************************************/
3446 void wl_wext_event_freq( struct net_device *dev )
3448 union iwreq_data wrqu;
3449 struct wl_private *lp = wl_priv(dev);
3450 /*------------------------------------------------------------------------*/
3453 memset( &wrqu, 0, sizeof( wrqu ));
3455 wrqu.freq.m = lp->Channel;
3456 wrqu.freq.e = 0;
3458 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3460 return;
3461 } // wl_wext_event_freq
3462 /*============================================================================*/
3467 /*******************************************************************************
3468 * wl_wext_event_mode()
3469 *******************************************************************************
3471 * DESCRIPTION:
3473 * This function is used to send an event that the mode of operation
3474 * for a specific device has changed.
3477 * PARAMETERS:
3479 * dev - the network device for which this event is to be issued
3481 * RETURNS:
3483 * N/A
3485 ******************************************************************************/
3486 void wl_wext_event_mode( struct net_device *dev )
3488 union iwreq_data wrqu;
3489 struct wl_private *lp = wl_priv(dev);
3490 /*------------------------------------------------------------------------*/
3493 memset( &wrqu, 0, sizeof( wrqu ));
3495 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3496 wrqu.mode = IW_MODE_INFRA;
3497 } else {
3498 wrqu.mode = IW_MODE_MASTER;
3501 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3503 return;
3504 } // wl_wext_event_mode
3505 /*============================================================================*/
3510 /*******************************************************************************
3511 * wl_wext_event_essid()
3512 *******************************************************************************
3514 * DESCRIPTION:
3516 * This function is used to send an event that the ESSID configuration for
3517 * a specific device has changed.
3520 * PARAMETERS:
3522 * dev - the network device for which this event is to be issued
3524 * RETURNS:
3526 * N/A
3528 ******************************************************************************/
3529 void wl_wext_event_essid( struct net_device *dev )
3531 union iwreq_data wrqu;
3532 struct wl_private *lp = wl_priv(dev);
3533 /*------------------------------------------------------------------------*/
3536 memset( &wrqu, 0, sizeof( wrqu ));
3538 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3539 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3540 the call to wireless_send_event() must also point to where the ESSID
3541 lives */
3542 wrqu.essid.length = strlen( lp->NetworkName );
3543 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3544 wrqu.essid.flags = 1;
3546 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3548 return;
3549 } // wl_wext_event_essid
3550 /*============================================================================*/
3555 /*******************************************************************************
3556 * wl_wext_event_encode()
3557 *******************************************************************************
3559 * DESCRIPTION:
3561 * This function is used to send an event that the encryption configuration
3562 * for a specific device has changed.
3565 * PARAMETERS:
3567 * dev - the network device for which this event is to be issued
3569 * RETURNS:
3571 * N/A
3573 ******************************************************************************/
3574 void wl_wext_event_encode( struct net_device *dev )
3576 union iwreq_data wrqu;
3577 struct wl_private *lp = wl_priv(dev);
3578 int index = 0;
3579 /*------------------------------------------------------------------------*/
3582 memset( &wrqu, 0, sizeof( wrqu ));
3584 if( lp->EnableEncryption == 0 ) {
3585 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3586 } else {
3587 wrqu.encoding.flags |= lp->TransmitKeyID;
3589 index = lp->TransmitKeyID - 1;
3591 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3592 if we're in AP mode */
3593 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3594 //;?should we restore this to allow smaller memory footprint
3596 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3597 if( lp->ExcludeUnencrypted ) {
3598 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3599 } else {
3600 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3604 #endif // HCF_TYPE_AP
3606 /* Only provide the key if permissions allow */
3607 if( capable( CAP_NET_ADMIN )) {
3608 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3609 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3610 } else {
3611 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3615 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3616 lp->DefaultKeys.key[index].key );
3618 return;
3619 } // wl_wext_event_encode
3620 /*============================================================================*/
3625 /*******************************************************************************
3626 * wl_wext_event_ap()
3627 *******************************************************************************
3629 * DESCRIPTION:
3631 * This function is used to send an event that the device has been
3632 * associated to a new AP.
3635 * PARAMETERS:
3637 * dev - the network device for which this event is to be issued
3639 * RETURNS:
3641 * N/A
3643 ******************************************************************************/
3644 void wl_wext_event_ap( struct net_device *dev )
3646 union iwreq_data wrqu;
3647 struct wl_private *lp = wl_priv(dev);
3648 int status;
3649 /*------------------------------------------------------------------------*/
3652 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3653 this event BEFORE sending the association event, as there are timing
3654 issues with the hostap supplicant. The supplicant will attempt to process
3655 an EAPOL-Key frame from an AP before receiving this information, which
3656 is required for a proper processed frame. */
3657 wl_wext_event_assoc_ie( dev );
3659 /* Get the BSSID */
3660 lp->ltvRecord.typ = CFG_CUR_BSSID;
3661 lp->ltvRecord.len = 4;
3663 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3664 if( status == HCF_SUCCESS ) {
3665 memset( &wrqu, 0, sizeof( wrqu ));
3667 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3669 wrqu.addr.sa_family = ARPHRD_ETHER;
3671 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3674 return;
3675 } // wl_wext_event_ap
3676 /*============================================================================*/
3680 /*******************************************************************************
3681 * wl_wext_event_scan_complete()
3682 *******************************************************************************
3684 * DESCRIPTION:
3686 * This function is used to send an event that a request for a network scan
3687 * has completed.
3690 * PARAMETERS:
3692 * dev - the network device for which this event is to be issued
3694 * RETURNS:
3696 * N/A
3698 ******************************************************************************/
3699 void wl_wext_event_scan_complete( struct net_device *dev )
3701 union iwreq_data wrqu;
3702 /*------------------------------------------------------------------------*/
3705 memset( &wrqu, 0, sizeof( wrqu ));
3707 wrqu.addr.sa_family = ARPHRD_ETHER;
3708 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3710 return;
3711 } // wl_wext_event_scan_complete
3712 /*============================================================================*/
3717 /*******************************************************************************
3718 * wl_wext_event_new_sta()
3719 *******************************************************************************
3721 * DESCRIPTION:
3723 * This function is used to send an event that an AP has registered a new
3724 * station.
3727 * PARAMETERS:
3729 * dev - the network device for which this event is to be issued
3731 * RETURNS:
3733 * N/A
3735 ******************************************************************************/
3736 void wl_wext_event_new_sta( struct net_device *dev )
3738 union iwreq_data wrqu;
3739 /*------------------------------------------------------------------------*/
3742 memset( &wrqu, 0, sizeof( wrqu ));
3744 /* Send the station's mac address here */
3745 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3746 wrqu.addr.sa_family = ARPHRD_ETHER;
3747 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3749 return;
3750 } // wl_wext_event_new_sta
3751 /*============================================================================*/
3756 /*******************************************************************************
3757 * wl_wext_event_expired_sta()
3758 *******************************************************************************
3760 * DESCRIPTION:
3762 * This function is used to send an event that an AP has deregistered a
3763 * station.
3766 * PARAMETERS:
3768 * dev - the network device for which this event is to be issued
3770 * RETURNS:
3772 * N/A
3774 ******************************************************************************/
3775 void wl_wext_event_expired_sta( struct net_device *dev )
3777 union iwreq_data wrqu;
3778 /*------------------------------------------------------------------------*/
3781 memset( &wrqu, 0, sizeof( wrqu ));
3783 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3784 wrqu.addr.sa_family = ARPHRD_ETHER;
3785 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3787 return;
3788 } // wl_wext_event_expired_sta
3789 /*============================================================================*/
3794 /*******************************************************************************
3795 * wl_wext_event_mic_failed()
3796 *******************************************************************************
3798 * DESCRIPTION:
3800 * This function is used to send an event that MIC calculations failed.
3803 * PARAMETERS:
3805 * dev - the network device for which this event is to be issued
3807 * RETURNS:
3809 * N/A
3811 ******************************************************************************/
3812 void wl_wext_event_mic_failed( struct net_device *dev )
3814 union iwreq_data wrqu;
3815 struct wl_private *lp = wl_priv(dev);
3816 struct iw_michaelmicfailure wxmic;
3817 int key_idx;
3818 char *addr1;
3819 char *addr2;
3820 WVLAN_RX_WMP_HDR *hdr;
3821 /*------------------------------------------------------------------------*/
3824 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3825 key_idx &= 0x03;
3827 /* Cast the lookahead buffer into a RFS format */
3828 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3830 /* Cast the addresses to byte buffers, as in the above RFS they are word
3831 length */
3832 addr1 = (char *)hdr->address1;
3833 addr2 = (char *)hdr->address2;
3835 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3836 hdr->status );
3838 memset(&wrqu, 0, sizeof(wrqu));
3839 memset(&wxmic, 0, sizeof(wxmic));
3841 wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3842 wxmic.flags |= (addr1[0] & 1) ?
3843 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
3844 wxmic.src_addr.sa_family = ARPHRD_ETHER;
3845 memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3847 wrqu.data.length = sizeof(wxmic);
3848 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3850 return;
3851 } // wl_wext_event_mic_failed
3852 /*============================================================================*/
3857 /*******************************************************************************
3858 * wl_wext_event_assoc_ie()
3859 *******************************************************************************
3861 * DESCRIPTION:
3863 * This function is used to send an event containing the WPA-IE generated
3864 * by the firmware in an association request.
3867 * PARAMETERS:
3869 * dev - the network device for which this event is to be issued
3871 * RETURNS:
3873 * N/A
3875 ******************************************************************************/
3876 void wl_wext_event_assoc_ie( struct net_device *dev )
3878 union iwreq_data wrqu;
3879 struct wl_private *lp = wl_priv(dev);
3880 int status;
3881 PROBE_RESP data;
3882 hcf_16 length;
3883 hcf_8 *wpa_ie;
3884 /*------------------------------------------------------------------------*/
3887 memset( &wrqu, 0, sizeof( wrqu ));
3889 /* Retrieve the Association Request IE */
3890 lp->ltvRecord.len = 45;
3891 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3893 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3894 if( status == HCF_SUCCESS )
3896 length = 0;
3897 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3898 wpa_ie = wl_parse_wpa_ie( &data, &length );
3900 if( length != 0 )
3902 wrqu.data.length = wpa_ie[1] + 2;
3903 wireless_send_event(dev, IWEVASSOCREQIE,
3904 &wrqu, wpa_ie);
3906 /* This bit is a hack. We send the respie
3907 * event at the same time */
3908 wireless_send_event(dev, IWEVASSOCRESPIE,
3909 &wrqu, wpa_ie);
3913 return;
3914 } // wl_wext_event_assoc_ie
3915 /*============================================================================*/
3916 /* Structures to export the Wireless Handlers */
3918 static const iw_handler wl_handler[] =
3920 IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
3921 IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
3922 IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
3923 IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
3924 IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
3925 IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
3926 IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
3927 IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
3928 IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
3929 IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
3930 IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
3931 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3932 IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
3933 #endif
3934 IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
3935 IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
3936 IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
3937 IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
3938 IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
3939 IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
3940 IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
3941 IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
3942 IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
3943 IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
3944 IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
3945 IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
3946 IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
3947 IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
3948 IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
3949 IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
3950 IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
3951 IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3952 IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
3955 static const iw_handler wl_private_handler[] =
3956 { /* SIOCIWFIRSTPRIV + */
3957 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3958 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3959 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3960 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3961 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3962 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3963 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3964 #endif
3967 struct iw_priv_args wl_priv_args[] = {
3968 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3969 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3970 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3971 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3972 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3973 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3974 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3975 #endif
3978 const struct iw_handler_def wl_iw_handler_def =
3980 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3981 .private = (iw_handler *) wl_private_handler,
3982 .private_args = (struct iw_priv_args *) wl_priv_args,
3983 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3984 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3985 .standard = (iw_handler *) wl_handler,
3986 .get_wireless_stats = wl_get_wireless_stats,