1 /*******************************************************************************
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
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
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.
42 * THIS SOFTWARE IS PROVIDED
\93AS IS
\94 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
55 ******************************************************************************/
57 /*******************************************************************************
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>
73 #include <wl_internal.h>
79 /* Set up the LTV to program the appropriate key */
80 static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr,
81 int set_tx, u8 *seq, u8 *key, size_t key_len)
85 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
86 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
89 * Check the key index here; if 0, load as Pairwise Key, otherwise,
90 * load as a group key. Note that for the Hermes, the RIDs for
91 * group/pairwise keys are different from each other and different
92 * than the default WEP keys as well.
97 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
100 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
103 /* Load the TKIP key */
104 memcpy(<v->u.u8[buf_idx], &key[0], 16);
108 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
109 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
112 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
113 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
115 /* Load the TxMIC key */
116 memcpy(<v->u.u8[buf_idx], &key[16], 8);
119 /* Load the RxMIC key */
120 memcpy(<v->u.u8[buf_idx], &key[24], 8);
128 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
130 /* Load the key Index */
132 /* If this is a Tx Key, set bit 8000 */
135 ltv->u.u16[buf_idx] = cpu_to_le16(key_idx);
139 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
140 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
142 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
143 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
144 memcpy(<v->u.u8[buf_idx], key, key_len);
148 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
159 /* Set up the LTV to clear the appropriate key */
160 static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr)
166 if (!is_broadcast_ether_addr(addr)) {
168 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
169 memcpy(<v->u.u8[0], addr, ETH_ALEN);
176 /* Clear the Group TKIP keys by index */
178 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
179 ltv->u.u16[0] = cpu_to_le16(key_idx);
190 /* Set the WEP keys in the wl_private structure */
191 static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
192 u8 *key, size_t key_len,
193 bool enable, bool set_tx)
195 hcf_8 encryption_state = lp->EnableEncryption;
196 int tk = lp->TransmitKeyID - 1; /* current key */
199 /* Is encryption supported? */
200 if (!wl_has_wep(&(lp->hcfCtx))) {
201 DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
206 DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
209 /* Check the size of the key */
214 /* Check the index */
215 if ((key_idx < 0) || (key_idx >= MAX_KEYS))
219 memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
221 /* Copy the key in the driver */
222 memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
225 lp->DefaultKeys.key[key_idx].len = key_len;
227 DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
228 DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
229 lp->DefaultKeys.key[key_idx].key,
230 lp->DefaultKeys.key[key_idx].len, key_idx);
232 /* Enable WEP (if possible) */
233 if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
234 lp->EnableEncryption = 1;
239 /* Do we want to just set the current transmit key? */
240 if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
241 DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
242 lp->DefaultKeys.key[key_idx].len);
244 if (lp->DefaultKeys.key[key_idx].len > 0) {
245 lp->TransmitKeyID = key_idx + 1;
246 lp->EnableEncryption = 1;
248 DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
255 DBG_WARNING(DbgInfo, "Invalid Key length\n");
262 lp->EnableEncryption = 1;
263 lp->wext_enc = IW_ENCODE_ALG_WEP;
265 lp->EnableEncryption = 0; /* disable encryption */
266 lp->wext_enc = IW_ENCODE_ALG_NONE;
269 DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
270 DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
271 DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
273 /* Write the changes to the card */
275 DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
278 if (lp->EnableEncryption == encryption_state) {
280 /* Dynamic WEP key update */
284 /* To switch encryption on/off, soft reset is
294 /*******************************************************************************
296 *******************************************************************************
305 * wrq - the wireless request buffer
311 ******************************************************************************/
312 static int wireless_commit(struct net_device *dev,
313 struct iw_request_info *info,
314 union iwreq_data *rqu, char *extra)
316 struct wl_private *lp = wl_priv(dev);
320 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
325 wl_lock( lp, &flags );
327 wl_act_int_off( lp );
333 wl_unlock(lp, &flags);
338 /*============================================================================*/
343 /*******************************************************************************
344 * wireless_get_protocol()
345 *******************************************************************************
349 * Returns a vendor-defined string that should identify the wireless
354 * wrq - the wireless request buffer
360 ******************************************************************************/
361 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
363 /* Originally, the driver was placing the string "Wireless" here. However,
364 the wireless extensions (/linux/wireless.h) indicate this string should
365 describe the wireless protocol. */
367 strcpy(name, "IEEE 802.11b");
370 } // wireless_get_protocol
371 /*============================================================================*/
376 /*******************************************************************************
377 * wireless_set_frequency()
378 *******************************************************************************
382 * Sets the frequency (channel) on which the card should Tx/Rx.
386 * wrq - the wireless request buffer
387 * lp - the device's private adapter structure
392 * errno value otherwise
394 ******************************************************************************/
395 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
397 struct wl_private *lp = wl_priv(dev);
402 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
407 if( !capable( CAP_NET_ADMIN )) {
413 /* If frequency specified, look up channel */
415 int f = freq->m / 100000;
416 channel = wl_get_chan_from_freq( f );
420 /* Channel specified */
426 /* If the channel is an 802.11a channel, set Bit 8 */
428 channel = channel | 0x100;
432 wl_lock( lp, &flags );
434 wl_act_int_off( lp );
436 lp->Channel = channel;
439 /* Commit the adapter parameters */
442 /* Send an event that channel/freq has been set */
443 wl_wext_event_freq( lp->dev );
447 wl_unlock(lp, &flags);
451 } // wireless_set_frequency
452 /*============================================================================*/
457 /*******************************************************************************
458 * wireless_get_frequency()
459 *******************************************************************************
463 * Gets the frequency (channel) on which the card is Tx/Rx.
467 * wrq - the wireless request buffer
468 * lp - the device's private adapter structure
474 ******************************************************************************/
475 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
478 struct wl_private *lp = wl_priv(dev);
482 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
487 wl_lock( lp, &flags );
489 wl_act_int_off( lp );
491 lp->ltvRecord.len = 2;
492 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
494 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
495 if( ret == HCF_SUCCESS ) {
496 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
498 freq->m = wl_get_freq_from_chan( channel ) * 100000;
504 wl_unlock(lp, &flags);
506 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
510 } // wireless_get_frequency
511 /*============================================================================*/
516 /*******************************************************************************
517 * wireless_get_range()
518 *******************************************************************************
522 * This function is used to provide misc info and statistics about the
527 * wrq - the wireless request buffer
528 * lp - the device's private adapter structure
533 * errno value otherwise
535 ******************************************************************************/
536 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
538 struct wl_private *lp = wl_priv(dev);
540 struct iw_range *range = (struct iw_range *) extra;
547 /* Set range information */
548 data->length = sizeof(struct iw_range);
549 memset(range, 0, sizeof(struct iw_range));
551 wl_lock( lp, &flags );
553 wl_act_int_off( lp );
555 /* Set range information */
556 memset( range, 0, sizeof( struct iw_range ));
559 /* Get the current transmit rate from the adapter */
560 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
561 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
563 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
564 if( status != HCF_SUCCESS ) {
565 /* Recovery action: reset and retry up to 10 times */
566 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
571 /* Holding the lock too long, makes a gap to allow other processes */
572 wl_unlock(lp, &flags);
573 wl_lock( lp, &flags );
575 status = wl_reset( dev );
576 if ( status != HCF_SUCCESS ) {
577 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
583 /* Holding the lock too long, makes a gap to allow other processes */
584 wl_unlock(lp, &flags);
585 wl_lock( lp, &flags );
590 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
596 /* Holding the lock too long, makes a gap to allow other processes */
597 wl_unlock(lp, &flags);
598 wl_lock( lp, &flags );
600 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
602 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
605 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
608 // NWID - NOT SUPPORTED
611 /* Channel/Frequency Info */
612 range->num_channels = RADIO_CHANNELS;
615 /* Signal Level Thresholds */
616 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
620 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
622 /* If the value returned in /proc/net/wireless is greater than the maximum range,
623 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
624 it requires a bit of contorsion... */
626 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
627 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
630 /* Set available rates */
631 range->num_bitrates = 0;
633 lp->ltvRecord.len = 6;
634 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
636 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
637 if( status == HCF_SUCCESS ) {
638 for( count = 0; count < MAX_RATES; count++ )
639 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
640 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
641 range->num_bitrates++;
644 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
649 /* RTS Threshold info */
650 range->min_rts = MIN_RTS_BYTES;
651 range->max_rts = MAX_RTS_BYTES;
653 // Frag Threshold info - NOT SUPPORTED
655 // Power Management info - NOT SUPPORTED
659 /* Holding the lock too long, makes a gap to allow other processes */
660 wl_unlock(lp, &flags);
661 wl_lock( lp, &flags );
663 /* Is WEP supported? */
665 if( wl_has_wep( &( lp->hcfCtx ))) {
666 /* WEP: RC4 40 bits */
667 range->encoding_size[0] = MIN_KEY_SIZE;
670 range->encoding_size[1] = MAX_KEY_SIZE;
671 range->num_encoding_sizes = 2;
672 range->max_encoding_tokens = MAX_KEYS;
676 range->txpower_capa = IW_TXPOW_MWATT;
677 range->num_txpower = 1;
678 range->txpower[0] = RADIO_TX_POWER_MWATT;
680 /* Wireless Extension Info */
681 range->we_version_compiled = WIRELESS_EXT;
682 range->we_version_source = WIRELESS_SUPPORT;
684 // Retry Limits and Lifetime - NOT SUPPORTED
686 /* Holding the lock too long, makes a gap to allow other processes */
687 wl_unlock(lp, &flags);
688 wl_lock( lp, &flags );
690 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
691 wl_wireless_stats( lp->dev );
692 range->avg_qual = lp->wstats.qual;
693 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
695 /* Event capability (kernel + driver) */
696 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
697 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
698 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
699 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
700 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
701 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
702 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
703 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
705 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
706 range->scan_capa = IW_SCAN_CAPA_NONE;
711 wl_unlock(lp, &flags);
714 } // wireless_get_range
715 /*============================================================================*/
718 /*******************************************************************************
719 * wireless_get_bssid()
720 *******************************************************************************
724 * Gets the BSSID the wireless device is currently associated with.
728 * wrq - the wireless request buffer
729 * lp - the device's private adapter structure
734 * errno value otherwise
736 ******************************************************************************/
737 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
739 struct wl_private *lp = wl_priv(dev);
742 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
744 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
746 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
751 wl_lock( lp, &flags );
753 wl_act_int_off( lp );
755 ap_addr->sa_family = ARPHRD_ETHER;
757 /* Assume AP mode here, which means the BSSID is our own MAC address. In
758 STA mode, this address will be overwritten with the actual BSSID using
760 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
763 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
764 //;?should we return an error status in AP mode
766 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
767 /* Get Current BSSID */
768 lp->ltvRecord.typ = CFG_CUR_BSSID;
769 lp->ltvRecord.len = 4;
770 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
772 if( status == HCF_SUCCESS ) {
773 /* Copy info into sockaddr struct */
774 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
780 #endif // (HCF_TYPE) & HCF_TYPE_STA
784 wl_unlock(lp, &flags);
788 } // wireless_get_bssid
789 /*============================================================================*/
794 /*******************************************************************************
795 * wireless_get_ap_list()
796 *******************************************************************************
800 * Gets the results of a network scan.
804 * wrq - the wireless request buffer
805 * lp - the device's private adapter structure
810 * errno value otherwise
812 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
813 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
814 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
816 ******************************************************************************/
817 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
819 struct wl_private *lp = wl_priv(dev);
825 struct sockaddr *hwa = NULL;
826 struct iw_quality *qual = NULL;
828 ScanResult *p = &lp->scan_results;
830 ProbeResult *p = &lp->probe_results;
833 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
838 wl_lock( lp, &flags );
840 wl_act_int_off( lp );
842 /* Set the completion state to FALSE */
843 lp->scan_results.scan_complete = FALSE;
844 lp->probe_results.scan_complete = FALSE;
845 /* Channels to scan */
846 lp->ltvRecord.len = 2;
847 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
848 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
849 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
850 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
852 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
853 disassociate from the network we are currently on */
854 lp->ltvRecord.len = 2;
855 lp->ltvRecord.typ = CFG_SCAN_SSID;
856 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
857 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
858 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
860 /* Initiate the scan */
862 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
864 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
869 //;? unlock? what about the access to lp below? is it broken?
870 wl_unlock(lp, &flags);
872 if( ret == HCF_SUCCESS ) {
873 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
874 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
875 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
876 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
877 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
880 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
881 other things in the meantime, This prevents system lockups by
882 giving some time back to the kernel */
883 for( count = 0; count < 100; count ++ ) {
892 if ( ret != HCF_SUCCESS ) {
893 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
895 num_aps = (*p)/*lp->probe_results*/.num_aps;
896 if (num_aps > IW_MAX_AP) {
899 data->length = num_aps;
900 hwa = (struct sockaddr *)extra;
901 qual = (struct iw_quality *) extra +
902 ( sizeof( struct sockaddr ) * num_aps );
904 /* This flag is used to tell the user if we provide quality
905 information. Since we provide signal/noise levels but no
906 quality info on a scan, this is set to 0. Setting to 1 and
907 providing a quality of 0 produces weird results. If we ever
908 provide quality (or can calculate it), this can be changed */
911 for( count = 0; count < num_aps; count++ ) {
913 memcpy( hwa[count].sa_data,
914 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
915 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
916 DBG_PRINT("BSSID: %pM\n",
917 (*p).ProbeTable[count].BSSID);
918 memcpy( hwa[count].sa_data,
919 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
922 /* Once the data is copied to the wireless struct, invalidate the
923 scan result to initiate a rescan on the next request */
924 (*p)/*lp->probe_results*/.scan_complete = FALSE;
925 /* Send the wireless event that the scan has completed, just in case
927 wl_wext_event_scan_complete( lp->dev );
932 } // wireless_get_ap_list
933 /*============================================================================*/
938 /*******************************************************************************
939 * wireless_set_sensitivity()
940 *******************************************************************************
944 * Sets the sensitivity (distance between APs) of the wireless card.
948 * wrq - the wireless request buffer
949 * lp - the device's private adapter structure
954 * errno value otherwise
956 ******************************************************************************/
957 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
959 struct wl_private *lp = wl_priv(dev);
962 int dens = sens->value;
964 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
969 if(( dens < 1 ) || ( dens > 3 )) {
974 wl_lock( lp, &flags );
976 wl_act_int_off( lp );
978 lp->DistanceBetweenAPs = dens;
983 wl_unlock(lp, &flags);
987 } // wireless_set_sensitivity
988 /*============================================================================*/
993 /*******************************************************************************
994 * wireless_get_sensitivity()
995 *******************************************************************************
999 * Gets the sensitivity (distance between APs) of the wireless card.
1003 * wrq - the wireless request buffer
1004 * lp - the device's private adapter structure
1009 * errno value otherwise
1011 ******************************************************************************/
1012 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1014 struct wl_private *lp = wl_priv(dev);
1017 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1022 /* not worth locking ... */
1023 sens->value = lp->DistanceBetweenAPs;
1024 sens->fixed = 0; /* auto */
1027 } // wireless_get_sensitivity
1028 /*============================================================================*/
1033 /*******************************************************************************
1034 * wireless_set_essid()
1035 *******************************************************************************
1039 * Sets the ESSID (network name) that the wireless device should associate
1044 * wrq - the wireless request buffer
1045 * lp - the device's private adapter structure
1050 * errno value otherwise
1052 ******************************************************************************/
1053 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
1055 struct wl_private *lp = wl_priv(dev);
1056 unsigned long flags;
1059 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1064 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
1069 wl_lock( lp, &flags );
1071 wl_act_int_off( lp );
1073 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
1075 /* data->flags is zero to ask for "any" */
1076 if( data->flags == 0 ) {
1077 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
1078 * ;?but there ain't no STAP anymore*/
1079 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
1080 strcpy( lp->NetworkName, "ANY" );
1082 //strcpy( lp->NetworkName, "ANY" );
1083 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
1086 memcpy( lp->NetworkName, ssid, data->length );
1089 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1091 /* Commit the adapter parameters */
1094 /* Send an event that ESSID has been set */
1095 wl_wext_event_essid( lp->dev );
1097 wl_act_int_on( lp );
1099 wl_unlock(lp, &flags);
1103 } // wireless_set_essid
1104 /*============================================================================*/
1109 /*******************************************************************************
1110 * wireless_get_essid()
1111 *******************************************************************************
1115 * Gets the ESSID (network name) that the wireless device is associated
1120 * wrq - the wireless request buffer
1121 * lp - the device's private adapter structure
1126 * errno value otherwise
1128 ******************************************************************************/
1129 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1132 struct wl_private *lp = wl_priv(dev);
1133 unsigned long flags;
1138 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1143 wl_lock( lp, &flags );
1145 wl_act_int_off( lp );
1147 /* Get the desired network name */
1148 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1151 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1152 //;?should we return an error status in AP mode
1154 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1159 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1160 //;?should we restore this to allow smaller memory footprint
1162 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1163 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1169 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1170 if( status == HCF_SUCCESS ) {
1171 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1173 /* Endian translate the string length */
1174 pName->length = CNV_LITTLE_TO_INT( pName->length );
1176 /* Copy the information into the user buffer */
1177 data->length = pName->length;
1179 if( pName->length < HCF_MAX_NAME_LEN ) {
1180 pName->name[pName->length] = '\0';
1186 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1187 //;?should we return an error status in AP mode
1189 /* if desired is null ("any"), return current or "any" */
1190 if( pName->name[0] == '\0' ) {
1191 /* Get the current network name */
1192 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1193 lp->ltvRecord.typ = CFG_CUR_SSID;
1195 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1197 if( status == HCF_SUCCESS ) {
1198 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1200 /* Endian translate the string length */
1201 pName->length = CNV_LITTLE_TO_INT( pName->length );
1203 /* Copy the information into the user buffer */
1204 data->length = pName->length;
1214 if (pName->length > IW_ESSID_MAX_SIZE) {
1219 memcpy(essid, pName->name, pName->length);
1226 wl_act_int_on( lp );
1228 wl_unlock(lp, &flags);
1232 } // wireless_get_essid
1233 /*============================================================================*/
1238 /*******************************************************************************
1239 * wireless_set_encode()
1240 *******************************************************************************
1244 * Sets the encryption keys and status (enable or disable).
1248 * wrq - the wireless request buffer
1249 * lp - the device's private adapter structure
1254 * errno value otherwise
1256 ******************************************************************************/
1257 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1259 struct wl_private *lp = wl_priv(dev);
1260 unsigned long flags;
1261 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1265 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
1270 if (erq->flags & IW_ENCODE_DISABLED)
1273 wl_lock(lp, &flags);
1277 ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1280 /* Send an event that Encryption has been set */
1282 wl_wext_event_encode(dev);
1286 wl_unlock(lp, &flags);
1292 /*******************************************************************************
1293 * wireless_get_encode()
1294 *******************************************************************************
1298 * Gets the encryption keys and status.
1302 * wrq - the wireless request buffer
1303 * lp - the device's private adapter structure
1308 * errno value otherwise
1310 ******************************************************************************/
1311 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1314 struct wl_private *lp = wl_priv(dev);
1315 unsigned long flags;
1319 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1321 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1326 /* Only super-user can see WEP key */
1327 if( !capable( CAP_NET_ADMIN )) {
1332 wl_lock( lp, &flags );
1334 wl_act_int_off( lp );
1336 /* Is it supported? */
1337 if( !wl_has_wep( &( lp->hcfCtx ))) {
1342 /* Basic checking */
1343 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1349 if( lp->EnableEncryption == 0 ) {
1350 erq->flags |= IW_ENCODE_DISABLED;
1353 /* Which key do we want */
1354 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1355 index = lp->TransmitKeyID - 1;
1358 erq->flags |= index + 1;
1360 /* Copy the key to the user buffer */
1361 erq->length = lp->DefaultKeys.key[index].len;
1363 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1367 wl_act_int_on( lp );
1369 wl_unlock(lp, &flags);
1373 } // wireless_get_encode
1374 /*============================================================================*/
1379 /*******************************************************************************
1380 * wireless_set_nickname()
1381 *******************************************************************************
1385 * Sets the nickname, or station name, of the wireless device.
1389 * wrq - the wireless request buffer
1390 * lp - the device's private adapter structure
1395 * errno value otherwise
1397 ******************************************************************************/
1398 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1400 struct wl_private *lp = wl_priv(dev);
1401 unsigned long flags;
1404 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1409 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1410 if( !capable(CAP_NET_ADMIN )) {
1416 /* Validate the new value */
1417 if(data->length > HCF_MAX_NAME_LEN) {
1422 wl_lock( lp, &flags );
1424 wl_act_int_off( lp );
1426 memset( lp->StationName, 0, sizeof( lp->StationName ));
1428 memcpy( lp->StationName, nickname, data->length );
1430 /* Commit the adapter parameters */
1433 wl_act_int_on( lp );
1435 wl_unlock(lp, &flags);
1439 } // wireless_set_nickname
1440 /*============================================================================*/
1445 /*******************************************************************************
1446 * wireless_get_nickname()
1447 *******************************************************************************
1451 * Gets the nickname, or station name, of the wireless device.
1455 * wrq - the wireless request buffer
1456 * lp - the device's private adapter structure
1461 * errno value otherwise
1463 ******************************************************************************/
1464 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1466 struct wl_private *lp = wl_priv(dev);
1467 unsigned long flags;
1472 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1477 wl_lock( lp, &flags );
1479 wl_act_int_off( lp );
1481 /* Get the current station name */
1482 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1483 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1485 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1487 if( status == HCF_SUCCESS ) {
1488 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1490 /* Endian translate the length */
1491 pName->length = CNV_LITTLE_TO_INT( pName->length );
1493 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1496 /* Copy the information into the user buffer */
1497 data->length = pName->length;
1498 memcpy(nickname, pName->name, pName->length);
1504 wl_act_int_on( lp );
1506 wl_unlock(lp, &flags);
1510 } // wireless_get_nickname
1511 /*============================================================================*/
1516 /*******************************************************************************
1517 * wireless_set_porttype()
1518 *******************************************************************************
1522 * Sets the port type of the wireless device.
1526 * wrq - the wireless request buffer
1527 * lp - the device's private adapter structure
1532 * errno value otherwise
1534 ******************************************************************************/
1535 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1537 struct wl_private *lp = wl_priv(dev);
1538 unsigned long flags;
1543 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1548 wl_lock( lp, &flags );
1550 wl_act_int_off( lp );
1552 /* Validate the new value */
1556 /* When user requests ad-hoc, set IBSS mode! */
1560 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1568 /* Both automatic and infrastructure set port to BSS/STA mode */
1572 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1577 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1579 case IW_MODE_MASTER:
1581 /* Set BSS/AP mode */
1585 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1589 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1599 if( portType != 0 ) {
1600 /* Only do something if there is a mode change */
1601 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1602 lp->PortType = portType;
1603 lp->CreateIBSS = createIBSS;
1605 /* Commit the adapter parameters */
1608 /* Send an event that mode has been set */
1609 wl_wext_event_mode( lp->dev );
1613 wl_act_int_on( lp );
1615 wl_unlock(lp, &flags);
1619 } // wireless_set_porttype
1620 /*============================================================================*/
1625 /*******************************************************************************
1626 * wireless_get_porttype()
1627 *******************************************************************************
1631 * Gets the port type of the wireless device.
1635 * wrq - the wireless request buffer
1636 * lp - the device's private adapter structure
1641 * errno value otherwise
1643 ******************************************************************************/
1644 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1647 struct wl_private *lp = wl_priv(dev);
1648 unsigned long flags;
1653 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1658 wl_lock( lp, &flags );
1660 wl_act_int_off( lp );
1662 /* Get the current port type */
1663 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1664 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1666 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1668 if( status == HCF_SUCCESS ) {
1669 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1671 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1673 switch( *pPortType ) {
1677 #if (HCF_TYPE) & HCF_TYPE_AP
1679 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1680 *mode = IW_MODE_MASTER;
1682 *mode = IW_MODE_INFRA;
1687 *mode = IW_MODE_INFRA;
1689 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1692 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1693 *mode = IW_MODE_MASTER;
1695 if( lp->CreateIBSS ) {
1696 *mode = IW_MODE_ADHOC;
1698 *mode = IW_MODE_INFRA;
1706 *mode = IW_MODE_ADHOC;
1717 wl_act_int_on( lp );
1719 wl_unlock(lp, &flags);
1723 } // wireless_get_porttype
1724 /*============================================================================*/
1729 /*******************************************************************************
1730 * wireless_set_power()
1731 *******************************************************************************
1735 * Sets the power management settings of the wireless device.
1739 * wrq - the wireless request buffer
1740 * lp - the device's private adapter structure
1745 * errno value otherwise
1747 ******************************************************************************/
1748 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1750 struct wl_private *lp = wl_priv(dev);
1751 unsigned long flags;
1754 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1759 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1761 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1762 if( !capable( CAP_NET_ADMIN )) {
1768 wl_lock( lp, &flags );
1770 wl_act_int_off( lp );
1772 /* Set the power management state based on the 'disabled' value */
1773 if( wrq->disabled ) {
1779 /* Commit the adapter parameters */
1782 wl_act_int_on( lp );
1784 wl_unlock(lp, &flags);
1788 } // wireless_set_power
1789 /*============================================================================*/
1794 /*******************************************************************************
1795 * wireless_get_power()
1796 *******************************************************************************
1800 * Gets the power management settings of the wireless device.
1804 * wrq - the wireless request buffer
1805 * lp - the device's private adapter structure
1810 * errno value otherwise
1812 ******************************************************************************/
1813 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1816 struct wl_private *lp = wl_priv(dev);
1817 unsigned long flags;
1820 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1825 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1827 wl_lock( lp, &flags );
1829 wl_act_int_off( lp );
1834 if( lp->PMEnabled ) {
1840 wl_act_int_on( lp );
1842 wl_unlock(lp, &flags);
1846 } // wireless_get_power
1847 /*============================================================================*/
1852 /*******************************************************************************
1853 * wireless_get_tx_power()
1854 *******************************************************************************
1858 * Gets the transmit power of the wireless device's radio.
1862 * wrq - the wireless request buffer
1863 * lp - the device's private adapter structure
1868 * errno value otherwise
1870 ******************************************************************************/
1871 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1873 struct wl_private *lp = wl_priv(dev);
1874 unsigned long flags;
1877 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1882 wl_lock( lp, &flags );
1884 wl_act_int_off( lp );
1886 #ifdef USE_POWER_DBM
1887 rrq->value = RADIO_TX_POWER_DBM;
1888 rrq->flags = IW_TXPOW_DBM;
1890 rrq->value = RADIO_TX_POWER_MWATT;
1891 rrq->flags = IW_TXPOW_MWATT;
1896 wl_act_int_on( lp );
1898 wl_unlock(lp, &flags);
1902 } // wireless_get_tx_power
1903 /*============================================================================*/
1908 /*******************************************************************************
1909 * wireless_set_rts_threshold()
1910 *******************************************************************************
1914 * Sets the RTS threshold for the wireless card.
1918 * wrq - the wireless request buffer
1919 * lp - the device's private adapter structure
1924 * errno value otherwise
1926 ******************************************************************************/
1927 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
1930 struct wl_private *lp = wl_priv(dev);
1931 unsigned long flags;
1932 int rthr = rts->value;
1934 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1939 if(rts->fixed == 0) {
1944 if( rts->disabled ) {
1948 if(( rthr < 256 ) || ( rthr > 2347 )) {
1953 wl_lock( lp, &flags );
1955 wl_act_int_off( lp );
1957 lp->RTSThreshold = rthr;
1961 wl_act_int_on( lp );
1963 wl_unlock(lp, &flags);
1967 } // wireless_set_rts_threshold
1968 /*============================================================================*/
1973 /*******************************************************************************
1974 * wireless_get_rts_threshold()
1975 *******************************************************************************
1979 * Gets the RTS threshold for the wireless card.
1983 * wrq - the wireless request buffer
1984 * lp - the device's private adapter structure
1989 * errno value otherwise
1991 ******************************************************************************/
1992 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
1995 struct wl_private *lp = wl_priv(dev);
1996 unsigned long flags;
1998 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2003 wl_lock( lp, &flags );
2005 wl_act_int_off( lp );
2007 rts->value = lp->RTSThreshold;
2009 rts->disabled = ( rts->value == 2347 );
2013 wl_act_int_on( lp );
2015 wl_unlock(lp, &flags);
2019 } // wireless_get_rts_threshold
2020 /*============================================================================*/
2026 /*******************************************************************************
2027 * wireless_set_rate()
2028 *******************************************************************************
2032 * Set the default data rate setting used by the wireless device.
2036 * wrq - the wireless request buffer
2037 * lp - the device's private adapter structure
2042 * errno value otherwise
2044 ******************************************************************************/
2045 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2047 struct wl_private *lp = wl_priv(dev);
2048 unsigned long flags;
2055 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2060 wl_lock( lp, &flags );
2062 wl_act_int_off( lp );
2066 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2067 if Bit 9 is set in the current channel RID */
2068 lp->ltvRecord.len = 2;
2069 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2071 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2073 if( status == HCF_SUCCESS ) {
2074 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2076 DBG_PRINT( "Index: %d\n", index );
2078 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2083 if( rrq->value > 0 &&
2084 rrq->value <= 1 * MEGABIT ) {
2085 lp->TxRateControl[index] = 0x0001;
2087 else if( rrq->value > 1 * MEGABIT &&
2088 rrq->value <= 2 * MEGABIT ) {
2089 if( rrq->fixed == 1 ) {
2090 lp->TxRateControl[index] = 0x0002;
2092 lp->TxRateControl[index] = 0x0003;
2095 else if( rrq->value > 2 * MEGABIT &&
2096 rrq->value <= 5 * MEGABIT ) {
2097 if( rrq->fixed == 1 ) {
2098 lp->TxRateControl[index] = 0x0004;
2100 lp->TxRateControl[index] = 0x0007;
2103 else if( rrq->value > 5 * MEGABIT &&
2104 rrq->value <= 6 * MEGABIT ) {
2105 if( rrq->fixed == 1 ) {
2106 lp->TxRateControl[index] = 0x0010;
2108 lp->TxRateControl[index] = 0x0017;
2111 else if( rrq->value > 6 * MEGABIT &&
2112 rrq->value <= 9 * MEGABIT ) {
2113 if( rrq->fixed == 1 ) {
2114 lp->TxRateControl[index] = 0x0020;
2116 lp->TxRateControl[index] = 0x0037;
2119 else if( rrq->value > 9 * MEGABIT &&
2120 rrq->value <= 11 * MEGABIT ) {
2121 if( rrq->fixed == 1 ) {
2122 lp->TxRateControl[index] = 0x0008;
2124 lp->TxRateControl[index] = 0x003F;
2127 else if( rrq->value > 11 * MEGABIT &&
2128 rrq->value <= 12 * MEGABIT ) {
2129 if( rrq->fixed == 1 ) {
2130 lp->TxRateControl[index] = 0x0040;
2132 lp->TxRateControl[index] = 0x007F;
2135 else if( rrq->value > 12 * MEGABIT &&
2136 rrq->value <= 18 * MEGABIT ) {
2137 if( rrq->fixed == 1 ) {
2138 lp->TxRateControl[index] = 0x0080;
2140 lp->TxRateControl[index] = 0x00FF;
2143 else if( rrq->value > 18 * MEGABIT &&
2144 rrq->value <= 24 * MEGABIT ) {
2145 if( rrq->fixed == 1 ) {
2146 lp->TxRateControl[index] = 0x0100;
2148 lp->TxRateControl[index] = 0x01FF;
2151 else if( rrq->value > 24 * MEGABIT &&
2152 rrq->value <= 36 * MEGABIT ) {
2153 if( rrq->fixed == 1 ) {
2154 lp->TxRateControl[index] = 0x0200;
2156 lp->TxRateControl[index] = 0x03FF;
2159 else if( rrq->value > 36 * MEGABIT &&
2160 rrq->value <= 48 * MEGABIT ) {
2161 if( rrq->fixed == 1 ) {
2162 lp->TxRateControl[index] = 0x0400;
2164 lp->TxRateControl[index] = 0x07FF;
2167 else if( rrq->value > 48 * MEGABIT &&
2168 rrq->value <= 54 * MEGABIT ) {
2169 if( rrq->fixed == 1 ) {
2170 lp->TxRateControl[index] = 0x0800;
2172 lp->TxRateControl[index] = 0x0FFF;
2175 else if( rrq->fixed == 0 ) {
2176 /* In this case, the user has not specified a bitrate, only the "auto"
2177 moniker. So, set to all supported rates */
2178 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2188 if( rrq->value > 0 &&
2189 rrq->value <= 1 * MEGABIT ) {
2190 lp->TxRateControl[0] = 1;
2192 else if( rrq->value > 1 * MEGABIT &&
2193 rrq->value <= 2 * MEGABIT ) {
2195 lp->TxRateControl[0] = 2;
2197 lp->TxRateControl[0] = 6;
2200 else if( rrq->value > 2 * MEGABIT &&
2201 rrq->value <= 5 * MEGABIT ) {
2203 lp->TxRateControl[0] = 4;
2205 lp->TxRateControl[0] = 7;
2208 else if( rrq->value > 5 * MEGABIT &&
2209 rrq->value <= 11 * MEGABIT ) {
2211 lp->TxRateControl[0] = 5;
2213 lp->TxRateControl[0] = 3;
2216 else if( rrq->fixed == 0 ) {
2217 /* In this case, the user has not specified a bitrate, only the "auto"
2218 moniker. So, set the rate to 11Mb auto */
2219 lp->TxRateControl[0] = 3;
2229 /* Commit the adapter parameters */
2234 wl_act_int_on( lp );
2236 wl_unlock(lp, &flags);
2240 } // wireless_set_rate
2241 /*============================================================================*/
2246 /*******************************************************************************
2247 * wireless_get_rate()
2248 *******************************************************************************
2252 * Get the default data rate setting used by the wireless device.
2256 * wrq - the wireless request buffer
2257 * lp - the device's private adapter structure
2262 * errno value otherwise
2264 ******************************************************************************/
2265 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2268 struct wl_private *lp = wl_priv(dev);
2269 unsigned long flags;
2274 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2279 wl_lock( lp, &flags );
2281 wl_act_int_off( lp );
2283 /* Get the current transmit rate from the adapter */
2284 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2285 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2287 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2289 if( status == HCF_SUCCESS ) {
2292 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2294 if( txRate & 0x0001 ) {
2297 else if( txRate & 0x0002 ) {
2300 else if( txRate & 0x0004 ) {
2303 else if( txRate & 0x0008 ) {
2306 else if( txRate & 0x00010 ) {
2309 else if( txRate & 0x00020 ) {
2312 else if( txRate & 0x00040 ) {
2315 else if( txRate & 0x00080 ) {
2318 else if( txRate & 0x00100 ) {
2321 else if( txRate & 0x00200 ) {
2324 else if( txRate & 0x00400 ) {
2327 else if( txRate & 0x00800 ) {
2333 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2337 rrq->value = txRate * MEGABIT;
2343 wl_act_int_on( lp );
2345 wl_unlock(lp, &flags);
2349 } // wireless_get_rate
2350 /*============================================================================*/
2355 #if 0 //;? Not used anymore
2356 /*******************************************************************************
2357 * wireless_get_private_interface()
2358 *******************************************************************************
2362 * Returns the Linux Wireless Extensions' compatible private interface of
2367 * wrq - the wireless request buffer
2368 * lp - the device's private adapter structure
2373 * errno value otherwise
2375 ******************************************************************************/
2376 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2380 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2385 if( wrq->u.data.pointer != NULL ) {
2386 struct iw_priv_args priv[] =
2388 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2389 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2390 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2391 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2392 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2393 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2396 /* Verify the user buffer */
2397 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2402 /* Copy the data into the user's buffer */
2403 wrq->u.data.length = NELEM( priv );
2404 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2409 } // wireless_get_private_interface
2410 /*============================================================================*/
2415 /*******************************************************************************
2416 * wireless_set_scan()
2417 *******************************************************************************
2421 * Instructs the driver to initiate a network scan.
2425 * wrq - the wireless request buffer
2426 * lp - the device's private adapter structure
2431 * errno value otherwise
2433 ******************************************************************************/
2434 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2436 struct wl_private *lp = wl_priv(dev);
2437 unsigned long flags;
2442 //;? Note: shows results as trace, returns always 0 unless BUSY
2444 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2449 wl_lock( lp, &flags );
2451 wl_act_int_off( lp );
2454 * This looks like a nice place to test if the HCF is still
2455 * communicating with the card. It seems that sometimes BAP_1
2456 * gets corrupted. By looking at the comments in HCF the
2457 * cause is still a mystery. Okay, the communication to the
2458 * card is dead, reset the card to revive.
2460 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2462 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2467 /* Set the completion state to FALSE */
2468 lp->probe_results.scan_complete = FALSE;
2471 /* Channels to scan */
2473 lp->ltvRecord.len = 5;
2474 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2475 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2476 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2477 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2478 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2480 lp->ltvRecord.len = 2;
2481 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2482 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2485 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2487 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2489 // Holding the lock too long, makes a gap to allow other processes
2490 wl_unlock(lp, &flags);
2491 wl_lock( lp, &flags );
2493 if( status != HCF_SUCCESS ) {
2497 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2500 // Holding the lock too long, makes a gap to allow other processes
2501 wl_unlock(lp, &flags);
2502 wl_lock( lp, &flags );
2508 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2509 disassociate from the network we are currently on */
2510 lp->ltvRecord.len = 18;
2511 lp->ltvRecord.typ = CFG_SCAN_SSID;
2512 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2513 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2515 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2517 // Holding the lock too long, makes a gap to allow other processes
2518 wl_unlock(lp, &flags);
2519 wl_lock( lp, &flags );
2521 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2523 /* Initiate the scan */
2524 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2525 retrieve probe response must always be used to support WPA */
2526 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2528 if( status == HCF_SUCCESS ) {
2529 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2531 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2534 wl_act_int_on( lp );
2536 wl_unlock(lp, &flags);
2540 } // wireless_set_scan
2541 /*============================================================================*/
2546 /*******************************************************************************
2547 * wireless_get_scan()
2548 *******************************************************************************
2552 * Instructs the driver to gather and return the results of a network scan.
2556 * wrq - the wireless request buffer
2557 * lp - the device's private adapter structure
2562 * errno value otherwise
2564 ******************************************************************************/
2565 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2567 struct wl_private *lp = wl_priv(dev);
2568 unsigned long flags;
2573 struct iw_event iwe;
2574 PROBE_RESP *probe_resp;
2579 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2584 wl_lock( lp, &flags );
2586 wl_act_int_off( lp );
2588 /* If the scan is not done, tell the calling process to try again later */
2589 if( !lp->probe_results.scan_complete ) {
2594 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2595 lp->probe_results.num_aps );
2598 buf_end = extra + IW_SCAN_MAX_DATA;
2600 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2601 /* Reference the probe response from the table */
2602 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2605 /* First entry MUST be the MAC address */
2606 memset( &iwe, 0, sizeof( iwe ));
2608 iwe.cmd = SIOCGIWAP;
2609 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2610 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2611 iwe.len = IW_EV_ADDR_LEN;
2613 buf = iwe_stream_add_event(info, buf, buf_end,
2614 &iwe, IW_EV_ADDR_LEN);
2616 /* Use the mode to indicate if it's a station or AP */
2617 /* Won't always be an AP if in IBSS mode */
2618 memset( &iwe, 0, sizeof( iwe ));
2620 iwe.cmd = SIOCGIWMODE;
2622 if( probe_resp->capability & CAPABILITY_IBSS ) {
2623 iwe.u.mode = IW_MODE_INFRA;
2625 iwe.u.mode = IW_MODE_MASTER;
2628 iwe.len = IW_EV_UINT_LEN;
2630 buf = iwe_stream_add_event(info, buf, buf_end,
2631 &iwe, IW_EV_UINT_LEN);
2633 /* Any quality information */
2634 memset(&iwe, 0, sizeof(iwe));
2637 iwe.u.qual.level = dbm(probe_resp->signal);
2638 iwe.u.qual.noise = dbm(probe_resp->silence);
2639 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2640 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2641 iwe.len = IW_EV_QUAL_LEN;
2643 buf = iwe_stream_add_event(info, buf, buf_end,
2644 &iwe, IW_EV_QUAL_LEN);
2647 /* ESSID information */
2648 if( probe_resp->rawData[1] > 0 ) {
2649 memset( &iwe, 0, sizeof( iwe ));
2651 iwe.cmd = SIOCGIWESSID;
2652 iwe.u.data.length = probe_resp->rawData[1];
2653 iwe.u.data.flags = 1;
2655 buf = iwe_stream_add_point(info, buf, buf_end,
2656 &iwe, &probe_resp->rawData[2]);
2660 /* Encryption Information */
2661 memset( &iwe, 0, sizeof( iwe ));
2663 iwe.cmd = SIOCGIWENCODE;
2664 iwe.u.data.length = 0;
2666 /* Check the capabilities field of the Probe Response to see if
2667 'privacy' is supported on the AP in question */
2668 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2669 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2671 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2674 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
2677 /* Frequency Info */
2678 memset( &iwe, 0, sizeof( iwe ));
2680 iwe.cmd = SIOCGIWFREQ;
2681 iwe.len = IW_EV_FREQ_LEN;
2682 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2685 buf = iwe_stream_add_event(info, buf, buf_end,
2686 &iwe, IW_EV_FREQ_LEN);
2689 /* Custom info (Beacon Interval) */
2690 memset( &iwe, 0, sizeof( iwe ));
2691 memset( msg, 0, sizeof( msg ));
2693 iwe.cmd = IWEVCUSTOM;
2694 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2695 iwe.u.data.length = strlen( msg );
2697 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
2704 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2705 if( wpa_ie != NULL ) {
2706 memset(&iwe, 0, sizeof(iwe));
2708 iwe.cmd = IWEVGENIE;
2709 iwe.u.data.length = wpa_ie_len;
2711 buf = iwe_stream_add_point(info, buf, buf_end,
2715 /* Add other custom info in formatted string format as needed... */
2718 data->length = buf - extra;
2722 wl_act_int_on( lp );
2724 wl_unlock(lp, &flags);
2728 } // wireless_get_scan
2729 /*============================================================================*/
2732 static const char * const auth_names[] = {
2733 "IW_AUTH_WPA_VERSION",
2734 "IW_AUTH_CIPHER_PAIRWISE",
2735 "IW_AUTH_CIPHER_GROUP",
2737 "IW_AUTH_TKIP_COUNTERMEASURES",
2738 "IW_AUTH_DROP_UNENCRYPTED",
2739 "IW_AUTH_80211_AUTH_ALG",
2740 "IW_AUTH_WPA_ENABLED",
2741 "IW_AUTH_RX_UNENCRYPTED_EAPOL",
2742 "IW_AUTH_ROAMING_CONTROL",
2743 "IW_AUTH_PRIVACY_INVOKED",
2744 "IW_AUTH_CIPHER_GROUP_MGMT",
2750 static int wireless_set_auth(struct net_device *dev,
2751 struct iw_request_info *info,
2752 struct iw_param *data, char *extra)
2754 struct wl_private *lp = wl_priv(dev);
2755 unsigned long flags;
2758 int iwa_idx = data->flags & IW_AUTH_INDEX;
2759 int iwa_val = data->value;
2761 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2766 wl_lock( lp, &flags );
2768 wl_act_int_off( lp );
2770 if (iwa_idx > IW_AUTH_MFP)
2771 iwa_idx = IW_AUTH_MFP + 1;
2772 DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
2774 case IW_AUTH_WPA_VERSION:
2775 /* We do support WPA */
2776 if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
2777 (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
2783 case IW_AUTH_WPA_ENABLED:
2784 DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
2786 lp->EnableEncryption = 2;
2788 lp->EnableEncryption = 0;
2790 /* Write straight to the card */
2792 ltv.typ = CFG_CNF_ENCRYPTION;
2793 ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
2794 ret = hcf_put_info(&lp->hcfCtx, (LTVP)<v);
2798 case IW_AUTH_TKIP_COUNTERMEASURES:
2800 /* Immediately disable card */
2801 lp->driverEnable = !iwa_val;
2802 if (lp->driverEnable)
2803 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2805 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2810 /* Management Frame Protection not supported.
2811 * Only fail if set to required.
2813 if (iwa_val == IW_AUTH_MFP_REQUIRED)
2819 case IW_AUTH_KEY_MGMT:
2821 /* Record required management suite.
2822 * Will take effect on next commit */
2824 lp->AuthKeyMgmtSuite = 4;
2826 lp->AuthKeyMgmtSuite = 0;
2831 case IW_AUTH_80211_AUTH_ALG:
2833 /* Just record whether open or shared is required.
2834 * Will take effect on next commit */
2837 if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
2838 lp->authentication = 1;
2839 else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
2840 lp->authentication = 0;
2845 case IW_AUTH_DROP_UNENCRYPTED:
2846 /* Only needed for AP */
2847 lp->ExcludeUnencrypted = iwa_val;
2851 case IW_AUTH_CIPHER_PAIRWISE:
2852 case IW_AUTH_CIPHER_GROUP:
2853 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2854 case IW_AUTH_ROAMING_CONTROL:
2855 case IW_AUTH_PRIVACY_INVOKED:
2856 /* Not used. May need to do something with
2857 * CIPHER_PAIRWISE and CIPHER_GROUP*/
2862 DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2863 /* return an error */
2868 wl_act_int_on( lp );
2870 wl_unlock(lp, &flags);
2874 } // wireless_set_auth
2875 /*============================================================================*/
2878 static void flush_tx(struct wl_private *lp)
2884 * Make sure that there is no data queued up in the firmware
2885 * before setting the TKIP keys. If this check is not
2886 * performed, some data may be sent out with incorrect MIC
2887 * and cause synchronization errors with the AP
2889 /* Check every 1ms for 100ms */
2890 for (count = 0; count < 100; count++) {
2894 ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
2897 hcf_get_info(&(lp->hcfCtx), (LTVP)<v);
2899 if (ltv.u.u16[0] == 0)
2904 DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
2908 static int wireless_set_encodeext(struct net_device *dev,
2909 struct iw_request_info *info,
2910 struct iw_point *erq, char *keybuf)
2912 struct wl_private *lp = wl_priv(dev);
2913 unsigned long flags;
2915 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
2917 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
2919 bool set_tx = false;
2921 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2926 if (erq->flags & IW_ENCODE_DISABLED) {
2927 ext->alg = IW_ENCODE_ALG_NONE;
2931 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2934 wl_lock(lp, &flags);
2938 memset(<v, 0, sizeof(ltv));
2941 case IW_ENCODE_ALG_TKIP:
2942 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
2944 if (sizeof(ext->rx_seq) != 8) {
2945 DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
2950 ret = hermes_set_tkip_keys(<v, key_idx, ext->addr.sa_data,
2952 ext->rx_seq, ext->key, ext->key_len);
2955 DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
2961 lp->wext_enc = IW_ENCODE_ALG_TKIP;
2964 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
2967 case IW_ENCODE_ALG_WEP:
2968 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
2970 if (erq->flags & IW_ENCODE_RESTRICTED) {
2971 DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
2976 ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
2981 case IW_ENCODE_ALG_CCMP:
2982 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
2986 case IW_ENCODE_ALG_NONE:
2987 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
2989 if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
2990 ret = hermes_clear_tkip_keys(<v, key_idx,
2993 lp->wext_enc = IW_ENCODE_ALG_NONE;
2994 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
2996 } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
2997 ret = hermes_set_wep_keys(lp, key_idx,
2998 ext->key, ext->key_len,
3007 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3016 wl_unlock(lp, &flags);
3021 /*============================================================================*/
3025 static int wireless_set_genie(struct net_device *dev,
3026 struct iw_request_info *info,
3027 struct iw_point *data, char *extra)
3032 /* We can't write this to the card, but apparently this
3033 * operation needs to succeed */
3038 /*============================================================================*/
3041 /*******************************************************************************
3042 * wl_wireless_stats()
3043 *******************************************************************************
3047 * Return the current device wireless statistics.
3051 * wrq - the wireless request buffer
3052 * lp - the device's private adapter structure
3057 * errno value otherwise
3059 ******************************************************************************/
3060 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3062 struct iw_statistics *pStats;
3063 struct wl_private *lp = wl_priv(dev);
3065 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3069 /* Initialize the statistics */
3070 pStats = &( lp->wstats );
3071 pStats->qual.updated = 0x00;
3073 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3075 CFG_COMMS_QUALITY_STRCT *pQual;
3076 CFG_HERMES_TALLIES_STRCT tallies;
3079 /* Update driver status */
3082 /* Get the current link quality information */
3083 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3084 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3085 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3087 if( status == HCF_SUCCESS ) {
3088 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3090 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3091 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3092 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3094 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3095 IW_QUAL_LEVEL_UPDATED |
3096 IW_QUAL_NOISE_UPDATED |
3099 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3102 /* Get the current tallies from the adapter */
3103 /* Only possible when the device is open */
3104 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3105 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3106 /* No endian translation is needed here, as CFG_TALLIES is an
3107 MSF RID; all processing is done on the host, not the card! */
3108 pStats->discard.nwid = 0L;
3109 pStats->discard.code = tallies.RxWEPUndecryptable;
3110 pStats->discard.misc = tallies.TxDiscards +
3111 tallies.RxFCSErrors +
3112 //tallies.RxDiscardsNoBuffer +
3113 tallies.TxDiscardsWrongSA;
3114 //;? Extra taken over from Linux driver based on 7.18 version
3115 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3116 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3118 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3121 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3126 } // wl_wireless_stats
3127 /*============================================================================*/
3132 /*******************************************************************************
3133 * wl_get_wireless_stats()
3134 *******************************************************************************
3138 * Return the current device wireless statistics. This function calls
3139 * wl_wireless_stats, but acquires spinlocks first as it can be called
3140 * directly by the network layer.
3144 * wrq - the wireless request buffer
3145 * lp - the device's private adapter structure
3150 * errno value otherwise
3152 ******************************************************************************/
3153 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3155 unsigned long flags;
3156 struct wl_private *lp = wl_priv(dev);
3157 struct iw_statistics *pStats = NULL;
3159 wl_lock( lp, &flags );
3161 wl_act_int_off( lp );
3164 if( lp->useRTS == 1 ) {
3165 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3169 pStats = wl_wireless_stats( dev );
3171 wl_act_int_on( lp );
3173 wl_unlock(lp, &flags);
3176 } // wl_get_wireless_stats
3179 /*******************************************************************************
3181 *******************************************************************************
3185 * Gather wireless spy statistics.
3189 * wrq - the wireless request buffer
3190 * lp - the device's private adapter structure
3195 * errno value otherwise
3197 ******************************************************************************/
3198 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3200 struct iw_quality wstats;
3204 struct wl_private *lp = wl_priv(dev);
3205 /*------------------------------------------------------------------------*/
3208 if (!lp->spy_data.spy_number) {
3212 /* Gather wireless spy statistics: for each packet, compare the source
3213 address with out list, and if match, get the stats. */
3214 memset( stats, 0, sizeof(stats));
3215 memset( desc, 0, sizeof(DESC_STRCT));
3217 desc[0].buf_addr = stats;
3218 desc[0].BUF_SIZE = sizeof(stats);
3219 desc[0].next_desc_addr = 0; // terminate list
3221 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3223 if( status == HCF_SUCCESS ) {
3224 wstats.level = (u_char) dbm(stats[1]);
3225 wstats.noise = (u_char) dbm(stats[0]);
3226 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3228 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3229 IW_QUAL_LEVEL_UPDATED |
3230 IW_QUAL_NOISE_UPDATED |
3233 wireless_spy_update( dev, mac, &wstats );
3236 /*============================================================================*/
3241 /*******************************************************************************
3242 * wl_wext_event_freq()
3243 *******************************************************************************
3247 * This function is used to send an event that the channel/freq
3248 * configuration for a specific device has changed.
3253 * dev - the network device for which this event is to be issued
3259 ******************************************************************************/
3260 void wl_wext_event_freq( struct net_device *dev )
3262 union iwreq_data wrqu;
3263 struct wl_private *lp = wl_priv(dev);
3264 /*------------------------------------------------------------------------*/
3267 memset( &wrqu, 0, sizeof( wrqu ));
3269 wrqu.freq.m = lp->Channel;
3272 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3275 } // wl_wext_event_freq
3276 /*============================================================================*/
3281 /*******************************************************************************
3282 * wl_wext_event_mode()
3283 *******************************************************************************
3287 * This function is used to send an event that the mode of operation
3288 * for a specific device has changed.
3293 * dev - the network device for which this event is to be issued
3299 ******************************************************************************/
3300 void wl_wext_event_mode( struct net_device *dev )
3302 union iwreq_data wrqu;
3303 struct wl_private *lp = wl_priv(dev);
3304 /*------------------------------------------------------------------------*/
3307 memset( &wrqu, 0, sizeof( wrqu ));
3309 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3310 wrqu.mode = IW_MODE_INFRA;
3312 wrqu.mode = IW_MODE_MASTER;
3315 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3318 } // wl_wext_event_mode
3319 /*============================================================================*/
3324 /*******************************************************************************
3325 * wl_wext_event_essid()
3326 *******************************************************************************
3330 * This function is used to send an event that the ESSID configuration for
3331 * a specific device has changed.
3336 * dev - the network device for which this event is to be issued
3342 ******************************************************************************/
3343 void wl_wext_event_essid( struct net_device *dev )
3345 union iwreq_data wrqu;
3346 struct wl_private *lp = wl_priv(dev);
3347 /*------------------------------------------------------------------------*/
3350 memset( &wrqu, 0, sizeof( wrqu ));
3352 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3353 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3354 the call to wireless_send_event() must also point to where the ESSID
3356 wrqu.essid.length = strlen( lp->NetworkName );
3357 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3358 wrqu.essid.flags = 1;
3360 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3363 } // wl_wext_event_essid
3364 /*============================================================================*/
3369 /*******************************************************************************
3370 * wl_wext_event_encode()
3371 *******************************************************************************
3375 * This function is used to send an event that the encryption configuration
3376 * for a specific device has changed.
3381 * dev - the network device for which this event is to be issued
3387 ******************************************************************************/
3388 void wl_wext_event_encode( struct net_device *dev )
3390 union iwreq_data wrqu;
3391 struct wl_private *lp = wl_priv(dev);
3393 /*------------------------------------------------------------------------*/
3396 memset( &wrqu, 0, sizeof( wrqu ));
3398 if( lp->EnableEncryption == 0 ) {
3399 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3401 wrqu.encoding.flags |= lp->TransmitKeyID;
3403 index = lp->TransmitKeyID - 1;
3405 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3406 if we're in AP mode */
3407 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3408 //;?should we restore this to allow smaller memory footprint
3410 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3411 if( lp->ExcludeUnencrypted ) {
3412 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3414 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3418 #endif // HCF_TYPE_AP
3420 /* Only provide the key if permissions allow */
3421 if( capable( CAP_NET_ADMIN )) {
3422 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3423 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3425 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3429 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3430 lp->DefaultKeys.key[index].key );
3433 } // wl_wext_event_encode
3434 /*============================================================================*/
3439 /*******************************************************************************
3440 * wl_wext_event_ap()
3441 *******************************************************************************
3445 * This function is used to send an event that the device has been
3446 * associated to a new AP.
3451 * dev - the network device for which this event is to be issued
3457 ******************************************************************************/
3458 void wl_wext_event_ap( struct net_device *dev )
3460 union iwreq_data wrqu;
3461 struct wl_private *lp = wl_priv(dev);
3463 /*------------------------------------------------------------------------*/
3466 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3467 this event BEFORE sending the association event, as there are timing
3468 issues with the hostap supplicant. The supplicant will attempt to process
3469 an EAPOL-Key frame from an AP before receiving this information, which
3470 is required for a proper processed frame. */
3471 wl_wext_event_assoc_ie( dev );
3474 lp->ltvRecord.typ = CFG_CUR_BSSID;
3475 lp->ltvRecord.len = 4;
3477 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3478 if( status == HCF_SUCCESS ) {
3479 memset( &wrqu, 0, sizeof( wrqu ));
3481 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3483 wrqu.addr.sa_family = ARPHRD_ETHER;
3485 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3489 } // wl_wext_event_ap
3490 /*============================================================================*/
3494 /*******************************************************************************
3495 * wl_wext_event_scan_complete()
3496 *******************************************************************************
3500 * This function is used to send an event that a request for a network scan
3506 * dev - the network device for which this event is to be issued
3512 ******************************************************************************/
3513 void wl_wext_event_scan_complete( struct net_device *dev )
3515 union iwreq_data wrqu;
3516 /*------------------------------------------------------------------------*/
3519 memset( &wrqu, 0, sizeof( wrqu ));
3521 wrqu.addr.sa_family = ARPHRD_ETHER;
3522 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3525 } // wl_wext_event_scan_complete
3526 /*============================================================================*/
3531 /*******************************************************************************
3532 * wl_wext_event_new_sta()
3533 *******************************************************************************
3537 * This function is used to send an event that an AP has registered a new
3543 * dev - the network device for which this event is to be issued
3549 ******************************************************************************/
3550 void wl_wext_event_new_sta( struct net_device *dev )
3552 union iwreq_data wrqu;
3553 /*------------------------------------------------------------------------*/
3556 memset( &wrqu, 0, sizeof( wrqu ));
3558 /* Send the station's mac address here */
3559 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3560 wrqu.addr.sa_family = ARPHRD_ETHER;
3561 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3564 } // wl_wext_event_new_sta
3565 /*============================================================================*/
3570 /*******************************************************************************
3571 * wl_wext_event_expired_sta()
3572 *******************************************************************************
3576 * This function is used to send an event that an AP has deregistered a
3582 * dev - the network device for which this event is to be issued
3588 ******************************************************************************/
3589 void wl_wext_event_expired_sta( struct net_device *dev )
3591 union iwreq_data wrqu;
3592 /*------------------------------------------------------------------------*/
3595 memset( &wrqu, 0, sizeof( wrqu ));
3597 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3598 wrqu.addr.sa_family = ARPHRD_ETHER;
3599 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3602 } // wl_wext_event_expired_sta
3603 /*============================================================================*/
3608 /*******************************************************************************
3609 * wl_wext_event_mic_failed()
3610 *******************************************************************************
3614 * This function is used to send an event that MIC calculations failed.
3619 * dev - the network device for which this event is to be issued
3625 ******************************************************************************/
3626 void wl_wext_event_mic_failed( struct net_device *dev )
3628 union iwreq_data wrqu;
3629 struct wl_private *lp = wl_priv(dev);
3630 struct iw_michaelmicfailure wxmic;
3634 WVLAN_RX_WMP_HDR *hdr;
3635 /*------------------------------------------------------------------------*/
3638 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3641 /* Cast the lookahead buffer into a RFS format */
3642 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3644 /* Cast the addresses to byte buffers, as in the above RFS they are word
3646 addr1 = (char *)hdr->address1;
3647 addr2 = (char *)hdr->address2;
3649 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3652 memset(&wrqu, 0, sizeof(wrqu));
3653 memset(&wxmic, 0, sizeof(wxmic));
3655 wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3656 wxmic.flags |= (addr1[0] & 1) ?
3657 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
3658 wxmic.src_addr.sa_family = ARPHRD_ETHER;
3659 memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3661 wrqu.data.length = sizeof(wxmic);
3662 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3665 } // wl_wext_event_mic_failed
3666 /*============================================================================*/
3671 /*******************************************************************************
3672 * wl_wext_event_assoc_ie()
3673 *******************************************************************************
3677 * This function is used to send an event containing the WPA-IE generated
3678 * by the firmware in an association request.
3683 * dev - the network device for which this event is to be issued
3689 ******************************************************************************/
3690 void wl_wext_event_assoc_ie( struct net_device *dev )
3692 union iwreq_data wrqu;
3693 struct wl_private *lp = wl_priv(dev);
3698 /*------------------------------------------------------------------------*/
3701 memset( &wrqu, 0, sizeof( wrqu ));
3703 /* Retrieve the Association Request IE */
3704 lp->ltvRecord.len = 45;
3705 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3707 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3708 if( status == HCF_SUCCESS )
3711 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3712 wpa_ie = wl_parse_wpa_ie( &data, &length );
3716 wrqu.data.length = wpa_ie[1] + 2;
3717 wireless_send_event(dev, IWEVASSOCREQIE,
3720 /* This bit is a hack. We send the respie
3721 * event at the same time */
3722 wireless_send_event(dev, IWEVASSOCRESPIE,
3728 } // wl_wext_event_assoc_ie
3729 /*============================================================================*/
3730 /* Structures to export the Wireless Handlers */
3732 static const iw_handler wl_handler[] =
3734 IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
3735 IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
3736 IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
3737 IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
3738 IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
3739 IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
3740 IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
3741 IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
3742 IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
3743 IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
3744 IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
3745 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3746 IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
3748 IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
3749 IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
3750 IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
3751 IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
3752 IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
3753 IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
3754 IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
3755 IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
3756 IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
3757 IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
3758 IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
3759 IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
3760 IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
3761 IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
3762 IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
3763 IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
3764 IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
3765 IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3766 IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
3769 static const iw_handler wl_private_handler[] =
3770 { /* SIOCIWFIRSTPRIV + */
3771 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3772 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3773 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3774 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3775 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3776 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3777 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3781 struct iw_priv_args wl_priv_args[] = {
3782 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3783 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3784 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3785 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3786 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3787 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3788 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3792 const struct iw_handler_def wl_iw_handler_def =
3794 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3795 .private = (iw_handler *) wl_private_handler,
3796 .private_args = (struct iw_priv_args *) wl_priv_args,
3797 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3798 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3799 .standard = (iw_handler *) wl_handler,
3800 .get_wireless_stats = wl_get_wireless_stats,