/* * 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 #include #include #include #include #include #include #endif #ifdef __LINUX_2_6__ #include #include #endif #include "./8192cd_debug.h" #include "./8192cd_comapi.h" #include "./8192cd_headers.h" #ifdef CONFIG_RTL_COMAPI_WLTOOLS #include #include #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; ibitrate[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; ipmib->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 ; jPMKIDList[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 ; jPMKIDList[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>>>>>>> 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