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 <asm/uaccess.h>
72 #include <wl_internal.h>
80 /* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS
81 #including linux/wireless.h), then these functions do not need to be included
85 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
86 iwe_stream_add_event(info, buf, end, iwe, len)
87 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
88 iwe_stream_add_point(info, buf, end, iwe, msg)
92 /*******************************************************************************
94 ******************************************************************************/
96 extern dbg_info_t *DbgInfo;
102 /*******************************************************************************
104 *******************************************************************************
113 * wrq - the wireless request buffer
119 ******************************************************************************/
120 static int wireless_commit(struct net_device *dev,
121 struct iw_request_info *info,
122 union iwreq_data *rqu, char *extra)
124 struct wl_private *lp = wl_priv(dev);
127 /*------------------------------------------------------------------------*/
129 DBG_FUNC( "wireless_commit" );
132 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
137 wl_lock( lp, &flags );
139 wl_act_int_off( lp );
145 wl_unlock(lp, &flags);
148 DBG_LEAVE( DbgInfo );
151 /*============================================================================*/
156 /*******************************************************************************
157 * wireless_get_protocol()
158 *******************************************************************************
162 * Returns a vendor-defined string that should identify the wireless
167 * wrq - the wireless request buffer
173 ******************************************************************************/
174 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
176 DBG_FUNC( "wireless_get_protocol" );
177 DBG_ENTER( DbgInfo );
179 /* Originally, the driver was placing the string "Wireless" here. However,
180 the wireless extensions (/linux/wireless.h) indicate this string should
181 describe the wireless protocol. */
183 strcpy(name, "IEEE 802.11b");
187 } // wireless_get_protocol
188 /*============================================================================*/
193 /*******************************************************************************
194 * wireless_set_frequency()
195 *******************************************************************************
199 * Sets the frequency (channel) on which the card should Tx/Rx.
203 * wrq - the wireless request buffer
204 * lp - the device's private adapter structure
209 * errno value otherwise
211 ******************************************************************************/
212 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
214 struct wl_private *lp = wl_priv(dev);
218 /*------------------------------------------------------------------------*/
221 DBG_FUNC( "wireless_set_frequency" );
222 DBG_ENTER( DbgInfo );
224 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
229 if( !capable( CAP_NET_ADMIN )) {
231 DBG_LEAVE( DbgInfo );
236 /* If frequency specified, look up channel */
238 int f = freq->m / 100000;
239 channel = wl_get_chan_from_freq( f );
243 /* Channel specified */
249 /* If the channel is an 802.11a channel, set Bit 8 */
251 channel = channel | 0x100;
255 wl_lock( lp, &flags );
257 wl_act_int_off( lp );
259 lp->Channel = channel;
262 /* Commit the adapter parameters */
265 /* Send an event that channel/freq has been set */
266 wl_wext_event_freq( lp->dev );
270 wl_unlock(lp, &flags);
273 DBG_LEAVE( DbgInfo );
275 } // wireless_set_frequency
276 /*============================================================================*/
281 /*******************************************************************************
282 * wireless_get_frequency()
283 *******************************************************************************
287 * Gets the frequency (channel) on which the card is Tx/Rx.
291 * wrq - the wireless request buffer
292 * lp - the device's private adapter structure
298 ******************************************************************************/
299 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
302 struct wl_private *lp = wl_priv(dev);
305 /*------------------------------------------------------------------------*/
308 DBG_FUNC( "wireless_get_frequency" );
309 DBG_ENTER( DbgInfo );
311 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
316 wl_lock( lp, &flags );
318 wl_act_int_off( lp );
320 lp->ltvRecord.len = 2;
321 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
323 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
324 if( ret == HCF_SUCCESS ) {
325 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
329 freq->m = wl_get_freq_from_chan( channel ) * 100000;
336 #endif /* USE_FREQUENCY */
341 wl_unlock(lp, &flags);
343 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
346 DBG_LEAVE( DbgInfo );
348 } // wireless_get_frequency
349 /*============================================================================*/
354 /*******************************************************************************
355 * wireless_get_range()
356 *******************************************************************************
360 * This function is used to provide misc info and statistics about the
365 * wrq - the wireless request buffer
366 * lp - the device's private adapter structure
371 * errno value otherwise
373 ******************************************************************************/
374 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
376 struct wl_private *lp = wl_priv(dev);
378 struct iw_range *range = (struct iw_range *) extra;
384 /*------------------------------------------------------------------------*/
387 DBG_FUNC( "wireless_get_range" );
388 DBG_ENTER( DbgInfo );
390 /* Set range information */
391 data->length = sizeof(struct iw_range);
392 memset(range, 0, sizeof(struct iw_range));
394 wl_lock( lp, &flags );
396 wl_act_int_off( lp );
398 /* Set range information */
399 memset( range, 0, sizeof( struct iw_range ));
402 /* Get the current transmit rate from the adapter */
403 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
404 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
406 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
407 if( status != HCF_SUCCESS ) {
408 /* Recovery action: reset and retry up to 10 times */
409 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
414 /* Holding the lock too long, make a gap to allow other processes */
415 wl_unlock(lp, &flags);
416 wl_lock( lp, &flags );
418 status = wl_reset( dev );
419 if ( status != HCF_SUCCESS ) {
420 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
426 /* Holding the lock too long, make a gap to allow other processes */
427 wl_unlock(lp, &flags);
428 wl_lock( lp, &flags );
433 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
439 /* Holding the lock too long, make a gap to allow other processes */
440 wl_unlock(lp, &flags);
441 wl_lock( lp, &flags );
443 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
445 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
448 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
451 // NWID - NOT SUPPORTED
454 /* Channel/Frequency Info */
455 range->num_channels = RADIO_CHANNELS;
458 /* Signal Level Thresholds */
459 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
465 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
467 /* If the value returned in /proc/net/wireless is greater than the maximum range,
468 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
469 it requires a bit of contorsion... */
471 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
472 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
475 range->max_qual.qual = 100;
476 range->max_qual.level = 100;
477 range->max_qual.noise = 100;
482 /* Set available rates */
483 range->num_bitrates = 0;
485 lp->ltvRecord.len = 6;
486 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
488 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
489 if( status == HCF_SUCCESS ) {
490 for( count = 0; count < MAX_RATES; count++ )
491 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
492 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
493 range->num_bitrates++;
496 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
501 /* RTS Threshold info */
502 range->min_rts = MIN_RTS_BYTES;
503 range->max_rts = MAX_RTS_BYTES;
505 // Frag Threshold info - NOT SUPPORTED
507 // Power Management info - NOT SUPPORTED
513 /* Holding the lock too long, make a gap to allow other processes */
514 wl_unlock(lp, &flags);
515 wl_lock( lp, &flags );
517 /* Is WEP supported? */
519 if( wl_has_wep( &( lp->hcfCtx ))) {
520 /* WEP: RC4 40 bits */
521 range->encoding_size[0] = MIN_KEY_SIZE;
524 range->encoding_size[1] = MAX_KEY_SIZE;
525 range->num_encoding_sizes = 2;
526 range->max_encoding_tokens = MAX_KEYS;
529 #endif /* WIRELESS_EXT > 8 */
532 range->txpower_capa = IW_TXPOW_MWATT;
533 range->num_txpower = 1;
534 range->txpower[0] = RADIO_TX_POWER_MWATT;
536 #if WIRELESS_EXT > 10
538 /* Wireless Extension Info */
539 range->we_version_compiled = WIRELESS_EXT;
540 range->we_version_source = WIRELESS_SUPPORT;
542 // Retry Limits and Lifetime - NOT SUPPORTED
547 #if WIRELESS_EXT > 11
549 /* Holding the lock too long, make a gap to allow other processes */
550 wl_unlock(lp, &flags);
551 wl_lock( lp, &flags );
553 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
554 wl_wireless_stats( lp->dev );
555 range->avg_qual = lp->wstats.qual;
556 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
560 /* Event capability (kernel + driver) */
561 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
562 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
563 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
564 range->event_capa[1] = IW_EVENT_CAPA_K_1;
565 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
566 IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
567 IW_EVENT_CAPA_MASK(IWEVEXPIRED));
569 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
574 wl_unlock(lp, &flags);
578 } // wireless_get_range
579 /*============================================================================*/
582 /*******************************************************************************
583 * wireless_get_bssid()
584 *******************************************************************************
588 * Gets the BSSID the wireless device is currently associated with.
592 * wrq - the wireless request buffer
593 * lp - the device's private adapter structure
598 * errno value otherwise
600 ******************************************************************************/
601 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
603 struct wl_private *lp = wl_priv(dev);
606 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
608 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
609 /*------------------------------------------------------------------------*/
612 DBG_FUNC( "wireless_get_bssid" );
613 DBG_ENTER( DbgInfo );
615 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
620 wl_lock( lp, &flags );
622 wl_act_int_off( lp );
624 memset( &ap_addr->sa_data, 0, ETH_ALEN );
626 ap_addr->sa_family = ARPHRD_ETHER;
628 /* Assume AP mode here, which means the BSSID is our own MAC address. In
629 STA mode, this address will be overwritten with the actual BSSID using
631 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
634 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
635 //;?should we return an error status in AP mode
637 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
638 /* Get Current BSSID */
639 lp->ltvRecord.typ = CFG_CUR_BSSID;
640 lp->ltvRecord.len = 4;
641 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
643 if( status == HCF_SUCCESS ) {
644 /* Copy info into sockaddr struct */
645 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
651 #endif // (HCF_TYPE) & HCF_TYPE_STA
655 wl_unlock(lp, &flags);
660 } // wireless_get_bssid
661 /*============================================================================*/
666 /*******************************************************************************
667 * wireless_get_ap_list()
668 *******************************************************************************
672 * Gets the results of a network scan.
676 * wrq - the wireless request buffer
677 * lp - the device's private adapter structure
682 * errno value otherwise
684 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
685 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
686 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
688 ******************************************************************************/
689 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
691 struct wl_private *lp = wl_priv(dev);
697 struct sockaddr *hwa = NULL;
698 struct iw_quality *qual = NULL;
700 ScanResult *p = &lp->scan_results;
702 ProbeResult *p = &lp->probe_results;
704 /*------------------------------------------------------------------------*/
706 DBG_FUNC( "wireless_get_ap_list" );
707 DBG_ENTER( DbgInfo );
709 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
714 wl_lock( lp, &flags );
716 wl_act_int_off( lp );
718 /* Set the completion state to FALSE */
719 lp->scan_results.scan_complete = FALSE;
720 lp->probe_results.scan_complete = FALSE;
721 /* Channels to scan */
722 lp->ltvRecord.len = 2;
723 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
724 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
725 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
726 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
728 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
729 disassociate from the network we are currently on */
730 lp->ltvRecord.len = 2;
731 lp->ltvRecord.typ = CFG_SCAN_SSID;
732 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
733 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
734 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
736 /* Initiate the scan */
738 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
740 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
745 //;? unlock? what about the access to lp below? is it broken?
746 wl_unlock(lp, &flags);
748 if( ret == HCF_SUCCESS ) {
749 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
750 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
751 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
752 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
753 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
756 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
757 other things in the meantime, This prevents system lockups by
758 giving some time back to the kernel */
759 for( count = 0; count < 100; count ++ ) {
768 if ( ret != HCF_SUCCESS ) {
769 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
771 num_aps = (*p)/*lp->probe_results*/.num_aps;
772 if (num_aps > IW_MAX_AP) {
775 data->length = num_aps;
776 hwa = (struct sockaddr *)extra;
777 qual = (struct iw_quality *) extra +
778 ( sizeof( struct sockaddr ) * num_aps );
780 /* This flag is used to tell the user if we provide quality
781 information. Since we provide signal/noise levels but no
782 quality info on a scan, this is set to 0. Setting to 1 and
783 providing a quality of 0 produces weird results. If we ever
784 provide quality (or can calculate it), this can be changed */
787 for( count = 0; count < num_aps; count++ ) {
789 memcpy( hwa[count].sa_data,
790 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
791 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
792 DBG_PRINT( "BSSID: %s\n", DbgHwAddr( (*p)/*lp->probe_results*/.ProbeTable[count].BSSID ));
793 memcpy( hwa[count].sa_data,
794 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
797 /* Once the data is copied to the wireless struct, invalidate the
798 scan result to initiate a rescan on the next request */
799 (*p)/*lp->probe_results*/.scan_complete = FALSE;
800 /* Send the wireless event that the scan has completed, just in case
802 wl_wext_event_scan_complete( lp->dev );
806 DBG_LEAVE( DbgInfo );
808 } // wireless_get_ap_list
809 /*============================================================================*/
814 /*******************************************************************************
815 * wireless_set_sensitivity()
816 *******************************************************************************
820 * Sets the sensitivity (distance between APs) of the wireless card.
824 * wrq - the wireless request buffer
825 * lp - the device's private adapter structure
830 * errno value otherwise
832 ******************************************************************************/
833 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
835 struct wl_private *lp = wl_priv(dev);
838 int dens = sens->value;
839 /*------------------------------------------------------------------------*/
842 DBG_FUNC( "wireless_set_sensitivity" );
843 DBG_ENTER( DbgInfo );
845 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
850 if(( dens < 1 ) || ( dens > 3 )) {
855 wl_lock( lp, &flags );
857 wl_act_int_off( lp );
859 lp->DistanceBetweenAPs = dens;
864 wl_unlock(lp, &flags);
867 DBG_LEAVE( DbgInfo );
869 } // wireless_set_sensitivity
870 /*============================================================================*/
875 /*******************************************************************************
876 * wireless_get_sensitivity()
877 *******************************************************************************
881 * Gets the sensitivity (distance between APs) of the wireless card.
885 * wrq - the wireless request buffer
886 * lp - the device's private adapter structure
891 * errno value otherwise
893 ******************************************************************************/
894 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
896 struct wl_private *lp = wl_priv(dev);
898 /*------------------------------------------------------------------------*/
899 /*------------------------------------------------------------------------*/
902 DBG_FUNC( "wireless_get_sensitivity" );
903 DBG_ENTER( DbgInfo );
905 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
910 /* not worth locking ... */
911 sens->value = lp->DistanceBetweenAPs;
912 sens->fixed = 0; /* auto */
914 DBG_LEAVE( DbgInfo );
916 } // wireless_get_sensitivity
917 /*============================================================================*/
922 /*******************************************************************************
923 * wireless_set_essid()
924 *******************************************************************************
928 * Sets the ESSID (network name) that the wireless device should associate
933 * wrq - the wireless request buffer
934 * lp - the device's private adapter structure
939 * errno value otherwise
941 ******************************************************************************/
942 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
944 struct wl_private *lp = wl_priv(dev);
948 DBG_FUNC( "wireless_set_essid" );
949 DBG_ENTER( DbgInfo );
951 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
956 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
961 wl_lock( lp, &flags );
963 wl_act_int_off( lp );
965 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
967 /* data->flags is zero to ask for "any" */
968 if( data->flags == 0 ) {
969 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
970 * ;?but there ain't no STAP anymore*/
971 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
972 strcpy( lp->NetworkName, "ANY" );
974 //strcpy( lp->NetworkName, "ANY" );
975 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
978 memcpy( lp->NetworkName, ssid, data->length );
981 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
983 /* Commit the adapter parameters */
986 /* Send an event that ESSID has been set */
987 wl_wext_event_essid( lp->dev );
991 wl_unlock(lp, &flags);
994 DBG_LEAVE( DbgInfo );
996 } // wireless_set_essid
997 /*============================================================================*/
1002 /*******************************************************************************
1003 * wireless_get_essid()
1004 *******************************************************************************
1008 * Gets the ESSID (network name) that the wireless device is associated
1013 * wrq - the wireless request buffer
1014 * lp - the device's private adapter structure
1019 * errno value otherwise
1021 ******************************************************************************/
1022 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1025 struct wl_private *lp = wl_priv(dev);
1026 unsigned long flags;
1030 /*------------------------------------------------------------------------*/
1033 DBG_FUNC( "wireless_get_essid" );
1034 DBG_ENTER( DbgInfo );
1036 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1041 wl_lock( lp, &flags );
1043 wl_act_int_off( lp );
1045 /* Get the desired network name */
1046 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1049 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1050 //;?should we return an error status in AP mode
1052 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1057 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1058 //;?should we restore this to allow smaller memory footprint
1060 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1061 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1067 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1068 if( status == HCF_SUCCESS ) {
1069 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1071 /* Endian translate the string length */
1072 pName->length = CNV_LITTLE_TO_INT( pName->length );
1074 /* Copy the information into the user buffer */
1075 data->length = pName->length;
1077 /* NOTE: Null terminating is necessary for proper display of the SSID in
1078 the wireless tools */
1079 data->length = pName->length + 1;
1080 if( pName->length < HCF_MAX_NAME_LEN ) {
1081 pName->name[pName->length] = '\0';
1087 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1088 //;?should we return an error status in AP mode
1089 #ifdef RETURN_CURRENT_NETWORKNAME
1091 /* if desired is null ("any"), return current or "any" */
1092 if( pName->name[0] == '\0' ) {
1093 /* Get the current network name */
1094 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1095 lp->ltvRecord.typ = CFG_CUR_SSID;
1097 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1099 if( status == HCF_SUCCESS ) {
1100 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1102 /* Endian translate the string length */
1103 pName->length = CNV_LITTLE_TO_INT( pName->length );
1105 /* Copy the information into the user buffer */
1106 data->length = pName->length + 1;
1107 if( pName->length < HCF_MAX_NAME_LEN ) {
1108 pName->name[pName->length] = '\0';
1118 #endif // RETURN_CURRENT_NETWORKNAME
1123 if (pName->length > IW_ESSID_MAX_SIZE) {
1128 memcpy(essid, pName->name, pName->length);
1135 wl_act_int_on( lp );
1137 wl_unlock(lp, &flags);
1140 DBG_LEAVE( DbgInfo );
1142 } // wireless_get_essid
1143 /*============================================================================*/
1148 /*******************************************************************************
1149 * wireless_set_encode()
1150 *******************************************************************************
1154 * Sets the encryption keys and status (enable or disable).
1158 * wrq - the wireless request buffer
1159 * lp - the device's private adapter structure
1164 * errno value otherwise
1166 ******************************************************************************/
1167 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1169 struct wl_private *lp = wl_priv(dev);
1170 unsigned long flags;
1173 #if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
1174 hcf_8 encryption_state;
1175 #endif // WIRELESS_EXT > 8
1176 /*------------------------------------------------------------------------*/
1179 DBG_FUNC( "wireless_set_encode" );
1180 DBG_ENTER( DbgInfo );
1182 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1187 wl_lock( lp, &flags );
1189 wl_act_int_off( lp );
1191 /* Is encryption supported? */
1192 if( !wl_has_wep( &( lp->hcfCtx ))) {
1193 DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1198 DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1199 keybuf, erq->length,
1202 /* Save state of Encryption switch */
1203 encryption_state = lp->EnableEncryption;
1205 /* Basic checking: do we have a key to set? */
1206 if((erq->length) != 0) {
1207 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1208 int tk = lp->TransmitKeyID - 1; // current key
1211 /* Check the size of the key */
1212 switch(erq->length) {
1219 /* Check the index */
1220 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1225 memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1227 /* Copy the key in the driver */
1228 memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1230 /* Set the length */
1231 lp->DefaultKeys.key[index].len = erq->length;
1233 DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1234 DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1235 lp->DefaultKeys.key[index].len, index );
1237 /* Enable WEP (if possible) */
1238 if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1239 lp->EnableEncryption = 1;
1245 DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1250 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1253 /* Do we want to just set the current transmit key? */
1254 if(( index >= 0 ) && ( index < MAX_KEYS )) {
1255 DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1256 lp->DefaultKeys.key[index].len );
1258 if( lp->DefaultKeys.key[index].len > 0 ) {
1259 lp->TransmitKeyID = index + 1;
1260 lp->EnableEncryption = 1;
1262 DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1263 DBG_LEAVE( DbgInfo );
1269 /* Read the flags */
1270 if( erq->flags & IW_ENCODE_DISABLED ) {
1271 lp->EnableEncryption = 0; // disable encryption
1273 lp->EnableEncryption = 1;
1276 if( erq->flags & IW_ENCODE_RESTRICTED ) {
1277 DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1278 ret = -EINVAL; // Invalid
1281 DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state );
1282 DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption );
1283 DBG_TRACE( DbgInfo, "erq->length : %d\n",
1285 DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n",
1288 /* Write the changes to the card */
1290 DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1291 lp->TransmitKeyID );
1293 if( lp->EnableEncryption == encryption_state ) {
1294 if( erq->length != 0 ) {
1295 /* Dynamic WEP key update */
1296 wl_set_wep_keys( lp );
1299 /* To switch encryption on/off, soft reset is required */
1304 /* Send an event that Encryption has been set */
1305 wl_wext_event_encode( dev );
1309 wl_act_int_on( lp );
1311 wl_unlock(lp, &flags);
1314 DBG_LEAVE( DbgInfo );
1316 } // wireless_set_encode
1317 /*============================================================================*/
1322 /*******************************************************************************
1323 * wireless_get_encode()
1324 *******************************************************************************
1328 * Gets the encryption keys and status.
1332 * wrq - the wireless request buffer
1333 * lp - the device's private adapter structure
1338 * errno value otherwise
1340 ******************************************************************************/
1341 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1344 struct wl_private *lp = wl_priv(dev);
1345 unsigned long flags;
1348 /*------------------------------------------------------------------------*/
1351 DBG_FUNC( "wireless_get_encode" );
1352 DBG_ENTER( DbgInfo );
1353 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1355 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1360 /* Only super-user can see WEP key */
1361 if( !capable( CAP_NET_ADMIN )) {
1363 DBG_LEAVE( DbgInfo );
1367 wl_lock( lp, &flags );
1369 wl_act_int_off( lp );
1371 /* Is it supported? */
1372 if( !wl_has_wep( &( lp->hcfCtx ))) {
1377 /* Basic checking */
1378 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1384 if( lp->EnableEncryption == 0 ) {
1385 erq->flags |= IW_ENCODE_DISABLED;
1388 /* Which key do we want */
1389 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1390 index = lp->TransmitKeyID - 1;
1393 erq->flags |= index + 1;
1395 /* Copy the key to the user buffer */
1396 erq->length = lp->DefaultKeys.key[index].len;
1398 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1402 wl_act_int_on( lp );
1404 wl_unlock(lp, &flags);
1407 DBG_LEAVE( DbgInfo );
1409 } // wireless_get_encode
1410 /*============================================================================*/
1415 /*******************************************************************************
1416 * wireless_set_nickname()
1417 *******************************************************************************
1421 * Sets the nickname, or station name, of the wireless device.
1425 * wrq - the wireless request buffer
1426 * lp - the device's private adapter structure
1431 * errno value otherwise
1433 ******************************************************************************/
1434 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1436 struct wl_private *lp = wl_priv(dev);
1437 unsigned long flags;
1439 /*------------------------------------------------------------------------*/
1442 DBG_FUNC( "wireless_set_nickname" );
1443 DBG_ENTER( DbgInfo );
1445 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1450 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1451 if( !capable(CAP_NET_ADMIN )) {
1453 DBG_LEAVE( DbgInfo );
1458 /* Validate the new value */
1459 if(data->length > HCF_MAX_NAME_LEN) {
1464 wl_lock( lp, &flags );
1466 wl_act_int_off( lp );
1468 memset( lp->StationName, 0, sizeof( lp->StationName ));
1470 memcpy( lp->StationName, nickname, data->length );
1472 /* Commit the adapter parameters */
1475 wl_act_int_on( lp );
1477 wl_unlock(lp, &flags);
1480 DBG_LEAVE( DbgInfo );
1482 } // wireless_set_nickname
1483 /*============================================================================*/
1488 /*******************************************************************************
1489 * wireless_get_nickname()
1490 *******************************************************************************
1494 * Gets the nickname, or station name, of the wireless device.
1498 * wrq - the wireless request buffer
1499 * lp - the device's private adapter structure
1504 * errno value otherwise
1506 ******************************************************************************/
1507 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1509 struct wl_private *lp = wl_priv(dev);
1510 unsigned long flags;
1514 /*------------------------------------------------------------------------*/
1517 DBG_FUNC( "wireless_get_nickname" );
1518 DBG_ENTER( DbgInfo );
1520 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1525 wl_lock( lp, &flags );
1527 wl_act_int_off( lp );
1529 /* Get the current station name */
1530 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1531 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1533 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1535 if( status == HCF_SUCCESS ) {
1536 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1538 /* Endian translate the length */
1539 pName->length = CNV_LITTLE_TO_INT( pName->length );
1541 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1544 /* Copy the information into the user buffer */
1545 data->length = pName->length;
1546 memcpy(nickname, pName->name, pName->length);
1552 wl_act_int_on( lp );
1554 wl_unlock(lp, &flags);
1559 } // wireless_get_nickname
1560 /*============================================================================*/
1565 /*******************************************************************************
1566 * wireless_set_porttype()
1567 *******************************************************************************
1571 * Sets the port type of the wireless device.
1575 * wrq - the wireless request buffer
1576 * lp - the device's private adapter structure
1581 * errno value otherwise
1583 ******************************************************************************/
1584 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1586 struct wl_private *lp = wl_priv(dev);
1587 unsigned long flags;
1591 /*------------------------------------------------------------------------*/
1593 DBG_FUNC( "wireless_set_porttype" );
1594 DBG_ENTER( DbgInfo );
1596 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1601 wl_lock( lp, &flags );
1603 wl_act_int_off( lp );
1605 /* Validate the new value */
1609 /* When user requests ad-hoc, set IBSS mode! */
1613 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1621 /* Both automatic and infrastructure set port to BSS/STA mode */
1625 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1630 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1632 case IW_MODE_MASTER:
1634 /* Set BSS/AP mode */
1638 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1642 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1652 if( portType != 0 ) {
1653 /* Only do something if there is a mode change */
1654 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1655 lp->PortType = portType;
1656 lp->CreateIBSS = createIBSS;
1658 /* Commit the adapter parameters */
1661 /* Send an event that mode has been set */
1662 wl_wext_event_mode( lp->dev );
1666 wl_act_int_on( lp );
1668 wl_unlock(lp, &flags);
1671 DBG_LEAVE( DbgInfo );
1673 } // wireless_set_porttype
1674 /*============================================================================*/
1679 /*******************************************************************************
1680 * wireless_get_porttype()
1681 *******************************************************************************
1685 * Gets the port type of the wireless device.
1689 * wrq - the wireless request buffer
1690 * lp - the device's private adapter structure
1695 * errno value otherwise
1697 ******************************************************************************/
1698 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1701 struct wl_private *lp = wl_priv(dev);
1702 unsigned long flags;
1706 /*------------------------------------------------------------------------*/
1709 DBG_FUNC( "wireless_get_porttype" );
1710 DBG_ENTER( DbgInfo );
1712 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1717 wl_lock( lp, &flags );
1719 wl_act_int_off( lp );
1721 /* Get the current port type */
1722 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1723 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1725 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1727 if( status == HCF_SUCCESS ) {
1728 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1730 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1732 switch( *pPortType ) {
1736 #if (HCF_TYPE) & HCF_TYPE_AP
1738 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1739 *mode = IW_MODE_MASTER;
1741 *mode = IW_MODE_INFRA;
1746 *mode = IW_MODE_INFRA;
1748 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1751 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1752 *mode = IW_MODE_MASTER;
1754 if( lp->CreateIBSS ) {
1755 *mode = IW_MODE_ADHOC;
1757 *mode = IW_MODE_INFRA;
1765 *mode = IW_MODE_ADHOC;
1776 wl_act_int_on( lp );
1778 wl_unlock(lp, &flags);
1781 DBG_LEAVE( DbgInfo );
1783 } // wireless_get_porttype
1784 /*============================================================================*/
1789 /*******************************************************************************
1790 * wireless_set_power()
1791 *******************************************************************************
1795 * Sets the power management settings of the wireless device.
1799 * wrq - the wireless request buffer
1800 * lp - the device's private adapter structure
1805 * errno value otherwise
1807 ******************************************************************************/
1808 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1810 struct wl_private *lp = wl_priv(dev);
1811 unsigned long flags;
1813 /*------------------------------------------------------------------------*/
1816 DBG_FUNC( "wireless_set_power" );
1817 DBG_ENTER( DbgInfo );
1819 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1824 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1826 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1827 if( !capable( CAP_NET_ADMIN )) {
1830 DBG_LEAVE( DbgInfo );
1835 wl_lock( lp, &flags );
1837 wl_act_int_off( lp );
1839 /* Set the power management state based on the 'disabled' value */
1840 if( wrq->disabled ) {
1846 /* Commit the adapter parameters */
1849 wl_act_int_on( lp );
1851 wl_unlock(lp, &flags);
1854 DBG_LEAVE( DbgInfo );
1856 } // wireless_set_power
1857 /*============================================================================*/
1862 /*******************************************************************************
1863 * wireless_get_power()
1864 *******************************************************************************
1868 * Gets the power management settings of the wireless device.
1872 * wrq - the wireless request buffer
1873 * lp - the device's private adapter structure
1878 * errno value otherwise
1880 ******************************************************************************/
1881 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1884 struct wl_private *lp = wl_priv(dev);
1885 unsigned long flags;
1887 /*------------------------------------------------------------------------*/
1888 DBG_FUNC( "wireless_get_power" );
1889 DBG_ENTER( DbgInfo );
1891 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1896 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1898 wl_lock( lp, &flags );
1900 wl_act_int_off( lp );
1905 if( lp->PMEnabled ) {
1911 wl_act_int_on( lp );
1913 wl_unlock(lp, &flags);
1916 DBG_LEAVE( DbgInfo );
1918 } // wireless_get_power
1919 /*============================================================================*/
1924 /*******************************************************************************
1925 * wireless_get_tx_power()
1926 *******************************************************************************
1930 * Gets the transmit power of the wireless device's radio.
1934 * wrq - the wireless request buffer
1935 * lp - the device's private adapter structure
1940 * errno value otherwise
1942 ******************************************************************************/
1943 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1945 struct wl_private *lp = wl_priv(dev);
1946 unsigned long flags;
1948 /*------------------------------------------------------------------------*/
1949 DBG_FUNC( "wireless_get_tx_power" );
1950 DBG_ENTER( DbgInfo );
1952 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1957 wl_lock( lp, &flags );
1959 wl_act_int_off( lp );
1961 #ifdef USE_POWER_DBM
1962 rrq->value = RADIO_TX_POWER_DBM;
1963 rrq->flags = IW_TXPOW_DBM;
1965 rrq->value = RADIO_TX_POWER_MWATT;
1966 rrq->flags = IW_TXPOW_MWATT;
1971 wl_act_int_on( lp );
1973 wl_unlock(lp, &flags);
1976 DBG_LEAVE( DbgInfo );
1978 } // wireless_get_tx_power
1979 /*============================================================================*/
1984 /*******************************************************************************
1985 * wireless_set_rts_threshold()
1986 *******************************************************************************
1990 * Sets the RTS threshold for the wireless card.
1994 * wrq - the wireless request buffer
1995 * lp - the device's private adapter structure
2000 * errno value otherwise
2002 ******************************************************************************/
2003 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2006 struct wl_private *lp = wl_priv(dev);
2007 unsigned long flags;
2008 int rthr = rts->value;
2009 /*------------------------------------------------------------------------*/
2012 DBG_FUNC( "wireless_set_rts_threshold" );
2013 DBG_ENTER( DbgInfo );
2015 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2020 if(rts->fixed == 0) {
2025 #if WIRELESS_EXT > 8
2026 if( rts->disabled ) {
2029 #endif /* WIRELESS_EXT > 8 */
2031 if(( rthr < 256 ) || ( rthr > 2347 )) {
2036 wl_lock( lp, &flags );
2038 wl_act_int_off( lp );
2040 lp->RTSThreshold = rthr;
2044 wl_act_int_on( lp );
2046 wl_unlock(lp, &flags);
2049 DBG_LEAVE( DbgInfo );
2051 } // wireless_set_rts_threshold
2052 /*============================================================================*/
2057 /*******************************************************************************
2058 * wireless_get_rts_threshold()
2059 *******************************************************************************
2063 * Gets the RTS threshold for the wireless card.
2067 * wrq - the wireless request buffer
2068 * lp - the device's private adapter structure
2073 * errno value otherwise
2075 ******************************************************************************/
2076 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2079 struct wl_private *lp = wl_priv(dev);
2080 unsigned long flags;
2081 /*------------------------------------------------------------------------*/
2083 DBG_FUNC( "wireless_get_rts_threshold" );
2084 DBG_ENTER( DbgInfo );
2086 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2091 wl_lock( lp, &flags );
2093 wl_act_int_off( lp );
2095 rts->value = lp->RTSThreshold;
2097 #if WIRELESS_EXT > 8
2099 rts->disabled = ( rts->value == 2347 );
2101 #endif /* WIRELESS_EXT > 8 */
2105 wl_act_int_on( lp );
2107 wl_unlock(lp, &flags);
2110 DBG_LEAVE( DbgInfo );
2112 } // wireless_get_rts_threshold
2113 /*============================================================================*/
2119 /*******************************************************************************
2120 * wireless_set_rate()
2121 *******************************************************************************
2125 * Set the default data rate setting used by the wireless device.
2129 * wrq - the wireless request buffer
2130 * lp - the device's private adapter structure
2135 * errno value otherwise
2137 ******************************************************************************/
2138 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2140 struct wl_private *lp = wl_priv(dev);
2141 unsigned long flags;
2147 /*------------------------------------------------------------------------*/
2150 DBG_FUNC( "wireless_set_rate" );
2151 DBG_ENTER( DbgInfo );
2153 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2158 wl_lock( lp, &flags );
2160 wl_act_int_off( lp );
2164 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2165 if Bit 9 is set in the current channel RID */
2166 lp->ltvRecord.len = 2;
2167 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2169 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2171 if( status == HCF_SUCCESS ) {
2172 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2174 DBG_PRINT( "Index: %d\n", index );
2176 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2177 DBG_LEAVE( DbgInfo );
2182 if( rrq->value > 0 &&
2183 rrq->value <= 1 * MEGABIT ) {
2184 lp->TxRateControl[index] = 0x0001;
2186 else if( rrq->value > 1 * MEGABIT &&
2187 rrq->value <= 2 * MEGABIT ) {
2188 if( rrq->fixed == 1 ) {
2189 lp->TxRateControl[index] = 0x0002;
2191 lp->TxRateControl[index] = 0x0003;
2194 else if( rrq->value > 2 * MEGABIT &&
2195 rrq->value <= 5 * MEGABIT ) {
2196 if( rrq->fixed == 1 ) {
2197 lp->TxRateControl[index] = 0x0004;
2199 lp->TxRateControl[index] = 0x0007;
2202 else if( rrq->value > 5 * MEGABIT &&
2203 rrq->value <= 6 * MEGABIT ) {
2204 if( rrq->fixed == 1 ) {
2205 lp->TxRateControl[index] = 0x0010;
2207 lp->TxRateControl[index] = 0x0017;
2210 else if( rrq->value > 6 * MEGABIT &&
2211 rrq->value <= 9 * MEGABIT ) {
2212 if( rrq->fixed == 1 ) {
2213 lp->TxRateControl[index] = 0x0020;
2215 lp->TxRateControl[index] = 0x0037;
2218 else if( rrq->value > 9 * MEGABIT &&
2219 rrq->value <= 11 * MEGABIT ) {
2220 if( rrq->fixed == 1 ) {
2221 lp->TxRateControl[index] = 0x0008;
2223 lp->TxRateControl[index] = 0x003F;
2226 else if( rrq->value > 11 * MEGABIT &&
2227 rrq->value <= 12 * MEGABIT ) {
2228 if( rrq->fixed == 1 ) {
2229 lp->TxRateControl[index] = 0x0040;
2231 lp->TxRateControl[index] = 0x007F;
2234 else if( rrq->value > 12 * MEGABIT &&
2235 rrq->value <= 18 * MEGABIT ) {
2236 if( rrq->fixed == 1 ) {
2237 lp->TxRateControl[index] = 0x0080;
2239 lp->TxRateControl[index] = 0x00FF;
2242 else if( rrq->value > 18 * MEGABIT &&
2243 rrq->value <= 24 * MEGABIT ) {
2244 if( rrq->fixed == 1 ) {
2245 lp->TxRateControl[index] = 0x0100;
2247 lp->TxRateControl[index] = 0x01FF;
2250 else if( rrq->value > 24 * MEGABIT &&
2251 rrq->value <= 36 * MEGABIT ) {
2252 if( rrq->fixed == 1 ) {
2253 lp->TxRateControl[index] = 0x0200;
2255 lp->TxRateControl[index] = 0x03FF;
2258 else if( rrq->value > 36 * MEGABIT &&
2259 rrq->value <= 48 * MEGABIT ) {
2260 if( rrq->fixed == 1 ) {
2261 lp->TxRateControl[index] = 0x0400;
2263 lp->TxRateControl[index] = 0x07FF;
2266 else if( rrq->value > 48 * MEGABIT &&
2267 rrq->value <= 54 * MEGABIT ) {
2268 if( rrq->fixed == 1 ) {
2269 lp->TxRateControl[index] = 0x0800;
2271 lp->TxRateControl[index] = 0x0FFF;
2274 else if( rrq->fixed == 0 ) {
2275 /* In this case, the user has not specified a bitrate, only the "auto"
2276 moniker. So, set to all supported rates */
2277 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2287 if( rrq->value > 0 &&
2288 rrq->value <= 1 * MEGABIT ) {
2289 lp->TxRateControl[0] = 1;
2291 else if( rrq->value > 1 * MEGABIT &&
2292 rrq->value <= 2 * MEGABIT ) {
2294 lp->TxRateControl[0] = 2;
2296 lp->TxRateControl[0] = 6;
2299 else if( rrq->value > 2 * MEGABIT &&
2300 rrq->value <= 5 * MEGABIT ) {
2302 lp->TxRateControl[0] = 4;
2304 lp->TxRateControl[0] = 7;
2307 else if( rrq->value > 5 * MEGABIT &&
2308 rrq->value <= 11 * MEGABIT ) {
2310 lp->TxRateControl[0] = 5;
2312 lp->TxRateControl[0] = 3;
2315 else if( rrq->fixed == 0 ) {
2316 /* In this case, the user has not specified a bitrate, only the "auto"
2317 moniker. So, set the rate to 11Mb auto */
2318 lp->TxRateControl[0] = 3;
2328 /* Commit the adapter parameters */
2333 wl_act_int_on( lp );
2335 wl_unlock(lp, &flags);
2338 DBG_LEAVE( DbgInfo );
2340 } // wireless_set_rate
2341 /*============================================================================*/
2346 /*******************************************************************************
2347 * wireless_get_rate()
2348 *******************************************************************************
2352 * Get the default data rate setting used by the wireless device.
2356 * wrq - the wireless request buffer
2357 * lp - the device's private adapter structure
2362 * errno value otherwise
2364 ******************************************************************************/
2365 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2368 struct wl_private *lp = wl_priv(dev);
2369 unsigned long flags;
2373 /*------------------------------------------------------------------------*/
2376 DBG_FUNC( "wireless_get_rate" );
2377 DBG_ENTER( DbgInfo );
2379 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2384 wl_lock( lp, &flags );
2386 wl_act_int_off( lp );
2388 /* Get the current transmit rate from the adapter */
2389 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2390 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2392 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2394 if( status == HCF_SUCCESS ) {
2397 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2399 if( txRate & 0x0001 ) {
2402 else if( txRate & 0x0002 ) {
2405 else if( txRate & 0x0004 ) {
2408 else if( txRate & 0x0008 ) {
2411 else if( txRate & 0x00010 ) {
2414 else if( txRate & 0x00020 ) {
2417 else if( txRate & 0x00040 ) {
2420 else if( txRate & 0x00080 ) {
2423 else if( txRate & 0x00100 ) {
2426 else if( txRate & 0x00200 ) {
2429 else if( txRate & 0x00400 ) {
2432 else if( txRate & 0x00800 ) {
2438 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2442 rrq->value = txRate * MEGABIT;
2448 wl_act_int_on( lp );
2450 wl_unlock(lp, &flags);
2453 DBG_LEAVE( DbgInfo );
2455 } // wireless_get_rate
2456 /*============================================================================*/
2461 #if 0 //;? Not used anymore
2462 /*******************************************************************************
2463 * wireless_get_private_interface()
2464 *******************************************************************************
2468 * Returns the Linux Wireless Extensions' compatible private interface of
2473 * wrq - the wireless request buffer
2474 * lp - the device's private adapter structure
2479 * errno value otherwise
2481 ******************************************************************************/
2482 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2485 /*------------------------------------------------------------------------*/
2488 DBG_FUNC( "wireless_get_private_interface" );
2489 DBG_ENTER( DbgInfo );
2491 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2496 if( wrq->u.data.pointer != NULL ) {
2497 struct iw_priv_args priv[] =
2499 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2500 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2501 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2502 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2503 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2504 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2507 /* Verify the user buffer */
2508 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2511 DBG_LEAVE( DbgInfo );
2515 /* Copy the data into the user's buffer */
2516 wrq->u.data.length = NELEM( priv );
2517 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2521 DBG_LEAVE( DbgInfo );
2523 } // wireless_get_private_interface
2524 /*============================================================================*/
2529 #if WIRELESS_EXT > 13
2531 /*******************************************************************************
2532 * wireless_set_scan()
2533 *******************************************************************************
2537 * Instructs the driver to initiate a network scan.
2541 * wrq - the wireless request buffer
2542 * lp - the device's private adapter structure
2547 * errno value otherwise
2549 ******************************************************************************/
2550 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2552 struct wl_private *lp = wl_priv(dev);
2553 unsigned long flags;
2557 /*------------------------------------------------------------------------*/
2559 //;? Note: shows results as trace, retruns always 0 unless BUSY
2561 DBG_FUNC( "wireless_set_scan" );
2562 DBG_ENTER( DbgInfo );
2564 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2569 wl_lock( lp, &flags );
2571 wl_act_int_off( lp );
2574 * This looks like a nice place to test if the HCF is still
2575 * communicating with the card. It seems that sometimes BAP_1
2576 * gets corrupted. By looking at the comments in HCF the
2577 * cause is still a mistery. Okay, the communication to the
2578 * card is dead, reset the card to revive.
2580 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2582 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2587 /* Set the completion state to FALSE */
2588 lp->probe_results.scan_complete = FALSE;
2591 /* Channels to scan */
2593 lp->ltvRecord.len = 5;
2594 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2595 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2596 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2597 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2598 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2600 lp->ltvRecord.len = 2;
2601 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2602 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2605 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2607 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2609 // Holding the lock too long, make a gap to allow other processes
2610 wl_unlock(lp, &flags);
2611 wl_lock( lp, &flags );
2613 if( status != HCF_SUCCESS ) {
2617 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2620 // Holding the lock too long, make a gap to allow other processes
2621 wl_unlock(lp, &flags);
2622 wl_lock( lp, &flags );
2628 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2629 disassociate from the network we are currently on */
2630 lp->ltvRecord.len = 18;
2631 lp->ltvRecord.typ = CFG_SCAN_SSID;
2632 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2633 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2635 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2637 // Holding the lock too long, make a gap to allow other processes
2638 wl_unlock(lp, &flags);
2639 wl_lock( lp, &flags );
2641 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2643 /* Initiate the scan */
2644 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2645 retrieve probe responses must always be used to support WPA */
2646 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2648 if( status == HCF_SUCCESS ) {
2649 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2651 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2654 wl_act_int_on( lp );
2656 wl_unlock(lp, &flags);
2661 } // wireless_set_scan
2662 /*============================================================================*/
2667 /*******************************************************************************
2668 * wireless_get_scan()
2669 *******************************************************************************
2673 * Instructs the driver to gather and return the results of a network scan.
2677 * wrq - the wireless request buffer
2678 * lp - the device's private adapter structure
2683 * errno value otherwise
2685 ******************************************************************************/
2686 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2688 struct wl_private *lp = wl_priv(dev);
2689 unsigned long flags;
2694 struct iw_event iwe;
2695 PROBE_RESP *probe_resp;
2699 /*------------------------------------------------------------------------*/
2702 DBG_FUNC( "wireless_get_scan" );
2703 DBG_ENTER( DbgInfo );
2705 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2710 wl_lock( lp, &flags );
2712 wl_act_int_off( lp );
2714 /* If the scan is not done, tell the calling process to try again later */
2715 if( !lp->probe_results.scan_complete ) {
2720 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2721 lp->probe_results.num_aps );
2724 buf_end = extra + IW_SCAN_MAX_DATA;
2726 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2727 /* Reference the probe response from the table */
2728 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2731 /* First entry MUST be the MAC address */
2732 memset( &iwe, 0, sizeof( iwe ));
2734 iwe.cmd = SIOCGIWAP;
2735 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2736 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2737 iwe.len = IW_EV_ADDR_LEN;
2739 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2742 /* Use the mode to indicate if it's a station or AP */
2743 /* Won't always be an AP if in IBSS mode */
2744 memset( &iwe, 0, sizeof( iwe ));
2746 iwe.cmd = SIOCGIWMODE;
2748 if( probe_resp->capability & CAPABILITY_IBSS ) {
2749 iwe.u.mode = IW_MODE_INFRA;
2751 iwe.u.mode = IW_MODE_MASTER;
2754 iwe.len = IW_EV_UINT_LEN;
2756 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2759 /* Any quality information */
2760 memset(&iwe, 0, sizeof(iwe));
2763 iwe.u.qual.level = dbm(probe_resp->signal);
2764 iwe.u.qual.noise = dbm(probe_resp->silence);
2765 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2766 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2767 iwe.len = IW_EV_QUAL_LEN;
2769 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2772 /* ESSID information */
2773 if( probe_resp->rawData[1] > 0 ) {
2774 memset( &iwe, 0, sizeof( iwe ));
2776 iwe.cmd = SIOCGIWESSID;
2777 iwe.u.data.length = probe_resp->rawData[1];
2778 iwe.u.data.flags = 1;
2780 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2784 /* Encryption Information */
2785 memset( &iwe, 0, sizeof( iwe ));
2787 iwe.cmd = SIOCGIWENCODE;
2788 iwe.u.data.length = 0;
2790 /* Check the capabilities field of the Probe Response to see if
2791 'privacy' is supported on the AP in question */
2792 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2793 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2795 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2798 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2801 /* Frequency Info */
2802 memset( &iwe, 0, sizeof( iwe ));
2804 iwe.cmd = SIOCGIWFREQ;
2805 iwe.len = IW_EV_FREQ_LEN;
2806 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2809 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2812 #if WIRELESS_EXT > 14
2813 /* Custom info (Beacon Interval) */
2814 memset( &iwe, 0, sizeof( iwe ));
2815 memset( msg, 0, sizeof( msg ));
2817 iwe.cmd = IWEVCUSTOM;
2818 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2819 iwe.u.data.length = strlen( msg );
2821 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2824 /* Custom info (WPA-IE) */
2828 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2829 if( wpa_ie != NULL ) {
2830 memset( &iwe, 0, sizeof( iwe ));
2831 memset( msg, 0, sizeof( msg ));
2833 iwe.cmd = IWEVCUSTOM;
2834 sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2835 iwe.u.data.length = strlen( msg );
2837 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2840 /* Add other custom info in formatted string format as needed... */
2844 data->length = buf - extra;
2848 wl_act_int_on( lp );
2850 wl_unlock(lp, &flags);
2853 DBG_LEAVE( DbgInfo );
2855 } // wireless_get_scan
2856 /*============================================================================*/
2858 #endif // WIRELESS_EXT > 13
2861 #if WIRELESS_EXT > 17
2863 static int wireless_set_auth(struct net_device *dev,
2864 struct iw_request_info *info,
2865 struct iw_param *data, char *extra)
2867 struct wl_private *lp = wl_priv(dev);
2868 unsigned long flags;
2870 int iwa_idx = data->flags & IW_AUTH_INDEX;
2871 int iwa_val = data->value;
2873 DBG_FUNC( "wireless_set_auth" );
2874 DBG_ENTER( DbgInfo );
2876 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2881 wl_lock( lp, &flags );
2883 wl_act_int_off( lp );
2886 case IW_AUTH_WPA_VERSION:
2887 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2888 /* We do support WPA only; how should DISABLED be treated? */
2889 if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2895 case IW_AUTH_WPA_ENABLED:
2896 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2898 lp->EnableEncryption = 2;
2900 lp->EnableEncryption = 0;
2904 case IW_AUTH_TKIP_COUNTERMEASURES:
2905 DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2906 lp->driverEnable = !iwa_val;
2907 if(lp->driverEnable)
2908 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2910 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2914 case IW_AUTH_DROP_UNENCRYPTED:
2915 DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2916 /* We do not actually do anything here, just to silence
2921 case IW_AUTH_CIPHER_PAIRWISE:
2922 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2923 /* not implemented, return an error */
2927 case IW_AUTH_CIPHER_GROUP:
2928 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2929 /* not implemented, return an error */
2933 case IW_AUTH_KEY_MGMT:
2934 DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2935 /* not implemented, return an error */
2939 case IW_AUTH_80211_AUTH_ALG:
2940 DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2941 /* not implemented, return an error */
2945 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2946 DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2947 /* not implemented, return an error */
2951 case IW_AUTH_ROAMING_CONTROL:
2952 DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2953 /* not implemented, return an error */
2957 case IW_AUTH_PRIVACY_INVOKED:
2958 DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2959 /* not implemented, return an error */
2964 DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2965 /* return an error */
2970 wl_act_int_on( lp );
2972 wl_unlock(lp, &flags);
2975 DBG_LEAVE( DbgInfo );
2977 } // wireless_set_auth
2978 /*============================================================================*/
2982 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
2983 int set_tx, u8 *seq, u8 *key, size_t key_len)
2988 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
2989 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
2991 DBG_FUNC( "hermes_set_key" );
2992 DBG_ENTER( DbgInfo );
2995 * Check the key index here; if 0, load as Pairwise Key, otherwise,
2996 * load as a group key. Note that for the Hermes, the RIDs for
2997 * group/pariwise keys are different from each other and different
2998 * than the default WEP keys as well.
3002 case IW_ENCODE_ALG_TKIP:
3003 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3006 * Make sure that there is no data queued up in the firmware
3007 * before setting the TKIP keys. If this check is not
3008 * performed, some data may be sent out with incorrect MIC
3009 * and cause synchronizarion errors with the AP
3011 /* Check every 1ms for 100ms */
3012 for( count = 0; count < 100; count++ )
3017 ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
3020 wl_get_info( sock, <v, ifname );
3022 if( ltv.u.u16[0] == 0 )
3030 wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
3037 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
3039 /* Load the BSSID */
3040 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
3041 buf_idx += ETH_ALEN;
3043 /* Load the TKIP key */
3044 memcpy(<v->u.u8[buf_idx], &key[0], 16);
3048 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3049 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3052 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3053 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3055 /* Load the TxMIC key */
3056 memcpy(<v->u.u8[buf_idx], &key[16], 8);
3059 /* Load the RxMIC key */
3060 memcpy(<v->u.u8[buf_idx], &key[24], 8);
3068 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3070 /* Load the key Index */
3071 ltv->u.u16[buf_idx] = key_idx;
3072 /* If this is a Tx Key, set bit 8000 */
3074 ltv->u.u16[buf_idx] |= 0x8000;
3078 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3079 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3081 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3082 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3083 memcpy(<v->u.u8[buf_idx], key, key_len);
3087 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3089 ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3099 case IW_ENCODE_ALG_WEP:
3100 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3103 case IW_ENCODE_ALG_CCMP:
3104 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3107 case IW_ENCODE_ALG_NONE:
3108 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3111 if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3112 //if (addr != NULL) {
3114 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3115 memcpy(<v->u.u8[0], addr, ETH_ALEN);
3122 /* Clear the Group TKIP keys by index */
3124 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3125 ltv->u.u16[0] = key_idx;
3134 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3138 DBG_LEAVE( DbgInfo );
3141 /*============================================================================*/
3145 static int wireless_set_encodeext (struct net_device *dev,
3146 struct iw_request_info *info,
3147 struct iw_point *erq, char *keybuf)
3149 struct wl_private *lp = wl_priv(dev);
3150 unsigned long flags;
3152 int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3154 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3156 DBG_FUNC( "wireless_set_encodeext" );
3157 DBG_ENTER( DbgInfo );
3159 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3164 if (sizeof(ext->rx_seq) != 8) {
3165 DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3170 /* Handle WEP keys via the old set encode procedure */
3171 if(ext->alg == IW_ENCODE_ALG_WEP) {
3172 struct iw_point wep_erq;
3175 /* Build request structure */
3176 wep_erq.flags = erq->flags; // take over flags with key index
3177 wep_erq.length = ext->key_len; // take length from extended key info
3178 wep_keybuf = ext->key; // pointer to the key text
3180 /* Call wireless_set_encode tot handle the WEP key */
3181 ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3185 /* Proceed for extended encode functions for WAP and NONE */
3186 wl_lock( lp, &flags );
3188 wl_act_int_off( lp );
3190 memset(<v, 0, sizeof(ltv));
3191 ret = hermes_set_key(<v, ext->alg, key_idx, ext->addr.sa_data,
3192 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3193 ext->rx_seq, ext->key, ext->key_len);
3196 DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3200 /* Put the key in HCF */
3201 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3204 if(ret == HCF_SUCCESS) {
3205 DBG_TRACE( DbgInfo, "Put key info succes\n");
3207 DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3210 wl_act_int_on( lp );
3212 wl_unlock(lp, &flags);
3215 DBG_LEAVE( DbgInfo );
3217 } // wireless_set_encodeext
3218 /*============================================================================*/
3222 static int wireless_get_genie(struct net_device *dev,
3223 struct iw_request_info *info,
3224 struct iw_point *data, char *extra)
3227 struct wl_private *lp = wl_priv(dev);
3228 unsigned long flags;
3232 DBG_FUNC( "wireless_get_genie" );
3233 DBG_ENTER( DbgInfo );
3235 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3240 wl_lock( lp, &flags );
3242 wl_act_int_off( lp );
3244 memset(<v, 0, sizeof(ltv));
3246 ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3247 lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3248 ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3250 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3252 wl_act_int_on( lp );
3254 wl_unlock(lp, &flags);
3257 DBG_LEAVE( DbgInfo );
3260 /*============================================================================*/
3263 #endif // WIRELESS_EXT > 17
3265 /*******************************************************************************
3266 * wl_wireless_stats()
3267 *******************************************************************************
3271 * Return the current device wireless statistics.
3275 * wrq - the wireless request buffer
3276 * lp - the device's private adapter structure
3281 * errno value otherwise
3283 ******************************************************************************/
3284 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3286 struct iw_statistics *pStats;
3287 struct wl_private *lp = wl_priv(dev);
3288 /*------------------------------------------------------------------------*/
3291 DBG_FUNC( "wl_wireless_stats" );
3293 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3297 /* Initialize the statistics */
3298 pStats = &( lp->wstats );
3299 pStats->qual.updated = 0x00;
3301 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3303 CFG_COMMS_QUALITY_STRCT *pQual;
3304 CFG_HERMES_TALLIES_STRCT tallies;
3307 /* Update driver status */
3310 /* Get the current link quality information */
3311 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3312 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3313 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3315 if( status == HCF_SUCCESS ) {
3316 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3319 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3320 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3321 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3323 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3324 IW_QUAL_LEVEL_UPDATED |
3325 IW_QUAL_NOISE_UPDATED |
3328 pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
3329 HCF_MIN_COMM_QUALITY,
3330 HCF_MAX_COMM_QUALITY );
3332 pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
3333 HCF_MIN_SIGNAL_LEVEL,
3334 HCF_MAX_SIGNAL_LEVEL );
3336 pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
3337 HCF_MIN_NOISE_LEVEL,
3338 HCF_MAX_NOISE_LEVEL );
3340 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3341 IW_QUAL_LEVEL_UPDATED |
3342 IW_QUAL_NOISE_UPDATED);
3343 #endif /* USE_DBM */
3345 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3348 /* Get the current tallies from the adapter */
3349 /* Only possible when the device is open */
3350 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3351 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3352 /* No endian translation is needed here, as CFG_TALLIES is an
3353 MSF RID; all processing is done on the host, not the card! */
3354 pStats->discard.nwid = 0L;
3355 pStats->discard.code = tallies.RxWEPUndecryptable;
3356 pStats->discard.misc = tallies.TxDiscards +
3357 tallies.RxFCSErrors +
3358 //tallies.RxDiscardsNoBuffer +
3359 tallies.TxDiscardsWrongSA;
3360 //;? Extra taken over from Linux driver based on 7.18 version
3361 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3362 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3364 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3367 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3371 DBG_LEAVE( DbgInfo );
3373 } // wl_wireless_stats
3374 /*============================================================================*/
3379 /*******************************************************************************
3380 * wl_get_wireless_stats()
3381 *******************************************************************************
3385 * Return the current device wireless statistics. This function calls
3386 * wl_wireless_stats, but acquires spinlocks first as it can be called
3387 * directly by the network layer.
3391 * wrq - the wireless request buffer
3392 * lp - the device's private adapter structure
3397 * errno value otherwise
3399 ******************************************************************************/
3400 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3402 unsigned long flags;
3403 struct wl_private *lp = wl_priv(dev);
3404 struct iw_statistics *pStats = NULL;
3405 /*------------------------------------------------------------------------*/
3407 DBG_FUNC( "wl_get_wireless_stats" );
3410 wl_lock( lp, &flags );
3412 wl_act_int_off( lp );
3415 if( lp->useRTS == 1 ) {
3416 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3420 pStats = wl_wireless_stats( dev );
3422 wl_act_int_on( lp );
3424 wl_unlock(lp, &flags);
3426 DBG_LEAVE( DbgInfo );
3428 } // wl_get_wireless_stats
3431 /*******************************************************************************
3433 *******************************************************************************
3437 * Gather wireless spy statistics.
3441 * wrq - the wireless request buffer
3442 * lp - the device's private adapter structure
3447 * errno value otherwise
3449 ******************************************************************************/
3450 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3452 struct iw_quality wstats;
3456 struct wl_private *lp = wl_priv(dev);
3457 /*------------------------------------------------------------------------*/
3460 if (!lp->spy_data.spy_number) {
3464 /* Gather wireless spy statistics: for each packet, compare the source
3465 address with out list, and if match, get the stats. */
3466 memset( stats, 0, sizeof(stats));
3467 memset( desc, 0, sizeof(DESC_STRCT));
3469 desc[0].buf_addr = stats;
3470 desc[0].BUF_SIZE = sizeof(stats);
3471 desc[0].next_desc_addr = 0; // terminate list
3473 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3475 if( status == HCF_SUCCESS ) {
3476 wstats.level = (u_char) dbm(stats[1]);
3477 wstats.noise = (u_char) dbm(stats[0]);
3478 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3480 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3481 IW_QUAL_LEVEL_UPDATED |
3482 IW_QUAL_NOISE_UPDATED |
3485 wireless_spy_update( dev, mac, &wstats );
3488 /*============================================================================*/
3493 /*******************************************************************************
3494 * wl_wext_event_freq()
3495 *******************************************************************************
3499 * This function is used to send an event that the channel/freq
3500 * configuration for a specific device has changed.
3505 * dev - the network device for which this event is to be issued
3511 ******************************************************************************/
3512 void wl_wext_event_freq( struct net_device *dev )
3514 #if WIRELESS_EXT > 13
3515 union iwreq_data wrqu;
3516 struct wl_private *lp = wl_priv(dev);
3517 /*------------------------------------------------------------------------*/
3520 memset( &wrqu, 0, sizeof( wrqu ));
3522 wrqu.freq.m = lp->Channel;
3525 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3526 #endif /* WIRELESS_EXT > 13 */
3529 } // wl_wext_event_freq
3530 /*============================================================================*/
3535 /*******************************************************************************
3536 * wl_wext_event_mode()
3537 *******************************************************************************
3541 * This function is used to send an event that the mode of operation
3542 * for a specific device has changed.
3547 * dev - the network device for which this event is to be issued
3553 ******************************************************************************/
3554 void wl_wext_event_mode( struct net_device *dev )
3556 #if WIRELESS_EXT > 13
3557 union iwreq_data wrqu;
3558 struct wl_private *lp = wl_priv(dev);
3559 /*------------------------------------------------------------------------*/
3562 memset( &wrqu, 0, sizeof( wrqu ));
3564 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3565 wrqu.mode = IW_MODE_INFRA;
3567 wrqu.mode = IW_MODE_MASTER;
3570 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3571 #endif /* WIRELESS_EXT > 13 */
3574 } // wl_wext_event_mode
3575 /*============================================================================*/
3580 /*******************************************************************************
3581 * wl_wext_event_essid()
3582 *******************************************************************************
3586 * This function is used to send an event that the ESSID configuration for
3587 * a specific device has changed.
3592 * dev - the network device for which this event is to be issued
3598 ******************************************************************************/
3599 void wl_wext_event_essid( struct net_device *dev )
3601 #if WIRELESS_EXT > 13
3602 union iwreq_data wrqu;
3603 struct wl_private *lp = wl_priv(dev);
3604 /*------------------------------------------------------------------------*/
3607 memset( &wrqu, 0, sizeof( wrqu ));
3609 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3610 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3611 the call to wireless_send_event() must also point to where the ESSID
3613 wrqu.essid.length = strlen( lp->NetworkName );
3614 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3615 wrqu.essid.flags = 1;
3617 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3618 #endif /* WIRELESS_EXT > 13 */
3621 } // wl_wext_event_essid
3622 /*============================================================================*/
3627 /*******************************************************************************
3628 * wl_wext_event_encode()
3629 *******************************************************************************
3633 * This function is used to send an event that the encryption configuration
3634 * for a specific device has changed.
3639 * dev - the network device for which this event is to be issued
3645 ******************************************************************************/
3646 void wl_wext_event_encode( struct net_device *dev )
3648 #if WIRELESS_EXT > 13
3649 union iwreq_data wrqu;
3650 struct wl_private *lp = wl_priv(dev);
3652 /*------------------------------------------------------------------------*/
3655 memset( &wrqu, 0, sizeof( wrqu ));
3657 if( lp->EnableEncryption == 0 ) {
3658 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3660 wrqu.encoding.flags |= lp->TransmitKeyID;
3662 index = lp->TransmitKeyID - 1;
3664 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3665 if we're in AP mode */
3666 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3667 //;?should we restore this to allow smaller memory footprint
3669 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3670 if( lp->ExcludeUnencrypted ) {
3671 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3673 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3677 #endif // HCF_TYPE_AP
3679 /* Only provide the key if permissions allow */
3680 if( capable( CAP_NET_ADMIN )) {
3681 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3682 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3684 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3688 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3689 lp->DefaultKeys.key[index].key );
3690 #endif /* WIRELESS_EXT > 13 */
3693 } // wl_wext_event_encode
3694 /*============================================================================*/
3699 /*******************************************************************************
3700 * wl_wext_event_ap()
3701 *******************************************************************************
3705 * This function is used to send an event that the device has been
3706 * associated to a new AP.
3711 * dev - the network device for which this event is to be issued
3717 ******************************************************************************/
3718 void wl_wext_event_ap( struct net_device *dev )
3720 #if WIRELESS_EXT > 13
3721 union iwreq_data wrqu;
3722 struct wl_private *lp = wl_priv(dev);
3724 /*------------------------------------------------------------------------*/
3727 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3728 this event BEFORE sending the association event, as there are timing
3729 issues with the hostap supplicant. The supplicant will attempt to process
3730 an EAPOL-Key frame from an AP before receiving this information, which
3731 is required properly process the said frame. */
3732 wl_wext_event_assoc_ie( dev );
3735 lp->ltvRecord.typ = CFG_CUR_BSSID;
3736 lp->ltvRecord.len = 4;
3738 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3739 if( status == HCF_SUCCESS ) {
3740 memset( &wrqu, 0, sizeof( wrqu ));
3742 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3744 wrqu.addr.sa_family = ARPHRD_ETHER;
3746 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3749 #endif /* WIRELESS_EXT > 13 */
3752 } // wl_wext_event_ap
3753 /*============================================================================*/
3757 /*******************************************************************************
3758 * wl_wext_event_scan_complete()
3759 *******************************************************************************
3763 * This function is used to send an event that a request for a network scan
3769 * dev - the network device for which this event is to be issued
3775 ******************************************************************************/
3776 void wl_wext_event_scan_complete( struct net_device *dev )
3778 #if WIRELESS_EXT > 13
3779 union iwreq_data wrqu;
3780 /*------------------------------------------------------------------------*/
3783 memset( &wrqu, 0, sizeof( wrqu ));
3785 wrqu.addr.sa_family = ARPHRD_ETHER;
3786 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3787 #endif /* WIRELESS_EXT > 13 */
3790 } // wl_wext_event_scan_complete
3791 /*============================================================================*/
3796 /*******************************************************************************
3797 * wl_wext_event_new_sta()
3798 *******************************************************************************
3802 * This function is used to send an event that an AP has registered a new
3808 * dev - the network device for which this event is to be issued
3814 ******************************************************************************/
3815 void wl_wext_event_new_sta( struct net_device *dev )
3817 #if WIRELESS_EXT > 14
3818 union iwreq_data wrqu;
3819 /*------------------------------------------------------------------------*/
3822 memset( &wrqu, 0, sizeof( wrqu ));
3824 /* Send the station's mac address here */
3825 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3826 wrqu.addr.sa_family = ARPHRD_ETHER;
3827 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3828 #endif /* WIRELESS_EXT > 14 */
3831 } // wl_wext_event_new_sta
3832 /*============================================================================*/
3837 /*******************************************************************************
3838 * wl_wext_event_expired_sta()
3839 *******************************************************************************
3843 * This function is used to send an event that an AP has deregistered a
3849 * dev - the network device for which this event is to be issued
3855 ******************************************************************************/
3856 void wl_wext_event_expired_sta( struct net_device *dev )
3858 #if WIRELESS_EXT > 14
3859 union iwreq_data wrqu;
3860 /*------------------------------------------------------------------------*/
3863 memset( &wrqu, 0, sizeof( wrqu ));
3865 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3866 wrqu.addr.sa_family = ARPHRD_ETHER;
3867 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3868 #endif /* WIRELESS_EXT > 14 */
3871 } // wl_wext_event_expired_sta
3872 /*============================================================================*/
3877 /*******************************************************************************
3878 * wl_wext_event_mic_failed()
3879 *******************************************************************************
3883 * This function is used to send an event that MIC calculations failed.
3888 * dev - the network device for which this event is to be issued
3894 ******************************************************************************/
3895 void wl_wext_event_mic_failed( struct net_device *dev )
3897 #if WIRELESS_EXT > 14
3899 union iwreq_data wrqu;
3900 struct wl_private *lp = wl_priv(dev);
3904 WVLAN_RX_WMP_HDR *hdr;
3905 /*------------------------------------------------------------------------*/
3908 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3911 /* Cast the lookahead buffer into a RFS format */
3912 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3914 /* Cast the addresses to byte buffers, as in the above RFS they are word
3916 addr1 = (char *)hdr->address1;
3917 addr2 = (char *)hdr->address2;
3919 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3922 memset( &wrqu, 0, sizeof( wrqu ));
3923 memset( msg, 0, sizeof( msg ));
3926 /* Becuase MIC failures are not part of the Wireless Extensions yet, they
3927 must be passed as a string using an IWEVCUSTOM event. In order for the
3928 event to be effective, the string format must be known by both the
3929 driver and the supplicant. The following is the string format used by the
3930 hostap project's WPA supplicant, and will be used here until the Wireless
3931 Extensions interface adds this support:
3933 MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
3936 /* NOTE: Format of MAC address (using colons to separate bytes) may cause
3937 a problem in future versions of the supplicant, if they ever
3938 actually parse these parameters */
3940 sprintf( msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
3941 "%s)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
3942 DbgHwAddr( addr2 ));
3944 wrqu.data.length = strlen( msg );
3945 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
3946 #endif /* WIRELESS_EXT > 14 */
3949 } // wl_wext_event_mic_failed
3950 /*============================================================================*/
3955 /*******************************************************************************
3956 * wl_wext_event_assoc_ie()
3957 *******************************************************************************
3961 * This function is used to send an event containing the WPA-IE generated
3962 * by the firmware in an association request.
3967 * dev - the network device for which this event is to be issued
3973 ******************************************************************************/
3974 void wl_wext_event_assoc_ie( struct net_device *dev )
3976 #if WIRELESS_EXT > 14
3978 union iwreq_data wrqu;
3979 struct wl_private *lp = wl_priv(dev);
3984 /*------------------------------------------------------------------------*/
3987 memset( &wrqu, 0, sizeof( wrqu ));
3988 memset( msg, 0, sizeof( msg ));
3990 /* Retrieve the Association Request IE */
3991 lp->ltvRecord.len = 45;
3992 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3994 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3995 if( status == HCF_SUCCESS )
3998 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3999 wpa_ie = wl_parse_wpa_ie( &data, &length );
4001 /* Becuase this event (Association WPA-IE) is not part of the Wireless
4002 Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
4003 In order for the event to be effective, the string format must be known
4004 by both the driver and the supplicant. The following is the string format
4005 used by the hostap project's WPA supplicant, and will be used here until
4006 the Wireless Extensions interface adds this support:
4008 ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
4013 sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
4014 wrqu.data.length = strlen( msg );
4015 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
4018 #endif /* WIRELESS_EXT > 14 */
4021 } // wl_wext_event_assoc_ie
4022 /*============================================================================*/
4023 /* Structures to export the Wireless Handlers */
4025 static const iw_handler wl_handler[] =
4027 (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */
4028 (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */
4029 (iw_handler) NULL, /* SIOCSIWNWID */
4030 (iw_handler) NULL, /* SIOCGIWNWID */
4031 (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */
4032 (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */
4033 (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */
4034 (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */
4035 (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */
4036 (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */
4037 (iw_handler) NULL , /* SIOCSIWRANGE */
4038 (iw_handler) wireless_get_range, /* SIOCGIWRANGE */
4039 (iw_handler) NULL , /* SIOCSIWPRIV */
4040 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
4041 (iw_handler) NULL , /* SIOCSIWSTATS */
4042 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
4043 iw_handler_set_spy, /* SIOCSIWSPY */
4044 iw_handler_get_spy, /* SIOCGIWSPY */
4045 NULL, /* SIOCSIWTHRSPY */
4046 NULL, /* SIOCGIWTHRSPY */
4047 (iw_handler) NULL, /* SIOCSIWAP */
4048 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4049 (iw_handler) wireless_get_bssid, /* SIOCGIWAP */
4051 (iw_handler) NULL, /* SIOCGIWAP */
4053 (iw_handler) NULL, /* SIOCSIWMLME */
4054 (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */
4055 (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */
4056 (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */
4057 (iw_handler) wireless_set_essid, /* SIOCSIWESSID */
4058 (iw_handler) wireless_get_essid, /* SIOCGIWESSID */
4059 (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */
4060 (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */
4061 (iw_handler) NULL, /* -- hole -- */
4062 (iw_handler) NULL, /* -- hole -- */
4063 (iw_handler) wireless_set_rate, /* SIOCSIWRATE */
4064 (iw_handler) wireless_get_rate, /* SIOCGIWRATE */
4065 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
4066 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
4067 (iw_handler) NULL, /* SIOCSIWFRAG */
4068 (iw_handler) NULL, /* SIOCGIWFRAG */
4069 (iw_handler) NULL, /* SIOCSIWTXPOW */
4070 (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */
4071 (iw_handler) NULL, /* SIOCSIWRETRY */
4072 (iw_handler) NULL, /* SIOCGIWRETRY */
4073 (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */
4074 (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */
4075 (iw_handler) wireless_set_power, /* SIOCSIWPOWER */
4076 (iw_handler) wireless_get_power, /* SIOCGIWPOWER */
4077 (iw_handler) NULL, /* -- hole -- */
4078 (iw_handler) NULL, /* -- hole -- */
4079 (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */
4080 (iw_handler) NULL, /* SIOCGIWGENIE */
4081 (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */
4082 (iw_handler) NULL, /* SIOCGIWAUTH */
4083 (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */
4084 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
4085 (iw_handler) NULL, /* SIOCSIWPMKSA */
4086 (iw_handler) NULL, /* -- hole -- */
4089 static const iw_handler wl_private_handler[] =
4090 { /* SIOCIWFIRSTPRIV + */
4091 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
4092 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
4093 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
4094 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
4095 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4096 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
4097 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
4101 struct iw_priv_args wl_priv_args[] = {
4102 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
4103 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
4104 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
4105 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
4106 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
4107 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
4108 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
4112 const struct iw_handler_def wl_iw_handler_def =
4114 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
4115 .private = (iw_handler *) wl_private_handler,
4116 .private_args = (struct iw_priv_args *) wl_priv_args,
4117 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
4118 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
4119 .standard = (iw_handler *) wl_handler,
4120 .get_wireless_stats = wl_get_wireless_stats,
4123 #endif // WIRELESS_EXT