+++ /dev/null
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _IOCTL_LINUX_C_
-
-#include <drv_conf.h>
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wlan_bssdef.h>
-#include <rtw_debug.h>
-#include <wifi.h>
-#include <rtw_mlme.h>
-#include <rtw_mlme_ext.h>
-#include <rtw_ioctl.h>
-#include <rtw_ioctl_set.h>
-#include <rtw_ioctl_query.h>
-
-//#ifdef CONFIG_MP_INCLUDED
-#include <rtw_mp_ioctl.h>
-//#endif
-
-#ifdef CONFIG_USB_HCI
-#include <usb_ops.h>
-#endif //CONFIG_USB_HCI
-#include <rtw_version.h>
-
-#ifdef CONFIG_RTL8192D
-#include <rtl8192d_hal.h>
-#endif
-
-#ifdef CONFIG_RTL8192C
-#include <rtl8192c_hal.h>
-#endif
-
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
-#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)
-#endif
-
-
-#define RTL_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
-
-#define SCAN_ITEM_SIZE 768
-#define MAX_CUSTOM_LEN 64
-#define RATE_COUNT 4
-
-#ifdef CONFIG_GLOBAL_UI_PID
-extern int ui_pid[3];
-#endif
-extern int sleep_resume;
-// combo scan
-#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
-#define WEXT_CSCAN_HEADER_SIZE 12
-#define WEXT_CSCAN_SSID_SECTION 'S'
-#define WEXT_CSCAN_CHANNEL_SECTION 'C'
-#define WEXT_CSCAN_NPROBE_SECTION 'N'
-#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
-#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
-#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
-#define WEXT_CSCAN_TYPE_SECTION 'T'
-
-
-extern u8 key_2char2num(u8 hch, u8 lch);
-extern u8 str_2char2num(u8 hch, u8 lch);
-
-int rfpwrstate_check(_adapter *padapter);
-
-u32 rtw_rates[] = {1000000,2000000,5500000,11000000,
- 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
-
-static const char * const iw_operation_mode[] =
-{
- "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor"
-};
-
-static int hex2num_i(char c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- return -1;
-}
-
-static int hex2byte_i(const char *hex)
-{
- int a, b;
- a = hex2num_i(*hex++);
- if (a < 0)
- return -1;
- b = hex2num_i(*hex++);
- if (b < 0)
- return -1;
- return (a << 4) | b;
-}
-
-/**
- * hwaddr_aton - Convert ASCII string to MAC address
- * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
- * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
- * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
- */
-static int hwaddr_aton_i(const char *txt, u8 *addr)
-{
- int i;
-
- for (i = 0; i < 6; i++) {
- int a, b;
-
- a = hex2num_i(*txt++);
- if (a < 0)
- return -1;
- b = hex2num_i(*txt++);
- if (b < 0)
- return -1;
- *addr++ = (a << 4) | b;
- if (i < 5 && *txt++ != ':')
- return -1;
- }
-
- return 0;
-}
-
-static void request_wps_pbc_event(_adapter *padapter)
-{
- u8 *buff, *p;
- union iwreq_data wrqu;
-
-
- buff = rtw_malloc(IW_CUSTOM_MAX);
- if(!buff)
- return;
-
- _rtw_memset(buff, 0, IW_CUSTOM_MAX);
-
- p=buff;
-
- p+=sprintf(p, "WPS_PBC_START.request=TRUE");
-
- _rtw_memset(&wrqu,0,sizeof(wrqu));
-
- wrqu.data.length = p-buff;
-
- wrqu.data.length = (wrqu.data.length<IW_CUSTOM_MAX) ? wrqu.data.length:IW_CUSTOM_MAX;
-
- DBG_8192C("%s\n", __FUNCTION__);
-
- wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
-
- if(buff)
- {
- rtw_mfree(buff, IW_CUSTOM_MAX);
- }
-
-}
-
-
-void indicate_wx_scan_complete_event(_adapter *padapter)
-{
- union iwreq_data wrqu;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
-
- //DBG_8192C("+rtw_indicate_wx_scan_complete_event\n");
- wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
-}
-
-
-void rtw_indicate_wx_assoc_event(_adapter *padapter)
-{
- union iwreq_data wrqu;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-
- _rtw_memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
-
- //DBG_8192C("+rtw_indicate_wx_assoc_event\n");
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-void rtw_indicate_wx_disassoc_event(_adapter *padapter)
-{
- union iwreq_data wrqu;
-
- _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- _rtw_memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
-
- //DBG_8192C("+rtw_indicate_wx_disassoc_event\n");
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-/*
-uint rtw_is_cckrates_included(u8 *rate)
-{
- u32 i = 0;
-
- while(rate[i]!=0)
- {
- if ( (((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
- (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22) )
- return _TRUE;
- i++;
- }
-
- return _FALSE;
-}
-
-uint rtw_is_cckratesonly_included(u8 *rate)
-{
- u32 i = 0;
-
- while(rate[i]!=0)
- {
- if ( (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
- (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22) )
- return _FALSE;
- i++;
- }
-
- return _TRUE;
-}
-*/
-
-static char *translate_scan(_adapter *padapter,
- struct iw_request_info* info, struct wlan_network *pnetwork,
- char *start, char *stop)
-{
- struct iw_event iwe;
- u16 cap;
- u32 ht_ielen = 0;
- char custom[MAX_CUSTOM_LEN];
- char *p;
- u16 max_rate=0, rate, ht_cap=_FALSE;
- u32 i = 0;
- char *current_val;
- long rssi;
- u8 bw_40MHz=0, short_GI=0;
- u16 mcs_rate=0;
- struct registry_priv *pregpriv = &padapter->registrypriv;
-#ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif //CONFIG_P2P
-
-#ifdef CONFIG_TDLS
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-
- if(pnetwork->network.Reserved[1]!='T')
- return start;
-#endif
-
-#ifdef CONFIG_P2P
- if ( ( pwdinfo->p2p_state != P2P_STATE_NONE ) && ( pwdinfo->p2p_state != P2P_STATE_IDLE ) )
- {
- u32 blnGotP2PIE = _FALSE;
-
- // User is doing the P2P device discovery
- // The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE.
- // If not, the driver should ignore this AP and go to the next AP.
-
- // Verifying the SSID
- if ( _rtw_memcmp( pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN ) )
- {
- u32 p2pielen = 0;
-
- // Verifying the P2P IE
- if ( rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen) )
- {
- blnGotP2PIE = _TRUE;
- }
-
- }
-
- if ( blnGotP2PIE == _FALSE )
- {
- return start;
- }
-
- }
-
-#endif //CONFIG_P2P
-
- /* AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-
- _rtw_memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
-
-#ifdef CONFIG_TDLS
- if(pmlmeinfo->tdls_dis_req==0){
-#endif
-
- /* Add the ESSID */
-#ifdef CONFIG_ANDROID
- if(rtw_validate_ssid(&(pnetwork->network.Ssid))==_FALSE)
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("translate_scan : rtw_validate_ssid==FALSE \n"));
- }
- else
-#endif
- {
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
- }
-
-#ifdef CONFIG_TDLS
- }
-#endif
-
- //parsing HT_CAP_IE
-#ifdef CONFIG_TDLS
- if(pmlmeinfo->tdls_dis_req==0)
- p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
- else
- //parsing TDLS discovery response frame, information elements start after fixed IE 5 bytes
- p = rtw_get_ie(&pnetwork->network.IEs[5], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-5);
-#else
- p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
-#endif
- if(p && ht_ielen>0)
- {
- struct ieee80211_ht_cap *pht_capie;
- ht_cap = _TRUE;
- pht_capie = (struct ieee80211_ht_cap *)(p+2);
- _rtw_memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
- bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1:0;
- short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1:0;
- }
-
- /* Add the protocol name */
- iwe.cmd = SIOCGIWNAME;
- if ((rtw_is_cckratesonly_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE)
- {
- if(ht_cap == _TRUE)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
- }
- else if ((rtw_is_cckrates_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE)
- {
- if(ht_cap == _TRUE)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
- }
- else
- {
- if(pnetwork->network.Configuration.DSConfig > 14)
- {
- if(ht_cap == _TRUE)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
- }
- else
- {
- if(ht_cap == _TRUE)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
- }
- }
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
-
-#ifdef CONFIG_TDLS
- if(pmlmeinfo->tdls_dis_req==0){
-#endif
-
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
-
-
- cap = le16_to_cpu(cap);
-
- if(cap & (WLAN_CAPABILITY_IBSS |WLAN_CAPABILITY_BSS)){
- if (cap & WLAN_CAPABILITY_BSS)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
- }
-
- if(pnetwork->network.Configuration.DSConfig<1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
- pnetwork->network.Configuration.DSConfig = 1;
-
- /* Add frequency/channel */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
- iwe.u.freq.e = 1;
- iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (cap & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
-
-#ifdef CONFIG_TDLS
- }
-#endif
-
- /*Add basic and extended rates */
- max_rate = 0;
- p = custom;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
- while(pnetwork->network.SupportedRates[i]!=0)
- {
- rate = pnetwork->network.SupportedRates[i]&0x7F;
- if (rate > max_rate)
- max_rate = rate;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
- "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
- i++;
- }
-
- if(ht_cap == _TRUE)
- {
- if(mcs_rate&0x8000)//MCS15
- {
- max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
-
- }
- else if(mcs_rate&0x0080)//MCS7
- {
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
- }
- else//default MCS7
- {
- DBG_8192C("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate);
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
- }
-
- max_rate = max_rate*2;//Mbps/2;
- }
-
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = max_rate * 500000;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
-
-#ifdef CONFIG_TDLS
- if(pmlmeinfo->tdls_dis_req==0){
-#endif
-
- //parsing WPA/WPA2 IE
- {
- u8 buf[MAX_WPA_IE_LEN];
- u8 wpa_ie[255],rsn_ie[255];
- u16 wpa_len=0,rsn_len=0;
- u8 *p;
- sint out_len=0;
- out_len=rtw_get_sec_ie(pnetwork->network.IEs ,pnetwork->network.IELength,rsn_ie,&rsn_len,wpa_ie,&wpa_len);
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: ssid=%s\n",pnetwork->network.Ssid.Ssid));
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
-
- if (wpa_len > 0)
- {
- p=buf;
- _rtw_memset(buf, 0, MAX_WPA_IE_LEN);
- p += sprintf(p, "wpa_ie=");
- for (i = 0; i < wpa_len; i++) {
- p += sprintf(p, "%02x", wpa_ie[i]);
- }
-
- _rtw_memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, &iwe,buf);
-
- _rtw_memset(&iwe, 0, sizeof(iwe));
- iwe.cmd =IWEVGENIE;
- iwe.u.data.length = wpa_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
- }
- if (rsn_len > 0)
- {
- p = buf;
- _rtw_memset(buf, 0, MAX_WPA_IE_LEN);
- p += sprintf(p, "rsn_ie=");
- for (i = 0; i < rsn_len; i++) {
- p += sprintf(p, "%02x", rsn_ie[i]);
- }
- _rtw_memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, &iwe,buf);
-
- _rtw_memset(&iwe, 0, sizeof(iwe));
- iwe.cmd =IWEVGENIE;
- iwe.u.data.length = rsn_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
- }
- }
-
- { //parsing WPS IE
- int cnt = 0,total_ielen=0;
- u8 *wpsie_ptr=NULL;
- uint wps_ielen = 0;
-
- u8 *ie_ptr = pnetwork->network.IEs +_FIXED_IE_LENGTH_;
- total_ielen= pnetwork->network.IELength - _FIXED_IE_LENGTH_;
- if((ie_ptr) && (total_ielen>0))
- {
- while(cnt < total_ielen)
- {
- if(rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen>2))
- {
- wpsie_ptr = &ie_ptr[cnt];
- iwe.cmd =IWEVGENIE;
- iwe.u.data.length = (u16)wps_ielen;
- start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
- }
- cnt+=ie_ptr[cnt+1]+2; //goto next
- }
- }
- }
-
-#ifdef CONFIG_TDLS
- }
-#endif
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- rssi = pnetwork->network.Rssi;//dBM
-
-#ifdef CONFIG_RTL8711
- rssi = (rssi*2) + 190;
- if(rssi>100) rssi = 100;
- if(rssi<0) rssi = 0;
-#endif
-
- //DBG_8192C("RSSI=0x%X%%\n", rssi);
-
- // we only update signal_level (signal strength) that is rssi.
- iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID
- #ifdef CONFIG_ANDROID
- | IW_QUAL_DBM
- #endif
- ;
-
- #ifdef CONFIG_ANDROID
- iwe.u.qual.level = (u8)pnetwork->network.Rssi;//dbm
- #else
- iwe.u.qual.level = (u8)pnetwork->network.PhyInfo.SignalStrength;//%
- #endif //CONFIG_ANDROID
-
- iwe.u.qual.qual = (u8)pnetwork->network.PhyInfo.SignalStrength; // signal quality
-
- #ifdef CONFIG_PLATFORM_ROCKCHIPS
- iwe.u.qual.noise = -100; // noise level suggest by zhf@rockchips
- #else
- iwe.u.qual.noise = 0; // noise level
- #endif //CONFIG_PLATFORM_ROCKCHIPS
-
- //DBG_8192C("iqual=%d, ilevel=%d, inoise=%d, iupdated=%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated);
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
-
- //how to translate rssi to ?%
- //rssi = (iwe.u.qual.level*2) + 190;
- //if(rssi>100) rssi = 100;
- //if(rssi<0) rssi = 0;
-
- return start;
-}
-
-static int wpa_set_auth_algs(struct net_device *dev, u32 value)
-{
- _adapter *padapter = (_adapter *) rtw_netdev_priv(dev);
- int ret = 0;
-
- if ((value & AUTH_ALG_SHARED_KEY)&&(value & AUTH_ALG_OPEN_SYSTEM))
- {
- DBG_8192C("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n",value);
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
- }
- else if (value & AUTH_ALG_SHARED_KEY)
- {
- DBG_8192C("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY [value:0x%x]\n",value);
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
-
-#ifdef CONFIG_PLATFORM_MT53XX
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
-#else
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
-#endif
- }
- else if(value & AUTH_ALG_OPEN_SYSTEM)
- {
- DBG_8192C("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
- //padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- if(padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK)
- {
-#ifdef CONFIG_PLATFORM_MT53XX
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
-#else
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
-#endif
- }
-
- }
- else if(value & AUTH_ALG_LEAP)
- {
- DBG_8192C("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
- }
- else
- {
- DBG_8192C("wpa_set_auth_algs, error!\n");
- ret = -EINVAL;
- }
-
- return ret;
-
-}
-
-static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
-{
- int ret = 0;
- u32 wep_key_idx, wep_key_len;
- NDIS_802_11_WEP *pwep = NULL;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-#ifdef CONFIG_P2P
- struct wifidirect_info* pwdinfo = &padapter->wdinfo;
-#endif //CONFIG_P2P
-
-_func_enter_;
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
- if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)
- {
- ret = -EINVAL;
- goto exit;
- }
-
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
- {
- if (param->u.crypt.idx >= WEP_KEYS)
- {
- ret = -EINVAL;
- goto exit;
- }
- } else {
- ret = -EINVAL;
- goto exit;
- }
-
- if (strcmp(param->u.crypt.alg, "WEP") == 0)
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("wpa_set_encryption, crypt.alg = WEP\n"));
- DBG_8192C("wpa_set_encryption, crypt.alg = WEP\n");
-
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
- padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
-
- wep_key_idx = param->u.crypt.idx;
- wep_key_len = param->u.crypt.key_len;
-
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("(1)wep_key_idx=%d\n", wep_key_idx));
- DBG_8192C("(1)wep_key_idx=%d\n", wep_key_idx);
-
- if (wep_key_idx > WEP_KEYS)
- return -EINVAL;
-
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("(2)wep_key_idx=%d\n", wep_key_idx));
-
- if (wep_key_len > 0)
- {
- wep_key_len = wep_key_len <= 5 ? 5 : 13;
-
- pwep =(NDIS_802_11_WEP *) rtw_malloc(wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial));
- if(pwep == NULL){
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,(" wpa_set_encryption: pwep allocate fail !!!\n"));
- goto exit;
- }
-
- _rtw_memset(pwep, 0, sizeof(NDIS_802_11_WEP));
-
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
-
- if(wep_key_len==13)
- {
- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
- padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;
- }
- }
- else {
- ret = -EINVAL;
- goto exit;
- }
-
- pwep->KeyIndex = wep_key_idx;
- pwep->KeyIndex |= 0x80000000;
-
- _rtw_memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
-
- if(param->u.crypt.set_tx)
- {
- DBG_8192C("wep, set_tx=1\n");
-
- if(rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
- {
- ret = -EOPNOTSUPP ;
- }
- }
- else
- {
- DBG_8192C("wep, set_tx=0\n");
-
- //don't update "psecuritypriv->dot11PrivacyAlgrthm" and
- //"psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to fw/cam
-
- if (wep_key_idx >= WEP_KEYS) {
- ret = -EOPNOTSUPP ;
- goto exit;
- }
-
- _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
- psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;
- rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
- }
-
- goto exit;
- }
-
- if(padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) // 802_1x
- {
- struct sta_info * psta,*pbcmc_sta;
- struct sta_priv * pstapriv = &padapter->stapriv;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) //sta mode
- {
- psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
- if (psta == NULL) {
- //DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail \n"));
- }
- else
- {
- //Jeff: don't disable ieee8021x_blocked while clearing key
- if (strcmp(param->u.crypt.alg, "none") != 0)
- psta->ieee8021x_blocked = _FALSE;
-
- if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
- (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
- {
- psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
- }
-
- if(param->u.crypt.set_tx ==1)//pairwise key
- {
- _rtw_memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
-
- if(strcmp(param->u.crypt.alg, "TKIP") == 0)//set mic key
- {
- //DEBUG_ERR(("\nset key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len));
- _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
- _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
-
- padapter->securitypriv.busetkipkey=_FALSE;
- //_set_timer(&padapter->securitypriv.tkip_timer, 50);
- }
-
- //DEBUG_ERR(("\n param->u.crypt.key_len=%d\n",param->u.crypt.key_len));
- //DEBUG_ERR(("\n ~~~~stastakey:unicastkey\n"));
- DBG_871X("\n ~~~~stastakey:unicastkey\n");
-
- rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE);
- }
- else//group key
- {
- _rtw_memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key,(param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
- _rtw_memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[16]),8);
- _rtw_memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[24]),8);
- padapter->securitypriv.binstallGrpkey = _TRUE;
- //DEBUG_ERR(("\n param->u.crypt.key_len=%d\n", param->u.crypt.key_len));
- //DEBUG_ERR(("\n ~~~~stastakey:groupkey\n"));
- DBG_871X("\n ~~~~stastakey:groupkey\n");
-
- padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
-
- rtw_set_key(padapter,&padapter->securitypriv,param->u.crypt.idx, 1);
-#ifdef CONFIG_P2P
- if ( pwdinfo->p2p_state == P2P_STATE_PROVISIONING_ING )
- {
- pwdinfo->p2p_state = P2P_STATE_PROVISIONING_DONE;
- }
-#endif //CONFIG_P2P
-
- }
- }
-
- pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
- if(pbcmc_sta==NULL)
- {
- //DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null \n"));
- }
- else
- {
- //Jeff: don't disable ieee8021x_blocked while clearing key
- if (strcmp(param->u.crypt.alg, "none") != 0)
- pbcmc_sta->ieee8021x_blocked = _FALSE;
-
- if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
- (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
- {
- pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
- }
- }
- }
- else if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) //adhoc mode
- {
- }
- }
-
-exit:
-
- if (pwep) {
- rtw_mfree((u8 *)pwep, wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial));
- }
-
- _func_exit_;
-
- return ret;
-}
-
-static int rtw_set_wpa_ie(_adapter *padapter, char *pie, unsigned short ielen)
-{
- u8 *buf=NULL, *pos=NULL;
- u32 left;
- int group_cipher = 0, pairwise_cipher = 0;
- int ret = 0;
-#ifdef CONFIG_P2P
- struct wifidirect_info* pwdinfo = &padapter->wdinfo;
-#endif //CONFIG_P2P
-
- if((ielen > MAX_WPA_IE_LEN) || (pie == NULL)){
- padapter->securitypriv.wps_phase = _FALSE;
- if(pie == NULL)
- return ret;
- else
- return -EINVAL;
- }
-
- if(ielen)
- {
- buf = rtw_zmalloc(ielen);
- if (buf == NULL){
- ret = -ENOMEM;
- goto exit;
- }
-
- _rtw_memcpy(buf, pie , ielen);
-/*
- //dump
- {
- int i;
- DBG_8192C("\n wpa_ie(length:%d):\n", ielen);
- for(i=0;i<ielen;i=i+8)
- DBG_8192C("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",buf[i],buf[i+1],buf[i+2],buf[i+3],buf[i+4],buf[i+5],buf[i+6],buf[i+7]);
- }
-*/
- pos = buf;
- if(ielen < RSN_HEADER_LEN){
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("Ie len too short %d\n", ielen));
- ret = -1;
- goto exit;
- }
-
-#if 0
- pos += RSN_HEADER_LEN;
- left = ielen - RSN_HEADER_LEN;
-
- if (left >= RSN_SELECTOR_LEN){
- pos += RSN_SELECTOR_LEN;
- left -= RSN_SELECTOR_LEN;
- }
- else if (left > 0){
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("Ie length mismatch, %u too much \n", left));
- ret =-1;
- goto exit;
- }
-#endif
-
- if(rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher) == _SUCCESS)
- {
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
- padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPAPSK;
- }
-
- if(rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher) == _SUCCESS)
- {
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
- padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPA2PSK;
- }
-
- switch(group_cipher)
- {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.dot118021XGrpPrivacy=_TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.dot118021XGrpPrivacy=_AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
-
- switch(pairwise_cipher)
- {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.dot11PrivacyAlgrthm=_TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.dot11PrivacyAlgrthm=_AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
-
- padapter->securitypriv.wps_phase = _FALSE;
- {//set wps_ie
- u16 cnt = 0;
- u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
-
- while( cnt < ielen )
- {
- eid = buf[cnt];
-
- if((eid==_VENDOR_SPECIFIC_IE_)&&(_rtw_memcmp(&buf[cnt+2], wps_oui, 4)==_TRUE))
- {
- DBG_8192C("SET WPS_IE\n");
-
- padapter->securitypriv.wps_ie_len = ( (buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2):(MAX_WPA_IE_LEN<<2);
-
- _rtw_memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
-
- padapter->securitypriv.wps_phase = _TRUE;
-
-#ifdef CONFIG_P2P
- if ( pwdinfo->p2p_state == P2P_STATE_GONEGO_OK )
- {
- pwdinfo->p2p_state = P2P_STATE_PROVISIONING_ING;
- }
-#endif //CONFIG_P2P
- DBG_8192C("SET WPS_IE, wps_phase==_TRUE\n");
-
- cnt += buf[cnt+1]+2;
-
- break;
- } else {
- cnt += buf[cnt+1]+2; //goto next
- }
- }
- }
- }
-
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
- ("rtw_set_wpa_ie: pairwise_cipher=0x%08x padapter->securitypriv.ndisencryptstatus=%d padapter->securitypriv.ndisauthtype=%d\n",
- pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
-
-exit:
-
- if (buf) rtw_mfree(buf, ielen);
-
- return ret;
-}
-
-static int rtw_wx_get_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- u16 cap;
- u32 ht_ielen = 0;
- char *p;
- u8 ht_cap=_FALSE;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
- NDIS_802_11_RATES_EX* prates = NULL;
-
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("cmd_code=%x\n", info->cmd));
-
- _func_enter_;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == _TRUE)
- {
- //parsing HT_CAP_IE
- p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
- if(p && ht_ielen>0)
- {
- ht_cap = _TRUE;
- }
-
- prates = &pcur_bss->SupportedRates;
-
- if (rtw_is_cckratesonly_included((u8*)prates) == _TRUE)
- {
- if(ht_cap == _TRUE)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
- }
- else if ((rtw_is_cckrates_included((u8*)prates)) == _TRUE)
- {
- if(ht_cap == _TRUE)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
- }
- else
- {
- if(pcur_bss->Configuration.DSConfig > 14)
- {
- if(ht_cap == _TRUE)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
- }
- else
- {
- if(ht_cap == _TRUE)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
- }
- }
- }
- else
- {
- //prates = &padapter->registrypriv.dev_network.SupportedRates;
- //snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
- snprintf(wrqu->name, IFNAMSIZ, "unassociated");
- }
-
- _func_exit_;
-
- return 0;
-}
-
-static int rtw_wx_set_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _func_enter_;
-
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
-
- _func_exit_;
-
- return 0;
-}
-
-static int rtw_wx_get_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
-
- if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
- {
- //wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000;
- wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = pcur_bss->Configuration.DSConfig;
-
- }
- else{
- wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
- }
-
- return 0;
-}
-
-static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
- int ret = 0;
-
- _func_enter_;
-
- if(_FAIL == rfpwrstate_check(padapter)) {
- ret= _FAIL;
- goto exit;
- }
-
- if (padapter->hw_init_completed==_FALSE){
- ret = -EPERM;
- goto exit;
- }
-
- switch(wrqu->mode)
- {
- case IW_MODE_AUTO:
- networkType = Ndis802_11AutoUnknown;
- DBG_8192C("set_mode = IW_MODE_AUTO\n");
- break;
- case IW_MODE_ADHOC:
- networkType = Ndis802_11IBSS;
- DBG_8192C("set_mode = IW_MODE_ADHOC\n");
- break;
- case IW_MODE_MASTER:
- networkType = Ndis802_11APMode;
- DBG_8192C("set_mode = IW_MODE_MASTER\n");
- //rtw_setopmode_cmd(padapter, networkType);
- break;
- case IW_MODE_INFRA:
- networkType = Ndis802_11Infrastructure;
- DBG_8192C("set_mode = IW_MODE_INFRA\n");
- break;
-
- default :
- ret = -EINVAL;;
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("\n Mode: %s is not supported \n", iw_operation_mode[wrqu->mode]));
- goto exit;
- }
-
-/*
- if(Ndis802_11APMode == networkType)
- {
- rtw_setopmode_cmd(padapter, networkType);
- }
- else
- {
- rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
- }
-*/
-
- if (rtw_set_802_11_infrastructure_mode(padapter, networkType) ==_FALSE){
-
- ret = -1;
- goto exit;
-
- }
-
- rtw_setopmode_cmd(padapter, networkType);
-
-exit:
-
- _func_exit_;
-
- return ret;
-
-}
-
-static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,(" rtw_wx_get_mode \n"));
-
- _func_enter_;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
- {
- wrqu->mode = IW_MODE_INFRA;
- }
- else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
-
- {
- wrqu->mode = IW_MODE_ADHOC;
- }
- else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
- {
- wrqu->mode = IW_MODE_MASTER;
- }
- else
- {
- wrqu->mode = IW_MODE_AUTO;
- }
-
- _func_exit_;
-
- return 0;
-
-}
-
-
-static int rtw_wx_set_pmkid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- u8 j,blInserted = _FALSE;
- int intReturn = _FALSE;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct iw_pmksa* pPMK = ( struct iw_pmksa* ) extra;
- u8 strZeroMacAddress[ ETH_ALEN ] = { 0x00 };
- u8 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.
- */
-
- _rtw_memcpy( strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
- if ( pPMK->cmd == IW_PMKSA_ADD )
- {
- DBG_8192C( "[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n" );
- if ( _rtw_memcmp( strIssueBssid, strZeroMacAddress, ETH_ALEN ) == _TRUE )
- {
- return( intReturn );
- }
- else
- {
- intReturn = _TRUE;
- }
- blInserted = _FALSE;
-
- //overwrite PMKID
- for(j=0 ; j<NUM_PMKID_CACHE; j++)
- {
- if( _rtw_memcmp( psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) ==_TRUE )
- { // BSSID is matched, the same AP => rewrite with new PMKID.
-
- DBG_8192C( "[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n" );
-
- _rtw_memcpy( psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
- psecuritypriv->PMKIDList[ j ].bUsed = _TRUE;
- psecuritypriv->PMKIDIndex = j+1;
- blInserted = _TRUE;
- break;
- }
- }
-
- if(!blInserted)
- {
- // Find a new entry
- DBG_8192C( "[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
- psecuritypriv->PMKIDIndex );
-
- _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
- _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
-
- psecuritypriv->PMKIDList[ psecuritypriv->PMKIDIndex ].bUsed = _TRUE;
- psecuritypriv->PMKIDIndex++ ;
- if(psecuritypriv->PMKIDIndex==16)
- {
- psecuritypriv->PMKIDIndex =0;
- }
- }
- }
- else if ( pPMK->cmd == IW_PMKSA_REMOVE )
- {
- DBG_8192C( "[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n" );
- intReturn = _TRUE;
- for(j=0 ; j<NUM_PMKID_CACHE; j++)
- {
- if( _rtw_memcmp( psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) ==_TRUE )
- { // BSSID is matched, the same AP => Remove this PMKID information and reset it.
- _rtw_memset( psecuritypriv->PMKIDList[ j ].Bssid, 0x00, ETH_ALEN );
- psecuritypriv->PMKIDList[ j ].bUsed = _FALSE;
- break;
- }
- }
- }
- else if ( pPMK->cmd == IW_PMKSA_FLUSH )
- {
- DBG_8192C( "[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n" );
- _rtw_memset( &psecuritypriv->PMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
- psecuritypriv->PMKIDIndex = 0;
- intReturn = _TRUE;
- }
- return( intReturn );
-}
-
-static int rtw_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- #ifdef CONFIG_PLATFORM_ROCKCHIPS
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-
- /*
- * 20110311 Commented by Jeff
- * For rockchip platform's wpa_driver_wext_get_rssi
- */
- if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
- //wrqu->sens.value=-padapter->recvpriv.signal_strength;
- wrqu->sens.value=-padapter->recvpriv.rssi;
- //DBG_871X("%s: %d\n", __FUNCTION__, wrqu->sens.value);
- wrqu->sens.fixed = 0; /* no auto select */
- } else
- #endif
- {
- wrqu->sens.value = 0;
- wrqu->sens.fixed = 0; /* no auto select */
- wrqu->sens.disabled = 1;
- }
- return 0;
-}
-
-static int rtw_wx_get_range(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_range *range = (struct iw_range *)extra;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- u16 val;
- int i;
-
- _func_enter_;
-
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_range. cmd_code=%x\n", info->cmd));
-
- wrqu->data.length = sizeof(*range);
- _rtw_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 = 7; /* Updated all three */
-
-
- range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
- range->avg_qual.level = 20 + -98;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 7; /* Updated all three */
-
- range->num_bitrates = RATE_COUNT;
-
- for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
- range->bitrate[i] = rtw_rates[i];
- }
-
- 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 = 16;
-
-// 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 */
-
- for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
-
- // Include only legal frequencies for some countries
- if(pmlmeext->channel_set[i].ChannelNum != 0)
- {
- range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
- range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
- range->freq[val].e = 1;
- val++;
- }
-
- if (val == IW_MAX_FREQUENCIES)
- break;
- }
-
- range->num_channels = val;
- range->num_frequency = val;
-
-// 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 //WIRELESS_EXT > 21
- 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
-
-
- _func_exit_;
-
- return 0;
-
-}
-
-//set bssid flow
-//s1. rtw_set_802_11_infrastructure_mode()
-//s2. rtw_set_802_11_authentication_mode()
-//s3. set_802_11_encryption_mode()
-//s4. rtw_set_802_11_bssid()
-static int rtw_wx_set_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
-{
- uint ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct sockaddr *temp = (struct sockaddr *)awrq;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- _list *phead;
- u8 *dst_bssid, *src_bssid;
- _queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- NDIS_802_11_AUTHENTICATION_MODE authmode;
-
- _func_enter_;
-
- if(_FAIL == rfpwrstate_check(padapter))
- {
- ret= -1;
- printk("%s: rfpwrstate_check fail.\n", __func__);
- goto exit;
- }
-
- if(!padapter->bup){
- ret = -1;
- goto exit;
- }
-
-
- if (temp->sa_family != ARPHRD_ETHER){
- ret = -EINVAL;
- printk("%s: temp->sa_family != ARPHRD_ETHER.\n", __func__);
- goto exit;
- }
-
- authmode = padapter->securitypriv.ndisauthtype;
-
- phead = get_list_head(queue);
- pmlmepriv->pscanned = get_next(phead);
-
- while (1)
- {
-
- if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == _TRUE)
- {
-#if 0
- ret = -EINVAL;
- goto exit;
-
- if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
- {
- rtw_set_802_11_bssid(padapter, temp->sa_data);
- goto exit;
- }
- else
- {
- ret = -EINVAL;
- goto exit;
- }
-#endif
-
- if (rtw_set_802_11_bssid(padapter, temp->sa_data) == _FALSE)
- ret = -1;
-
- goto exit;
- }
-
- pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
-
- pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
-
- dst_bssid = pnetwork->network.MacAddress;
-
- src_bssid = temp->sa_data;
-
- if ((_rtw_memcmp(dst_bssid, src_bssid, ETH_ALEN)) == _TRUE)
- {
- if(!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode))
- {
- ret = -1;
- goto exit;
- }
-
- break;
- }
-
- }
-
- rtw_set_802_11_authentication_mode(padapter, authmode);
-
- //set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);
-
- if (rtw_set_802_11_bssid(padapter, temp->sa_data) == _FALSE) {
- ret = -1;
- goto exit;
- }
-
-exit:
-
- _func_exit_;
-
- return ret;
-}
-
-static int rtw_wx_get_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
-
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
-
- _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
-
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_wap\n"));
-
- _func_enter_;
-
- if ( ((check_fwstate(pmlmepriv, _FW_LINKED)) == _TRUE) ||
- ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == _TRUE) ||
- ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == _TRUE) )
- {
-
- _rtw_memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
- }
- else
- {
- _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
- }
-
- _func_exit_;
-
- return 0;
-
-}
-
-static int rtw_wx_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-#if 0
-/* SIOCSIWMLME data */
-struct iw_mlme
-{
- __u16 cmd; /* IW_MLME_* */
- __u16 reason_code;
- struct sockaddr addr;
-};
-#endif
-
- int ret=0;
- u16 reason;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_mlme *mlme = (struct iw_mlme *) extra;
-
-
- if(mlme==NULL)
- return -1;
-
- reason = cpu_to_le16(mlme->reason_code);
-
- switch (mlme->cmd)
- {
- case IW_MLME_DEAUTH:
- if(!rtw_set_802_11_disassociate(padapter))
- ret = -1;
- break;
-
- case IW_MLME_DISASSOC:
- if(!rtw_set_802_11_disassociate(padapter))
- ret = -1;
-
- break;
-
- default:
- return -EOPNOTSUPP;
- }
-
- return ret;
-
-}
-
-int rfpwrstate_check(_adapter *padapter)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- int ret = _SUCCESS;
-
- //block here for system suspend only
- if((pwrpriv->bInternalAutoSuspend == _FALSE) && (_TRUE == pwrpriv->bInSuspend )){
- ret = _FAIL;
- goto exit;
- }
-
- if( pwrpriv->power_mgnt == PS_MODE_ACTIVE ) {
- goto exit;
- }
-
- if((pwrpriv->bInternalAutoSuspend == _TRUE) && (padapter->net_closed == _TRUE)) {
- ret = _FAIL;
- goto exit;
- }
- if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
- {
- ret = _SUCCESS;
- goto exit;
- }
-
- if(rf_off == pwrpriv->rf_pwrstate )
- {
-#ifdef CONFIG_USB_HCI
-#ifdef CONFIG_AUTOSUSPEND
- if(pwrpriv->brfoffbyhw==_TRUE)
- {
- DBG_8192C("hw still in rf_off state ...........\n");
- ret = _FAIL;
- goto exit;
- }
- else if(padapter->registrypriv.usbss_enable)
- {
- DBG_8192C("\n %s call autoresume_enter....\n",__FUNCTION__);
- if(_FAIL == autoresume_enter(padapter))
- {
- DBG_8192C("======> autoresume fail.............\n");
- ret = _FAIL;
- goto exit;
- }
- }
- else
-#endif
-#endif
- {
-#ifdef CONFIG_IPS
- DBG_8192C("\n %s call ips_leave....\n",__FUNCTION__);
- if(_FAIL == ips_leave(padapter))
- {
- DBG_8192C("======> ips_leave fail.............\n");
- ret = _FAIL;
- goto exit;
- }
-#endif
- }
- }else {
- //Jeff: reset timer to avoid falling ips or selective suspend soon
- if(pwrpriv->bips_processing == _FALSE)
- rtw_set_pwr_state_check_timer(pwrpriv);
- }
-
-exit:
- return ret;
-
-}
-
-static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- u8 _status = _FALSE;
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv= &padapter->mlmepriv;
- NDIS_802_11_SSID ssid;
- _irqL irqL;
-
-#ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
-#endif //CONFIG_P2P
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_set_scan\n"));
-
-_func_enter_;
-
- #ifdef DBG_IOCTL
- DBG_871X("DBG_IOCTL %s:%d\n",__FUNCTION__, __LINE__);
- #endif
-
-#ifdef CONFIG_MP_INCLUDED
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
- {
- ret = -1;
- goto exit;
- }
-#endif
-
- if(_FAIL == rfpwrstate_check(padapter))
- {
- ret= -1;
- goto exit;
- }
-
- if(padapter->bDriverStopped){
- DBG_8192C("bDriverStopped=%d\n", padapter->bDriverStopped);
- ret= -1;
- goto exit;
- }
-
- if(!padapter->bup){
- ret = -1;
- goto exit;
- }
-
- if (padapter->hw_init_completed==_FALSE){
- ret = -1;
- goto exit;
- }
-
- // When Busy Traffic, driver do not site survey. So driver return success.
- // wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout.
- // modify by thomas 2011-02-22.
- if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)
- {
- indicate_wx_scan_complete_event(padapter);
- goto exit;
- }
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
- {
- indicate_wx_scan_complete_event(padapter);
- goto exit;
- }
-
-// Mareded by Albert 20101103
-// For the DMP WiFi Display project, the driver won't to scan because
-// the pmlmepriv->scan_interval is always equal to 3.
-// So, the wpa_supplicant won't find out the WPS SoftAP.
-
-/*
- if(pmlmepriv->scan_interval>10)
- pmlmepriv->scan_interval = 0;
-
- if(pmlmepriv->scan_interval > 0)
- {
- DBG_8192C("scan done\n");
- ret = 0;
- goto exit;
- }
-
-*/
-#ifdef CONFIG_P2P
- if ( ( pwdinfo->p2p_state != P2P_STATE_NONE ) && ( pwdinfo->p2p_state != P2P_STATE_IDLE ) )
- {
- pwdinfo->p2p_state = P2P_STATE_FIND_PHASE_SEARCH;
- pwdinfo->find_phase_state_exchange_cnt = 0;
- rtw_free_network_queue(padapter, _TRUE);
- }
-#endif //CONFIG_P2P
-
-#if WIRELESS_EXT >= 17
- if (wrqu->data.length == sizeof(struct iw_scan_req))
- {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
-
- if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
- {
- int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
-
- _rtw_memset((unsigned char*)&ssid, 0, sizeof(NDIS_802_11_SSID));
-
- _rtw_memcpy(ssid.Ssid, req->essid, len);
- ssid.SsidLength = len;
-
- DBG_8192C("IW_SCAN_THIS_ESSID, ssid=%s, len=%d\n", req->essid, req->essid_len);
-
- _enter_critical_bh(&pmlmepriv->lock, &irqL);
-
- _status = rtw_sitesurvey_cmd(padapter, &ssid);
-
- _exit_critical_bh(&pmlmepriv->lock, &irqL);
-
- }
- else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
- {
- DBG_8192C("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
- }
-
- }
- else
-#endif
-
- if( wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
- && _rtw_memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
- )
- {
- int len = wrqu->data.length -WEXT_CSCAN_HEADER_SIZE;
- char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
- char section;
- char sec_len;
-
- //DBG_871X("%s COMBO_SCAN header is recognized\n", __FUNCTION__);
-
- _rtw_memset((unsigned char*)&ssid, 0, sizeof(NDIS_802_11_SSID));
-
- while(len >= 1) {
- sscanf(pos, "%c", §ion);
- pos+=1; len-=1;
-
- switch(section) {
- case WEXT_CSCAN_SSID_SECTION:
- DBG_871X("WEXT_CSCAN_SSID_SECTION\n");
- if(len < 1) len = 0;
- sscanf(pos, "%c", &sec_len);
- pos+=1; len-=1;
-
- if(len >= sec_len) {
- ssid.SsidLength = sec_len;
- _rtw_memcpy(ssid.Ssid, pos, ssid.SsidLength);
- DBG_871X("%s COMBO_SCAN with specific ssid:%s\n", __FUNCTION__, ssid.Ssid);
- }
-
- pos+=sec_len; len-=sec_len;
- break;
-
- #if 0
- case WEXT_CSCAN_CHANNEL_SECTION:
- DBG_871X("WEXT_CSCAN_CHANNEL_SECTION\n");
-
- pos+=1; len-=1;
- break;
- case WEXT_CSCAN_NPROBE_SECTION:
- DBG_871X("WEXT_CSCAN_NPROBE_SECTION\n");
- break;
- case WEXT_CSCAN_ACTV_DWELL_SECTION:
- DBG_871X("WEXT_CSCAN_ACTV_DWELL_SECTION\n");
- break;
- case WEXT_CSCAN_PASV_DWELL_SECTION:
- DBG_871X("WEXT_CSCAN_PASV_DWELL_SECTION\n");
- break;
- case WEXT_CSCAN_HOME_DWELL_SECTION:
- DBG_871X("WEXT_CSCAN_HOME_DWELL_SECTION\n");
- break;
- case WEXT_CSCAN_TYPE_SECTION:
- DBG_871X("WEXT_CSCAN_TYPE_SECTION\n");
- break;
- #endif
-
- default:
- //DBG_871X("Unknown CSCAN section %c\n", section);
- len = 0; // stop parsing
- }
-
- }
-
- //jeff: it has still some scan paramater to parse, we only do this now...
- _enter_critical_bh(&pmlmepriv->lock, &irqL);
- _status = rtw_sitesurvey_cmd(padapter, &ssid);
- _exit_critical_bh(&pmlmepriv->lock, &irqL);
-
- } else
-
- {
- _status = rtw_set_802_11_bssid_list_scan(padapter);
- }
-
- if(_status == _FALSE)
- ret = -1;
-
-exit:
- #ifdef DBG_IOCTL
- DBG_871X("DBG_IOCTL %s:%d return %d\n",__FUNCTION__, __LINE__, ret);
- #endif
-
-_func_exit_;
-
- return ret;
-}
-
-int rtw_is_fit_regulatory_domain(RT_CHANNEL_INFO *channel_set, u32 channel)
-{
- int i;
-
- for(i=0;channel_set[i].ChannelNum!=0;i++)
- {
- if(channel == channel_set[i].ChannelNum)
- return _TRUE;
- }
-
- if(channel_set[i].ChannelNum == 0)
- return _FALSE;
- return _TRUE;
-}
-
-static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- _irqL irqL;
- _list *plist, *phead;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- _queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- char *ev = extra;
- char *stop = ev + wrqu->data.length;
- u32 ret = 0;
- u32 cnt=0;
- u32 wait_for_surveydone;
-#ifdef CONFIG_P2P
- struct wifidirect_info* pwdinfo = &padapter->wdinfo;
-#endif //CONFIG_P2P
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan\n"));
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
-
- _func_enter_;
-
- #ifdef DBG_IOCTL
- DBG_871X("DBG_IOCTL %s:%d\n",__FUNCTION__, __LINE__);
- #endif
-
- if(padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped)
- {
- ret = -EINVAL;
- goto exit;
- }
-
- // 20110214 Commented by Jeff:
- // In rockchip 2818 platforms with low-speed IO, the UI will not show scan list bause of this busy waiting
-#ifndef CONFIG_ANDROID
-#ifdef CONFIG_P2P
- if ( pwdinfo->p2p_state != P2P_STATE_NONE )
- {
- // P2P is enabled
- wait_for_surveydone = 200;
- }
- else
- {
- // P2P is disabled
- wait_for_surveydone = 100;
- }
-#else
- {
- wait_for_surveydone = 100;
- }
-#endif //CONFIG_P2P
- while((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == _TRUE)
- {
- rtw_msleep_os(30);
- cnt++;
- if(cnt > wait_for_surveydone )
- break;
- }
-#endif
-
- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- phead = get_list_head(queue);
- plist = get_next(phead);
-
- while(1)
- {
- if (rtw_end_of_queue_search(phead,plist)== _TRUE)
- break;
-
- if((stop - ev) < SCAN_ITEM_SIZE) {
- ret = -E2BIG;
- break;
- }
-
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-
- /*
- * Filter the hidden SSID.
- */
- if (pnetwork->network.Ssid.SsidLength <= 0)
- {
- plist = get_next(plist);
- continue;
- }
-
- if( _TRUE == rtw_is_fit_regulatory_domain(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) )
- ev=translate_scan(padapter, a, pnetwork, ev, stop);
-
- plist = get_next(plist);
-
- }
-
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- wrqu->data.length = ev-extra;
- wrqu->data.flags = 0;
-
-exit:
-
- _func_exit_;
-
- #ifdef DBG_IOCTL
- DBG_871X("DBG_IOCTL %s:%d return %d\n",__FUNCTION__, __LINE__, ret);
- #endif
-
- return ret ;
-
-}
-
-//set ssid flow
-//s1. rtw_set_802_11_infrastructure_mode()
-//s2. set_802_11_authenticaion_mode()
-//s3. set_802_11_encryption_mode()
-//s4. rtw_set_802_11_ssid()
-static int rtw_wx_set_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- _queue *queue = &pmlmepriv->scanned_queue;
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- _list *phead;
- s8 status = _TRUE;
- struct wlan_network *pnetwork = NULL;
-
- NDIS_802_11_AUTHENTICATION_MODE authmode;
- NDIS_802_11_SSID ndis_ssid;
- u8 *dst_ssid, *src_ssid;
-
- uint ret = 0, len;
-
- _func_enter_;
-
- #ifdef DBG_IOCTL
- DBG_871X("DBG_IOCTL %s:%d\n",__FUNCTION__, __LINE__);
- #endif
-
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
- ("+rtw_wx_set_essid: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
- if(_FAIL == rfpwrstate_check(padapter))
- {
- ret = -1;
- goto exit;
- }
-
- if(!padapter->bup){
- ret = -1;
- goto exit;
- }
-
-#if WIRELESS_EXT <= 20
- if ((wrqu->essid.length-1) > IW_ESSID_MAX_SIZE){
-#else
- if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
-#endif
- ret= -E2BIG;
- goto exit;
- }
-
- if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- ret = -1;
- goto exit;
- }
-
- authmode = padapter->securitypriv.ndisauthtype;
- DBG_8192C("=>%s\n",__FUNCTION__);
- if (wrqu->essid.flags && wrqu->essid.length)
- {
- // Commented by Albert 20100519
- // We got the codes in "set_info" function of iwconfig source code.
- // =========================================
- // wrq.u.essid.length = strlen(essid) + 1;
- // if(we_kernel_version > 20)
- // wrq.u.essid.length--;
- // =========================================
- // That means, if the WIRELESS_EXT less than or equal to 20, the correct ssid len should subtract 1.
-#if WIRELESS_EXT <= 20
- len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE;
-#else
- len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
-#endif
-
- DBG_8192C("ssid=%s, len=%d\n", extra, wrqu->essid.length);
-
- _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
- ndis_ssid.SsidLength = len;
- _rtw_memcpy(ndis_ssid.Ssid, extra, len);
- src_ssid = ndis_ssid.Ssid;
-
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid=[%s]\n", src_ssid));
-
- phead = get_list_head(queue);
- pmlmepriv->pscanned = get_next(phead);
-
- while (1)
- {
- if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == _TRUE)
- {
-#if 0
- if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
- {
- rtw_set_802_11_ssid(padapter, &ndis_ssid);
-
- goto exit;
- }
- else
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("rtw_wx_set_ssid(): scanned_queue is empty\n"));
- ret = -EINVAL;
- goto exit;
- }
-#endif
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
- ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
-
- break;
- }
-
- pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
-
- pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
-
- dst_ssid = pnetwork->network.Ssid.Ssid;
-
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
- ("rtw_wx_set_essid: dst_ssid=%s\n",
- pnetwork->network.Ssid.Ssid));
-
- if ((_rtw_memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength) == _TRUE) &&
- (pnetwork->network.Ssid.SsidLength==ndis_ssid.SsidLength))
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
- ("rtw_wx_set_essid: find match, set infra mode\n"));
-
- if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
- {
- if(pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
- continue;
- }
-
- if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == _FALSE)
- {
- ret = -1;
- goto exit;
- }
-
- break;
- }
- }
-
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
- ("set ssid: set_802_11_auth. mode=%d\n", authmode));
- rtw_set_802_11_authentication_mode(padapter, authmode);
- //set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);
- if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {
- ret = -1;
- goto exit;
- }
- }
- DBG_8192C("<=%s\n",__FUNCTION__);
-exit:
-
- #ifdef DBG_IOCTL
- DBG_871X("DBG_IOCTL %s:%d return %d\n",__FUNCTION__, __LINE__, ret);
- #endif
-
- _func_exit_;
-
- return ret;
-}
-
-static int rtw_wx_get_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- u32 len,ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
-
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_essid\n"));
-
- _func_enter_;
-
- if ( (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
- {
- len = pcur_bss->Ssid.SsidLength;
-
- wrqu->essid.length = len;
-
- _rtw_memcpy(extra, pcur_bss->Ssid.Ssid, len);
-
- wrqu->essid.flags = 1;
- }
- else
- {
- ret = -1;
- goto exit;
- }
-
-exit:
-
- _func_exit_;
-
- return ret;
-
-}
-
-static int rtw_wx_set_rate(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- int i, ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- u8 datarates[NumRates];
- u32 target_rate = wrqu->bitrate.value;
- u32 fixed = wrqu->bitrate.fixed;
- u32 ratevalue = 0;
- u8 mpdatarate[NumRates]={11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
-
-_func_enter_;
-
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,(" rtw_wx_set_rate \n"));
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("target_rate = %d, fixed = %d\n",target_rate,fixed));
-
- if(target_rate == -1){
- ratevalue = 11;
- goto set_rate;
- }
- target_rate = target_rate/100000;
-
- switch(target_rate){
- case 10:
- ratevalue = 0;
- break;
- case 20:
- ratevalue = 1;
- break;
- case 55:
- ratevalue = 2;
- break;
- case 60:
- ratevalue = 3;
- break;
- case 90:
- ratevalue = 4;
- break;
- case 110:
- ratevalue = 5;
- break;
- case 120:
- ratevalue = 6;
- break;
- case 180:
- ratevalue = 7;
- break;
- case 240:
- ratevalue = 8;
- break;
- case 360:
- ratevalue = 9;
- break;
- case 480:
- ratevalue = 10;
- break;
- case 540:
- ratevalue = 11;
- break;
- default:
- ratevalue = 11;
- break;
- }
-
-set_rate:
-
- for(i=0; i<NumRates; i++)
- {
- if(ratevalue==mpdatarate[i])
- {
- datarates[i] = mpdatarate[i];
- if(fixed == 0)
- break;
- }
- else{
- datarates[i] = 0xff;
- }
-
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("datarate_inx=%d\n",datarates[i]));
- }
-
- if( rtw_setdatarate_cmd(padapter, datarates) !=_SUCCESS){
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("rtw_wx_set_rate Fail!!!\n"));
- ret = -1;
- }
-
-_func_exit_;
-
- return ret;
-}
-
-static int rtw_wx_get_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int i;
- u8 *p;
- u16 rate = 0, max_rate = 0, ht_cap=_FALSE;
- u32 ht_ielen = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
- struct ieee80211_ht_cap *pht_capie;
- u8 bw_40MHz=0, short_GI=0;
- u16 mcs_rate=0;
- u8 rf_type = 0;
- struct registry_priv *pregpriv = &padapter->registrypriv;
-
-
- i=0;
-#ifdef CONFIG_MP_INCLUDED
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
- return -1;
-#endif
- if((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
- {
- p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
- if(p && ht_ielen>0)
- {
- ht_cap = _TRUE;
-
- pht_capie = (struct ieee80211_ht_cap *)(p+2);
-
- _rtw_memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
-
- bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1:0;
-
- short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1:0;
- }
-
- while( (pcur_bss->SupportedRates[i]!=0) && (pcur_bss->SupportedRates[i]!=0xFF))
- {
- rate = pcur_bss->SupportedRates[i]&0x7F;
- if(rate>max_rate)
- max_rate = rate;
-
- wrqu->bitrate.fixed = 0; /* no auto select */
- //wrqu->bitrate.disabled = 1/;
-
- i++;
- }
-
- if(ht_cap == _TRUE)
- {
-#if 0 //have some issue,neet to debug - 20101008-georgia
- if(mcs_rate&0x8000)//MCS15
- {
- max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
-
- }
- else if(mcs_rate&0x0080)//MCS7
- {
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
- }
- else//default MCS7
- {
- //DBG_8192C("wx_get_rate, mcs_rate_bitmap=0x%x\n", mcs_rate);
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
- }
-#else
- padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
- if(rf_type == RF_1T1R)
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
- else
- max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
-#endif
- max_rate = max_rate*2;//Mbps/2
- wrqu->bitrate.value = max_rate*500000;
-
- }
- else
- {
- wrqu->bitrate.value = max_rate*500000;
- }
-
- }
- else
- {
- return -1;
- }
-
- return 0;
-
-}
-
-static int rtw_wx_get_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- _func_enter_;
- RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,(" rtw_wx_get_rts \n"));
-
- wrqu->rts.value = padapter->registrypriv.rts_thresh;
- wrqu->rts.fixed = 0; /* no auto select */
- //wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
-
- _func_exit_;
-
- return 0;
-}
-
-static int rtw_wx_set_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- _func_enter_;
-
- if (wrqu->frag.disabled)
- padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
- else {
- if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
- wrqu->frag.value > MAX_FRAG_THRESHOLD)
- return -EINVAL;
-
- padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
- }
-
- _func_exit_;
-
- return 0;
-
-}
-
-
-static int rtw_wx_get_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- _func_enter_;
-
- wrqu->frag.value = padapter->xmitpriv.frag_len;
- wrqu->frag.fixed = 0; /* no auto select */
- //wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
-
- _func_exit_;
-
- return 0;
-}
-
-static int rtw_wx_get_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
-
- wrqu->retry.value = 7;
- wrqu->retry.fixed = 0; /* no auto select */
- wrqu->retry.disabled = 1;
-
- return 0;
-
-}
-
-#if 0
-#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
-#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
-#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
-#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
-#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
-#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
-#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
-#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
-/*
-iwconfig wlan0 key on -> flags = 0x6001 -> maybe it means auto
-iwconfig wlan0 key off -> flags = 0x8800
-iwconfig wlan0 key open -> flags = 0x2800
-iwconfig wlan0 key open 1234567890 -> flags = 0x2000
-iwconfig wlan0 key restricted -> flags = 0x4800
-iwconfig wlan0 key open [3] 1234567890 -> flags = 0x2003
-iwconfig wlan0 key restricted [2] 1234567890 -> flags = 0x4002
-iwconfig wlan0 key open [3] -> flags = 0x2803
-iwconfig wlan0 key restricted [2] -> flags = 0x4802
-*/
-#endif
-
-static int rtw_wx_set_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- u32 key, ret = 0;
- u32 keyindex_provided;
- NDIS_802_11_WEP wep;
- NDIS_802_11_AUTHENTICATION_MODE authmode;
-
- struct iw_point *erq = &(wrqu->encoding);
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- DBG_8192C("+rtw_wx_set_enc, flags=0x%x\n", erq->flags);
-
- _rtw_memset(&wep, 0, sizeof(NDIS_802_11_WEP));
-
- key = erq->flags & IW_ENCODE_INDEX;
-
- _func_enter_;
-
- if (erq->flags & IW_ENCODE_DISABLED)
- {
- DBG_8192C("EncryptionDisabled\n");
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype=authmode;
-
- goto exit;
- }
-
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- keyindex_provided = 1;
- }
- else
- {
- keyindex_provided = 0;
- key = padapter->securitypriv.dot11PrivacyKeyIndex;
- DBG_8192C("rtw_wx_set_enc, key=%d\n", key);
- }
-
- //set authentication mode
- if(erq->flags & IW_ENCODE_OPEN)
- {
- DBG_8192C("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;//Ndis802_11EncryptionDisabled;
-
-#ifdef CONFIG_PLATFORM_MT53XX
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
-#else
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open;
-#endif
-
- padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype=authmode;
- }
- else if(erq->flags & IW_ENCODE_RESTRICTED)
- {
- DBG_8192C("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
-
-#ifdef CONFIG_PLATFORM_MT53XX
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
-#else
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Shared;
-#endif
-
- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
- padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
- authmode = Ndis802_11AuthModeShared;
- padapter->securitypriv.ndisauthtype=authmode;
- }
- else
- {
- DBG_8192C("rtw_wx_set_enc():erq->flags=0x%x\n", erq->flags);
-
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;//Ndis802_11EncryptionDisabled;
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
- padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype=authmode;
- }
-
- wep.KeyIndex = key;
- if (erq->length > 0)
- {
- wep.KeyLength = erq->length <= 5 ? 5 : 13;
-
- wep.Length = wep.KeyLength + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
- }
- else
- {
- wep.KeyLength = 0 ;
-
- if(keyindex_provided == 1)// set key_id only, no given KeyMaterial(erq->length==0).
- {
- padapter->securitypriv.dot11PrivacyKeyIndex = key;
-
- DBG_8192C("(keyindex_provided == 1), keyid=%d, key_len=%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
-
- switch(padapter->securitypriv.dot11DefKeylen[key])
- {
- case 5:
- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
- break;
- case 13:
- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
- break;
- default:
- padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
- break;
- }
-
- goto exit;
-
- }
-
- }
-
- wep.KeyIndex |= 0x80000000;
-
- _rtw_memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
-
- if (rtw_set_802_11_add_wep(padapter, &wep) == _FALSE) {
- if(rf_on == pwrpriv->rf_pwrstate )
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
-exit:
-
- _func_exit_;
-
- return ret;
-
-}
-
-static int rtw_wx_get_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- uint key, ret =0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *erq = &(wrqu->encoding);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-
- _func_enter_;
-
- if(check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE)
- {
- if(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE)
- {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
- }
-
-
- key = erq->flags & IW_ENCODE_INDEX;
-
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- } else
- {
- key = padapter->securitypriv.dot11PrivacyKeyIndex;
- }
-
- erq->flags = key + 1;
-
- //if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
- //{
- // erq->flags |= IW_ENCODE_OPEN;
- //}
-
- switch(padapter->securitypriv.ndisencryptstatus)
- {
- case Ndis802_11EncryptionNotSupported:
- case Ndis802_11EncryptionDisabled:
-
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
-
- break;
-
- case Ndis802_11Encryption1Enabled:
-
- erq->length = padapter->securitypriv.dot11DefKeylen[key];
-
- if(erq->length)
- {
- _rtw_memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
-
- erq->flags |= IW_ENCODE_ENABLED;
-
- if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
- {
- erq->flags |= IW_ENCODE_OPEN;
- }
- else if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
- {
- erq->flags |= IW_ENCODE_RESTRICTED;
- }
- }
- else
- {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- }
-
- break;
-
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption3Enabled:
-
- erq->length = 16;
- erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
-
- break;
-
- default:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
-
- break;
-
- }
-
- _func_exit_;
-
- return ret;
-
-}
-
-static int rtw_wx_get_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- wrqu->power.value = 0;
- wrqu->power.fixed = 0; /* no auto select */
- wrqu->power.disabled = 1;
-
- return 0;
-
-}
-
-static int rtw_wx_set_gen_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
-
- return ret;
-}
-
-static int rtw_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_param *param = (struct iw_param*)&(wrqu->param);
- int ret = 0;
-
- switch (param->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
-
- break;
- case IW_AUTH_CIPHER_GROUP:
-
- break;
- case IW_AUTH_KEY_MGMT:
- /*
- * ??? does not use these parameters
- */
- break;
-
- case IW_AUTH_TKIP_COUNTERMEASURES:
- {
- if ( param->value )
- { // wpa_supplicant is enabling the tkip countermeasure.
- padapter->securitypriv.btkip_countermeasure = _TRUE;
- }
- else
- { // wpa_supplicant is disabling the tkip countermeasure.
- padapter->securitypriv.btkip_countermeasure = _FALSE;
- }
- break;
- }
- case IW_AUTH_DROP_UNENCRYPTED:
- {
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
-
- if(padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
- {
- break;//it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled,
- // then it needn't reset it;
- }
-
- if(param->value){
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
- padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeOpen;
- }
-
- break;
- }
-
- case IW_AUTH_80211_AUTH_ALG:
-
- #if defined(CONFIG_ANDROID) //&& !defined(CONFIG_PLATFORM_ROCKCHIPS)
- /*
- * It's the starting point of a link layer connection using wpa_supplicant
- */
- if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- rtw_disassoc_cmd(padapter);
- DBG_871X("%s...call rtw_indicate_disconnect\n ",__FUNCTION__);
- rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter);
- }
- #endif
-
-
- ret = wpa_set_auth_algs(dev, (u32)param->value);
-
- break;
-
- case IW_AUTH_WPA_ENABLED:
-
- //if(param->value)
- // padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; //802.1x
- //else
- // padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;//open system
-
- //_disassociate(priv);
-
- break;
-
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- //ieee->ieee802_1x = param->value;
- break;
-
- case IW_AUTH_PRIVACY_INVOKED:
- //ieee->privacy_invoked = param->value;
- break;
-
- default:
- return -EOPNOTSUPP;
-
- }
-
- return ret;
-
-}
-
-static int rtw_wx_set_enc_ext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- char *alg_name;
- u32 param_len;
- struct ieee_param *param = NULL;
- struct iw_point *pencoding = &wrqu->encoding;
- struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
- int ret=0;
-
- param_len = sizeof(struct ieee_param) + pext->key_len;
- param = (struct ieee_param *)rtw_malloc(param_len);
- if (param == NULL)
- return -1;
-
- _rtw_memset(param, 0, param_len);
-
- param->cmd = IEEE_CMD_SET_ENCRYPTION;
- _rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
-
-
- switch (pext->alg) {
- case IW_ENCODE_ALG_NONE:
- //todo: remove key
- //remove = 1;
- alg_name = "none";
- break;
- case IW_ENCODE_ALG_WEP:
- alg_name = "WEP";
- break;
- case IW_ENCODE_ALG_TKIP:
- alg_name = "TKIP";
- break;
- case IW_ENCODE_ALG_CCMP:
- alg_name = "CCMP";
- break;
- default:
- return -1;
- }
-
- strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
-
-
- if(pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)//?
- {
- param->u.crypt.set_tx = 0;
- }
-
- if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)//?
- {
- param->u.crypt.set_tx = 1;
- }
-
- param->u.crypt.idx = (pencoding->flags&0x00FF) -1 ;
-
- if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- {
- _rtw_memcpy(param->u.crypt.seq, pext->rx_seq, 8);
- }
-
- if(pext->key_len)
- {
- param->u.crypt.key_len = pext->key_len;
- //_rtw_memcpy(param + 1, pext + 1, pext->key_len);
- _rtw_memcpy(param->u.crypt.key, pext + 1, pext->key_len);
- }
-
-
- if (pencoding->flags & IW_ENCODE_DISABLED)
- {
- //todo: remove key
- //remove = 1;
- }
-
- ret = wpa_set_encryption(dev, param, param_len);
-
-
- if(param)
- {
- rtw_mfree((u8*)param, param_len);
- }
-
-
- return ret;
-
-}
-
-
-static int rtw_wx_get_nick(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- //struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- //struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- if(extra)
- {
- wrqu->data.length = 14;
- wrqu->data.flags = 1;
- _rtw_memcpy(extra, "<WIFI@REALTEK>", 14);
- }
-
- //rtw_signal_process(pid, SIGUSR1); //for test
-
- //dump debug info here
-/*
- u32 dot11AuthAlgrthm; // 802.11 auth, could be open, shared, and 8021x
- u32 dot11PrivacyAlgrthm; // This specify the privacy for shared auth. algorithm.
- u32 dot118021XGrpPrivacy; // This specify the privacy algthm. used for Grp key
- u32 ndisauthtype;
- u32 ndisencryptstatus;
-*/
-
- //DBG_8192C("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
- // psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
- // psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
-
- //DBG_8192C("enc_alg=0x%x\n", psecuritypriv->dot11PrivacyAlgrthm);
- //DBG_8192C("auth_type=0x%x\n", psecuritypriv->ndisauthtype);
- //DBG_8192C("enc_type=0x%x\n", psecuritypriv->ndisencryptstatus);
-
-#if 0
- DBG_8192C("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
- DBG_8192C("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
- DBG_8192C("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
- DBG_8192C("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
- DBG_8192C("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
-
- DBG_8192C("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
-
-
- DBG_8192C("\n");
-
- DBG_8192C("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
- DBG_8192C("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
-
- DBG_8192C("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
-
- DBG_8192C("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
-
- DBG_8192C("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
- DBG_8192C("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
-
- DBG_8192C("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
- DBG_8192C("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
- DBG_8192C("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
- DBG_8192C("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
-#endif
-
- return 0;
-
-}
-
-static int rtw_wx_read32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- u32 addr;
- u32 data32;
-
-
- addr = *(u32*)extra;
- data32 = rtw_read32(padapter, addr);
- sprintf(extra, "0x%08x", data32);
-
- return 0;
-}
-
-static int rtw_wx_write32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- u32 addr;
- u32 data32;
-
-
- addr = *(u32*)extra;
- data32 = *((u32*)extra + 1);
- rtw_write32(padapter, addr, data32);
-
- return 0;
-}
-
-static int rtw_wx_read_rf(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- u32 path, addr, data32;
-
-
- path = *(u32*)extra;
- addr = *((u32*)extra + 1);
- data32 = padapter->HalFunc.read_rfreg(padapter, path, addr, 0xFFFFF);
-// DBG_8192C("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32);
- /*
- * IMPORTANT!!
- * Only when wireless private ioctl is at odd order,
- * "extra" would be copied to user space.
- */
- sprintf(extra, "0x%05x", data32);
-
- return 0;
-}
-
-static int rtw_wx_write_rf(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- u32 path, addr, data32;
-
-
- path = *(u32*)extra;
- addr = *((u32*)extra + 1);
- data32 = *((u32*)extra + 2);
-// DBG_8192C("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32);
- padapter->HalFunc.write_rfreg(padapter, path, addr, 0xFFFFF, data32);
-
- return 0;
-}
-
-static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- return -1;
-}
-
-static int dummy(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- //struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-
- //DBG_8192C("cmd_code=%x, fwstate=0x%x\n", a->cmd, get_fwstate(pmlmepriv));
-
- return -1;
-
-}
-
-static int rtw_wx_set_channel_plan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- extern int rtw_channel_plan;
-
- #if 0
- rtw_channel_plan = (int)wrqu->data.pointer;
- pregistrypriv->channel_plan = rtw_channel_plan;
- pmlmepriv->ChannelPlan = pregistrypriv->channel_plan;
- #else
- pmlmepriv->ChannelPlan = (u8) (*((int *)wrqu));
- #endif
-
- if( _SUCCESS == rtw_set_chplan_cmd(padapter, pmlmepriv->ChannelPlan) ) {
- DBG_871X("\n======== Set channel_plan = 0x%02X ========\n", pmlmepriv->ChannelPlan);
- } else
- return -EPERM;
-
- return 0;
-}
-
-static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
-#ifdef CONFIG_PLATFORM_MT53XX
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_,
- ("WLAN IOCTL: cmd_code=%x, fwstate=0x%x\n",
- a->cmd, get_fwstate(pmlmepriv));
-#endif
- return 0;
-}
-
-static int rtw_wx_get_sensitivity(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *buf)
-{
-#ifdef CONFIG_PLATFORM_MT53XX
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- //wrqu->qual.level = (u8)padapter->mlmepriv.cur_network.network.Rssi;
-
- wrqu->qual.level = padapter->recvpriv.fw_rssi;
-
- DBG_8192C(" level = %u\n", wrqu->qual.level );
-#endif
- return 0;
-}
-
-static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-#ifdef CONFIG_PLATFORM_MT53XX
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- return rtw_set_wpa_ie(padapter, wrqu->data.pointer, wrqu->data.length);
-#else
- return 0;
-#endif
-}
-
-/*
-typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-*/
-/*
- * For all data larger than 16 octets, we need to use a
- * pointer to memory allocated in user space.
- */
-static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- #if 0
-struct iw_point
-{
- void __user *pointer; /* Pointer to the data (in user space) */
- __u16 length; /* number of fields or size in bytes */
- __u16 flags; /* Optional params */
-};
- #endif
-
-#ifdef CONFIG_DRVEXT_MODULE
- u8 res;
- struct drvext_handler *phandler;
- struct drvext_oidparam *poidparam;
- int ret;
- u16 len;
- u8 *pparmbuf, bset;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *p = &wrqu->data;
-
- if( (!p->length) || (!p->pointer)){
- ret = -EINVAL;
- goto _rtw_drvext_hdl_exit;
- }
-
-
- bset = (u8)(p->flags&0xFFFF);
- len = p->length;
- pparmbuf = (u8*)rtw_malloc(len);
- if (pparmbuf == NULL){
- ret = -ENOMEM;
- goto _rtw_drvext_hdl_exit;
- }
-
- if(bset)//set info
- {
- if (copy_from_user(pparmbuf, p->pointer,len)) {
- rtw_mfree(pparmbuf, len);
- ret = -EFAULT;
- goto _rtw_drvext_hdl_exit;
- }
- }
- else//query info
- {
-
- }
-
-
- //
- poidparam = (struct drvext_oidparam *)pparmbuf;
-
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("drvext set oid subcode [%d], len[%d], InformationBufferLength[%d]\r\n",
- poidparam->subcode, poidparam->len, len));
-
-
- //check subcode
- if ( poidparam->subcode >= MAX_DRVEXT_HANDLERS)
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext handlers\r\n"));
- ret = -EINVAL;
- goto _rtw_drvext_hdl_exit;
- }
-
-
- if ( poidparam->subcode >= MAX_DRVEXT_OID_SUBCODES)
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext subcodes\r\n"));
- ret = -EINVAL;
- goto _rtw_drvext_hdl_exit;
- }
-
-
- phandler = drvextoidhandlers + poidparam->subcode;
-
- if (poidparam->len != phandler->parmsize)
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext param size %d vs %d\r\n",
- poidparam->len , phandler->parmsize));
- ret = -EINVAL;
- goto _rtw_drvext_hdl_exit;
- }
-
-
- res = phandler->handler(&padapter->drvextpriv, bset, poidparam->data);
-
- if(res==0)
- {
- ret = 0;
-
- if (bset == 0x00) {//query info
- //_rtw_memcpy(p->pointer, pparmbuf, len);
- if (copy_to_user(p->pointer, pparmbuf, len))
- ret = -EFAULT;
- }
- }
- else
- ret = -EFAULT;
-
-
-_rtw_drvext_hdl_exit:
-
- return ret;
-
-#endif
-
- return 0;
-
-}
-
-static void rtw_dbg_mode_hdl(_adapter *padapter, u32 id, u8 *pdata, u32 len)
-{
- pRW_Reg RegRWStruct;
- struct rf_reg_param *prfreg;
- u8 path;
- u8 offset;
- u32 value;
-
- DBG_8192C("%s\n", __FUNCTION__);
-
- switch(id)
- {
- case GEN_MP_IOCTL_SUBCODE(MP_START):
- DBG_8192C("871x_driver is only for normal mode, can't enter mp mode\n");
- break;
- case GEN_MP_IOCTL_SUBCODE(READ_REG):
- RegRWStruct = (pRW_Reg)pdata;
- switch (RegRWStruct->width)
- {
- case 1:
- RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
- break;
- case 2:
- RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
- break;
- case 4:
- RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
- break;
- default:
- break;
- }
-
- break;
- case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
- RegRWStruct = (pRW_Reg)pdata;
- switch (RegRWStruct->width)
- {
- case 1:
- rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
- break;
- case 2:
- rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
- break;
- case 4:
- rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
- break;
- default:
- break;
- }
-
- break;
- case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
-
- prfreg = (struct rf_reg_param *)pdata;
-
- path = (u8)prfreg->path;
- offset = (u8)prfreg->offset;
-
- value = padapter->HalFunc.read_rfreg(padapter, path, offset, 0xffffffff);
-
- prfreg->value = value;
-
- break;
- case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
-
- prfreg = (struct rf_reg_param *)pdata;
-
- path = (u8)prfreg->path;
- offset = (u8)prfreg->offset;
- value = prfreg->value;
-
- padapter->HalFunc.write_rfreg(padapter, path, offset, 0xffffffff, value);
-
- break;
- case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
- DBG_8192C("==> trigger gpio 0\n");
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_TRIGGER_GPIO_0, 0);
- break;
-#ifdef CONFIG_BT_COEXIST
- case GEN_MP_IOCTL_SUBCODE(SET_DM_BT):
- DBG_8192C("==> set dm_bt_coexist:%x\n",*(u8 *)pdata);
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_BT_SET_COEXIST, pdata);
- break;
- case GEN_MP_IOCTL_SUBCODE(DEL_BA):
- DBG_8192C("==> delete ba:%x\n",*(u8 *)pdata);
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_BT_ISSUE_DELBA, pdata);
- break;
-#endif
-#ifdef SILENT_RESET_FOR_SPECIFIC_PLATFOM
- case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
- if(padapter->HalFunc.sreset_get_wifi_status)
- *pdata = padapter->HalFunc.sreset_get_wifi_status(padapter);
- break;
-#endif
-
- default:
- break;
- }
-
-}
-
-static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- unsigned long BytesRead, BytesWritten, BytesNeeded;
- struct oid_par_priv oid_par;
- struct mp_ioctl_handler *phandler;
- struct mp_ioctl_param *poidparam;
- uint status=0;
- u16 len;
- u8 *pparmbuf = NULL, bset;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *p = &wrqu->data;
-
- //DBG_8192C("+rtw_mp_ioctl_hdl\n");
-
- //mutex_lock(&ioctl_mutex);
-
- if ((!p->length) || (!p->pointer)) {
- ret = -EINVAL;
- goto _rtw_mp_ioctl_hdl_exit;
- }
-
- pparmbuf = NULL;
- bset = (u8)(p->flags & 0xFFFF);
- len = p->length;
- pparmbuf = (u8*)rtw_malloc(len);
- if (pparmbuf == NULL){
- ret = -ENOMEM;
- goto _rtw_mp_ioctl_hdl_exit;
- }
-
- if (copy_from_user(pparmbuf, p->pointer, len)) {
- ret = -EFAULT;
- goto _rtw_mp_ioctl_hdl_exit;
- }
-
- poidparam = (struct mp_ioctl_param *)pparmbuf;
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
- ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
- poidparam->subcode, poidparam->len, len));
-
- if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
- ret = -EINVAL;
- goto _rtw_mp_ioctl_hdl_exit;
- }
-
- //DBG_8192C("%s: %d\n", __func__, poidparam->subcode);
-
-#ifdef CONFIG_MP_INCLUDED
- phandler = mp_ioctl_hdl + poidparam->subcode;
-
- if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize))
- {
- RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
- ("no matching drvext param size %d vs %d\r\n",
- poidparam->len, phandler->paramsize));
- ret = -EINVAL;
- goto _rtw_mp_ioctl_hdl_exit;
- }
-
- if (phandler->handler)
- {
- oid_par.adapter_context = padapter;
- oid_par.oid = phandler->oid;
- oid_par.information_buf = poidparam->data;
- oid_par.information_buf_len = poidparam->len;
- oid_par.dbg = 0;
-
- BytesWritten = 0;
- BytesNeeded = 0;
-
- if (bset) {
- oid_par.bytes_rw = &BytesRead;
- oid_par.bytes_needed = &BytesNeeded;
- oid_par.type_of_oid = SET_OID;
- } else {
- oid_par.bytes_rw = &BytesWritten;
- oid_par.bytes_needed = &BytesNeeded;
- oid_par.type_of_oid = QUERY_OID;
- }
-
- status = phandler->handler(&oid_par);
-
- //todo:check status, BytesNeeded, etc.
- }
- else {
- DBG_8192C("rtw_mp_ioctl_hdl(): err!, subcode=%d, oid=%d, handler=%p\n",
- poidparam->subcode, phandler->oid, phandler->handler);
- ret = -EFAULT;
- goto _rtw_mp_ioctl_hdl_exit;
- }
-#else
-
- rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
-
-#endif
-
- if (bset == 0x00) {//query info
- if (copy_to_user(p->pointer, pparmbuf, len))
- ret = -EFAULT;
- }
-
- if (status) {
- ret = -EFAULT;
- goto _rtw_mp_ioctl_hdl_exit;
- }
-
-_rtw_mp_ioctl_hdl_exit:
-
- if (pparmbuf)
- rtw_mfree(pparmbuf, len);
-
- //mutex_unlock(&ioctl_mutex);
-
- return ret;
-}
-
-static int rtw_get_ap_info(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int bssid_match, ret = 0;
- u32 cnt=0, wpa_ielen;
- _irqL irqL;
- _list *plist, *phead;
- unsigned char *pbuf;
- u8 bssid[ETH_ALEN];
- char data[32];
- struct wlan_network *pnetwork = NULL;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- _queue *queue = &(pmlmepriv->scanned_queue);
- struct iw_point *pdata = &wrqu->data;
-
- DBG_8192C("+rtw_get_aplist_info\n");
-
- if((padapter->bDriverStopped) || (pdata==NULL))
- {
- ret= -EINVAL;
- goto exit;
- }
-
- while((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == _TRUE)
- {
- rtw_msleep_os(30);
- cnt++;
- if(cnt > 100)
- break;
- }
-
-
- //pdata->length = 0;//?
- pdata->flags = 0;
- if(pdata->length>=32)
- {
- if(copy_from_user(data, pdata->pointer, 32))
- {
- ret= -EINVAL;
- goto exit;
- }
- }
- else
- {
- ret= -EINVAL;
- goto exit;
- }
-
- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- phead = get_list_head(queue);
- plist = get_next(phead);
-
- while(1)
- {
- if (rtw_end_of_queue_search(phead,plist)== _TRUE)
- break;
-
-
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-
- //if(hwaddr_aton_i(pdata->pointer, bssid))
- if(hwaddr_aton_i(data, bssid))
- {
- DBG_8192C("Invalid BSSID '%s'.\n", (u8*)data);
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
- return -EINVAL;
- }
-
-
- if(_rtw_memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN) == _TRUE)//BSSID match, then check if supporting wpa/wpa2
- {
- DBG_8192C("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
-
- pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
- if(pbuf && (wpa_ielen>0))
- {
- pdata->flags = 1;
- break;
- }
-
- pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
- if(pbuf && (wpa_ielen>0))
- {
- pdata->flags = 2;
- break;
- }
-
- }
-
- plist = get_next(plist);
-
- }
-
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- if(pdata->length>=34)
- {
- if(copy_to_user((u8*)pdata->pointer+32, (u8*)&pdata->flags, 1))
- {
- ret= -EINVAL;
- goto exit;
- }
- }
-
-exit:
-
- return ret;
-
-}
-
-static int rtw_set_pid(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = rtw_netdev_priv(dev);
- int *pdata = (int *)wrqu;
- int selector;
-
- if((padapter->bDriverStopped) || (pdata==NULL))
- {
- ret= -EINVAL;
- goto exit;
- }
-
- selector = *pdata;
- if(selector < 3 && selector >=0) {
- padapter->pid[selector] = *(pdata+1);
- #ifdef CONFIG_GLOBAL_UI_PID
- ui_pid[selector] = *(pdata+1);
- #endif
- DBG_871X("%s set pid[%d]=%d\n", __FUNCTION__, selector ,padapter->pid[selector]);
- }
- else
- DBG_871X("%s selector %d error\n", __FUNCTION__, selector);
-
-exit:
-
- return ret;
-
-}
-
-static int rtw_wps_start(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- u32 u32wps_start = 0;
- unsigned int uintRet = 0;
-
- uintRet = copy_from_user( ( void* ) &u32wps_start, pdata->pointer, 4 );
-
- if((padapter->bDriverStopped) || (pdata==NULL))
- {
- ret= -EINVAL;
- goto exit;
- }
-
- if ( u32wps_start == 0 )
- {
- u32wps_start = *extra;
- }
-
- DBG_8192C( "[%s] wps_start = %d\n", __FUNCTION__, u32wps_start );
-
- if ( u32wps_start == 1 ) // WPS Start
- {
- rtw_led_control(padapter, LED_CTL_START_WPS);
- }
- else if ( u32wps_start == 2 ) // WPS Stop because of wps success
- {
- rtw_led_control(padapter, LED_CTL_STOP_WPS);
- }
- else if ( u32wps_start == 3 ) // WPS Stop because of wps fail
- {
- rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
- }
-exit:
-
- return ret;
-
-}
-
-#ifdef CONFIG_P2P
-
-void restore_p2p_state_timer_process (void *FunctionContext)
-{
- _adapter *adapter = (_adapter *)FunctionContext;
- struct wifidirect_info *pwdinfo = &adapter->wdinfo;
-
- p2p_protocol_wk_cmd( adapter, P2P_RESTORE_STATE_WK );
-}
-
-void pre_tx_scan_timer_process (void *FunctionContext)
-{
- _adapter *adapter = (_adapter *) FunctionContext;
- struct wifidirect_info *pwdinfo = &adapter->wdinfo;
- _irqL irqL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- u8 _status = 0;
-
- _enter_critical_bh(&pmlmepriv->lock, &irqL);
-
- // Commented by Albert 20110805
- // Todo: Use the issuing probe request directly instead of using the rtw_sitesurvey_cmd!!
-
- if ( P2P_STATE_TX_PROVISION_DIS_REQ == pwdinfo->p2p_state )
- {
- if ( _TRUE == pwdinfo->tx_prov_disc_info.benable ) // the provision discovery request frame is trigger to send or not
- {
- p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK );
- //issue_probereq_p2p( adapter );
- //_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
- }
- }
- else if ( P2P_STATE_GONEGO_ING == pwdinfo->p2p_state )
- {
- if ( _TRUE == pwdinfo->nego_req_info.benable )
- {
- p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK );
- //issue_probereq_p2p( adapter );
- //_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
- }
- }
- else
- {
- DBG_8192C( "[%s] p2p_state is %d, ignore!!\n", __FUNCTION__, pwdinfo->p2p_state );
- }
-
- _exit_critical_bh(&pmlmepriv->lock, &irqL);
-}
-
-void find_phase_timer_process (void *FunctionContext)
-{
- _adapter *adapter = (_adapter *)FunctionContext;
-
- adapter->wdinfo.find_phase_state_exchange_cnt++;
-
- p2p_protocol_wk_cmd( adapter, P2P_FIND_PHASE_WK );
-}
-
-static void init_wifidirect_info( _adapter* padapter, char* pinitValue)
-{
- struct wifidirect_info *pwdinfo;
-
- pwdinfo = &padapter->wdinfo;
-
- pwdinfo->padapter = padapter;
-
- //init device&interface address
- _rtw_memcpy(pwdinfo->device_addr, myid(&(padapter->eeprompriv)), ETH_ALEN);
- _rtw_memcpy(pwdinfo->interface_addr, myid(&(padapter->eeprompriv)), ETH_ALEN);
-
- // 1, 6, 11 are the social channel defined in the WiFi Direct specification.
- pwdinfo->social_chan[0] = 1;
- pwdinfo->social_chan[1] = 6;
- pwdinfo->social_chan[2] = 11;
- pwdinfo->social_chan[3] = 0; // channel 0 for scanning ending in site survey function.
-
- // Use the channel 11 as the listen channel
- pwdinfo->listen_channel = 11;
-
- if ( *pinitValue == '1' )
- {
- pwdinfo->role = P2P_ROLE_DEVICE;
- pwdinfo->p2p_state = P2P_STATE_LISTEN;
- pwdinfo->intent = 1;
- }
- else if ( *pinitValue == '2' )
- {
- pwdinfo->role = P2P_ROLE_CLIENT;
- pwdinfo->p2p_state = P2P_STATE_GONEGO_OK;
- pwdinfo->intent = 1;
- }
- else if ( *pinitValue == '3' )
- {
- pwdinfo->role = P2P_ROLE_GO;
- pwdinfo->p2p_state = P2P_STATE_GONEGO_OK;
- pwdinfo->intent = 15;
- }
-
-
- pwdinfo->pre_p2p_state = P2P_STATE_NONE;
-
-// Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 )
- pwdinfo->support_rate[0] = 0x8c; // 6(B)
- pwdinfo->support_rate[1] = 0x92; // 9(B)
- pwdinfo->support_rate[2] = 0x18; // 12
- pwdinfo->support_rate[3] = 0x24; // 18
- pwdinfo->support_rate[4] = 0x30; // 24
- pwdinfo->support_rate[5] = 0x48; // 36
- pwdinfo->support_rate[6] = 0x60; // 48
- pwdinfo->support_rate[7] = 0x6c; // 54
-
- _rtw_memcpy( ( void* ) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7 );
-
- _rtw_memset( pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN );
- _rtw_memcpy( pwdinfo->device_name, "Realtek DMP Device", 18 );
- pwdinfo->device_name_len = 18;
-
- _rtw_memset( &pwdinfo->invitereq_info, 0x00, sizeof( struct tx_invite_req_info ) );
- pwdinfo->invitereq_info.token = 3; // Token used for P2P invitation request frame.
- pwdinfo->invitereq_info.peer_operation_ch = pwdinfo->listen_channel;
-
- _rtw_memset( &pwdinfo->inviteresp_info, 0x00, sizeof( struct tx_invite_resp_info ) );
- pwdinfo->inviteresp_info.token = 0;
-
- pwdinfo->profileindex = 0;
- _rtw_memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
-
- _init_timer( &pwdinfo->find_phase_timer, padapter->pnetdev, find_phase_timer_process, padapter );
- _init_timer( &pwdinfo->restore_p2p_state_timer, padapter->pnetdev, restore_p2p_state_timer_process, padapter );
- _init_timer( &pwdinfo->pre_tx_scan_timer, padapter->pnetdev, pre_tx_scan_timer_process, padapter );
-
- pwdinfo->find_phase_state_exchange_cnt = 0;
-
- pwdinfo->listen_dwell = ( u8 ) (( rtw_get_current_time() % 3 ) + 1);
- DBG_8192C( "[%s] listen_dwell time is %d00ms\n", __FUNCTION__, pwdinfo->listen_dwell );
-
- _rtw_memset( &pwdinfo->tx_prov_disc_info, 0x00, sizeof( struct tx_provdisc_req_info ) );
- pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
-
- _rtw_memset( &pwdinfo->nego_req_info, 0x00, sizeof( struct tx_nego_req_info ) );
-
- pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
- pwdinfo->negotiation_dialog_token = 1;
-
- _rtw_memset( pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN );
- pwdinfo->nego_ssidlen = 0;
-
- pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
-#ifdef CONFIG_WFD
- pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY;
- _rtw_memset( &pwdinfo->wfd_info, 0x00, sizeof( struct wifi_display_info ) );
- pwdinfo->wfd_info.rtsp_ctrlport = 554;
- pwdinfo->wfd_info.peer_rtsp_ctrlport = 0; // Reset to 0
-#else
- pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
-#endif //CONFIG_WFD
- pwdinfo->channel_cnt = 0;
- _rtw_memset( pwdinfo->channel_list, 0x00, 13 );
-
- _rtw_memset( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4 );
- _rtw_memset( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3 );
-}
-
-static int rtw_p2p_enable(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- if ( ( *extra == '1' ) || ( *extra == '2' ) || ( *extra == '3' ) )
- {
- u8 channel, ch_offset;
- u16 bwmode;
-
- // Enable P2P function
- init_wifidirect_info(padapter, extra );
-
- //leave IPS/Autosuspend
- if(_FAIL == rfpwrstate_check(padapter))
- {
- return -EFAULT;
- }
-
- if(pwdinfo->p2p_state == P2P_STATE_LISTEN)
- {
- // Stay at the listen state and wait for discovery.
- channel = pwdinfo->listen_channel;
- ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- bwmode = HT_CHANNEL_WIDTH_20;
- }
- else
- {
- pwdinfo->operating_channel = pmlmeext->cur_channel;
-
- channel = pwdinfo->operating_channel;
- ch_offset = pmlmeext->cur_ch_offset;
- bwmode = pmlmeext->cur_bwmode;
- }
-
- set_channel_bwmode(padapter, channel, ch_offset, bwmode);
-
- }
- else if ( *extra == '0' )
- { // Disable P2P Listen State
- if ( pwdinfo->p2p_state != P2P_STATE_NONE )
- {
- _rtw_memset( pwdinfo, 0x00, sizeof( struct wifidirect_info) );
- pwdinfo->p2p_state = P2P_STATE_NONE;
- }
- if(pwrpriv->bips_processing == _FALSE){
- rtw_set_pwr_state_check_timer(pwrpriv);
- }
- }
-
- return ret;
-
-}
-
-static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
-
- DBG_8192C( "[%s] ssid = %s, len = %d\n", __FUNCTION__, extra, strlen( extra ) );
- _rtw_memcpy( pwdinfo->nego_ssid, extra, strlen( extra ) );
- pwdinfo->nego_ssidlen = strlen( extra );
-
- return ret;
-
-}
-
-
-static int rtw_p2p_set_intent(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
- u8 intent = pwdinfo->intent;
-
- switch( wrqu->data.length )
- {
- case 1:
- {
- intent = extra[ 0 ] - '0';
- break;
- }
- case 2:
- {
- intent = str_2char2num( extra[ 0 ], extra[ 1 ]);
- break;
- }
- }
-
- if ( intent <= 15 )
- {
- pwdinfo->intent= intent;
- }
- else
- {
- ret = -1;
- }
-
- DBG_8192C( "[%s] intent = %d\n", __FUNCTION__, intent);
-
- return ret;
-
-}
-
-static int rtw_p2p_set_listen_ch(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
- u8 listen_ch = pwdinfo->listen_channel; // Listen channel number
-
- switch( wrqu->data.length )
- {
- case 1:
- {
- listen_ch = extra[ 0 ] - '0';
- break;
- }
- case 2:
- {
- listen_ch = str_2char2num( extra[ 0 ], extra[ 1 ]);
- break;
- }
- }
-
- if ( listen_ch > 0 && listen_ch <= 13 )
- {
- pwdinfo->listen_channel = listen_ch;
- set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
- }
- else
- {
- ret = -1;
- }
-
- DBG_8192C( "[%s] listen_ch = %d\n", __FUNCTION__, pwdinfo->listen_channel );
-
- return ret;
-
-}
-
-static int rtw_p2p_set_op_ch(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-// Commented by Albert 20110524
-// This function is used to set the operating channel if the driver will become the group owner
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
- u8 op_ch = pwdinfo->operating_channel; // Operating channel number
-
- switch( wrqu->data.length )
- {
- case 1:
- {
- op_ch = extra[ 0 ] - '0';
- break;
- }
- case 2:
- {
- op_ch = str_2char2num( extra[ 0 ], extra[ 1 ]);
- break;
- }
- }
-
- if ( op_ch > 0 && op_ch <= 13 )
- {
- pwdinfo->operating_channel = op_ch;
- }
- else
- {
- ret = -1;
- }
-
- printk( "[%s] op_ch = %d\n", __FUNCTION__, pwdinfo->operating_channel );
-
- return ret;
-
-}
-
-
-static int rtw_p2p_profilefound(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
-
- // Comment by Albert 2010/10/13
- // Input data format:
- // Ex: 0
- // Ex: 1XXXXXXXXXXXXYYSSID
- // 0 => Reflush the profile record list.
- // 1 => Add the profile list
- // XXXXXXXXXXXX => peer's MAC Address ( 00:E0:4C:00:00:01 => 00E04C000001 )
- // YY => SSID Length
- // SSID => SSID for persistence group
-
- DBG_8192C( "[%s] In value = %s, len = %d \n", __FUNCTION__, extra, wrqu->data.length -1);
-
-
- // The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function.
- if ( pwdinfo->p2p_state != P2P_STATE_NONE )
- {
- if ( extra[ 0 ] == '0' )
- {
- // Remove all the profile information of wifidirect_info structure.
- _rtw_memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
- pwdinfo->profileindex = 0;
- }
- else
- {
- if ( pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM )
- {
- ret = -1;
- }
- else
- {
- int jj, kk;
-
- // Add this profile information into pwdinfo->profileinfo
- // Ex: 1XXXXXXXXXXXXYYSSID
- for( jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 2 )
- {
- pwdinfo->profileinfo[ pwdinfo->profileindex ].peermac[ jj ] = key_2char2num(extra[ kk ], extra[ kk+ 1 ]);
- }
-
- pwdinfo->profileinfo[ pwdinfo->profileindex ].ssidlen = ( extra[13] - '0' ) * 10 + ( extra[ 14 ] - '0' );
- _rtw_memcpy( pwdinfo->profileinfo[ pwdinfo->profileindex ].ssid, &extra[ 15 ], pwdinfo->profileinfo[ pwdinfo->profileindex ].ssidlen );
- pwdinfo->profileindex++;
- }
- }
- }
-
- return ret;
-
-}
-
-static int rtw_p2p_setDN(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
-
-
- DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
- pwdinfo->device_name_len = wrqu->data.length - 1;
- _rtw_memset( pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN );
- _rtw_memcpy( pwdinfo->device_name, extra, pwdinfo->device_name_len );
-
- return ret;
-
-}
-
-
-static int rtw_p2p_get_status(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
-
-
- DBG_8192C( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, pwdinfo->role, pwdinfo->p2p_state,
- pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
- pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
-
- // Commented by Albert 2010/10/12
- // Because of the output size limitation, I had removed the "Role" information.
- // About the "Role" information, we will use the new private IOCTL to get the "Role" information.
- sprintf( extra, "\n\nStatus=%.2d\n", pwdinfo->p2p_state );
- wrqu->data.length = strlen( extra );
-
- if ( pwdinfo->p2p_state == P2P_STATE_LISTEN )
- {
- // Stay at the listen state and wait for discovery.
- set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
- }
-
- return ret;
-
-}
-
-// Commented by Albert 20110520
-// This function will return the config method description
-// This config method description will show us which config method the remote P2P device is intented to use
-// by sending the provisioning discovery request frame.
-
-static int rtw_p2p_get_req_cm(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
-
- sprintf( extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req );
- wrqu->data.length = strlen( extra );
- return ret;
-
-}
-
-
-static int rtw_p2p_get_role(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
-
-
- DBG_8192C( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, pwdinfo->role, pwdinfo->p2p_state,
- pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
- pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
-
- sprintf( extra, "\n\nRole=%.2d\n", pwdinfo->role );
- wrqu->data.length = strlen( extra );
- return ret;
-
-}
-
-
-static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
-
-
- DBG_8192C( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, pwdinfo->role, pwdinfo->p2p_state,
- pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
- pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
-
- sprintf( extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
- pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
- pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
- wrqu->data.length = strlen( extra );
- return ret;
-
-}
-
-static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
-
- DBG_8192C( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, pwdinfo->role, pwdinfo->p2p_state,
- pwdinfo->rx_prov_disc_info.peerDevAddr[ 0 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 1 ],
- pwdinfo->rx_prov_disc_info.peerDevAddr[ 2 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 3 ],
- pwdinfo->rx_prov_disc_info.peerDevAddr[ 4 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 5 ]);
- sprintf( extra, "\n%.2X%.2X%.2X%.2X%.2X%.2X",
- pwdinfo->rx_prov_disc_info.peerDevAddr[ 0 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 1 ],
- pwdinfo->rx_prov_disc_info.peerDevAddr[ 2 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 3 ],
- pwdinfo->rx_prov_disc_info.peerDevAddr[ 4 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 5 ]);
- wrqu->data.length = strlen( extra );
- return ret;
-
-}
-
-static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
- u8 peerMAC[ ETH_ALEN ] = { 0x00 };
- int jj,kk;
- u8 peerMACStr[ 17 ] = { 0x00 };
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- _irqL irqL;
- _list *plist, *phead;
- _queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- u8 blnMatch = 0;
-
-
- // Commented by Albert 20110727
- // The input data is the MAC address which the application wants to know its WPS config method.
- // After knowing its WPS config method, the application can decide the config method for provisioning discovery.
- // Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05
-
- DBG_8192C( "[%s] data = %s\n", __FUNCTION__, ( char* ) extra );
- _rtw_memcpy( peerMACStr , extra , 17 );
-
-
- for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
- {
- peerMAC[ jj ] = key_2char2num( peerMACStr[kk], peerMACStr[kk+ 1] );
- }
-
- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- phead = get_list_head(queue);
- plist = get_next(phead);
-
- while(1)
- {
- if (rtw_end_of_queue_search(phead,plist)== _TRUE)
- break;
-
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
- if ( _rtw_memcmp( pnetwork->network.MacAddress, peerMAC, ETH_ALEN ) )
- {
- u8 wpsie[ 200 ] = { 0x00 };
- uint wpsie_len = 0;
- u16 attr_content = 0;
- uint attr_contentlen = 0;
-
- // The mac address is matched.
-
- if ( rtw_get_wps_ie_p2p( &pnetwork->network.IEs[ 12 ], pnetwork->network.IELength - 12, wpsie, &wpsie_len ) )
- {
- rtw_get_wps_attr_content( wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, ( u8* ) &attr_content, &attr_contentlen);
- if ( attr_contentlen )
- {
- attr_content = be16_to_cpu( attr_content );
- sprintf( extra, "\n\nM=%.4d", attr_content );
- _rtw_memcpy( wrqu->data.pointer, extra, 4 + 4 );
- *( (u8*) wrqu->data.pointer + 4 + 4 ) = 0x00;
- blnMatch = 1;
- }
- }
-
- break;
- }
-
- plist = get_next(plist);
-
- }
-
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- if ( !blnMatch )
- {
- sprintf( extra, "\n\nM=0000" );
- _rtw_memcpy( wrqu->data.pointer, extra, 4 + 4 );
- *( (u8*) wrqu->data.pointer + 4 + 4 ) = 0x00;
- }
-
- return ret;
-
-}
-
-#ifdef CONFIG_WFD
-static int rtw_p2p_get_peer_WFD_port(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
-
- DBG_8192C( "[%s] p2p_state = %d\n", __FUNCTION__, pwdinfo->p2p_state );
-
- sprintf( extra, "\n\nPort=%d\n", pwdinfo->wfd_info.peer_rtsp_ctrlport );
- DBG_8192C( "[%s] remote port = %d\n", __FUNCTION__, pwdinfo->wfd_info.peer_rtsp_ctrlport );
-
- wrqu->data.length = strlen( extra );
- return ret;
-
-}
-#endif // CONFIG_WFD
-
-static int rtw_p2p_get_device_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
- u8 peerMAC[ ETH_ALEN ] = { 0x00 };
- int jj,kk;
- u8 peerMACStr[ 17 ] = { 0x00 };
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- _irqL irqL;
- _list *plist, *phead;
- _queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- u8 blnMatch = 0;
-
-
- // Commented by Kurt 20110727
- // The input data is the MAC address which the application wants to know its device name.
- // Such user interface could show peer device's device name instead of ssid.
- // Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05
-
- DBG_8192C( "[%s] data = %s\n", __FUNCTION__, ( char* ) extra );
- _rtw_memcpy( peerMACStr , extra , 17 );
-
-
- for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
- {
- peerMAC[ jj ] = key_2char2num( peerMACStr[kk], peerMACStr[kk+ 1] );
- }
-
- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- phead = get_list_head(queue);
- plist = get_next(phead);
-
- while(1)
- {
- if (rtw_end_of_queue_search(phead,plist)== _TRUE)
- break;
-
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
- if ( _rtw_memcmp( pnetwork->network.MacAddress, peerMAC, ETH_ALEN ) )
- {
- u8 wpsie[ 200 ] = { 0x00 };
- uint wpsie_len = 0;
- u8 dev_name[ WPS_MAX_DEVICE_NAME_LEN ] = { 0x00 };
- uint dev_len = 0;
-
-
- // The mac address is matched.
-
- if ( rtw_get_wps_ie_p2p( &pnetwork->network.IEs[ 12 ], pnetwork->network.IELength - 12, wpsie, &wpsie_len ) )
- {
- rtw_get_wps_attr_content( wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
- if ( dev_len )
- {
- sprintf( extra, "\n\nN=%s", dev_name );
- _rtw_memcpy( wrqu->data.pointer, extra, dev_len + 4 );
- *( (u8*) wrqu->data.pointer + dev_len + 4 ) = 0x00;
- blnMatch = 1;
- }
- }
- break;
- }
-
- plist = get_next(plist);
-
- }
-
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- if ( !blnMatch )
- {
- sprintf( extra, "\n\nN=0000" );
- _rtw_memcpy( wrqu->data.pointer, extra, 4 + 4 );
- *( (u8*) wrqu->data.pointer + 4 + 4 ) = 0x00;
- }
-
- return ret;
-
-}
-
-static int rtw_p2p_connect(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
- u8 peerMAC[ ETH_ALEN ] = { 0x00 };
- int jj,kk;
- u8 peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- _irqL irqL;
- _list *plist, *phead;
- _queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- uint uintPeerChannel = 0;
-
- // Commented by Albert 20110304
- // The input data contains two informations.
- // 1. First information is the MAC address which wants to formate with
- // 2. Second information is the WPS PINCode or "pbc" string for push button method
- // Format: 00:E0:4C:00:00:05
- // Format: 00:E0:4C:00:00:05
-
- DBG_8192C( "[%s] data = %s\n", __FUNCTION__, extra );
-
- if ( ( pwdinfo->p2p_state == P2P_STATE_NONE ) || ( pwdinfo->p2p_state == P2P_STATE_IDLE ) )
- {
- DBG_8192C( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
- return ret;
- }
-
- if ( pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO )
- {
- return -1;
- }
-
- for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
- {
- peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
- }
-
- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- phead = get_list_head(queue);
- plist = get_next(phead);
-
- while(1)
- {
- if (rtw_end_of_queue_search(phead,plist)== _TRUE)
- break;
-
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
- if ( _rtw_memcmp( pnetwork->network.MacAddress, peerMAC, ETH_ALEN ) )
- {
- uintPeerChannel = pnetwork->network.Configuration.DSConfig;
- break;
- }
-
- plist = get_next(plist);
-
- }
-
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- if ( uintPeerChannel )
- {
- //set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
- _rtw_memset( &pwdinfo->nego_req_info, 0x00, sizeof( struct tx_nego_req_info ) );
- pwdinfo->nego_req_info.peer_channel_num[ 0 ] = uintPeerChannel;
- _rtw_memcpy( pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN );
- pwdinfo->nego_req_info.benable = _TRUE;
-
- pwdinfo->pre_p2p_state = pwdinfo->p2p_state;
- pwdinfo->p2p_state = P2P_STATE_GONEGO_ING;
-
- printk( "[%s] Start PreTx Procedure!\n", __FUNCTION__ );
- _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
- _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT );
- }
- else
- {
- printk( "[%s] Not Found in Scanning Queue~\n", __FUNCTION__ );
- ret = -1;
- }
-exit:
-
- return ret;
-}
-
-static int rtw_p2p_prov_disc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
- u8 peerMAC[ ETH_ALEN ] = { 0x00 };
- int jj,kk;
- u8 peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- _list *plist, *phead;
- _queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- uint uintPeerChannel = 0;
- u8 p2pie[255] = { 0x00 }, attr_content[50] = { 0x00 }, _status = 0;
- uint p2pielen = 0, attr_contentlen = 0;
- _irqL irqL;
-
- // Commented by Albert 20110301
- // The input data contains two informations.
- // 1. First information is the MAC address which wants to issue the provisioning discovery request frame.
- // 2. Second information is the WPS configuration method which wants to discovery
- // Format: 00:E0:4C:00:00:05_display
- // Format: 00:E0:4C:00:00:05_keypad
- // Format: 00:E0:4C:00:00:05_pbc
- // Format: 00:E0:4C:00:00:05_label
-
- DBG_8192C( "[%s] data = %s\n", __FUNCTION__, extra );
-
- if ( ( pwdinfo->p2p_state == P2P_STATE_NONE ) || ( pwdinfo->p2p_state == P2P_STATE_IDLE ) )
- {
- DBG_8192C( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
- return ret;
- }
- else
- {
- // Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request.
- _rtw_memset( pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN );
- _rtw_memset( pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN );
- _rtw_memset( &pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof( NDIS_802_11_SSID ) );
- pwdinfo->tx_prov_disc_info.peer_channel_num[ 0 ] = 0;
- pwdinfo->tx_prov_disc_info.peer_channel_num[ 1 ] = 0;
- pwdinfo->tx_prov_disc_info.benable = _FALSE;
- }
-
- for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
- {
- peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
- }
-
- if ( _rtw_memcmp( &extra[ 18 ], "display", 7 ) )
- {
- pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
- }
- else if ( _rtw_memcmp( &extra[ 18 ], "keypad", 7 ) )
- {
- pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
- }
- else if ( _rtw_memcmp( &extra[ 18 ], "pbc", 3 ) )
- {
- pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
- }
- else if ( _rtw_memcmp( &extra[ 18 ], "label", 5 ) )
- {
- pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
- }
- else
- {
- DBG_8192C( "[%s] Unknown WPS config methodn", __FUNCTION__ );
- return( ret );
- }
-
- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- phead = get_list_head(queue);
- plist = get_next(phead);
-
- while(1)
- {
- if (rtw_end_of_queue_search(phead,plist)== _TRUE)
- break;
-
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-
- // Commented by Albert 2011/05/18
- // Match the device address located in the P2P IE
- // This is for the case that the P2P device address is not the same as the P2P interface address.
-
- if ( rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, p2pie, &p2pielen) )
- {
- // The P2P Device ID attribute is included in the Beacon frame.
- // The P2P Device Info attribute is included in the probe response frame.
-
- if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen) )
- {
- // Handle the P2P Device ID attribute of Beacon first
- if ( _rtw_memcmp( attr_content, peerMAC, ETH_ALEN ) )
- {
- uintPeerChannel = pnetwork->network.Configuration.DSConfig;
- break;
- }
- }
- else if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen) )
- {
- // Handle the P2P Device Info attribute of probe response
- if ( _rtw_memcmp( attr_content, peerMAC, ETH_ALEN ) )
- {
- uintPeerChannel = pnetwork->network.Configuration.DSConfig;
- break;
- }
- }
-
- }
-
- plist = get_next(plist);
-
- }
-
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
-
- if ( uintPeerChannel )
- {
- _rtw_memcpy( pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN );
- _rtw_memcpy( pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN );
- pwdinfo->tx_prov_disc_info.peer_channel_num[0] = ( u16 ) uintPeerChannel;
- pwdinfo->tx_prov_disc_info.benable = _TRUE;
- pwdinfo->pre_p2p_state = pwdinfo->p2p_state;
- pwdinfo->p2p_state = P2P_STATE_TX_PROVISION_DIS_REQ;
-
- if ( P2P_ROLE_CLIENT == pwdinfo->role )
- {
- _rtw_memcpy( &pwdinfo->tx_prov_disc_info.ssid, pnetwork->network.Ssid.Ssid, sizeof( NDIS_802_11_SSID ) );
- }
- else if ( ( P2P_ROLE_DEVICE == pwdinfo->role ) || ( P2P_ROLE_GO == pwdinfo->role ) )
- {
- _rtw_memcpy( pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN );
- pwdinfo->tx_prov_disc_info.ssid.SsidLength= P2P_WILDCARD_SSID_LEN;
- }
-
- set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
- _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
- _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
-
- }
- else
- {
- DBG_8192C( "[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__ );
- }
-exit:
-
- return ret;
-
-}
-
-// Added by Albert 20110328
-// This function is used to inform the driver the user had specified the pin code value or pbc
-// to application.
-
-static int rtw_p2p_got_wpsinfo(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
-
-
- DBG_8192C( "[%s] data = %s\n", __FUNCTION__, extra );
- // Added by Albert 20110328
- // if the input data is P2P_NO_WPSINFO -> reset the wpsinfo
- // if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device.
- // if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself.
- // if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC
-
- if ( *extra == '0' )
- {
- pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
- }
- else if ( *extra == '1' )
- {
- pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
- }
- else if ( *extra == '2' )
- {
- pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
- }
- else if ( *extra == '3' )
- {
- pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
- }
- else
- {
- pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
- }
-
- return ret;
-
-}
-
-#endif //CONFIG_P2P
-
-static int rtw_p2p_set(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
-#ifdef CONFIG_P2P
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- DBG_8192C( "[%s] extra = %s\n", __FUNCTION__, extra );
-
- if ( _rtw_memcmp( extra, "enable=", 7 ) )
- {
- rtw_p2p_enable( dev, info, wrqu, &extra[7] );
- }
- else if ( _rtw_memcmp( extra, "setDN=", 6 ) )
- {
- wrqu->data.length -= 6;
- rtw_p2p_setDN( dev, info, wrqu, &extra[6] );
- }
- else if ( _rtw_memcmp( extra, "profilefound=", 13 ) )
- {
- wrqu->data.length -= 13;
- rtw_p2p_profilefound( dev, info, wrqu, &extra[13] );
- }
- else if ( _rtw_memcmp( extra, "prov_disc=", 10 ) )
- {
- wrqu->data.length -= 10;
- rtw_p2p_prov_disc( dev, info, wrqu, &extra[10] );
- }
- else if ( _rtw_memcmp( extra, "nego=", 5 ) )
- {
- wrqu->data.length -= 5;
- rtw_p2p_connect( dev, info, wrqu, &extra[5] );
- }
- else if ( _rtw_memcmp( extra, "intent=", 7 ) )
- {
- // Commented by Albert 2011/03/23
- // The wrqu->data.length will include the null character
- // So, we will decrease 7 + 1
- wrqu->data.length -= 8;
- rtw_p2p_set_intent( dev, info, wrqu, &extra[7] );
- }
- else if ( _rtw_memcmp( extra, "ssid=", 5 ) )
- {
- wrqu->data.length -= 5;
- rtw_p2p_set_go_nego_ssid( dev, info, wrqu, &extra[5] );
- }
- else if ( _rtw_memcmp( extra, "got_wpsinfo=", 12 ) )
- {
- wrqu->data.length -= 12;
- rtw_p2p_got_wpsinfo( dev, info, wrqu, &extra[12] );
- }
- else if ( _rtw_memcmp( extra, "listen_ch=", 10 ) )
- {
- // Commented by Albert 2011/05/24
- // The wrqu->data.length will include the null character
- // So, we will decrease (10 + 1)
- wrqu->data.length -= 11;
- rtw_p2p_set_listen_ch( dev, info, wrqu, &extra[10] );
- }
- else if ( _rtw_memcmp( extra, "op_ch=", 6 ) )
- {
- // Commented by Albert 2011/05/24
- // The wrqu->data.length will include the null character
- // So, we will decrease (6 + 1)
- wrqu->data.length -= 7;
- rtw_p2p_set_op_ch( dev, info, wrqu, &extra[6] );
- }
-
-
-#endif //CONFIG_P2P
-
- return ret;
-
-}
-
-static int rtw_p2p_get(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
-
-#ifdef CONFIG_P2P
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- DBG_8192C( "[%s] extra = %s\n", __FUNCTION__, (char*) wrqu->data.pointer );
-
- if ( _rtw_memcmp( wrqu->data.pointer, "status", 6 ) )
- {
- rtw_p2p_get_status( dev, info, wrqu, extra );
- }
- else if ( _rtw_memcmp( wrqu->data.pointer, "role", 4 ) )
- {
- rtw_p2p_get_role( dev, info, wrqu, extra);
- }
- else if ( _rtw_memcmp( wrqu->data.pointer, "peer_ifa", 8 ) )
- {
- rtw_p2p_get_peer_ifaddr( dev, info, wrqu, extra);
- }
- else if ( _rtw_memcmp( wrqu->data.pointer, "req_cm", 6 ) )
- {
- rtw_p2p_get_req_cm( dev, info, wrqu, extra);
- }
- else if ( _rtw_memcmp( wrqu->data.pointer, "peer_deva", 9 ) )
- {
- rtw_p2p_get_peer_devaddr( dev, info, wrqu, extra);
- }
-#ifdef CONFIG_WFD
- else if ( _rtw_memcmp( wrqu->data.pointer, "peer_port", 9 ) )
- {
- rtw_p2p_get_peer_WFD_port( dev, info, wrqu, extra );
- }
-#endif // CONFIG_WFD
-
-#endif //CONFIG_P2P
-
- return ret;
-
-}
-
-static int rtw_p2p_get2(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
-
-#ifdef CONFIG_P2P
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct iw_point *pdata = &wrqu->data;
- struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- DBG_8192C( "[%s] extra = %s\n", __FUNCTION__, (char*) wrqu->data.pointer );
-
- if ( _rtw_memcmp( extra, "wpsCM=", 6 ) )
- {
- wrqu->data.length -= 6;
- rtw_p2p_get_wps_configmethod( dev, info, wrqu, &extra[6]);
- }
- else if ( _rtw_memcmp( extra, "devN=", 5 ) )
- {
- wrqu->data.length -= 5;
- rtw_p2p_get_device_name( dev, info, wrqu, &extra[5] );
- }
-
-#endif //CONFIG_P2P
-
- return ret;
-
-}
-
-extern char *ifname;
-extern int rtw_change_ifname(_adapter *padapter, const char *ifname);
-static int rtw_rereg_nd_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- static char old_ifname[IFNAMSIZ] = {0};
- static u8 old_ips_mode;
- static u8 old_bRegUseLed;
- int ret = 0;
- _adapter *padapter = rtw_netdev_priv(dev);
- char new_ifname[IFNAMSIZ];
-
- if(old_ifname[0] == 0) {
- strncpy(old_ifname, ifname, IFNAMSIZ);
- old_ifname[IFNAMSIZ-1] = 0;
- }
-
- //DBG_871X("%s wrqu->data.length:%d\n", __FUNCTION__, wrqu->data.length);
- if(wrqu->data.length > IFNAMSIZ)
- return -EFAULT;
-
- if ( copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ) ) {
- return -EFAULT;
- }
-
- if( 0 == strcmp(old_ifname, new_ifname) ) {
- return ret;
- }
-
- DBG_871X("%s new_ifname:%s\n", __FUNCTION__, new_ifname);
- if( 0 != (ret = rtw_change_ifname(padapter, new_ifname)) ) {
- goto exit;
- }
-
- if(_rtw_memcmp(old_ifname, "disable%d", 9) == _TRUE) {
- padapter->ledpriv.bRegUseLed= old_bRegUseLed;
- rtw_sw_led_init(padapter);
- rtw_ips_mode_req(&padapter->pwrctrlpriv, old_ips_mode);
- }
-
- strncpy(old_ifname, new_ifname, IFNAMSIZ);
- old_ifname[IFNAMSIZ-1] = 0;
-
- if(_rtw_memcmp(new_ifname, "disable%d", 9) == _TRUE) {
-
- DBG_871X("%s disable\n", __FUNCTION__);
- // free network queue for Android's timming issue
- rtw_free_network_queue(padapter, _TRUE);
-
- // close led
- rtw_led_control(padapter, LED_CTL_POWER_OFF);
- old_bRegUseLed = padapter->ledpriv.bRegUseLed;
- padapter->ledpriv.bRegUseLed= _FALSE;
- rtw_sw_led_deinit(padapter);
-
- // the interface is being "disabled", we can do deeper IPS
- old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
- rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
- }
-exit:
- return ret;
-
-}
-
-#if 0
-void mac_reg_dump(_adapter *padapter)
-{
- int i,j=1;
- DBG_8192C("\n======= MAC REG =======\n");
- for(i=0x0;i<0x300;i+=4)
- {
- if(j%4==1) DBG_8192C("0x%02x",i);
- DBG_8192C(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) DBG_8192C("\n");
- }
- for(i=0x400;i<0x800;i+=4)
- {
- if(j%4==1) DBG_8192C("0x%02x",i);
- DBG_8192C(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) DBG_8192C("\n");
- }
-}
-void bb_reg_dump(_adapter *padapter)
-{
- int i,j=1;
- DBG_8192C("\n======= BB REG =======\n");
- for(i=0x800;i<0x1000;i+=4)
- {
- if(j%4==1) DBG_8192C("0x%02x",i);
-
- DBG_8192C(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) DBG_8192C("\n");
- }
-}
-void rf_reg_dump(_adapter *padapter)
-{
- int i,j=1,path;
- u32 value;
- DBG_8192C("\n======= RF REG =======\n");
- for(path=0;path<2;path++)
- {
- DBG_8192C("\nRF_Path(%x)\n",path);
- for(i=0;i<0x100;i++)
- {
- value = PHY_QueryRFReg(padapter, (RF90_RADIO_PATH_E)path,i, bMaskDWord);
- if(j%4==1) DBG_8192C("0x%02x ",i);
- DBG_8192C(" 0x%08x ",value);
- if((j++)%4==0) DBG_8192C("\n");
- }
- }
-}
-
-#endif
-
-void mac_reg_dump(_adapter *padapter)
-{
- int i,j=1;
- DBG_8192C("\n======= MAC REG =======\n");
- for(i=0x0;i<0x300;i+=4)
- {
- if(j%4==1) DBG_8192C("0x%02x",i);
- DBG_8192C(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) DBG_8192C("\n");
- }
- for(i=0x400;i<0x800;i+=4)
- {
- if(j%4==1) DBG_8192C("0x%02x",i);
- DBG_8192C(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) DBG_8192C("\n");
- }
-}
-void bb_reg_dump(_adapter *padapter)
-{
- int i,j=1;
- DBG_8192C("\n======= BB REG =======\n");
- for(i=0x800;i<0x1000;i+=4)
- {
- if(j%4==1) DBG_8192C("0x%02x",i);
-
- DBG_8192C(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) DBG_8192C("\n");
- }
-}
-void rf_reg_dump(_adapter *padapter)
-{
- int i,j=1,path;
- u32 value;
- u8 rf_type,path_nums = 0;
- padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-
- DBG_8192C("\n======= RF REG =======\n");
- if((RF_1T2R == rf_type) ||(RF_1T1R ==rf_type ))
- path_nums = 1;
- else
- path_nums = 2;
-
- for(path=0;path<path_nums;path++)
- {
- DBG_8192C("\nRF_Path(%x)\n",path);
- for(i=0;i<0x100;i++)
- {
- //value = PHY_QueryRFReg(padapter, (RF90_RADIO_PATH_E)path,i, bMaskDWord);
- value =padapter->HalFunc.read_rfreg(padapter, path, i, 0xffffffff);
- if(j%4==1) DBG_8192C("0x%02x ",i);
- DBG_8192C(" 0x%08x ",value);
- if((j++)%4==0) DBG_8192C("\n");
- }
- }
-}
-
-static int rtw_dbg_port(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _irqL irqL;
- int ret = 0;
- u8 major_cmd, minor_cmd;
- u16 arg;
- u32 extra_arg, *pdata, val32;
- struct sta_info *psta;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct wlan_network *cur_network = &(pmlmepriv->cur_network);
- struct sta_priv *pstapriv = &padapter->stapriv;
-
-
- pdata = (u32*)&wrqu->data;
-
- val32 = *pdata;
- arg = (u16)(val32&0x0000ffff);
- major_cmd = (u8)(val32>>24);
- minor_cmd = (u8)((val32>>16)&0x00ff);
-
- extra_arg = *(pdata+1);
-
- switch(major_cmd)
- {
- case 0x70://read_reg
- switch(minor_cmd)
- {
- case 1:
- DBG_8192C("rtw_read8(0x%x)=0x%x\n", arg, rtw_read8(padapter, arg));
- break;
- case 2:
- DBG_8192C("rtw_read16(0x%x)=0x%x\n", arg, rtw_read16(padapter, arg));
- break;
- case 4:
- DBG_8192C("rtw_read32(0x%x)=0x%x\n", arg, rtw_read32(padapter, arg));
- break;
- }
- break;
- case 0x71://write_reg
- switch(minor_cmd)
- {
- case 1:
- rtw_write8(padapter, arg, extra_arg);
- DBG_8192C("rtw_write8(0x%x)=0x%x\n", arg, rtw_read8(padapter, arg));
- break;
- case 2:
- rtw_write16(padapter, arg, extra_arg);
- DBG_8192C("rtw_write16(0x%x)=0x%x\n", arg, rtw_read16(padapter, arg));
- break;
- case 4:
- rtw_write32(padapter, arg, extra_arg);
- DBG_8192C("rtw_write32(0x%x)=0x%x\n", arg, rtw_read32(padapter, arg));
- break;
- }
- break;
- case 0x72://read_bb
- DBG_8192C("read_bbreg(0x%x)=0x%x\n", arg, padapter->HalFunc.read_bbreg(padapter, arg, 0xffffffff));
- break;
- case 0x73://write_bb
- padapter->HalFunc.write_bbreg(padapter, arg, 0xffffffff, extra_arg);
- DBG_8192C("write_bbreg(0x%x)=0x%x\n", arg, padapter->HalFunc.read_bbreg(padapter, arg, 0xffffffff));
- break;
- case 0x74://read_rf
- DBG_8192C("read RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n",minor_cmd,arg,padapter->HalFunc.read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
- break;
- case 0x75://write_rf
- padapter->HalFunc.write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
- DBG_8192C("write RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n",minor_cmd,arg, padapter->HalFunc.read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
- break;
-
- case 0x76:
- switch(minor_cmd)
- {
- case 0x00: //normal mode,
- padapter->recvpriv.is_signal_dbg = 0;
- break;
- case 0x01: //dbg mode
- padapter->recvpriv.is_signal_dbg = 1;
- extra_arg = extra_arg>100?100:extra_arg;
- extra_arg = extra_arg<0?0:extra_arg;
- padapter->recvpriv.signal_strength_dbg=extra_arg;
- break;
- }
- break;
- case 0x7F:
- switch(minor_cmd)
- {
- case 0x0:
- DBG_8192C("fwstate=0x%x\n", get_fwstate(pmlmepriv));
- break;
- case 0x01:
- DBG_8192C("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
- psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
- psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
- break;
- case 0x02:
- DBG_8192C("pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
- break;
- case 0x03:
- DBG_8192C("qos_option=%d\n", pmlmepriv->qospriv.qos_option);
- DBG_8192C("ht_option=%d\n", pmlmepriv->htpriv.ht_option);
- break;
- case 0x04:
- DBG_8192C("cur_ch=%d\n", pmlmeext->cur_channel);
- DBG_8192C("cur_bw=%d\n", pmlmeext->cur_bwmode);
- DBG_8192C("cur_ch_off=%d\n", pmlmeext->cur_ch_offset);
- break;
- case 0x05:
- psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
- if(psta)
- {
- int i;
- struct recv_reorder_ctrl *preorder_ctrl;
-
- DBG_8192C("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
- DBG_8192C("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
- DBG_8192C("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
- DBG_8192C("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
- DBG_8192C("bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
- DBG_8192C("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
- DBG_8192C("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
-
- for(i=0;i<16;i++)
- {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- if(preorder_ctrl->enable)
- {
- DBG_8192C("tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq);
- }
- }
-
- }
- else
- {
- DBG_8192C("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
- }
- break;
- case 0x06:
- {
- u8 DMFlag;
- padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_DM_FLAG, (u8 *)(&DMFlag));
- DBG_8192C("(B)DMFlag=0x%x, arg=0x%x\n", DMFlag, arg);
- DMFlag = (u8)(0x0f&arg);
- DBG_8192C("(A)DMFlag=0x%x\n", DMFlag);
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_DM_FLAG, (u8 *)(&DMFlag));
- }
- break;
- case 0x07:
- DBG_8192C("bSurpriseRemoved=%d, bDriverStopped=%d\n",
- padapter->bSurpriseRemoved, padapter->bDriverStopped);
- break;
- case 0x08:
- {
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- DBG_8192C("free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d\n",
- pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt);
- #ifdef CONFIG_USB_HCI
- DBG_8192C("rx_urb_pending_cn=%d\n", precvpriv->rx_pending_cnt);
- #endif
- }
- break;
- case 0x09:
- {
- int i, j;
- _list *plist, *phead;
- struct recv_reorder_ctrl *preorder_ctrl;
-
-#ifdef CONFIG_AP_MODE
- DBG_8192C("sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
-#endif
- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
-
- for(i=0; i< NUM_STA; i++)
- {
- phead = &(pstapriv->sta_hash[i]);
- plist = get_next(phead);
-
- while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
- {
- psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
-
- plist = get_next(plist);
-
- if(extra_arg == psta->aid)
- {
- DBG_8192C("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
- DBG_8192C("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
- DBG_8192C("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
- DBG_8192C("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
- DBG_8192C("bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
- DBG_8192C("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
- DBG_8192C("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
- DBG_8192C("capability=0x%x\n", psta->capability);
- DBG_8192C("flags=0x%x\n", psta->flags);
- DBG_8192C("wpa_psk=0x%x\n", psta->wpa_psk);
- DBG_8192C("wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
- DBG_8192C("wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
- DBG_8192C("qos_info=0x%x\n", psta->qos_info);
- DBG_8192C("dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
-
-
-
- for(j=0;j<16;j++)
- {
- preorder_ctrl = &psta->recvreorder_ctrl[j];
- if(preorder_ctrl->enable)
- {
- DBG_8192C("tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq);
- }
- }
-
- }
-
- }
- }
-
- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
-
- }
- break;
-
- case 0x0c://dump rx packet
- {
- DBG_8192C("dump rx packet (%d)\n",extra_arg);
- //pHalData->bDumpRxPkt =extra_arg;
- padapter->HalFunc.SetHalDefVarHandler(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
- }
- break;
-#if 0
- case 0x0d://dump cam
- {
- //u8 entry = (u8) extra_arg;
- u8 entry=0;
- //dump cam
- for(entry=0;entry<32;entry++)
- read_cam(padapter,entry);
- }
- break;
-#endif
- #ifdef SILENT_RESET_FOR_SPECIFIC_PLATFOM
- case 0x0f:
- {
- if(extra_arg == 0){
- DBG_8192C("###### silent reset test.......#####\n");
- if(padapter->HalFunc.silentreset)
- padapter->HalFunc.silentreset(padapter);
- }
-
- }
- break;
- case 0x12:
- {
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- DBG_8192C("==>silent resete cnts:%d\n",pwrpriv->ips_enter_cnts);
- }
- break;
-
- #endif
-
- case 0x10:// driver version display
- DBG_8192C("rtw driver version=%s\n", DRIVERVERSION);
- break;
- case 0x11:
- {
- DBG_8192C("turn %s Rx RSSI display function\n",(extra_arg==1)?"on":"off");
- padapter->bRxRSSIDisplay = extra_arg ;
- }
- break;
-#if 1
- case 0xdd://registers dump , 0 for mac reg,1 for bb reg, 2 for rf reg
- {
- if(extra_arg==0){
- mac_reg_dump(padapter);
- }
- else if(extra_arg==1){
- bb_reg_dump(padapter);
- }
- else if(extra_arg==2){
- rf_reg_dump(padapter);
- }
-
- }
- break;
-#endif
- case 0xee://turn on/off dynamic funcs
- {
- u8 dm_flag;
-
- if(0xf==extra_arg){
- padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_DBG_DM_FUNC,&dm_flag);
- DBG_8192C(" === DMFlag(0x%02x) === \n",dm_flag);
- DBG_8192C("extra_arg = 0 - disable all dynamic func \n");
- DBG_8192C("extra_arg = 1 - disable DIG- BIT(0)\n");
- DBG_8192C("extra_arg = 2 - disable High power - BIT(1)\n");
- DBG_8192C("extra_arg = 3 - disable tx power tracking - BIT(2)\n");
- DBG_8192C("extra_arg = 4 - disable BT coexistence - BIT(3)\n");
- DBG_8192C("extra_arg = 5 - disable antenna diversity - BIT(4)\n");
- DBG_8192C("extra_arg = 6 - enable all dynamic func \n");
- }
- else{
- /* extra_arg = 0 - disable all dynamic func
- extra_arg = 1 - disable DIG
- extra_arg = 2 - disable tx power tracking
- extra_arg = 3 - turn on all dynamic func
- */
- padapter->HalFunc.SetHalDefVarHandler(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
- padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_DBG_DM_FUNC,&dm_flag);
- DBG_8192C(" === DMFlag(0x%02x) === \n",dm_flag);
- }
- }
- break;
-
- case 0xfd:
- rtw_write8(padapter, 0xc50, arg);
- DBG_8192C("wr(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
- rtw_write8(padapter, 0xc58, arg);
- DBG_8192C("wr(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
- break;
- case 0xfe:
- DBG_8192C("rd(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
- DBG_8192C("rd(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
- break;
- case 0xff:
- {
- DBG_8192C("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
- DBG_8192C("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
- DBG_8192C("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
- DBG_8192C("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
- DBG_8192C("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
-
- DBG_8192C("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
-
-
- DBG_8192C("\n");
-
- DBG_8192C("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
- DBG_8192C("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
-
- DBG_8192C("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
-
- DBG_8192C("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
-
- DBG_8192C("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
- DBG_8192C("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
-
- DBG_8192C("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
- DBG_8192C("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
- DBG_8192C("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
- DBG_8192C("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
- }
- break;
- }
- break;
- default:
- DBG_8192C("error dbg cmd!\n");
- break;
- }
-
-
- return ret;
-
-}
-
-static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- uint ret=0;
- u32 flags;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- switch (name){
- case IEEE_PARAM_WPA_ENABLED:
-
- padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X; //802.1x
-
- //ret = ieee80211_wpa_enable(ieee, value);
-
- switch((value)&0xff)
- {
- case 1 : //WPA
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; //WPA_PSK
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case 2: //WPA2
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; //WPA2_PSK
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- }
-
- RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("wpa_set_param:padapter->securitypriv.ndisauthtype=%d\n", padapter->securitypriv.ndisauthtype));
-
- break;
-
- case IEEE_PARAM_TKIP_COUNTERMEASURES:
- //ieee->tkip_countermeasures=value;
- break;
-
- case IEEE_PARAM_DROP_UNENCRYPTED:
- {
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
-
-#if 0
- struct ieee80211_security sec = {
- .flags = SEC_ENABLED,
- .enabled = value,
- };
- ieee->drop_unencrypted = value;
- /* We only change SEC_LEVEL for open mode. Others
- * are set by ipw_wpa_set_encryption.
- */
- if (!value) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_0;
- }
- else {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- }
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-#endif
- break;
-
- }
- case IEEE_PARAM_PRIVACY_INVOKED:
-
- //ieee->privacy_invoked=value;
-
- break;
-
- case IEEE_PARAM_AUTH_ALGS:
-
- ret = wpa_set_auth_algs(dev, value);
-
- break;
-
- case IEEE_PARAM_IEEE_802_1X:
-
- //ieee->ieee802_1x=value;
-
- break;
-
- case IEEE_PARAM_WPAX_SELECT:
-
- // added for WPA2 mixed mode
- //DBG_8192C(KERN_WARNING "------------------------>wpax value = %x\n", value);
- /*
- spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
- ieee->wpax_type_set = 1;
- ieee->wpax_type_notify = value;
- spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
- */
-
- break;
-
- default:
-
-
-
- ret = -EOPNOTSUPP;
-
-
- break;
-
- }
-
- return ret;
-
-}
-
-static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
-{
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- switch (command)
- {
- case IEEE_MLME_STA_DEAUTH:
-
- if(!rtw_set_802_11_disassociate(padapter))
- ret = -1;
-
- break;
-
- case IEEE_MLME_STA_DISASSOC:
-
- if(!rtw_set_802_11_disassociate(padapter))
- ret = -1;
-
- break;
-
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
- return ret;
-
-}
-
-static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
-{
- struct ieee_param *param;
- uint ret=0;
-
- //down(&ieee->wx_sem);
-
- if (p->length < sizeof(struct ieee_param) || !p->pointer){
- ret = -EINVAL;
- goto out;
- }
-
- param = (struct ieee_param *)rtw_malloc(p->length);
- if (param == NULL)
- {
- ret = -ENOMEM;
- goto out;
- }
-
- if (copy_from_user(param, p->pointer, p->length))
- {
- rtw_mfree((u8*)param, p->length);
- ret = -EFAULT;
- goto out;
- }
-
- switch (param->cmd) {
-
- case IEEE_CMD_SET_WPA_PARAM:
- ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
- break;
-
- case IEEE_CMD_SET_WPA_IE:
- //ret = wpa_set_wpa_ie(dev, param, p->length);
- ret = rtw_set_wpa_ie((_adapter *)rtw_netdev_priv(dev), (char*)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
- break;
-
- case IEEE_CMD_SET_ENCRYPTION:
- ret = wpa_set_encryption(dev, param, p->length);
- break;
-
- case IEEE_CMD_MLME:
- ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
- break;
-
- default:
- DBG_8192C("Unknown WPA supplicant request: %d\n", param->cmd);
- ret = -EOPNOTSUPP;
- break;
-
- }
-
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
-
- rtw_mfree((u8 *)param, p->length);
-
-out:
-
- //up(&ieee->wx_sem);
-
- return ret;
-
-}
-
-#ifdef CONFIG_AP_MODE
-static u8 set_pairwise_key(_adapter *padapter, struct sta_info *psta)
-{
- struct cmd_obj* ph2c;
- struct set_stakey_parm *psetstakey_para;
- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
- u8 res=_SUCCESS;
-
- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
- if ( ph2c == NULL){
- res= _FAIL;
- goto exit;
- }
-
- psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));
- if(psetstakey_para==NULL){
- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
- res=_FAIL;
- goto exit;
- }
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
-
-
- psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
-
- _rtw_memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
-
- _rtw_memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
-
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
- return res;
-
-}
-
-static int set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)
-{
- u8 keylen;
- struct cmd_obj* pcmd;
- struct setkey_parm *psetkeyparm;
- struct cmd_priv *pcmdpriv=&(padapter->cmdpriv);
- int res=_SUCCESS;
-
- DBG_8192C("%s\n", __FUNCTION__);
-
- pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
- if(pcmd==NULL){
- res= _FAIL;
- goto exit;
- }
- psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));
- if(psetkeyparm==NULL){
- rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
- res= _FAIL;
- goto exit;
- }
-
- _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
-
- psetkeyparm->keyid=(u8)keyid;
-
- psetkeyparm->algorithm = alg;
-
- psetkeyparm->set_tx = 1;
-
- switch(alg)
- {
- case _WEP40_:
- keylen = 5;
- break;
- case _WEP104_:
- keylen = 13;
- break;
- case _TKIP_:
- case _TKIP_WTMIC_:
- case _AES_:
- keylen = 16;
- default:
- keylen = 16;
- }
-
- _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);
-
- pcmd->cmdcode = _SetKey_CMD_;
- pcmd->parmbuf = (u8 *)psetkeyparm;
- pcmd->cmdsz = (sizeof(struct setkey_parm));
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
-
-
- _rtw_init_listhead(&pcmd->list);
-
- res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-
-exit:
-
- return res;
-
-
-}
-
-static int set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid)
-{
- u8 alg;
-
- switch(keylen)
- {
- case 5:
- alg =_WEP40_;
- break;
- case 13:
- alg =_WEP104_;
- break;
- default:
- alg =_NO_PRIVACY_;
- }
-
- return set_group_key(padapter, key, alg, keyid);
-
-}
-
-
-static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
-{
- int ret = 0;
- u32 wep_key_idx, wep_key_len;
- NDIS_802_11_WEP *pwep = NULL;
- struct sta_info *psta = NULL, *pbcmc_sta = NULL;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv* psecuritypriv=&(padapter->securitypriv);
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- DBG_8192C("%s\n", __FUNCTION__);
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
- //sizeof(struct ieee_param) = 64 bytes;
- //if (param_len != (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)
- if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len)
- {
- ret = -EINVAL;
- goto exit;
- }
-
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
- {
- if (param->u.crypt.idx >= WEP_KEYS)
- {
- ret = -EINVAL;
- goto exit;
- }
- }
- else
- {
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if(!psta)
- {
- //ret = -EINVAL;
- DBG_8192C("rtw_set_encryption(), sta has already been removed or never been added\n");
- goto exit;
- }
- }
-
- if (strcmp(param->u.crypt.alg, "none") == 0 && (psta==NULL))
- {
- //todo:clear default encryption keys
-
- DBG_8192C("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
-
- goto exit;
- }
-
-
- if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta==NULL))
- {
- DBG_8192C("r871x_set_encryption, crypt.alg = WEP\n");
-
- wep_key_idx = param->u.crypt.idx;
- wep_key_len = param->u.crypt.key_len;
-
- DBG_8192C("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
-
- if((wep_key_idx >= WEP_KEYS) || (wep_key_len<=0))
- {
- ret = -EINVAL;
- goto exit;
- }
-
-
- if (wep_key_len > 0)
- {
- wep_key_len = wep_key_len <= 5 ? 5 : 13;
-
- pwep =(NDIS_802_11_WEP *)rtw_malloc(wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial));
- if(pwep == NULL){
- DBG_8192C(" r871x_set_encryption: pwep allocate fail !!!\n");
- goto exit;
- }
-
- _rtw_memset(pwep, 0, sizeof(NDIS_802_11_WEP));
-
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
-
- }
-
- pwep->KeyIndex = wep_key_idx;
-
- _rtw_memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
-
- if(param->u.crypt.set_tx)
- {
- DBG_8192C("wep, set_tx=1\n");
-
- psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
- psecuritypriv->dot11PrivacyAlgrthm=_WEP40_;
- psecuritypriv->dot118021XGrpPrivacy=_WEP40_;
-
- if(pwep->KeyLength==13)
- {
- psecuritypriv->dot11PrivacyAlgrthm=_WEP104_;
- psecuritypriv->dot118021XGrpPrivacy=_WEP104_;
- }
-
-
- psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
-
- _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
-
- psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;
-
- set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
-
-
- }
- else
- {
- DBG_8192C("wep, set_tx=0\n");
-
- //don't update "psecuritypriv->dot11PrivacyAlgrthm" and
- //"psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to cam
-
- _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
-
- psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
-
- set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
-
- }
-
- goto exit;
-
- }
-
-
- if(!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) // //group key
- {
- if(param->u.crypt.set_tx ==1)
- {
- if(strcmp(param->u.crypt.alg, "WEP") == 0)
- {
- DBG_8192C("%s, set group_key, WEP\n", __FUNCTION__);
-
- _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
-
- psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
- if(param->u.crypt.key_len==13)
- {
- psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
- }
-
- }
- else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
- {
- DBG_8192C("%s, set group_key, TKIP\n", __FUNCTION__);
-
- psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
-
- _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
-
- //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
- //set mic key
- _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
- _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
-
- psecuritypriv->busetkipkey = _TRUE;
-
- }
- else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
- {
- DBG_8192C("%s, set group_key, CCMP\n", __FUNCTION__);
-
- psecuritypriv->dot118021XGrpPrivacy = _AES_;
-
- _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
- }
- else
- {
- DBG_8192C("%s, set group_key, none\n", __FUNCTION__);
-
- psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
- }
-
- psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
-
- psecuritypriv->binstallGrpkey = _TRUE;
-
- psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!
-
- set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
-
- pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
- if(pbcmc_sta)
- {
- pbcmc_sta->ieee8021x_blocked = _FALSE;
- pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy
- }
-
- }
-
- goto exit;
-
- }
-
- if(psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) // psk/802_1x
- {
- if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
- {
- if(param->u.crypt.set_tx ==1)
- {
- _rtw_memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
-
- if(strcmp(param->u.crypt.alg, "WEP") == 0)
- {
- DBG_8192C("%s, set pairwise key, WEP\n", __FUNCTION__);
-
- psta->dot118021XPrivacy = _WEP40_;
- if(param->u.crypt.key_len==13)
- {
- psta->dot118021XPrivacy = _WEP104_;
- }
- }
- else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
- {
- DBG_8192C("%s, set pairwise key, TKIP\n", __FUNCTION__);
-
- psta->dot118021XPrivacy = _TKIP_;
-
- //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
- //set mic key
- _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
- _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
-
- psecuritypriv->busetkipkey = _TRUE;
-
- }
- else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
- {
-
- DBG_8192C("%s, set pairwise key, CCMP\n", __FUNCTION__);
-
- psta->dot118021XPrivacy = _AES_;
- }
- else
- {
- DBG_8192C("%s, set pairwise key, none\n", __FUNCTION__);
-
- psta->dot118021XPrivacy = _NO_PRIVACY_;
- }
-
- set_pairwise_key(padapter, psta);
-
- psta->ieee8021x_blocked = _FALSE;
-
- }
- else//group key???
- {
- if(strcmp(param->u.crypt.alg, "WEP") == 0)
- {
- _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
-
- psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
- if(param->u.crypt.key_len==13)
- {
- psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
- }
- }
- else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
- {
- psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
-
- _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
-
- //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
- //set mic key
- _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
- _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
-
- psecuritypriv->busetkipkey = _TRUE;
-
- }
- else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
- {
- psecuritypriv->dot118021XGrpPrivacy = _AES_;
-
- _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
- }
- else
- {
- psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
- }
-
- psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
-
- psecuritypriv->binstallGrpkey = _TRUE;
-
- psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!
-
- set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
-
- pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
- if(pbcmc_sta)
- {
- pbcmc_sta->ieee8021x_blocked = _FALSE;
- pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy
- }
-
- }
-
- }
-
- }
-
-exit:
-
- if(pwep)
- {
- rtw_mfree((u8 *)pwep, wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial));
- }
-
- return ret;
-
-}
-
-static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
-{
- int ret=0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct sta_priv *pstapriv = &padapter->stapriv;
- unsigned char *pbuf = param->u.bcn_ie.buf;
-
-
- DBG_8192C("%s, len=%d\n", __FUNCTION__, len);
-
- if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
- return -EINVAL;
-
- _rtw_memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
-
- if((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<=0))
- pstapriv->max_num_sta = NUM_STA;
-
-
- if(rtw_check_beacon_data(padapter, pbuf, (len-12-2)) == _SUCCESS)// 12 = param header, 2:no packed
- ret = 0;
- else
- ret = -EINVAL;
-
-
- return ret;
-
-}
-
-static int rtw_hostapd_sta_flush(struct net_device *dev)
-{
- //_irqL irqL;
- //_list *phead, *plist;
- int ret=0;
- //struct sta_info *psta = NULL;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- //struct sta_priv *pstapriv = &padapter->stapriv;
-
- DBG_8192C("%s\n", __FUNCTION__);
-
- flush_all_cam_entry(padapter); //clear CAM
-
-#if 0
- phead = &pstapriv->asoc_list;
- plist = get_next(phead);
-
- //free sta asoc_queue
- while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
- {
- psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-
- plist = get_next(plist);
-
- rtw_list_delete(&psta->asoc_list);
-
- //tear down Rx AMPDU
- send_delba(padapter, 0, psta->hwaddr);// recipient
-
- //tear down TX AMPDU
- send_delba(padapter, 1, psta->hwaddr);// // originator
- psta->htpriv.agg_enable_bitmap = 0x0;//reset
- psta->htpriv.candidate_tid_bitmap = 0x0;//reset
-
- issue_deauth(padapter, psta->hwaddr, WLAN_REASON_DEAUTH_LEAVING);
-
- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
- rtw_free_stainfo(padapter, psta);
- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
-
- }
-#endif
-
- ret = rtw_sta_flush(padapter);
-
- return ret;
-
-}
-
-static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
-{
- _irqL irqL;
- int ret=0;
- struct sta_info *psta = NULL;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- DBG_8192C("rtw_add_sta(aid=%d)=" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
-
- if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
- {
- return -EINVAL;
- }
-
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
- {
- return -EINVAL;
- }
-
-/*
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if(psta)
- {
- DBG_8192C("rtw_add_sta(), free has been added psta=%p\n", psta);
- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
- rtw_free_stainfo(padapter, psta);
- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
-
- psta = NULL;
- }
-*/
- //psta = rtw_alloc_stainfo(pstapriv, param->sta_addr);
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if(psta)
- {
- int flags = param->u.add_sta.flags;
-
- //DBG_8192C("rtw_add_sta(), init sta's variables, psta=%p\n", psta);
-
- psta->aid = param->u.add_sta.aid;//aid=1~2007
-
- _rtw_memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
-
-
- //check wmm cap.
- if(WLAN_STA_WME&flags)
- psta->qos_option = 1;
- else
- psta->qos_option = 0;
-
- if(pmlmepriv->qospriv.qos_option == 0)
- psta->qos_option = 0;
-
-
-#ifdef CONFIG_80211N_HT
- //chec 802.11n ht cap.
- if(WLAN_STA_HT&flags)
- {
- psta->htpriv.ht_option = _TRUE;
- psta->qos_option = 1;
- _rtw_memcpy((void*)&psta->htpriv.ht_cap, (void*)¶m->u.add_sta.ht_cap, sizeof(struct ieee80211_ht_cap));
- }
- else
- {
- psta->htpriv.ht_option = _FALSE;
- }
-
- if(pmlmepriv->htpriv.ht_option == _FALSE)
- psta->htpriv.ht_option = _FALSE;
-#endif
-
-
- update_sta_info_apmode(padapter, psta);
-
-
- }
- else
- {
- ret = -ENOMEM;
- }
-
- return ret;
-
-}
-
-static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
-{
- _irqL irqL;
- int ret=0;
- struct sta_info *psta = NULL;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- DBG_8192C("rtw_del_sta=" MAC_FMT "\n", MAC_ARG(param->sta_addr));
-
- if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
- {
- return -EINVAL;
- }
-
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
- {
- return -EINVAL;
- }
-
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if(psta)
- {
- //DBG_8192C("free psta=%p, aid=%d\n", psta, psta->aid);
-
-#if 0
- //tear down Rx AMPDU
- send_delba(padapter, 0, psta->hwaddr);// recipient
-
- //tear down TX AMPDU
- send_delba(padapter, 1, psta->hwaddr);// // originator
- psta->htpriv.agg_enable_bitmap = 0x0;//reset
- psta->htpriv.candidate_tid_bitmap = 0x0;//reset
-
- issue_deauth(padapter, psta->hwaddr, WLAN_REASON_DEAUTH_LEAVING);
-
- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
- rtw_free_stainfo(padapter, psta);
- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
-
- pstapriv->sta_dz_bitmap &=~BIT(psta->aid);
- pstapriv->tim_bitmap &=~BIT(psta->aid);
-#endif
-
- ap_free_sta(padapter, psta);
-
- psta = NULL;
-
- }
- else
- {
- DBG_8192C("rtw_del_sta(), sta has already been removed or never been added\n");
-
- //ret = -1;
- }
-
-
- return ret;
-
-}
-
-static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
-{
- int ret=0;
- struct sta_info *psta = NULL;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- DBG_8192C("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
-
- if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
- {
- return -EINVAL;
- }
-
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
- {
- return -EINVAL;
- }
-
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if(psta)
- {
- if((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC))
- {
- int wpa_ie_len;
- int copy_len;
-
- wpa_ie_len = psta->wpa_ie[1];
-
- copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
-
- param->u.wpa_ie.len = copy_len;
-
- _rtw_memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
- }
- else
- {
- //ret = -1;
- DBG_8192C("sta's wpa_ie is NONE\n");
- }
- }
- else
- {
- ret = -1;
- }
-
- return ret;
-
-}
-
-static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
-{
- int ret=0;
- unsigned char wps_oui[4]={0x0,0x50,0xf2,0x04};
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- int ie_len;
-
- DBG_8192C("%s, len=%d\n", __FUNCTION__, len);
-
- if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
- return -EINVAL;
-
- ie_len = len-12-2;// 12 = param header, 2:no packed
-
-
- if(pmlmepriv->wps_beacon_ie)
- {
- rtw_mfree(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
- pmlmepriv->wps_beacon_ie = NULL;
- }
-
- if(ie_len>0)
- {
- pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
- pmlmepriv->wps_beacon_ie_len = ie_len;
- if ( pmlmepriv->wps_beacon_ie == NULL) {
- DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
- return -EINVAL;
- }
-
- _rtw_memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
-
- update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE);
-
- pmlmeext->bstart_bss = _TRUE;
-
- }
-
-
- return ret;
-
-}
-
-static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
-{
- int ret=0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- int ie_len;
-
- DBG_8192C("%s, len=%d\n", __FUNCTION__, len);
-
- if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
- return -EINVAL;
-
- ie_len = len-12-2;// 12 = param header, 2:no packed
-
-
- if(pmlmepriv->wps_probe_resp_ie)
- {
- rtw_mfree(pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
- pmlmepriv->wps_probe_resp_ie = NULL;
- }
-
- if(ie_len>0)
- {
- pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
- pmlmepriv->wps_probe_resp_ie_len = ie_len;
- if ( pmlmepriv->wps_probe_resp_ie == NULL) {
- DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
- return -EINVAL;
- }
- _rtw_memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
- }
-
-
- return ret;
-
-}
-
-static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
-{
- int ret=0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- int ie_len;
-
- DBG_8192C("%s, len=%d\n", __FUNCTION__, len);
-
- if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
- return -EINVAL;
-
- ie_len = len-12-2;// 12 = param header, 2:no packed
-
-
- if(pmlmepriv->wps_assoc_resp_ie)
- {
- rtw_mfree(pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
- pmlmepriv->wps_assoc_resp_ie = NULL;
- }
-
- if(ie_len>0)
- {
- pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
- pmlmepriv->wps_assoc_resp_ie_len = ie_len;
- if ( pmlmepriv->wps_assoc_resp_ie == NULL) {
- DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
- return -EINVAL;
- }
-
- _rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
- }
-
-
- return ret;
-
-}
-
-static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
-{
- struct ieee_param *param;
- int ret=0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- //DBG_8192C("%s\n", __FUNCTION__);
-
- /*
- * this function is expect to call in master mode, which allows no power saving
- * so, we just check hw_init_completed instead of call rfpwrstate_check()
- */
-
- if (padapter->hw_init_completed==_FALSE){
- ret = -EPERM;
- goto out;
- }
-
-
- //if (p->length < sizeof(struct ieee_param) || !p->pointer){
- if(!p->pointer){
- ret = -EINVAL;
- goto out;
- }
-
- param = (struct ieee_param *)rtw_malloc(p->length);
- if (param == NULL)
- {
- ret = -ENOMEM;
- goto out;
- }
-
- if (copy_from_user(param, p->pointer, p->length))
- {
- rtw_mfree((u8*)param, p->length);
- ret = -EFAULT;
- goto out;
- }
-
- //DBG_8192C("%s, cmd=%d\n", __FUNCTION__, param->cmd);
-
- switch (param->cmd)
- {
- case RTL871X_HOSTAPD_FLUSH:
-
- ret = rtw_hostapd_sta_flush(dev);
-
- break;
-
- case RTL871X_HOSTAPD_ADD_STA:
-
- ret = rtw_add_sta(dev, param);
-
- break;
-
- case RTL871X_HOSTAPD_REMOVE_STA:
-
- ret = rtw_del_sta(dev, param);
-
- break;
-
- case RTL871X_HOSTAPD_SET_BEACON:
-
- ret = rtw_set_beacon(dev, param, p->length);
-
- break;
-
- case RTL871X_SET_ENCRYPTION:
-
- ret = rtw_set_encryption(dev, param, p->length);
-
- break;
-
- case RTL871X_HOSTAPD_GET_WPAIE_STA:
-
- ret = rtw_get_sta_wpaie(dev, param);
-
- break;
-
- case RTL871X_HOSTAPD_SET_WPS_BEACON:
-
- ret = rtw_set_wps_beacon(dev, param, p->length);
-
- break;
-
- case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
-
- ret = rtw_set_wps_probe_resp(dev, param, p->length);
-
- break;
-
- case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
-
- ret = rtw_set_wps_assoc_resp(dev, param, p->length);
-
- break;
-
- default:
- DBG_8192C("Unknown hostapd request: %d\n", param->cmd);
- ret = -EOPNOTSUPP;
- break;
-
- }
-
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
-
-
- rtw_mfree((u8 *)param, p->length);
-
-out:
-
- return ret;
-
-}
-#endif
-
-enum ANDROID_WIFI_CMD {
- ANDROID_WIFI_CMD_START = 0,
- ANDROID_WIFI_CMD_STOP,
- ANDROID_WIFI_CMD_RSSI,
- ANDROID_WIFI_CMD_LINKSPEED,
- ANDROID_WIFI_CMD_MACADDR,
- ANDROID_WIFI_CMD_SCAN_ACTIVE,
- ANDROID_WIFI_CMD_SCAN_PASSIVE,
- ANDROID_WIFI_CMD_COUNTRY,
- ANDROID_WIFI_CMD_SCAN_CHANNELS,
- ANDROID_WIFI_CMD_MAX
-};
-
-const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
- "START",
- "STOP",
- "RSSI",
- "LINKSPEED",
- "MACADDR",
- "SCAN-ACTIVE",
- "SCAN-PASSIVE",
- "COUNTRY",
- "SCAN-CHANNELS"
-};
-#define RTL8188_WAKELOCK_NAME "rtl8188_wifi_wakelock"
-
-static struct wake_lock rtl8188_suspend_lock;
-
-int rtl8188_wakelock_init = 0;
-
-void rtl8188_power_save_init(void)
-{
- wake_lock_init(&rtl8188_suspend_lock, WAKE_LOCK_SUSPEND, RTL8188_WAKELOCK_NAME);
- wake_lock(&rtl8188_suspend_lock);
-
- rtl8188_wakelock_init = 2;
-}
-
-void rtl8188_power_save_exit(void)
-{
- rtl8188_wakelock_init = 0;
- msleep(100);
-
- if (rtl8188_wakelock_init == 2)
- wake_unlock(&rtl8188_suspend_lock);
- wake_lock_destroy(&rtl8188_suspend_lock);
-}
-
-extern char init_channel_plan;
-
-static int rtw_wx_set_priv(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
-{
-
-#ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
- char *ext_dbg;
-#endif
-
- int ret = 0;
- int len = 0;
- char *ext;
- int i;
- char iwext[IW_CUSTOM_MAX + 1];
- union iwreq_data uwrq;
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_point *dwrq = (struct iw_point*)awrq;
-
- //RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, ("+rtw_wx_set_priv\n"));
-
- len = dwrq->length;
- if (!(ext = rtw_vmalloc(len)))
- return -ENOMEM;
-
- if (copy_from_user(ext, dwrq->pointer, len)) {
- rtw_vmfree(ext, len);
- return -EFAULT;
- }
-
-
- //RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_,
- // ("rtw_wx_set_priv: %s req=%s\n",
- // dev->name, ext));
-
- #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
- if (!(ext_dbg = rtw_vmalloc(len)))
- {
- rtw_vmfree(ext, len);
- return -ENOMEM;
- }
-
- _rtw_memcpy(ext_dbg, ext, len);
- #endif
-
- //added for wps2.0 @20110524
- if(dwrq->flags == 0x8766 && len > 8)
- {
- u32 cp_sz;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- u8 *probereq_wpsie = ext;
- int probereq_wpsie_len = len;
- u8 wps_oui[4]={0x0,0x50,0xf2,0x04};
-
- if((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
- (_rtw_memcmp(&probereq_wpsie[2], wps_oui, 4) ==_TRUE))
- {
-
- cp_sz = probereq_wpsie_len>MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN:probereq_wpsie_len;
-
- _rtw_memcpy(pmlmepriv->probereq_wpsie, probereq_wpsie, cp_sz);
- pmlmepriv->probereq_wpsie_len = cp_sz;
-
- }
-
- goto FREE_EXT;
-
- }
-
- if( len >= WEXT_CSCAN_HEADER_SIZE
- && _rtw_memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
- ){
- ret = rtw_wx_set_scan(dev, info, awrq, ext);
- goto FREE_EXT;
- }
-
-#ifdef CONFIG_ANDROID
- //DBG_871X("rtw_wx_set_priv: %s req=%s\n", dev->name, ext);
-
- for(i=0; i<len; i++) {
- if(*(ext+i)>='a' && *(ext+i)<='z' ) {
- *(ext+i)+= 'A'-'a';
- }
- }
-
- for(i=0 ; i<ANDROID_WIFI_CMD_MAX; i++)
- if(0 == strncmp(ext , android_wifi_cmd_str[i], strlen(android_wifi_cmd_str[i])) )
- break;
-
- switch(i) {
-
- //Turn on Wi-Fi hardware
- //OK if successful
- case ANDROID_WIFI_CMD_START :
- printk("ANDROID_WIFI_CMD_START..........\n");
- if (rtl8188_wakelock_init == 1)
- {
- wake_lock(&rtl8188_suspend_lock);
- rtl8188_wakelock_init = 2;
- }
- while( sleep_resume == 0){
- printk("waiting for wifi driver to be ready...\n");
- msleep(500);
- }
- sprintf(iwext, "START");
- uwrq.data.length = strlen("START");
- wireless_send_event(dev, IWEVCUSTOM, &uwrq, iwext);
- sprintf(ext, "OK");
- break;
-
- //Turn off Wi-Fi hardwoare
- //OK if successful
- case ANDROID_WIFI_CMD_STOP :
- printk("ANDROID_WIFI_CMD_STOP..........\n");
- sprintf(iwext, "STOP");
- uwrq.data.length = strlen("STOP");
- wireless_send_event(dev, IWEVCUSTOM, &uwrq, iwext);
- sprintf(ext, "OK");
- if (rtl8188_wakelock_init == 2)
- {
- wake_unlock(&rtl8188_suspend_lock);
- rtl8188_wakelock_init = 1;
- }
- break;
-
- //Return received signal strength indicator in dbm for current AP
- //<ssid> rssi xx
- case ANDROID_WIFI_CMD_RSSI :
- {
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct wlan_network *pcur_network = &pmlmepriv->cur_network;
-
- if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
- sprintf(ext, "WIFI rssi %d", padapter->recvpriv.rssi);
- //sprintf(ext, "%s rssi %d", pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
- } else {
- sprintf(ext, "OK");
- }
- }
- break;
-
- //Return link speed in MBPS
- //LinkSpeed xx
- case ANDROID_WIFI_CMD_LINKSPEED :
- {
- union iwreq_data wrqd;
- int ret_inner;
- int mbps;
-
- if( 0!=(ret_inner=rtw_wx_get_rate(dev, info, &wrqd, extra)) ){
- //DBG_8192C("rtw_wx_set_priv: (SIOCSIWPRIV) %s req=%s rtw_wx_get_rate return %d\n",
- //dev->name, ext, ret);
- //goto FREE_EXT;
- mbps=0;
- } else {
- mbps=wrqd.bitrate.value / 1000000;
- }
-
- sprintf(ext, "LINKSPEED %d", mbps);
- }
- break;
-
- //Return mac address of the station
- //Macaddr = xx:xx:xx:xx:xx:xx
- case ANDROID_WIFI_CMD_MACADDR :
- sprintf(ext, "MACADDR = " MAC_FMT, MAC_ARG(dev->dev_addr));
- break;
-
- //Set scan type to active
- //OK if successful
- case ANDROID_WIFI_CMD_SCAN_ACTIVE :
- {
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- pmlmepriv->scan_mode=SCAN_ACTIVE;
- sprintf(ext, "OK");
- }
- break;
-
- //Set scan type to passive
- //OK if successfu
- case ANDROID_WIFI_CMD_SCAN_PASSIVE :
- {
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- pmlmepriv->scan_mode=SCAN_PASSIVE;
- sprintf(ext, "OK");
- }
- break;
-
- case ANDROID_WIFI_CMD_COUNTRY :
- {
- char country_code[10];
- int channel_plan;
- union iwreq_data wrqd;
- int ret_inner;
-
- sscanf(ext,"%*s %s",country_code);
-
- if(0 == strcmp(country_code, "US"))
- channel_plan = RT_CHANNEL_DOMAIN_FCC;
- else if(0 == strcmp(country_code, "EU"))
- channel_plan = RT_CHANNEL_DOMAIN_ETSI;
- else if(0 == strcmp(country_code, "JP"))
- channel_plan = RT_CHANNEL_DOMAIN_MKK;
- else
- DBG_871X("%s unknown country_code:%s\n", __FUNCTION__, country_code);
- init_channel_plan = channel_plan;
-
- _rtw_memcpy(&wrqd, &channel_plan, sizeof(int));
-
- if( 0!=(ret_inner=rtw_wx_set_channel_plan(dev, info, &wrqd, extra)) ){
- DBG_871X("%s rtw_wx_set_channel_plan error\n", __FUNCTION__);
- }
-
- sprintf(ext, "OK");
- }
- break;
-
- case ANDROID_WIFI_CMD_SCAN_CHANNELS:
- {
- int current_channels = 11;
-
- //printk("GET: init_channel_plan = %d\n", init_channel_plan);
- if (init_channel_plan == 0)
- current_channels = 11;
- else if (init_channel_plan == 2)
- current_channels = 13;
- else if (init_channel_plan == 5)
- current_channels = 14;
-
- sprintf(ext, "Scan-Channels = %d", current_channels);
- printk("Get Channels return %d (init_channel_plan=%d)\n",
- current_channels, init_channel_plan);
-
- break;
- }
- default :
- #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
- DBG_871X("%s: %s unknowned req=%s\n", __FUNCTION__,
- dev->name, ext_dbg);
- #endif
-
- sprintf(ext, "OK");
-
- }
-
- if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext)+1)) ) )
- ret = -EFAULT;
-
- #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
- DBG_871X("%s: %s req=%s rep=%s dwrq->length=%d, strlen(ext)+1=%d\n", __FUNCTION__,
- dev->name, ext_dbg ,ext, dwrq->length, (u16)(strlen(ext)+1));
- #endif
-#endif //end of CONFIG_ANDROID
-
-
-FREE_EXT:
-
- rtw_vmfree(ext, len);
- #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
- rtw_vmfree(ext_dbg, len);
- #endif
-
- //DBG_871X("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret=%d\n",
- // dev->name, ret);
-
- return ret;
-
-}
-
-#if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_MP_IWPRIV_SUPPORT)
-
-/*
- * Input Format: %s,%d,%d
- * %s is width, could be
- * "b" for 1 byte
- * "w" for WORD (2 bytes)
- * "dw" for DWORD (4 bytes)
- * 1st %d is address(offset)
- * 2st %d is data to write
- */
-static int rtw_mp_write_reg(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- char *pch, *pnext, *ptmp;
- char *width_str;
- char width;
- u32 addr, data;
- int ret;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- pch = extra;
- pnext = strpbrk(pch, " ,.-");
- if (pnext == NULL) return -EINVAL;
- *pnext = 0;
- width_str = pch;
-
- pch = pnext + 1;
- pnext = strpbrk(pch, " ,.-");
- if (pnext == NULL) return -EINVAL;
- *pnext = 0;
- addr = simple_strtoul(pch, &ptmp, 16);
- if (addr > 0x3FFF) return -EINVAL;
-
- pch = pnext + 1;
- if ((pch - extra) >= wrqu->data.length) return -EINVAL;
- data = simple_strtoul(pch, &ptmp, 16);
-
- ret = 0;
- width = width_str[0];
- switch (width) {
- case 'b':
- // 1 byte
- if (data > 0xFF) {
- ret = -EINVAL;
- break;
- }
- rtw_write8(padapter, addr, data);
- break;
- case 'w':
- // 2 bytes
- if (data > 0xFFFF) {
- ret = -EINVAL;
- break;
- }
- rtw_write16(padapter, addr, data);
- break;
- case 'd':
- // 4 bytes
- rtw_write32(padapter, addr, data);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-/*
- * Input Format: %s,%d
- * %s is width, could be
- * "b" for 1 byte
- * "w" for WORD (2 bytes)
- * "dw" for DWORD (4 bytes)
- * %d is address(offset)
- *
- * Return:
- * %d for data readed
- */
-static int rtw_mp_read_reg(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- char input[128];
- char *pch, *pnext, *ptmp;
- char *width_str;
- char width;
- u32 addr;
- u32 *data = (u32*)extra;
- int ret;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- if (wrqu->data.length > 128) return -EFAULT;
- if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- pch = input;
- pnext = strpbrk(pch, " ,.-");
- if (pnext == NULL) return -EINVAL;
- *pnext = 0;
- width_str = pch;
-
- pch = pnext + 1;
- if ((pch - input) >= wrqu->data.length) return -EINVAL;
- addr = simple_strtoul(pch, &ptmp, 16);
- if (addr > 0x3FFF) return -EINVAL;
-
- ret = 0;
- width = width_str[0];
- switch (width) {
- case 'b':
- // 1 byte
- *(u8*)data = rtw_read8(padapter, addr);
- wrqu->data.length = 1;
- break;
- case 'w':
- // 2 bytes
- *(u16*)data = rtw_read16(padapter, addr);
- wrqu->data.length = 2;
- break;
- case 'd':
- // 4 bytes
- *data = rtw_read32(padapter, addr);
- wrqu->data.length = 4;
- break;
- default:
- wrqu->data.length = 0;
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-/*
- * Input Format: %d,%x,%x
- * %d is RF path, should be smaller than MAX_RF_PATH_NUMS
- * 1st %x is address(offset)
- * 2st %x is data to write
- */
-static int rtw_mp_write_rf(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u32 path, addr, data;
- int ret;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- ret = sscanf(extra, "%d,%x,%x", &path, &addr, &data);
- if (ret < 3) return -EINVAL;
-
- if (path >= MAX_RF_PATH_NUMS) return -EINVAL;
- if (addr > 0xFF) return -EINVAL;
- if (data > 0xFFFFF) return -EINVAL;
-
- write_rfreg(padapter, path, addr, data);
-
- return 0;
-}
-
-/*
- * Input Format: %d,%x
- * %d is RF path, should be smaller than MAX_RF_PATH_NUMS
- * %x is address(offset)
- *
- * Return:
- * %d for data readed
- */
-static int rtw_mp_read_rf(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- char input[128];
- u32 path, addr;
- u32 *data = (u32*)extra;
- int ret;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- if (wrqu->data.length > 128) return -EFAULT;
- if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- ret = sscanf(input, "%d,%x", &path, &addr);
- if (ret < 2) return -EINVAL;
-
- if (path >= MAX_RF_PATH_NUMS) return -EINVAL;
- if (addr > 0xFF) return -EINVAL;
-
- *data = read_rfreg(padapter, path, addr);
- wrqu->data.length = 4;
-
- return 0;
-}
-
-static int rtw_mp_start(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 val8;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- if (padapter->registrypriv.mp_mode == 0)
- return -EPERM;
-
- if (padapter->mppriv.mode == MP_OFF) {
- if (mp_start_test(padapter) == _FAIL)
- return -EPERM;
- padapter->mppriv.mode = MP_ON;
- }
-
- return 0;
-}
-
-static int rtw_mp_stop(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- if (padapter->mppriv.mode != MP_OFF) {
- mp_stop_test(padapter);
- padapter->mppriv.mode = MP_OFF;
- }
-
- return 0;
-}
-
-extern int wifirate2_ratetbl_inx(unsigned char rate);
-
-static int rtw_mp_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u32 rate = MPT_RATE_1M;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
- rate = *(u32*)extra;
-
- if(rate <= 0x7f)
- rate = wifirate2_ratetbl_inx( (u8)rate);
- else
- rate =(rate-0x80+MPT_RATE_MCS0);
-
- //DBG_8192C("%s: rate=%d\n", __func__, rate);
-
- if (rate >= MPT_RATE_LAST )
- return -EINVAL;
-
- padapter->mppriv.rateidx = rate;
- Hal_SetDataRate(padapter);
-
- return 0;
-}
-
-static int rtw_mp_channel(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u32 channel = 1;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
- channel = *(u32*)extra;
- //DBG_8192C("%s: channel=%d\n", __func__, channel);
-
- //if (channel > 14)
- // return -EINVAL;
-
- padapter->mppriv.channel = channel;
- Hal_SetChannel(padapter);
-
- return 0;
-}
-
-static int rtw_mp_bandwidth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u32 bandwidth=0, sg=0;
- u8 buffer[40];
- PADAPTER padapter = rtw_netdev_priv(dev);
- if (copy_from_user(buffer, (void*)wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
- //DBG_8192C("%s:iwpriv in=%s\n", __func__, extra);
-
- sscanf(buffer, "40M=%d,shortGI=%d", &bandwidth, &sg);
-
- if (bandwidth != HT_CHANNEL_WIDTH_40)
- bandwidth = HT_CHANNEL_WIDTH_20;
-
- //DBG_8192C("%s: bw=%d sg=%d \n", __func__, bandwidth , sg);
- padapter->mppriv.bandwidth = (u8)bandwidth;
- padapter->mppriv.preamble = sg;
-
- SetBandwidth(padapter);
-
- return 0;
-}
-
-static int rtw_mp_txpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 buffer[40];
- u32 idx_a,idx_b;
-
-
- PADAPTER padapter = rtw_netdev_priv(dev);
- if (copy_from_user(buffer, (void*)wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- sscanf(buffer,"patha=%d,pathb=%d",&idx_a,&idx_b);
- //DBG_8192C("%s: tx_pwr_idx_a=%x b=%x\n", __func__, idx_a, idx_b);
-
- padapter->mppriv.txpoweridx = (u8)idx_a;
- padapter->mppriv.txpoweridx_b = (u8)idx_b;
-
- Hal_SetAntennaPathPower(padapter);
-
- return 0;
-}
-
-static int rtw_mp_ant_tx(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 i;
- u16 antenna = 0;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
- //DBG_8192C("%s: extra=%s\n", __func__, extra);
- for (i=0; i < (wrqu->data.length-1); i++){
- switch(extra[i])
- {
- case 'a' :
- antenna|=ANTENNA_A;
- break;
- case 'b':
- antenna|=ANTENNA_B;
- break;
- }
- }
- //antenna |= BIT(extra[i]-'a');
-
- //DBG_8192C("%s: antenna=0x%x\n", __func__, antenna);
- padapter->mppriv.antenna_tx = antenna;
- //DBG_8192C("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_tx);
-
- Hal_SetAntenna(padapter);
- return 0;
-}
-
-static int rtw_mp_ant_rx(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 i;
- u16 antenna = 0;
- u8 buffer[16];
- PADAPTER padapter = rtw_netdev_priv(dev);
-
- if (copy_from_user(buffer, (void*)wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
- //DBG_8192C("%s: extra=%s\n", __func__, buffer);
-
- for (i=0; i < strlen(buffer); i++) {
-
- switch(buffer[i])
- {
- case 'a' :
- antenna|=ANTENNA_A;
- break;
- case 'b':
- antenna|=ANTENNA_B;
- break;
- }
- }
-
- //DBG_8192C("%s: antenna=0x%x\n", __func__, antenna);
- padapter->mppriv.antenna_rx = antenna;
- //DBG_8192C("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_rx);
-
- Hal_SetAntenna(padapter);
-
- return 0;
-}
-
-static int rtw_mp_ctx(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
- u32 bStartTest = 1;
- u32 count = 0;
- u8 buffer[40];
- struct mp_priv *pmp_priv;
- struct pkt_attrib *pattrib;
-
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- pmp_priv = &padapter->mppriv;
-
- if (copy_from_user(buffer, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
- DBG_8192C("%s: in=%s\n", __func__, buffer);
-
- countPkTx = strncmp(buffer, "count=", 5); // strncmp TRUE is 0
- cotuTx = strncmp(buffer, "background", 20);
- CarrSprTx = strncmp(buffer, "background,cs", 20);
- scTx = strncmp(buffer, "background,sc", 20);
- sgleTx = strncmp(buffer, "background,stone", 20);
- pkTx = strncmp(buffer, "background,pkt", 20);
- stop = strncmp(buffer, "stop", 5);
- sscanf(buffer, "count=%d,pkt", &count);
- //DBG_8192C("%s: count=%d countPkTx=%d cotuTx=%d CarrSprTx=%d scTx=%d sgleTx=%d pkTx=%d stop=%d\n", __func__, count, countPkTx, cotuTx, CarrSprTx, pkTx, sgleTx, scTx, stop);
-
- if (stop == 0) {
- bStartTest = 0; // To set Stop
- pmp_priv->tx.stop = 1;
- } else {
- bStartTest = 1;
- if (pmp_priv->mode != MP_ON) {
- if (pmp_priv->tx.stop != 1) {
- DBG_8192C("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
- return -EFAULT;
- }
- }
- }
-
- if (pkTx == 0 || countPkTx == 0)
- pmp_priv->mode = MP_PACKET_TX;
- if (sgleTx == 0)
- pmp_priv->mode = MP_SINGLE_TONE_TX;
- if (cotuTx == 0)
- pmp_priv->mode = MP_CONTINUOUS_TX;
- if (CarrSprTx == 0)
- pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
- if (scTx == 0)
- pmp_priv->mode = MP_SINGLE_CARRIER_TX;
-
- switch (pmp_priv->mode)
- {
- case MP_PACKET_TX:
- //DBG_8192C("%s:pkTx %d\n", __func__,bStartTest);
- if (bStartTest == 0) {
- pmp_priv->tx.stop = 1;
- pmp_priv->mode = MP_ON;
- } else if (pmp_priv->tx.stop == 1) {
- //DBG_8192C("%s:countPkTx %d\n", __func__,count);
- pmp_priv->tx.stop = 0;
- pmp_priv->tx.count = count;
- pmp_priv->tx.payload = 2;
- pattrib = &pmp_priv->tx.attrib;
- pattrib->pktlen = 1000;
- _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
- SetPacketTx(padapter);
- } else {
- //DBG_8192C("%s: pkTx not stop\n", __func__);
- return -EFAULT;
- }
- return 0;
-
- case MP_SINGLE_TONE_TX:
- //DBG_8192C("%s: sgleTx %d \n", __func__, bStartTest);
- Hal_SetSingleToneTx(padapter, (u8)bStartTest);
- break;
-
- case MP_CONTINUOUS_TX:
- //DBG_8192C("%s: cotuTx %d\n", __func__, bStartTest);
- Hal_SetContinuousTx(padapter, (u8)bStartTest);
- break;
-
- case MP_CARRIER_SUPPRISSION_TX:
- //DBG_8192C("%s: CarrSprTx %d\n", __func__, bStartTest);
- Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
- break;
-
- case MP_SINGLE_CARRIER_TX:
- //DBG_8192C("%s: scTx %d\n", __func__, bStartTest);
- Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
- break;
-
- default:
- //DBG_8192C("%s:No Match MP_MODE\n", __func__);
- return -EFAULT;
- }
-
- if (bStartTest) {
- struct mp_priv *pmp_priv = &padapter->mppriv;
- if (pmp_priv->tx.stop == 0) {
- pmp_priv->tx.stop = 1;
- //DBG_8192C("%s: pkt tx is running...\n", __func__);
- rtw_msleep_os(5);
- }
- pmp_priv->tx.stop = 0;
- pmp_priv->tx.count = 1;
- SetPacketTx(padapter);
- } else {
- pmp_priv->mode = MP_ON;
- }
-
- return 0;
-}
-
-static int rtw_mp_arx(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 bStartRx=0;
- PADAPTER padapter = rtw_netdev_priv(dev);
- u8 buffer[40];
-
- if (copy_from_user(buffer, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- //DBG_8192C("%s: %s\n", __func__, buffer);
-
- bStartRx = (strncmp(buffer, "start", 5)==0)?1:0; // strncmp TRUE is 0
-
- SetPacketRx(padapter, bStartRx);
-
- return 0;
-}
-
-static int rtw_mp_trx_query(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u32 txok,txfail,rxok,rxfail;
- PADAPTER padapter = rtw_netdev_priv(dev);
- if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- txok=padapter->mppriv.tx.sended;
- txfail=0;
- rxok = padapter->mppriv.rx_pktcount;
- rxfail = padapter->mppriv.rx_crcerrpktcount;
-
- _rtw_memset(extra, '\0', 128);
-
- sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ", txok, txfail,rxok,rxfail);
-
- wrqu->data.length=strlen(extra)+1;
-
- return 0;
-}
-
-static int rtw_mp_pwrtrk(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 enable;
- u32 thermal;
- s32 ret;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- enable = 1;
- if (wrqu->data.length > 1) { // not empty string
- if (strncmp(extra, "stop", 4) == 0)
- enable = 0;
- else {
- if (sscanf(extra, "ther=%d", &thermal)) {
- ret = Hal_SetThermalMeter(padapter, (u8)thermal);
- if (ret == _FAIL) return -EPERM;
- } else
- return -EINVAL;
- }
- }
-
- ret = Hal_SetPowerTracking(padapter, enable);
- if (ret == _FAIL) return -EPERM;
-
- return 0;
-}
-
-static int rtw_mp_psd(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- wrqu->data.length = mp_query_psd(padapter, extra);
-
- return 0;
-}
-
-static int rtw_mp_thermal(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 val;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
-
- Hal_GetThermalMeter(padapter, &val);
- *(u8*)extra = val;
- wrqu->data.length = 1;
-
- return 0;
-}
-
-static int rtw_mp_reset_stats(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct mp_priv *pmp_priv;
- struct pkt_attrib *pattrib;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
- pmp_priv = &padapter->mppriv;
-
- pmp_priv->tx.sended = 0;
- padapter->mppriv.rx_pktcount = 0;
- padapter->mppriv.rx_crcerrpktcount = 0;
-
- return 0;
-}
-
-static int rtw_mp_dump(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct mp_priv *pmp_priv;
- struct pkt_attrib *pattrib;
- u32 value;
- u8 rf_type,path_nums = 0;
- u32 i,j=1,path;
- PADAPTER padapter = rtw_netdev_priv(dev);
-
- pmp_priv = &padapter->mppriv;
-
-
- if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- if ( strncmp(extra, "all", 4)==0 )
- {
- printk("\n======= MAC REG =======\n");
- for ( i=0x0;i<0x300;i+=4 )
- {
- if(j%4==1) printk("0x%02x",i);
- printk(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) printk("\n");
- }
- for( i=0x400;i<0x800;i+=4 )
- {
- if(j%4==1) printk("0x%02x",i);
- printk(" 0x%08x ",rtw_read32(padapter,i));
- if((j++)%4 == 0) printk("\n");
- }
-
- i,j=1;
- padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-
- printk("\n======= RF REG =======\n");
- if(( RF_1T2R == rf_type ) ||( RF_1T1R ==rf_type ))
- path_nums = 1;
- else
- path_nums = 2;
-
- for(path=0;path<path_nums;path++)
- {
-#ifdef CONFIG_RTL8192D
- for (i = 0; i < 0x50; i++)
-#else
- for (i = 0; i < 0x34; i++)
-#endif
- {
- //value = PHY_QueryRFReg(padapter, (RF90_RADIO_PATH_E)path,i, bMaskDWord);
- value =padapter->HalFunc.read_rfreg(padapter, path, i, 0xffffffff);
- if(j%4==1) printk("0x%02x ",i);
- printk(" 0x%08x ",value);
- if((j++)%4==0) printk("\n");
- }
- }
- }
- return 0;
-}
-#endif
-
-static int rtw_mp_efuse_get(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- PADAPTER padapter = rtw_netdev_priv(dev);
- struct mp_priv *pmp_priv;
-
- int i,j =0;
- u8 data[EFUSE_MAP_SIZE];
- u8 rawdata[EFUSE_MAX_SIZE];
- u16 mapLen=0;
- char *pch, *ptmp, *token, *tmp[3]={0x00,0x00,0x00};
- u16 addr = 0, cnts = 0, max_available_size = 0,raw_cursize = 0 ,raw_maxsize = 0;
-
- _rtw_memset(data, '\0', sizeof(data));
- _rtw_memset(rawdata, '\0', sizeof(rawdata));
-
- if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
- return -EFAULT;
-
- pch = extra;
- DBG_8192C("%s: in=%s\n", __func__, extra);
-
- i=0;
- //mac 16 "00e04c871200" rmap,00,2
- while ( (token = strsep (&pch,",") )!=NULL )
- {
- if(i>2) break;
- tmp[i] = token;
- i++;
- }
-
- if ( strcmp(tmp[0],"realmap") == 0 ) {
-
- DBG_8192C("strcmp OK = %s \n" ,tmp[0]);
-
- mapLen = EFUSE_MAP_SIZE;
-
- if (rtw_efuse_map_read(padapter, 0, mapLen, data) == _SUCCESS){
- DBG_8192C("\t rtw_efuse_map_read \n");
- }else {
- DBG_8192C("\t rtw_efuse_map_read : Fail \n");
- return -EFAULT;
- }
- _rtw_memset(extra, '\0', sizeof(extra));
- DBG_8192C("\tOFFSET\tVALUE(hex)\n");
- sprintf(extra, "%s \n", extra);
- for ( i = 0; i < EFUSE_MAP_SIZE; i += 16 )
- {
- DBG_8192C("\t0x%02x\t", i);
- sprintf(extra, "%s \t0x%02x\t", extra,i);
- for (j = 0; j < 8; j++)
- {
- DBG_8192C("%02X ", data[i+j]);
- sprintf(extra, "%s %02X", extra, data[i+j]);
- }
- DBG_8192C("\t");
- sprintf(extra,"%s\t",extra);
- for (; j < 16; j++){
- DBG_8192C("%02X ", data[i+j]);
- sprintf(extra, "%s %02X", extra, data[i+j]);
- }
- DBG_8192C("\n");
- sprintf(extra,"%s\n",extra);
- }
- DBG_8192C("\n");
- wrqu->data.length = strlen(extra);
-
- return 0;
- }
- else if ( strcmp(tmp[0],"rmap") == 0 ) {
- if ( tmp[1]==NULL || tmp[2]==NULL ) return -EINVAL;
- // rmap addr cnts
- addr = simple_strtoul(tmp[1], &ptmp, 16);
-
- DBG_8192C("addr = %x \n" ,addr);
-
- cnts=simple_strtoul(tmp[2], &ptmp,10);
- if(cnts==0) return -EINVAL;
-
- DBG_8192C("cnts = %d \n" ,cnts);
- //_rtw_memset(extra, '\0', wrqu->data.length);
-
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
- if ((addr + cnts) > max_available_size) {
- DBG_8192C("(addr + cnts parameter error \n");
- return -EFAULT;
- }
-
- if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL)
- {
- DBG_8192C("rtw_efuse_access error \n");
- }
- else{
- DBG_8192C("rtw_efuse_access ok \n");
- }
-
- _rtw_memset(extra, '\0', sizeof(extra));
- for ( i = 0; i < cnts; i ++) {
- DBG_8192C("0x%02x", data[i]);
- sprintf(extra, "%s 0x%02X", extra, data[i]);
- DBG_8192C(" ");
- sprintf(extra,"%s ",extra);
- }
-
- wrqu->data.length = strlen(extra)+1;
-
- DBG_8192C("extra = %s ", extra);
-
- return 0;
- }
- else if ( strcmp(tmp[0],"realraw") == 0 ) {
- addr=0;
- mapLen = EFUSE_MAX_SIZE;
-
- if (rtw_efuse_access(padapter, _FALSE, addr, mapLen, rawdata) == _FAIL)
- {
- DBG_8192C("\t rtw_efuse_map_read : Fail \n");
- return -EFAULT;
- } else
- {
- DBG_8192C("\t rtw_efuse_access raw ok \n");
- }
-
- _rtw_memset(extra, '\0', sizeof(extra));
- for ( i=0; i<mapLen; i++ ) {
- DBG_8192C(" %02x", rawdata[i]);
- sprintf(extra, "%s %02x", extra, rawdata[i] );
-
- if ((i & 0xF) == 0xF){
- DBG_8192C("\n\t");
- sprintf(extra, "%s\n\t", extra);
- }
- else if ((i & 0x7) == 0x7){
- DBG_8192C("\t");
- sprintf(extra, "%s\t", extra);
- }
- }
- wrqu->data.length = strlen(extra);
- return 0;
- }
- else if ( strcmp(tmp[0],"mac") == 0 ) {
- if ( tmp[1]==NULL || tmp[2]==NULL ) return -EINVAL;
- #ifdef CONFIG_RTL8192C
- addr = 0x16;
- cnts = 6;
- #endif
- #ifdef CONFIG_RTL8192D
- addr = 0x19;
- cnts = 6;
- #endif
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
- if ((addr + mapLen) > max_available_size) {
- DBG_8192C("(addr + cnts parameter error \n");
- return -EFAULT;
- }
- if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL)
- {
- DBG_8192C("rtw_efuse_access error \n");
- }
- else{
- DBG_8192C("rtw_efuse_access ok \n");
- }
- _rtw_memset(extra, '\0', sizeof(extra));
- for ( i = 0; i < cnts; i ++) {
- DBG_8192C("0x%02x", data[i]);
- sprintf(extra, "%s 0x%02X", extra, data[i+j]);
- DBG_8192C(" ");
- sprintf(extra,"%s ",extra);
- }
- wrqu->data.length = strlen(extra);
- return 0;
- }
- else if ( strcmp(tmp[0],"vidpid") == 0 ) {
- if ( tmp[1]==NULL || tmp[2]==NULL ) return -EINVAL;
- #ifdef CONFIG_RTL8192C
- addr=0x0a;
- #endif
- #ifdef CONFIG_RTL8192D
- addr = 0x0c;
- #endif
- cnts = 4;
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
- if ((addr + mapLen) > max_available_size) {
- DBG_8192C("(addr + cnts parameter error \n");
- return -EFAULT;
- }
- if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL)
- {
- DBG_8192C("rtw_efuse_access error \n");
- }
- else{
- DBG_8192C("rtw_efuse_access ok \n");
- }
- _rtw_memset(extra, '\0', sizeof(extra));
- for ( i = 0; i < cnts; i ++) {
- DBG_8192C("0x%02x", data[i]);
- sprintf(extra, "%s 0x%02X", extra, data[i+j]);
- DBG_8192C(" ");
- sprintf(extra,"%s ",extra);
- }
- wrqu->data.length = strlen(extra);
- return 0;
- }
- else if ( strcmp(tmp[0],"ableraw") == 0 ) {
- efuse_GetCurrentSize(padapter,&raw_cursize);
- raw_maxsize = efuse_GetMaxSize(padapter);
- sprintf(extra, "%s : [ available raw size] = %d",extra,raw_maxsize-raw_cursize);
- wrqu->data.length = strlen(extra);
-
- return 0;
- }else
- {
- sprintf(extra, "%s : Command not found\n",extra);
- wrqu->data.length = strlen(extra);
- return 0;
- }
-
- return 0;
-}
-
-static int rtw_mp_efuse_set(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- PADAPTER padapter = rtw_netdev_priv(dev);
-
- u8 buffer[40];
- u32 i,jj,kk;
- u8 setdata[EFUSE_MAP_SIZE];
- u8 setrawdata[EFUSE_MAX_SIZE];
- char *pch, *ptmp, *token, *edata,*tmp[3]={0x00,0x00,0x00};
-
- u16 addr = 0, max_available_size = 0;
- u32 cnts = 0;
-
- pch = extra;
- DBG_8192C("%s: in=%s\n", __func__, extra);
-
- i=0;
- while ( (token = strsep (&pch,",") )!=NULL )
- {
- if(i>2) break;
- tmp[i] = token;
- i++;
- }
-
- // tmp[0],[1],[2]
- // wmap,addr,00e04c871200
- if ( strcmp(tmp[0],"wmap") == 0 ) {
- if ( tmp[1]==NULL || tmp[2]==NULL ) return -EINVAL;
- if ( ! strlen( tmp[2] )/2 > 1 ) return -EFAULT;
-
- addr = simple_strtoul( tmp[1], &ptmp, 16 );
- addr = addr & 0xFF;
- DBG_8192C("addr = %x \n" ,addr);
-
- cnts = strlen( tmp[2] )/2;
- if ( cnts == 0) return -EFAULT;
-
- DBG_8192C("cnts = %d \n" ,cnts);
- DBG_8192C("target data = %s \n" ,tmp[2]);
-
- for( jj = 0, kk = 0; jj < cnts; jj++, kk += 2 )
- {
- setdata[jj] = key_2char2num( tmp[2][kk], tmp[2][kk+ 1] );
- }
-
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
-
- if ((addr + cnts) > max_available_size) {
- DBG_8192C("parameter error \n");
- return -EFAULT;
- }
- if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
- DBG_8192C("rtw_efuse_map_write error \n");
- return -EFAULT;
- } else
- DBG_8192C("rtw_efuse_map_write ok \n");
-
- return 0;
- }
- else if ( strcmp(tmp[0],"wraw") == 0 ) {
- if ( tmp[1]==NULL || tmp[2]==NULL ) return -EINVAL;
- if ( ! strlen( tmp[2] )/2 > 1 ) return -EFAULT;
- addr = simple_strtoul( tmp[1], &ptmp, 16 );
- addr = addr & 0xFF;
- DBG_8192C("addr = %x \n" ,addr);
-
- cnts=strlen( tmp[2] )/2;
- if ( cnts == 0) return -EFAULT;
-
- DBG_8192C(" cnts = %d \n" ,cnts );
- DBG_8192C("target data = %s \n" ,tmp[2] );
-
- for( jj = 0, kk = 0; jj < cnts; jj++, kk += 2 )
- {
- setrawdata[jj] = key_2char2num( tmp[2][kk], tmp[2][kk+ 1] );
- }
-
- if ( rtw_efuse_access( padapter, _TRUE, addr, cnts, setrawdata ) == _FAIL ){
- DBG_8192C("\t rtw_efuse_map_read : Fail \n");
- return -EFAULT;
- } else
- DBG_8192C("\t rtw_efuse_access raw ok \n");
-
- return 0;
- }
- else if ( strcmp(tmp[0],"mac") == 0 ) {
- if ( tmp[1]==NULL || tmp[2]==NULL ) return -EINVAL;
- //mac,00e04c871200
- #ifdef CONFIG_RTL8192C
- addr = 0x16;
- #endif
- #ifdef CONFIG_RTL8192D
- addr = 0x19;
- #endif
- cnts = strlen( tmp[1] )/2;
- if ( cnts == 0) return -EFAULT;
- if ( cnts > 6 ){
- DBG_8192C("error data for mac addr = %s \n" ,tmp[1]);
- return -EFAULT;
- }
-
- DBG_8192C("target data = %s \n" ,tmp[1]);
-
- for( jj = 0, kk = 0; jj < cnts; jj++, kk += 2 )
- {
- setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk+ 1]);
- }
-
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
-
- if ((addr + cnts) > max_available_size) {
- DBG_8192C("parameter error \n");
- return -EFAULT;
- }
- if ( rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL ) {
- DBG_8192C("rtw_efuse_map_write error \n");
- return -EFAULT;
- } else
- DBG_8192C("rtw_efuse_map_write ok \n");
-
- return 0;
- }
- else if ( strcmp(tmp[0],"vidpid") == 0 ) {
- if ( tmp[1]==NULL || tmp[2]==NULL ) return -EINVAL;
- // pidvid,da0b7881
- #ifdef CONFIG_RTL8192C
- addr=0x0a;
- #endif
- #ifdef CONFIG_RTL8192D
- addr = 0x0c;
- #endif
-
- cnts=strlen( tmp[1] )/2;
- if ( cnts == 0) return -EFAULT;
- DBG_8192C("target data = %s \n" ,tmp[1]);
-
- for( jj = 0, kk = 0; jj < cnts; jj++, kk += 2 )
- {
- setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk+ 1]);
- }
-
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
-
- if ((addr + cnts) > max_available_size) {
- DBG_8192C("parameter error \n");
- return -EFAULT;
- }
-
- if ( rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL ) {
- DBG_8192C("rtw_efuse_map_write error \n");
- return -EFAULT;
- } else
- DBG_8192C("rtw_efuse_map_write ok \n");
-
- return 0;
- }
- else{
- printk("Command not found\n");
- return 0;
- }
-
- return 0;
-}
-
-static int rtw_tdls_setup(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
-
-#ifdef CONFIG_TDLS
-
- u8 i;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- u8 mac_addr[ETH_ALEN];
-
- DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
-
- for(i=0; i < ETH_ALEN; i++){
- mac_addr[i]=key_2char2num(*(extra+2*i), *(extra+2*i+1));
- }
-
- issue_tdls_setup_req(padapter, mac_addr);
-
-#endif
-
- return ret;
-}
-
-
-static int rtw_tdls_teardown(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
-
-#ifdef CONFIG_TDLS
-
- u8 i;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- u8 mac_addr[ETH_ALEN];
-
- DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
-
- for(i=0; i < ETH_ALEN; i++){
- mac_addr[i]=key_2char2num(*(extra+2*i), *(extra+2*i+1));
-
- }
-
- issue_tdls_teardown(padapter, mac_addr);
-
-#endif
-
- return ret;
-}
-
-
-static int rtw_tdls_discovery(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
-
-#ifdef CONFIG_TDLS
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-
- DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
-
- if(*extra=='0')
- pmlmeinfo->tdls_dis_req=0;
- else if(*extra=='1')
- pmlmeinfo->tdls_dis_req=1;
-
-#endif
-
- return ret;
-}
-
-static int rtw_tdls_ch_switch(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
-
-#ifdef CONFIG_TDLS
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 i, mac_addr[ETH_ALEN];
- struct sta_info *ptdls_sta = NULL;
-
- DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
-
- if(*extra=='o' && *(extra+1)=='n'){
- pmlmeinfo->tdls_ch_sensing=1;
- return ret;
- }
-
- for(i=0; i < ETH_ALEN; i++){
- mac_addr[i]=key_2char2num(*(extra+2*i), *(extra+2*i+1));
-
- }
- pmlmeinfo->tdls_ch_sensing=1;
- ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
- ptdls_sta->option=4;
- _set_workitem(&ptdls_sta->option_workitem);
-
-#endif
-
- return ret;
-}
-static int rtw_tdls_ch_switch_off(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
-
-#ifdef CONFIG_TDLS
-
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 i, mac_addr[ETH_ALEN];
- struct sta_info *ptdls_sta = NULL;
-
- DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
-
- for(i=0; i < ETH_ALEN; i++){
- mac_addr[i]=key_2char2num(*(extra+2*i), *(extra+2*i+1));
-
- }
-
- ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
-
- ptdls_sta->state |= TDLS_SW_OFF_STATE;
-/*
- if((ptdls_sta->state & TDLS_AT_OFF_CH_STATE) && (ptdls_sta->state & TDLS_PEER_AT_OFF_STATE)){
- pmlmeinfo->tdls_candidate_ch= pmlmeext->cur_channel;
- issue_tdls_ch_switch_req(padapter, mac_addr);
- DBG_8192C("issue tdls ch switch req back to base channel\n");
- }
-*/
-
-#endif
-
- return ret;
-}
-
-static int rtw_tdls(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
-
-#ifdef CONFIG_TDLS
-
- DBG_8192C( "[%s] extra = %s\n", __FUNCTION__, extra );
-
- if ( _rtw_memcmp( extra, "setup=", 6 ) )
- {
- wrqu->data.length -=6;
- rtw_tdls_setup( dev, info, wrqu, &extra[6] );
- }
- else if (_rtw_memcmp( extra, "tear=", 5 ) )
- {
- wrqu->data.length -= 5;
- rtw_tdls_teardown( dev, info, wrqu, &extra[5] );
- }
- else if (_rtw_memcmp( extra, "dis=", 4 ) )
- {
- wrqu->data.length -= 4;
- rtw_tdls_discovery( dev, info, wrqu, &extra[4] );
- }
- else if (_rtw_memcmp( extra, "sw=", 3 ) )
- {
- wrqu->data.length -= 3;
- rtw_tdls_ch_switch( dev, info, wrqu, &extra[3] );
- }
- else if (_rtw_memcmp( extra, "swoff=", 6 ) )
- {
- wrqu->data.length -= 6;
- rtw_tdls_ch_switch_off( dev, info, wrqu, &extra[6] );
- }
-#endif
-
- return ret;
-}
-
-
-static int rtw_pm_set_lps(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
- u8 mode = 0;
-
- switch( wrqu->data.length -1 )
- {
- case 1:
- {
- mode = extra[ 0 ] - '0';
- break;
- }
- case 2:
- {
- mode = str_2char2num( extra[ 0 ], extra[ 1 ]);
- break;
- }
- }
-
- if ( mode < PS_MODE_NUM )
- {
- if(pwrctrlpriv->power_mgnt !=mode)
- {
- if(PS_MODE_ACTIVE == mode)
- {
- LeaveAllPowerSaveMode(padapter);
- }
- else
- {
- pwrctrlpriv->LpsIdleCount = 2;
- }
- pwrctrlpriv->power_mgnt = mode;
- pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?_TRUE:_FALSE;
- }
- }
- else
- {
- ret = -1;
- }
-
- return ret;
-
-}
-
-static int rtw_pm_set_ips(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- _adapter *padapter = rtw_netdev_priv(dev);
- struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
- unsigned mode = 0;
-
- sscanf(extra, "%u", &mode);
-
- if( mode == IPS_NORMAL || mode == IPS_LEVEL_2 ) {
- rtw_ips_mode_req(pwrctrlpriv, mode);
- pwrctrlpriv->power_mgnt = PS_MODE_MIN;
- rtw_set_pwr_state_check_timer(pwrctrlpriv);
- DBG_871X("%s %s\n", __FUNCTION__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
- return 0;
- }
- else if(mode ==IPS_NONE){
- if(_FAIL == rfpwrstate_check(padapter))
- {
- return -EFAULT;
- }
- pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE;
- }
- else {
- return -EFAULT;
- }
- return 0;
-}
-
-static int rtw_pm_set(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
-
- DBG_8192C( "[%s] extra = %s\n", __FUNCTION__, extra );
-
- if ( _rtw_memcmp( extra, "lps=", 4 ) )
- {
- wrqu->data.length -= 4;
- rtw_pm_set_lps( dev, info, wrqu, &extra[4] );
- }
- if ( _rtw_memcmp( extra, "ips=", 4 ) )
- {
- wrqu->data.length -= 4;
- rtw_pm_set_ips(dev, info, wrqu, &extra[4]);
- }
-
- return ret;
-}
-
-
-//based on "driver_ipw" and for hostapd
-int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iwreq *wrq = (struct iwreq *)rq;
- int ret=0;
-
- //down(&priv->wx_sem);
-
- switch (cmd)
- {
- case RTL_IOCTL_WPA_SUPPLICANT:
- ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
- break;
-#ifdef CONFIG_AP_MODE
- case RTL_IOCTL_HOSTAPD:
- ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
- break;
-#endif
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
- //up(&priv->wx_sem);
-
- return ret;
-
-}
-
-static iw_handler rtw_handlers[] =
-{
- NULL, /* SIOCSIWCOMMIT */
- rtw_wx_get_name, /* SIOCGIWNAME */
- dummy, /* SIOCSIWNWID */
- dummy, /* SIOCGIWNWID */
- rtw_wx_set_freq, /* SIOCSIWFREQ */
- rtw_wx_get_freq, /* SIOCGIWFREQ */
- rtw_wx_set_mode, /* SIOCSIWMODE */
- rtw_wx_get_mode, /* SIOCGIWMODE */
- dummy, /* SIOCSIWSENS */
- rtw_wx_get_sens, /* SIOCGIWSENS */
- NULL, /* SIOCSIWRANGE */
- rtw_wx_get_range, /* SIOCGIWRANGE */
- rtw_wx_set_priv, /* SIOCSIWPRIV */
- NULL, /* SIOCGIWPRIV */
- NULL, /* SIOCSIWSTATS */
- NULL, /* SIOCGIWSTATS */
- dummy, /* SIOCSIWSPY */
- dummy, /* SIOCGIWSPY */
- NULL, /* SIOCGIWTHRSPY */
- NULL, /* SIOCWIWTHRSPY */
- rtw_wx_set_wap, /* SIOCSIWAP */
- rtw_wx_get_wap, /* SIOCGIWAP */
- rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */
- dummy, /* SIOCGIWAPLIST -- depricated */
- rtw_wx_set_scan, /* SIOCSIWSCAN */
- rtw_wx_get_scan, /* SIOCGIWSCAN */
- rtw_wx_set_essid, /* SIOCSIWESSID */
- rtw_wx_get_essid, /* SIOCGIWESSID */
- dummy, /* SIOCSIWNICKN */
- rtw_wx_get_nick, /* SIOCGIWNICKN */
- NULL, /* -- hole -- */
- NULL, /* -- hole -- */
- rtw_wx_set_rate, /* SIOCSIWRATE */
- rtw_wx_get_rate, /* SIOCGIWRATE */
- dummy, /* SIOCSIWRTS */
- rtw_wx_get_rts, /* SIOCGIWRTS */
- rtw_wx_set_frag, /* SIOCSIWFRAG */
- rtw_wx_get_frag, /* SIOCGIWFRAG */
- dummy, /* SIOCSIWTXPOW */
- dummy, /* SIOCGIWTXPOW */
- dummy, /* SIOCSIWRETRY */
- rtw_wx_get_retry, /* SIOCGIWRETRY */
- rtw_wx_set_enc, /* SIOCSIWENCODE */
- rtw_wx_get_enc, /* SIOCGIWENCODE */
- dummy, /* SIOCSIWPOWER */
- rtw_wx_get_power, /* SIOCGIWPOWER */
- NULL, /*---hole---*/
- NULL, /*---hole---*/
- rtw_wx_set_gen_ie, /* SIOCSIWGENIE */
- NULL, /* SIOCGWGENIE */
- rtw_wx_set_auth, /* SIOCSIWAUTH */
- NULL, /* SIOCGIWAUTH */
- rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
- NULL, /* SIOCGIWENCODEEXT */
- rtw_wx_set_pmkid, /* SIOCSIWPMKSA */
- NULL, /*---hole---*/
-};
-
-#if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_MP_IWPRIV_SUPPORT)
-
-static const struct iw_priv_args rtw_private_args[] =
-{
- {SIOCIWFIRSTPRIV + 0x00, IW_PRIV_TYPE_CHAR | 128, 0, "write_reg"},
- {SIOCIWFIRSTPRIV + 0x01, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 4, "read_reg"},
- {SIOCIWFIRSTPRIV + 0x02, IW_PRIV_TYPE_CHAR | 128, 0, "write_rf" },
- {SIOCIWFIRSTPRIV + 0x03, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 4, "read_rf" },
- {SIOCIWFIRSTPRIV + 0x04, IW_PRIV_TYPE_NONE, 0, "mp_start"},
- {SIOCIWFIRSTPRIV + 0x05, IW_PRIV_TYPE_NONE, 0, "mp_stop"},
- {SIOCIWFIRSTPRIV + 0x06, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mp_rate"},
- {SIOCIWFIRSTPRIV + 0x07, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mp_channel"},
- {SIOCIWFIRSTPRIV + 0x08, IW_PRIV_TYPE_CHAR | 40, 0, "mp_bandwidth"},
- {SIOCIWFIRSTPRIV + 0x09, IW_PRIV_TYPE_CHAR | 40, 0, "mp_txpower"},
- {SIOCIWFIRSTPRIV + 0x0a, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "mp_ant_tx"},
- {SIOCIWFIRSTPRIV + 0x0b, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "mp_ant_rx"},
- {SIOCIWFIRSTPRIV + 0x0c, IW_PRIV_TYPE_CHAR | 128, 0, "mp_ctx"},
- {SIOCIWFIRSTPRIV + 0x0d, 0, IW_PRIV_TYPE_CHAR | 128, "mp_query"},
- {SIOCIWFIRSTPRIV + 0x0e, IW_PRIV_TYPE_CHAR | 40, 0, "mp_arx"},
- {SIOCIWFIRSTPRIV + 0x0f, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "mp_psd"},
- {SIOCIWFIRSTPRIV + 0x10, IW_PRIV_TYPE_CHAR | 40, 0, "mp_pwrtrk"},
- {SIOCIWFIRSTPRIV + 0x11, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "mp_ther"},
- {SIOCIWFIRSTPRIV + 0x12, 0, 0, "mp_ioctl"}, // mp_ioctl
- {SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED |0x700 ,"efuse_get"},
- {SIOCIWFIRSTPRIV + 0x14, IW_PRIV_TYPE_CHAR | 128, 0, "efuse_set"},
- {SIOCIWFIRSTPRIV + 0x15, IW_PRIV_TYPE_CHAR | 128, 0, "mp_reset_stats"},
- {SIOCIWFIRSTPRIV + 0x16, IW_PRIV_TYPE_CHAR | 128, 0, "mp_dump"},
-
-};
-
-static iw_handler rtw_private_handler[] =
-{
- rtw_mp_write_reg, // set, 0x00 = 0
- rtw_mp_read_reg, // get, 0x01 = 1
- rtw_mp_write_rf, // set, 0x02 = 2
- rtw_mp_read_rf, // get, 0x03 = 3
- rtw_mp_start,
- rtw_mp_stop,
- rtw_mp_rate,
- rtw_mp_channel,
- rtw_mp_bandwidth,
- rtw_mp_txpower,
- rtw_mp_ant_tx,
- rtw_mp_ant_rx,
- rtw_mp_ctx,
- rtw_mp_trx_query, // get, 0x0d = 13
- rtw_mp_arx,
- rtw_mp_psd, // get, 0x0f = 15
- rtw_mp_pwrtrk, // set, 0x10 = 16
- rtw_mp_thermal, // get, 0x11 = 17
- rtw_mp_ioctl_hdl,
- rtw_mp_efuse_get,
- rtw_mp_efuse_set,
- rtw_mp_reset_stats,
- rtw_mp_dump,
-};
-
-#else // not inlucde MP
-
-static const struct iw_priv_args rtw_private_args[] = {
- {
- SIOCIWFIRSTPRIV + 0x0,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "rtw_write32"
- },
- {
- SIOCIWFIRSTPRIV + 0x1,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rtw_read32"
- },
- {
- SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
- },
- {
- SIOCIWFIRSTPRIV + 0x3, 0, 0, "" // mp_ioctl
- },
- {
- SIOCIWFIRSTPRIV + 0x4,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
- },
- {
- SIOCIWFIRSTPRIV + 0x5,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
- },
- {
- SIOCIWFIRSTPRIV + 0x6,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
- },
-//for PLATFORM_MT53XX
- {
- SIOCIWFIRSTPRIV + 0x7,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
- },
- {
- SIOCIWFIRSTPRIV + 0x8,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
- },
- {
- SIOCIWFIRSTPRIV + 0x9,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
- },
-
-//for RTK_DMP_PLATFORM
- {
- SIOCIWFIRSTPRIV + 0xA,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
- },
-
- {
- SIOCIWFIRSTPRIV + 0xB,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
- },
- {
- SIOCIWFIRSTPRIV + 0xC,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
- },
- {
- SIOCIWFIRSTPRIV + 0xD,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
- },
-#if 0
- {
- SIOCIWFIRSTPRIV + 0xE,0,0, "wowlan_ctrl"
- },
-#endif
- {
- SIOCIWFIRSTPRIV + 0x10,
- IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
- },
- {
- SIOCIWFIRSTPRIV + 0x11,
- IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN , "p2p_get"
- },
- {
- SIOCIWFIRSTPRIV + 0x12,
- IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ , "p2p_get2"
- },
-#ifdef CONFIG_TDLS
- {SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},
- {
- SIOCIWFIRSTPRIV + 0x14,
- IW_PRIV_TYPE_CHAR | 64, 0, "tdls"
- },
-#endif
- {
- SIOCIWFIRSTPRIV + 0x16,
- IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "pm_set"
- },
-
- {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"},
-
- {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 128, 0, "efuse_set"},
- {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED |0x700 ,"efuse_get"},
-
-};
-
-static iw_handler rtw_private_handler[] =
-{
- rtw_wx_write32, //0x00
- rtw_wx_read32, //0x01
- rtw_drvext_hdl, //0x02
- rtw_mp_ioctl_hdl, //0x03
-
-// for MM DTV platform
- rtw_get_ap_info, //0x04
-
- rtw_set_pid, //0x05
- rtw_wps_start, //0x06
-
-// for PLATFORM_MT53XX
- rtw_wx_get_sensitivity, //0x07
- rtw_wx_set_mtk_wps_probe_ie, //0x08
- rtw_wx_set_mtk_wps_ie, //0x09
-
-// for RTK_DMP_PLATFORM
-// Set Channel depend on the country code
- rtw_wx_set_channel_plan, //0x0A
-
- rtw_dbg_port, //0x0B
- rtw_wx_write_rf, //0x0C
- rtw_wx_read_rf, //0x0D
-
-#if 0
- rtw_wowlan_ctrl, //0x0E
-#else
- rtw_wx_priv_null, //0x0E
-#endif
- rtw_wx_priv_null, //0x0F
-
- rtw_p2p_set, //0x10
- rtw_p2p_get, //0x11
- rtw_p2p_get2, //0x12
-
- NULL, //0x13
- rtw_tdls, //0x14
- rtw_wx_priv_null, //0x15
-
- rtw_pm_set, //0x16
- rtw_wx_priv_null, //0x17
- rtw_rereg_nd_name, //0x18
- rtw_wx_priv_null, //0x19
-
- rtw_mp_efuse_set, //0x1A
- rtw_mp_efuse_get, //0x1B
- // 0x1C is reserved for hostapd
-};
-
-#endif // #if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_MP_IWPRIV_SUPPORT)
-
-#if WIRELESS_EXT >= 17
-static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
-{
- _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
- struct iw_statistics *piwstats=&padapter->iwstats;
- int tmp_level = 0;
- int tmp_qual = 0;
- int tmp_noise = 0;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != _TRUE)
- {
- piwstats->qual.qual = 0;
- piwstats->qual.level = 0;
- piwstats->qual.noise = 0;
- //DBG_8192C("No link level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
- }
- else{
- #ifdef CONFIG_ANDROID
- tmp_level = padapter->recvpriv.rssi;
- #else
- tmp_level = padapter->recvpriv.signal_strength;
- #endif
-
- tmp_qual =padapter->recvpriv.signal_strength; //padapter->recvpriv.signal_qual;
- tmp_noise =padapter->recvpriv.noise;
- //DBG_8192C("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise,padapter->recvpriv.rssi);
-
- piwstats->qual.level = tmp_level;
- piwstats->qual.qual = tmp_qual;
- piwstats->qual.noise = tmp_noise;
- }
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
- piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;//|IW_QUAL_DBM;
-#else
-#ifdef RTK_DMP_PLATFORM
- //IW_QUAL_DBM= 0x8, if driver use this flag, wireless extension will show value of dbm.
- //remove this flag for show percentage 0~100
- piwstats->qual.updated = 0x07;
-#else
- piwstats->qual.updated = 0x0f;
-#endif
-#endif
-
- #ifdef CONFIG_ANDROID
- piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
- #endif
-
- return &padapter->iwstats;
-}
-#endif
-
-struct iw_handler_def rtw_handlers_def =
-{
- .standard = rtw_handlers,
- .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
- .private = rtw_private_handler,
- .private_args = (struct iw_priv_args *)rtw_private_args,
- .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
- .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
-#if WIRELESS_EXT >= 17
- .get_wireless_stats = rtw_get_wireless_stats,
-#endif
-};
-
--- /dev/null
+begin 644 os_dep/linux/ioctl_linux.o
+M?T5,1@$!`0````````````$`*``!``````````````#8:0``````!30`````
+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
+M424"`&S<`H#Y-P.(`@``N`(``'@#``"``P``C`,``)0#``"@`P``L`,``+@#
+M``!L````.``<`!4```!,`0``4```````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M```HL@&!L+!?A```````````L+"P@$````"PL*"```$``+"PL(`(`0``L+"P
+M@%@!``"PL*"`J`$``+"PL(#L`0``L+"P@`@"``"PL*"`7`(``+"PL(!X`@``
+ML+"P@)0"``"PL+"`K`(``+"H`8#D`@``L+"P@.P"``"PL+"`]`(``+"PL(#\
+M`@``L+"P@`0#``"PL+"`#`,``+"PL(`4`P``L+"B@'P#``"PL+"`A`,``+"P
+ML(",`P``L+"P@)0#``"PL+"`F`,``+"PL("<`P``L*X!@"0$``"PL+"`+`0`
+M`+"PH("L!```L+"J@/0$``"O*+*`?`L``+"L`8"H#````````%`0``"PJP2`
+M'!(``+"PJ(#H$@``L*P!@(@4``"PL*B`H!0``+"L`X#\%P``L+"H@"08``"P
+MKPZ`S!H``+"N`8!,'0``L+"J@(`=``"PK@.`J!\``+"PJH`,(0``L+"H@$`A
+M``"PL*J`D"$``+"PJH#\(0``L*P'@"@D``"PL*Z`P"<``+"PKH`(*0``L+"J
+M@"`J``"PKP2`W"T``+"PJ(#T+0``7X0"@)PO``"PJ@>`\#```%^$"H!0,@``
+ML*L"@-0S``"O"+&`%#4``+"PJH"(-0``KT2R@%1!``"PKP:`@$(``+"PJH#D
+M0@``L+"N@`1$``"PJ02`7$0``+"I!("T1```L*D$@/1$``"PKPJ`/$<``*\_
+M&(!D30``L+"J@`Q.``"PL*Z`\$X``+"PJ(`@3P``L*\$@$A>``"PL*B`B%X`
+M`+"PJH``4/($"PH)"`<&!00#`@$`_P```')T=U]W>%]S971?=V%P``!#4T-!
+M3B!3`0``4P```````%#R!`40$!`-`````0`````````%`````%#R!."+```"
+M2```<G1W7W=R:71E,S(``````.&+```!2!`H<G1W7W)E860S,@```````.*+
+M````````9')I=F5R7V5X=````````..+````````````````````````````
+M`.2+```!2```87!I;F9O`````````````.6+```"2```<V5T<&ED````````
+M`````.:+```!2```=W!S7W-T87)T`````````.>+```!2```9V5T7W-E;G-I
+M=&EV:71Y`.B+```!2```=W!S7W!R;V)?<F5Q7VEE`.F+```!2```=W!S7V%S
+M<V]C7W)E<5]I9>J+```!2```8VAA;FYE;%]P;&%N`````.N+```"2```9&)G
+M`````````````````.R+```#2```<F9W`````````````````.V+```"2!`H
+M<F9R`````````````````/"+``!`(```<#)P7W-E=````````````/&+``!`
+M($`H<#)P7V=E=````````````/*+``!`(!`@<#)P7V=E=#(``````````/:+
+M``!`(```<&U?<V5T`````````````/B+```0(```<F5R96=?;F1?;F%M90``
+M`/J+``"`(```969U<V5?<V5T`````````/N+``"`(``O969U<V5?9V5T````
+M`````#!X)3`U>```+````')E86QM87``)7,@"@`````E<R`),'@E,#)X"0`E
+M<R`E,#)8`"5S"0`E<PH`<FUA<``````E<R`P>"4P,E@````E<R``<F5A;')A
+M=P`E<R`E,#)X`"5S"@D`````;6%C`'9I9'!I9```86)L97)A=P`E<R`Z(%L@
+M879A:6QA8FQE(')A=R!S:7IE72`]("5D`"5S(#H@0V]M;6%N9"!N;W0@9F]U
+M;F0*`'=M87``````=W)A=P````!#;VUM86YD(&YO="!F;W5N9`H``&1I<V%B
+M;&4E9````&QP<ST`````:7!S/0`````E=0``,'@E,#AX```\5TE&24!214%,
+M5$5+/@``5T50`&YO;F4`````5$M)4`````!#0TU0`````$E%144@.#`R+C$Q
+M8FX```!)145%(#@P,BXQ,6(`````245%12`X,#(N,3%B9VX``$E%144@.#`R
+M+C$Q8F<```!)145%(#@P,BXQ,6%N````245%12`X,#(N,3%A`````$E%144@
+M.#`R+C$Q9VX```!)145%(#@P,BXQ,6<`````=6YA<W-O8VEA=&5D`````"!2
+M871E<R`H36(O<RDZ(```````+C4``"5D)7,@````=W!A7VEE/0`E,#)X````
+M`')S;E]I93T`)7,Z(')F<'=R<W1A=&5?8VAE8VL@9F%I;"X*`"5S.B!T96UP
+M+3YS85]F86UI;'D@(3T@05)02%)$7T542$52+@H````E8P``04Y$4D])1%]7
+M249)7T--1%]35$%25"XN+BXN+BXN+BX*````=V%I=&EN9R!F;W(@=VEF:2!D
+M<FEV97(@=&\@8F4@<F5A9'DN+BX*`%-405)4````3TL``$%.1%)/241?5TE&
+M25]#341?4U1/4"XN+BXN+BXN+BX*`````%-43U``````5TE&22!R<W-I("5D
+M`````$Q)3DM34$5%1"`E9`````!-04-!1$12(#T@)3`R>#HE,#)X.B4P,G@Z
+M)3`R>#HE,#)X.B4P,G@`)2IS("5S``!54P``154``$I0``!38V%N+4-H86YN
+M96QS(#T@)60``$=E="!#:&%N;F5L<R!R971U<FX@)60@*&EN:71?8VAA;FYE
+M;%]P;&%N/25D*0H``')T;#@Q.#A?=VEF:5]W86ME;&]C:P```%)34TD`````
+M3$E.2U-0145$````34%#041$4@!30T%.+4%#5$E610!30T%.+5!!4U-)5D4`
+M````0T]53E1260!30T%.+4-(04Y.14Q3`````$=#0SH@*$=.52D@-"XT+C``
+M02H```!A96%B:0`!(`````4W+4$`!@H'00@!$@04`14!%P,8`1D!&@(>`0`N
+M<WEM=&%B`"YS=')T86(`+G-H<W1R=&%B`"YR96PN=&5X=``N<F5L+F1A=&$`
+M+F)S<P`N05)-+F5X=&%B`"YR96PN05)-+F5X:61X`"YR;V1A=&$`+G)O9&%T
+M82YS='(Q+C0`+F-O;6UE;G0`+FYO=&4N1TY5+7-T86-K`"Y!4DTN871T<FEB
+M=71E<P``````````````````````````````````````````````````````
+M`!\````!````!@`````````T````P%X`````````````!``````````;````
+M"0``````````````M)```%`8```/`````0````0````(````*0````$````#
+M`````````/1>``"\`0`````````````$`````````"4````)````````````
+M```$J0``B`(```\````#````!`````@````O````"`````,`````````L&``
+M`&````````````````@`````````-`````$````"`````````+!@```,````
+M```````````$`````````$,````!``!P@@````````"\8```0`(```$`````
+M````!``````````_````"0``````````````C*L``%@"```/````!P````0`
+M```(````3@````$````"`````````/QB``!(`@`````````````$````````
+M`%8````!````,@````````!$90``R`,`````````````!`````$```!E````
+M`0``````````````#&D``!(```````````````$`````````;@````$`````
+M`````````!YI```````````````````!`````````'X````#``!P````````
+M```>:0``*P```````````````0`````````1`````P``````````````26D`
+M`(X```````````````$``````````0````(``````````````(!L``#`%@``
+M$````/P````$````$`````D````#``````````````!`@P``<0T`````````
+M`````0```````````````````````````````0``````````````!`#Q_P``
+M``````````````,``0`````````````````#``,``````````````````P`%
+M``\`````````0`````(``0`9``````````````````$`````````````````
+M`P`&``````````````````,`!P`<````0````,`````"``$`&0```$``````
+M```````!`"X``````0``"`````(``0`9``````$```````````$`/@````@!
+M``!0`````@`!`!D````(`0```````````0!.````6`$``%`````"``$`&0``
+M`%@!```````````!`!D```"H`0```````````0!>````[`$``!P````"``$`
+M&0```.P!```````````!`&T````(`@``5`````(``0`9````"`(`````````
+M``$`?0```%P"```<`````@`!`!D```!<`@```````````0"-````>`(``!P`
+M```"``$`&0```'@"```````````!`)X```"4`@``&`````(``0`9````E`(`
+M``````````$`KP```*P"```X`````@`!`!D```"L`@```````````0"_````
+MY`(```@````"``$`&0```.0"```````````!`-````#L`@``"`````(``0`9
+M````[`(```````````$`U@```/0"```(`````@`!`!D```#T`@``````````
+M`0#R````_`(```@````"``$`&0```/P"```````````!``D!```$`P``"```
+M``(``0`9````!`,```````````$`'P$```P#```(`````@`!`!D````,`P``
+M`````````0`N`0``%`,``&@````"``$`&0```!0#```````````!`#H!``!\
+M`P``"`````(``0`9````?`,```````````$`1@$``(0#```(`````@`!`!D`
+M``"$`P```````````0!2`0``C`,```@````"``$`&0```(P#```````````!
+M`!D```"4`P```````````0`9````F`,```````````$`&0```)P#````````
+M```!`%\!```D!```"`````(``0`9````)`0```````````$`:`$``"P$``"`
+M`````@`!`!D````L!````````````0!_`0``K`0``$@````"``$`&0```*P$
+M```````````!`(X!````````````````"@"3`0``]`0``(@&```"``$`&0``
+M`/0$```````````!`*0!```(````````````"@"I`0``#`````````````H`
+MK@$``"@````````````*`+,!```X````````````"@"X`0``4```````````
+M``H`O@$``%@````````````*`,0!```P````````````"@#)`0``8```````
+M``````H`SP$``&@````````````*`-4!``!L````````````"@#;`0``=```
+M``````````H`X0$``'P````````````*`.<!``"<````````````"@#M`0``
+M9`L```````````$`\`$``'P+```L`0```@`!`!D```!\"P```````````0#^
+M`0``J`P``*@#```"``$`&0```*@,```````````!``\"``"T````````````
+M"@`5`@``O`````````````H`[0$``$P0```````````!`!L"``!0$```S`$`
+M``(``0`9````4!````````````$`+0(````````````````%`#<"``#8````
+M````````"@#M`0``&!(```````````$`&0```!P2```````````!`#T"``#H
+M$@``H`$```(``0`9````Z!(```````````$`2`(``.0````````````*`$X"
+M``#L````````````"@!4`@``]`````````````H`6@(``(@4```8`````@`!
+M`!D```"(%````````````0!I`@``H!0``%P#```"``$`&0```*`4````````
+M```!`.T!``#4%````````````0`9````$!4```````````$`=@(``/P7```H
+M`````@`!`!D```#\%P```````````0".`@``)!@``*@"```"``$`&0```"08
+M```````````!`)X"``#,&@``@`(```(``0`9````S!H```````````$`KP(`
+M`$P=```T`````@`!`!D```!,'0```````````0"]`@``^`````````````H`
+MPP(``(`=```H`@```@`!`!D```"`'0```````````0#4`@``J!\``&0!```"
+M``$`&0```*@?```````````!`.T!```H(````````````0`9````1"``````
+M``````$`XP(```PA```T`````@`!`!D````,(0```````````0#S`@````$`
+M``````````H`^0(``$`A``!0`````@`!`!D```!`(0```````````0`*`P``
+MD"$``&P````"``$`&0```)`A```````````!`!D#``#\(0``+`(```(``0`9
+M````_"$```````````$`*`,``"@D``"8`P```@`!`!D````H)```````````
+M`0`[`P``$`$```````````H`[0$``+@G```````````!`$$#``#`)P``2`$`
+M``(``0`9````P"<```````````$`[0$``"0H```````````!`!D````T*```
+M`````````0!4`P``%`$```````````H`6@,``!P!```````````*`&`#```D
+M`0``````````"@!F`P``""D``!@!```"``$`&0````@I```````````!`.T!
+M```P*0```````````0`9````7"D```````````$`=@,``"`J``"\`P```@`!
+M`!D````@*@```````````0#M`0``/"L```````````$`&0```'PK````````
+M```!`.T!```8+````````````0`9````6"P```````````$`A0,`````````
+M```````)`(\#``#<+0``&`````(``0`9````W"T```````````$`H0,``/0M
+M``"H`0```@`!`!D```#T+0```````````0"Q`P``G"\``%0!```"``$`&0``
+M`)PO```````````!`.T!``#L,````````````0#!`P``\#```&`!```"``$`
+M&0```/`P```````````!`-(#``!0,@``A`$```(``0`9````4#(`````````
+M``$`X@,``"P!```````````*`.@#```\`0``````````"@#N`P``3`$`````
+M``````H`]`,``%P!```````````*`/H#``!L`0``````````"@``!```?`$`
+M``````````H`!@0``(P!```````````*``P$``"<`0``````````"@`2!```
+MK`$```````````H`&`0``-0S``!``0```@`!`!D```#4,P```````````0`I
+M!`````````````````,`,P0``!0U``!T`````@`!`!D````4-0``````````
+M`0!#!```B#4``,P+```"``$`&0```(@U```````````!`%($``"\`0``````
+M````"@!8!```T`$```````````H`7@0``,P!```````````*`&0$``#4`0``
+M````````"@!J!```W`$```````````H`<`0``.0!```````````*`'8$``#L
+M`0``````````"@!\!```5$$``"P!```"``$`&0```%1!```````````!`(P$
+M``"`0@``9`````(``0`9````@$(```````````$`G`0``.1"```@`0```@`!
+M`!D```#D0@```````````0#M`0``^$,```````````$`&0````1$````````
+M```!`!D```!<1````````````0`9````M$0```````````$`JP0``/1$``!(
+M`@```@`!`!D```#T1````````````0#M`0``-$<```````````$`NP0``#Q'
+M```H!@```@`!`!D````\1P```````````0#M`0``%$D```````````$`&0``
+M`#A)```````````!`,L$```\`@``````````"@#1!```B`(```````````H`
+MUP0``)`"```````````*`-T$``"4`@``````````"@#C!```N`(`````````
+M``H`Z00``,`"```````````*`.\$``#0`@``````````"@#U!```X`(`````
+M``````H`^P0```@#```````````*``$%```0`P``````````"@`'!0``%`,`
+M``````````H`#04``!@#```````````*`!,%```<`P``````````"@`9!0``
+M,`,```````````H`[0$``%1-```````````!`!\%``!D30``J`````(``0`9
+M````9$T```````````$`[0$``*1-```````````!`!D```"T30``````````
+M`0`O!0``#$X``.0````"``$`&0````Q.```````````!`#T%``#P3@``,```
+M``(``0`9````\$X```````````$`&0```"!/```````````!`.T!``#T3P``
+M`````````0`9````!%````````````$`[0$``&A2```````````!`!D```"T
+M4@```````````0#M`0``-%X```````````$`&0```$A>```````````!`.T!
+M``"$7@```````````0`9````B%X```````````$`204``&`#```````````*
+M``````````````````,`"0!/!0````````0````!``D`[0$`````````````
+M```)`%L%```$````#0````$`"0!G!0``%`````\````!``D`=@4``#0````$
+M`````0`)`((%```X````!0````$`"0"-!0``0`````D````!``D`F`4``$P`
+M```$`````0`)`*0%``!0````^`$```$`"0#M`0````````````````,`M04`
+M`&P```#@`````0`#`,(%``!,`0``<`````$``P`````````````````#``H`
+M[0$````````````````%`-8%````````$`````$`!0#G!0``$`````$````!
+M``4`_`4``!$````!`````0`%``\&```8````2`````$`!0``````````````
+M```#``P``````````````````P`+``````````````````,`#0`D!@``````
+M```````0````.P8``*@!``!$````$@`!`%@&`````````````!````!?!@``
+ME`,```0````2``$`;`8``)@#```$````$@`!`'@&``"<`P``B````!(``0"$
+M!@`````````````0````C`8`````````````$````)@&`````````````!``
+M``"I!@`````````````0````LP8`````````````$````+H&````````````
+M`!````#!!@`````````````0````U`8`````````````$````-L&````````
+M`````!````#J!@`````````````0`````P<`````````````$````!0'````
+M`````````!`````I!P`````````````0````.@<`````````````$````$@'
+M`````````````!````!<!P`````````````0````8P<`````````````$```
+M`'H'`````````````!````"!!P`````````````0````B0<`````````````
+M$````)L'`````````````!````"G!P`````````````0````MP<`````````
+M````$````,X'`````````````!````#@!P``'!(``,P````2``$`\0<`````
+M````````$````/D'`````````````!`````#"``````````````0````$0@`
+M````````````$````"<(`````````````!`````N"``````````````0````
+M.P@`````````````$````$<(`````````````!````!4"``````````````0
+M````9`@`````````````$````'4(`````````````!````"-"```````````
+M```0````G0@`````````````$````+`(`````````````!````"^"```````
+M```````0````S0@`````````````$````-T(`````````````!````#L"```
+M```````````0````^`@`````````````$`````,)`````````````!`````/
+M"0`````````````0````&PD`````````````$````"8)`````````````!``
+M```R"0`````````````0````20D`````````````$````%4)````````````
+M`!````!G"0`````````````0````?`D`````````````$````(T)````````
+M`````!````"E"0`````````````0````O@D`````````````$````,L)````
+M`````````!````#<"0`````````````0````[@D`````````````$````/D)
+M`````````````!`````-"@`````````````0````,`H`````````````$```
+M`%,*`````````````!````!G"@`````````````0````A`H`````````````
+M$````(T*`````````````!````"F"@`````````````0````L@H`````````
+M````$````+D*`````````````!````#+"@`````````````0````Y@H`````
+M````````$````/4*`````````````!`````#"P`````````````0````'PL`
+M````````````$````#0+```$1```6````!(``0!3"P`````````````0````
+M9PL``%Q$``!8````$@`!`(,+``"T1```0````!(``0"C"P`````````````0
+M````M@L`````````````$````-4+`````````````!````#B"P``````````
+M```0````[@L`````````````$````/8+`````````````!``````#```````
+M```````0````#0P`````````````$````!0,`````````````!`````@#```
+M```````````0````,@P`````````````$````$0,`````````````!````!7
+M#``````````````0````9PP``"!/```H#P``$@`!`'$,`````````````!``
+M``"%#``````````````0````DPP`````````````$````*H,````````````
+M`!````"V#``````````````0````S`P`````````````$````-H,``!(7@``
+M0````!(``0#R#``````````````0````!`T``(A>```X````$@`!`!P-````
+M`````````!`````K#0```````#`````1``,`-0T``#`````D````$0`#`$H-
+M```4````!````!$`!0!@#0``5````!@````1``,``&EO8W1L7VQI;G5X+F,`
+M:&5X,FYU;5]I`"1A`'=P85]S971?875T:%]A;&=S`')T=U]W>%]S971?9G)E
+M<0!R='=?=WA?9V5T7VUO9&4`<G1W7W=X7V=E=%]S96YS`')T=U]W>%]G971?
+M<G1S`')T=U]W>%]S971?9G)A9P!R='=?=WA?9V5T7V9R86<`<G1W7W=X7V=E
+M=%]R971R>0!R='=?=WA?9V5T7W!O=V5R`')T=U]W>%]W<FET95]R9@!R='=?
+M=WA?<')I=E]N=6QL`&1U;6UY`')T=U]W>%]S971?;71K7W=P<U]P<F]B95]I
+M90!R='=?=WA?9V5T7W-E;G-I=&EV:71Y`')T=U]W>%]S971?;71K7W=P<U]I
+M90!R='=?9')V97AT7VAD;`!R='=?<V5T7W!I9`!R='=?<#)P7W-E=`!R='=?
+M<#)P7V=E=`!R='=?<#)P7V=E=#(`<G1W7W1D;',`<G1W7V=E=%]W:7)E;&5S
+M<U]S=&%T<P!R='=?=WA?<F5A9%]R9@`N3$,P`')T=U]M<%]E9G5S95]G970`
+M+DQ#,0`N3$,R`"Y,0S4`+DQ#.``N3$,Q,0`N3$,Q,@`N3$,V`"Y,0S$S`"Y,
+M0S$T`"Y,0S$U`"Y,0S$V`"Y,0S$W`"Y,0S$X`"1D`')T=U]W<'-?<W1A<G0`
+M<G1W7VUP7V5F=7-E7W-E=``N3$,Q.0`N3$,R,`!R='=?<F5R96=?;F1?;F%M
+M90`N3$%.0TA/4C``+DQ#,C(`<G1W7W!M7W-E=``N3$,R,P`N3$,R-``N3$,R
+M-0!R='=?=WA?=W)I=&4S,@!R='=?9&)G7W!O<G0`<G1W7W=X7W-E=%]C:&%N
+M;F5L7W!L86X`<G1W7V=E=%]A<%]I;F9O`')T=U]M<%]I;V-T;%]H9&P`<G1W
+M7W=X7W)E860S,@`N3$,R-@!R='=?=WA?<V5T7W!M:VED`')T=U]W>%]G971?
+M96YC`')T=U]W>%]G971?;FEC:P`N3$,R-P!R='=?=WA?9V5T7V5S<VED`')T
+M=U]W>%]G971?=V%P`')T=U]W>%]S971?96YC`'=P85]S971?96YC<GEP=&EO
+M;@`N3$,R.`!R='=?=WA?<V5T7V5N8U]E>'0`+DQ#,CD`+DQ#,S``+DQ#,S$`
+M<G1W7W=X7W-E=%]A=71H`')T=U]S971?=W!A7VEE`"Y,04Y#2$]2,0!R='=?
+M=WA?<V5T7V=E;E]I90!R='=?=WA?9V5T7W)A=&4`<G1W7W=X7W-E=%]R871E
+M`')T=U]W>%]S971?97-S:60`<G1W7W=X7V=E=%]N86UE`"Y,0S,R`"Y,0S,S
+M`"Y,0S,T`"Y,0S,U`"Y,0S,V`"Y,0S,W`"Y,0S,X`"Y,0S,Y`"Y,0S0P`')T
+M=U]W>%]G971?<F%N9V4`+DQ!3D-(3U(R`')T=U]W>%]G971?9G)E<0!T<F%N
+M<VQA=&5?<V-A;@`N3$,T,0`N3$,T,P`N3$,T,@`N3$,T-``N3$,T-0`N3$,T
+M-@`N3$,T-P!R='=?=WA?9V5T7W-C86X`<G1W7W=X7W-E=%]M;&UE`')T=U]W
+M>%]S971?=V%P`')T=U]W>%]S971?<V-A;@!R='=?=WA?<V5T7W!R:78`+DQ#
+M-3(`+DQ#-30`+DQ#-34`+DQ#-38`+DQ#-3<`+DQ#-3@`+DQ#-3D`+DQ#-C``
+M+DQ#-C$`+DQ#-C(`+DQ#-C,`+DQ#-C0`+DQ#-C4`+DQ#-C8`<G1W7W=X7W-E
+M=%]M;V1E`'-E=%]G<F]U<%]K97D`<V5T7W=E<%]K97D`+DQ#-C<`0RXV,3DN
+M-#$Q-C0`0RXV-#8N-#$X.3``7U]F=6YC7U\N-#$T-C0`0RXW-3$N-#,W-3,`
+M0U-75$-(+C<X-`!#4U=40T@N-S@W`$,N-S,S+C0S-3(V`')T=U]P<FEV871E
+M7V%R9W,`<G1W7VAA;F1L97)S`')T=U]P<FEV871E7VAA;F1L97(`;VQD7VEF
+M;F%M92XT,C<Q-@!O;&1?8E)E9U5S94QE9"XT,C<Q.`!O;&1?:7!S7VUO9&4N
+M-#(W,3<`<G1L.#$X.%]S=7-P96YD7VQO8VL`7U]A96%B:5]U;G=I;F1?8W!P
+M7W!R,`!R='=?:7-?9FET7W)E9W5L871O<GE?9&]M86EN`'5I7W!I9`!M86-?
+M<F5G7V1U;7``8F)?<F5G7V1U;7``<F9?<F5G7V1U;7``<W!R:6YT9@!?<G1W
+M7VUE;7-E=`!?7V-O<'E?9G)O;5]U<V5R`%]?;65M>F5R;P!S=')S97``<W1R
+M8VUP`')T=U]E9G5S95]M87!?<F5A9`!S=')L96X`<VEM<&QE7W-T<G1O=6P`
+M14954T5?1V5T169U<V5$969I;FET:6]N`')T=U]E9G5S95]A8V-E<W,`969U
+M<V5?1V5T0W5R<F5N=%-I>F4`969U<V5?1V5T36%X4VEZ90!K97E?,F-H87(R
+M;G5M`')T=U]E9G5S95]M87!?=W)I=&4`<')I;G1K`%]?865A8FE?=6YW:6YD
+M7V-P<%]P<C$`:69N86UE`'-T<FYC<'D`<G1W7V-H86YG95]I9FYA;64`7W)T
+M=U]M96UC;7``<G1W7W-W7VQE9%]I;FET`')T=U]F<F5E7VYE='=O<FM?<75E
+M=64`<G1W7W-W7VQE9%]D96EN:70`<F9P=W)S=&%T95]C:&5C:P!J:69F:65S
+M`&UO9%]T:6UE<@!S=')?,F-H87(R;G5M`$QE879E06QL4&]W97)3879E36]D
+M90!S<V-A;F8`7W)T=U]W<FET93,R`%]R='=?=W)I=&4X`%]R='=?=W)I=&4Q
+M-@!R='=?9V5T7W-T86EN9F\`;&]C86Q?8FA?9&ES86)L90!R='=?96YD7V]F
+M7W%U975E7W-E87)C:`!L;V-A;%]B:%]E;F%B;&4`<G1W7W-E=%]C:'!L86Y?
+M8VUD`')T=U]M<VQE97!?;W,`<G1W7V=E=%]W<&%?:64`<G1W7V=E=%]W<&$R
+M7VEE`%]?8V]P>5]T;U]U<V5R`%]R='=?;6%L;&]C`%]R='=?<F5A9#@`7W)T
+M=U]R96%D,38`7W)T=U]R96%D,S(`7W)T=U]M9G)E90!?<G1W7VUE;6-P>0!R
+M='=?<V5T7S@P,E\Q,5]A9&1?=V5P`')T=U]S971?:V5Y`')T=U]S971S=&%K
+M97E?8VUD`')T=U]G971?8F-M8U]S=&%I;F9O`')T=U]D:7-A<W-O8U]C;60`
+M<G1W7VEN9&EC871E7V1I<V-O;FYE8W0`<G1W7V9R965?87-S;V-?<F5S;W5R
+M8V5S`%]R='=?>FUA;&QO8P!R='=?<&%R<V5?=W!A7VEE`')T=U]P87)S95]W
+M<&$R7VEE`')T=U]G971?:64`<G1W7W-E=&1A=&%R871E7V-M9`!R='=?<V5T
+M7S@P,E\Q,5]I;F9R87-T<G5C='5R95]M;V1E`')T=U]S971?.#`R7S$Q7V%U
+M=&AE;G1I8V%T:6]N7VUO9&4`<G1W7W-E=%\X,#)?,3%?<W-I9`!R='=?:7-?
+M8V-K<F%T97-O;FQY7VEN8VQU9&5D`'-N<')I;G1F`')T=U]I<U]C8VMR871E
+M<U]I;F-L=61E9`!R='=?8V@R9G)E<0!M96UC<'D`<G1W7W9A;&ED871E7W-S
+M:60`<G1W7V=E=%]C87!A8FEL:71Y7V9R;VU?:64`<G1W7V=E=%]S96-?:64`
+M<G1W7VES7W=P<U]I90!R='=?<V5T7S@P,E\Q,5]D:7-A<W-O8VEA=&4`<G1W
+M7W-E=%\X,#)?,3%?8G-S:60`<G1W7VEN9&EC871E7W=X7V1I<V%S<V]C7V5V
+M96YT`'=I<F5L97-S7W-E;F1?979E;G0`<G1W7VEN9&EC871E7W=X7V%S<V]C
+M7V5V96YT`&EN9&EC871E7W=X7W-C86Y?8V]M<&QE=&5?979E;G0`<G1W7W-I
+M=&5S=7)V97E?8VUD`')T=U]S971?.#`R7S$Q7V)S<VED7VQI<W1?<V-A;@!?
+M<G1W7W9M86QL;V,`7W)T=U]V;69R964`<W1R;F-M<`!W86ME7VQO8VL`<VQE
+M97!?<F5S=6UE`&US;&5E<`!W86ME7W5N;&]C:P!I;FET7V-H86YN96Q?<&QA
+M;@!R='=?<V5T;W!M;V1E7V-M9`!?<G1W7VEN:71?;&ES=&AE860`<G1W7V5N
+M<75E=65?8VUD`')T=U]I;V-T;`!F;'5S:%]A;&Q?8V%M7V5N=')Y`')T=U]S
+M=&%?9FQU<V@`=7!D871E7W-T85]I;F9O7V%P;6]D90!A<%]F<F5E7W-T80!R
+M='=?8VAE8VM?8F5A8V]N7V1A=&$`=7!D871E7V)E86-O;@!R=&PX,3@X7W!O
+M=V5R7W-A=F5?97AI=`!W86ME7VQO8VM?9&5S=')O>0!R=&PX,3@X7W!O=V5R
+M7W-A=F5?:6YI=`!W86ME7VQO8VM?:6YI=`!R='=?<F%T97,`86YD<F]I9%]W
+M:69I7V-M9%]S='(`<G1L.#$X.%]W86ME;&]C:U]I;FET`')T=U]H86YD;&5R
+M<U]D968`````7`,``"O^``!@`P``+/X``-P$```K.P``X`0``"P[``#H!```
+M'`(!`#0%```<`P$`1`4``!P#`0!\!0``'`0!`)P%```<!0$`P`4``"L^``#$
+M!0``+#X``.P%```<!@$```8``"L_```$!@``+#\```@&```<!P$`)`8``!P(
+M`0`\!@``'`,!`$P&```<`@$`6`8``"M```!<!@``+$```'`&```<`@$`E`8`
+M`!P"`0"P!@``'`(!`,0&```<`@$`Y`8``!P"`0#X!@``'`D!``P'```K00``
+M$`<``"Q!```4!P``'`<!`$0'```<"@$`6`<``!P*`0",!P``'`L!`+@'```<
+M"`$`R`<``!P#`0#P!P``'`(!```(```<`@$`%`@``!P)`0`L"```*T(``#`(
+M```L0@``-`@``!P'`0!8"```'`P!`'`(```<`P$`>`@``"M#``!\"```+$,`
+M`(0(```K1```B`@``"Q$``","```*T4``)`(```L10``I`@``!P"`0#`"```
+M'`(!`.`(```<`@$`]`@``!P)`0`("0``*T8```P)```L1@``$`D``!P'`0!4
+M"0``'`L!`'@)```<"`$`B`D``!P#`0"L"0``'`(!`+P)```<`@$`T`D``!P)
+M`0#D"0``*T<``.@)```L1P``[`D``!P'`0`P"@``'`L!`%0*```<"`$`9`H`
+M`!P#`0"("@``'`(!`)@*```<`@$`K`H``!P)`0#`"@``*T@``,0*```L2```
+MR`H``!P'`0#H"@``'`T!`/`*```<#@$`!`L``"M)```("P``+$D``!`+```<
+M`@$`&`L``!P)`0`L"P``*TH``#`+```L2@``.`L``!P"`0!`"P``'`D!`&0+
+M```"\P``:`L```+S``!L"P```O,``'`+```"\P``=`L```+S``!X"P```O,`
+M`,@+```<!`$`V`L``!P%`0#<#```*SX``.`,```L/@``!`T``!P&`0`8#0``
+M*U```!P-```L4```(`T``!P'`0!,#0``'`H!`%@-```<"0$`>`T``!P/`0"T
+M#0``'`L!`-P-```<$`$`\`T``"M1``#T#0``+%$``/@-```<!P$`)`X``!P*
+M`0`P#@``'`D!`%`.```<#P$`@`X``!P,`0"4#@``*T8``)@.```L1@``G`X`
+M`!P'`0#$#@``'`D!`.P.```<#P$`)`\``!P+`0!,#P``'!`!`&`/```K1P``
+M9`\``"Q'``!H#P``'`<!`)`/```<"0$`L`\``!P/`0#H#P``'`L!`!`0```<
+M$`$`)!```!P1`0!,$````O,``&`0```K50``9!```"Q5``!X$```*Q,!`'P0
+M```L$P$`C!```!P4`0#4$```'`0!`.P0```<!0$`^!```"M5``#\$```+%4`
+M``01```<!P$`'!$``!P5`0`H$0``*U4``"P1```L50``,!$``"M6```T$0``
+M+%8``#P1```<%@$`7!$``!P7`0!L$0``*U4``'`1```L50``A!$``!P4`0"4
+M$0``*U8``)@1```L5@``H!$``!P6`0"T$0``'!@!`/`1```<&0$`&!(```($
+M``"4$@``*QL!`)@2```L&P$`R!(``!P<`0``$P``*UL```03```L6P``#!,`
+M`!P6`0!D$P``'!T!`)P3```<'@$`O!,``"M<``#`$P``+%P``,@3```<%@$`
+M]!,``"M=``#X$P``+%T``/P3```<'P$`(!0``"L;`0`D%```+!L!`%04```<
+M'`$`:!0``!P:`0"4%```'"`!`-04```"`@``V!0```("``#<%````@(``.`4
+M```"`@``Y!0```("``#H%````@(``.P4```"`@``\!0```("``#T%````@(`
+M`/@4```"`@``_!0```("````%0```@(```05```"`@``"!4```("```,%0``
+M`@(``#05```<(0$`2!4``!PB`0!<%0``'"`!`$06```<(P$`C!8``!PD`0#4
+M%@``'"4!``@7```<)@$`1!<``!S_``!8%P``'``!`&P7```<`0$`W!<``!PA
+M`0#L%P``'"$!`!`8```<)P$`:!@``!PH`0#(&```'`0!`.`8```<!0$`[!@`
+M`!PD`0`H&0``'"4!`*@9```<)@$`R!D``!PI`0#\&0``'"H!`$0:```<)@$`
+MB!H``!PK`0"\&@``'!8!```;```<+`$`0!L``!P$`0!@&P``'`4!`-P;```<
+M+0$`\!L``!PN`0`$'```'"\!`#@<```<(0$`3!P``!PB`0!@'```'"`!``P=
+M```<*P$`1!T``!PP`0!<'0``'"\!`&@=```K;```;!T``"QL``!T'0``'`(!
+M`+`=```<,0$`S!T``!P6`0``'@``'!8!`"0>```<,0$`G!X``!P6`0#`'@``
+M'`,!``@?```<`P$`5!\``!PQ`0!P'P``'#$!`"@@```"`@``+"````("```P
+M(````@(``#0@```"`@``."````("```\(````@(``$`@```"`@``C"```!PQ
+M`0`H(0``*W4``"PA```L=0``-"$``!PQ`0!X(0``'#$!`+`A```<`P$`W"$`
+M`!PQ`0#P(0``'`,!`!PB```<`P$`[",``!PQ`0#X(P``'#(!`(@D```K?@``
+MC"0``"Q^``"0)```'`<!`.PD```<+`$`!"4``!P#`0!`)0``'#$!`%@E```<
+M,@$`A"4``!PQ`0"H)0``'#,!`.@E```<(P$`_"4``!P'`0!,)@``'#$!`%@F
+M```<!P$`<"8``!PQ`0"`)@``'#$!`)PF```<-`$`R"8``!PQ`0#L)@``'#$!
+M``PG```<,0$`-"<``!PS`0`\)P``'#4!`%`G```<!P$`L"<``!PP`0"X)P``
+M`O,``+PG```"\P``W"<``!PL`0#X)P``'`,!`!`H```<`P$`)"@```("```H
+M*````@(``"PH```"`@``,"@```("```T*```*WX``#@H```L?@``0"@``"N$
+M``!$*```+(0``$PH```KA0``4"@``"R%``!8*```*X8``%PH```LA@``;"@`
+M`!P4`0"T*```'#$!`-0H```<,0$`]"@``!PP`0`P*0```@(``#0I```"`@``
+M."D```("```\*0```@(``$`I```"`@``1"D```("``!(*0```@(``$PI```"
+M`@``4"D```("``!4*0```@(``%@I```"`@``["D``!PV`0#T*0``'#<!`/PI
+M```<.`$`D"H``!PY`0"L*@``'#$!`-`J```<.@$`!"L``!P[`0`\*P```@(`
+M`$`K```"`@``1"L```("``!(*P```@(``$PK```"`@``4"L```("``!4*P``
+M`@(``%@K```"`@``7"L```("``!@*P```@(``&0K```"`@``:"L```("``!L
+M*P```@(``'`K```"`@``="L```("``!X*P```@(``!@L```"`@``'"P```("
+M```@+````@(``"0L```"`@``*"P```("```L+````@(``#`L```"`@``-"P`
+M``("```X+````@(``#PL```"`@``0"P```("``!$+````@(``$@L```"`@``
+M3"P```("``!0+````@(``%0L```"`@``\"P``"N1``#T+```+)$``"@M```<
+M%@$`8"T``!PQ`0"P+0``*Y$``+0M```LD0``U"T``!PP`0!`+@``'#P!`&@N
+M```<,0$`U#```!P]`0#L,````N8```@Q```<&@$`=#$``!P#`0",,0``'#$!
+M`*@Q```<)0$`S#$``!P6`0`,,@``'#X!`"`R```</P$`+#(``!Q``0"(,@``
+M'#P!`*PR```<00$`R#(``"N=``#,,@``+)T``-`R```<0@$`X#(``"N>``#D
+M,@``+)X``.@R```<0@$`]#(``!Q#`0`0,P``*Y\``!0S```LGP``&#,``!Q"
+M`0`H,P``*Z```"PS```LH```,#,``!Q"`0!4,P``*Z$``%@S```LH0``7#,`
+M`!Q"`0!L,P``*Z(``'`S```LH@``=#,``!Q"`0",,P``*Z,``)`S```LHP``
+ME#,``!Q"`0"D,P``*Z0``*@S```LI```K#,``!Q"`0"\,P``*Z4``,`S```L
+MI0``Q#,``!Q"`0#T,P``'`,!`$`T```KJ```1#0``"RH``"\-```'$0!`#`U
+M```<1`$`7#4``!Q$`0#0-0``'#$!`/PU```<10$`##8``!Q%`0`8-@``'$8!
+M`'PV```<10$`C#8``!Q%`0"@-@``'$4!`,@V```</`$`]#8``!PQ`0!0-P``
+M'$$!`'`W```KG0``=#<``"R=``!X-P``'$(!`(@W```KG@``C#<``"R>``"0
+M-P``'$(!`)PW```<0P$`O#<``"N?``#`-P``+)\``,0W```<0@$`U#<``"N@
+M``#8-P``+*```-PW```<0@$`!#@``"NA```(.```+*$```PX```<0@$`'#@`
+M`"NB```@.```+*(``"0X```<0@$`0#@``"NC``!$.```+*,``$@X```<0@$`
+M6#@``"ND``!<.```+*0``&`X```<0@$`C#@``!Q%`0"<.```'$4!`,`X```<
+M1P$`U#@``!PQ`0`H.0``'$4!`#@Y```<10$`:#D``!Q$`0"X.0``'$4!`,@Y
+M```<10$`.#H``!Q%`0!(.@``'$4!`%PZ```<10$`<#H``"NM``!T.@``+*T`
+M`'@Z```<0@$`H#H``"NN``"D.@``+*X``*PZ```KKP``M#H``"RO``"X.@``
+M*[```+PZ```LL```_#H``!Q"`0`\/```'$4!`$P\```<10$`A#P``!Q(`0"H
+M/```'`,!`*P\```KL0``L#P``"RQ``#8/```*[(``-P\```LL@``]#P``!P"
+M`0`</0``'`,!`#0]```<"0$`<#T``!Q%`0"`/0``'$4!`)0]```<10$`J#T`
+M`!P#`0#T/0``'$4!``0^```<10$`&#X``!Q%`0!`/@``'`,!`$0^```KLP``
+M2#X``"RS``!P/@``*[(``'0^```LL@``C#X``!P"`0"T/@``'`,!`,P^```<
+M"0$`"#\``!Q%`0`8/P``'$4!`"P_```<10$`0#\``!P#`0",/P``'$4!`)P_
+M```<10$`L#\``!Q%`0`L0```'$D!`(Q````<10$`G$```!Q%`0"P0```'$4!
+M`#!!```<10$`0$$``!Q%`0"800``'"0!`-1!```<)0$`#$(``!S]``!80@``
+M'"8!`+!"```<2@$`Q$(``!Q*`0#T0@``'!H!``A#```<$0$`.$,``!P1`0!H
+M0P``'"4!`'Q#```<2P$`I$,``!P6`0"X0P``'#X!`,Q#```</P$`V$,``!Q+
+M`0#X0P```O,``/Q#```"Y@```$0```+S```@1```'`,!`#A$```<`P$`4$0`
+M`!Q-`0!X1```'`,!`)!$```<,0$`J$0``!Q-`0#01```'`,!`.A$```<30$`
+M#$4``!P:`0!810``'$\!`'1%```<3P$`M$4``!P#`0#$10``'#$!`,Q%```<
+M)`$`\$4``!Q0`0`$1@``'"8!`"!&```<%@$`1$8``!P#`0!H1@``'!\!`)!&
+M```<'P$`M$8``!PQ`0#,1@``'"0!`/!&```<4`$`!$<``!PF`0`01P``'%$!
+M`#1'```"Y@``.$<```+S``!D1P``'%(!`*1'```<!`$`Q$<``!P%`0#01P``
+M'%,!``!(```KD0``!$@``"R1```H2```'!8!`$Q(```<,0$`@$@``!P6`0#<
+M2```'`D!`.Q(```<5`$`%$D```("```820```@(``!Q)```"`@``($D```("
+M```D20```@(``"A)```"`@``+$D```("```P20```@(``#1)```"`@``.$D`
+M`"O%```\20``+,4``$!)```<$0$`1$D``"M5``!(20``+%4``&!)```<50$`
+M;$D``"M6`0!P20``+%8!`)!)```<$0$`F$D``!Q7`0"L20``*\8``+!)```L
+MQ@``Y$D``!Q-`0#L20``*\<``/!)```LQP``^$D``!Q%`0``2@``*\@```1*
+M```LR```"$H``!P1`0`02@``*\D``!1*```LR0``2$H``!Q-`0!02@``*\<`
+M`%1*```LQP``7$H``!Q%`0!@2@``*U4``&1*```L50``?$H``!Q8`0"<2@``
+M*\H``*!*```LR@``K$H``!P"`0"X2@``*\<``+Q*```LQP``Q$H``!Q%`0`$
+M2P``*\L```A+```LRP``$$L``!P"`0!(2P``*\P``$Q+```LS```4$L``!P"
+M`0!D2P``*\<``&A+```LQP``<$L``!Q%`0"$2P``*\<``(A+```LQP``D$L`
+M`!Q%`0"@2P``*\T``*1+```LS0``K$L``!P?`0"T2P``*\X``+A+```LS@``
+MO$L``!P'`0#42P``*\\``-A+```LSP``W$L``!P'`0#T2P``*]```/A+```L
+MT```_$L``!P'`0`,3```*UD!`!!,```L60$`+$P``!PQ`0!(3```*\<``$Q,
+M```LQP``5$P``!Q%`0!<3```*UD!`&!,```L60$`D$P``"O1``"43```+-$`
+M`)Q,```<`@$`H$P``"M9`0"D3```+%D!`*A,```KT@``K$P``"S2``"X3```
+M'!$!`,1,```KQP``R$P``"S'``#03```'$4!`.!,```<"0$`)$T``!PK`0!$
+M30``'%,!`%1-```"Y@``6$T```(#``!<30```O,``&!-```"5@$`=$T``!P:
+M`0"D30```@(``*A-```"`@``K$T```("``"P30```@(``.!-```</@$`]$T`
+M`!Q:`0`D3@``'#D!`$!.```<.0$`5$X``!PP`0!L3@``'`,!`)!.```KD0``
+ME$X``"R1``"L3@``'#$!`-!.```<6P$`X$X``!Q<`0`$3P``*Y$```A/```L
+MD0``9$\``!PL`0"L3P``'`0!`,A/```<!0$`U$\``!PP`0#T3P```@(``/A/
+M```"`@``_$\```("````4````@(``!A1```<2@$`+%$``!Q*`0"`40``'"L!
+M`)A1```<,`$`V%$``!PL`0`@4@``'`0!`#Q2```<!0$`2%(``!PP`0!H4@``
+M`@(``&Q2```"`@``<%(```("``!T4@```@(``'A2```"`@``?%(```("``"`
+M4@```@(``(12```"`@``B%(```("``",4@```@(``)!2```"`@``E%(```("
+M``"84@```@(``)Q2```"`@``H%(```("``"D4@```@(``*A2```"`@``K%(`
+M``("``"P4@```@(``,12```<7@$`S%(``!Q?`0`04P``'",!`#A3```<,0$`
+MB%,``!PQ`0"@4P``'&`!`.Q3```<(P$`!%0``!QA`0`\5```'#$!`&A4```<
+M8@$`W%0``!PC`0#X5```'`<!``Q5```<!P$`:%4``!PL`0"`50``'`,!`*!5
+M```<,0$`"%8``!PQ`0!(5@``'#$!`+Q6```<,0$`[%8``!P'`0`H5P``'#$!
+M`$Q7```<,0$`;%<``!PQ`0"(5P``'`<!`,!7```<,0$`%%@``!PU`0",6```
+M'#$!`)A8```<!P$`R%@``!P'`0#H6```'#$!`/A8```<,0$`%%D``!P'`0`P
+M60``'#D!`$19```<.0$`6%D``!PP`0!D60``'%L!`)Q9```<,0$`K%D``!PQ
+M`0"\60``'%P!`/19```<,0$`)%H``!P'`0!@6@``'#$!`(1:```<,0$`I%H`
+M`!PQ`0#`6@``'`<!`/A:```<,0$`3%L``!PU`0"`6P``'#`!`,1;```<(P$`
+M"%P``!PQ`0!07```'#`!`&Q<```<+`$`B%P``!PQ`0"<7```'&,!`.1<```<
+M,`$``%T``!PL`0`<70``'#$!`%A=```<,`$`=%T``!PL`0"070``'#$!`-Q=
+M```<*P$`]%T``!PP`0`07@``'`<!`#1>```"\P``.%X```+S```\7@```O,`
+M`$!>```"\P``1%X```+F``!,7@``*U4``%!>```L50``8%X``!Q7`0!T7@``
+M'%@!`'Q>```<90$`A%X```($``",7@``*U4``)!>```L50``H%X``"OE``"D
+M7@``+.4``*A>```<9P$`L%X``!Q5`0`P`````O,``#0````"\P``.`````+S
+M```\`````O,``$`````"\P``1`````+S``!(`````O,``$P````"\P``4```
+M``+S``!4`````@,``&`````"`P``9`````+F``!H`````C<``'`````"FP``
+M=`````(@``!X`````B```'P````""P``@`````*I``"$`````M0``(@````"
+M#0``C`````(@``"0`````@\``)@````"I@``G`````+!``"L`````B```+``
+M```"(```O`````*X``#``````G@``,0````"M@``R`````(@``#,`````KX`
+M`-`````"M```U`````*9``#8`````G8``-P````"(```X`````)S``#L````
+M`I8``/`````"E```]`````(@``#X`````A(``/P````"%`````$```(6```$
+M`0```B````@!```"(```#`$```(@```0`0```A@``!0!```">@``&`$```)O
+M```<`0```B```"`!```"&@``+`$```*2```T`0```H<``#P!```"@```1`$`
+M``)M``!,`0```EX``%`!```":@``5`$```(H``!8`0```F@``%P!```"9@``
+M8`$```(J``!D`0```DP``&@!```")```;`$```(B``!P`0```B8``'0!```"
+M9```>`$```)@``!\`0```AP``(`!```".0``A`$```(>``"(`0```AX``(P!
+M```"+```D`$```(N``"4`0```C```)P!```"-0``H`$```(>``"D`0```ED`
+M`*@!```"'@``K`$```)3``"P`0```AX``+0!```"3@``N`$```(\````````
+M*@(`````````_```"````"H"```0````*@(``!@````J`@``(````"H"```H
+M````*@(``#`````J`@``.````"H"``!`````*@(``$@````J`@``4````"H"
+M``!8````*@(``&`````J`@``:````"H"``!P````*@(``'@````J`@``@```
+M`"H"``"(````*@(``)`````J`@``F````"H"``"@````*@(``*@````J`@``
+ML````"H"``"X````*@(``,`````J`@``R````"H"``#0````*@(``-@````J
+M`@``X````"H"``#H````*@(``/`````J`@``\``````2`0#T````*@<``/@`
+M```J`@````$``"H"```(`0``*@(``!`!```J`@``&`$``"H"```@`0``*@(`
+M`"@!```J`@``,`$``"H"```X`0``*@(``$`!```J`@``2`$``"H"``!0`0``
+M*@(``%@!```J`@``8`$``"H"``!H`0``*@(``'`!```J`@``>`$``"H"``"`
+M`0``*@(``(@!```J`@``D`$``"H"``"8`0``*@(``*`!```J`@``J`$``"H"
+M``"P`0``*@(``+@!```J`@``P`$``"H"``#(`0``*@(``-`!```J`@``V`$`
+M`"H"``#@`0``*@(``.@!```J`@``\`$``"H"``#X`0``*@(````"```J`@``
+M"`(``"H"```0`@``*@(``!@"```J`@``(`(``"H"```H`@``*@(``#`"```J
++`@``.`(``"H"````
+`
+end