1 /*******************************************************************************
2  * Agere Systems Inc.
3  * Wireless device driver for Linux (wlags49).
4  *
5  * Copyright (c) 1998-2003 Agere Systems Inc.
6  * All rights reserved.
7  *   http://www.agere.com
8  *
9  * Initially developed by TriplePoint, Inc.
10  *   http://www.triplepoint.com
11  *
12  *------------------------------------------------------------------------------
13  *
14  * SOFTWARE LICENSE
15  *
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.
20  *
21  * Copyright � 2003 Agere Systems Inc.
22  * All rights reserved.
23  *
24  * Redistribution and use in source or binary forms, with or without
25  * modifications, are permitted provided that the following conditions are met:
26  *
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
30  *    distribution.
31  *
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.
35  *
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.
39  *
40  * Disclaimer
41  *
42  * THIS SOFTWARE IS PROVIDED �AS IS� 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
53  * DAMAGE.
54  *
55  ******************************************************************************/
56 
57 /*******************************************************************************
58  *  include files
59  ******************************************************************************/
60 #include <wl_version.h>
61 
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <asm/uaccess.h>
66 
67 #include <debug.h>
68 #include <hcf.h>
69 #include <hcfdef.h>
70 
71 #include <wl_if.h>
72 #include <wl_internal.h>
73 #include <wl_util.h>
74 #include <wl_main.h>
75 #include <wl_wext.h>
76 #include <wl_priv.h>
77 
78 
79 
80 /* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS
81    #including linux/wireless.h), then these functions do not need to be included
82    in the build. */
83 #ifdef WIRELESS_EXT
84 
85 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
86     iwe_stream_add_event(info, buf, end, iwe, len)
87 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
88     iwe_stream_add_point(info, buf, end, iwe, msg)
89 
90 
91 
92 /*******************************************************************************
93  * global definitions
94  ******************************************************************************/
95 #if DBG
96 extern dbg_info_t *DbgInfo;
97 #endif  // DBG
98 
99 
100 
101 
102 /*******************************************************************************
103  *	wireless_commit()
104  *******************************************************************************
105  *
106  *  DESCRIPTION:
107  *
108  *      Commit
109  *  protocol used.
110  *
111  *  PARAMETERS:
112  *
113  *      wrq - the wireless request buffer
114  *
115  *  RETURNS:
116  *
117  *      N/A
118  *
119  ******************************************************************************/
wireless_commit(struct net_device * dev,struct iw_request_info * info,union iwreq_data * rqu,char * extra)120 static int wireless_commit(struct net_device *dev,
121 			   struct iw_request_info *info,
122 			   union iwreq_data *rqu, char *extra)
123 {
124 	struct wl_private *lp = wl_priv(dev);
125 	unsigned long flags;
126 	int ret = 0;
127 	/*------------------------------------------------------------------------*/
128 
129 	DBG_FUNC( "wireless_commit" );
130 	DBG_ENTER(DbgInfo);
131 
132 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
133 		ret = -EBUSY;
134 		goto out;
135 	}
136 
137 	wl_lock( lp, &flags );
138 
139     	wl_act_int_off( lp );
140 
141 	wl_apply(lp);
142 
143     	wl_act_int_on( lp );
144 
145 	wl_unlock(lp, &flags);
146 
147 out:
148 	DBG_LEAVE( DbgInfo );
149 	return ret;
150 } // wireless_commit
151 /*============================================================================*/
152 
153 
154 
155 
156 /*******************************************************************************
157  *	wireless_get_protocol()
158  *******************************************************************************
159  *
160  *  DESCRIPTION:
161  *
162  *      Returns a vendor-defined string that should identify the wireless
163  *  protocol used.
164  *
165  *  PARAMETERS:
166  *
167  *      wrq - the wireless request buffer
168  *
169  *  RETURNS:
170  *
171  *      N/A
172  *
173  ******************************************************************************/
wireless_get_protocol(struct net_device * dev,struct iw_request_info * info,char * name,char * extra)174 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
175 {
176 	DBG_FUNC( "wireless_get_protocol" );
177 	DBG_ENTER( DbgInfo );
178 
179 	/* Originally, the driver was placing the string "Wireless" here. However,
180 	   the wireless extensions (/linux/wireless.h) indicate this string should
181 	   describe the wireless protocol. */
182 
183 	strcpy(name, "IEEE 802.11b");
184 
185 	DBG_LEAVE(DbgInfo);
186 	return 0;
187 } // wireless_get_protocol
188 /*============================================================================*/
189 
190 
191 
192 
193 /*******************************************************************************
194  *	wireless_set_frequency()
195  *******************************************************************************
196  *
197  *  DESCRIPTION:
198  *
199  *      Sets the frequency (channel) on which the card should Tx/Rx.
200  *
201  *  PARAMETERS:
202  *
203  *      wrq - the wireless request buffer
204  *      lp  - the device's private adapter structure
205  *
206  *  RETURNS:
207  *
208  *      0 on success
209  *      errno value otherwise
210  *
211  ******************************************************************************/
wireless_set_frequency(struct net_device * dev,struct iw_request_info * info,struct iw_freq * freq,char * extra)212 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
213 {
214 	struct wl_private *lp = wl_priv(dev);
215 	unsigned long flags;
216 	int channel = 0;
217 	int ret     = 0;
218 	/*------------------------------------------------------------------------*/
219 
220 
221 	DBG_FUNC( "wireless_set_frequency" );
222 	DBG_ENTER( DbgInfo );
223 
224 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
225 		ret = -EBUSY;
226 		goto out;
227 	}
228 
229 	if( !capable( CAP_NET_ADMIN )) {
230 		ret = -EPERM;
231 		DBG_LEAVE( DbgInfo );
232 		return ret;
233 	}
234 
235 
236 	/* If frequency specified, look up channel */
237 	if( freq->e == 1 ) {
238 		int f = freq->m / 100000;
239 		channel = wl_get_chan_from_freq( f );
240 	}
241 
242 
243 	/* Channel specified */
244 	if( freq->e == 0 ) {
245 		channel = freq->m;
246 	}
247 
248 
249 	/* If the channel is an 802.11a channel, set Bit 8 */
250 	if( channel > 14 ) {
251 		channel = channel | 0x100;
252 	}
253 
254 
255 	wl_lock( lp, &flags );
256 
257     	wl_act_int_off( lp );
258 
259 	lp->Channel = channel;
260 
261 
262 	/* Commit the adapter parameters */
263 	wl_apply( lp );
264 
265 	/* Send an event that channel/freq has been set */
266 	wl_wext_event_freq( lp->dev );
267 
268     	wl_act_int_on( lp );
269 
270 	wl_unlock(lp, &flags);
271 
272 out:
273 	DBG_LEAVE( DbgInfo );
274 	return ret;
275 } // wireless_set_frequency
276 /*============================================================================*/
277 
278 
279 
280 
281 /*******************************************************************************
282  *	wireless_get_frequency()
283  *******************************************************************************
284  *
285  *  DESCRIPTION:
286  *
287  *      Gets the frequency (channel) on which the card is Tx/Rx.
288  *
289  *  PARAMETERS:
290  *
291  *      wrq - the wireless request buffer
292  *      lp  - the device's private adapter structure
293  *
294  *  RETURNS:
295  *
296  *      N/A
297  *
298  ******************************************************************************/
wireless_get_frequency(struct net_device * dev,struct iw_request_info * info,struct iw_freq * freq,char * extra)299 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
300 
301 {
302 	struct wl_private *lp = wl_priv(dev);
303 	unsigned long flags;
304 	int ret = -1;
305 	/*------------------------------------------------------------------------*/
306 
307 
308 	DBG_FUNC( "wireless_get_frequency" );
309 	DBG_ENTER( DbgInfo );
310 
311 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
312 		ret = -EBUSY;
313 		goto out;
314 	}
315 
316 	wl_lock( lp, &flags );
317 
318     	wl_act_int_off( lp );
319 
320 	lp->ltvRecord.len = 2;
321 	lp->ltvRecord.typ = CFG_CUR_CHANNEL;
322 
323 	ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
324 	if( ret == HCF_SUCCESS ) {
325 		hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
326 
327 #ifdef USE_FREQUENCY
328 
329 		freq->m = wl_get_freq_from_chan( channel ) * 100000;
330 		freq->e = 1;
331 #else
332 
333 		freq->m = channel;
334 		freq->e = 0;
335 
336 #endif /* USE_FREQUENCY */
337 	}
338 
339     	wl_act_int_on( lp );
340 
341 	wl_unlock(lp, &flags);
342 
343 	ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
344 
345 out:
346 	DBG_LEAVE( DbgInfo );
347 	return ret;
348 } // wireless_get_frequency
349 /*============================================================================*/
350 
351 
352 
353 
354 /*******************************************************************************
355  *	wireless_get_range()
356  *******************************************************************************
357  *
358  *  DESCRIPTION:
359  *
360  *      This function is used to provide misc info and statistics about the
361  *  wireless device.
362  *
363  *  PARAMETERS:
364  *
365  *      wrq - the wireless request buffer
366  *      lp  - the device's private adapter structure
367  *
368  *  RETURNS:
369  *
370  *      0 on success
371  *      errno value otherwise
372  *
373  ******************************************************************************/
wireless_get_range(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)374 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
375 {
376 	struct wl_private *lp = wl_priv(dev);
377 	unsigned long      flags;
378 	struct iw_range   *range = (struct iw_range *) extra;
379 	int                ret = 0;
380 	int                status = -1;
381 	int                count;
382 	__u16             *pTxRate;
383 	int                retries = 0;
384 	/*------------------------------------------------------------------------*/
385 
386 
387 	DBG_FUNC( "wireless_get_range" );
388 	DBG_ENTER( DbgInfo );
389 
390 	/* Set range information */
391 	data->length = sizeof(struct iw_range);
392 	memset(range, 0, sizeof(struct iw_range));
393 
394 	wl_lock( lp, &flags );
395 
396     	wl_act_int_off( lp );
397 
398 	/* Set range information */
399 	memset( range, 0, sizeof( struct iw_range ));
400 
401 retry:
402 	/* Get the current transmit rate from the adapter */
403 	lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
404 	lp->ltvRecord.typ = CFG_CUR_TX_RATE;
405 
406 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
407 	if( status != HCF_SUCCESS ) {
408 		/* Recovery action: reset and retry up to 10 times */
409 		DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
410 
411 		if (retries < 10) {
412 			retries++;
413 
414 			/* Holding the lock too long, make a gap to allow other processes */
415 			wl_unlock(lp, &flags);
416 			wl_lock( lp, &flags );
417 
418 			status = wl_reset( dev );
419 			if ( status != HCF_SUCCESS ) {
420 				DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
421 
422 				ret = -EFAULT;
423 				goto out_unlock;
424 			}
425 
426 			/* Holding the lock too long, make a gap to allow other processes */
427 			wl_unlock(lp, &flags);
428 			wl_lock( lp, &flags );
429 
430 			goto retry;
431 
432 		} else {
433 			DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
434 			ret = -EFAULT;
435 			goto out_unlock;
436 		}
437 	}
438 
439 	/* Holding the lock too long, make a gap to allow other processes */
440 	wl_unlock(lp, &flags);
441 	wl_lock( lp, &flags );
442 
443 	pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
444 
445 	range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
446 
447 	if (retries > 0) {
448 		DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
449 	}
450 
451 	// NWID - NOT SUPPORTED
452 
453 
454 	/* Channel/Frequency Info */
455 	range->num_channels = RADIO_CHANNELS;
456 
457 
458 	/* Signal Level Thresholds */
459 	range->sensitivity = RADIO_SENSITIVITY_LEVELS;
460 
461 
462 	/* Link quality */
463 #ifdef USE_DBM
464 
465 	range->max_qual.qual     = (u_char)HCF_MAX_COMM_QUALITY;
466 
467 	/* If the value returned in /proc/net/wireless is greater than the maximum range,
468 	   iwconfig assumes that the value is in dBm. Because an unsigned char is used,
469 	   it requires a bit of contorsion... */
470 
471 	range->max_qual.level   = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
472 	range->max_qual.noise   = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
473 #else
474 
475 	range->max_qual.qual    = 100;
476 	range->max_qual.level   = 100;
477 	range->max_qual.noise   = 100;
478 
479 #endif /* USE_DBM */
480 
481 
482 	/* Set available rates */
483 	range->num_bitrates = 0;
484 
485 	lp->ltvRecord.len = 6;
486 	lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
487 
488 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
489 	if( status == HCF_SUCCESS ) {
490 		for( count = 0; count < MAX_RATES; count++ )
491 			if( lp->ltvRecord.u.u8[count+2] != 0 ) {
492 				range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
493 				range->num_bitrates++;
494 			}
495 	} else {
496 		DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
497 		ret = -EFAULT;
498 		goto out_unlock;
499 	}
500 
501 	/* RTS Threshold info */
502 	range->min_rts   = MIN_RTS_BYTES;
503 	range->max_rts   = MAX_RTS_BYTES;
504 
505 	// Frag Threshold info - NOT SUPPORTED
506 
507 	// Power Management info - NOT SUPPORTED
508 
509 	/* Encryption */
510 
511 #if WIRELESS_EXT > 8
512 
513 	/* Holding the lock too long, make a gap to allow other processes */
514 	wl_unlock(lp, &flags);
515 	wl_lock( lp, &flags );
516 
517 	/* Is WEP supported? */
518 
519 	if( wl_has_wep( &( lp->hcfCtx ))) {
520 		/* WEP: RC4 40 bits */
521 		range->encoding_size[0]      = MIN_KEY_SIZE;
522 
523 		/* RC4 ~128 bits */
524 		range->encoding_size[1]      = MAX_KEY_SIZE;
525 		range->num_encoding_sizes    = 2;
526 		range->max_encoding_tokens   = MAX_KEYS;
527 	}
528 
529 #endif /* WIRELESS_EXT > 8 */
530 
531 	/* Tx Power Info */
532 	range->txpower_capa  = IW_TXPOW_MWATT;
533 	range->num_txpower   = 1;
534 	range->txpower[0]    = RADIO_TX_POWER_MWATT;
535 
536 #if WIRELESS_EXT > 10
537 
538 	/* Wireless Extension Info */
539 	range->we_version_compiled   = WIRELESS_EXT;
540 	range->we_version_source     = WIRELESS_SUPPORT;
541 
542 	// Retry Limits and Lifetime - NOT SUPPORTED
543 
544 #endif
545 
546 
547 #if WIRELESS_EXT > 11
548 
549 	/* Holding the lock too long, make a gap to allow other processes */
550 	wl_unlock(lp, &flags);
551 	wl_lock( lp, &flags );
552 
553 	DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
554 	wl_wireless_stats( lp->dev );
555 	range->avg_qual = lp->wstats.qual;
556 	DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
557 
558 #endif
559 
560 	/* Event capability (kernel + driver) */
561 	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
562 				IW_EVENT_CAPA_MASK(SIOCGIWAP) |
563 				IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
564 	range->event_capa[1] = IW_EVENT_CAPA_K_1;
565 	range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
566 				IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
567 				IW_EVENT_CAPA_MASK(IWEVEXPIRED));
568 
569 	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
570 
571 out_unlock:
572     	wl_act_int_on( lp );
573 
574 	wl_unlock(lp, &flags);
575 
576 	DBG_LEAVE(DbgInfo);
577 	return ret;
578 } // wireless_get_range
579 /*============================================================================*/
580 
581 
582 /*******************************************************************************
583  *	wireless_get_bssid()
584  *******************************************************************************
585  *
586  *  DESCRIPTION:
587  *
588  *      Gets the BSSID the wireless device is currently associated with.
589  *
590  *  PARAMETERS:
591  *
592  *      wrq - the wireless request buffer
593  *      lp  - the device's private adapter structure
594  *
595  *  RETURNS:
596  *
597  *      0 on success
598  *      errno value otherwise
599  *
600  ******************************************************************************/
wireless_get_bssid(struct net_device * dev,struct iw_request_info * info,struct sockaddr * ap_addr,char * extra)601 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
602 {
603 	struct wl_private *lp = wl_priv(dev);
604 	unsigned long flags;
605 	int ret = 0;
606 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
607 	int status = -1;
608 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
609 	/*------------------------------------------------------------------------*/
610 
611 
612 	DBG_FUNC( "wireless_get_bssid" );
613 	DBG_ENTER( DbgInfo );
614 
615 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
616 		ret = -EBUSY;
617 		goto out;
618 	}
619 
620 	wl_lock( lp, &flags );
621 
622     	wl_act_int_off( lp );
623 
624 	memset( &ap_addr->sa_data, 0, ETH_ALEN );
625 
626 	ap_addr->sa_family = ARPHRD_ETHER;
627 
628 	/* Assume AP mode here, which means the BSSID is our own MAC address. In
629 	   STA mode, this address will be overwritten with the actual BSSID using
630 	   the code below. */
631 	memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
632 
633 
634 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
635 					//;?should we return an error status in AP mode
636 
637 	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
638 		/* Get Current BSSID */
639 		lp->ltvRecord.typ = CFG_CUR_BSSID;
640 		lp->ltvRecord.len = 4;
641 		status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
642 
643 		if( status == HCF_SUCCESS ) {
644 			/* Copy info into sockaddr struct */
645 			memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
646 		} else {
647 			ret = -EFAULT;
648 		}
649 	}
650 
651 #endif // (HCF_TYPE) & HCF_TYPE_STA
652 
653     	wl_act_int_on( lp );
654 
655 	wl_unlock(lp, &flags);
656 
657 out:
658 	DBG_LEAVE(DbgInfo);
659 	return ret;
660 } // wireless_get_bssid
661 /*============================================================================*/
662 
663 
664 
665 
666 /*******************************************************************************
667  *	wireless_get_ap_list()
668  *******************************************************************************
669  *
670  *  DESCRIPTION:
671  *
672  *      Gets the results of a network scan.
673  *
674  *  PARAMETERS:
675  *
676  *      wrq - the wireless request buffer
677  *      lp  - the device's private adapter structure
678  *
679  *  RETURNS:
680  *
681  *      0 on success
682  *      errno value otherwise
683  *
684  *  NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
685  *       implements SIOCGIWAPLIST only to provide backwards compatibility. For
686  *       all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
687  *
688  ******************************************************************************/
wireless_get_ap_list(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)689 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
690 {
691 	struct wl_private *lp = wl_priv(dev);
692 	unsigned long	  flags;
693 	int                 ret;
694 	int                 num_aps = -1;
695 	int                 sec_count = 0;
696 	hcf_32              count;
697 	struct sockaddr     *hwa = NULL;
698 	struct iw_quality   *qual = NULL;
699 #ifdef WARP
700 	ScanResult			*p = &lp->scan_results;
701 #else
702 	ProbeResult         *p = &lp->probe_results;
703 #endif  // WARP
704 	/*------------------------------------------------------------------------*/
705 
706 	DBG_FUNC( "wireless_get_ap_list" );
707 	DBG_ENTER( DbgInfo );
708 
709 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
710 		ret = -EBUSY;
711 		goto out;
712 	}
713 
714 	wl_lock( lp, &flags );
715 
716     	wl_act_int_off( lp );
717 
718 	/* Set the completion state to FALSE */
719 	lp->scan_results.scan_complete = FALSE;
720 	lp->probe_results.scan_complete = FALSE;
721 	/* Channels to scan */
722 	lp->ltvRecord.len       = 2;
723 	lp->ltvRecord.typ       = CFG_SCAN_CHANNELS_2GHZ;
724 	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x7FFF );
725 	ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
726 	DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
727 
728 	/* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
729 	   disassociate from the network we are currently on */
730 	lp->ltvRecord.len       = 2;
731 	lp->ltvRecord.typ       = CFG_SCAN_SSID;
732 	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
733 	ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
734 	DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
735 
736 	/* Initiate the scan */
737 #ifdef WARP
738 	ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
739 #else
740 	ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
741 #endif  // WARP
742 
743     	wl_act_int_on( lp );
744 
745 	//;? unlock? what about the access to lp below? is it broken?
746 	wl_unlock(lp, &flags);
747 
748 	if( ret == HCF_SUCCESS ) {
749 		DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
750 		while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
751 			DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
752 			/* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
753 			if( sec_count++ > MAX_SCAN_TIME_SEC ) {
754 				ret = -EIO;
755 			} else {
756 				/* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
757 				   other things in the meantime, This prevents system lockups by
758 				   giving some time back to the kernel */
759 				for( count = 0; count < 100; count ++ ) {
760 					mdelay( 10 );
761 					schedule( );
762 				}
763 			}
764 		}
765 
766 		rmb();
767 
768 		if ( ret != HCF_SUCCESS ) {
769 			DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
770 		} else {
771 			num_aps             = (*p)/*lp->probe_results*/.num_aps;
772 			if (num_aps > IW_MAX_AP) {
773 				num_aps = IW_MAX_AP;
774 			}
775 			data->length = num_aps;
776 			hwa = (struct sockaddr *)extra;
777 			qual = (struct iw_quality *) extra +
778 					( sizeof( struct sockaddr ) * num_aps );
779 
780 			/* This flag is used to tell the user if we provide quality
781 			   information. Since we provide signal/noise levels but no
782 			   quality info on a scan, this is set to 0. Setting to 1 and
783 			   providing a quality of 0 produces weird results. If we ever
784 			   provide quality (or can calculate it), this can be changed */
785 			data->flags = 0;
786 
787 			for( count = 0; count < num_aps; count++ ) {
788 #ifdef WARP
789 				memcpy( hwa[count].sa_data,
790 						(*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
791 #else  //;?why use BSSID and bssid as names in seemingly very comparable situations
792 				DBG_PRINT("BSSID: %pM\n",
793 						(*p).ProbeTable[count].BSSID);
794 				memcpy( hwa[count].sa_data,
795 						(*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
796 #endif // WARP
797 			}
798 			/* Once the data is copied to the wireless struct, invalidate the
799 			   scan result to initiate a rescan on the next request */
800 			(*p)/*lp->probe_results*/.scan_complete = FALSE;
801 			/* Send the wireless event that the scan has completed, just in case
802 			   it's needed */
803 			wl_wext_event_scan_complete( lp->dev );
804 		}
805 	}
806 out:
807 	DBG_LEAVE( DbgInfo );
808 	return ret;
809 } // wireless_get_ap_list
810 /*============================================================================*/
811 
812 
813 
814 
815 /*******************************************************************************
816  *	wireless_set_sensitivity()
817  *******************************************************************************
818  *
819  *  DESCRIPTION:
820  *
821  *      Sets the sensitivity (distance between APs) of the wireless card.
822  *
823  *  PARAMETERS:
824  *
825  *      wrq - the wireless request buffer
826  *      lp  - the device's private adapter structure
827  *
828  *  RETURNS:
829  *
830  *      0 on success
831  *      errno value otherwise
832  *
833  ******************************************************************************/
wireless_set_sensitivity(struct net_device * dev,struct iw_request_info * info,struct iw_param * sens,char * extra)834 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
835 {
836 	struct wl_private *lp = wl_priv(dev);
837 	unsigned long flags;
838 	int ret = 0;
839 	int dens = sens->value;
840 	/*------------------------------------------------------------------------*/
841 
842 
843 	DBG_FUNC( "wireless_set_sensitivity" );
844 	DBG_ENTER( DbgInfo );
845 
846 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
847 		ret = -EBUSY;
848 		goto out;
849 	}
850 
851 	if(( dens < 1 ) || ( dens > 3 )) {
852 		ret = -EINVAL;
853 		goto out;
854 	}
855 
856 	wl_lock( lp, &flags );
857 
858     	wl_act_int_off( lp );
859 
860 	lp->DistanceBetweenAPs = dens;
861 	wl_apply( lp );
862 
863     	wl_act_int_on( lp );
864 
865 	wl_unlock(lp, &flags);
866 
867 out:
868 	DBG_LEAVE( DbgInfo );
869 	return ret;
870 } // wireless_set_sensitivity
871 /*============================================================================*/
872 
873 
874 
875 
876 /*******************************************************************************
877  *	wireless_get_sensitivity()
878  *******************************************************************************
879  *
880  *  DESCRIPTION:
881  *
882  *      Gets the sensitivity (distance between APs) of the wireless card.
883  *
884  *  PARAMETERS:
885  *
886  *      wrq - the wireless request buffer
887  *      lp  - the device's private adapter structure
888  *
889  *  RETURNS:
890  *
891  *      0 on success
892  *      errno value otherwise
893  *
894  ******************************************************************************/
wireless_get_sensitivity(struct net_device * dev,struct iw_request_info * info,struct iw_param * sens,char * extra)895 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
896 {
897 	struct wl_private *lp = wl_priv(dev);
898 	int ret = 0;
899 	/*------------------------------------------------------------------------*/
900 	/*------------------------------------------------------------------------*/
901 
902 
903 	DBG_FUNC( "wireless_get_sensitivity" );
904 	DBG_ENTER( DbgInfo );
905 
906 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
907 		ret = -EBUSY;
908 		goto out;
909 	}
910 
911 	/* not worth locking ... */
912 	sens->value = lp->DistanceBetweenAPs;
913 	sens->fixed = 0;	/* auto */
914 out:
915 	DBG_LEAVE( DbgInfo );
916 	return ret;
917 } // wireless_get_sensitivity
918 /*============================================================================*/
919 
920 
921 
922 
923 /*******************************************************************************
924  *	wireless_set_essid()
925  *******************************************************************************
926  *
927  *  DESCRIPTION:
928  *
929  *      Sets the ESSID (network name) that the wireless device should associate
930  *  with.
931  *
932  *  PARAMETERS:
933  *
934  *      wrq - the wireless request buffer
935  *      lp  - the device's private adapter structure
936  *
937  *  RETURNS:
938  *
939  *      0 on success
940  *      errno value otherwise
941  *
942  ******************************************************************************/
wireless_set_essid(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * ssid)943 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
944 {
945 	struct wl_private *lp = wl_priv(dev);
946 	unsigned long flags;
947 	int ret = 0;
948 
949 	DBG_FUNC( "wireless_set_essid" );
950 	DBG_ENTER( DbgInfo );
951 
952 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
953 		ret = -EBUSY;
954 		goto out;
955 	}
956 
957 	if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
958 		ret = -EINVAL;
959 		goto out;
960 	}
961 
962 	wl_lock( lp, &flags );
963 
964     	wl_act_int_off( lp );
965 
966 	memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
967 
968 	/* data->flags is zero to ask for "any" */
969 	if( data->flags == 0 ) {
970 		/* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
971 		 * ;?but there ain't no STAP anymore*/
972 		if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
973 			strcpy( lp->NetworkName, "ANY" );
974 		} else {
975 			//strcpy( lp->NetworkName, "ANY" );
976 			strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
977 		}
978 	} else {
979 		memcpy( lp->NetworkName, ssid, data->length );
980 	}
981 
982 	DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
983 
984 	/* Commit the adapter parameters */
985 	wl_apply( lp );
986 
987 	/* Send an event that ESSID has been set */
988 	wl_wext_event_essid( lp->dev );
989 
990     	wl_act_int_on( lp );
991 
992 	wl_unlock(lp, &flags);
993 
994 out:
995 	DBG_LEAVE( DbgInfo );
996 	return ret;
997 } // wireless_set_essid
998 /*============================================================================*/
999 
1000 
1001 
1002 
1003 /*******************************************************************************
1004  *	wireless_get_essid()
1005  *******************************************************************************
1006  *
1007  *  DESCRIPTION:
1008  *
1009  *      Gets the ESSID (network name) that the wireless device is associated
1010  *  with.
1011  *
1012  *  PARAMETERS:
1013  *
1014  *      wrq - the wireless request buffer
1015  *      lp  - the device's private adapter structure
1016  *
1017  *  RETURNS:
1018  *
1019  *      0 on success
1020  *      errno value otherwise
1021  *
1022  ******************************************************************************/
wireless_get_essid(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * essid)1023 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1024 
1025 {
1026 	struct wl_private *lp = wl_priv(dev);
1027 	unsigned long flags;
1028 	int         ret = 0;
1029 	int         status = -1;
1030 	wvName_t    *pName;
1031 	/*------------------------------------------------------------------------*/
1032 
1033 
1034 	DBG_FUNC( "wireless_get_essid" );
1035 	DBG_ENTER( DbgInfo );
1036 
1037 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1038 		ret = -EBUSY;
1039 		goto out;
1040 	}
1041 
1042 	wl_lock( lp, &flags );
1043 
1044     	wl_act_int_off( lp );
1045 
1046 	/* Get the desired network name */
1047 	lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1048 
1049 
1050 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1051 					//;?should we return an error status in AP mode
1052 
1053 	lp->ltvRecord.typ = CFG_DESIRED_SSID;
1054 
1055 #endif
1056 
1057 
1058 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1059 		//;?should we restore this to allow smaller memory footprint
1060 
1061 	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1062 		lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1063 	}
1064 
1065 #endif // HCF_AP
1066 
1067 
1068 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1069 	if( status == HCF_SUCCESS ) {
1070 		pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1071 
1072 		/* Endian translate the string length */
1073 		pName->length = CNV_LITTLE_TO_INT( pName->length );
1074 
1075 		/* Copy the information into the user buffer */
1076 		data->length = pName->length;
1077 
1078 		/* NOTE: Null terminating is necessary for proper display of the SSID in
1079 		   the wireless tools */
1080 		data->length = pName->length + 1;
1081 		if( pName->length < HCF_MAX_NAME_LEN ) {
1082 			pName->name[pName->length] = '\0';
1083 		}
1084 
1085 		data->flags = 1;
1086 
1087 
1088 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1089 					//;?should we return an error status in AP mode
1090 #ifdef RETURN_CURRENT_NETWORKNAME
1091 
1092 		/* if desired is null ("any"), return current or "any" */
1093 		if( pName->name[0] == '\0' ) {
1094 			/* Get the current network name */
1095 			lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1096 			lp->ltvRecord.typ = CFG_CUR_SSID;
1097 
1098 			status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1099 
1100 			if( status == HCF_SUCCESS ) {
1101 				pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1102 
1103 				/* Endian translate the string length */
1104 				pName->length = CNV_LITTLE_TO_INT( pName->length );
1105 
1106 				/* Copy the information into the user buffer */
1107 				data->length = pName->length + 1;
1108 				if( pName->length < HCF_MAX_NAME_LEN ) {
1109 					pName->name[pName->length] = '\0';
1110 				}
1111 
1112 				data->flags = 1;
1113 			} else {
1114 				ret = -EFAULT;
1115 				goto out_unlock;
1116 			}
1117 		}
1118 
1119 #endif // RETURN_CURRENT_NETWORKNAME
1120 #endif // HCF_STA
1121 
1122 		data->length--;
1123 
1124 		if (pName->length > IW_ESSID_MAX_SIZE) {
1125 			ret = -EFAULT;
1126 			goto out_unlock;
1127 		}
1128 
1129 		memcpy(essid, pName->name, pName->length);
1130 	} else {
1131 		ret = -EFAULT;
1132 		goto out_unlock;
1133 	}
1134 
1135 out_unlock:
1136     	wl_act_int_on( lp );
1137 
1138 	wl_unlock(lp, &flags);
1139 
1140 out:
1141 	DBG_LEAVE( DbgInfo );
1142 	return ret;
1143 } // wireless_get_essid
1144 /*============================================================================*/
1145 
1146 
1147 
1148 
1149 /*******************************************************************************
1150  *	wireless_set_encode()
1151  *******************************************************************************
1152  *
1153  *  DESCRIPTION:
1154  *
1155  *     Sets the encryption keys and status (enable or disable).
1156  *
1157  *  PARAMETERS:
1158  *
1159  *      wrq - the wireless request buffer
1160  *      lp  - the device's private adapter structure
1161  *
1162  *  RETURNS:
1163  *
1164  *      0 on success
1165  *      errno value otherwise
1166  *
1167  ******************************************************************************/
wireless_set_encode(struct net_device * dev,struct iw_request_info * info,struct iw_point * erq,char * keybuf)1168 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1169 {
1170 	struct wl_private *lp = wl_priv(dev);
1171 	unsigned long flags;
1172 	int     ret = 0;
1173 
1174 #if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
1175 	hcf_8   encryption_state;
1176 #endif // WIRELESS_EXT > 8
1177 	/*------------------------------------------------------------------------*/
1178 
1179 
1180 	DBG_FUNC( "wireless_set_encode" );
1181 	DBG_ENTER( DbgInfo );
1182 
1183 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1184 		ret = -EBUSY;
1185 		goto out;
1186 	}
1187 
1188 	wl_lock( lp, &flags );
1189 
1190     	wl_act_int_off( lp );
1191 
1192 	/* Is encryption supported? */
1193 	if( !wl_has_wep( &( lp->hcfCtx ))) {
1194 		DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1195 		ret = -EOPNOTSUPP;
1196 		goto out_unlock;
1197 	}
1198 
1199 	DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1200 				keybuf, erq->length,
1201 				erq->flags);
1202 
1203 	/* Save state of Encryption switch */
1204 	encryption_state = lp->EnableEncryption;
1205 
1206 	/* Basic checking: do we have a key to set? */
1207 	if((erq->length) != 0) {
1208 		int index   = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1209 		int tk      = lp->TransmitKeyID - 1;		// current key
1210 
1211 
1212 		/* Check the size of the key */
1213 		switch(erq->length) {
1214 		case 0:
1215 			break;
1216 
1217 		case MIN_KEY_SIZE:
1218 		case MAX_KEY_SIZE:
1219 
1220 			/* Check the index */
1221 			if(( index < 0 ) || ( index >= MAX_KEYS )) {
1222 				index = tk;
1223 			}
1224 
1225 			/* Cleanup */
1226 			memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1227 
1228 			/* Copy the key in the driver */
1229 			memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1230 
1231 			/* Set the length */
1232 			lp->DefaultKeys.key[index].len = erq->length;
1233 
1234 			DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1235 			DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1236 						lp->DefaultKeys.key[index].len, index );
1237 
1238 			/* Enable WEP (if possible) */
1239 			if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1240 				lp->EnableEncryption = 1;
1241 			}
1242 
1243 			break;
1244 
1245 		default:
1246 			DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1247 			ret = -EINVAL;
1248 			goto out_unlock;
1249 		}
1250 	} else {
1251 		int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1252 
1253 
1254 		/* Do we want to just set the current transmit key? */
1255 		if(( index >= 0 ) && ( index < MAX_KEYS )) {
1256 			DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1257 						lp->DefaultKeys.key[index].len );
1258 
1259 			if( lp->DefaultKeys.key[index].len > 0 ) {
1260 				lp->TransmitKeyID       = index + 1;
1261 				lp->EnableEncryption    = 1;
1262 			} else {
1263 				DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1264 				DBG_LEAVE( DbgInfo );
1265 				ret = -EINVAL;
1266 			}
1267 		}
1268 	}
1269 
1270 	/* Read the flags */
1271 	if( erq->flags & IW_ENCODE_DISABLED ) {
1272 		lp->EnableEncryption = 0;	// disable encryption
1273 	} else {
1274 		lp->EnableEncryption = 1;
1275 	}
1276 
1277 	if( erq->flags & IW_ENCODE_RESTRICTED ) {
1278 		DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1279 		ret = -EINVAL;		// Invalid
1280 	}
1281 
1282 	DBG_TRACE( DbgInfo, "encryption_state :       %d\n", encryption_state );
1283 	DBG_TRACE( DbgInfo, "lp->EnableEncryption :   %d\n", lp->EnableEncryption );
1284 	DBG_TRACE( DbgInfo, "erq->length            : %d\n",
1285 			   erq->length);
1286 	DBG_TRACE( DbgInfo, "erq->flags             : 0x%x\n",
1287 			   erq->flags);
1288 
1289 	/* Write the changes to the card */
1290 	if( ret == 0 ) {
1291 		DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1292 					lp->TransmitKeyID );
1293 
1294 		if( lp->EnableEncryption == encryption_state ) {
1295 			if( erq->length != 0 ) {
1296 				/* Dynamic WEP key update */
1297 				wl_set_wep_keys( lp );
1298 			}
1299 		} else {
1300 			/* To switch encryption on/off, soft reset is required */
1301 			wl_apply( lp );
1302 		}
1303 	}
1304 
1305 	/* Send an event that Encryption has been set */
1306 	wl_wext_event_encode( dev );
1307 
1308 out_unlock:
1309 
1310     	wl_act_int_on( lp );
1311 
1312 	wl_unlock(lp, &flags);
1313 
1314 out:
1315 	DBG_LEAVE( DbgInfo );
1316 	return ret;
1317 } // wireless_set_encode
1318 /*============================================================================*/
1319 
1320 
1321 
1322 
1323 /*******************************************************************************
1324  *	wireless_get_encode()
1325  *******************************************************************************
1326  *
1327  *  DESCRIPTION:
1328  *
1329  *     Gets the encryption keys and status.
1330  *
1331  *  PARAMETERS:
1332  *
1333  *      wrq - the wireless request buffer
1334  *      lp  - the device's private adapter structure
1335  *
1336  *  RETURNS:
1337  *
1338  *      0 on success
1339  *      errno value otherwise
1340  *
1341  ******************************************************************************/
wireless_get_encode(struct net_device * dev,struct iw_request_info * info,struct iw_point * erq,char * key)1342 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1343 
1344 {
1345 	struct wl_private *lp = wl_priv(dev);
1346 	unsigned long flags;
1347 	int ret = 0;
1348 	int index;
1349 	/*------------------------------------------------------------------------*/
1350 
1351 
1352 	DBG_FUNC( "wireless_get_encode" );
1353 	DBG_ENTER( DbgInfo );
1354 	DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1355 
1356 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1357 		ret = -EBUSY;
1358 		goto out;
1359 	}
1360 
1361 	/* Only super-user can see WEP key */
1362 	if( !capable( CAP_NET_ADMIN )) {
1363 		ret = -EPERM;
1364 		DBG_LEAVE( DbgInfo );
1365 		return ret;
1366 	}
1367 
1368 	wl_lock( lp, &flags );
1369 
1370     	wl_act_int_off( lp );
1371 
1372 	/* Is it supported? */
1373 	if( !wl_has_wep( &( lp->hcfCtx ))) {
1374 		ret = -EOPNOTSUPP;
1375 		goto out_unlock;
1376 	}
1377 
1378 	/* Basic checking */
1379 	index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1380 
1381 
1382 	/* Set the flags */
1383 	erq->flags = 0;
1384 
1385 	if( lp->EnableEncryption == 0 ) {
1386 		erq->flags |= IW_ENCODE_DISABLED;
1387 	}
1388 
1389 	/* Which key do we want */
1390 	if(( index < 0 ) || ( index >= MAX_KEYS )) {
1391 		index = lp->TransmitKeyID - 1;
1392 	}
1393 
1394 	erq->flags |= index + 1;
1395 
1396 	/* Copy the key to the user buffer */
1397 	erq->length = lp->DefaultKeys.key[index].len;
1398 
1399 	memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1400 
1401 out_unlock:
1402 
1403     	wl_act_int_on( lp );
1404 
1405 	wl_unlock(lp, &flags);
1406 
1407 out:
1408 	DBG_LEAVE( DbgInfo );
1409 	return ret;
1410 } // wireless_get_encode
1411 /*============================================================================*/
1412 
1413 
1414 
1415 
1416 /*******************************************************************************
1417  *	wireless_set_nickname()
1418  *******************************************************************************
1419  *
1420  *  DESCRIPTION:
1421  *
1422  *     Sets the nickname, or station name, of the wireless device.
1423  *
1424  *  PARAMETERS:
1425  *
1426  *      wrq - the wireless request buffer
1427  *      lp  - the device's private adapter structure
1428  *
1429  *  RETURNS:
1430  *
1431  *      0 on success
1432  *      errno value otherwise
1433  *
1434  ******************************************************************************/
wireless_set_nickname(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * nickname)1435 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1436 {
1437 	struct wl_private *lp = wl_priv(dev);
1438 	unsigned long flags;
1439 	int ret = 0;
1440 	/*------------------------------------------------------------------------*/
1441 
1442 
1443 	DBG_FUNC( "wireless_set_nickname" );
1444 	DBG_ENTER( DbgInfo );
1445 
1446 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1447 		ret = -EBUSY;
1448 		goto out;
1449 	}
1450 
1451 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1452 	if( !capable(CAP_NET_ADMIN )) {
1453 		ret = -EPERM;
1454 		DBG_LEAVE( DbgInfo );
1455 		return ret;
1456 	}
1457 #endif
1458 
1459 	/* Validate the new value */
1460 	if(data->length > HCF_MAX_NAME_LEN) {
1461 		ret = -EINVAL;
1462 		goto out;
1463 	}
1464 
1465 	wl_lock( lp, &flags );
1466 
1467     	wl_act_int_off( lp );
1468 
1469 	memset( lp->StationName, 0, sizeof( lp->StationName ));
1470 
1471 	memcpy( lp->StationName, nickname, data->length );
1472 
1473 	/* Commit the adapter parameters */
1474 	wl_apply( lp );
1475 
1476     	wl_act_int_on( lp );
1477 
1478 	wl_unlock(lp, &flags);
1479 
1480 out:
1481 	DBG_LEAVE( DbgInfo );
1482 	return ret;
1483 } // wireless_set_nickname
1484 /*============================================================================*/
1485 
1486 
1487 
1488 
1489 /*******************************************************************************
1490  *	wireless_get_nickname()
1491  *******************************************************************************
1492  *
1493  *  DESCRIPTION:
1494  *
1495  *     Gets the nickname, or station name, of the wireless device.
1496  *
1497  *  PARAMETERS:
1498  *
1499  *      wrq - the wireless request buffer
1500  *      lp  - the device's private adapter structure
1501  *
1502  *  RETURNS:
1503  *
1504  *      0 on success
1505  *      errno value otherwise
1506  *
1507  ******************************************************************************/
wireless_get_nickname(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * nickname)1508 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1509 {
1510 	struct wl_private *lp = wl_priv(dev);
1511 	unsigned long flags;
1512 	int         ret = 0;
1513 	int         status = -1;
1514 	wvName_t    *pName;
1515 	/*------------------------------------------------------------------------*/
1516 
1517 
1518 	DBG_FUNC( "wireless_get_nickname" );
1519 	DBG_ENTER( DbgInfo );
1520 
1521 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1522 		ret = -EBUSY;
1523 		goto out;
1524 	}
1525 
1526 	wl_lock( lp, &flags );
1527 
1528     	wl_act_int_off( lp );
1529 
1530 	/* Get the current station name */
1531 	lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1532 	lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1533 
1534 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1535 
1536 	if( status == HCF_SUCCESS ) {
1537 		pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1538 
1539 		/* Endian translate the length */
1540 		pName->length = CNV_LITTLE_TO_INT( pName->length );
1541 
1542 		if ( pName->length > IW_ESSID_MAX_SIZE ) {
1543 			ret = -EFAULT;
1544 		} else {
1545 			/* Copy the information into the user buffer */
1546 			data->length = pName->length;
1547 			memcpy(nickname, pName->name, pName->length);
1548 		}
1549 	} else {
1550 		ret = -EFAULT;
1551 	}
1552 
1553     	wl_act_int_on( lp );
1554 
1555 	wl_unlock(lp, &flags);
1556 
1557 out:
1558 	DBG_LEAVE(DbgInfo);
1559 	return ret;
1560 } // wireless_get_nickname
1561 /*============================================================================*/
1562 
1563 
1564 
1565 
1566 /*******************************************************************************
1567  *	wireless_set_porttype()
1568  *******************************************************************************
1569  *
1570  *  DESCRIPTION:
1571  *
1572  *     Sets the port type of the wireless device.
1573  *
1574  *  PARAMETERS:
1575  *
1576  *      wrq - the wireless request buffer
1577  *      lp  - the device's private adapter structure
1578  *
1579  *  RETURNS:
1580  *
1581  *      0 on success
1582  *      errno value otherwise
1583  *
1584  ******************************************************************************/
wireless_set_porttype(struct net_device * dev,struct iw_request_info * info,__u32 * mode,char * extra)1585 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1586 {
1587 	struct wl_private *lp = wl_priv(dev);
1588 	unsigned long flags;
1589 	int ret = 0;
1590 	hcf_16  portType;
1591 	hcf_16	createIBSS;
1592 	/*------------------------------------------------------------------------*/
1593 
1594 	DBG_FUNC( "wireless_set_porttype" );
1595 	DBG_ENTER( DbgInfo );
1596 
1597 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1598 		ret = -EBUSY;
1599 		goto out;
1600 	}
1601 
1602 	wl_lock( lp, &flags );
1603 
1604     	wl_act_int_off( lp );
1605 
1606 	/* Validate the new value */
1607 	switch( *mode ) {
1608 	case IW_MODE_ADHOC:
1609 
1610 		/* When user requests ad-hoc, set IBSS mode! */
1611 		portType         = 1;
1612 		createIBSS       = 1;
1613 
1614 		lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1615 
1616 		break;
1617 
1618 
1619 	case IW_MODE_AUTO:
1620 	case IW_MODE_INFRA:
1621 
1622 		/* Both automatic and infrastructure set port to BSS/STA mode */
1623 		portType         = 1;
1624 		createIBSS       = 0;
1625 
1626 		lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1627 
1628 		break;
1629 
1630 
1631 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1632 
1633 	case IW_MODE_MASTER:
1634 
1635 		/* Set BSS/AP mode */
1636 		portType             = 1;
1637 
1638 		lp->CreateIBSS       = 0;
1639 		lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1640 
1641 		break;
1642 
1643 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1644 
1645 
1646 	default:
1647 
1648 		portType   = 0;
1649 		createIBSS = 0;
1650 		ret = -EINVAL;
1651 	}
1652 
1653 	if( portType != 0 ) {
1654 		/* Only do something if there is a mode change */
1655 		if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1656 			lp->PortType   = portType;
1657 			lp->CreateIBSS = createIBSS;
1658 
1659 			/* Commit the adapter parameters */
1660 			wl_go( lp );
1661 
1662 			/* Send an event that mode has been set */
1663 			wl_wext_event_mode( lp->dev );
1664 		}
1665 	}
1666 
1667     	wl_act_int_on( lp );
1668 
1669 	wl_unlock(lp, &flags);
1670 
1671 out:
1672 	DBG_LEAVE( DbgInfo );
1673 	return ret;
1674 } // wireless_set_porttype
1675 /*============================================================================*/
1676 
1677 
1678 
1679 
1680 /*******************************************************************************
1681  *	wireless_get_porttype()
1682  *******************************************************************************
1683  *
1684  *  DESCRIPTION:
1685  *
1686  *     Gets the port type of the wireless device.
1687  *
1688  *  PARAMETERS:
1689  *
1690  *      wrq - the wireless request buffer
1691  *      lp  - the device's private adapter structure
1692  *
1693  *  RETURNS:
1694  *
1695  *      0 on success
1696  *      errno value otherwise
1697  *
1698  ******************************************************************************/
wireless_get_porttype(struct net_device * dev,struct iw_request_info * info,__u32 * mode,char * extra)1699 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1700 
1701 {
1702 	struct wl_private *lp = wl_priv(dev);
1703 	unsigned long flags;
1704 	int     ret = 0;
1705 	int     status = -1;
1706 	hcf_16  *pPortType;
1707 	/*------------------------------------------------------------------------*/
1708 
1709 
1710 	DBG_FUNC( "wireless_get_porttype" );
1711 	DBG_ENTER( DbgInfo );
1712 
1713 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1714 		ret = -EBUSY;
1715 		goto out;
1716 	}
1717 
1718 	wl_lock( lp, &flags );
1719 
1720     	wl_act_int_off( lp );
1721 
1722 	/* Get the current port type */
1723 	lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1724 	lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1725 
1726 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1727 
1728 	if( status == HCF_SUCCESS ) {
1729 		pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1730 
1731 		*pPortType = CNV_LITTLE_TO_INT( *pPortType );
1732 
1733 		switch( *pPortType ) {
1734 		case 1:
1735 
1736 #if 0
1737 #if (HCF_TYPE) & HCF_TYPE_AP
1738 
1739 			if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1740 				*mode = IW_MODE_MASTER;
1741 			} else {
1742 				*mode = IW_MODE_INFRA;
1743 			}
1744 
1745 #else
1746 
1747 			*mode = IW_MODE_INFRA;
1748 
1749 #endif  /* (HCF_TYPE) & HCF_TYPE_AP */
1750 #endif
1751 
1752 			if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1753 				*mode =  IW_MODE_MASTER;
1754 			} else {
1755 				if( lp->CreateIBSS ) {
1756 					*mode = IW_MODE_ADHOC;
1757 				} else {
1758 					*mode = IW_MODE_INFRA;
1759 				}
1760 			}
1761 
1762 			break;
1763 
1764 
1765 		case 3:
1766 			*mode = IW_MODE_ADHOC;
1767 			break;
1768 
1769 		default:
1770 			ret = -EFAULT;
1771 			break;
1772 		}
1773 	} else {
1774 		ret = -EFAULT;
1775 	}
1776 
1777     	wl_act_int_on( lp );
1778 
1779 	wl_unlock(lp, &flags);
1780 
1781 out:
1782 	DBG_LEAVE( DbgInfo );
1783 	return ret;
1784 } // wireless_get_porttype
1785 /*============================================================================*/
1786 
1787 
1788 
1789 
1790 /*******************************************************************************
1791  *	wireless_set_power()
1792  *******************************************************************************
1793  *
1794  *  DESCRIPTION:
1795  *
1796  *     Sets the power management settings of the wireless device.
1797  *
1798  *  PARAMETERS:
1799  *
1800  *      wrq - the wireless request buffer
1801  *      lp  - the device's private adapter structure
1802  *
1803  *  RETURNS:
1804  *
1805  *      0 on success
1806  *      errno value otherwise
1807  *
1808  ******************************************************************************/
wireless_set_power(struct net_device * dev,struct iw_request_info * info,struct iw_param * wrq,char * extra)1809 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1810 {
1811 	struct wl_private *lp = wl_priv(dev);
1812 	unsigned long flags;
1813 	int ret = 0;
1814 	/*------------------------------------------------------------------------*/
1815 
1816 
1817 	DBG_FUNC( "wireless_set_power" );
1818 	DBG_ENTER( DbgInfo );
1819 
1820 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1821 		ret = -EBUSY;
1822 		goto out;
1823 	}
1824 
1825 	DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1826 
1827 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1828 	if( !capable( CAP_NET_ADMIN )) {
1829 		ret = -EPERM;
1830 
1831 		DBG_LEAVE( DbgInfo );
1832 		return ret;
1833 	}
1834 #endif
1835 
1836 	wl_lock( lp, &flags );
1837 
1838     	wl_act_int_off( lp );
1839 
1840 	/* Set the power management state based on the 'disabled' value */
1841 	if( wrq->disabled ) {
1842 		lp->PMEnabled = 0;
1843 	} else {
1844 		lp->PMEnabled = 1;
1845 	}
1846 
1847 	/* Commit the adapter parameters */
1848 	wl_apply( lp );
1849 
1850     	wl_act_int_on( lp );
1851 
1852 	wl_unlock(lp, &flags);
1853 
1854 out:
1855 	DBG_LEAVE( DbgInfo );
1856 	return ret;
1857 } // wireless_set_power
1858 /*============================================================================*/
1859 
1860 
1861 
1862 
1863 /*******************************************************************************
1864  *	wireless_get_power()
1865  *******************************************************************************
1866  *
1867  *  DESCRIPTION:
1868  *
1869  *     Gets the power management settings of the wireless device.
1870  *
1871  *  PARAMETERS:
1872  *
1873  *      wrq - the wireless request buffer
1874  *      lp  - the device's private adapter structure
1875  *
1876  *  RETURNS:
1877  *
1878  *      0 on success
1879  *      errno value otherwise
1880  *
1881  ******************************************************************************/
wireless_get_power(struct net_device * dev,struct iw_request_info * info,struct iw_param * rrq,char * extra)1882 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1883 
1884 {
1885 	struct wl_private *lp = wl_priv(dev);
1886 	unsigned long flags;
1887 	int ret = 0;
1888 	/*------------------------------------------------------------------------*/
1889 	DBG_FUNC( "wireless_get_power" );
1890 	DBG_ENTER( DbgInfo );
1891 
1892 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1893 		ret = -EBUSY;
1894 		goto out;
1895 	}
1896 
1897 	DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1898 
1899 	wl_lock( lp, &flags );
1900 
1901     	wl_act_int_off( lp );
1902 
1903 	rrq->flags = 0;
1904 	rrq->value = 0;
1905 
1906 	if( lp->PMEnabled ) {
1907 		rrq->disabled = 0;
1908 	} else {
1909 		rrq->disabled = 1;
1910 	}
1911 
1912     	wl_act_int_on( lp );
1913 
1914 	wl_unlock(lp, &flags);
1915 
1916 out:
1917 	DBG_LEAVE( DbgInfo );
1918 	return ret;
1919 } // wireless_get_power
1920 /*============================================================================*/
1921 
1922 
1923 
1924 
1925 /*******************************************************************************
1926  *	wireless_get_tx_power()
1927  *******************************************************************************
1928  *
1929  *  DESCRIPTION:
1930  *
1931  *     Gets the transmit power of the wireless device's radio.
1932  *
1933  *  PARAMETERS:
1934  *
1935  *      wrq - the wireless request buffer
1936  *      lp  - the device's private adapter structure
1937  *
1938  *  RETURNS:
1939  *
1940  *      0 on success
1941  *      errno value otherwise
1942  *
1943  ******************************************************************************/
wireless_get_tx_power(struct net_device * dev,struct iw_request_info * info,struct iw_param * rrq,char * extra)1944 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1945 {
1946 	struct wl_private *lp = wl_priv(dev);
1947 	unsigned long flags;
1948 	int ret = 0;
1949 	/*------------------------------------------------------------------------*/
1950 	DBG_FUNC( "wireless_get_tx_power" );
1951 	DBG_ENTER( DbgInfo );
1952 
1953 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1954 		ret = -EBUSY;
1955 		goto out;
1956 	}
1957 
1958 	wl_lock( lp, &flags );
1959 
1960     	wl_act_int_off( lp );
1961 
1962 #ifdef USE_POWER_DBM
1963 	rrq->value = RADIO_TX_POWER_DBM;
1964 	rrq->flags = IW_TXPOW_DBM;
1965 #else
1966 	rrq->value = RADIO_TX_POWER_MWATT;
1967 	rrq->flags = IW_TXPOW_MWATT;
1968 #endif
1969 	rrq->fixed = 1;
1970 	rrq->disabled = 0;
1971 
1972     	wl_act_int_on( lp );
1973 
1974 	wl_unlock(lp, &flags);
1975 
1976 out:
1977 	DBG_LEAVE( DbgInfo );
1978 	return ret;
1979 } // wireless_get_tx_power
1980 /*============================================================================*/
1981 
1982 
1983 
1984 
1985 /*******************************************************************************
1986  *	wireless_set_rts_threshold()
1987  *******************************************************************************
1988  *
1989  *  DESCRIPTION:
1990  *
1991  *     Sets the RTS threshold for the wireless card.
1992  *
1993  *  PARAMETERS:
1994  *
1995  *      wrq - the wireless request buffer
1996  *      lp  - the device's private adapter structure
1997  *
1998  *  RETURNS:
1999  *
2000  *      0 on success
2001  *      errno value otherwise
2002  *
2003  ******************************************************************************/
wireless_set_rts_threshold(struct net_device * dev,struct iw_request_info * info,struct iw_param * rts,char * extra)2004 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2005 {
2006 	int ret = 0;
2007 	struct wl_private *lp = wl_priv(dev);
2008 	unsigned long flags;
2009 	int rthr = rts->value;
2010 	/*------------------------------------------------------------------------*/
2011 
2012 
2013 	DBG_FUNC( "wireless_set_rts_threshold" );
2014 	DBG_ENTER( DbgInfo );
2015 
2016 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2017 		ret = -EBUSY;
2018 		goto out;
2019 	}
2020 
2021 	if(rts->fixed == 0) {
2022 		ret = -EINVAL;
2023 		goto out;
2024 	}
2025 
2026 #if WIRELESS_EXT > 8
2027 	if( rts->disabled ) {
2028 		rthr = 2347;
2029 	}
2030 #endif /* WIRELESS_EXT > 8 */
2031 
2032 	if(( rthr < 256 ) || ( rthr > 2347 )) {
2033 		ret = -EINVAL;
2034 		goto out;
2035 	}
2036 
2037 	wl_lock( lp, &flags );
2038 
2039     	wl_act_int_off( lp );
2040 
2041 	lp->RTSThreshold = rthr;
2042 
2043 	wl_apply( lp );
2044 
2045     	wl_act_int_on( lp );
2046 
2047 	wl_unlock(lp, &flags);
2048 
2049 out:
2050 	DBG_LEAVE( DbgInfo );
2051 	return ret;
2052 } // wireless_set_rts_threshold
2053 /*============================================================================*/
2054 
2055 
2056 
2057 
2058 /*******************************************************************************
2059  *	wireless_get_rts_threshold()
2060  *******************************************************************************
2061  *
2062  *  DESCRIPTION:
2063  *
2064  *     Gets the RTS threshold for the wireless card.
2065  *
2066  *  PARAMETERS:
2067  *
2068  *      wrq - the wireless request buffer
2069  *      lp  - the device's private adapter structure
2070  *
2071  *  RETURNS:
2072  *
2073  *      0 on success
2074  *      errno value otherwise
2075  *
2076  ******************************************************************************/
wireless_get_rts_threshold(struct net_device * dev,struct iw_request_info * info,struct iw_param * rts,char * extra)2077 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2078 {
2079 	int ret = 0;
2080 	struct wl_private *lp = wl_priv(dev);
2081 	unsigned long flags;
2082 	/*------------------------------------------------------------------------*/
2083 
2084 	DBG_FUNC( "wireless_get_rts_threshold" );
2085 	DBG_ENTER( DbgInfo );
2086 
2087 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2088 		ret = -EBUSY;
2089 		goto out;
2090 	}
2091 
2092 	wl_lock( lp, &flags );
2093 
2094     	wl_act_int_off( lp );
2095 
2096 	rts->value = lp->RTSThreshold;
2097 
2098 #if WIRELESS_EXT > 8
2099 
2100 	rts->disabled = ( rts->value == 2347 );
2101 
2102 #endif /* WIRELESS_EXT > 8 */
2103 
2104 	rts->fixed = 1;
2105 
2106     	wl_act_int_on( lp );
2107 
2108 	wl_unlock(lp, &flags);
2109 
2110 out:
2111 	DBG_LEAVE( DbgInfo );
2112 	return ret;
2113 } // wireless_get_rts_threshold
2114 /*============================================================================*/
2115 
2116 
2117 
2118 
2119 
2120 /*******************************************************************************
2121  *	wireless_set_rate()
2122  *******************************************************************************
2123  *
2124  *  DESCRIPTION:
2125  *
2126  *      Set the default data rate setting used by the wireless device.
2127  *
2128  *  PARAMETERS:
2129  *
2130  *      wrq - the wireless request buffer
2131  *      lp  - the device's private adapter structure
2132  *
2133  *  RETURNS:
2134  *
2135  *      0 on success
2136  *      errno value otherwise
2137  *
2138  ******************************************************************************/
wireless_set_rate(struct net_device * dev,struct iw_request_info * info,struct iw_param * rrq,char * extra)2139 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2140 {
2141 	struct wl_private *lp = wl_priv(dev);
2142 	unsigned long flags;
2143 	int ret = 0;
2144 #ifdef WARP
2145 	int status = -1;
2146 	int index = 0;
2147 #endif  // WARP
2148 	/*------------------------------------------------------------------------*/
2149 
2150 
2151 	DBG_FUNC( "wireless_set_rate" );
2152 	DBG_ENTER( DbgInfo );
2153 
2154 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2155 		ret = -EBUSY;
2156 		goto out;
2157 	}
2158 
2159 	wl_lock( lp, &flags );
2160 
2161     	wl_act_int_off( lp );
2162 
2163 #ifdef WARP
2164 
2165 	/* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2166 	   if Bit 9 is set in the current channel RID */
2167 	lp->ltvRecord.len = 2;
2168 	lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2169 
2170 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2171 
2172 	if( status == HCF_SUCCESS ) {
2173 		index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2174 
2175 		DBG_PRINT( "Index: %d\n", index );
2176 	} else {
2177 		DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2178 		DBG_LEAVE( DbgInfo );
2179 		ret = -EINVAL;
2180 		goto out_unlock;
2181 	}
2182 
2183 	if( rrq->value > 0 &&
2184 		rrq->value <= 1 * MEGABIT ) {
2185 		lp->TxRateControl[index] = 0x0001;
2186 	}
2187 	else if( rrq->value > 1 * MEGABIT &&
2188 			rrq->value <= 2 * MEGABIT ) {
2189 		if( rrq->fixed == 1 ) {
2190 			lp->TxRateControl[index] = 0x0002;
2191 		} else {
2192 			lp->TxRateControl[index] = 0x0003;
2193 		}
2194 	}
2195 	else if( rrq->value > 2 * MEGABIT &&
2196 			rrq->value <= 5 * MEGABIT ) {
2197 		if( rrq->fixed == 1 ) {
2198 			lp->TxRateControl[index] = 0x0004;
2199 		} else {
2200 			lp->TxRateControl[index] = 0x0007;
2201 		}
2202 	}
2203 	else if( rrq->value > 5 * MEGABIT &&
2204 			rrq->value <= 6 * MEGABIT ) {
2205 		if( rrq->fixed == 1 ) {
2206 			lp->TxRateControl[index] = 0x0010;
2207 		} else {
2208 			lp->TxRateControl[index] = 0x0017;
2209 		}
2210 	}
2211 	else if( rrq->value > 6 * MEGABIT &&
2212 			rrq->value <= 9 * MEGABIT ) {
2213 		if( rrq->fixed == 1 ) {
2214 			lp->TxRateControl[index] = 0x0020;
2215 		} else {
2216 			lp->TxRateControl[index] = 0x0037;
2217 		}
2218 	}
2219 	else if( rrq->value > 9 * MEGABIT &&
2220 			rrq->value <= 11 * MEGABIT ) {
2221 		if( rrq->fixed == 1 ) {
2222 			lp->TxRateControl[index] = 0x0008;
2223 		} else {
2224 			lp->TxRateControl[index] = 0x003F;
2225 		}
2226 	}
2227 	else if( rrq->value > 11 * MEGABIT &&
2228 			rrq->value <= 12 * MEGABIT ) {
2229 		if( rrq->fixed == 1 ) {
2230 			lp->TxRateControl[index] = 0x0040;
2231 		} else {
2232 			lp->TxRateControl[index] = 0x007F;
2233 		}
2234 	}
2235 	else if( rrq->value > 12 * MEGABIT &&
2236 			rrq->value <= 18 * MEGABIT ) {
2237 		if( rrq->fixed == 1 ) {
2238 			lp->TxRateControl[index] = 0x0080;
2239 		} else {
2240 			lp->TxRateControl[index] = 0x00FF;
2241 		}
2242 	}
2243 	else if( rrq->value > 18 * MEGABIT &&
2244 			rrq->value <= 24 * MEGABIT ) {
2245 		if( rrq->fixed == 1 ) {
2246 			lp->TxRateControl[index] = 0x0100;
2247 		} else {
2248 			lp->TxRateControl[index] = 0x01FF;
2249 		}
2250 	}
2251 	else if( rrq->value > 24 * MEGABIT &&
2252 			rrq->value <= 36 * MEGABIT ) {
2253 		if( rrq->fixed == 1 ) {
2254 			lp->TxRateControl[index] = 0x0200;
2255 		} else {
2256 			lp->TxRateControl[index] = 0x03FF;
2257 		}
2258 	}
2259 	else if( rrq->value > 36 * MEGABIT &&
2260 			rrq->value <= 48 * MEGABIT ) {
2261 		if( rrq->fixed == 1 ) {
2262 			lp->TxRateControl[index] = 0x0400;
2263 		} else {
2264 			lp->TxRateControl[index] = 0x07FF;
2265 		}
2266 	}
2267 	else if( rrq->value > 48 * MEGABIT &&
2268 			rrq->value <= 54 * MEGABIT ) {
2269 		if( rrq->fixed == 1 ) {
2270 			lp->TxRateControl[index] = 0x0800;
2271 		} else {
2272 			lp->TxRateControl[index] = 0x0FFF;
2273 		}
2274 	}
2275 	else if( rrq->fixed == 0 ) {
2276 		/* In this case, the user has not specified a bitrate, only the "auto"
2277 		   moniker. So, set to all supported rates */
2278 		lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2279 	} else {
2280 		rrq->value = 0;
2281 		ret = -EINVAL;
2282 		goto out_unlock;
2283 	}
2284 
2285 
2286 #else
2287 
2288 	if( rrq->value > 0 &&
2289 			rrq->value <= 1 * MEGABIT ) {
2290 		lp->TxRateControl[0] = 1;
2291 	}
2292 	else if( rrq->value > 1 * MEGABIT &&
2293 			rrq->value <= 2 * MEGABIT ) {
2294 		if( rrq->fixed ) {
2295 			lp->TxRateControl[0] = 2;
2296 		} else {
2297 			lp->TxRateControl[0] = 6;
2298 		}
2299 	}
2300 	else if( rrq->value > 2 * MEGABIT &&
2301 			rrq->value <= 5 * MEGABIT ) {
2302 		if( rrq->fixed ) {
2303 			lp->TxRateControl[0] = 4;
2304 		} else {
2305 			lp->TxRateControl[0] = 7;
2306 		}
2307 	}
2308 	else if( rrq->value > 5 * MEGABIT &&
2309 			rrq->value <= 11 * MEGABIT ) {
2310 		if( rrq->fixed)  {
2311 			lp->TxRateControl[0] = 5;
2312 		} else {
2313 			lp->TxRateControl[0] = 3;
2314 		}
2315 	}
2316 	else if( rrq->fixed == 0 ) {
2317 		/* In this case, the user has not specified a bitrate, only the "auto"
2318 		   moniker. So, set the rate to 11Mb auto */
2319 		lp->TxRateControl[0] = 3;
2320 	} else {
2321 		rrq->value = 0;
2322 		ret = -EINVAL;
2323 		goto out_unlock;
2324 	}
2325 
2326 #endif  // WARP
2327 
2328 
2329 	/* Commit the adapter parameters */
2330 	wl_apply( lp );
2331 
2332 out_unlock:
2333 
2334     	wl_act_int_on( lp );
2335 
2336 	wl_unlock(lp, &flags);
2337 
2338 out:
2339 	DBG_LEAVE( DbgInfo );
2340 	return ret;
2341 } // wireless_set_rate
2342 /*============================================================================*/
2343 
2344 
2345 
2346 
2347 /*******************************************************************************
2348  *	wireless_get_rate()
2349  *******************************************************************************
2350  *
2351  *  DESCRIPTION:
2352  *
2353  *      Get the default data rate setting used by the wireless device.
2354  *
2355  *  PARAMETERS:
2356  *
2357  *      wrq - the wireless request buffer
2358  *      lp  - the device's private adapter structure
2359  *
2360  *  RETURNS:
2361  *
2362  *      0 on success
2363  *      errno value otherwise
2364  *
2365  ******************************************************************************/
wireless_get_rate(struct net_device * dev,struct iw_request_info * info,struct iw_param * rrq,char * extra)2366 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2367 
2368 {
2369 	struct wl_private *lp = wl_priv(dev);
2370 	unsigned long flags;
2371 	int     ret = 0;
2372 	int     status = -1;
2373 	hcf_16  txRate;
2374 	/*------------------------------------------------------------------------*/
2375 
2376 
2377 	DBG_FUNC( "wireless_get_rate" );
2378 	DBG_ENTER( DbgInfo );
2379 
2380 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2381 		ret = -EBUSY;
2382 		goto out;
2383 	}
2384 
2385 	wl_lock( lp, &flags );
2386 
2387     	wl_act_int_off( lp );
2388 
2389 	/* Get the current transmit rate from the adapter */
2390 	lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2391 	lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2392 
2393 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2394 
2395 	if( status == HCF_SUCCESS ) {
2396 #ifdef WARP
2397 
2398 		txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2399 
2400 		if( txRate & 0x0001 ) {
2401 			txRate = 1;
2402 		}
2403 		else if( txRate & 0x0002 ) {
2404 			txRate = 2;
2405 		}
2406 		else if( txRate & 0x0004 ) {
2407 			txRate = 5;
2408 		}
2409 		else if( txRate & 0x0008 ) {
2410 			txRate = 11;
2411 		}
2412 		else if( txRate & 0x00010 ) {
2413 			txRate = 6;
2414 		}
2415 		else if( txRate & 0x00020 ) {
2416 			txRate = 9;
2417 		}
2418 		else if( txRate & 0x00040 ) {
2419 			txRate = 12;
2420 		}
2421 		else if( txRate & 0x00080 ) {
2422 			txRate = 18;
2423 		}
2424 		else if( txRate & 0x00100 ) {
2425 			txRate = 24;
2426 		}
2427 		else if( txRate & 0x00200 ) {
2428 			txRate = 36;
2429 		}
2430 		else if( txRate & 0x00400 ) {
2431 			txRate = 48;
2432 		}
2433 		else if( txRate & 0x00800 ) {
2434 			txRate = 54;
2435 		}
2436 
2437 #else
2438 
2439 		txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2440 
2441 #endif  // WARP
2442 
2443 		rrq->value = txRate * MEGABIT;
2444 	} else {
2445 		rrq->value = 0;
2446 		ret = -EFAULT;
2447 	}
2448 
2449     	wl_act_int_on( lp );
2450 
2451 	wl_unlock(lp, &flags);
2452 
2453 out:
2454 	DBG_LEAVE( DbgInfo );
2455 	return ret;
2456 } // wireless_get_rate
2457 /*============================================================================*/
2458 
2459 
2460 
2461 
2462 #if 0 //;? Not used anymore
2463 /*******************************************************************************
2464  *	wireless_get_private_interface()
2465  *******************************************************************************
2466  *
2467  *  DESCRIPTION:
2468  *
2469  *      Returns the Linux Wireless Extensions' compatible private interface of
2470  *  the driver.
2471  *
2472  *  PARAMETERS:
2473  *
2474  *      wrq - the wireless request buffer
2475  *      lp  - the device's private adapter structure
2476  *
2477  *  RETURNS:
2478  *
2479  *      0 on success
2480  *      errno value otherwise
2481  *
2482  ******************************************************************************/
2483 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2484 {
2485 	int ret = 0;
2486 	/*------------------------------------------------------------------------*/
2487 
2488 
2489 	DBG_FUNC( "wireless_get_private_interface" );
2490 	DBG_ENTER( DbgInfo );
2491 
2492 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2493 		ret = -EBUSY;
2494 		goto out;
2495 	}
2496 
2497 	if( wrq->u.data.pointer != NULL ) {
2498 		struct iw_priv_args priv[] =
2499 		{
2500 			{ SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2501 			{ SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2502 			{ SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2503 			{ SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2504 			{ SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2505 			{ SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2506 		};
2507 
2508 		/* Verify the user buffer */
2509 		ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2510 
2511 		if( ret != 0 ) {
2512 			DBG_LEAVE( DbgInfo );
2513 			return ret;
2514 		}
2515 
2516 		/* Copy the data into the user's buffer */
2517 		wrq->u.data.length = NELEM( priv );
2518 		copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2519 	}
2520 
2521 out:
2522 	DBG_LEAVE( DbgInfo );
2523 	return ret;
2524 } // wireless_get_private_interface
2525 /*============================================================================*/
2526 #endif
2527 
2528 
2529 
2530 #if WIRELESS_EXT > 13
2531 
2532 /*******************************************************************************
2533  *	wireless_set_scan()
2534  *******************************************************************************
2535  *
2536  *  DESCRIPTION:
2537  *
2538  *      Instructs the driver to initiate a network scan.
2539  *
2540  *  PARAMETERS:
2541  *
2542  *      wrq - the wireless request buffer
2543  *      lp  - the device's private adapter structure
2544  *
2545  *  RETURNS:
2546  *
2547  *      0 on success
2548  *      errno value otherwise
2549  *
2550  ******************************************************************************/
wireless_set_scan(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)2551 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2552 {
2553 	struct wl_private *lp = wl_priv(dev);
2554 	unsigned long flags;
2555 	int                 ret = 0;
2556 	int                 status = -1;
2557 	int		    retries = 0;
2558 	/*------------------------------------------------------------------------*/
2559 
2560 	//;? Note: shows results as trace, retruns always 0 unless BUSY
2561 
2562 	DBG_FUNC( "wireless_set_scan" );
2563 	DBG_ENTER( DbgInfo );
2564 
2565 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2566 		ret = -EBUSY;
2567 		goto out;
2568 	}
2569 
2570 	wl_lock( lp, &flags );
2571 
2572     	wl_act_int_off( lp );
2573 
2574 	/*
2575          * This looks like a nice place to test if the HCF is still
2576          * communicating with the card. It seems that sometimes BAP_1
2577          * gets corrupted. By looking at the comments in HCF the
2578          * cause is still a mystery. Okay, the communication to the
2579          * card is dead, reset the card to revive.
2580          */
2581 	if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2582 	{
2583 		DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2584 		wl_reset( dev );
2585 	}
2586 
2587 retry:
2588 	/* Set the completion state to FALSE */
2589 	lp->probe_results.scan_complete = FALSE;
2590 
2591 
2592 	/* Channels to scan */
2593 #ifdef WARP
2594 	lp->ltvRecord.len       = 5;
2595 	lp->ltvRecord.typ       = CFG_SCAN_CHANNEL;
2596 	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x3FFF );  // 2.4 GHz Band
2597 	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( 0xFFFF );  // 5.0 GHz Band
2598 	lp->ltvRecord.u.u16[2]  = CNV_INT_TO_LITTLE( 0xFFFF );  //      ..
2599 	lp->ltvRecord.u.u16[3]  = CNV_INT_TO_LITTLE( 0x0007 );  //      ..
2600 #else
2601 	lp->ltvRecord.len       = 2;
2602 	lp->ltvRecord.typ       = CFG_SCAN_CHANNEL;
2603 	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x7FFF );
2604 #endif  // WARP
2605 
2606 	status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2607 
2608 	DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result      : 0x%x\n", status );
2609 
2610 	// Holding the lock too long, make a gap to allow other processes
2611 	wl_unlock(lp, &flags);
2612 	wl_lock( lp, &flags );
2613 
2614 	if( status != HCF_SUCCESS ) {
2615 		//Recovery
2616 		retries++;
2617 		if(retries <= 10) {
2618 			DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2619 			wl_reset( dev );
2620 
2621 			// Holding the lock too long, make a gap to allow other processes
2622 			wl_unlock(lp, &flags);
2623 			wl_lock( lp, &flags );
2624 
2625 			goto retry;
2626 		}
2627 	}
2628 
2629 	/* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2630 	   disassociate from the network we are currently on */
2631 	lp->ltvRecord.len       = 18;
2632 	lp->ltvRecord.typ       = CFG_SCAN_SSID;
2633 	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
2634 	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( 0 );
2635 
2636 	status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2637 
2638 	// Holding the lock too long, make a gap to allow other processes
2639 	wl_unlock(lp, &flags);
2640 	wl_lock( lp, &flags );
2641 
2642 	DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2643 
2644 	/* Initiate the scan */
2645 	/* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2646 	   retrieve probe responses must always be used to support WPA */
2647 	status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2648 
2649 	if( status == HCF_SUCCESS ) {
2650 		DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2651 	} else {
2652 		DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2653 	}
2654 
2655     	wl_act_int_on( lp );
2656 
2657 	wl_unlock(lp, &flags);
2658 
2659 out:
2660 	DBG_LEAVE(DbgInfo);
2661 	return ret;
2662 } // wireless_set_scan
2663 /*============================================================================*/
2664 
2665 
2666 
2667 
2668 /*******************************************************************************
2669  *	wireless_get_scan()
2670  *******************************************************************************
2671  *
2672  *  DESCRIPTION:
2673  *
2674  *      Instructs the driver to gather and return the results of a network scan.
2675  *
2676  *  PARAMETERS:
2677  *
2678  *      wrq - the wireless request buffer
2679  *      lp  - the device's private adapter structure
2680  *
2681  *  RETURNS:
2682  *
2683  *      0 on success
2684  *      errno value otherwise
2685  *
2686  ******************************************************************************/
wireless_get_scan(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)2687 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2688 {
2689 	struct wl_private *lp = wl_priv(dev);
2690 	unsigned long flags;
2691 	int                 ret = 0;
2692 	int                 count;
2693 	char                *buf;
2694 	char                *buf_end;
2695 	struct iw_event     iwe;
2696 	PROBE_RESP          *probe_resp;
2697 	hcf_8               msg[512];
2698 	hcf_8               *wpa_ie;
2699 	hcf_16              wpa_ie_len;
2700 	/*------------------------------------------------------------------------*/
2701 
2702 
2703 	DBG_FUNC( "wireless_get_scan" );
2704 	DBG_ENTER( DbgInfo );
2705 
2706 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2707 		ret = -EBUSY;
2708 		goto out;
2709 	}
2710 
2711 	wl_lock( lp, &flags );
2712 
2713     	wl_act_int_off( lp );
2714 
2715 	/* If the scan is not done, tell the calling process to try again later */
2716 	if( !lp->probe_results.scan_complete ) {
2717 		ret = -EAGAIN;
2718 		goto out_unlock;
2719 	}
2720 
2721 	DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2722 			   lp->probe_results.num_aps );
2723 
2724 	buf     = extra;
2725 	buf_end = extra + IW_SCAN_MAX_DATA;
2726 
2727 	for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2728 		/* Reference the probe response from the table */
2729 		probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2730 
2731 
2732 		/* First entry MUST be the MAC address */
2733 		memset( &iwe, 0, sizeof( iwe ));
2734 
2735 		iwe.cmd                 = SIOCGIWAP;
2736 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2737 		memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2738 		iwe.len                 = IW_EV_ADDR_LEN;
2739 
2740 		buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2741 
2742 
2743 		/* Use the mode to indicate if it's a station or AP */
2744 		/* Won't always be an AP if in IBSS mode */
2745 		memset( &iwe, 0, sizeof( iwe ));
2746 
2747 		iwe.cmd = SIOCGIWMODE;
2748 
2749 		if( probe_resp->capability & CAPABILITY_IBSS ) {
2750 			iwe.u.mode = IW_MODE_INFRA;
2751 		} else {
2752 			iwe.u.mode = IW_MODE_MASTER;
2753 		}
2754 
2755 		iwe.len = IW_EV_UINT_LEN;
2756 
2757 		buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2758 
2759 
2760 		/* Any quality information */
2761 		memset(&iwe, 0, sizeof(iwe));
2762 
2763 		iwe.cmd             = IWEVQUAL;
2764 		iwe.u.qual.level    = dbm(probe_resp->signal);
2765 		iwe.u.qual.noise    = dbm(probe_resp->silence);
2766 		iwe.u.qual.qual     = iwe.u.qual.level - iwe.u.qual.noise;
2767 		iwe.u.qual.updated  = lp->probe_results.scan_complete | IW_QUAL_DBM;
2768 		iwe.len             = IW_EV_QUAL_LEN;
2769 
2770 		buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2771 
2772 
2773 		/* ESSID information */
2774 		if( probe_resp->rawData[1] > 0 ) {
2775 			memset( &iwe, 0, sizeof( iwe ));
2776 
2777 			iwe.cmd = SIOCGIWESSID;
2778 			iwe.u.data.length = probe_resp->rawData[1];
2779 			iwe.u.data.flags = 1;
2780 
2781 			buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2782 		}
2783 
2784 
2785 		/* Encryption Information */
2786 		memset( &iwe, 0, sizeof( iwe ));
2787 
2788 		iwe.cmd             = SIOCGIWENCODE;
2789 		iwe.u.data.length   = 0;
2790 
2791 		/* Check the capabilities field of the Probe Response to see if
2792 		   'privacy' is supported on the AP in question */
2793 		if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2794 			iwe.u.data.flags |= IW_ENCODE_ENABLED;
2795 		} else {
2796 			iwe.u.data.flags |= IW_ENCODE_DISABLED;
2797 		}
2798 
2799 		buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2800 
2801 
2802 		/* Frequency Info */
2803 		memset( &iwe, 0, sizeof( iwe ));
2804 
2805 		iwe.cmd = SIOCGIWFREQ;
2806 		iwe.len = IW_EV_FREQ_LEN;
2807 		iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2808 		iwe.u.freq.e = 0;
2809 
2810 		buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2811 
2812 
2813 #if WIRELESS_EXT > 14
2814 		/* Custom info (Beacon Interval) */
2815 		memset( &iwe, 0, sizeof( iwe ));
2816 		memset( msg, 0, sizeof( msg ));
2817 
2818 		iwe.cmd = IWEVCUSTOM;
2819 		sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2820 		iwe.u.data.length = strlen( msg );
2821 
2822 		buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2823 
2824 
2825 		/* Custom info (WPA-IE) */
2826 		wpa_ie = NULL;
2827 		wpa_ie_len = 0;
2828 
2829 		wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2830 		if( wpa_ie != NULL ) {
2831 			memset( &iwe, 0, sizeof( iwe ));
2832 			memset( msg, 0, sizeof( msg ));
2833 
2834 			iwe.cmd = IWEVCUSTOM;
2835 			sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2836 			iwe.u.data.length = strlen( msg );
2837 
2838 			buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2839 		}
2840 
2841 		/* Add other custom info in formatted string format as needed... */
2842 #endif
2843 	}
2844 
2845 	data->length = buf - extra;
2846 
2847 out_unlock:
2848 
2849     	wl_act_int_on( lp );
2850 
2851 	wl_unlock(lp, &flags);
2852 
2853 out:
2854 	DBG_LEAVE( DbgInfo );
2855 	return ret;
2856 } // wireless_get_scan
2857 /*============================================================================*/
2858 
2859 #endif  // WIRELESS_EXT > 13
2860 
2861 
2862 #if WIRELESS_EXT > 17
2863 
wireless_set_auth(struct net_device * dev,struct iw_request_info * info,struct iw_param * data,char * extra)2864 static int wireless_set_auth(struct net_device *dev,
2865 			  struct iw_request_info *info,
2866 			  struct iw_param *data, char *extra)
2867 {
2868 	struct wl_private *lp = wl_priv(dev);
2869 	unsigned long flags;
2870 	int			      ret;
2871 	int			      iwa_idx = data->flags & IW_AUTH_INDEX;
2872 	int			      iwa_val = data->value;
2873 
2874 	DBG_FUNC( "wireless_set_auth" );
2875 	DBG_ENTER( DbgInfo );
2876 
2877 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2878 		ret = -EBUSY;
2879 		goto out;
2880 	}
2881 
2882 	wl_lock( lp, &flags );
2883 
2884     	wl_act_int_off( lp );
2885 
2886 	switch (iwa_idx) {
2887 		case IW_AUTH_WPA_VERSION:
2888 			DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2889 			/* We do support WPA only; how should DISABLED be treated? */
2890 			if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2891 				ret = 0;
2892 			else
2893 				ret = -EINVAL;
2894 			break;
2895 
2896 		case IW_AUTH_WPA_ENABLED:
2897 			DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2898 			if (iwa_val)
2899 				lp->EnableEncryption = 2;
2900 			else
2901 				lp->EnableEncryption = 0;
2902 			ret = 0;
2903 			break;
2904 
2905 		case IW_AUTH_TKIP_COUNTERMEASURES:
2906 			DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2907 			lp->driverEnable = !iwa_val;
2908 			if(lp->driverEnable)
2909 				hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2910 			else
2911 				hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2912 			ret = 0;
2913 			break;
2914 
2915 		case IW_AUTH_DROP_UNENCRYPTED:
2916 			DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2917 			/* We do not actually do anything here, just to silence
2918 			 * wpa_supplicant */
2919 			ret = 0;
2920 			break;
2921 
2922 		case IW_AUTH_CIPHER_PAIRWISE:
2923 			DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2924 			/* not implemented, return an error */
2925 			ret = -EINVAL;
2926 			break;
2927 
2928 		case IW_AUTH_CIPHER_GROUP:
2929 			DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2930 			/* not implemented, return an error */
2931 			ret = -EINVAL;
2932 			break;
2933 
2934 		case IW_AUTH_KEY_MGMT:
2935 			DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2936 			/* not implemented, return an error */
2937 			ret = -EINVAL;
2938 			break;
2939 
2940 		case IW_AUTH_80211_AUTH_ALG:
2941 			DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2942 			/* not implemented, return an error */
2943 			ret = -EINVAL;
2944 			break;
2945 
2946 		case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2947 			DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2948 			/* not implemented, return an error */
2949 			ret = -EINVAL;
2950 			break;
2951 
2952 		case IW_AUTH_ROAMING_CONTROL:
2953 			DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2954 			/* not implemented, return an error */
2955 			ret = -EINVAL;
2956 			break;
2957 
2958 		case IW_AUTH_PRIVACY_INVOKED:
2959 			DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2960 			/* not implemented, return an error */
2961 			ret = -EINVAL;
2962 			break;
2963 
2964 		default:
2965 			DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2966 			/* return an error */
2967 			ret = -EINVAL;
2968 			break;
2969 	}
2970 
2971     	wl_act_int_on( lp );
2972 
2973 	wl_unlock(lp, &flags);
2974 
2975 out:
2976 	DBG_LEAVE( DbgInfo );
2977 	return ret;
2978 } // wireless_set_auth
2979 /*============================================================================*/
2980 
2981 
2982 
hermes_set_key(ltv_t * ltv,int alg,int key_idx,u8 * addr,int set_tx,u8 * seq,u8 * key,size_t key_len)2983 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
2984 			  int set_tx, u8 *seq, u8 *key, size_t key_len)
2985 {
2986 	int ret = -EINVAL;
2987 	// int   count = 0;
2988 	int   buf_idx = 0;
2989 	hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
2990 		{ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
2991 
2992 	DBG_FUNC( "hermes_set_key" );
2993 	DBG_ENTER( DbgInfo );
2994 
2995 	/*
2996          * Check the key index here; if 0, load as Pairwise Key, otherwise,
2997          * load as a group key. Note that for the Hermes, the RIDs for
2998          * group/pariwise keys are different from each other and different
2999          * than the default WEP keys as well.
3000          */
3001 	switch (alg)
3002 	{
3003 	case IW_ENCODE_ALG_TKIP:
3004 		DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3005 #if 0
3006 		/*
3007                  * Make sure that there is no data queued up in the firmware
3008                  * before setting the TKIP keys. If this check is not
3009                  * performed, some data may be sent out with incorrect MIC
3010                  * and cause synchronizarion errors with the AP
3011                  */
3012 		/* Check every 1ms for 100ms */
3013 		for( count = 0; count < 100; count++ )
3014 		{
3015 			usleep( 1000 );
3016 
3017 			ltv.len = 2;
3018 			ltv.typ = 0xFD91;  // This RID not defined in HCF yet!!!
3019 			ltv.u.u16[0] = 0;
3020 
3021 			wl_get_info( sock, &ltv, ifname );
3022 
3023 			if( ltv.u.u16[0] == 0 )
3024 			{
3025 				break;
3026 			}
3027 		}
3028 
3029 		if( count == 100 )
3030 		{
3031 			wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
3032 		}
3033 #endif
3034 
3035 		switch (key_idx) {
3036 		case 0:
3037 			ltv->len = 28;
3038 			ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
3039 
3040 			/* Load the BSSID */
3041 			memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
3042 			buf_idx += ETH_ALEN;
3043 
3044 			/* Load the TKIP key */
3045 			memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
3046 			buf_idx += 16;
3047 
3048 			/* Load the TSC */
3049 			memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3050 			buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3051 
3052 			/* Load the RSC */
3053 			memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3054 			buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3055 
3056 			/* Load the TxMIC key */
3057 			memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
3058 			buf_idx += 8;
3059 
3060 			/* Load the RxMIC key */
3061 			memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
3062 
3063 			ret = 0;
3064 			break;
3065 		case 1:
3066 		case 2:
3067 		case 3:
3068 			ltv->len = 26;
3069 			ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3070 
3071 			/* Load the key Index */
3072 			ltv->u.u16[buf_idx] = key_idx;
3073 			/* If this is a Tx Key, set bit 8000 */
3074 			if(set_tx)
3075 				ltv->u.u16[buf_idx] |= 0x8000;
3076 			buf_idx += 2;
3077 
3078 			/* Load the RSC */
3079 			memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3080 			buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3081 
3082 			/* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3083 			   CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3084 			memcpy(&ltv->u.u8[buf_idx], key, key_len);
3085 			buf_idx += key_len;
3086 
3087 			/* Load the TSC */
3088 			memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3089 
3090 			ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3091 
3092 			ret = 0;
3093 			break;
3094 		default:
3095 			break;
3096 		}
3097 
3098 		break;
3099 
3100 	case IW_ENCODE_ALG_WEP:
3101 		DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3102 		break;
3103 
3104 	case IW_ENCODE_ALG_CCMP:
3105 		DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3106 		break;
3107 
3108 	case IW_ENCODE_ALG_NONE:
3109 		DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3110 		switch (key_idx) {
3111 		case 0:
3112 			if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3113 			//if (addr != NULL) {
3114 				ltv->len = 7;
3115 				ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3116 				memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
3117 				ret = 0;
3118 			}
3119 			break;
3120 		case 1:
3121 		case 2:
3122 		case 3:
3123 			/* Clear the Group TKIP keys by index */
3124 			ltv->len = 2;
3125 			ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3126 			ltv->u.u16[0] = key_idx;
3127 
3128 			ret = 0;
3129 			break;
3130 		default:
3131 			break;
3132 		}
3133 		break;
3134 	default:
3135 		DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3136 		break;
3137 	}
3138 
3139 	DBG_LEAVE( DbgInfo );
3140 	return ret;
3141 } // hermes_set_key
3142 /*============================================================================*/
3143 
3144 
3145 
wireless_set_encodeext(struct net_device * dev,struct iw_request_info * info,struct iw_point * erq,char * keybuf)3146 static int wireless_set_encodeext (struct net_device *dev,
3147 					struct iw_request_info *info,
3148 					struct iw_point *erq, char *keybuf)
3149 {
3150 	struct wl_private *lp = wl_priv(dev);
3151 	unsigned long flags;
3152 	int			      ret;
3153 	int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3154 	ltv_t ltv;
3155 	struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3156 
3157 	DBG_FUNC( "wireless_set_encodeext" );
3158 	DBG_ENTER( DbgInfo );
3159 
3160 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3161 		ret = -EBUSY;
3162 		goto out;
3163 	}
3164 
3165 	if (sizeof(ext->rx_seq) != 8) {
3166 		DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3167 		DBG_LEAVE(DbgInfo);
3168 		return -EINVAL;
3169 	}
3170 
3171 	/* Handle WEP keys via the old set encode procedure */
3172 	if(ext->alg == IW_ENCODE_ALG_WEP) {
3173 		struct iw_point  wep_erq;
3174 		char            *wep_keybuf;
3175 
3176 		/* Build request structure */
3177 		wep_erq.flags  = erq->flags;   // take over flags with key index
3178 		wep_erq.length = ext->key_len; // take length from extended key info
3179 		wep_keybuf     = ext->key;     // pointer to the key text
3180 
3181 		/* Call wireless_set_encode tot handle the WEP key */
3182 		ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3183 		goto out;
3184 	}
3185 
3186 	/* Proceed for extended encode functions for WAP and NONE */
3187 	wl_lock( lp, &flags );
3188 
3189     	wl_act_int_off( lp );
3190 
3191 	memset(&ltv, 0, sizeof(ltv));
3192 	ret = hermes_set_key(&ltv, ext->alg, key_idx, ext->addr.sa_data,
3193 				ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3194 				ext->rx_seq, ext->key, ext->key_len);
3195 
3196 	if (ret != 0) {
3197 		DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3198 		goto out_unlock;
3199 	}
3200 
3201 	/* Put the key in HCF */
3202 	ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3203 
3204 out_unlock:
3205 	if(ret == HCF_SUCCESS) {
3206 		DBG_TRACE( DbgInfo, "Put key info succes\n");
3207 	} else {
3208 		DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3209 	}
3210 
3211     	wl_act_int_on( lp );
3212 
3213 	wl_unlock(lp, &flags);
3214 
3215 out:
3216 	DBG_LEAVE( DbgInfo );
3217 	return ret;
3218 } // wireless_set_encodeext
3219 /*============================================================================*/
3220 
3221 
3222 
wireless_get_genie(struct net_device * dev,struct iw_request_info * info,struct iw_point * data,char * extra)3223 static int wireless_get_genie(struct net_device *dev,
3224 					   struct iw_request_info *info,
3225 					   struct iw_point *data, char *extra)
3226 
3227 {
3228 	struct wl_private *lp = wl_priv(dev);
3229 	unsigned long flags;
3230 	int   ret = 0;
3231 	ltv_t ltv;
3232 
3233 	DBG_FUNC( "wireless_get_genie" );
3234 	DBG_ENTER( DbgInfo );
3235 
3236 	if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3237 		ret = -EBUSY;
3238 		goto out;
3239 	}
3240 
3241 	wl_lock( lp, &flags );
3242 
3243     	wl_act_int_off( lp );
3244 
3245 	memset(&ltv, 0, sizeof(ltv));
3246 	ltv.len = 2;
3247 	ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3248 	lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3249 	ltv.u.u16[0]  = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3250 
3251 	ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3252 
3253     	wl_act_int_on( lp );
3254 
3255 	wl_unlock(lp, &flags);
3256 
3257 out:
3258 	DBG_LEAVE( DbgInfo );
3259 	return ret;
3260 }
3261 /*============================================================================*/
3262 
3263 
3264 #endif // WIRELESS_EXT > 17
3265 
3266 /*******************************************************************************
3267  *	wl_wireless_stats()
3268  *******************************************************************************
3269  *
3270  *  DESCRIPTION:
3271  *
3272  *      Return the current device wireless statistics.
3273  *
3274  *  PARAMETERS:
3275  *
3276  *      wrq - the wireless request buffer
3277  *      lp  - the device's private adapter structure
3278  *
3279  *  RETURNS:
3280  *
3281  *      0 on success
3282  *      errno value otherwise
3283  *
3284  ******************************************************************************/
wl_wireless_stats(struct net_device * dev)3285 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3286 {
3287 	struct iw_statistics    *pStats;
3288 	struct wl_private       *lp = wl_priv(dev);
3289 	/*------------------------------------------------------------------------*/
3290 
3291 
3292 	DBG_FUNC( "wl_wireless_stats" );
3293 	DBG_ENTER(DbgInfo);
3294 	DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3295 
3296 	pStats = NULL;
3297 
3298 	/* Initialize the statistics */
3299 	pStats			= &( lp->wstats );
3300 	pStats->qual.updated    = 0x00;
3301 
3302 	if( !( lp->flags & WVLAN2_UIL_BUSY ))
3303 	{
3304 		CFG_COMMS_QUALITY_STRCT *pQual;
3305 		CFG_HERMES_TALLIES_STRCT tallies;
3306 		int                         status;
3307 
3308 		/* Update driver status */
3309 		pStats->status = 0;
3310 
3311 		/* Get the current link quality information */
3312 		lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3313 		lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3314 		status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3315 
3316 		if( status == HCF_SUCCESS ) {
3317 			pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3318 
3319 #ifdef USE_DBM
3320 			pStats->qual.qual  = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3321 			pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3322 			pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3323 
3324 			pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED  |
3325                                                  IW_QUAL_LEVEL_UPDATED |
3326                                                  IW_QUAL_NOISE_UPDATED |
3327                                                  IW_QUAL_DBM);
3328 #else
3329 			pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
3330 						     HCF_MIN_COMM_QUALITY,
3331 						     HCF_MAX_COMM_QUALITY );
3332 
3333 			pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
3334 						      HCF_MIN_SIGNAL_LEVEL,
3335 						      HCF_MAX_SIGNAL_LEVEL );
3336 
3337 			pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
3338 						      HCF_MIN_NOISE_LEVEL,
3339 						      HCF_MAX_NOISE_LEVEL );
3340 
3341 			pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED  |
3342                                                  IW_QUAL_LEVEL_UPDATED |
3343                                                  IW_QUAL_NOISE_UPDATED);
3344 #endif /* USE_DBM */
3345 		} else {
3346 			memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3347 		}
3348 
3349 		/* Get the current tallies from the adapter */
3350                 /* Only possible when the device is open */
3351 		if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3352 			if( wl_get_tallies( lp, &tallies ) == 0 ) {
3353 				/* No endian translation is needed here, as CFG_TALLIES is an
3354 				   MSF RID; all processing is done on the host, not the card! */
3355 				pStats->discard.nwid = 0L;
3356 				pStats->discard.code = tallies.RxWEPUndecryptable;
3357 				pStats->discard.misc = tallies.TxDiscards +
3358 						       tallies.RxFCSErrors +
3359 						       //tallies.RxDiscardsNoBuffer +
3360 						       tallies.TxDiscardsWrongSA;
3361 				//;? Extra taken over from Linux driver based on 7.18 version
3362 				pStats->discard.retries = tallies.TxRetryLimitExceeded;
3363 				pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3364 			} else {
3365 				memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3366 			}
3367 		} else {
3368 			memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3369 		}
3370 	}
3371 
3372 	DBG_LEAVE( DbgInfo );
3373 	return pStats;
3374 } // wl_wireless_stats
3375 /*============================================================================*/
3376 
3377 
3378 
3379 
3380 /*******************************************************************************
3381  *	wl_get_wireless_stats()
3382  *******************************************************************************
3383  *
3384  *  DESCRIPTION:
3385  *
3386  *      Return the current device wireless statistics. This function calls
3387  *      wl_wireless_stats, but acquires spinlocks first as it can be called
3388  *      directly by the network layer.
3389  *
3390  *  PARAMETERS:
3391  *
3392  *      wrq - the wireless request buffer
3393  *      lp  - the device's private adapter structure
3394  *
3395  *  RETURNS:
3396  *
3397  *      0 on success
3398  *      errno value otherwise
3399  *
3400  ******************************************************************************/
wl_get_wireless_stats(struct net_device * dev)3401 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3402 {
3403 	unsigned long           flags;
3404 	struct wl_private       *lp = wl_priv(dev);
3405 	struct iw_statistics    *pStats = NULL;
3406 	/*------------------------------------------------------------------------*/
3407 
3408 	DBG_FUNC( "wl_get_wireless_stats" );
3409 	DBG_ENTER(DbgInfo);
3410 
3411 	wl_lock( lp, &flags );
3412 
3413     	wl_act_int_off( lp );
3414 
3415 #ifdef USE_RTS
3416 	if( lp->useRTS == 1 ) {
3417 		DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3418 	} else
3419 #endif
3420 	{
3421 		pStats = wl_wireless_stats( dev );
3422 	}
3423     	wl_act_int_on( lp );
3424 
3425 	wl_unlock(lp, &flags);
3426 
3427 	DBG_LEAVE( DbgInfo );
3428 	return pStats;
3429 } // wl_get_wireless_stats
3430 
3431 
3432 /*******************************************************************************
3433  *	wl_spy_gather()
3434  *******************************************************************************
3435  *
3436  *  DESCRIPTION:
3437  *
3438  *      Gather wireless spy statistics.
3439  *
3440  *  PARAMETERS:
3441  *
3442  *      wrq - the wireless request buffer
3443  *      lp  - the device's private adapter structure
3444  *
3445  *  RETURNS:
3446  *
3447  *      0 on success
3448  *      errno value otherwise
3449  *
3450  ******************************************************************************/
wl_spy_gather(struct net_device * dev,u_char * mac)3451 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3452 {
3453 	struct iw_quality wstats;
3454 	int                     status;
3455 	u_char                  stats[2];
3456 	DESC_STRCT              desc[1];
3457 	struct wl_private   *lp = wl_priv(dev);
3458 	/*------------------------------------------------------------------------*/
3459 
3460 	/* shortcut */
3461 	if (!lp->spy_data.spy_number) {
3462 		return;
3463 	}
3464 
3465 	/* Gather wireless spy statistics: for each packet, compare the source
3466 	   address with out list, and if match, get the stats. */
3467 	memset( stats, 0, sizeof(stats));
3468 	memset( desc, 0, sizeof(DESC_STRCT));
3469 
3470 	desc[0].buf_addr	= stats;
3471 	desc[0].BUF_SIZE	= sizeof(stats);
3472 	desc[0].next_desc_addr  = 0;		// terminate list
3473 
3474 	status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3475 
3476 	if( status == HCF_SUCCESS ) {
3477 		wstats.level = (u_char) dbm(stats[1]);
3478 		wstats.noise = (u_char) dbm(stats[0]);
3479 		wstats.qual  = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3480 
3481 		wstats.updated = (IW_QUAL_QUAL_UPDATED  |
3482 				  IW_QUAL_LEVEL_UPDATED |
3483 				  IW_QUAL_NOISE_UPDATED |
3484 				  IW_QUAL_DBM);
3485 
3486 		wireless_spy_update( dev, mac, &wstats );
3487 	}
3488 } // wl_spy_gather
3489 /*============================================================================*/
3490 
3491 
3492 
3493 
3494 /*******************************************************************************
3495  *	wl_wext_event_freq()
3496  *******************************************************************************
3497  *
3498  *  DESCRIPTION:
3499  *
3500  *      This function is used to send an event that the channel/freq
3501  *      configuration for a specific device has changed.
3502  *
3503  *
3504  *  PARAMETERS:
3505  *
3506  *      dev - the network device for which this event is to be issued
3507  *
3508  *  RETURNS:
3509  *
3510  *      N/A
3511  *
3512  ******************************************************************************/
wl_wext_event_freq(struct net_device * dev)3513 void wl_wext_event_freq( struct net_device *dev )
3514 {
3515 #if WIRELESS_EXT > 13
3516 	union iwreq_data wrqu;
3517 	struct wl_private *lp = wl_priv(dev);
3518 	/*------------------------------------------------------------------------*/
3519 
3520 
3521 	memset( &wrqu, 0, sizeof( wrqu ));
3522 
3523 	wrqu.freq.m = lp->Channel;
3524 	wrqu.freq.e = 0;
3525 
3526 	wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3527 #endif /* WIRELESS_EXT > 13 */
3528 
3529 	return;
3530 } // wl_wext_event_freq
3531 /*============================================================================*/
3532 
3533 
3534 
3535 
3536 /*******************************************************************************
3537  *	wl_wext_event_mode()
3538  *******************************************************************************
3539  *
3540  *  DESCRIPTION:
3541  *
3542  *      This function is used to send an event that the mode of operation
3543  *      for a specific device has changed.
3544  *
3545  *
3546  *  PARAMETERS:
3547  *
3548  *      dev - the network device for which this event is to be issued
3549  *
3550  *  RETURNS:
3551  *
3552  *      N/A
3553  *
3554  ******************************************************************************/
wl_wext_event_mode(struct net_device * dev)3555 void wl_wext_event_mode( struct net_device *dev )
3556 {
3557 #if WIRELESS_EXT > 13
3558 	union iwreq_data wrqu;
3559 	struct wl_private *lp = wl_priv(dev);
3560 	/*------------------------------------------------------------------------*/
3561 
3562 
3563 	memset( &wrqu, 0, sizeof( wrqu ));
3564 
3565 	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
3566 		wrqu.mode = IW_MODE_INFRA;
3567 	} else {
3568 		wrqu.mode = IW_MODE_MASTER;
3569 	}
3570 
3571 	wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3572 #endif /* WIRELESS_EXT > 13 */
3573 
3574 	return;
3575 } // wl_wext_event_mode
3576 /*============================================================================*/
3577 
3578 
3579 
3580 
3581 /*******************************************************************************
3582  *	wl_wext_event_essid()
3583  *******************************************************************************
3584  *
3585  *  DESCRIPTION:
3586  *
3587  *      This function is used to send an event that the ESSID configuration for
3588  *      a specific device has changed.
3589  *
3590  *
3591  *  PARAMETERS:
3592  *
3593  *      dev - the network device for which this event is to be issued
3594  *
3595  *  RETURNS:
3596  *
3597  *      N/A
3598  *
3599  ******************************************************************************/
wl_wext_event_essid(struct net_device * dev)3600 void wl_wext_event_essid( struct net_device *dev )
3601 {
3602 #if WIRELESS_EXT > 13
3603 	union iwreq_data wrqu;
3604 	struct wl_private *lp = wl_priv(dev);
3605 	/*------------------------------------------------------------------------*/
3606 
3607 
3608 	memset( &wrqu, 0, sizeof( wrqu ));
3609 
3610 	/* Fill out the buffer. Note that the buffer doesn't actually contain the
3611 	   ESSID, but a pointer to the contents. In addition, the 'extra' field of
3612 	   the call to wireless_send_event() must also point to where the ESSID
3613 	   lives */
3614 	wrqu.essid.length  = strlen( lp->NetworkName );
3615 	wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3616 	wrqu.essid.flags   = 1;
3617 
3618 	wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3619 #endif /* WIRELESS_EXT > 13 */
3620 
3621 	return;
3622 } // wl_wext_event_essid
3623 /*============================================================================*/
3624 
3625 
3626 
3627 
3628 /*******************************************************************************
3629  *	wl_wext_event_encode()
3630  *******************************************************************************
3631  *
3632  *  DESCRIPTION:
3633  *
3634  *      This function is used to send an event that the encryption configuration
3635  *      for a specific device has changed.
3636  *
3637  *
3638  *  PARAMETERS:
3639  *
3640  *      dev - the network device for which this event is to be issued
3641  *
3642  *  RETURNS:
3643  *
3644  *      N/A
3645  *
3646  ******************************************************************************/
wl_wext_event_encode(struct net_device * dev)3647 void wl_wext_event_encode( struct net_device *dev )
3648 {
3649 #if WIRELESS_EXT > 13
3650 	union iwreq_data wrqu;
3651 	struct wl_private *lp = wl_priv(dev);
3652 	int index = 0;
3653 	/*------------------------------------------------------------------------*/
3654 
3655 
3656 	memset( &wrqu, 0, sizeof( wrqu ));
3657 
3658 	if( lp->EnableEncryption == 0 ) {
3659 		wrqu.encoding.flags = IW_ENCODE_DISABLED;
3660 	} else {
3661 		wrqu.encoding.flags |= lp->TransmitKeyID;
3662 
3663 		index = lp->TransmitKeyID - 1;
3664 
3665 		/* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3666 		   if we're in AP mode */
3667 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3668 		//;?should we restore this to allow smaller memory footprint
3669 
3670 		if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
3671 			if( lp->ExcludeUnencrypted ) {
3672 				wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3673 			} else {
3674 				wrqu.encoding.flags |= IW_ENCODE_OPEN;
3675 			}
3676 		}
3677 
3678 #endif  // HCF_TYPE_AP
3679 
3680 		/* Only provide the key if permissions allow */
3681 		if( capable( CAP_NET_ADMIN )) {
3682 			wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3683 			wrqu.encoding.length  = lp->DefaultKeys.key[index].len;
3684 		} else {
3685 			wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3686 		}
3687 	}
3688 
3689 	wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3690 						 lp->DefaultKeys.key[index].key );
3691 #endif /* WIRELESS_EXT > 13 */
3692 
3693 	return;
3694 } // wl_wext_event_encode
3695 /*============================================================================*/
3696 
3697 
3698 
3699 
3700 /*******************************************************************************
3701  *	wl_wext_event_ap()
3702  *******************************************************************************
3703  *
3704  *  DESCRIPTION:
3705  *
3706  *      This function is used to send an event that the device has been
3707  *      associated to a new AP.
3708  *
3709  *
3710  *  PARAMETERS:
3711  *
3712  *      dev - the network device for which this event is to be issued
3713  *
3714  *  RETURNS:
3715  *
3716  *      N/A
3717  *
3718  ******************************************************************************/
wl_wext_event_ap(struct net_device * dev)3719 void wl_wext_event_ap( struct net_device *dev )
3720 {
3721 #if WIRELESS_EXT > 13
3722 	union iwreq_data wrqu;
3723 	struct wl_private *lp = wl_priv(dev);
3724 	int status;
3725 	/*------------------------------------------------------------------------*/
3726 
3727 
3728 	/* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3729 	   this event BEFORE sending the association event, as there are timing
3730 	   issues with the hostap supplicant. The supplicant will attempt to process
3731 	   an EAPOL-Key frame from an AP before receiving this information, which
3732 	   is required properly process the said frame. */
3733 	wl_wext_event_assoc_ie( dev );
3734 
3735 	/* Get the BSSID */
3736 	lp->ltvRecord.typ = CFG_CUR_BSSID;
3737 	lp->ltvRecord.len = 4;
3738 
3739 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3740 	if( status == HCF_SUCCESS ) {
3741 		memset( &wrqu, 0, sizeof( wrqu ));
3742 
3743 		memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3744 
3745 		wrqu.addr.sa_family = ARPHRD_ETHER;
3746 
3747 		wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3748 	}
3749 
3750 #endif /* WIRELESS_EXT > 13 */
3751 
3752 	return;
3753 } // wl_wext_event_ap
3754 /*============================================================================*/
3755 
3756 
3757 
3758 /*******************************************************************************
3759  *	wl_wext_event_scan_complete()
3760  *******************************************************************************
3761  *
3762  *  DESCRIPTION:
3763  *
3764  *      This function is used to send an event that a request for a network scan
3765  *      has completed.
3766  *
3767  *
3768  *  PARAMETERS:
3769  *
3770  *      dev - the network device for which this event is to be issued
3771  *
3772  *  RETURNS:
3773  *
3774  *      N/A
3775  *
3776  ******************************************************************************/
wl_wext_event_scan_complete(struct net_device * dev)3777 void wl_wext_event_scan_complete( struct net_device *dev )
3778 {
3779 #if WIRELESS_EXT > 13
3780 	union iwreq_data wrqu;
3781 	/*------------------------------------------------------------------------*/
3782 
3783 
3784 	memset( &wrqu, 0, sizeof( wrqu ));
3785 
3786 	wrqu.addr.sa_family = ARPHRD_ETHER;
3787 	wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3788 #endif /* WIRELESS_EXT > 13 */
3789 
3790 	return;
3791 } // wl_wext_event_scan_complete
3792 /*============================================================================*/
3793 
3794 
3795 
3796 
3797 /*******************************************************************************
3798  *	wl_wext_event_new_sta()
3799  *******************************************************************************
3800  *
3801  *  DESCRIPTION:
3802  *
3803  *      This function is used to send an event that an AP has registered a new
3804  *      station.
3805  *
3806  *
3807  *  PARAMETERS:
3808  *
3809  *      dev - the network device for which this event is to be issued
3810  *
3811  *  RETURNS:
3812  *
3813  *      N/A
3814  *
3815  ******************************************************************************/
wl_wext_event_new_sta(struct net_device * dev)3816 void wl_wext_event_new_sta( struct net_device *dev )
3817 {
3818 #if WIRELESS_EXT > 14
3819 	union iwreq_data wrqu;
3820 	/*------------------------------------------------------------------------*/
3821 
3822 
3823 	memset( &wrqu, 0, sizeof( wrqu ));
3824 
3825 	/* Send the station's mac address here */
3826 	memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3827 	wrqu.addr.sa_family = ARPHRD_ETHER;
3828 	wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3829 #endif /* WIRELESS_EXT > 14 */
3830 
3831 	return;
3832 } // wl_wext_event_new_sta
3833 /*============================================================================*/
3834 
3835 
3836 
3837 
3838 /*******************************************************************************
3839  *	wl_wext_event_expired_sta()
3840  *******************************************************************************
3841  *
3842  *  DESCRIPTION:
3843  *
3844  *      This function is used to send an event that an AP has deregistered a
3845  *      station.
3846  *
3847  *
3848  *  PARAMETERS:
3849  *
3850  *      dev - the network device for which this event is to be issued
3851  *
3852  *  RETURNS:
3853  *
3854  *      N/A
3855  *
3856  ******************************************************************************/
wl_wext_event_expired_sta(struct net_device * dev)3857 void wl_wext_event_expired_sta( struct net_device *dev )
3858 {
3859 #if WIRELESS_EXT > 14
3860 	union iwreq_data wrqu;
3861 	/*------------------------------------------------------------------------*/
3862 
3863 
3864 	memset( &wrqu, 0, sizeof( wrqu ));
3865 
3866 	memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3867 	wrqu.addr.sa_family = ARPHRD_ETHER;
3868 	wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3869 #endif /* WIRELESS_EXT > 14 */
3870 
3871 	return;
3872 } // wl_wext_event_expired_sta
3873 /*============================================================================*/
3874 
3875 
3876 
3877 
3878 /*******************************************************************************
3879  *	wl_wext_event_mic_failed()
3880  *******************************************************************************
3881  *
3882  *  DESCRIPTION:
3883  *
3884  *      This function is used to send an event that MIC calculations failed.
3885  *
3886  *
3887  *  PARAMETERS:
3888  *
3889  *      dev - the network device for which this event is to be issued
3890  *
3891  *  RETURNS:
3892  *
3893  *      N/A
3894  *
3895  ******************************************************************************/
wl_wext_event_mic_failed(struct net_device * dev)3896 void wl_wext_event_mic_failed( struct net_device *dev )
3897 {
3898 #if WIRELESS_EXT > 14
3899 	char               msg[512];
3900 	union iwreq_data   wrqu;
3901 	struct wl_private *lp = wl_priv(dev);
3902 	int                key_idx;
3903 	char              *addr1;
3904 	char              *addr2;
3905 	WVLAN_RX_WMP_HDR  *hdr;
3906 	/*------------------------------------------------------------------------*/
3907 
3908 
3909 	key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3910 	key_idx &= 0x03;
3911 
3912 	/* Cast the lookahead buffer into a RFS format */
3913 	hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3914 
3915 	/* Cast the addresses to byte buffers, as in the above RFS they are word
3916 	   length */
3917 	addr1 = (char *)hdr->address1;
3918 	addr2 = (char *)hdr->address2;
3919 
3920 	DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3921 			   hdr->status );
3922 
3923 	memset( &wrqu, 0, sizeof( wrqu ));
3924 	memset( msg, 0, sizeof( msg ));
3925 
3926 
3927 	/* Because MIC failures are not part of the Wireless Extensions yet, they
3928 	   must be passed as a string using an IWEVCUSTOM event. In order for the
3929 	   event to be effective, the string format must be known by both the
3930 	   driver and the supplicant. The following is the string format used by the
3931 	   hostap project's WPA supplicant, and will be used here until the Wireless
3932 	   Extensions interface adds this support:
3933 
3934 	   MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
3935    */
3936 
3937 	/* NOTE: Format of MAC address (using colons to separate bytes) may cause
3938 			 a problem in future versions of the supplicant, if they ever
3939 			 actually parse these parameters */
3940 #if DBG
3941 	sprintf(msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast "
3942 			"addr=%pM)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
3943 			addr2);
3944 #endif
3945 	wrqu.data.length = strlen( msg );
3946 	wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
3947 #endif /* WIRELESS_EXT > 14 */
3948 
3949 	return;
3950 } // wl_wext_event_mic_failed
3951 /*============================================================================*/
3952 
3953 
3954 
3955 
3956 /*******************************************************************************
3957  *	wl_wext_event_assoc_ie()
3958  *******************************************************************************
3959  *
3960  *  DESCRIPTION:
3961  *
3962  *      This function is used to send an event containing the WPA-IE generated
3963  *      by the firmware in an association request.
3964  *
3965  *
3966  *  PARAMETERS:
3967  *
3968  *      dev - the network device for which this event is to be issued
3969  *
3970  *  RETURNS:
3971  *
3972  *      N/A
3973  *
3974  ******************************************************************************/
wl_wext_event_assoc_ie(struct net_device * dev)3975 void wl_wext_event_assoc_ie( struct net_device *dev )
3976 {
3977 #if WIRELESS_EXT > 14
3978 	char               msg[512];
3979 	union iwreq_data   wrqu;
3980 	struct wl_private *lp = wl_priv(dev);
3981 	int status;
3982 	PROBE_RESP         data;
3983 	hcf_16             length;
3984 	hcf_8              *wpa_ie;
3985 	/*------------------------------------------------------------------------*/
3986 
3987 
3988 	memset( &wrqu, 0, sizeof( wrqu ));
3989 	memset( msg, 0, sizeof( msg ));
3990 
3991 	/* Retrieve the Association Request IE */
3992 	lp->ltvRecord.len = 45;
3993 	lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3994 
3995 	status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3996 	if( status == HCF_SUCCESS )
3997 	{
3998 		length = 0;
3999 		memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
4000 		wpa_ie = wl_parse_wpa_ie( &data, &length );
4001 
4002 		/* Because this event (Association WPA-IE) is not part of the Wireless
4003 		Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
4004 		In order for the event to be effective, the string format must be known
4005 		by both the driver and the supplicant. The following is the string format
4006 		used by the hostap project's WPA supplicant, and will be used here until
4007 		the Wireless Extensions interface adds this support:
4008 
4009 		ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
4010 		*/
4011 
4012 		if( length != 0 )
4013 		{
4014 			sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
4015 			wrqu.data.length = strlen( msg );
4016 			wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
4017 		}
4018 	}
4019 #endif /* WIRELESS_EXT > 14 */
4020 
4021 	return;
4022 }  // wl_wext_event_assoc_ie
4023 /*============================================================================*/
4024 /* Structures to export the Wireless Handlers */
4025 
4026 static const iw_handler wl_handler[] =
4027 {
4028                 (iw_handler) wireless_commit,           /* SIOCSIWCOMMIT */
4029                 (iw_handler) wireless_get_protocol,     /* SIOCGIWNAME */
4030                 (iw_handler) NULL,                      /* SIOCSIWNWID */
4031                 (iw_handler) NULL,                      /* SIOCGIWNWID */
4032                 (iw_handler) wireless_set_frequency,    /* SIOCSIWFREQ */
4033                 (iw_handler) wireless_get_frequency,    /* SIOCGIWFREQ */
4034                 (iw_handler) wireless_set_porttype,     /* SIOCSIWMODE */
4035                 (iw_handler) wireless_get_porttype,     /* SIOCGIWMODE */
4036                 (iw_handler) wireless_set_sensitivity,  /* SIOCSIWSENS */
4037                 (iw_handler) wireless_get_sensitivity,  /* SIOCGIWSENS */
4038                 (iw_handler) NULL ,                     /* SIOCSIWRANGE */
4039                 (iw_handler) wireless_get_range,        /* SIOCGIWRANGE */
4040                 (iw_handler) NULL ,                     /* SIOCSIWPRIV */
4041                 (iw_handler) NULL /* kernel code */,    /* SIOCGIWPRIV */
4042                 (iw_handler) NULL ,                     /* SIOCSIWSTATS */
4043                 (iw_handler) NULL /* kernel code */,    /* SIOCGIWSTATS */
4044                 iw_handler_set_spy,                     /* SIOCSIWSPY */
4045                 iw_handler_get_spy,                     /* SIOCGIWSPY */
4046                 NULL,                                   /* SIOCSIWTHRSPY */
4047                 NULL,                                   /* SIOCGIWTHRSPY */
4048                 (iw_handler) NULL,                      /* SIOCSIWAP */
4049 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4050                 (iw_handler) wireless_get_bssid,        /* SIOCGIWAP */
4051 #else
4052                 (iw_handler) NULL,                      /* SIOCGIWAP */
4053 #endif
4054                 (iw_handler) NULL,                      /* SIOCSIWMLME */
4055                 (iw_handler) wireless_get_ap_list,      /* SIOCGIWAPLIST */
4056                 (iw_handler) wireless_set_scan,         /* SIOCSIWSCAN */
4057                 (iw_handler) wireless_get_scan,         /* SIOCGIWSCAN */
4058                 (iw_handler) wireless_set_essid,        /* SIOCSIWESSID */
4059                 (iw_handler) wireless_get_essid,        /* SIOCGIWESSID */
4060                 (iw_handler) wireless_set_nickname,     /* SIOCSIWNICKN */
4061                 (iw_handler) wireless_get_nickname,     /* SIOCGIWNICKN */
4062                 (iw_handler) NULL,                      /* -- hole -- */
4063                 (iw_handler) NULL,                      /* -- hole -- */
4064                 (iw_handler) wireless_set_rate,         /* SIOCSIWRATE */
4065                 (iw_handler) wireless_get_rate,         /* SIOCGIWRATE */
4066                 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
4067                 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
4068                 (iw_handler) NULL,                      /* SIOCSIWFRAG */
4069                 (iw_handler) NULL,                      /* SIOCGIWFRAG */
4070                 (iw_handler) NULL,                      /* SIOCSIWTXPOW */
4071                 (iw_handler) wireless_get_tx_power,     /* SIOCGIWTXPOW */
4072                 (iw_handler) NULL,                      /* SIOCSIWRETRY */
4073                 (iw_handler) NULL,                      /* SIOCGIWRETRY */
4074                 (iw_handler) wireless_set_encode,       /* SIOCSIWENCODE */
4075                 (iw_handler) wireless_get_encode,       /* SIOCGIWENCODE */
4076                 (iw_handler) wireless_set_power,        /* SIOCSIWPOWER */
4077                 (iw_handler) wireless_get_power,        /* SIOCGIWPOWER */
4078                 (iw_handler) NULL,                      /* -- hole -- */
4079                 (iw_handler) NULL,                      /* -- hole -- */
4080                 (iw_handler) wireless_get_genie,        /* SIOCSIWGENIE */
4081                 (iw_handler) NULL,                      /* SIOCGIWGENIE */
4082                 (iw_handler) wireless_set_auth,         /* SIOCSIWAUTH */
4083                 (iw_handler) NULL,                      /* SIOCGIWAUTH */
4084                 (iw_handler) wireless_set_encodeext,    /* SIOCSIWENCODEEXT */
4085                 (iw_handler) NULL,                      /* SIOCGIWENCODEEXT */
4086                 (iw_handler) NULL,                      /* SIOCSIWPMKSA */
4087                 (iw_handler) NULL,                      /* -- hole -- */
4088 };
4089 
4090 static const iw_handler wl_private_handler[] =
4091 {                                                       /* SIOCIWFIRSTPRIV + */
4092                 wvlan_set_netname,                      /* 0: SIOCSIWNETNAME */
4093                 wvlan_get_netname,                      /* 1: SIOCGIWNETNAME */
4094                 wvlan_set_station_nickname,             /* 2: SIOCSIWSTANAME */
4095                 wvlan_get_station_nickname,             /* 3: SIOCGIWSTANAME */
4096 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4097                 wvlan_set_porttype,                     /* 4: SIOCSIWPORTTYPE */
4098                 wvlan_get_porttype,                     /* 5: SIOCGIWPORTTYPE */
4099 #endif
4100 };
4101 
4102 struct iw_priv_args wl_priv_args[] = {
4103         {SIOCSIWNETNAME,    IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
4104         {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN,    "gnetwork_name" },
4105         {SIOCSIWSTANAME,    IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
4106         {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN,    "gstation_name" },
4107 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
4108         {SIOCSIWPORTTYPE,    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
4109         {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,    "gport_type" },
4110 #endif
4111 };
4112 
4113 const struct iw_handler_def wl_iw_handler_def =
4114 {
4115         .num_private        = sizeof(wl_private_handler) / sizeof(iw_handler),
4116         .private            = (iw_handler *) wl_private_handler,
4117         .private_args       = (struct iw_priv_args *) wl_priv_args,
4118         .num_private_args   = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
4119         .num_standard       = sizeof(wl_handler) / sizeof(iw_handler),
4120         .standard           = (iw_handler *) wl_handler,
4121         .get_wireless_stats = wl_get_wireless_stats,
4122 };
4123 
4124 #endif // WIRELESS_EXT
4125