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>
78 /*******************************************************************************
80 ******************************************************************************/
82 extern dbg_info_t *DbgInfo;
86 /* Set up the LTV to program the appropriate key */
87 static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr,
88 int set_tx, u8 *seq, u8 *key, size_t key_len)
92 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
93 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
98 * Check the key index here; if 0, load as Pairwise Key, otherwise,
99 * load as a group key. Note that for the Hermes, the RIDs for
100 * group/pairwise keys are different from each other and different
101 * than the default WEP keys as well.
106 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
109 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
112 /* Load the TKIP key */
113 memcpy(<v->u.u8[buf_idx], &key[0], 16);
117 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
118 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
121 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
122 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
124 /* Load the TxMIC key */
125 memcpy(<v->u.u8[buf_idx], &key[16], 8);
128 /* Load the RxMIC key */
129 memcpy(<v->u.u8[buf_idx], &key[24], 8);
137 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
139 /* Load the key Index */
141 /* If this is a Tx Key, set bit 8000 */
144 ltv->u.u16[buf_idx] = cpu_to_le16(key_idx);
148 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
149 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
151 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
152 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
153 memcpy(<v->u.u8[buf_idx], key, key_len);
157 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
169 /* Set up the LTV to clear the appropriate key */
170 static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr)
176 if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
178 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
179 memcpy(<v->u.u8[0], addr, ETH_ALEN);
186 /* Clear the Group TKIP keys by index */
188 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
189 ltv->u.u16[0] = cpu_to_le16(key_idx);
200 /* Set the WEP keys in the wl_private structure */
201 static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
202 u8 *key, size_t key_len,
203 bool enable, bool set_tx)
205 hcf_8 encryption_state = lp->EnableEncryption;
206 int tk = lp->TransmitKeyID - 1; /* current key */
209 /* Is encryption supported? */
210 if (!wl_has_wep(&(lp->hcfCtx))) {
211 DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
216 DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
219 /* Check the size of the key */
224 /* Check the index */
225 if ((key_idx < 0) || (key_idx >= MAX_KEYS))
229 memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
231 /* Copy the key in the driver */
232 memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
235 lp->DefaultKeys.key[key_idx].len = key_len;
237 DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
238 DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
239 lp->DefaultKeys.key[key_idx].key,
240 lp->DefaultKeys.key[key_idx].len, key_idx);
242 /* Enable WEP (if possible) */
243 if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
244 lp->EnableEncryption = 1;
249 /* Do we want to just set the current transmit key? */
250 if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
251 DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
252 lp->DefaultKeys.key[key_idx].len);
254 if (lp->DefaultKeys.key[key_idx].len > 0) {
255 lp->TransmitKeyID = key_idx + 1;
256 lp->EnableEncryption = 1;
258 DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
265 DBG_WARNING(DbgInfo, "Invalid Key length\n");
272 lp->EnableEncryption = 1;
273 lp->wext_enc = IW_ENCODE_ALG_WEP;
275 lp->EnableEncryption = 0; /* disable encryption */
276 lp->wext_enc = IW_ENCODE_ALG_NONE;
279 DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
280 DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
281 DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
283 /* Write the changes to the card */
285 DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
288 if (lp->EnableEncryption == encryption_state) {
290 /* Dynamic WEP key update */
294 /* To switch encryption on/off, soft reset is
304 /*******************************************************************************
306 *******************************************************************************
315 * wrq - the wireless request buffer
321 ******************************************************************************/
322 static int wireless_commit(struct net_device *dev,
323 struct iw_request_info *info,
324 union iwreq_data *rqu, char *extra)
326 struct wl_private *lp = wl_priv(dev);
329 /*------------------------------------------------------------------------*/
331 DBG_FUNC( "wireless_commit" );
334 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
339 wl_lock( lp, &flags );
341 wl_act_int_off( lp );
347 wl_unlock(lp, &flags);
350 DBG_LEAVE( DbgInfo );
353 /*============================================================================*/
358 /*******************************************************************************
359 * wireless_get_protocol()
360 *******************************************************************************
364 * Returns a vendor-defined string that should identify the wireless
369 * wrq - the wireless request buffer
375 ******************************************************************************/
376 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
378 DBG_FUNC( "wireless_get_protocol" );
379 DBG_ENTER( DbgInfo );
381 /* Originally, the driver was placing the string "Wireless" here. However,
382 the wireless extensions (/linux/wireless.h) indicate this string should
383 describe the wireless protocol. */
385 strcpy(name, "IEEE 802.11b");
389 } // wireless_get_protocol
390 /*============================================================================*/
395 /*******************************************************************************
396 * wireless_set_frequency()
397 *******************************************************************************
401 * Sets the frequency (channel) on which the card should Tx/Rx.
405 * wrq - the wireless request buffer
406 * lp - the device's private adapter structure
411 * errno value otherwise
413 ******************************************************************************/
414 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
416 struct wl_private *lp = wl_priv(dev);
420 /*------------------------------------------------------------------------*/
423 DBG_FUNC( "wireless_set_frequency" );
424 DBG_ENTER( DbgInfo );
426 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
431 if( !capable( CAP_NET_ADMIN )) {
433 DBG_LEAVE( DbgInfo );
438 /* If frequency specified, look up channel */
440 int f = freq->m / 100000;
441 channel = wl_get_chan_from_freq( f );
445 /* Channel specified */
451 /* If the channel is an 802.11a channel, set Bit 8 */
453 channel = channel | 0x100;
457 wl_lock( lp, &flags );
459 wl_act_int_off( lp );
461 lp->Channel = channel;
464 /* Commit the adapter parameters */
467 /* Send an event that channel/freq has been set */
468 wl_wext_event_freq( lp->dev );
472 wl_unlock(lp, &flags);
475 DBG_LEAVE( DbgInfo );
477 } // wireless_set_frequency
478 /*============================================================================*/
483 /*******************************************************************************
484 * wireless_get_frequency()
485 *******************************************************************************
489 * Gets the frequency (channel) on which the card is Tx/Rx.
493 * wrq - the wireless request buffer
494 * lp - the device's private adapter structure
500 ******************************************************************************/
501 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
504 struct wl_private *lp = wl_priv(dev);
507 /*------------------------------------------------------------------------*/
510 DBG_FUNC( "wireless_get_frequency" );
511 DBG_ENTER( DbgInfo );
513 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
518 wl_lock( lp, &flags );
520 wl_act_int_off( lp );
522 lp->ltvRecord.len = 2;
523 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
525 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
526 if( ret == HCF_SUCCESS ) {
527 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
529 freq->m = wl_get_freq_from_chan( channel ) * 100000;
535 wl_unlock(lp, &flags);
537 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
540 DBG_LEAVE( DbgInfo );
542 } // wireless_get_frequency
543 /*============================================================================*/
548 /*******************************************************************************
549 * wireless_get_range()
550 *******************************************************************************
554 * This function is used to provide misc info and statistics about the
559 * wrq - the wireless request buffer
560 * lp - the device's private adapter structure
565 * errno value otherwise
567 ******************************************************************************/
568 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
570 struct wl_private *lp = wl_priv(dev);
572 struct iw_range *range = (struct iw_range *) extra;
578 /*------------------------------------------------------------------------*/
581 DBG_FUNC( "wireless_get_range" );
582 DBG_ENTER( DbgInfo );
584 /* Set range information */
585 data->length = sizeof(struct iw_range);
586 memset(range, 0, sizeof(struct iw_range));
588 wl_lock( lp, &flags );
590 wl_act_int_off( lp );
592 /* Set range information */
593 memset( range, 0, sizeof( struct iw_range ));
596 /* Get the current transmit rate from the adapter */
597 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
598 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
600 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
601 if( status != HCF_SUCCESS ) {
602 /* Recovery action: reset and retry up to 10 times */
603 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
608 /* Holding the lock too long, make a gap to allow other processes */
609 wl_unlock(lp, &flags);
610 wl_lock( lp, &flags );
612 status = wl_reset( dev );
613 if ( status != HCF_SUCCESS ) {
614 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
620 /* Holding the lock too long, make a gap to allow other processes */
621 wl_unlock(lp, &flags);
622 wl_lock( lp, &flags );
627 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
633 /* Holding the lock too long, make a gap to allow other processes */
634 wl_unlock(lp, &flags);
635 wl_lock( lp, &flags );
637 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
639 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
642 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
645 // NWID - NOT SUPPORTED
648 /* Channel/Frequency Info */
649 range->num_channels = RADIO_CHANNELS;
652 /* Signal Level Thresholds */
653 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
657 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
659 /* If the value returned in /proc/net/wireless is greater than the maximum range,
660 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
661 it requires a bit of contorsion... */
663 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
664 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
667 /* Set available rates */
668 range->num_bitrates = 0;
670 lp->ltvRecord.len = 6;
671 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
673 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
674 if( status == HCF_SUCCESS ) {
675 for( count = 0; count < MAX_RATES; count++ )
676 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
677 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
678 range->num_bitrates++;
681 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
686 /* RTS Threshold info */
687 range->min_rts = MIN_RTS_BYTES;
688 range->max_rts = MAX_RTS_BYTES;
690 // Frag Threshold info - NOT SUPPORTED
692 // Power Management info - NOT SUPPORTED
696 /* Holding the lock too long, make a gap to allow other processes */
697 wl_unlock(lp, &flags);
698 wl_lock( lp, &flags );
700 /* Is WEP supported? */
702 if( wl_has_wep( &( lp->hcfCtx ))) {
703 /* WEP: RC4 40 bits */
704 range->encoding_size[0] = MIN_KEY_SIZE;
707 range->encoding_size[1] = MAX_KEY_SIZE;
708 range->num_encoding_sizes = 2;
709 range->max_encoding_tokens = MAX_KEYS;
713 range->txpower_capa = IW_TXPOW_MWATT;
714 range->num_txpower = 1;
715 range->txpower[0] = RADIO_TX_POWER_MWATT;
717 /* Wireless Extension Info */
718 range->we_version_compiled = WIRELESS_EXT;
719 range->we_version_source = WIRELESS_SUPPORT;
721 // Retry Limits and Lifetime - NOT SUPPORTED
723 /* Holding the lock too long, make a gap to allow other processes */
724 wl_unlock(lp, &flags);
725 wl_lock( lp, &flags );
727 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
728 wl_wireless_stats( lp->dev );
729 range->avg_qual = lp->wstats.qual;
730 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
732 /* Event capability (kernel + driver) */
733 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
734 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
735 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
736 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
737 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
738 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
739 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
740 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
742 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
743 range->scan_capa = IW_SCAN_CAPA_NONE;
748 wl_unlock(lp, &flags);
752 } // wireless_get_range
753 /*============================================================================*/
756 /*******************************************************************************
757 * wireless_get_bssid()
758 *******************************************************************************
762 * Gets the BSSID the wireless device is currently associated with.
766 * wrq - the wireless request buffer
767 * lp - the device's private adapter structure
772 * errno value otherwise
774 ******************************************************************************/
775 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
777 struct wl_private *lp = wl_priv(dev);
780 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
782 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
783 /*------------------------------------------------------------------------*/
786 DBG_FUNC( "wireless_get_bssid" );
787 DBG_ENTER( DbgInfo );
789 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
794 wl_lock( lp, &flags );
796 wl_act_int_off( lp );
798 memset( &ap_addr->sa_data, 0, ETH_ALEN );
800 ap_addr->sa_family = ARPHRD_ETHER;
802 /* Assume AP mode here, which means the BSSID is our own MAC address. In
803 STA mode, this address will be overwritten with the actual BSSID using
805 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
808 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
809 //;?should we return an error status in AP mode
811 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
812 /* Get Current BSSID */
813 lp->ltvRecord.typ = CFG_CUR_BSSID;
814 lp->ltvRecord.len = 4;
815 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
817 if( status == HCF_SUCCESS ) {
818 /* Copy info into sockaddr struct */
819 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
825 #endif // (HCF_TYPE) & HCF_TYPE_STA
829 wl_unlock(lp, &flags);
834 } // wireless_get_bssid
835 /*============================================================================*/
840 /*******************************************************************************
841 * wireless_get_ap_list()
842 *******************************************************************************
846 * Gets the results of a network scan.
850 * wrq - the wireless request buffer
851 * lp - the device's private adapter structure
856 * errno value otherwise
858 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
859 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
860 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
862 ******************************************************************************/
863 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
865 struct wl_private *lp = wl_priv(dev);
871 struct sockaddr *hwa = NULL;
872 struct iw_quality *qual = NULL;
874 ScanResult *p = &lp->scan_results;
876 ProbeResult *p = &lp->probe_results;
878 /*------------------------------------------------------------------------*/
880 DBG_FUNC( "wireless_get_ap_list" );
881 DBG_ENTER( DbgInfo );
883 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
888 wl_lock( lp, &flags );
890 wl_act_int_off( lp );
892 /* Set the completion state to FALSE */
893 lp->scan_results.scan_complete = FALSE;
894 lp->probe_results.scan_complete = FALSE;
895 /* Channels to scan */
896 lp->ltvRecord.len = 2;
897 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
898 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
899 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
900 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
902 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
903 disassociate from the network we are currently on */
904 lp->ltvRecord.len = 2;
905 lp->ltvRecord.typ = CFG_SCAN_SSID;
906 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
907 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
908 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
910 /* Initiate the scan */
912 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
914 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
919 //;? unlock? what about the access to lp below? is it broken?
920 wl_unlock(lp, &flags);
922 if( ret == HCF_SUCCESS ) {
923 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
924 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
925 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
926 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
927 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
930 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
931 other things in the meantime, This prevents system lockups by
932 giving some time back to the kernel */
933 for( count = 0; count < 100; count ++ ) {
942 if ( ret != HCF_SUCCESS ) {
943 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
945 num_aps = (*p)/*lp->probe_results*/.num_aps;
946 if (num_aps > IW_MAX_AP) {
949 data->length = num_aps;
950 hwa = (struct sockaddr *)extra;
951 qual = (struct iw_quality *) extra +
952 ( sizeof( struct sockaddr ) * num_aps );
954 /* This flag is used to tell the user if we provide quality
955 information. Since we provide signal/noise levels but no
956 quality info on a scan, this is set to 0. Setting to 1 and
957 providing a quality of 0 produces weird results. If we ever
958 provide quality (or can calculate it), this can be changed */
961 for( count = 0; count < num_aps; count++ ) {
963 memcpy( hwa[count].sa_data,
964 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
965 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
966 DBG_PRINT("BSSID: %pM\n",
967 (*p).ProbeTable[count].BSSID);
968 memcpy( hwa[count].sa_data,
969 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
972 /* Once the data is copied to the wireless struct, invalidate the
973 scan result to initiate a rescan on the next request */
974 (*p)/*lp->probe_results*/.scan_complete = FALSE;
975 /* Send the wireless event that the scan has completed, just in case
977 wl_wext_event_scan_complete( lp->dev );
981 DBG_LEAVE( DbgInfo );
983 } // wireless_get_ap_list
984 /*============================================================================*/
989 /*******************************************************************************
990 * wireless_set_sensitivity()
991 *******************************************************************************
995 * Sets the sensitivity (distance between APs) of the wireless card.
999 * wrq - the wireless request buffer
1000 * lp - the device's private adapter structure
1005 * errno value otherwise
1007 ******************************************************************************/
1008 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1010 struct wl_private *lp = wl_priv(dev);
1011 unsigned long flags;
1013 int dens = sens->value;
1014 /*------------------------------------------------------------------------*/
1017 DBG_FUNC( "wireless_set_sensitivity" );
1018 DBG_ENTER( DbgInfo );
1020 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1025 if(( dens < 1 ) || ( dens > 3 )) {
1030 wl_lock( lp, &flags );
1032 wl_act_int_off( lp );
1034 lp->DistanceBetweenAPs = dens;
1037 wl_act_int_on( lp );
1039 wl_unlock(lp, &flags);
1042 DBG_LEAVE( DbgInfo );
1044 } // wireless_set_sensitivity
1045 /*============================================================================*/
1050 /*******************************************************************************
1051 * wireless_get_sensitivity()
1052 *******************************************************************************
1056 * Gets the sensitivity (distance between APs) of the wireless card.
1060 * wrq - the wireless request buffer
1061 * lp - the device's private adapter structure
1066 * errno value otherwise
1068 ******************************************************************************/
1069 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1071 struct wl_private *lp = wl_priv(dev);
1073 /*------------------------------------------------------------------------*/
1074 /*------------------------------------------------------------------------*/
1077 DBG_FUNC( "wireless_get_sensitivity" );
1078 DBG_ENTER( DbgInfo );
1080 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1085 /* not worth locking ... */
1086 sens->value = lp->DistanceBetweenAPs;
1087 sens->fixed = 0; /* auto */
1089 DBG_LEAVE( DbgInfo );
1091 } // wireless_get_sensitivity
1092 /*============================================================================*/
1097 /*******************************************************************************
1098 * wireless_set_essid()
1099 *******************************************************************************
1103 * Sets the ESSID (network name) that the wireless device should associate
1108 * wrq - the wireless request buffer
1109 * lp - the device's private adapter structure
1114 * errno value otherwise
1116 ******************************************************************************/
1117 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
1119 struct wl_private *lp = wl_priv(dev);
1120 unsigned long flags;
1123 DBG_FUNC( "wireless_set_essid" );
1124 DBG_ENTER( DbgInfo );
1126 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1131 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
1136 wl_lock( lp, &flags );
1138 wl_act_int_off( lp );
1140 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
1142 /* data->flags is zero to ask for "any" */
1143 if( data->flags == 0 ) {
1144 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
1145 * ;?but there ain't no STAP anymore*/
1146 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
1147 strcpy( lp->NetworkName, "ANY" );
1149 //strcpy( lp->NetworkName, "ANY" );
1150 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
1153 memcpy( lp->NetworkName, ssid, data->length );
1156 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1158 /* Commit the adapter parameters */
1161 /* Send an event that ESSID has been set */
1162 wl_wext_event_essid( lp->dev );
1164 wl_act_int_on( lp );
1166 wl_unlock(lp, &flags);
1169 DBG_LEAVE( DbgInfo );
1171 } // wireless_set_essid
1172 /*============================================================================*/
1177 /*******************************************************************************
1178 * wireless_get_essid()
1179 *******************************************************************************
1183 * Gets the ESSID (network name) that the wireless device is associated
1188 * wrq - the wireless request buffer
1189 * lp - the device's private adapter structure
1194 * errno value otherwise
1196 ******************************************************************************/
1197 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1200 struct wl_private *lp = wl_priv(dev);
1201 unsigned long flags;
1205 /*------------------------------------------------------------------------*/
1208 DBG_FUNC( "wireless_get_essid" );
1209 DBG_ENTER( DbgInfo );
1211 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1216 wl_lock( lp, &flags );
1218 wl_act_int_off( lp );
1220 /* Get the desired network name */
1221 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1224 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1225 //;?should we return an error status in AP mode
1227 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1232 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1233 //;?should we restore this to allow smaller memory footprint
1235 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1236 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1242 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1243 if( status == HCF_SUCCESS ) {
1244 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1246 /* Endian translate the string length */
1247 pName->length = CNV_LITTLE_TO_INT( pName->length );
1249 /* Copy the information into the user buffer */
1250 data->length = pName->length;
1252 if( pName->length < HCF_MAX_NAME_LEN ) {
1253 pName->name[pName->length] = '\0';
1259 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1260 //;?should we return an error status in AP mode
1262 /* if desired is null ("any"), return current or "any" */
1263 if( pName->name[0] == '\0' ) {
1264 /* Get the current network name */
1265 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1266 lp->ltvRecord.typ = CFG_CUR_SSID;
1268 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1270 if( status == HCF_SUCCESS ) {
1271 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1273 /* Endian translate the string length */
1274 pName->length = CNV_LITTLE_TO_INT( pName->length );
1276 /* Copy the information into the user buffer */
1277 data->length = pName->length;
1287 if (pName->length > IW_ESSID_MAX_SIZE) {
1292 memcpy(essid, pName->name, pName->length);
1299 wl_act_int_on( lp );
1301 wl_unlock(lp, &flags);
1304 DBG_LEAVE( DbgInfo );
1306 } // wireless_get_essid
1307 /*============================================================================*/
1312 /*******************************************************************************
1313 * wireless_set_encode()
1314 *******************************************************************************
1318 * Sets the encryption keys and status (enable or disable).
1322 * wrq - the wireless request buffer
1323 * lp - the device's private adapter structure
1328 * errno value otherwise
1330 ******************************************************************************/
1331 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1333 struct wl_private *lp = wl_priv(dev);
1334 unsigned long flags;
1335 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1341 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
1346 if (erq->flags & IW_ENCODE_DISABLED)
1349 wl_lock(lp, &flags);
1353 ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1356 /* Send an event that Encryption has been set */
1358 wl_wext_event_encode(dev);
1362 wl_unlock(lp, &flags);
1369 /*******************************************************************************
1370 * wireless_get_encode()
1371 *******************************************************************************
1375 * Gets the encryption keys and status.
1379 * wrq - the wireless request buffer
1380 * lp - the device's private adapter structure
1385 * errno value otherwise
1387 ******************************************************************************/
1388 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1391 struct wl_private *lp = wl_priv(dev);
1392 unsigned long flags;
1395 /*------------------------------------------------------------------------*/
1398 DBG_FUNC( "wireless_get_encode" );
1399 DBG_ENTER( DbgInfo );
1400 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1402 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1407 /* Only super-user can see WEP key */
1408 if( !capable( CAP_NET_ADMIN )) {
1410 DBG_LEAVE( DbgInfo );
1414 wl_lock( lp, &flags );
1416 wl_act_int_off( lp );
1418 /* Is it supported? */
1419 if( !wl_has_wep( &( lp->hcfCtx ))) {
1424 /* Basic checking */
1425 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1431 if( lp->EnableEncryption == 0 ) {
1432 erq->flags |= IW_ENCODE_DISABLED;
1435 /* Which key do we want */
1436 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1437 index = lp->TransmitKeyID - 1;
1440 erq->flags |= index + 1;
1442 /* Copy the key to the user buffer */
1443 erq->length = lp->DefaultKeys.key[index].len;
1445 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1449 wl_act_int_on( lp );
1451 wl_unlock(lp, &flags);
1454 DBG_LEAVE( DbgInfo );
1456 } // wireless_get_encode
1457 /*============================================================================*/
1462 /*******************************************************************************
1463 * wireless_set_nickname()
1464 *******************************************************************************
1468 * Sets the nickname, or station name, of the wireless device.
1472 * wrq - the wireless request buffer
1473 * lp - the device's private adapter structure
1478 * errno value otherwise
1480 ******************************************************************************/
1481 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1483 struct wl_private *lp = wl_priv(dev);
1484 unsigned long flags;
1486 /*------------------------------------------------------------------------*/
1489 DBG_FUNC( "wireless_set_nickname" );
1490 DBG_ENTER( DbgInfo );
1492 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1497 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1498 if( !capable(CAP_NET_ADMIN )) {
1500 DBG_LEAVE( DbgInfo );
1505 /* Validate the new value */
1506 if(data->length > HCF_MAX_NAME_LEN) {
1511 wl_lock( lp, &flags );
1513 wl_act_int_off( lp );
1515 memset( lp->StationName, 0, sizeof( lp->StationName ));
1517 memcpy( lp->StationName, nickname, data->length );
1519 /* Commit the adapter parameters */
1522 wl_act_int_on( lp );
1524 wl_unlock(lp, &flags);
1527 DBG_LEAVE( DbgInfo );
1529 } // wireless_set_nickname
1530 /*============================================================================*/
1535 /*******************************************************************************
1536 * wireless_get_nickname()
1537 *******************************************************************************
1541 * Gets the nickname, or station name, of the wireless device.
1545 * wrq - the wireless request buffer
1546 * lp - the device's private adapter structure
1551 * errno value otherwise
1553 ******************************************************************************/
1554 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1556 struct wl_private *lp = wl_priv(dev);
1557 unsigned long flags;
1561 /*------------------------------------------------------------------------*/
1564 DBG_FUNC( "wireless_get_nickname" );
1565 DBG_ENTER( DbgInfo );
1567 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1572 wl_lock( lp, &flags );
1574 wl_act_int_off( lp );
1576 /* Get the current station name */
1577 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1578 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1580 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1582 if( status == HCF_SUCCESS ) {
1583 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1585 /* Endian translate the length */
1586 pName->length = CNV_LITTLE_TO_INT( pName->length );
1588 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1591 /* Copy the information into the user buffer */
1592 data->length = pName->length;
1593 memcpy(nickname, pName->name, pName->length);
1599 wl_act_int_on( lp );
1601 wl_unlock(lp, &flags);
1606 } // wireless_get_nickname
1607 /*============================================================================*/
1612 /*******************************************************************************
1613 * wireless_set_porttype()
1614 *******************************************************************************
1618 * Sets the port type of the wireless device.
1622 * wrq - the wireless request buffer
1623 * lp - the device's private adapter structure
1628 * errno value otherwise
1630 ******************************************************************************/
1631 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1633 struct wl_private *lp = wl_priv(dev);
1634 unsigned long flags;
1638 /*------------------------------------------------------------------------*/
1640 DBG_FUNC( "wireless_set_porttype" );
1641 DBG_ENTER( DbgInfo );
1643 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1648 wl_lock( lp, &flags );
1650 wl_act_int_off( lp );
1652 /* Validate the new value */
1656 /* When user requests ad-hoc, set IBSS mode! */
1660 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1668 /* Both automatic and infrastructure set port to BSS/STA mode */
1672 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1677 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1679 case IW_MODE_MASTER:
1681 /* Set BSS/AP mode */
1685 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1689 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1699 if( portType != 0 ) {
1700 /* Only do something if there is a mode change */
1701 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1702 lp->PortType = portType;
1703 lp->CreateIBSS = createIBSS;
1705 /* Commit the adapter parameters */
1708 /* Send an event that mode has been set */
1709 wl_wext_event_mode( lp->dev );
1713 wl_act_int_on( lp );
1715 wl_unlock(lp, &flags);
1718 DBG_LEAVE( DbgInfo );
1720 } // wireless_set_porttype
1721 /*============================================================================*/
1726 /*******************************************************************************
1727 * wireless_get_porttype()
1728 *******************************************************************************
1732 * Gets the port type of the wireless device.
1736 * wrq - the wireless request buffer
1737 * lp - the device's private adapter structure
1742 * errno value otherwise
1744 ******************************************************************************/
1745 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1748 struct wl_private *lp = wl_priv(dev);
1749 unsigned long flags;
1753 /*------------------------------------------------------------------------*/
1756 DBG_FUNC( "wireless_get_porttype" );
1757 DBG_ENTER( DbgInfo );
1759 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1764 wl_lock( lp, &flags );
1766 wl_act_int_off( lp );
1768 /* Get the current port type */
1769 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1770 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1772 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1774 if( status == HCF_SUCCESS ) {
1775 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1777 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1779 switch( *pPortType ) {
1783 #if (HCF_TYPE) & HCF_TYPE_AP
1785 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1786 *mode = IW_MODE_MASTER;
1788 *mode = IW_MODE_INFRA;
1793 *mode = IW_MODE_INFRA;
1795 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1798 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1799 *mode = IW_MODE_MASTER;
1801 if( lp->CreateIBSS ) {
1802 *mode = IW_MODE_ADHOC;
1804 *mode = IW_MODE_INFRA;
1812 *mode = IW_MODE_ADHOC;
1823 wl_act_int_on( lp );
1825 wl_unlock(lp, &flags);
1828 DBG_LEAVE( DbgInfo );
1830 } // wireless_get_porttype
1831 /*============================================================================*/
1836 /*******************************************************************************
1837 * wireless_set_power()
1838 *******************************************************************************
1842 * Sets the power management settings of the wireless device.
1846 * wrq - the wireless request buffer
1847 * lp - the device's private adapter structure
1852 * errno value otherwise
1854 ******************************************************************************/
1855 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1857 struct wl_private *lp = wl_priv(dev);
1858 unsigned long flags;
1860 /*------------------------------------------------------------------------*/
1863 DBG_FUNC( "wireless_set_power" );
1864 DBG_ENTER( DbgInfo );
1866 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1871 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1873 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1874 if( !capable( CAP_NET_ADMIN )) {
1877 DBG_LEAVE( DbgInfo );
1882 wl_lock( lp, &flags );
1884 wl_act_int_off( lp );
1886 /* Set the power management state based on the 'disabled' value */
1887 if( wrq->disabled ) {
1893 /* Commit the adapter parameters */
1896 wl_act_int_on( lp );
1898 wl_unlock(lp, &flags);
1901 DBG_LEAVE( DbgInfo );
1903 } // wireless_set_power
1904 /*============================================================================*/
1909 /*******************************************************************************
1910 * wireless_get_power()
1911 *******************************************************************************
1915 * Gets the power management settings of the wireless device.
1919 * wrq - the wireless request buffer
1920 * lp - the device's private adapter structure
1925 * errno value otherwise
1927 ******************************************************************************/
1928 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1931 struct wl_private *lp = wl_priv(dev);
1932 unsigned long flags;
1934 /*------------------------------------------------------------------------*/
1935 DBG_FUNC( "wireless_get_power" );
1936 DBG_ENTER( DbgInfo );
1938 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1943 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1945 wl_lock( lp, &flags );
1947 wl_act_int_off( lp );
1952 if( lp->PMEnabled ) {
1958 wl_act_int_on( lp );
1960 wl_unlock(lp, &flags);
1963 DBG_LEAVE( DbgInfo );
1965 } // wireless_get_power
1966 /*============================================================================*/
1971 /*******************************************************************************
1972 * wireless_get_tx_power()
1973 *******************************************************************************
1977 * Gets the transmit power of the wireless device's radio.
1981 * wrq - the wireless request buffer
1982 * lp - the device's private adapter structure
1987 * errno value otherwise
1989 ******************************************************************************/
1990 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1992 struct wl_private *lp = wl_priv(dev);
1993 unsigned long flags;
1995 /*------------------------------------------------------------------------*/
1996 DBG_FUNC( "wireless_get_tx_power" );
1997 DBG_ENTER( DbgInfo );
1999 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2004 wl_lock( lp, &flags );
2006 wl_act_int_off( lp );
2008 #ifdef USE_POWER_DBM
2009 rrq->value = RADIO_TX_POWER_DBM;
2010 rrq->flags = IW_TXPOW_DBM;
2012 rrq->value = RADIO_TX_POWER_MWATT;
2013 rrq->flags = IW_TXPOW_MWATT;
2018 wl_act_int_on( lp );
2020 wl_unlock(lp, &flags);
2023 DBG_LEAVE( DbgInfo );
2025 } // wireless_get_tx_power
2026 /*============================================================================*/
2031 /*******************************************************************************
2032 * wireless_set_rts_threshold()
2033 *******************************************************************************
2037 * Sets the RTS threshold for the wireless card.
2041 * wrq - the wireless request buffer
2042 * lp - the device's private adapter structure
2047 * errno value otherwise
2049 ******************************************************************************/
2050 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2053 struct wl_private *lp = wl_priv(dev);
2054 unsigned long flags;
2055 int rthr = rts->value;
2056 /*------------------------------------------------------------------------*/
2059 DBG_FUNC( "wireless_set_rts_threshold" );
2060 DBG_ENTER( DbgInfo );
2062 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2067 if(rts->fixed == 0) {
2072 if( rts->disabled ) {
2076 if(( rthr < 256 ) || ( rthr > 2347 )) {
2081 wl_lock( lp, &flags );
2083 wl_act_int_off( lp );
2085 lp->RTSThreshold = rthr;
2089 wl_act_int_on( lp );
2091 wl_unlock(lp, &flags);
2094 DBG_LEAVE( DbgInfo );
2096 } // wireless_set_rts_threshold
2097 /*============================================================================*/
2102 /*******************************************************************************
2103 * wireless_get_rts_threshold()
2104 *******************************************************************************
2108 * Gets the RTS threshold for the wireless card.
2112 * wrq - the wireless request buffer
2113 * lp - the device's private adapter structure
2118 * errno value otherwise
2120 ******************************************************************************/
2121 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2124 struct wl_private *lp = wl_priv(dev);
2125 unsigned long flags;
2126 /*------------------------------------------------------------------------*/
2128 DBG_FUNC( "wireless_get_rts_threshold" );
2129 DBG_ENTER( DbgInfo );
2131 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2136 wl_lock( lp, &flags );
2138 wl_act_int_off( lp );
2140 rts->value = lp->RTSThreshold;
2142 rts->disabled = ( rts->value == 2347 );
2146 wl_act_int_on( lp );
2148 wl_unlock(lp, &flags);
2151 DBG_LEAVE( DbgInfo );
2153 } // wireless_get_rts_threshold
2154 /*============================================================================*/
2160 /*******************************************************************************
2161 * wireless_set_rate()
2162 *******************************************************************************
2166 * Set the default data rate setting used by the wireless device.
2170 * wrq - the wireless request buffer
2171 * lp - the device's private adapter structure
2176 * errno value otherwise
2178 ******************************************************************************/
2179 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2181 struct wl_private *lp = wl_priv(dev);
2182 unsigned long flags;
2188 /*------------------------------------------------------------------------*/
2191 DBG_FUNC( "wireless_set_rate" );
2192 DBG_ENTER( DbgInfo );
2194 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2199 wl_lock( lp, &flags );
2201 wl_act_int_off( lp );
2205 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2206 if Bit 9 is set in the current channel RID */
2207 lp->ltvRecord.len = 2;
2208 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2210 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2212 if( status == HCF_SUCCESS ) {
2213 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2215 DBG_PRINT( "Index: %d\n", index );
2217 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2218 DBG_LEAVE( DbgInfo );
2223 if( rrq->value > 0 &&
2224 rrq->value <= 1 * MEGABIT ) {
2225 lp->TxRateControl[index] = 0x0001;
2227 else if( rrq->value > 1 * MEGABIT &&
2228 rrq->value <= 2 * MEGABIT ) {
2229 if( rrq->fixed == 1 ) {
2230 lp->TxRateControl[index] = 0x0002;
2232 lp->TxRateControl[index] = 0x0003;
2235 else if( rrq->value > 2 * MEGABIT &&
2236 rrq->value <= 5 * MEGABIT ) {
2237 if( rrq->fixed == 1 ) {
2238 lp->TxRateControl[index] = 0x0004;
2240 lp->TxRateControl[index] = 0x0007;
2243 else if( rrq->value > 5 * MEGABIT &&
2244 rrq->value <= 6 * MEGABIT ) {
2245 if( rrq->fixed == 1 ) {
2246 lp->TxRateControl[index] = 0x0010;
2248 lp->TxRateControl[index] = 0x0017;
2251 else if( rrq->value > 6 * MEGABIT &&
2252 rrq->value <= 9 * MEGABIT ) {
2253 if( rrq->fixed == 1 ) {
2254 lp->TxRateControl[index] = 0x0020;
2256 lp->TxRateControl[index] = 0x0037;
2259 else if( rrq->value > 9 * MEGABIT &&
2260 rrq->value <= 11 * MEGABIT ) {
2261 if( rrq->fixed == 1 ) {
2262 lp->TxRateControl[index] = 0x0008;
2264 lp->TxRateControl[index] = 0x003F;
2267 else if( rrq->value > 11 * MEGABIT &&
2268 rrq->value <= 12 * MEGABIT ) {
2269 if( rrq->fixed == 1 ) {
2270 lp->TxRateControl[index] = 0x0040;
2272 lp->TxRateControl[index] = 0x007F;
2275 else if( rrq->value > 12 * MEGABIT &&
2276 rrq->value <= 18 * MEGABIT ) {
2277 if( rrq->fixed == 1 ) {
2278 lp->TxRateControl[index] = 0x0080;
2280 lp->TxRateControl[index] = 0x00FF;
2283 else if( rrq->value > 18 * MEGABIT &&
2284 rrq->value <= 24 * MEGABIT ) {
2285 if( rrq->fixed == 1 ) {
2286 lp->TxRateControl[index] = 0x0100;
2288 lp->TxRateControl[index] = 0x01FF;
2291 else if( rrq->value > 24 * MEGABIT &&
2292 rrq->value <= 36 * MEGABIT ) {
2293 if( rrq->fixed == 1 ) {
2294 lp->TxRateControl[index] = 0x0200;
2296 lp->TxRateControl[index] = 0x03FF;
2299 else if( rrq->value > 36 * MEGABIT &&
2300 rrq->value <= 48 * MEGABIT ) {
2301 if( rrq->fixed == 1 ) {
2302 lp->TxRateControl[index] = 0x0400;
2304 lp->TxRateControl[index] = 0x07FF;
2307 else if( rrq->value > 48 * MEGABIT &&
2308 rrq->value <= 54 * MEGABIT ) {
2309 if( rrq->fixed == 1 ) {
2310 lp->TxRateControl[index] = 0x0800;
2312 lp->TxRateControl[index] = 0x0FFF;
2315 else if( rrq->fixed == 0 ) {
2316 /* In this case, the user has not specified a bitrate, only the "auto"
2317 moniker. So, set to all supported rates */
2318 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2328 if( rrq->value > 0 &&
2329 rrq->value <= 1 * MEGABIT ) {
2330 lp->TxRateControl[0] = 1;
2332 else if( rrq->value > 1 * MEGABIT &&
2333 rrq->value <= 2 * MEGABIT ) {
2335 lp->TxRateControl[0] = 2;
2337 lp->TxRateControl[0] = 6;
2340 else if( rrq->value > 2 * MEGABIT &&
2341 rrq->value <= 5 * MEGABIT ) {
2343 lp->TxRateControl[0] = 4;
2345 lp->TxRateControl[0] = 7;
2348 else if( rrq->value > 5 * MEGABIT &&
2349 rrq->value <= 11 * MEGABIT ) {
2351 lp->TxRateControl[0] = 5;
2353 lp->TxRateControl[0] = 3;
2356 else if( rrq->fixed == 0 ) {
2357 /* In this case, the user has not specified a bitrate, only the "auto"
2358 moniker. So, set the rate to 11Mb auto */
2359 lp->TxRateControl[0] = 3;
2369 /* Commit the adapter parameters */
2374 wl_act_int_on( lp );
2376 wl_unlock(lp, &flags);
2379 DBG_LEAVE( DbgInfo );
2381 } // wireless_set_rate
2382 /*============================================================================*/
2387 /*******************************************************************************
2388 * wireless_get_rate()
2389 *******************************************************************************
2393 * Get the default data rate setting used by the wireless device.
2397 * wrq - the wireless request buffer
2398 * lp - the device's private adapter structure
2403 * errno value otherwise
2405 ******************************************************************************/
2406 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2409 struct wl_private *lp = wl_priv(dev);
2410 unsigned long flags;
2414 /*------------------------------------------------------------------------*/
2417 DBG_FUNC( "wireless_get_rate" );
2418 DBG_ENTER( DbgInfo );
2420 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2425 wl_lock( lp, &flags );
2427 wl_act_int_off( lp );
2429 /* Get the current transmit rate from the adapter */
2430 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2431 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2433 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2435 if( status == HCF_SUCCESS ) {
2438 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2440 if( txRate & 0x0001 ) {
2443 else if( txRate & 0x0002 ) {
2446 else if( txRate & 0x0004 ) {
2449 else if( txRate & 0x0008 ) {
2452 else if( txRate & 0x00010 ) {
2455 else if( txRate & 0x00020 ) {
2458 else if( txRate & 0x00040 ) {
2461 else if( txRate & 0x00080 ) {
2464 else if( txRate & 0x00100 ) {
2467 else if( txRate & 0x00200 ) {
2470 else if( txRate & 0x00400 ) {
2473 else if( txRate & 0x00800 ) {
2479 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2483 rrq->value = txRate * MEGABIT;
2489 wl_act_int_on( lp );
2491 wl_unlock(lp, &flags);
2494 DBG_LEAVE( DbgInfo );
2496 } // wireless_get_rate
2497 /*============================================================================*/
2502 #if 0 //;? Not used anymore
2503 /*******************************************************************************
2504 * wireless_get_private_interface()
2505 *******************************************************************************
2509 * Returns the Linux Wireless Extensions' compatible private interface of
2514 * wrq - the wireless request buffer
2515 * lp - the device's private adapter structure
2520 * errno value otherwise
2522 ******************************************************************************/
2523 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2526 /*------------------------------------------------------------------------*/
2529 DBG_FUNC( "wireless_get_private_interface" );
2530 DBG_ENTER( DbgInfo );
2532 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2537 if( wrq->u.data.pointer != NULL ) {
2538 struct iw_priv_args priv[] =
2540 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2541 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2542 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2543 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2544 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2545 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2548 /* Verify the user buffer */
2549 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2552 DBG_LEAVE( DbgInfo );
2556 /* Copy the data into the user's buffer */
2557 wrq->u.data.length = NELEM( priv );
2558 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2562 DBG_LEAVE( DbgInfo );
2564 } // wireless_get_private_interface
2565 /*============================================================================*/
2570 /*******************************************************************************
2571 * wireless_set_scan()
2572 *******************************************************************************
2576 * Instructs the driver to initiate a network scan.
2580 * wrq - the wireless request buffer
2581 * lp - the device's private adapter structure
2586 * errno value otherwise
2588 ******************************************************************************/
2589 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2591 struct wl_private *lp = wl_priv(dev);
2592 unsigned long flags;
2596 /*------------------------------------------------------------------------*/
2598 //;? Note: shows results as trace, retruns always 0 unless BUSY
2600 DBG_FUNC( "wireless_set_scan" );
2601 DBG_ENTER( DbgInfo );
2603 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2608 wl_lock( lp, &flags );
2610 wl_act_int_off( lp );
2613 * This looks like a nice place to test if the HCF is still
2614 * communicating with the card. It seems that sometimes BAP_1
2615 * gets corrupted. By looking at the comments in HCF the
2616 * cause is still a mystery. Okay, the communication to the
2617 * card is dead, reset the card to revive.
2619 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2621 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2626 /* Set the completion state to FALSE */
2627 lp->probe_results.scan_complete = FALSE;
2630 /* Channels to scan */
2632 lp->ltvRecord.len = 5;
2633 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2634 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2635 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2636 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2637 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2639 lp->ltvRecord.len = 2;
2640 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2641 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2644 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2646 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2648 // Holding the lock too long, make a gap to allow other processes
2649 wl_unlock(lp, &flags);
2650 wl_lock( lp, &flags );
2652 if( status != HCF_SUCCESS ) {
2656 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2659 // Holding the lock too long, make a gap to allow other processes
2660 wl_unlock(lp, &flags);
2661 wl_lock( lp, &flags );
2667 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2668 disassociate from the network we are currently on */
2669 lp->ltvRecord.len = 18;
2670 lp->ltvRecord.typ = CFG_SCAN_SSID;
2671 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2672 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2674 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2676 // Holding the lock too long, make a gap to allow other processes
2677 wl_unlock(lp, &flags);
2678 wl_lock( lp, &flags );
2680 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2682 /* Initiate the scan */
2683 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2684 retrieve probe responses must always be used to support WPA */
2685 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2687 if( status == HCF_SUCCESS ) {
2688 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2690 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2693 wl_act_int_on( lp );
2695 wl_unlock(lp, &flags);
2700 } // wireless_set_scan
2701 /*============================================================================*/
2706 /*******************************************************************************
2707 * wireless_get_scan()
2708 *******************************************************************************
2712 * Instructs the driver to gather and return the results of a network scan.
2716 * wrq - the wireless request buffer
2717 * lp - the device's private adapter structure
2722 * errno value otherwise
2724 ******************************************************************************/
2725 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2727 struct wl_private *lp = wl_priv(dev);
2728 unsigned long flags;
2733 struct iw_event iwe;
2734 PROBE_RESP *probe_resp;
2738 /*------------------------------------------------------------------------*/
2741 DBG_FUNC( "wireless_get_scan" );
2742 DBG_ENTER( DbgInfo );
2744 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2749 wl_lock( lp, &flags );
2751 wl_act_int_off( lp );
2753 /* If the scan is not done, tell the calling process to try again later */
2754 if( !lp->probe_results.scan_complete ) {
2759 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2760 lp->probe_results.num_aps );
2763 buf_end = extra + IW_SCAN_MAX_DATA;
2765 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2766 /* Reference the probe response from the table */
2767 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2770 /* First entry MUST be the MAC address */
2771 memset( &iwe, 0, sizeof( iwe ));
2773 iwe.cmd = SIOCGIWAP;
2774 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2775 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2776 iwe.len = IW_EV_ADDR_LEN;
2778 buf = iwe_stream_add_event(info, buf, buf_end,
2779 &iwe, IW_EV_ADDR_LEN);
2781 /* Use the mode to indicate if it's a station or AP */
2782 /* Won't always be an AP if in IBSS mode */
2783 memset( &iwe, 0, sizeof( iwe ));
2785 iwe.cmd = SIOCGIWMODE;
2787 if( probe_resp->capability & CAPABILITY_IBSS ) {
2788 iwe.u.mode = IW_MODE_INFRA;
2790 iwe.u.mode = IW_MODE_MASTER;
2793 iwe.len = IW_EV_UINT_LEN;
2795 buf = iwe_stream_add_event(info, buf, buf_end,
2796 &iwe, IW_EV_UINT_LEN);
2798 /* Any quality information */
2799 memset(&iwe, 0, sizeof(iwe));
2802 iwe.u.qual.level = dbm(probe_resp->signal);
2803 iwe.u.qual.noise = dbm(probe_resp->silence);
2804 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2805 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2806 iwe.len = IW_EV_QUAL_LEN;
2808 buf = iwe_stream_add_event(info, buf, buf_end,
2809 &iwe, IW_EV_QUAL_LEN);
2812 /* ESSID information */
2813 if( probe_resp->rawData[1] > 0 ) {
2814 memset( &iwe, 0, sizeof( iwe ));
2816 iwe.cmd = SIOCGIWESSID;
2817 iwe.u.data.length = probe_resp->rawData[1];
2818 iwe.u.data.flags = 1;
2820 buf = iwe_stream_add_point(info, buf, buf_end,
2821 &iwe, &probe_resp->rawData[2]);
2825 /* Encryption Information */
2826 memset( &iwe, 0, sizeof( iwe ));
2828 iwe.cmd = SIOCGIWENCODE;
2829 iwe.u.data.length = 0;
2831 /* Check the capabilities field of the Probe Response to see if
2832 'privacy' is supported on the AP in question */
2833 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2834 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2836 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2839 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
2842 /* Frequency Info */
2843 memset( &iwe, 0, sizeof( iwe ));
2845 iwe.cmd = SIOCGIWFREQ;
2846 iwe.len = IW_EV_FREQ_LEN;
2847 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2850 buf = iwe_stream_add_event(info, buf, buf_end,
2851 &iwe, IW_EV_FREQ_LEN);
2854 /* Custom info (Beacon Interval) */
2855 memset( &iwe, 0, sizeof( iwe ));
2856 memset( msg, 0, sizeof( msg ));
2858 iwe.cmd = IWEVCUSTOM;
2859 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2860 iwe.u.data.length = strlen( msg );
2862 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
2869 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2870 if( wpa_ie != NULL ) {
2871 memset(&iwe, 0, sizeof(iwe));
2873 iwe.cmd = IWEVGENIE;
2874 iwe.u.data.length = wpa_ie_len;
2876 buf = iwe_stream_add_point(info, buf, buf_end,
2880 /* Add other custom info in formatted string format as needed... */
2883 data->length = buf - extra;
2887 wl_act_int_on( lp );
2889 wl_unlock(lp, &flags);
2892 DBG_LEAVE( DbgInfo );
2894 } // wireless_get_scan
2895 /*============================================================================*/
2898 static const char * const auth_names[] = {
2899 "IW_AUTH_WPA_VERSION",
2900 "IW_AUTH_CIPHER_PAIRWISE",
2901 "IW_AUTH_CIPHER_GROUP",
2903 "IW_AUTH_TKIP_COUNTERMEASURES",
2904 "IW_AUTH_DROP_UNENCRYPTED",
2905 "IW_AUTH_80211_AUTH_ALG",
2906 "IW_AUTH_WPA_ENABLED",
2907 "IW_AUTH_RX_UNENCRYPTED_EAPOL",
2908 "IW_AUTH_ROAMING_CONTROL",
2909 "IW_AUTH_PRIVACY_INVOKED",
2910 "IW_AUTH_CIPHER_GROUP_MGMT",
2916 static int wireless_set_auth(struct net_device *dev,
2917 struct iw_request_info *info,
2918 struct iw_param *data, char *extra)
2920 struct wl_private *lp = wl_priv(dev);
2921 unsigned long flags;
2924 int iwa_idx = data->flags & IW_AUTH_INDEX;
2925 int iwa_val = data->value;
2927 DBG_FUNC( "wireless_set_auth" );
2928 DBG_ENTER( DbgInfo );
2930 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2935 wl_lock( lp, &flags );
2937 wl_act_int_off( lp );
2939 if (iwa_idx > IW_AUTH_MFP)
2940 iwa_idx = IW_AUTH_MFP + 1;
2941 DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
2943 case IW_AUTH_WPA_VERSION:
2944 /* We do support WPA */
2945 if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
2946 (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
2952 case IW_AUTH_WPA_ENABLED:
2953 DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
2955 lp->EnableEncryption = 2;
2957 lp->EnableEncryption = 0;
2959 /* Write straight to the card */
2961 ltv.typ = CFG_CNF_ENCRYPTION;
2962 ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
2963 ret = hcf_put_info(&lp->hcfCtx, (LTVP)<v);
2967 case IW_AUTH_TKIP_COUNTERMEASURES:
2969 /* Immediately disable card */
2970 lp->driverEnable = !iwa_val;
2971 if (lp->driverEnable)
2972 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2974 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2979 /* Management Frame Protection not supported.
2980 * Only fail if set to required.
2982 if (iwa_val == IW_AUTH_MFP_REQUIRED)
2988 case IW_AUTH_KEY_MGMT:
2990 /* Record required management suite.
2991 * Will take effect on next commit */
2993 lp->AuthKeyMgmtSuite = 4;
2995 lp->AuthKeyMgmtSuite = 0;
3000 case IW_AUTH_80211_AUTH_ALG:
3002 /* Just record whether open or shared is required.
3003 * Will take effect on next commit */
3006 if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
3007 lp->authentication = 1;
3008 else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
3009 lp->authentication = 0;
3014 case IW_AUTH_DROP_UNENCRYPTED:
3015 /* Only needed for AP */
3016 lp->ExcludeUnencrypted = iwa_val;
3020 case IW_AUTH_CIPHER_PAIRWISE:
3021 case IW_AUTH_CIPHER_GROUP:
3022 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3023 case IW_AUTH_ROAMING_CONTROL:
3024 case IW_AUTH_PRIVACY_INVOKED:
3025 /* Not used. May need to do something with
3026 * CIPHER_PAIRWISE and CIPHER_GROUP*/
3031 DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
3032 /* return an error */
3037 wl_act_int_on( lp );
3039 wl_unlock(lp, &flags);
3042 DBG_LEAVE( DbgInfo );
3044 } // wireless_set_auth
3045 /*============================================================================*/
3048 static void flush_tx(struct wl_private *lp)
3054 * Make sure that there is no data queued up in the firmware
3055 * before setting the TKIP keys. If this check is not
3056 * performed, some data may be sent out with incorrect MIC
3057 * and cause synchronizarion errors with the AP
3059 /* Check every 1ms for 100ms */
3060 for (count = 0; count < 100; count++) {
3064 ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
3067 hcf_get_info(&(lp->hcfCtx), (LTVP)<v);
3069 if (ltv.u.u16[0] == 0)
3074 DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
3078 static int wireless_set_encodeext(struct net_device *dev,
3079 struct iw_request_info *info,
3080 struct iw_point *erq, char *keybuf)
3082 struct wl_private *lp = wl_priv(dev);
3083 unsigned long flags;
3085 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
3087 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3089 bool set_tx = false;
3093 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
3098 if (erq->flags & IW_ENCODE_DISABLED) {
3099 ext->alg = IW_ENCODE_ALG_NONE;
3103 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
3106 wl_lock(lp, &flags);
3110 memset(<v, 0, sizeof(ltv));
3113 case IW_ENCODE_ALG_TKIP:
3114 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3116 if (sizeof(ext->rx_seq) != 8) {
3117 DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
3123 ret = hermes_set_tkip_keys(<v, key_idx, ext->addr.sa_data,
3125 ext->rx_seq, ext->key, ext->key_len);
3128 DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
3134 lp->wext_enc = IW_ENCODE_ALG_TKIP;
3137 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3140 case IW_ENCODE_ALG_WEP:
3141 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3143 if (erq->flags & IW_ENCODE_RESTRICTED) {
3144 DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
3149 ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
3154 case IW_ENCODE_ALG_CCMP:
3155 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3159 case IW_ENCODE_ALG_NONE:
3160 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3162 if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
3163 ret = hermes_clear_tkip_keys(<v, key_idx,
3166 lp->wext_enc = IW_ENCODE_ALG_NONE;
3167 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3169 } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
3170 ret = hermes_set_wep_keys(lp, key_idx,
3171 ext->key, ext->key_len,
3180 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3189 wl_unlock(lp, &flags);
3195 /*============================================================================*/
3199 static int wireless_set_genie(struct net_device *dev,
3200 struct iw_request_info *info,
3201 struct iw_point *data, char *extra)
3208 /* We can't write this to the card, but apparently this
3209 * operation needs to succeed */
3215 /*============================================================================*/
3218 /*******************************************************************************
3219 * wl_wireless_stats()
3220 *******************************************************************************
3224 * Return the current device wireless statistics.
3228 * wrq - the wireless request buffer
3229 * lp - the device's private adapter structure
3234 * errno value otherwise
3236 ******************************************************************************/
3237 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3239 struct iw_statistics *pStats;
3240 struct wl_private *lp = wl_priv(dev);
3241 /*------------------------------------------------------------------------*/
3244 DBG_FUNC( "wl_wireless_stats" );
3246 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3250 /* Initialize the statistics */
3251 pStats = &( lp->wstats );
3252 pStats->qual.updated = 0x00;
3254 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3256 CFG_COMMS_QUALITY_STRCT *pQual;
3257 CFG_HERMES_TALLIES_STRCT tallies;
3260 /* Update driver status */
3263 /* Get the current link quality information */
3264 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3265 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3266 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3268 if( status == HCF_SUCCESS ) {
3269 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3271 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3272 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3273 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3275 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3276 IW_QUAL_LEVEL_UPDATED |
3277 IW_QUAL_NOISE_UPDATED |
3280 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3283 /* Get the current tallies from the adapter */
3284 /* Only possible when the device is open */
3285 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3286 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3287 /* No endian translation is needed here, as CFG_TALLIES is an
3288 MSF RID; all processing is done on the host, not the card! */
3289 pStats->discard.nwid = 0L;
3290 pStats->discard.code = tallies.RxWEPUndecryptable;
3291 pStats->discard.misc = tallies.TxDiscards +
3292 tallies.RxFCSErrors +
3293 //tallies.RxDiscardsNoBuffer +
3294 tallies.TxDiscardsWrongSA;
3295 //;? Extra taken over from Linux driver based on 7.18 version
3296 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3297 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3299 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3302 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3306 DBG_LEAVE( DbgInfo );
3308 } // wl_wireless_stats
3309 /*============================================================================*/
3314 /*******************************************************************************
3315 * wl_get_wireless_stats()
3316 *******************************************************************************
3320 * Return the current device wireless statistics. This function calls
3321 * wl_wireless_stats, but acquires spinlocks first as it can be called
3322 * directly by the network layer.
3326 * wrq - the wireless request buffer
3327 * lp - the device's private adapter structure
3332 * errno value otherwise
3334 ******************************************************************************/
3335 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3337 unsigned long flags;
3338 struct wl_private *lp = wl_priv(dev);
3339 struct iw_statistics *pStats = NULL;
3340 /*------------------------------------------------------------------------*/
3342 DBG_FUNC( "wl_get_wireless_stats" );
3345 wl_lock( lp, &flags );
3347 wl_act_int_off( lp );
3350 if( lp->useRTS == 1 ) {
3351 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3355 pStats = wl_wireless_stats( dev );
3357 wl_act_int_on( lp );
3359 wl_unlock(lp, &flags);
3361 DBG_LEAVE( DbgInfo );
3363 } // wl_get_wireless_stats
3366 /*******************************************************************************
3368 *******************************************************************************
3372 * Gather wireless spy statistics.
3376 * wrq - the wireless request buffer
3377 * lp - the device's private adapter structure
3382 * errno value otherwise
3384 ******************************************************************************/
3385 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3387 struct iw_quality wstats;
3391 struct wl_private *lp = wl_priv(dev);
3392 /*------------------------------------------------------------------------*/
3395 if (!lp->spy_data.spy_number) {
3399 /* Gather wireless spy statistics: for each packet, compare the source
3400 address with out list, and if match, get the stats. */
3401 memset( stats, 0, sizeof(stats));
3402 memset( desc, 0, sizeof(DESC_STRCT));
3404 desc[0].buf_addr = stats;
3405 desc[0].BUF_SIZE = sizeof(stats);
3406 desc[0].next_desc_addr = 0; // terminate list
3408 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3410 if( status == HCF_SUCCESS ) {
3411 wstats.level = (u_char) dbm(stats[1]);
3412 wstats.noise = (u_char) dbm(stats[0]);
3413 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3415 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3416 IW_QUAL_LEVEL_UPDATED |
3417 IW_QUAL_NOISE_UPDATED |
3420 wireless_spy_update( dev, mac, &wstats );
3423 /*============================================================================*/
3428 /*******************************************************************************
3429 * wl_wext_event_freq()
3430 *******************************************************************************
3434 * This function is used to send an event that the channel/freq
3435 * configuration for a specific device has changed.
3440 * dev - the network device for which this event is to be issued
3446 ******************************************************************************/
3447 void wl_wext_event_freq( struct net_device *dev )
3449 union iwreq_data wrqu;
3450 struct wl_private *lp = wl_priv(dev);
3451 /*------------------------------------------------------------------------*/
3454 memset( &wrqu, 0, sizeof( wrqu ));
3456 wrqu.freq.m = lp->Channel;
3459 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3462 } // wl_wext_event_freq
3463 /*============================================================================*/
3468 /*******************************************************************************
3469 * wl_wext_event_mode()
3470 *******************************************************************************
3474 * This function is used to send an event that the mode of operation
3475 * for a specific device has changed.
3480 * dev - the network device for which this event is to be issued
3486 ******************************************************************************/
3487 void wl_wext_event_mode( struct net_device *dev )
3489 union iwreq_data wrqu;
3490 struct wl_private *lp = wl_priv(dev);
3491 /*------------------------------------------------------------------------*/
3494 memset( &wrqu, 0, sizeof( wrqu ));
3496 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3497 wrqu.mode = IW_MODE_INFRA;
3499 wrqu.mode = IW_MODE_MASTER;
3502 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3505 } // wl_wext_event_mode
3506 /*============================================================================*/
3511 /*******************************************************************************
3512 * wl_wext_event_essid()
3513 *******************************************************************************
3517 * This function is used to send an event that the ESSID configuration for
3518 * a specific device has changed.
3523 * dev - the network device for which this event is to be issued
3529 ******************************************************************************/
3530 void wl_wext_event_essid( struct net_device *dev )
3532 union iwreq_data wrqu;
3533 struct wl_private *lp = wl_priv(dev);
3534 /*------------------------------------------------------------------------*/
3537 memset( &wrqu, 0, sizeof( wrqu ));
3539 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3540 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3541 the call to wireless_send_event() must also point to where the ESSID
3543 wrqu.essid.length = strlen( lp->NetworkName );
3544 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3545 wrqu.essid.flags = 1;
3547 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3550 } // wl_wext_event_essid
3551 /*============================================================================*/
3556 /*******************************************************************************
3557 * wl_wext_event_encode()
3558 *******************************************************************************
3562 * This function is used to send an event that the encryption configuration
3563 * for a specific device has changed.
3568 * dev - the network device for which this event is to be issued
3574 ******************************************************************************/
3575 void wl_wext_event_encode( struct net_device *dev )
3577 union iwreq_data wrqu;
3578 struct wl_private *lp = wl_priv(dev);
3580 /*------------------------------------------------------------------------*/
3583 memset( &wrqu, 0, sizeof( wrqu ));
3585 if( lp->EnableEncryption == 0 ) {
3586 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3588 wrqu.encoding.flags |= lp->TransmitKeyID;
3590 index = lp->TransmitKeyID - 1;
3592 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3593 if we're in AP mode */
3594 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3595 //;?should we restore this to allow smaller memory footprint
3597 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3598 if( lp->ExcludeUnencrypted ) {
3599 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3601 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3605 #endif // HCF_TYPE_AP
3607 /* Only provide the key if permissions allow */
3608 if( capable( CAP_NET_ADMIN )) {
3609 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3610 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3612 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3616 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3617 lp->DefaultKeys.key[index].key );
3620 } // wl_wext_event_encode
3621 /*============================================================================*/
3626 /*******************************************************************************
3627 * wl_wext_event_ap()
3628 *******************************************************************************
3632 * This function is used to send an event that the device has been
3633 * associated to a new AP.
3638 * dev - the network device for which this event is to be issued
3644 ******************************************************************************/
3645 void wl_wext_event_ap( struct net_device *dev )
3647 union iwreq_data wrqu;
3648 struct wl_private *lp = wl_priv(dev);
3650 /*------------------------------------------------------------------------*/
3653 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3654 this event BEFORE sending the association event, as there are timing
3655 issues with the hostap supplicant. The supplicant will attempt to process
3656 an EAPOL-Key frame from an AP before receiving this information, which
3657 is required properly process the said frame. */
3658 wl_wext_event_assoc_ie( dev );
3661 lp->ltvRecord.typ = CFG_CUR_BSSID;
3662 lp->ltvRecord.len = 4;
3664 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3665 if( status == HCF_SUCCESS ) {
3666 memset( &wrqu, 0, sizeof( wrqu ));
3668 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3670 wrqu.addr.sa_family = ARPHRD_ETHER;
3672 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3676 } // wl_wext_event_ap
3677 /*============================================================================*/
3681 /*******************************************************************************
3682 * wl_wext_event_scan_complete()
3683 *******************************************************************************
3687 * This function is used to send an event that a request for a network scan
3693 * dev - the network device for which this event is to be issued
3699 ******************************************************************************/
3700 void wl_wext_event_scan_complete( struct net_device *dev )
3702 union iwreq_data wrqu;
3703 /*------------------------------------------------------------------------*/
3706 memset( &wrqu, 0, sizeof( wrqu ));
3708 wrqu.addr.sa_family = ARPHRD_ETHER;
3709 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3712 } // wl_wext_event_scan_complete
3713 /*============================================================================*/
3718 /*******************************************************************************
3719 * wl_wext_event_new_sta()
3720 *******************************************************************************
3724 * This function is used to send an event that an AP has registered a new
3730 * dev - the network device for which this event is to be issued
3736 ******************************************************************************/
3737 void wl_wext_event_new_sta( struct net_device *dev )
3739 union iwreq_data wrqu;
3740 /*------------------------------------------------------------------------*/
3743 memset( &wrqu, 0, sizeof( wrqu ));
3745 /* Send the station's mac address here */
3746 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3747 wrqu.addr.sa_family = ARPHRD_ETHER;
3748 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3751 } // wl_wext_event_new_sta
3752 /*============================================================================*/
3757 /*******************************************************************************
3758 * wl_wext_event_expired_sta()
3759 *******************************************************************************
3763 * This function is used to send an event that an AP has deregistered a
3769 * dev - the network device for which this event is to be issued
3775 ******************************************************************************/
3776 void wl_wext_event_expired_sta( struct net_device *dev )
3778 union iwreq_data wrqu;
3779 /*------------------------------------------------------------------------*/
3782 memset( &wrqu, 0, sizeof( wrqu ));
3784 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3785 wrqu.addr.sa_family = ARPHRD_ETHER;
3786 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3789 } // wl_wext_event_expired_sta
3790 /*============================================================================*/
3795 /*******************************************************************************
3796 * wl_wext_event_mic_failed()
3797 *******************************************************************************
3801 * This function is used to send an event that MIC calculations failed.
3806 * dev - the network device for which this event is to be issued
3812 ******************************************************************************/
3813 void wl_wext_event_mic_failed( struct net_device *dev )
3815 union iwreq_data wrqu;
3816 struct wl_private *lp = wl_priv(dev);
3817 struct iw_michaelmicfailure wxmic;
3821 WVLAN_RX_WMP_HDR *hdr;
3822 /*------------------------------------------------------------------------*/
3825 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3828 /* Cast the lookahead buffer into a RFS format */
3829 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3831 /* Cast the addresses to byte buffers, as in the above RFS they are word
3833 addr1 = (char *)hdr->address1;
3834 addr2 = (char *)hdr->address2;
3836 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3839 memset(&wrqu, 0, sizeof(wrqu));
3840 memset(&wxmic, 0, sizeof(wxmic));
3842 wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3843 wxmic.flags |= (addr1[0] & 1) ?
3844 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
3845 wxmic.src_addr.sa_family = ARPHRD_ETHER;
3846 memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3848 wrqu.data.length = sizeof(wxmic);
3849 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3852 } // wl_wext_event_mic_failed
3853 /*============================================================================*/
3858 /*******************************************************************************
3859 * wl_wext_event_assoc_ie()
3860 *******************************************************************************
3864 * This function is used to send an event containing the WPA-IE generated
3865 * by the firmware in an association request.
3870 * dev - the network device for which this event is to be issued
3876 ******************************************************************************/
3877 void wl_wext_event_assoc_ie( struct net_device *dev )
3879 union iwreq_data wrqu;
3880 struct wl_private *lp = wl_priv(dev);
3885 /*------------------------------------------------------------------------*/
3888 memset( &wrqu, 0, sizeof( wrqu ));
3890 /* Retrieve the Association Request IE */
3891 lp->ltvRecord.len = 45;
3892 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3894 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3895 if( status == HCF_SUCCESS )
3898 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3899 wpa_ie = wl_parse_wpa_ie( &data, &length );
3903 wrqu.data.length = wpa_ie[1] + 2;
3904 wireless_send_event(dev, IWEVASSOCREQIE,
3907 /* This bit is a hack. We send the respie
3908 * event at the same time */
3909 wireless_send_event(dev, IWEVASSOCRESPIE,
3915 } // wl_wext_event_assoc_ie
3916 /*============================================================================*/
3917 /* Structures to export the Wireless Handlers */
3919 static const iw_handler wl_handler[] =
3921 IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
3922 IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
3923 IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
3924 IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
3925 IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
3926 IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
3927 IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
3928 IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
3929 IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
3930 IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
3931 IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
3932 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3933 IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
3935 IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
3936 IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
3937 IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
3938 IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
3939 IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
3940 IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
3941 IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
3942 IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
3943 IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
3944 IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
3945 IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
3946 IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
3947 IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
3948 IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
3949 IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
3950 IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
3951 IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
3952 IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3953 IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
3956 static const iw_handler wl_private_handler[] =
3957 { /* SIOCIWFIRSTPRIV + */
3958 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3959 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3960 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3961 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3962 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3963 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3964 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3968 struct iw_priv_args wl_priv_args[] = {
3969 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3970 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3971 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3972 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3973 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3974 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3975 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3979 const struct iw_handler_def wl_iw_handler_def =
3981 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3982 .private = (iw_handler *) wl_private_handler,
3983 .private_args = (struct iw_priv_args *) wl_priv_args,
3984 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3985 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3986 .standard = (iw_handler *) wl_handler,
3987 .get_wireless_stats = wl_get_wireless_stats,