2007-02-10 12:25:27 -02:00
/**
* This file contains ioctl functions
*/
# include <linux/ctype.h>
# include <linux/delay.h>
# include <linux/if.h>
# include <linux/if_arp.h>
# include <linux/wireless.h>
# include <linux/bitops.h>
2008-09-24 18:13:14 -04:00
# include <net/lib80211.h>
2007-02-10 12:25:27 -02:00
# include <net/iw_handler.h>
# include "host.h"
# include "radiotap.h"
# include "decl.h"
# include "defs.h"
# include "dev.h"
# include "wext.h"
2008-04-02 16:27:42 +02:00
# include "scan.h"
2007-02-10 12:25:27 -02:00
# include "assoc.h"
2007-12-11 15:50:59 -05:00
# include "cmd.h"
2007-02-10 12:25:27 -02:00
2007-11-23 15:43:44 +01:00
static inline void lbs_postpone_association_work ( struct lbs_private * priv )
2007-10-26 10:12:14 +02:00
{
2007-12-08 20:04:36 +00:00
if ( priv - > surpriseremoved )
2007-10-26 10:12:14 +02:00
return ;
cancel_delayed_work ( & priv - > assoc_work ) ;
queue_delayed_work ( priv - > work_thread , & priv - > assoc_work , HZ / 2 ) ;
}
2008-09-11 15:32:50 -07:00
static inline void lbs_do_association_work ( struct lbs_private * priv )
{
if ( priv - > surpriseremoved )
return ;
cancel_delayed_work ( & priv - > assoc_work ) ;
queue_delayed_work ( priv - > work_thread , & priv - > assoc_work , 0 ) ;
}
2007-11-23 15:43:44 +01:00
static inline void lbs_cancel_association_work ( struct lbs_private * priv )
2007-10-26 10:12:14 +02:00
{
cancel_delayed_work ( & priv - > assoc_work ) ;
2007-12-08 20:04:36 +00:00
kfree ( priv - > pending_assoc_req ) ;
priv - > pending_assoc_req = NULL ;
2007-10-26 10:12:14 +02:00
}
2009-10-22 15:30:56 +02:00
void lbs_send_disconnect_notification ( struct lbs_private * priv )
{
union iwreq_data wrqu ;
memset ( wrqu . ap_addr . sa_data , 0x00 , ETH_ALEN ) ;
wrqu . ap_addr . sa_family = ARPHRD_ETHER ;
wireless_send_event ( priv - > dev , SIOCGIWAP , & wrqu , NULL ) ;
}
2009-10-22 15:30:57 +02:00
static void lbs_send_iwevcustom_event ( struct lbs_private * priv , s8 * str )
2009-10-22 15:30:52 +02:00
{
union iwreq_data iwrq ;
u8 buf [ 50 ] ;
lbs_deb_enter ( LBS_DEB_WEXT ) ;
memset ( & iwrq , 0 , sizeof ( union iwreq_data ) ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
snprintf ( buf , sizeof ( buf ) - 1 , " %s " , str ) ;
iwrq . data . length = strlen ( buf ) + 1 + IW_EV_LCP_LEN ;
/* Send Event to upper layer */
lbs_deb_wext ( " event indication string %s \n " , ( char * ) buf ) ;
lbs_deb_wext ( " event indication length %d \n " , iwrq . data . length ) ;
lbs_deb_wext ( " sending wireless event IWEVCUSTOM for %s \n " , str ) ;
wireless_send_event ( priv - > dev , IWEVCUSTOM , & iwrq , buf ) ;
lbs_deb_leave ( LBS_DEB_WEXT ) ;
}
2009-10-22 15:30:57 +02:00
/**
* @ brief This function handles MIC failure event .
*
* @ param priv A pointer to struct lbs_private structure
* @ para event the event id
* @ return n / a
*/
void lbs_send_mic_failureevent ( struct lbs_private * priv , u32 event )
{
char buf [ 50 ] ;
lbs_deb_enter ( LBS_DEB_CMD ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
sprintf ( buf , " %s " , " MLME-MICHAELMICFAILURE.indication " ) ;
if ( event = = MACREG_INT_CODE_MIC_ERR_UNICAST )
strcat ( buf , " unicast " ) ;
else
strcat ( buf , " multicast " ) ;
lbs_send_iwevcustom_event ( priv , buf ) ;
lbs_deb_leave ( LBS_DEB_CMD ) ;
}
2007-02-10 12:25:27 -02:00
/**
* @ brief Find the channel frequency power info with specific channel
*
2007-12-08 20:04:36 +00:00
* @ param priv A pointer to struct lbs_private structure
2007-02-10 12:25:27 -02:00
* @ param band it can be BAND_A , BAND_G or BAND_B
* @ param channel the channel for looking
* @ return A pointer to struct chan_freq_power structure or NULL if not find .
*/
2007-11-23 15:43:44 +01:00
struct chan_freq_power * lbs_find_cfp_by_band_and_channel (
2007-12-08 20:04:36 +00:00
struct lbs_private * priv ,
2007-11-23 15:43:44 +01:00
u8 band ,
u16 channel )
2007-02-10 12:25:27 -02:00
{
struct chan_freq_power * cfp = NULL ;
struct region_channel * rc ;
int i , j ;
2007-12-08 20:04:36 +00:00
for ( j = 0 ; ! cfp & & ( j < ARRAY_SIZE ( priv - > region_channel ) ) ; j + + ) {
rc = & priv - > region_channel [ j ] ;
2007-02-10 12:25:27 -02:00
if ( ! rc - > valid | | ! rc - > CFP )
continue ;
if ( rc - > band ! = band )
continue ;
for ( i = 0 ; i < rc - > nrcfp ; i + + ) {
if ( rc - > CFP [ i ] . channel = = channel ) {
cfp = & rc - > CFP [ i ] ;
break ;
}
}
}
if ( ! cfp & & channel )
2007-11-15 18:05:47 -05:00
lbs_deb_wext ( " lbs_find_cfp_by_band_and_channel: can't find "
2007-05-25 11:27:16 -04:00
" cfp by band %d / channel %d \n " , band , channel ) ;
2007-02-10 12:25:27 -02:00
return cfp ;
}
/**
* @ brief Find the channel frequency power info with specific frequency
*
2007-12-08 20:04:36 +00:00
* @ param priv A pointer to struct lbs_private structure
2007-02-10 12:25:27 -02:00
* @ param band it can be BAND_A , BAND_G or BAND_B
* @ param freq the frequency for looking
* @ return A pointer to struct chan_freq_power structure or NULL if not find .
*/
2007-11-23 15:43:44 +01:00
static struct chan_freq_power * find_cfp_by_band_and_freq (
2007-12-08 20:04:36 +00:00
struct lbs_private * priv ,
2007-11-23 15:43:44 +01:00
u8 band ,
u32 freq )
2007-02-10 12:25:27 -02:00
{
struct chan_freq_power * cfp = NULL ;
struct region_channel * rc ;
int i , j ;
2007-12-08 20:04:36 +00:00
for ( j = 0 ; ! cfp & & ( j < ARRAY_SIZE ( priv - > region_channel ) ) ; j + + ) {
rc = & priv - > region_channel [ j ] ;
2007-02-10 12:25:27 -02:00
if ( ! rc - > valid | | ! rc - > CFP )
continue ;
if ( rc - > band ! = band )
continue ;
for ( i = 0 ; i < rc - > nrcfp ; i + + ) {
if ( rc - > CFP [ i ] . freq = = freq ) {
cfp = & rc - > CFP [ i ] ;
break ;
}
}
}
if ( ! cfp & & freq )
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " find_cfp_by_band_and_freql: can't find cfp by "
" band %d / freq %d \n " , band , freq ) ;
2007-02-10 12:25:27 -02:00
return cfp ;
}
/**
2007-08-02 11:40:45 -04:00
* @ brief Copy active data rates based on adapter mode and status
2007-02-10 12:25:27 -02:00
*
2007-12-08 20:04:36 +00:00
* @ param priv A pointer to struct lbs_private structure
2007-02-10 12:25:27 -02:00
* @ param rate The buf to return the active rates
*/
2007-12-08 20:04:36 +00:00
static void copy_active_data_rates ( struct lbs_private * priv , u8 * rates )
2007-02-10 12:25:27 -02:00
{
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( ( priv - > connect_status ! = LBS_CONNECTED ) & &
2009-12-02 15:26:01 +01:00
! lbs_mesh_connected ( priv ) )
2007-11-15 18:05:47 -05:00
memcpy ( rates , lbs_bg_rates , MAX_RATES ) ;
2007-08-02 11:40:45 -04:00
else
2007-12-08 20:04:36 +00:00
memcpy ( rates , priv - > curbssparams . rates , MAX_RATES ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:40:45 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_get_name ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
char * cwrq , char * extra )
{
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 13:16:30 -04:00
/* We could add support for 802.11n here as needed. Jean II */
snprintf ( cwrq , IFNAMSIZ , " IEEE 802.11b/g " ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_freq ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_freq * fwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct chan_freq_power * cfp ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
cfp = lbs_find_cfp_by_band_and_channel ( priv , 0 ,
2009-10-22 15:30:50 +02:00
priv - > channel ) ;
2007-02-10 12:25:27 -02:00
if ( ! cfp ) {
2009-10-22 15:30:50 +02:00
if ( priv - > channel )
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " invalid channel %d \n " ,
2009-10-22 15:30:50 +02:00
priv - > channel ) ;
2007-02-10 12:25:27 -02:00
return - EINVAL ;
}
fwrq - > m = ( long ) cfp - > freq * 100000 ;
fwrq - > e = 1 ;
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " freq %u \n " , fwrq - > m ) ;
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_wap ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct sockaddr * awrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( priv - > connect_status = = LBS_CONNECTED ) {
memcpy ( awrq - > sa_data , priv - > curbssparams . bssid , ETH_ALEN ) ;
2007-02-10 12:25:27 -02:00
} else {
memset ( awrq - > sa_data , 0 , ETH_ALEN ) ;
}
awrq - > sa_family = ARPHRD_ETHER ;
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_set_nick ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_point * dwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
/*
* Check the size of the string
*/
if ( dwrq - > length > 16 ) {
return - E2BIG ;
}
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
memset ( priv - > nodename , 0 , sizeof ( priv - > nodename ) ) ;
memcpy ( priv - > nodename , extra , dwrq - > length ) ;
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_nick ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_point * dwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
dwrq - > length = strlen ( priv - > nodename ) ;
memcpy ( extra , priv - > nodename , dwrq - > length ) ;
2007-10-09 15:04:14 +02:00
extra [ dwrq - > length ] = ' \0 ' ;
2007-02-10 12:25:27 -02:00
2007-10-09 15:04:14 +02:00
dwrq - > flags = 1 ; /* active */
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2009-12-02 15:26:02 +01:00
# ifdef CONFIG_LIBERTAS_MESH
2007-05-25 23:08:34 -04:00
static int mesh_get_nick ( struct net_device * dev , struct iw_request_info * info ,
struct iw_point * dwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-05-25 23:08:34 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
/* Use nickname to indicate that mesh is on */
2009-12-02 15:26:01 +01:00
if ( lbs_mesh_connected ( priv ) ) {
2007-05-25 23:08:34 -04:00
strncpy ( extra , " Mesh " , 12 ) ;
extra [ 12 ] = ' \0 ' ;
2007-08-02 13:16:30 -04:00
dwrq - > length = strlen ( extra ) ;
2007-05-25 23:08:34 -04:00
}
else {
extra [ 0 ] = ' \0 ' ;
2007-08-02 13:16:30 -04:00
dwrq - > length = 0 ;
2007-05-25 23:08:34 -04:00
}
lbs_deb_leave ( LBS_DEB_WEXT ) ;
return 0 ;
}
2009-12-02 15:26:02 +01:00
# endif
2007-10-09 15:04:14 +02:00
2007-11-15 18:05:47 -05:00
static int lbs_set_rts ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
int ret = 0 ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-09-10 12:49:00 -04:00
u32 val = vwrq - > value ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
if ( vwrq - > disabled )
val = MRVDRV_RTS_MAX_VALUE ;
2007-02-10 12:25:27 -02:00
2008-09-15 17:25:54 -04:00
if ( val > MRVDRV_RTS_MAX_VALUE ) /* min rts value is 0 */
2008-09-10 12:49:00 -04:00
return - EINVAL ;
ret = lbs_set_snmp_mib ( priv , SNMP_MIB_OID_RTS_THRESHOLD , ( u16 ) val ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_rts ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-09-10 12:49:00 -04:00
int ret = 0 ;
u16 val = 0 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
ret = lbs_get_snmp_mib ( priv , SNMP_MIB_OID_RTS_THRESHOLD , & val ) ;
2007-05-25 11:27:16 -04:00
if ( ret )
goto out ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
vwrq - > value = val ;
2008-09-15 17:25:54 -04:00
vwrq - > disabled = val > MRVDRV_RTS_MAX_VALUE ; /* min rts value is 0 */
2007-02-10 12:25:27 -02:00
vwrq - > fixed = 1 ;
2007-05-25 11:27:16 -04:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_set_frag ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-09-10 12:49:00 -04:00
int ret = 0 ;
u32 val = vwrq - > value ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
if ( vwrq - > disabled )
val = MRVDRV_FRAG_MAX_VALUE ;
if ( val < MRVDRV_FRAG_MIN_VALUE | | val > MRVDRV_FRAG_MAX_VALUE )
return - EINVAL ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
ret = lbs_set_snmp_mib ( priv , SNMP_MIB_OID_FRAG_THRESHOLD , ( u16 ) val ) ;
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_frag ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-09-10 12:49:00 -04:00
int ret = 0 ;
u16 val = 0 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
ret = lbs_get_snmp_mib ( priv , SNMP_MIB_OID_FRAG_THRESHOLD , & val ) ;
2007-05-25 11:27:16 -04:00
if ( ret )
goto out ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
vwrq - > value = val ;
vwrq - > disabled = ( ( val < MRVDRV_FRAG_MIN_VALUE )
| | ( val > MRVDRV_FRAG_MAX_VALUE ) ) ;
2007-02-10 12:25:27 -02:00
vwrq - > fixed = 1 ;
2007-05-25 11:27:16 -04:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_mode ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info , u32 * uwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
* uwrq = priv - > mode ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2009-12-02 15:26:02 +01:00
# ifdef CONFIG_LIBERTAS_MESH
2007-05-25 23:08:34 -04:00
static int mesh_wlan_get_mode ( struct net_device * dev ,
struct iw_request_info * info , u32 * uwrq ,
char * extra )
{
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2008-09-10 12:49:00 -04:00
* uwrq = IW_MODE_REPEAT ;
2007-05-25 23:08:34 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
return 0 ;
}
2009-12-02 15:26:02 +01:00
# endif
2007-05-25 23:08:34 -04:00
2007-11-15 18:05:47 -05:00
static int lbs_get_txpow ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-08-19 15:15:35 -04:00
s16 curlevel = 0 ;
2008-08-21 17:51:07 -04:00
int ret = 0 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-08-21 17:51:07 -04:00
if ( ! priv - > radio_on ) {
lbs_deb_wext ( " tx power off \n " ) ;
vwrq - > value = 0 ;
vwrq - > disabled = 1 ;
goto out ;
}
2008-08-19 15:15:35 -04:00
ret = lbs_get_tx_power ( priv , & curlevel , NULL , NULL ) ;
2007-05-25 11:27:16 -04:00
if ( ret )
goto out ;
2007-02-10 12:25:27 -02:00
2008-08-19 15:15:35 -04:00
lbs_deb_wext ( " tx power level %d dbm \n " , curlevel ) ;
priv - > txpower_cur = curlevel ;
2008-08-21 17:51:07 -04:00
2008-08-19 15:15:35 -04:00
vwrq - > value = curlevel ;
2007-02-10 12:25:27 -02:00
vwrq - > fixed = 1 ;
2008-08-21 17:51:07 -04:00
vwrq - > disabled = 0 ;
vwrq - > flags = IW_TXPOW_DBM ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_set_retry ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-09-10 12:49:00 -04:00
int ret = 0 ;
u16 slimit = 0 , llimit = 0 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
if ( ( vwrq - > flags & IW_RETRY_TYPE ) ! = IW_RETRY_LIMIT )
return - EOPNOTSUPP ;
/* The MAC has a 4-bit Total_Tx_Count register
Total_Tx_Count = 1 + Tx_Retry_Count */
2007-02-10 12:25:27 -02:00
# define TX_RETRY_MIN 0
# define TX_RETRY_MAX 14
2008-09-10 12:49:00 -04:00
if ( vwrq - > value < TX_RETRY_MIN | | vwrq - > value > TX_RETRY_MAX )
return - EINVAL ;
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
/* Add 1 to convert retry count to try count */
if ( vwrq - > flags & IW_RETRY_SHORT )
slimit = ( u16 ) ( vwrq - > value + 1 ) ;
else if ( vwrq - > flags & IW_RETRY_LONG )
llimit = ( u16 ) ( vwrq - > value + 1 ) ;
else
slimit = llimit = ( u16 ) ( vwrq - > value + 1 ) ; /* set both */
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
if ( llimit ) {
ret = lbs_set_snmp_mib ( priv , SNMP_MIB_OID_LONG_RETRY_LIMIT ,
llimit ) ;
if ( ret )
goto out ;
}
2007-02-10 12:25:27 -02:00
2008-09-10 12:49:00 -04:00
if ( slimit ) {
/* txretrycount follows the short retry limit */
priv - > txretrycount = slimit ;
ret = lbs_set_snmp_mib ( priv , SNMP_MIB_OID_SHORT_RETRY_LIMIT ,
slimit ) ;
2007-05-25 11:27:16 -04:00
if ( ret )
goto out ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 11:27:16 -04:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_get_retry ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
int ret = 0 ;
2008-09-10 12:49:00 -04:00
u16 val = 0 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
vwrq - > disabled = 0 ;
2008-09-10 12:49:00 -04:00
if ( vwrq - > flags & IW_RETRY_LONG ) {
ret = lbs_get_snmp_mib ( priv , SNMP_MIB_OID_LONG_RETRY_LIMIT , & val ) ;
if ( ret )
goto out ;
/* Subtract 1 to convert try count to retry count */
vwrq - > value = val - 1 ;
vwrq - > flags = IW_RETRY_LIMIT | IW_RETRY_LONG ;
} else {
ret = lbs_get_snmp_mib ( priv , SNMP_MIB_OID_SHORT_RETRY_LIMIT , & val ) ;
if ( ret )
goto out ;
/* txretry count follows the short retry limit */
priv - > txretrycount = val ;
2007-02-10 12:25:27 -02:00
/* Subtract 1 to convert try count to retry count */
2008-09-10 12:49:00 -04:00
vwrq - > value = val - 1 ;
vwrq - > flags = IW_RETRY_LIMIT | IW_RETRY_SHORT ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 11:27:16 -04:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
static inline void sort_channels ( struct iw_freq * freq , int num )
{
int i , j ;
struct iw_freq temp ;
for ( i = 0 ; i < num ; i + + )
for ( j = i + 1 ; j < num ; j + + )
if ( freq [ i ] . i > freq [ j ] . i ) {
temp . i = freq [ i ] . i ;
temp . m = freq [ i ] . m ;
freq [ i ] . i = freq [ j ] . i ;
freq [ i ] . m = freq [ j ] . m ;
freq [ j ] . i = temp . i ;
freq [ j ] . m = temp . m ;
}
}
/* data rate listing
MULTI_BANDS :
abg a b b / g
Infra G ( 12 ) A ( 8 ) B ( 4 ) G ( 12 )
Adhoc A + B ( 12 ) A ( 8 ) B ( 4 ) B ( 4 )
non - MULTI_BANDS :
b b / g
Infra B ( 4 ) G ( 12 )
Adhoc B ( 4 ) B ( 4 )
*/
/**
* @ brief Get Range Info
*
* @ param dev A pointer to net_device structure
* @ param info A pointer to iw_request_info structure
* @ param vwrq A pointer to iw_param structure
* @ param extra A pointer to extra data buf
* @ return 0 - - success , otherwise fail
*/
2007-11-15 18:05:47 -05:00
static int lbs_get_range ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_point * dwrq , char * extra )
{
int i , j ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct iw_range * range = ( struct iw_range * ) extra ;
struct chan_freq_power * cfp ;
2007-08-02 11:40:45 -04:00
u8 rates [ MAX_RATES + 1 ] ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
dwrq - > length = sizeof ( struct iw_range ) ;
memset ( range , 0 , sizeof ( struct iw_range ) ) ;
range - > min_nwid = 0 ;
range - > max_nwid = 0 ;
memset ( rates , 0 , sizeof ( rates ) ) ;
2007-12-08 20:04:36 +00:00
copy_active_data_rates ( priv , rates ) ;
2007-08-02 11:40:45 -04:00
range - > num_bitrates = strnlen ( rates , IW_MAX_BITRATES ) ;
for ( i = 0 ; i < range - > num_bitrates ; i + + )
range - > bitrate [ i ] = rates [ i ] * 500000 ;
2007-02-10 12:25:27 -02:00
range - > num_bitrates = i ;
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " IW_MAX_BITRATES %d, num_bitrates %d \n " , IW_MAX_BITRATES ,
2007-02-10 12:25:27 -02:00
range - > num_bitrates ) ;
range - > num_frequency = 0 ;
2008-03-05 07:05:32 +01:00
range - > scan_capa = IW_SCAN_CAPA_ESSID ;
2009-10-22 15:30:45 +02:00
for ( j = 0 ; ( range - > num_frequency < IW_MAX_FREQUENCIES )
& & ( j < ARRAY_SIZE ( priv - > region_channel ) ) ; j + + ) {
cfp = priv - > region_channel [ j ] . CFP ;
2007-02-10 12:25:27 -02:00
for ( i = 0 ; ( range - > num_frequency < IW_MAX_FREQUENCIES )
2009-10-22 15:30:45 +02:00
& & priv - > region_channel [ j ] . valid
& & cfp
& & ( i < priv - > region_channel [ j ] . nrcfp ) ; i + + ) {
range - > freq [ range - > num_frequency ] . i =
( long ) cfp - > channel ;
2007-02-10 12:25:27 -02:00
range - > freq [ range - > num_frequency ] . m =
2009-10-22 15:30:45 +02:00
( long ) cfp - > freq * 100000 ;
2007-02-10 12:25:27 -02:00
range - > freq [ range - > num_frequency ] . e = 1 ;
2009-10-22 15:30:45 +02:00
cfp + + ;
2007-02-10 12:25:27 -02:00
range - > num_frequency + + ;
}
}
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " IW_MAX_FREQUENCIES %d, num_frequency %d \n " ,
2007-02-10 12:25:27 -02:00
IW_MAX_FREQUENCIES , range - > num_frequency ) ;
range - > num_channels = range - > num_frequency ;
sort_channels ( & range - > freq [ 0 ] , range - > num_frequency ) ;
/*
* Set an indication of the max TCP throughput in bit / s that we can
* expect using this interface
*/
if ( i > 2 )
range - > throughput = 5000 * 1000 ;
else
range - > throughput = 1500 * 1000 ;
range - > min_rts = MRVDRV_RTS_MIN_VALUE ;
range - > max_rts = MRVDRV_RTS_MAX_VALUE ;
range - > min_frag = MRVDRV_FRAG_MIN_VALUE ;
range - > max_frag = MRVDRV_FRAG_MAX_VALUE ;
range - > encoding_size [ 0 ] = 5 ;
range - > encoding_size [ 1 ] = 13 ;
range - > num_encoding_sizes = 2 ;
range - > max_encoding_tokens = 4 ;
2008-03-19 14:25:18 +01:00
/*
* Right now we support only " iwconfig ethX power on|off "
*/
range - > pm_capa = IW_POWER_ON ;
2007-02-10 12:25:27 -02:00
/*
* Minimum version we recommend
*/
range - > we_version_source = 15 ;
/*
* Version we are compiled with
*/
range - > we_version_compiled = WIRELESS_EXT ;
range - > retry_capa = IW_RETRY_LIMIT ;
range - > retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX ;
range - > min_retry = TX_RETRY_MIN ;
range - > max_retry = TX_RETRY_MAX ;
/*
* Set the qual , level and noise range values
*/
range - > max_qual . qual = 100 ;
range - > max_qual . level = 0 ;
range - > max_qual . noise = 0 ;
range - > max_qual . updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM ;
range - > avg_qual . qual = 70 ;
/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
range - > avg_qual . level = 0 ;
range - > avg_qual . noise = 0 ;
range - > avg_qual . updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM ;
range - > sensitivity = 0 ;
2008-08-19 15:15:35 -04:00
/* Setup the supported power level ranges */
2007-02-10 12:25:27 -02:00
memset ( range - > txpower , 0 , sizeof ( range - > txpower ) ) ;
2008-08-19 15:15:35 -04:00
range - > txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE ;
range - > txpower [ 0 ] = priv - > txpower_min ;
range - > txpower [ 1 ] = priv - > txpower_max ;
range - > num_txpower = 2 ;
2007-02-10 12:25:27 -02:00
range - > event_capa [ 0 ] = ( IW_EVENT_CAPA_K_0 |
IW_EVENT_CAPA_MASK ( SIOCGIWAP ) |
IW_EVENT_CAPA_MASK ( SIOCGIWSCAN ) ) ;
range - > event_capa [ 1 ] = IW_EVENT_CAPA_K_1 ;
2007-12-08 20:04:36 +00:00
if ( priv - > fwcapinfo & FW_CAPINFO_WPA ) {
2007-02-10 12:25:27 -02:00
range - > enc_capa = IW_ENC_CAPA_WPA
| IW_ENC_CAPA_WPA2
| IW_ENC_CAPA_CIPHER_TKIP
| IW_ENC_CAPA_CIPHER_CCMP ;
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_set_power ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2009-09-30 20:04:38 -07:00
int ret = 0 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2009-06-16 13:20:01 -07:00
if ( ! ( priv - > fwcapinfo & FW_CAPINFO_PS ) ) {
2007-12-17 14:41:13 -05:00
if ( vwrq - > disabled )
return 0 ;
else
return - EINVAL ;
}
2007-02-10 12:25:27 -02:00
/* PS is currently supported only in Infrastructure mode
* Remove this check if it is to be supported in IBSS mode also
*/
if ( vwrq - > disabled ) {
2007-12-08 20:04:36 +00:00
priv - > psmode = LBS802_11POWERMODECAM ;
if ( priv - > psstate ! = PS_STATE_FULL_POWER ) {
2007-11-15 18:05:47 -05:00
lbs_ps_wakeup ( priv , CMD_OPTION_WAITFORRSP ) ;
2007-02-10 12:25:27 -02:00
}
return 0 ;
}
if ( ( vwrq - > flags & IW_POWER_TYPE ) = = IW_POWER_TIMEOUT ) {
2007-05-25 11:27:16 -04:00
lbs_deb_wext (
" setting power timeout is not supported \n " ) ;
2007-02-10 12:25:27 -02:00
return - EINVAL ;
} else if ( ( vwrq - > flags & IW_POWER_TYPE ) = = IW_POWER_PERIOD ) {
2009-09-30 20:04:38 -07:00
vwrq - > value = vwrq - > value / 1000 ;
if ( ! priv - > enter_deep_sleep ) {
lbs_pr_err ( " deep sleep feature is not implemented "
" for this interface driver \n " ) ;
return - EINVAL ;
}
if ( priv - > connect_status = = LBS_CONNECTED ) {
if ( ( priv - > is_auto_deep_sleep_enabled ) & &
( vwrq - > value = = - 1000 ) ) {
lbs_exit_auto_deep_sleep ( priv ) ;
return 0 ;
} else {
lbs_pr_err ( " can't use deep sleep cmd in "
" connected state \n " ) ;
return - EINVAL ;
}
}
if ( ( vwrq - > value < 0 ) & & ( vwrq - > value ! = - 1000 ) ) {
lbs_pr_err ( " unknown option \n " ) ;
return - EINVAL ;
}
if ( vwrq - > value > 0 ) {
if ( ! priv - > is_auto_deep_sleep_enabled ) {
priv - > is_activity_detected = 0 ;
priv - > auto_deep_sleep_timeout = vwrq - > value ;
lbs_enter_auto_deep_sleep ( priv ) ;
} else {
priv - > auto_deep_sleep_timeout = vwrq - > value ;
lbs_deb_debugfs ( " auto deep sleep: "
" already enabled \n " ) ;
}
return 0 ;
} else {
if ( priv - > is_auto_deep_sleep_enabled ) {
lbs_exit_auto_deep_sleep ( priv ) ;
/* Try to exit deep sleep if auto */
/*deep sleep disabled */
ret = lbs_set_deep_sleep ( priv , 0 ) ;
}
if ( vwrq - > value = = 0 )
ret = lbs_set_deep_sleep ( priv , 1 ) ;
else if ( vwrq - > value = = - 1000 )
ret = lbs_set_deep_sleep ( priv , 0 ) ;
return ret ;
}
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
if ( priv - > psmode ! = LBS802_11POWERMODECAM ) {
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-12-08 20:04:36 +00:00
priv - > psmode = LBS802_11POWERMODEMAX_PSP ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( priv - > connect_status = = LBS_CONNECTED ) {
2007-11-15 18:05:47 -05:00
lbs_ps_sleep ( priv , CMD_OPTION_WAITFORRSP ) ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2009-09-30 20:04:38 -07:00
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_power ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
vwrq - > value = 0 ;
2008-03-19 14:25:18 +01:00
vwrq - > flags = 0 ;
vwrq - > disabled = priv - > psmode = = LBS802_11POWERMODECAM
| | priv - > connect_status = = LBS_DISCONNECTED ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static struct iw_statistics * lbs_get_wireless_stats ( struct net_device * dev )
2007-02-10 12:25:27 -02:00
{
enum {
POOR = 30 ,
FAIR = 60 ,
GOOD = 80 ,
VERY_GOOD = 90 ,
EXCELLENT = 95 ,
PERFECT = 100
} ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
u32 rssi_qual ;
u32 tx_qual ;
u32 quality = 0 ;
2009-10-08 19:38:45 -07:00
int ret , stats_valid = 0 ;
2007-02-10 12:25:27 -02:00
u8 rssi ;
u32 tx_retries ;
2008-03-17 12:45:58 +01:00
struct cmd_ds_802_11_get_log log ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
priv - > wstats . status = priv - > mode ;
2007-02-10 12:25:27 -02:00
/* If we're not associated, all quality values are meaningless */
2007-12-08 20:04:36 +00:00
if ( ( priv - > connect_status ! = LBS_CONNECTED ) & &
2009-12-02 15:26:01 +01:00
! lbs_mesh_connected ( priv ) )
2007-02-10 12:25:27 -02:00
goto out ;
/* Quality by RSSI */
priv - > wstats . qual . level =
2007-12-08 20:04:36 +00:00
CAL_RSSI ( priv - > SNR [ TYPE_BEACON ] [ TYPE_NOAVG ] ,
priv - > NF [ TYPE_BEACON ] [ TYPE_NOAVG ] ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( priv - > NF [ TYPE_BEACON ] [ TYPE_NOAVG ] = = 0 ) {
2007-02-10 12:25:27 -02:00
priv - > wstats . qual . noise = MRVDRV_NF_DEFAULT_SCAN_VALUE ;
} else {
priv - > wstats . qual . noise =
2007-12-08 20:04:36 +00:00
CAL_NF ( priv - > NF [ TYPE_BEACON ] [ TYPE_NOAVG ] ) ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " signal level %#x \n " , priv - > wstats . qual . level ) ;
lbs_deb_wext ( " noise %#x \n " , priv - > wstats . qual . noise ) ;
2007-02-10 12:25:27 -02:00
rssi = priv - > wstats . qual . level - priv - > wstats . qual . noise ;
if ( rssi < 15 )
rssi_qual = rssi * POOR / 10 ;
else if ( rssi < 20 )
rssi_qual = ( rssi - 15 ) * ( FAIR - POOR ) / 5 + POOR ;
else if ( rssi < 30 )
rssi_qual = ( rssi - 20 ) * ( GOOD - FAIR ) / 5 + FAIR ;
else if ( rssi < 40 )
rssi_qual = ( rssi - 30 ) * ( VERY_GOOD - GOOD ) /
10 + GOOD ;
else
rssi_qual = ( rssi - 40 ) * ( PERFECT - VERY_GOOD ) /
10 + VERY_GOOD ;
quality = rssi_qual ;
/* Quality by TX errors */
2009-03-20 19:36:36 +00:00
priv - > wstats . discard . retries = dev - > stats . tx_errors ;
2007-02-10 12:25:27 -02:00
2008-03-17 12:45:58 +01:00
memset ( & log , 0 , sizeof ( log ) ) ;
log . hdr . size = cpu_to_le16 ( sizeof ( log ) ) ;
2009-10-08 19:38:45 -07:00
ret = lbs_cmd_with_response ( priv , CMD_802_11_GET_LOG , & log ) ;
if ( ret )
goto out ;
2008-03-17 12:45:58 +01:00
tx_retries = le32_to_cpu ( log . retry ) ;
2007-02-10 12:25:27 -02:00
if ( tx_retries > 75 )
tx_qual = ( 90 - tx_retries ) * POOR / 15 ;
else if ( tx_retries > 70 )
tx_qual = ( 75 - tx_retries ) * ( FAIR - POOR ) / 5 + POOR ;
else if ( tx_retries > 65 )
tx_qual = ( 70 - tx_retries ) * ( GOOD - FAIR ) / 5 + FAIR ;
else if ( tx_retries > 50 )
tx_qual = ( 65 - tx_retries ) * ( VERY_GOOD - GOOD ) /
15 + GOOD ;
else
tx_qual = ( 50 - tx_retries ) *
( PERFECT - VERY_GOOD ) / 50 + VERY_GOOD ;
quality = min ( quality , tx_qual ) ;
2008-03-17 12:45:58 +01:00
priv - > wstats . discard . code = le32_to_cpu ( log . wepundecryptable ) ;
2007-02-10 12:25:27 -02:00
priv - > wstats . discard . retries = tx_retries ;
2008-03-17 12:45:58 +01:00
priv - > wstats . discard . misc = le32_to_cpu ( log . ackfailure ) ;
2007-02-10 12:25:27 -02:00
/* Calculate quality */
2007-08-02 13:07:15 -04:00
priv - > wstats . qual . qual = min_t ( u8 , quality , 100 ) ;
2007-02-10 12:25:27 -02:00
priv - > wstats . qual . updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM ;
stats_valid = 1 ;
/* update stats asynchronously for future calls */
2009-10-08 19:38:45 -07:00
ret = lbs_prepare_and_send_command ( priv , CMD_802_11_RSSI , 0 ,
2007-02-10 12:25:27 -02:00
0 , 0 , NULL ) ;
2009-10-08 19:38:45 -07:00
if ( ret )
lbs_pr_err ( " RSSI command failed \n " ) ;
2007-02-10 12:25:27 -02:00
out :
if ( ! stats_valid ) {
priv - > wstats . miss . beacon = 0 ;
priv - > wstats . discard . retries = 0 ;
priv - > wstats . qual . qual = 0 ;
priv - > wstats . qual . level = 0 ;
priv - > wstats . qual . noise = 0 ;
priv - > wstats . qual . updated = IW_QUAL_ALL_UPDATED ;
priv - > wstats . qual . updated | = IW_QUAL_NOISE_INVALID |
IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID ;
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return & priv - > wstats ;
}
2007-11-15 18:05:47 -05:00
static int lbs_set_freq ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_freq * fwrq , char * extra )
{
2007-05-25 16:46:33 -04:00
int ret = - EINVAL ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct chan_freq_power * cfp ;
2007-05-25 16:46:33 -04:00
struct assoc_request * assoc_req ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
assoc_req = lbs_get_association_request ( priv ) ;
2007-05-25 16:46:33 -04:00
if ( ! assoc_req ) {
ret = - ENOMEM ;
goto out ;
}
2007-02-10 12:25:27 -02:00
2007-05-25 16:46:33 -04:00
/* If setting by frequency, convert to a channel */
if ( fwrq - > e = = 1 ) {
2007-02-10 12:25:27 -02:00
long f = fwrq - > m / 100000 ;
2007-12-08 20:04:36 +00:00
cfp = find_cfp_by_band_and_freq ( priv , 0 , f ) ;
2007-02-10 12:25:27 -02:00
if ( ! cfp ) {
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " invalid freq %ld \n " , f ) ;
2007-05-25 16:46:33 -04:00
goto out ;
2007-02-10 12:25:27 -02:00
}
fwrq - > e = 0 ;
2007-05-25 16:46:33 -04:00
fwrq - > m = ( int ) cfp - > channel ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 16:46:33 -04:00
/* Setting by channel number */
2007-02-10 12:25:27 -02:00
if ( fwrq - > m > 1000 | | fwrq - > e > 0 ) {
2007-05-25 16:46:33 -04:00
goto out ;
}
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
cfp = lbs_find_cfp_by_band_and_channel ( priv , 0 , fwrq - > m ) ;
2007-05-25 16:46:33 -04:00
if ( ! cfp ) {
goto out ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 16:46:33 -04:00
assoc_req - > channel = fwrq - > m ;
ret = 0 ;
2007-05-25 11:27:16 -04:00
out :
2007-05-25 16:46:33 -04:00
if ( ret = = 0 ) {
set_bit ( ASSOC_FLAG_CHANNEL , & assoc_req - > flags ) ;
2007-11-15 18:05:47 -05:00
lbs_postpone_association_work ( priv ) ;
2007-05-25 16:46:33 -04:00
} else {
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-05-25 16:46:33 -04:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-05-25 16:46:33 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2009-12-02 15:26:02 +01:00
# ifdef CONFIG_LIBERTAS_MESH
2007-12-11 19:56:28 -05:00
static int lbs_mesh_set_freq ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_freq * fwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-12-11 19:56:28 -05:00
struct chan_freq_power * cfp ;
int ret = - EINVAL ;
lbs_deb_enter ( LBS_DEB_WEXT ) ;
/* If setting by frequency, convert to a channel */
if ( fwrq - > e = = 1 ) {
long f = fwrq - > m / 100000 ;
cfp = find_cfp_by_band_and_freq ( priv , 0 , f ) ;
if ( ! cfp ) {
lbs_deb_wext ( " invalid freq %ld \n " , f ) ;
goto out ;
}
fwrq - > e = 0 ;
fwrq - > m = ( int ) cfp - > channel ;
}
/* Setting by channel number */
if ( fwrq - > m > 1000 | | fwrq - > e > 0 ) {
goto out ;
}
cfp = lbs_find_cfp_by_band_and_channel ( priv , 0 , fwrq - > m ) ;
if ( ! cfp ) {
goto out ;
}
2009-10-22 15:30:50 +02:00
if ( fwrq - > m ! = priv - > channel ) {
2007-12-11 19:56:28 -05:00
lbs_deb_wext ( " mesh channel change forces eth disconnect \n " ) ;
if ( priv - > mode = = IW_MODE_INFRA )
2008-08-21 17:46:18 -04:00
lbs_cmd_80211_deauthenticate ( priv ,
priv - > curbssparams . bssid ,
WLAN_REASON_DEAUTH_LEAVING ) ;
2007-12-11 19:56:28 -05:00
else if ( priv - > mode = = IW_MODE_ADHOC )
2008-08-21 21:46:59 -04:00
lbs_adhoc_stop ( priv ) ;
2007-12-11 19:56:28 -05:00
}
2008-05-17 00:55:10 -07:00
lbs_mesh_config ( priv , CMD_ACT_MESH_CONFIG_START , fwrq - > m ) ;
2007-12-13 00:32:36 -05:00
lbs_update_channel ( priv ) ;
2007-12-11 19:56:28 -05:00
ret = 0 ;
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
}
2009-12-02 15:26:02 +01:00
# endif
2007-12-11 19:56:28 -05:00
2007-11-15 18:05:47 -05:00
static int lbs_set_rate ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-12-11 15:50:59 -05:00
u8 new_rate = 0 ;
2007-08-02 11:40:45 -04:00
int ret = - EINVAL ;
u8 rates [ MAX_RATES + 1 ] ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2009-09-30 20:04:38 -07:00
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " vwrq->value %d \n " , vwrq - > value ) ;
2008-05-24 10:59:49 +01:00
lbs_deb_wext ( " vwrq->fixed %d \n " , vwrq - > fixed ) ;
if ( vwrq - > fixed & & vwrq - > value = = - 1 )
goto out ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:40:45 -04:00
/* Auto rate? */
2008-05-24 10:59:49 +01:00
priv - > enablehwauto = ! vwrq - > fixed ;
if ( vwrq - > value = = - 1 )
2007-12-08 20:04:36 +00:00
priv - > cur_rate = 0 ;
2008-05-24 10:59:49 +01:00
else {
2007-08-02 11:40:45 -04:00
if ( vwrq - > value % 100000 )
goto out ;
2007-02-10 12:25:27 -02:00
2008-05-24 10:59:49 +01:00
new_rate = vwrq - > value / 500000 ;
priv - > cur_rate = new_rate ;
/* the rest is only needed for lbs_set_data_rate() */
2007-02-10 12:25:27 -02:00
memset ( rates , 0 , sizeof ( rates ) ) ;
2007-12-08 20:04:36 +00:00
copy_active_data_rates ( priv , rates ) ;
2007-08-02 11:40:45 -04:00
if ( ! memchr ( rates , new_rate , sizeof ( rates ) ) ) {
lbs_pr_alert ( " fixed data rate 0x%X out of range \n " ,
new_rate ) ;
goto out ;
2007-02-10 12:25:27 -02:00
}
2008-09-26 11:34:35 -04:00
if ( priv - > fwrelease < 0x09000000 ) {
ret = lbs_set_power_adapt_cfg ( priv , 0 ,
POW_ADAPT_DEFAULT_P0 ,
POW_ADAPT_DEFAULT_P1 ,
POW_ADAPT_DEFAULT_P2 ) ;
if ( ret )
goto out ;
}
ret = lbs_set_tpc_cfg ( priv , 0 , TPC_DEFAULT_P0 , TPC_DEFAULT_P1 ,
TPC_DEFAULT_P2 , 1 ) ;
if ( ret )
goto out ;
2007-02-10 12:25:27 -02:00
}
2008-05-24 10:59:49 +01:00
/* Try the newer command first (Firmware Spec 5.1 and above) */
ret = lbs_cmd_802_11_rate_adapt_rateset ( priv , CMD_ACT_SET ) ;
/* Fallback to older version */
if ( ret )
ret = lbs_set_data_rate ( priv , new_rate ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:40:45 -04:00
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_rate ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( priv - > connect_status = = LBS_CONNECTED ) {
vwrq - > value = priv - > cur_rate * 500000 ;
2007-08-02 11:40:45 -04:00
2008-05-24 10:59:49 +01:00
if ( priv - > enablehwauto )
2007-08-02 11:40:45 -04:00
vwrq - > fixed = 0 ;
else
vwrq - > fixed = 1 ;
2007-02-10 12:25:27 -02:00
} else {
2007-08-02 11:40:45 -04:00
vwrq - > fixed = 0 ;
vwrq - > value = 0 ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_set_mode ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info , u32 * uwrq , char * extra )
{
int ret = 0 ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct assoc_request * assoc_req ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-05-10 22:58:02 -04:00
if ( ( * uwrq ! = IW_MODE_ADHOC )
& & ( * uwrq ! = IW_MODE_INFRA )
& & ( * uwrq ! = IW_MODE_AUTO ) ) {
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " Invalid mode: 0x%x \n " , * uwrq ) ;
2007-05-10 22:58:02 -04:00
ret = - EINVAL ;
goto out ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
assoc_req = lbs_get_association_request ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( ! assoc_req ) {
ret = - ENOMEM ;
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
} else {
2007-05-10 22:58:02 -04:00
assoc_req - > mode = * uwrq ;
2007-02-10 12:25:27 -02:00
set_bit ( ASSOC_FLAG_MODE , & assoc_req - > flags ) ;
2007-11-15 18:05:47 -05:00
lbs_postpone_association_work ( priv ) ;
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " Switching to mode: 0x%x \n " , * uwrq ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-05-10 22:58:02 -04:00
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
/**
* @ brief Get Encryption key
*
* @ param dev A pointer to net_device structure
* @ param info A pointer to iw_request_info structure
* @ param vwrq A pointer to iw_param structure
* @ param extra A pointer to extra data buf
* @ return 0 - - success , otherwise fail
*/
2007-11-15 18:05:47 -05:00
static int lbs_get_encode ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_point * dwrq , u8 * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
int index = ( dwrq - > flags & IW_ENCODE_INDEX ) - 1 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " flags 0x%x, index %d, length %d, wep_tx_keyidx %d \n " ,
2007-12-08 20:04:36 +00:00
dwrq - > flags , index , dwrq - > length , priv - > wep_tx_keyidx ) ;
2007-02-10 12:25:27 -02:00
dwrq - > flags = 0 ;
/* Authentication method */
2007-12-08 20:04:36 +00:00
switch ( priv - > secinfo . auth_mode ) {
2007-05-10 22:56:42 -04:00
case IW_AUTH_ALG_OPEN_SYSTEM :
2007-02-10 12:25:27 -02:00
dwrq - > flags = IW_ENCODE_OPEN ;
break ;
2007-05-10 22:56:42 -04:00
case IW_AUTH_ALG_SHARED_KEY :
case IW_AUTH_ALG_LEAP :
2007-02-10 12:25:27 -02:00
dwrq - > flags = IW_ENCODE_RESTRICTED ;
break ;
default :
dwrq - > flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN ;
break ;
}
memset ( extra , 0 , 16 ) ;
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
/* Default to returning current transmit key */
if ( index < 0 )
2007-12-08 20:04:36 +00:00
index = priv - > wep_tx_keyidx ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( ( priv - > wep_keys [ index ] . len ) & & priv - > secinfo . wep_enabled ) {
memcpy ( extra , priv - > wep_keys [ index ] . key ,
priv - > wep_keys [ index ] . len ) ;
dwrq - > length = priv - > wep_keys [ index ] . len ;
2007-02-10 12:25:27 -02:00
dwrq - > flags | = ( index + 1 ) ;
/* Return WEP enabled */
dwrq - > flags & = ~ IW_ENCODE_DISABLED ;
2007-12-08 20:04:36 +00:00
} else if ( ( priv - > secinfo . WPAenabled )
| | ( priv - > secinfo . WPA2enabled ) ) {
2007-02-10 12:25:27 -02:00
/* return WPA enabled */
dwrq - > flags & = ~ IW_ENCODE_DISABLED ;
2007-12-07 19:32:12 +00:00
dwrq - > flags | = IW_ENCODE_NOKEY ;
2007-02-10 12:25:27 -02:00
} else {
dwrq - > flags | = IW_ENCODE_DISABLED ;
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-10-03 17:59:30 -07:00
lbs_deb_wext ( " key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d \n " ,
2007-02-10 12:25:27 -02:00
extra [ 0 ] , extra [ 1 ] , extra [ 2 ] ,
extra [ 3 ] , extra [ 4 ] , extra [ 5 ] , dwrq - > length ) ;
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " return flags 0x%x \n " , dwrq - > flags ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
/**
* @ brief Set Encryption key ( internal )
*
* @ param priv A pointer to private card structure
* @ param key_material A pointer to key material
* @ param key_length length of key material
* @ param index key index to set
* @ param set_tx_key Force set TX key ( 1 = yes , 0 = no )
* @ return 0 - - success , otherwise fail
*/
2007-11-15 18:05:47 -05:00
static int lbs_set_wep_key ( struct assoc_request * assoc_req ,
2007-02-10 12:25:27 -02:00
const char * key_material ,
u16 key_length ,
u16 index ,
int set_tx_key )
{
2007-05-25 11:27:16 -04:00
int ret = 0 ;
2007-08-02 10:45:55 -04:00
struct enc_key * pkey ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
/* Paranoid validation of key index */
if ( index > 3 ) {
2007-05-25 11:27:16 -04:00
ret = - EINVAL ;
goto out ;
2007-02-10 12:25:27 -02:00
}
/* validate max key length */
if ( key_length > KEY_LEN_WEP_104 ) {
2007-05-25 11:27:16 -04:00
ret = - EINVAL ;
goto out ;
2007-02-10 12:25:27 -02:00
}
pkey = & assoc_req - > wep_keys [ index ] ;
if ( key_length > 0 ) {
2007-08-02 10:45:55 -04:00
memset ( pkey , 0 , sizeof ( struct enc_key ) ) ;
2007-02-10 12:25:27 -02:00
pkey - > type = KEY_TYPE_ID_WEP ;
/* Standardize the key length */
pkey - > len = ( key_length > KEY_LEN_WEP_40 ) ?
KEY_LEN_WEP_104 : KEY_LEN_WEP_40 ;
memcpy ( pkey - > key , key_material , key_length ) ;
}
if ( set_tx_key ) {
/* Ensure the chosen key is valid */
if ( ! pkey - > len ) {
2007-05-25 11:27:16 -04:00
lbs_deb_wext ( " key not set, so cannot enable it \n " ) ;
ret = - EINVAL ;
goto out ;
2007-02-10 12:25:27 -02:00
}
assoc_req - > wep_tx_keyidx = index ;
}
2007-05-10 22:57:23 -04:00
assoc_req - > secinfo . wep_enabled = 1 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
static int validate_key_index ( u16 def_index , u16 raw_index ,
u16 * out_index , u16 * is_default )
{
if ( ! out_index | | ! is_default )
return - EINVAL ;
/* Verify index if present, otherwise use default TX key index */
if ( raw_index > 0 ) {
if ( raw_index > 4 )
return - EINVAL ;
* out_index = raw_index - 1 ;
} else {
* out_index = def_index ;
* is_default = 1 ;
}
return 0 ;
}
static void disable_wep ( struct assoc_request * assoc_req )
{
int i ;
2007-05-25 23:01:24 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
/* Set Open System auth mode */
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_OPEN_SYSTEM ;
2007-02-10 12:25:27 -02:00
/* Clear WEP keys and mark WEP as disabled */
2007-05-10 22:57:23 -04:00
assoc_req - > secinfo . wep_enabled = 0 ;
2007-02-10 12:25:27 -02:00
for ( i = 0 ; i < 4 ; i + + )
assoc_req - > wep_keys [ i ] . len = 0 ;
set_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ;
set_bit ( ASSOC_FLAG_WEP_KEYS , & assoc_req - > flags ) ;
2007-05-25 23:01:24 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
}
static void disable_wpa ( struct assoc_request * assoc_req )
{
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-08-02 10:45:55 -04:00
memset ( & assoc_req - > wpa_mcast_key , 0 , sizeof ( struct enc_key ) ) ;
2007-05-25 23:01:24 -04:00
assoc_req - > wpa_mcast_key . flags = KEY_INFO_WPA_MCAST ;
set_bit ( ASSOC_FLAG_WPA_MCAST_KEY , & assoc_req - > flags ) ;
2007-08-02 10:45:55 -04:00
memset ( & assoc_req - > wpa_unicast_key , 0 , sizeof ( struct enc_key ) ) ;
2007-05-25 23:01:24 -04:00
assoc_req - > wpa_unicast_key . flags = KEY_INFO_WPA_UNICAST ;
set_bit ( ASSOC_FLAG_WPA_UCAST_KEY , & assoc_req - > flags ) ;
assoc_req - > secinfo . WPAenabled = 0 ;
assoc_req - > secinfo . WPA2enabled = 0 ;
set_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ;
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
}
/**
* @ brief Set Encryption key
*
* @ param dev A pointer to net_device structure
* @ param info A pointer to iw_request_info structure
* @ param vwrq A pointer to iw_param structure
* @ param extra A pointer to extra data buf
* @ return 0 - - success , otherwise fail
*/
2007-11-15 18:05:47 -05:00
static int lbs_set_encode ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_point * dwrq , char * extra )
{
int ret = 0 ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct assoc_request * assoc_req ;
u16 is_default = 0 , index = 0 , set_tx_key = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
assoc_req = lbs_get_association_request ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( ! assoc_req ) {
ret = - ENOMEM ;
goto out ;
}
if ( dwrq - > flags & IW_ENCODE_DISABLED ) {
disable_wep ( assoc_req ) ;
2007-05-25 23:01:24 -04:00
disable_wpa ( assoc_req ) ;
2007-02-10 12:25:27 -02:00
goto out ;
}
ret = validate_key_index ( assoc_req - > wep_tx_keyidx ,
( dwrq - > flags & IW_ENCODE_INDEX ) ,
& index , & is_default ) ;
if ( ret ) {
ret = - EINVAL ;
goto out ;
}
/* If WEP isn't enabled, or if there is no key data but a valid
* index , set the TX key .
*/
2007-05-10 22:57:23 -04:00
if ( ! assoc_req - > secinfo . wep_enabled | | ( dwrq - > length = = 0 & & ! is_default ) )
2007-02-10 12:25:27 -02:00
set_tx_key = 1 ;
2007-11-15 18:05:47 -05:00
ret = lbs_set_wep_key ( assoc_req , extra , dwrq - > length , index , set_tx_key ) ;
2007-02-10 12:25:27 -02:00
if ( ret )
goto out ;
if ( dwrq - > length )
set_bit ( ASSOC_FLAG_WEP_KEYS , & assoc_req - > flags ) ;
if ( set_tx_key )
set_bit ( ASSOC_FLAG_WEP_TX_KEYIDX , & assoc_req - > flags ) ;
if ( dwrq - > flags & IW_ENCODE_RESTRICTED ) {
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_SHARED_KEY ;
2007-02-10 12:25:27 -02:00
} else if ( dwrq - > flags & IW_ENCODE_OPEN ) {
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_OPEN_SYSTEM ;
2007-02-10 12:25:27 -02:00
}
out :
if ( ret = = 0 ) {
set_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ;
2007-11-15 18:05:47 -05:00
lbs_postpone_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
} else {
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
/**
* @ brief Get Extended Encryption key ( WPA / 802.1 x and WEP )
*
* @ param dev A pointer to net_device structure
* @ param info A pointer to iw_request_info structure
* @ param vwrq A pointer to iw_param structure
* @ param extra A pointer to extra data buf
* @ return 0 on success , otherwise failure
*/
2007-11-15 18:05:47 -05:00
static int lbs_get_encodeext ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_point * dwrq ,
char * extra )
{
int ret = - EINVAL ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct iw_encode_ext * ext = ( struct iw_encode_ext * ) extra ;
int index , max_key_len ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
max_key_len = dwrq - > length - sizeof ( * ext ) ;
if ( max_key_len < 0 )
goto out ;
index = dwrq - > flags & IW_ENCODE_INDEX ;
if ( index ) {
if ( index < 1 | | index > 4 )
goto out ;
index - - ;
} else {
2007-12-08 20:04:36 +00:00
index = priv - > wep_tx_keyidx ;
2007-02-10 12:25:27 -02:00
}
2007-10-26 21:51:26 +02:00
if ( ! ( ext - > ext_flags & IW_ENCODE_EXT_GROUP_KEY ) & &
2007-02-10 12:25:27 -02:00
ext - > alg ! = IW_ENCODE_ALG_WEP ) {
2007-12-08 20:04:36 +00:00
if ( index ! = 0 | | priv - > mode ! = IW_MODE_INFRA )
2007-02-10 12:25:27 -02:00
goto out ;
}
dwrq - > flags = index + 1 ;
memset ( ext , 0 , sizeof ( * ext ) ) ;
2007-12-08 20:04:36 +00:00
if ( ! priv - > secinfo . wep_enabled
& & ! priv - > secinfo . WPAenabled
& & ! priv - > secinfo . WPA2enabled ) {
2007-02-10 12:25:27 -02:00
ext - > alg = IW_ENCODE_ALG_NONE ;
ext - > key_len = 0 ;
dwrq - > flags | = IW_ENCODE_DISABLED ;
} else {
u8 * key = NULL ;
2007-12-08 20:04:36 +00:00
if ( priv - > secinfo . wep_enabled
& & ! priv - > secinfo . WPAenabled
& & ! priv - > secinfo . WPA2enabled ) {
2007-05-25 23:01:24 -04:00
/* WEP */
2007-02-10 12:25:27 -02:00
ext - > alg = IW_ENCODE_ALG_WEP ;
2007-12-08 20:04:36 +00:00
ext - > key_len = priv - > wep_keys [ index ] . len ;
key = & priv - > wep_keys [ index ] . key [ 0 ] ;
} else if ( ! priv - > secinfo . wep_enabled
& & ( priv - > secinfo . WPAenabled | |
priv - > secinfo . WPA2enabled ) ) {
2007-02-10 12:25:27 -02:00
/* WPA */
2007-08-02 10:45:55 -04:00
struct enc_key * pkey = NULL ;
2007-05-25 23:01:24 -04:00
2007-12-08 20:04:36 +00:00
if ( priv - > wpa_mcast_key . len
& & ( priv - > wpa_mcast_key . flags & KEY_INFO_WPA_ENABLED ) )
pkey = & priv - > wpa_mcast_key ;
else if ( priv - > wpa_unicast_key . len
& & ( priv - > wpa_unicast_key . flags & KEY_INFO_WPA_ENABLED ) )
pkey = & priv - > wpa_unicast_key ;
2007-05-25 23:01:24 -04:00
if ( pkey ) {
if ( pkey - > type = = KEY_TYPE_ID_AES ) {
ext - > alg = IW_ENCODE_ALG_CCMP ;
} else {
ext - > alg = IW_ENCODE_ALG_TKIP ;
}
ext - > key_len = pkey - > len ;
key = & pkey - > key [ 0 ] ;
} else {
ext - > alg = IW_ENCODE_ALG_TKIP ;
ext - > key_len = 0 ;
}
2007-02-10 12:25:27 -02:00
} else {
goto out ;
}
if ( ext - > key_len > max_key_len ) {
ret = - E2BIG ;
goto out ;
}
if ( ext - > key_len )
memcpy ( ext - > key , key , ext - > key_len ) ;
else
dwrq - > flags | = IW_ENCODE_NOKEY ;
dwrq - > flags | = IW_ENCODE_ENABLED ;
}
ret = 0 ;
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
/**
* @ brief Set Encryption key Extended ( WPA / 802.1 x and WEP )
*
* @ param dev A pointer to net_device structure
* @ param info A pointer to iw_request_info structure
* @ param vwrq A pointer to iw_param structure
* @ param extra A pointer to extra data buf
* @ return 0 - - success , otherwise fail
*/
2007-11-15 18:05:47 -05:00
static int lbs_set_encodeext ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_point * dwrq ,
char * extra )
{
int ret = 0 ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct iw_encode_ext * ext = ( struct iw_encode_ext * ) extra ;
int alg = ext - > alg ;
struct assoc_request * assoc_req ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
assoc_req = lbs_get_association_request ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( ! assoc_req ) {
ret = - ENOMEM ;
goto out ;
}
if ( ( alg = = IW_ENCODE_ALG_NONE ) | | ( dwrq - > flags & IW_ENCODE_DISABLED ) ) {
disable_wep ( assoc_req ) ;
2007-05-25 23:01:24 -04:00
disable_wpa ( assoc_req ) ;
2007-02-10 12:25:27 -02:00
} else if ( alg = = IW_ENCODE_ALG_WEP ) {
u16 is_default = 0 , index , set_tx_key = 0 ;
ret = validate_key_index ( assoc_req - > wep_tx_keyidx ,
( dwrq - > flags & IW_ENCODE_INDEX ) ,
& index , & is_default ) ;
if ( ret )
goto out ;
/* If WEP isn't enabled, or if there is no key data but a valid
* index , or if the set - TX - key flag was passed , set the TX key .
*/
2007-05-10 22:57:23 -04:00
if ( ! assoc_req - > secinfo . wep_enabled
2007-02-10 12:25:27 -02:00
| | ( dwrq - > length = = 0 & & ! is_default )
| | ( ext - > ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) )
set_tx_key = 1 ;
/* Copy key to driver */
2007-11-15 18:05:47 -05:00
ret = lbs_set_wep_key ( assoc_req , ext - > key , ext - > key_len , index ,
2007-02-10 12:25:27 -02:00
set_tx_key ) ;
if ( ret )
goto out ;
if ( dwrq - > flags & IW_ENCODE_RESTRICTED ) {
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_SHARED_KEY ;
2007-02-10 12:25:27 -02:00
} else if ( dwrq - > flags & IW_ENCODE_OPEN ) {
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_OPEN_SYSTEM ;
2007-02-10 12:25:27 -02:00
}
/* Mark the various WEP bits as modified */
set_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ;
if ( dwrq - > length )
set_bit ( ASSOC_FLAG_WEP_KEYS , & assoc_req - > flags ) ;
if ( set_tx_key )
set_bit ( ASSOC_FLAG_WEP_TX_KEYIDX , & assoc_req - > flags ) ;
} else if ( ( alg = = IW_ENCODE_ALG_TKIP ) | | ( alg = = IW_ENCODE_ALG_CCMP ) ) {
2007-08-02 10:45:55 -04:00
struct enc_key * pkey ;
2007-02-10 12:25:27 -02:00
/* validate key length */
if ( ( ( alg = = IW_ENCODE_ALG_TKIP )
& & ( ext - > key_len ! = KEY_LEN_WPA_TKIP ) )
| | ( ( alg = = IW_ENCODE_ALG_CCMP )
& & ( ext - > key_len ! = KEY_LEN_WPA_AES ) ) ) {
2007-11-19 17:48:27 -08:00
lbs_deb_wext ( " invalid size %d for key of alg "
2007-05-25 11:27:16 -04:00
" type %d \n " ,
2007-02-10 12:25:27 -02:00
ext - > key_len ,
alg ) ;
ret = - EINVAL ;
goto out ;
}
2007-05-25 23:01:24 -04:00
if ( ext - > ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
2007-02-10 12:25:27 -02:00
pkey = & assoc_req - > wpa_mcast_key ;
2007-05-25 23:01:24 -04:00
set_bit ( ASSOC_FLAG_WPA_MCAST_KEY , & assoc_req - > flags ) ;
} else {
2007-02-10 12:25:27 -02:00
pkey = & assoc_req - > wpa_unicast_key ;
2007-05-25 23:01:24 -04:00
set_bit ( ASSOC_FLAG_WPA_UCAST_KEY , & assoc_req - > flags ) ;
}
2007-02-10 12:25:27 -02:00
2007-08-02 10:45:55 -04:00
memset ( pkey , 0 , sizeof ( struct enc_key ) ) ;
2007-02-10 12:25:27 -02:00
memcpy ( pkey - > key , ext - > key , ext - > key_len ) ;
pkey - > len = ext - > key_len ;
2007-05-25 23:01:24 -04:00
if ( pkey - > len )
pkey - > flags | = KEY_INFO_WPA_ENABLED ;
2007-02-10 12:25:27 -02:00
2007-05-25 23:01:24 -04:00
/* Do this after zeroing key structure */
2007-02-10 12:25:27 -02:00
if ( ext - > ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
pkey - > flags | = KEY_INFO_WPA_MCAST ;
} else {
pkey - > flags | = KEY_INFO_WPA_UNICAST ;
}
2007-05-25 23:01:24 -04:00
if ( alg = = IW_ENCODE_ALG_TKIP ) {
2007-02-10 12:25:27 -02:00
pkey - > type = KEY_TYPE_ID_TKIP ;
2007-05-25 23:01:24 -04:00
} else if ( alg = = IW_ENCODE_ALG_CCMP ) {
2007-02-10 12:25:27 -02:00
pkey - > type = KEY_TYPE_ID_AES ;
2007-05-25 23:01:24 -04:00
}
2007-02-10 12:25:27 -02:00
/* If WPA isn't enabled yet, do that now */
if ( assoc_req - > secinfo . WPAenabled = = 0
& & assoc_req - > secinfo . WPA2enabled = = 0 ) {
assoc_req - > secinfo . WPAenabled = 1 ;
assoc_req - > secinfo . WPA2enabled = 1 ;
set_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ;
}
2008-09-11 15:32:50 -07:00
/* Only disable wep if necessary: can't waste time here. */
if ( priv - > mac_control & CMD_ACT_MAC_WEP_ENABLE )
disable_wep ( assoc_req ) ;
2007-02-10 12:25:27 -02:00
}
out :
2008-09-16 18:08:39 -07:00
if ( ret = = 0 ) {
/* 802.1x and WPA rekeying must happen as quickly as possible,
* especially during the 4 - way handshake ; thus if in
* infrastructure mode , and either ( a ) 802.1 x is enabled or
* ( b ) WPA is being used , set the key right away .
*/
if ( assoc_req - > mode = = IW_MODE_INFRA & &
( ( assoc_req - > secinfo . key_mgmt & IW_AUTH_KEY_MGMT_802_1X ) | |
( assoc_req - > secinfo . key_mgmt & IW_AUTH_KEY_MGMT_PSK ) | |
assoc_req - > secinfo . WPAenabled | |
assoc_req - > secinfo . WPA2enabled ) ) {
lbs_do_association_work ( priv ) ;
} else
lbs_postpone_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
} else {
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_set_genie ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_point * dwrq ,
char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
int ret = 0 ;
struct assoc_request * assoc_req ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
assoc_req = lbs_get_association_request ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( ! assoc_req ) {
ret = - ENOMEM ;
goto out ;
}
if ( dwrq - > length > MAX_WPA_IE_LEN | |
( dwrq - > length & & extra = = NULL ) ) {
ret = - EINVAL ;
goto out ;
}
if ( dwrq - > length ) {
memcpy ( & assoc_req - > wpa_ie [ 0 ] , extra , dwrq - > length ) ;
assoc_req - > wpa_ie_len = dwrq - > length ;
} else {
2007-12-08 20:04:36 +00:00
memset ( & assoc_req - > wpa_ie [ 0 ] , 0 , sizeof ( priv - > wpa_ie ) ) ;
2007-02-10 12:25:27 -02:00
assoc_req - > wpa_ie_len = 0 ;
}
out :
if ( ret = = 0 ) {
set_bit ( ASSOC_FLAG_WPA_IE , & assoc_req - > flags ) ;
2007-11-15 18:05:47 -05:00
lbs_postpone_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
} else {
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_genie ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_point * dwrq ,
char * extra )
{
2007-05-25 11:27:16 -04:00
int ret = 0 ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( priv - > wpa_ie_len = = 0 ) {
2007-02-10 12:25:27 -02:00
dwrq - > length = 0 ;
2007-05-25 11:27:16 -04:00
goto out ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
if ( dwrq - > length < priv - > wpa_ie_len ) {
2007-05-25 11:27:16 -04:00
ret = - E2BIG ;
goto out ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
dwrq - > length = priv - > wpa_ie_len ;
memcpy ( extra , & priv - > wpa_ie [ 0 ] , priv - > wpa_ie_len ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_set_auth ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_param * dwrq ,
char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct assoc_request * assoc_req ;
int ret = 0 ;
int updated = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
assoc_req = lbs_get_association_request ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( ! assoc_req ) {
ret = - ENOMEM ;
goto out ;
}
switch ( dwrq - > flags & IW_AUTH_INDEX ) {
2009-07-31 20:02:19 -07:00
case IW_AUTH_PRIVACY_INVOKED :
case IW_AUTH_RX_UNENCRYPTED_EAPOL :
2007-02-10 12:25:27 -02:00
case IW_AUTH_TKIP_COUNTERMEASURES :
case IW_AUTH_CIPHER_PAIRWISE :
case IW_AUTH_CIPHER_GROUP :
2007-05-25 23:01:24 -04:00
case IW_AUTH_DROP_UNENCRYPTED :
2007-02-10 12:25:27 -02:00
/*
* libertas does not use these parameters
*/
break ;
2008-09-16 18:08:39 -07:00
case IW_AUTH_KEY_MGMT :
assoc_req - > secinfo . key_mgmt = dwrq - > value ;
updated = 1 ;
break ;
2007-02-10 12:25:27 -02:00
case IW_AUTH_WPA_VERSION :
if ( dwrq - > value & IW_AUTH_WPA_VERSION_DISABLED ) {
assoc_req - > secinfo . WPAenabled = 0 ;
assoc_req - > secinfo . WPA2enabled = 0 ;
2007-05-25 23:01:24 -04:00
disable_wpa ( assoc_req ) ;
2007-02-10 12:25:27 -02:00
}
if ( dwrq - > value & IW_AUTH_WPA_VERSION_WPA ) {
assoc_req - > secinfo . WPAenabled = 1 ;
2007-05-10 22:57:23 -04:00
assoc_req - > secinfo . wep_enabled = 0 ;
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_OPEN_SYSTEM ;
2007-02-10 12:25:27 -02:00
}
if ( dwrq - > value & IW_AUTH_WPA_VERSION_WPA2 ) {
assoc_req - > secinfo . WPA2enabled = 1 ;
2007-05-10 22:57:23 -04:00
assoc_req - > secinfo . wep_enabled = 0 ;
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_OPEN_SYSTEM ;
2007-02-10 12:25:27 -02:00
}
updated = 1 ;
break ;
case IW_AUTH_80211_AUTH_ALG :
if ( dwrq - > value & IW_AUTH_ALG_SHARED_KEY ) {
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_SHARED_KEY ;
2007-02-10 12:25:27 -02:00
} else if ( dwrq - > value & IW_AUTH_ALG_OPEN_SYSTEM ) {
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_OPEN_SYSTEM ;
2007-02-10 12:25:27 -02:00
} else if ( dwrq - > value & IW_AUTH_ALG_LEAP ) {
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_LEAP ;
2007-02-10 12:25:27 -02:00
} else {
ret = - EINVAL ;
}
updated = 1 ;
break ;
case IW_AUTH_WPA_ENABLED :
if ( dwrq - > value ) {
if ( ! assoc_req - > secinfo . WPAenabled & &
! assoc_req - > secinfo . WPA2enabled ) {
assoc_req - > secinfo . WPAenabled = 1 ;
assoc_req - > secinfo . WPA2enabled = 1 ;
2007-05-10 22:57:23 -04:00
assoc_req - > secinfo . wep_enabled = 0 ;
2007-05-10 22:56:42 -04:00
assoc_req - > secinfo . auth_mode = IW_AUTH_ALG_OPEN_SYSTEM ;
2007-02-10 12:25:27 -02:00
}
} else {
assoc_req - > secinfo . WPAenabled = 0 ;
assoc_req - > secinfo . WPA2enabled = 0 ;
2007-05-25 23:01:24 -04:00
disable_wpa ( assoc_req ) ;
2007-02-10 12:25:27 -02:00
}
updated = 1 ;
break ;
default :
ret = - EOPNOTSUPP ;
break ;
}
out :
if ( ret = = 0 ) {
if ( updated )
set_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ;
2007-11-15 18:05:47 -05:00
lbs_postpone_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
} else if ( ret ! = - EOPNOTSUPP ) {
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_auth ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct iw_request_info * info ,
struct iw_param * dwrq ,
char * extra )
{
2007-05-25 11:27:16 -04:00
int ret = 0 ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
switch ( dwrq - > flags & IW_AUTH_INDEX ) {
2008-09-16 18:08:39 -07:00
case IW_AUTH_KEY_MGMT :
dwrq - > value = priv - > secinfo . key_mgmt ;
break ;
2007-02-10 12:25:27 -02:00
case IW_AUTH_WPA_VERSION :
dwrq - > value = 0 ;
2007-12-08 20:04:36 +00:00
if ( priv - > secinfo . WPAenabled )
2007-02-10 12:25:27 -02:00
dwrq - > value | = IW_AUTH_WPA_VERSION_WPA ;
2007-12-08 20:04:36 +00:00
if ( priv - > secinfo . WPA2enabled )
2007-02-10 12:25:27 -02:00
dwrq - > value | = IW_AUTH_WPA_VERSION_WPA2 ;
if ( ! dwrq - > value )
dwrq - > value | = IW_AUTH_WPA_VERSION_DISABLED ;
break ;
case IW_AUTH_80211_AUTH_ALG :
2007-12-08 20:04:36 +00:00
dwrq - > value = priv - > secinfo . auth_mode ;
2007-02-10 12:25:27 -02:00
break ;
case IW_AUTH_WPA_ENABLED :
2007-12-08 20:04:36 +00:00
if ( priv - > secinfo . WPAenabled & & priv - > secinfo . WPA2enabled )
2007-02-10 12:25:27 -02:00
dwrq - > value = 1 ;
break ;
default :
2007-05-25 11:27:16 -04:00
ret = - EOPNOTSUPP ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_set_txpow ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_param * vwrq , char * extra )
{
int ret = 0 ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-08-19 15:15:35 -04:00
s16 dbm = ( s16 ) vwrq - > value ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
if ( vwrq - > disabled ) {
2008-08-21 17:51:07 -04:00
lbs_set_radio ( priv , RADIO_PREAMBLE_AUTO , 0 ) ;
2008-08-19 15:15:35 -04:00
goto out ;
2007-02-10 12:25:27 -02:00
}
2008-08-19 15:15:35 -04:00
if ( vwrq - > fixed = = 0 ) {
2008-09-11 11:17:25 -07:00
/* User requests automatic tx power control, however there are
* many auto tx settings . For now use firmware defaults until
* we come up with a good way to expose these to the user . */
if ( priv - > fwrelease < 0x09000000 ) {
ret = lbs_set_power_adapt_cfg ( priv , 1 ,
POW_ADAPT_DEFAULT_P0 ,
POW_ADAPT_DEFAULT_P1 ,
POW_ADAPT_DEFAULT_P2 ) ;
if ( ret )
goto out ;
}
ret = lbs_set_tpc_cfg ( priv , 0 , TPC_DEFAULT_P0 , TPC_DEFAULT_P1 ,
TPC_DEFAULT_P2 , 1 ) ;
if ( ret )
goto out ;
2008-08-19 15:15:35 -04:00
dbm = priv - > txpower_max ;
} else {
/* Userspace check in iwrange if it should use dBm or mW,
* therefore this should never happen . . . Jean II */
if ( ( vwrq - > flags & IW_TXPOW_TYPE ) ! = IW_TXPOW_DBM ) {
ret = - EOPNOTSUPP ;
goto out ;
}
2007-02-10 12:25:27 -02:00
2008-09-11 11:17:25 -07:00
/* Validate requested power level against firmware allowed
* levels */
2008-08-19 15:15:35 -04:00
if ( priv - > txpower_min & & ( dbm < priv - > txpower_min ) ) {
ret = - EINVAL ;
goto out ;
}
2007-02-10 12:25:27 -02:00
2008-08-19 15:15:35 -04:00
if ( priv - > txpower_max & & ( dbm > priv - > txpower_max ) ) {
ret = - EINVAL ;
goto out ;
}
2008-09-11 11:17:25 -07:00
if ( priv - > fwrelease < 0x09000000 ) {
ret = lbs_set_power_adapt_cfg ( priv , 0 ,
POW_ADAPT_DEFAULT_P0 ,
POW_ADAPT_DEFAULT_P1 ,
POW_ADAPT_DEFAULT_P2 ) ;
if ( ret )
goto out ;
}
ret = lbs_set_tpc_cfg ( priv , 0 , TPC_DEFAULT_P0 , TPC_DEFAULT_P1 ,
TPC_DEFAULT_P2 , 1 ) ;
if ( ret )
goto out ;
2008-08-19 15:15:35 -04:00
}
2007-02-10 12:25:27 -02:00
2008-08-21 17:51:07 -04:00
/* If the radio was off, turn it on */
if ( ! priv - > radio_on ) {
ret = lbs_set_radio ( priv , RADIO_PREAMBLE_AUTO , 1 ) ;
if ( ret )
goto out ;
}
2007-02-10 12:25:27 -02:00
2008-08-19 15:15:35 -04:00
lbs_deb_wext ( " txpower set %d dBm \n " , dbm ) ;
2007-02-10 12:25:27 -02:00
2008-08-19 15:15:35 -04:00
ret = lbs_set_tx_power ( priv , dbm ) ;
2007-02-10 12:25:27 -02:00
2008-08-19 15:15:35 -04:00
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
static int lbs_get_essid ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_point * dwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
/*
* Note : if dwrq - > flags ! = 0 , we should get the relevant SSID from
* the SSID list . . .
*/
/*
* Get the current SSID
*/
2007-12-08 20:04:36 +00:00
if ( priv - > connect_status = = LBS_CONNECTED ) {
memcpy ( extra , priv - > curbssparams . ssid ,
priv - > curbssparams . ssid_len ) ;
2007-02-10 12:25:27 -02:00
} else {
memset ( extra , 0 , 32 ) ;
}
/*
* If none , we may want to get the one that was set
*/
2007-12-08 20:04:36 +00:00
dwrq - > length = priv - > curbssparams . ssid_len ;
2007-02-10 12:25:27 -02:00
dwrq - > flags = 1 ; /* active */
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-15 18:05:47 -05:00
static int lbs_set_essid ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct iw_point * dwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
int ret = 0 ;
2009-10-22 15:30:47 +02:00
u8 ssid [ IEEE80211_MAX_SSID_LEN ] ;
2007-05-28 23:54:55 -04:00
u8 ssid_len = 0 ;
2007-02-10 12:25:27 -02:00
struct assoc_request * assoc_req ;
2007-05-28 23:54:55 -04:00
int in_ssid_len = dwrq - > length ;
2008-09-30 20:59:05 -04:00
DECLARE_SSID_BUF ( ssid_buf ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-08-21 17:51:07 -04:00
if ( ! priv - > radio_on ) {
ret = - EINVAL ;
goto out ;
}
2007-02-10 12:25:27 -02:00
/* Check the size of the string */
2009-10-22 15:30:47 +02:00
if ( in_ssid_len > IEEE80211_MAX_SSID_LEN ) {
2007-02-10 12:25:27 -02:00
ret = - E2BIG ;
goto out ;
}
2007-05-28 23:54:55 -04:00
memset ( & ssid , 0 , sizeof ( ssid ) ) ;
2007-02-10 12:25:27 -02:00
2007-05-28 23:54:55 -04:00
if ( ! dwrq - > flags | | ! in_ssid_len ) {
2007-02-10 12:25:27 -02:00
/* "any" SSID requested; leave SSID blank */
} else {
/* Specific SSID requested */
2007-05-28 23:54:55 -04:00
memcpy ( & ssid , extra , in_ssid_len ) ;
ssid_len = in_ssid_len ;
2007-02-10 12:25:27 -02:00
}
2007-05-28 23:54:55 -04:00
if ( ! ssid_len ) {
lbs_deb_wext ( " requested any SSID \n " ) ;
} else {
lbs_deb_wext ( " requested SSID '%s' \n " ,
2008-09-30 20:59:05 -04:00
print_ssid ( ssid_buf , ssid , ssid_len ) ) ;
2007-05-28 23:54:55 -04:00
}
2007-02-10 12:25:27 -02:00
out :
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
if ( ret = = 0 ) {
/* Get or create the current association request */
2007-12-08 20:04:36 +00:00
assoc_req = lbs_get_association_request ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( ! assoc_req ) {
ret = - ENOMEM ;
} else {
/* Copy the SSID to the association request */
2009-10-22 15:30:47 +02:00
memcpy ( & assoc_req - > ssid , & ssid , IEEE80211_MAX_SSID_LEN ) ;
2007-05-28 23:54:55 -04:00
assoc_req - > ssid_len = ssid_len ;
2007-02-10 12:25:27 -02:00
set_bit ( ASSOC_FLAG_SSID , & assoc_req - > flags ) ;
2007-11-15 18:05:47 -05:00
lbs_postpone_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
}
}
/* Cancel the association request if there was an error */
if ( ret ! = 0 ) {
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2009-12-02 15:26:02 +01:00
# ifdef CONFIG_LIBERTAS_MESH
2007-12-11 19:30:57 -05:00
static int lbs_mesh_get_essid ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * dwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-12-11 19:30:57 -05:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
memcpy ( extra , priv - > mesh_ssid , priv - > mesh_ssid_len ) ;
dwrq - > length = priv - > mesh_ssid_len ;
dwrq - > flags = 1 ; /* active */
lbs_deb_leave ( LBS_DEB_WEXT ) ;
return 0 ;
}
static int lbs_mesh_set_essid ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * dwrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-12-11 19:30:57 -05:00
int ret = 0 ;
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2008-08-21 17:51:07 -04:00
if ( ! priv - > radio_on ) {
ret = - EINVAL ;
goto out ;
}
2007-12-11 19:30:57 -05:00
/* Check the size of the string */
2009-10-22 15:30:47 +02:00
if ( dwrq - > length > IEEE80211_MAX_SSID_LEN ) {
2007-12-11 19:30:57 -05:00
ret = - E2BIG ;
goto out ;
}
if ( ! dwrq - > flags | | ! dwrq - > length ) {
ret = - EINVAL ;
goto out ;
} else {
/* Specific SSID requested */
memcpy ( priv - > mesh_ssid , extra , dwrq - > length ) ;
priv - > mesh_ssid_len = dwrq - > length ;
}
2008-05-17 00:55:10 -07:00
lbs_mesh_config ( priv , CMD_ACT_MESH_CONFIG_START ,
2009-10-22 15:30:50 +02:00
priv - > channel ) ;
2007-12-11 19:30:57 -05:00
out :
lbs_deb_leave_args ( LBS_DEB_WEXT , " ret %d " , ret ) ;
return ret ;
}
2009-12-02 15:26:02 +01:00
# endif
2007-12-11 19:30:57 -05:00
2007-02-10 12:25:27 -02:00
/**
* @ brief Connect to the AP or Ad - hoc Network with specific bssid
*
* @ param dev A pointer to net_device structure
* @ param info A pointer to iw_request_info structure
* @ param awrq A pointer to iw_param structure
* @ param extra A pointer to extra data buf
* @ return 0 - - success , otherwise fail
*/
2007-11-15 18:05:47 -05:00
static int lbs_set_wap ( struct net_device * dev , struct iw_request_info * info ,
2007-02-10 12:25:27 -02:00
struct sockaddr * awrq , char * extra )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
struct assoc_request * assoc_req ;
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
2008-08-21 17:51:07 -04:00
if ( ! priv - > radio_on )
return - EINVAL ;
2007-02-10 12:25:27 -02:00
if ( awrq - > sa_family ! = ARPHRD_ETHER )
return - EINVAL ;
2008-10-27 15:59:26 -07:00
lbs_deb_wext ( " ASSOC: WAP: sa_data %pM \n " , awrq - > sa_data ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
/* Get or create the current association request */
2007-12-08 20:04:36 +00:00
assoc_req = lbs_get_association_request ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( ! assoc_req ) {
2007-11-15 18:05:47 -05:00
lbs_cancel_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
ret = - ENOMEM ;
} else {
/* Copy the BSSID to the association request */
memcpy ( & assoc_req - > bssid , awrq - > sa_data , ETH_ALEN ) ;
set_bit ( ASSOC_FLAG_BSSID , & assoc_req - > flags ) ;
2007-11-15 18:05:47 -05:00
lbs_postpone_association_work ( priv ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
/*
* iwconfig settable callbacks
*/
2007-11-15 18:05:47 -05:00
static const iw_handler lbs_handler [ ] = {
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* SIOCSIWCOMMIT */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_get_name , /* SIOCGIWNAME */
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* SIOCSIWNWID */
( iw_handler ) NULL , /* SIOCGIWNWID */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_freq , /* SIOCSIWFREQ */
( iw_handler ) lbs_get_freq , /* SIOCGIWFREQ */
( iw_handler ) lbs_set_mode , /* SIOCSIWMODE */
( iw_handler ) lbs_get_mode , /* SIOCGIWMODE */
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* SIOCSIWSENS */
( iw_handler ) NULL , /* SIOCGIWSENS */
( iw_handler ) NULL , /* SIOCSIWRANGE */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_get_range , /* SIOCGIWRANGE */
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* SIOCSIWPRIV */
( iw_handler ) NULL , /* SIOCGIWPRIV */
( iw_handler ) NULL , /* SIOCSIWSTATS */
( iw_handler ) NULL , /* SIOCGIWSTATS */
iw_handler_set_spy , /* SIOCSIWSPY */
iw_handler_get_spy , /* SIOCGIWSPY */
iw_handler_set_thrspy , /* SIOCSIWTHRSPY */
iw_handler_get_thrspy , /* SIOCGIWTHRSPY */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_wap , /* SIOCSIWAP */
( iw_handler ) lbs_get_wap , /* SIOCGIWAP */
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* SIOCSIWMLME */
( iw_handler ) NULL , /* SIOCGIWAPLIST - deprecated */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_scan , /* SIOCSIWSCAN */
( iw_handler ) lbs_get_scan , /* SIOCGIWSCAN */
( iw_handler ) lbs_set_essid , /* SIOCSIWESSID */
( iw_handler ) lbs_get_essid , /* SIOCGIWESSID */
( iw_handler ) lbs_set_nick , /* SIOCSIWNICKN */
( iw_handler ) lbs_get_nick , /* SIOCGIWNICKN */
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* -- hole -- */
( iw_handler ) NULL , /* -- hole -- */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_rate , /* SIOCSIWRATE */
( iw_handler ) lbs_get_rate , /* SIOCGIWRATE */
( iw_handler ) lbs_set_rts , /* SIOCSIWRTS */
( iw_handler ) lbs_get_rts , /* SIOCGIWRTS */
( iw_handler ) lbs_set_frag , /* SIOCSIWFRAG */
( iw_handler ) lbs_get_frag , /* SIOCGIWFRAG */
( iw_handler ) lbs_set_txpow , /* SIOCSIWTXPOW */
( iw_handler ) lbs_get_txpow , /* SIOCGIWTXPOW */
( iw_handler ) lbs_set_retry , /* SIOCSIWRETRY */
( iw_handler ) lbs_get_retry , /* SIOCGIWRETRY */
( iw_handler ) lbs_set_encode , /* SIOCSIWENCODE */
( iw_handler ) lbs_get_encode , /* SIOCGIWENCODE */
( iw_handler ) lbs_set_power , /* SIOCSIWPOWER */
( iw_handler ) lbs_get_power , /* SIOCGIWPOWER */
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* -- hole -- */
( iw_handler ) NULL , /* -- hole -- */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_genie , /* SIOCSIWGENIE */
( iw_handler ) lbs_get_genie , /* SIOCGIWGENIE */
( iw_handler ) lbs_set_auth , /* SIOCSIWAUTH */
( iw_handler ) lbs_get_auth , /* SIOCGIWAUTH */
( iw_handler ) lbs_set_encodeext , /* SIOCSIWENCODEEXT */
( iw_handler ) lbs_get_encodeext , /* SIOCGIWENCODEEXT */
2007-02-10 12:25:27 -02:00
( iw_handler ) NULL , /* SIOCSIWPMKSA */
} ;
2009-12-02 15:26:02 +01:00
struct iw_handler_def lbs_handler_def = {
. num_standard = ARRAY_SIZE ( lbs_handler ) ,
. standard = ( iw_handler * ) lbs_handler ,
. get_wireless_stats = lbs_get_wireless_stats ,
} ;
2007-02-10 12:25:27 -02:00
2009-12-02 15:26:02 +01:00
# ifdef CONFIG_LIBERTAS_MESH
2007-05-25 23:08:34 -04:00
static const iw_handler mesh_wlan_handler [ ] = {
( iw_handler ) NULL , /* SIOCSIWCOMMIT */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_get_name , /* SIOCGIWNAME */
2007-05-25 23:08:34 -04:00
( iw_handler ) NULL , /* SIOCSIWNWID */
( iw_handler ) NULL , /* SIOCGIWNWID */
2007-12-11 19:56:28 -05:00
( iw_handler ) lbs_mesh_set_freq , /* SIOCSIWFREQ */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_get_freq , /* SIOCGIWFREQ */
2007-05-25 23:08:34 -04:00
( iw_handler ) NULL , /* SIOCSIWMODE */
( iw_handler ) mesh_wlan_get_mode , /* SIOCGIWMODE */
( iw_handler ) NULL , /* SIOCSIWSENS */
( iw_handler ) NULL , /* SIOCGIWSENS */
( iw_handler ) NULL , /* SIOCSIWRANGE */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_get_range , /* SIOCGIWRANGE */
2007-05-25 23:08:34 -04:00
( iw_handler ) NULL , /* SIOCSIWPRIV */
( iw_handler ) NULL , /* SIOCGIWPRIV */
( iw_handler ) NULL , /* SIOCSIWSTATS */
( iw_handler ) NULL , /* SIOCGIWSTATS */
iw_handler_set_spy , /* SIOCSIWSPY */
iw_handler_get_spy , /* SIOCGIWSPY */
iw_handler_set_thrspy , /* SIOCSIWTHRSPY */
iw_handler_get_thrspy , /* SIOCGIWTHRSPY */
( iw_handler ) NULL , /* SIOCSIWAP */
( iw_handler ) NULL , /* SIOCGIWAP */
( iw_handler ) NULL , /* SIOCSIWMLME */
( iw_handler ) NULL , /* SIOCGIWAPLIST - deprecated */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_scan , /* SIOCSIWSCAN */
( iw_handler ) lbs_get_scan , /* SIOCGIWSCAN */
2007-12-11 19:30:57 -05:00
( iw_handler ) lbs_mesh_set_essid , /* SIOCSIWESSID */
( iw_handler ) lbs_mesh_get_essid , /* SIOCGIWESSID */
2007-05-25 23:08:34 -04:00
( iw_handler ) NULL , /* SIOCSIWNICKN */
( iw_handler ) mesh_get_nick , /* SIOCGIWNICKN */
( iw_handler ) NULL , /* -- hole -- */
( iw_handler ) NULL , /* -- hole -- */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_rate , /* SIOCSIWRATE */
( iw_handler ) lbs_get_rate , /* SIOCGIWRATE */
( iw_handler ) lbs_set_rts , /* SIOCSIWRTS */
( iw_handler ) lbs_get_rts , /* SIOCGIWRTS */
( iw_handler ) lbs_set_frag , /* SIOCSIWFRAG */
( iw_handler ) lbs_get_frag , /* SIOCGIWFRAG */
( iw_handler ) lbs_set_txpow , /* SIOCSIWTXPOW */
( iw_handler ) lbs_get_txpow , /* SIOCGIWTXPOW */
( iw_handler ) lbs_set_retry , /* SIOCSIWRETRY */
( iw_handler ) lbs_get_retry , /* SIOCGIWRETRY */
( iw_handler ) lbs_set_encode , /* SIOCSIWENCODE */
( iw_handler ) lbs_get_encode , /* SIOCGIWENCODE */
( iw_handler ) lbs_set_power , /* SIOCSIWPOWER */
( iw_handler ) lbs_get_power , /* SIOCGIWPOWER */
2007-05-25 23:08:34 -04:00
( iw_handler ) NULL , /* -- hole -- */
( iw_handler ) NULL , /* -- hole -- */
2007-11-15 18:05:47 -05:00
( iw_handler ) lbs_set_genie , /* SIOCSIWGENIE */
( iw_handler ) lbs_get_genie , /* SIOCGIWGENIE */
( iw_handler ) lbs_set_auth , /* SIOCSIWAUTH */
( iw_handler ) lbs_get_auth , /* SIOCGIWAUTH */
( iw_handler ) lbs_set_encodeext , /* SIOCSIWENCODEEXT */
( iw_handler ) lbs_get_encodeext , /* SIOCGIWENCODEEXT */
2007-05-25 23:08:34 -04:00
( iw_handler ) NULL , /* SIOCSIWPMKSA */
} ;
struct iw_handler_def mesh_handler_def = {
2007-09-02 18:30:18 +08:00
. num_standard = ARRAY_SIZE ( mesh_wlan_handler ) ,
2007-05-25 23:08:34 -04:00
. standard = ( iw_handler * ) mesh_wlan_handler ,
2007-11-15 18:05:47 -05:00
. get_wireless_stats = lbs_get_wireless_stats ,
2007-05-25 23:08:34 -04:00
} ;
2009-12-02 15:26:02 +01:00
# endif