M7350/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_comapi.c
2024-09-09 08:59:52 +00:00

3995 lines
101 KiB
C
Executable File

/*
* API-compatible handling routines
*
*
*
* Copyright (c) 2009 Realtek Semiconductor Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define _8192CD_COMAPI_C_
#ifdef __KERNEL__
#include <linux/module.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/unistd.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/delay.h>
#endif
#ifdef __LINUX_2_6__
#include <linux/initrd.h>
#include <linux/syscalls.h>
#endif
#include "./8192cd_debug.h"
#include "./8192cd_comapi.h"
#include "./8192cd_headers.h"
#ifdef CONFIG_RTL_COMAPI_WLTOOLS
#include <linux/if_arp.h>
#include <net/iw_handler.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_A, _B, _C, _D, _E)
#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_A, _B, _C, _D, _E)
#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_A, _B, _C, _D, _E, _F)
#else
#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_B, _C, _D, _E)
#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_B, _C, _D, _E)
#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_B, _C, _D, _E, _F)
#endif
typedef struct _CH_FREQ_MAP_{
UINT16 channel;
UINT16 freqKHz;
}CH_FREQ_MAP;
CH_FREQ_MAP CH_HZ_ID_MAP[] =
{
{1, 2412},
{2, 2417},
{3, 2422},
{4, 2427},
{5, 2432},
{6, 2437},
{7, 2442},
{8, 2447},
{9, 2452},
{10, 2457},
{11, 2462},
{12, 2467},
{13, 2472},
{14, 2484},
/* UNII */
{36, 5180},
{40, 5200},
{44, 5220},
{48, 5240},
{52, 5260},
{56, 5280},
{60, 5300},
{64, 5320},
{149, 5745},
{153, 5765},
{157, 5785},
{161, 5805},
{165, 5825},
{167, 5835},
{169, 5845},
{171, 5855},
{173, 5865},
/* HiperLAN2 */
{100, 5500},
{104, 5520},
{108, 5540},
{112, 5560},
{116, 5580},
{120, 5600},
{124, 5620},
{128, 5640},
{132, 5660},
{136, 5680},
{140, 5700},
/* Japan MMAC */
{34, 5170},
{38, 5190},
{42, 5210},
{46, 5230},
/* Japan */
{184, 4920},
{188, 4940},
{192, 4960},
{196, 4980},
{208, 5040}, /* Japan, means J08 */
{212, 5060}, /* Japan, means J12 */
{216, 5080}, /* Japan, means J16 */
};
int CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP)/sizeof(CH_FREQ_MAP));
#define MAP_CHANNEL_ID_TO_KHZ(_ch, _khz) \
do{ \
int _chIdx; \
for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\
{ \
if ((_ch) == CH_HZ_ID_MAP[_chIdx].channel) \
{ \
(_khz) = CH_HZ_ID_MAP[_chIdx].freqKHz * 1000; \
break; \
} \
} \
if (_chIdx == CH_HZ_ID_MAP_NUM) \
(_khz) = 2412000; \
}while(0)
#define MAP_KHZ_TO_CHANNEL_ID(_khz, _ch) \
do{ \
int _chIdx; \
for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\
{ \
if ((_khz) == CH_HZ_ID_MAP[_chIdx].freqKHz) \
{ \
(_ch) = CH_HZ_ID_MAP[_chIdx].channel; \
break; \
} \
} \
if (_chIdx == CH_HZ_ID_MAP_NUM) \
(_ch) = 1; \
}while(0)
/*
struct iw_statistics *rtl8192cd_get_wireless_stats(struct net_device *net_dev)
{
// client mode only
return NULL;
}
*/
#ifdef WIFI_WPAS_CLI
extern void clean_for_join(struct rtl8192cd_priv *priv);
void use_ap_scan( RTL_PRIV *priv )
{
RTL_PRIV *r_priv;
priv->pshare->bScanInProcess = FALSE;
if ( IS_ROOT_INTERFACE(priv) ) {
printk("cliW: ss_req\n");
priv->ss_req_ongoing = 1;
start_clnt_ss(priv);
} else {
printk("cliW: vxd req\n");
r_priv = GET_ROOT(priv);
r_priv->ss_ssidlen = 0;
r_priv->ss_req_ongoing = SSFROM_WPAS;
start_clnt_ss(r_priv);
}
}
#if 0
void switch_chan(struct rtl8192cd_priv *priv, struct bss_desc *bss_desp)
{
struct rtl8192cd_priv *root_priv;
u8 is_40m, channel, ch_offset;
int bw;
unsigned long flags;
printk("vxd chan follows\n");
//RTL_W8(TXPAUSE, 0xff);
channel = bss_desp->channel;
priv->pmib->dot11RFEntry.dot11channel = channel;
if ((bss_desp->t_stamp[1] & (BIT(1) | BIT(2))) == (BIT(1) | BIT(2)))
ch_offset = HT_2NDCH_OFFSET_BELOW;
else if ((bss_desp->t_stamp[1] & (BIT(1)|BIT(2))) == BIT(1))
ch_offset = HT_2NDCH_OFFSET_ABOVE;
else
ch_offset = HT_2NDCH_OFFSET_DONTCARE;
if ( ch_offset != 0 )
is_40m = 1;
if ( IS_VXD_INTERFACE(priv) ) {
root_priv = GET_ROOT(priv);
bw = (root_priv->pmib->dot11nConfigEntry.dot11nUse40M && is_40m);
if (0 == bw)
ch_offset = HT_2NDCH_OFFSET_DONTCARE;
priv->pshare->is_40m_bw = bw;
priv->pshare->CurrentChannelBW = bw;
priv->pshare->offset_2nd_chan = ch_offset;
priv->pmib->dot11RFEntry.dot11channel = channel;
priv->pmib->dot11nConfigEntry.dot11nUse40M = bw;
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset;
root_priv->pmib->dot11RFEntry.dot11channel = channel;
root_priv->pmib->dot11nConfigEntry.dot11nUse40M = bw;
root_priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset;
root_priv->ht_cap_len = 0; // re-construct HT IE
init_beacon(root_priv);
#ifdef MBSSID
if (root_priv->pmib->miscEntry.vap_enable) {
struct rtl8192cd_priv *vap_priv;
int i;
for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) {
vap_priv = root_priv->pvap_priv[i];
if (IS_DRV_OPEN(vap_priv)) {
vap_priv->pmib->dot11RFEntry.dot11channel = channel;
vap_priv->pmib->dot11nConfigEntry.dot11nUse40M = bw;
vap_priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset;
vap_priv->ht_cap_len = 0; // re-construct HT IE
init_beacon(vap_priv);
}
}
}
#endif // MBSSID
} else {
root_priv = priv;
priv->pshare->is_40m_bw = is_40m;
priv->pshare->CurrentChannelBW = is_40m;
priv->pshare->offset_2nd_chan = ch_offset;
priv->pmib->dot11RFEntry.dot11channel = channel;
priv->pmib->dot11nConfigEntry.dot11nUse40M = is_40m;
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset;
#ifdef UNIVERSAL_REPEATER
// TO DO ...
#endif
}
SwBWMode(root_priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan);
SwChnl(root_priv, channel, priv->pshare->offset_2nd_chan);
// RTL_W8(TXPAUSE, 0x00);
// update_beacon
}
#endif
int rtl_wx_dummy(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
return -1;
}
int rtl_wx_join(struct rtl8192cd_priv *priv, struct bss_desc *bss_desp)
{
char tmpbuf[33];
printk("cliW: join opmode: %x res:%x \n", OPMODE, priv->join_res);
if (!netif_running(priv->dev))
{
printk("WiFi driver is NOT open!!\n");
return 1;
}
else if (priv->ss_req_ongoing)
{
printk("Site Survey is not finished yet!!\n");
return 2;
}
//if ( priv->join_res == STATE_Sta_No_Bss )
// goto cnti_join;
// memcpy((void *)&(priv->pmib->dot11Bss) ,
// (void *)&priv->site_survey->bss_backup[bss_num] , sizeof(struct bss_desc));
memcpy(&(priv->pmib->dot11Bss), bss_desp, sizeof(struct bss_desc));
#if 0
if ( priv->join_req_ongoing ) {
printk("cliW: no join under connecinting \n");
return 0;
}
#endif
if( ( priv->pmib->dot11Bss.ssidlen < 0) || (priv->pmib->dot11Bss.ssidlen > 32) ) {
printk("cliW: wrong ssid len\n");
return 3;
}
#if 0
if (priv->ss_req_ongoing || priv->join_req_ongoing ) {
printk("cliW: no join under scanning \n");
return 0;
}
#endif
if ( OPMODE & ( WIFI_AUTH_STATE1 | WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE) ) {
printk("cliW: no joining when in auth\n");
return 4;
}
#if 0
if ( OPMODE & WIFI_ASOC_STATE || (priv->join_res == STATE_Sta_Bss) ) {
printk("cliW: no joining when in asso\n");
return 0;
}
#endif
#ifdef WIFI_SIMPLE_CONFIG
//_Eric if (priv->pmib->wscEntry.wsc_enable && (priv->pmib->dot11Bss.bsstype&WIFI_WPS))
if (priv->pmib->wscEntry.wsc_enable)
{
//priv->pmib->dot11Bss.bsstype &= ~WIFI_WPS;
priv->wps_issue_join_req = 1;
}
else
#endif
{
if (check_bss_encrypt(priv) == FAIL)
{
printk("Encryption mismatch!\n");
return 5;
}
}
if ((priv->pmib->dot11Bss.ssidlen == 0) || (priv->pmib->dot11Bss.ssid[0] == '\0'))
{
printk("Error !! Join to a hidden AP!\n");
return 6;
}
#ifdef UNIVERSAL_REPEATER
disable_vxd_ap(GET_VXD_PRIV(priv));
#endif
memcpy(tmpbuf, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen);
tmpbuf[priv->pmib->dot11Bss.ssidlen] = '\0';
printk("going to join bss: %s\n", tmpbuf);
memcpy(SSID2SCAN, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen);
SSID2SCAN_LEN = priv->pmib->dot11Bss.ssidlen;
SSID_LEN = SSID2SCAN_LEN;
memcpy(SSID, SSID2SCAN, SSID_LEN);
memset(BSSID, 0, MACADDRLEN);
#ifdef INCLUDE_WPA_PSK //_Eric ??
//if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK)
//derivePSK(priv);
#endif
priv->join_req_ongoing = 1;
priv->authModeRetry = 0;
// switch_chan() is replaced with clnt_switch_chan_to_bss in start_clnt_auth
//switch_chan(priv, bss_desp);
printk("cliw: start join... in ch:%d\n", bss_desp->channel);
#if defined(CONFIG_PCI_HCI)
start_clnt_join(priv);
#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
// avoid IQK handling race condition between start_clnt_auth and TXPowerTracking
// so we indicate WPAS_JOIN event to cmd_thread to do start_clnt_join()
notify_wpas_join(priv);
#endif
return 0;
}
int rtl_wx_get_name(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct stat_info *pstat;
struct wifi_mib *pmib;
char *p;
DEBUG_INFO("cmd_code=%x\n", info->cmd);
DBFENTER;
pstat = priv->pstat_cache;
if (pstat == NULL) {
DEBUG_INFO("pstat is NULL\n");
return 0;
}
pmib = GET_MIB(priv);
if ((pstat->state & (WIFI_ASOC_STATE | WIFI_AUTH_SUCCESS)) == ((WIFI_ASOC_STATE | WIFI_AUTH_SUCCESS)))
{
p = wrqu->name;
p += sprintf(p, "IEEE 802.11");
if (pmib->dot11BssType.net_work_type & WIRELESS_11A) {
p += sprintf(p, "a");
}
if (pmib->dot11BssType.net_work_type & WIRELESS_11B) {
p += sprintf(p, "b");
}
if (pmib->dot11BssType.net_work_type & WIRELESS_11G) {
p += sprintf(p, "g");
}
if (pmib->dot11BssType.net_work_type & WIRELESS_11N) {
p += sprintf(p, "n");
}
if (pmib->dot11BssType.net_work_type & WIRELESS_11AC) {
p += sprintf(p, "ac");
}
}
else
{
//prates = &padapter->registrypriv.dev_network.SupportedRates;
//snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
snprintf(wrqu->name, IFNAMSIZ, "off/any");
}
DBFEXIT;
return 0;
}
int rtl_wx_set_mode(struct net_device *dev, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0;
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
switch(wrqu->mode)
{
case IW_MODE_AUTO:
if (OPMODE & WIFI_STATION_STATE) {
OPMODE = WIFI_STATION_STATE;
printk("set_mode = IW_MODE_AUTO ==> WIFI_STATION_STATE\n");
} else {
OPMODE = WIFI_AP_STATE;
printk("set_mode = IW_MODE_AUTO ==> WIFI_AP_STATE\n");
}
break;
case IW_MODE_ADHOC:
OPMODE = WIFI_ADHOC_STATE;
printk("set_mode = IW_MODE_ADHOC\n");
break;
case IW_MODE_MASTER:
OPMODE = WIFI_AP_STATE;
printk("set_mode = IW_MODE_MASTER\n");
break;
case IW_MODE_INFRA:
OPMODE = WIFI_STATION_STATE;
printk("set_mode = IW_MODE_INFRA\n");
break;
default :
ret = -EINVAL;
DEBUG_WARN("Mode: %d is not supported\n", wrqu->mode);
break;
}
// TODO: Active the Operation Mode
return ret;
}
int rtl_wx_get_sens(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
wrqu->sens.value = 0;
wrqu->sens.fixed = 0; /* no auto select */
wrqu->sens.disabled = 1;
return 0;
}
void clean_conn_var(RTL_PRIV *priv)
{
if (timer_pending(&priv->reauth_timer))
del_timer_sync (&priv->reauth_timer);
if (timer_pending(&priv->reassoc_timer))
del_timer_sync (&priv->reassoc_timer);
#if 0
priv->reauth_count = 0;
priv->reassoc_count = 0;
priv->auth_seq = 0;
priv->join_res = STATE_Sta_No_Bss;
priv->reauth_count = 0;
priv->reassoc_count = 0;
#endif
priv->join_req_ongoing = 0;
priv->ss_req_ongoing = 0;
clean_for_join(priv);
}
#if WIRELESS_EXT >= 18
int rtl_wx_set_mlme(
struct net_device *dev,
struct iw_request_info *info,
struct iw_point *erq,
char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct iw_mlme *wextmlme = (struct iw_mlme *)extra;
struct stat_info *pstat;
#ifdef SDIO_AP_OFFLOAD
ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_COMAPI);
#endif
switch(wextmlme->cmd) {
case IW_MLME_DEAUTH:
printk("Set MLME: IW_MLME_DEAUTH, Reason=%d\n", wextmlme->reason_code);
if (OPMODE & (WIFI_AUTH_SUCCESS))
{
issue_deauth(priv,BSSID,wextmlme->reason_code);
delay_ms(50); //Give some time to wait TX done
OPMODE &= ~(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE) ;
pstat = get_stainfo(priv, BSSID);
if (pstat != NULL)
{
if (asoc_list_del(priv, pstat))
{
if (pstat->expire_to > 0)
{
cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__);
check_sta_characteristic(priv, pstat, DECREASE);
}
}
free_stainfo(priv, pstat);
}
event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL);
}
clean_conn_var(priv);
break;
case IW_MLME_DISASSOC:
printk("Set MLME: IW_MLME_DISASSOC, Reason=%d\n", wextmlme->reason_code);
if((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE))
{
pstat = get_stainfo(priv, BSSID);
issue_disassoc(priv, BSSID, wextmlme->reason_code);
if (pstat != NULL)
{
if (pstat->expire_to > 0)
{
cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__);
check_sta_characteristic(priv, pstat, DECREASE);
}
free_stainfo(priv, pstat);
/* memset(&priv->pmib->dot11Bss, 0, sizeof(struct bss_desc));
memset(priv->pmib->dot11StationConfigEntry.dot11Bssid, 0, MACADDRLEN);
memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID));
priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = 0;
memset(priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID));
priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen = 0;
memset(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan));
priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen = 0;
memset(priv->pmib->dot11StationConfigEntry.dot11DesiredBssid, 0, 6);
priv->wpas_manual_assoc = 1; //_Eric ?? when to let driver auto-connect ??
*/
priv->join_res = STATE_Sta_No_Bss;
// pstat->state &= (~WIFI_ASOC_STATE);
}
}
OPMODE &= ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE);
event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL);
clean_conn_var(priv);
break;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
case IW_MLME_AUTH:
case IW_MLME_ASSOC:
break;
#endif
default:
#ifdef SDIO_AP_OFFLOAD
ap_offload_activate(priv, OFFLOAD_PROHIBIT_COMAPI);
#endif
return -EINVAL;
}
#ifdef SDIO_AP_OFFLOAD
ap_offload_activate(priv, OFFLOAD_PROHIBIT_COMAPI);
#endif
return 0;
}
#endif
int rtl_wx_get_freq(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
unsigned int ch;
unsigned long khz;
if (priv == NULL) {
/* if 1st open fail, pAd will be free;
* So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
ch = priv->pmib->dot11RFEntry.dot11channel;
MAP_CHANNEL_ID_TO_KHZ(ch, khz);
wrqu->freq.m = khz * 100;
wrqu->freq.e = 1;
wrqu->freq.i = ch;
return 0;
}
#endif // WIFI_WPAS_CLI
int rtl_siwfreq(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
unsigned int chan=0;
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if (wrqu->freq.e > 1)
return -EINVAL;
if((wrqu->freq.e == 0) && (wrqu->freq.m <= 1000))
chan = wrqu->freq.m; // Setting by channel number
else
#ifdef WIFI_WPAS_CLI
MAP_KHZ_TO_CHANNEL_ID( (wrqu->freq.m /100000) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G,
#else
MAP_KHZ_TO_CHANNEL_ID( (wrqu->freq.m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G,
#endif
priv->pmib->dot11RFEntry.dot11channel = chan;
#ifdef WIFI_WPAS_CLI
printk("cliW: wrqu->freq.m: %d chan:%d \n", wrqu->freq.m, chan);
#else
#ifdef WIFI_HAPD
if (!netif_running(priv->dev))
return 0;
else
#endif
SwChnl(priv, chan, priv->pshare->offset_2nd_chan);
#endif
return 0;
}
int rtl_giwfreq(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
unsigned int ch;
//unsigned long m = 2412000;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
ch = priv->pmib->dot11RFEntry.dot11channel;
/*
MAP_CHANNEL_ID_TO_KHZ(ch, m);
wrqu->freq.m = m * 100;
wrqu->freq.e = 1;
wrqu->freq.i = 0;
*/
wrqu->freq.m = ch;
wrqu->freq.e = 0;
wrqu->freq.i = 0;
return 0;
}
int rtl_siwmode(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret = 0;
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef SUPPORT_MONITOR
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
#endif
switch(wrqu->mode)
{
case IW_MODE_AUTO: // 0
#ifdef WIFI_WPAS_CLI
if (OPMODE & WIFI_STATION_STATE) {
OPMODE_VAL(OPMODE & WIFI_STATION_STATE);
printk("set_mode = IW_MODE_AUTO ==> WIFI_STATION_STATE\n");
} else {
OPMODE_VAL(OPMODE & WIFI_AP_STATE);
printk("set_mode = IW_MODE_AUTO ==> WIFI_AP_STATE\n");
}
#else
OPMODE_VAL(OPMODE & WIFI_AP_STATE);
printk("set_mode = IW_MODE_AUTO\n");
#endif
break;
case IW_MODE_ADHOC: // 1
OPMODE_VAL(OPMODE & WIFI_ADHOC_STATE);
printk("set_mode = IW_MODE_ADHOC\n");
break;
case IW_MODE_MASTER: // 3
OPMODE_VAL(OPMODE & WIFI_AP_STATE);
#ifdef SUPPORT_MONITOR
priv->is_monitor_mode = FALSE;
panic_printk("priv->is_monitor_mode = %d,\n", priv->is_monitor_mode);
del_timer(&priv->chan_switch_timer);
#endif
printk("set_mode = IW_MODE_MASTER\n");
// setopmode_cmd(padapter, networkType);
break;
case IW_MODE_INFRA: // 2
OPMODE_VAL(OPMODE & WIFI_STATION_STATE);
printk("set_mode = IW_MODE_INFRA\n");
break;
#ifdef SUPPORT_MONITOR
case IW_MODE_MONITOR:
OPMODE |= WIFI_SITE_MONITOR;
priv->is_monitor_mode = TRUE;
priv->chan_num = 0;
RTL_W32(RCR, RCR_APP_FCS | RCR_APP_MIC | RCR_APP_ICV | RCR_APP_PHYSTS | RCR_HTC_LOC_CTRL
| RCR_AMF | RCR_ADF | RCR_AICV | RCR_ACRC32 | RCR_CBSSID_ADHOC | RCR_AB | RCR_AM | RCR_APM | RCR_AAP);
init_timer(&priv->chan_switch_timer);
priv->chan_switch_timer.data = (unsigned long) priv;
priv->chan_switch_timer.function = rtl8192cd_chan_switch_timer;
SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan);
SwChnl(priv, priv->available_chnl[priv->chan_num], priv->pshare->offset_2nd_chan);
mod_timer(&priv->chan_switch_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.chan_switch_time));
panic_printk("priv->is_monitor_mode = %d \n", priv->is_monitor_mode);
panic_printk("set_mode = IW_MODE_MONITOR\n");
break;
#endif
default :
ret = -EINVAL;
}
return ret;
}
int rtl_giwmode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if (OPMODE & WIFI_AP_STATE)
wrqu->mode = IW_MODE_MASTER;
else if (OPMODE & WIFI_STATION_STATE)
wrqu->mode = IW_MODE_INFRA;
else if (OPMODE & WIFI_ADHOC_STATE)
wrqu->mode = IW_MODE_ADHOC;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
else if (OPMODE & WIFI_SITE_MONITOR)
wrqu->mode = IW_MODE_MONITOR;
#endif
else
wrqu->mode = IW_MODE_AUTO;
return 0;
}
#define MAX_FRAG_THRESHOLD 2346
#define MIN_FRAG_THRESHOLD 256
#define MAX_RTS_THRESHOLD 2347
#ifdef BALONG_PLT
enum ANDROID_WIFI_CMD {
ANDROID_WIFI_CMD_START,
ANDROID_WIFI_CMD_STOP,
ANDROID_WIFI_CMD_SCAN_ACTIVE,
ANDROID_WIFI_CMD_SCAN_PASSIVE,
ANDROID_WIFI_CMD_RSSI,
ANDROID_WIFI_CMD_LINKSPEED,
ANDROID_WIFI_CMD_RXFILTER_START,
ANDROID_WIFI_CMD_RXFILTER_STOP,
ANDROID_WIFI_CMD_RXFILTER_ADD,
ANDROID_WIFI_CMD_RXFILTER_REMOVE,
ANDROID_WIFI_CMD_BTCOEXSCAN_START,
ANDROID_WIFI_CMD_BTCOEXSCAN_STOP,
ANDROID_WIFI_CMD_BTCOEXMODE,
ANDROID_WIFI_CMD_SETSUSPENDOPT,
ANDROID_WIFI_CMD_P2P_DEV_ADDR,
ANDROID_WIFI_CMD_SETFWPATH,
ANDROID_WIFI_CMD_SETBAND,
ANDROID_WIFI_CMD_GETBAND,
ANDROID_WIFI_CMD_COUNTRY,
ANDROID_WIFI_CMD_P2P_SET_NOA,
ANDROID_WIFI_CMD_P2P_GET_NOA,
ANDROID_WIFI_CMD_P2P_SET_PS,
ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE,
#ifdef PNO_SUPPORT
ANDROID_WIFI_CMD_PNOSSIDCLR_SET,
ANDROID_WIFI_CMD_PNOSETUP_SET,
ANDROID_WIFI_CMD_PNOENABLE_SET,
ANDROID_WIFI_CMD_PNODEBUG_SET,
#endif
ANDROID_WIFI_CMD_MACADDR,
ANDROID_WIFI_CMD_BLOCK,
ANDROID_WIFI_CMD_WFD_ENABLE,
ANDROID_WIFI_CMD_WFD_DISABLE,
ANDROID_WIFI_CMD_WFD_SET_TCPPORT,
ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT,
ANDROID_WIFI_CMD_WFD_SET_DEVTYPE,
ANDROID_WIFI_CMD_SET_KEEP_ALIVE,
PRIV_WIFI_CMD_CSCAN_S,
ANDROID_WIFI_CMD_MAX
};
const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
"START",
"STOP",
"SCAN-ACTIVE",
"SCAN-PASSIVE",
"RSSI",
"LINKSPEED",
"RXFILTER-START",
"RXFILTER-STOP",
"RXFILTER-ADD",
"RXFILTER-REMOVE",
"BTCOEXSCAN-START",
"BTCOEXSCAN-STOP",
"BTCOEXMODE",
"SETSUSPENDOPT",
"P2P_DEV_ADDR",
"SETFWPATH",
"SETBAND",
"GETBAND",
"COUNTRY",
"P2P_SET_NOA",
"P2P_GET_NOA",
"P2P_SET_PS",
"SET_AP_WPS_P2P_IE",
#ifdef PNO_SUPPORT
"PNOSSIDCLR",
"PNOSETUP ",
"PNOFORCE",
"PNODEBUG",
#endif
"MACADDR",
"BLOCK",
"WFD-ENABLE",
"WFD-DISABLE",
"WFD-SET-TCPPORT",
"WFD-SET-MAXTPUT",
"WFD-SET-DEVTYPE",
"KEEP_ALIVE",
"CSCAN S"
};
int rtw_android_cmdstr_to_num(char *cmdstr)
{
int cmd_num;
int i;
if ( cmdstr == NULL ) {
printk("cliw: no comp str\n");
return 0;
}
// printk("cliW: ANDROID_WIFI_CMD=%s\n", cmdstr);
for(cmd_num=0 ; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++) {
if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
break;
}
return cmd_num;
}
char tmp_str[256];
int rtl_sipriv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *awrq,
char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL )
return -ENETDOWN;
printk("cliW: rtl_sipriv\n");
}
#define WEXT_CSCAN_HEADER_SIZE 12
#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
#define WEXT_CSCAN_SSID_SECTION 'S'
// format : len - 1B , ssid
#define WEXT_CSCAN_CHANNEL_SECTION 'C'
// ch: 1B
#define WEXT_CSCAN_NPROBE_SECTION 'N'
// 1B
#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
// 2B
#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
// 2B
#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
// 2B
struct combo_scan ssid_scan_list[CSCAN_MAXNUM];
void parse_combo_ssid_info(char *ext)
{
int ssid_cnt = 0;
int i;
unsigned char ssid_len;
char *bp = ext;
char buf[256];
#if 0
if ( strlen(ext) < WEXT_CSCAN_HEADER_SIZE + 3 ) {
printk("cliW: combo scan erro format: %d\n");
return;
}
#endif
printk("cliQ: start parse combo scan\n");
for (i=0 ; i< CSCAN_MAXNUM; i++);
memset(&ssid_scan_list[0], 0, sizeof(struct combo_scan));
bp = ext + WEXT_CSCAN_HEADER_SIZE;
while( bp != NULL ) {
// printk("cliW: %x %x %x %x\n", *bp, *(bp+1), *(bp+2), 'S');
if ( *bp == WEXT_CSCAN_SSID_SECTION ) {
if ( *(bp + 1) == 0 ) {
printk("cliW: ssid ==0 \n");
return;
}
ssid_len = *(bp + 1);
//memcpy(buf, (bp + 2) , ssid_len);
//buf[ssid_len] = '\0';
memcpy(ssid_scan_list[ssid_cnt].ssid, (bp + 2) , ssid_len);
ssid_scan_list[ssid_cnt].ssid[ssid_len] = '\0';
ssid_scan_list[ssid_cnt].ssid_len = ssid_len;
ssid_scan_list[ssid_cnt].used = 1;
if ( ssid_cnt > CSCAN_MAXNUM ) {
printk("cliQ: ssid list more than max, skip\n");
bp += ssid_len + 1;
continue;
}
printk("cliQ:ssid %d %s\n", ssid_len, ssid_scan_list[ssid_cnt].ssid);
ssid_cnt++;
bp += ssid_len + 2;
} else if ( *bp == WEXT_CSCAN_CHANNEL_SECTION || *bp == WEXT_CSCAN_NPROBE_SECTION ) {
i = *(bp + 1);
if ( *bp == WEXT_CSCAN_CHANNEL_SECTION )
printk("cliQ: scan ch:%d\n", i);
if ( *bp == WEXT_CSCAN_NPROBE_SECTION )
printk("cliQ: scan np probe:%d\n", i);
bp += 2;
} else {
i = *(bp + 1);
if ( *bp == WEXT_CSCAN_ACTV_DWELL_SECTION ) {
printk("cliQ: scan active dwell time:%d\n", i);
} else if ( *bp == WEXT_CSCAN_PASV_DWELL_SECTION ) {
printk("cliQ: scan passive dwell time:%d\n", i);
} else if ( *bp == WEXT_CSCAN_HOME_DWELL_SECTION ) {
printk("cliQ: scan home dwell time:%d\n", i);
printk("cliQ: parse done\n");
return;
} else {
printk("cliQ: parse parm error \n");
return;
}
bp += 3;
}
}
}
int rtl_gipriv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *awrq,
char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct stat_info *pstat;
int ret = 0, len = 0;
int i;
char *ext;
struct iw_point *dwrq = (struct iw_point*)awrq;
if (priv == NULL )
return -ENETDOWN;
#if !(defined(WIFI_HAPD) || defined (WIFI_WPAS))
if (!netif_running(priv->dev))
return -ENETDOWN;
#endif
#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved))
return -ENETDOWN;
#endif
len = dwrq->length;
ext = tmp_str;
if (copy_from_user(ext, dwrq->pointer, len)) {
return -EFAULT;
}
i = rtw_android_cmdstr_to_num(ext);
// printk("acli: gipriv 1 num:%d\n", i);
switch(i) {
case ANDROID_WIFI_CMD_SET_KEEP_ALIVE :
if ( (OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE) )
{
char *pch, *ptmp, *token, *tmp[3]={0x00,0x00,0x00};
u32 prd;
pch = ext;
i = 0;
printk("get cmd SET_KEEP_ALIVE \n");
while ((token = strsep(&pch, " ")) != NULL) {
if (i > 2) break;
tmp[i] = token;
i++;
}
#if 0
if ( i >=2 ) {
// printk("s1:%s s2:%s s3:%s\n", tmp[0], tmp[1], tmp[2]);
prd = simple_strtoul(tmp[1], &ptmp, 10);
// printk("prd:%d\n", prd);
if ( prd >= 1000 ) {
priv->keep_alive_time = prd / 1000;
}
}
#endif
sprintf(ext, "OK");
}
break;
case ANDROID_WIFI_CMD_RSSI :
if ( (OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE) )
{
pstat = get_stainfo(priv, BSSID);
sprintf(ext, "%s rssi %d", SSID, (pstat->rssi - 100) );
#if 0
printk("cliW: %s\n", ext);
printk("cliW: dbm: %d\n", translate_percentage_to_dbm(pstat->rssi));
printk("cliW: sg %d\n", pstat->sq);
#endif
} else {
sprintf(ext, "OK");
// printk("cliW: %s\n", ext);
}
break;
case PRIV_WIFI_CMD_CSCAN_S:
parse_combo_ssid_info(ext);
if (IS_VXD_INTERFACE(priv)) {
priv->ss_req_ongoing = 1;
use_ap_scan(priv);
} else {
priv->ss_req_ongoing = 1;
start_clnt_ss(priv);
}
sprintf(ext, "OK");
break;
default :
printk("cmd not found: %s\n", ext);
sprintf(ext, "OK");
}
if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext)+1)) ) )
ret = -EFAULT;
out:
return 0;
}
#endif // BALONG_PLT
int rtl_giwrange(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct iw_range *range = (struct iw_range *)extra;
int i;
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL || range == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
wrqu->data.length = sizeof(*range);
memset(range, 0, sizeof(*range));
/* Let's try to keep this struct in the same order as in
* linux/include/wireless.h
*/
/* TODO: See what values we can set, and remove the ones we can't
* set, or fill them with some default data.
*/
/* ~5 Mb/s real (802.11b) */
range->throughput = 5 * 1000 * 1000;
// TODO: Not used in 802.11b?
// range->min_nwid; /* Minimal NWID we are able to set */
// TODO: Not used in 802.11b?
// range->max_nwid; /* Maximal NWID we are able to set */
/* Old Frequency (backward compat - moved lower ) */
// range->old_num_channels;
// range->old_num_frequency;
// range->old_freq[6]; /* Filler to keep "version" at the same offset */
/* signal level threshold range */
//percent values between 0 and 100.
range->max_qual.qual = 100;
//range->max_qual.level = 100;
//range->max_qual.noise = 100;
range->max_qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID; /* Updated only qual b'coz not sure */
range->avg_qual.qual = 60;
/* TODO: Find real 'good' to 'bad' threshol value for RSSI */
//range->avg_qual.level = 20;
//range->avg_qual.noise = 0;
range->avg_qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID; /* Updated only qual b'coz not sure */
range->num_bitrates = AP_BSSRATE_LEN;
for(i=0; i<AP_BSSRATE_LEN && i < IW_MAX_BITRATES; i++)
{
if (AP_BSSRATE[i] == 0x00)
break;
range->bitrate[i] = (AP_BSSRATE[i]&0x7f)* 500000;
}
range->min_frag = MIN_FRAG_THRESHOLD;
range->max_frag = MAX_FRAG_THRESHOLD;
range->pm_capa = 0;
range->we_version_compiled = WIRELESS_EXT;
range->we_version_source = 12;
// range->retry_capa; /* What retry options are supported */
// range->retry_flags; /* How to decode max/min retry limit */
// range->r_time_flags; /* How to decode max/min retry life */
// range->min_retry; /* Minimal number of retries */
// range->max_retry; /* Maximal number of retries */
// range->min_r_time; /* Minimal retry lifetime */
// range->max_r_time; /* Maximal retry lifetime */
range->encoding_size[0]=5;
range->encoding_size[1]=13;
range->num_encoding_sizes = 2;
range->max_encoding_tokens = 4;
range->num_channels = priv->available_chnl_num;
range->num_frequency = priv->available_chnl_num;
for (i = 0; i < priv->available_chnl_num && i < IW_MAX_FREQUENCIES; i++) {
u32 m = 0;
range->freq[i].i = i + 1;
//range->freq[val].m = CH_HZ_ID_MAP[i].freqKHz * 100000;
MAP_CHANNEL_ID_TO_KHZ(priv->available_chnl[i], m);
range->freq[i].m = m* 100;
range->freq[i].e = 1;
}
// Commented by Albert 2009/10/13
// The following code will proivde the security capability to network manager.
// If the driver doesn't provide this capability to network manager,
// the WPA/WPA2 routers can't be choosen in the network manager.
/*
#define IW_SCAN_CAPA_NONE 0x00
#define IW_SCAN_CAPA_ESSID 0x01
#define IW_SCAN_CAPA_BSSID 0x02
#define IW_SCAN_CAPA_CHANNEL 0x04
#define IW_SCAN_CAPA_MODE 0x08
#define IW_SCAN_CAPA_RATE 0x10
#define IW_SCAN_CAPA_TYPE 0x20
#define IW_SCAN_CAPA_TIME 0x40
*/
#if WIRELESS_EXT > 17
range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
#endif
#ifdef IW_SCAN_CAPA_ESSID
range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |IW_SCAN_CAPA_BSSID|
IW_SCAN_CAPA_CHANNEL|IW_SCAN_CAPA_MODE|IW_SCAN_CAPA_RATE;
#endif
return 0;
}
#ifdef WIFI_WPAS_CLI
int rtl_siwap(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if (priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) {
memset(&priv->pmib->dot11OperationEntry.hwaddr, 0, WLAN_ADDR_LEN);
memcpy(&priv->pmib->dot11OperationEntry.hwaddr, wrqu->ap_addr.sa_data, MACADDRLEN);
clean_for_join(priv);
return 0;
}
#if defined (WIFI_WPAS)//_Eric ??
else if ( (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) ||
(priv->pmib->dot11OperationEntry.opmode & WIFI_ADHOC_STATE) )
{
unsigned char null_mac[] = {0,0,0,0,0,0};
struct bss_desc bss_desp;
if ( memcmp(wrqu->ap_addr.sa_data, null_mac, MACADDRLEN) ) {
int i, found=0, ret=0;
for(i = 0 ; i < priv->site_survey->count_backup ; i++)
{
if(!memcmp(priv->site_survey->bss_backup[i].bssid , wrqu->ap_addr.sa_data, MACADDRLEN))
{
memcpy((void *)&bss_desp,
(void *)&priv->site_survey->bss_backup[i], sizeof(struct bss_desc));
found = 1;
break;
}
}
if(found == 0) {
printk("BSSID NOT Found !!\n");
} else {
ret = rtl_wx_join(priv, &bss_desp);
if(ret != 0)
printk("cliW: rtl_wpas_join Failed: err:%d !!\n", ret);
}
}
return 0;
}
#endif
else
return -EOPNOTSUPP;
}
#else // !WIFI_WPAS_CLI
int rtl_siwap(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if (priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) {
memset(&priv->pmib->dot11OperationEntry.hwaddr, 0, WLAN_ADDR_LEN);
memcpy(&priv->pmib->dot11OperationEntry.hwaddr, wrqu->ap_addr.sa_data, MACADDRLEN);
return 0;
} else {
#ifdef WIFI_WPAS //_Eric ??
if ( (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) ||
(priv->pmib->dot11OperationEntry.opmode & WIFI_ADHOC_STATE) )
{
memset(&priv->pmib->dot11Bss.bssid, 0, WLAN_ADDR_LEN);
memcpy(&priv->pmib->dot11Bss.bssid, wrqu->ap_addr.sa_data, MACADDRLEN);
return 0;
}
else
return -EOPNOTSUPP;
#else
//memset(&priv->pmib->dot11Bss.bssid, 0, WLAN_ADDR_LEN);
//memcpy(&priv->pmib->dot11Bss.bssid, ap_addr->sa_data, MACADDRLEN);
return -EOPNOTSUPP;
#endif
}
}
#endif // WIFI_WPAS_CLI
int rtl_giwap(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
wrqu->ap_addr.sa_family = ARPHRD_ETHER;
if (priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE)
memcpy(wrqu->ap_addr.sa_data, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN);
else
memcpy(wrqu->ap_addr.sa_data, priv->pmib->dot11Bss.bssid, MACADDRLEN);
return 0;
}
int rtl_iwaplist(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct sockaddr addr[IW_MAX_AP];
struct iw_quality qual[IW_MAX_AP];
int i;
struct list_head *phead, *plist;
struct stat_info *pstat;
#ifdef SMP_SYNC
unsigned long flags = 0;
#endif
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
i = 0;
phead = &priv->asoc_list;
SMP_LOCK_ASOC_LIST(flags);
plist = phead->next;
while (plist != phead && i < IW_MAX_AP) {
pstat = list_entry(plist, struct stat_info, asoc_list);
addr[i].sa_family = ARPHRD_ETHER;
memcpy(addr[i].sa_data, &pstat->hwaddr, WLAN_ADDR_LEN);
qual[i].qual = pstat->rssi;
//qual[i].level = pstat->sq;
//qual[i].noise = 0
qual[i].updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID;
plist = plist->next;
i++;
}
SMP_UNLOCK_ASOC_LIST(flags);
data->length = i;
memcpy(extra, &addr, i*sizeof(addr[0]));
data->flags = 1; /* signal quality present (sort of) */
memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i]));
return 0;
}
int rtl_siwessid(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *essid)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
char str[100];
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved))
return -ENETDOWN;
#endif
#ifdef WIFI_WPAS_CLI
if (!memcmp(priv->pmib->dot11Bss.bssid, NULL_MAC_ADDR, MACADDRLEN))
return 0;
#endif
snprintf(str, sizeof(str), "ssid=%s", essid);
return set_mib(priv, str);
}
int rtl_giwessid(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *essid)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
wrqu->essid.flags = 1;
wrqu->essid.length = SSID_LEN;
memcpy(essid, SSID, SSID_LEN);
return 0;
}
int rtl_siwrate(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
UINT32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
//printk("rtl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed);
/* rate = -1 => auto rate
rate = X, fixed = 1 => (fixed rate X)
*/
if (rate == -1)
{
//Auto Rate
priv->pmib->dot11StationConfigEntry.autoRate = TRUE;
priv->pmib->dot11StationConfigEntry.fixedTxRate = 0;
}
else
{
if (fixed)
{
unsigned int txRate = rate / 10000000;
int i, len;
unsigned char *rateset, *p;
rateset = AP_BSSRATE;
len = AP_BSSRATE_LEN;
for(i=0,p=rateset; i<len; i++,p++)
{
if (*p == 0x00)
break;
if (get_rate_from_bit_value(*p) == txRate) {
priv->pmib->dot11StationConfigEntry.autoRate = FALSE;
priv->pmib->dot11StationConfigEntry.fixedTxRate = *p;
return 0;
}
}
return -EOPNOTSUPP;
}
else
{
// TODO: rate = X, fixed = 0 => (rates <= X)
return -EOPNOTSUPP;
}
}
return 0;
}
int rtl_giwrate(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
unsigned int txRate;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if (priv->pmib->dot11StationConfigEntry.autoRate)
txRate = find_rate(priv, NULL, 1, 0);
else
txRate = get_rate_from_bit_value(priv->pmib->dot11StationConfigEntry.fixedTxRate);
//printk ("txRate = %d\n", txRate);
wrqu->bitrate.value = txRate * 1000000;
wrqu->bitrate.disabled = 0;
return 0;
}
#define MAX_RTS_THRESHOLD 2347
int rtl_siwrts(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
u16 val;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#ifndef WIFI_HAPD
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if (wrqu->rts.disabled)
val = MAX_RTS_THRESHOLD;
else if (wrqu->rts.value < 0 || wrqu->rts.value > MAX_RTS_THRESHOLD)
return -EINVAL;
else if (wrqu->rts.value == 0)
val = MAX_RTS_THRESHOLD;
else
val = wrqu->rts.value;
if (val != RTSTHRSLD)
RTSTHRSLD = val;
return 0;
}
int rtl_giwrts(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
wrqu->rts.value = RTSTHRSLD;
wrqu->rts.disabled = (wrqu->rts.value == MAX_RTS_THRESHOLD);
wrqu->rts.fixed = 1;
return 0;
}
int rtl_siwfrag(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
u16 val;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if (wrqu->frag.disabled)
val = MAX_FRAG_THRESHOLD;
else if (wrqu->frag.value >= MIN_FRAG_THRESHOLD || wrqu->frag.value <= MAX_FRAG_THRESHOLD)
val = __cpu_to_le16(wrqu->frag.value & ~0x1); /* even numbers only */
else if (wrqu->frag.value == 0)
val = MAX_FRAG_THRESHOLD;
else
return -EINVAL;
FRAGTHRSLD = val;
return 0;
}
int rtl_giwfrag(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
wrqu->frag.value = FRAGTHRSLD;
wrqu->frag.disabled = (wrqu->frag.value == MAX_FRAG_THRESHOLD);
wrqu->frag.fixed = 1;
return 0;
}
int rtl_siwretry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
priv->pmib->dot11OperationEntry.dot11ShortRetryLimit = wrqu->retry.value;
return 0;
}
int rtl_giwretry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
wrqu->retry.value = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit;
wrqu->retry.fixed = 0; /* no auto select */
wrqu->retry.flags |= (IW_RETRY_LIMIT |IW_RETRY_ON);
wrqu->retry.disabled = 0;
return 0;
}
int rtl_siwencode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
u32 key, ret = 0;
u32 keyindex_provided;
int i;
// NDIS_802_11_WEP wep;
// NDIS_802_11_AUTHENTICATION_MODE authmode;
struct iw_point *erq = &(wrqu->encoding);
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
printk("rtl_siwencode: erq->flags=0x%x erq->length=%d keybuf=%02x%02x%02x%02x%02x\n", erq->flags, erq->length,
keybuf[0],keybuf[1],keybuf[2],keybuf[3],keybuf[4]);
if (erq->flags & IW_ENCODE_DISABLED)
{
printk("rtl_siwencode: EncryptionDisabled\n");
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; //open system
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
goto exit;
}
key = erq->flags & IW_ENCODE_INDEX;
if (key) {
if (key > 4)
return -EINVAL;
key--;
keyindex_provided = 1;
}
else
{
keyindex_provided = 0;
key = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex;
printk("rtl_siwencode, key=%d\n", key);
}
//set authentication mode
if (erq->flags & IW_ENCODE_OPEN)
{
printk("rtl_siwencode: IW_ENCODE_OPEN\n");
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; //open system
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
}
else if (erq->flags & IW_ENCODE_RESTRICTED)
{
printk("rtl_siwencode: IW_ENCODE_RESTRICTED\n");
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 1; //shared system
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
}
else
{
printk("rtl_siwencode: IW_ENCODE_OPEN\n");
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; //open system
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
}
priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex = key;
if (erq->length > 0) {
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = erq->length <= 5 ? _WEP_40_PRIVACY_ : _WEP_104_PRIVACY_;
priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = erq->length <= 5 ? 8 : 16;
} else {
if (keyindex_provided == 1)// set key_id only, no given KeyMaterial(erq->length==0).
{
printk("rtl_siwencode: keyindex provided, keyid=%d, key_len=%d\n", key, erq->length);
switch (priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen)
{
case 5:
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_40_PRIVACY_;
break;
case 13:
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_104_PRIVACY_;
break;
default:
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_;
break;
}
goto exit;
}
}
#ifdef WIFI_WPAS_CLI
memcpy(priv->pmib->dot11DefaultKeysTable.keytype[key].skey, keybuf, erq->length);
CamAddOneEntry(priv, priv->pmib->dot11Bss.bssid, key,
(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm)<<2,
0, priv->pmib->dot11DefaultKeysTable.keytype[key].skey);
#else
for (i=0; i<4; i++) {
memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[i].skey[0], keybuf, erq->length);
}
#endif
exit:
return ret;
}
int rtl_giwencode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *key)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct iw_point *erq = &(wrqu->encoding);
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS))
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#endif
if ((OPMODE & (WIFI_AP_STATE|WIFI_STATION_STATE|WIFI_ADHOC_STATE)) &&
!priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm &&
(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ ||
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_)) {
int key_len;
priv->pmib->dot11GroupKeysTable.dot11Privacy = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm;
if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_)
key_len = 5;
else
key_len = 13;
// copy wep key
erq->flags = (priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex + 1) & IW_ENCODE_INDEX;
erq->length = key_len;
memcpy(key, &priv->pmib->dot11DefaultKeysTable.keytype[priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0], key_len);
if (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm == 1)
erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */
else
erq->flags |= IW_ENCODE_OPEN; /* XXX */
erq->flags |= IW_ENCODE_ENABLED; /* XXX */
}
else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_) {
erq->length = 0;
erq->flags = IW_ENCODE_DISABLED;
}
return 0;
}
int rtl_giwpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
//_adapter *padapter = netdev_priv(dev);
wrqu->power.value = 0;
wrqu->power.fixed = 0; /* no auto select */
wrqu->power.disabled = 1;
return 0;
}
#ifdef WIFI_WPAS_CLI
int rtl_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct iw_point *data = &wrqu->data;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved))
return -ENETDOWN;
#endif
// TODO: If traffic is busy, we may need to skip this scanning
if ( OPMODE & WIFI_ASOC_STATE ) {
printk("cliW: try scanning in association\n");
goto ind_done;
}
if ( OPMODE & ( WIFI_AUTH_STATE1 | WIFI_AUTH_SUCCESS) ) {
printk("cliW: no scanning when connecting\n");
goto ind_done;
}
if (data && (data->flags & IW_SCAN_THIS_ESSID)) {
struct iw_scan_req* req = (struct iw_scan_req*)extra;
if (req->essid_len)
{
priv->ss_ssidlen = req->essid_len;
if (priv->ss_ssidlen > 32)
priv->ss_ssidlen = 32;
memset(priv->ss_ssid, 0, 32);
memcpy(priv->ss_ssid, req->essid, priv->ss_ssidlen);
SSID2SCAN_LEN = (req->essid_len > 32) ? 32 : req->essid_len;
memcpy(SSID2SCAN, req->essid, SSID2SCAN_LEN);
use_ap_scan(priv);
}
} else {
printk("cliW: wildcard ssid \n");
priv->ss_ssidlen = 0;
use_ap_scan(priv);
}
done:
return 0;
ind_done:
event_indicate_wpas(priv, NULL, WPAS_SCAN_DONE, NULL);
return 0;
}
#else // !WIFI_WPAS_CLI
int rtl_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
INT8 ret=-1;
RTL_PRIV *priv = GET_DEV_PRIV(dev);
unsigned long flags;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
ret=rtl8192cd_ss_req(priv, (unsigned char *) &wrqu->data, 0);
if(0!=wrqu->data.length)
{
if(extra!=NULL && (!strcmp(extra,"rtl8192cd_ioctl")))//called from rtl8192cd_ioctl
{
#ifdef WIFI_WPAS //_Eric ??
if (ioctl_copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1))
memcpy(wrqu->data.pointer, &ret, 1);
#else
if (ioctl_copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1))
return -1;
#endif
}
else //called from iwhandler.
{
#ifdef WIFI_WPAS //_Eric ??
if (copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1))
memcpy(data, &ret, 1);
#else
if (copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1))
return -1;
#endif
}
}
//wait ss done
wait_event_interruptible_timeout(priv->ss_wait,(!priv->ss_req_ongoing),RTL_SECONDS_TO_JIFFIES(5));
return 0;
}
#endif // WIFI_WPAS_CLI
#ifdef WIFI_WPAS //_Eric ?? AP mode (HAPD) will attemp to scan or not ??
int rtl_giwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
int i=0, j=0;
char * current_ev = extra;
char * previous_ev = extra;
char * end_buf;
char * current_val;
#ifndef IWEVGENIE
unsigned char idx;
#endif // IWEVGENIE //
struct iw_event iwe;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
//check if the interface is down
if (!netif_running(priv->dev))
{
printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved)) {
printk("cliw: driver shutdown now\n");
return -ENETDOWN;
}
#endif
if (priv->site_survey->count_backup== 0)
{
wrqu->data.length = 0;
return 0;
}
#if WIRELESS_EXT >= 17
if (wrqu->data.length > 0)
end_buf = extra + wrqu->data.length;
else
end_buf = extra + IW_SCAN_MAX_DATA;
#else
end_buf = extra + IW_SCAN_MAX_DATA;
#endif
memset(extra, 0, wrqu->data.length);
for (i = 0; i < priv->site_survey->count_backup; i++)
{
if ((current_ev >= end_buf) || ( (wrqu->data.length - (current_ev - extra)) <= 200))
{
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
}
// The first entry must be the MAC address
//MAC address
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, priv->site_survey->bss_backup[i].bssid, MACADDRLEN);
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
//ESSID
//================================
memset(&iwe, 0, sizeof(iwe));
//printk("ESSID %s %d\n",priv->site_survey->bss_backup[i].ssid, priv->site_survey->bss_backup[i].ssidlen);
iwe.cmd = SIOCGIWESSID;
iwe.u.data.length = (priv->site_survey->bss_backup[i].ssidlen <= 32) ? priv->site_survey->bss_backup[i].ssidlen : 32;
iwe.u.data.flags = 1;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->bss_backup[i].ssid);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
//Network Type
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWMODE;
if (priv->site_survey->bss_backup[i].bsstype & WIFI_ADHOC_STATE)
{
iwe.u.mode = IW_MODE_ADHOC;
}
else if (priv->site_survey->bss_backup[i].bsstype & WIFI_STATION_STATE)
{
iwe.u.mode = IW_MODE_INFRA;
}
else if (priv->site_survey->bss_backup[i].bsstype & WIFI_AP_STATE)
{
iwe.u.mode = IW_MODE_MASTER;
}
else
{
iwe.u.mode = IW_MODE_AUTO;
}
iwe.len = IW_EV_UINT_LEN;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
//Channel and Frequency
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWFREQ;
{
u8 ch = priv->site_survey->bss_backup[i].channel;
u32 m = 0;
MAP_CHANNEL_ID_TO_KHZ(ch, m);
iwe.u.freq.m = m;
iwe.u.freq.e = 3;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
}
//Add quality statistics
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVQUAL;
iwe.u.qual.level = priv->site_survey->bss_backup[i].rssi - 100;
iwe.u.qual.qual = priv->site_survey->bss_backup[i].sq;
iwe.u.qual.noise = 0; /* cliW */
// not sure about signal level and noise level, To Do: determin the SNR
//iwe.u.qual.noise = signal_todbm((u8)(100-priv->site_survey->bss[i].rssi)) -25;
// iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID;
iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM ;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
#define WLAN_CAPABILITY_PRIVACY (1<<4)
// Encryption capability
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWENCODE;
if (priv->site_survey->bss_backup[i].capability & WLAN_CAPABILITY_PRIVACY) // if Privacy
iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (u8 *)&priv->pmib->dot11DefaultKeysTable.keytype[priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0]);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
// support rate
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWRATE;
iwe.u.bitrate.fixed = 0;
iwe.u.bitrate.disabled = 0;
iwe.u.bitrate.value = 0;
current_val = current_ev + IW_EV_LCP_LEN;
for (j=0; dot11_rate_table[j]; j++)
{
if (priv->site_survey->bss_backup[i].supportrate & (BIT(j)))
{
iwe.u.bitrate.value = dot11_rate_table[j]*500000;
current_val = IWE_STREAM_ADD_VALUE(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
}
}
if (priv->site_survey->bss_backup[i].network & WIRELESS_11N)
{
// TODO: Report MCS Rate
}
/* remove fixed header if no rates were added */
if ((current_val - current_ev) > IW_EV_LCP_LEN)
current_ev = current_val;
/* Add WPA/RSN IE */
#if WIRELESS_EXT >= 18
//WPAIE
//================================
if(priv->site_survey->wpa_ie_backup[i].wpa_ie_len > 0){
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVGENIE;
iwe.u.data.length = priv->site_survey->wpa_ie_backup[i].wpa_ie_len;
iwe.u.data.flags = 1;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->wpa_ie_backup[i].data);
if (current_ev == previous_ev) {
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
}
}
//RSNIE
//================================
if(priv->site_survey->rsn_ie_backup[i].rsn_ie_len > 0) {
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVGENIE;
iwe.u.data.length = priv->site_survey->rsn_ie_backup[i].rsn_ie_len;
iwe.u.data.flags = 1;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->rsn_ie_backup[i].data);
if (current_ev == previous_ev) {
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
}
}
#endif
/*
Protocol:
it will show scanned AP's WirelessMode .
it might be
802.11a
802.11a/n
802.11g/n
802.11b/g/n
802.11g
802.11b/g
*/
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWNAME;
{
struct bss_desc *pBss=&priv->site_survey->bss_backup[i];
//int rateCnt=0;
if (pBss->network==WIRELESS_11B)
strcpy(iwe.u.name, "802.11b");
else if (pBss->network==WIRELESS_11G)
strcpy(iwe.u.name, "802.11g");
else if (pBss->network==(WIRELESS_11G|WIRELESS_11B))
strcpy(iwe.u.name, "802.11b/g");
else if (pBss->network==(WIRELESS_11N))
strcpy(iwe.u.name, "802.11n");
else if (pBss->network==(WIRELESS_11G|WIRELESS_11N))
strcpy(iwe.u.name, "802.11g/n");
else if (pBss->network==(WIRELESS_11G|WIRELESS_11B | WIRELESS_11N))
strcpy(iwe.u.name, "802.11b/g/n");
else if(pBss->network== WIRELESS_11A)
strcpy(iwe.u.name, "802.11a");
else
strcpy(iwe.u.name, "---");
}
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
#ifdef WIFI_SIMPLE_CONFIG
//WPSIE
//================================
if (priv->site_survey->bss_backup[i].t_stamp[1] & BIT(8)) {
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVGENIE;
iwe.u.data.length = priv->site_survey->wscie[i].wps_ie_len;
iwe.u.data.flags = 1;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_POINT(info, current_ev,
end_buf, &iwe, (char *)priv->site_survey->wscie[i].data);
if (current_ev == previous_ev) {
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
}
}
#endif // WIFI_SIMPLE_CONFIG
}
wrqu->data.length = current_ev - extra;
return 0;
}
#else
int rtl_giwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
int i=0;
char * current_ev = extra;
char * previous_ev = extra;
char * end_buf;
//char * current_val;
#ifndef IWEVGENIE
unsigned char idx;
#endif // IWEVGENIE //
struct iw_event iwe;
if (priv == NULL)
{
/* if 1st open fail, pAd will be free;
So the net_dev->priv will be NULL in 2rd open */
return -ENETDOWN;
}
//check if the interface is down
if (!netif_running(priv->dev))
{
//printk("\nFail: interface not opened\n");
return -ENETDOWN;
}
if (priv->site_survey->count == 0)
{
wrqu->data.length = 0;
return 0;
}
#if WIRELESS_EXT >= 17
if (wrqu->data.length > 0)
end_buf = extra + wrqu->data.length;
else
end_buf = extra + IW_SCAN_MAX_DATA;
#else
end_buf = extra + IW_SCAN_MAX_DATA;
#endif
for (i = 0; i < priv->site_survey->count; i++)
{
if (current_ev >= end_buf)
{
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
}
//MAC address
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, &priv->site_survey->bss[i].bssid, MACADDRLEN);
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
/*
Protocol:
it will show scanned AP's WirelessMode .
it might be
802.11a
802.11a/n
802.11g/n
802.11b/g/n
802.11g
802.11b/g
*/
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWNAME;
{
struct bss_desc *pBss=&priv->site_survey->bss[i];
//int rateCnt=0;
if (pBss->network==WIRELESS_11B)
strcpy(iwe.u.name, "802.11b");
else if (pBss->network==WIRELESS_11G)
strcpy(iwe.u.name, "802.11g");
else if (pBss->network==(WIRELESS_11G|WIRELESS_11B))
strcpy(iwe.u.name, "802.11b/g");
else if (pBss->network==(WIRELESS_11N))
strcpy(iwe.u.name, "802.11n");
else if (pBss->network==(WIRELESS_11G|WIRELESS_11N))
strcpy(iwe.u.name, "802.11g/n");
else if (pBss->network==(WIRELESS_11G|WIRELESS_11B | WIRELESS_11N))
strcpy(iwe.u.name, "802.11b/g/n");
else if(pBss->network== WIRELESS_11A)
strcpy(iwe.u.name, "802.11a");
else
strcpy(iwe.u.name, "---");
}
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
//ESSID
//================================
memset(&iwe, 0, sizeof(iwe));
//printk("ESSID %s %d\n",priv->site_survey->bss[i].ssid, priv->site_survey->bss[i].ssidlen);
iwe.cmd = SIOCGIWESSID;
iwe.u.data.length = priv->site_survey->bss[i].ssidlen;
iwe.u.data.flags = 1;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->bss[i].ssid);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
//Network Type
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWMODE;
if (priv->site_survey->bss[i].bsstype & WIFI_ADHOC_STATE)
{
iwe.u.mode = IW_MODE_ADHOC;
}
else if (priv->site_survey->bss[i].bsstype & WIFI_STATION_STATE)
{
iwe.u.mode = IW_MODE_INFRA;
}
else if (priv->site_survey->bss[i].bsstype & WIFI_AP_STATE)
{
iwe.u.mode = IW_MODE_MASTER;
}
else
{
iwe.u.mode = IW_MODE_AUTO;
}
iwe.len = IW_EV_UINT_LEN;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
//Channel and Frequency
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWFREQ;
{
u8 ch = priv->site_survey->bss[i].channel;
//u32 m = 0;
//MAP_CHANNEL_ID_TO_KHZ(ch, m);
//iwe.u.freq.m = m * 100;
//iwe.u.freq.e = 1;
iwe.u.freq.m = ch;
iwe.u.freq.e = 0;
iwe.u.freq.i = 0;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
}
//Add quality statistics
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = priv->site_survey->bss[i].rssi;
// not sure about signal level and noise level
//iwe.u.qual.level = (u8) priv->site_survey->bss[i].sq;
//iwe.u.qual.noise = signal_todbm((u8)(100-priv->site_survey->bss[i].rssi)) -25;
iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID;
current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
#if 0
//Encyption key
//================================
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWENCODE;
if (priv->site_survey->bss[i].capability & 0x0010)
iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
previous_ev = current_ev;
current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (u8 *)priv->pmib->dot11DefaultKeysTable.keytype[priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0]);
if (current_ev == previous_ev)
#if WIRELESS_EXT >= 17
return -E2BIG;
#else
break;
#endif
#endif
}
wrqu->data.length = current_ev - extra;
return 0;
}
#endif
#ifdef WIFI_WPAS_CLI
const u1Byte WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
const u1Byte WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
const u1Byte WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
const u1Byte WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
const u1Byte WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
const u1Byte WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
const u1Byte RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
const u1Byte RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
const u1Byte RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
//const u1Byte RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
const u1Byte RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
const u1Byte RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
unsigned char rtw_get_wpa_cipher_suite(u1Byte *s)
{
unsigned char cipher = 0;
if (memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0)
cipher = _NO_PRIVACY_;
else if (memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0)
cipher = _WEP_40_PRIVACY_;
else if (memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0)
cipher = _TKIP_PRIVACY_;
else if (memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0)
cipher = _CCMP_PRIVACY_;
else if (memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0)
cipher = _WEP_104_PRIVACY_;
return cipher;
}
unsigned char rtw_get_wpa2_cipher_suite(u1Byte *s)
{
unsigned char cipher = 0;
if (memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0)
cipher = _NO_PRIVACY_;
else if (memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0)
cipher = _WEP_40_PRIVACY_;
else if (memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0)
cipher = _TKIP_PRIVACY_;
else if (memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0)
cipher = _CCMP_PRIVACY_;
else if (memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0)
cipher = _WEP_104_PRIVACY_;
return cipher;
}
int rtw_parse_wpa_ie(u1Byte* wpa_ie, int wpa_ie_len, unsigned char *group_cipher, unsigned char *pairwise_cipher)
{
int i, ret=0;
int left, count;
pu1Byte pos;
if (wpa_ie_len <= 0) {
/* No WPA IE - fail silently */
return 1;
}
if ((*wpa_ie != WPA_IE_ID) || (*(wpa_ie+1) != (u1Byte)(wpa_ie_len - 2)) ||
(memcmp(wpa_ie+2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0) )
{
return 1;
}
pos = wpa_ie;
pos += 8;
left = wpa_ie_len - 8;
//group_cipher
if (left >= WPA_SELECTOR_LEN)
{
*group_cipher = rtw_get_wpa_cipher_suite(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
else if (left > 0)
{
DEBUG_INFO("%s: ie length mismatch, %u too much", __FUNCTION__, left);
return 1;
}
//pairwise_cipher
if (left >= 2)
{
count = le16_to_cpu(*(u2Byte*)pos);//
pos += 2;
left -= 2;
if (count == 0 || left < count * WPA_SELECTOR_LEN) {
DEBUG_INFO("%s: ie count botch (pairwise), "
"count %u left %u", __FUNCTION__, count, left);
return 1;
}
for (i = 0; i < count; i++)
{
*pairwise_cipher = rtw_get_wpa_cipher_suite(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
}
else if (left == 1)
{
DEBUG_INFO("%s: ie too short (for key mgmt)", __FUNCTION__);
return 1;
}
return ret;
}
int rtw_parse_wpa2_ie(u1Byte* rsn_ie, int rsn_ie_len, unsigned char *group_cipher, unsigned char *pairwise_cipher)
{
int i, ret=0;
int left, count;
u1Byte *pos;
if (rsn_ie_len <= 0)
{
/* No RSN IE - fail silently */
return 1;
}
if ((*rsn_ie!= WPA2_IE_ID) || (*(rsn_ie+1) != (u1Byte)(rsn_ie_len - 2)))
{
return 1;
}
pos = rsn_ie;
pos += 4;
left = rsn_ie_len - 4;
//group_cipher
if (left >= RSN_SELECTOR_LEN) {
*group_cipher = rtw_get_wpa2_cipher_suite(pos);
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
} else if (left > 0) {
DEBUG_INFO("%s: ie length mismatch, %u too much", __FUNCTION__, left);
return 1;
}
//pairwise_cipher
if (left >= 2)
{
count = le16_to_cpu(*(u16*)pos);//
pos += 2;
left -= 2;
if (count == 0 || left < count * RSN_SELECTOR_LEN) {
DEBUG_INFO("%s: ie count botch (pairwise), "
"count %u left %u", __FUNCTION__, count, left);
return 1;
}
for (i = 0; i < count; i++)
{
*pairwise_cipher = rtw_get_wpa2_cipher_suite(pos);
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
}
}
else if (left == 1)
{
DEBUG_INFO("%s: ie too short (for key mgmt)", __FUNCTION__);
return 1;
}
return ret;
}
void rtw_set_wpa_cipher_bit(struct rtl8192cd_priv *priv, unsigned char enc_type)
{
switch (enc_type) {
case _WEP_40_PRIVACY_:
priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(0);
break;
case _TKIP_PRIVACY_:
priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(1);
break;
case _WRAP_PRIVACY_:
priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(2);
break;
case _CCMP_PRIVACY_:
priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(3);
break;
case _WEP_104_PRIVACY_:
priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(4);
break;
default:
break;
}
}
int rtl_siwgenie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
u1Byte *buf=NULL;
unsigned char group_cipher = 0, pairwise_cipher = 0;
int ret = 0;
u2Byte ielen;
WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info;
DEBUG_INFO("%s:IE_Len=%d\n", __FUNCTION__, wrqu->data.length);
ielen = wrqu->data.length;
if((ielen > MAX_WPA_IE_LEN) || (extra == NULL)){
priv->pmib->wscEntry.wsc_enable = 0;
priv->pmib->wscEntry.assoc_ielen = 0;
if(extra == NULL)
return ret;
else
return -EINVAL;
}
printk("rtl_siwgenie\n");
if ( ielen == 0 ) {
priv->pmib->dot11RsnIE.rsnielen = 0;
} else {
#if 0
if (wrqu->data.length < sizeof(DOT11_RSN_IE_HEADER))
{
DEBUG_ERR("Invalid IE Length(%d) or Null data pointer\n", wrqu->data.length);
return -EINVAL;
}
#endif
buf = kzalloc(ielen, GFP_KERNEL);
if (buf == NULL){
return -ENOMEM;
}
memcpy(buf, extra, ielen);
if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher) == 0)
{
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2;
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = pairwise_cipher;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1;
priv->pmib->dot1180211AuthEntry.dot11WPACipher |= 1 << (pairwise_cipher-1);
priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0;
priv->pmib->dot11GroupKeysTable.dot11Privacy = group_cipher;
pGblInfo->MulticastCipher = group_cipher ;
pGblInfo->UnicastCipher[0] = pairwise_cipher ;
BUG_ON(sizeof(priv->pmib->dot11RsnIE.rsnie) < ielen);
memcpy(priv->pmib->dot11RsnIE.rsnie, &buf[0], ielen);
priv->pmib->dot11RsnIE.rsnielen = ielen;
}
else if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher) == 0)
{
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2;
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = pairwise_cipher;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1;
priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0;
priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher |= 1 << (pairwise_cipher-1);
priv->pmib->dot11GroupKeysTable.dot11Privacy = group_cipher;
pGblInfo->MulticastCipher = group_cipher ;
pGblInfo->UnicastCipherWPA2[0] = pairwise_cipher;
BUG_ON(sizeof(priv->pmib->dot11RsnIE.rsnie) < ielen);
memcpy(priv->pmib->dot11RsnIE.rsnie, &buf[0], ielen);
priv->pmib->dot11RsnIE.rsnielen = ielen;
}
{//set wps_ie
int cnt = 0;
unsigned char wps_ie_found=0;
unsigned char eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
while( cnt < ielen )
{
eid = buf[cnt];
if((eid==VENDOR_SPECIFIC_IE)&&(memcmp(&buf[cnt+2], wps_oui, 4)==0))
{
DEBUG_INFO("%s: SET WPS_IE\n",__FUNCTION__);
priv->pmib->wscEntry.wsc_enable = 1;
priv->pmib->wscEntry.assoc_ielen = ( (buf[cnt+1]+2) < (256)) ? (buf[cnt+1]+2):(256);
memset(priv->pmib->wscEntry.assoc_ie, 0x0, 256);
memcpy(priv->pmib->wscEntry.assoc_ie, &buf[cnt], priv->pmib->wscEntry.assoc_ielen);
wps_ie_found = 1;
break;
}
cnt += buf[cnt+1]+2; //goto next
}
if (!wps_ie_found)
{
priv->pmib->wscEntry.wsc_enable = 0;
priv->pmib->wscEntry.assoc_ielen = 0;
}
}
kfree(buf);
}
return ret;
}
int rtl_siwauth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct iw_param *param = (struct iw_param*)&(wrqu->param);
int value = param->value;
int ret = 0;
printk("rtl_siwauth : cmd:%d val:%d\n", (param->flags & IW_AUTH_INDEX), param->value);
switch (param->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
#ifdef CONFIG_RTL_WAPI_SUPPORT
priv->pmib->wapiInfo.wapiType = wapiDisable;
if(value == IW_AUTH_WAPI_VERSION_1)
{
priv->pmib->wapiInfo.wapiType = wapiTypePSK;
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == 0;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0;
priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0;
} else
#endif
if (value == IW_AUTH_WPA_VERSION_DISABLED) {
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0;
priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0;
}
else if (value == IW_AUTH_WPA_VERSION_WPA)
{
priv->pmib->wapiInfo.wapiType = wapiDisable;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA;
}
else if (value == IW_AUTH_WPA_VERSION_WPA2)
{
priv->pmib->wapiInfo.wapiType = wapiDisable;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2;
}
break;
case IW_AUTH_CIPHER_PAIRWISE:
DEBUG_INFO("set_auth(IW_AUTH_CIPHER_PAIRWISE) value=%d\n", param->value);
if (param->value & IW_AUTH_CIPHER_WEP40)
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_40_PRIVACY_;
else if (param->value & IW_AUTH_CIPHER_WEP104)
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_104_PRIVACY_;
else if (param->value & IW_AUTH_CIPHER_TKIP)
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _TKIP_PRIVACY_;
else if (param->value & IW_AUTH_CIPHER_CCMP)
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _CCMP_PRIVACY_;
else if (param->value & IW_AUTH_CIPHER_NONE)
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_;
else {
return -EINVAL;
}
break;
case IW_AUTH_CIPHER_GROUP:
DEBUG_INFO("set_auth(IW_AUTH_CIPHER_GROUP) value=%d\n", value);
if (value & IW_AUTH_CIPHER_WEP40)
priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_WEP40;
else if (value & IW_AUTH_CIPHER_WEP104)
priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_WEP104;
else if (value & IW_AUTH_CIPHER_TKIP)
priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_TKIP;
else if (value & IW_AUTH_CIPHER_CCMP)
priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_CCMP;
else if (value & IW_AUTH_CIPHER_NONE)
priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_NONE;
else {
return -EINVAL;
}
break;
case IW_AUTH_KEY_MGMT:
#ifdef CONFIG_RTL_WAPI_SUPPORT
if (priv->pmib->wapiInfo.wapiType != wapiDisable)
{
if(value == IW_AUTH_KEY_MGMT_WAPI_PSK)
priv->pmib->wapiInfo.wapiType = wapiTypePSK;
else
priv->pmib->wapiInfo.wapiType = wapiTypeCert;
DEBUG_INFO("%s: IW_AUTH_KEY_MGMT wapiType %d \n", __FUNCTION__, priv->pmib->wapiInfo.wapiType);
} else
#endif
#if 0
if (value & IW_AUTH_KEY_MGMT_802_1X)
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1;
else
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
#endif
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
// TODO: TKIP countermeasures
break;
case IW_AUTH_DROP_UNENCRYPTED:
break;
case IW_AUTH_80211_AUTH_ALG:
if ((param->value & IW_AUTH_ALG_SHARED_KEY)&&(param->value & IW_AUTH_ALG_OPEN_SYSTEM))
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; // Auto
else if(param->value & IW_AUTH_ALG_OPEN_SYSTEM)
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; // Open
else if (param->value & IW_AUTH_ALG_SHARED_KEY)
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 1; // Shared
else if (param->value & IW_AUTH_ALG_LEAP)
{
DEBUG_WARN("%s: wpa_set_auth_algs, AUTH_ALG_LEAP\n", __FUNCTION__);
}
else
ret = -EINVAL;
break;
case IW_AUTH_WPA_ENABLED:
if ( param->value == 0 ) {
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0;
priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0;
priv->pmib->dot11GroupKeysTable.dot11Privacy = 0;
priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0;
priv->pmib->dot11RsnIE.rsnielen = 0;
}
break;
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
//ieee->ieee802_1x = param->value;
break;
case IW_AUTH_PRIVACY_INVOKED:
//ieee->privacy_invoked = param->value;
break;
#ifdef CONFIG_RTL_WAPI_SUPPORT
case IW_AUTH_WAPI_ENABLED:
break;
#endif
default:
return -EOPNOTSUPP;
}
return ret;
}
int rtl_giwauth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct iw_param *param = (struct iw_param*)&(wrqu->param);
int ret = 0;
DEBUG_INFO("%s: get_auth: flags=0x%x authmode=%d\n", __FUNCTION__, wrq->flags, authmode);
param->value = 0;
switch (param->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
#ifdef CONFIG_RTL_WAPI_SUPPORT
if (priv->pmib->wapiInfo.wapiType != wapiDisable)
{
param->value |= IW_AUTH_WAPI_VERSION_1;
}
#endif
if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA)
{
param->value |= IW_AUTH_WPA_VERSION_WPA;
}
if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2)
{
param->value |= IW_AUTH_WPA_VERSION_WPA2;
}
break;
case IW_AUTH_CIPHER_PAIRWISE:
if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_)
{
param->value |= IW_AUTH_CIPHER_WEP40;
}
else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_)
{
param->value |= IW_AUTH_CIPHER_WEP104;
}
else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_)
{
param->value |= IW_AUTH_CIPHER_TKIP;
}
else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)
{
param->value |= IW_AUTH_CIPHER_CCMP;
}
else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_)
{
param->value |= IW_AUTH_CIPHER_NONE;
}
break;
case IW_AUTH_KEY_MGMT:
#ifdef CONFIG_RTL_WAPI_SUPPORT
if (priv->pmib->wapiInfo.wapiType != wapiDisable)
{
if (priv->pmib->wapiInfo.wapiType == wapiTypePSK)
param->value = IW_AUTH_KEY_MGMT_WAPI_PSK;
else
param->value = IW_AUTH_KEY_MGMT_WAPI_CERT;
} else
#endif
if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm)
{
if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK)
param->value = IW_AUTH_KEY_MGMT_PSK;
else
param->value = IW_AUTH_KEY_MGMT_802_1X;
}
break;
// TODO:==>
case IW_AUTH_80211_AUTH_ALG:
switch (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm) {
case 0:
param->value = IW_AUTH_ALG_OPEN_SYSTEM;
break;
case 1:
param->value = IW_AUTH_ALG_OPEN_SYSTEM;
break;
default:
DEBUG_ERR("%s: invalid auth_alg(%d)\n", __FUNCTION__,priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm);
param->value = IW_AUTH_ALG_OPEN_SYSTEM;
break;
}
break;
case IW_AUTH_WPA_ENABLED:
// TODO:
break;
default:
ret = -EOPNOTSUPP;
}
DEBUG_INFO("%s: flags=0x%x value=%d ret=%d\n", __FUNCTION__, param->flags, param->value, ret);
return ret;
}
int rtl_siwencodeext(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
s4Byte alg = ext->alg;
u1Byte EncAlgorithm = DOT11_ENC_NONE;
s4Byte KeyIndex;
u4Byte KeyLength=0;
BOOLEAN IsDefaultKey = FALSE;
pu1Byte KeyMaterial = ext->key;
BOOLEAN IsGroupKey = FALSE;
// u8Byte KeyRSC;
int ret=0;
DOT11_SET_KEY Set_Key;
struct stat_info *pstat;
memset((char *)&Set_Key, 0, sizeof(Set_Key));
if (encoding->flags & IW_ENCODE_DISABLED) {
alg = IW_ENCODE_ALG_NONE;
}
/* Get Key Index and convet to our own defined key index */
KeyIndex = (encoding->flags & IW_ENCODE_INDEX) - 1;
KeyLength = ext->key_len;
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
IsDefaultKey = TRUE;
}
//if ((ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) || (IS_BCAST(ext->addr.sa_data))) {
if ( (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ) {
IsGroupKey = TRUE;
}
printk("siwencode alg:%x ext_flags:%x/ len:%u\n", (u4Byte)alg, ext->ext_flags, KeyLength);
DEBUG_INFO("%s: \n", __FUNCTION__);
DEBUG_INFO("KeyIndex = %d\n", KeyIndex);
DEBUG_INFO("KeyLength = %u\n", KeyLength);
//DEBUG_INFO("KeyMaterial = %32s\n", KeyMaterial);
DEBUG_INFO("IsDefaultKey = %d\n", IsDefaultKey);
DEBUG_INFO("IsGroupKey = %d\n", IsGroupKey);
#ifdef SDIO_AP_OFFLOAD
ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_COMAPI);
#endif
switch (alg) {
case IW_ENCODE_ALG_NONE:
/* Clear all keys */
EncAlgorithm = DOT11_ENC_NONE;
break;
case IW_ENCODE_ALG_WEP:
if ((KeyIndex < 0) || (KeyIndex >= 4))
{
ret = -EINVAL;
goto set_encodeext_end;
}
if(KeyLength == 5){
EncAlgorithm = DOT11_ENC_WEP40;
}
else if(KeyLength == 13) {
EncAlgorithm = DOT11_ENC_WEP104;
}
else
{
ret = -EINVAL;
goto set_encodeext_end;
}
break;
case IW_ENCODE_ALG_TKIP:
EncAlgorithm = DOT11_ENC_TKIP;
// Check key length for TKIP.
if(KeyLength != 32) {
if (IsGroupKey && (KeyLength == 5 || KeyLength == 13)) {
// 5 = WEP40 13 = WEP104 16 = CKIP
if(KeyLength == 5) {
EncAlgorithm = DOT11_ENC_WEP40;
} else {
EncAlgorithm = DOT11_ENC_WEP104;
}
DEBUG_WARN("%s: Check key length 5 or 13 for Mix-mode WEP.\n", __FUNCTION__);
} else {
DEBUG_ERR("TKIP KeyLength:%u != 32\n", KeyLength);
ret = -EINVAL;
goto set_encodeext_end;
}
}
break;
case IW_ENCODE_ALG_CCMP:
EncAlgorithm = DOT11_ENC_CCMP;
if(KeyLength != 16) {
// For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case.
if(KeyLength == 32)
KeyLength = 16;
}
if((KeyLength != 16) && (KeyLength != 32)) {
if (IsGroupKey && (KeyLength == 5 || KeyLength == 13)) {
// 5 = WEP40 13 = WEP104 16 = CKIP
if(KeyLength == 5) {
EncAlgorithm = DOT11_ENC_WEP40;
} else {
EncAlgorithm = DOT11_ENC_WEP104;
}
DEBUG_WARN("%s: Check key length 5 or 13 for Mix-mode WEP.\n", __FUNCTION__);
} else {
DEBUG_ERR("AES_CCM KeyLength:%u != 16\n", KeyLength);
ret = -EINVAL;
goto set_encodeext_end;
}
}
break;
default:
ret = -EINVAL;
goto set_encodeext_end;
}
if (KeyLength > 0) {
if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104)) {
memcpy(priv->pmib->dot11DefaultKeysTable.keytype[KeyIndex].skey, KeyMaterial, KeyLength);
}
if (IsDefaultKey) {
if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104)) {
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = KeyLength <= 5 ? _WEP_40_PRIVACY_ : _WEP_104_PRIVACY_;
priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = KeyLength <= 5 ? 8 : 16;
priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex = KeyIndex;
// don't setup PTK CAM because BSSID is unavailable before first join.
// PTK CAM will be set on set_keymapping_wep when association success.
if (IsGroupKey) {
struct Dot11EncryptKey *pEncryptKey;
priv->pmib->dot11GroupKeysTable.dot11Privacy = EncAlgorithm;
priv->pmib->dot11GroupKeysTable.keyid = KeyIndex;
pEncryptKey = &priv->pmib->dot11GroupKeysTable.dot11EncryptKey;
pEncryptKey->dot11TTKeyLen = KeyLength <= 5 ? 5 : 13;
pEncryptKey->dot11TMicKeyLen = 0;
memset(pEncryptKey->dot11TTKey.skey, 0, sizeof(pEncryptKey->dot11TTKey.skey));
memcpy(pEncryptKey->dot11TTKey.skey, KeyMaterial, pEncryptKey->dot11TTKeyLen);
}
goto set_encodeext_end;
}
}
if (IsGroupKey) {
/* cliW: not set group key in wep key */
if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104)) {
goto set_encodeext_end;
}
/* cliW: fix group key for wpa_supplicant rekey use toogle index */
if ((EncAlgorithm == DOT11_ENC_TKIP) || (EncAlgorithm == DOT11_ENC_CCMP))
KeyIndex = 1;
priv->pmib->dot11GroupKeysTable.dot11Privacy = EncAlgorithm;
priv->pmib->dot11GroupKeysTable.keyid = KeyIndex;
}
/* cliW test supplicant using [ len : tx : rx ] key format */
if ( EncAlgorithm == DOT11_ENC_TKIP ) {
char tmp[8];
#if 1
WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info;
if ( IsDefaultKey ) {
pGblInfo->GkeyReady = TRUE;
pGblInfo->GN = KeyIndex;
}
pGblInfo->MulticastCipher = _TKIP_PRIVACY_;
#endif
memcpy(tmp, KeyMaterial+16, 8);
memcpy(KeyMaterial+16, KeyMaterial+24, 8);
memcpy(KeyMaterial+24, tmp, 8);
}
memcpy(Set_Key.MACAddr, ext->addr.sa_data, MACADDRLEN);
if (IsDefaultKey)
Set_Key.KeyType = DOT11_KeyType_Pairwise;
else
Set_Key.KeyType = (IsGroupKey ? DOT11_KeyType_Group : DOT11_KeyType_Pairwise);
Set_Key.EncType = EncAlgorithm;
Set_Key.KeyIndex = KeyIndex;
Set_Key.KeyLen = KeyLength;
ret = DOT11_Process_Set_Key(dev, NULL, &Set_Key, KeyMaterial);
if ((EncAlgorithm == DOT11_ENC_TKIP) || (EncAlgorithm == DOT11_ENC_CCMP))
{
pstat = get_stainfo(priv, ext->addr.sa_data);
if ((pstat != NULL) && (pstat->state & WIFI_ASOC_STATE))
pstat->ieee8021x_ctrlport = 1;
}
}
else if (EncAlgorithm == DOT11_ENC_NONE)
{
// Remove Key
DOT11_DELETE_KEY Delete_Key;
struct iw_point wrq;
if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104))
{
memset(priv->pmib->dot11DefaultKeysTable.keytype[KeyIndex].skey, 0, 16);
}
if (IsDefaultKey)
{
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_;
priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = 0;
}
wrq.pointer = (caddr_t)&Delete_Key;
wrq.length = sizeof(DOT11_DELETE_KEY);
memset(&Delete_Key, 0, sizeof(Delete_Key));
Delete_Key.EventId = DOT11_EVENT_DELETE_KEY;
Delete_Key.IsMoreEvent = FALSE;
Delete_Key.KeyType = (IsGroupKey ? DOT11_KeyType_Group : DOT11_KeyType_Pairwise);
memcpy(Delete_Key.MACAddr, ext->addr.sa_data, MACADDRLEN);
// check root intf is up before deleting key to avoid stuck in CAM_read_mac_config
if (IS_DRV_OPEN(GET_ROOT(priv)))
ret = DOT11_Process_Delete_Key(priv->dev, &wrq);
}
set_encodeext_end:
#ifdef SDIO_AP_OFFLOAD
ap_offload_activate(priv, OFFLOAD_PROHIBIT_COMAPI);
#endif
return ret;
}
int rtl_giwencodeext(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
s4Byte key_index;
s4Byte ret = 0;
s4Byte max_key_len;
char *pkey=NULL;
// char keybuf[32];
int keylen=0;
DEBUG_INFO("rtwlan_ioctl: rtioctl_get_encodeext: \n");
max_key_len = encoding->length - sizeof(struct iw_encode_ext);
if (max_key_len < 0)
return -EINVAL;
key_index = (encoding->flags & IW_ENCODE_INDEX) - 1;
memset(ext, 0, sizeof(struct iw_encode_ext));
switch (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) {
case _WEP_40_PRIVACY_:
case _WEP_104_PRIVACY_:
ext->alg = IW_ENCODE_ALG_WEP;
encoding->flags |= IW_ENCODE_ENABLED;
pkey = priv->pmib->dot11DefaultKeysTable.keytype[key_index].skey;
keylen = 16;
break;
case _TKIP_PRIVACY_:
ext->alg = IW_ENCODE_ALG_TKIP;
encoding->flags |= IW_ENCODE_ENABLED;
// TODO: get key
break;
case _CCMP_PRIVACY_:
ext->alg = IW_ENCODE_ALG_CCMP;
encoding->flags |= IW_ENCODE_ENABLED;
// TODO: get key
break;
case _NO_PRIVACY_:
default:
ext->alg = IW_ENCODE_ALG_NONE;
encoding->flags |= IW_ENCODE_NOKEY;
break;
}
if (!(encoding->flags & IW_ENCODE_NOKEY)) {
if (max_key_len < keylen) {
ret = -E2BIG;
goto out;
}
if (pkey)
memcpy (ext->key, pkey, keylen);
}
out:
return ret;
}
int rtl_siwpmkid(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
unsigned char j,blInserted = _FALSE;
int ret=0;
#if 0
struct iw_pmksa* pPMK = ( struct iw_pmksa* ) extra;
unsigned char strZeroMacAddress[ ETH_ALEN ] = { 0x00 };
unsigned char strIssueBssid[ ETH_ALEN ] = { 0x00 };
/*
struct iw_pmksa
{
__u32 cmd;
struct sockaddr bssid;
__u8 pmkid[IW_PMKID_LEN]; //IW_PMKID_LEN=16
}
There are the BSSID information in the bssid.sa_data array.
If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver.
If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver.
*/
memcpy( strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
if ( pPMK->cmd == IW_PMKSA_ADD )
{
DEBUG_INFO( "%s: IW_PMKSA_ADD!\n", __FUNCTION__ );
if (!memcmp( strIssueBssid, strZeroMacAddress, ETH_ALEN ))
{
return (-EINVAL);
}
blInserted = _FALSE;
//overwrite PMKID
for(j=0 ; j<NUM_PMKID_CACHE; j++)
{
if( !memcmp( priv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) )
{ // BSSID is matched, the same AP => rewrite with new PMKID.
DEBUG_INFO( "%s: BSSID exists in the PMKList.\n", __FUNCTION__ );
memcpy( priv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
priv->PMKIDList[ j ].bUsed = _TRUE;
priv->PMKIDIndex = j+1;
blInserted = _TRUE;
break;
}
}
if(!blInserted)
{
// Find a new entry
DEBUG_INFO( "[%s] Use the new entry index = %d for this PMKID.\n", __FUNCTION__,
priv->PMKIDIndex );
memcpy(priv->PMKIDList[priv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
memcpy(priv->PMKIDList[priv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
priv->PMKIDList[priv->PMKIDIndex ].bUsed = _TRUE;
priv->PMKIDIndex++ ;
if(priv->PMKIDIndex == NUM_PMKID_CACHE)
{
priv->PMKIDIndex = 0;
}
}
}
else if ( pPMK->cmd == IW_PMKSA_REMOVE )
{
DEBUG_INFO( "[%s] IW_PMKSA_REMOVE!\n", __FUNCTION__ );
for(j=0 ; j<NUM_PMKID_CACHE; j++)
{
if( !memcmp( priv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN))
{ // BSSID is matched, the same AP => Remove this PMKID information and reset it.
memset( priv->PMKIDList[ j ].Bssid, 0x00, ETH_ALEN );
priv->PMKIDList[ j ].bUsed = _FALSE;
break;
}
}
}
else if ( pPMK->cmd == IW_PMKSA_FLUSH )
{
DEBUG_INFO( "[%s] IW_PMKSA_FLUSH!\n", __FUNCTION__ );
memset( &priv->PMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
priv->PMKIDIndex = 0;
}
#endif
return( ret );
}
#endif // WIFI_WPAS_CLI
#endif // CONFIG_RTL_COMAPI_WLTOOLS
#ifdef CONFIG_RTL_COMAPI_CFGFILE
#define CFG_FILE_PATH "/etc/Wireless/RTL8192CD.dat"
void del_mib_list(struct net_device *dev);
int CfgFileSetMib(struct net_device *dev, char *buf);
int CfgFileProc(struct net_device *dev)
{
//RTL_PRIV *priv = dev->priv;
unsigned char *mem_ptr;
int ret = 0;
printk("-------> Set MIB from " CFG_FILE_PATH "\n");
if((mem_ptr = (unsigned char *)kmalloc(MAX_CONFIG_FILE_SIZE, GFP_ATOMIC)) == NULL) {
printk("%s: not enough memory\n", __FUNCTION__);
return -1;
}
memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE);
ret = CfgFileRead(dev, mem_ptr);
if (ret < 0)
{
printk("%s: ReadCfgFile failed (%d)\n", __FUNCTION__, ret);
goto proc_exit;
}
//printk("%s\n", mem_ptr);
del_mib_list(dev);
CfgFileSetMib(dev, mem_ptr);
printk("<------- Set MIB from " CFG_FILE_PATH " Success\n");
proc_exit:
kfree(mem_ptr);
return ret;
}
int CfgFileRead(struct net_device *dev, char *buf)
{
//RTL_PRIV *priv = dev->priv;
struct file *fp;
mm_segment_t oldfs;
//size_t len;
//int read_bytes = 0;
int ret = 0;
oldfs = get_fs();
set_fs(get_ds());
fp = filp_open(CFG_FILE_PATH, O_RDONLY, 0);
if(IS_ERR(fp)) {
ret = PTR_ERR(fp);
printk("Fail to open configuration file. (%d)\n", ret);
goto err_exit;
}
if (!(fp->f_op && fp->f_op->read)) {
printk("Fail to support file ops: read\n");
ret = -1;
goto err_close;
}
if ((ret = fp->f_op->read(fp, buf, MAX_CONFIG_FILE_SIZE, &fp->f_pos))< 0){
printk("Fail to read file. (%d)\n", ret);
goto err_close;
}
err_close:
filp_close(fp, NULL);
err_exit:
set_fs(oldfs);
return ret;
}
static int rewrite_line (unsigned char **dst, unsigned char **src)
{
int cnt=0;
char *s = *src;
char *d = *dst;
char *loc=NULL, *vl_s=NULL, *vl_e=NULL;
unsigned char quoted = 0;
//printk("src = %s(%d)\n", *src, strlen(*src));
loc=strchr(s, '"');
if (loc) {
unsigned int i = strlen(*src);
vl_s=loc;
while (i>0){
char *t = (char *)((unsigned long)s+i-1);
if (*t=='"' && t > vl_s ){
vl_e = t;
quoted = 1;
break;
}
i--;
}
}
while (*s) {
u8 noop = 0;
if (quoted ==1 && (vl_s < s && s < vl_e))
noop = 1;
if ( noop == 0 ) {
if ((*s=='\r') || (*s=='\n') || (*s=='#') || (*s=='\0'))
break;
if ((*s == '\t')||(*s == ' ')||(*s == '"')){
s++;
continue;
}
}
*d = *s;
s++;
d++;
cnt++;
}
*d = '\0';
//printk(" dst = %s\n", *dst);
return cnt;
}
int CfgFileSetMib(struct net_device *dev, char *buf)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
unsigned char *line_head, *next_head;
unsigned char *cmd_buf, *mibstr, *valstr, *mibstart;
//struct mib_cfg_func *tmp_mibcfg;
int ret = 0;
#ifdef VENDOR_PARAM_COMPATIBLE
int arg_num = sizeof(RTL_SUPPORT_MIBCFG)/sizeof(struct mib_cfg_func);
#endif //VENDOR_PARAM_COMPATIBLE
if((cmd_buf = (unsigned char *)kmalloc(MAX_PARAM_BUF_SIZE, GFP_ATOMIC)) == NULL) {
printk("%s(%d): not enough memory\n", __FUNCTION__, __LINE__);
return -1;
}
if((mibstr = (unsigned char *)kmalloc(20, GFP_ATOMIC)) == NULL) {
printk("%s(%d): not enough memory\n", __FUNCTION__, __LINE__);
return -1;
}
if((valstr = (unsigned char *)kmalloc(MAX_PARAM_BUF_SIZE, GFP_ATOMIC)) == NULL) {
printk("%s(%d): not enough memory\n", __FUNCTION__, __LINE__);
return -1;
}
next_head = buf;
do {
char *loc;
int len = 0, miblen = 0, vallen = 0;
//int i=0;
memset(cmd_buf, 0, MAX_PARAM_BUF_SIZE);
memset(mibstr, 0, 20);
memset(valstr, 0, MAX_PARAM_BUF_SIZE);
line_head = next_head;
next_head = get_line(&line_head);
if (line_head == NULL)
break;
if (line_head[0] == '#')
continue;
len = rewrite_line(&cmd_buf, &line_head);
//printk("%s (%d)\n", cmd_buf, len);
#ifdef VENDOR_PARAM_COMPATIBLE
/* To compatible with other vendor's parameters, each parameter must have its own process function - chris*/
loc = strchr(mibstart, '=');
miblen = (u32)loc - (u32)mibstart;
vallen = len - miblen -1;
if (vallen>0) {
for (i=0; i<arg_num; i++) {
if (strcmp(mibstr, RTL_SUPPORT_MIBCFG[i].name) == 0) {
if(!RTL_SUPPORT_MIBCFG[i].set_proc(priv, valstr)) {
printk("CFGFILE set %s failed \n", mibstr);
return -1;
}
break;
}
}
}
#else
//printk(">>>>>>>> cmd=%s , %s, %c \n",cmd_buf, dev->name, cmd_buf[strlen(dev->name)]);
if (!strncmp(dev->name, cmd_buf, strlen(dev->name))&&(cmd_buf[strlen(dev->name)]!='-')) {
mibstart = cmd_buf + strlen(dev->name)+1;
} else
continue;
loc = strchr(mibstart, '=');
miblen = (u32)loc - (u32)mibstart;
vallen = len - (strlen(dev->name)+1) - (miblen+1);
if (vallen>0) {
ret = set_mib(priv, mibstart);
if (ret < 0) {
strncpy(mibstr, mibstart, miblen);
strncpy(valstr, (char*)((u32)loc+1), vallen);
//printk("(%s) = (%s) (%d)\n", mibstr, valstr, vallen);
printk("CFGFILE set_mib \"%s\" failed \n", mibstart);
//return -1;
}
#endif // VENDOR_PARAM_COMPATIBLE
}
} while (1);
kfree(cmd_buf);
kfree(mibstr);
kfree(valstr);
return ret;
}
void del_mib_list(struct net_device *dev)
{
RTL_PRIV *priv = GET_DEV_PRIV(dev);
if (priv->pmib) {
#ifdef WDS
priv->pmib->dot11WdsInfo.wdsNum = 0;
#endif
priv->pmib->dot11StationConfigEntry.dot11AclNum=0;
}
}
#endif //CONFIG_RTL_COMAPI_CFGFILE