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)
164 if (!is_broadcast_ether_addr(addr)) {
166 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
167 memcpy(<v->u.u8[0], addr, ETH_ALEN);
173 /* Clear the Group TKIP keys by index */
175 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
176 ltv->u.u16[0] = cpu_to_le16(key_idx);
186 /* Set the WEP keys in the wl_private structure */
187 static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
188 u8 *key, size_t key_len,
189 bool enable, bool set_tx)
191 hcf_8 encryption_state = lp->EnableEncryption;
192 int tk = lp->TransmitKeyID - 1; /* current key */
195 /* Is encryption supported? */
196 if (!wl_has_wep(&(lp->hcfCtx))) {
197 DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
202 DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
205 /* Check the size of the key */
210 /* Check the index */
211 if ((key_idx < 0) || (key_idx >= MAX_KEYS))
215 memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
217 /* Copy the key in the driver */
218 memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
221 lp->DefaultKeys.key[key_idx].len = key_len;
223 DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
224 DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
225 lp->DefaultKeys.key[key_idx].key,
226 lp->DefaultKeys.key[key_idx].len, key_idx);
228 /* Enable WEP (if possible) */
229 if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
230 lp->EnableEncryption = 1;
235 /* Do we want to just set the current transmit key? */
236 if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
237 DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
238 lp->DefaultKeys.key[key_idx].len);
240 if (lp->DefaultKeys.key[key_idx].len > 0) {
241 lp->TransmitKeyID = key_idx + 1;
242 lp->EnableEncryption = 1;
244 DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
251 DBG_WARNING(DbgInfo, "Invalid Key length\n");
258 lp->EnableEncryption = 1;
259 lp->wext_enc = IW_ENCODE_ALG_WEP;
261 lp->EnableEncryption = 0; /* disable encryption */
262 lp->wext_enc = IW_ENCODE_ALG_NONE;
265 DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
266 DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
267 DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
269 /* Write the changes to the card */
271 DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
274 if (lp->EnableEncryption == encryption_state) {
276 /* Dynamic WEP key update */
280 /* To switch encryption on/off, soft reset is
290 /*******************************************************************************
292 *******************************************************************************
301 * wrq - the wireless request buffer
307 ******************************************************************************/
308 static int wireless_commit(struct net_device *dev,
309 struct iw_request_info *info,
310 union iwreq_data *rqu, char *extra)
312 struct wl_private *lp = wl_priv(dev);
316 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
321 wl_lock( lp, &flags );
323 wl_act_int_off( lp );
329 wl_unlock(lp, &flags);
334 /*============================================================================*/
339 /*******************************************************************************
340 * wireless_get_protocol()
341 *******************************************************************************
345 * Returns a vendor-defined string that should identify the wireless
350 * wrq - the wireless request buffer
356 ******************************************************************************/
357 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
359 /* Originally, the driver was placing the string "Wireless" here. However,
360 the wireless extensions (/linux/wireless.h) indicate this string should
361 describe the wireless protocol. */
363 strcpy(name, "IEEE 802.11b");
366 } // wireless_get_protocol
367 /*============================================================================*/
372 /*******************************************************************************
373 * wireless_set_frequency()
374 *******************************************************************************
378 * Sets the frequency (channel) on which the card should Tx/Rx.
382 * wrq - the wireless request buffer
383 * lp - the device's private adapter structure
388 * errno value otherwise
390 ******************************************************************************/
391 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
393 struct wl_private *lp = wl_priv(dev);
398 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
403 if( !capable( CAP_NET_ADMIN )) {
409 /* If frequency specified, look up channel */
411 int f = freq->m / 100000;
412 channel = wl_get_chan_from_freq( f );
416 /* Channel specified */
422 /* If the channel is an 802.11a channel, set Bit 8 */
424 channel = channel | 0x100;
428 wl_lock( lp, &flags );
430 wl_act_int_off( lp );
432 lp->Channel = channel;
435 /* Commit the adapter parameters */
438 /* Send an event that channel/freq has been set */
439 wl_wext_event_freq( lp->dev );
443 wl_unlock(lp, &flags);
447 } // wireless_set_frequency
448 /*============================================================================*/
453 /*******************************************************************************
454 * wireless_get_frequency()
455 *******************************************************************************
459 * Gets the frequency (channel) on which the card is Tx/Rx.
463 * wrq - the wireless request buffer
464 * lp - the device's private adapter structure
470 ******************************************************************************/
471 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
474 struct wl_private *lp = wl_priv(dev);
478 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
483 wl_lock( lp, &flags );
485 wl_act_int_off( lp );
487 lp->ltvRecord.len = 2;
488 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
490 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
491 if( ret == HCF_SUCCESS ) {
492 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
494 freq->m = wl_get_freq_from_chan( channel ) * 100000;
500 wl_unlock(lp, &flags);
502 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
506 } // wireless_get_frequency
507 /*============================================================================*/
512 /*******************************************************************************
513 * wireless_get_range()
514 *******************************************************************************
518 * This function is used to provide misc info and statistics about the
523 * wrq - the wireless request buffer
524 * lp - the device's private adapter structure
529 * errno value otherwise
531 ******************************************************************************/
532 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
534 struct wl_private *lp = wl_priv(dev);
536 struct iw_range *range = (struct iw_range *) extra;
543 /* Set range information */
544 data->length = sizeof(struct iw_range);
545 memset(range, 0, sizeof(struct iw_range));
547 wl_lock( lp, &flags );
549 wl_act_int_off( lp );
551 /* Set range information */
552 memset( range, 0, sizeof( struct iw_range ));
555 /* Get the current transmit rate from the adapter */
556 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
557 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
559 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
560 if( status != HCF_SUCCESS ) {
561 /* Recovery action: reset and retry up to 10 times */
562 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
567 /* Holding the lock too long, makes a gap to allow other processes */
568 wl_unlock(lp, &flags);
569 wl_lock( lp, &flags );
571 status = wl_reset( dev );
572 if ( status != HCF_SUCCESS ) {
573 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
579 /* Holding the lock too long, makes a gap to allow other processes */
580 wl_unlock(lp, &flags);
581 wl_lock( lp, &flags );
586 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
592 /* Holding the lock too long, makes a gap to allow other processes */
593 wl_unlock(lp, &flags);
594 wl_lock( lp, &flags );
596 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
598 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
601 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
604 // NWID - NOT SUPPORTED
607 /* Channel/Frequency Info */
608 range->num_channels = RADIO_CHANNELS;
611 /* Signal Level Thresholds */
612 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
616 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
618 /* If the value returned in /proc/net/wireless is greater than the maximum range,
619 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
620 it requires a bit of contorsion... */
622 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
623 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
626 /* Set available rates */
627 range->num_bitrates = 0;
629 lp->ltvRecord.len = 6;
630 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
632 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
633 if( status == HCF_SUCCESS ) {
634 for( count = 0; count < MAX_RATES; count++ )
635 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
636 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
637 range->num_bitrates++;
640 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
645 /* RTS Threshold info */
646 range->min_rts = MIN_RTS_BYTES;
647 range->max_rts = MAX_RTS_BYTES;
649 // Frag Threshold info - NOT SUPPORTED
651 // Power Management info - NOT SUPPORTED
655 /* Holding the lock too long, makes a gap to allow other processes */
656 wl_unlock(lp, &flags);
657 wl_lock( lp, &flags );
659 /* Is WEP supported? */
661 if( wl_has_wep( &( lp->hcfCtx ))) {
662 /* WEP: RC4 40 bits */
663 range->encoding_size[0] = MIN_KEY_SIZE;
666 range->encoding_size[1] = MAX_KEY_SIZE;
667 range->num_encoding_sizes = 2;
668 range->max_encoding_tokens = MAX_KEYS;
672 range->txpower_capa = IW_TXPOW_MWATT;
673 range->num_txpower = 1;
674 range->txpower[0] = RADIO_TX_POWER_MWATT;
676 /* Wireless Extension Info */
677 range->we_version_compiled = WIRELESS_EXT;
678 range->we_version_source = WIRELESS_SUPPORT;
680 // Retry Limits and Lifetime - NOT SUPPORTED
682 /* Holding the lock too long, makes a gap to allow other processes */
683 wl_unlock(lp, &flags);
684 wl_lock( lp, &flags );
686 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
687 wl_wireless_stats( lp->dev );
688 range->avg_qual = lp->wstats.qual;
689 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
691 /* Event capability (kernel + driver) */
692 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
693 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
694 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
695 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
696 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
697 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
698 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
699 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
701 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
702 range->scan_capa = IW_SCAN_CAPA_NONE;
707 wl_unlock(lp, &flags);
710 } // wireless_get_range
711 /*============================================================================*/
714 /*******************************************************************************
715 * wireless_get_bssid()
716 *******************************************************************************
720 * Gets the BSSID the wireless device is currently associated with.
724 * wrq - the wireless request buffer
725 * lp - the device's private adapter structure
730 * errno value otherwise
732 ******************************************************************************/
733 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
735 struct wl_private *lp = wl_priv(dev);
738 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
740 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
742 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
747 wl_lock( lp, &flags );
749 wl_act_int_off( lp );
751 ap_addr->sa_family = ARPHRD_ETHER;
753 /* Assume AP mode here, which means the BSSID is our own MAC address. In
754 STA mode, this address will be overwritten with the actual BSSID using
756 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
759 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
760 //;?should we return an error status in AP mode
762 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
763 /* Get Current BSSID */
764 lp->ltvRecord.typ = CFG_CUR_BSSID;
765 lp->ltvRecord.len = 4;
766 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
768 if( status == HCF_SUCCESS ) {
769 /* Copy info into sockaddr struct */
770 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
776 #endif // (HCF_TYPE) & HCF_TYPE_STA
780 wl_unlock(lp, &flags);
784 } // wireless_get_bssid
785 /*============================================================================*/
790 /*******************************************************************************
791 * wireless_get_ap_list()
792 *******************************************************************************
796 * Gets the results of a network scan.
800 * wrq - the wireless request buffer
801 * lp - the device's private adapter structure
806 * errno value otherwise
808 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
809 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
810 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
812 ******************************************************************************/
813 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
815 struct wl_private *lp = wl_priv(dev);
821 struct sockaddr *hwa = NULL;
822 struct iw_quality *qual = NULL;
824 ScanResult *p = &lp->scan_results;
826 ProbeResult *p = &lp->probe_results;
829 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
834 wl_lock( lp, &flags );
836 wl_act_int_off( lp );
838 /* Set the completion state to FALSE */
839 lp->scan_results.scan_complete = FALSE;
840 lp->probe_results.scan_complete = FALSE;
841 /* Channels to scan */
842 lp->ltvRecord.len = 2;
843 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
844 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
845 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
846 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
848 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
849 disassociate from the network we are currently on */
850 lp->ltvRecord.len = 2;
851 lp->ltvRecord.typ = CFG_SCAN_SSID;
852 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
853 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
854 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
856 /* Initiate the scan */
858 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
860 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
865 //;? unlock? what about the access to lp below? is it broken?
866 wl_unlock(lp, &flags);
868 if( ret == HCF_SUCCESS ) {
869 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
870 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
871 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
872 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
873 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
876 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
877 other things in the meantime, This prevents system lockups by
878 giving some time back to the kernel */
879 for( count = 0; count < 100; count ++ ) {
888 if ( ret != HCF_SUCCESS ) {
889 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
891 num_aps = (*p)/*lp->probe_results*/.num_aps;
892 if (num_aps > IW_MAX_AP) {
895 data->length = num_aps;
896 hwa = (struct sockaddr *)extra;
897 qual = (struct iw_quality *) extra +
898 ( sizeof( struct sockaddr ) * num_aps );
900 /* This flag is used to tell the user if we provide quality
901 information. Since we provide signal/noise levels but no
902 quality info on a scan, this is set to 0. Setting to 1 and
903 providing a quality of 0 produces weird results. If we ever
904 provide quality (or can calculate it), this can be changed */
907 for( count = 0; count < num_aps; count++ ) {
909 memcpy( hwa[count].sa_data,
910 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
911 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
912 DBG_PRINT("BSSID: %pM\n",
913 (*p).ProbeTable[count].BSSID);
914 memcpy( hwa[count].sa_data,
915 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
918 /* Once the data is copied to the wireless struct, invalidate the
919 scan result to initiate a rescan on the next request */
920 (*p)/*lp->probe_results*/.scan_complete = FALSE;
921 /* Send the wireless event that the scan has completed, just in case
923 wl_wext_event_scan_complete( lp->dev );
928 } // wireless_get_ap_list
929 /*============================================================================*/
934 /*******************************************************************************
935 * wireless_set_sensitivity()
936 *******************************************************************************
940 * Sets the sensitivity (distance between APs) of the wireless card.
944 * wrq - the wireless request buffer
945 * lp - the device's private adapter structure
950 * errno value otherwise
952 ******************************************************************************/
953 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
955 struct wl_private *lp = wl_priv(dev);
958 int dens = sens->value;
960 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
965 if(( dens < 1 ) || ( dens > 3 )) {
970 wl_lock( lp, &flags );
972 wl_act_int_off( lp );
974 lp->DistanceBetweenAPs = dens;
979 wl_unlock(lp, &flags);
983 } // wireless_set_sensitivity
984 /*============================================================================*/
989 /*******************************************************************************
990 * wireless_get_sensitivity()
991 *******************************************************************************
995 * Gets the sensitivity (distance between APs) of the wireless card.
999 * wrq - the wireless request buffer
1000 * lp - the device's private adapter structure
1005 * errno value otherwise
1007 ******************************************************************************/
1008 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1010 struct wl_private *lp = wl_priv(dev);
1013 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1018 /* not worth locking ... */
1019 sens->value = lp->DistanceBetweenAPs;
1020 sens->fixed = 0; /* auto */
1023 } // wireless_get_sensitivity
1024 /*============================================================================*/
1029 /*******************************************************************************
1030 * wireless_set_essid()
1031 *******************************************************************************
1035 * Sets the ESSID (network name) that the wireless device should associate
1040 * wrq - the wireless request buffer
1041 * lp - the device's private adapter structure
1046 * errno value otherwise
1048 ******************************************************************************/
1049 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
1051 struct wl_private *lp = wl_priv(dev);
1052 unsigned long flags;
1055 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1060 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN) {
1065 wl_lock( lp, &flags );
1067 wl_act_int_off( lp );
1069 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
1071 /* data->flags is zero to ask for "any" */
1072 if( data->flags == 0 ) {
1073 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
1074 * ;?but there ain't no STAP anymore*/
1075 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
1076 strcpy( lp->NetworkName, "ANY" );
1078 //strcpy( lp->NetworkName, "ANY" );
1079 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
1082 memcpy( lp->NetworkName, ssid, data->length );
1085 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1087 /* Commit the adapter parameters */
1090 /* Send an event that ESSID has been set */
1091 wl_wext_event_essid( lp->dev );
1093 wl_act_int_on( lp );
1095 wl_unlock(lp, &flags);
1099 } // wireless_set_essid
1100 /*============================================================================*/
1105 /*******************************************************************************
1106 * wireless_get_essid()
1107 *******************************************************************************
1111 * Gets the ESSID (network name) that the wireless device is associated
1116 * wrq - the wireless request buffer
1117 * lp - the device's private adapter structure
1122 * errno value otherwise
1124 ******************************************************************************/
1125 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1128 struct wl_private *lp = wl_priv(dev);
1129 unsigned long flags;
1134 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1139 wl_lock( lp, &flags );
1141 wl_act_int_off( lp );
1143 /* Get the desired network name */
1144 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1147 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1148 //;?should we return an error status in AP mode
1150 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1155 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1156 //;?should we restore this to allow smaller memory footprint
1158 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1159 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1165 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1166 if( status == HCF_SUCCESS ) {
1167 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1169 /* Endian translate the string length */
1170 pName->length = CNV_LITTLE_TO_INT( pName->length );
1172 /* Copy the information into the user buffer */
1173 data->length = pName->length;
1175 if( pName->length < HCF_MAX_NAME_LEN ) {
1176 pName->name[pName->length] = '\0';
1182 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1183 //;?should we return an error status in AP mode
1185 /* if desired is null ("any"), return current or "any" */
1186 if( pName->name[0] == '\0' ) {
1187 /* Get the current network name */
1188 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1189 lp->ltvRecord.typ = CFG_CUR_SSID;
1191 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1193 if( status == HCF_SUCCESS ) {
1194 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1196 /* Endian translate the string length */
1197 pName->length = CNV_LITTLE_TO_INT( pName->length );
1199 /* Copy the information into the user buffer */
1200 data->length = pName->length;
1210 if (pName->length > IW_ESSID_MAX_SIZE) {
1215 memcpy(essid, pName->name, pName->length);
1222 wl_act_int_on( lp );
1224 wl_unlock(lp, &flags);
1228 } // wireless_get_essid
1229 /*============================================================================*/
1234 /*******************************************************************************
1235 * wireless_set_encode()
1236 *******************************************************************************
1240 * Sets the encryption keys and status (enable or disable).
1244 * wrq - the wireless request buffer
1245 * lp - the device's private adapter structure
1250 * errno value otherwise
1252 ******************************************************************************/
1253 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1255 struct wl_private *lp = wl_priv(dev);
1256 unsigned long flags;
1257 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1261 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
1266 if (erq->flags & IW_ENCODE_DISABLED)
1269 wl_lock(lp, &flags);
1273 ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1276 /* Send an event that Encryption has been set */
1278 wl_wext_event_encode(dev);
1282 wl_unlock(lp, &flags);
1288 /*******************************************************************************
1289 * wireless_get_encode()
1290 *******************************************************************************
1294 * Gets the encryption keys and status.
1298 * wrq - the wireless request buffer
1299 * lp - the device's private adapter structure
1304 * errno value otherwise
1306 ******************************************************************************/
1307 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1310 struct wl_private *lp = wl_priv(dev);
1311 unsigned long flags;
1315 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1317 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1322 /* Only super-user can see WEP key */
1323 if( !capable( CAP_NET_ADMIN )) {
1328 wl_lock( lp, &flags );
1330 wl_act_int_off( lp );
1332 /* Is it supported? */
1333 if( !wl_has_wep( &( lp->hcfCtx ))) {
1338 /* Basic checking */
1339 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1345 if( lp->EnableEncryption == 0 ) {
1346 erq->flags |= IW_ENCODE_DISABLED;
1349 /* Which key do we want */
1350 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1351 index = lp->TransmitKeyID - 1;
1354 erq->flags |= index + 1;
1356 /* Copy the key to the user buffer */
1357 erq->length = lp->DefaultKeys.key[index].len;
1359 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1363 wl_act_int_on( lp );
1365 wl_unlock(lp, &flags);
1369 } // wireless_get_encode
1370 /*============================================================================*/
1375 /*******************************************************************************
1376 * wireless_set_nickname()
1377 *******************************************************************************
1381 * Sets the nickname, or station name, of the wireless device.
1385 * wrq - the wireless request buffer
1386 * lp - the device's private adapter structure
1391 * errno value otherwise
1393 ******************************************************************************/
1394 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1396 struct wl_private *lp = wl_priv(dev);
1397 unsigned long flags;
1400 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1405 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1406 if( !capable(CAP_NET_ADMIN )) {
1412 /* Validate the new value */
1413 if(data->length > HCF_MAX_NAME_LEN) {
1418 wl_lock( lp, &flags );
1420 wl_act_int_off( lp );
1422 memset( lp->StationName, 0, sizeof( lp->StationName ));
1424 memcpy( lp->StationName, nickname, data->length );
1426 /* Commit the adapter parameters */
1429 wl_act_int_on( lp );
1431 wl_unlock(lp, &flags);
1435 } // wireless_set_nickname
1436 /*============================================================================*/
1441 /*******************************************************************************
1442 * wireless_get_nickname()
1443 *******************************************************************************
1447 * Gets the nickname, or station name, of the wireless device.
1451 * wrq - the wireless request buffer
1452 * lp - the device's private adapter structure
1457 * errno value otherwise
1459 ******************************************************************************/
1460 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1462 struct wl_private *lp = wl_priv(dev);
1463 unsigned long flags;
1468 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1473 wl_lock( lp, &flags );
1475 wl_act_int_off( lp );
1477 /* Get the current station name */
1478 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1479 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1481 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1483 if( status == HCF_SUCCESS ) {
1484 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1486 /* Endian translate the length */
1487 pName->length = CNV_LITTLE_TO_INT( pName->length );
1489 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1492 /* Copy the information into the user buffer */
1493 data->length = pName->length;
1494 memcpy(nickname, pName->name, pName->length);
1500 wl_act_int_on( lp );
1502 wl_unlock(lp, &flags);
1506 } // wireless_get_nickname
1507 /*============================================================================*/
1512 /*******************************************************************************
1513 * wireless_set_porttype()
1514 *******************************************************************************
1518 * Sets the port type of the wireless device.
1522 * wrq - the wireless request buffer
1523 * lp - the device's private adapter structure
1528 * errno value otherwise
1530 ******************************************************************************/
1531 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1533 struct wl_private *lp = wl_priv(dev);
1534 unsigned long flags;
1539 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1544 wl_lock( lp, &flags );
1546 wl_act_int_off( lp );
1548 /* Validate the new value */
1552 /* When user requests ad-hoc, set IBSS mode! */
1556 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1564 /* Both automatic and infrastructure set port to BSS/STA mode */
1568 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1573 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1575 case IW_MODE_MASTER:
1577 /* Set BSS/AP mode */
1581 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1585 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1595 if( portType != 0 ) {
1596 /* Only do something if there is a mode change */
1597 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1598 lp->PortType = portType;
1599 lp->CreateIBSS = createIBSS;
1601 /* Commit the adapter parameters */
1604 /* Send an event that mode has been set */
1605 wl_wext_event_mode( lp->dev );
1609 wl_act_int_on( lp );
1611 wl_unlock(lp, &flags);
1615 } // wireless_set_porttype
1616 /*============================================================================*/
1621 /*******************************************************************************
1622 * wireless_get_porttype()
1623 *******************************************************************************
1627 * Gets the port type of the wireless device.
1631 * wrq - the wireless request buffer
1632 * lp - the device's private adapter structure
1637 * errno value otherwise
1639 ******************************************************************************/
1640 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1643 struct wl_private *lp = wl_priv(dev);
1644 unsigned long flags;
1649 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1654 wl_lock( lp, &flags );
1656 wl_act_int_off( lp );
1658 /* Get the current port type */
1659 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1660 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1662 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1664 if( status == HCF_SUCCESS ) {
1665 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1667 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1669 switch( *pPortType ) {
1673 #if (HCF_TYPE) & HCF_TYPE_AP
1675 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1676 *mode = IW_MODE_MASTER;
1678 *mode = IW_MODE_INFRA;
1683 *mode = IW_MODE_INFRA;
1685 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1688 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1689 *mode = IW_MODE_MASTER;
1691 if( lp->CreateIBSS ) {
1692 *mode = IW_MODE_ADHOC;
1694 *mode = IW_MODE_INFRA;
1702 *mode = IW_MODE_ADHOC;
1713 wl_act_int_on( lp );
1715 wl_unlock(lp, &flags);
1719 } // wireless_get_porttype
1720 /*============================================================================*/
1725 /*******************************************************************************
1726 * wireless_set_power()
1727 *******************************************************************************
1731 * Sets the power management settings of the wireless device.
1735 * wrq - the wireless request buffer
1736 * lp - the device's private adapter structure
1741 * errno value otherwise
1743 ******************************************************************************/
1744 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1746 struct wl_private *lp = wl_priv(dev);
1747 unsigned long flags;
1750 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1755 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1757 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1758 if( !capable( CAP_NET_ADMIN )) {
1764 wl_lock( lp, &flags );
1766 wl_act_int_off( lp );
1768 /* Set the power management state based on the 'disabled' value */
1769 if( wrq->disabled ) {
1775 /* Commit the adapter parameters */
1778 wl_act_int_on( lp );
1780 wl_unlock(lp, &flags);
1784 } // wireless_set_power
1785 /*============================================================================*/
1790 /*******************************************************************************
1791 * wireless_get_power()
1792 *******************************************************************************
1796 * Gets the power management settings of the wireless device.
1800 * wrq - the wireless request buffer
1801 * lp - the device's private adapter structure
1806 * errno value otherwise
1808 ******************************************************************************/
1809 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1812 struct wl_private *lp = wl_priv(dev);
1813 unsigned long flags;
1816 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1821 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1823 wl_lock( lp, &flags );
1825 wl_act_int_off( lp );
1830 if( lp->PMEnabled ) {
1836 wl_act_int_on( lp );
1838 wl_unlock(lp, &flags);
1842 } // wireless_get_power
1843 /*============================================================================*/
1848 /*******************************************************************************
1849 * wireless_get_tx_power()
1850 *******************************************************************************
1854 * Gets the transmit power of the wireless device's radio.
1858 * wrq - the wireless request buffer
1859 * lp - the device's private adapter structure
1864 * errno value otherwise
1866 ******************************************************************************/
1867 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1869 struct wl_private *lp = wl_priv(dev);
1870 unsigned long flags;
1873 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1878 wl_lock( lp, &flags );
1880 wl_act_int_off( lp );
1882 #ifdef USE_POWER_DBM
1883 rrq->value = RADIO_TX_POWER_DBM;
1884 rrq->flags = IW_TXPOW_DBM;
1886 rrq->value = RADIO_TX_POWER_MWATT;
1887 rrq->flags = IW_TXPOW_MWATT;
1892 wl_act_int_on( lp );
1894 wl_unlock(lp, &flags);
1898 } // wireless_get_tx_power
1899 /*============================================================================*/
1904 /*******************************************************************************
1905 * wireless_set_rts_threshold()
1906 *******************************************************************************
1910 * Sets the RTS threshold for the wireless card.
1914 * wrq - the wireless request buffer
1915 * lp - the device's private adapter structure
1920 * errno value otherwise
1922 ******************************************************************************/
1923 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
1926 struct wl_private *lp = wl_priv(dev);
1927 unsigned long flags;
1928 int rthr = rts->value;
1930 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1935 if(rts->fixed == 0) {
1940 if( rts->disabled ) {
1944 if(( rthr < 256 ) || ( rthr > 2347 )) {
1949 wl_lock( lp, &flags );
1951 wl_act_int_off( lp );
1953 lp->RTSThreshold = rthr;
1957 wl_act_int_on( lp );
1959 wl_unlock(lp, &flags);
1963 } // wireless_set_rts_threshold
1964 /*============================================================================*/
1969 /*******************************************************************************
1970 * wireless_get_rts_threshold()
1971 *******************************************************************************
1975 * Gets the RTS threshold for the wireless card.
1979 * wrq - the wireless request buffer
1980 * lp - the device's private adapter structure
1985 * errno value otherwise
1987 ******************************************************************************/
1988 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
1991 struct wl_private *lp = wl_priv(dev);
1992 unsigned long flags;
1994 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1999 wl_lock( lp, &flags );
2001 wl_act_int_off( lp );
2003 rts->value = lp->RTSThreshold;
2005 rts->disabled = ( rts->value == 2347 );
2009 wl_act_int_on( lp );
2011 wl_unlock(lp, &flags);
2015 } // wireless_get_rts_threshold
2016 /*============================================================================*/
2022 /*******************************************************************************
2023 * wireless_set_rate()
2024 *******************************************************************************
2028 * Set the default data rate setting used by the wireless device.
2032 * wrq - the wireless request buffer
2033 * lp - the device's private adapter structure
2038 * errno value otherwise
2040 ******************************************************************************/
2041 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2043 struct wl_private *lp = wl_priv(dev);
2044 unsigned long flags;
2051 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2056 wl_lock( lp, &flags );
2058 wl_act_int_off( lp );
2062 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2063 if Bit 9 is set in the current channel RID */
2064 lp->ltvRecord.len = 2;
2065 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2067 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2069 if( status == HCF_SUCCESS ) {
2070 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2072 DBG_PRINT( "Index: %d\n", index );
2074 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2079 if( rrq->value > 0 &&
2080 rrq->value <= 1 * MEGABIT ) {
2081 lp->TxRateControl[index] = 0x0001;
2083 else if( rrq->value > 1 * MEGABIT &&
2084 rrq->value <= 2 * MEGABIT ) {
2085 if( rrq->fixed == 1 ) {
2086 lp->TxRateControl[index] = 0x0002;
2088 lp->TxRateControl[index] = 0x0003;
2091 else if( rrq->value > 2 * MEGABIT &&
2092 rrq->value <= 5 * MEGABIT ) {
2093 if( rrq->fixed == 1 ) {
2094 lp->TxRateControl[index] = 0x0004;
2096 lp->TxRateControl[index] = 0x0007;
2099 else if( rrq->value > 5 * MEGABIT &&
2100 rrq->value <= 6 * MEGABIT ) {
2101 if( rrq->fixed == 1 ) {
2102 lp->TxRateControl[index] = 0x0010;
2104 lp->TxRateControl[index] = 0x0017;
2107 else if( rrq->value > 6 * MEGABIT &&
2108 rrq->value <= 9 * MEGABIT ) {
2109 if( rrq->fixed == 1 ) {
2110 lp->TxRateControl[index] = 0x0020;
2112 lp->TxRateControl[index] = 0x0037;
2115 else if( rrq->value > 9 * MEGABIT &&
2116 rrq->value <= 11 * MEGABIT ) {
2117 if( rrq->fixed == 1 ) {
2118 lp->TxRateControl[index] = 0x0008;
2120 lp->TxRateControl[index] = 0x003F;
2123 else if( rrq->value > 11 * MEGABIT &&
2124 rrq->value <= 12 * MEGABIT ) {
2125 if( rrq->fixed == 1 ) {
2126 lp->TxRateControl[index] = 0x0040;
2128 lp->TxRateControl[index] = 0x007F;
2131 else if( rrq->value > 12 * MEGABIT &&
2132 rrq->value <= 18 * MEGABIT ) {
2133 if( rrq->fixed == 1 ) {
2134 lp->TxRateControl[index] = 0x0080;
2136 lp->TxRateControl[index] = 0x00FF;
2139 else if( rrq->value > 18 * MEGABIT &&
2140 rrq->value <= 24 * MEGABIT ) {
2141 if( rrq->fixed == 1 ) {
2142 lp->TxRateControl[index] = 0x0100;
2144 lp->TxRateControl[index] = 0x01FF;
2147 else if( rrq->value > 24 * MEGABIT &&
2148 rrq->value <= 36 * MEGABIT ) {
2149 if( rrq->fixed == 1 ) {
2150 lp->TxRateControl[index] = 0x0200;
2152 lp->TxRateControl[index] = 0x03FF;
2155 else if( rrq->value > 36 * MEGABIT &&
2156 rrq->value <= 48 * MEGABIT ) {
2157 if( rrq->fixed == 1 ) {
2158 lp->TxRateControl[index] = 0x0400;
2160 lp->TxRateControl[index] = 0x07FF;
2163 else if( rrq->value > 48 * MEGABIT &&
2164 rrq->value <= 54 * MEGABIT ) {
2165 if( rrq->fixed == 1 ) {
2166 lp->TxRateControl[index] = 0x0800;
2168 lp->TxRateControl[index] = 0x0FFF;
2171 else if( rrq->fixed == 0 ) {
2172 /* In this case, the user has not specified a bitrate, only the "auto"
2173 moniker. So, set to all supported rates */
2174 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2184 if( rrq->value > 0 &&
2185 rrq->value <= 1 * MEGABIT ) {
2186 lp->TxRateControl[0] = 1;
2188 else if( rrq->value > 1 * MEGABIT &&
2189 rrq->value <= 2 * MEGABIT ) {
2191 lp->TxRateControl[0] = 2;
2193 lp->TxRateControl[0] = 6;
2196 else if( rrq->value > 2 * MEGABIT &&
2197 rrq->value <= 5 * MEGABIT ) {
2199 lp->TxRateControl[0] = 4;
2201 lp->TxRateControl[0] = 7;
2204 else if( rrq->value > 5 * MEGABIT &&
2205 rrq->value <= 11 * MEGABIT ) {
2207 lp->TxRateControl[0] = 5;
2209 lp->TxRateControl[0] = 3;
2212 else if( rrq->fixed == 0 ) {
2213 /* In this case, the user has not specified a bitrate, only the "auto"
2214 moniker. So, set the rate to 11Mb auto */
2215 lp->TxRateControl[0] = 3;
2225 /* Commit the adapter parameters */
2230 wl_act_int_on( lp );
2232 wl_unlock(lp, &flags);
2236 } // wireless_set_rate
2237 /*============================================================================*/
2242 /*******************************************************************************
2243 * wireless_get_rate()
2244 *******************************************************************************
2248 * Get the default data rate setting used by the wireless device.
2252 * wrq - the wireless request buffer
2253 * lp - the device's private adapter structure
2258 * errno value otherwise
2260 ******************************************************************************/
2261 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2264 struct wl_private *lp = wl_priv(dev);
2265 unsigned long flags;
2270 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2275 wl_lock( lp, &flags );
2277 wl_act_int_off( lp );
2279 /* Get the current transmit rate from the adapter */
2280 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2281 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2283 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2285 if( status == HCF_SUCCESS ) {
2288 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2290 if( txRate & 0x0001 ) {
2293 else if( txRate & 0x0002 ) {
2296 else if( txRate & 0x0004 ) {
2299 else if( txRate & 0x0008 ) {
2302 else if( txRate & 0x00010 ) {
2305 else if( txRate & 0x00020 ) {
2308 else if( txRate & 0x00040 ) {
2311 else if( txRate & 0x00080 ) {
2314 else if( txRate & 0x00100 ) {
2317 else if( txRate & 0x00200 ) {
2320 else if( txRate & 0x00400 ) {
2323 else if( txRate & 0x00800 ) {
2329 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2333 rrq->value = txRate * MEGABIT;
2339 wl_act_int_on( lp );
2341 wl_unlock(lp, &flags);
2345 } // wireless_get_rate
2346 /*============================================================================*/
2351 #if 0 //;? Not used anymore
2352 /*******************************************************************************
2353 * wireless_get_private_interface()
2354 *******************************************************************************
2358 * Returns the Linux Wireless Extensions' compatible private interface of
2363 * wrq - the wireless request buffer
2364 * lp - the device's private adapter structure
2369 * errno value otherwise
2371 ******************************************************************************/
2372 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2376 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2381 if( wrq->u.data.pointer != NULL ) {
2382 struct iw_priv_args priv[] =
2384 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2385 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2386 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2387 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2388 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2389 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2392 /* Verify the user buffer */
2393 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2398 /* Copy the data into the user's buffer */
2399 wrq->u.data.length = NELEM( priv );
2400 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2405 } // wireless_get_private_interface
2406 /*============================================================================*/
2411 /*******************************************************************************
2412 * wireless_set_scan()
2413 *******************************************************************************
2417 * Instructs the driver to initiate a network scan.
2421 * wrq - the wireless request buffer
2422 * lp - the device's private adapter structure
2427 * errno value otherwise
2429 ******************************************************************************/
2430 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2432 struct wl_private *lp = wl_priv(dev);
2433 unsigned long flags;
2438 //;? Note: shows results as trace, returns always 0 unless BUSY
2440 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2445 wl_lock( lp, &flags );
2447 wl_act_int_off( lp );
2450 * This looks like a nice place to test if the HCF is still
2451 * communicating with the card. It seems that sometimes BAP_1
2452 * gets corrupted. By looking at the comments in HCF the
2453 * cause is still a mystery. Okay, the communication to the
2454 * card is dead, reset the card to revive.
2456 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2458 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2463 /* Set the completion state to FALSE */
2464 lp->probe_results.scan_complete = FALSE;
2467 /* Channels to scan */
2469 lp->ltvRecord.len = 5;
2470 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2471 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2472 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2473 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2474 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2476 lp->ltvRecord.len = 2;
2477 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2478 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2481 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2483 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2485 // Holding the lock too long, makes a gap to allow other processes
2486 wl_unlock(lp, &flags);
2487 wl_lock( lp, &flags );
2489 if( status != HCF_SUCCESS ) {
2493 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2496 // Holding the lock too long, makes a gap to allow other processes
2497 wl_unlock(lp, &flags);
2498 wl_lock( lp, &flags );
2504 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2505 disassociate from the network we are currently on */
2506 lp->ltvRecord.len = 18;
2507 lp->ltvRecord.typ = CFG_SCAN_SSID;
2508 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2509 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2511 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2513 // Holding the lock too long, makes a gap to allow other processes
2514 wl_unlock(lp, &flags);
2515 wl_lock( lp, &flags );
2517 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2519 /* Initiate the scan */
2520 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2521 retrieve probe response must always be used to support WPA */
2522 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2524 if( status == HCF_SUCCESS ) {
2525 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2527 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2530 wl_act_int_on( lp );
2532 wl_unlock(lp, &flags);
2536 } // wireless_set_scan
2537 /*============================================================================*/
2542 /*******************************************************************************
2543 * wireless_get_scan()
2544 *******************************************************************************
2548 * Instructs the driver to gather and return the results of a network scan.
2552 * wrq - the wireless request buffer
2553 * lp - the device's private adapter structure
2558 * errno value otherwise
2560 ******************************************************************************/
2561 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2563 struct wl_private *lp = wl_priv(dev);
2564 unsigned long flags;
2569 struct iw_event iwe;
2570 PROBE_RESP *probe_resp;
2575 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2580 wl_lock( lp, &flags );
2582 wl_act_int_off( lp );
2584 /* If the scan is not done, tell the calling process to try again later */
2585 if( !lp->probe_results.scan_complete ) {
2590 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2591 lp->probe_results.num_aps );
2594 buf_end = extra + IW_SCAN_MAX_DATA;
2596 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2597 /* Reference the probe response from the table */
2598 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2601 /* First entry MUST be the MAC address */
2602 memset( &iwe, 0, sizeof( iwe ));
2604 iwe.cmd = SIOCGIWAP;
2605 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2606 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2607 iwe.len = IW_EV_ADDR_LEN;
2609 buf = iwe_stream_add_event(info, buf, buf_end,
2610 &iwe, IW_EV_ADDR_LEN);
2612 /* Use the mode to indicate if it's a station or AP */
2613 /* Won't always be an AP if in IBSS mode */
2614 memset( &iwe, 0, sizeof( iwe ));
2616 iwe.cmd = SIOCGIWMODE;
2618 if( probe_resp->capability & CAPABILITY_IBSS ) {
2619 iwe.u.mode = IW_MODE_INFRA;
2621 iwe.u.mode = IW_MODE_MASTER;
2624 iwe.len = IW_EV_UINT_LEN;
2626 buf = iwe_stream_add_event(info, buf, buf_end,
2627 &iwe, IW_EV_UINT_LEN);
2629 /* Any quality information */
2630 memset(&iwe, 0, sizeof(iwe));
2633 iwe.u.qual.level = dbm(probe_resp->signal);
2634 iwe.u.qual.noise = dbm(probe_resp->silence);
2635 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2636 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2637 iwe.len = IW_EV_QUAL_LEN;
2639 buf = iwe_stream_add_event(info, buf, buf_end,
2640 &iwe, IW_EV_QUAL_LEN);
2643 /* ESSID information */
2644 if( probe_resp->rawData[1] > 0 ) {
2645 memset( &iwe, 0, sizeof( iwe ));
2647 iwe.cmd = SIOCGIWESSID;
2648 iwe.u.data.length = probe_resp->rawData[1];
2649 iwe.u.data.flags = 1;
2651 buf = iwe_stream_add_point(info, buf, buf_end,
2652 &iwe, &probe_resp->rawData[2]);
2656 /* Encryption Information */
2657 memset( &iwe, 0, sizeof( iwe ));
2659 iwe.cmd = SIOCGIWENCODE;
2660 iwe.u.data.length = 0;
2662 /* Check the capabilities field of the Probe Response to see if
2663 'privacy' is supported on the AP in question */
2664 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2665 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2667 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2670 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
2673 /* Frequency Info */
2674 memset( &iwe, 0, sizeof( iwe ));
2676 iwe.cmd = SIOCGIWFREQ;
2677 iwe.len = IW_EV_FREQ_LEN;
2678 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2681 buf = iwe_stream_add_event(info, buf, buf_end,
2682 &iwe, IW_EV_FREQ_LEN);
2685 /* Custom info (Beacon Interval) */
2686 memset( &iwe, 0, sizeof( iwe ));
2687 memset( msg, 0, sizeof( msg ));
2689 iwe.cmd = IWEVCUSTOM;
2690 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2691 iwe.u.data.length = strlen( msg );
2693 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
2700 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2701 if( wpa_ie != NULL ) {
2702 memset(&iwe, 0, sizeof(iwe));
2704 iwe.cmd = IWEVGENIE;
2705 iwe.u.data.length = wpa_ie_len;
2707 buf = iwe_stream_add_point(info, buf, buf_end,
2711 /* Add other custom info in formatted string format as needed... */
2714 data->length = buf - extra;
2718 wl_act_int_on( lp );
2720 wl_unlock(lp, &flags);
2724 } // wireless_get_scan
2725 /*============================================================================*/
2728 static const char * const auth_names[] = {
2729 "IW_AUTH_WPA_VERSION",
2730 "IW_AUTH_CIPHER_PAIRWISE",
2731 "IW_AUTH_CIPHER_GROUP",
2733 "IW_AUTH_TKIP_COUNTERMEASURES",
2734 "IW_AUTH_DROP_UNENCRYPTED",
2735 "IW_AUTH_80211_AUTH_ALG",
2736 "IW_AUTH_WPA_ENABLED",
2737 "IW_AUTH_RX_UNENCRYPTED_EAPOL",
2738 "IW_AUTH_ROAMING_CONTROL",
2739 "IW_AUTH_PRIVACY_INVOKED",
2740 "IW_AUTH_CIPHER_GROUP_MGMT",
2746 static int wireless_set_auth(struct net_device *dev,
2747 struct iw_request_info *info,
2748 struct iw_param *data, char *extra)
2750 struct wl_private *lp = wl_priv(dev);
2751 unsigned long flags;
2754 int iwa_idx = data->flags & IW_AUTH_INDEX;
2755 int iwa_val = data->value;
2757 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2762 wl_lock( lp, &flags );
2764 wl_act_int_off( lp );
2766 if (iwa_idx > IW_AUTH_MFP)
2767 iwa_idx = IW_AUTH_MFP + 1;
2768 DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
2770 case IW_AUTH_WPA_VERSION:
2771 /* We do support WPA */
2772 if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
2773 (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
2779 case IW_AUTH_WPA_ENABLED:
2780 DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
2782 lp->EnableEncryption = 2;
2784 lp->EnableEncryption = 0;
2786 /* Write straight to the card */
2788 ltv.typ = CFG_CNF_ENCRYPTION;
2789 ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
2790 ret = hcf_put_info(&lp->hcfCtx, (LTVP)<v);
2794 case IW_AUTH_TKIP_COUNTERMEASURES:
2796 /* Immediately disable card */
2797 lp->driverEnable = !iwa_val;
2798 if (lp->driverEnable)
2799 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2801 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2806 /* Management Frame Protection not supported.
2807 * Only fail if set to required.
2809 if (iwa_val == IW_AUTH_MFP_REQUIRED)
2815 case IW_AUTH_KEY_MGMT:
2817 /* Record required management suite.
2818 * Will take effect on next commit */
2820 lp->AuthKeyMgmtSuite = 4;
2822 lp->AuthKeyMgmtSuite = 0;
2827 case IW_AUTH_80211_AUTH_ALG:
2829 /* Just record whether open or shared is required.
2830 * Will take effect on next commit */
2833 if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
2834 lp->authentication = 1;
2835 else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
2836 lp->authentication = 0;
2841 case IW_AUTH_DROP_UNENCRYPTED:
2842 /* Only needed for AP */
2843 lp->ExcludeUnencrypted = iwa_val;
2847 case IW_AUTH_CIPHER_PAIRWISE:
2848 case IW_AUTH_CIPHER_GROUP:
2849 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2850 case IW_AUTH_ROAMING_CONTROL:
2851 case IW_AUTH_PRIVACY_INVOKED:
2852 /* Not used. May need to do something with
2853 * CIPHER_PAIRWISE and CIPHER_GROUP*/
2858 DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2859 /* return an error */
2864 wl_act_int_on( lp );
2866 wl_unlock(lp, &flags);
2870 } // wireless_set_auth
2871 /*============================================================================*/
2874 static void flush_tx(struct wl_private *lp)
2880 * Make sure that there is no data queued up in the firmware
2881 * before setting the TKIP keys. If this check is not
2882 * performed, some data may be sent out with incorrect MIC
2883 * and cause synchronization errors with the AP
2885 /* Check every 1ms for 100ms */
2886 for (count = 0; count < 100; count++) {
2890 ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
2893 hcf_get_info(&(lp->hcfCtx), (LTVP)<v);
2895 if (ltv.u.u16[0] == 0)
2900 DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
2904 static int wireless_set_encodeext(struct net_device *dev,
2905 struct iw_request_info *info,
2906 struct iw_point *erq, char *keybuf)
2908 struct wl_private *lp = wl_priv(dev);
2909 unsigned long flags;
2911 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
2913 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
2915 bool set_tx = false;
2917 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2922 if (erq->flags & IW_ENCODE_DISABLED) {
2923 ext->alg = IW_ENCODE_ALG_NONE;
2927 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2930 wl_lock(lp, &flags);
2934 memset(<v, 0, sizeof(ltv));
2937 case IW_ENCODE_ALG_TKIP:
2938 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
2940 if (sizeof(ext->rx_seq) != 8) {
2941 DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
2946 ret = hermes_set_tkip_keys(<v, key_idx, ext->addr.sa_data,
2948 ext->rx_seq, ext->key, ext->key_len);
2951 DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
2957 lp->wext_enc = IW_ENCODE_ALG_TKIP;
2960 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
2963 case IW_ENCODE_ALG_WEP:
2964 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
2966 if (erq->flags & IW_ENCODE_RESTRICTED) {
2967 DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
2972 ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
2977 case IW_ENCODE_ALG_CCMP:
2978 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
2982 case IW_ENCODE_ALG_NONE:
2983 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
2985 if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
2986 ret = hermes_clear_tkip_keys(<v, key_idx,
2989 lp->wext_enc = IW_ENCODE_ALG_NONE;
2990 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
2992 } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
2993 ret = hermes_set_wep_keys(lp, key_idx,
2994 ext->key, ext->key_len,
3003 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3012 wl_unlock(lp, &flags);
3017 /*============================================================================*/
3021 static int wireless_set_genie(struct net_device *dev,
3022 struct iw_request_info *info,
3023 struct iw_point *data, char *extra)
3026 /* We can't write this to the card, but apparently this
3027 * operation needs to succeed */
3031 /*============================================================================*/
3034 /*******************************************************************************
3035 * wl_wireless_stats()
3036 *******************************************************************************
3040 * Return the current device wireless statistics.
3044 * wrq - the wireless request buffer
3045 * lp - the device's private adapter structure
3050 * errno value otherwise
3052 ******************************************************************************/
3053 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3055 struct iw_statistics *pStats;
3056 struct wl_private *lp = wl_priv(dev);
3058 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3062 /* Initialize the statistics */
3063 pStats = &( lp->wstats );
3064 pStats->qual.updated = 0x00;
3066 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3068 CFG_COMMS_QUALITY_STRCT *pQual;
3069 CFG_HERMES_TALLIES_STRCT tallies;
3072 /* Update driver status */
3075 /* Get the current link quality information */
3076 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3077 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3078 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3080 if( status == HCF_SUCCESS ) {
3081 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3083 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3084 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3085 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3087 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3088 IW_QUAL_LEVEL_UPDATED |
3089 IW_QUAL_NOISE_UPDATED |
3092 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3095 /* Get the current tallies from the adapter */
3096 /* Only possible when the device is open */
3097 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3098 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3099 /* No endian translation is needed here, as CFG_TALLIES is an
3100 MSF RID; all processing is done on the host, not the card! */
3101 pStats->discard.nwid = 0L;
3102 pStats->discard.code = tallies.RxWEPUndecryptable;
3103 pStats->discard.misc = tallies.TxDiscards +
3104 tallies.RxFCSErrors +
3105 //tallies.RxDiscardsNoBuffer +
3106 tallies.TxDiscardsWrongSA;
3107 //;? Extra taken over from Linux driver based on 7.18 version
3108 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3109 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3111 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3114 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3119 } // wl_wireless_stats
3120 /*============================================================================*/
3125 /*******************************************************************************
3126 * wl_get_wireless_stats()
3127 *******************************************************************************
3131 * Return the current device wireless statistics. This function calls
3132 * wl_wireless_stats, but acquires spinlocks first as it can be called
3133 * directly by the network layer.
3137 * wrq - the wireless request buffer
3138 * lp - the device's private adapter structure
3143 * errno value otherwise
3145 ******************************************************************************/
3146 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3148 unsigned long flags;
3149 struct wl_private *lp = wl_priv(dev);
3150 struct iw_statistics *pStats = NULL;
3152 wl_lock( lp, &flags );
3154 wl_act_int_off( lp );
3157 if( lp->useRTS == 1 ) {
3158 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3162 pStats = wl_wireless_stats( dev );
3164 wl_act_int_on( lp );
3166 wl_unlock(lp, &flags);
3169 } // wl_get_wireless_stats
3172 /*******************************************************************************
3174 *******************************************************************************
3178 * Gather wireless spy statistics.
3182 * wrq - the wireless request buffer
3183 * lp - the device's private adapter structure
3188 * errno value otherwise
3190 ******************************************************************************/
3191 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3193 struct iw_quality wstats;
3197 struct wl_private *lp = wl_priv(dev);
3198 /*------------------------------------------------------------------------*/
3201 if (!lp->spy_data.spy_number) {
3205 /* Gather wireless spy statistics: for each packet, compare the source
3206 address with out list, and if match, get the stats. */
3207 memset( stats, 0, sizeof(stats));
3208 memset( desc, 0, sizeof(DESC_STRCT));
3210 desc[0].buf_addr = stats;
3211 desc[0].BUF_SIZE = sizeof(stats);
3212 desc[0].next_desc_addr = 0; // terminate list
3214 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3216 if( status == HCF_SUCCESS ) {
3217 wstats.level = (u_char) dbm(stats[1]);
3218 wstats.noise = (u_char) dbm(stats[0]);
3219 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3221 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3222 IW_QUAL_LEVEL_UPDATED |
3223 IW_QUAL_NOISE_UPDATED |
3226 wireless_spy_update( dev, mac, &wstats );
3229 /*============================================================================*/
3234 /*******************************************************************************
3235 * wl_wext_event_freq()
3236 *******************************************************************************
3240 * This function is used to send an event that the channel/freq
3241 * configuration for a specific device has changed.
3246 * dev - the network device for which this event is to be issued
3252 ******************************************************************************/
3253 void wl_wext_event_freq( struct net_device *dev )
3255 union iwreq_data wrqu;
3256 struct wl_private *lp = wl_priv(dev);
3257 /*------------------------------------------------------------------------*/
3260 memset( &wrqu, 0, sizeof( wrqu ));
3262 wrqu.freq.m = lp->Channel;
3265 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3268 } // wl_wext_event_freq
3269 /*============================================================================*/
3274 /*******************************************************************************
3275 * wl_wext_event_mode()
3276 *******************************************************************************
3280 * This function is used to send an event that the mode of operation
3281 * for a specific device has changed.
3286 * dev - the network device for which this event is to be issued
3292 ******************************************************************************/
3293 void wl_wext_event_mode( struct net_device *dev )
3295 union iwreq_data wrqu;
3296 struct wl_private *lp = wl_priv(dev);
3297 /*------------------------------------------------------------------------*/
3300 memset( &wrqu, 0, sizeof( wrqu ));
3302 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3303 wrqu.mode = IW_MODE_INFRA;
3305 wrqu.mode = IW_MODE_MASTER;
3308 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3311 } // wl_wext_event_mode
3312 /*============================================================================*/
3317 /*******************************************************************************
3318 * wl_wext_event_essid()
3319 *******************************************************************************
3323 * This function is used to send an event that the ESSID configuration for
3324 * a specific device has changed.
3329 * dev - the network device for which this event is to be issued
3335 ******************************************************************************/
3336 void wl_wext_event_essid( struct net_device *dev )
3338 union iwreq_data wrqu;
3339 struct wl_private *lp = wl_priv(dev);
3340 /*------------------------------------------------------------------------*/
3343 memset( &wrqu, 0, sizeof( wrqu ));
3345 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3346 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3347 the call to wireless_send_event() must also point to where the ESSID
3349 wrqu.essid.length = strlen( lp->NetworkName );
3350 wrqu.essid.pointer = (void __user *)lp->NetworkName;
3351 wrqu.essid.flags = 1;
3353 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3356 } // wl_wext_event_essid
3357 /*============================================================================*/
3362 /*******************************************************************************
3363 * wl_wext_event_encode()
3364 *******************************************************************************
3368 * This function is used to send an event that the encryption configuration
3369 * for a specific device has changed.
3374 * dev - the network device for which this event is to be issued
3380 ******************************************************************************/
3381 void wl_wext_event_encode( struct net_device *dev )
3383 union iwreq_data wrqu;
3384 struct wl_private *lp = wl_priv(dev);
3386 /*------------------------------------------------------------------------*/
3389 memset( &wrqu, 0, sizeof( wrqu ));
3391 if( lp->EnableEncryption == 0 ) {
3392 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3394 wrqu.encoding.flags |= lp->TransmitKeyID;
3396 index = lp->TransmitKeyID - 1;
3398 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3399 if we're in AP mode */
3400 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3401 //;?should we restore this to allow smaller memory footprint
3403 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3404 if( lp->ExcludeUnencrypted ) {
3405 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3407 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3411 #endif // HCF_TYPE_AP
3413 /* Only provide the key if permissions allow */
3414 if( capable( CAP_NET_ADMIN )) {
3415 wrqu.encoding.pointer = (void __user *)lp->DefaultKeys.key[index].key;
3416 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3418 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3422 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3423 lp->DefaultKeys.key[index].key );
3426 } // wl_wext_event_encode
3427 /*============================================================================*/
3432 /*******************************************************************************
3433 * wl_wext_event_ap()
3434 *******************************************************************************
3438 * This function is used to send an event that the device has been
3439 * associated to a new AP.
3444 * dev - the network device for which this event is to be issued
3450 ******************************************************************************/
3451 void wl_wext_event_ap( struct net_device *dev )
3453 union iwreq_data wrqu;
3454 struct wl_private *lp = wl_priv(dev);
3456 /*------------------------------------------------------------------------*/
3459 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3460 this event BEFORE sending the association event, as there are timing
3461 issues with the hostap supplicant. The supplicant will attempt to process
3462 an EAPOL-Key frame from an AP before receiving this information, which
3463 is required for a proper processed frame. */
3464 wl_wext_event_assoc_ie( dev );
3467 lp->ltvRecord.typ = CFG_CUR_BSSID;
3468 lp->ltvRecord.len = 4;
3470 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3471 if( status == HCF_SUCCESS ) {
3472 memset( &wrqu, 0, sizeof( wrqu ));
3474 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3476 wrqu.addr.sa_family = ARPHRD_ETHER;
3478 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3482 } // wl_wext_event_ap
3483 /*============================================================================*/
3487 /*******************************************************************************
3488 * wl_wext_event_scan_complete()
3489 *******************************************************************************
3493 * This function is used to send an event that a request for a network scan
3499 * dev - the network device for which this event is to be issued
3505 ******************************************************************************/
3506 void wl_wext_event_scan_complete( struct net_device *dev )
3508 union iwreq_data wrqu;
3509 /*------------------------------------------------------------------------*/
3512 memset( &wrqu, 0, sizeof( wrqu ));
3514 wrqu.addr.sa_family = ARPHRD_ETHER;
3515 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3518 } // wl_wext_event_scan_complete
3519 /*============================================================================*/
3524 /*******************************************************************************
3525 * wl_wext_event_new_sta()
3526 *******************************************************************************
3530 * This function is used to send an event that an AP has registered a new
3536 * dev - the network device for which this event is to be issued
3542 ******************************************************************************/
3543 void wl_wext_event_new_sta( struct net_device *dev )
3545 union iwreq_data wrqu;
3546 /*------------------------------------------------------------------------*/
3549 memset( &wrqu, 0, sizeof( wrqu ));
3551 /* Send the station's mac address here */
3552 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3553 wrqu.addr.sa_family = ARPHRD_ETHER;
3554 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3557 } // wl_wext_event_new_sta
3558 /*============================================================================*/
3563 /*******************************************************************************
3564 * wl_wext_event_expired_sta()
3565 *******************************************************************************
3569 * This function is used to send an event that an AP has deregistered a
3575 * dev - the network device for which this event is to be issued
3581 ******************************************************************************/
3582 void wl_wext_event_expired_sta( struct net_device *dev )
3584 union iwreq_data wrqu;
3585 /*------------------------------------------------------------------------*/
3588 memset( &wrqu, 0, sizeof( wrqu ));
3590 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3591 wrqu.addr.sa_family = ARPHRD_ETHER;
3592 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3595 } // wl_wext_event_expired_sta
3596 /*============================================================================*/
3601 /*******************************************************************************
3602 * wl_wext_event_mic_failed()
3603 *******************************************************************************
3607 * This function is used to send an event that MIC calculations failed.
3612 * dev - the network device for which this event is to be issued
3618 ******************************************************************************/
3619 void wl_wext_event_mic_failed( struct net_device *dev )
3621 union iwreq_data wrqu;
3622 struct wl_private *lp = wl_priv(dev);
3623 struct iw_michaelmicfailure wxmic;
3627 WVLAN_RX_WMP_HDR *hdr;
3628 /*------------------------------------------------------------------------*/
3631 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3634 /* Cast the lookahead buffer into a RFS format */
3635 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3637 /* Cast the addresses to byte buffers, as in the above RFS they are word
3639 addr1 = (char *)hdr->address1;
3640 addr2 = (char *)hdr->address2;
3642 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3645 memset(&wrqu, 0, sizeof(wrqu));
3646 memset(&wxmic, 0, sizeof(wxmic));
3648 wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3649 wxmic.flags |= (addr1[0] & 1) ?
3650 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
3651 wxmic.src_addr.sa_family = ARPHRD_ETHER;
3652 memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3654 wrqu.data.length = sizeof(wxmic);
3655 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3658 } // wl_wext_event_mic_failed
3659 /*============================================================================*/
3664 /*******************************************************************************
3665 * wl_wext_event_assoc_ie()
3666 *******************************************************************************
3670 * This function is used to send an event containing the WPA-IE generated
3671 * by the firmware in an association request.
3676 * dev - the network device for which this event is to be issued
3682 ******************************************************************************/
3683 void wl_wext_event_assoc_ie( struct net_device *dev )
3685 union iwreq_data wrqu;
3686 struct wl_private *lp = wl_priv(dev);
3691 /*------------------------------------------------------------------------*/
3694 memset( &wrqu, 0, sizeof( wrqu ));
3696 /* Retrieve the Association Request IE */
3697 lp->ltvRecord.len = 45;
3698 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3700 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3701 if( status == HCF_SUCCESS )
3704 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3705 wpa_ie = wl_parse_wpa_ie( &data, &length );
3709 wrqu.data.length = wpa_ie[1] + 2;
3710 wireless_send_event(dev, IWEVASSOCREQIE,
3713 /* This bit is a hack. We send the respie
3714 * event at the same time */
3715 wireless_send_event(dev, IWEVASSOCRESPIE,
3721 } // wl_wext_event_assoc_ie
3722 /*============================================================================*/
3723 /* Structures to export the Wireless Handlers */
3725 static const iw_handler wl_handler[] =
3727 IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
3728 IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
3729 IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
3730 IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
3731 IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
3732 IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
3733 IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
3734 IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
3735 IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
3736 IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
3737 IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
3738 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3739 IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
3741 IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
3742 IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
3743 IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
3744 IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
3745 IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
3746 IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
3747 IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
3748 IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
3749 IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
3750 IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
3751 IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
3752 IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
3753 IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
3754 IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
3755 IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
3756 IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
3757 IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
3758 IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3759 IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
3762 static const iw_handler wl_private_handler[] =
3763 { /* SIOCIWFIRSTPRIV + */
3764 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3765 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3766 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3767 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3768 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3769 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3770 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3774 static struct iw_priv_args wl_priv_args[] = {
3775 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3776 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3777 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3778 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3779 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3780 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3781 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3785 const struct iw_handler_def wl_iw_handler_def =
3787 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3788 .private = (iw_handler *) wl_private_handler,
3789 .private_args = (struct iw_priv_args *) wl_priv_args,
3790 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3791 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3792 .standard = (iw_handler *) wl_handler,
3793 .get_wireless_stats = wl_get_wireless_stats,