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: %pM\n",
793 (*p).ProbeTable[count].BSSID);
794 memcpy( hwa[count].sa_data,
795 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
798 /* Once the data is copied to the wireless struct, invalidate the
799 scan result to initiate a rescan on the next request */
800 (*p)/*lp->probe_results*/.scan_complete = FALSE;
801 /* Send the wireless event that the scan has completed, just in case
803 wl_wext_event_scan_complete( lp->dev );
807 DBG_LEAVE( DbgInfo );
809 } // wireless_get_ap_list
810 /*============================================================================*/
815 /*******************************************************************************
816 * wireless_set_sensitivity()
817 *******************************************************************************
821 * Sets the sensitivity (distance between APs) of the wireless card.
825 * wrq - the wireless request buffer
826 * lp - the device's private adapter structure
831 * errno value otherwise
833 ******************************************************************************/
834 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
836 struct wl_private *lp = wl_priv(dev);
839 int dens = sens->value;
840 /*------------------------------------------------------------------------*/
843 DBG_FUNC( "wireless_set_sensitivity" );
844 DBG_ENTER( DbgInfo );
846 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
851 if(( dens < 1 ) || ( dens > 3 )) {
856 wl_lock( lp, &flags );
858 wl_act_int_off( lp );
860 lp->DistanceBetweenAPs = dens;
865 wl_unlock(lp, &flags);
868 DBG_LEAVE( DbgInfo );
870 } // wireless_set_sensitivity
871 /*============================================================================*/
876 /*******************************************************************************
877 * wireless_get_sensitivity()
878 *******************************************************************************
882 * Gets the sensitivity (distance between APs) of the wireless card.
886 * wrq - the wireless request buffer
887 * lp - the device's private adapter structure
892 * errno value otherwise
894 ******************************************************************************/
895 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
897 struct wl_private *lp = wl_priv(dev);
899 /*------------------------------------------------------------------------*/
900 /*------------------------------------------------------------------------*/
903 DBG_FUNC( "wireless_get_sensitivity" );
904 DBG_ENTER( DbgInfo );
906 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
911 /* not worth locking ... */
912 sens->value = lp->DistanceBetweenAPs;
913 sens->fixed = 0; /* auto */
915 DBG_LEAVE( DbgInfo );
917 } // wireless_get_sensitivity
918 /*============================================================================*/
923 /*******************************************************************************
924 * wireless_set_essid()
925 *******************************************************************************
929 * Sets the ESSID (network name) that the wireless device should associate
934 * wrq - the wireless request buffer
935 * lp - the device's private adapter structure
940 * errno value otherwise
942 ******************************************************************************/
943 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
945 struct wl_private *lp = wl_priv(dev);
949 DBG_FUNC( "wireless_set_essid" );
950 DBG_ENTER( DbgInfo );
952 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
957 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
962 wl_lock( lp, &flags );
964 wl_act_int_off( lp );
966 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
968 /* data->flags is zero to ask for "any" */
969 if( data->flags == 0 ) {
970 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
971 * ;?but there ain't no STAP anymore*/
972 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
973 strcpy( lp->NetworkName, "ANY" );
975 //strcpy( lp->NetworkName, "ANY" );
976 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
979 memcpy( lp->NetworkName, ssid, data->length );
982 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
984 /* Commit the adapter parameters */
987 /* Send an event that ESSID has been set */
988 wl_wext_event_essid( lp->dev );
992 wl_unlock(lp, &flags);
995 DBG_LEAVE( DbgInfo );
997 } // wireless_set_essid
998 /*============================================================================*/
1003 /*******************************************************************************
1004 * wireless_get_essid()
1005 *******************************************************************************
1009 * Gets the ESSID (network name) that the wireless device is associated
1014 * wrq - the wireless request buffer
1015 * lp - the device's private adapter structure
1020 * errno value otherwise
1022 ******************************************************************************/
1023 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1026 struct wl_private *lp = wl_priv(dev);
1027 unsigned long flags;
1031 /*------------------------------------------------------------------------*/
1034 DBG_FUNC( "wireless_get_essid" );
1035 DBG_ENTER( DbgInfo );
1037 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1042 wl_lock( lp, &flags );
1044 wl_act_int_off( lp );
1046 /* Get the desired network name */
1047 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1050 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1051 //;?should we return an error status in AP mode
1053 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1058 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1059 //;?should we restore this to allow smaller memory footprint
1061 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1062 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1068 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1069 if( status == HCF_SUCCESS ) {
1070 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1072 /* Endian translate the string length */
1073 pName->length = CNV_LITTLE_TO_INT( pName->length );
1075 /* Copy the information into the user buffer */
1076 data->length = pName->length;
1078 /* NOTE: Null terminating is necessary for proper display of the SSID in
1079 the wireless tools */
1080 data->length = pName->length + 1;
1081 if( pName->length < HCF_MAX_NAME_LEN ) {
1082 pName->name[pName->length] = '\0';
1088 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1089 //;?should we return an error status in AP mode
1090 #ifdef RETURN_CURRENT_NETWORKNAME
1092 /* if desired is null ("any"), return current or "any" */
1093 if( pName->name[0] == '\0' ) {
1094 /* Get the current network name */
1095 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1096 lp->ltvRecord.typ = CFG_CUR_SSID;
1098 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1100 if( status == HCF_SUCCESS ) {
1101 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1103 /* Endian translate the string length */
1104 pName->length = CNV_LITTLE_TO_INT( pName->length );
1106 /* Copy the information into the user buffer */
1107 data->length = pName->length + 1;
1108 if( pName->length < HCF_MAX_NAME_LEN ) {
1109 pName->name[pName->length] = '\0';
1119 #endif // RETURN_CURRENT_NETWORKNAME
1124 if (pName->length > IW_ESSID_MAX_SIZE) {
1129 memcpy(essid, pName->name, pName->length);
1136 wl_act_int_on( lp );
1138 wl_unlock(lp, &flags);
1141 DBG_LEAVE( DbgInfo );
1143 } // wireless_get_essid
1144 /*============================================================================*/
1149 /*******************************************************************************
1150 * wireless_set_encode()
1151 *******************************************************************************
1155 * Sets the encryption keys and status (enable or disable).
1159 * wrq - the wireless request buffer
1160 * lp - the device's private adapter structure
1165 * errno value otherwise
1167 ******************************************************************************/
1168 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1170 struct wl_private *lp = wl_priv(dev);
1171 unsigned long flags;
1174 #if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
1175 hcf_8 encryption_state;
1176 #endif // WIRELESS_EXT > 8
1177 /*------------------------------------------------------------------------*/
1180 DBG_FUNC( "wireless_set_encode" );
1181 DBG_ENTER( DbgInfo );
1183 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1188 wl_lock( lp, &flags );
1190 wl_act_int_off( lp );
1192 /* Is encryption supported? */
1193 if( !wl_has_wep( &( lp->hcfCtx ))) {
1194 DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1199 DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1200 keybuf, erq->length,
1203 /* Save state of Encryption switch */
1204 encryption_state = lp->EnableEncryption;
1206 /* Basic checking: do we have a key to set? */
1207 if((erq->length) != 0) {
1208 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1209 int tk = lp->TransmitKeyID - 1; // current key
1212 /* Check the size of the key */
1213 switch(erq->length) {
1220 /* Check the index */
1221 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1226 memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1228 /* Copy the key in the driver */
1229 memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1231 /* Set the length */
1232 lp->DefaultKeys.key[index].len = erq->length;
1234 DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1235 DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1236 lp->DefaultKeys.key[index].len, index );
1238 /* Enable WEP (if possible) */
1239 if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1240 lp->EnableEncryption = 1;
1246 DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1251 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1254 /* Do we want to just set the current transmit key? */
1255 if(( index >= 0 ) && ( index < MAX_KEYS )) {
1256 DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1257 lp->DefaultKeys.key[index].len );
1259 if( lp->DefaultKeys.key[index].len > 0 ) {
1260 lp->TransmitKeyID = index + 1;
1261 lp->EnableEncryption = 1;
1263 DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1264 DBG_LEAVE( DbgInfo );
1270 /* Read the flags */
1271 if( erq->flags & IW_ENCODE_DISABLED ) {
1272 lp->EnableEncryption = 0; // disable encryption
1274 lp->EnableEncryption = 1;
1277 if( erq->flags & IW_ENCODE_RESTRICTED ) {
1278 DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1279 ret = -EINVAL; // Invalid
1282 DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state );
1283 DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption );
1284 DBG_TRACE( DbgInfo, "erq->length : %d\n",
1286 DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n",
1289 /* Write the changes to the card */
1291 DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1292 lp->TransmitKeyID );
1294 if( lp->EnableEncryption == encryption_state ) {
1295 if( erq->length != 0 ) {
1296 /* Dynamic WEP key update */
1297 wl_set_wep_keys( lp );
1300 /* To switch encryption on/off, soft reset is required */
1305 /* Send an event that Encryption has been set */
1306 wl_wext_event_encode( dev );
1310 wl_act_int_on( lp );
1312 wl_unlock(lp, &flags);
1315 DBG_LEAVE( DbgInfo );
1317 } // wireless_set_encode
1318 /*============================================================================*/
1323 /*******************************************************************************
1324 * wireless_get_encode()
1325 *******************************************************************************
1329 * Gets the encryption keys and status.
1333 * wrq - the wireless request buffer
1334 * lp - the device's private adapter structure
1339 * errno value otherwise
1341 ******************************************************************************/
1342 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1345 struct wl_private *lp = wl_priv(dev);
1346 unsigned long flags;
1349 /*------------------------------------------------------------------------*/
1352 DBG_FUNC( "wireless_get_encode" );
1353 DBG_ENTER( DbgInfo );
1354 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1356 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1361 /* Only super-user can see WEP key */
1362 if( !capable( CAP_NET_ADMIN )) {
1364 DBG_LEAVE( DbgInfo );
1368 wl_lock( lp, &flags );
1370 wl_act_int_off( lp );
1372 /* Is it supported? */
1373 if( !wl_has_wep( &( lp->hcfCtx ))) {
1378 /* Basic checking */
1379 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1385 if( lp->EnableEncryption == 0 ) {
1386 erq->flags |= IW_ENCODE_DISABLED;
1389 /* Which key do we want */
1390 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1391 index = lp->TransmitKeyID - 1;
1394 erq->flags |= index + 1;
1396 /* Copy the key to the user buffer */
1397 erq->length = lp->DefaultKeys.key[index].len;
1399 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1403 wl_act_int_on( lp );
1405 wl_unlock(lp, &flags);
1408 DBG_LEAVE( DbgInfo );
1410 } // wireless_get_encode
1411 /*============================================================================*/
1416 /*******************************************************************************
1417 * wireless_set_nickname()
1418 *******************************************************************************
1422 * Sets the nickname, or station name, of the wireless device.
1426 * wrq - the wireless request buffer
1427 * lp - the device's private adapter structure
1432 * errno value otherwise
1434 ******************************************************************************/
1435 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1437 struct wl_private *lp = wl_priv(dev);
1438 unsigned long flags;
1440 /*------------------------------------------------------------------------*/
1443 DBG_FUNC( "wireless_set_nickname" );
1444 DBG_ENTER( DbgInfo );
1446 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1451 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1452 if( !capable(CAP_NET_ADMIN )) {
1454 DBG_LEAVE( DbgInfo );
1459 /* Validate the new value */
1460 if(data->length > HCF_MAX_NAME_LEN) {
1465 wl_lock( lp, &flags );
1467 wl_act_int_off( lp );
1469 memset( lp->StationName, 0, sizeof( lp->StationName ));
1471 memcpy( lp->StationName, nickname, data->length );
1473 /* Commit the adapter parameters */
1476 wl_act_int_on( lp );
1478 wl_unlock(lp, &flags);
1481 DBG_LEAVE( DbgInfo );
1483 } // wireless_set_nickname
1484 /*============================================================================*/
1489 /*******************************************************************************
1490 * wireless_get_nickname()
1491 *******************************************************************************
1495 * Gets the nickname, or station name, of the wireless device.
1499 * wrq - the wireless request buffer
1500 * lp - the device's private adapter structure
1505 * errno value otherwise
1507 ******************************************************************************/
1508 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1510 struct wl_private *lp = wl_priv(dev);
1511 unsigned long flags;
1515 /*------------------------------------------------------------------------*/
1518 DBG_FUNC( "wireless_get_nickname" );
1519 DBG_ENTER( DbgInfo );
1521 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1526 wl_lock( lp, &flags );
1528 wl_act_int_off( lp );
1530 /* Get the current station name */
1531 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1532 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1534 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1536 if( status == HCF_SUCCESS ) {
1537 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1539 /* Endian translate the length */
1540 pName->length = CNV_LITTLE_TO_INT( pName->length );
1542 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1545 /* Copy the information into the user buffer */
1546 data->length = pName->length;
1547 memcpy(nickname, pName->name, pName->length);
1553 wl_act_int_on( lp );
1555 wl_unlock(lp, &flags);
1560 } // wireless_get_nickname
1561 /*============================================================================*/
1566 /*******************************************************************************
1567 * wireless_set_porttype()
1568 *******************************************************************************
1572 * Sets the port type of the wireless device.
1576 * wrq - the wireless request buffer
1577 * lp - the device's private adapter structure
1582 * errno value otherwise
1584 ******************************************************************************/
1585 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1587 struct wl_private *lp = wl_priv(dev);
1588 unsigned long flags;
1592 /*------------------------------------------------------------------------*/
1594 DBG_FUNC( "wireless_set_porttype" );
1595 DBG_ENTER( DbgInfo );
1597 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1602 wl_lock( lp, &flags );
1604 wl_act_int_off( lp );
1606 /* Validate the new value */
1610 /* When user requests ad-hoc, set IBSS mode! */
1614 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1622 /* Both automatic and infrastructure set port to BSS/STA mode */
1626 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1631 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1633 case IW_MODE_MASTER:
1635 /* Set BSS/AP mode */
1639 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1643 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1653 if( portType != 0 ) {
1654 /* Only do something if there is a mode change */
1655 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1656 lp->PortType = portType;
1657 lp->CreateIBSS = createIBSS;
1659 /* Commit the adapter parameters */
1662 /* Send an event that mode has been set */
1663 wl_wext_event_mode( lp->dev );
1667 wl_act_int_on( lp );
1669 wl_unlock(lp, &flags);
1672 DBG_LEAVE( DbgInfo );
1674 } // wireless_set_porttype
1675 /*============================================================================*/
1680 /*******************************************************************************
1681 * wireless_get_porttype()
1682 *******************************************************************************
1686 * Gets the port type of the wireless device.
1690 * wrq - the wireless request buffer
1691 * lp - the device's private adapter structure
1696 * errno value otherwise
1698 ******************************************************************************/
1699 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1702 struct wl_private *lp = wl_priv(dev);
1703 unsigned long flags;
1707 /*------------------------------------------------------------------------*/
1710 DBG_FUNC( "wireless_get_porttype" );
1711 DBG_ENTER( DbgInfo );
1713 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1718 wl_lock( lp, &flags );
1720 wl_act_int_off( lp );
1722 /* Get the current port type */
1723 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1724 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1726 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1728 if( status == HCF_SUCCESS ) {
1729 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1731 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1733 switch( *pPortType ) {
1737 #if (HCF_TYPE) & HCF_TYPE_AP
1739 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1740 *mode = IW_MODE_MASTER;
1742 *mode = IW_MODE_INFRA;
1747 *mode = IW_MODE_INFRA;
1749 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1752 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1753 *mode = IW_MODE_MASTER;
1755 if( lp->CreateIBSS ) {
1756 *mode = IW_MODE_ADHOC;
1758 *mode = IW_MODE_INFRA;
1766 *mode = IW_MODE_ADHOC;
1777 wl_act_int_on( lp );
1779 wl_unlock(lp, &flags);
1782 DBG_LEAVE( DbgInfo );
1784 } // wireless_get_porttype
1785 /*============================================================================*/
1790 /*******************************************************************************
1791 * wireless_set_power()
1792 *******************************************************************************
1796 * Sets the power management settings of the wireless device.
1800 * wrq - the wireless request buffer
1801 * lp - the device's private adapter structure
1806 * errno value otherwise
1808 ******************************************************************************/
1809 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1811 struct wl_private *lp = wl_priv(dev);
1812 unsigned long flags;
1814 /*------------------------------------------------------------------------*/
1817 DBG_FUNC( "wireless_set_power" );
1818 DBG_ENTER( DbgInfo );
1820 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1825 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1827 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1828 if( !capable( CAP_NET_ADMIN )) {
1831 DBG_LEAVE( DbgInfo );
1836 wl_lock( lp, &flags );
1838 wl_act_int_off( lp );
1840 /* Set the power management state based on the 'disabled' value */
1841 if( wrq->disabled ) {
1847 /* Commit the adapter parameters */
1850 wl_act_int_on( lp );
1852 wl_unlock(lp, &flags);
1855 DBG_LEAVE( DbgInfo );
1857 } // wireless_set_power
1858 /*============================================================================*/
1863 /*******************************************************************************
1864 * wireless_get_power()
1865 *******************************************************************************
1869 * Gets the power management settings of the wireless device.
1873 * wrq - the wireless request buffer
1874 * lp - the device's private adapter structure
1879 * errno value otherwise
1881 ******************************************************************************/
1882 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1885 struct wl_private *lp = wl_priv(dev);
1886 unsigned long flags;
1888 /*------------------------------------------------------------------------*/
1889 DBG_FUNC( "wireless_get_power" );
1890 DBG_ENTER( DbgInfo );
1892 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1897 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1899 wl_lock( lp, &flags );
1901 wl_act_int_off( lp );
1906 if( lp->PMEnabled ) {
1912 wl_act_int_on( lp );
1914 wl_unlock(lp, &flags);
1917 DBG_LEAVE( DbgInfo );
1919 } // wireless_get_power
1920 /*============================================================================*/
1925 /*******************************************************************************
1926 * wireless_get_tx_power()
1927 *******************************************************************************
1931 * Gets the transmit power of the wireless device's radio.
1935 * wrq - the wireless request buffer
1936 * lp - the device's private adapter structure
1941 * errno value otherwise
1943 ******************************************************************************/
1944 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1946 struct wl_private *lp = wl_priv(dev);
1947 unsigned long flags;
1949 /*------------------------------------------------------------------------*/
1950 DBG_FUNC( "wireless_get_tx_power" );
1951 DBG_ENTER( DbgInfo );
1953 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1958 wl_lock( lp, &flags );
1960 wl_act_int_off( lp );
1962 #ifdef USE_POWER_DBM
1963 rrq->value = RADIO_TX_POWER_DBM;
1964 rrq->flags = IW_TXPOW_DBM;
1966 rrq->value = RADIO_TX_POWER_MWATT;
1967 rrq->flags = IW_TXPOW_MWATT;
1972 wl_act_int_on( lp );
1974 wl_unlock(lp, &flags);
1977 DBG_LEAVE( DbgInfo );
1979 } // wireless_get_tx_power
1980 /*============================================================================*/
1985 /*******************************************************************************
1986 * wireless_set_rts_threshold()
1987 *******************************************************************************
1991 * Sets the RTS threshold for the wireless card.
1995 * wrq - the wireless request buffer
1996 * lp - the device's private adapter structure
2001 * errno value otherwise
2003 ******************************************************************************/
2004 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2007 struct wl_private *lp = wl_priv(dev);
2008 unsigned long flags;
2009 int rthr = rts->value;
2010 /*------------------------------------------------------------------------*/
2013 DBG_FUNC( "wireless_set_rts_threshold" );
2014 DBG_ENTER( DbgInfo );
2016 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2021 if(rts->fixed == 0) {
2026 #if WIRELESS_EXT > 8
2027 if( rts->disabled ) {
2030 #endif /* WIRELESS_EXT > 8 */
2032 if(( rthr < 256 ) || ( rthr > 2347 )) {
2037 wl_lock( lp, &flags );
2039 wl_act_int_off( lp );
2041 lp->RTSThreshold = rthr;
2045 wl_act_int_on( lp );
2047 wl_unlock(lp, &flags);
2050 DBG_LEAVE( DbgInfo );
2052 } // wireless_set_rts_threshold
2053 /*============================================================================*/
2058 /*******************************************************************************
2059 * wireless_get_rts_threshold()
2060 *******************************************************************************
2064 * Gets the RTS threshold for the wireless card.
2068 * wrq - the wireless request buffer
2069 * lp - the device's private adapter structure
2074 * errno value otherwise
2076 ******************************************************************************/
2077 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2080 struct wl_private *lp = wl_priv(dev);
2081 unsigned long flags;
2082 /*------------------------------------------------------------------------*/
2084 DBG_FUNC( "wireless_get_rts_threshold" );
2085 DBG_ENTER( DbgInfo );
2087 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2092 wl_lock( lp, &flags );
2094 wl_act_int_off( lp );
2096 rts->value = lp->RTSThreshold;
2098 #if WIRELESS_EXT > 8
2100 rts->disabled = ( rts->value == 2347 );
2102 #endif /* WIRELESS_EXT > 8 */
2106 wl_act_int_on( lp );
2108 wl_unlock(lp, &flags);
2111 DBG_LEAVE( DbgInfo );
2113 } // wireless_get_rts_threshold
2114 /*============================================================================*/
2120 /*******************************************************************************
2121 * wireless_set_rate()
2122 *******************************************************************************
2126 * Set the default data rate setting used by the wireless device.
2130 * wrq - the wireless request buffer
2131 * lp - the device's private adapter structure
2136 * errno value otherwise
2138 ******************************************************************************/
2139 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2141 struct wl_private *lp = wl_priv(dev);
2142 unsigned long flags;
2148 /*------------------------------------------------------------------------*/
2151 DBG_FUNC( "wireless_set_rate" );
2152 DBG_ENTER( DbgInfo );
2154 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2159 wl_lock( lp, &flags );
2161 wl_act_int_off( lp );
2165 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2166 if Bit 9 is set in the current channel RID */
2167 lp->ltvRecord.len = 2;
2168 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2170 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2172 if( status == HCF_SUCCESS ) {
2173 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2175 DBG_PRINT( "Index: %d\n", index );
2177 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2178 DBG_LEAVE( DbgInfo );
2183 if( rrq->value > 0 &&
2184 rrq->value <= 1 * MEGABIT ) {
2185 lp->TxRateControl[index] = 0x0001;
2187 else if( rrq->value > 1 * MEGABIT &&
2188 rrq->value <= 2 * MEGABIT ) {
2189 if( rrq->fixed == 1 ) {
2190 lp->TxRateControl[index] = 0x0002;
2192 lp->TxRateControl[index] = 0x0003;
2195 else if( rrq->value > 2 * MEGABIT &&
2196 rrq->value <= 5 * MEGABIT ) {
2197 if( rrq->fixed == 1 ) {
2198 lp->TxRateControl[index] = 0x0004;
2200 lp->TxRateControl[index] = 0x0007;
2203 else if( rrq->value > 5 * MEGABIT &&
2204 rrq->value <= 6 * MEGABIT ) {
2205 if( rrq->fixed == 1 ) {
2206 lp->TxRateControl[index] = 0x0010;
2208 lp->TxRateControl[index] = 0x0017;
2211 else if( rrq->value > 6 * MEGABIT &&
2212 rrq->value <= 9 * MEGABIT ) {
2213 if( rrq->fixed == 1 ) {
2214 lp->TxRateControl[index] = 0x0020;
2216 lp->TxRateControl[index] = 0x0037;
2219 else if( rrq->value > 9 * MEGABIT &&
2220 rrq->value <= 11 * MEGABIT ) {
2221 if( rrq->fixed == 1 ) {
2222 lp->TxRateControl[index] = 0x0008;
2224 lp->TxRateControl[index] = 0x003F;
2227 else if( rrq->value > 11 * MEGABIT &&
2228 rrq->value <= 12 * MEGABIT ) {
2229 if( rrq->fixed == 1 ) {
2230 lp->TxRateControl[index] = 0x0040;
2232 lp->TxRateControl[index] = 0x007F;
2235 else if( rrq->value > 12 * MEGABIT &&
2236 rrq->value <= 18 * MEGABIT ) {
2237 if( rrq->fixed == 1 ) {
2238 lp->TxRateControl[index] = 0x0080;
2240 lp->TxRateControl[index] = 0x00FF;
2243 else if( rrq->value > 18 * MEGABIT &&
2244 rrq->value <= 24 * MEGABIT ) {
2245 if( rrq->fixed == 1 ) {
2246 lp->TxRateControl[index] = 0x0100;
2248 lp->TxRateControl[index] = 0x01FF;
2251 else if( rrq->value > 24 * MEGABIT &&
2252 rrq->value <= 36 * MEGABIT ) {
2253 if( rrq->fixed == 1 ) {
2254 lp->TxRateControl[index] = 0x0200;
2256 lp->TxRateControl[index] = 0x03FF;
2259 else if( rrq->value > 36 * MEGABIT &&
2260 rrq->value <= 48 * MEGABIT ) {
2261 if( rrq->fixed == 1 ) {
2262 lp->TxRateControl[index] = 0x0400;
2264 lp->TxRateControl[index] = 0x07FF;
2267 else if( rrq->value > 48 * MEGABIT &&
2268 rrq->value <= 54 * MEGABIT ) {
2269 if( rrq->fixed == 1 ) {
2270 lp->TxRateControl[index] = 0x0800;
2272 lp->TxRateControl[index] = 0x0FFF;
2275 else if( rrq->fixed == 0 ) {
2276 /* In this case, the user has not specified a bitrate, only the "auto"
2277 moniker. So, set to all supported rates */
2278 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2288 if( rrq->value > 0 &&
2289 rrq->value <= 1 * MEGABIT ) {
2290 lp->TxRateControl[0] = 1;
2292 else if( rrq->value > 1 * MEGABIT &&
2293 rrq->value <= 2 * MEGABIT ) {
2295 lp->TxRateControl[0] = 2;
2297 lp->TxRateControl[0] = 6;
2300 else if( rrq->value > 2 * MEGABIT &&
2301 rrq->value <= 5 * MEGABIT ) {
2303 lp->TxRateControl[0] = 4;
2305 lp->TxRateControl[0] = 7;
2308 else if( rrq->value > 5 * MEGABIT &&
2309 rrq->value <= 11 * MEGABIT ) {
2311 lp->TxRateControl[0] = 5;
2313 lp->TxRateControl[0] = 3;
2316 else if( rrq->fixed == 0 ) {
2317 /* In this case, the user has not specified a bitrate, only the "auto"
2318 moniker. So, set the rate to 11Mb auto */
2319 lp->TxRateControl[0] = 3;
2329 /* Commit the adapter parameters */
2334 wl_act_int_on( lp );
2336 wl_unlock(lp, &flags);
2339 DBG_LEAVE( DbgInfo );
2341 } // wireless_set_rate
2342 /*============================================================================*/
2347 /*******************************************************************************
2348 * wireless_get_rate()
2349 *******************************************************************************
2353 * Get the default data rate setting used by the wireless device.
2357 * wrq - the wireless request buffer
2358 * lp - the device's private adapter structure
2363 * errno value otherwise
2365 ******************************************************************************/
2366 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2369 struct wl_private *lp = wl_priv(dev);
2370 unsigned long flags;
2374 /*------------------------------------------------------------------------*/
2377 DBG_FUNC( "wireless_get_rate" );
2378 DBG_ENTER( DbgInfo );
2380 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2385 wl_lock( lp, &flags );
2387 wl_act_int_off( lp );
2389 /* Get the current transmit rate from the adapter */
2390 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2391 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2393 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2395 if( status == HCF_SUCCESS ) {
2398 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2400 if( txRate & 0x0001 ) {
2403 else if( txRate & 0x0002 ) {
2406 else if( txRate & 0x0004 ) {
2409 else if( txRate & 0x0008 ) {
2412 else if( txRate & 0x00010 ) {
2415 else if( txRate & 0x00020 ) {
2418 else if( txRate & 0x00040 ) {
2421 else if( txRate & 0x00080 ) {
2424 else if( txRate & 0x00100 ) {
2427 else if( txRate & 0x00200 ) {
2430 else if( txRate & 0x00400 ) {
2433 else if( txRate & 0x00800 ) {
2439 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2443 rrq->value = txRate * MEGABIT;
2449 wl_act_int_on( lp );
2451 wl_unlock(lp, &flags);
2454 DBG_LEAVE( DbgInfo );
2456 } // wireless_get_rate
2457 /*============================================================================*/
2462 #if 0 //;? Not used anymore
2463 /*******************************************************************************
2464 * wireless_get_private_interface()
2465 *******************************************************************************
2469 * Returns the Linux Wireless Extensions' compatible private interface of
2474 * wrq - the wireless request buffer
2475 * lp - the device's private adapter structure
2480 * errno value otherwise
2482 ******************************************************************************/
2483 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2486 /*------------------------------------------------------------------------*/
2489 DBG_FUNC( "wireless_get_private_interface" );
2490 DBG_ENTER( DbgInfo );
2492 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2497 if( wrq->u.data.pointer != NULL ) {
2498 struct iw_priv_args priv[] =
2500 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2501 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2502 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2503 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2504 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2505 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2508 /* Verify the user buffer */
2509 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2512 DBG_LEAVE( DbgInfo );
2516 /* Copy the data into the user's buffer */
2517 wrq->u.data.length = NELEM( priv );
2518 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2522 DBG_LEAVE( DbgInfo );
2524 } // wireless_get_private_interface
2525 /*============================================================================*/
2530 #if WIRELESS_EXT > 13
2532 /*******************************************************************************
2533 * wireless_set_scan()
2534 *******************************************************************************
2538 * Instructs the driver to initiate a network scan.
2542 * wrq - the wireless request buffer
2543 * lp - the device's private adapter structure
2548 * errno value otherwise
2550 ******************************************************************************/
2551 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2553 struct wl_private *lp = wl_priv(dev);
2554 unsigned long flags;
2558 /*------------------------------------------------------------------------*/
2560 //;? Note: shows results as trace, retruns always 0 unless BUSY
2562 DBG_FUNC( "wireless_set_scan" );
2563 DBG_ENTER( DbgInfo );
2565 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2570 wl_lock( lp, &flags );
2572 wl_act_int_off( lp );
2575 * This looks like a nice place to test if the HCF is still
2576 * communicating with the card. It seems that sometimes BAP_1
2577 * gets corrupted. By looking at the comments in HCF the
2578 * cause is still a mystery. Okay, the communication to the
2579 * card is dead, reset the card to revive.
2581 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2583 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2588 /* Set the completion state to FALSE */
2589 lp->probe_results.scan_complete = FALSE;
2592 /* Channels to scan */
2594 lp->ltvRecord.len = 5;
2595 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2596 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2597 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2598 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2599 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2601 lp->ltvRecord.len = 2;
2602 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2603 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2606 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2608 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2610 // Holding the lock too long, make a gap to allow other processes
2611 wl_unlock(lp, &flags);
2612 wl_lock( lp, &flags );
2614 if( status != HCF_SUCCESS ) {
2618 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2621 // Holding the lock too long, make a gap to allow other processes
2622 wl_unlock(lp, &flags);
2623 wl_lock( lp, &flags );
2629 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2630 disassociate from the network we are currently on */
2631 lp->ltvRecord.len = 18;
2632 lp->ltvRecord.typ = CFG_SCAN_SSID;
2633 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2634 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2636 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2638 // Holding the lock too long, make a gap to allow other processes
2639 wl_unlock(lp, &flags);
2640 wl_lock( lp, &flags );
2642 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2644 /* Initiate the scan */
2645 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2646 retrieve probe responses must always be used to support WPA */
2647 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2649 if( status == HCF_SUCCESS ) {
2650 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2652 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2655 wl_act_int_on( lp );
2657 wl_unlock(lp, &flags);
2662 } // wireless_set_scan
2663 /*============================================================================*/
2668 /*******************************************************************************
2669 * wireless_get_scan()
2670 *******************************************************************************
2674 * Instructs the driver to gather and return the results of a network scan.
2678 * wrq - the wireless request buffer
2679 * lp - the device's private adapter structure
2684 * errno value otherwise
2686 ******************************************************************************/
2687 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2689 struct wl_private *lp = wl_priv(dev);
2690 unsigned long flags;
2695 struct iw_event iwe;
2696 PROBE_RESP *probe_resp;
2700 /*------------------------------------------------------------------------*/
2703 DBG_FUNC( "wireless_get_scan" );
2704 DBG_ENTER( DbgInfo );
2706 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2711 wl_lock( lp, &flags );
2713 wl_act_int_off( lp );
2715 /* If the scan is not done, tell the calling process to try again later */
2716 if( !lp->probe_results.scan_complete ) {
2721 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2722 lp->probe_results.num_aps );
2725 buf_end = extra + IW_SCAN_MAX_DATA;
2727 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2728 /* Reference the probe response from the table */
2729 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2732 /* First entry MUST be the MAC address */
2733 memset( &iwe, 0, sizeof( iwe ));
2735 iwe.cmd = SIOCGIWAP;
2736 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2737 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2738 iwe.len = IW_EV_ADDR_LEN;
2740 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2743 /* Use the mode to indicate if it's a station or AP */
2744 /* Won't always be an AP if in IBSS mode */
2745 memset( &iwe, 0, sizeof( iwe ));
2747 iwe.cmd = SIOCGIWMODE;
2749 if( probe_resp->capability & CAPABILITY_IBSS ) {
2750 iwe.u.mode = IW_MODE_INFRA;
2752 iwe.u.mode = IW_MODE_MASTER;
2755 iwe.len = IW_EV_UINT_LEN;
2757 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2760 /* Any quality information */
2761 memset(&iwe, 0, sizeof(iwe));
2764 iwe.u.qual.level = dbm(probe_resp->signal);
2765 iwe.u.qual.noise = dbm(probe_resp->silence);
2766 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2767 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2768 iwe.len = IW_EV_QUAL_LEN;
2770 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2773 /* ESSID information */
2774 if( probe_resp->rawData[1] > 0 ) {
2775 memset( &iwe, 0, sizeof( iwe ));
2777 iwe.cmd = SIOCGIWESSID;
2778 iwe.u.data.length = probe_resp->rawData[1];
2779 iwe.u.data.flags = 1;
2781 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2785 /* Encryption Information */
2786 memset( &iwe, 0, sizeof( iwe ));
2788 iwe.cmd = SIOCGIWENCODE;
2789 iwe.u.data.length = 0;
2791 /* Check the capabilities field of the Probe Response to see if
2792 'privacy' is supported on the AP in question */
2793 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2794 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2796 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2799 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2802 /* Frequency Info */
2803 memset( &iwe, 0, sizeof( iwe ));
2805 iwe.cmd = SIOCGIWFREQ;
2806 iwe.len = IW_EV_FREQ_LEN;
2807 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2810 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2813 #if WIRELESS_EXT > 14
2814 /* Custom info (Beacon Interval) */
2815 memset( &iwe, 0, sizeof( iwe ));
2816 memset( msg, 0, sizeof( msg ));
2818 iwe.cmd = IWEVCUSTOM;
2819 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2820 iwe.u.data.length = strlen( msg );
2822 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2825 /* Custom info (WPA-IE) */
2829 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2830 if( wpa_ie != NULL ) {
2831 memset( &iwe, 0, sizeof( iwe ));
2832 memset( msg, 0, sizeof( msg ));
2834 iwe.cmd = IWEVCUSTOM;
2835 sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2836 iwe.u.data.length = strlen( msg );
2838 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2841 /* Add other custom info in formatted string format as needed... */
2845 data->length = buf - extra;
2849 wl_act_int_on( lp );
2851 wl_unlock(lp, &flags);
2854 DBG_LEAVE( DbgInfo );
2856 } // wireless_get_scan
2857 /*============================================================================*/
2859 #endif // WIRELESS_EXT > 13
2862 #if WIRELESS_EXT > 17
2864 static int wireless_set_auth(struct net_device *dev,
2865 struct iw_request_info *info,
2866 struct iw_param *data, char *extra)
2868 struct wl_private *lp = wl_priv(dev);
2869 unsigned long flags;
2871 int iwa_idx = data->flags & IW_AUTH_INDEX;
2872 int iwa_val = data->value;
2874 DBG_FUNC( "wireless_set_auth" );
2875 DBG_ENTER( DbgInfo );
2877 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2882 wl_lock( lp, &flags );
2884 wl_act_int_off( lp );
2887 case IW_AUTH_WPA_VERSION:
2888 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2889 /* We do support WPA only; how should DISABLED be treated? */
2890 if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2896 case IW_AUTH_WPA_ENABLED:
2897 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2899 lp->EnableEncryption = 2;
2901 lp->EnableEncryption = 0;
2905 case IW_AUTH_TKIP_COUNTERMEASURES:
2906 DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2907 lp->driverEnable = !iwa_val;
2908 if(lp->driverEnable)
2909 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2911 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2915 case IW_AUTH_DROP_UNENCRYPTED:
2916 DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2917 /* We do not actually do anything here, just to silence
2922 case IW_AUTH_CIPHER_PAIRWISE:
2923 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2924 /* not implemented, return an error */
2928 case IW_AUTH_CIPHER_GROUP:
2929 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2930 /* not implemented, return an error */
2934 case IW_AUTH_KEY_MGMT:
2935 DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2936 /* not implemented, return an error */
2940 case IW_AUTH_80211_AUTH_ALG:
2941 DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2942 /* not implemented, return an error */
2946 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2947 DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2948 /* not implemented, return an error */
2952 case IW_AUTH_ROAMING_CONTROL:
2953 DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2954 /* not implemented, return an error */
2958 case IW_AUTH_PRIVACY_INVOKED:
2959 DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2960 /* not implemented, return an error */
2965 DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2966 /* return an error */
2971 wl_act_int_on( lp );
2973 wl_unlock(lp, &flags);
2976 DBG_LEAVE( DbgInfo );
2978 } // wireless_set_auth
2979 /*============================================================================*/
2983 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
2984 int set_tx, u8 *seq, u8 *key, size_t key_len)
2989 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
2990 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
2992 DBG_FUNC( "hermes_set_key" );
2993 DBG_ENTER( DbgInfo );
2996 * Check the key index here; if 0, load as Pairwise Key, otherwise,
2997 * load as a group key. Note that for the Hermes, the RIDs for
2998 * group/pariwise keys are different from each other and different
2999 * than the default WEP keys as well.
3003 case IW_ENCODE_ALG_TKIP:
3004 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3007 * Make sure that there is no data queued up in the firmware
3008 * before setting the TKIP keys. If this check is not
3009 * performed, some data may be sent out with incorrect MIC
3010 * and cause synchronizarion errors with the AP
3012 /* Check every 1ms for 100ms */
3013 for( count = 0; count < 100; count++ )
3018 ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
3021 wl_get_info( sock, <v, ifname );
3023 if( ltv.u.u16[0] == 0 )
3031 wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
3038 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
3040 /* Load the BSSID */
3041 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
3042 buf_idx += ETH_ALEN;
3044 /* Load the TKIP key */
3045 memcpy(<v->u.u8[buf_idx], &key[0], 16);
3049 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3050 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3053 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3054 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3056 /* Load the TxMIC key */
3057 memcpy(<v->u.u8[buf_idx], &key[16], 8);
3060 /* Load the RxMIC key */
3061 memcpy(<v->u.u8[buf_idx], &key[24], 8);
3069 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3071 /* Load the key Index */
3072 ltv->u.u16[buf_idx] = key_idx;
3073 /* If this is a Tx Key, set bit 8000 */
3075 ltv->u.u16[buf_idx] |= 0x8000;
3079 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3080 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3082 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3083 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3084 memcpy(<v->u.u8[buf_idx], key, key_len);
3088 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3090 ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3100 case IW_ENCODE_ALG_WEP:
3101 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3104 case IW_ENCODE_ALG_CCMP:
3105 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3108 case IW_ENCODE_ALG_NONE:
3109 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3112 if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3113 //if (addr != NULL) {
3115 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3116 memcpy(<v->u.u8[0], addr, ETH_ALEN);
3123 /* Clear the Group TKIP keys by index */
3125 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3126 ltv->u.u16[0] = key_idx;
3135 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3139 DBG_LEAVE( DbgInfo );
3142 /*============================================================================*/
3146 static int wireless_set_encodeext (struct net_device *dev,
3147 struct iw_request_info *info,
3148 struct iw_point *erq, char *keybuf)
3150 struct wl_private *lp = wl_priv(dev);
3151 unsigned long flags;
3153 int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3155 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3157 DBG_FUNC( "wireless_set_encodeext" );
3158 DBG_ENTER( DbgInfo );
3160 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3165 if (sizeof(ext->rx_seq) != 8) {
3166 DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3171 /* Handle WEP keys via the old set encode procedure */
3172 if(ext->alg == IW_ENCODE_ALG_WEP) {
3173 struct iw_point wep_erq;
3176 /* Build request structure */
3177 wep_erq.flags = erq->flags; // take over flags with key index
3178 wep_erq.length = ext->key_len; // take length from extended key info
3179 wep_keybuf = ext->key; // pointer to the key text
3181 /* Call wireless_set_encode tot handle the WEP key */
3182 ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3186 /* Proceed for extended encode functions for WAP and NONE */
3187 wl_lock( lp, &flags );
3189 wl_act_int_off( lp );
3191 memset(<v, 0, sizeof(ltv));
3192 ret = hermes_set_key(<v, ext->alg, key_idx, ext->addr.sa_data,
3193 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3194 ext->rx_seq, ext->key, ext->key_len);
3197 DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3201 /* Put the key in HCF */
3202 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3205 if(ret == HCF_SUCCESS) {
3206 DBG_TRACE( DbgInfo, "Put key info succes\n");
3208 DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3211 wl_act_int_on( lp );
3213 wl_unlock(lp, &flags);
3216 DBG_LEAVE( DbgInfo );
3218 } // wireless_set_encodeext
3219 /*============================================================================*/
3223 static int wireless_get_genie(struct net_device *dev,
3224 struct iw_request_info *info,
3225 struct iw_point *data, char *extra)
3228 struct wl_private *lp = wl_priv(dev);
3229 unsigned long flags;
3233 DBG_FUNC( "wireless_get_genie" );
3234 DBG_ENTER( DbgInfo );
3236 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3241 wl_lock( lp, &flags );
3243 wl_act_int_off( lp );
3245 memset(<v, 0, sizeof(ltv));
3247 ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3248 lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3249 ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3251 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3253 wl_act_int_on( lp );
3255 wl_unlock(lp, &flags);
3258 DBG_LEAVE( DbgInfo );
3261 /*============================================================================*/
3264 #endif // WIRELESS_EXT > 17
3266 /*******************************************************************************
3267 * wl_wireless_stats()
3268 *******************************************************************************
3272 * Return the current device wireless statistics.
3276 * wrq - the wireless request buffer
3277 * lp - the device's private adapter structure
3282 * errno value otherwise
3284 ******************************************************************************/
3285 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3287 struct iw_statistics *pStats;
3288 struct wl_private *lp = wl_priv(dev);
3289 /*------------------------------------------------------------------------*/
3292 DBG_FUNC( "wl_wireless_stats" );
3294 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3298 /* Initialize the statistics */
3299 pStats = &( lp->wstats );
3300 pStats->qual.updated = 0x00;
3302 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3304 CFG_COMMS_QUALITY_STRCT *pQual;
3305 CFG_HERMES_TALLIES_STRCT tallies;
3308 /* Update driver status */
3311 /* Get the current link quality information */
3312 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3313 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3314 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3316 if( status == HCF_SUCCESS ) {
3317 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3320 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3321 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3322 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3324 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3325 IW_QUAL_LEVEL_UPDATED |
3326 IW_QUAL_NOISE_UPDATED |
3329 pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
3330 HCF_MIN_COMM_QUALITY,
3331 HCF_MAX_COMM_QUALITY );
3333 pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
3334 HCF_MIN_SIGNAL_LEVEL,
3335 HCF_MAX_SIGNAL_LEVEL );
3337 pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
3338 HCF_MIN_NOISE_LEVEL,
3339 HCF_MAX_NOISE_LEVEL );
3341 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3342 IW_QUAL_LEVEL_UPDATED |
3343 IW_QUAL_NOISE_UPDATED);
3344 #endif /* USE_DBM */
3346 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3349 /* Get the current tallies from the adapter */
3350 /* Only possible when the device is open */
3351 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3352 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3353 /* No endian translation is needed here, as CFG_TALLIES is an
3354 MSF RID; all processing is done on the host, not the card! */
3355 pStats->discard.nwid = 0L;
3356 pStats->discard.code = tallies.RxWEPUndecryptable;
3357 pStats->discard.misc = tallies.TxDiscards +
3358 tallies.RxFCSErrors +
3359 //tallies.RxDiscardsNoBuffer +
3360 tallies.TxDiscardsWrongSA;
3361 //;? Extra taken over from Linux driver based on 7.18 version
3362 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3363 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3365 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3368 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3372 DBG_LEAVE( DbgInfo );
3374 } // wl_wireless_stats
3375 /*============================================================================*/
3380 /*******************************************************************************
3381 * wl_get_wireless_stats()
3382 *******************************************************************************
3386 * Return the current device wireless statistics. This function calls
3387 * wl_wireless_stats, but acquires spinlocks first as it can be called
3388 * directly by the network layer.
3392 * wrq - the wireless request buffer
3393 * lp - the device's private adapter structure
3398 * errno value otherwise
3400 ******************************************************************************/
3401 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3403 unsigned long flags;
3404 struct wl_private *lp = wl_priv(dev);
3405 struct iw_statistics *pStats = NULL;
3406 /*------------------------------------------------------------------------*/
3408 DBG_FUNC( "wl_get_wireless_stats" );
3411 wl_lock( lp, &flags );
3413 wl_act_int_off( lp );
3416 if( lp->useRTS == 1 ) {
3417 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3421 pStats = wl_wireless_stats( dev );
3423 wl_act_int_on( lp );
3425 wl_unlock(lp, &flags);
3427 DBG_LEAVE( DbgInfo );
3429 } // wl_get_wireless_stats
3432 /*******************************************************************************
3434 *******************************************************************************
3438 * Gather wireless spy statistics.
3442 * wrq - the wireless request buffer
3443 * lp - the device's private adapter structure
3448 * errno value otherwise
3450 ******************************************************************************/
3451 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3453 struct iw_quality wstats;
3457 struct wl_private *lp = wl_priv(dev);
3458 /*------------------------------------------------------------------------*/
3461 if (!lp->spy_data.spy_number) {
3465 /* Gather wireless spy statistics: for each packet, compare the source
3466 address with out list, and if match, get the stats. */
3467 memset( stats, 0, sizeof(stats));
3468 memset( desc, 0, sizeof(DESC_STRCT));
3470 desc[0].buf_addr = stats;
3471 desc[0].BUF_SIZE = sizeof(stats);
3472 desc[0].next_desc_addr = 0; // terminate list
3474 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3476 if( status == HCF_SUCCESS ) {
3477 wstats.level = (u_char) dbm(stats[1]);
3478 wstats.noise = (u_char) dbm(stats[0]);
3479 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3481 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3482 IW_QUAL_LEVEL_UPDATED |
3483 IW_QUAL_NOISE_UPDATED |
3486 wireless_spy_update( dev, mac, &wstats );
3489 /*============================================================================*/
3494 /*******************************************************************************
3495 * wl_wext_event_freq()
3496 *******************************************************************************
3500 * This function is used to send an event that the channel/freq
3501 * configuration for a specific device has changed.
3506 * dev - the network device for which this event is to be issued
3512 ******************************************************************************/
3513 void wl_wext_event_freq( struct net_device *dev )
3515 #if WIRELESS_EXT > 13
3516 union iwreq_data wrqu;
3517 struct wl_private *lp = wl_priv(dev);
3518 /*------------------------------------------------------------------------*/
3521 memset( &wrqu, 0, sizeof( wrqu ));
3523 wrqu.freq.m = lp->Channel;
3526 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3527 #endif /* WIRELESS_EXT > 13 */
3530 } // wl_wext_event_freq
3531 /*============================================================================*/
3536 /*******************************************************************************
3537 * wl_wext_event_mode()
3538 *******************************************************************************
3542 * This function is used to send an event that the mode of operation
3543 * for a specific device has changed.
3548 * dev - the network device for which this event is to be issued
3554 ******************************************************************************/
3555 void wl_wext_event_mode( struct net_device *dev )
3557 #if WIRELESS_EXT > 13
3558 union iwreq_data wrqu;
3559 struct wl_private *lp = wl_priv(dev);
3560 /*------------------------------------------------------------------------*/
3563 memset( &wrqu, 0, sizeof( wrqu ));
3565 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3566 wrqu.mode = IW_MODE_INFRA;
3568 wrqu.mode = IW_MODE_MASTER;
3571 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3572 #endif /* WIRELESS_EXT > 13 */
3575 } // wl_wext_event_mode
3576 /*============================================================================*/
3581 /*******************************************************************************
3582 * wl_wext_event_essid()
3583 *******************************************************************************
3587 * This function is used to send an event that the ESSID configuration for
3588 * a specific device has changed.
3593 * dev - the network device for which this event is to be issued
3599 ******************************************************************************/
3600 void wl_wext_event_essid( struct net_device *dev )
3602 #if WIRELESS_EXT > 13
3603 union iwreq_data wrqu;
3604 struct wl_private *lp = wl_priv(dev);
3605 /*------------------------------------------------------------------------*/
3608 memset( &wrqu, 0, sizeof( wrqu ));
3610 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3611 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3612 the call to wireless_send_event() must also point to where the ESSID
3614 wrqu.essid.length = strlen( lp->NetworkName );
3615 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3616 wrqu.essid.flags = 1;
3618 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3619 #endif /* WIRELESS_EXT > 13 */
3622 } // wl_wext_event_essid
3623 /*============================================================================*/
3628 /*******************************************************************************
3629 * wl_wext_event_encode()
3630 *******************************************************************************
3634 * This function is used to send an event that the encryption configuration
3635 * for a specific device has changed.
3640 * dev - the network device for which this event is to be issued
3646 ******************************************************************************/
3647 void wl_wext_event_encode( struct net_device *dev )
3649 #if WIRELESS_EXT > 13
3650 union iwreq_data wrqu;
3651 struct wl_private *lp = wl_priv(dev);
3653 /*------------------------------------------------------------------------*/
3656 memset( &wrqu, 0, sizeof( wrqu ));
3658 if( lp->EnableEncryption == 0 ) {
3659 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3661 wrqu.encoding.flags |= lp->TransmitKeyID;
3663 index = lp->TransmitKeyID - 1;
3665 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3666 if we're in AP mode */
3667 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3668 //;?should we restore this to allow smaller memory footprint
3670 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3671 if( lp->ExcludeUnencrypted ) {
3672 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3674 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3678 #endif // HCF_TYPE_AP
3680 /* Only provide the key if permissions allow */
3681 if( capable( CAP_NET_ADMIN )) {
3682 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3683 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3685 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3689 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3690 lp->DefaultKeys.key[index].key );
3691 #endif /* WIRELESS_EXT > 13 */
3694 } // wl_wext_event_encode
3695 /*============================================================================*/
3700 /*******************************************************************************
3701 * wl_wext_event_ap()
3702 *******************************************************************************
3706 * This function is used to send an event that the device has been
3707 * associated to a new AP.
3712 * dev - the network device for which this event is to be issued
3718 ******************************************************************************/
3719 void wl_wext_event_ap( struct net_device *dev )
3721 #if WIRELESS_EXT > 13
3722 union iwreq_data wrqu;
3723 struct wl_private *lp = wl_priv(dev);
3725 /*------------------------------------------------------------------------*/
3728 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3729 this event BEFORE sending the association event, as there are timing
3730 issues with the hostap supplicant. The supplicant will attempt to process
3731 an EAPOL-Key frame from an AP before receiving this information, which
3732 is required properly process the said frame. */
3733 wl_wext_event_assoc_ie( dev );
3736 lp->ltvRecord.typ = CFG_CUR_BSSID;
3737 lp->ltvRecord.len = 4;
3739 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3740 if( status == HCF_SUCCESS ) {
3741 memset( &wrqu, 0, sizeof( wrqu ));
3743 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3745 wrqu.addr.sa_family = ARPHRD_ETHER;
3747 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3750 #endif /* WIRELESS_EXT > 13 */
3753 } // wl_wext_event_ap
3754 /*============================================================================*/
3758 /*******************************************************************************
3759 * wl_wext_event_scan_complete()
3760 *******************************************************************************
3764 * This function is used to send an event that a request for a network scan
3770 * dev - the network device for which this event is to be issued
3776 ******************************************************************************/
3777 void wl_wext_event_scan_complete( struct net_device *dev )
3779 #if WIRELESS_EXT > 13
3780 union iwreq_data wrqu;
3781 /*------------------------------------------------------------------------*/
3784 memset( &wrqu, 0, sizeof( wrqu ));
3786 wrqu.addr.sa_family = ARPHRD_ETHER;
3787 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3788 #endif /* WIRELESS_EXT > 13 */
3791 } // wl_wext_event_scan_complete
3792 /*============================================================================*/
3797 /*******************************************************************************
3798 * wl_wext_event_new_sta()
3799 *******************************************************************************
3803 * This function is used to send an event that an AP has registered a new
3809 * dev - the network device for which this event is to be issued
3815 ******************************************************************************/
3816 void wl_wext_event_new_sta( struct net_device *dev )
3818 #if WIRELESS_EXT > 14
3819 union iwreq_data wrqu;
3820 /*------------------------------------------------------------------------*/
3823 memset( &wrqu, 0, sizeof( wrqu ));
3825 /* Send the station's mac address here */
3826 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3827 wrqu.addr.sa_family = ARPHRD_ETHER;
3828 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3829 #endif /* WIRELESS_EXT > 14 */
3832 } // wl_wext_event_new_sta
3833 /*============================================================================*/
3838 /*******************************************************************************
3839 * wl_wext_event_expired_sta()
3840 *******************************************************************************
3844 * This function is used to send an event that an AP has deregistered a
3850 * dev - the network device for which this event is to be issued
3856 ******************************************************************************/
3857 void wl_wext_event_expired_sta( struct net_device *dev )
3859 #if WIRELESS_EXT > 14
3860 union iwreq_data wrqu;
3861 /*------------------------------------------------------------------------*/
3864 memset( &wrqu, 0, sizeof( wrqu ));
3866 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3867 wrqu.addr.sa_family = ARPHRD_ETHER;
3868 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3869 #endif /* WIRELESS_EXT > 14 */
3872 } // wl_wext_event_expired_sta
3873 /*============================================================================*/
3878 /*******************************************************************************
3879 * wl_wext_event_mic_failed()
3880 *******************************************************************************
3884 * This function is used to send an event that MIC calculations failed.
3889 * dev - the network device for which this event is to be issued
3895 ******************************************************************************/
3896 void wl_wext_event_mic_failed( struct net_device *dev )
3898 #if WIRELESS_EXT > 14
3900 union iwreq_data wrqu;
3901 struct wl_private *lp = wl_priv(dev);
3905 WVLAN_RX_WMP_HDR *hdr;
3906 /*------------------------------------------------------------------------*/
3909 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3912 /* Cast the lookahead buffer into a RFS format */
3913 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3915 /* Cast the addresses to byte buffers, as in the above RFS they are word
3917 addr1 = (char *)hdr->address1;
3918 addr2 = (char *)hdr->address2;
3920 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3923 memset( &wrqu, 0, sizeof( wrqu ));
3924 memset( msg, 0, sizeof( msg ));
3927 /* Because MIC failures are not part of the Wireless Extensions yet, they
3928 must be passed as a string using an IWEVCUSTOM event. In order for the
3929 event to be effective, the string format must be known by both the
3930 driver and the supplicant. The following is the string format used by the
3931 hostap project's WPA supplicant, and will be used here until the Wireless
3932 Extensions interface adds this support:
3934 MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
3937 /* NOTE: Format of MAC address (using colons to separate bytes) may cause
3938 a problem in future versions of the supplicant, if they ever
3939 actually parse these parameters */
3941 sprintf(msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast "
3942 "addr=%pM)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
3945 wrqu.data.length = strlen( msg );
3946 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
3947 #endif /* WIRELESS_EXT > 14 */
3950 } // wl_wext_event_mic_failed
3951 /*============================================================================*/
3956 /*******************************************************************************
3957 * wl_wext_event_assoc_ie()
3958 *******************************************************************************
3962 * This function is used to send an event containing the WPA-IE generated
3963 * by the firmware in an association request.
3968 * dev - the network device for which this event is to be issued
3974 ******************************************************************************/
3975 void wl_wext_event_assoc_ie( struct net_device *dev )
3977 #if WIRELESS_EXT > 14
3979 union iwreq_data wrqu;
3980 struct wl_private *lp = wl_priv(dev);
3985 /*------------------------------------------------------------------------*/
3988 memset( &wrqu, 0, sizeof( wrqu ));
3989 memset( msg, 0, sizeof( msg ));
3991 /* Retrieve the Association Request IE */
3992 lp->ltvRecord.len = 45;
3993 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3995 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3996 if( status == HCF_SUCCESS )
3999 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
4000 wpa_ie = wl_parse_wpa_ie( &data, &length );
4002 /* Because this event (Association WPA-IE) is not part of the Wireless
4003 Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
4004 In order for the event to be effective, the string format must be known
4005 by both the driver and the supplicant. The following is the string format
4006 used by the hostap project's WPA supplicant, and will be used here until
4007 the Wireless Extensions interface adds this support:
4009 ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
4014 sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
4015 wrqu.data.length = strlen( msg );
4016 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
4019 #endif /* WIRELESS_EXT > 14 */
4022 } // wl_wext_event_assoc_ie
4023 /*============================================================================*/
4024 /* Structures to export the Wireless Handlers */
4026 static const iw_handler wl_handler[] =
4028 (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */
4029 (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */
4030 (iw_handler) NULL, /* SIOCSIWNWID */
4031 (iw_handler) NULL, /* SIOCGIWNWID */
4032 (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */
4033 (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */
4034 (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */
4035 (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */
4036 (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */
4037 (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */
4038 (iw_handler) NULL , /* SIOCSIWRANGE */
4039 (iw_handler) wireless_get_range, /* SIOCGIWRANGE */
4040 (iw_handler) NULL , /* SIOCSIWPRIV */
4041 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
4042 (iw_handler) NULL , /* SIOCSIWSTATS */
4043 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
4044 iw_handler_set_spy, /* SIOCSIWSPY */
4045 iw_handler_get_spy, /* SIOCGIWSPY */
4046 NULL, /* SIOCSIWTHRSPY */
4047 NULL, /* SIOCGIWTHRSPY */
4048 (iw_handler) NULL, /* SIOCSIWAP */
4049 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4050 (iw_handler) wireless_get_bssid, /* SIOCGIWAP */
4052 (iw_handler) NULL, /* SIOCGIWAP */
4054 (iw_handler) NULL, /* SIOCSIWMLME */
4055 (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */
4056 (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */
4057 (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */
4058 (iw_handler) wireless_set_essid, /* SIOCSIWESSID */
4059 (iw_handler) wireless_get_essid, /* SIOCGIWESSID */
4060 (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */
4061 (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */
4062 (iw_handler) NULL, /* -- hole -- */
4063 (iw_handler) NULL, /* -- hole -- */
4064 (iw_handler) wireless_set_rate, /* SIOCSIWRATE */
4065 (iw_handler) wireless_get_rate, /* SIOCGIWRATE */
4066 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
4067 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
4068 (iw_handler) NULL, /* SIOCSIWFRAG */
4069 (iw_handler) NULL, /* SIOCGIWFRAG */
4070 (iw_handler) NULL, /* SIOCSIWTXPOW */
4071 (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */
4072 (iw_handler) NULL, /* SIOCSIWRETRY */
4073 (iw_handler) NULL, /* SIOCGIWRETRY */
4074 (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */
4075 (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */
4076 (iw_handler) wireless_set_power, /* SIOCSIWPOWER */
4077 (iw_handler) wireless_get_power, /* SIOCGIWPOWER */
4078 (iw_handler) NULL, /* -- hole -- */
4079 (iw_handler) NULL, /* -- hole -- */
4080 (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */
4081 (iw_handler) NULL, /* SIOCGIWGENIE */
4082 (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */
4083 (iw_handler) NULL, /* SIOCGIWAUTH */
4084 (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */
4085 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
4086 (iw_handler) NULL, /* SIOCSIWPMKSA */
4087 (iw_handler) NULL, /* -- hole -- */
4090 static const iw_handler wl_private_handler[] =
4091 { /* SIOCIWFIRSTPRIV + */
4092 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
4093 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
4094 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
4095 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
4096 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4097 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
4098 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
4102 struct iw_priv_args wl_priv_args[] = {
4103 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
4104 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
4105 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
4106 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
4107 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
4108 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
4109 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
4113 const struct iw_handler_def wl_iw_handler_def =
4115 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
4116 .private = (iw_handler *) wl_private_handler,
4117 .private_args = (struct iw_priv_args *) wl_priv_args,
4118 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
4119 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
4120 .standard = (iw_handler *) wl_handler,
4121 .get_wireless_stats = wl_get_wireless_stats,
4124 #endif // WIRELESS_EXT