1 /*******************************************************************************
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
16 * This software is provided subject to the following terms and conditions,
17 * which you should read carefully before using the software. Using this
18 * software indicates your acceptance of these terms and conditions. If you do
19 * not agree with these terms and conditions, do not use the software.
21 * Copyright © 2003 Agere Systems Inc.
22 * All rights reserved.
24 * Redistribution and use in source or binary forms, with or without
25 * modifications, are permitted provided that the following conditions are met:
27 * . Redistributions of source code must retain the above copyright notice, this
28 * list of conditions and the following Disclaimer as comments in the code as
29 * well as in the documentation and/or other materials provided with the
32 * . Redistributions in binary form must reproduce the above copyright notice,
33 * this list of conditions and the following Disclaimer in the documentation
34 * and/or other materials provided with the distribution.
36 * . Neither the name of Agere Systems Inc. nor the names of the contributors
37 * may be used to endorse or promote products derived from this software
38 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED
\93AS IS
\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
43 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
45 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
46 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
55 ******************************************************************************/
57 /*******************************************************************************
59 ******************************************************************************/
60 #include <wl_version.h>
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <linux/etherdevice.h>
66 #include <asm/uaccess.h>
73 #include <wl_internal.h>
79 /*******************************************************************************
81 ******************************************************************************/
83 extern dbg_info_t *DbgInfo;
87 /* Set up the LTV to program the appropriate key */
88 static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr,
89 int set_tx, u8 *seq, u8 *key, size_t key_len)
93 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
94 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
99 * Check the key index here; if 0, load as Pairwise Key, otherwise,
100 * load as a group key. Note that for the Hermes, the RIDs for
101 * group/pairwise keys are different from each other and different
102 * than the default WEP keys as well.
107 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
110 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
113 /* Load the TKIP key */
114 memcpy(<v->u.u8[buf_idx], &key[0], 16);
118 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
119 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
122 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
123 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
125 /* Load the TxMIC key */
126 memcpy(<v->u.u8[buf_idx], &key[16], 8);
129 /* Load the RxMIC key */
130 memcpy(<v->u.u8[buf_idx], &key[24], 8);
138 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
140 /* Load the key Index */
142 /* If this is a Tx Key, set bit 8000 */
145 ltv->u.u16[buf_idx] = cpu_to_le16(key_idx);
149 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
150 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
152 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
153 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
154 memcpy(<v->u.u8[buf_idx], key, key_len);
158 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
170 /* Set up the LTV to clear the appropriate key */
171 static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr)
177 if (!is_broadcast_ether_addr(addr)) {
179 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
180 memcpy(<v->u.u8[0], addr, ETH_ALEN);
187 /* Clear the Group TKIP keys by index */
189 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
190 ltv->u.u16[0] = cpu_to_le16(key_idx);
201 /* Set the WEP keys in the wl_private structure */
202 static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
203 u8 *key, size_t key_len,
204 bool enable, bool set_tx)
206 hcf_8 encryption_state = lp->EnableEncryption;
207 int tk = lp->TransmitKeyID - 1; /* current key */
210 /* Is encryption supported? */
211 if (!wl_has_wep(&(lp->hcfCtx))) {
212 DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
217 DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
220 /* Check the size of the key */
225 /* Check the index */
226 if ((key_idx < 0) || (key_idx >= MAX_KEYS))
230 memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
232 /* Copy the key in the driver */
233 memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
236 lp->DefaultKeys.key[key_idx].len = key_len;
238 DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
239 DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
240 lp->DefaultKeys.key[key_idx].key,
241 lp->DefaultKeys.key[key_idx].len, key_idx);
243 /* Enable WEP (if possible) */
244 if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
245 lp->EnableEncryption = 1;
250 /* Do we want to just set the current transmit key? */
251 if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
252 DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
253 lp->DefaultKeys.key[key_idx].len);
255 if (lp->DefaultKeys.key[key_idx].len > 0) {
256 lp->TransmitKeyID = key_idx + 1;
257 lp->EnableEncryption = 1;
259 DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
266 DBG_WARNING(DbgInfo, "Invalid Key length\n");
273 lp->EnableEncryption = 1;
274 lp->wext_enc = IW_ENCODE_ALG_WEP;
276 lp->EnableEncryption = 0; /* disable encryption */
277 lp->wext_enc = IW_ENCODE_ALG_NONE;
280 DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
281 DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
282 DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
284 /* Write the changes to the card */
286 DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
289 if (lp->EnableEncryption == encryption_state) {
291 /* Dynamic WEP key update */
295 /* To switch encryption on/off, soft reset is
305 /*******************************************************************************
307 *******************************************************************************
316 * wrq - the wireless request buffer
322 ******************************************************************************/
323 static int wireless_commit(struct net_device *dev,
324 struct iw_request_info *info,
325 union iwreq_data *rqu, char *extra)
327 struct wl_private *lp = wl_priv(dev);
330 /*------------------------------------------------------------------------*/
332 DBG_FUNC( "wireless_commit" );
335 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
340 wl_lock( lp, &flags );
342 wl_act_int_off( lp );
348 wl_unlock(lp, &flags);
351 DBG_LEAVE( DbgInfo );
354 /*============================================================================*/
359 /*******************************************************************************
360 * wireless_get_protocol()
361 *******************************************************************************
365 * Returns a vendor-defined string that should identify the wireless
370 * wrq - the wireless request buffer
376 ******************************************************************************/
377 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
379 DBG_FUNC( "wireless_get_protocol" );
380 DBG_ENTER( DbgInfo );
382 /* Originally, the driver was placing the string "Wireless" here. However,
383 the wireless extensions (/linux/wireless.h) indicate this string should
384 describe the wireless protocol. */
386 strcpy(name, "IEEE 802.11b");
390 } // wireless_get_protocol
391 /*============================================================================*/
396 /*******************************************************************************
397 * wireless_set_frequency()
398 *******************************************************************************
402 * Sets the frequency (channel) on which the card should Tx/Rx.
406 * wrq - the wireless request buffer
407 * lp - the device's private adapter structure
412 * errno value otherwise
414 ******************************************************************************/
415 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
417 struct wl_private *lp = wl_priv(dev);
421 /*------------------------------------------------------------------------*/
424 DBG_FUNC( "wireless_set_frequency" );
425 DBG_ENTER( DbgInfo );
427 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
432 if( !capable( CAP_NET_ADMIN )) {
434 DBG_LEAVE( DbgInfo );
439 /* If frequency specified, look up channel */
441 int f = freq->m / 100000;
442 channel = wl_get_chan_from_freq( f );
446 /* Channel specified */
452 /* If the channel is an 802.11a channel, set Bit 8 */
454 channel = channel | 0x100;
458 wl_lock( lp, &flags );
460 wl_act_int_off( lp );
462 lp->Channel = channel;
465 /* Commit the adapter parameters */
468 /* Send an event that channel/freq has been set */
469 wl_wext_event_freq( lp->dev );
473 wl_unlock(lp, &flags);
476 DBG_LEAVE( DbgInfo );
478 } // wireless_set_frequency
479 /*============================================================================*/
484 /*******************************************************************************
485 * wireless_get_frequency()
486 *******************************************************************************
490 * Gets the frequency (channel) on which the card is Tx/Rx.
494 * wrq - the wireless request buffer
495 * lp - the device's private adapter structure
501 ******************************************************************************/
502 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
505 struct wl_private *lp = wl_priv(dev);
508 /*------------------------------------------------------------------------*/
511 DBG_FUNC( "wireless_get_frequency" );
512 DBG_ENTER( DbgInfo );
514 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
519 wl_lock( lp, &flags );
521 wl_act_int_off( lp );
523 lp->ltvRecord.len = 2;
524 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
526 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
527 if( ret == HCF_SUCCESS ) {
528 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
530 freq->m = wl_get_freq_from_chan( channel ) * 100000;
536 wl_unlock(lp, &flags);
538 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
541 DBG_LEAVE( DbgInfo );
543 } // wireless_get_frequency
544 /*============================================================================*/
549 /*******************************************************************************
550 * wireless_get_range()
551 *******************************************************************************
555 * This function is used to provide misc info and statistics about the
560 * wrq - the wireless request buffer
561 * lp - the device's private adapter structure
566 * errno value otherwise
568 ******************************************************************************/
569 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
571 struct wl_private *lp = wl_priv(dev);
573 struct iw_range *range = (struct iw_range *) extra;
579 /*------------------------------------------------------------------------*/
582 DBG_FUNC( "wireless_get_range" );
583 DBG_ENTER( DbgInfo );
585 /* Set range information */
586 data->length = sizeof(struct iw_range);
587 memset(range, 0, sizeof(struct iw_range));
589 wl_lock( lp, &flags );
591 wl_act_int_off( lp );
593 /* Set range information */
594 memset( range, 0, sizeof( struct iw_range ));
597 /* Get the current transmit rate from the adapter */
598 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
599 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
601 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
602 if( status != HCF_SUCCESS ) {
603 /* Recovery action: reset and retry up to 10 times */
604 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
609 /* Holding the lock too long, makes a gap to allow other processes */
610 wl_unlock(lp, &flags);
611 wl_lock( lp, &flags );
613 status = wl_reset( dev );
614 if ( status != HCF_SUCCESS ) {
615 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
621 /* Holding the lock too long, makes a gap to allow other processes */
622 wl_unlock(lp, &flags);
623 wl_lock( lp, &flags );
628 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
634 /* Holding the lock too long, makes a gap to allow other processes */
635 wl_unlock(lp, &flags);
636 wl_lock( lp, &flags );
638 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
640 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
643 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
646 // NWID - NOT SUPPORTED
649 /* Channel/Frequency Info */
650 range->num_channels = RADIO_CHANNELS;
653 /* Signal Level Thresholds */
654 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
658 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
660 /* If the value returned in /proc/net/wireless is greater than the maximum range,
661 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
662 it requires a bit of contorsion... */
664 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
665 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
668 /* Set available rates */
669 range->num_bitrates = 0;
671 lp->ltvRecord.len = 6;
672 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
674 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
675 if( status == HCF_SUCCESS ) {
676 for( count = 0; count < MAX_RATES; count++ )
677 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
678 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
679 range->num_bitrates++;
682 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
687 /* RTS Threshold info */
688 range->min_rts = MIN_RTS_BYTES;
689 range->max_rts = MAX_RTS_BYTES;
691 // Frag Threshold info - NOT SUPPORTED
693 // Power Management info - NOT SUPPORTED
697 /* Holding the lock too long, makes a gap to allow other processes */
698 wl_unlock(lp, &flags);
699 wl_lock( lp, &flags );
701 /* Is WEP supported? */
703 if( wl_has_wep( &( lp->hcfCtx ))) {
704 /* WEP: RC4 40 bits */
705 range->encoding_size[0] = MIN_KEY_SIZE;
708 range->encoding_size[1] = MAX_KEY_SIZE;
709 range->num_encoding_sizes = 2;
710 range->max_encoding_tokens = MAX_KEYS;
714 range->txpower_capa = IW_TXPOW_MWATT;
715 range->num_txpower = 1;
716 range->txpower[0] = RADIO_TX_POWER_MWATT;
718 /* Wireless Extension Info */
719 range->we_version_compiled = WIRELESS_EXT;
720 range->we_version_source = WIRELESS_SUPPORT;
722 // Retry Limits and Lifetime - NOT SUPPORTED
724 /* Holding the lock too long, makes a gap to allow other processes */
725 wl_unlock(lp, &flags);
726 wl_lock( lp, &flags );
728 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
729 wl_wireless_stats( lp->dev );
730 range->avg_qual = lp->wstats.qual;
731 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
733 /* Event capability (kernel + driver) */
734 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
735 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
736 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
737 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
738 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
739 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
740 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
741 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
743 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
744 range->scan_capa = IW_SCAN_CAPA_NONE;
749 wl_unlock(lp, &flags);
753 } // wireless_get_range
754 /*============================================================================*/
757 /*******************************************************************************
758 * wireless_get_bssid()
759 *******************************************************************************
763 * Gets the BSSID the wireless device is currently associated with.
767 * wrq - the wireless request buffer
768 * lp - the device's private adapter structure
773 * errno value otherwise
775 ******************************************************************************/
776 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
778 struct wl_private *lp = wl_priv(dev);
781 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
783 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
784 /*------------------------------------------------------------------------*/
787 DBG_FUNC( "wireless_get_bssid" );
788 DBG_ENTER( DbgInfo );
790 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
795 wl_lock( lp, &flags );
797 wl_act_int_off( lp );
799 ap_addr->sa_family = ARPHRD_ETHER;
801 /* Assume AP mode here, which means the BSSID is our own MAC address. In
802 STA mode, this address will be overwritten with the actual BSSID using
804 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
807 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
808 //;?should we return an error status in AP mode
810 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
811 /* Get Current BSSID */
812 lp->ltvRecord.typ = CFG_CUR_BSSID;
813 lp->ltvRecord.len = 4;
814 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
816 if( status == HCF_SUCCESS ) {
817 /* Copy info into sockaddr struct */
818 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
824 #endif // (HCF_TYPE) & HCF_TYPE_STA
828 wl_unlock(lp, &flags);
833 } // wireless_get_bssid
834 /*============================================================================*/
839 /*******************************************************************************
840 * wireless_get_ap_list()
841 *******************************************************************************
845 * Gets the results of a network scan.
849 * wrq - the wireless request buffer
850 * lp - the device's private adapter structure
855 * errno value otherwise
857 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
858 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
859 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
861 ******************************************************************************/
862 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
864 struct wl_private *lp = wl_priv(dev);
870 struct sockaddr *hwa = NULL;
871 struct iw_quality *qual = NULL;
873 ScanResult *p = &lp->scan_results;
875 ProbeResult *p = &lp->probe_results;
877 /*------------------------------------------------------------------------*/
879 DBG_FUNC( "wireless_get_ap_list" );
880 DBG_ENTER( DbgInfo );
882 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
887 wl_lock( lp, &flags );
889 wl_act_int_off( lp );
891 /* Set the completion state to FALSE */
892 lp->scan_results.scan_complete = FALSE;
893 lp->probe_results.scan_complete = FALSE;
894 /* Channels to scan */
895 lp->ltvRecord.len = 2;
896 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
897 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
898 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
899 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
901 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
902 disassociate from the network we are currently on */
903 lp->ltvRecord.len = 2;
904 lp->ltvRecord.typ = CFG_SCAN_SSID;
905 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
906 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
907 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
909 /* Initiate the scan */
911 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
913 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
918 //;? unlock? what about the access to lp below? is it broken?
919 wl_unlock(lp, &flags);
921 if( ret == HCF_SUCCESS ) {
922 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
923 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
924 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
925 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
926 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
929 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
930 other things in the meantime, This prevents system lockups by
931 giving some time back to the kernel */
932 for( count = 0; count < 100; count ++ ) {
941 if ( ret != HCF_SUCCESS ) {
942 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
944 num_aps = (*p)/*lp->probe_results*/.num_aps;
945 if (num_aps > IW_MAX_AP) {
948 data->length = num_aps;
949 hwa = (struct sockaddr *)extra;
950 qual = (struct iw_quality *) extra +
951 ( sizeof( struct sockaddr ) * num_aps );
953 /* This flag is used to tell the user if we provide quality
954 information. Since we provide signal/noise levels but no
955 quality info on a scan, this is set to 0. Setting to 1 and
956 providing a quality of 0 produces weird results. If we ever
957 provide quality (or can calculate it), this can be changed */
960 for( count = 0; count < num_aps; count++ ) {
962 memcpy( hwa[count].sa_data,
963 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
964 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
965 DBG_PRINT("BSSID: %pM\n",
966 (*p).ProbeTable[count].BSSID);
967 memcpy( hwa[count].sa_data,
968 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
971 /* Once the data is copied to the wireless struct, invalidate the
972 scan result to initiate a rescan on the next request */
973 (*p)/*lp->probe_results*/.scan_complete = FALSE;
974 /* Send the wireless event that the scan has completed, just in case
976 wl_wext_event_scan_complete( lp->dev );
980 DBG_LEAVE( DbgInfo );
982 } // wireless_get_ap_list
983 /*============================================================================*/
988 /*******************************************************************************
989 * wireless_set_sensitivity()
990 *******************************************************************************
994 * Sets the sensitivity (distance between APs) of the wireless card.
998 * wrq - the wireless request buffer
999 * lp - the device's private adapter structure
1004 * errno value otherwise
1006 ******************************************************************************/
1007 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1009 struct wl_private *lp = wl_priv(dev);
1010 unsigned long flags;
1012 int dens = sens->value;
1013 /*------------------------------------------------------------------------*/
1016 DBG_FUNC( "wireless_set_sensitivity" );
1017 DBG_ENTER( DbgInfo );
1019 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1024 if(( dens < 1 ) || ( dens > 3 )) {
1029 wl_lock( lp, &flags );
1031 wl_act_int_off( lp );
1033 lp->DistanceBetweenAPs = dens;
1036 wl_act_int_on( lp );
1038 wl_unlock(lp, &flags);
1041 DBG_LEAVE( DbgInfo );
1043 } // wireless_set_sensitivity
1044 /*============================================================================*/
1049 /*******************************************************************************
1050 * wireless_get_sensitivity()
1051 *******************************************************************************
1055 * Gets the sensitivity (distance between APs) of the wireless card.
1059 * wrq - the wireless request buffer
1060 * lp - the device's private adapter structure
1065 * errno value otherwise
1067 ******************************************************************************/
1068 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1070 struct wl_private *lp = wl_priv(dev);
1072 /*------------------------------------------------------------------------*/
1073 /*------------------------------------------------------------------------*/
1076 DBG_FUNC( "wireless_get_sensitivity" );
1077 DBG_ENTER( DbgInfo );
1079 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1084 /* not worth locking ... */
1085 sens->value = lp->DistanceBetweenAPs;
1086 sens->fixed = 0; /* auto */
1088 DBG_LEAVE( DbgInfo );
1090 } // wireless_get_sensitivity
1091 /*============================================================================*/
1096 /*******************************************************************************
1097 * wireless_set_essid()
1098 *******************************************************************************
1102 * Sets the ESSID (network name) that the wireless device should associate
1107 * wrq - the wireless request buffer
1108 * lp - the device's private adapter structure
1113 * errno value otherwise
1115 ******************************************************************************/
1116 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
1118 struct wl_private *lp = wl_priv(dev);
1119 unsigned long flags;
1122 DBG_FUNC( "wireless_set_essid" );
1123 DBG_ENTER( DbgInfo );
1125 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1130 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
1135 wl_lock( lp, &flags );
1137 wl_act_int_off( lp );
1139 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
1141 /* data->flags is zero to ask for "any" */
1142 if( data->flags == 0 ) {
1143 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
1144 * ;?but there ain't no STAP anymore*/
1145 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
1146 strcpy( lp->NetworkName, "ANY" );
1148 //strcpy( lp->NetworkName, "ANY" );
1149 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
1152 memcpy( lp->NetworkName, ssid, data->length );
1155 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1157 /* Commit the adapter parameters */
1160 /* Send an event that ESSID has been set */
1161 wl_wext_event_essid( lp->dev );
1163 wl_act_int_on( lp );
1165 wl_unlock(lp, &flags);
1168 DBG_LEAVE( DbgInfo );
1170 } // wireless_set_essid
1171 /*============================================================================*/
1176 /*******************************************************************************
1177 * wireless_get_essid()
1178 *******************************************************************************
1182 * Gets the ESSID (network name) that the wireless device is associated
1187 * wrq - the wireless request buffer
1188 * lp - the device's private adapter structure
1193 * errno value otherwise
1195 ******************************************************************************/
1196 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1199 struct wl_private *lp = wl_priv(dev);
1200 unsigned long flags;
1204 /*------------------------------------------------------------------------*/
1207 DBG_FUNC( "wireless_get_essid" );
1208 DBG_ENTER( DbgInfo );
1210 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1215 wl_lock( lp, &flags );
1217 wl_act_int_off( lp );
1219 /* Get the desired network name */
1220 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1223 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1224 //;?should we return an error status in AP mode
1226 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1231 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1232 //;?should we restore this to allow smaller memory footprint
1234 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1235 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1241 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1242 if( status == HCF_SUCCESS ) {
1243 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1245 /* Endian translate the string length */
1246 pName->length = CNV_LITTLE_TO_INT( pName->length );
1248 /* Copy the information into the user buffer */
1249 data->length = pName->length;
1251 if( pName->length < HCF_MAX_NAME_LEN ) {
1252 pName->name[pName->length] = '\0';
1258 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1259 //;?should we return an error status in AP mode
1261 /* if desired is null ("any"), return current or "any" */
1262 if( pName->name[0] == '\0' ) {
1263 /* Get the current network name */
1264 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1265 lp->ltvRecord.typ = CFG_CUR_SSID;
1267 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1269 if( status == HCF_SUCCESS ) {
1270 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1272 /* Endian translate the string length */
1273 pName->length = CNV_LITTLE_TO_INT( pName->length );
1275 /* Copy the information into the user buffer */
1276 data->length = pName->length;
1286 if (pName->length > IW_ESSID_MAX_SIZE) {
1291 memcpy(essid, pName->name, pName->length);
1298 wl_act_int_on( lp );
1300 wl_unlock(lp, &flags);
1303 DBG_LEAVE( DbgInfo );
1305 } // wireless_get_essid
1306 /*============================================================================*/
1311 /*******************************************************************************
1312 * wireless_set_encode()
1313 *******************************************************************************
1317 * Sets the encryption keys and status (enable or disable).
1321 * wrq - the wireless request buffer
1322 * lp - the device's private adapter structure
1327 * errno value otherwise
1329 ******************************************************************************/
1330 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1332 struct wl_private *lp = wl_priv(dev);
1333 unsigned long flags;
1334 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1340 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
1345 if (erq->flags & IW_ENCODE_DISABLED)
1348 wl_lock(lp, &flags);
1352 ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1355 /* Send an event that Encryption has been set */
1357 wl_wext_event_encode(dev);
1361 wl_unlock(lp, &flags);
1368 /*******************************************************************************
1369 * wireless_get_encode()
1370 *******************************************************************************
1374 * Gets the encryption keys and status.
1378 * wrq - the wireless request buffer
1379 * lp - the device's private adapter structure
1384 * errno value otherwise
1386 ******************************************************************************/
1387 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1390 struct wl_private *lp = wl_priv(dev);
1391 unsigned long flags;
1394 /*------------------------------------------------------------------------*/
1397 DBG_FUNC( "wireless_get_encode" );
1398 DBG_ENTER( DbgInfo );
1399 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1401 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1406 /* Only super-user can see WEP key */
1407 if( !capable( CAP_NET_ADMIN )) {
1409 DBG_LEAVE( DbgInfo );
1413 wl_lock( lp, &flags );
1415 wl_act_int_off( lp );
1417 /* Is it supported? */
1418 if( !wl_has_wep( &( lp->hcfCtx ))) {
1423 /* Basic checking */
1424 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1430 if( lp->EnableEncryption == 0 ) {
1431 erq->flags |= IW_ENCODE_DISABLED;
1434 /* Which key do we want */
1435 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1436 index = lp->TransmitKeyID - 1;
1439 erq->flags |= index + 1;
1441 /* Copy the key to the user buffer */
1442 erq->length = lp->DefaultKeys.key[index].len;
1444 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1448 wl_act_int_on( lp );
1450 wl_unlock(lp, &flags);
1453 DBG_LEAVE( DbgInfo );
1455 } // wireless_get_encode
1456 /*============================================================================*/
1461 /*******************************************************************************
1462 * wireless_set_nickname()
1463 *******************************************************************************
1467 * Sets the nickname, or station name, of the wireless device.
1471 * wrq - the wireless request buffer
1472 * lp - the device's private adapter structure
1477 * errno value otherwise
1479 ******************************************************************************/
1480 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1482 struct wl_private *lp = wl_priv(dev);
1483 unsigned long flags;
1485 /*------------------------------------------------------------------------*/
1488 DBG_FUNC( "wireless_set_nickname" );
1489 DBG_ENTER( DbgInfo );
1491 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1496 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1497 if( !capable(CAP_NET_ADMIN )) {
1499 DBG_LEAVE( DbgInfo );
1504 /* Validate the new value */
1505 if(data->length > HCF_MAX_NAME_LEN) {
1510 wl_lock( lp, &flags );
1512 wl_act_int_off( lp );
1514 memset( lp->StationName, 0, sizeof( lp->StationName ));
1516 memcpy( lp->StationName, nickname, data->length );
1518 /* Commit the adapter parameters */
1521 wl_act_int_on( lp );
1523 wl_unlock(lp, &flags);
1526 DBG_LEAVE( DbgInfo );
1528 } // wireless_set_nickname
1529 /*============================================================================*/
1534 /*******************************************************************************
1535 * wireless_get_nickname()
1536 *******************************************************************************
1540 * Gets the nickname, or station name, of the wireless device.
1544 * wrq - the wireless request buffer
1545 * lp - the device's private adapter structure
1550 * errno value otherwise
1552 ******************************************************************************/
1553 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1555 struct wl_private *lp = wl_priv(dev);
1556 unsigned long flags;
1560 /*------------------------------------------------------------------------*/
1563 DBG_FUNC( "wireless_get_nickname" );
1564 DBG_ENTER( DbgInfo );
1566 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1571 wl_lock( lp, &flags );
1573 wl_act_int_off( lp );
1575 /* Get the current station name */
1576 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1577 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1579 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1581 if( status == HCF_SUCCESS ) {
1582 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1584 /* Endian translate the length */
1585 pName->length = CNV_LITTLE_TO_INT( pName->length );
1587 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1590 /* Copy the information into the user buffer */
1591 data->length = pName->length;
1592 memcpy(nickname, pName->name, pName->length);
1598 wl_act_int_on( lp );
1600 wl_unlock(lp, &flags);
1605 } // wireless_get_nickname
1606 /*============================================================================*/
1611 /*******************************************************************************
1612 * wireless_set_porttype()
1613 *******************************************************************************
1617 * Sets the port type of the wireless device.
1621 * wrq - the wireless request buffer
1622 * lp - the device's private adapter structure
1627 * errno value otherwise
1629 ******************************************************************************/
1630 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1632 struct wl_private *lp = wl_priv(dev);
1633 unsigned long flags;
1637 /*------------------------------------------------------------------------*/
1639 DBG_FUNC( "wireless_set_porttype" );
1640 DBG_ENTER( DbgInfo );
1642 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1647 wl_lock( lp, &flags );
1649 wl_act_int_off( lp );
1651 /* Validate the new value */
1655 /* When user requests ad-hoc, set IBSS mode! */
1659 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1667 /* Both automatic and infrastructure set port to BSS/STA mode */
1671 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1676 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1678 case IW_MODE_MASTER:
1680 /* Set BSS/AP mode */
1684 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1688 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1698 if( portType != 0 ) {
1699 /* Only do something if there is a mode change */
1700 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1701 lp->PortType = portType;
1702 lp->CreateIBSS = createIBSS;
1704 /* Commit the adapter parameters */
1707 /* Send an event that mode has been set */
1708 wl_wext_event_mode( lp->dev );
1712 wl_act_int_on( lp );
1714 wl_unlock(lp, &flags);
1717 DBG_LEAVE( DbgInfo );
1719 } // wireless_set_porttype
1720 /*============================================================================*/
1725 /*******************************************************************************
1726 * wireless_get_porttype()
1727 *******************************************************************************
1731 * Gets the port type of the wireless device.
1735 * wrq - the wireless request buffer
1736 * lp - the device's private adapter structure
1741 * errno value otherwise
1743 ******************************************************************************/
1744 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1747 struct wl_private *lp = wl_priv(dev);
1748 unsigned long flags;
1752 /*------------------------------------------------------------------------*/
1755 DBG_FUNC( "wireless_get_porttype" );
1756 DBG_ENTER( DbgInfo );
1758 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1763 wl_lock( lp, &flags );
1765 wl_act_int_off( lp );
1767 /* Get the current port type */
1768 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1769 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1771 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1773 if( status == HCF_SUCCESS ) {
1774 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1776 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1778 switch( *pPortType ) {
1782 #if (HCF_TYPE) & HCF_TYPE_AP
1784 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1785 *mode = IW_MODE_MASTER;
1787 *mode = IW_MODE_INFRA;
1792 *mode = IW_MODE_INFRA;
1794 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1797 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1798 *mode = IW_MODE_MASTER;
1800 if( lp->CreateIBSS ) {
1801 *mode = IW_MODE_ADHOC;
1803 *mode = IW_MODE_INFRA;
1811 *mode = IW_MODE_ADHOC;
1822 wl_act_int_on( lp );
1824 wl_unlock(lp, &flags);
1827 DBG_LEAVE( DbgInfo );
1829 } // wireless_get_porttype
1830 /*============================================================================*/
1835 /*******************************************************************************
1836 * wireless_set_power()
1837 *******************************************************************************
1841 * Sets the power management settings of the wireless device.
1845 * wrq - the wireless request buffer
1846 * lp - the device's private adapter structure
1851 * errno value otherwise
1853 ******************************************************************************/
1854 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1856 struct wl_private *lp = wl_priv(dev);
1857 unsigned long flags;
1859 /*------------------------------------------------------------------------*/
1862 DBG_FUNC( "wireless_set_power" );
1863 DBG_ENTER( DbgInfo );
1865 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1870 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1872 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1873 if( !capable( CAP_NET_ADMIN )) {
1876 DBG_LEAVE( DbgInfo );
1881 wl_lock( lp, &flags );
1883 wl_act_int_off( lp );
1885 /* Set the power management state based on the 'disabled' value */
1886 if( wrq->disabled ) {
1892 /* Commit the adapter parameters */
1895 wl_act_int_on( lp );
1897 wl_unlock(lp, &flags);
1900 DBG_LEAVE( DbgInfo );
1902 } // wireless_set_power
1903 /*============================================================================*/
1908 /*******************************************************************************
1909 * wireless_get_power()
1910 *******************************************************************************
1914 * Gets the power management settings of the wireless device.
1918 * wrq - the wireless request buffer
1919 * lp - the device's private adapter structure
1924 * errno value otherwise
1926 ******************************************************************************/
1927 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1930 struct wl_private *lp = wl_priv(dev);
1931 unsigned long flags;
1933 /*------------------------------------------------------------------------*/
1934 DBG_FUNC( "wireless_get_power" );
1935 DBG_ENTER( DbgInfo );
1937 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1942 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1944 wl_lock( lp, &flags );
1946 wl_act_int_off( lp );
1951 if( lp->PMEnabled ) {
1957 wl_act_int_on( lp );
1959 wl_unlock(lp, &flags);
1962 DBG_LEAVE( DbgInfo );
1964 } // wireless_get_power
1965 /*============================================================================*/
1970 /*******************************************************************************
1971 * wireless_get_tx_power()
1972 *******************************************************************************
1976 * Gets the transmit power of the wireless device's radio.
1980 * wrq - the wireless request buffer
1981 * lp - the device's private adapter structure
1986 * errno value otherwise
1988 ******************************************************************************/
1989 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1991 struct wl_private *lp = wl_priv(dev);
1992 unsigned long flags;
1994 /*------------------------------------------------------------------------*/
1995 DBG_FUNC( "wireless_get_tx_power" );
1996 DBG_ENTER( DbgInfo );
1998 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2003 wl_lock( lp, &flags );
2005 wl_act_int_off( lp );
2007 #ifdef USE_POWER_DBM
2008 rrq->value = RADIO_TX_POWER_DBM;
2009 rrq->flags = IW_TXPOW_DBM;
2011 rrq->value = RADIO_TX_POWER_MWATT;
2012 rrq->flags = IW_TXPOW_MWATT;
2017 wl_act_int_on( lp );
2019 wl_unlock(lp, &flags);
2022 DBG_LEAVE( DbgInfo );
2024 } // wireless_get_tx_power
2025 /*============================================================================*/
2030 /*******************************************************************************
2031 * wireless_set_rts_threshold()
2032 *******************************************************************************
2036 * Sets the RTS threshold for the wireless card.
2040 * wrq - the wireless request buffer
2041 * lp - the device's private adapter structure
2046 * errno value otherwise
2048 ******************************************************************************/
2049 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2052 struct wl_private *lp = wl_priv(dev);
2053 unsigned long flags;
2054 int rthr = rts->value;
2055 /*------------------------------------------------------------------------*/
2058 DBG_FUNC( "wireless_set_rts_threshold" );
2059 DBG_ENTER( DbgInfo );
2061 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2066 if(rts->fixed == 0) {
2071 if( rts->disabled ) {
2075 if(( rthr < 256 ) || ( rthr > 2347 )) {
2080 wl_lock( lp, &flags );
2082 wl_act_int_off( lp );
2084 lp->RTSThreshold = rthr;
2088 wl_act_int_on( lp );
2090 wl_unlock(lp, &flags);
2093 DBG_LEAVE( DbgInfo );
2095 } // wireless_set_rts_threshold
2096 /*============================================================================*/
2101 /*******************************************************************************
2102 * wireless_get_rts_threshold()
2103 *******************************************************************************
2107 * Gets the RTS threshold for the wireless card.
2111 * wrq - the wireless request buffer
2112 * lp - the device's private adapter structure
2117 * errno value otherwise
2119 ******************************************************************************/
2120 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2123 struct wl_private *lp = wl_priv(dev);
2124 unsigned long flags;
2125 /*------------------------------------------------------------------------*/
2127 DBG_FUNC( "wireless_get_rts_threshold" );
2128 DBG_ENTER( DbgInfo );
2130 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2135 wl_lock( lp, &flags );
2137 wl_act_int_off( lp );
2139 rts->value = lp->RTSThreshold;
2141 rts->disabled = ( rts->value == 2347 );
2145 wl_act_int_on( lp );
2147 wl_unlock(lp, &flags);
2150 DBG_LEAVE( DbgInfo );
2152 } // wireless_get_rts_threshold
2153 /*============================================================================*/
2159 /*******************************************************************************
2160 * wireless_set_rate()
2161 *******************************************************************************
2165 * Set the default data rate setting used by the wireless device.
2169 * wrq - the wireless request buffer
2170 * lp - the device's private adapter structure
2175 * errno value otherwise
2177 ******************************************************************************/
2178 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2180 struct wl_private *lp = wl_priv(dev);
2181 unsigned long flags;
2187 /*------------------------------------------------------------------------*/
2190 DBG_FUNC( "wireless_set_rate" );
2191 DBG_ENTER( DbgInfo );
2193 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2198 wl_lock( lp, &flags );
2200 wl_act_int_off( lp );
2204 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2205 if Bit 9 is set in the current channel RID */
2206 lp->ltvRecord.len = 2;
2207 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2209 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2211 if( status == HCF_SUCCESS ) {
2212 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2214 DBG_PRINT( "Index: %d\n", index );
2216 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2217 DBG_LEAVE( DbgInfo );
2222 if( rrq->value > 0 &&
2223 rrq->value <= 1 * MEGABIT ) {
2224 lp->TxRateControl[index] = 0x0001;
2226 else if( rrq->value > 1 * MEGABIT &&
2227 rrq->value <= 2 * MEGABIT ) {
2228 if( rrq->fixed == 1 ) {
2229 lp->TxRateControl[index] = 0x0002;
2231 lp->TxRateControl[index] = 0x0003;
2234 else if( rrq->value > 2 * MEGABIT &&
2235 rrq->value <= 5 * MEGABIT ) {
2236 if( rrq->fixed == 1 ) {
2237 lp->TxRateControl[index] = 0x0004;
2239 lp->TxRateControl[index] = 0x0007;
2242 else if( rrq->value > 5 * MEGABIT &&
2243 rrq->value <= 6 * MEGABIT ) {
2244 if( rrq->fixed == 1 ) {
2245 lp->TxRateControl[index] = 0x0010;
2247 lp->TxRateControl[index] = 0x0017;
2250 else if( rrq->value > 6 * MEGABIT &&
2251 rrq->value <= 9 * MEGABIT ) {
2252 if( rrq->fixed == 1 ) {
2253 lp->TxRateControl[index] = 0x0020;
2255 lp->TxRateControl[index] = 0x0037;
2258 else if( rrq->value > 9 * MEGABIT &&
2259 rrq->value <= 11 * MEGABIT ) {
2260 if( rrq->fixed == 1 ) {
2261 lp->TxRateControl[index] = 0x0008;
2263 lp->TxRateControl[index] = 0x003F;
2266 else if( rrq->value > 11 * MEGABIT &&
2267 rrq->value <= 12 * MEGABIT ) {
2268 if( rrq->fixed == 1 ) {
2269 lp->TxRateControl[index] = 0x0040;
2271 lp->TxRateControl[index] = 0x007F;
2274 else if( rrq->value > 12 * MEGABIT &&
2275 rrq->value <= 18 * MEGABIT ) {
2276 if( rrq->fixed == 1 ) {
2277 lp->TxRateControl[index] = 0x0080;
2279 lp->TxRateControl[index] = 0x00FF;
2282 else if( rrq->value > 18 * MEGABIT &&
2283 rrq->value <= 24 * MEGABIT ) {
2284 if( rrq->fixed == 1 ) {
2285 lp->TxRateControl[index] = 0x0100;
2287 lp->TxRateControl[index] = 0x01FF;
2290 else if( rrq->value > 24 * MEGABIT &&
2291 rrq->value <= 36 * MEGABIT ) {
2292 if( rrq->fixed == 1 ) {
2293 lp->TxRateControl[index] = 0x0200;
2295 lp->TxRateControl[index] = 0x03FF;
2298 else if( rrq->value > 36 * MEGABIT &&
2299 rrq->value <= 48 * MEGABIT ) {
2300 if( rrq->fixed == 1 ) {
2301 lp->TxRateControl[index] = 0x0400;
2303 lp->TxRateControl[index] = 0x07FF;
2306 else if( rrq->value > 48 * MEGABIT &&
2307 rrq->value <= 54 * MEGABIT ) {
2308 if( rrq->fixed == 1 ) {
2309 lp->TxRateControl[index] = 0x0800;
2311 lp->TxRateControl[index] = 0x0FFF;
2314 else if( rrq->fixed == 0 ) {
2315 /* In this case, the user has not specified a bitrate, only the "auto"
2316 moniker. So, set to all supported rates */
2317 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2327 if( rrq->value > 0 &&
2328 rrq->value <= 1 * MEGABIT ) {
2329 lp->TxRateControl[0] = 1;
2331 else if( rrq->value > 1 * MEGABIT &&
2332 rrq->value <= 2 * MEGABIT ) {
2334 lp->TxRateControl[0] = 2;
2336 lp->TxRateControl[0] = 6;
2339 else if( rrq->value > 2 * MEGABIT &&
2340 rrq->value <= 5 * MEGABIT ) {
2342 lp->TxRateControl[0] = 4;
2344 lp->TxRateControl[0] = 7;
2347 else if( rrq->value > 5 * MEGABIT &&
2348 rrq->value <= 11 * MEGABIT ) {
2350 lp->TxRateControl[0] = 5;
2352 lp->TxRateControl[0] = 3;
2355 else if( rrq->fixed == 0 ) {
2356 /* In this case, the user has not specified a bitrate, only the "auto"
2357 moniker. So, set the rate to 11Mb auto */
2358 lp->TxRateControl[0] = 3;
2368 /* Commit the adapter parameters */
2373 wl_act_int_on( lp );
2375 wl_unlock(lp, &flags);
2378 DBG_LEAVE( DbgInfo );
2380 } // wireless_set_rate
2381 /*============================================================================*/
2386 /*******************************************************************************
2387 * wireless_get_rate()
2388 *******************************************************************************
2392 * Get the default data rate setting used by the wireless device.
2396 * wrq - the wireless request buffer
2397 * lp - the device's private adapter structure
2402 * errno value otherwise
2404 ******************************************************************************/
2405 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2408 struct wl_private *lp = wl_priv(dev);
2409 unsigned long flags;
2413 /*------------------------------------------------------------------------*/
2416 DBG_FUNC( "wireless_get_rate" );
2417 DBG_ENTER( DbgInfo );
2419 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2424 wl_lock( lp, &flags );
2426 wl_act_int_off( lp );
2428 /* Get the current transmit rate from the adapter */
2429 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2430 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2432 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2434 if( status == HCF_SUCCESS ) {
2437 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2439 if( txRate & 0x0001 ) {
2442 else if( txRate & 0x0002 ) {
2445 else if( txRate & 0x0004 ) {
2448 else if( txRate & 0x0008 ) {
2451 else if( txRate & 0x00010 ) {
2454 else if( txRate & 0x00020 ) {
2457 else if( txRate & 0x00040 ) {
2460 else if( txRate & 0x00080 ) {
2463 else if( txRate & 0x00100 ) {
2466 else if( txRate & 0x00200 ) {
2469 else if( txRate & 0x00400 ) {
2472 else if( txRate & 0x00800 ) {
2478 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2482 rrq->value = txRate * MEGABIT;
2488 wl_act_int_on( lp );
2490 wl_unlock(lp, &flags);
2493 DBG_LEAVE( DbgInfo );
2495 } // wireless_get_rate
2496 /*============================================================================*/
2501 #if 0 //;? Not used anymore
2502 /*******************************************************************************
2503 * wireless_get_private_interface()
2504 *******************************************************************************
2508 * Returns the Linux Wireless Extensions' compatible private interface of
2513 * wrq - the wireless request buffer
2514 * lp - the device's private adapter structure
2519 * errno value otherwise
2521 ******************************************************************************/
2522 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2525 /*------------------------------------------------------------------------*/
2528 DBG_FUNC( "wireless_get_private_interface" );
2529 DBG_ENTER( DbgInfo );
2531 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2536 if( wrq->u.data.pointer != NULL ) {
2537 struct iw_priv_args priv[] =
2539 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2540 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2541 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2542 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2543 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2544 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2547 /* Verify the user buffer */
2548 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2551 DBG_LEAVE( DbgInfo );
2555 /* Copy the data into the user's buffer */
2556 wrq->u.data.length = NELEM( priv );
2557 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2561 DBG_LEAVE( DbgInfo );
2563 } // wireless_get_private_interface
2564 /*============================================================================*/
2569 /*******************************************************************************
2570 * wireless_set_scan()
2571 *******************************************************************************
2575 * Instructs the driver to initiate a network scan.
2579 * wrq - the wireless request buffer
2580 * lp - the device's private adapter structure
2585 * errno value otherwise
2587 ******************************************************************************/
2588 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2590 struct wl_private *lp = wl_priv(dev);
2591 unsigned long flags;
2595 /*------------------------------------------------------------------------*/
2597 //;? Note: shows results as trace, returns always 0 unless BUSY
2599 DBG_FUNC( "wireless_set_scan" );
2600 DBG_ENTER( DbgInfo );
2602 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2607 wl_lock( lp, &flags );
2609 wl_act_int_off( lp );
2612 * This looks like a nice place to test if the HCF is still
2613 * communicating with the card. It seems that sometimes BAP_1
2614 * gets corrupted. By looking at the comments in HCF the
2615 * cause is still a mystery. Okay, the communication to the
2616 * card is dead, reset the card to revive.
2618 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2620 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2625 /* Set the completion state to FALSE */
2626 lp->probe_results.scan_complete = FALSE;
2629 /* Channels to scan */
2631 lp->ltvRecord.len = 5;
2632 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2633 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2634 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2635 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2636 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2638 lp->ltvRecord.len = 2;
2639 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2640 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2643 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2645 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2647 // Holding the lock too long, makes a gap to allow other processes
2648 wl_unlock(lp, &flags);
2649 wl_lock( lp, &flags );
2651 if( status != HCF_SUCCESS ) {
2655 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2658 // Holding the lock too long, makes a gap to allow other processes
2659 wl_unlock(lp, &flags);
2660 wl_lock( lp, &flags );
2666 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2667 disassociate from the network we are currently on */
2668 lp->ltvRecord.len = 18;
2669 lp->ltvRecord.typ = CFG_SCAN_SSID;
2670 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2671 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2673 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2675 // Holding the lock too long, makes a gap to allow other processes
2676 wl_unlock(lp, &flags);
2677 wl_lock( lp, &flags );
2679 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2681 /* Initiate the scan */
2682 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2683 retrieve probe response must always be used to support WPA */
2684 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2686 if( status == HCF_SUCCESS ) {
2687 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2689 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2692 wl_act_int_on( lp );
2694 wl_unlock(lp, &flags);
2699 } // wireless_set_scan
2700 /*============================================================================*/
2705 /*******************************************************************************
2706 * wireless_get_scan()
2707 *******************************************************************************
2711 * Instructs the driver to gather and return the results of a network scan.
2715 * wrq - the wireless request buffer
2716 * lp - the device's private adapter structure
2721 * errno value otherwise
2723 ******************************************************************************/
2724 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2726 struct wl_private *lp = wl_priv(dev);
2727 unsigned long flags;
2732 struct iw_event iwe;
2733 PROBE_RESP *probe_resp;
2737 /*------------------------------------------------------------------------*/
2740 DBG_FUNC( "wireless_get_scan" );
2741 DBG_ENTER( DbgInfo );
2743 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2748 wl_lock( lp, &flags );
2750 wl_act_int_off( lp );
2752 /* If the scan is not done, tell the calling process to try again later */
2753 if( !lp->probe_results.scan_complete ) {
2758 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2759 lp->probe_results.num_aps );
2762 buf_end = extra + IW_SCAN_MAX_DATA;
2764 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2765 /* Reference the probe response from the table */
2766 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2769 /* First entry MUST be the MAC address */
2770 memset( &iwe, 0, sizeof( iwe ));
2772 iwe.cmd = SIOCGIWAP;
2773 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2774 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2775 iwe.len = IW_EV_ADDR_LEN;
2777 buf = iwe_stream_add_event(info, buf, buf_end,
2778 &iwe, IW_EV_ADDR_LEN);
2780 /* Use the mode to indicate if it's a station or AP */
2781 /* Won't always be an AP if in IBSS mode */
2782 memset( &iwe, 0, sizeof( iwe ));
2784 iwe.cmd = SIOCGIWMODE;
2786 if( probe_resp->capability & CAPABILITY_IBSS ) {
2787 iwe.u.mode = IW_MODE_INFRA;
2789 iwe.u.mode = IW_MODE_MASTER;
2792 iwe.len = IW_EV_UINT_LEN;
2794 buf = iwe_stream_add_event(info, buf, buf_end,
2795 &iwe, IW_EV_UINT_LEN);
2797 /* Any quality information */
2798 memset(&iwe, 0, sizeof(iwe));
2801 iwe.u.qual.level = dbm(probe_resp->signal);
2802 iwe.u.qual.noise = dbm(probe_resp->silence);
2803 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2804 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2805 iwe.len = IW_EV_QUAL_LEN;
2807 buf = iwe_stream_add_event(info, buf, buf_end,
2808 &iwe, IW_EV_QUAL_LEN);
2811 /* ESSID information */
2812 if( probe_resp->rawData[1] > 0 ) {
2813 memset( &iwe, 0, sizeof( iwe ));
2815 iwe.cmd = SIOCGIWESSID;
2816 iwe.u.data.length = probe_resp->rawData[1];
2817 iwe.u.data.flags = 1;
2819 buf = iwe_stream_add_point(info, buf, buf_end,
2820 &iwe, &probe_resp->rawData[2]);
2824 /* Encryption Information */
2825 memset( &iwe, 0, sizeof( iwe ));
2827 iwe.cmd = SIOCGIWENCODE;
2828 iwe.u.data.length = 0;
2830 /* Check the capabilities field of the Probe Response to see if
2831 'privacy' is supported on the AP in question */
2832 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2833 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2835 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2838 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
2841 /* Frequency Info */
2842 memset( &iwe, 0, sizeof( iwe ));
2844 iwe.cmd = SIOCGIWFREQ;
2845 iwe.len = IW_EV_FREQ_LEN;
2846 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2849 buf = iwe_stream_add_event(info, buf, buf_end,
2850 &iwe, IW_EV_FREQ_LEN);
2853 /* Custom info (Beacon Interval) */
2854 memset( &iwe, 0, sizeof( iwe ));
2855 memset( msg, 0, sizeof( msg ));
2857 iwe.cmd = IWEVCUSTOM;
2858 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2859 iwe.u.data.length = strlen( msg );
2861 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
2868 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2869 if( wpa_ie != NULL ) {
2870 memset(&iwe, 0, sizeof(iwe));
2872 iwe.cmd = IWEVGENIE;
2873 iwe.u.data.length = wpa_ie_len;
2875 buf = iwe_stream_add_point(info, buf, buf_end,
2879 /* Add other custom info in formatted string format as needed... */
2882 data->length = buf - extra;
2886 wl_act_int_on( lp );
2888 wl_unlock(lp, &flags);
2891 DBG_LEAVE( DbgInfo );
2893 } // wireless_get_scan
2894 /*============================================================================*/
2897 static const char * const auth_names[] = {
2898 "IW_AUTH_WPA_VERSION",
2899 "IW_AUTH_CIPHER_PAIRWISE",
2900 "IW_AUTH_CIPHER_GROUP",
2902 "IW_AUTH_TKIP_COUNTERMEASURES",
2903 "IW_AUTH_DROP_UNENCRYPTED",
2904 "IW_AUTH_80211_AUTH_ALG",
2905 "IW_AUTH_WPA_ENABLED",
2906 "IW_AUTH_RX_UNENCRYPTED_EAPOL",
2907 "IW_AUTH_ROAMING_CONTROL",
2908 "IW_AUTH_PRIVACY_INVOKED",
2909 "IW_AUTH_CIPHER_GROUP_MGMT",
2915 static int wireless_set_auth(struct net_device *dev,
2916 struct iw_request_info *info,
2917 struct iw_param *data, char *extra)
2919 struct wl_private *lp = wl_priv(dev);
2920 unsigned long flags;
2923 int iwa_idx = data->flags & IW_AUTH_INDEX;
2924 int iwa_val = data->value;
2926 DBG_FUNC( "wireless_set_auth" );
2927 DBG_ENTER( DbgInfo );
2929 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2934 wl_lock( lp, &flags );
2936 wl_act_int_off( lp );
2938 if (iwa_idx > IW_AUTH_MFP)
2939 iwa_idx = IW_AUTH_MFP + 1;
2940 DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
2942 case IW_AUTH_WPA_VERSION:
2943 /* We do support WPA */
2944 if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
2945 (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
2951 case IW_AUTH_WPA_ENABLED:
2952 DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
2954 lp->EnableEncryption = 2;
2956 lp->EnableEncryption = 0;
2958 /* Write straight to the card */
2960 ltv.typ = CFG_CNF_ENCRYPTION;
2961 ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
2962 ret = hcf_put_info(&lp->hcfCtx, (LTVP)<v);
2966 case IW_AUTH_TKIP_COUNTERMEASURES:
2968 /* Immediately disable card */
2969 lp->driverEnable = !iwa_val;
2970 if (lp->driverEnable)
2971 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2973 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2978 /* Management Frame Protection not supported.
2979 * Only fail if set to required.
2981 if (iwa_val == IW_AUTH_MFP_REQUIRED)
2987 case IW_AUTH_KEY_MGMT:
2989 /* Record required management suite.
2990 * Will take effect on next commit */
2992 lp->AuthKeyMgmtSuite = 4;
2994 lp->AuthKeyMgmtSuite = 0;
2999 case IW_AUTH_80211_AUTH_ALG:
3001 /* Just record whether open or shared is required.
3002 * Will take effect on next commit */
3005 if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
3006 lp->authentication = 1;
3007 else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
3008 lp->authentication = 0;
3013 case IW_AUTH_DROP_UNENCRYPTED:
3014 /* Only needed for AP */
3015 lp->ExcludeUnencrypted = iwa_val;
3019 case IW_AUTH_CIPHER_PAIRWISE:
3020 case IW_AUTH_CIPHER_GROUP:
3021 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3022 case IW_AUTH_ROAMING_CONTROL:
3023 case IW_AUTH_PRIVACY_INVOKED:
3024 /* Not used. May need to do something with
3025 * CIPHER_PAIRWISE and CIPHER_GROUP*/
3030 DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
3031 /* return an error */
3036 wl_act_int_on( lp );
3038 wl_unlock(lp, &flags);
3041 DBG_LEAVE( DbgInfo );
3043 } // wireless_set_auth
3044 /*============================================================================*/
3047 static void flush_tx(struct wl_private *lp)
3053 * Make sure that there is no data queued up in the firmware
3054 * before setting the TKIP keys. If this check is not
3055 * performed, some data may be sent out with incorrect MIC
3056 * and cause synchronization errors with the AP
3058 /* Check every 1ms for 100ms */
3059 for (count = 0; count < 100; count++) {
3063 ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
3066 hcf_get_info(&(lp->hcfCtx), (LTVP)<v);
3068 if (ltv.u.u16[0] == 0)
3073 DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
3077 static int wireless_set_encodeext(struct net_device *dev,
3078 struct iw_request_info *info,
3079 struct iw_point *erq, char *keybuf)
3081 struct wl_private *lp = wl_priv(dev);
3082 unsigned long flags;
3084 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
3086 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3088 bool set_tx = false;
3092 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
3097 if (erq->flags & IW_ENCODE_DISABLED) {
3098 ext->alg = IW_ENCODE_ALG_NONE;
3102 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
3105 wl_lock(lp, &flags);
3109 memset(<v, 0, sizeof(ltv));
3112 case IW_ENCODE_ALG_TKIP:
3113 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3115 if (sizeof(ext->rx_seq) != 8) {
3116 DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
3122 ret = hermes_set_tkip_keys(<v, key_idx, ext->addr.sa_data,
3124 ext->rx_seq, ext->key, ext->key_len);
3127 DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
3133 lp->wext_enc = IW_ENCODE_ALG_TKIP;
3136 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3139 case IW_ENCODE_ALG_WEP:
3140 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3142 if (erq->flags & IW_ENCODE_RESTRICTED) {
3143 DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
3148 ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
3153 case IW_ENCODE_ALG_CCMP:
3154 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3158 case IW_ENCODE_ALG_NONE:
3159 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3161 if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
3162 ret = hermes_clear_tkip_keys(<v, key_idx,
3165 lp->wext_enc = IW_ENCODE_ALG_NONE;
3166 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3168 } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
3169 ret = hermes_set_wep_keys(lp, key_idx,
3170 ext->key, ext->key_len,
3179 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3188 wl_unlock(lp, &flags);
3194 /*============================================================================*/
3198 static int wireless_set_genie(struct net_device *dev,
3199 struct iw_request_info *info,
3200 struct iw_point *data, char *extra)
3207 /* We can't write this to the card, but apparently this
3208 * operation needs to succeed */
3214 /*============================================================================*/
3217 /*******************************************************************************
3218 * wl_wireless_stats()
3219 *******************************************************************************
3223 * Return the current device wireless statistics.
3227 * wrq - the wireless request buffer
3228 * lp - the device's private adapter structure
3233 * errno value otherwise
3235 ******************************************************************************/
3236 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3238 struct iw_statistics *pStats;
3239 struct wl_private *lp = wl_priv(dev);
3240 /*------------------------------------------------------------------------*/
3243 DBG_FUNC( "wl_wireless_stats" );
3245 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3249 /* Initialize the statistics */
3250 pStats = &( lp->wstats );
3251 pStats->qual.updated = 0x00;
3253 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3255 CFG_COMMS_QUALITY_STRCT *pQual;
3256 CFG_HERMES_TALLIES_STRCT tallies;
3259 /* Update driver status */
3262 /* Get the current link quality information */
3263 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3264 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3265 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3267 if( status == HCF_SUCCESS ) {
3268 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3270 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3271 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3272 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3274 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3275 IW_QUAL_LEVEL_UPDATED |
3276 IW_QUAL_NOISE_UPDATED |
3279 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3282 /* Get the current tallies from the adapter */
3283 /* Only possible when the device is open */
3284 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3285 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3286 /* No endian translation is needed here, as CFG_TALLIES is an
3287 MSF RID; all processing is done on the host, not the card! */
3288 pStats->discard.nwid = 0L;
3289 pStats->discard.code = tallies.RxWEPUndecryptable;
3290 pStats->discard.misc = tallies.TxDiscards +
3291 tallies.RxFCSErrors +
3292 //tallies.RxDiscardsNoBuffer +
3293 tallies.TxDiscardsWrongSA;
3294 //;? Extra taken over from Linux driver based on 7.18 version
3295 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3296 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3298 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3301 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3305 DBG_LEAVE( DbgInfo );
3307 } // wl_wireless_stats
3308 /*============================================================================*/
3313 /*******************************************************************************
3314 * wl_get_wireless_stats()
3315 *******************************************************************************
3319 * Return the current device wireless statistics. This function calls
3320 * wl_wireless_stats, but acquires spinlocks first as it can be called
3321 * directly by the network layer.
3325 * wrq - the wireless request buffer
3326 * lp - the device's private adapter structure
3331 * errno value otherwise
3333 ******************************************************************************/
3334 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3336 unsigned long flags;
3337 struct wl_private *lp = wl_priv(dev);
3338 struct iw_statistics *pStats = NULL;
3339 /*------------------------------------------------------------------------*/
3341 DBG_FUNC( "wl_get_wireless_stats" );
3344 wl_lock( lp, &flags );
3346 wl_act_int_off( lp );
3349 if( lp->useRTS == 1 ) {
3350 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3354 pStats = wl_wireless_stats( dev );
3356 wl_act_int_on( lp );
3358 wl_unlock(lp, &flags);
3360 DBG_LEAVE( DbgInfo );
3362 } // wl_get_wireless_stats
3365 /*******************************************************************************
3367 *******************************************************************************
3371 * Gather wireless spy statistics.
3375 * wrq - the wireless request buffer
3376 * lp - the device's private adapter structure
3381 * errno value otherwise
3383 ******************************************************************************/
3384 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3386 struct iw_quality wstats;
3390 struct wl_private *lp = wl_priv(dev);
3391 /*------------------------------------------------------------------------*/
3394 if (!lp->spy_data.spy_number) {
3398 /* Gather wireless spy statistics: for each packet, compare the source
3399 address with out list, and if match, get the stats. */
3400 memset( stats, 0, sizeof(stats));
3401 memset( desc, 0, sizeof(DESC_STRCT));
3403 desc[0].buf_addr = stats;
3404 desc[0].BUF_SIZE = sizeof(stats);
3405 desc[0].next_desc_addr = 0; // terminate list
3407 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3409 if( status == HCF_SUCCESS ) {
3410 wstats.level = (u_char) dbm(stats[1]);
3411 wstats.noise = (u_char) dbm(stats[0]);
3412 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3414 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3415 IW_QUAL_LEVEL_UPDATED |
3416 IW_QUAL_NOISE_UPDATED |
3419 wireless_spy_update( dev, mac, &wstats );
3422 /*============================================================================*/
3427 /*******************************************************************************
3428 * wl_wext_event_freq()
3429 *******************************************************************************
3433 * This function is used to send an event that the channel/freq
3434 * configuration for a specific device has changed.
3439 * dev - the network device for which this event is to be issued
3445 ******************************************************************************/
3446 void wl_wext_event_freq( struct net_device *dev )
3448 union iwreq_data wrqu;
3449 struct wl_private *lp = wl_priv(dev);
3450 /*------------------------------------------------------------------------*/
3453 memset( &wrqu, 0, sizeof( wrqu ));
3455 wrqu.freq.m = lp->Channel;
3458 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3461 } // wl_wext_event_freq
3462 /*============================================================================*/
3467 /*******************************************************************************
3468 * wl_wext_event_mode()
3469 *******************************************************************************
3473 * This function is used to send an event that the mode of operation
3474 * for a specific device has changed.
3479 * dev - the network device for which this event is to be issued
3485 ******************************************************************************/
3486 void wl_wext_event_mode( struct net_device *dev )
3488 union iwreq_data wrqu;
3489 struct wl_private *lp = wl_priv(dev);
3490 /*------------------------------------------------------------------------*/
3493 memset( &wrqu, 0, sizeof( wrqu ));
3495 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3496 wrqu.mode = IW_MODE_INFRA;
3498 wrqu.mode = IW_MODE_MASTER;
3501 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3504 } // wl_wext_event_mode
3505 /*============================================================================*/
3510 /*******************************************************************************
3511 * wl_wext_event_essid()
3512 *******************************************************************************
3516 * This function is used to send an event that the ESSID configuration for
3517 * a specific device has changed.
3522 * dev - the network device for which this event is to be issued
3528 ******************************************************************************/
3529 void wl_wext_event_essid( struct net_device *dev )
3531 union iwreq_data wrqu;
3532 struct wl_private *lp = wl_priv(dev);
3533 /*------------------------------------------------------------------------*/
3536 memset( &wrqu, 0, sizeof( wrqu ));
3538 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3539 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3540 the call to wireless_send_event() must also point to where the ESSID
3542 wrqu.essid.length = strlen( lp->NetworkName );
3543 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3544 wrqu.essid.flags = 1;
3546 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3549 } // wl_wext_event_essid
3550 /*============================================================================*/
3555 /*******************************************************************************
3556 * wl_wext_event_encode()
3557 *******************************************************************************
3561 * This function is used to send an event that the encryption configuration
3562 * for a specific device has changed.
3567 * dev - the network device for which this event is to be issued
3573 ******************************************************************************/
3574 void wl_wext_event_encode( struct net_device *dev )
3576 union iwreq_data wrqu;
3577 struct wl_private *lp = wl_priv(dev);
3579 /*------------------------------------------------------------------------*/
3582 memset( &wrqu, 0, sizeof( wrqu ));
3584 if( lp->EnableEncryption == 0 ) {
3585 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3587 wrqu.encoding.flags |= lp->TransmitKeyID;
3589 index = lp->TransmitKeyID - 1;
3591 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3592 if we're in AP mode */
3593 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3594 //;?should we restore this to allow smaller memory footprint
3596 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3597 if( lp->ExcludeUnencrypted ) {
3598 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3600 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3604 #endif // HCF_TYPE_AP
3606 /* Only provide the key if permissions allow */
3607 if( capable( CAP_NET_ADMIN )) {
3608 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3609 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3611 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3615 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3616 lp->DefaultKeys.key[index].key );
3619 } // wl_wext_event_encode
3620 /*============================================================================*/
3625 /*******************************************************************************
3626 * wl_wext_event_ap()
3627 *******************************************************************************
3631 * This function is used to send an event that the device has been
3632 * associated to a new AP.
3637 * dev - the network device for which this event is to be issued
3643 ******************************************************************************/
3644 void wl_wext_event_ap( struct net_device *dev )
3646 union iwreq_data wrqu;
3647 struct wl_private *lp = wl_priv(dev);
3649 /*------------------------------------------------------------------------*/
3652 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3653 this event BEFORE sending the association event, as there are timing
3654 issues with the hostap supplicant. The supplicant will attempt to process
3655 an EAPOL-Key frame from an AP before receiving this information, which
3656 is required for a proper processed frame. */
3657 wl_wext_event_assoc_ie( dev );
3660 lp->ltvRecord.typ = CFG_CUR_BSSID;
3661 lp->ltvRecord.len = 4;
3663 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3664 if( status == HCF_SUCCESS ) {
3665 memset( &wrqu, 0, sizeof( wrqu ));
3667 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3669 wrqu.addr.sa_family = ARPHRD_ETHER;
3671 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3675 } // wl_wext_event_ap
3676 /*============================================================================*/
3680 /*******************************************************************************
3681 * wl_wext_event_scan_complete()
3682 *******************************************************************************
3686 * This function is used to send an event that a request for a network scan
3692 * dev - the network device for which this event is to be issued
3698 ******************************************************************************/
3699 void wl_wext_event_scan_complete( struct net_device *dev )
3701 union iwreq_data wrqu;
3702 /*------------------------------------------------------------------------*/
3705 memset( &wrqu, 0, sizeof( wrqu ));
3707 wrqu.addr.sa_family = ARPHRD_ETHER;
3708 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3711 } // wl_wext_event_scan_complete
3712 /*============================================================================*/
3717 /*******************************************************************************
3718 * wl_wext_event_new_sta()
3719 *******************************************************************************
3723 * This function is used to send an event that an AP has registered a new
3729 * dev - the network device for which this event is to be issued
3735 ******************************************************************************/
3736 void wl_wext_event_new_sta( struct net_device *dev )
3738 union iwreq_data wrqu;
3739 /*------------------------------------------------------------------------*/
3742 memset( &wrqu, 0, sizeof( wrqu ));
3744 /* Send the station's mac address here */
3745 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3746 wrqu.addr.sa_family = ARPHRD_ETHER;
3747 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3750 } // wl_wext_event_new_sta
3751 /*============================================================================*/
3756 /*******************************************************************************
3757 * wl_wext_event_expired_sta()
3758 *******************************************************************************
3762 * This function is used to send an event that an AP has deregistered a
3768 * dev - the network device for which this event is to be issued
3774 ******************************************************************************/
3775 void wl_wext_event_expired_sta( struct net_device *dev )
3777 union iwreq_data wrqu;
3778 /*------------------------------------------------------------------------*/
3781 memset( &wrqu, 0, sizeof( wrqu ));
3783 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3784 wrqu.addr.sa_family = ARPHRD_ETHER;
3785 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3788 } // wl_wext_event_expired_sta
3789 /*============================================================================*/
3794 /*******************************************************************************
3795 * wl_wext_event_mic_failed()
3796 *******************************************************************************
3800 * This function is used to send an event that MIC calculations failed.
3805 * dev - the network device for which this event is to be issued
3811 ******************************************************************************/
3812 void wl_wext_event_mic_failed( struct net_device *dev )
3814 union iwreq_data wrqu;
3815 struct wl_private *lp = wl_priv(dev);
3816 struct iw_michaelmicfailure wxmic;
3820 WVLAN_RX_WMP_HDR *hdr;
3821 /*------------------------------------------------------------------------*/
3824 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3827 /* Cast the lookahead buffer into a RFS format */
3828 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3830 /* Cast the addresses to byte buffers, as in the above RFS they are word
3832 addr1 = (char *)hdr->address1;
3833 addr2 = (char *)hdr->address2;
3835 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3838 memset(&wrqu, 0, sizeof(wrqu));
3839 memset(&wxmic, 0, sizeof(wxmic));
3841 wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3842 wxmic.flags |= (addr1[0] & 1) ?
3843 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
3844 wxmic.src_addr.sa_family = ARPHRD_ETHER;
3845 memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3847 wrqu.data.length = sizeof(wxmic);
3848 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3851 } // wl_wext_event_mic_failed
3852 /*============================================================================*/
3857 /*******************************************************************************
3858 * wl_wext_event_assoc_ie()
3859 *******************************************************************************
3863 * This function is used to send an event containing the WPA-IE generated
3864 * by the firmware in an association request.
3869 * dev - the network device for which this event is to be issued
3875 ******************************************************************************/
3876 void wl_wext_event_assoc_ie( struct net_device *dev )
3878 union iwreq_data wrqu;
3879 struct wl_private *lp = wl_priv(dev);
3884 /*------------------------------------------------------------------------*/
3887 memset( &wrqu, 0, sizeof( wrqu ));
3889 /* Retrieve the Association Request IE */
3890 lp->ltvRecord.len = 45;
3891 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3893 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3894 if( status == HCF_SUCCESS )
3897 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3898 wpa_ie = wl_parse_wpa_ie( &data, &length );
3902 wrqu.data.length = wpa_ie[1] + 2;
3903 wireless_send_event(dev, IWEVASSOCREQIE,
3906 /* This bit is a hack. We send the respie
3907 * event at the same time */
3908 wireless_send_event(dev, IWEVASSOCRESPIE,
3914 } // wl_wext_event_assoc_ie
3915 /*============================================================================*/
3916 /* Structures to export the Wireless Handlers */
3918 static const iw_handler wl_handler[] =
3920 IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
3921 IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
3922 IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
3923 IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
3924 IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
3925 IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
3926 IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
3927 IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
3928 IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
3929 IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
3930 IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
3931 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3932 IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
3934 IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
3935 IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
3936 IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
3937 IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
3938 IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
3939 IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
3940 IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
3941 IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
3942 IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
3943 IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
3944 IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
3945 IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
3946 IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
3947 IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
3948 IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
3949 IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
3950 IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
3951 IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3952 IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
3955 static const iw_handler wl_private_handler[] =
3956 { /* SIOCIWFIRSTPRIV + */
3957 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3958 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3959 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3960 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3961 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3962 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3963 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3967 struct iw_priv_args wl_priv_args[] = {
3968 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3969 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3970 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3971 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3972 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3973 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3974 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3978 const struct iw_handler_def wl_iw_handler_def =
3980 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3981 .private = (iw_handler *) wl_private_handler,
3982 .private_args = (struct iw_priv_args *) wl_priv_args,
3983 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3984 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3985 .standard = (iw_handler *) wl_handler,
3986 .get_wireless_stats = wl_get_wireless_stats,