summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rtl8192ce/os_dep/linux
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rtl8192ce/os_dep/linux')
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_cfg80211.c5065
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_linux.c10981
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/mlme_linux.c565
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/os_intfs.c2269
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/pci_intf.c1962
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/pci_ops_linux.c24
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/recv_linux.c451
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/rtw_android.c804
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/sdio_intf.c742
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/sdio_ops_linux.c438
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/usb_intf.c1662
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/usb_ops_linux.c715
-rwxr-xr-xdrivers/net/wireless/rtl8192ce/os_dep/linux/xmit_linux.c404
13 files changed, 26082 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_cfg80211.c
new file mode 100755
index 000000000000..e51180231542
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_cfg80211.c
@@ -0,0 +1,5065 @@
+/******************************************************************************
+ *
+ * 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_CFG80211_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtw_ioctl.h>
+#include <rtw_ioctl_set.h>
+#include <rtw_ioctl_query.h>
+#include <xmit_osdep.h>
+
+#ifdef CONFIG_IOCTL_CFG80211
+
+#include "ioctl_cfg80211.h"
+
+#define RTW_SCAN_IE_LEN_MAX 2304
+#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 //ms
+#define RTW_MAX_NUM_PMKIDS 4
+
+#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
+
+static const u32 rtw_cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+};
+
+#define RATETAB_ENT(_rate, _rateid, _flags) \
+ { \
+ .bitrate = (_rate), \
+ .hw_value = (_rateid), \
+ .flags = (_flags), \
+ }
+
+#define CHAN2G(_channel, _freq, _flags) { \
+ .band = IEEE80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define CHAN5G(_channel, _flags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = 5000 + (5 * (_channel)), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+static struct ieee80211_rate rtw_rates[] = {
+ RATETAB_ENT(10, 0x1, 0),
+ RATETAB_ENT(20, 0x2, 0),
+ RATETAB_ENT(55, 0x4, 0),
+ RATETAB_ENT(110, 0x8, 0),
+ RATETAB_ENT(60, 0x10, 0),
+ RATETAB_ENT(90, 0x20, 0),
+ RATETAB_ENT(120, 0x40, 0),
+ RATETAB_ENT(180, 0x80, 0),
+ RATETAB_ENT(240, 0x100, 0),
+ RATETAB_ENT(360, 0x200, 0),
+ RATETAB_ENT(480, 0x400, 0),
+ RATETAB_ENT(540, 0x800, 0),
+};
+
+#define rtw_a_rates (rtw_rates + 4)
+#define RTW_A_RATES_NUM 8
+#define rtw_g_rates (rtw_rates + 0)
+#define RTW_G_RATES_NUM 12
+
+#define RTW_2G_CHANNELS_NUM 14
+#define RTW_5G_CHANNELS_NUM 37
+
+static struct ieee80211_channel rtw_2ghz_channels[] = {
+ CHAN2G(1, 2412, 0),
+ CHAN2G(2, 2417, 0),
+ CHAN2G(3, 2422, 0),
+ CHAN2G(4, 2427, 0),
+ CHAN2G(5, 2432, 0),
+ CHAN2G(6, 2437, 0),
+ CHAN2G(7, 2442, 0),
+ CHAN2G(8, 2447, 0),
+ CHAN2G(9, 2452, 0),
+ CHAN2G(10, 2457, 0),
+ CHAN2G(11, 2462, 0),
+ CHAN2G(12, 2467, 0),
+ CHAN2G(13, 2472, 0),
+ CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel rtw_5ghz_a_channels[] = {
+ CHAN5G(34, 0), CHAN5G(36, 0),
+ CHAN5G(38, 0), CHAN5G(40, 0),
+ CHAN5G(42, 0), CHAN5G(44, 0),
+ CHAN5G(46, 0), CHAN5G(48, 0),
+ CHAN5G(52, 0), CHAN5G(56, 0),
+ CHAN5G(60, 0), CHAN5G(64, 0),
+ CHAN5G(100, 0), CHAN5G(104, 0),
+ CHAN5G(108, 0), CHAN5G(112, 0),
+ CHAN5G(116, 0), CHAN5G(120, 0),
+ CHAN5G(124, 0), CHAN5G(128, 0),
+ CHAN5G(132, 0), CHAN5G(136, 0),
+ CHAN5G(140, 0), CHAN5G(149, 0),
+ CHAN5G(153, 0), CHAN5G(157, 0),
+ CHAN5G(161, 0), CHAN5G(165, 0),
+ CHAN5G(184, 0), CHAN5G(188, 0),
+ CHAN5G(192, 0), CHAN5G(196, 0),
+ CHAN5G(200, 0), CHAN5G(204, 0),
+ CHAN5G(208, 0), CHAN5G(212, 0),
+ CHAN5G(216, 0),
+};
+
+
+void rtw_2g_channels_init(struct ieee80211_channel *channels)
+{
+ _rtw_memcpy((void*)channels, (void*)rtw_2ghz_channels,
+ sizeof(struct ieee80211_channel)*RTW_2G_CHANNELS_NUM
+ );
+}
+
+void rtw_5g_channels_init(struct ieee80211_channel *channels)
+{
+ _rtw_memcpy((void*)channels, (void*)rtw_5ghz_a_channels,
+ sizeof(struct ieee80211_channel)*RTW_5G_CHANNELS_NUM
+ );
+}
+
+void rtw_2g_rates_init(struct ieee80211_rate *rates)
+{
+ _rtw_memcpy(rates, rtw_g_rates,
+ sizeof(struct ieee80211_rate)*RTW_G_RATES_NUM
+ );
+}
+
+void rtw_5g_rates_init(struct ieee80211_rate *rates)
+{
+ _rtw_memcpy(rates, rtw_a_rates,
+ sizeof(struct ieee80211_rate)*RTW_A_RATES_NUM
+ );
+}
+
+struct ieee80211_supported_band *rtw_spt_band_alloc(
+ enum ieee80211_band band
+ )
+{
+ struct ieee80211_supported_band *spt_band = NULL;
+ int n_channels, n_bitrates;
+
+ if(band == IEEE80211_BAND_2GHZ)
+ {
+ n_channels = RTW_2G_CHANNELS_NUM;
+ n_bitrates = RTW_G_RATES_NUM;
+ }
+ else if(band == IEEE80211_BAND_5GHZ)
+ {
+ n_channels = RTW_5G_CHANNELS_NUM;
+ n_bitrates = RTW_A_RATES_NUM;
+ }
+ else
+ {
+ goto exit;
+ }
+
+ spt_band = (struct ieee80211_supported_band *)rtw_zmalloc(
+ sizeof(struct ieee80211_supported_band)
+ + sizeof(struct ieee80211_channel)*n_channels
+ + sizeof(struct ieee80211_rate)*n_bitrates
+ );
+ if(!spt_band)
+ goto exit;
+
+ spt_band->channels = (struct ieee80211_channel*)(((u8*)spt_band)+sizeof(struct ieee80211_supported_band));
+ spt_band->bitrates= (struct ieee80211_rate*)(((u8*)spt_band->channels)+sizeof(struct ieee80211_channel)*n_channels);
+ spt_band->band = band;
+ spt_band->n_channels = n_channels;
+ spt_band->n_bitrates = n_bitrates;
+
+ if(band == IEEE80211_BAND_2GHZ)
+ {
+ rtw_2g_channels_init(spt_band->channels);
+ rtw_2g_rates_init(spt_band->bitrates);
+ }
+ else if(band == IEEE80211_BAND_5GHZ)
+ {
+ rtw_5g_channels_init(spt_band->channels);
+ rtw_5g_rates_init(spt_band->bitrates);
+ }
+
+ //spt_band.ht_cap
+
+exit:
+
+ return spt_band;
+}
+
+void rtw_spt_band_free(struct ieee80211_supported_band *spt_band)
+{
+ u32 size;
+
+ if(!spt_band)
+ return;
+
+ if(spt_band->band == IEEE80211_BAND_2GHZ)
+ {
+ size = sizeof(struct ieee80211_supported_band)
+ + sizeof(struct ieee80211_channel)*RTW_2G_CHANNELS_NUM
+ + sizeof(struct ieee80211_rate)*RTW_G_RATES_NUM;
+ }
+ else if(spt_band->band == IEEE80211_BAND_5GHZ)
+ {
+ size = sizeof(struct ieee80211_supported_band)
+ + sizeof(struct ieee80211_channel)*RTW_5G_CHANNELS_NUM
+ + sizeof(struct ieee80211_rate)*RTW_A_RATES_NUM;
+ }
+ else
+ {
+
+ }
+ rtw_mfree((u8*)spt_band, size);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+static const struct ieee80211_txrx_stypes
+rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+ [NL80211_IFTYPE_ADHOC] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_STATION] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_AP] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_AP_VLAN] = {
+ /* copy AP */
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_P2P_CLIENT] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_P2P_GO] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+};
+#endif
+
+static int rtw_ieee80211_channel_to_frequency(int chan, int band)
+{
+ /* see 802.11 17.3.8.3.2 and Annex J
+ * there are overlapping channel numbers in 5GHz and 2GHz bands */
+
+ if (band == IEEE80211_BAND_5GHZ) {
+ if (chan >= 182 && chan <= 196)
+ return 4000 + chan * 5;
+ else
+ return 5000 + chan * 5;
+ } else { /* IEEE80211_BAND_2GHZ */
+ if (chan == 14)
+ return 2484;
+ else if (chan < 14)
+ return 2407 + chan * 5;
+ else
+ return 0; /* not supported */
+ }
+}
+
+static int rtw_cfg80211_inform_bss(_adapter *padapter, struct wlan_network *pnetwork)
+{
+ int ret=0;
+ struct ieee80211_channel *notify_channel;
+ struct cfg80211_bss *bss;
+ //struct ieee80211_supported_band *band;
+ u16 channel;
+ u32 freq;
+ u64 notify_timestamp;
+ u16 notify_capability;
+ u16 notify_interval;
+ u8 *notify_ie;
+ size_t notify_ielen;
+ s32 notify_signal;
+ u8 buf[768], *pbuf;
+ size_t len;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ unsigned short *fctrl;
+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ struct wireless_dev *wdev = padapter->rtw_wdev;
+ struct wiphy *wiphy = wdev->wiphy;
+
+
+ //printk("%s\n", __func__);
+
+
+ channel = pnetwork->network.Configuration.DSConfig;
+ if (channel <= RTW_CH_MAX_2G_CHANNEL)
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+ else
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
+
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ //rtw_get_timestampe_from_ie()
+ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
+
+ notify_interval = le16_to_cpu(*(u16*)rtw_get_beacon_interval_from_ie(pnetwork->network.IEs));
+ notify_capability = le16_to_cpu(*(u16*)rtw_get_capability_from_ie(pnetwork->network.IEs));
+
+
+ notify_ie = pnetwork->network.IEs+_FIXED_IE_LENGTH_;
+ notify_ielen = pnetwork->network.IELength-_FIXED_IE_LENGTH_;
+
+ //notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
+
+ //We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm)
+ notify_signal = 100*translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);//dbm
+
+/*
+ printk("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ pnetwork->network.MacAddress[0], pnetwork->network.MacAddress[1], pnetwork->network.MacAddress[2],
+ pnetwork->network.MacAddress[3], pnetwork->network.MacAddress[4], pnetwork->network.MacAddress[5]);
+ printk("Channel: %d(%d)\n", channel, freq);
+ printk("Capability: %X\n", notify_capability);
+ printk("Beacon interval: %d\n", notify_interval);
+ printk("Signal: %d\n", notify_signal);
+ printk("notify_timestamp: %#018llx\n", notify_timestamp);
+*/
+
+ pbuf = buf;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pbuf;
+ fctrl = &(pwlanhdr->frame_ctl);
+ *(fctrl) = 0;
+
+ SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
+ //pmlmeext->mgnt_seq++;
+
+ if (pnetwork->network.Reserved[0] == 1) { // WIFI_BEACON
+ _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+ SetFrameSubType(pbuf, WIFI_BEACON);
+ } else {
+ _rtw_memcpy(pwlanhdr->addr1, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ SetFrameSubType(pbuf, WIFI_PROBERSP);
+ }
+
+ _rtw_memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);
+
+
+ pbuf += sizeof(struct rtw_ieee80211_hdr_3addr);
+ len = sizeof (struct rtw_ieee80211_hdr_3addr);
+
+ _rtw_memcpy(pbuf, pnetwork->network.IEs, pnetwork->network.IELength);
+ len += pnetwork->network.IELength;
+
+ //#ifdef CONFIG_P2P
+ //if(rtw_get_p2p_ie(pnetwork->network.IEs+12, pnetwork->network.IELength-12, NULL, NULL))
+ //{
+ // printk("%s, got p2p_ie\n", __func__);
+ //}
+ //#endif
+
+
+#if 1
+ bss = cfg80211_inform_bss_frame(wiphy, notify_channel, (struct ieee80211_mgmt *)buf,
+ len, notify_signal, GFP_ATOMIC);
+#else
+
+ bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)pnetwork->network.MacAddress,
+ notify_timestamp, notify_capability, notify_interval, notify_ie,
+ notify_ielen, notify_signal, GFP_ATOMIC/*GFP_KERNEL*/);
+#endif
+
+ if (unlikely(!bss)) {
+ printk("rtw_cfg80211_inform_bss error\n");
+ return -EINVAL;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef COMPAT_KERNEL_RELEASE
+ //patch for cfg80211, update beacon ies to information_elements
+ if (pnetwork->network.Reserved[0] == 1) { // WIFI_BEACON
+
+ if(bss->len_information_elements != bss->len_beacon_ies)
+ {
+ bss->information_elements = bss->beacon_ies;
+ bss->len_information_elements = bss->len_beacon_ies;
+ }
+ }
+#endif //COMPAT_KERNEL_RELEASE
+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+
+/*
+ {
+ if( bss->information_elements == bss->proberesp_ies)
+ {
+ if( bss->len_information_elements != bss->len_proberesp_ies)
+ {
+ printk("error!, len_information_elements != bss->len_proberesp_ies\n");
+ }
+
+ }
+ else if(bss->len_information_elements < bss->len_beacon_ies)
+ {
+ bss->information_elements = bss->beacon_ies;
+ bss->len_information_elements = bss->len_beacon_ies;
+ }
+ }
+*/
+
+ cfg80211_put_bss(bss);
+
+ return ret;
+
+}
+
+void rtw_cfg80211_indicate_connect(_adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+ struct wireless_dev *pwdev = padapter->rtw_wdev;
+#ifdef CONFIG_P2P
+ struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif
+
+
+ printk("%s(padapter=%p)\n", __func__, padapter);
+
+ if (pwdev->iftype != NL80211_IFTYPE_STATION
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ && pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT
+ #endif
+ ) {
+ return;
+ }
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+ return;
+
+#ifdef CONFIG_P2P
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ printk("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
+ }
+#endif //CONFIG_P2P
+
+ #ifdef CONFIG_LAYER2_ROAMING
+ if(pmlmepriv->to_roaming > 0) {
+ //rtw_cfg80211_inform_bss(padapter, cur_network);
+ DBG_871X("%s call cfg80211_roamed\n", __FUNCTION__);
+ cfg80211_roamed(padapter->pnetdev,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)
+ NULL,
+ #endif
+ cur_network->network.MacAddress,
+ cur_network->network.IEs+_FIXED_IE_LENGTH_, cur_network->network.IELength-_FIXED_IE_LENGTH_,
+ NULL, 0, GFP_ATOMIC
+ );
+ }
+ else
+ #endif
+ {
+ printk("pwdev->sme_state(b)=%d\n", pwdev->sme_state);
+ cfg80211_connect_result(padapter->pnetdev, cur_network->network.MacAddress, NULL, 0, NULL, 0,
+ WLAN_STATUS_SUCCESS, GFP_ATOMIC/*GFP_KERNEL*/);
+ printk("pwdev->sme_state(a)=%d\n", pwdev->sme_state);
+ }
+}
+
+void rtw_cfg80211_indicate_disconnect(_adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wireless_dev *pwdev = padapter->rtw_wdev;
+#ifdef CONFIG_P2P
+ struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif
+
+ printk("%s(padapter=%p)\n", __func__, padapter);
+
+ if (pwdev->iftype != NL80211_IFTYPE_STATION
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ && pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT
+ #endif
+ ) {
+ return;
+ }
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+ return;
+
+#ifdef CONFIG_P2P
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ _cancel_timer_ex( &pwdinfo->find_phase_timer );
+ _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+ _cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
+
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+
+ printk("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
+ }
+#endif //CONFIG_P2P
+
+ printk("pwdev->sme_state(b)=%d\n", pwdev->sme_state);
+
+ if(pwdev->sme_state==CFG80211_SME_CONNECTING)
+ cfg80211_connect_result(padapter->pnetdev, NULL, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC/*GFP_KERNEL*/);
+ else if(pwdev->sme_state==CFG80211_SME_CONNECTED)
+ cfg80211_disconnected(padapter->pnetdev, 0,
+ NULL, 0, GFP_ATOMIC);
+ //else
+ //printk("pwdev->sme_state=%d\n", pwdev->sme_state);
+
+ printk("pwdev->sme_state(a)=%d\n", pwdev->sme_state);
+
+}
+
+
+#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_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+ int ret = 0;
+ u32 wep_key_idx, wep_key_len,wep_total_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;
+ wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+ pwep =(NDIS_802_11_WEP *)rtw_malloc(wep_total_len);
+ if(pwep == NULL){
+ DBG_8192C(" r871x_set_encryption: pwep allocate fail !!!\n");
+ goto exit;
+ }
+
+ _rtw_memset(pwep, 0, wep_total_len);
+
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+
+ }
+
+ 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(param->u.crypt.set_tx == 0)
+ {
+ 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;
+
+ psta->bpairwise_key_installed = _TRUE;
+
+ }
+ 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_total_len);
+ }
+
+ return ret;
+
+}
+#endif
+
+static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+ int ret = 0;
+ u32 wep_key_idx, wep_key_len,wep_total_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_;
+
+ printk("%s\n", __func__);
+
+ 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;
+ wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+ pwep =(NDIS_802_11_WEP *) rtw_malloc(wep_total_len);
+ 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, wep_total_len);
+
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+
+ 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;
+
+ //printk("%s, : dot11AuthAlgrthm == dot11AuthAlgrthm_8021X \n", __func__);
+
+ 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"));
+ printk("%s, : Obtain Sta_info fail \n", __func__);
+ }
+ 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
+ {
+
+ printk("%s, : param->u.crypt.set_tx ==1 \n", __func__);
+
+ _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(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+ {
+ rtw_p2p_set_state(pwdinfo, 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:
+
+ printk("%s, ret=%d\n", __func__, ret);
+
+ if (pwep) {
+ rtw_mfree((u8 *)pwep,wep_total_len);
+ }
+
+ _func_exit_;
+
+ return ret;
+}
+
+static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ u8 key_index, const u8 *mac_addr,
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ struct key_params *params)
+{
+ char *alg_name;
+ u32 param_len;
+ struct ieee_param *param = NULL;
+ int ret=0;
+ struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ DBG_871X(FUNC_NDEV_FMT" adding key for %pM\n", FUNC_NDEV_ARG(ndev), mac_addr);
+ DBG_871X("cipher=0x%x\n", params->cipher);
+ DBG_871X("key_len=0x%x\n", params->key_len);
+ DBG_871X("seq_len=0x%x\n", params->seq_len);
+ DBG_871X("key_index=%d\n", key_index);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ DBG_871X("pairwise=%d\n", pairwise);
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+
+ param_len = sizeof(struct ieee_param) + params->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 (params->cipher) {
+ case IW_AUTH_CIPHER_NONE:
+ //todo: remove key
+ //remove = 1;
+ alg_name = "none";
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ alg_name = "WEP";
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ alg_name = "TKIP";
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ alg_name = "CCMP";
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
+
+
+ if (!mac_addr || is_broadcast_ether_addr(mac_addr))
+ {
+ param->u.crypt.set_tx = 0;
+ } else {
+ param->u.crypt.set_tx = 1;
+ }
+
+
+ //param->u.crypt.idx = key_index - 1;
+ param->u.crypt.idx = key_index;
+
+ if (params->seq_len && params->seq)
+ {
+ _rtw_memcpy(param->u.crypt.seq, params->seq, params->seq_len);
+ }
+
+ if(params->key_len && params->key)
+ {
+ param->u.crypt.key_len = params->key_len;
+ _rtw_memcpy(param->u.crypt.key, params->key, params->key_len);
+ }
+
+ //if(rtw_wdev->iftype == NL80211_IFTYPE_STATION)
+ if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+ {
+ ret = rtw_cfg80211_set_encryption(ndev, param, param_len);
+ }
+ else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)//else if(rtw_wdev->iftype == NL80211_IFTYPE_AP)
+ {
+#ifdef CONFIG_AP_MODE
+ if(mac_addr)
+ _rtw_memcpy(param->sta_addr, (void*)mac_addr, ETH_ALEN);
+
+ ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len);
+#endif
+ }
+ else
+ {
+ printk("error! fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype);
+
+ }
+
+ if(param)
+ {
+ rtw_mfree((u8*)param, param_len);
+ }
+
+ return ret;
+
+}
+
+static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ u8 key_index, const u8 *mac_addr,
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ void *cookie,
+ void (*callback)(void *cookie,
+ struct key_params*))
+{
+#if 0
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+ struct iwm_key *key = &iwm->keys[key_index];
+ struct key_params params;
+
+ IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
+
+ memset(&params, 0, sizeof(params));
+
+ params.cipher = key->cipher;
+ params.key_len = key->key_len;
+ params.seq_len = key->seq_len;
+ params.seq = key->seq;
+ params.key = key->key;
+
+ callback(cookie, &params);
+
+ return key->key_len ? 0 : -ENOENT;
+#endif
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ return 0;
+}
+
+static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ u8 key_index, bool pairwise, const u8 *mac_addr)
+#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ u8 key_index, const u8 *mac_addr)
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+{
+#if 0
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+ struct iwm_key *key = &iwm->keys[key_index];
+
+ if (!iwm->keys[key_index].key_len) {
+ IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
+ return 0;
+ }
+
+ if (key_index == iwm->default_key)
+ iwm->default_key = -1;
+
+ return iwm_set_key(iwm, 1, key);
+#endif
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ return 0;
+}
+
+static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
+ struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)
+ u8 key_index, bool unicast, bool multicast)
+#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ u8 key_index)
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+{
+#if 0
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+
+ IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
+
+ if (!iwm->keys[key_index].key_len) {
+ IWM_ERR(iwm, "Key %d not used\n", key_index);
+ return -EINVAL;
+ }
+
+ iwm->default_key = key_index;
+
+ return iwm_set_tx_key(iwm, key_index);
+#endif
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ return 0;
+}
+
+static int cfg80211_rtw_get_station(struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 *mac, struct station_info *sinfo)
+{
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if(!mac) {
+ DBG_871X(FUNC_NDEV_FMT" mac==%p\n", FUNC_NDEV_ARG(ndev), mac);
+ return -ENOENT;
+ }
+
+#ifdef CONFIG_DEBUG_CFG80211
+ DBG_871X(FUNC_NDEV_FMT" mac="MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));
+#endif
+
+ //for infra./P2PClient mode
+ if( check_fwstate(pmlmepriv, WIFI_STATION_STATE)
+ && check_fwstate(pmlmepriv, _FW_LINKED)
+ )
+ {
+ struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+
+ if (_rtw_memcmp(mac, cur_network->network.MacAddress, ETH_ALEN) == _FALSE)
+ {
+ DBG_871X("%s, mismatch bssid="MAC_FMT"\n", __func__, MAC_ARG(cur_network->network.MacAddress));
+ return -ENOENT;
+ }
+
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
+
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+ sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
+ }
+
+ //for Ad-Hoc/AP mode
+ if ( ( check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)
+ ||check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)
+ ||check_fwstate(pmlmepriv, WIFI_AP_STATE) )
+ && check_fwstate(pmlmepriv, _FW_LINKED)
+ )
+ {
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ psta = rtw_get_stainfo(pstapriv, mac);
+ if(psta == NULL)
+ {
+ printk("%s, sta_info is null\n", __func__);
+ return -ENOENT;
+ }
+
+ //TODO: should acquire station info...
+ }
+
+ return 0;
+}
+
+extern int netdev_open(struct net_device *pnetdev);
+#ifdef CONFIG_CONCURRENT_MODE
+extern int netdev_if2_open(struct net_device *pnetdev);
+#endif
+
+static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
+ struct net_device *ndev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ enum nl80211_iftype old_type;
+ NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
+#ifdef CONFIG_P2P
+ struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif
+ int ret = 0;
+ u8 change = _FALSE;
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(!padapter->isprimary)
+ {
+ DBG_871X(FUNC_NDEV_FMT" call netdev_if2_open\n", FUNC_NDEV_ARG(ndev));
+ if(netdev_if2_open(ndev) != 0) {
+ ret= -EPERM;
+ goto exit;
+ }
+ }
+ else
+#endif //CONFIG_CONCURRENT_MODE
+ {
+ DBG_871X(FUNC_NDEV_FMT" call netdev_open\n", FUNC_NDEV_ARG(ndev));
+ if(netdev_open(ndev) != 0) {
+ ret= -EPERM;
+ goto exit;
+ }
+ }
+
+ if(_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret= -EPERM;
+ goto exit;
+ }
+
+ old_type = rtw_wdev->iftype;
+ DBG_871X(FUNC_NDEV_FMT" old_iftype=%d, new_iftype=%d\n",
+ FUNC_NDEV_ARG(ndev), old_type, type);
+
+ if(old_type != type)
+ change = _TRUE;
+
+ switch (type) {
+ case NL80211_IFTYPE_ADHOC:
+ networkType = Ndis802_11IBSS;
+ break;
+#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE))
+ case NL80211_IFTYPE_P2P_CLIENT:
+#endif
+ case NL80211_IFTYPE_STATION:
+ networkType = Ndis802_11Infrastructure;
+ #ifdef CONFIG_P2P
+ if(change && rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+ {
+ _cancel_timer_ex( &pwdinfo->find_phase_timer );
+ _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+ _cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
+
+ //it means remove GO and change mode from AP(GO) to station(P2P DEVICE)
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+
+ printk("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
+ }
+ #endif //CONFIG_P2P
+ break;
+#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE))
+ case NL80211_IFTYPE_P2P_GO:
+#endif
+ case NL80211_IFTYPE_AP:
+ networkType = Ndis802_11APMode;
+ #ifdef CONFIG_P2P
+ if(change && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ //it means P2P Group created, we will be GO and change mode from P2P DEVICE to AP(GO)
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ }
+ #endif //CONFIG_P2P
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ rtw_wdev->iftype = type;
+
+ if (rtw_set_802_11_infrastructure_mode(padapter, networkType) ==_FALSE)
+ {
+ rtw_wdev->iftype = old_type;
+ ret = -EPERM;
+ goto exit;
+ }
+
+ rtw_setopmode_cmd(padapter, networkType);
+
+exit:
+
+ return ret;
+}
+
+void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv, bool aborted)
+{
+ _irqL irqL;
+
+ _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+ if(pwdev_priv->scan_request != NULL)
+ {
+ //struct cfg80211_scan_request *scan_request = pwdev_priv->scan_request;
+
+ #ifdef CONFIG_DEBUG_CFG80211
+ DBG_871X("%s with scan req\n", __FUNCTION__);
+ #endif
+
+ //avoid WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
+ //if(scan_request == wiphy_to_dev(scan_request->wiphy)->scan_req)
+ if(pwdev_priv->scan_request->wiphy != pwdev_priv->rtw_wdev->wiphy)
+ {
+ printk("error wiphy compare\n");
+ }
+ else
+ {
+ cfg80211_scan_done(pwdev_priv->scan_request, aborted);
+ }
+
+ pwdev_priv->scan_request = NULL;
+
+ } else {
+ #ifdef CONFIG_DEBUG_CFG80211
+ DBG_871X("%s without scan req\n", __FUNCTION__);
+ #endif
+ }
+ _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+}
+
+void rtw_cfg80211_surveydone_event_callback(_adapter *padapter)
+{
+ _irqL irqL;
+ _list *plist, *phead;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ _queue *queue = &(pmlmepriv->scanned_queue);
+ struct wlan_network *pnetwork = NULL;
+ u32 cnt=0;
+ u32 wait_for_surveydone;
+ sint wait_status;
+#ifdef CONFIG_P2P
+ struct wifidirect_info* pwdinfo = &padapter->wdinfo;
+#endif //CONFIG_P2P
+ struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s\n", __func__);
+#endif
+
+#if 0
+ if(padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped)
+ {
+ return;
+ }
+
+#ifdef CONFIG_P2P
+ if(!rtw_p2p_chk_state(pwdinfo, 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
+
+
+ wait_status = _FW_UNDER_SURVEY
+ #ifndef CONFIG_ANDROID
+ |_FW_UNDER_LINKING
+ #endif
+ ;
+
+ while(check_fwstate(pmlmepriv, wait_status) == _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;
+
+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+ //report network only if the current channel set contains the channel to which this network belongs
+ if( _TRUE == rtw_is_channel_set_contains_channel(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig)
+ #ifdef CONFIG_VALIDATE_SSID
+ && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))
+ #endif
+ )
+ {
+ //ev=translate_scan(padapter, a, pnetwork, ev, stop);
+ rtw_cfg80211_inform_bss(padapter, pnetwork);
+ }
+
+ plist = get_next(plist);
+
+ }
+
+ _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+
+ #if 0
+ // Disable P2P Listen State
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ _cancel_timer_ex( &pwdinfo->find_phase_timer );
+ _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+ _cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
+
+ //rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
+#endif
+
+ if(pwrpriv->bips_processing == _FALSE){
+ rtw_set_pwr_state_check_timer(pwrpriv);
+ }
+ }
+ #endif
+
+ //call this after other things have been done
+ rtw_indicate_scan_done(padapter, _FALSE);
+
+}
+
+static int rtw_cfg80211_set_probe_req_wpsp2pie(struct net_device *net, char *buf, int len)
+{
+ int ret = 0;
+ uint wps_ielen = 0;
+ u8 *wps_ie;
+ u32 p2p_ielen = 0;
+ u8 *p2p_ie;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, ielen=%d\n", __func__, len);
+#endif
+
+ if(len>0)
+ {
+ if((wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen)))
+ {
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("probe_req_wps_ielen=%d\n", wps_ielen);
+ #endif
+
+ if(pmlmepriv->wps_probe_req_ie)
+ {
+ u32 free_len = pmlmepriv->wps_probe_req_ie_len;
+ pmlmepriv->wps_probe_req_ie_len = 0;
+ rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
+ pmlmepriv->wps_probe_req_ie = NULL;
+ }
+
+ pmlmepriv->wps_probe_req_ie = rtw_malloc(wps_ielen);
+ if ( pmlmepriv->wps_probe_req_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+ _rtw_memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);
+ pmlmepriv->wps_probe_req_ie_len = wps_ielen;
+ }
+
+ buf += wps_ielen;
+ len -= wps_ielen;
+
+ #ifdef CONFIG_P2P
+ if((p2p_ie=rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen)))
+ {
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("probe_req_p2p_ielen=%d\n", p2p_ielen);
+ #endif
+
+ if(pmlmepriv->p2p_probe_req_ie)
+ {
+ u32 free_len = pmlmepriv->p2p_probe_req_ie_len;
+ pmlmepriv->p2p_probe_req_ie_len = 0;
+ rtw_mfree(pmlmepriv->p2p_probe_req_ie, free_len);
+ pmlmepriv->p2p_probe_req_ie = NULL;
+ }
+
+ pmlmepriv->p2p_probe_req_ie = rtw_malloc(len);
+ if ( pmlmepriv->p2p_probe_req_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+ _rtw_memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);
+ pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;
+ }
+ #endif //CONFIG_P2P
+
+ }
+
+ return ret;
+
+}
+
+void rtw_cfg80211_scan_abort(_adapter *padapter)
+{
+ u32 cnt=0;
+ u32 wait_for_surveydone;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+//#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s\n", __func__);
+//#endif
+
+ wait_for_surveydone = 10;
+
+ pmlmeext->scan_abort = _TRUE;
+
+ while(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
+ {
+ printk("%s : fw_state=_FW_UNDER_SURVEY!\n", __func__);
+
+ rtw_msleep_os(20);
+ cnt++;
+ if(cnt > wait_for_surveydone )
+ {
+ printk("waiting for scan_abort time out!\n");
+
+#ifdef CONFIG_PLATFORM_MSTAR_TITANIA12
+ //_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ set_survey_timer(pmlmeext, 0);
+ _set_timer(&pmlmepriv->scan_to_timer, 50);
+#endif
+ break;
+ }
+ }
+
+ pmlmeext->scan_abort = _FALSE;
+
+ rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev), _TRUE);
+
+}
+
+static int cfg80211_rtw_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request)
+{
+ int i;
+ u8 _status = _FALSE;
+ int ret = 0;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct mlme_priv *pmlmepriv= &padapter->mlmepriv;
+ NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];
+ _irqL irqL;
+ u8 *wps_ie=NULL;
+ uint wps_ielen=0;
+ u8 *p2p_ie=NULL;
+ uint p2p_ielen=0;
+#ifdef CONFIG_P2P
+ struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif //CONFIG_P2P
+ struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
+ struct cfg80211_ssid *ssids = request->ssids;
+ int social_channel = 0, j = 0;
+ bool need_indicate_scan_done = _FALSE;
+#ifdef CONFIG_CONCURRENT_MODE
+ PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
+#endif
+
+#ifdef CONFIG_DEBUG_CFG80211
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+#endif
+
+#ifdef CONFIG_MP_INCLUDED
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
+ {
+ ret = -EPERM;
+ goto exit;
+ }
+#endif
+
+ _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+ pwdev_priv->scan_request = request;
+ _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+ {
+
+#ifdef CONFIG_DEBUG_CFG80211
+ DBG_871X("%s under WIFI_AP_STATE\n", __FUNCTION__);
+#endif
+ //need_indicate_scan_done = _TRUE;
+ //goto check_need_indicate_scan_done;
+ }
+
+ if(_FAIL == rtw_pwr_wakeup(padapter)) {
+ need_indicate_scan_done = _TRUE;
+ goto check_need_indicate_scan_done;
+ }
+
+ #ifdef CONFIG_P2P
+ if( ssids->ssid != NULL )
+ {
+ if( _rtw_memcmp(ssids->ssid, "DIRECT-", 7)
+ && rtw_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)
+ )
+ {
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
+ wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = _TRUE;
+ }
+ else
+ {
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
+ #endif
+ }
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+
+ if(request->n_channels == 3 &&
+ request->channels[0]->hw_value == 1 &&
+ request->channels[1]->hw_value == 6 &&
+ request->channels[2]->hw_value == 11
+ )
+ {
+ social_channel = 1;
+ }
+ }
+ }
+ #endif //CONFIG_P2P
+
+ if(request->ie && request->ie_len>0)
+ {
+ rtw_cfg80211_set_probe_req_wpsp2pie( ndev, (u8 *)request->ie, request->ie_len );
+ }
+
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)
+ {
+ printk("%s, bBusyTraffic == _TRUE\n", __func__);
+ need_indicate_scan_done = _TRUE;
+ goto check_need_indicate_scan_done;
+ }
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(pbuddy_mlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)
+ {
+ printk("%s, bBusyTraffic == _TRUE at buddy_intf\n", __func__);
+ need_indicate_scan_done = _TRUE;
+ goto check_need_indicate_scan_done;
+ }
+#endif
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
+ {
+ printk("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);
+ need_indicate_scan_done = _TRUE;
+ goto check_need_indicate_scan_done;
+ }
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if (check_fwstate(pbuddy_mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
+ {
+ if(check_fwstate(pbuddy_mlmepriv, _FW_UNDER_SURVEY))
+ {
+ printk("scanning_via_buddy_intf\n");
+ pmlmepriv->scanning_via_buddy_intf = _TRUE;
+ }
+
+ printk("buddy_intf is now scanning or connecting\n");
+
+ need_indicate_scan_done = _TRUE;
+ goto check_need_indicate_scan_done;
+ }
+#endif
+
+
+#ifdef CONFIG_P2P
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
+ {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+ rtw_free_network_queue(padapter, _TRUE);
+
+ if(social_channel == 0)
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+ else
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_SOCIAL_LAST);
+ }
+#endif //CONFIG_P2P
+
+
+ _rtw_memset(ssid, 0, sizeof(NDIS_802_11_SSID)*RTW_SSID_SCAN_AMOUNT);
+ //parsing request ssids, n_ssids
+ for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("ssid=%s, len=%d\n", ssids[i].ssid, ssids[i].ssid_len);
+ #endif
+ _rtw_memcpy(ssid[i].Ssid, ssids[i].ssid, ssids[i].ssid_len);
+ ssid[i].SsidLength = ssids[i].ssid_len;
+ }
+
+
+#ifdef CONFIG_DEBUG_CFG80211
+ //parsing channels, n_channels
+ DBG_871X("%s n_channels:%u\n", __FUNCTION__, request->n_channels);
+#endif
+
+ _enter_critical_bh(&pmlmepriv->lock, &irqL);
+ _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
+ _exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+
+ if(_status == _FALSE)
+ {
+ ret = -1;
+ }
+
+check_need_indicate_scan_done:
+ if(need_indicate_scan_done)
+ rtw_cfg80211_surveydone_event_callback(padapter);
+
+exit:
+
+ return ret;
+
+}
+
+static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+#if 0
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+ (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
+ int ret;
+
+ iwm->conf.rts_threshold = wiphy->rts_threshold;
+
+ ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+ CFG_RTS_THRESHOLD,
+ iwm->conf.rts_threshold);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+ (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
+ int ret;
+
+ iwm->conf.frag_threshold = wiphy->frag_threshold;
+
+ ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
+ CFG_FRAG_THRESHOLD,
+ iwm->conf.frag_threshold);
+ if (ret < 0)
+ return ret;
+ }
+#endif
+ printk("%s\n", __func__);
+ return 0;
+}
+
+static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_ibss_params *params)
+{
+#if 0
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+ struct ieee80211_channel *chan = params->channel;
+
+ if (!test_bit(IWM_STATUS_READY, &iwm->status))
+ return -EIO;
+
+ /* UMAC doesn't support creating or joining an IBSS network
+ * with specified bssid. */
+ if (params->bssid)
+ return -EOPNOTSUPP;
+
+ iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
+ iwm->umac_profile->ibss.band = chan->band;
+ iwm->umac_profile->ibss.channel = iwm->channel;
+ iwm->umac_profile->ssid.ssid_len = params->ssid_len;
+ memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
+
+ return iwm_send_mlme_profile(iwm);
+#endif
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ return 0;
+}
+
+static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
+{
+#if 0
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+ if (iwm->umac_profile_active)
+ return iwm_invalidate_mlme_profile(iwm);
+#endif
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ return 0;
+}
+
+static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32 wpa_version)
+{
+ printk("%s, wpa_version=%d\n", __func__, wpa_version);
+
+
+ if (!wpa_version) {
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+ return 0;
+ }
+
+
+ if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
+ {
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
+ }
+
+/*
+ if (wpa_version & NL80211_WPA_VERSION_2)
+ {
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
+ }
+*/
+
+ return 0;
+
+}
+
+static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
+ enum nl80211_auth_type sme_auth_type)
+{
+ printk("%s, nl80211_auth_type=%d\n", __func__, sme_auth_type);
+
+
+ switch (sme_auth_type) {
+ case NL80211_AUTHTYPE_AUTOMATIC:
+
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+
+ break;
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+
+ if(psecuritypriv->ndisauthtype>Ndis802_11AuthModeWPA)
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+
+ psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+
+ break;
+ default:
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ //return -ENOTSUPP;
+ }
+
+ return 0;
+
+}
+
+static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 cipher, bool ucast)
+{
+ u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
+
+ u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
+ &psecuritypriv->dot118021XGrpPrivacy;
+
+ printk("%s, ucast=%d, cipher=0x%x\n", __func__, ucast, cipher);
+
+
+ if (!cipher) {
+ *profile_cipher = _NO_PRIVACY_;
+ psecuritypriv->ndisencryptstatus = ndisencryptstatus;
+ return 0;
+ }
+
+ switch (cipher) {
+ case IW_AUTH_CIPHER_NONE:
+ *profile_cipher = _NO_PRIVACY_;
+ ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ *profile_cipher = _WEP40_;
+ ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ *profile_cipher = _WEP104_;
+ ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ *profile_cipher = _TKIP_;
+ ndisencryptstatus = Ndis802_11Encryption2Enabled;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ *profile_cipher = _AES_;
+ ndisencryptstatus = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ printk("Unsupported cipher: 0x%x\n", cipher);
+ return -ENOTSUPP;
+ }
+
+ if(ucast)
+ {
+ psecuritypriv->ndisencryptstatus = ndisencryptstatus;
+
+ //if(psecuritypriv->dot11PrivacyAlgrthm >= _AES_)
+ // psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
+ }
+
+ return 0;
+}
+
+static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, u32 key_mgt)
+{
+ printk("%s, key_mgt=0x%x\n", __func__, key_mgt);
+
+ if (key_mgt == WLAN_AKM_SUITE_8021X)
+ //*auth_type = UMAC_AUTH_TYPE_8021X;
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+ else if (key_mgt == WLAN_AKM_SUITE_PSK) {
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+ } else {
+ printk("Invalid key mgt: 0x%x\n", key_mgt);
+ //return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rtw_cfg80211_set_wpa_ie(_adapter *padapter, u8 *pie, size_t 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
+ int wpa_ielen=0;
+ int wpa2_ielen=0;
+ u8 *pwpa, *pwpa2;
+
+
+ if((ielen > MAX_WPA_IE_LEN+MAX_WPS_IE_LEN+MAX_P2P_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("set 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
+
+ pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen);
+ pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen);
+
+ if(pwpa && wpa_ielen>0)
+ {
+ if(rtw_parse_wpa_ie(pwpa, wpa_ielen+2, &group_cipher, &pairwise_cipher) == _SUCCESS)
+ {
+ padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
+ padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPAPSK;
+ _rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen+2);
+
+ printk("got wpa_ie\n");
+ }
+ }
+
+ if(pwpa2 && wpa2_ielen>0)
+ {
+ if(rtw_parse_wpa2_ie(pwpa2, wpa2_ielen+2, &group_cipher, &pairwise_cipher) == _SUCCESS)
+ {
+ padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
+ padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPA2PSK;
+ _rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0], wpa2_ielen+2);
+
+ printk("got wpa2_ie\n");
+ }
+ }
+
+ 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};
+ uint wps_ielen=0;
+ u8 *pwps;
+
+ pwps = rtw_get_wps_ie(buf, ielen, NULL, &wps_ielen);
+
+ //while( cnt < ielen )
+ while( cnt < wps_ielen )
+ {
+ //eid = buf[cnt];
+ eid = pwps[cnt];
+
+ if((eid==_VENDOR_SPECIFIC_IE_)&&(_rtw_memcmp(&pwps[cnt+2], wps_oui, 4)==_TRUE))
+ {
+ DBG_8192C("SET WPS_IE\n");
+
+ padapter->securitypriv.wps_ie_len = ( (pwps[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (pwps[cnt+1]+2):(MAX_WPA_IE_LEN<<2);
+
+ _rtw_memcpy(padapter->securitypriv.wps_ie, &pwps[cnt], padapter->securitypriv.wps_ie_len);
+
+ if(pwpa==NULL && pwpa2==NULL)
+ {
+ padapter->securitypriv.wps_phase = _TRUE;
+
+ DBG_8192C("SET WPS_IE, wps_phase==_TRUE\n");
+ }
+#ifdef CONFIG_P2P
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
+ {
+ //rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
+ }
+#endif //CONFIG_P2P
+
+ cnt += pwps[cnt+1]+2;
+
+ break;
+ } else {
+ cnt += pwps[cnt+1]+2; //goto next
+ }
+ }
+ }//set wps_ie
+
+ #ifdef CONFIG_P2P
+ {//check p2p_ie for assoc req;
+ uint p2p_ielen=0;
+ u8 *p2p_ie;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ if((p2p_ie=rtw_get_p2p_ie(buf, ielen, NULL, &p2p_ielen)))
+ {
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("%s p2p_assoc_req_ielen=%d\n", __FUNCTION__, p2p_ielen);
+ #endif
+
+ if(pmlmepriv->p2p_assoc_req_ie)
+ {
+ u32 free_len = pmlmepriv->p2p_assoc_req_ie_len;
+ pmlmepriv->p2p_assoc_req_ie_len = 0;
+ rtw_mfree(pmlmepriv->p2p_assoc_req_ie, free_len);
+ pmlmepriv->p2p_assoc_req_ie = NULL;
+ }
+
+ pmlmepriv->p2p_assoc_req_ie = rtw_malloc(p2p_ielen);
+ if ( pmlmepriv->p2p_assoc_req_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ goto exit;
+
+ }
+ _rtw_memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);
+ pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;
+
+ }
+ }
+ #endif //CONFIG_P2P
+
+ }
+
+
+ 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 cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_connect_params *sme)
+{
+ int ret=0;
+ _irqL irqL;
+ _list *phead;
+ struct wlan_network *pnetwork = NULL;
+ NDIS_802_11_AUTHENTICATION_MODE authmode;
+ NDIS_802_11_SSID ndis_ssid;
+ u8 *dst_ssid, *src_ssid;
+ u8 *dst_bssid, *src_bssid;
+ //u8 matched_by_bssid=_FALSE;
+ //u8 matched_by_ssid=_FALSE;
+ u8 matched=_FALSE;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ _queue *queue = &pmlmepriv->scanned_queue;
+
+ DBG_871X("=>"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ DBG_871X("privacy=%d, key=%p, key_len=%d, key_idx=%d\n",
+ sme->privacy, sme->key, sme->key_len, sme->key_idx);
+
+
+ if(wdev_to_priv(padapter->rtw_wdev)->block == _TRUE)
+ {
+ ret = -EBUSY;
+ DBG_871X("%s wdev_priv.block is set\n", __FUNCTION__);
+ goto exit;
+ }
+
+#ifdef CONFIG_PLATFORM_MSTAR_TITANIA12
+ printk("MStar Android!\n");
+ if((wdev_to_priv(padapter->rtw_wdev))->bandroid_scan == _FALSE)
+ {
+#ifdef CONFIG_P2P
+ struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+#endif //CONFIG_P2P
+ {
+ ret = -EBUSY;
+ printk("Android hasn't attached yet!\n");
+ goto exit;
+ }
+ }
+#endif
+
+ if(_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret= -EPERM;
+ goto exit;
+ }
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ ret = -EPERM;
+ goto exit;
+ }
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
+ {
+ printk("%s, but buddy_intf is under scanning or linking\n", __FUNCTION__);
+
+ ret = -EINVAL;
+
+ goto exit;
+ }
+#endif
+
+ if (!sme->ssid || !sme->ssid_len)
+ {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (sme->ssid_len > IW_ESSID_MAX_SIZE){
+
+ ret= -E2BIG;
+ goto exit;
+ }
+
+
+ _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
+ ndis_ssid.SsidLength = sme->ssid_len;
+ _rtw_memcpy(ndis_ssid.Ssid, sme->ssid, sme->ssid_len);
+
+ DBG_8192C("ssid=%s, len=%d\n", ndis_ssid.Ssid, sme->ssid_len);
+
+
+ if (sme->bssid)
+ printk("bssid="MAC_FMT"\n", MAC_ARG(sme->bssid));
+
+
+ if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
+ {
+ ret = -EBUSY;
+ printk("%s, fw_state=0x%x, goto exit\n", __FUNCTION__, pmlmepriv->fw_state);
+ goto exit;
+ }
+
+
+ _enter_critical_bh(&queue->lock, &irqL);
+
+ phead = get_list_head(queue);
+ pmlmepriv->pscanned = get_next(phead);
+
+ while (1)
+ {
+ if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == _TRUE)
+ {
+ break;
+ }
+
+ pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+ pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+
+ dst_ssid = pnetwork->network.Ssid.Ssid;
+ dst_bssid = pnetwork->network.MacAddress;
+
+ if(sme->bssid) {
+ if(_rtw_memcmp(pnetwork->network.MacAddress, sme->bssid, ETH_ALEN) == _FALSE)
+ continue;
+ }
+
+ if(sme->ssid && sme->ssid_len) {
+ if( pnetwork->network.Ssid.SsidLength != sme->ssid_len
+ || _rtw_memcmp(pnetwork->network.Ssid.Ssid, sme->ssid, sme->ssid_len) == _FALSE
+ )
+ continue;
+ }
+
+
+ if (sme->bssid)
+ {
+ src_bssid = sme->bssid;
+
+ if ((_rtw_memcmp(dst_bssid, src_bssid, ETH_ALEN)) == _TRUE)
+ {
+ printk("matched by bssid\n");
+
+ ndis_ssid.SsidLength = pnetwork->network.Ssid.SsidLength;
+ _rtw_memcpy(ndis_ssid.Ssid, pnetwork->network.Ssid.Ssid, pnetwork->network.Ssid.SsidLength);
+
+ matched=_TRUE;
+ break;
+ }
+
+ }
+ else if (sme->ssid && sme->ssid_len)
+ {
+ src_ssid = ndis_ssid.Ssid;
+
+ if ((_rtw_memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength) == _TRUE) &&
+ (pnetwork->network.Ssid.SsidLength==ndis_ssid.SsidLength))
+ {
+ printk("matched by ssid\n");
+ matched=_TRUE;
+ break;
+ }
+ }
+
+ }
+
+ _exit_critical_bh(&queue->lock, &irqL);
+
+ if((matched == _FALSE) || (pnetwork== NULL))
+ {
+ ret = -ENOENT;
+ printk("connect, matched == _FALSE, goto exit\n");
+ goto exit;
+ }
+
+
+ if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == _FALSE)
+ {
+ ret = -EPERM;
+ goto exit;
+ }
+
+
+ psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; //open system
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+
+
+ ret = rtw_cfg80211_set_wpa_version(psecuritypriv, sme->crypto.wpa_versions);
+ if (ret < 0)
+ goto exit;
+
+ ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
+ if (ret < 0)
+ goto exit;
+
+
+ if (sme->crypto.n_ciphers_pairwise) {
+ ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.ciphers_pairwise[0], _TRUE);
+ if (ret < 0)
+ goto exit;
+ }
+
+ //For WEP Shared auth
+ if((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared
+ || psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) && sme->key
+ )
+ {
+ u32 wep_key_idx, wep_key_len,wep_total_len;
+ NDIS_802_11_WEP *pwep = NULL;
+ DBG_871X("%s(): Shared/Auto WEP\n",__FUNCTION__);
+
+ wep_key_idx = sme->key_idx;
+ wep_key_len = sme->key_len;
+
+ if (sme->key_idx > WEP_KEYS) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (wep_key_len > 0)
+ {
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+ wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+ pwep =(NDIS_802_11_WEP *) rtw_malloc(wep_total_len);
+ if(pwep == NULL){
+ DBG_871X(" wpa_set_encryption: pwep allocate fail !!!\n");
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ _rtw_memset(pwep, 0, wep_total_len);
+
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+
+ 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, (void *)sme->key, pwep->KeyLength);
+
+ if(rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
+ {
+ ret = -EOPNOTSUPP ;
+ }
+
+ if (pwep) {
+ rtw_mfree((u8 *)pwep,wep_total_len);
+ }
+
+ if(ret < 0)
+ goto exit;
+ }
+
+ ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.cipher_group, _FALSE);
+ if (ret < 0)
+ return ret;
+
+ if (sme->crypto.n_akm_suites) {
+ ret = rtw_cfg80211_set_key_mgt(psecuritypriv, sme->crypto.akm_suites[0]);
+ if (ret < 0)
+ goto exit;
+ }
+
+ printk("%s, ie_len=%d\n", __func__, sme->ie_len);
+
+ ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
+ if (ret < 0)
+ goto exit;
+
+ authmode = psecuritypriv->ndisauthtype;
+ rtw_set_802_11_authentication_mode(padapter, authmode);
+
+ //rtw_set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);
+
+ if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {
+ ret = -1;
+ goto exit;
+ }
+
+
+ printk("set ssid:dot11AuthAlgrthm=%d, dot11PrivacyAlgrthm=%d, dot118021XGrpPrivacy=%d\n", psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, psecuritypriv->dot118021XGrpPrivacy);
+
+exit:
+
+ DBG_8192C("<=%s, ret %d\n",__FUNCTION__, ret);
+
+ return ret;
+}
+
+static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
+ u16 reason_code)
+{
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ 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, 1);
+ }
+
+ return 0;
+}
+
+static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) || defined(COMPAT_KERNEL_RELEASE)
+ enum nl80211_tx_power_setting type, int mbm)
+#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+ enum tx_power_setting type, int dbm)
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+{
+#if 0
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+ int ret;
+
+ switch (type) {
+ case NL80211_TX_POWER_AUTOMATIC:
+ return 0;
+ case NL80211_TX_POWER_FIXED:
+ if (mbm < 0 || (mbm % 100))
+ return -EOPNOTSUPP;
+
+ if (!test_bit(IWM_STATUS_READY, &iwm->status))
+ return 0;
+
+ ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+ CFG_TX_PWR_LIMIT_USR,
+ MBM_TO_DBM(mbm) * 2);
+ if (ret < 0)
+ return ret;
+
+ return iwm_tx_power_trigger(iwm);
+ default:
+ IWM_ERR(iwm, "Unsupported power type: %d\n", type);
+ return -EOPNOTSUPP;
+ }
+#endif
+ printk("%s\n", __func__);
+ return 0;
+}
+
+static int cfg80211_rtw_get_txpower(struct wiphy *wiphy, int *dbm)
+{
+ //_adapter *padapter = wiphy_to_adapter(wiphy);
+
+ printk("%s\n", __func__);
+
+ *dbm = (12);
+
+ return 0;
+}
+
+static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *ndev,
+ bool enabled, int timeout)
+{
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+
+ DBG_871X(FUNC_NDEV_FMT" enabled:%u, timeout:%d\n", FUNC_NDEV_ARG(ndev),
+ enabled, timeout);
+
+#if defined(CONFIG_CONCURRENT_MODE)
+ return -EPERM;
+#endif /* defined(CONFIG_CONCURRENT_MODE) */
+
+ if(enabled)
+ rtw_pm_set_lps(padapter, PS_MODE_MIN);
+ else
+ rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+ return 0;
+}
+
+static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
+ struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+ u8 index,blInserted = _FALSE;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u8 strZeroMacAddress[ ETH_ALEN ] = { 0x00 };
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(netdev));
+
+ if ( _rtw_memcmp( pmksa->bssid, strZeroMacAddress, ETH_ALEN ) == _TRUE )
+ {
+ return -EINVAL;
+ }
+
+ blInserted = _FALSE;
+
+ //overwrite PMKID
+ for(index=0 ; index<NUM_PMKID_CACHE; index++)
+ {
+ if( _rtw_memcmp( psecuritypriv->PMKIDList[index].Bssid, pmksa->bssid, ETH_ALEN) ==_TRUE )
+ { // BSSID is matched, the same AP => rewrite with new PMKID.
+ DBG_871X(FUNC_NDEV_FMT" BSSID exists in the PMKList.\n", FUNC_NDEV_ARG(netdev));
+
+ _rtw_memcpy( psecuritypriv->PMKIDList[index].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
+ psecuritypriv->PMKIDList[index].bUsed = _TRUE;
+ psecuritypriv->PMKIDIndex = index+1;
+ blInserted = _TRUE;
+ break;
+ }
+ }
+
+ if(!blInserted)
+ {
+ // Find a new entry
+ DBG_871X(FUNC_NDEV_FMT" Use the new entry index = %d for this PMKID.\n",
+ FUNC_NDEV_ARG(netdev), psecuritypriv->PMKIDIndex );
+
+ _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, pmksa->bssid, ETH_ALEN);
+ _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
+
+ psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = _TRUE;
+ psecuritypriv->PMKIDIndex++ ;
+ if(psecuritypriv->PMKIDIndex==16)
+ {
+ psecuritypriv->PMKIDIndex =0;
+ }
+ }
+
+ return 0;
+}
+
+static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
+ struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+ u8 index, bMatched = _FALSE;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(netdev));
+
+ for(index=0 ; index<NUM_PMKID_CACHE; index++)
+ {
+ if( _rtw_memcmp( psecuritypriv->PMKIDList[index].Bssid, pmksa->bssid, ETH_ALEN) ==_TRUE )
+ { // BSSID is matched, the same AP => Remove this PMKID information and reset it.
+ _rtw_memset( psecuritypriv->PMKIDList[index].Bssid, 0x00, ETH_ALEN );
+ _rtw_memset( psecuritypriv->PMKIDList[index].PMKID, 0x00, WLAN_PMKID_LEN );
+ psecuritypriv->PMKIDList[index].bUsed = _FALSE;
+ bMatched = _TRUE;
+ break;
+ }
+ }
+
+ if(_FALSE == bMatched)
+ {
+ DBG_871X(FUNC_NDEV_FMT" do not have matched BSSID\n"
+ , FUNC_NDEV_ARG(netdev));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
+ struct net_device *netdev)
+{
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(netdev));
+
+ _rtw_memset( &psecuritypriv->PMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
+ psecuritypriv->PMKIDIndex = 0;
+
+ return 0;
+}
+
+#ifdef CONFIG_AP_MODE
+void rtw_cfg80211_indicate_sta_assoc(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)
+{
+ s32 freq;
+ int channel;
+ struct wireless_dev *pwdev = padapter->rtw_wdev;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct net_device *ndev = padapter->pnetdev;
+
+ printk("%s(padapter=%p,%s)\n", __func__, padapter, ndev->name);
+
+#if defined(RTW_USE_CFG80211_STA_EVENT)
+ {
+ struct station_info sinfo;
+ u8 ie_offset;
+ if (GetFrameSubType(pmgmt_frame) == WIFI_ASSOCREQ)
+ ie_offset = _ASOCREQ_IE_OFFSET_;
+ else // WIFI_REASSOCREQ
+ ie_offset = _REASOCREQ_IE_OFFSET_;
+
+ sinfo.filled = 0;
+ sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
+ sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;
+ sinfo.assoc_req_ies_len = frame_len - WLAN_HDR_A3_LEN - ie_offset;
+ cfg80211_new_sta(ndev, GetAddr2Ptr(pmgmt_frame), &sinfo, GFP_ATOMIC);
+ }
+#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
+ channel = pmlmeext->cur_channel;
+ if (channel <= RTW_CH_MAX_2G_CHANNEL)
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+ else
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
+
+ #ifdef COMPAT_KERNEL_RELEASE
+ rtw_cfg80211_rx_mgmt(ndev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
+ #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+ rtw_cfg80211_rx_mgmt(ndev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
+ #else //COMPAT_KERNEL_RELEASE
+ {
+ //to avoid WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION) when calling cfg80211_send_rx_assoc()
+ #ifndef CONFIG_PLATFORM_MSTAR_TITANIA12
+ pwdev->iftype = NL80211_IFTYPE_STATION;
+ #endif //CONFIG_PLATFORM_MSTAR_TITANIA12
+ printk("iftype=%d before call cfg80211_send_rx_assoc()\n", pwdev->iftype);
+ rtw_cfg80211_send_rx_assoc(ndev, NULL, pmgmt_frame, frame_len);
+ printk("iftype=%d after call cfg80211_send_rx_assoc()\n", pwdev->iftype);
+ pwdev->iftype = NL80211_IFTYPE_AP;
+ //cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC);
+ }
+ #endif //COMPAT_KERNEL_RELEASE
+#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
+
+}
+
+void rtw_cfg80211_indicate_sta_disassoc(_adapter *padapter, unsigned char *da, unsigned short reason)
+{
+ s32 freq;
+ int channel;
+ u8 *pmgmt_frame;
+ uint frame_len;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ unsigned short *fctrl;
+ u8 mgmt_buf[128] = {0};
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct net_device *ndev = padapter->pnetdev;
+
+ printk("%s(padapter=%p,%s)\n", __func__, padapter, ndev->name);
+
+#if defined(RTW_USE_CFG80211_STA_EVENT)
+ cfg80211_del_sta(ndev, da, GFP_ATOMIC);
+#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
+ channel = pmlmeext->cur_channel;
+ if (channel <= RTW_CH_MAX_2G_CHANNEL)
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+ else
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
+
+ pmgmt_frame = mgmt_buf;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pmgmt_frame;
+
+ fctrl = &(pwlanhdr->frame_ctl);
+ *(fctrl) = 0;
+
+ //_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ //_rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr1, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr2, da, ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pmgmt_frame, WIFI_DEAUTH);
+
+ pmgmt_frame += sizeof(struct rtw_ieee80211_hdr_3addr);
+ frame_len = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ reason = cpu_to_le16(reason);
+ pmgmt_frame = rtw_set_fixed_ie(pmgmt_frame, _RSON_CODE_ , (unsigned char *)&reason, &frame_len);
+
+ #ifdef COMPAT_KERNEL_RELEASE
+ rtw_cfg80211_rx_mgmt(padapter->pnetdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);
+ #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+ rtw_cfg80211_rx_mgmt(padapter->pnetdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);
+ #else //COMPAT_KERNEL_RELEASE
+ cfg80211_send_disassoc(padapter->pnetdev, mgmt_buf, frame_len);
+ //cfg80211_rx_action(padapter->pnetdev, freq, mgmt_buf, frame_len, GFP_ATOMIC);
+ #endif //COMPAT_KERNEL_RELEASE
+#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
+}
+
+static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
+{
+ int ret = 0;
+
+ printk("%s\n", __func__);
+
+ return ret;
+}
+
+static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
+{
+ int ret = 0;
+
+ printk("%s\n", __func__);
+
+ return ret;
+}
+
+static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struct net_device *ndev)
+{
+ int ret = 0;
+ int rtap_len;
+ int qos_len = 0;
+ int dot11_hdr_len = 24;
+ int snap_len = 6;
+ unsigned char *pdata;
+ unsigned short frame_ctl;
+ unsigned char src_mac_addr[6];
+ unsigned char dst_mac_addr[6];
+ struct ieee80211_hdr *dot11_hdr;
+ struct ieee80211_radiotap_header *rtap_hdr;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
+ goto fail;
+
+ rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
+ if (unlikely(rtap_hdr->it_version))
+ goto fail;
+
+ rtap_len = ieee80211_get_radiotap_len(skb->data);
+ if (unlikely(skb->len < rtap_len))
+ goto fail;
+
+ if(rtap_len != 14)
+ {
+ printk("radiotap len (should be 14): %d\n", rtap_len);
+ goto fail;
+ }
+
+ /* Skip the ratio tap header */
+ skb_pull(skb, rtap_len);
+
+ dot11_hdr = (struct ieee80211_hdr *)skb->data;
+ frame_ctl = le16_to_cpu(dot11_hdr->frame_control);
+ /* Check if the QoS bit is set */
+ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
+ /* Check if this ia a Wireless Distribution System (WDS) frame
+ * which has 4 MAC addresses
+ */
+ if (dot11_hdr->frame_control & 0x0080)
+ qos_len = 2;
+ if ((dot11_hdr->frame_control & 0x0300) == 0x0300)
+ dot11_hdr_len += 6;
+
+ memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
+ memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
+
+ /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
+ * for two MAC addresses
+ */
+ skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);
+ pdata = (unsigned char*)skb->data;
+ memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
+ memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));
+
+ printk("should be eapol packet\n");
+
+ /* Use the real net device to transmit the packet */
+ ret = rtw_xmit_entry(skb, padapter->pnetdev);
+
+ return ret;
+
+ }
+ else if((frame_ctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) == cpu_to_le16(IEEE80211_STYPE_ACTION))
+ {
+ //only for action frames
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ //u8 category, action, OUI_Subtype, dialogToken=0;
+ //unsigned char *frame_body;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ u8 *buf = skb->data;
+ u32 len = skb->len;
+
+ #ifdef CONFIG_P2P
+ if(rtw_p2p_check_frames(padapter, buf, len, _TRUE) < 0)
+ {
+ goto fail;
+ }
+ #ifdef CONFIG_WFD
+ {
+ struct wifi_display_info *pwfd_info;
+
+ pwfd_info = padapter->wdinfo.wfd_info;
+
+ if ( _TRUE == pwfd_info->wfd_enable )
+ {
+ rtw_append_wfd_ie( padapter, buf, &skb->len );
+ }
+ }
+ #endif // CONFIG_WFD
+ #endif // CONFIG_P2P
+
+ //starting alloc mgmt frame to dump it
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ goto fail;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->retry_ctrl = _FALSE;
+
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+ _rtw_memcpy(pframe, (void*)buf, len);
+ pattrib->pktlen = len;
+
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+ //update seq number
+ pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
+ pattrib->seqnum = pmlmeext->mgnt_seq;
+ pmlmeext->mgnt_seq++;
+
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+
+ }
+ else
+ {
+ printk("frame_ctl=0x%x\n", frame_ctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE));
+ }
+
+
+fail:
+
+ dev_kfree_skb(skb);
+
+ return 0;
+
+}
+
+static void rtw_cfg80211_monitor_if_set_multicast_list(struct net_device *ndev)
+{
+ printk("%s\n", __func__);
+}
+
+static int rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
+{
+ int ret = 0;
+
+ printk("%s\n", __func__);
+
+ return ret;
+}
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
+ .ndo_open = rtw_cfg80211_monitor_if_open,
+ .ndo_stop = rtw_cfg80211_monitor_if_close,
+ .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+ .ndo_set_multicast_list = rtw_cfg80211_monitor_if_set_multicast_list,
+ #endif
+ .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
+};
+#endif
+
+static struct net_device *rtw_cfg80211_add_monitor_if(_adapter *padapter, char *name)
+{
+ int ret = 0;
+ struct net_device* ndev = NULL;
+ struct rtw_netdev_priv_indicator *pnpi;
+ struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
+
+ printk("%s\n", __func__);
+
+ if (!name ) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if((strnicmp(name, pwdev_priv->ifname_mon, strlen(name)) ==0)
+ && pwdev_priv->pmon_ndev)
+ {
+ ndev = pwdev_priv->pmon_ndev;
+
+ printk("%s, monitor interface(%s) has existed\n", __func__, name);
+
+ goto out;
+ }
+
+
+ ndev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));
+ if (!ndev) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+ strncpy(ndev->name, name, IFNAMSIZ);
+ ndev->name[IFNAMSIZ - 1] = 0;
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+ ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
+#else
+ ndev->open = rtw_cfg80211_monitor_if_open;
+ ndev->stop = rtw_cfg80211_monitor_if_close;
+ ndev->hard_start_xmit = rtw_cfg80211_monitor_if_xmit_entry;
+ ndev->set_mac_address = rtw_cfg80211_monitor_if_set_mac_address;
+#endif
+
+ pnpi = netdev_priv(ndev);
+ pnpi->priv = padapter;
+ pnpi->sizeof_priv = sizeof(_adapter);
+
+ ret = register_netdevice(ndev);
+ if (ret) {
+ goto out;
+ }
+
+ pwdev_priv->pmon_ndev = ndev;
+ _rtw_memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ+1);
+
+out:
+ if (ret && ndev)
+ {
+ free_netdev(ndev);
+ ndev = NULL;
+ }
+
+
+ printk("%s, ndev=%p, pmon_ndev=%p, ret=%d\n", __func__, ndev, pwdev_priv->pmon_ndev, ret);
+
+ return ndev;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)
+static struct net_device * cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, char *name,
+#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+static int cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, char *name,
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ struct net_device* ndev = NULL;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+
+ printk("%s(padapter=%p), ifname=%s, type=%d\n", __func__, padapter, name, type);
+
+
+ switch (type) {
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_MESH_POINT:
+
+ break;
+ case NL80211_IFTYPE_MONITOR:
+ ndev = rtw_cfg80211_add_monitor_if(padapter, name);
+ break;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ case NL80211_IFTYPE_P2P_CLIENT:
+#endif
+ case NL80211_IFTYPE_STATION:
+
+ break;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ case NL80211_IFTYPE_P2P_GO:
+#endif
+ case NL80211_IFTYPE_AP:
+
+ break;
+ default:
+ printk("Unsupported interface type\n");
+ break;
+ }
+
+ printk("ndev=%p\n", ndev);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)
+ return ndev;
+#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ return 0;
+#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+
+}
+
+static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy, struct net_device *ndev)
+{
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct rtw_wdev_priv *pwdev_priv = (struct rtw_wdev_priv *)wiphy_priv(wiphy);
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ if(ndev)
+ {
+ unregister_netdev(ndev);
+
+ free_netdev(ndev);
+
+ if(ndev == pwdev_priv->pmon_ndev)
+ {
+ printk("remove monitor interface\n");
+ pwdev_priv->pmon_ndev = NULL;
+ pwdev_priv->ifname_mon[0] = '\0';
+ }
+ }
+
+ return 0;
+}
+
+static int rtw_add_beacon(_adapter *adapter, const u8 *head, size_t head_len, const u8 *tail, size_t tail_len)
+{
+ int ret=0;
+ u8 *pbuf = NULL;
+ uint len, wps_ielen=0;
+ uint p2p_ielen=0;
+ u8 *p2p_ie;
+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+ //struct sta_priv *pstapriv = &padapter->stapriv;
+
+
+ printk("%s, beacon_head_len=%d, beacon_tail_len=%d\n", __FUNCTION__, head_len, tail_len);
+
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
+ return -EINVAL;
+
+ if(head_len<24)
+ return -EINVAL;
+
+
+ pbuf = rtw_zmalloc(head_len+tail_len);
+ if(!pbuf)
+ return -ENOMEM;
+
+
+ //_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;
+
+
+ _rtw_memcpy(pbuf, (void *)head+24, head_len-24);// 24=beacon header len.
+ _rtw_memcpy(pbuf+head_len-24, (void *)tail, tail_len);
+
+ len = head_len+tail_len-24;
+
+ //check wps ie if inclued
+ if(rtw_get_wps_ie(pbuf+_FIXED_IE_LENGTH_, len-_FIXED_IE_LENGTH_, NULL, &wps_ielen))
+ printk("add bcn, wps_ielen=%d\n", wps_ielen);
+
+#ifdef CONFIG_P2P
+ //check p2p ie if inclued
+ if(rtw_get_p2p_ie(pbuf+_FIXED_IE_LENGTH_, len-_FIXED_IE_LENGTH_, NULL, &p2p_ielen))
+ printk("got p2p_ie, len=%d\n", p2p_ielen);
+#endif
+
+ // pbss_network->IEs will not include p2p_ie
+ if(rtw_check_beacon_data(adapter, pbuf, len-p2p_ielen) == _SUCCESS)
+ //if(rtw_check_beacon_data(padapter, pbuf, len) == _SUCCESS)
+ {
+#ifdef CONFIG_P2P
+ //check p2p if enable
+ if((p2p_ie=rtw_get_p2p_ie(pbuf+_FIXED_IE_LENGTH_, len-_FIXED_IE_LENGTH_, NULL, &p2p_ielen)))
+ {
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo= &(adapter->wdinfo);
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ printk("Enable P2P function for the first time\n");
+ rtw_p2p_enable(adapter, P2P_ROLE_GO);
+ wdev_to_priv(adapter->rtw_wdev)->p2p_enabled = _TRUE;
+ }
+ else
+ {
+ _cancel_timer_ex( &pwdinfo->find_phase_timer );
+ _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+ _cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
+
+ printk("enter GO Mode, p2p_ielen=%d\n", p2p_ielen);
+
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ pwdinfo->intent = 15;
+ }
+
+ pwdinfo->operating_channel = pmlmeext->cur_channel;
+
+ }
+#endif //CONFIG_P2P
+
+ ret = 0;
+
+ }
+ else
+ {
+ ret = -EINVAL;
+ }
+
+
+ rtw_mfree(pbuf, head_len+tail_len);
+
+ return ret;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+static int cfg80211_rtw_add_beacon(struct wiphy *wiphy, struct net_device *ndev,
+ struct beacon_parameters *info)
+{
+ int ret=0;
+ _adapter *adapter = wiphy_to_adapter(wiphy);
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
+
+ return ret;
+}
+
+static int cfg80211_rtw_set_beacon(struct wiphy *wiphy, struct net_device *ndev,
+ struct beacon_parameters *info)
+{
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ pmlmeext->bstart_bss = _TRUE;
+
+ cfg80211_rtw_add_beacon(wiphy, ndev, info);
+
+ return 0;
+}
+
+static int cfg80211_rtw_del_beacon(struct wiphy *wiphy, struct net_device *ndev)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ return 0;
+}
+#else
+static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_ap_settings *settings)
+{
+ int ret = 0;
+ _adapter *adapter = wiphy_to_adapter(wiphy);
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ ret = rtw_add_beacon(adapter, settings->beacon.head, settings->beacon.head_len,
+ settings->beacon.tail, settings->beacon.tail_len);
+
+ return ret;
+}
+
+static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_beacon_data *info)
+{
+ int ret = 0;
+ _adapter *adapter = wiphy_to_adapter(wiphy);
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
+
+ return ret;
+}
+
+static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+ return 0;
+}
+
+#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+
+static int cfg80211_rtw_add_station(struct wiphy *wiphy, struct net_device *ndev,
+ u8 *mac, struct station_parameters *params)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ return 0;
+}
+
+static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev,
+ u8 *mac)
+{
+ int ret=0;
+ _irqL irqL;
+ _list *phead, *plist;
+ struct sta_info *psta = NULL;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_871X("+"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
+ {
+ printk("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n", __func__);
+ return -EINVAL;
+ }
+
+
+ if(!mac)
+ {
+ printk("flush all sta, and cam_entry\n");
+
+ flush_all_cam_entry(padapter); //clear CAM
+
+ ret = rtw_sta_flush(padapter);
+
+ return ret;
+ }
+
+
+ printk("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
+
+ if (mac[0] == 0xff && mac[1] == 0xff &&
+ mac[2] == 0xff && mac[3] == 0xff &&
+ mac[4] == 0xff && mac[5] == 0xff)
+ {
+ return -EINVAL;
+ }
+
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ //check asoc_queue
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+
+ plist = get_next(plist);
+
+ if(_rtw_memcmp(mac, psta->hwaddr, ETH_ALEN))
+ {
+ if(psta->dot8021xalg == 1 && psta->bpairwise_key_installed == _FALSE)
+ {
+ DBG_8192C("%s, sta's dot8021xalg = 1 and key_installed = _FALSE\n", __func__);
+ }
+ else
+ {
+ DBG_8192C("free psta=%p, aid=%d\n", psta, psta->aid);
+
+ rtw_list_delete(&psta->asoc_list);
+
+ //_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ ap_free_sta(padapter, psta);
+ //_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ psta = NULL;
+
+ break;
+ }
+
+ }
+
+ }
+
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+
+#if 0
+ psta = rtw_get_stainfo(pstapriv, mac);
+ if(psta)
+ {
+ //DBG_8192C("free psta=%p, aid=%d\n", psta, psta->aid);
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
+ {
+ rtw_list_delete(&psta->asoc_list);
+ ap_free_sta(padapter, psta);
+
+ }
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ psta = NULL;
+
+ }
+ else
+ {
+ DBG_8192C("cfg80211_rtw_del_station(), sta has already been removed or never been added\n");
+
+ //ret = -1;
+ }
+#endif
+
+ DBG_871X("-"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ return ret;
+
+}
+
+static int cfg80211_rtw_change_station(struct wiphy *wiphy, struct net_device *ndev,
+ u8 *mac, struct station_parameters *params)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ return 0;
+}
+
+static int cfg80211_rtw_dump_station(struct wiphy *wiphy, struct net_device *ndev,
+ int idx, u8 *mac, struct station_info *sinfo)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ //TODO: dump scanned queue
+
+ return -ENOENT;
+}
+
+static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
+ struct bss_parameters *params)
+{
+ u8 i;
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+/*
+ printk("use_cts_prot=%d\n", params->use_cts_prot);
+ printk("use_short_preamble=%d\n", params->use_short_preamble);
+ printk("use_short_slot_time=%d\n", params->use_short_slot_time);
+ printk("ap_isolate=%d\n", params->ap_isolate);
+
+ printk("basic_rates_len=%d\n", params->basic_rates_len);
+ for(i=0; i<params->basic_rates_len; i++)
+ {
+ printk("basic_rates=%d\n", params->basic_rates[i]);
+
+ }
+*/
+ return 0;
+
+}
+
+static int cfg80211_rtw_set_channel(struct wiphy *wiphy, struct net_device *ndev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ return 0;
+}
+
+static int cfg80211_rtw_auth(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_auth_request *req)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ return 0;
+}
+
+static int cfg80211_rtw_assoc(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_assoc_request *req)
+{
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ return 0;
+}
+#endif //CONFIG_AP_MODE
+
+void rtw_cfg80211_rx_action_p2p(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)
+{
+ s32 freq;
+ int channel;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(padapter->pcodatapriv)
+ channel = padapter->pcodatapriv->co_ch;
+#else
+ channel = pmlmeext->cur_channel;
+#endif
+
+//#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, cur_ch=%d\n", __func__, channel);
+//#endif
+
+#ifdef CONFIG_P2P
+ rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, _FALSE);
+#endif //CONFIG_P2P
+
+ if (channel <= RTW_CH_MAX_2G_CHANNEL)
+ {
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+ }
+ else
+ {
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ rtw_cfg80211_rx_mgmt(padapter->pnetdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
+#else
+ cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC);
+#endif
+
+}
+
+void rtw_cfg80211_rx_p2p_action_public(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)
+{
+ s32 freq;
+ int channel;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(padapter->pcodatapriv)
+ channel = padapter->pcodatapriv->co_ch;
+#else
+ channel = pmlmeext->cur_channel;
+#endif
+
+//#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, cur_ch=%d\n", __func__, channel);
+//#endif
+
+#ifdef CONFIG_P2P
+ rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, _FALSE);
+#endif
+
+ if (channel <= RTW_CH_MAX_2G_CHANNEL)
+ {
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+ }
+ else
+ {
+ freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ rtw_cfg80211_rx_mgmt(padapter->pnetdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
+#else
+ cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC);
+#endif
+
+}
+
+#ifdef CONFIG_P2P
+void rtw_cfg80211_issue_p2p_provision_request(_adapter *padapter, const u8 *buf, size_t len)
+{
+ u16 wps_devicepassword_id = 0x0000;
+ uint wps_devicepassword_id_len = 0;
+ u8 wpsie[ 255 ] = { 0x00 }, p2p_ie[ 255 ] = { 0x00 };
+ uint p2p_ielen = 0;
+ uint wpsielen = 0;
+ u32 devinfo_contentlen = 0;
+ u8 devinfo_content[64] = { 0x00 };
+ u16 capability = 0;
+ uint capability_len = 0;
+
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ u8 dialogToken = 1;
+ u32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_PROVISION_DISC_REQ;
+ u32 p2pielen = 0;
+#ifdef CONFIG_WFD
+ u32 wfdielen = 0;
+#endif //CONFIG_WFD
+
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ unsigned short *fctrl;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+ u8 *frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
+ size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
+
+
+ DBG_871X( "[%s] In\n", __FUNCTION__ );
+
+ //prepare for building provision_request frame
+ _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr1Ptr(buf), ETH_ALEN);
+ _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, GetAddr1Ptr(buf), ETH_ALEN);
+
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
+
+ rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
+ rtw_get_wps_attr_content( wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
+ wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );
+
+ switch(wps_devicepassword_id)
+ {
+ case WPS_DPID_PIN:
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
+ break;
+ case WPS_DPID_USER_SPEC:
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
+ break;
+ case WPS_DPID_MACHINE_SPEC:
+ break;
+ case WPS_DPID_REKEY:
+ break;
+ case WPS_DPID_PBC:
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
+ break;
+ case WPS_DPID_REGISTRAR_SPEC:
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
+ break;
+ default:
+ break;
+ }
+
+
+ if ( rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, p2p_ie, &p2p_ielen ) )
+ {
+
+ rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, devinfo_content, &devinfo_contentlen);
+ rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&capability, &capability_len);
+
+ }
+
+
+ //start to build provision_request frame
+ _rtw_memset(wpsie, 0, sizeof(wpsie));
+ _rtw_memset(p2p_ie, 0, sizeof(p2p_ie));
+ p2p_ielen = 0;
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &(pwlanhdr->frame_ctl);
+ *(fctrl) = 0;
+
+ _rtw_memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
+
+
+ //build_prov_disc_request_p2p_ie
+ // P2P OUI
+ p2pielen = 0;
+ p2p_ie[ p2pielen++ ] = 0x50;
+ p2p_ie[ p2pielen++ ] = 0x6F;
+ p2p_ie[ p2pielen++ ] = 0x9A;
+ p2p_ie[ p2pielen++ ] = 0x09; // WFA P2P v1.0
+
+ // Commented by Albert 20110301
+ // According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes
+ // 1. P2P Capability
+ // 2. Device Info
+ // 3. Group ID ( When joining an operating P2P Group )
+
+ // P2P Capability ATTR
+ // Type:
+ p2p_ie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+ // Length:
+ //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+ RTW_PUT_LE16(p2p_ie + p2pielen, 0x0002);
+ p2pielen += 2;
+
+ // Value:
+ // Device Capability Bitmap, 1 byte
+ // Group Capability Bitmap, 1 byte
+ _rtw_memcpy(p2p_ie + p2pielen, &capability, 2);
+ p2pielen += 2;
+
+
+ // Device Info ATTR
+ // Type:
+ p2p_ie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
+
+ // Length:
+ // 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes)
+ // + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
+ //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
+ RTW_PUT_LE16(p2p_ie + p2pielen, devinfo_contentlen);
+ p2pielen += 2;
+
+ // Value:
+ _rtw_memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);
+ p2pielen += devinfo_contentlen;
+
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2p_ie, &p2p_ielen);
+ //p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, NULL, 0, pwdinfo->tx_prov_disc_info.peerDevAddr);
+ //pframe += p2pielen;
+ pattrib->pktlen += p2p_ielen;
+
+ wpsielen = 0;
+ // WPS OUI
+ *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
+ wpsielen += 4;
+
+ // WPS version
+ // Type:
+ *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
+ wpsielen += 2;
+
+ // Length:
+ *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+ wpsielen += 2;
+
+ // Value:
+ wpsie[wpsielen++] = WPS_VERSION_1; // Version 1.0
+
+ // Config Method
+ // Type:
+ *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
+ wpsielen += 2;
+
+ // Length:
+ *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+ wpsielen += 2;
+
+ // Value:
+ *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->tx_prov_disc_info.wps_config_method_request );
+ wpsielen += 2;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
+
+
+#ifdef CONFIG_WFD
+ wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
+ pframe += wfdielen;
+ pattrib->pktlen += wfdielen;
+#endif //CONFIG_WFD
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+
+ //if(wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
+ //{
+ // printk("waiting for p2p peer key-in PIN CODE\n");
+ // rtw_msleep_os(15000); // 15 sec for key in PIN CODE, workaround for GS2 before issuing Nego Req.
+ //}
+
+}
+
+static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy, struct net_device *ndev,
+ struct ieee80211_channel * channel,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration, u64 *cookie)
+{
+ s32 err = 0;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
+ u8 remain_ch = (u8) ieee80211_frequency_to_channel(channel->center_freq);
+ u8 ready_on_channel = _FALSE;
+
+ DBG_871X(FUNC_NDEV_FMT" ch:%u duration:%d\n", FUNC_NDEV_ARG(ndev), remain_ch, duration);
+
+ if(_FAIL == rtw_pwr_wakeup(padapter)) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ pcfg80211_wdinfo->remain_on_ch_dev = ndev;
+ _rtw_memcpy(&pcfg80211_wdinfo->remain_on_ch_channel, channel, sizeof(struct ieee80211_channel));
+ pcfg80211_wdinfo->remain_on_ch_type= channel_type;
+ pcfg80211_wdinfo->remain_on_ch_cookie= *cookie;
+
+ rtw_cfg80211_scan_abort(padapter);
+
+ //if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
+ wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = _TRUE;
+ }
+ else
+ {
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
+#endif
+ }
+
+
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(check_buddy_fwstate(padapter, _FW_LINKED) &&
+ (duration<pwdinfo->ext_listen_interval))
+ {
+ duration = duration + pwdinfo->ext_listen_interval;
+ }
+#endif
+
+ pcfg80211_wdinfo->restore_channel = pmlmeext->cur_channel;
+
+ if(rtw_is_channel_set_contains_channel(pmlmeext->channel_set, remain_ch)) {
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+ if(remain_ch != pbuddy_mlmeext->cur_channel)
+ {
+ if(ATOMIC_READ(&pwdev_priv->switch_ch_to)==1)
+ {
+ printk("%s, issue nulldata pwrbit=1\n", __func__);
+ issue_nulldata(padapter->pbuddy_adapter, 1);
+
+ ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
+
+ printk("%s, set switch ch timer\n", __func__);
+ _set_timer(&pwdinfo->ap_p2p_switch_timer, duration-pwdinfo->ext_listen_interval);
+ }
+ }
+
+ ready_on_channel = _TRUE;
+ //pmlmeext->cur_channel = remain_ch;
+ //set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }else
+#endif //CONFIG_CONCURRENT_MODE
+ if(remain_ch != pmlmeext->cur_channel )
+ {
+ ready_on_channel = _TRUE;
+ //pmlmeext->cur_channel = remain_ch;
+ //set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }
+ } else {
+ DBG_871X("%s remain_ch:%u not in channel plan!!!!\n", __FUNCTION__, remain_ch);
+ }
+
+
+
+
+ //call this after other things have been done
+#ifdef CONFIG_CONCURRENT_MODE
+ if(ATOMIC_READ(&pwdev_priv->ro_ch_to)==1)
+ {
+ u8 co_channel = 0xff;
+ ATOMIC_SET(&pwdev_priv->ro_ch_to, 0);
+#endif
+
+ if(ready_on_channel == _TRUE)
+ {
+ pmlmeext->cur_channel = remain_ch;
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(padapter->pcodatapriv)
+ co_channel = padapter->pcodatapriv->co_ch;
+
+ if(co_channel !=remain_ch)
+#endif
+ set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }
+
+ printk("%s, set ro ch timer\n", __func__);
+
+ _set_timer( &pcfg80211_wdinfo->remain_on_ch_timer, duration);
+
+#ifdef CONFIG_CONCURRENT_MODE
+ }
+#endif
+
+ cfg80211_ready_on_channel(ndev, *cookie, channel, channel_type, duration, GFP_KERNEL);
+
+ pwdinfo->listen_channel = pmlmeext->cur_channel;
+
+exit:
+ return err;
+}
+
+static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *ndev,
+ u64 cookie)
+{
+ s32 err = 0;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+ //Modified bu Kurt 20120114
+ _cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
+#ifdef CONFIG_CONCURRENT_MODE
+ ATOMIC_SET(&pwdev_priv->ro_ch_to, 1);
+#endif
+
+ #if 0
+ // Disable P2P Listen State
+ if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+ {
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ _cancel_timer_ex( &pwdinfo->find_phase_timer );
+ _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+ _cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
+
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
+ _rtw_memset(pwdinfo, 0x00, sizeof(struct wifidirect_info));
+
+ if(pwrpriv->bips_processing == _FALSE){
+ rtw_set_pwr_state_check_timer(pwrpriv);
+ }
+ }
+ }
+ else
+ #endif
+ {
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
+#endif
+ }
+
+ return err;
+}
+
+#endif //CONFIG_P2P
+
+static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)
+ struct ieee80211_channel *chan, bool offchan,
+ enum nl80211_channel_type channel_type,
+ bool channel_type_valid, unsigned int wait,
+#else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ bool channel_type_valid,
+ #endif
+#endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ const u8 *buf, size_t len,
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))
+ bool no_cck,
+ #endif
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+ bool dont_wait_for_ack,
+ #endif
+ u64 *cookie)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ const struct ieee80211_mgmt *mgmt;
+ //u8 category, action, OUI_Subtype, dialogToken=0;
+ //unsigned char *frame_body;
+ int ret = 0;
+ int type = (-1);
+ u16 fc;
+ bool ack = _TRUE;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ _adapter *padapter = wiphy_to_adapter(wiphy);
+ struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 tx_ch = (u8)ieee80211_frequency_to_channel(chan->center_freq);
+
+
+ /* cookie generation */
+ *cookie = (unsigned long) buf;
+
+ DBG_871X(FUNC_NDEV_FMT" len=%d, ch=%d, ch_type=%d\n", FUNC_NDEV_ARG(ndev),
+ len, ieee80211_frequency_to_channel(chan->center_freq), channel_type);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ printk("channel_type_valid=%d\n", channel_type_valid);
+#endif
+
+ mgmt = (const struct ieee80211_mgmt *) buf;
+ fc = mgmt->frame_control;
+ if (fc != IEEE80211_STYPE_ACTION)
+ {
+ if (fc == IEEE80211_STYPE_PROBE_RESP)
+ {
+ printk("%s, fc == IEEE80211_STYPE_PROBE_RESP\n", __func__);
+ }
+ else
+ {
+ printk("%s, frame_control == 0x%x\n", __func__, fc);
+ }
+
+ //cfg80211_mgmt_tx_status(dev, *cookie, buf, len, ack, GFP_KERNEL);
+
+ goto exit;
+
+ }
+ else
+ {
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, do: scan_abort\n", __func__);
+#endif
+
+ /* Abort the dwell time of any previous off-channel action frame that may
+ * be still in effect. Sending off-channel action frames relies on the
+ * driver's scan engine. If a previous off-channel action frame tx is
+ * still in progress (including the dwell time), then this new action
+ * frame will not be sent out.
+ */
+
+ rtw_cfg80211_scan_abort(padapter);
+ }
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ u8 co_channel=0xff;
+ PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+ if(padapter->pcodatapriv)
+ co_channel = padapter->pcodatapriv->co_ch;
+
+ if(tx_ch != pbuddy_mlmeext->cur_channel)
+ {
+ if(ATOMIC_READ(&pwdev_priv->switch_ch_to)==1)
+ {
+ printk("%s, issue nulldata pwrbit=1\n", __func__);
+ issue_nulldata(padapter->pbuddy_adapter, 1);
+
+ ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
+
+ printk("%s, set switch ch timer\n", __func__);
+ _set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period);
+ }
+ }
+
+ pmlmeext->cur_channel = tx_ch;
+
+ if(tx_ch != co_channel)
+ set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+
+ }else
+#endif //CONFIG_CONCURRENT_MODE
+ if( tx_ch != pmlmeext->cur_channel )
+ {
+ pmlmeext->cur_channel = tx_ch;
+ set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }
+
+#ifdef CONFIG_P2P
+ if( (type = rtw_p2p_check_frames(padapter, buf, len, _TRUE)) < 0)
+ {
+ ack = _FALSE;
+ goto exit;
+ }
+#endif
+
+
+ //if(type == P2P_GO_NEGO_REQ)
+ //{
+ // rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len);
+ //}
+
+
+ //starting alloc mgmt frame to dump it
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ ack = _FALSE;
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->retry_ctrl = _FALSE;
+
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+ _rtw_memcpy(pframe, (void*)buf, len);
+ pattrib->pktlen = len;
+
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+ //update seq number
+ pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
+ pattrib->seqnum = pmlmeext->mgnt_seq;
+ pmlmeext->mgnt_seq++;
+
+#ifdef CONFIG_WFD
+ {
+ struct wifi_display_info *pwfd_info;
+
+ pwfd_info = padapter->wdinfo.wfd_info;
+
+ if ( _TRUE == pwfd_info->wfd_enable )
+ {
+ rtw_append_wfd_ie( padapter, pframe, &pattrib->pktlen );
+ }
+ }
+#endif // CONFIG_WFD
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, ack=%d, ok!\n", __func__, ack );
+#endif
+
+ //indicate ack before issue frame to avoid racing with rsp frame
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
+#elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,34) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,35))
+ cfg80211_action_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
+#endif
+
+ dump_mgntframe(padapter, pmgntframe);
+
+ return ret;
+
+exit:
+
+ printk("%s, ack=%d \n", __func__, ack );
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
+#elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,34) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,35))
+ cfg80211_action_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
+#endif
+
+ return ret;
+
+}
+
+static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, struct net_device *ndev,
+ u16 frame_type, bool reg)
+{
+
+#ifdef CONFIG_DEBUG_CFG80211
+ DBG_871X(FUNC_NDEV_FMT" frame_type: %x, reg: %d\n", FUNC_NDEV_ARG(ndev),
+ frame_type, reg);
+#endif
+
+ if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
+ return;
+
+ return;
+}
+
+static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf, int len)
+{
+ int ret = 0;
+ uint wps_ielen = 0;
+ u8 *wps_ie;
+ u32 p2p_ielen = 0;
+ u8 wps_oui[8]={0x0,0x50,0xf2,0x04};
+ u8 *p2p_ie;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+ DBG_871X(FUNC_NDEV_FMT" ielen=%d\n", FUNC_NDEV_ARG(ndev), len);
+
+ if(len>0)
+ {
+ if((wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen)))
+ {
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("bcn_wps_ielen=%d\n", wps_ielen);
+ #endif
+
+ if(pmlmepriv->wps_beacon_ie)
+ {
+ u32 free_len = pmlmepriv->wps_beacon_ie_len;
+ pmlmepriv->wps_beacon_ie_len = 0;
+ rtw_mfree(pmlmepriv->wps_beacon_ie, free_len);
+ pmlmepriv->wps_beacon_ie = NULL;
+ }
+
+ pmlmepriv->wps_beacon_ie = rtw_malloc(wps_ielen);
+ if ( pmlmepriv->wps_beacon_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+
+ _rtw_memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);
+ pmlmepriv->wps_beacon_ie_len = wps_ielen;
+
+ update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE);
+
+ }
+
+ buf += wps_ielen;
+ len -= wps_ielen;
+
+ #ifdef CONFIG_P2P
+ if((p2p_ie=rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen)))
+ {
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("bcn_p2p_ielen=%d\n", p2p_ielen);
+ #endif
+
+ if(pmlmepriv->p2p_beacon_ie)
+ {
+ u32 free_len = pmlmepriv->p2p_beacon_ie_len;
+ pmlmepriv->p2p_beacon_ie_len = 0;
+ rtw_mfree(pmlmepriv->p2p_beacon_ie, free_len);
+ pmlmepriv->p2p_beacon_ie = NULL;
+ }
+
+ pmlmepriv->p2p_beacon_ie = rtw_malloc(p2p_ielen);
+ if ( pmlmepriv->p2p_beacon_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+
+ _rtw_memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);
+ pmlmepriv->p2p_beacon_ie_len = p2p_ielen;
+
+ }
+ #endif //CONFIG_P2P
+
+ pmlmeext->bstart_bss = _TRUE;
+
+ }
+
+ return ret;
+
+}
+
+static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net, char *buf, int len)
+{
+ int ret = 0;
+ uint wps_ielen = 0;
+ u8 *wps_ie;
+ u32 p2p_ielen = 0;
+ u8 *p2p_ie;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, ielen=%d\n", __func__, len);
+#endif
+
+ if(len>0)
+ {
+ if((wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen)))
+ {
+ uint attr_contentlen = 0;
+ u16 uconfig_method, *puconfig_method = NULL;
+
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("probe_resp_wps_ielen=%d\n", wps_ielen);
+ #endif
+
+ if(pmlmepriv->wps_probe_resp_ie)
+ {
+ u32 free_len = pmlmepriv->wps_probe_resp_ie_len;
+ pmlmepriv->wps_probe_resp_ie_len = 0;
+ rtw_mfree(pmlmepriv->wps_probe_resp_ie, free_len);
+ pmlmepriv->wps_probe_resp_ie = NULL;
+ }
+
+ pmlmepriv->wps_probe_resp_ie = rtw_malloc(wps_ielen);
+ if ( pmlmepriv->wps_probe_resp_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+
+ //add PUSH_BUTTON config_method by driver self in wpsie of probe_resp at GO Mode
+ if ( (puconfig_method = (u16*)rtw_get_wps_attr_content( wps_ie, wps_ielen, WPS_ATTR_CONF_METHOD , NULL, &attr_contentlen)) != NULL )
+ {
+ #ifdef CONFIG_DEBUG_CFG80211
+ //printk("config_method in wpsie of probe_resp = 0x%x\n", be16_to_cpu(*puconfig_method));
+ #endif
+
+ uconfig_method = WPS_CM_PUSH_BUTTON;
+ uconfig_method = cpu_to_be16( uconfig_method );
+
+ *puconfig_method |= uconfig_method;
+ }
+
+ _rtw_memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);
+ pmlmepriv->wps_probe_resp_ie_len = wps_ielen;
+
+ }
+
+ buf += wps_ielen;
+ len -= wps_ielen;
+
+ #ifdef CONFIG_P2P
+ if((p2p_ie=rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen)))
+ {
+ u8 is_GO = _FALSE;
+ u32 attr_contentlen = 0;
+ u16 cap_attr=0;
+
+ #ifdef CONFIG_DEBUG_CFG80211
+ printk("probe_resp_p2p_ielen=%d\n", p2p_ielen);
+ #endif
+
+ //Check P2P Capability ATTR
+ if( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen) )
+ {
+ u8 grp_cap=0;
+ //DBG_8192C( "[%s] Got P2P Capability Attr!!\n", __FUNCTION__ );
+ cap_attr = le16_to_cpu(cap_attr);
+ grp_cap = (u8)((cap_attr >> 8)&0xff);
+
+ is_GO = (grp_cap&BIT(0)) ? _TRUE:_FALSE;
+
+ if(is_GO)
+ printk("Got P2P Capability Attr, grp_cap=0x%x, is_GO\n", grp_cap);
+ }
+
+
+ if(is_GO == _FALSE)
+ {
+ if(pmlmepriv->p2p_probe_resp_ie)
+ {
+ u32 free_len = pmlmepriv->p2p_probe_resp_ie_len;
+ pmlmepriv->p2p_probe_resp_ie_len = 0;
+ rtw_mfree(pmlmepriv->p2p_probe_resp_ie, free_len);
+ pmlmepriv->p2p_probe_resp_ie = NULL;
+ }
+
+ pmlmepriv->p2p_probe_resp_ie = rtw_malloc(p2p_ielen);
+ if ( pmlmepriv->p2p_probe_resp_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+ _rtw_memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie, p2p_ielen);
+ pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;
+ }
+ else
+ {
+ if(pmlmepriv->p2p_go_probe_resp_ie)
+ {
+ u32 free_len = pmlmepriv->p2p_go_probe_resp_ie_len;
+ pmlmepriv->p2p_go_probe_resp_ie_len = 0;
+ rtw_mfree(pmlmepriv->p2p_go_probe_resp_ie, free_len);
+ pmlmepriv->p2p_go_probe_resp_ie = NULL;
+ }
+
+ pmlmepriv->p2p_go_probe_resp_ie = rtw_malloc(p2p_ielen);
+ if ( pmlmepriv->p2p_go_probe_resp_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+ _rtw_memcpy(pmlmepriv->p2p_go_probe_resp_ie, p2p_ie, p2p_ielen);
+ pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;
+ }
+
+ }
+ #endif //CONFIG_P2P
+
+ }
+
+ return ret;
+
+}
+
+static int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net, char *buf, int len)
+{
+ int ret = 0;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ printk("%s, ielen=%d\n", __func__, len);
+
+ if(len>0)
+ {
+ if(pmlmepriv->wps_assoc_resp_ie)
+ {
+ u32 free_len = pmlmepriv->wps_assoc_resp_ie_len;
+ pmlmepriv->wps_assoc_resp_ie_len = 0;
+ rtw_mfree(pmlmepriv->wps_assoc_resp_ie, free_len);
+ pmlmepriv->wps_assoc_resp_ie = NULL;
+ }
+
+ pmlmepriv->wps_assoc_resp_ie = rtw_malloc(len);
+ if ( pmlmepriv->wps_assoc_resp_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+
+ }
+ _rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, buf, len);
+ pmlmepriv->wps_assoc_resp_ie_len = len;
+ }
+
+ return ret;
+
+}
+
+int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
+ int type)
+{
+ int ret = 0;
+ uint wps_ielen = 0;
+ u32 p2p_ielen = 0;
+
+#ifdef CONFIG_DEBUG_CFG80211
+ printk("%s, ielen=%d\n", __func__, len);
+#endif
+
+ if( (rtw_get_wps_ie(buf, len, NULL, &wps_ielen) && (wps_ielen>0))
+ #ifdef CONFIG_P2P
+ || (rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen) && (p2p_ielen>0))
+ #endif
+ )
+ {
+ if (net != NULL)
+ {
+ switch (type)
+ {
+ case 0x1: //BEACON
+ ret = rtw_cfg80211_set_beacon_wpsp2pie(net, buf, len);
+ break;
+ case 0x2: //PROBE_RESP
+ ret = rtw_cfg80211_set_probe_resp_wpsp2pie(net, buf, len);
+ break;
+ case 0x4: //ASSOC_RESP
+ ret = rtw_cfg80211_set_assoc_resp_wpsp2pie(net, buf, len);
+ break;
+ }
+ }
+ }
+
+ return ret;
+
+}
+
+static struct cfg80211_ops rtw_cfg80211_ops = {
+ .change_virtual_intf = cfg80211_rtw_change_iface,
+ .add_key = cfg80211_rtw_add_key,
+ .get_key = cfg80211_rtw_get_key,
+ .del_key = cfg80211_rtw_del_key,
+ .set_default_key = cfg80211_rtw_set_default_key,
+ .get_station = cfg80211_rtw_get_station,
+ .scan = cfg80211_rtw_scan,
+ .set_wiphy_params = cfg80211_rtw_set_wiphy_params,
+ .connect = cfg80211_rtw_connect,
+ .disconnect = cfg80211_rtw_disconnect,
+ .join_ibss = cfg80211_rtw_join_ibss,
+ .leave_ibss = cfg80211_rtw_leave_ibss,
+ .set_tx_power = cfg80211_rtw_set_txpower,
+ .get_tx_power = cfg80211_rtw_get_txpower,
+ .set_power_mgmt = cfg80211_rtw_set_power_mgmt,
+ .set_pmksa = cfg80211_rtw_set_pmksa,
+ .del_pmksa = cfg80211_rtw_del_pmksa,
+ .flush_pmksa = cfg80211_rtw_flush_pmksa,
+
+#ifdef CONFIG_AP_MODE
+ .add_virtual_intf = cfg80211_rtw_add_virtual_intf,
+ .del_virtual_intf = cfg80211_rtw_del_virtual_intf,
+
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
+ .add_beacon = cfg80211_rtw_add_beacon,
+ .set_beacon = cfg80211_rtw_set_beacon,
+ .del_beacon = cfg80211_rtw_del_beacon,
+ #else
+ .start_ap = cfg80211_rtw_start_ap,
+ .change_beacon = cfg80211_rtw_change_beacon,
+ .stop_ap = cfg80211_rtw_stop_ap,
+ #endif
+
+ .add_station = cfg80211_rtw_add_station,
+ .del_station = cfg80211_rtw_del_station,
+ .change_station = cfg80211_rtw_change_station,
+ .dump_station = cfg80211_rtw_dump_station,
+ .change_bss = cfg80211_rtw_change_bss,
+ .set_channel = cfg80211_rtw_set_channel,
+ //.auth = cfg80211_rtw_auth,
+ //.assoc = cfg80211_rtw_assoc,
+#endif //CONFIG_AP_MODE
+
+#ifdef CONFIG_P2P
+ .remain_on_channel = cfg80211_rtw_remain_on_channel,
+ .cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+ .mgmt_tx = cfg80211_rtw_mgmt_tx,
+ .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
+#elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,34) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,35))
+ .action = cfg80211_rtw_mgmt_tx,
+#endif
+};
+
+static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum ieee80211_band band, u8 rf_type)
+{
+
+#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
+#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
+
+ ht_cap->ht_supported = _TRUE;
+
+ ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
+
+ /*
+ *Maximum length of AMPDU that the STA can receive.
+ *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
+ */
+ ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+
+ /*Minimum MPDU start spacing , */
+ ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+
+ ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+
+ /*
+ *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
+ *base on ant_num
+ *rx_mask: RX mask
+ *if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7
+ *if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15
+ *if rx_ant >=3 rx_mask[2]=0xff;
+ *if BW_40 rx_mask[4]=0x01;
+ *highest supported RX rate
+ */
+ if(rf_type == RF_1T1R)
+ {
+ ht_cap->mcs.rx_mask[0] = 0xFF;
+ ht_cap->mcs.rx_mask[1] = 0x00;
+ ht_cap->mcs.rx_mask[4] = 0x01;
+
+ ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
+ }
+ else if((rf_type == RF_1T2R) || (rf_type==RF_2T2R))
+ {
+ ht_cap->mcs.rx_mask[0] = 0xFF;
+ ht_cap->mcs.rx_mask[1] = 0xFF;
+ ht_cap->mcs.rx_mask[4] = 0x01;
+
+ ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
+ }
+ else
+ {
+ printk("%s, error rf_type=%d\n", __func__, rf_type);
+ }
+
+}
+
+void rtw_cfg80211_init_wiphy(_adapter *padapter)
+{
+ u8 rf_type;
+ struct ieee80211_supported_band *bands;
+ struct wireless_dev *pwdev = padapter->rtw_wdev;
+ struct wiphy *wiphy = pwdev->wiphy;
+
+ padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+ printk("%s:rf_type=%d\n", __func__, rf_type);
+
+ bands = wiphy->bands[IEEE80211_BAND_2GHZ];
+ if(bands)
+ rtw_cfg80211_init_ht_capab(&bands->ht_cap, IEEE80211_BAND_2GHZ, rf_type);
+
+ bands = wiphy->bands[IEEE80211_BAND_5GHZ];
+ if(bands)
+ rtw_cfg80211_init_ht_capab(&bands->ht_cap, IEEE80211_BAND_5GHZ, rf_type);
+}
+
+static void rtw_cfg80211_preinit_wiphy(_adapter *padapter, struct wiphy *wiphy)
+{
+
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+ wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
+ wiphy->max_scan_ie_len = RTW_SCAN_IE_LEN_MAX;
+ wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)
+ wiphy->max_remain_on_channel_duration = RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
+#endif
+
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
+ | BIT(NL80211_IFTYPE_ADHOC)
+#ifdef CONFIG_AP_MODE
+ | BIT(NL80211_IFTYPE_AP)
+ | BIT(NL80211_IFTYPE_MONITOR)
+#endif
+#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE))
+ | BIT(NL80211_IFTYPE_P2P_CLIENT)
+ | BIT(NL80211_IFTYPE_P2P_GO)
+#endif
+ ;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
+#ifdef CONFIG_AP_MODE
+ wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
+#endif //CONFIG_AP_MODE
+#endif
+
+ wiphy->cipher_suites = rtw_cipher_suites;
+ wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
+
+ wiphy->bands[IEEE80211_BAND_2GHZ] = rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
+ wiphy->bands[IEEE80211_BAND_5GHZ] = rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) && LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
+ wiphy->flags |= WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;
+#endif
+
+ if(padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
+ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ else
+ wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+}
+
+int rtw_wdev_alloc(_adapter *padapter, struct device *dev)
+{
+ int ret = 0;
+ struct wireless_dev *wdev;
+ struct rtw_wdev_priv *pwdev_priv;
+ struct net_device *pnetdev = padapter->pnetdev;
+
+ printk("%s(padapter=%p)\n", __func__, padapter);
+
+ wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));
+ if (!wdev) {
+ printk("Couldn't allocate wireless device\n");
+ return (-ENOMEM);
+ }
+
+ wdev->wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
+ if (!wdev->wiphy) {
+ printk("Couldn't allocate wiphy device\n");
+ ret = -ENOMEM;
+ goto out_err_new;
+ }
+
+ set_wiphy_dev(wdev->wiphy, dev);
+
+ //
+ padapter->rtw_wdev = wdev;
+ pnetdev->ieee80211_ptr = wdev;
+
+ //init pwdev_priv
+ pwdev_priv = wdev_to_priv(wdev);
+ pwdev_priv->pmon_ndev = NULL;
+ pwdev_priv->ifname_mon[0] = '\0';
+ pwdev_priv->rtw_wdev = wdev;
+ pwdev_priv->padapter = padapter;
+ pwdev_priv->scan_request = NULL;
+ _rtw_spinlock_init(&pwdev_priv->scan_req_lock);
+
+ pwdev_priv->p2p_enabled = _FALSE;
+ pwdev_priv->provdisc_req_issued = _FALSE;
+
+ pwdev_priv->bandroid_scan = _FALSE;
+
+#ifdef CONFIG_CONCURRENT_MODE
+ ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
+ ATOMIC_SET(&pwdev_priv->ro_ch_to, 1);
+#endif
+
+ wdev->netdev = pnetdev;
+ //wdev->iftype = NL80211_IFTYPE_STATION;
+ wdev->iftype = NL80211_IFTYPE_MONITOR; // for rtw_setopmode_cmd() in cfg80211_rtw_change_iface()
+
+ rtw_cfg80211_preinit_wiphy(padapter, wdev->wiphy);
+
+ ret = wiphy_register(wdev->wiphy);
+ if (ret < 0) {
+ printk("Couldn't register wiphy device\n");
+ goto out_err_register;
+ }
+
+ SET_NETDEV_DEV(pnetdev, wiphy_dev(wdev->wiphy));
+
+ return ret;
+
+ out_err_register:
+ wiphy_free(wdev->wiphy);
+
+ out_err_new:
+ rtw_mfree((u8*)wdev, sizeof(struct wireless_dev));
+
+ return ret;
+
+}
+
+void rtw_wdev_free(struct wireless_dev *wdev)
+{
+ struct rtw_wdev_priv *pwdev_priv;
+
+ printk("%s(wdev=%p)\n", __func__, wdev);
+
+ if (!wdev)
+ return;
+
+ pwdev_priv = wdev_to_priv(wdev);
+
+ printk("%s, scan abort when device remove\n", __func__);
+ rtw_cfg80211_indicate_scan_done(pwdev_priv, _TRUE);
+
+ if(pwdev_priv->pmon_ndev)
+ {
+ printk("%s, unregister monitor interface\n", __func__);
+
+ unregister_netdev(pwdev_priv->pmon_ndev);
+
+ free_netdev(pwdev_priv->pmon_ndev);
+ }
+
+
+ wiphy_unregister(wdev->wiphy);
+
+ rtw_spt_band_free(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
+ rtw_spt_band_free(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
+
+ wiphy_free(wdev->wiphy);
+
+ rtw_mfree((u8*)wdev, sizeof(struct wireless_dev));
+}
+
+#endif //CONFIG_IOCTL_CFG80211
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_linux.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_linux.c
new file mode 100755
index 000000000000..a403f2f9dc70
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/ioctl_linux.c
@@ -0,0 +1,10981 @@
+/******************************************************************************
+ *
+ * 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_MP_INCLUDED
+#include <rtw_mp.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
+
+// combo scan
+#define WEXT_CSCAN_AMOUNT 9
+#define WEXT_CSCAN_BUF_LEN 360
+#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);
+extern u8 convert_ip_addr(u8 hch, u8 mch, u8 lch);
+
+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 indicate_wx_custom_event(_adapter *padapter, char *msg)
+{
+ u8 *buff, *p;
+ union iwreq_data wrqu;
+
+ if (strlen(msg) > IW_CUSTOM_MAX) {
+ DBG_871X("%s strlen(msg):%u > IW_CUSTOM_MAX:%u\n", __FUNCTION__ ,strlen(msg), IW_CUSTOM_MAX);
+ return;
+ }
+
+ buff = rtw_zmalloc(IW_CUSTOM_MAX+1);
+ if(!buff)
+ return;
+
+ _rtw_memcpy(buff, msg, strlen(msg));
+
+ _rtw_memset(&wrqu,0,sizeof(wrqu));
+ wrqu.data.length = strlen(msg);
+
+ DBG_871X("%s %s\n", __FUNCTION__, buff);
+ wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
+
+ rtw_mfree(buff, IW_CUSTOM_MAX+1);
+
+}
+
+
+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_871X("%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_871X("+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_871X("+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_871X("+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_P2P
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ 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);
+
+ /* Add the ESSID */
+ 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);
+
+ //parsing HT_CAP_IE
+ p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
+
+ if(p && ht_ielen>0)
+ {
+ struct rtw_ieee80211_ht_cap *pht_capie;
+ ht_cap = _TRUE;
+ pht_capie = (struct rtw_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);
+
+ /* 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);
+
+ /*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_871X("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);
+
+ //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
+ uint cnt = 0,total_ielen;
+ 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_;
+
+ 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
+ }
+ }
+
+ /* 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_871X("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_SIGNAL_DISPLAY_DBM
+ | IW_QUAL_DBM
+ #endif
+ ;
+
+ #ifdef CONFIG_SIGNAL_DISPLAY_DBM
+ iwe.u.qual.level = (u8) translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);//dbm
+ #else
+ iwe.u.qual.level = (u8)pnetwork->network.PhyInfo.SignalStrength;//%
+ #endif
+
+ iwe.u.qual.qual = (u8)pnetwork->network.PhyInfo.SignalQuality; // 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_871X("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_871X("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_871X("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_871X("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_871X("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
+ }
+ else
+ {
+ DBG_871X("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,wep_total_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_871X("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_871X("(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;
+ wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+ pwep =(NDIS_802_11_WEP *) rtw_malloc(wep_total_len);
+ 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, wep_total_len);
+
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+
+ 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_871X("wep, set_tx=1\n");
+
+ if(rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
+ {
+ ret = -EOPNOTSUPP ;
+ }
+ }
+ else
+ {
+ DBG_871X("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(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+ {
+ rtw_p2p_set_state(pwdinfo, 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_total_len);
+ }
+
+ _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_871X("\n wpa_ie(length:%d):\n", ielen);
+ for(i=0;i<ielen;i=i+8)
+ DBG_871X("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;
+ _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+ }
+
+ if(rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher) == _SUCCESS)
+ {
+ padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
+ padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPA2PSK;
+ _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+ }
+
+ 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_871X("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(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
+ {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
+ }
+#endif //CONFIG_P2P
+ DBG_871X("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 == rtw_pwr_wakeup(padapter)) {
+ ret= -EPERM;
+ goto exit;
+ }
+
+ if (padapter->hw_init_completed==_FALSE){
+ ret = -EPERM;
+ goto exit;
+ }
+
+ switch(wrqu->mode)
+ {
+ case IW_MODE_AUTO:
+ networkType = Ndis802_11AutoUnknown;
+ DBG_871X("set_mode = IW_MODE_AUTO\n");
+ break;
+ case IW_MODE_ADHOC:
+ networkType = Ndis802_11IBSS;
+ DBG_871X("set_mode = IW_MODE_ADHOC\n");
+ break;
+ case IW_MODE_MASTER:
+ networkType = Ndis802_11APMode;
+ DBG_871X("set_mode = IW_MODE_MASTER\n");
+ //rtw_setopmode_cmd(padapter, networkType);
+ break;
+ case IW_MODE_INFRA:
+ networkType = Ndis802_11Infrastructure;
+ DBG_871X("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 = -EPERM;
+ 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_871X( "[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_871X( "[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_871X( "[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_871X( "[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_871X( "[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)
+{
+ _irqL irqL;
+ 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_;
+/*
+#ifdef CONFIG_CONCURRENT_MODE
+ if(padapter->iface_type > PRIMARY_IFACE)
+ {
+ ret = -EINVAL;
+ goto exit;
+ }
+#endif
+*/
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
+ {
+ printk("set bssid, but buddy_intf is under scanning or linking\n");
+
+ ret = -EINVAL;
+
+ goto exit;
+ }
+#endif
+
+#ifdef CONFIG_DUALMAC_CONCURRENT
+ if (dc_check_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)== _TRUE)
+ {
+ printk("set bssid, but buddy_intf is under scanning or linking\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+#endif
+
+ if(_FAIL == rtw_pwr_wakeup(padapter))
+ {
+ ret= -1;
+ goto exit;
+ }
+
+ if(!padapter->bup){
+ ret = -1;
+ goto exit;
+ }
+
+
+ if (temp->sa_family != ARPHRD_ETHER){
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ authmode = padapter->securitypriv.ndisauthtype;
+ _enter_critical_bh(&queue->lock, &irqL);
+ 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
+
+ break;
+ }
+
+ 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;
+ _exit_critical_bh(&queue->lock, &irqL);
+ goto exit;
+ }
+
+ break;
+ }
+
+ }
+ _exit_critical_bh(&queue->lock, &irqL);
+
+ 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;
+
+ printk("%s\n", __FUNCTION__);
+
+ reason = cpu_to_le16(mlme->reason_code);
+
+
+ printk("%s, cmd=%d, reason=%d\n", __FUNCTION__, mlme->cmd, reason);
+
+ 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;
+
+}
+
+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[RTW_SSID_SCAN_AMOUNT];
+ _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_CONCURRENT_MODE
+ if(padapter->iface_type > PRIMARY_IFACE)
+ {
+ ret = -1;
+ goto exit;
+ }
+#endif
+*/
+
+#ifdef CONFIG_MP_INCLUDED
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
+ {
+ ret = -1;
+ goto exit;
+ }
+#endif
+
+ if(_FAIL == rtw_pwr_wakeup(padapter))
+ {
+ ret= -1;
+ goto exit;
+ }
+
+ if(padapter->bDriverStopped){
+ DBG_871X("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;
+ }
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
+ {
+ if(check_buddy_fwstate(padapter, _FW_UNDER_SURVEY))
+ {
+ printk("scanning_via_buddy_intf\n");
+ pmlmepriv->scanning_via_buddy_intf = _TRUE;
+ }
+
+ indicate_wx_scan_complete_event(padapter);
+
+ goto exit;
+ }
+#endif
+
+#ifdef CONFIG_DUALMAC_CONCURRENT
+ if (dc_check_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)== _TRUE)
+ {
+ indicate_wx_scan_complete_event(padapter);
+ goto exit;
+ }
+#endif
+
+// 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_871X("scan done\n");
+ ret = 0;
+ goto exit;
+ }
+
+*/
+#ifdef CONFIG_P2P
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
+ rtw_free_network_queue(padapter, _TRUE);
+ }
+#endif //CONFIG_P2P
+
+ _rtw_memset(ssid, 0, sizeof(NDIS_802_11_SSID)*RTW_SSID_SCAN_AMOUNT);
+
+#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_memcpy(ssid[0].Ssid, req->essid, len);
+ ssid[0].SsidLength = len;
+
+ DBG_871X("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, 1);
+
+ _exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+ }
+ else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
+ {
+ DBG_871X("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;
+ int ssid_index = 0;
+
+ //DBG_871X("%s COMBO_SCAN header is recognized\n", __FUNCTION__);
+
+ while(len >= 1) {
+ section = *(pos++); len-=1;
+
+ switch(section) {
+ case WEXT_CSCAN_SSID_SECTION:
+ //DBG_871X("WEXT_CSCAN_SSID_SECTION\n");
+ if(len < 1) {
+ len = 0;
+ break;
+ }
+
+ sec_len = *(pos++); len-=1;
+
+ if(sec_len>0 && sec_len<=len) {
+ ssid[ssid_index].SsidLength = sec_len;
+ _rtw_memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
+ //DBG_871X("%s COMBO_SCAN with specific ssid:%s, %d\n", __FUNCTION__
+ // , ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength);
+ ssid_index++;
+ }
+
+ pos+=sec_len; len-=sec_len;
+ break;
+
+
+ case WEXT_CSCAN_CHANNEL_SECTION:
+ //DBG_871X("WEXT_CSCAN_CHANNEL_SECTION\n");
+ pos+=1; len-=1;
+ break;
+ case WEXT_CSCAN_ACTV_DWELL_SECTION:
+ //DBG_871X("WEXT_CSCAN_ACTV_DWELL_SECTION\n");
+ pos+=2; len-=2;
+ break;
+ case WEXT_CSCAN_PASV_DWELL_SECTION:
+ //DBG_871X("WEXT_CSCAN_PASV_DWELL_SECTION\n");
+ pos+=2; len-=2;
+ break;
+ case WEXT_CSCAN_HOME_DWELL_SECTION:
+ //DBG_871X("WEXT_CSCAN_HOME_DWELL_SECTION\n");
+ pos+=2; len-=2;
+ break;
+ case WEXT_CSCAN_TYPE_SECTION:
+ //DBG_871X("WEXT_CSCAN_TYPE_SECTION\n");
+ pos+=1; len-=1;
+ break;
+ #if 0
+ case WEXT_CSCAN_NPROBE_SECTION:
+ DBG_871X("WEXT_CSCAN_NPROBE_SECTION\n");
+ break;
+ #endif
+
+ default:
+ //DBG_871X("Unknown CSCAN section %c\n", section);
+ len = 0; // stop parsing
+ }
+ //DBG_871X("len:%d\n", len);
+
+ }
+
+ //jeff: it has still some scan paramater to parse, we only do this now...
+ _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
+
+ } else
+
+ {
+ _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
+ }
+
+ 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;
+}
+
+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;
+ sint wait_status;
+#ifdef CONFIG_CONCURRENT_MODE
+ //PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+ //struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
+#endif
+#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
+
+/*
+#ifdef CONFIG_CONCURRENT_MODE
+ if(padapter->iface_type > PRIMARY_IFACE)
+ {
+ ret = -EINVAL;
+ goto exit;
+ }
+#endif
+*/
+ if(padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped)
+ {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+#ifdef CONFIG_P2P
+ if(!rtw_p2p_chk_state(pwdinfo, 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
+
+/*
+#ifdef CONFIG_CONCURRENT_MODE
+ if(pmlmepriv->scanning_via_buddy_intf == _TRUE)
+ {
+ pmlmepriv->scanning_via_buddy_intf = _FALSE;//reset
+
+ // change pointers to buddy interface
+ padapter = pbuddy_adapter;
+ pmlmepriv = pbuddy_mlmepriv;
+ queue = &(pbuddy_mlmepriv->scanned_queue);
+
+ }
+#endif // CONFIG_CONCURRENT_MODE
+*/
+
+ wait_status = _FW_UNDER_SURVEY
+ #ifndef CONFIG_ANDROID
+ |_FW_UNDER_LINKING
+ #endif
+ ;
+
+#ifdef CONFIG_DUALMAC_CONCURRENT
+ while(dc_check_fwstate(padapter, wait_status)== _TRUE)
+ {
+ rtw_msleep_os(30);
+ cnt++;
+ if(cnt > wait_for_surveydone )
+ break;
+ }
+#endif // CONFIG_DUALMAC_CONCURRENT
+
+ while(check_fwstate(pmlmepriv, wait_status) == _TRUE)
+ {
+ rtw_msleep_os(30);
+ cnt++;
+ if(cnt > wait_for_surveydone )
+ break;
+ }
+
+ _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);
+
+ //report network only if the current channel set contains the channel to which this network belongs
+ if( _TRUE == rtw_is_channel_set_contains_channel(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig)
+ #ifdef CONFIG_VALIDATE_SSID
+ && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))
+ #endif
+ )
+ {
+ 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)
+{
+ _irqL irqL;
+ _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
+
+/*
+#ifdef CONFIG_CONCURRENT_MODE
+ if(padapter->iface_type > PRIMARY_IFACE)
+ {
+ ret = -EINVAL;
+ goto exit;
+ }
+#endif
+*/
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
+ {
+ printk("set ssid, but buddy_intf is under scanning or linking\n");
+
+ ret = -EINVAL;
+
+ goto exit;
+ }
+#endif
+
+#ifdef CONFIG_DUALMAC_CONCURRENT
+ if (dc_check_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)== _TRUE)
+ {
+ printk("set bssid, but buddy_intf is under scanning or linking\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+#endif
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
+ ("+rtw_wx_set_essid: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
+ if(_FAIL == rtw_pwr_wakeup(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_871X("=>%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_871X("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));
+ _enter_critical_bh(&queue->lock, &irqL);
+ 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;
+ _exit_critical_bh(&queue->lock, &irqL);
+ goto exit;
+ }
+
+ break;
+ }
+ }
+ _exit_critical_bh(&queue->lock, &irqL);
+ 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;
+ }
+ }
+
+exit:
+
+ DBG_871X("<=%s, ret %d\n",__FUNCTION__, ret);
+
+ #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)
+{
+ u16 max_rate = 0;
+
+ max_rate = rtw_get_cur_max_rate((_adapter *)rtw_netdev_priv(dev));
+
+ if(max_rate == 0)
+ return -EPERM;
+
+ wrqu->bitrate.fixed = 0; /* no auto select */
+ wrqu->bitrate.value = max_rate * 100000;
+
+ 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_871X("+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_871X("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_871X("rtw_wx_set_enc, key=%d\n", key);
+ }
+
+ //set authentication mode
+ if(erq->flags & IW_ENCODE_OPEN)
+ {
+ DBG_871X("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_871X("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_871X("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_871X("(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) || 1
+ /*
+ * 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, 1);
+ }
+ #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_871X("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_871X("enc_alg=0x%x\n", psecuritypriv->dot11PrivacyAlgrthm);
+ //DBG_871X("auth_type=0x%x\n", psecuritypriv->ndisauthtype);
+ //DBG_871X("enc_type=0x%x\n", psecuritypriv->ndisencryptstatus);
+
+#if 0
+ DBG_871X("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
+ DBG_871X("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
+ DBG_871X("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
+ DBG_871X("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
+ DBG_871X("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
+
+ DBG_871X("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
+
+
+ DBG_871X("\n");
+
+ DBG_871X("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
+ DBG_871X("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
+
+ DBG_871X("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
+
+ DBG_871X("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
+
+ DBG_871X("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
+ DBG_871X("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
+
+ DBG_871X("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
+ DBG_871X("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
+ DBG_871X("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
+ DBG_871X("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)
+{
+ PADAPTER padapter;
+ struct iw_point *p;
+ u16 len;
+ u32 addr;
+ u32 data32;
+ u32 bytes;
+ u8 *ptmp;
+
+
+ padapter = (PADAPTER)rtw_netdev_priv(dev);
+ p = &wrqu->data;
+ len = p->length;
+ ptmp = (u8*)rtw_malloc(len);
+ if (NULL == ptmp)
+ return -ENOMEM;
+
+ if (copy_from_user(ptmp, p->pointer, len)) {
+ rtw_mfree(ptmp, len);
+ return -EFAULT;
+ }
+
+ bytes = 0;
+ addr = 0;
+ sscanf(ptmp, "%d,%x", &bytes, &addr);
+
+ switch (bytes) {
+ case 1:
+ data32 = rtw_read8(padapter, addr);
+ sprintf(extra, "0x%02X", data32);
+ break;
+ case 2:
+ data32 = rtw_read16(padapter, addr);
+ sprintf(extra, "0x%04X", data32);
+ break;
+ case 4:
+ data32 = rtw_read32(padapter, addr);
+ sprintf(extra, "0x%08X", data32);
+ break;
+ default:
+ printk(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
+ return -EINVAL;
+ }
+ printk(KERN_INFO "%s: addr=0x%08X data=%s\n", __func__, addr, extra);
+
+ rtw_mfree(ptmp, len);
+
+ return 0;
+}
+
+static int rtw_wx_write32(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+ u32 addr;
+ u32 data32;
+ u32 bytes;
+
+
+ bytes = 0;
+ addr = 0;
+ data32 = 0;
+ sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
+
+ switch (bytes) {
+ case 1:
+ rtw_write8(padapter, addr, (u8)data32);
+ printk(KERN_INFO "%s: addr=0x%08X data=0x%02X\n", __func__, addr, (u8)data32);
+ break;
+ case 2:
+ rtw_write16(padapter, addr, (u16)data32);
+ printk(KERN_INFO "%s: addr=0x%08X data=0x%04X\n", __func__, addr, (u16)data32);
+ break;
+ case 4:
+ rtw_write32(padapter, addr, data32);
+ printk(KERN_INFO "%s: addr=0x%08X data=0x%08X\n", __func__, addr, data32);
+ break;
+ default:
+ printk(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
+ return -EINVAL;
+ }
+
+ 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_871X("%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_871X("%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_871X("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;
+ u8 channel_plan_req = (u8) (*((int *)wrqu));
+
+ #if 0
+ rtw_channel_plan = (int)wrqu->data.pointer;
+ pregistrypriv->channel_plan = rtw_channel_plan;
+ pmlmepriv->ChannelPlan = pregistrypriv->channel_plan;
+ #endif
+
+ if( _SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1) ) {
+ 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);
+
+ // Modified by Albert 20110914
+ // This is in dbm format for MTK platform.
+ wrqu->qual.level = padapter->recvpriv.rssi;
+ DBG_871X(" 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_871X("%s\n", __FUNCTION__);
+
+ switch(id)
+ {
+ case GEN_MP_IOCTL_SUBCODE(MP_START):
+ DBG_871X("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_871X("==> 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_871X("==> 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_871X("==> delete ba:%x\n",*(u8 *)pdata);
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_BT_ISSUE_DELBA, pdata);
+ break;
+#endif
+#ifdef DBG_CONFIG_ERROR_DETECT
+ case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
+ *pdata = rtw_hal_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;
+ u32 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;
+ PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
+ struct iw_point *p = &wrqu->data;
+
+ //DBG_871X("+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_871X("%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_871X("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_871X("+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_871X("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_871X("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_871X( "[%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);
+ }
+
+#ifdef CONFIG_INTEL_WIDI
+ process_intel_widi_wps_status(padapter, u32wps_start);
+#endif //CONFIG_INTEL_WIDI
+
+exit:
+
+ return ret;
+
+}
+
+#ifdef CONFIG_P2P
+static int rtw_wext_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;
+ enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
+
+ if(*extra == '0' )
+ init_role = P2P_ROLE_DISABLE;
+ else if(*extra == '1')
+ init_role = P2P_ROLE_DEVICE;
+ else if(*extra == '2')
+ init_role = P2P_ROLE_CLIENT;
+ else if(*extra == '3')
+ init_role = P2P_ROLE_GO;
+
+ if(_FAIL == rtw_p2p_enable(padapter, init_role))
+ {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ //set channel/bandwidth
+ if(init_role != P2P_ROLE_DISABLE)
+ {
+ u8 channel, ch_offset;
+ u16 bwmode;
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
+ {
+ // Stay at the listen state and wait for discovery.
+ channel = pwdinfo->listen_channel;
+ pwdinfo->operating_channel = pwdinfo->listen_channel;
+ ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ bwmode = HT_CHANNEL_WIDTH_20;
+ }
+#ifdef CONFIG_CONCURRENT_MODE
+ else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
+ {
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ //struct wifidirect_info *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
+ struct mlme_priv *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+ _set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval );
+ if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
+ {
+ pwdinfo->operating_channel = pbuddy_mlmeext->cur_channel;
+ // How about the ch_offset and bwmode ??
+ }
+ else
+ {
+ pwdinfo->operating_channel = pwdinfo->listen_channel;
+ }
+ }
+#endif
+ 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);
+ }
+
+exit:
+ 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_871X( "[%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 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_871X( "[%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 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 == 1 ) || ( listen_ch == 6 ) || ( listen_ch == 11 ) )
+ {
+ 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_871X( "[%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 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 )
+ {
+ pwdinfo->operating_channel = op_ch;
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ DBG_871X( "[%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 wifidirect_info *pwdinfo= &(padapter->wdinfo);
+
+ // Comment by Albert 2010/10/13
+ // Input data format:
+ // Ex: 0
+ // Ex: 1XX:XX:XX:XX:XX:XXYYSSID
+ // 0 => Reflush the profile record list.
+ // 1 => Add the profile list
+ // XX:XX:XX:XX:XX:XX => peer's MAC Address ( ex: 00:E0:4C:00:00:01 )
+ // YY => SSID Length
+ // SSID => SSID for persistence group
+
+ DBG_871X( "[%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(!rtw_p2p_chk_state(pwdinfo, 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: 1XX:XX:XX:XX:XX:XXYYSSID
+ for( jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3 )
+ {
+ pwdinfo->profileinfo[ pwdinfo->profileindex ].peermac[ jj ] = key_2char2num(extra[ kk ], extra[ kk+ 1 ]);
+ }
+
+ //pwdinfo->profileinfo[ pwdinfo->profileindex ].ssidlen = ( extra[18] - '0' ) * 10 + ( extra[ 19 ] - '0' );
+ //_rtw_memcpy( pwdinfo->profileinfo[ pwdinfo->profileindex ].ssid, &extra[ 20 ], 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 wifidirect_info *pwdinfo= &(padapter->wdinfo);
+
+
+ DBG_871X( "[%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_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ 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", rtw_p2p_state(pwdinfo) );
+ wrqu->data.length = strlen( extra );
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
+ {
+ // Stay at the listen state and wait for discovery.
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( !check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }
+#else
+ set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+#endif
+ }
+
+ 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_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ 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", rtw_p2p_role(pwdinfo) );
+ 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_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ 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_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ 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_groupid(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%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
+ pwdinfo->groupid_info.go_device_addr[ 0 ], pwdinfo->groupid_info.go_device_addr[ 1 ],
+ pwdinfo->groupid_info.go_device_addr[ 2 ], pwdinfo->groupid_info.go_device_addr[ 3 ],
+ pwdinfo->groupid_info.go_device_addr[ 4 ], pwdinfo->groupid_info.go_device_addr[ 5 ],
+ pwdinfo->groupid_info.ssid);
+ 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;
+ u16 attr_content = 0;
+ uint attr_contentlen = 0;
+ //6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer
+ u8 attr_content_str[ 6 + 17 ] = { 0x00 };
+
+ // 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_871X( "[%s] data = %s\n", __FUNCTION__, ( char* ) extra );
+ if ( copy_from_user(peerMACStr, wrqu->data.pointer + 6 , 17) ) {
+ return -EFAULT;
+ }
+
+
+ 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;
+ uint wpsie_len = 0;
+
+ // The mac address is matched.
+
+ if ( (wpsie=rtw_get_wps_ie( &pnetwork->network.IEs[ 12 ], pnetwork->network.IELength - 12, NULL, &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( attr_content_str, "\n\nM=%.4d", attr_content );
+ blnMatch = 1;
+ }
+ }
+
+ break;
+ }
+
+ plist = get_next(plist);
+
+ }
+
+ _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+ if ( !blnMatch )
+ {
+ sprintf( attr_content_str, "\n\nM=0000" );
+ }
+
+ if ( copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17)) {
+ return -EFAULT;
+ }
+
+ 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_871X( "[%s] p2p_state = %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );
+
+ sprintf( extra, "\n\nPort=%d\n", pwdinfo->wfd_info->peer_rtsp_ctrlport );
+ DBG_871X( "[%s] remote port = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
+
+ wrqu->data.length = strlen( extra );
+ return ret;
+
+}
+
+static int rtw_p2p_get_peer_wfd_preferred_connection(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\nwfd_pc=%d\n", pwdinfo->wfd_info->wfd_pc );
+ DBG_871X( "[%s] wfd_pc = %d\n", __FUNCTION__, pwdinfo->wfd_info->wfd_pc );
+
+ wrqu->data.length = strlen( extra );
+ pwdinfo->wfd_info->wfd_pc = _FALSE; // Reset the WFD preferred connection to P2P
+ return ret;
+
+}
+
+static int rtw_p2p_get_peer_wfd_session_available(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\nwfd_sa=%d\n", pwdinfo->wfd_info->peer_session_avail );
+ DBG_871X( "[%s] wfd_sa = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_session_avail );
+
+ wrqu->data.length = strlen( extra );
+ pwdinfo->wfd_info->peer_session_avail = _TRUE; // Reset the WFD session available
+ 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;
+ u8 dev_name[ WPS_MAX_DEVICE_NAME_LEN ] = { 0x00 };
+ uint dev_len = 0;
+ u8 dev_name_str[ WPS_MAX_DEVICE_NAME_LEN + 5 ] = { 0x00 }; // +5 is for the str "devN=", we have to clear it at wrqu->data.pointer
+
+ // 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_871X( "[%s] data = %s\n", __FUNCTION__, ( char* ) extra );
+ if ( copy_from_user(peerMACStr, wrqu->data.pointer + 5 , 17) ) {
+ return -EFAULT;
+ }
+
+ 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;
+ uint wpsie_len = 0;
+
+ // The mac address is matched.
+
+ if ( (wpsie=rtw_get_wps_ie( &pnetwork->network.IEs[ 12 ], pnetwork->network.IELength - 12, NULL, &wpsie_len )) )
+ {
+ rtw_get_wps_attr_content( wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
+ if ( dev_len )
+ {
+ sprintf( dev_name_str, "\n\nN=%s", dev_name );
+ blnMatch = 1;
+ }
+ }
+ break;
+ }
+
+ plist = get_next(plist);
+
+ }
+
+ _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+ if ( !blnMatch )
+ {
+ sprintf( dev_name_str, "\n\nN=0000" );
+ }
+
+ if ( copy_to_user(wrqu->data.pointer, dev_name_str, 5+ (( dev_len > 17 )? dev_len : 17) )) {
+ return -EFAULT;
+ }
+
+ 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 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;
+#ifdef CONFIG_CONCURRENT_MODE
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif // CONFIG_CONCURRENT_MODE
+
+
+ // 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_871X( "[%s] data = %s\n", __FUNCTION__, extra );
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ DBG_871X( "[%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 )
+ {
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
+ }
+#endif // CONFIG_CONCURRENT_MODE
+
+ _rtw_memset( &pwdinfo->nego_req_info, 0x00, sizeof( struct tx_nego_req_info ) );
+ _rtw_memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_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;
+
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ // Have to enter the power saving with the AP
+ set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
+ issue_nulldata( pbuddy_adapter, 1 );
+ issue_nulldata( pbuddy_adapter, 1 );
+ }
+#endif // CONFIG_CONCURRENT_MODE
+
+ DBG_871X( "[%s] Start PreTx Procedure!\n", __FUNCTION__ );
+ _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_GO_NEGO_TIMEOUT );
+ }
+ else
+ {
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT );
+ }
+#else
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT );
+#endif // CONFIG_CONCURRENT_MODE
+
+ }
+ else
+ {
+ DBG_871X( "[%s] Not Found in Scanning Queue~\n", __FUNCTION__ );
+ ret = -1;
+ }
+exit:
+ return ret;
+}
+
+static int rtw_p2p_invite_req(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 );
+ 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 attr_content[50] = { 0x00 }, _status = 0;
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ _irqL irqL;
+ struct tx_invite_req_info* pinvite_req_info = &pwdinfo->invitereq_info;
+#ifdef CONFIG_CONCURRENT_MODE
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_priv *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif // CONFIG_CONCURRENT_MODE
+
+#ifdef CONFIG_WFD
+ struct wifi_display_info* pwfd_info = pwdinfo->wfd_info;
+#endif // CONFIG_WFD
+
+ // Commented by Albert 20120321
+ // The input data contains two informations.
+ // 1. First information is the P2P device address which you want to send to.
+ // 2. Second information is the group id which combines with GO's mac address, space and GO's ssid.
+ // Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy"
+ // Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy
+
+ DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
+
+ if ( wrqu->data.length <= 37 )
+ {
+ DBG_871X( "[%s] Wrong format!\n", __FUNCTION__ );
+ return ret;
+ }
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
+ return ret;
+ }
+ else
+ {
+ // Reset the content of struct tx_invite_req_info
+ pinvite_req_info->benable = _FALSE;
+ _rtw_memset( pinvite_req_info->go_bssid, 0x00, ETH_ALEN );
+ _rtw_memset( pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN );
+ pinvite_req_info->ssidlen = 0x00;
+ pinvite_req_info->operating_ch = pwdinfo->operating_channel;
+ _rtw_memset( pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN );
+ pinvite_req_info->token = 3;
+ }
+
+ for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
+ {
+ pinvite_req_info->peer_macaddr[ 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);
+
+ // 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 ( (p2pie=rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &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, pinvite_req_info->peer_macaddr, 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, pinvite_req_info->peer_macaddr, ETH_ALEN ) )
+ {
+ uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+ break;
+ }
+ }
+
+ }
+
+ plist = get_next(plist);
+
+ }
+
+ _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+#ifdef CONFIG_WFD
+ if ( uintPeerChannel )
+ {
+ u8 wfd_ie[ 128 ] = { 0x00 };
+ uint wfd_ielen = 0;
+
+ if ( rtw_get_wfd_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, wfd_ie, &wfd_ielen ) )
+ {
+ u8 wfd_devinfo[ 6 ] = { 0x00 };
+ uint wfd_devlen = 6;
+
+ DBG_871X( "[%s] Found WFD IE!\n", __FUNCTION__ );
+ if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
+ {
+ u16 wfd_devinfo_field = 0;
+
+ // Commented by Albert 20120319
+ // The first two bytes are the WFD device information field of WFD device information subelement.
+ // In big endian format.
+ wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
+ if ( wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL )
+ {
+ pwfd_info->peer_session_avail = _TRUE;
+ }
+ else
+ {
+ pwfd_info->peer_session_avail = _FALSE;
+ }
+ }
+ }
+
+ if ( _FALSE == pwfd_info->peer_session_avail )
+ {
+ DBG_871X( "[%s] WFD Session not avaiable!\n", __FUNCTION__ );
+ goto exit;
+ }
+ }
+#endif // CONFIG_WFD
+
+ if ( uintPeerChannel )
+ {
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
+ {
+ _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
+ }
+#endif // CONFIG_CONCURRENT_MODE
+
+ // Store the GO's bssid
+ for( jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3 )
+ {
+ pinvite_req_info->go_bssid[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
+ }
+
+ // Store the GO's ssid
+ pinvite_req_info->ssidlen = wrqu->data.length - 36;
+ _rtw_memcpy( pinvite_req_info->go_ssid, &extra[ 36 ], (u32) pinvite_req_info->ssidlen );
+ pinvite_req_info->benable = _TRUE;
+ pinvite_req_info->peer_ch = uintPeerChannel;
+
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
+ {
+ // Have to enter the power saving with the AP
+ set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
+ issue_nulldata( pbuddy_adapter, 1 );
+ issue_nulldata( pbuddy_adapter, 1 );
+ }
+ else
+ {
+ set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }
+#else
+ set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+#endif
+
+ _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
+ {
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_INVITE_TIMEOUT );
+ }
+ else
+ {
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT );
+ }
+#else
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT );
+#endif // CONFIG_CONCURRENT_MODE
+
+
+ }
+ else
+ {
+ DBG_871X( "[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__ );
+ }
+exit:
+
+ return ret;
+
+}
+
+static int rtw_p2p_set_persistent(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 );
+ 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 attr_content[50] = { 0x00 }, _status = 0;
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ _irqL irqL;
+ struct tx_invite_req_info* pinvite_req_info = &pwdinfo->invitereq_info;
+#ifdef CONFIG_CONCURRENT_MODE
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_priv *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif // CONFIG_CONCURRENT_MODE
+
+#ifdef CONFIG_WFD
+ struct wifi_display_info* pwfd_info = pwdinfo->wfd_info;
+#endif // CONFIG_WFD
+
+ // Commented by Albert 20120328
+ // The input data is 0 or 1
+ // 0: disable persistent group functionality
+ // 1: enable persistent group founctionality
+
+ DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
+ return ret;
+ }
+ else
+ {
+ if ( extra[ 0 ] == '0' ) // Disable the persistent group function.
+ {
+ pwdinfo->persistent_supported = _FALSE;
+ }
+ else if ( extra[ 0 ] == '1' ) // Enable the persistent group function.
+ {
+ pwdinfo->persistent_supported = _TRUE;
+ }
+ else
+ {
+ pwdinfo->persistent_supported = _FALSE;
+ }
+ }
+ printk( "[%s] persistent_supported = %d\n", __FUNCTION__, pwdinfo->persistent_supported );
+
+exit:
+
+ return ret;
+
+}
+
+static int rtw_p2p_set_pc(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;
+ u8 attr_content[50] = { 0x00 }, _status = 0;
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ _irqL irqL;
+ uint uintPeerChannel = 0;
+#ifdef CONFIG_CONCURRENT_MODE
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif // CONFIG_CONCURRENT_MODE
+
+#ifdef CONFIG_WFD
+ struct wifi_display_info* pwfd_info = pwdinfo->wfd_info;
+#endif // CONFIG_WFD
+
+ // Commented by Albert 20120512
+ // 1. Input information is the MAC address which wants to know the Preferred Connection bit (PC bit)
+ // Format: 00:E0:4C:00:00:05
+
+ DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
+ return ret;
+ }
+
+ 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);
+
+ // 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 ( (p2pie=rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)) )
+ {
+ // The P2P Device ID attribute is included in the Beacon frame.
+ // The P2P Device Info attribute is included in the probe response frame.
+ printk( "[%s] Got P2P IE\n", __FUNCTION__ );
+ 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
+ printk( "[%s] P2P_ATTR_DEVICE_ID \n", __FUNCTION__ );
+ 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
+ printk( "[%s] P2P_ATTR_DEVICE_INFO \n", __FUNCTION__ );
+ 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);
+ printk( "[%s] channel = %d\n", __FUNCTION__, uintPeerChannel );
+#ifdef CONFIG_WFD
+ if ( uintPeerChannel )
+ {
+ u8 wfd_ie[ 128 ] = { 0x00 };
+ uint wfd_ielen = 0;
+
+ if ( rtw_get_wfd_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, wfd_ie, &wfd_ielen ) )
+ {
+ u8 wfd_devinfo[ 6 ] = { 0x00 };
+ uint wfd_devlen = 6;
+
+ DBG_871X( "[%s] Found WFD IE!\n", __FUNCTION__ );
+ if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
+ {
+ u16 wfd_devinfo_field = 0;
+
+ // Commented by Albert 20120319
+ // The first two bytes are the WFD device information field of WFD device information subelement.
+ // In big endian format.
+ wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
+ if ( wfd_devinfo_field & WFD_DEVINFO_PC_TDLS )
+ {
+ pwfd_info->wfd_pc = _TRUE;
+ }
+ else
+ {
+ pwfd_info->wfd_pc = _FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ DBG_871X( "[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__ );
+ }
+#endif // CONFIG_WFD
+
+exit:
+
+ return ret;
+
+}
+
+// To set the WFD session available to enable or disable
+static int rtw_p2p_set_sa(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 );
+ 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 attr_content[50] = { 0x00 }, _status = 0;
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ _irqL irqL;
+ struct tx_invite_req_info* pinvite_req_info = &pwdinfo->invitereq_info;
+#ifdef CONFIG_CONCURRENT_MODE
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_priv *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif // CONFIG_CONCURRENT_MODE
+
+#ifdef CONFIG_WFD
+ struct wifi_display_info* pwfd_info = pwdinfo->wfd_info;
+#endif // CONFIG_WFD
+
+ // Commented by Albert 20120328
+ // The input data is 0 or 1
+ // 0: disable persistent group functionality
+ // 1: enable persistent group founctionality
+
+ DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
+
+ if( 0 )
+ {
+ DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
+ return ret;
+ }
+ else
+ {
+ if ( extra[ 0 ] == '0' ) // Disable the session available.
+ {
+ pwdinfo->session_available = _FALSE;
+ }
+ else if ( extra[ 0 ] == '1' ) // Enable the session available.
+ {
+ pwdinfo->session_available = _TRUE;
+ }
+ else
+ {
+ pwdinfo->session_available = _FALSE;
+ }
+ }
+ printk( "[%s] session available = %d\n", __FUNCTION__, pwdinfo->session_available );
+
+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 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 attr_content[50] = { 0x00 }, _status = 0;
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ _irqL irqL;
+#ifdef CONFIG_CONCURRENT_MODE
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif // CONFIG_CONCURRENT_MODE
+
+#ifdef CONFIG_WFD
+ struct wifi_display_info* pwfd_info = pwdinfo->wfd_info;
+#endif // CONFIG_WFD
+
+ // 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_871X( "[%s] data = %s\n", __FUNCTION__, extra );
+
+ if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ DBG_871X( "[%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_871X( "[%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 ( (p2pie=rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &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);
+
+#ifdef CONFIG_WFD
+ {
+ u8 wfd_ie[ 128 ] = { 0x00 };
+ uint wfd_ielen = 0;
+
+ if ( rtw_get_wfd_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, wfd_ie, &wfd_ielen ) )
+ {
+ u8 wfd_devinfo[ 6 ] = { 0x00 };
+ uint wfd_devlen = 6;
+
+ DBG_871X( "[%s] Found WFD IE!\n", __FUNCTION__ );
+ if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
+ {
+ u16 wfd_devinfo_field = 0;
+
+ // Commented by Albert 20120319
+ // The first two bytes are the WFD device information field of WFD device information subelement.
+ // In big endian format.
+ wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
+ if ( wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL )
+ {
+ pwfd_info->peer_session_avail = _TRUE;
+ }
+ else
+ {
+ pwfd_info->peer_session_avail = _FALSE;
+ }
+ }
+ }
+
+ if ( _FALSE == pwfd_info->peer_session_avail )
+ {
+ DBG_871X( "[%s] WFD Session not avaiable!\n", __FUNCTION__ );
+ goto exit;
+ }
+ }
+#endif // CONFIG_WFD
+
+ if ( uintPeerChannel )
+ {
+
+ DBG_871X( "[%s] peer channel: %d!\n", __FUNCTION__, uintPeerChannel );
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
+ }
+#endif // CONFIG_CONCURRENT_MODE
+ _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;
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
+
+ if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
+ {
+ _rtw_memcpy( &pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof( NDIS_802_11_SSID ) );
+ }
+ else if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+ {
+ _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;
+ }
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ // Have to enter the power saving with the AP
+ set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
+ issue_nulldata( pbuddy_adapter, 1 );
+ issue_nulldata( pbuddy_adapter, 1 );
+ }
+ else
+ {
+ set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }
+#else
+ set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+#endif
+
+ _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+ {
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_PROVISION_TIMEOUT );
+ }
+ else
+ {
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
+ }
+#else
+ _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
+#endif // CONFIG_CONCURRENT_MODE
+
+
+ }
+ else
+ {
+ DBG_871X( "[%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 wifidirect_info *pwdinfo = &( padapter->wdinfo );
+
+
+ DBG_871X( "[%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_871X( "[%s] extra = %s\n", __FUNCTION__, extra );
+
+ if ( _rtw_memcmp( extra, "enable=", 7 ) )
+ {
+ rtw_wext_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] );
+ }
+ else if ( _rtw_memcmp( extra, "invite=", 7 ) )
+ {
+ wrqu->data.length -= 8;
+ rtw_p2p_invite_req( dev, info, wrqu, &extra[7] );
+ }
+ else if ( _rtw_memcmp( extra, "persistent=", 11 ) )
+ {
+ wrqu->data.length -= 11;
+ rtw_p2p_set_persistent( dev, info, wrqu, &extra[11] );
+ }
+ else if ( _rtw_memcmp( extra, "sa=", 3 ) )
+ {
+ // sa: WFD Session Available information
+ wrqu->data.length -= 3;
+ rtw_p2p_set_sa( dev, info, wrqu, &extra[3] );
+ }
+ else if ( _rtw_memcmp( extra, "pc=", 3 ) )
+ {
+ // pc: WFD Preferred Connection
+ wrqu->data.length -= 3;
+ rtw_p2p_set_pc( dev, info, wrqu, &extra[3] );
+ }
+
+#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_871X( "[%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);
+ }
+ else if ( _rtw_memcmp( wrqu->data.pointer, "group_id", 8 ) )
+ {
+ rtw_p2p_get_groupid( 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 );
+ }
+ else if ( _rtw_memcmp( wrqu->data.pointer, "wfd_sa", 6 ) )
+ {
+ rtw_p2p_get_peer_wfd_session_available( dev, info, wrqu, extra );
+ }
+ else if ( _rtw_memcmp( wrqu->data.pointer, "wfd_pc", 6 ) )
+ {
+ rtw_p2p_get_peer_wfd_preferred_connection( 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_871X( "[%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 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)
+{
+ int ret = 0;
+ _adapter *padapter = rtw_netdev_priv(dev);
+ struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
+ char new_ifname[IFNAMSIZ];
+
+ if(rereg_priv->old_ifname[0] == 0) {
+ char *reg_ifname;
+#ifdef CONFIG_CONCURRENT_MODE
+ if (padapter->isprimary)
+ reg_ifname = padapter->registrypriv.ifname;
+ else
+#endif
+ reg_ifname = padapter->registrypriv.if2name;
+
+ strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
+ rereg_priv->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(rereg_priv->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(rereg_priv->old_ifname, "disable%d", 9) == _TRUE) {
+ padapter->ledpriv.bRegUseLed= rereg_priv->old_bRegUseLed;
+ rtw_sw_led_init(padapter);
+ rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
+ }
+
+ strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
+ rereg_priv->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);
+ rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
+ padapter->ledpriv.bRegUseLed= _FALSE;
+ rtw_sw_led_deinit(padapter);
+
+ // the interface is being "disabled", we can do deeper IPS
+ rereg_priv->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_871X("\n======= MAC REG =======\n");
+ for(i=0x0;i<0x300;i+=4)
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\n");
+ }
+ for(i=0x400;i<0x800;i+=4)
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\n");
+ }
+}
+void bb_reg_dump(_adapter *padapter)
+{
+ int i,j=1;
+ DBG_871X("\n======= BB REG =======\n");
+ for(i=0x800;i<0x1000;i+=4)
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\n");
+ }
+}
+void rf_reg_dump(_adapter *padapter)
+{
+ int i,j=1,path;
+ u32 value;
+ DBG_871X("\n======= RF REG =======\n");
+ for(path=0;path<2;path++)
+ {
+ DBG_871X("\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_871X("0x%02x ",i);
+ DBG_871X(" 0x%08x ",value);
+ if((j++)%4==0) DBG_871X("\n");
+ }
+ }
+}
+
+#endif
+
+void mac_reg_dump(_adapter *padapter)
+{
+ int i,j=1;
+ DBG_871X("\n======= MAC REG =======\n");
+ for(i=0x0;i<0x300;i+=4)
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\n");
+ }
+ for(i=0x400;i<0x800;i+=4)
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\n");
+ }
+}
+void bb_reg_dump(_adapter *padapter)
+{
+ int i,j=1;
+ DBG_871X("\n======= BB REG =======\n");
+ for(i=0x800;i<0x1000;i+=4)
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\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_871X("\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_871X("\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_871X("0x%02x ",i);
+ DBG_871X(" 0x%08x ",value);
+ if((j++)%4==0) DBG_871X("\n");
+ }
+ }
+}
+
+#ifdef CONFIG_IOL
+#include <rtw_iol.h>
+#endif
+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_871X("rtw_read8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
+ break;
+ case 2:
+ DBG_871X("rtw_read16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
+ break;
+ case 4:
+ DBG_871X("rtw_read32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
+ break;
+ }
+ break;
+ case 0x71://write_reg
+ switch(minor_cmd)
+ {
+ case 1:
+ rtw_write8(padapter, arg, extra_arg);
+ DBG_871X("rtw_write8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
+ break;
+ case 2:
+ rtw_write16(padapter, arg, extra_arg);
+ DBG_871X("rtw_write16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
+ break;
+ case 4:
+ rtw_write32(padapter, arg, extra_arg);
+ DBG_871X("rtw_write32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
+ break;
+ }
+ break;
+ case 0x72://read_bb
+ DBG_871X("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_871X("write_bbreg(0x%x)=0x%x\n", arg, padapter->HalFunc.read_bbreg(padapter, arg, 0xffffffff));
+ break;
+ case 0x74://read_rf
+ DBG_871X("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_871X("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 0x78: //IOL test
+ switch(minor_cmd)
+ {
+ #ifdef CONFIG_IOL
+ case 0x04: //LLT table initialization test
+ {
+ u8 page_boundary = 0xf9;
+ {
+ struct xmit_frame *xmit_frame;
+
+ if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
+
+
+ if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500) )
+ ret = -EPERM;
+ }
+ }
+ break;
+ case 0x05: //blink LED test
+ {
+ u16 reg = 0x4c;
+ u32 blink_num = 50;
+ u32 blink_delay_ms = 200;
+ int i;
+
+ {
+ struct xmit_frame *xmit_frame;
+
+ if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for(i=0;i<blink_num;i++){
+ rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00);
+ rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+ rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08);
+ rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+ }
+ if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200) )
+ ret = -EPERM;
+ }
+ }
+ break;
+
+ case 0x06: //continuous wirte byte test
+ {
+ u16 reg = arg;
+ u16 start_value = 0;
+ u32 write_num = extra_arg;
+ int i;
+ u8 final;
+
+ {
+ struct xmit_frame *xmit_frame;
+
+ if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for(i=0;i<write_num;i++){
+ rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value);
+ }
+ if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000))
+ ret = -EPERM;
+ }
+
+ if(start_value+write_num-1 == (final=rtw_read8(padapter, reg)) ) {
+ DBG_871X("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+ } else {
+ DBG_871X("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+ }
+ }
+ break;
+
+ case 0x07: //continuous wirte word test
+ {
+ u16 reg = arg;
+ u16 start_value = 200;
+ u32 write_num = extra_arg;
+
+ int i;
+ u16 final;
+
+ {
+ struct xmit_frame *xmit_frame;
+
+ if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for(i=0;i<write_num;i++){
+ rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value);
+ }
+ if(_SUCCESS !=rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000))
+ ret = -EPERM;
+ }
+
+ if(start_value+write_num-1 == (final=rtw_read16(padapter, reg)) ) {
+ DBG_871X("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+ } else {
+ DBG_871X("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+ }
+ }
+ break;
+
+ case 0x08: //continuous wirte dword test
+ {
+ u16 reg = arg;
+ u32 start_value = 0x110000c7;
+ u32 write_num = extra_arg;
+
+ int i;
+ u32 final;
+
+ {
+ struct xmit_frame *xmit_frame;
+
+ if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for(i=0;i<write_num;i++){
+ rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value);
+ }
+ if(_SUCCESS !=rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000))
+ ret = -EPERM;
+
+ }
+
+ if(start_value+write_num-1 == (final=rtw_read32(padapter, reg)) ) {
+ DBG_871X("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+ } else {
+ DBG_871X("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+ }
+ }
+ break;
+ #endif //CONFIG_IOL
+ }
+ break;
+
+ case 0x7F:
+ switch(minor_cmd)
+ {
+ case 0x0:
+ DBG_871X("fwstate=0x%x\n", get_fwstate(pmlmepriv));
+ break;
+ case 0x01:
+ DBG_871X("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_871X("pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
+ break;
+ case 0x03:
+ DBG_871X("qos_option=%d\n", pmlmepriv->qospriv.qos_option);
+ DBG_871X("ht_option=%d\n", pmlmepriv->htpriv.ht_option);
+ break;
+ case 0x04:
+ DBG_871X("cur_ch=%d\n", pmlmeext->cur_channel);
+ DBG_871X("cur_bw=%d\n", pmlmeext->cur_bwmode);
+ DBG_871X("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_871X("SSID=%s\n", cur_network->network.Ssid.Ssid);
+ DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
+ DBG_871X("cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
+ DBG_871X("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
+ DBG_871X("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+ DBG_871X("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+ DBG_871X("bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
+ DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+ DBG_871X("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_871X("tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq);
+ }
+ }
+
+ }
+ else
+ {
+ DBG_871X("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_871X("(B)DMFlag=0x%x, arg=0x%x\n", DMFlag, arg);
+ DMFlag = (u8)(0x0f&arg);
+ DBG_871X("(A)DMFlag=0x%x\n", DMFlag);
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_DM_FLAG, (u8 *)(&DMFlag));
+ }
+ break;
+ case 0x07:
+ DBG_871X("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_871X("free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d, free_xmit_extbuf_cnt=%d\n",
+ pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt);
+ #ifdef CONFIG_USB_HCI
+ DBG_871X("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_871X("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_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
+ DBG_871X("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
+ DBG_871X("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+ DBG_871X("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+ DBG_871X("bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
+ DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+ DBG_871X("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+#ifdef CONFIG_AP_MODE
+ DBG_871X("capability=0x%x\n", psta->capability);
+ DBG_871X("flags=0x%x\n", psta->flags);
+ DBG_871X("wpa_psk=0x%x\n", psta->wpa_psk);
+ DBG_871X("wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
+ DBG_871X("wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
+ DBG_871X("qos_info=0x%x\n", psta->qos_info);
+#endif
+ DBG_871X("dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
+
+
+
+ for(j=0;j<16;j++)
+ {
+ preorder_ctrl = &psta->recvreorder_ctrl[j];
+ if(preorder_ctrl->enable)
+ {
+ DBG_871X("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_871X("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 DBG_CONFIG_ERROR_DETECT
+ case 0x0f:
+ {
+ if(extra_arg == 0){
+ DBG_871X("###### silent reset test.......#####\n");
+ rtw_hal_sreset_reset(padapter);
+ }
+
+ }
+ break;
+ case 0x12:
+ {
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ DBG_871X("==>silent resete cnts:%d\n",pwrpriv->ips_enter_cnts);
+ }
+ break;
+
+ #endif
+
+ case 0x10:// driver version display
+ DBG_871X("rtw driver version=%s\n", DRIVERVERSION);
+ break;
+ case 0x11:
+ {
+ DBG_871X("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_871X(" === DMFlag(0x%02x) === \n",dm_flag);
+ DBG_871X("extra_arg = 0 - disable all dynamic func \n");
+ DBG_871X("extra_arg = 1 - disable DIG- BIT(0)\n");
+ DBG_871X("extra_arg = 2 - disable High power - BIT(1)\n");
+ DBG_871X("extra_arg = 3 - disable tx power tracking - BIT(2)\n");
+ DBG_871X("extra_arg = 4 - disable BT coexistence - BIT(3)\n");
+ DBG_871X("extra_arg = 5 - disable antenna diversity - BIT(4)\n");
+ DBG_871X("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_871X(" === DMFlag(0x%02x) === \n",dm_flag);
+ }
+ }
+ break;
+
+ case 0xfd:
+ rtw_write8(padapter, 0xc50, arg);
+ DBG_871X("wr(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
+ rtw_write8(padapter, 0xc58, arg);
+ DBG_871X("wr(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
+ break;
+ case 0xfe:
+ DBG_871X("rd(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
+ DBG_871X("rd(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
+ break;
+ case 0xff:
+ {
+ DBG_871X("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
+ DBG_871X("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
+ DBG_871X("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
+ DBG_871X("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
+ DBG_871X("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
+
+ DBG_871X("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
+
+
+ DBG_871X("\n");
+
+ DBG_871X("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
+ DBG_871X("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
+
+ DBG_871X("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
+
+ DBG_871X("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
+
+ DBG_871X("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
+ DBG_871X("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
+
+ DBG_871X("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
+ DBG_871X("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
+ DBG_871X("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
+ DBG_871X("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
+ }
+ break;
+ }
+ break;
+ default:
+ DBG_871X("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_871X(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_871X("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_871X("%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,wep_total_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_871X("%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_871X("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_871X("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
+
+ goto exit;
+ }
+
+
+ if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta==NULL))
+ {
+ DBG_871X("r871x_set_encryption, crypt.alg = WEP\n");
+
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+ DBG_871X("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;
+ wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+ pwep =(NDIS_802_11_WEP *)rtw_malloc(wep_total_len);
+ if(pwep == NULL){
+ DBG_871X(" r871x_set_encryption: pwep allocate fail !!!\n");
+ goto exit;
+ }
+
+ _rtw_memset(pwep, 0, wep_total_len);
+
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+
+ }
+
+ pwep->KeyIndex = wep_key_idx;
+
+ _rtw_memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
+
+ if(param->u.crypt.set_tx)
+ {
+ DBG_871X("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_871X("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_871X("%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_871X("%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_871X("%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_871X("%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_871X("%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_871X("%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_871X("%s, set pairwise key, CCMP\n", __FUNCTION__);
+
+ psta->dot118021XPrivacy = _AES_;
+ }
+ else
+ {
+ DBG_871X("%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_total_len);
+ }
+
+ 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_871X("%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_871X("%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_871X("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_871X("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_871X("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*)&param->u.add_sta.ht_cap, sizeof(struct rtw_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_871X("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_871X("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
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
+ {
+ rtw_list_delete(&psta->asoc_list);
+ ap_free_sta(padapter, psta);
+
+ }
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+
+
+ psta = NULL;
+
+ }
+ else
+ {
+ DBG_871X("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_871X("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_871X("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_871X("%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_871X("%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_871X("%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_871X("%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_hidden_ssid(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 mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ u8 value;
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
+ return -EINVAL;
+
+ if(param->u.wpa_param.name != 0) //dummy test...
+ {
+ DBG_871X("%s name(%u) != 0\n", __FUNCTION__, param->u.wpa_param.name);
+ }
+
+ value = param->u.wpa_param.value;
+
+ //use the same definition of hostapd's ignore_broadcast_ssid
+ if(value != 1 && value != 2)
+ value = 0;
+
+ DBG_871X("%s value(%u)\n", __FUNCTION__, value);
+ pmlmeinfo->hidden_ssid_mode = value;
+
+ 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_871X("%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_871X("%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_871X("%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_871X("%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;
+
+ case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
+
+ ret = rtw_set_hidden_ssid(dev, param, p->length);
+
+ break;
+
+ default:
+ DBG_871X("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
+
+#include <rtw_android.h>
+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;
+
+ _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;
+
+ printk("probe_req_wps_ielen=%d\n", cp_sz);
+
+ if(pmlmepriv->wps_probe_req_ie)
+ {
+ u32 free_len = pmlmepriv->wps_probe_req_ie_len;
+ pmlmepriv->wps_probe_req_ie_len = 0;
+ rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
+ pmlmepriv->wps_probe_req_ie = NULL;
+ }
+
+ pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
+ if ( pmlmepriv->wps_probe_req_ie == NULL) {
+ printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
+ ret = -EINVAL;
+ goto FREE_EXT;
+
+ }
+
+ _rtw_memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
+ pmlmepriv->wps_probe_req_ie_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);
+
+ i = rtw_android_cmdstr_to_num(ext);
+
+ switch(i) {
+ case ANDROID_WIFI_CMD_START :
+ indicate_wx_custom_event(padapter, "START");
+ break;
+ case ANDROID_WIFI_CMD_STOP :
+ indicate_wx_custom_event(padapter, "STOP");
+ break;
+ 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, "%s rssi %d", pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
+ } else {
+ sprintf(ext, "OK");
+ }
+ }
+ break;
+ case ANDROID_WIFI_CMD_LINKSPEED :
+ {
+ u16 mbps = rtw_get_cur_max_rate(padapter)/10;
+ sprintf(ext, "LINKSPEED %d", mbps);
+ }
+ break;
+ case ANDROID_WIFI_CMD_MACADDR :
+ sprintf(ext, "MACADDR = " MAC_FMT, MAC_ARG(dev->dev_addr));
+ break;
+ case ANDROID_WIFI_CMD_SCAN_ACTIVE :
+ {
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ pmlmepriv->scan_mode=SCAN_ACTIVE;
+ sprintf(ext, "OK");
+ }
+ break;
+ 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 = RT_CHANNEL_DOMAIN_FCC;
+ 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 if(0 == strcmp(country_code, "CN"))
+ channel_plan = RT_CHANNEL_DOMAIN_CHINA;
+ else
+ DBG_871X("%s unknown country_code:%s, set to RT_CHANNEL_DOMAIN_FCC\n", __FUNCTION__, country_code);
+
+ _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;
+ 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;
+
+}
+
+static int rtw_mp_efuse_get(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wdata, char *extra)
+{
+ struct iw_point *wrqu = (struct iw_point *)wdata;
+ 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->pointer, wrqu->length))
+ return -EFAULT;
+
+ pch = extra;
+ DBG_871X("%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_871X("strcmp OK = %s \n" ,tmp[0]);
+
+ mapLen = EFUSE_MAP_SIZE;
+
+ if (rtw_efuse_map_read(padapter, 0, mapLen, data) == _SUCCESS){
+ DBG_871X("\t rtw_efuse_map_read \n");
+ }else {
+ DBG_871X("\t rtw_efuse_map_read : Fail \n");
+ return -EFAULT;
+ }
+ _rtw_memset(extra, '\0', sizeof(extra));
+ DBG_871X("\tOFFSET\tVALUE(hex)\n");
+ sprintf(extra, "%s \n", extra);
+ for ( i = 0; i < EFUSE_MAP_SIZE; i += 16 )
+ {
+ DBG_871X("\t0x%02x\t", i);
+ sprintf(extra, "%s \t0x%02x\t", extra,i);
+ for (j = 0; j < 8; j++)
+ {
+ DBG_871X("%02X ", data[i+j]);
+ sprintf(extra, "%s %02X", extra, data[i+j]);
+ }
+ DBG_871X("\t");
+ sprintf(extra,"%s\t",extra);
+ for (; j < 16; j++){
+ DBG_871X("%02X ", data[i+j]);
+ sprintf(extra, "%s %02X", extra, data[i+j]);
+ }
+ DBG_871X("\n");
+ sprintf(extra,"%s\n",extra);
+ }
+ DBG_871X("\n");
+ wrqu->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_871X("addr = %x \n" ,addr);
+
+ cnts=simple_strtoul(tmp[2], &ptmp,10);
+ if(cnts==0) return -EINVAL;
+
+ DBG_871X("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_871X("(addr + cnts parameter error \n");
+ return -EFAULT;
+ }
+
+ if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL)
+ {
+ DBG_871X("rtw_efuse_access error \n");
+ }
+ else{
+ DBG_871X("rtw_efuse_access ok \n");
+ }
+
+ _rtw_memset(extra, '\0', sizeof(extra));
+ for ( i = 0; i < cnts; i ++) {
+ DBG_871X("0x%02x", data[i]);
+ sprintf(extra, "%s 0x%02X", extra, data[i]);
+ DBG_871X(" ");
+ sprintf(extra,"%s ",extra);
+ }
+
+ wrqu->length = strlen(extra)+1;
+
+ DBG_871X("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_871X("\t rtw_efuse_map_read : Fail \n");
+ return -EFAULT;
+ } else
+ {
+ DBG_871X("\t rtw_efuse_access raw ok \n");
+ }
+
+ _rtw_memset(extra, '\0', sizeof(extra));
+ for ( i=0; i<mapLen; i++ ) {
+ DBG_871X(" %02x", rawdata[i]);
+ sprintf(extra, "%s %02x", extra, rawdata[i] );
+
+ if ((i & 0xF) == 0xF){
+ DBG_871X("\n\t");
+ sprintf(extra, "%s\n\t", extra);
+ }
+ else if ((i & 0x7) == 0x7){
+ DBG_871X("\t");
+ sprintf(extra, "%s\t", extra);
+ }
+ }
+ wrqu->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_871X("(addr + cnts parameter error \n");
+ return -EFAULT;
+ }
+ if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL)
+ {
+ DBG_871X("rtw_efuse_access error \n");
+ }
+ else{
+ DBG_871X("rtw_efuse_access ok \n");
+ }
+ _rtw_memset(extra, '\0', sizeof(extra));
+ for ( i = 0; i < cnts; i ++) {
+ DBG_871X("0x%02x", data[i]);
+ sprintf(extra, "%s 0x%02X", extra, data[i+j]);
+ DBG_871X(" ");
+ sprintf(extra,"%s ",extra);
+ }
+ wrqu->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_871X("(addr + cnts parameter error \n");
+ return -EFAULT;
+ }
+ if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL)
+ {
+ DBG_871X("rtw_efuse_access error \n");
+ }
+ else{
+ DBG_871X("rtw_efuse_access ok \n");
+ }
+ _rtw_memset(extra, '\0', sizeof(extra));
+ for ( i = 0; i < cnts; i ++) {
+ DBG_871X("0x%02x", data[i]);
+ sprintf(extra, "%s 0x%02X", extra, data[i+j]);
+ DBG_871X(" ");
+ sprintf(extra,"%s ",extra);
+ }
+ wrqu->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->length = strlen(extra);
+
+ return 0;
+ }else
+ {
+ sprintf(extra, "%s : Command not found\n",extra);
+ wrqu->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 *wdata, char *extra)
+{
+ struct iw_point *wrqu = (struct iw_point *)wdata;
+ 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_871X("%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_871X("addr = %x \n" ,addr);
+
+ cnts = strlen( tmp[2] )/2;
+ if ( cnts == 0) return -EFAULT;
+
+ DBG_871X("cnts = %d \n" ,cnts);
+ DBG_871X("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_871X("parameter error \n");
+ return -EFAULT;
+ }
+ if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+ DBG_871X("rtw_efuse_map_write error \n");
+ return -EFAULT;
+ } else
+ DBG_871X("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_871X("addr = %x \n" ,addr);
+
+ cnts=strlen( tmp[2] )/2;
+ if ( cnts == 0) return -EFAULT;
+
+ DBG_871X(" cnts = %d \n" ,cnts );
+ DBG_871X("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_871X("\t rtw_efuse_map_read : Fail \n");
+ return -EFAULT;
+ } else
+ DBG_871X("\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_871X("error data for mac addr = %s \n" ,tmp[1]);
+ return -EFAULT;
+ }
+
+ DBG_871X("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_871X("parameter error \n");
+ return -EFAULT;
+ }
+ if ( rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL ) {
+ DBG_871X("rtw_efuse_map_write error \n");
+ return -EFAULT;
+ } else
+ DBG_871X("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_871X("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_871X("parameter error \n");
+ return -EFAULT;
+ }
+
+ if ( rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL ) {
+ DBG_871X("rtw_efuse_map_write error \n");
+ return -EFAULT;
+ } else
+ DBG_871X("rtw_efuse_map_write ok \n");
+
+ return 0;
+ }
+ else{
+ DBG_871X("Command not found\n");
+ return 0;
+ }
+
+ return 0;
+}
+
+
+
+#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,
+ struct iw_point *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->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,
+ struct iw_point *wrqu, char *extra)
+{
+ char input[wrqu->length];
+ char *pch, *pnext, *ptmp;
+ char *width_str;
+ char width;
+ char data[20],tmp[20];
+ u32 addr;
+ //u32 *data = (u32*)extra;
+ u32 ret, i=0, j=0, strtout=0;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+ if (wrqu->length > 128) return -EFAULT;
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->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->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);
+ sprintf(extra, "%d\n", rtw_read8(padapter, addr));
+ wrqu->length = 4;
+ break;
+ case 'w':
+ // 2 bytes
+ //*(u16*)data = rtw_read16(padapter, addr);
+ sprintf(data, "%04d\n", rtw_read16(padapter, addr));
+ for( i=0 ; i <= strlen(data) ; i++)
+ {
+ if( i%2==0 )
+ {
+ tmp[j]=' ';
+ j++;
+ }
+ if ( data[i] != '\0' )
+ tmp[j] = data[i];
+
+ j++;
+ }
+ pch = tmp;
+ DBG_871X("pch=%s",pch);
+
+ while( *pch != '\0' )
+ {
+ pnext = strpbrk(pch, " ");
+ pnext++;
+ if ( *pnext != '\0' )
+ {
+ strtout = simple_strtoul (pnext , &ptmp, 16);
+ sprintf( extra, "%s %d" ,extra ,strtout );
+ }
+ else{
+ break;
+ }
+ pch = pnext;
+ }
+ wrqu->length = 8;
+ break;
+ case 'd':
+ // 4 bytes
+ //*data = rtw_read32(padapter, addr);
+ sprintf(data, "%08x", rtw_read32(padapter, addr));
+ //add read data format blank
+ for( i=0 ; i <= strlen(data) ; i++)
+ {
+ if( i%2==0 )
+ {
+ tmp[j]=' ';
+ j++;
+ }
+ tmp[j] = data[i];
+ j++;
+ }
+ pch = tmp;
+ DBG_871X("pch=%s",pch);
+
+ while( *pch != '\0' )
+ {
+ pnext = strpbrk(pch, " ");
+ pnext++;
+ if ( *pnext != '\0' )
+ {
+ strtout = simple_strtoul (pnext , &ptmp, 16);
+ sprintf( extra, "%s %d" ,extra ,strtout );
+ }
+ else{
+ break;
+ }
+ pch = pnext;
+ }
+ wrqu->length = 20;
+ break;
+
+ default:
+ wrqu->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,
+ struct iw_point *wrqu, char *extra)
+{
+/*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,
+ struct iw_point *wrqu, char *extra)
+{
+ char input[wrqu->length];
+ char *pch, *pnext, *ptmp;
+ char data[20],tmp[20];
+ //u32 *data = (u32*)extra;
+ u32 path, addr;
+ u32 ret,i=0 ,j=0,strtou=0;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+ if (wrqu->length > 128) return -EFAULT;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ ret = sscanf(extra, "%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);
+ sprintf(data, "%08x", read_rfreg(padapter, path, addr));
+ //add read data format blank
+ for( i=0 ; i <= strlen(data) ; i++)
+ {
+ if( i%2==0 )
+ {
+ tmp[j]=' ';
+ j++;
+ }
+ tmp[j] = data[i];
+ j++;
+ }
+ pch = tmp;
+ DBG_871X("pch=%s",pch);
+
+ while( *pch != '\0' )
+ {
+ pnext = strpbrk(pch, " ");
+ pnext++;
+ if ( *pnext != '\0' )
+ {
+ strtou = simple_strtoul (pnext , &ptmp, 16);
+ sprintf( extra, "%s %d" ,extra ,strtou );
+ }
+ else{
+ break;
+ }
+ pch = pnext;
+ }
+ wrqu->length = 10;
+
+ return 0;
+}
+
+static int rtw_mp_start(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *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,
+ struct iw_point *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,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 rate = MPT_RATE_1M;
+ u8 input[wrqu->length];
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ rate = rtw_atoi(input);
+ sprintf( extra, "Set data rate to %d" , rate );
+
+ if(rate <= 0x7f)
+ rate = wifirate2_ratetbl_inx( (u8)rate);
+ else
+ rate =(rate-0x80+MPT_RATE_MCS0);
+
+ //DBG_871X("%s: rate=%d\n", __func__, rate);
+
+ if (rate >= MPT_RATE_LAST )
+ return -EINVAL;
+
+ padapter->mppriv.rateidx = rate;
+ Hal_SetDataRate(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ return 0;
+}
+
+static int rtw_mp_channel(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+
+ PADAPTER padapter = rtw_netdev_priv(dev);
+ u8 input[wrqu->length];
+ u32 channel = 1;
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ channel = rtw_atoi(input);
+ //DBG_871X("%s: channel=%d\n", __func__, channel);
+ sprintf( extra, "Change channel %d to channel %d", padapter->mppriv.channel , channel );
+
+ padapter->mppriv.channel = channel;
+ Hal_SetChannel(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ return 0;
+}
+
+static int rtw_mp_bandwidth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *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_871X("%s:iwpriv in=%s\n", __func__, extra);
+
+ sscanf(extra, "40M=%d,shortGI=%d", &bandwidth, &sg);
+
+ if (bandwidth != HT_CHANNEL_WIDTH_40)
+ bandwidth = HT_CHANNEL_WIDTH_20;
+
+ //DBG_871X("%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,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 idx_a=0,idx_b=0;
+ u8 input[wrqu->length];
+
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ sscanf(input,"patha=%d,pathb=%d",&idx_a,&idx_b);
+ //DBG_871X("%s: tx_pwr_idx_a=%x b=%x\n", __func__, idx_a, idx_b);
+
+ sprintf( extra, "Set power level path_A:%d path_B:%d", idx_a , idx_b );
+ padapter->mppriv.txpoweridx = (u8)idx_a;
+ padapter->mppriv.txpoweridx_b = (u8)idx_b;
+
+ Hal_SetAntennaPathPower(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ return 0;
+}
+
+static int rtw_mp_ant_tx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 i;
+ u8 input[wrqu->length];
+ u16 antenna = 0;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ DBG_871X("%s: input=%s\n", __func__, input);
+
+ sprintf( extra, "switch Tx antenna to %s", input );
+
+ for (i=0; i < strlen(input); i++)
+ {
+ switch(input[i])
+ {
+ case 'a' :
+ antenna|=ANTENNA_A;
+ break;
+ case 'b':
+ antenna|=ANTENNA_B;
+ break;
+ }
+ }
+ //antenna |= BIT(extra[i]-'a');
+ DBG_871X("%s: antenna=0x%x\n", __func__, antenna);
+ padapter->mppriv.antenna_tx = antenna;
+ DBG_871X("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_tx);
+
+ Hal_SetAntenna(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ return 0;
+}
+
+static int rtw_mp_ant_rx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 i;
+ u16 antenna = 0;
+ u8 input[wrqu->length];
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+ //DBG_871X("%s: input=%s\n", __func__, input);
+
+ for (i=0; i < strlen(input); i++) {
+
+ switch( input[i] )
+ {
+ case 'a' :
+ antenna|=ANTENNA_A;
+ break;
+ case 'b':
+ antenna|=ANTENNA_B;
+ break;
+ }
+ }
+
+ //DBG_871X("%s: antenna=0x%x\n", __func__, antenna);
+ padapter->mppriv.antenna_rx = antenna;
+ //DBG_871X("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_rx);
+ Hal_SetAntenna(padapter);
+ wrqu->length = strlen(extra) + 1;
+
+ return 0;
+}
+
+static int rtw_mp_ctx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
+ u32 bStartTest = 1;
+ u32 count = 0;
+ struct mp_priv *pmp_priv;
+ struct pkt_attrib *pattrib;
+
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+ pmp_priv = &padapter->mppriv;
+
+ if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ DBG_871X("%s: in=%s\n", __func__, extra);
+
+ countPkTx = strncmp(extra, "count=", 5); // strncmp TRUE is 0
+ cotuTx = strncmp(extra, "background", 20);
+ CarrSprTx = strncmp(extra, "background,cs", 20);
+ scTx = strncmp(extra, "background,sc", 20);
+ sgleTx = strncmp(extra, "background,stone", 20);
+ pkTx = strncmp(extra, "background,pkt", 20);
+ stop = strncmp(extra, "stop", 5);
+ sscanf(extra, "count=%d,pkt", &count);
+
+ //DBG_871X("%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);
+ _rtw_memset(extra, '\0', sizeof(extra));
+
+ if (stop == 0) {
+ bStartTest = 0; // To set Stop
+ pmp_priv->tx.stop = 1;
+ sprintf( extra, "Stop continuous Tx");
+ } else {
+ bStartTest = 1;
+ if (pmp_priv->mode != MP_ON) {
+ if (pmp_priv->tx.stop != 1) {
+ DBG_871X("%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_871X("%s:pkTx %d\n", __func__,bStartTest);
+ if (bStartTest == 0)
+ {
+ pmp_priv->tx.stop = 1;
+ pmp_priv->mode = MP_ON;
+ sprintf( extra, "Stop continuous Tx");
+ }
+ else if (pmp_priv->tx.stop == 1)
+ {
+ sprintf( extra, "Start continuous DA=ffffffffffff len=1500 count=%u,\n",count);
+ //DBG_871X("%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 = 1460;
+ _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
+ SetPacketTx(padapter);
+ }
+ else {
+ //DBG_871X("%s: pkTx not stop\n", __func__);
+ return -EFAULT;
+ }
+ wrqu->length = strlen(extra);
+ return 0;
+
+ case MP_SINGLE_TONE_TX:
+ //DBG_871X("%s: sgleTx %d \n", __func__, bStartTest);
+ if (bStartTest != 0){
+ sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
+ Hal_SetSingleToneTx(padapter, (u8)bStartTest);
+ }
+ break;
+
+ case MP_CONTINUOUS_TX:
+ //DBG_871X("%s: cotuTx %d\n", __func__, bStartTest);
+ if (bStartTest != 0){
+ sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
+ Hal_SetContinuousTx(padapter, (u8)bStartTest);
+ }
+ break;
+
+ case MP_CARRIER_SUPPRISSION_TX:
+ //DBG_871X("%s: CarrSprTx %d\n", __func__, bStartTest);
+ if (bStartTest != 0){
+ if( pmp_priv->rateidx <= MPT_RATE_11M )
+ {
+ sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
+ Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
+ }else
+ sprintf( extra, "Specify carrier suppression but not CCK rate");
+ }
+ break;
+
+ case MP_SINGLE_CARRIER_TX:
+ //DBG_871X("%s: scTx %d\n", __func__, bStartTest);
+ if (bStartTest != 0){
+ sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
+ Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
+ }
+ break;
+
+ default:
+ //DBG_871X("%s:No Match MP_MODE\n", __func__);
+ sprintf( extra, "Error! Continuous-Tx is not on-going.");
+ return -EFAULT;
+ }
+
+ if (bStartTest) {
+ struct mp_priv *pmp_priv = &padapter->mppriv;
+ if (pmp_priv->tx.stop == 0) {
+ pmp_priv->tx.stop = 1;
+ //DBG_871X("%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;
+ }
+
+ wrqu->length = strlen(extra);
+ return 0;
+}
+
+static int rtw_mp_arx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 bStartRx=0,bStopRx=0;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+ u8 input[wrqu->length];
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ DBG_871X("%s: %s\n", __func__, input);
+
+ bStartRx = (strncmp(input, "start", 5)==0)?1:0; // strncmp TRUE is 0
+ bStopRx = (strncmp(input, "stop", 5)==0)?1:0; // strncmp TRUE is 0
+ SetPacketRx(padapter, bStartRx);
+
+ if(bStartRx)
+ {
+ sprintf( extra, "start");
+ wrqu->length = strlen(extra) + 1;
+ }
+ else if(bStopRx)
+ {
+ sprintf( extra, "Received packet OK:%d CRC error:%d",padapter->mppriv.rx_pktcount,
+ padapter->mppriv.rx_crcerrpktcount);
+ wrqu->length = strlen(extra) + 1;
+ }
+
+
+ return 0;
+}
+
+static int rtw_mp_trx_query(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *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->length=strlen(extra)+1;
+
+ return 0;
+}
+
+static int rtw_mp_pwrtrk(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 enable;
+ u32 thermal;
+ s32 ret;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+ enable = 1;
+ if (wrqu->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,
+ struct iw_point *wrqu, char *extra)
+{
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+ if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ wrqu->length = mp_query_psd(padapter, extra);
+
+ return 0;
+}
+
+static int rtw_mp_thermal(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 val;
+ u16 bwrite=1;
+ #ifdef CONFIG_RTL8192C
+ u16 addr=0x78;
+ #endif
+ #ifdef CONFIG_RTL8192D
+ u16 addr=0xc3;
+ #endif
+ u16 cnt=1;
+ u16 max_available_size=0;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+ if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ //DBG_871X("print extra %s \n",extra);
+
+ bwrite = strncmp(extra, "write", 6); // strncmp TRUE is 0
+
+ Hal_GetThermalMeter(padapter, &val);
+
+ if( bwrite == 0 )
+ {
+ //DBG_871X("to write val:%d",val);
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
+ if( 2 > max_available_size )
+ {
+ DBG_871X("no available efuse!\n");
+ return -EFAULT;
+ }
+ if ( rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL )
+ {
+ DBG_871X("rtw_efuse_map_write error \n");
+ return -EFAULT;
+ }
+ else
+ {
+ sprintf(extra, " efuse write ok :%d", val);
+ }
+ }
+ else
+ {
+ sprintf(extra, "%d", val);
+ }
+ wrqu->length = strlen(extra);
+
+ return 0;
+}
+
+static int rtw_mp_reset_stats(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *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,
+ struct iw_point *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 )
+ {
+ DBG_871X("\n======= MAC REG =======\n");
+ for ( i=0x0;i<0x300;i+=4 )
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\n");
+ }
+ for( i=0x400;i<0x800;i+=4 )
+ {
+ if(j%4==1) DBG_871X("0x%02x",i);
+ DBG_871X(" 0x%08x ",rtw_read32(padapter,i));
+ if((j++)%4 == 0) DBG_871X("\n");
+ }
+
+ i,j=1;
+ padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+ DBG_871X("\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) DBG_871X("0x%02x ",i);
+ DBG_871X(" 0x%08x ",value);
+ if((j++)%4==0) DBG_871X("\n");
+ }
+ }
+ }
+ return 0;
+}
+
+static int rtw_mp_phypara(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+
+ PADAPTER padapter = rtw_netdev_priv(dev);
+ char input[wrqu->length];
+ u32 valxcap;
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ DBG_871X("%s:iwpriv in=%s\n", __func__, input);
+
+ sscanf(input, "xcap=%d", &valxcap);
+
+ if (!IS_HARDWARE_TYPE_8192D(padapter))
+ return 0;
+#ifdef CONFIG_RTL8192D
+ Hal_ProSetCrystalCap( padapter , valxcap );
+#endif
+
+ sprintf( extra, "Set xcap=%d",valxcap );
+ wrqu->length = strlen(extra) + 1;
+
+return 0;
+
+}
+
+
+/* update Tx AGC offset */
+static int rtw_mp_antBdiff(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+
+
+ // MPT_ProSetTxAGCOffset
+ return 0;
+}
+
+
+static int rtw_mp_set(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wdata, char *extra)
+{
+ struct iw_point *wrqu = (struct iw_point *)wdata;
+ u32 subcmd = wrqu->flags;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+ if (padapter == NULL)
+ {
+ return -ENETDOWN;
+ }
+
+ //_rtw_memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+
+ if (extra == NULL)
+ {
+ wrqu->length = 0;
+ return -EIO;
+ }
+
+ switch(subcmd)
+ {
+ case WRITE_REG :
+ rtw_mp_write_reg (dev,info,wrqu,extra);
+ break;
+
+ case WRITE_RF:
+ rtw_mp_write_rf (dev,info,wrqu,extra);
+ break;
+
+ case MP_START:
+ DBG_871X("set case mp_start \n");
+ rtw_mp_start (dev,info,wrqu,extra);
+ break;
+
+ case MP_STOP:
+ DBG_871X("set case mp_stop \n");
+ rtw_mp_stop (dev,info,wrqu,extra);
+ break;
+
+ case MP_BANDWIDTH:
+ DBG_871X("set case mp_bandwidth \n");
+ rtw_mp_bandwidth (dev,info,wrqu,extra);
+ break;
+ case MP_PWRTRK:
+ DBG_871X("set case MP_PWRTRK \n");
+ rtw_mp_pwrtrk (dev,info,wrqu,extra);
+ break;
+
+ case MP_RESET_STATS:
+ DBG_871X("set case MP_RESET_STATS \n");
+ rtw_mp_reset_stats (dev,info,wrqu,extra);
+ break;
+
+ case EFUSE_SET:
+ DBG_871X("efuse set \n");
+ rtw_mp_efuse_set (dev,info,wdata,extra);
+ break;
+
+ }
+
+
+ return 0;
+}
+
+
+static int rtw_mp_get(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wdata, char *extra)
+{
+ struct iw_point *wrqu = (struct iw_point *)wdata;
+ u32 subcmd = wrqu->flags;
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+ DBG_871X("in mp_get extra= %s \n",extra);
+
+ if (padapter == NULL)
+ {
+ return -ENETDOWN;
+ }
+ if (extra == NULL)
+ {
+ wrqu->length = 0;
+ return -EIO;
+ }
+
+ switch(subcmd)
+ {
+ case MP_PHYPARA:
+ DBG_871X("mp_get MP_PHYPARA \n");
+ rtw_mp_phypara(dev,info,wrqu,extra);
+ break;
+
+ case MP_CHANNEL:
+ DBG_871X("set case mp_channel \n");
+ rtw_mp_channel (dev,info,wrqu,extra);
+ break;
+
+ case READ_REG:
+ DBG_871X("mp_get READ_REG \n");
+ rtw_mp_read_reg (dev,info,wrqu,extra);
+ break;
+ case READ_RF:
+ DBG_871X("mp_get READ_RF \n");
+ rtw_mp_read_rf (dev,info,wrqu,extra);
+ break;
+
+ case MP_RATE:
+ DBG_871X("set case mp_rate \n");
+ rtw_mp_rate (dev,info,wrqu,extra);
+ break;
+
+ case MP_TXPOWER:
+ DBG_871X("set case MP_TXPOWER \n");
+ rtw_mp_txpower (dev,info,wrqu,extra);
+ break;
+
+ case MP_ANT_TX:
+ DBG_871X("set case MP_ANT_TX \n");
+ rtw_mp_ant_tx (dev,info,wrqu,extra);
+ break;
+
+ case MP_ANT_RX:
+ DBG_871X("set case MP_ANT_RX \n");
+ rtw_mp_ant_rx (dev,info,wrqu,extra);
+ break;
+
+ case MP_QUERY:
+ DBG_871X("mp_get mp_query MP_QUERY \n");
+ rtw_mp_trx_query(dev,info,wrqu,extra);
+ break;
+
+ case MP_CTX:
+ DBG_871X("set case MP_CTX \n");
+ rtw_mp_ctx (dev,info,wrqu,extra);
+ break;
+
+ case MP_ARX:
+ DBG_871X("set case MP_ARX \n");
+ rtw_mp_arx (dev,info,wrqu,extra);
+ break;
+
+ case EFUSE_GET:
+ DBG_871X("efuse get EFUSE_GET \n");
+ rtw_mp_efuse_get(dev,info,wdata,extra);
+ break;
+
+ case MP_DUMP:
+ DBG_871X("set case MP_DUMP \n");
+ rtw_mp_dump (dev,info,wrqu,extra);
+ break;
+ case MP_PSD:
+ DBG_871X("set case MP_PSD \n");
+ rtw_mp_psd (dev,info,wrqu,extra);
+ break;
+
+ case MP_THER:
+ DBG_871X("set case MP_THER \n");
+ rtw_mp_thermal (dev,info,wrqu,extra);
+ break;
+
+
+ }
+
+return 0;
+}
+
+#endif //#if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_MP_IWPRIV_SUPPORT)
+
+static int rtw_wfd_tdls_enable(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ if ( extra[ 0 ] == '0' )
+ {
+ padapter->wdinfo.wfd_tdls_enable = 0;
+ }
+ else
+ {
+ padapter->wdinfo.wfd_tdls_enable = 1;
+ }
+
+#endif //CONFIG_WFD
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+static int rtw_tdls_weaksec(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+ u8 i, j;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+ DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ if ( extra[ 0 ] == '0' )
+ {
+ padapter->wdinfo.wfd_tdls_weaksec = 0;
+ }
+ else
+ {
+ padapter->wdinfo.wfd_tdls_weaksec = 1;
+ }
+#endif
+
+ return ret;
+}
+
+
+static int rtw_tdls_enable(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 tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ _irqL irqL;
+ _list *plist, *phead;
+ s32 index;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 tdls_sta[NUM_STA][ETH_ALEN];
+ u8 empty_hwaddr[ETH_ALEN] = { 0x00 };
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ _rtw_memset(tdls_sta, 0x00, sizeof(tdls_sta));
+
+ if ( extra[ 0 ] == '0' )
+ {
+ ptdlsinfo->enable = 0;
+
+ if(pstapriv->asoc_sta_count==1)
+ return ret;
+
+ _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+ for(index=0; index< NUM_STA; index++)
+ {
+ phead = &(pstapriv->sta_hash[index]);
+ 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(psta->tdls_sta_state != TDLS_STATE_NONE)
+ {
+ _rtw_memcpy(tdls_sta[index], psta->hwaddr, ETH_ALEN);
+ }
+ }
+ }
+ _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+ for(index=0; index< NUM_STA; index++)
+ {
+ if( !_rtw_memcmp(tdls_sta[index], empty_hwaddr, ETH_ALEN) )
+ {
+ printk("issue tear down to "MAC_FMT"\n", MAC_ARG(tdls_sta[index]));
+ issue_tdls_teardown(padapter, tdls_sta[index]);
+ }
+ }
+ rtw_tdls_cmd(padapter, myid(&(padapter->eeprompriv)), TDLS_RS_RCR);
+ rtw_reset_tdls_info(padapter);
+ }
+ else if ( extra[ 0 ] == '1' )
+ {
+ ptdlsinfo->enable = 1;
+ }
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+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, j;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+ u8 mac_addr[ETH_ALEN];
+
+#ifdef CONFIG_WFD
+ struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif // CONFIG_WFD
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
+ mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
+ }
+
+#ifdef CONFIG_WFD
+ if ( _AES_ != padapter->securitypriv.dot11PrivacyAlgrthm )
+ {
+ // Weak Security situation with AP.
+ if ( 0 == pwdinfo->wfd_tdls_weaksec )
+ {
+ // Can't send the tdls setup request out!!
+ DBG_871X( "[%s] Current link is not AES, SKIP sending the tdls setup request!!\n", __FUNCTION__ );
+ }
+ else
+ {
+ issue_tdls_setup_req(padapter, mac_addr);
+ }
+ }
+ else
+#endif // CONFIG_WFD
+ {
+ 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,j;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+ struct sta_info *ptdls_sta = NULL;
+ u8 mac_addr[ETH_ALEN];
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
+ mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
+ }
+
+ ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), mac_addr);
+
+ if(ptdls_sta != NULL)
+ {
+ ptdls_sta->stat_code = _RSON_TDLS_TEAR_UN_RSN_;
+ issue_tdls_teardown(padapter, mac_addr);
+ }
+
+#endif //CONFIG_TDLS
+
+ 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);
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ issue_tdls_dis_req(padapter, NULL);
+
+#endif //CONFIG_TDLS
+
+ 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 tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ u8 i, j, mac_addr[ETH_ALEN];
+ struct sta_info *ptdls_sta = NULL;
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
+ mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
+ }
+
+ ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
+ if( ptdls_sta == NULL )
+ return ret;
+ ptdlsinfo->ch_sensing=1;
+
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_INIT_CH_SEN);
+
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+static int rtw_tdls_pson(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, j, mac_addr[ETH_ALEN];
+ struct sta_info *ptdls_sta = NULL;
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
+ mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
+ }
+
+ ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
+
+ issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta, 1);
+
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+static int rtw_tdls_psoff(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, j, mac_addr[ETH_ALEN];
+ struct sta_info *ptdls_sta = NULL;
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
+ mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
+ }
+
+ ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
+
+ issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta, 0);
+
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+static int rtw_tdls_setip(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+ u8 i=0, j=0, k=0, tag=0, ip[3] = { 0xff }, *ptr = extra;
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1 );
+
+
+ while( i < 4 )
+ {
+ for( j=0; j < 4; j++)
+ {
+ if( *( extra + j + tag ) == '.' || *( extra + j + tag ) == '\0' )
+ {
+ if( j == 1 )
+ pwfd_info->ip_address[i]=convert_ip_addr( '0', '0', *(extra+(j-1)+tag));
+ if( j == 2 )
+ pwfd_info->ip_address[i]=convert_ip_addr( '0', *(extra+(j-2)+tag), *(extra+(j-1)+tag));
+ if( j == 3 )
+ pwfd_info->ip_address[i]=convert_ip_addr( *(extra+(j-3)+tag), *(extra+(j-2)+tag), *(extra+(j-1)+tag));
+
+ tag += j + 1;
+ break;
+ }
+ }
+ i++;
+ }
+
+ printk( "[%s] Set IP = %u.%u.%u.%u \n", __FUNCTION__,
+ ptdlsinfo->wfd_info->ip_address[0], ptdlsinfo->wfd_info->ip_address[1],
+ ptdlsinfo->wfd_info->ip_address[2], ptdlsinfo->wfd_info->ip_address[3]
+ );
+
+#endif //CONFIG_WFD
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+static int rtw_tdls_getip(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+
+ printk( "[%s]\n", __FUNCTION__);
+
+ sprintf( extra, "\n\n%u.%u.%u.%u\n",
+ pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
+ pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]
+ );
+
+ printk( "[%s] IP=%u.%u.%u.%u\n", __FUNCTION__,
+ pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
+ pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]
+ );
+
+ wrqu->data.length = strlen( extra );
+
+#endif //CONFIG_WFD
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+static int rtw_tdls_getport(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+
+ printk( "[%s]\n", __FUNCTION__);
+
+ sprintf( extra, "\n\n%d\n", pwfd_info->peer_rtsp_ctrlport );
+ printk( "[%s] remote port = %d\n", __FUNCTION__, pwfd_info->peer_rtsp_ctrlport );
+
+ wrqu->data.length = strlen( extra );
+
+#endif //CONFIG_WFD
+#endif //CONFIG_TDLS
+
+ return ret;
+
+}
+
+//WFDTDLS, for sigma test
+static int rtw_tdls_dis_result(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+
+ printk( "[%s]\n", __FUNCTION__);
+
+ if(ptdlsinfo->dev_discovered == 1 )
+ {
+ sprintf( extra, "\n\nDis=1\n" );
+ ptdlsinfo->dev_discovered = 0;
+ }
+
+ wrqu->data.length = strlen( extra );
+
+#endif //CONFIG_WFD
+#endif //CONFIG_TDLS
+
+ return ret;
+
+}
+
+//WFDTDLS, for sigma test
+static int rtw_wfd_tdls_status(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+
+ printk( "[%s]\n", __FUNCTION__);
+
+ if(ptdlsinfo->setup_state == TDLS_LINKED_STATE )
+ {
+ sprintf( extra, "\n\nStatus=1\n" );
+ }
+ else
+ {
+ sprintf( extra, "\n\nStatus=0\n" );
+ }
+
+ wrqu->data.length = strlen( extra );
+
+#endif //CONFIG_WFD
+#endif //CONFIG_TDLS
+
+ 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);
+ u8 i, j, mac_addr[ETH_ALEN];
+ struct sta_info *ptdls_sta = NULL;
+
+ printk( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1 );
+
+ for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
+ mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
+ }
+
+ ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
+
+ ptdls_sta->tdls_sta_state |= TDLS_SW_OFF_STATE;
+/*
+ if((ptdls_sta->tdls_sta_state & TDLS_AT_OFF_CH_STATE) && (ptdls_sta->tdls_sta_state & TDLS_PEER_AT_OFF_STATE)){
+ pmlmeinfo->tdls_candidate_ch= pmlmeext->cur_channel;
+ issue_tdls_ch_switch_req(padapter, mac_addr);
+ DBG_871X("issue tdls ch switch req back to base channel\n");
+ }
+*/
+
+#endif //CONFIG_TDLS
+
+ 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
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+ printk( "[%s] extra = %s\n", __FUNCTION__, extra );
+ // WFD Sigma will use the tdls enable command to let the driver know we want to test the tdls now!
+ if ( _rtw_memcmp( extra, "wfdenable=", 10 ) )
+ {
+ wrqu->data.length -=10;
+ rtw_wfd_tdls_enable( dev, info, wrqu, &extra[10] );
+ return ret;
+ }
+ else if ( _rtw_memcmp( extra, "weaksec=", 8 ) )
+ {
+ wrqu->data.length -=8;
+ rtw_tdls_weaksec( dev, info, wrqu, &extra[8] );
+ return ret;
+ }
+ else if ( _rtw_memcmp( extra, "tdlsenable=", 11 ) )
+ {
+ wrqu->data.length -=11;
+ rtw_tdls_enable( dev, info, wrqu, &extra[11] );
+ return ret;
+ }
+
+ if( padapter->tdlsinfo.enable == 0 )
+ {
+ printk("tdls haven't enabled\n");
+ return 0;
+ }
+
+ 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] );
+ }
+ else if (_rtw_memcmp( extra, "pson=", 5 ) )
+ {
+ wrqu->data.length -= 5;
+ rtw_tdls_pson( dev, info, wrqu, &extra[5] );
+ }
+ else if (_rtw_memcmp( extra, "psoff=", 6 ) )
+ {
+ wrqu->data.length -= 6;
+ rtw_tdls_psoff( dev, info, wrqu, &extra[6] );
+ }
+#ifdef CONFIG_WFD
+ else if (_rtw_memcmp( extra, "setip=", 6 ) )
+ {
+ wrqu->data.length -= 6;
+ rtw_tdls_setip( dev, info, wrqu, &extra[6] );
+ }
+ else if (_rtw_memcmp( extra, "tprobe=", 6 ) )
+ {
+ issue_tunneled_probe_req((_adapter *)rtw_netdev_priv(dev));
+ }
+#endif //CONFIG_WFD
+
+#endif //CONFIG_TDLS
+
+ return ret;
+}
+
+
+static int rtw_tdls_get(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_WFD
+
+ DBG_871X( "[%s] extra = %s\n", __FUNCTION__, (char*) wrqu->data.pointer );
+
+ if ( _rtw_memcmp( wrqu->data.pointer, "ip", 2 ) )
+ {
+ rtw_tdls_getip( dev, info, wrqu, extra );
+ }
+ if ( _rtw_memcmp( wrqu->data.pointer, "port", 4 ) )
+ {
+ rtw_tdls_getport( dev, info, wrqu, extra );
+ }
+
+ //WFDTDLS, for sigma test
+ if ( _rtw_memcmp( wrqu->data.pointer, "dis", 3 ) )
+ {
+ rtw_tdls_dis_result( dev, info, wrqu, extra );
+ }
+ if ( _rtw_memcmp( wrqu->data.pointer, "status", 6 ) )
+ {
+ rtw_wfd_tdls_status( dev, info, wrqu, extra );
+ }
+
+#endif //CONFIG_WFD
+
+ return ret;
+}
+
+static int rtw_pm_set(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ unsigned mode = 0;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+ DBG_871X( "[%s] extra = %s\n", __FUNCTION__, extra );
+
+ if ( _rtw_memcmp( extra, "lps=", 4 ) )
+ {
+ sscanf(extra+4, "%u", &mode);
+ ret = rtw_pm_set_lps(padapter,mode);
+ }
+ else if ( _rtw_memcmp( extra, "ips=", 4 ) )
+ {
+ sscanf(extra+4, "%u", &mode);
+ ret = rtw_pm_set_ips(padapter,mode);
+ }
+ else{
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_WOWLAN
+static int rtw_wowlan_ctrl(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct oid_par_priv oid_par;
+ struct wowlan_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_871X("+rtw_wowlan_ctrl\n");
+
+ //mutex_lock(&ioctl_mutex);
+
+ if ((!p->length) || (!p->pointer)) {
+ ret = -EINVAL;
+ goto _rtw_wowlan_ctrl_exit;
+ }
+
+ pparmbuf = NULL;
+ bset = (u8)(p->flags & 0xFFFF);
+ len = p->length;
+ pparmbuf = (u8*)rtw_malloc(len);
+ if (pparmbuf == NULL){
+ ret = -ENOMEM;
+ goto _rtw_wowlan_ctrl_exit;
+ }
+
+ if (copy_from_user(pparmbuf, p->pointer, len)) {
+ ret = -EFAULT;
+ goto _rtw_wowlan_ctrl_exit_free;
+ }
+ poidparam = (struct wowlan_ioctl_param *)pparmbuf;
+
+ if(padapter->pwrctrlpriv.bSupportRemoteWakeup==_FALSE){
+ ret = -EPERM;
+ DBG_871X("+rtw_wowlan_ctrl: Device didn't support the remote wakeup!!\n");
+ goto _rtw_wowlan_ctrl_exit_free;
+ }
+ padapter->HalFunc.SetHwRegHandler(padapter,HW_VAR_WOWLAN,(u8 *)poidparam);
+
+ DBG_871X("rtw_wowlan_ctrl: subcode [%d], len[%d], buffer_len[%d]\r\n",
+ poidparam->subcode, poidparam->len, len);
+
+ if (copy_to_user(p->pointer, pparmbuf, len)) {
+ ret = -EFAULT;
+ }
+
+
+_rtw_wowlan_ctrl_exit_free:
+ //DBG_871X("-rtw_wowlan_ctrl( subcode = %d)\n", poidparam->subcode);
+ rtw_mfree(pparmbuf, len);
+_rtw_wowlan_ctrl_exit:
+
+
+ return ret;
+}
+#endif //CONFIG_WOWLAN
+
+#ifdef CONFIG_INTEL_WIDI
+static int rtw_widi_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);
+
+ process_intel_widi_cmd(padapter, extra);
+
+ return ret;
+}
+
+static int rtw_widi_set_probe_request(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ u8 *pbuf = NULL;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+#if 1
+ pbuf = rtw_malloc(sizeof(l2_msg_t));
+ if(pbuf)
+ {
+ _rtw_memcpy(pbuf, wrqu->data.pointer, wrqu->data.length);
+ intel_widi_wk_cmd(padapter, INTEL_WIDI_ISSUE_PROB_WK, pbuf);
+ }
+#else
+ DBG_871X( "[%s] len = %d\n", __FUNCTION__,wrqu->data.length);
+
+ issue_probereq_widi(padapter, wrqu->data.pointer);
+#endif
+ return ret;
+}
+
+#endif // CONFIG_INTEL_WIDI
+
+#ifdef RTL8723A_SDIO_LOOPBACK
+#include <rtl8723a_hal.h>
+
+static s32 initLoopback(PADAPTER padapter)
+{
+ PLOOPBACKDATA ploopback;
+
+
+ if (padapter->ploopback == NULL) {
+ ploopback = (PLOOPBACKDATA)rtw_zmalloc(sizeof(LOOPBACKDATA));
+ if (ploopback == NULL) return -ENOMEM;
+
+ _rtw_init_sema(&ploopback->sema, 0);
+
+ ploopback->bstop = _TRUE;
+ ploopback->cnt = 0;
+ ploopback->size = 300;
+ _rtw_memset(ploopback->msg, 0, sizeof(ploopback->msg));
+
+ padapter->ploopback = ploopback;
+ }
+
+ return 0;
+}
+
+static void freeLoopback(PADAPTER padapter)
+{
+ PLOOPBACKDATA ploopback;
+
+
+ ploopback = padapter->ploopback;
+ if (ploopback) {
+ rtw_mfree((u8*)ploopback, sizeof(LOOPBACKDATA));
+ padapter->ploopback = NULL;
+ }
+}
+
+static s32 initpseudoadhoc(PADAPTER padapter)
+{
+ NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
+ s32 err;
+
+ networkType = Ndis802_11IBSS;
+ err = rtw_set_802_11_infrastructure_mode(padapter, networkType);
+ if (err == _FALSE) return _FAIL;
+
+ err = rtw_setopmode_cmd(padapter, networkType);
+ if (err == _FAIL) return _FAIL;
+
+ return _SUCCESS;
+}
+
+static s32 createpseudoadhoc(PADAPTER padapter)
+{
+ NDIS_802_11_AUTHENTICATION_MODE authmode;
+ struct mlme_priv *pmlmepriv;
+ NDIS_802_11_SSID *passoc_ssid;
+ WLAN_BSSID_EX *pdev_network;
+ u8 *pibss;
+ u8 ssid[] = "pseduo_ad-hoc";
+ s32 err;
+ _irqL irqL;
+
+
+ pmlmepriv = &padapter->mlmepriv;
+
+ authmode = Ndis802_11AuthModeOpen;
+ err = rtw_set_802_11_authentication_mode(padapter, authmode);
+ if (err == _FALSE) return _FAIL;
+
+ passoc_ssid = &pmlmepriv->assoc_ssid;
+ _rtw_memset(passoc_ssid, 0, sizeof(NDIS_802_11_SSID));
+ passoc_ssid->SsidLength = sizeof(ssid) - 1;
+ _rtw_memcpy(passoc_ssid->Ssid, ssid, passoc_ssid->SsidLength);
+
+ pdev_network = &padapter->registrypriv.dev_network;
+ pibss = padapter->registrypriv.dev_network.MacAddress;
+ _rtw_memcpy(&pdev_network->Ssid, passoc_ssid, sizeof(NDIS_802_11_SSID));
+
+ rtw_update_registrypriv_dev_network(padapter);
+ rtw_generate_random_ibss(pibss);
+
+ _enter_critical_bh(&pmlmepriv->lock, &irqL);
+ pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+ _exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+#if 0
+ err = rtw_createbss_cmd(padapter);
+ if (err == _FAIL) return _FAIL;
+#else
+{
+ struct wlan_network *pcur_network;
+ struct sta_info *psta;
+
+ //3 create a new psta
+ pcur_network = &pmlmepriv->cur_network;
+
+ //clear psta in the cur_network, if any
+ psta = rtw_get_stainfo(&padapter->stapriv, pcur_network->network.MacAddress);
+ if (psta) rtw_free_stainfo(padapter, psta);
+
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pibss);
+ if (psta == NULL) return _FAIL;
+
+ //3 join psudo AdHoc
+ pcur_network->join_res = 1;
+ pcur_network->aid = psta->aid = 1;
+ _rtw_memcpy(&pcur_network->network, pdev_network, get_WLAN_BSSID_EX_sz(pdev_network));
+
+ // set msr to WIFI_FW_ADHOC_STATE
+#if 0
+ Set_NETYPE0_MSR(padapter, WIFI_FW_ADHOC_STATE);
+#else
+ {
+ u8 val8;
+
+ val8 = rtw_read8(padapter, MSR);
+ val8 &= 0xFC; // clear NETYPE0
+ val8 |= WIFI_FW_ADHOC_STATE & 0x3;
+ rtw_write8(padapter, MSR, val8);
+ }
+#endif
+}
+#endif
+
+ return _SUCCESS;
+}
+
+extern void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc);
+extern void rtl8723a_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
+
+static struct xmit_frame* createloopbackpkt(PADAPTER padapter, u32 size)
+{
+ struct xmit_priv *pxmitpriv;
+ struct xmit_frame *pframe;
+ struct xmit_buf *pxmitbuf;
+ struct pkt_attrib *pattrib;
+ struct tx_desc *desc;
+ u8 *pkt_start, *pkt_end, *ptr;
+ struct rtw_ieee80211_hdr *hdr;
+ s32 bmcast;
+ _irqL irqL;
+
+
+ if ((TXDESC_SIZE + WLANHDR_OFFSET + size) > MAX_XMITBUF_SZ) return NULL;
+
+ pxmitpriv = &padapter->xmitpriv;
+ pframe = NULL;
+
+ //2 1. allocate xmit frame
+ pframe = rtw_alloc_xmitframe(pxmitpriv);
+ if (pframe == NULL) return NULL;
+ pframe->padapter = padapter;
+
+ //2 2. allocate xmit buffer
+ _enter_critical_bh(&pxmitpriv->lock, &irqL);
+ pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+ _exit_critical_bh(&pxmitpriv->lock, &irqL);
+ if (pxmitbuf == NULL) {
+ rtw_free_xmitframe_ex(pxmitpriv, pframe);
+ return NULL;
+ }
+
+ pframe->pxmitbuf = pxmitbuf;
+ pframe->buf_addr = pxmitbuf->pbuf;
+ pxmitbuf->priv_data = pframe;
+
+ //2 3. update_attrib()
+ pattrib = &pframe->attrib;
+
+ // init xmitframe attribute
+ _rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
+
+ pattrib->ether_type = 0x8723;
+ _rtw_memcpy(pattrib->src, padapter->eeprompriv.mac_addr, ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+ _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
+ _rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+// pattrib->pctrl = 0;
+// pattrib->dhcp_pkt = 0;
+// pattrib->pktlen = 0;
+ pattrib->ack_policy = 0;
+// pattrib->pkt_hdrlen = ETH_HLEN;
+ pattrib->hdrlen = WLAN_HDR_A3_LEN;
+ pattrib->subtype = WIFI_DATA;
+ pattrib->priority = 0;
+ pattrib->qsel = pattrib->priority;
+// do_queue_select(padapter, pattrib);
+ pattrib->nr_frags = 1;
+ pattrib->encrypt = 0;
+ pattrib->bswenc = _FALSE;
+ pattrib->qos_en = _FALSE;
+
+ bmcast = IS_MCAST(pattrib->ra);
+ if (bmcast) {
+ pattrib->mac_id = 1;
+ pattrib->psta = rtw_get_bcmc_stainfo(padapter);
+ } else {
+ pattrib->mac_id = 0;
+ pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
+ }
+
+ pattrib->pktlen = size;
+ pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
+
+ //2 4. fill TX descriptor
+ desc = (struct tx_desc*)pframe->buf_addr;
+ _rtw_memset(desc, 0, TXDESC_SIZE);
+
+ rtl8723a_fill_default_txdesc(pframe, (u8*)desc);
+
+ // Hw set sequence number
+ ((PTXDESC)desc)->hwseq_en = 0; // HWSEQ_EN, 0:disable, 1:enable
+// ((PTXDESC)desc)->hwseq_sel = 0; // HWSEQ_SEL
+
+ ((PTXDESC)desc)->disdatafb = 1;
+
+ // convert to little endian
+ desc->txdw0 = cpu_to_le32(desc->txdw0);
+ desc->txdw1 = cpu_to_le32(desc->txdw1);
+ desc->txdw2 = cpu_to_le32(desc->txdw2);
+ desc->txdw3 = cpu_to_le32(desc->txdw3);
+ desc->txdw4 = cpu_to_le32(desc->txdw4);
+ desc->txdw5 = cpu_to_le32(desc->txdw5);
+ desc->txdw6 = cpu_to_le32(desc->txdw6);
+ desc->txdw7 = cpu_to_le32(desc->txdw7);
+#ifdef CONFIG_PCI_HCI
+ desc->txdw8 = cpu_to_le32(desc->txdw8);
+ desc->txdw9 = cpu_to_le32(desc->txdw9);
+ desc->txdw10 = cpu_to_le32(desc->txdw10);
+ desc->txdw11 = cpu_to_le32(desc->txdw11);
+ desc->txdw12 = cpu_to_le32(desc->txdw12);
+ desc->txdw13 = cpu_to_le32(desc->txdw13);
+ desc->txdw14 = cpu_to_le32(desc->txdw14);
+ desc->txdw15 = cpu_to_le32(desc->txdw15);
+#endif
+
+ rtl8723a_cal_txdesc_chksum(desc);
+
+ //2 5. coalesce
+ pkt_start = pframe->buf_addr + TXDESC_SIZE;
+ pkt_end = pkt_start + pattrib->last_txcmdsz;
+
+ //3 5.1. make wlan header, make_wlanhdr()
+ hdr = (struct rtw_ieee80211_hdr *)pkt_start;
+ SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
+ _rtw_memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); // DA
+ _rtw_memcpy(hdr->addr2, pattrib->src, ETH_ALEN); // SA
+ _rtw_memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); // RA, BSSID
+
+ //3 5.2. make payload
+ ptr = pkt_start + pattrib->hdrlen;
+ get_random_bytes(ptr, pkt_end - ptr);
+
+ pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
+ pxmitbuf->ptail += pxmitbuf->len;
+
+ return pframe;
+}
+
+static void freeloopbackpkt(PADAPTER padapter, struct xmit_frame *pframe)
+{
+ struct xmit_priv *pxmitpriv;
+ struct xmit_buf *pxmitbuf;
+
+
+ pxmitpriv = &padapter->xmitpriv;
+ pxmitbuf = pframe->pxmitbuf;
+
+ rtw_free_xmitframe_ex(pxmitpriv, pframe);
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+}
+
+extern u32 get_txfifo_hwaddr(struct xmit_frame *pxmitframe);
+
+thread_return lbk_thread(thread_context context)
+{
+ s32 err;
+ PADAPTER padapter;
+ PLOOPBACKDATA ploopback;
+ struct xmit_frame *pxmitframe;
+ u32 cnt, ok, fail, i, headerlen;
+ u32 pktsize;
+ u32 ff_hwaddr;
+
+
+ padapter = (PADAPTER)context;
+ ploopback = padapter->ploopback;
+ if (ploopback == NULL) return -1;
+ cnt = 0;
+ ok = 0;
+ fail = 0;
+
+ daemonize("%s", "RTW_LBK_THREAD");
+ allow_signal(SIGTERM);
+
+ do {
+ if (ploopback->size == 0) {
+ get_random_bytes(&pktsize, 4);
+ pktsize = (pktsize % 1535) + 1; // 1~1535
+ } else
+ pktsize = ploopback->size;
+
+ pxmitframe = createloopbackpkt(padapter, pktsize);
+ if (pxmitframe == NULL) {
+ sprintf(ploopback->msg, "loopback FAIL! 3. create Packet FAIL!");
+ break;
+ }
+
+ ploopback->txsize = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
+ _rtw_memcpy(ploopback->txbuf, pxmitframe->buf_addr, ploopback->txsize);
+
+ ff_hwaddr = get_txfifo_hwaddr(pxmitframe);
+ rtw_write_port(padapter, ff_hwaddr, ploopback->txsize, ploopback->txbuf);
+ cnt++;
+
+ _rtw_down_sema(&ploopback->sema);
+
+{
+ PHAL_DATA_TYPE phal;
+ struct recv_stat *prxstat;
+ struct recv_stat report;
+ PRXREPORT prxreport;
+ u32 drvinfosize;
+ u32 rxpktsize;
+ u8 fcssize;
+
+ prxstat = (struct recv_stat*)ploopback->rxbuf;
+ report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
+ report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
+ report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
+ report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
+ report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
+ report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
+
+ prxreport = (PRXREPORT)&report;
+ drvinfosize = prxreport->drvinfosize << 3;
+ rxpktsize = prxreport->pktlen;
+
+ phal = GET_HAL_DATA(padapter);
+ if (phal->ReceiveConfig & RCR_APPFCS) fcssize = IEEE80211_FCS_LEN;
+ else fcssize = 0;
+
+ if ((ploopback->txsize - TXDESC_SIZE) != (rxpktsize - fcssize)) {
+ printk("%s: cnt=%d, size not match! tx=%d rx=%d\n",
+ __func__, i, ploopback->txsize - TXDESC_SIZE,
+ rxpktsize - fcssize);
+ err = _FALSE;
+ } else {
+ err = _rtw_memcmp(ploopback->txbuf + TXDESC_SIZE,\
+ ploopback->rxbuf + RXDESC_SIZE + drvinfosize,\
+ ploopback->txsize - TXDESC_SIZE);
+ }
+}
+
+ if (err == _TRUE)
+ ok++;
+ else
+ fail++;
+
+ ploopback->txsize = 0;
+ _rtw_memset(ploopback->txbuf, 0, 0x8000);
+ ploopback->rxsize = 0;
+ _rtw_memset(ploopback->rxbuf, 0, 0x8000);
+
+ freeloopbackpkt(padapter, pxmitframe);
+ pxmitframe = NULL;
+
+ if (signal_pending(current)) {
+ flush_signals(current);
+ }
+
+ if ((ploopback->bstop == _TRUE) ||
+ ((ploopback->cnt != 0) && (ploopback->cnt == cnt)))
+ {
+ u32 ok_rate, fail_rate;
+ ok_rate = (ok*100)/cnt;
+ fail_rate = (fail*100)/cnt;
+ sprintf(ploopback->msg, "loopback result: ok=%d%%(%d/%d),error=%d%%(%d/%d)", ok_rate, ok, cnt, fail_rate, fail, cnt);
+ break;
+ }
+ } while (1);
+
+ ploopback->bstop = _TRUE;
+
+ thread_exit();
+}
+
+static void loopbackTest(PADAPTER padapter, u32 cnt, u32 size, u8* pmsg)
+{
+ PLOOPBACKDATA ploopback;
+ u32 len;
+ s32 err;
+
+
+ ploopback = padapter->ploopback;
+
+ if (ploopback)
+ {
+ ploopback->bstop = _TRUE;
+ len = 0;
+ do {
+ len = strlen(ploopback->msg);
+ if (len) break;
+ rtw_msleep_os(1);
+ } while (1);
+ _rtw_memcpy(pmsg, ploopback->msg, len+1);
+ freeLoopback(padapter);
+ return;
+ }
+
+ // create pseudo ad-hoc connection
+ err = initpseudoadhoc(padapter);
+ if (err == _FAIL) {
+ sprintf(pmsg, "loopback FAIL! 1.1 init ad-hoc FAIL!");
+ return;
+ }
+
+ err = createpseudoadhoc(padapter);
+ if (err == _FAIL) {
+ sprintf(pmsg, "loopback FAIL! 1.2 create ad-hoc master FAIL!");
+ return;
+ }
+
+ err = initLoopback(padapter);
+ if (err) {
+ sprintf(pmsg, "loopback FAIL! 2. init FAIL! error code=%d", err);
+ return;
+ }
+
+ ploopback = padapter->ploopback;
+
+ ploopback->bstop = _FALSE;
+ ploopback->cnt = cnt;
+ ploopback->size = size;
+ ploopback->lbkthread = kernel_thread(lbk_thread, padapter, CLONE_FS|CLONE_FILES);
+ if (ploopback->lbkthread < 0) {
+ freeLoopback(padapter);
+ sprintf(pmsg, "loopback start FAIL! cnt=%d", cnt);
+ return;
+ }
+
+ sprintf(pmsg, "loopback start! cnt=%d", cnt);
+}
+
+extern u8 _InitPowerOn(PADAPTER padapter);
+extern s32 rtl8723a_FirmwareDownload(PADAPTER padapter);
+
+static int rtw_test(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ u32 len;
+ u8 *pbuf, *pch;
+ char *ptmp;
+ u8 *delim = ",";
+ PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+ printk("+%s\n", __func__);
+ len = wrqu->data.length;
+
+ pbuf = (u8*)rtw_zmalloc(len);
+ if (pbuf == NULL) {
+ printk("%s: no memory!\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
+ rtw_mfree(pbuf, len);
+ printk("%s: copy from user fail!\n", __func__);
+ return -EFAULT;
+ }
+ printk("%s: string=\"%s\"\n", __func__, pbuf);
+
+ ptmp = (char*)pbuf;
+ pch = strsep(&ptmp, delim);
+ if ((pch == NULL) || (strlen(pch) == 0)) {
+ rtw_mfree(pbuf, len);
+ printk("%s: parameter error(level 1)!\n", __func__);
+ return -EFAULT;
+ }
+
+#ifdef RTL8723A_SDIO_LOOPBACK
+ if (strcmp(pch, "loopback") == 0)
+ {
+ s32 cnt = 0;
+ u32 size = 64;
+
+ pch = strsep(&ptmp, delim);
+ if ((pch == NULL) || (strlen(pch) == 0)) {
+ rtw_mfree(pbuf, len);
+ printk("%s: parameter error(level 2)!\n", __func__);
+ return -EFAULT;
+ }
+
+ sscanf(pch, "%d", &cnt);
+ printk("%s: loopback cnt=%d\n", __func__, cnt);
+
+ pch = strsep(&ptmp, delim);
+ if ((pch == NULL) || (strlen(pch) == 0)) {
+ rtw_mfree(pbuf, len);
+ printk("%s: parameter error(level 2)!\n", __func__);
+ return -EFAULT;
+ }
+
+ sscanf(pch, "%d", &size);
+ printk("%s: loopback size=%d\n", __func__, size);
+
+ loopbackTest(padapter, cnt, size, extra);
+ wrqu->data.length = strlen(extra) + 1;
+
+ rtw_mfree(pbuf, len);
+ return 0;
+ }
+#endif
+
+ if (strcmp(pch, "poweron") == 0)
+ {
+ s32 ret;
+
+ ret = _InitPowerOn(padapter);
+ if (_FAIL == ret)
+ printk("%s: power on FAIL!\n", __func__);
+ else
+ printk("%s: power on OK.\n", __func__);
+
+ rtw_mfree(pbuf, len);
+ return 0;
+ }
+
+ if (strcmp(pch, "dlfw") == 0)
+ {
+ s32 ret;
+
+ ret = rtl8723a_FirmwareDownload(padapter);
+ if (_FAIL == ret)
+ printk("%s: download FW FAIL!\n", __func__);
+ else
+ printk("%s: download FW OK.\n", __func__);
+
+ rtw_mfree(pbuf, len);
+ return 0;
+ }
+
+ rtw_mfree(pbuf, len);
+ return 0;
+}
+#else
+static int rtw_test(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ printk("%s\n", __func__);
+ return 0;
+}
+#endif //RTL8723A_SDIO_LOOPBACK
+
+#include <rtw_android.h>
+int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct iwreq *wrq = (struct iwreq *)rq;
+ int ret=0;
+
+ 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;
+#ifdef CONFIG_NO_WIRELESS_HANDLERS
+ case SIOCSIWMODE:
+ ret = rtw_wx_set_mode(dev, NULL, &wrq->u, NULL);
+ break;
+#endif
+#endif
+ case (SIOCDEVPRIVATE+1):
+ ret = rtw_android_priv_cmd(dev, rq, cmd);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ 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 | 1024, 0 , ""}, //set
+ { SIOCIWFIRSTPRIV + 0x01, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , ""},//get
+/* --- sub-ioctls definitions --- */
+ { MP_START , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start" }, //set
+ { MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara" },//get
+ { MP_STOP , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop" }, //set
+ { MP_CHANNEL , IW_PRIV_TYPE_CHAR | 1024 , IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel" },//get
+ { MP_BANDWIDTH , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, //set
+ { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },//get
+ { MP_RESET_STATS , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
+ { MP_QUERY , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "mp_query"}, //get
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { READ_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg" },
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { READ_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf" },
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_PSD , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump" },
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_TXPOWER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_ANT_TX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_ANT_RX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { WRITE_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg" },
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { WRITE_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf" },
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_CTX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
+ { MP_NULL, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},//set
+ { MP_ARX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
+ { MP_ANT_RX , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ant_rx"},
+ { MP_THER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
+ { EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set" },
+ { EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get" },
+ { MP_PWRTRK , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
+ { MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, // mp_ioctl
+
+
+ { SIOCIWFIRSTPRIV + 0x02, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "test"},//set
+};
+
+
+static iw_handler rtw_private_handler[] =
+{
+ rtw_mp_set,
+ rtw_mp_get,
+};
+
+#else // not inlucde MP
+
+static const struct iw_priv_args rtw_private_args[] = {
+ {
+ SIOCIWFIRSTPRIV + 0x0,
+ IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x1,
+ IW_PRIV_TYPE_CHAR | 0x7FF,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
+ },
+ {
+ 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"
+ },
+#ifdef CONFIG_WOWLAN
+ {
+ SIOCIWFIRSTPRIV + 0xE,0,0, "wowlan_ctrl"
+ },
+#endif // CONFIG_WOWLAN
+ {
+ 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"
+ },
+ {SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0,"NULL"},
+ {
+ SIOCIWFIRSTPRIV + 0x14,
+ IW_PRIV_TYPE_CHAR | 64, 0, "tdls"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x15,
+ IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN , "tdls_get"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x16,
+ IW_PRIV_TYPE_CHAR | 64, 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"},
+ {
+ SIOCIWFIRSTPRIV + 0x1D,
+ IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
+ },
+#ifdef CONFIG_INTEL_WIDI
+ {
+ SIOCIWFIRSTPRIV + 0x1E,
+ IW_PRIV_TYPE_CHAR | 64, 0, "widi_set"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x1F,
+ IW_PRIV_TYPE_CHAR | 128, 0, "widi_prob_req"
+ },
+#endif // CONFIG_INTEL_WIDI
+};
+
+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
+
+#ifdef CONFIG_WOWLAN
+ rtw_wowlan_ctrl, //0x0E
+#else
+ rtw_wx_priv_null, //0x0E
+#endif //CONFIG_WOWLAN
+ rtw_wx_priv_null, //0x0F
+
+ rtw_p2p_set, //0x10
+ rtw_p2p_get, //0x11
+ rtw_p2p_get2, //0x12
+
+ NULL, //0x13
+ rtw_tdls, //0x14
+ rtw_tdls_get, //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
+ NULL, // 0x1C is reserved for hostapd
+ rtw_test , // 0x1D
+#ifdef CONFIG_INTEL_WIDI
+ rtw_widi_set, //0x1E
+ rtw_widi_set_probe_request, //0x1F
+#endif // CONFIG_INTEL_WIDI
+};
+
+#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_871X("No link level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
+ }
+ else{
+ #ifdef CONFIG_SIGNAL_DISPLAY_DBM
+ tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
+ #else
+ tmp_level = padapter->recvpriv.signal_strength;
+ #endif
+
+ tmp_qual = padapter->recvpriv.signal_qual;
+ tmp_noise =padapter->recvpriv.noise;
+ //DBG_871X("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_SIGNAL_DISPLAY_DBM
+ 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
+};
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/mlme_linux.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/mlme_linux.c
new file mode 100755
index 000000000000..b1a6507e18d0
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/mlme_linux.c
@@ -0,0 +1,565 @@
+/******************************************************************************
+ *
+ * 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 _MLME_OSDEP_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <mlme_osdep.h>
+
+
+#ifdef RTK_DMP_PLATFORM
+void Linkup_workitem_callback(struct work_struct *work)
+{
+ struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkup_workitem);
+ _adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
+
+_func_enter_;
+
+ RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+ Linkup_workitem_callback\n"));
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12))
+ kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKUP);
+#else
+ kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKUP);
+#endif
+
+_func_exit_;
+}
+
+void Linkdown_workitem_callback(struct work_struct *work)
+{
+ struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkdown_workitem);
+ _adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
+
+_func_enter_;
+
+ RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+ Linkdown_workitem_callback\n"));
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12))
+ kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKDOWN);
+#else
+ kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKDOWN);
+#endif
+
+_func_exit_;
+}
+#endif
+
+
+/*
+void sitesurvey_ctrl_handler(void *FunctionContext)
+{
+ _adapter *adapter = (_adapter *)FunctionContext;
+
+ _sitesurvey_ctrl_handler(adapter);
+
+ _set_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer, 3000);
+}
+*/
+
+void rtw_join_timeout_handler (void *FunctionContext)
+{
+ _adapter *adapter = (_adapter *)FunctionContext;
+ _rtw_join_timeout_handler(adapter);
+}
+
+
+void _rtw_scan_timeout_handler (void *FunctionContext)
+{
+ _adapter *adapter = (_adapter *)FunctionContext;
+ rtw_scan_timeout_handler(adapter);
+}
+
+
+void _dynamic_check_timer_handlder (void *FunctionContext)
+{
+ _adapter *adapter = (_adapter *)FunctionContext;
+
+ rtw_dynamic_check_timer_handlder(adapter);
+
+ _set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
+}
+
+#ifdef CONFIG_SET_SCAN_DENY_TIMER
+void _rtw_set_scan_deny_timer_hdl(void *FunctionContext)
+{
+ _adapter *adapter = (_adapter *)FunctionContext;
+ rtw_set_scan_deny_timer_hdl(adapter);
+}
+#endif
+
+
+void rtw_init_mlme_timer(_adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ _init_timer(&(pmlmepriv->assoc_timer), padapter->pnetdev, rtw_join_timeout_handler, padapter);
+ //_init_timer(&(pmlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer), padapter->pnetdev, sitesurvey_ctrl_handler, padapter);
+ _init_timer(&(pmlmepriv->scan_to_timer), padapter->pnetdev, _rtw_scan_timeout_handler, padapter);
+
+ _init_timer(&(pmlmepriv->dynamic_chk_timer), padapter->pnetdev, _dynamic_check_timer_handlder, padapter);
+
+ #ifdef CONFIG_SET_SCAN_DENY_TIMER
+ _init_timer(&(pmlmepriv->set_scan_deny_timer), padapter->pnetdev, _rtw_set_scan_deny_timer_hdl, padapter);
+ #endif
+
+#ifdef RTK_DMP_PLATFORM
+ _init_workitem(&(pmlmepriv->Linkup_workitem), Linkup_workitem_callback, padapter);
+ _init_workitem(&(pmlmepriv->Linkdown_workitem), Linkdown_workitem_callback, padapter);
+#endif
+
+}
+
+extern void rtw_indicate_wx_assoc_event(_adapter *padapter);
+extern void rtw_indicate_wx_disassoc_event(_adapter *padapter);
+
+void rtw_os_indicate_connect(_adapter *adapter)
+{
+
+_func_enter_;
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_cfg80211_indicate_connect(adapter);
+#endif //CONFIG_IOCTL_CFG80211
+
+ rtw_indicate_wx_assoc_event(adapter);
+ netif_carrier_on(adapter->pnetdev);
+
+ if(adapter->pid[2] !=0)
+ rtw_signal_process(adapter->pid[2], SIGALRM);
+
+#ifdef RTK_DMP_PLATFORM
+ _set_workitem(&adapter->mlmepriv.Linkup_workitem);
+#endif
+
+_func_exit_;
+
+}
+
+extern void indicate_wx_scan_complete_event(_adapter *padapter);
+void rtw_os_indicate_scan_done( _adapter *padapter, bool aborted)
+{
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev), aborted);
+#endif
+ indicate_wx_scan_complete_event(padapter);
+}
+
+static RT_PMKID_LIST backupPMKIDList[ NUM_PMKID_CACHE ];
+void rtw_reset_securitypriv( _adapter *adapter )
+{
+ u8 backupPMKIDIndex = 0;
+ u8 backupTKIPCountermeasure = 0x00;
+ u32 backupTKIPcountermeasure_time = 0;
+
+ if(adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)//802.1x
+ {
+ // Added by Albert 2009/02/18
+ // We have to backup the PMK information for WiFi PMK Caching test item.
+ //
+ // Backup the btkip_countermeasure information.
+ // When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds.
+
+ _rtw_memset( &backupPMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
+
+ _rtw_memcpy( &backupPMKIDList[ 0 ], &adapter->securitypriv.PMKIDList[ 0 ], sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
+ backupPMKIDIndex = adapter->securitypriv.PMKIDIndex;
+ backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure;
+ backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time;
+
+ _rtw_memset((unsigned char *)&adapter->securitypriv, 0, sizeof (struct security_priv));
+ //_init_timer(&(adapter->securitypriv.tkip_timer),adapter->pnetdev, rtw_use_tkipkey_handler, adapter);
+
+ // Added by Albert 2009/02/18
+ // Restore the PMK information to securitypriv structure for the following connection.
+ _rtw_memcpy( &adapter->securitypriv.PMKIDList[ 0 ], &backupPMKIDList[ 0 ], sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
+ adapter->securitypriv.PMKIDIndex = backupPMKIDIndex;
+ adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure;
+ adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time;
+
+ adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+
+ }
+ else //reset values in securitypriv
+ {
+ //if(adapter->mlmepriv.fw_state & WIFI_STATION_STATE)
+ //{
+ struct security_priv *psec_priv=&adapter->securitypriv;
+
+ psec_priv->dot11AuthAlgrthm =dot11AuthAlgrthm_Open; //open system
+ psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ psec_priv->dot11PrivacyKeyIndex = 0;
+
+ psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ psec_priv->dot118021XGrpKeyid = 1;
+
+ psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
+ psec_priv->wps_phase = _FALSE;
+ //}
+ }
+}
+
+void rtw_os_indicate_disconnect( _adapter *adapter )
+{
+ //RT_PMKID_LIST backupPMKIDList[ NUM_PMKID_CACHE ];
+
+_func_enter_;
+
+ netif_carrier_off(adapter->pnetdev); // Do it first for tx broadcast pkt after disconnection issue!
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_cfg80211_indicate_disconnect(adapter);
+#endif //CONFIG_IOCTL_CFG80211
+
+ rtw_indicate_wx_disassoc_event(adapter);
+
+#ifdef RTK_DMP_PLATFORM
+ _set_workitem(&adapter->mlmepriv.Linkdown_workitem);
+#endif
+ rtw_reset_securitypriv( adapter );
+
+_func_exit_;
+
+}
+
+void rtw_report_sec_ie(_adapter *adapter,u8 authmode,u8 *sec_ie)
+{
+ uint len;
+ u8 *buff,*p,i;
+ union iwreq_data wrqu;
+
+_func_enter_;
+
+ RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+rtw_report_sec_ie, authmode=%d\n", authmode));
+
+ buff = NULL;
+ if(authmode==_WPA_IE_ID_)
+ {
+ RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("rtw_report_sec_ie, authmode=%d\n", authmode));
+
+ buff = rtw_malloc(IW_CUSTOM_MAX);
+
+ _rtw_memset(buff,0,IW_CUSTOM_MAX);
+
+ p=buff;
+
+ p+=sprintf(p,"ASSOCINFO(ReqIEs=");
+
+ len = sec_ie[1]+2;
+ len = (len < IW_CUSTOM_MAX) ? len:IW_CUSTOM_MAX;
+
+ for(i=0;i<len;i++){
+ p+=sprintf(p,"%02x",sec_ie[i]);
+ }
+
+ p+=sprintf(p,")");
+
+ _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;
+
+ wireless_send_event(adapter->pnetdev,IWEVCUSTOM,&wrqu,buff);
+
+ if(buff)
+ rtw_mfree(buff, IW_CUSTOM_MAX);
+
+ }
+
+_func_exit_;
+
+}
+
+void _survey_timer_hdl (void *FunctionContext)
+{
+ _adapter *padapter = (_adapter *)FunctionContext;
+
+ survey_timer_hdl(padapter);
+}
+
+void _link_timer_hdl (void *FunctionContext)
+{
+ _adapter *padapter = (_adapter *)FunctionContext;
+ link_timer_hdl(padapter);
+}
+
+void _addba_timer_hdl(void *FunctionContext)
+{
+ struct sta_info *psta = (struct sta_info *)FunctionContext;
+ addba_timer_hdl(psta);
+}
+
+void init_addba_retry_timer(_adapter *padapter, struct sta_info *psta)
+{
+
+ _init_timer(&psta->addba_retry_timer, padapter->pnetdev, _addba_timer_hdl, psta);
+}
+
+/*
+void _reauth_timer_hdl(void *FunctionContext)
+{
+ _adapter *padapter = (_adapter *)FunctionContext;
+ reauth_timer_hdl(padapter);
+}
+
+void _reassoc_timer_hdl(void *FunctionContext)
+{
+ _adapter *padapter = (_adapter *)FunctionContext;
+ reassoc_timer_hdl(padapter);
+}
+*/
+
+void init_mlme_ext_timer(_adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ _init_timer(&pmlmeext->survey_timer, padapter->pnetdev, _survey_timer_hdl, padapter);
+ _init_timer(&pmlmeext->link_timer, padapter->pnetdev, _link_timer_hdl, padapter);
+ //_init_timer(&pmlmeext->ADDBA_timer, padapter->pnetdev, _addba_timer_hdl, padapter);
+
+ //_init_timer(&pmlmeext->reauth_timer, padapter->pnetdev, _reauth_timer_hdl, padapter);
+ //_init_timer(&pmlmeext->reassoc_timer, padapter->pnetdev, _reassoc_timer_hdl, padapter);
+}
+
+#ifdef CONFIG_AP_MODE
+
+void rtw_indicate_sta_assoc_event(_adapter *padapter, struct sta_info *psta)
+{
+ union iwreq_data wrqu;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if(psta==NULL)
+ return;
+
+ if(psta->aid > NUM_STA)
+ return;
+
+ if(pstapriv->sta_aid[psta->aid - 1] != psta)
+ return;
+
+
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ _rtw_memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+ DBG_871X("+rtw_indicate_sta_assoc_event\n");
+
+ wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
+
+}
+
+void rtw_indicate_sta_disassoc_event(_adapter *padapter, struct sta_info *psta)
+{
+ union iwreq_data wrqu;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if(psta==NULL)
+ return;
+
+ if(psta->aid > NUM_STA)
+ return;
+
+ if(pstapriv->sta_aid[psta->aid - 1] != psta)
+ return;
+
+
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ _rtw_memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+ DBG_871X("+rtw_indicate_sta_disassoc_event\n");
+
+ wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
+
+}
+
+
+#ifdef CONFIG_HOSTAPD_MLME
+
+static int mgnt_xmit_entry(struct sk_buff *skb, struct net_device *pnetdev)
+{
+ struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
+ _adapter *padapter = (_adapter *)phostapdpriv->padapter;
+
+ //DBG_871X("%s\n", __FUNCTION__);
+
+ return padapter->HalFunc.hostap_mgnt_xmit_entry(padapter, skb);
+}
+
+static int mgnt_netdev_open(struct net_device *pnetdev)
+{
+ struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
+
+ DBG_871X("mgnt_netdev_open: MAC Address:" MAC_FMT "\n", MAC_ARG(pnetdev->dev_addr));
+
+
+ init_usb_anchor(&phostapdpriv->anchored);
+
+ if(!netif_queue_stopped(pnetdev))
+ netif_start_queue(pnetdev);
+ else
+ netif_wake_queue(pnetdev);
+
+
+ netif_carrier_on(pnetdev);
+
+ //rtw_write16(phostapdpriv->padapter, 0x0116, 0x0100);//only excluding beacon
+
+ return 0;
+}
+static int mgnt_netdev_close(struct net_device *pnetdev)
+{
+ struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
+
+ DBG_871X("%s\n", __FUNCTION__);
+
+ usb_kill_anchored_urbs(&phostapdpriv->anchored);
+
+ netif_carrier_off(pnetdev);
+
+ if (!rtw_netif_queue_stopped(pnetdev))
+ rtw_netif_stop_queue(pnetdev);
+
+ //rtw_write16(phostapdpriv->padapter, 0x0116, 0x3f3f);
+
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+static const struct net_device_ops rtl871x_mgnt_netdev_ops = {
+ .ndo_open = mgnt_netdev_open,
+ .ndo_stop = mgnt_netdev_close,
+ .ndo_start_xmit = mgnt_xmit_entry,
+ //.ndo_set_mac_address = r871x_net_set_mac_address,
+ //.ndo_get_stats = r871x_net_get_stats,
+ //.ndo_do_ioctl = r871x_mp_ioctl,
+};
+#endif
+
+int hostapd_mode_init(_adapter *padapter)
+{
+ unsigned char mac[ETH_ALEN];
+ struct hostapd_priv *phostapdpriv;
+ struct net_device *pnetdev;
+
+ pnetdev = rtw_alloc_etherdev(sizeof(struct hostapd_priv));
+ if (!pnetdev)
+ return -ENOMEM;
+
+ //SET_MODULE_OWNER(pnetdev);
+ ether_setup(pnetdev);
+
+ //pnetdev->type = ARPHRD_IEEE80211;
+
+ phostapdpriv = rtw_netdev_priv(pnetdev);
+ phostapdpriv->pmgnt_netdev = pnetdev;
+ phostapdpriv->padapter= padapter;
+ padapter->phostapdpriv = phostapdpriv;
+
+ //pnetdev->init = NULL;
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+
+ DBG_871X("register rtl871x_mgnt_netdev_ops to netdev_ops\n");
+
+ pnetdev->netdev_ops = &rtl871x_mgnt_netdev_ops;
+
+#else
+
+ pnetdev->open = mgnt_netdev_open;
+
+ pnetdev->stop = mgnt_netdev_close;
+
+ pnetdev->hard_start_xmit = mgnt_xmit_entry;
+
+ //pnetdev->set_mac_address = r871x_net_set_mac_address;
+
+ //pnetdev->get_stats = r871x_net_get_stats;
+
+ //pnetdev->do_ioctl = r871x_mp_ioctl;
+
+#endif
+
+ pnetdev->watchdog_timeo = HZ; /* 1 second timeout */
+
+ //pnetdev->wireless_handlers = NULL;
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
+ pnetdev->features |= NETIF_F_IP_CSUM;
+#endif
+
+
+
+ if(dev_alloc_name(pnetdev,"mgnt.wlan%d") < 0)
+ {
+ DBG_871X("hostapd_mode_init(): dev_alloc_name, fail! \n");
+ }
+
+
+ //SET_NETDEV_DEV(pnetdev, pintfpriv->udev);
+
+
+ mac[0]=0x00;
+ mac[1]=0xe0;
+ mac[2]=0x4c;
+ mac[3]=0x87;
+ mac[4]=0x11;
+ mac[5]=0x12;
+
+ _rtw_memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
+
+
+ netif_carrier_off(pnetdev);
+
+
+ /* Tell the network stack we exist */
+ if (register_netdev(pnetdev) != 0)
+ {
+ DBG_871X("hostapd_mode_init(): register_netdev fail!\n");
+
+ if(pnetdev)
+ {
+ rtw_free_netdev(pnetdev);
+ }
+ }
+
+ return 0;
+
+}
+
+void hostapd_mode_unload(_adapter *padapter)
+{
+ struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
+ struct net_device *pnetdev = phostapdpriv->pmgnt_netdev;
+
+ unregister_netdev(pnetdev);
+ rtw_free_netdev(pnetdev);
+
+}
+
+#endif
+#endif
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/os_intfs.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/os_intfs.c
new file mode 100755
index 000000000000..802af7f0e8b0
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/os_intfs.c
@@ -0,0 +1,2269 @@
+/******************************************************************************
+ *
+ * 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 _OS_INTFS_C_
+
+#include <drv_conf.h>
+
+#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
+
+#error "Shall be Linux or Windows, but not both!\n"
+
+#endif
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <xmit_osdep.h>
+#include <recv_osdep.h>
+#include <hal_init.h>
+#include <rtw_ioctl.h>
+#include <rtw_version.h>
+
+#ifdef CONFIG_USB_HCI
+#include <usb_osintf.h>
+#endif
+
+#ifdef CONFIG_PCI_HCI
+#include <pci_osintf.h>
+#endif
+
+#ifdef CONFIG_BR_EXT
+#include <rtw_br_ext.h>
+#endif //CONFIG_BR_EXT
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
+MODULE_AUTHOR("Realtek Semiconductor Corp.");
+MODULE_VERSION(DRIVERVERSION);
+
+/* module param defaults */
+int rtw_chip_version = 0x00;
+int rtw_rfintfs = HWPI;
+int rtw_lbkmode = 0;//RTL8712_AIR_TRX;
+
+
+int rtw_network_mode = Ndis802_11IBSS;//Ndis802_11Infrastructure;//infra, ad-hoc, auto
+//NDIS_802_11_SSID ssid;
+int rtw_channel = 1;//ad-hoc support requirement
+int rtw_wireless_mode = WIRELESS_11BG_24N;
+int rtw_vrtl_carrier_sense = AUTO_VCS;
+int rtw_vcs_type = RTS_CTS;//*
+int rtw_rts_thresh = 2347;//*
+int rtw_frag_thresh = 2346;//*
+int rtw_preamble = PREAMBLE_LONG;//long, short, auto
+int rtw_scan_mode = 1;//active, passive
+int rtw_adhoc_tx_pwr = 1;
+int rtw_soft_ap = 0;
+//int smart_ps = 1;
+#ifdef CONFIG_POWER_SAVING
+int rtw_power_mgnt = 1;
+#ifdef CONFIG_IPS_LEVEL_2
+int rtw_ips_mode = IPS_LEVEL_2;
+#else
+int rtw_ips_mode = IPS_NORMAL;
+#endif
+#else
+int rtw_power_mgnt = PS_MODE_ACTIVE;
+int rtw_ips_mode = IPS_NONE;
+#endif
+module_param(rtw_ips_mode, int, 0644);
+MODULE_PARM_DESC(rtw_ips_mode,"The default IPS mode");
+
+int rtw_radio_enable = 1;
+int rtw_long_retry_lmt = 7;
+int rtw_short_retry_lmt = 7;
+int rtw_busy_thresh = 40;
+//int qos_enable = 0; //*
+int rtw_ack_policy = NORMAL_ACK;
+#ifdef CONFIG_MP_INCLUDED
+int rtw_mp_mode = 1;
+#else
+int rtw_mp_mode = 0;
+#endif
+int rtw_software_encrypt = 0;
+int rtw_software_decrypt = 0;
+
+int rtw_acm_method = 0;// 0:By SW 1:By HW.
+
+int rtw_wmm_enable = 1;// default is set to enable the wmm.
+int rtw_uapsd_enable = 0;
+int rtw_uapsd_max_sp = NO_LIMIT;
+int rtw_uapsd_acbk_en = 0;
+int rtw_uapsd_acbe_en = 0;
+int rtw_uapsd_acvi_en = 0;
+int rtw_uapsd_acvo_en = 0;
+
+#ifdef CONFIG_80211N_HT
+int rtw_ht_enable = 1;
+int rtw_cbw40_enable = 3; // 0 :diable, bit(0): enable 2.4g, bit(1): enable 5g
+int rtw_ampdu_enable = 1;//for enable tx_ampdu
+int rtw_rx_stbc = 1;// 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
+int rtw_ampdu_amsdu = 0;// 0: disabled, 1:enabled, 2:auto
+#endif
+
+int rtw_lowrate_two_xmit = 1;//Use 2 path Tx to transmit MCS0~7 and legacy mode
+
+//int rf_config = RF_1T2R; // 1T2R
+int rtw_rf_config = RF_819X_MAX_TYPE; //auto
+int rtw_low_power = 0;
+#ifdef CONFIG_WIFI_TEST
+int rtw_wifi_spec = 1;//for wifi test
+#else
+int rtw_wifi_spec = 0;
+#endif
+int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
+
+#ifdef CONFIG_BT_COEXIST
+int rtw_bt_iso = 2;// 0:Low, 1:High, 2:From Efuse
+int rtw_bt_sco = 3;// 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy
+int rtw_bt_ampdu =1 ;// 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU.
+#endif
+int rtw_AcceptAddbaReq = _TRUE;// 0:Reject AP's Add BA req, 1:Accept AP's Add BA req.
+
+int rtw_antdiv_cfg = 2; // 0:OFF , 1:ON, 2:decide by Efuse config
+
+#ifdef CONFIG_USB_AUTOSUSPEND
+int rtw_enusbss = 1;//0:disable,1:enable
+#else
+int rtw_enusbss = 0;//0:disable,1:enable
+#endif
+
+int rtw_hwpdn_mode=2;//0:disable,1:enable,2: by EFUSE config
+
+#ifdef CONFIG_HW_PWRP_DETECTION
+int rtw_hwpwrp_detect = 1;
+#else
+int rtw_hwpwrp_detect = 0; //HW power ping detect 0:disable , 1:enable
+#endif
+
+#ifdef CONFIG_USB_HCI
+int rtw_hw_wps_pbc = 1;
+#else
+int rtw_hw_wps_pbc = 0;
+#endif
+
+#ifdef CONFIG_TX_MCAST2UNI
+int rtw_mc2u_disable = 0;
+#endif // CONFIG_TX_MCAST2UNI
+
+int rtw_mac_phy_mode = 0; //0:by efuse, 1:smsp, 2:dmdp, 3:dmsp.
+
+#ifdef CONFIG_80211D
+int rtw_80211d = 0;
+#endif
+
+char* ifname = "wlan%d";
+module_param(ifname, charp, 0644);
+MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
+
+char* if2name = "wlan%d";
+module_param(if2name, charp, 0644);
+MODULE_PARM_DESC(if2name, "The default name to allocate for second interface");
+
+char* rtw_initmac = 0; // temp mac address if users want to use instead of the mac address in Efuse
+
+module_param(rtw_initmac, charp, 0644);
+module_param(rtw_channel_plan, int, 0644);
+module_param(rtw_chip_version, int, 0644);
+module_param(rtw_rfintfs, int, 0644);
+module_param(rtw_lbkmode, int, 0644);
+module_param(rtw_network_mode, int, 0644);
+module_param(rtw_channel, int, 0644);
+module_param(rtw_mp_mode, int, 0644);
+module_param(rtw_wmm_enable, int, 0644);
+module_param(rtw_vrtl_carrier_sense, int, 0644);
+module_param(rtw_vcs_type, int, 0644);
+module_param(rtw_busy_thresh, int, 0644);
+#ifdef CONFIG_80211N_HT
+module_param(rtw_ht_enable, int, 0644);
+module_param(rtw_cbw40_enable, int, 0644);
+module_param(rtw_ampdu_enable, int, 0644);
+module_param(rtw_rx_stbc, int, 0644);
+module_param(rtw_ampdu_amsdu, int, 0644);
+#endif
+
+module_param(rtw_lowrate_two_xmit, int, 0644);
+
+module_param(rtw_rf_config, int, 0644);
+module_param(rtw_power_mgnt, int, 0644);
+module_param(rtw_low_power, int, 0644);
+module_param(rtw_wifi_spec, int, 0644);
+
+module_param(rtw_antdiv_cfg, int, 0644);
+
+
+module_param(rtw_enusbss, int, 0644);
+module_param(rtw_hwpdn_mode, int, 0644);
+module_param(rtw_hwpwrp_detect, int, 0644);
+
+module_param(rtw_hw_wps_pbc, int, 0644);
+
+#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
+char *rtw_adaptor_info_caching_file_path= "/data/misc/wifi/rtw_cache";
+module_param(rtw_adaptor_info_caching_file_path, charp, 0644);
+MODULE_PARM_DESC(rtw_adaptor_info_caching_file_path, "The path of adapter info cache file");
+#endif //CONFIG_ADAPTOR_INFO_CACHING_FILE
+
+#ifdef CONFIG_LAYER2_ROAMING
+uint rtw_max_roaming_times=2;
+module_param(rtw_max_roaming_times, uint, 0644);
+MODULE_PARM_DESC(rtw_max_roaming_times,"The max roaming times to try");
+#endif //CONFIG_LAYER2_ROAMING
+
+#ifdef CONFIG_IOL
+bool rtw_force_iol=_FALSE;
+module_param(rtw_force_iol, bool, 0644);
+MODULE_PARM_DESC(rtw_force_iol,"Force to enable IOL");
+#endif //CONFIG_IOL
+
+#ifdef CONFIG_FILE_FWIMG
+char *rtw_fw_file_path= "";
+module_param(rtw_fw_file_path, charp, 0644);
+MODULE_PARM_DESC(rtw_fw_file_path, "The path of fw image");
+#endif //CONFIG_FILE_FWIMG
+
+#ifdef CONFIG_TX_MCAST2UNI
+module_param(rtw_mc2u_disable, int, 0644);
+#endif // CONFIG_TX_MCAST2UNI
+
+module_param(rtw_mac_phy_mode, int, 0644);
+
+#ifdef CONFIG_80211D
+module_param(rtw_80211d, int, 0644);
+#endif
+
+uint rtw_notch_filter = RTW_NOTCH_FILTER;
+module_param(rtw_notch_filter, uint, 0644);
+MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P");
+
+static uint loadparam( _adapter *padapter, _nic_hdl pnetdev);
+int _netdev_open(struct net_device *pnetdev);
+int netdev_open (struct net_device *pnetdev);
+static int netdev_close (struct net_device *pnetdev);
+
+//#ifdef RTK_DMP_PLATFORM
+#ifdef CONFIG_PROC_DEBUG
+#define RTL8192C_PROC_NAME "rtl819xC"
+#define RTL8192D_PROC_NAME "rtl819xD"
+static char rtw_proc_name[IFNAMSIZ];
+static struct proc_dir_entry *rtw_proc = NULL;
+static int rtw_proc_cnt = 0;
+
+#define RTW_PROC_NAME DRV_NAME
+
+void rtw_proc_init_one(struct net_device *dev)
+{
+ struct proc_dir_entry *dir_dev = NULL;
+ struct proc_dir_entry *entry=NULL;
+ _adapter *padapter = rtw_netdev_priv(dev);
+ u8 rf_type;
+
+ if(rtw_proc == NULL)
+ {
+ if(padapter->chip_type == RTL8188C_8192C)
+ {
+ _rtw_memcpy(rtw_proc_name, RTL8192C_PROC_NAME, sizeof(RTL8192C_PROC_NAME));
+ }
+ else if(padapter->chip_type == RTL8192D)
+ {
+ _rtw_memcpy(rtw_proc_name, RTL8192D_PROC_NAME, sizeof(RTL8192D_PROC_NAME));
+ }
+ else if(padapter->chip_type == RTL8723A)
+ {
+ _rtw_memcpy(rtw_proc_name, RTW_PROC_NAME, sizeof(RTW_PROC_NAME));
+ }
+ else if(padapter->chip_type == RTL8188E)
+ {
+ _rtw_memcpy(rtw_proc_name, RTW_PROC_NAME, sizeof(RTW_PROC_NAME));
+ }
+ else
+ {
+ _rtw_memcpy(rtw_proc_name, RTW_PROC_NAME, sizeof(RTW_PROC_NAME));
+ }
+
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+ rtw_proc=create_proc_entry(rtw_proc_name, S_IFDIR, proc_net);
+#else
+ rtw_proc=create_proc_entry(rtw_proc_name, S_IFDIR, init_net.proc_net);
+#endif
+ if (rtw_proc == NULL) {
+ DBG_871X(KERN_ERR "Unable to create rtw_proc directory\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("ver_info", S_IFREG | S_IRUGO, rtw_proc, proc_get_drv_version, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("log_level", S_IFREG | S_IRUGO,
+ rtw_proc, proc_get_log_level, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_log_level;
+ }
+
+
+
+ if(padapter->dir_dev == NULL)
+ {
+ padapter->dir_dev = create_proc_entry(dev->name,
+ S_IFDIR | S_IRUGO | S_IXUGO,
+ rtw_proc);
+
+ dir_dev = padapter->dir_dev;
+
+ if(dir_dev==NULL)
+ {
+ if(rtw_proc_cnt == 0)
+ {
+ if(rtw_proc){
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+ remove_proc_entry(rtw_proc_name, proc_net);
+#else
+ remove_proc_entry(rtw_proc_name, init_net.proc_net);
+#endif
+ rtw_proc = NULL;
+ }
+ }
+
+ DBG_871X("Unable to create dir_dev directory\n");
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ rtw_proc_cnt++;
+
+ entry = create_proc_read_entry("write_reg", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_write_reg, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_write_reg;
+
+ entry = create_proc_read_entry("read_reg", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_read_reg, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_read_reg;
+
+
+ entry = create_proc_read_entry("fwstate", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_fwstate, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+
+ entry = create_proc_read_entry("sec_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_sec_info, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+
+ entry = create_proc_read_entry("mlmext_state", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mlmext_state, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+
+ entry = create_proc_read_entry("qos_option", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_qos_option, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("ht_option", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_ht_option, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_info, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("ap_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_ap_info, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("adapter_state", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_adapter_state, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("trx_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_trx_info, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("mac_reg_dump1", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mac_reg_dump1, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("mac_reg_dump2", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mac_reg_dump2, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("mac_reg_dump3", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mac_reg_dump3, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("bb_reg_dump1", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_bb_reg_dump1, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("bb_reg_dump2", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_bb_reg_dump2, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("bb_reg_dump3", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_bb_reg_dump3, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_reg_dump1", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump1, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_reg_dump2", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump2, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if((RF_1T2R == rf_type) ||(RF_1T1R ==rf_type )) {
+ entry = create_proc_read_entry("rf_reg_dump3", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump3, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_reg_dump4", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump4, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ }
+
+#ifdef CONFIG_AP_MODE
+
+ entry = create_proc_read_entry("all_sta_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_all_sta_info, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+#endif
+
+#ifdef DBG_MEMORY_LEAK
+ entry = create_proc_read_entry("_malloc_cnt", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_malloc_cnt, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+#endif
+
+#ifdef CONFIG_FIND_BEST_CHANNEL
+ entry = create_proc_read_entry("best_channel", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_best_channel, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+#endif
+
+ entry = create_proc_read_entry("rx_signal", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rx_signal, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_rx_signal;
+
+ entry = create_proc_read_entry("cbw40_enable", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_cbw40_enable, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_cbw40_enable;
+
+ entry = create_proc_read_entry("ampdu_enable", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_ampdu_enable, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_ampdu_enable;
+
+ entry = create_proc_read_entry("rx_stbc", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rx_stbc, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_rx_stbc;
+
+
+ entry = create_proc_read_entry("path_rssi", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_two_path_rssi, dev);
+
+ entry = create_proc_read_entry("vid", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_vid, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("pid", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_pid, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rssi_disp", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rssi_disp, dev);
+ if (!entry) {
+ DBG_871X("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_rssi_disp;
+
+}
+
+void rtw_proc_remove_one(struct net_device *dev)
+{
+ struct proc_dir_entry *dir_dev = NULL;
+ _adapter *padapter = rtw_netdev_priv(dev);
+ u8 rf_type;
+
+ dir_dev = padapter->dir_dev;
+ padapter->dir_dev = NULL;
+
+ if (dir_dev) {
+
+ remove_proc_entry("write_reg", dir_dev);
+ remove_proc_entry("read_reg", dir_dev);
+ remove_proc_entry("fwstate", dir_dev);
+ remove_proc_entry("sec_info", dir_dev);
+ remove_proc_entry("mlmext_state", dir_dev);
+ remove_proc_entry("qos_option", dir_dev);
+ remove_proc_entry("ht_option", dir_dev);
+ remove_proc_entry("rf_info", dir_dev);
+ remove_proc_entry("ap_info", dir_dev);
+ remove_proc_entry("adapter_state", dir_dev);
+ remove_proc_entry("trx_info", dir_dev);
+
+ remove_proc_entry("mac_reg_dump1", dir_dev);
+ remove_proc_entry("mac_reg_dump2", dir_dev);
+ remove_proc_entry("mac_reg_dump3", dir_dev);
+ remove_proc_entry("bb_reg_dump1", dir_dev);
+ remove_proc_entry("bb_reg_dump2", dir_dev);
+ remove_proc_entry("bb_reg_dump3", dir_dev);
+ remove_proc_entry("rf_reg_dump1", dir_dev);
+ remove_proc_entry("rf_reg_dump2", dir_dev);
+ padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if((RF_1T2R == rf_type) ||(RF_1T1R ==rf_type )) {
+ remove_proc_entry("rf_reg_dump3", dir_dev);
+ remove_proc_entry("rf_reg_dump4", dir_dev);
+ }
+#ifdef CONFIG_AP_MODE
+ remove_proc_entry("all_sta_info", dir_dev);
+#endif
+
+#ifdef DBG_MEMORY_LEAK
+ remove_proc_entry("_malloc_cnt", dir_dev);
+#endif
+
+#ifdef CONFIG_FIND_BEST_CHANNEL
+ remove_proc_entry("best_channel", dir_dev);
+#endif
+ remove_proc_entry("rx_signal", dir_dev);
+
+ remove_proc_entry("cbw40_enable", dir_dev);
+
+ remove_proc_entry("ampdu_enable", dir_dev);
+
+ remove_proc_entry("rx_stbc", dir_dev);
+
+ remove_proc_entry("path_rssi", dir_dev);
+
+ remove_proc_entry("vid", dir_dev);
+
+ remove_proc_entry("pid", dir_dev);
+
+ remove_proc_entry("rssi_disp", dir_dev);
+
+ remove_proc_entry(dev->name, rtw_proc);
+ dir_dev = NULL;
+
+ }
+ else
+ {
+ return;
+ }
+
+ rtw_proc_cnt--;
+
+ if(rtw_proc_cnt == 0)
+ {
+ if(rtw_proc){
+ remove_proc_entry("ver_info", rtw_proc);
+
+ remove_proc_entry("log_level", rtw_proc);
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+ remove_proc_entry(rtw_proc_name, proc_net);
+#else
+ remove_proc_entry(rtw_proc_name, init_net.proc_net);
+#endif
+ rtw_proc = NULL;
+ }
+ }
+}
+#endif
+
+uint loadparam( _adapter *padapter, _nic_hdl pnetdev);
+uint loadparam( _adapter *padapter, _nic_hdl pnetdev)
+{
+
+ uint status = _SUCCESS;
+ struct registry_priv *registry_par = &padapter->registrypriv;
+
+_func_enter_;
+
+ registry_par->chip_version = (u8)rtw_chip_version;
+ registry_par->rfintfs = (u8)rtw_rfintfs;
+ registry_par->lbkmode = (u8)rtw_lbkmode;
+ //registry_par->hci = (u8)hci;
+ registry_par->network_mode = (u8)rtw_network_mode;
+
+ _rtw_memcpy(registry_par->ssid.Ssid, "ANY", 3);
+ registry_par->ssid.SsidLength = 3;
+
+ registry_par->channel = (u8)rtw_channel;
+ registry_par->wireless_mode = (u8)rtw_wireless_mode;
+ registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense ;
+ registry_par->vcs_type = (u8)rtw_vcs_type;
+ registry_par->rts_thresh=(u16)rtw_rts_thresh;
+ registry_par->frag_thresh=(u16)rtw_frag_thresh;
+ registry_par->preamble = (u8)rtw_preamble;
+ registry_par->scan_mode = (u8)rtw_scan_mode;
+ registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr;
+ registry_par->soft_ap= (u8)rtw_soft_ap;
+ //registry_par->smart_ps = (u8)rtw_smart_ps;
+ registry_par->power_mgnt = (u8)rtw_power_mgnt;
+ registry_par->ips_mode = (u8)rtw_ips_mode;
+ registry_par->radio_enable = (u8)rtw_radio_enable;
+ registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt;
+ registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt;
+ registry_par->busy_thresh = (u16)rtw_busy_thresh;
+ //registry_par->qos_enable = (u8)rtw_qos_enable;
+ registry_par->ack_policy = (u8)rtw_ack_policy;
+ registry_par->mp_mode = (u8)rtw_mp_mode;
+ registry_par->software_encrypt = (u8)rtw_software_encrypt;
+ registry_par->software_decrypt = (u8)rtw_software_decrypt;
+
+ registry_par->acm_method = (u8)rtw_acm_method;
+
+ //UAPSD
+ registry_par->wmm_enable = (u8)rtw_wmm_enable;
+ registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
+ registry_par->uapsd_max_sp = (u8)rtw_uapsd_max_sp;
+ registry_par->uapsd_acbk_en = (u8)rtw_uapsd_acbk_en;
+ registry_par->uapsd_acbe_en = (u8)rtw_uapsd_acbe_en;
+ registry_par->uapsd_acvi_en = (u8)rtw_uapsd_acvi_en;
+ registry_par->uapsd_acvo_en = (u8)rtw_uapsd_acvo_en;
+
+#ifdef CONFIG_80211N_HT
+ registry_par->ht_enable = (u8)rtw_ht_enable;
+ registry_par->cbw40_enable = (u8)rtw_cbw40_enable;
+ registry_par->ampdu_enable = (u8)rtw_ampdu_enable;
+ registry_par->rx_stbc = (u8)rtw_rx_stbc;
+ registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
+#endif
+
+ registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit;
+ registry_par->rf_config = (u8)rtw_rf_config;
+ registry_par->low_power = (u8)rtw_low_power;
+
+
+ registry_par->wifi_spec = (u8)rtw_wifi_spec;
+
+ registry_par->channel_plan = (u8)rtw_channel_plan;
+
+#ifdef CONFIG_BT_COEXIST
+ registry_par->bt_iso = (u8)rtw_bt_iso;
+ registry_par->bt_sco = (u8)rtw_bt_sco;
+ registry_par->bt_ampdu = (u8)rtw_bt_ampdu;
+#endif
+ registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq;
+
+ registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
+
+#ifdef CONFIG_AUTOSUSPEND
+ registry_par->usbss_enable = (u8)rtw_enusbss;//0:disable,1:enable
+#endif
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+ registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;//0:disable,1:enable,2:by EFUSE config
+ registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect;//0:disable,1:enable
+#endif
+
+ registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc;
+
+#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
+ snprintf(registry_par->adaptor_info_caching_file_path, PATH_LENGTH_MAX, "%s", rtw_adaptor_info_caching_file_path);
+ registry_par->adaptor_info_caching_file_path[PATH_LENGTH_MAX-1]=0;
+#endif
+
+#ifdef CONFIG_LAYER2_ROAMING
+ registry_par->max_roaming_times = (u8)rtw_max_roaming_times;
+#endif
+
+#ifdef CONFIG_IOL
+ registry_par->force_iol = rtw_force_iol;
+#endif
+
+ registry_par->mac_phy_mode = rtw_mac_phy_mode;
+
+#ifdef CONFIG_80211D
+ registry_par->enable80211d = (u8)rtw_80211d;
+#endif
+
+ snprintf(registry_par->ifname, 16, "%s", ifname);
+ snprintf(registry_par->if2name, 16, "%s", if2name);
+
+ registry_par->notch_filter = (u8)rtw_notch_filter;
+
+_func_exit_;
+
+ return status;
+}
+
+static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+ struct sockaddr *addr = p;
+
+ if(padapter->bup == _FALSE)
+ {
+ //DBG_871X("r8711_net_set_mac_address(), MAC=%x:%x:%x:%x:%x:%x\n", addr->sa_data[0], addr->sa_data[1], addr->sa_data[2], addr->sa_data[3],
+ //addr->sa_data[4], addr->sa_data[5]);
+ _rtw_memcpy(padapter->eeprompriv.mac_addr, addr->sa_data, ETH_ALEN);
+ //_rtw_memcpy(pnetdev->dev_addr, addr->sa_data, ETH_ALEN);
+ //padapter->bset_hwaddr = _TRUE;
+ }
+
+ return 0;
+}
+
+static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct recv_priv *precvpriv = &(padapter->recvpriv);
+
+ padapter->stats.tx_packets = pxmitpriv->tx_pkts;//pxmitpriv->tx_pkts++;
+ padapter->stats.rx_packets = precvpriv->rx_pkts;//precvpriv->rx_pkts++;
+ padapter->stats.tx_dropped = pxmitpriv->tx_drop;
+ padapter->stats.rx_dropped = precvpriv->rx_drop;
+ padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
+ padapter->stats.rx_bytes = precvpriv->rx_bytes;
+
+ return &padapter->stats;
+}
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+/*
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 0
+ * AC_VI -> queue 1
+ * AC_BE -> queue 2
+ * AC_BK -> queue 3
+ */
+static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+/* Given a data frame determine the 802.1p/1d tag to use. */
+unsigned int rtw_classify8021d(struct sk_buff *skb)
+{
+ unsigned int dscp;
+
+ /* skb->priority values from 256->263 are magic values to
+ * directly indicate a specific 802.1d priority. This is used
+ * to allow 802.1d priority to be passed directly in from VLAN
+ * tags, etc.
+ */
+ if (skb->priority >= 256 && skb->priority <= 263)
+ return skb->priority - 256;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ dscp = ip_hdr(skb)->tos & 0xfc;
+ break;
+ default:
+ return 0;
+ }
+
+ return dscp >> 5;
+}
+
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+ _adapter *padapter = rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ skb->priority = rtw_classify8021d(skb);
+
+ if(pmlmepriv->acm_mask != 0)
+ {
+ skb->priority = qos_acm(pmlmepriv->acm_mask, skb->priority);
+ }
+
+ return rtw_1d_to_queue[skb->priority];
+}
+#endif
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+static const struct net_device_ops rtw_netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = rtw_xmit_entry,
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+ .ndo_select_queue = rtw_select_queue,
+#endif
+ .ndo_set_mac_address = rtw_net_set_mac_address,
+ .ndo_get_stats = rtw_net_get_stats,
+ .ndo_do_ioctl = rtw_ioctl,
+};
+#endif
+
+int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname)
+{
+ _adapter *padapter = rtw_netdev_priv(pnetdev);
+
+#ifdef CONFIG_EASY_REPLACEMENT
+ struct net_device *TargetNetdev = NULL;
+ _adapter *TargetAdapter = NULL;
+ struct net *devnet = NULL;
+
+ if(padapter->bDongle == 1)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+ TargetNetdev = dev_get_by_name("wlan0");
+#else
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
+ devnet = pnetdev->nd_net;
+ #else
+ devnet = dev_net(pnetdev);
+ #endif
+ TargetNetdev = dev_get_by_name(devnet, "wlan0");
+#endif
+ if(TargetNetdev) {
+ DBG_871X("Force onboard module driver disappear !!!\n");
+ TargetAdapter = rtw_netdev_priv(TargetNetdev);
+ TargetAdapter->DriverState = DRIVER_DISAPPEAR;
+
+ padapter->pid[0] = TargetAdapter->pid[0];
+ padapter->pid[1] = TargetAdapter->pid[1];
+ padapter->pid[2] = TargetAdapter->pid[2];
+
+ dev_put(TargetNetdev);
+ unregister_netdev(TargetNetdev);
+#ifdef CONFIG_PROC_DEBUG
+ if(TargetAdapter->chip_type == padapter->chip_type)
+ rtw_proc_remove_one(TargetNetdev);
+#endif
+ padapter->DriverState = DRIVER_REPLACE_DONGLE;
+ }
+ }
+#endif
+
+ if(dev_alloc_name(pnetdev, ifname) < 0)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("dev_alloc_name, fail! \n"));
+ }
+
+ netif_carrier_off(pnetdev);
+ //rtw_netif_stop_queue(pnetdev);
+
+ return 0;
+}
+
+struct net_device *rtw_init_netdev(_adapter *old_padapter)
+{
+ _adapter *padapter;
+ struct net_device *pnetdev;
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("+init_net_dev\n"));
+
+ if(old_padapter != NULL)
+ pnetdev = rtw_alloc_etherdev_with_old_priv(sizeof(_adapter), (void *)old_padapter);
+ else
+ pnetdev = rtw_alloc_etherdev(sizeof(_adapter));
+
+ if (!pnetdev)
+ return NULL;
+
+ padapter = rtw_netdev_priv(pnetdev);
+ padapter->pnetdev = pnetdev;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+ SET_MODULE_OWNER(pnetdev);
+#endif
+
+ //pnetdev->init = NULL;
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+ DBG_871X("register rtw_netdev_ops to netdev_ops\n");
+ pnetdev->netdev_ops = &rtw_netdev_ops;
+#else
+ pnetdev->open = netdev_open;
+ pnetdev->stop = netdev_close;
+ pnetdev->hard_start_xmit = rtw_xmit_entry;
+ pnetdev->set_mac_address = rtw_net_set_mac_address;
+ pnetdev->get_stats = rtw_net_get_stats;
+ pnetdev->do_ioctl = rtw_ioctl;
+#endif
+
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
+ pnetdev->features |= NETIF_F_IP_CSUM;
+#endif
+ //pnetdev->tx_timeout = NULL;
+ pnetdev->watchdog_timeo = HZ*3; /* 3 second timeout */
+ pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def;
+
+#ifdef WIRELESS_SPY
+ //priv->wireless_data.spy_data = &priv->spy_data;
+ //pnetdev->wireless_data = &priv->wireless_data;
+#endif
+
+ //step 2.
+ loadparam(padapter, pnetdev);
+
+ return pnetdev;
+
+}
+
+u32 rtw_start_drv_threads(_adapter *padapter)
+{
+
+ u32 _status = _SUCCESS;
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("+rtw_start_drv_threads\n"));
+#ifdef CONFIG_XMIT_THREAD_MODE
+ padapter->xmitThread = kernel_thread(rtw_xmit_thread, padapter, CLONE_FS|CLONE_FILES);
+ if(padapter->xmitThread < 0)
+ _status = _FAIL;
+#endif
+
+#ifdef CONFIG_RECV_THREAD_MODE
+ padapter->recvThread = kernel_thread(rtw_recv_thread, padapter, CLONE_FS|CLONE_FILES);
+ if(padapter->recvThread < 0)
+ _status = _FAIL;
+#endif
+
+ padapter->cmdThread = kernel_thread(rtw_cmd_thread, padapter, CLONE_FS|CLONE_FILES);
+ if(padapter->cmdThread < 0)
+ _status = _FAIL;
+ else
+ _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); //wait for cmd_thread to run
+
+
+#ifdef CONFIG_EVENT_THREAD_MODE
+ padapter->evtThread = kernel_thread(event_thread, padapter, CLONE_FS|CLONE_FILES);
+ if(padapter->evtThread < 0)
+ _status = _FAIL;
+#endif
+
+ return _status;
+
+}
+
+void rtw_stop_drv_threads (_adapter *padapter)
+{
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("+rtw_stop_drv_threads\n"));
+
+ //Below is to termindate rtw_cmd_thread & event_thread...
+ _rtw_up_sema(&padapter->cmdpriv.cmd_queue_sema);
+ //_rtw_up_sema(&padapter->cmdpriv.cmd_done_sema);
+ if(padapter->cmdThread){
+ _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema);
+ }
+
+#ifdef CONFIG_EVENT_THREAD_MODE
+ _rtw_up_sema(&padapter->evtpriv.evt_notify);
+ if(padapter->evtThread){
+ _rtw_down_sema(&padapter->evtpriv.terminate_evtthread_sema);
+ }
+#endif
+
+#ifdef CONFIG_XMIT_THREAD_MODE
+ // Below is to termindate tx_thread...
+ _rtw_up_sema(&padapter->xmitpriv.xmit_sema);
+ _rtw_down_sema(&padapter->xmitpriv.terminate_xmitthread_sema);
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("\n drv_halt: rtw_xmit_thread can be terminated ! \n"));
+#endif
+
+#ifdef CONFIG_RECV_THREAD_MODE
+ // Below is to termindate rx_thread...
+ _rtw_up_sema(&padapter->recvpriv.recv_sema);
+ _rtw_down_sema(&padapter->recvpriv.terminate_recvthread_sema);
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("\n drv_halt:recv_thread can be terminated! \n"));
+#endif
+
+
+}
+
+u8 rtw_init_default_value(_adapter *padapter);
+u8 rtw_init_default_value(_adapter *padapter)
+{
+ u8 ret = _SUCCESS;
+ struct registry_priv* pregistrypriv = &padapter->registrypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv= &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ //xmit_priv
+ pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
+ pxmitpriv->vcs = pregistrypriv->vcs_type;
+ pxmitpriv->vcs_type = pregistrypriv->vcs_type;
+ //pxmitpriv->rts_thresh = pregistrypriv->rts_thresh;
+ pxmitpriv->frag_len = pregistrypriv->frag_thresh;
+
+
+
+ //recv_priv
+
+
+ //mlme_priv
+ pmlmepriv->scan_interval = SCAN_INTERVAL;// 30*2 sec = 60sec
+ pmlmepriv->scan_mode = SCAN_ACTIVE;
+
+ //qos_priv
+ //pmlmepriv->qospriv.qos_option = pregistrypriv->wmm_enable;
+
+ //ht_priv
+#ifdef CONFIG_80211N_HT
+ pmlmepriv->htpriv.ampdu_enable = _FALSE;//set to disabled
+#endif
+
+ //security_priv
+ //rtw_get_encrypt_decrypt_from_registrypriv(padapter);
+ psecuritypriv->binstallGrpkey = _FAIL;
+ psecuritypriv->sw_encrypt=pregistrypriv->software_encrypt;
+ psecuritypriv->sw_decrypt=pregistrypriv->software_decrypt;
+
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; //open system
+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+
+ psecuritypriv->dot11PrivacyKeyIndex = 0;
+
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ psecuritypriv->dot118021XGrpKeyid = 1;
+
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled;
+
+
+ //pwrctrl_priv
+
+
+ //registry_priv
+ rtw_init_registrypriv_dev_network(padapter);
+ rtw_update_registrypriv_dev_network(padapter);
+
+
+ //hal_priv
+ padapter->HalFunc.init_default_value(padapter);
+
+ //misc.
+ padapter->bReadPortCancel = _FALSE;
+ padapter->bWritePortCancel = _FALSE;
+ padapter->bRxRSSIDisplay = 0;
+
+ return ret;
+}
+
+u8 rtw_reset_drv_sw(_adapter *padapter)
+{
+ u8 ret8=_SUCCESS;
+ struct mlme_priv *pmlmepriv= &padapter->mlmepriv;
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ //hal_priv
+ padapter->HalFunc.init_default_value(padapter);
+ padapter->bReadPortCancel = _FALSE;
+ padapter->bWritePortCancel = _FALSE;
+ padapter->bRxRSSIDisplay = 0;
+ pmlmepriv->scan_interval = SCAN_INTERVAL;// 30*2 sec = 60sec
+
+ pwrctrlpriv->bips_processing = _FALSE;
+ pwrctrlpriv->rf_pwrstate = rf_on;
+ pwrctrlpriv->bInSuspend = _FALSE;
+
+ padapter->xmitpriv.tx_pkts = 0;
+ padapter->recvpriv.rx_pkts = 0;
+
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY |_FW_UNDER_LINKING);
+
+#ifdef CONFIG_AUTOSUSPEND
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
+ padapter->dvobjpriv.pusbdev->autosuspend_disabled = 1;//autosuspend disabled by the user
+ #endif
+#endif
+
+#ifdef DBG_CONFIG_ERROR_DETECT
+ rtw_hal_sreset_reset_value(padapter);
+#endif
+ pwrctrlpriv->pwr_state_check_cnts = 0;
+
+ //mlmeextpriv
+ padapter->mlmeextpriv.sitesurvey_res.state= SCAN_DISABLE;
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+ rtw_set_signal_stat_timer(&padapter->recvpriv);
+#endif
+
+ return ret8;
+}
+
+
+u8 rtw_init_drv_sw(_adapter *padapter)
+{
+
+ u8 ret8=_SUCCESS;
+
+_func_enter_;
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("+rtw_init_drv_sw\n"));
+
+ if ((rtw_init_cmd_priv(&padapter->cmdpriv)) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("\n Can't init cmd_priv\n"));
+ ret8=_FAIL;
+ goto exit;
+ }
+
+ padapter->cmdpriv.padapter=padapter;
+
+ if ((rtw_init_evt_priv(&padapter->evtpriv)) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("\n Can't init evt_priv\n"));
+ ret8=_FAIL;
+ goto exit;
+ }
+
+
+ if (rtw_init_mlme_priv(padapter) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("\n Can't init mlme_priv\n"));
+ ret8=_FAIL;
+ goto exit;
+ }
+
+#ifdef CONFIG_IOCTL_CFG80211
+#ifdef CONFIG_P2P
+ rtw_init_cfg80211_wifidirect_info(padapter);
+#endif //CONFIG_P2P
+#endif //CONFIG_IOCTL_CFG80211
+
+ if(init_mlme_ext_priv(padapter) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("\n Can't init mlme_ext_priv\n"));
+ ret8=_FAIL;
+ goto exit;
+ }
+
+#ifdef CONFIG_TDLS
+ if(rtw_init_tdls_info(padapter) == _FAIL)
+ {
+ DBG_871X("Can't rtw_init_tdls_info\n");
+ ret8=_FAIL;
+ goto exit;
+ }
+#endif //CONFIG_TDLS
+
+ if(_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL)
+ {
+ DBG_871X("Can't _rtw_init_xmit_priv\n");
+ ret8=_FAIL;
+ goto exit;
+ }
+
+ if(_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL)
+ {
+ DBG_871X("Can't _rtw_init_recv_priv\n");
+ ret8=_FAIL;
+ goto exit;
+ }
+
+ // We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
+ //_rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));
+
+ //_init_timer(&(padapter->securitypriv.tkip_timer), padapter->pifp, rtw_use_tkipkey_handler, padapter);
+
+ if(_rtw_init_sta_priv(&padapter->stapriv) == _FAIL)
+ {
+ DBG_871X("Can't _rtw_init_sta_priv\n");
+ ret8=_FAIL;
+ goto exit;
+ }
+
+ padapter->stapriv.padapter = padapter;
+
+ rtw_init_bcmc_stainfo(padapter);
+
+ rtw_init_pwrctrl_priv(padapter);
+
+ //_rtw_memset((u8 *)&padapter->qospriv, 0, sizeof (struct qos_priv));//move to mlme_priv
+
+#ifdef CONFIG_MP_INCLUDED
+ if (init_mp_priv(padapter) == _FAIL) {
+ DBG_871X("%s: initialize MP private data Fail!\n", __func__);
+ }
+#endif
+
+ ret8 = rtw_init_default_value(padapter);
+
+ rtw_dm_init(padapter);
+ rtw_sw_led_init(padapter);
+
+#ifdef DBG_CONFIG_ERROR_DETECT
+ rtw_hal_sreset_init(padapter);
+#endif
+
+#ifdef CONFIG_INTEL_WIDI
+ if(rtw_init_intel_widi(padapter) == _FAIL)
+ {
+ DBG_871X("Can't rtw_init_intel_widi\n");
+ ret8=_FAIL;
+ goto exit;
+ }
+#endif //CONFIG_INTEL_WIDI
+
+#ifdef CONFIG_BR_EXT
+ _rtw_spinlock_init(&padapter->br_ext_lock);
+#endif // CONFIG_BR_EXT
+
+exit:
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("-rtw_init_drv_sw\n"));
+
+ _func_exit_;
+
+ return ret8;
+
+}
+
+void rtw_cancel_all_timer(_adapter *padapter)
+{
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("+rtw_cancel_all_timer\n"));
+
+ _cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("rtw_cancel_all_timer:cancel association timer complete! \n"));
+
+ //_cancel_timer_ex(&padapter->securitypriv.tkip_timer);
+ //RT_TRACE(_module_os_intfs_c_,_drv_info_,("rtw_cancel_all_timer:cancel tkip_timer! \n"));
+
+ _cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("rtw_cancel_all_timer:cancel scan_to_timer! \n"));
+
+ _cancel_timer_ex(&padapter->mlmepriv.dynamic_chk_timer);
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("rtw_cancel_all_timer:cancel dynamic_chk_timer! \n"));
+
+ // cancel sw led timer
+ rtw_sw_led_deinit(padapter);
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("rtw_cancel_all_timer:cancel DeInitSwLeds! \n"));
+
+ _cancel_timer_ex(&padapter->pwrctrlpriv.pwr_state_check_timer);
+
+#ifdef CONFIG_IOCTL_CFG80211
+#ifdef CONFIG_P2P
+ _cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
+#endif //CONFIG_P2P
+#endif //CONFIG_IOCTL_CFG80211
+
+#ifdef CONFIG_SET_SCAN_DENY_TIMER
+ _cancel_timer_ex(&padapter->mlmepriv.set_scan_deny_timer);
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("rtw_cancel_all_timer:cancel set_scan_deny_timer! \n"));
+#endif
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+ _cancel_timer_ex(&padapter->recvpriv.signal_stat_timer);
+#endif
+
+ // cancel dm timer
+ padapter->HalFunc.dm_deinit(padapter);
+
+}
+
+u8 rtw_free_drv_sw(_adapter *padapter)
+{
+ struct net_device *pnetdev = (struct net_device*)padapter->pnetdev;
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("==>rtw_free_drv_sw"));
+
+
+ //we can call rtw_p2p_enable here, but:
+ // 1. rtw_p2p_enable may have IO operation
+ // 2. rtw_p2p_enable is bundled with wext interface
+ #ifdef CONFIG_P2P
+ {
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ _cancel_timer_ex( &pwdinfo->find_phase_timer );
+ _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+ _cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
+ }
+ }
+ #endif
+
+
+#ifdef CONFIG_BR_EXT
+ _rtw_spinlock_free(&padapter->br_ext_lock);
+#endif // CONFIG_BR_EXT
+
+#ifdef CONFIG_INTEL_WIDI
+ rtw_free_intel_widi(padapter);
+#endif //CONFIG_INTEL_WIDI
+
+ free_mlme_ext_priv(&padapter->mlmeextpriv);
+
+#ifdef CONFIG_TDLS
+ //rtw_free_tdls_info(&padapter->tdlsinfo);
+#endif //CONFIG_TDLS
+
+ rtw_free_cmd_priv(&padapter->cmdpriv);
+
+ rtw_free_evt_priv(&padapter->evtpriv);
+
+ rtw_free_mlme_priv(&padapter->mlmepriv);
+
+ //free_io_queue(padapter);
+
+ _rtw_free_xmit_priv(&padapter->xmitpriv);
+
+ _rtw_free_sta_priv(&padapter->stapriv); //will free bcmc_stainfo here
+
+ _rtw_free_recv_priv(&padapter->recvpriv);
+
+ rtw_free_pwrctrl_priv(padapter);
+
+ //rtw_mfree((void *)padapter, sizeof (padapter));
+
+#ifdef CONFIG_DRVEXT_MODULE
+ free_drvext(&padapter->drvextpriv);
+#endif
+
+ padapter->HalFunc.free_hal_data(padapter);
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("<==rtw_free_drv_sw\n"));
+
+ //free the old_pnetdev
+ if(padapter->rereg_nd_name_priv.old_pnetdev) {
+ free_netdev(padapter->rereg_nd_name_priv.old_pnetdev);
+ padapter->rereg_nd_name_priv.old_pnetdev = NULL;
+ }
+
+#ifdef CONFIG_DUALMAC_CONCURRENT
+ // clear pbuddy_adapter to avoid access wrong pointer.
+ if(padapter->pbuddy_adapter != NULL)
+ {
+ padapter->pbuddy_adapter->pbuddy_adapter = NULL;
+ }
+#endif
+
+ if(pnetdev)
+ {
+ rtw_free_netdev(pnetdev);
+ }
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("-rtw_free_drv_sw\n"));
+
+ return _SUCCESS;
+
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+int _netdev_if2_open(struct net_device *pnetdev)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+ _adapter *primary_padapter = padapter->pbuddy_adapter;
+
+ DBG_871X("+871x_drv - if2_open, bup=%d\n", padapter->bup);
+
+ if(primary_padapter->bup == _FALSE || primary_padapter->hw_init_completed == _FALSE)
+ {
+ _netdev_open(primary_padapter->pnetdev);
+ }
+
+ if(padapter->bup == _FALSE && primary_padapter->bup == _TRUE &&
+ primary_padapter->hw_init_completed == _TRUE)
+ {
+ int i;
+
+ padapter->bDriverStopped = _FALSE;
+ padapter->bSurpriseRemoved = _FALSE;
+ padapter->bCardDisableWOHSM = _FALSE;
+
+
+ _rtw_memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
+
+
+ _rtw_memcpy(padapter->HalData, primary_padapter->HalData, padapter->hal_data_sz);
+
+ padapter->bFWReady = primary_padapter->bFWReady;
+
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_DM_INIT_PWDB, NULL);
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MAC_ADDR, pnetdev->dev_addr);
+
+ //if (init_mlme_ext_priv(padapter) == _FAIL)
+ // goto netdev_if2_open_error;
+
+
+ if(rtw_start_drv_threads(padapter) == _FAIL)
+ {
+ goto netdev_if2_open_error;
+ }
+
+
+ if(padapter->intf_start)
+ {
+ padapter->intf_start(padapter);
+ }
+
+
+ padapter->hw_init_completed = _TRUE;
+
+
+#ifdef CONFIG_PROC_DEBUG
+ padapter->dir_dev = NULL;
+ rtw_proc_init_one(pnetdev);
+#endif
+
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_cfg80211_init_wiphy(padapter);
+#endif
+
+ padapter->bup = _TRUE;
+
+ }
+
+ padapter->net_closed = _FALSE;
+
+ _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);
+
+ if(!rtw_netif_queue_stopped(pnetdev))
+ rtw_netif_start_queue(pnetdev);
+ else
+ rtw_netif_wake_queue(pnetdev);
+
+#ifdef CONFIG_P2P
+ init_wifidirect_info( padapter, P2P_ROLE_DISABLE );
+ reset_global_wifidirect_info( padapter );
+#ifdef CONFIG_WFD
+ if(rtw_init_wifi_display_info(padapter) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("\n Can't init init_wifi_display_info\n"));
+
+ goto netdev_if2_open_error;
+ }
+#endif //CONFIG_WFD
+#endif // CONFIG_P2P
+
+ DBG_871X("-871x_drv - if2_open, bup=%d\n", padapter->bup);
+ return 0;
+
+netdev_if2_open_error:
+
+ padapter->bup = _FALSE;
+
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+
+ return (-1);
+
+}
+
+int netdev_if2_open(struct net_device *pnetdev)
+{
+ int ret;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+
+ _enter_critical_mutex(padapter->hw_init_mutex, NULL);
+ ret = _netdev_if2_open(pnetdev);
+ _exit_critical_mutex(padapter->hw_init_mutex, NULL);
+ return ret;
+}
+
+static int netdev_if2_close(struct net_device *pnetdev)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+
+ padapter->net_closed = _TRUE;
+
+ if(pnetdev)
+ {
+ if (!rtw_netif_queue_stopped(pnetdev))
+ rtw_netif_stop_queue(pnetdev);
+ }
+
+#ifdef CONFIG_IOCTL_CFG80211
+ DBG_871X("call rtw_cfg80211_scan_abort when netdev_if2_close\n");
+ rtw_cfg80211_scan_abort(padapter);
+ wdev_to_priv(padapter->rtw_wdev)->bandroid_scan = _FALSE;
+#endif
+
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+static const struct net_device_ops rtw_netdev_if2_ops = {
+ .ndo_open = netdev_if2_open,
+ .ndo_stop = netdev_if2_close,
+ .ndo_start_xmit = rtw_xmit_entry,
+ .ndo_set_mac_address = rtw_net_set_mac_address,
+ .ndo_get_stats = rtw_net_get_stats,
+ .ndo_do_ioctl = rtw_ioctl,
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+ .ndo_select_queue = rtw_select_queue,
+#endif
+};
+#endif
+
+
+#ifdef CONFIG_USB_HCI
+ #include <usb_hal.h>
+#endif
+
+struct net_device *rtw_drv_if2_init(_adapter *primary_padapter, char *name)
+{
+ int res = _FAIL;
+ struct net_device *pnetdev;
+ _adapter *padapter = NULL;
+ struct dvobj_priv *pdvobjpriv;
+ u8 mac[ETH_ALEN];
+#ifdef CONFIG_USB_HCI
+ struct usb_interface *pusb_intf;
+ struct usb_device *pusbdev;
+#endif
+
+ pnetdev = rtw_init_netdev(NULL);
+ if (!pnetdev)
+ goto error_rtw_drv_if2_init;
+
+ //
+ padapter = rtw_netdev_priv(pnetdev);
+
+ //
+ _rtw_memcpy(padapter, primary_padapter, sizeof(_adapter));
+ padapter->ph2c_fwcmd_mutex = primary_padapter->ph2c_fwcmd_mutex;
+ padapter->psetch_mutex = primary_padapter->psetch_mutex;
+ padapter->psetbw_mutex = primary_padapter->psetbw_mutex;
+ padapter->hw_init_mutex = primary_padapter->hw_init_mutex;
+
+ //
+ padapter->bup = _FALSE;
+ padapter->net_closed = _TRUE;
+ padapter->hw_init_completed = _FALSE;
+
+
+ //
+ padapter->pnetdev = pnetdev;
+
+ //
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
+ printk("register rtw_netdev_if2_ops to netdev_ops\n");
+ pnetdev->netdev_ops = &rtw_netdev_if2_ops;
+#else
+ pnetdev->open = netdev_if2_open;
+ pnetdev->stop = netdev_if2_close;
+#endif
+
+
+#ifdef CONFIG_NO_WIRELESS_HANDLERS
+ pnetdev->wireless_handlers = NULL;
+#endif
+
+ pdvobjpriv = &padapter->dvobjpriv;
+ pdvobjpriv->padapter = padapter;
+
+
+ //set adapter_type/iface type
+ padapter->isprimary = _FALSE;
+ padapter->adapter_type = SECONDARY_ADAPTER;
+
+ padapter->iface_type = IFACE_PORT0;//
+ //padapter->iface_type = IFACE_PORT1;//
+
+ padapter->pbuddy_adapter = primary_padapter;
+
+#ifdef CONFIG_USB_HCI
+ pusb_intf = primary_padapter->dvobjpriv.pusbintf;
+ pusbdev = primary_padapter->dvobjpriv.pusbdev;
+
+ SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
+ pdvobjpriv->pusbintf = pusb_intf ;
+ pdvobjpriv->pusbdev = pusbdev;
+ //pdvobjpriv->pusbdev = interface_to_usbdev(pusb_intf);
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_wdev_alloc(padapter, &pusb_intf->dev);
+#endif //CONFIG_IOCTL_CFG80211
+#endif //CONFIG_USB_HCI
+
+#if defined(CONFIG_IOCTL_CFG80211)&&defined(CONFIG_PCI_HCI)
+ SET_NETDEV_DEV(pnetdev, &(pdvobjpriv->ppcidev->dev));
+ rtw_wdev_alloc(padapter, &(pdvobjpriv->ppcidev->dev));
+#endif //CONFIG_IOCTL_CFG80211
+
+
+ //set interface_type/chip_type/HardwareType
+ padapter->interface_type = primary_padapter->interface_type;
+ padapter->chip_type = primary_padapter->chip_type;
+ padapter->HardwareType = primary_padapter->HardwareType;
+
+
+ //set hal data & hal ops
+ if(padapter->chip_type == RTL8188C_8192C)
+ {
+#ifdef CONFIG_RTL8192C
+#ifdef CONFIG_PCI_HCI
+ rtl8192ce_set_hal_ops(padapter);
+#else
+ rtl8192cu_set_hal_ops(padapter);
+#endif
+#endif
+ }
+ else if(padapter->chip_type == RTL8192D)
+ {
+#ifdef CONFIG_RTL8192D
+ rtl8192du_set_hal_ops(padapter);
+#endif
+ }
+
+ padapter->HalFunc.inirp_init = NULL;
+ padapter->HalFunc.inirp_deinit = NULL;
+
+
+ //
+ padapter->dvobj_init = primary_padapter->dvobj_init;
+ padapter->dvobj_deinit = primary_padapter->dvobj_deinit;
+ padapter->intf_start = primary_padapter->intf_start;
+ padapter->intf_stop = primary_padapter->intf_stop;
+
+ //initialize the dvobj_priv
+ if(padapter->dvobj_init(padapter) != _SUCCESS)
+ goto error_rtw_drv_if2_init;
+
+
+ //init drv data
+ if(rtw_init_drv_sw(padapter)!= _SUCCESS)
+ goto error_rtw_drv_if2_init;
+
+
+ // alloc dev name after got efuse data.
+ if(name == NULL)
+ name = padapter->registrypriv.if2name;
+
+ rtw_init_netdev_name(pnetdev, name);
+
+ //get mac address from primary_padapter
+ _rtw_memcpy(mac, primary_padapter->eeprompriv.mac_addr, ETH_ALEN);
+
+ if (((mac[0]==0xff) &&(mac[1]==0xff) && (mac[2]==0xff) &&
+ (mac[3]==0xff) && (mac[4]==0xff) &&(mac[5]==0xff)) ||
+ ((mac[0]==0x0) && (mac[1]==0x0) && (mac[2]==0x0) &&
+ (mac[3]==0x0) && (mac[4]==0x0) &&(mac[5]==0x0)))
+ {
+ mac[0] = 0x00;
+ mac[1] = 0xe0;
+ mac[2] = 0x4c;
+ mac[3] = 0x87;
+ mac[4] = 0x11;
+ mac[5] = 0x22;
+ }
+ else
+ {
+ //If the BIT1 is 0, the address is universally administered.
+ //If it is 1, the address is locally administered
+ mac[0] |= BIT(1); // locally administered
+
+ }
+
+ _rtw_memcpy(padapter->eeprompriv.mac_addr, mac, ETH_ALEN);
+
+ _rtw_memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
+
+ printk("MAC Address (if2) = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+
+ primary_padapter->pbuddy_adapter = padapter;
+
+ //set adapter_type/iface type for primary padapter
+ primary_padapter->isprimary = _TRUE;
+ primary_padapter->adapter_type = PRIMARY_ADAPTER;
+ //primary_padapter->iface_type = IFACE_PORT0;//
+ primary_padapter->iface_type = IFACE_PORT1;//
+
+
+ //prepare concurrent shared data buffer
+ if(!primary_padapter->pcodatapriv)
+ {
+ struct co_data_priv *pcodatapriv;
+
+ pcodatapriv = (struct co_data_priv*)rtw_zvmalloc(sizeof(struct co_data_priv));
+
+ primary_padapter->pcodatapriv = pcodatapriv;
+ padapter->pcodatapriv = pcodatapriv;
+
+ //concurrent shared data init.
+ pcodatapriv->co_ch = rtw_channel;
+ pcodatapriv->co_bw = HT_CHANNEL_WIDTH_20;
+ pcodatapriv->co_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ }
+
+ /* Tell the network stack we exist */
+ if (register_netdev(pnetdev) != 0)
+ {
+ goto error_rtw_drv_if2_init;
+ }
+
+ res = _SUCCESS;
+
+ //return res;
+ return pnetdev;
+
+
+error_rtw_drv_if2_init:
+
+ padapter->dvobj_deinit(padapter);
+
+ //if(padapter->HalData)
+ // rtw_mfree(padapter->HalData, sizeof(HAL_DATA_TYPE));
+
+ rtw_free_drv_sw(padapter);
+
+ //return res;
+ return NULL;
+
+}
+
+void rtw_drv_if2_free(_adapter *primary_padapter)
+{
+ _adapter *padapter=NULL;
+ struct net_device *pnetdev=NULL;
+#ifdef CONFIG_IOCTL_CFG80211
+ struct wireless_dev *wdev;
+#endif //CONFIG_IOCTL_CFG80211
+
+ if(primary_padapter && primary_padapter->adapter_type == PRIMARY_ADAPTER)
+ {
+ padapter = primary_padapter->pbuddy_adapter;
+ //pnetdev = padapter->pnetdev;
+ }
+
+ if(padapter==NULL)
+ return;
+
+ //primary_padapter->pbuddy_adapter = NULL;
+
+ pnetdev = padapter->pnetdev;
+
+#ifdef CONFIG_IOCTL_CFG80211
+ wdev = padapter->rtw_wdev;
+#endif //CONFIG_IOCTL_CFG80211
+
+ if(pnetdev)
+ {
+ unregister_netdev(pnetdev); //will call netdev_close()
+
+#ifdef CONFIG_PROC_DEBUG
+ if(padapter->bup == _TRUE)
+ rtw_proc_remove_one(pnetdev);
+#endif
+
+ }
+
+ rtw_cancel_all_timer(padapter);
+
+ if(padapter->bup == _TRUE)
+ {
+ padapter->bDriverStopped = _TRUE;
+
+ if(padapter->intf_stop)
+ {
+ padapter->intf_stop(padapter);
+ }
+
+ rtw_stop_drv_threads(padapter);
+
+ if(padapter->dvobj_deinit)
+ {
+ padapter->dvobj_deinit(padapter);
+ }
+
+ padapter->bup = _FALSE;
+ }
+
+ primary_padapter->pbuddy_adapter = NULL;
+
+ padapter->pcodatapriv = NULL;
+
+ rtw_free_drv_sw(padapter);
+
+
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_wdev_free(wdev);
+#endif //CONFIG_IOCTL_CFG80211
+
+ //free concurrent shared data buffer
+ if(primary_padapter->pcodatapriv)
+ {
+ rtw_vmfree((u8*)primary_padapter->pcodatapriv, sizeof(struct co_data_priv));
+
+ primary_padapter->pcodatapriv = NULL;
+ }
+
+}
+#endif //end of CONFIG_CONCURRENT_MODE
+
+#ifdef CONFIG_BR_EXT
+void netdev_br_init(struct net_device *netdev)
+{
+ _adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+ rcu_read_lock();
+#endif // (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+
+ //if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE)
+ {
+ //struct net_bridge *br = netdev->br_port->br;//->dev->dev_addr;
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+ if (netdev->br_port)
+#else // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+ if (rcu_dereference(adapter->pnetdev->rx_handler_data))
+#endif // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+ {
+ struct net_device *br_netdev;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+ br_netdev = dev_get_by_name(CONFIG_BR_EXT_BRNAME);
+#else // (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+ struct net *devnet = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
+ devnet = netdev->nd_net;
+#else // (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
+ devnet = dev_net(netdev);
+#endif // (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
+
+ br_netdev = dev_get_by_name(devnet, CONFIG_BR_EXT_BRNAME);
+#endif // (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+
+ if (br_netdev) {
+ memcpy(adapter->br_mac, br_netdev->dev_addr, ETH_ALEN);
+ dev_put(br_netdev);
+ } else
+ printk("%s()-%d: dev_get_by_name(%s) failed!", __FUNCTION__, __LINE__, CONFIG_BR_EXT_BRNAME);
+ }
+
+ adapter->ethBrExtInfo.addPPPoETag = 1;
+ }
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+ rcu_read_unlock();
+#endif // (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+}
+#endif //CONFIG_BR_EXT
+
+int _netdev_open(struct net_device *pnetdev)
+{
+ uint status;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("+871x_drv - dev_open\n"));
+ DBG_871X("+871x_drv - drv_open, bup=%d\n", padapter->bup);
+
+ if(pwrctrlpriv->ps_flag == _TRUE){
+ padapter->net_closed = _FALSE;
+ goto netdev_open_normal_process;
+ }
+
+ if(padapter->bup == _FALSE)
+ {
+ padapter->bDriverStopped = _FALSE;
+ padapter->bSurpriseRemoved = _FALSE;
+ padapter->bCardDisableWOHSM = _FALSE;
+
+ status = rtw_hal_init(padapter);
+ if (status ==_FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("rtl871x_hal_init(): Can't init h/w!\n"));
+ goto netdev_open_error;
+ }
+
+ DBG_871X("MAC Address = "MAC_FMT"\n", MAC_ARG(pnetdev->dev_addr));
+
+
+ status=rtw_start_drv_threads(padapter);
+ if(status ==_FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("Initialize driver software resource Failed!\n"));
+ goto netdev_open_error;
+ }
+
+
+ if (init_hw_mlme_ext(padapter) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("can't init mlme_ext_priv\n"));
+ goto netdev_open_error;
+ }
+
+
+#ifdef CONFIG_DRVEXT_MODULE
+ init_drvext(padapter);
+#endif
+
+ if(padapter->intf_start)
+ {
+ padapter->intf_start(padapter);
+ }
+
+#ifdef CONFIG_PROC_DEBUG
+#ifndef RTK_DMP_PLATFORM
+ rtw_proc_init_one(pnetdev);
+#endif
+#endif
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_cfg80211_init_wiphy(padapter);
+#endif
+
+ rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+ padapter->bup = _TRUE;
+ }
+ padapter->net_closed = _FALSE;
+
+ _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);
+
+ if(( pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE ) ||(padapter->pwrctrlpriv.bHWPwrPindetect))
+ {
+ padapter->pwrctrlpriv.bips_processing = _FALSE;
+ rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
+ }
+
+ //netif_carrier_on(pnetdev);//call this func when rtw_joinbss_event_callback return success
+ if(!rtw_netif_queue_stopped(pnetdev))
+ rtw_netif_start_queue(pnetdev);
+ else
+ rtw_netif_wake_queue(pnetdev);
+
+#ifdef CONFIG_BR_EXT
+ netdev_br_init(pnetdev);
+#endif // CONFIG_BR_EXT
+
+#ifdef CONFIG_P2P
+ init_wifidirect_info( padapter, P2P_ROLE_DISABLE );
+ reset_global_wifidirect_info( padapter );
+#ifdef CONFIG_WFD
+ if(rtw_init_wifi_display_info(padapter) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("\n Can't init init_wifi_display_info\n"));
+
+ goto netdev_open_error;
+ }
+#endif //CONFIG_WFD
+#endif // CONFIG_P2P
+
+netdev_open_normal_process:
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("-871x_drv - dev_open\n"));
+ DBG_871X("-871x_drv - drv_open, bup=%d\n", padapter->bup);
+
+ return 0;
+
+netdev_open_error:
+
+ padapter->bup = _FALSE;
+
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("-871x_drv - dev_open, fail!\n"));
+ DBG_871X("-871x_drv - drv_open fail, bup=%d\n", padapter->bup);
+
+ return (-1);
+
+}
+
+int netdev_open(struct net_device *pnetdev)
+{
+ int ret;
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+
+ _enter_critical_mutex(padapter->hw_init_mutex, NULL);
+ ret = _netdev_open(pnetdev);
+ _exit_critical_mutex(padapter->hw_init_mutex, NULL);
+
+ return ret;
+}
+
+#ifdef CONFIG_IPS
+int ips_netdrv_open(_adapter *padapter)
+{
+ int status = _SUCCESS;
+ padapter->net_closed = _FALSE;
+ DBG_871X("===> %s.........\n",__FUNCTION__);
+
+
+ padapter->bDriverStopped = _FALSE;
+ padapter->bSurpriseRemoved = _FALSE;
+ padapter->bCardDisableWOHSM = _FALSE;
+ padapter->bup = _TRUE;
+
+ status = rtw_hal_init(padapter);
+ if (status ==_FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("ips_netdrv_open(): Can't init h/w!\n"));
+ goto netdev_open_error;
+ }
+
+ if(padapter->intf_start)
+ {
+ padapter->intf_start(padapter);
+ }
+
+ rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
+ _set_timer(&padapter->mlmepriv.dynamic_chk_timer,5000);
+
+ return _SUCCESS;
+
+netdev_open_error:
+ padapter->bup = _FALSE;
+ DBG_871X("-ips_netdrv_open - drv_open failure, bup=%d\n", padapter->bup);
+
+ return _FAIL;
+}
+
+
+int rtw_ips_pwr_up(_adapter *padapter)
+{
+ int result;
+ u32 start_time = rtw_get_current_time();
+ DBG_871X("===> rtw_ips_pwr_up..............\n");
+ rtw_reset_drv_sw(padapter);
+ result = ips_netdrv_open(padapter);
+
+ rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+ DBG_871X("<=== rtw_ips_pwr_up.............. in %dms\n", rtw_get_passing_time_ms(start_time));
+ return result;
+
+}
+
+void rtw_ips_pwr_down(_adapter *padapter)
+{
+ u32 start_time = rtw_get_current_time();
+ DBG_871X("===> rtw_ips_pwr_down...................\n");
+
+ padapter->bCardDisableWOHSM = _TRUE;
+ padapter->net_closed = _TRUE;
+
+ rtw_led_control(padapter, LED_CTL_POWER_OFF);
+
+ rtw_ips_dev_unload(padapter);
+ padapter->bCardDisableWOHSM = _FALSE;
+ DBG_871X("<=== rtw_ips_pwr_down..................... in %dms\n", rtw_get_passing_time_ms(start_time));
+}
+#endif
+void rtw_ips_dev_unload(_adapter *padapter)
+{
+ struct net_device *pnetdev= (struct net_device*)padapter->pnetdev;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ DBG_871X("====> %s...\n",__FUNCTION__);
+
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_FIFO_CLEARN_UP, 0);
+
+ if(padapter->intf_stop)
+ {
+ padapter->intf_stop(padapter);
+ }
+
+ //s5.
+ if(padapter->bSurpriseRemoved == _FALSE)
+ {
+ rtw_hal_deinit(padapter);
+ }
+
+}
+
+int pm_netdev_open(struct net_device *pnetdev,u8 bnormal)
+{
+ int status;
+ if(bnormal)
+ status = netdev_open(pnetdev);
+#ifdef CONFIG_IPS
+ else
+ status = (_SUCCESS == ips_netdrv_open((_adapter *)rtw_netdev_priv(pnetdev)))?(0):(-1);
+#endif
+
+ return status;
+}
+
+static int netdev_close(struct net_device *pnetdev)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("+871x_drv - drv_close\n"));
+
+ if(padapter->pwrctrlpriv.bInternalAutoSuspend == _TRUE)
+ {
+ //rtw_pwr_wakeup(padapter);
+ if(padapter->pwrctrlpriv.rf_pwrstate == rf_off)
+ padapter->pwrctrlpriv.ps_flag = _TRUE;
+ }
+ padapter->net_closed = _TRUE;
+
+/* if(!padapter->hw_init_completed)
+ {
+ DBG_871X("(1)871x_drv - drv_close, bup=%d, hw_init_completed=%d\n", padapter->bup, padapter->hw_init_completed);
+
+ padapter->bDriverStopped = _TRUE;
+
+ rtw_dev_unload(padapter);
+ }
+ else*/
+ if(padapter->pwrctrlpriv.rf_pwrstate == rf_on){
+ DBG_871X("(2)871x_drv - drv_close, bup=%d, hw_init_completed=%d\n", padapter->bup, padapter->hw_init_completed);
+
+ //s1.
+ if(pnetdev)
+ {
+ if (!rtw_netif_queue_stopped(pnetdev))
+ rtw_netif_stop_queue(pnetdev);
+ }
+
+#ifndef CONFIG_ANDROID
+ //s2.
+ //s2-1. issue rtw_disassoc_cmd to fw
+ rtw_disassoc_cmd(padapter);
+ //s2-2. indicate disconnect to os
+ rtw_indicate_disconnect(padapter);
+ //s2-3.
+ rtw_free_assoc_resources(padapter, 1);
+ //s2-4.
+ rtw_free_network_queue(padapter,_TRUE);
+#endif
+ // Close LED
+ rtw_led_control(padapter, LED_CTL_POWER_OFF);
+ }
+
+#ifdef CONFIG_BR_EXT
+ //if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE))
+ {
+ //void nat25_db_cleanup(_adapter *priv);
+ nat25_db_cleanup(padapter);
+ }
+#endif // CONFIG_BR_EXT
+
+#ifdef CONFIG_P2P
+ #ifdef CONFIG_IOCTL_CFG80211
+ if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == _TRUE)
+ wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = _FALSE;
+ #endif
+ rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
+#endif //CONFIG_P2P
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_cfg80211_scan_abort(padapter);
+ wdev_to_priv(padapter->rtw_wdev)->bandroid_scan = _FALSE;
+ padapter->rtw_wdev->iftype = NL80211_IFTYPE_MONITOR; //set this at the end
+#endif //CONFIG_IOCTL_CFG80211
+
+ RT_TRACE(_module_os_intfs_c_,_drv_info_,("-871x_drv - drv_close\n"));
+ DBG_871X("-871x_drv - drv_close, bup=%d\n", padapter->bup);
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/pci_intf.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/pci_intf.c
new file mode 100755
index 000000000000..9da600eeab94
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/pci_intf.c
@@ -0,0 +1,1962 @@
+/******************************************************************************
+ *
+ * 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 _HCI_INTF_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <xmit_osdep.h>
+#include <hal_init.h>
+#include <rtw_version.h>
+
+#ifndef CONFIG_PCI_HCI
+
+#error "CONFIG_PCI_HCI shall be on!\n"
+
+#endif
+
+#include <pci_ops.h>
+#include <pci_osintf.h>
+#include <pci_hal.h>
+
+#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
+
+#error "Shall be Linux or Windows, but not both!\n"
+
+#endif
+
+#ifdef CONFIG_80211N_HT
+extern int rtw_ht_enable;
+extern int rtw_cbw40_enable;
+extern int rtw_ampdu_enable;//for enable tx_ampdu
+#endif
+
+#ifdef CONFIG_PM
+extern int pm_netdev_open(struct net_device *pnetdev);
+static int rtw_suspend(struct pci_dev *pdev, pm_message_t state);
+static int rtw_resume(struct pci_dev *pdev);
+#endif
+
+
+static int rtw_drv_init(struct pci_dev *pdev, const struct pci_device_id *pdid);
+static void rtw_dev_remove(struct pci_dev *pdev);
+
+static struct specific_device_id specific_device_id_tbl[] = {
+ {.idVendor=0x0b05, .idProduct=0x1791, .flags=SPEC_DEV_ID_DISABLE_HT},
+ {.idVendor=0x13D3, .idProduct=0x3311, .flags=SPEC_DEV_ID_DISABLE_HT},
+ {}
+};
+
+struct pci_device_id rtw_pci_id_tbl[] = {
+#ifdef CONFIG_RTL8192C
+ {PCI_DEVICE(PCI_VENDER_ID_REALTEK, 0x8191)},
+ {PCI_DEVICE(PCI_VENDER_ID_REALTEK, 0x8178)},
+ {PCI_DEVICE(PCI_VENDER_ID_REALTEK, 0x8177)},
+ {PCI_DEVICE(PCI_VENDER_ID_REALTEK, 0x8176)},
+#endif
+#ifdef CONFIG_RTL8192D
+ {PCI_DEVICE(PCI_VENDER_ID_REALTEK, 0x8193)},
+ {PCI_DEVICE(PCI_VENDER_ID_REALTEK, 0x002B)},
+#endif
+ {},
+};
+
+struct pci_drv_priv {
+ struct pci_driver rtw_pci_drv;
+ int drv_registered;
+
+ _mutex hw_init_mutex;
+#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
+ //global variable
+ _mutex h2c_fwcmd_mutex;
+ _mutex setch_mutex;
+ _mutex setbw_mutex;
+#endif
+};
+
+
+static struct pci_drv_priv pci_drvpriv = {
+ .rtw_pci_drv.name = (char*)DRV_NAME,
+ .rtw_pci_drv.probe = rtw_drv_init,
+ .rtw_pci_drv.remove = rtw_dev_remove,
+ .rtw_pci_drv.id_table = rtw_pci_id_tbl,
+#ifdef CONFIG_PM
+ .rtw_pci_drv.suspend = rtw_suspend,
+ .rtw_pci_drv.resume = rtw_resume,
+#else
+ .rtw_pci_drv.suspend = NULL,
+ .rtw_pci_drv.resume = NULL,
+#endif
+};
+
+
+MODULE_DEVICE_TABLE(pci, rtw_pci_id_tbl);
+
+
+static u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
+ INTEL_VENDOR_ID,
+ ATI_VENDOR_ID,
+ AMD_VENDOR_ID,
+ SIS_VENDOR_ID
+};
+
+static u8 rtw_pci_platform_switch_device_pci_aspm(_adapter *padapter, u8 value)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ u8 bresult = _SUCCESS;
+ int error;
+
+ value |= 0x40;
+
+ error = pci_write_config_byte(pdvobjpriv->ppcidev, 0x80, value);
+
+ if(error != 0)
+ {
+ bresult = _FALSE;
+ DBG_871X("rtw_pci_platform_switch_device_pci_aspm error (%d)\n",error);
+ }
+
+ return bresult;
+}
+
+//
+// When we set 0x01 to enable clk request. Set 0x0 to disable clk req.
+//
+static u8 rtw_pci_switch_clk_req(_adapter *padapter, u8 value)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ u8 buffer, bresult = _SUCCESS;
+ int error;
+
+ buffer = value;
+
+ if(!padapter->hw_init_completed)
+ return bresult;
+
+ error = pci_write_config_byte(pdvobjpriv->ppcidev, 0x81, value);
+
+ if(error != 0)
+ {
+ bresult = _FALSE;
+ DBG_871X("rtw_pci_switch_clk_req error (%d)\n",error);
+ }
+
+ return bresult;
+}
+
+#if 0
+//Description:
+//Disable RTL8192SE ASPM & Disable Pci Bridge ASPM
+void rtw_pci_disable_aspm(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ u32 pcicfg_addrport = 0;
+ u8 num4bytes;
+ u8 linkctrl_reg;
+ u16 pcibridge_linkctrlreg, aspmlevel = 0;
+
+ // When there exists anyone's busnum, devnum, and funcnum that are set to 0xff,
+ // we do not execute any action and return.
+ // if it is not intel bus then don't enable ASPM.
+ if ((pcipriv->busnumber == 0xff
+ && pcipriv->devnumber == 0xff
+ && pcipriv->funcnumber == 0xff)
+ || (pcipriv->pcibridge_busnum == 0xff
+ && pcipriv->pcibridge_devnum == 0xff
+ && pcipriv->pcibridge_funcnum == 0xff))
+ {
+ DBG_871X("PlatformEnableASPM(): Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n");
+ return;
+ }
+
+ if (pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) {
+ DBG_871X("%s(): Disable ASPM. Recognize the Bus of PCI(Bridge) as UNKNOWN.\n", __func__);
+ }
+
+ if (pwrpriv->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) {
+ RT_CLEAR_PS_LEVEL(pwrpriv, RT_RF_OFF_LEVL_CLK_REQ);
+ rtw_pci_switch_clk_req(padapter, 0x0);
+ }
+
+ {
+ // Suggested by SD1 for promising device will in L0 state after an I/O.
+ u8 tmp_u1b;
+
+ pci_read_config_byte(pdvobjpriv->ppcidev, 0x80, &tmp_u1b);
+ }
+
+ // Retrieve original configuration settings.
+ linkctrl_reg = pcipriv->linkctrl_reg;
+ pcibridge_linkctrlreg = pcipriv->pcibridge_linkctrlreg;
+
+ // Set corresponding value.
+ aspmlevel |= BIT(0) | BIT(1);
+ linkctrl_reg &= ~aspmlevel;
+ pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1));
+
+ rtw_pci_platform_switch_device_pci_aspm(padapter, linkctrl_reg);
+ rtw_udelay_os(50);
+
+ //When there exists anyone's busnum, devnum, and funcnum that are set to 0xff,
+ // we do not execute any action and return.
+ if ((pcipriv->busnumber == 0xff &&
+ pcipriv->devnumber == 0xff &&
+ pcipriv->funcnumber == 0xff) ||
+ (pcipriv->pcibridge_busnum == 0xff &&
+ pcipriv->pcibridge_devnum == 0xff
+ && pcipriv->pcibridge_funcnum == 0xff))
+ {
+ //Do Nothing!!
+ }
+ else
+ {
+ //4 //Disable Pci Bridge ASPM
+ pcicfg_addrport = (pcipriv->pcibridge_busnum << 16) |
+ (pcipriv->pcibridge_devnum << 11) |
+ (pcipriv->pcibridge_funcnum << 8) | (1 << 31);
+ num4bytes = (pcipriv->pcibridge_pciehdr_offset + 0x10) / 4;
+
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (num4bytes << 2));
+
+ // now grab data port with device|vendor 4 byte dword
+ NdisRawWritePortUchar(PCI_CONF_DATA, pcibridge_linkctrlreg);
+
+ DBG_871X("rtw_pci_disable_aspm():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n",
+ pcipriv->pcibridge_busnum, pcipriv->pcibridge_devnum,
+ pcipriv->pcibridge_funcnum,
+ (pcipriv->pcibridge_pciehdr_offset+0x10), pcibridge_linkctrlreg);
+
+ rtw_udelay_os(50);
+ }
+}
+
+//[ASPM]
+//Description:
+// Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for power saving
+// We should follow the sequence to enable RTL8192SE first then enable Pci Bridge ASPM
+// or the system will show bluescreen.
+void rtw_pci_enable_aspm(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ u16 aspmlevel = 0;
+ u32 pcicfg_addrport = 0;
+ u8 num4bytes;
+ u8 u_pcibridge_aspmsetting = 0;
+ u8 u_device_aspmsetting = 0;
+
+ // When there exists anyone's busnum, devnum, and funcnum that are set to 0xff,
+ // we do not execute any action and return.
+ // if it is not intel bus then don't enable ASPM.
+
+ if ((pcipriv->busnumber == 0xff
+ && pcipriv->devnumber == 0xff
+ && pcipriv->funcnumber == 0xff)
+ || (pcipriv->pcibridge_busnum == 0xff
+ && pcipriv->pcibridge_devnum == 0xff
+ && pcipriv->pcibridge_funcnum == 0xff))
+ {
+ DBG_871X("PlatformEnableASPM(): Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n");
+ return;
+ }
+
+ //4 Enable Pci Bridge ASPM
+ pcicfg_addrport = (pcipriv->pcibridge_busnum << 16)
+ | (pcipriv->pcibridge_devnum << 11)
+ | (pcipriv->pcibridge_funcnum << 8) | (1 << 31);
+ num4bytes = (pcipriv->pcibridge_pciehdr_offset + 0x10) / 4;
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (num4bytes << 2));
+ // now grab data port with device|vendor 4 byte dword
+
+ u_pcibridge_aspmsetting = pcipriv->pcibridge_linkctrlreg | pdvobjpriv->const_hostpci_aspm_setting;
+
+ if (pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL ||
+ pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_SIS)
+ u_pcibridge_aspmsetting &= ~BIT(0);
+
+ NdisRawWritePortUchar(PCI_CONF_DATA, u_pcibridge_aspmsetting);
+
+ DBG_871X("PlatformEnableASPM():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n",
+ pcipriv->pcibridge_busnum,
+ pcipriv->pcibridge_devnum,
+ pcipriv->pcibridge_funcnum,
+ (pcipriv->pcibridge_pciehdr_offset+0x10),
+ u_pcibridge_aspmsetting);
+
+ rtw_udelay_os(50);
+
+ // Get ASPM level (with/without Clock Req)
+ aspmlevel |= pdvobjpriv->const_devicepci_aspm_setting;
+ u_device_aspmsetting = pcipriv->linkctrl_reg;
+ u_device_aspmsetting |= aspmlevel;
+
+ rtw_pci_platform_switch_device_pci_aspm(padapter, u_device_aspmsetting); //(priv->linkctrl_reg | ASPMLevel));
+
+ if (pwrpriv->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) {
+ rtw_pci_switch_clk_req(padapter, (pwrpriv->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0);
+ RT_SET_PS_LEVEL(pwrpriv, RT_RF_OFF_LEVL_CLK_REQ);
+ }
+
+ rtw_udelay_os(50);
+}
+
+//
+//Description:
+//To get link control field by searching from PCIe capability lists.
+//
+static u8
+rtw_get_link_control_field(_adapter *padapter, u8 busnum, u8 devnum,
+ u8 funcnum)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ struct rt_pci_capabilities_header capability_hdr;
+ u8 capability_offset, num4bytes;
+ u32 pcicfg_addrport = 0;
+ u8 linkctrl_reg;
+ u8 status = _FALSE;
+
+ //If busnum, devnum, funcnum are set to 0xff.
+ if (busnum == 0xff && devnum == 0xff && funcnum == 0xff) {
+ DBG_871X("GetLinkControlField(): Fail to find PCIe Capability\n");
+ return _FALSE;
+ }
+
+ pcicfg_addrport = (busnum << 16) | (devnum << 11) | (funcnum << 8) | (1 << 31);
+
+ //2PCIeCap
+
+ // The device supports capability lists. Find the capabilities.
+ num4bytes = 0x34 / 4;
+ //get capability_offset
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (num4bytes << 2));
+ // now grab data port with device|vendor 4 byte dword
+ NdisRawReadPortUchar(PCI_CONF_DATA, &capability_offset);
+
+ // Loop through the capabilities in search of the power management capability.
+ // The list is NULL-terminated, so the last offset will always be zero.
+
+ while (capability_offset != 0) {
+ // First find the number of 4 Byte.
+ num4bytes = capability_offset / 4;
+
+ // Read the header of the capability at this offset. If the retrieved capability is not
+ // the power management capability that we are looking for, follow the link to the
+ // next capability and continue looping.
+
+ //4 get capability_hdr
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (num4bytes << 2));
+ // now grab data port with device|vendor 4 byte dword
+ NdisRawReadPortUshort(PCI_CONF_DATA, (u16 *) & capability_hdr);
+
+ // Found the PCI express capability
+ if (capability_hdr.capability_id == PCI_CAPABILITY_ID_PCI_EXPRESS)
+ {
+ break;
+ }
+ else
+ {
+ // This is some other capability. Keep looking for the PCI express capability.
+ capability_offset = capability_hdr.next;
+ }
+ }
+
+ if (capability_hdr.capability_id == PCI_CAPABILITY_ID_PCI_EXPRESS) //
+ {
+ num4bytes = (capability_offset + 0x10) / 4;
+
+ //4 Read Link Control Register
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (num4bytes << 2));
+ // now grab data port with device|vendor 4 byte dword
+ NdisRawReadPortUchar(PCI_CONF_DATA, &linkctrl_reg);
+
+ pcipriv->pcibridge_pciehdr_offset = capability_offset;
+ pcipriv->pcibridge_linkctrlreg = linkctrl_reg;
+
+ status = _TRUE;
+ }
+ else
+ {
+ // We didn't find a PCIe capability.
+ DBG_871X("GetLinkControlField(): Cannot Find PCIe Capability\n");
+ }
+
+ return status;
+}
+
+//
+//Description:
+//To get PCI bus infomation and return busnum, devnum, and funcnum about
+//the bus(bridge) which the device binds.
+//
+static u8
+rtw_get_pci_bus_info(_adapter *padapter,
+ u16 vendorid,
+ u16 deviceid,
+ u8 irql, u8 basecode, u8 subclass, u8 filed19val,
+ u8 * busnum, u8 * devnum, u8 * funcnum)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_dev *pdev = pdvobjpriv->ppcidev;
+ u8 busnum_idx, devicenum_idx, functionnum_idx;
+ u32 pcicfg_addrport = 0;
+ u32 dev_venid = 0, classcode, field19, headertype;
+ u16 venId, devId;
+ u8 basec, subc, irqline;
+ u16 regoffset;
+ u8 b_singlefunc = _FALSE;
+ u8 b_bridgechk = _FALSE;
+
+ *busnum = 0xFF;
+ *devnum = 0xFF;
+ *funcnum = 0xFF;
+
+ //DBG_871X("==============>vendorid:%x,deviceid:%x,irql:%x\n", vendorid,deviceid,irql);
+ if ((basecode == PCI_CLASS_BRIDGE_DEV) &&
+ (subclass == PCI_SUBCLASS_BR_PCI_TO_PCI)
+ && (filed19val == U1DONTCARE))
+ b_bridgechk = _TRUE;
+
+ // perform a complete pci bus scan operation
+ for (busnum_idx = 0; busnum_idx < PCI_MAX_BRIDGE_NUMBER; busnum_idx++) //255
+ {
+ for (devicenum_idx = 0; devicenum_idx < PCI_MAX_DEVICES; devicenum_idx++) //32
+ {
+ b_singlefunc = _FALSE;
+ for (functionnum_idx = 0; functionnum_idx < PCI_MAX_FUNCTION; functionnum_idx++) //8
+ {
+ //
+ // <Roger_Notes> We have to skip redundant Bus scan to prevent unexpected system hang
+ // if single function is present in this device.
+ // 2009.02.26.
+ //
+ if (functionnum_idx == 0) {
+ //4 get header type (DWORD #3)
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31);
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (3 << 2));
+ NdisRawReadPortUlong(PCI_CONF_DATA, &headertype);
+ headertype = ((headertype >> 16) & 0x0080) >> 7; // address 0x0e[7].
+ if (headertype == 0) //Single function
+ b_singlefunc = _TRUE;
+ }
+ else
+ {//By pass the following scan process.
+ if (b_singlefunc == _TRUE)
+ break;
+ }
+
+ // Set access enable control.
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31);
+
+ //4 // Get vendorid/ deviceid
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport);
+ // now grab data port with device|vendor 4 byte dword
+ NdisRawReadPortUlong(PCI_CONF_DATA, &dev_venid);
+
+ // if data port is full of 1s, no device is present
+ // some broken boards return 0 if a slot is empty:
+ if (dev_venid == 0xFFFFFFFF || dev_venid == 0)
+ continue; //PCI_INVALID_VENDORID
+
+ // 4 // Get irql
+ regoffset = 0x3C;
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31) | (regoffset & 0xFFFFFFFC);
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport);
+ NdisRawReadPortUchar((PCI_CONF_DATA +(regoffset & 0x3)), &irqline);
+
+ venId = (u16) (dev_venid >> 0) & 0xFFFF;
+ devId = (u16) (dev_venid >> 16) & 0xFFFF;
+
+ // Check Vendor ID
+ if (!b_bridgechk && (venId != vendorid) && (vendorid != U2DONTCARE))
+ continue;
+
+ // Check Device ID
+ if (!b_bridgechk && (devId != deviceid) && (deviceid != U2DONTCARE))
+ continue;
+
+ // Check irql
+ if (!b_bridgechk && (irqline != irql) && (irql != U1DONTCARE))
+ continue;
+
+ //4 get Class Code
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31);
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (2 << 2));
+ NdisRawReadPortUlong(PCI_CONF_DATA, &classcode);
+ classcode = classcode >> 8;
+
+ basec = (u8) (classcode >> 16) & 0xFF;
+ subc = (u8) (classcode >> 8) & 0xFF;
+ if (b_bridgechk && (venId != vendorid) && (basec == basecode) && (subc == subclass))
+ return _TRUE;
+
+ // Check Vendor ID
+ if (b_bridgechk && (venId != vendorid) && (vendorid != U2DONTCARE))
+ continue;
+
+ // Check Device ID
+ if (b_bridgechk && (devId != deviceid) && (deviceid != U2DONTCARE))
+ continue;
+
+ // Check irql
+ if (b_bridgechk && (irqline != irql) && (irql != U1DONTCARE))
+ continue;
+
+ //4 get field 0x19 value (DWORD #6)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (6 << 2));
+ NdisRawReadPortUlong(PCI_CONF_DATA, &field19);
+ field19 = (field19 >> 8) & 0xFF;
+
+ //4 Matching Class Code and filed19.
+ if ((basec == basecode) && (subc == subclass) && ((field19 == filed19val) || (filed19val == U1DONTCARE))) {
+ *busnum = busnum_idx;
+ *devnum = devicenum_idx;
+ *funcnum = functionnum_idx;
+
+ DBG_871X("GetPciBusInfo(): Find Device(%X:%X) bus=%d dev=%d, func=%d\n",
+ vendorid, deviceid, busnum_idx, devicenum_idx, functionnum_idx);
+ return _TRUE;
+ }
+ }
+ }
+ }
+
+ DBG_871X("GetPciBusInfo(): Cannot Find Device(%X:%X:%X)\n", vendorid, deviceid, dev_venid);
+
+ return _FALSE;
+}
+
+static u8
+rtw_get_pci_brideg_info(_adapter *padapter,
+ u8 basecode,
+ u8 subclass,
+ u8 filed19val, u8 * busnum, u8 * devnum,
+ u8 * funcnum, u16 * vendorid, u16 * deviceid)
+{
+ u8 busnum_idx, devicenum_idx, functionnum_idx;
+ u32 pcicfg_addrport = 0;
+ u32 dev_venid, classcode, field19, headertype;
+ u16 venId, devId;
+ u8 basec, subc, irqline;
+ u16 regoffset;
+ u8 b_singlefunc = _FALSE;
+
+ *busnum = 0xFF;
+ *devnum = 0xFF;
+ *funcnum = 0xFF;
+
+ // perform a complete pci bus scan operation
+ for (busnum_idx = 0; busnum_idx < PCI_MAX_BRIDGE_NUMBER; busnum_idx++) //255
+ {
+ for (devicenum_idx = 0; devicenum_idx < PCI_MAX_DEVICES; devicenum_idx++) //32
+ {
+ b_singlefunc = _FALSE;
+ for (functionnum_idx = 0; functionnum_idx < PCI_MAX_FUNCTION; functionnum_idx++) //8
+ {
+ //
+ // <Roger_Notes> We have to skip redundant Bus scan to prevent unexpected system hang
+ // if single function is present in this device.
+ // 2009.02.26.
+ //
+ if (functionnum_idx == 0)
+ {
+ //4 get header type (DWORD #3)
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31);
+ //NdisRawWritePortUlong((ULONG_PTR)PCI_CONF_ADDRESS , pcicfg_addrport + (3 << 2));
+ //NdisRawReadPortUlong((ULONG_PTR)PCI_CONF_DATA, &headertype);
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (3 << 2));
+ NdisRawReadPortUlong(PCI_CONF_DATA, &headertype);
+ headertype = ((headertype >> 16) & 0x0080) >> 7; // address 0x0e[7].
+ if (headertype == 0) //Single function
+ b_singlefunc = _TRUE;
+ }
+ else
+ {//By pass the following scan process.
+ if (b_singlefunc == _TRUE)
+ break;
+ }
+
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31);
+
+ //4 // Get vendorid/ deviceid
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport);
+ // now grab data port with device|vendor 4 byte dword
+ NdisRawReadPortUlong(PCI_CONF_DATA, &dev_venid);
+
+ //4 Get irql
+ regoffset = 0x3C;
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31) | (regoffset & 0xFFFFFFFC);
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport);
+ NdisRawReadPortUchar((PCI_CONF_DATA + (regoffset & 0x3)), &irqline);
+
+ venId = (u16) (dev_venid >> 0) & 0xFFFF;
+ devId = (u16) (dev_venid >> 16) & 0xFFFF;
+
+ //4 get Class Code
+ pcicfg_addrport = (busnum_idx << 16) | (devicenum_idx << 11) | (functionnum_idx << 8) | (1 << 31);
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (2 << 2));
+ NdisRawReadPortUlong(PCI_CONF_DATA, &classcode);
+ classcode = classcode >> 8;
+
+ basec = (u8) (classcode >> 16) & 0xFF;
+ subc = (u8) (classcode >> 8) & 0xFF;
+
+ //4 get field 0x19 value (DWORD #6)
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (6 << 2));
+ NdisRawReadPortUlong(PCI_CONF_DATA, &field19);
+ field19 = (field19 >> 8) & 0xFF;
+
+ //4 Matching Class Code and filed19.
+ if ((basec == basecode) && (subc == subclass) && ((field19 == filed19val) || (filed19val == U1DONTCARE))) {
+ *busnum = busnum_idx;
+ *devnum = devicenum_idx;
+ *funcnum = functionnum_idx;
+ *vendorid = venId;
+ *deviceid = devId;
+
+ DBG_871X("GetPciBridegInfo : Find Device(%X:%X) bus=%d dev=%d, func=%d\n",
+ venId, devId, busnum_idx, devicenum_idx, functionnum_idx);
+
+ return _TRUE;
+ }
+ }
+ }
+ }
+
+ DBG_871X("GetPciBridegInfo(): Cannot Find PciBridge for Device\n");
+
+ return _FALSE;
+} // end of GetPciBridegInfo
+
+//
+//Description:
+//To find specific bridge information.
+//
+static void rtw_find_bridge_info(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ u8 pcibridge_busnum = 0xff;
+ u8 pcibridge_devnum = 0xff;
+ u8 pcibridge_funcnum = 0xff;
+ u16 pcibridge_vendorid = 0xff;
+ u16 pcibridge_deviceid = 0xff;
+ u8 tmp = 0;
+
+ rtw_get_pci_brideg_info(padapter,
+ PCI_CLASS_BRIDGE_DEV,
+ PCI_SUBCLASS_BR_PCI_TO_PCI,
+ pcipriv->busnumber,
+ &pcibridge_busnum,
+ &pcibridge_devnum, &pcibridge_funcnum,
+ &pcibridge_vendorid, &pcibridge_deviceid);
+
+ // match the array of vendor id and regonize which chipset is used.
+ pcipriv->pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN;
+
+ for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
+ if (pcibridge_vendorid == pcibridge_vendors[tmp]) {
+ pcipriv->pcibridge_vendor = tmp;
+ DBG_871X("Pci Bridge Vendor is found index: %d\n", tmp);
+ break;
+ }
+ }
+ DBG_871X("Pci Bridge Vendor is %x\n", pcibridge_vendors[tmp]);
+
+ // Update corresponding PCI bus info.
+ pcipriv->pcibridge_busnum = pcibridge_busnum;
+ pcipriv->pcibridge_devnum = pcibridge_devnum;
+ pcipriv->pcibridge_funcnum = pcibridge_funcnum;
+ pcipriv->pcibridge_vendorid = pcibridge_vendorid;
+ pcipriv->pcibridge_deviceid = pcibridge_deviceid;
+
+}
+
+static u8
+rtw_get_amd_l1_patch(_adapter *padapter, u8 busnum, u8 devnum,
+ u8 funcnum)
+{
+ u8 status = _FALSE;
+ u8 offset_e0;
+ unsigned offset_e4;
+ u32 pcicfg_addrport = 0;
+
+ pcicfg_addrport = (busnum << 16) | (devnum << 11) | (funcnum << 8) | (1 << 31);
+
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + 0xE0);
+ NdisRawWritePortUchar(PCI_CONF_DATA, 0xA0);
+
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + 0xE0);
+ NdisRawReadPortUchar(PCI_CONF_DATA, &offset_e0);
+
+ if (offset_e0 == 0xA0)
+ {
+ NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + 0xE4);
+ NdisRawReadPortUlong(PCI_CONF_DATA, &offset_e4);
+ //DbgPrint("Offset E4 %x\n", offset_e4);
+ if (offset_e4 & BIT(23))
+ status = _TRUE;
+ }
+
+ return status;
+}
+#else
+/*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/
+void rtw_pci_disable_aspm(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct pci_dev *pdev = pdvobjpriv->ppcidev;
+ struct pci_dev *bridge_pdev = pdev->bus->self;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ u8 linkctrl_reg;
+ u16 pcibridge_linkctrlreg;
+ u16 aspmlevel = 0;
+
+ // We do not diable/enable ASPM by driver, in the future, the BIOS will enable host and NIC ASPM.
+ // Advertised by SD1 victorh. Added by tynli. 2009.11.23.
+ if(pdvobjpriv->const_pci_aspm == 0)
+ return;
+
+ if(!padapter->hw_init_completed)
+ return;
+
+ if (pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s(): PCI(Bridge) UNKNOWN.\n", __FUNCTION__));
+ return;
+ }
+
+ linkctrl_reg = pcipriv->linkctrl_reg;
+ pcibridge_linkctrlreg = pcipriv->pcibridge_linkctrlreg;
+
+ // Set corresponding value.
+ aspmlevel |= BIT(0) | BIT(1);
+ linkctrl_reg &=~aspmlevel;
+ pcibridge_linkctrlreg &=~aspmlevel;
+
+ if (pwrpriv->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) {
+ RT_CLEAR_PS_LEVEL(pwrpriv, RT_RF_OFF_LEVL_CLK_REQ);
+ rtw_pci_switch_clk_req(padapter, 0x0);
+ }
+
+ {
+ /*for promising device will in L0 state after an I/O.*/
+ u8 tmp_u1b;
+ pci_read_config_byte(pdev, 0x80, &tmp_u1b);
+ }
+
+ rtw_pci_platform_switch_device_pci_aspm(padapter, linkctrl_reg);
+ rtw_udelay_os(50);
+
+ //When there exists anyone's BusNum, DevNum, and FuncNum that are set to 0xff,
+ // we do not execute any action and return. Added by tynli.
+ if( (pcipriv->busnumber == 0xff && pcipriv->devnumber == 0xff && pcipriv->funcnumber == 0xff) ||
+ (pcipriv->pcibridge_busnum == 0xff && pcipriv->pcibridge_devnum == 0xff && pcipriv->pcibridge_funcnum == 0xff) )
+ {
+ // Do Nothing!!
+ }
+ else
+ {
+ /*Disable Pci Bridge ASPM*/
+ //NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + (num4bytes << 2));
+ //NdisRawWritePortUchar(PCI_CONF_DATA, pcibridge_linkctrlreg);
+ pci_write_config_byte(bridge_pdev, pcipriv->pcibridge_pciehdr_offset + 0x10, pcibridge_linkctrlreg);
+
+ DBG_871X("rtw_pci_disable_aspm():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n",
+ pcipriv->pcibridge_busnum, pcipriv->pcibridge_devnum,
+ pcipriv->pcibridge_funcnum,
+ (pcipriv->pcibridge_pciehdr_offset+0x10), pcibridge_linkctrlreg);
+
+ rtw_udelay_os(50);
+ }
+
+}
+
+/*Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for
+power saving We should follow the sequence to enable
+RTL8192SE first then enable Pci Bridge ASPM
+or the system will show bluescreen.*/
+void rtw_pci_enable_aspm(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct pci_dev *pdev = pdvobjpriv->ppcidev;
+ struct pci_dev *bridge_pdev = pdev->bus->self;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ u16 aspmlevel = 0;
+ u8 u_pcibridge_aspmsetting = 0;
+ u8 u_device_aspmsetting = 0;
+ u32 u_device_aspmsupportsetting = 0;
+
+ // We do not diable/enable ASPM by driver, in the future, the BIOS will enable host and NIC ASPM.
+ // Advertised by SD1 victorh. Added by tynli. 2009.11.23.
+ if(pdvobjpriv->const_pci_aspm == 0)
+ return;
+
+ //When there exists anyone's BusNum, DevNum, and FuncNum that are set to 0xff,
+ // we do not execute any action and return. Added by tynli.
+ if( (pcipriv->busnumber == 0xff && pcipriv->devnumber == 0xff && pcipriv->funcnumber == 0xff) ||
+ (pcipriv->pcibridge_busnum == 0xff && pcipriv->pcibridge_devnum == 0xff && pcipriv->pcibridge_funcnum == 0xff) )
+ {
+ DBG_871X("rtw_pci_enable_aspm(): Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n");
+ return;
+ }
+
+//Get Bridge ASPM Support
+//not to enable bridge aspm if bridge does not support
+//Added by sherry 20100803
+ if (IS_HARDWARE_TYPE_8192DE(padapter))
+ {
+ //PciCfgAddrPort = (pcipriv->pcibridge_busnum << 16)|(pcipriv->pcibridge_devnum<< 11)|(pcipriv->pcibridge_funcnum << 8)|(1 << 31);
+ //Num4Bytes = (pcipriv->pcibridge_pciehdr_offset+0x0C)/4;
+ //NdisRawWritePortUlong((ULONG_PTR)PCI_CONF_ADDRESS , PciCfgAddrPort+(Num4Bytes << 2));
+ //NdisRawReadPortUlong((ULONG_PTR)PCI_CONF_DATA,&uDeviceASPMSupportSetting);
+ pci_read_config_dword(bridge_pdev, (pcipriv->pcibridge_pciehdr_offset+0x0C), &u_device_aspmsupportsetting);
+ DBG_871X("rtw_pci_enable_aspm(): Bridge ASPM support %x \n",u_device_aspmsupportsetting);
+ if(((u_device_aspmsupportsetting & BIT(11)) != BIT(11)) || ((u_device_aspmsupportsetting & BIT(10)) != BIT(10)))
+ {
+ if(pdvobjpriv->const_devicepci_aspm_setting == 3)
+ {
+ DBG_871X("rtw_pci_enable_aspm(): Bridge not support L0S or L1\n");
+ return;
+ }
+ else if(pdvobjpriv->const_devicepci_aspm_setting == 2)
+ {
+ if((u_device_aspmsupportsetting & BIT(11)) != BIT(11))
+ {
+ DBG_871X("rtw_pci_enable_aspm(): Bridge not support L1 \n");
+ return;
+ }
+ }
+ else if(pdvobjpriv->const_devicepci_aspm_setting == 1)
+ {
+ if((u_device_aspmsupportsetting & BIT(10)) != BIT(10))
+ {
+ DBG_871X("rtw_pci_enable_aspm(): Bridge not support L0s \n");
+ return;
+ }
+
+ }
+ }
+ else
+ {
+ DBG_871X("rtw_pci_enable_aspm(): Bridge support L0s and L1 \n");
+ }
+ }
+
+
+ /*Enable Pci Bridge ASPM*/
+ //PciCfgAddrPort = (pcipriv->pcibridge_busnum << 16)|(pcipriv->pcibridge_devnum<< 11) |(pcipriv->pcibridge_funcnum << 8)|(1 << 31);
+ //Num4Bytes = (pcipriv->pcibridge_pciehdr_offset+0x10)/4;
+ // set up address port at 0xCF8 offset field= 0 (dev|vend)
+ //NdisRawWritePortUlong(PCI_CONF_ADDRESS, PciCfgAddrPort + (Num4Bytes << 2));
+ // now grab data port with device|vendor 4 byte dword
+
+ u_pcibridge_aspmsetting = pcipriv->pcibridge_linkctrlreg;
+ u_pcibridge_aspmsetting |= pdvobjpriv->const_hostpci_aspm_setting;
+
+ if (pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL ||
+ pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_SIS )
+ u_pcibridge_aspmsetting &= ~BIT(0); // for intel host 42 device 43
+
+ //NdisRawWritePortUchar(PCI_CONF_DATA, u_pcibridge_aspmsetting);
+ pci_write_config_byte(bridge_pdev, (pcipriv->pcibridge_pciehdr_offset+0x10), u_pcibridge_aspmsetting);
+
+ DBG_871X("PlatformEnableASPM():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n",
+ pcipriv->pcibridge_busnum, pcipriv->pcibridge_devnum, pcipriv->pcibridge_funcnum,
+ (pcipriv->pcibridge_pciehdr_offset+0x10),
+ u_pcibridge_aspmsetting);
+
+ rtw_udelay_os(50);
+
+ /*Get ASPM level (with/without Clock Req)*/
+ aspmlevel |= pdvobjpriv->const_devicepci_aspm_setting;
+ u_device_aspmsetting = pcipriv->linkctrl_reg;
+ u_device_aspmsetting |= aspmlevel; // device 43
+
+ rtw_pci_platform_switch_device_pci_aspm(padapter, u_device_aspmsetting);
+
+ if (pwrpriv->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) {
+ rtw_pci_switch_clk_req(padapter, (pwrpriv->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0);
+ RT_SET_PS_LEVEL(pwrpriv, RT_RF_OFF_LEVL_CLK_REQ);
+ }
+
+ rtw_udelay_os(50);
+}
+
+static u8 rtw_pci_get_amd_l1_patch(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_dev *pdev = pdvobjpriv->ppcidev;
+ struct pci_dev *bridge_pdev = pdev->bus->self;
+ u8 status = _FALSE;
+ u8 offset_e0;
+ u32 offset_e4;
+
+ //NdisRawWritePortUlong(PCI_CONF_ADDRESS,pcicfg_addrport + 0xE0);
+ //NdisRawWritePortUchar(PCI_CONF_DATA, 0xA0);
+ pci_write_config_byte(bridge_pdev, 0xE0, 0xA0);
+
+ //NdisRawWritePortUlong(PCI_CONF_ADDRESS,pcicfg_addrport + 0xE0);
+ //NdisRawReadPortUchar(PCI_CONF_DATA, &offset_e0);
+ pci_read_config_byte(bridge_pdev, 0xE0, &offset_e0);
+
+ if (offset_e0 == 0xA0) {
+ //NdisRawWritePortUlong(PCI_CONF_ADDRESS, pcicfg_addrport + 0xE4);
+ //NdisRawReadPortUlong(PCI_CONF_DATA, &offset_e4);
+ pci_read_config_dword(bridge_pdev, 0xE4, &offset_e4);
+ if (offset_e4 & BIT(23))
+ status = _TRUE;
+ }
+
+ return status;
+}
+
+static void rtw_pci_get_linkcontrol_field(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ struct pci_dev *pdev = pdvobjpriv->ppcidev;
+ struct pci_dev *bridge_pdev = pdev->bus->self;
+ u8 capabilityoffset = pcipriv->pcibridge_pciehdr_offset;
+ u8 linkctrl_reg;
+
+ /*Read Link Control Register*/
+ pci_read_config_byte(bridge_pdev, capabilityoffset + PCI_EXP_LNKCTL, &linkctrl_reg);
+
+ pcipriv->pcibridge_linkctrlreg = linkctrl_reg;
+}
+#endif
+
+static void rtw_pci_parse_configuration(struct pci_dev *pdev, _adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ u8 tmp;
+ int pos;
+ u8 linkctrl_reg;
+
+ //Link Control Register
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);
+ pcipriv->linkctrl_reg = linkctrl_reg;
+
+ //DBG_871X("Link Control Register = %x\n", pcipriv->linkctrl_reg);
+
+ pci_read_config_byte(pdev, 0x98, &tmp);
+ tmp |= BIT(4);
+ pci_write_config_byte(pdev, 0x98, tmp);
+
+ //tmp = 0x17;
+ //pci_write_config_byte(pdev, 0x70f, tmp);
+}
+
+//
+// Update PCI dependent default settings.
+//
+static void rtw_pci_update_default_setting(_adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ //reset pPSC->reg_rfps_level & priv->b_support_aspm
+ pwrpriv->reg_rfps_level = 0;
+ pwrpriv->b_support_aspm = 0;
+
+ // Dynamic Mechanism,
+ //pAdapter->HalFunc.SetHalDefVarHandler(pAdapter, HAL_DEF_INIT_GAIN, &(pDevice->InitGainState));
+
+ // Update PCI ASPM setting
+ pwrpriv->const_amdpci_aspm = pdvobjpriv->const_amdpci_aspm;
+ switch (pdvobjpriv->const_pci_aspm) {
+ case 0: // No ASPM
+ break;
+
+ case 1: // ASPM dynamically enabled/disable.
+ pwrpriv->reg_rfps_level |= RT_RF_LPS_LEVEL_ASPM;
+ break;
+
+ case 2: // ASPM with Clock Req dynamically enabled/disable.
+ pwrpriv->reg_rfps_level |= (RT_RF_LPS_LEVEL_ASPM | RT_RF_OFF_LEVL_CLK_REQ);
+ break;
+
+ case 3: // Always enable ASPM and Clock Req from initialization to halt.
+ pwrpriv->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM);
+ pwrpriv->reg_rfps_level |= (RT_RF_PS_LEVEL_ALWAYS_ASPM | RT_RF_OFF_LEVL_CLK_REQ);
+ break;
+
+ case 4: // Always enable ASPM without Clock Req from initialization to halt.
+ pwrpriv->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM | RT_RF_OFF_LEVL_CLK_REQ);
+ pwrpriv->reg_rfps_level |= RT_RF_PS_LEVEL_ALWAYS_ASPM;
+ break;
+ }
+
+ pwrpriv->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC;
+
+ // Update Radio OFF setting
+ switch (pdvobjpriv->const_hwsw_rfoff_d3) {
+ case 1:
+ if (pwrpriv->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM)
+ pwrpriv->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM;
+ break;
+
+ case 2:
+ if (pwrpriv->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM)
+ pwrpriv->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM;
+ pwrpriv->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC;
+ break;
+
+ case 3:
+ pwrpriv->reg_rfps_level |= RT_RF_OFF_LEVL_PCI_D3;
+ break;
+ }
+
+ // Update Rx 2R setting
+ //pPSC->reg_rfps_level |= ((pDevice->RegLPS2RDisable) ? RT_RF_LPS_DISALBE_2R : 0);
+
+ //
+ // Set HW definition to determine if it supports ASPM.
+ //
+ switch (pdvobjpriv->const_support_pciaspm) {
+ case 0: // Not support ASPM.
+ {
+ u8 b_support_aspm = _FALSE;
+ pwrpriv->b_support_aspm = b_support_aspm;
+ }
+ break;
+
+ case 1: // Support ASPM.
+ {
+ u8 b_support_aspm = _TRUE;
+ u8 b_support_backdoor = _TRUE;
+
+ pwrpriv->b_support_aspm = b_support_aspm;
+
+ /*if(pAdapter->MgntInfo.CustomerID == RT_CID_TOSHIBA &&
+ pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_AMD &&
+ !pcipriv->amd_l1_patch)
+ b_support_backdoor = _FALSE;*/
+
+ pwrpriv->b_support_backdoor = b_support_backdoor;
+ }
+ break;
+
+ case 2: // Set by Chipset.
+ // ASPM value set by chipset.
+ if (pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) {
+ u8 b_support_aspm = _TRUE;
+ pwrpriv->b_support_aspm = b_support_aspm;
+ }
+ break;
+
+ default:
+ // Do nothing. Set when finding the chipset.
+ break;
+ }
+}
+
+static void rtw_pci_initialize_adapter_common(_adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ rtw_pci_update_default_setting(padapter);
+
+ if (pwrpriv->reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM) {
+ // Always enable ASPM & Clock Req.
+ rtw_pci_enable_aspm(padapter);
+ RT_SET_PS_LEVEL(pwrpriv, RT_RF_PS_LEVEL_ALWAYS_ASPM);
+ }
+
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) || (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+#define rtw_pci_interrupt(x,y,z) rtw_pci_interrupt(x,y)
+#endif
+
+static irqreturn_t rtw_pci_interrupt(int irq, void *priv, struct pt_regs *regs)
+{
+ _adapter *padapter = (_adapter *)priv;
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+
+
+ if (pdvobjpriv->irq_enabled == 0) {
+ return IRQ_HANDLED;
+ }
+
+ if(padapter->HalFunc.interrupt_handler(padapter) == _FAIL)
+ return IRQ_HANDLED;
+ //return IRQ_NONE;
+
+ return IRQ_HANDLED;
+}
+
+static u32 pci_dvobj_init(_adapter *padapter)
+{
+ u32 status = _SUCCESS;
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct pci_priv *pcipriv = &(pdvobjpriv->pcipriv);
+ struct pci_dev *pdev = pdvobjpriv->ppcidev;
+ struct pci_dev *bridge_pdev = pdev->bus->self;
+ u8 tmp;
+
+_func_enter_;
+
+#if 1
+ /*find bus info*/
+ pcipriv->busnumber = pdev->bus->number;
+ pcipriv->devnumber = PCI_SLOT(pdev->devfn);
+ pcipriv->funcnumber = PCI_FUNC(pdev->devfn);
+
+ /*find bridge info*/
+ pcipriv->pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN;
+ if(bridge_pdev){
+ pcipriv->pcibridge_vendorid = bridge_pdev->vendor;
+ for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
+ if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
+ pcipriv->pcibridge_vendor = tmp;
+ DBG_871X("Pci Bridge Vendor is found index: %d, %x\n", tmp, pcibridge_vendors[tmp]);
+ break;
+ }
+ }
+ }
+
+ //if (pcipriv->pcibridge_vendor != PCI_BRIDGE_VENDOR_UNKNOWN) {
+ if(bridge_pdev){
+ pcipriv->pcibridge_busnum = bridge_pdev->bus->number;
+ pcipriv->pcibridge_devnum = PCI_SLOT(bridge_pdev->devfn);
+ pcipriv->pcibridge_funcnum = PCI_FUNC(bridge_pdev->devfn);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ pcipriv->pcibridge_pciehdr_offset = pci_find_capability(bridge_pdev, PCI_CAP_ID_EXP);
+#else
+ pcipriv->pcibridge_pciehdr_offset = bridge_pdev->pcie_cap;
+#endif
+
+ rtw_pci_get_linkcontrol_field(padapter);
+
+ if (pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_AMD) {
+ pcipriv->amd_l1_patch = rtw_pci_get_amd_l1_patch(padapter);
+ }
+ }
+#else
+ //
+ // Find bridge related info.
+ //
+ rtw_get_pci_bus_info(padapter,
+ pdev->vendor,
+ pdev->device,
+ (u8) pdvobjpriv->irqline,
+ 0x02, 0x80, U1DONTCARE,
+ &pcipriv->busnumber,
+ &pcipriv->devnumber,
+ &pcipriv->funcnumber);
+
+ rtw_find_bridge_info(padapter);
+
+ if (pcipriv->pcibridge_vendor != PCI_BRIDGE_VENDOR_UNKNOWN) {
+ rtw_get_link_control_field(padapter,
+ pcipriv->pcibridge_busnum,
+ pcipriv->pcibridge_devnum,
+ pcipriv->pcibridge_funcnum);
+
+ if (pcipriv->pcibridge_vendor == PCI_BRIDGE_VENDOR_AMD) {
+ pcipriv->amd_l1_patch =
+ rtw_get_amd_l1_patch(padapter,
+ pcipriv->pcibridge_busnum,
+ pcipriv->pcibridge_devnum,
+ pcipriv->pcibridge_funcnum);
+ }
+ }
+#endif
+
+ //
+ // Allow the hardware to look at PCI config information.
+ //
+ rtw_pci_parse_configuration(pdev, padapter);
+
+ DBG_871X("pcidev busnumber:devnumber:funcnumber:"
+ "vendor:link_ctl %d:%d:%d:%x:%x\n",
+ pcipriv->busnumber,
+ pcipriv->devnumber,
+ pcipriv->funcnumber,
+ pdev->vendor,
+ pcipriv->linkctrl_reg);
+
+ DBG_871X("pci_bridge busnumber:devnumber:funcnumber:vendor:"
+ "pcie_cap:link_ctl_reg: %d:%d:%d:%x:%x:%x:%x\n",
+ pcipriv->pcibridge_busnum,
+ pcipriv->pcibridge_devnum,
+ pcipriv->pcibridge_funcnum,
+ pcibridge_vendors[pcipriv->pcibridge_vendor],
+ pcipriv->pcibridge_pciehdr_offset,
+ pcipriv->pcibridge_linkctrlreg,
+ pcipriv->amd_l1_patch);
+
+ //.2
+ if ((rtw_init_io_priv(padapter, pci_set_intf_ops)) == _FAIL)
+ {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,(" \n Can't init io_reqs\n"));
+ status = _FAIL;
+ }
+
+ //.3
+ intf_read_chip_version(padapter);
+ //.4
+ intf_chip_configure(padapter);
+
+_func_exit_;
+
+ return status;
+}
+
+static void pci_dvobj_deinit(_adapter * padapter)
+{
+ //struct dvobj_priv *pdvobjpriv=&padapter->dvobjpriv;
+
+_func_enter_;
+
+_func_exit_;
+}
+
+
+static void decide_chip_type_by_pci_device_id(_adapter *padapter, struct pci_dev *pdev)
+{
+ u16 venderid, deviceid, irqline;
+ u8 revisionid;
+ struct dvobj_priv *pdvobjpriv=&padapter->dvobjpriv;
+
+
+ venderid = pdev->vendor;
+ deviceid = pdev->device;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &revisionid); // PCI_REVISION_ID 0x08
+#else
+ revisionid = pdev->revision;
+#endif
+ pci_read_config_word(pdev, PCI_INTERRUPT_LINE, &irqline); // PCI_INTERRUPT_LINE 0x3c
+ pdvobjpriv->irqline = irqline;
+
+
+ //
+ // Decide hardware type here.
+ //
+ if( deviceid == HAL_HW_PCI_8185_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8188_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8198_DEVICE_ID)
+ {
+ DBG_871X("Adapter (8185/8185B) is found- VendorID/DeviceID=%x/%x\n", venderid, deviceid);
+ padapter->HardwareType=HARDWARE_TYPE_RTL8185;
+ }
+ else if (deviceid == HAL_HW_PCI_8190_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_0045_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_0046_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_DLINK_DEVICE_ID)
+ {
+ DBG_871X("Adapter(8190 PCI) is found - vendorid/deviceid=%x/%x\n", venderid, deviceid);
+ padapter->HardwareType = HARDWARE_TYPE_RTL8190P;
+ }
+ else if (deviceid == HAL_HW_PCI_8192_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_0044_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_0047_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8192SE_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8174_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8173_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8172_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8171_DEVICE_ID)
+ {
+ // 8192e and and 8192se may have the same device ID 8192. However, their Revision
+ // ID is different
+ // Added for 92DE. We deferentiate it from SVID,SDID.
+ if( pdev->subsystem_vendor == 0x10EC && pdev->subsystem_device == 0xE020){
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192DE;
+ DBG_871X("Adapter(8192DE) is found - VendorID/DeviceID/RID=%X/%X/%X\n", venderid, deviceid, revisionid);
+ }else{
+ switch (revisionid) {
+ case HAL_HW_PCI_REVISION_ID_8192PCIE:
+ DBG_871X("Adapter(8192 PCI-E) is found - vendorid/deviceid=%x/%x\n", venderid, deviceid);
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192E;
+ break;
+ case HAL_HW_PCI_REVISION_ID_8192SE:
+ DBG_871X("Adapter(8192SE) is found - vendorid/deviceid=%x/%x\n", venderid, deviceid);
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192SE;
+ break;
+ default:
+ DBG_871X("Err: Unknown device - vendorid/deviceid=%x/%x\n", venderid, deviceid);
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192SE;
+ break;
+ }
+ }
+ }
+ else if(deviceid==HAL_HW_PCI_8723E_DEVICE_ID )
+ {//RTL8723E may have the same device ID with RTL8192CET
+ padapter->HardwareType = HARDWARE_TYPE_RTL8723AE;
+ DBG_871X("Adapter(8723 PCI-E) is found - VendorID/DeviceID=%x/%x\n", venderid, deviceid);
+ }
+ else if (deviceid == HAL_HW_PCI_8192CET_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8192CE_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8191CE_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_8188CE_DEVICE_ID)
+ {
+ DBG_871X("Adapter(8192C PCI-E) is found - vendorid/deviceid=%x/%x\n", venderid, deviceid);
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192CE;
+ }
+ else if (deviceid == HAL_HW_PCI_8192DE_DEVICE_ID ||
+ deviceid == HAL_HW_PCI_002B_DEVICE_ID ){
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192DE;
+ DBG_871X("Adapter(8192DE) is found - VendorID/DeviceID/RID=%X/%X/%X\n", venderid, deviceid, revisionid);
+ }
+ else
+ {
+ DBG_871X("Err: Unknown device - vendorid/deviceid=%x/%x\n", venderid, deviceid);
+ //padapter->HardwareType = HAL_DEFAULT_HARDWARE_TYPE;
+ }
+
+
+ padapter->chip_type = NULL_CHIP_TYPE;
+
+ //TODO:
+#ifdef CONFIG_RTL8192C
+ padapter->chip_type = RTL8188C_8192C;
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192CE;
+#endif
+#ifdef CONFIG_RTL8192D
+ pdvobjpriv->InterfaceNumber = revisionid;
+
+ padapter->chip_type = RTL8192D;
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192DE;
+#endif
+
+}
+
+static void pci_intf_start(_adapter *padapter)
+{
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+pci_intf_start\n"));
+ DBG_871X("+pci_intf_start\n");
+
+ //Enable hw interrupt
+ padapter->HalFunc.enable_interrupt(padapter);
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-pci_intf_start\n"));
+ DBG_871X("-pci_intf_start\n");
+}
+
+static void pci_intf_stop(_adapter *padapter)
+{
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+pci_intf_stop\n"));
+
+ //Disable hw interrupt
+ if(padapter->bSurpriseRemoved == _FALSE)
+ {
+ //device still exists, so driver can do i/o operation
+ padapter->HalFunc.disable_interrupt(padapter);
+ tasklet_disable(&(padapter->recvpriv.recv_tasklet));
+ tasklet_disable(&(padapter->recvpriv.irq_prepare_beacon_tasklet));
+ tasklet_disable(&(padapter->xmitpriv.xmit_tasklet));
+
+#ifdef CONFIG_CONCURRENT_MODE
+ /* This function only be called at driver removing. disable buddy_adapter too
+ don't disable interrupt of buddy_adapter because it is same as primary.
+ */
+ if (padapter->pbuddy_adapter){
+ tasklet_disable(&(padapter->pbuddy_adapter->recvpriv.recv_tasklet));
+ tasklet_disable(&(padapter->pbuddy_adapter->recvpriv.irq_prepare_beacon_tasklet));
+ tasklet_disable(&(padapter->pbuddy_adapter->xmitpriv.xmit_tasklet));
+ }
+#endif
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("pci_intf_stop: SurpriseRemoved==_FALSE\n"));
+ }
+ else
+ {
+ // Clear irq_enabled to prevent handle interrupt function.
+ padapter->dvobjpriv.irq_enabled = 0;
+ }
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-pci_intf_stop\n"));
+
+}
+
+
+static void rtw_dev_unload(_adapter *padapter)
+{
+ struct net_device *pnetdev= (struct net_device*)padapter->pnetdev;
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_dev_unload\n"));
+
+ if(padapter->bup == _TRUE)
+ {
+ DBG_871X("+rtw_dev_unload\n");
+ //s1.
+/* if(pnetdev)
+ {
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+ }
+
+ //s2.
+ //s2-1. issue rtw_disassoc_cmd to fw
+ rtw_disassoc_cmd(padapter);
+ //s2-2. indicate disconnect to os
+ rtw_indicate_disconnect(padapter);
+ //s2-3.
+ rtw_free_assoc_resources(padapter, 1);
+ //s2-4.
+ rtw_free_network_queue(padapter, _TRUE);*/
+
+ padapter->bDriverStopped = _TRUE;
+
+ //s3.
+ if(padapter->intf_stop)
+ {
+ padapter->intf_stop(padapter);
+ }
+
+ //s4.
+ rtw_stop_drv_threads(padapter);
+
+
+ //s5.
+ if(padapter->bSurpriseRemoved == _FALSE)
+ {
+ DBG_871X("r871x_dev_unload()->rtl871x_hal_deinit()\n");
+ rtw_hal_deinit(padapter);
+
+ padapter->bSurpriseRemoved = _TRUE;
+ }
+
+ padapter->bup = _FALSE;
+
+ }
+ else
+ {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("r871x_dev_unload():padapter->bup == _FALSE\n" ));
+ }
+
+ DBG_871X("-rtw_dev_unload\n");
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-rtw_dev_unload\n"));
+
+}
+
+static void disable_ht_for_spec_devid(const struct pci_device_id *pdid)
+{
+#ifdef CONFIG_80211N_HT
+ u16 vid, pid;
+ u32 flags;
+ int i;
+ int num = sizeof(specific_device_id_tbl)/sizeof(struct specific_device_id);
+
+ for(i=0; i<num; i++)
+ {
+ vid = specific_device_id_tbl[i].idVendor;
+ pid = specific_device_id_tbl[i].idProduct;
+ flags = specific_device_id_tbl[i].flags;
+
+ if((pdid->vendor==vid) && (pdid->device==pid) && (flags&SPEC_DEV_ID_DISABLE_HT))
+ {
+ rtw_ht_enable = 0;
+ rtw_cbw40_enable = 0;
+ rtw_ampdu_enable = 0;
+ }
+
+ }
+#endif
+}
+
+#ifdef CONFIG_PM
+static int rtw_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ _func_enter_;
+
+
+ _func_exit_;
+ return 0;
+}
+
+static int rtw_resume(struct pci_dev *pdev)
+{
+ _func_enter_;
+
+
+ _func_exit_;
+
+ return 0;
+}
+#endif
+
+#ifdef RTK_DMP_PLATFORM
+#define pci_iounmap(x,y) iounmap(y)
+#endif
+
+/*
+ * drv_init() - a device potentially for us
+ *
+ * notes: drv_init() is called when the bus driver has located a card for us to support.
+ * We accept the new device by returning 0.
+*/
+static int rtw_drv_init(struct pci_dev *pdev, const struct pci_device_id *pdid)
+{
+ int i, err = -ENODEV;
+
+ uint status;
+ _adapter *padapter = NULL;
+ struct dvobj_priv *pdvobjpriv;
+ struct net_device *pnetdev;
+ unsigned long pmem_start, pmem_len, pmem_flags;
+ u8 bdma64 = _FALSE;
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
+ //DBG_871X("+rtw_drv_init\n");
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ DBG_871X(KERN_ERR "%s : Cannot enable new PCI device\n", pci_name(pdev));
+ return err;
+ }
+
+#ifdef CONFIG_64BIT_DMA
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ DBG_871X("RTL819xCE: Using 64bit DMA\n");
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ DBG_871X(KERN_ERR "Unable to obtain 64bit DMA for consistent allocations\n");
+ err = -ENOMEM;
+ pci_disable_device(pdev);
+ return err;
+ }
+ bdma64 = _TRUE;
+ } else
+#endif
+ {
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ DBG_871X(KERN_ERR "Unable to obtain 32bit DMA for consistent allocations\n");
+ err = -ENOMEM;
+ pci_disable_device(pdev);
+ return err;
+ }
+ }
+ }
+
+ pci_set_master(pdev);
+
+ //step 0.
+ disable_ht_for_spec_devid(pdid);
+
+
+ //step 1. set USB interface data
+ // init data
+ pnetdev = rtw_init_netdev(NULL);
+ if (!pnetdev){
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ if(bdma64){
+ pnetdev->features |= NETIF_F_HIGHDMA;
+ }
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+ SET_NETDEV_DEV(pnetdev, &pdev->dev);
+#endif
+
+ padapter = rtw_netdev_priv(pnetdev);
+ padapter->bDriverStopped=_TRUE;
+ pdvobjpriv = &padapter->dvobjpriv;
+ pdvobjpriv->padapter = padapter;
+ pdvobjpriv->ppcidev = pdev;
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_wdev_alloc(padapter, &pdev->dev);
+#endif //CONFIG_IOCTL_CFG80211
+ // set data
+ pci_set_drvdata(pdev, pnetdev);
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ DBG_871X(KERN_ERR "Can't obtain PCI resources\n");
+ goto fail1;
+ }
+ //MEM map
+ pmem_start = pci_resource_start(pdev, 2);
+ pmem_len = pci_resource_len(pdev, 2);
+ pmem_flags = pci_resource_flags(pdev, 2);
+
+#ifdef RTK_DMP_PLATFORM
+ pdvobjpriv->pci_mem_start = (unsigned long)ioremap_nocache( pmem_start, pmem_len);
+#else
+ pdvobjpriv->pci_mem_start = (unsigned long)pci_iomap(pdev, 2, pmem_len); // shared mem start
+#endif
+ if (pdvobjpriv->pci_mem_start == 0) {
+ DBG_871X(KERN_ERR "Can't map PCI mem\n");
+ goto fail2;
+ }
+
+ DBG_871X("Memory mapped space start: 0x%08lx len:%08lx flags:%08lx, after map:0x%08lx\n",
+ pmem_start, pmem_len, pmem_flags, pdvobjpriv->pci_mem_start);
+
+ // Disable Clk Request */
+ pci_write_config_byte(pdev, 0x81, 0);
+ // leave D3 mode */
+ pci_write_config_byte(pdev, 0x44, 0);
+ pci_write_config_byte(pdev, 0x04, 0x06);
+ pci_write_config_byte(pdev, 0x04, 0x07);
+
+
+ //set interface_type to usb
+ padapter->interface_type = RTW_PCIE;
+
+ //step 1-1., decide the chip_type via vid/pid
+ decide_chip_type_by_pci_device_id(padapter, pdev);
+
+ //step 2.
+ if(padapter->chip_type== RTL8188C_8192C)
+ {
+#ifdef CONFIG_RTL8192C
+ rtl8192ce_set_hal_ops(padapter);
+#endif
+ }
+ else if(padapter->chip_type == RTL8192D)
+ {
+#ifdef CONFIG_RTL8192D
+ rtl8192de_set_hal_ops(padapter);
+#endif
+ }
+ else
+ {
+ status = _FAIL;
+ goto error;
+ }
+
+ //step 3. initialize the dvobj_priv
+ padapter->dvobj_init=&pci_dvobj_init;
+ padapter->dvobj_deinit=&pci_dvobj_deinit;
+ padapter->intf_start=&pci_intf_start;
+ padapter->intf_stop=&pci_intf_stop;
+
+ if (padapter->dvobj_init == NULL){
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("\n Initialize dvobjpriv.dvobj_init error!!!\n"));
+ goto error;
+ }
+
+ status = padapter->dvobj_init(padapter);
+ if (status != _SUCCESS) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("initialize device object priv Failed!\n"));
+ goto error;
+ }
+
+ pnetdev->irq = pdev->irq;
+
+ //step 4. read efuse/eeprom data and get mac_addr
+ intf_read_chip_info(padapter);
+
+ //step 5.
+ status = rtw_init_drv_sw(padapter);
+ if(status ==_FAIL){
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("Initialize driver software resource Failed!\n"));
+ goto error;
+ }
+
+ status = padapter->HalFunc.inirp_init(padapter);
+ if(status ==_FAIL){
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("Initialize PCI desc ring Failed!\n"));
+ goto error;
+ }
+
+ rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
+ rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
+
+ _rtw_memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
+ DBG_871X("MAC Address from pnetdev->dev_addr= "MAC_FMT"\n", MAC_ARG(pnetdev->dev_addr));
+
+
+ padapter->HalFunc.disable_interrupt(padapter);
+
+#if defined(IRQF_SHARED)
+ err = request_irq(pdev->irq, &rtw_pci_interrupt, IRQF_SHARED, DRV_NAME, padapter);
+#else
+ err = request_irq(pdev->irq, &rtw_pci_interrupt, SA_SHIRQ, DRV_NAME, padapter);
+#endif
+ if (err) {
+ DBG_871X("Error allocating IRQ %d",pdev->irq);
+ goto error;
+ } else {
+ pdvobjpriv->irq_alloc = 1;
+ DBG_871X("Request_irq OK, IRQ %d\n",pdev->irq);
+ }
+
+ //step 6. Init pci related configuration
+ rtw_pci_initialize_adapter_common(padapter);
+
+ //step 7.
+ /* Tell the network stack we exist */
+ if (register_netdev(pnetdev) != 0) {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("register_netdev() failed\n"));
+ goto error;
+ }
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-drv_init - Adapter->bDriverStopped=%d, Adapter->bSurpriseRemoved=%d\n",padapter->bDriverStopped, padapter->bSurpriseRemoved));
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-871x_drv - drv_init, success!\n"));
+ //DBG_871X("-871x_drv - drv_init, success!\n");
+
+#ifdef CONFIG_PROC_DEBUG
+#ifdef RTK_DMP_PLATFORM
+ rtw_proc_init_one(pnetdev);
+#endif
+#endif
+
+#ifdef CONFIG_HOSTAPD_MLME
+ hostapd_mode_init(padapter);
+#endif
+
+ padapter->hw_init_mutex = &pci_drvpriv.hw_init_mutex;
+#ifdef CONFIG_CONCURRENT_MODE
+ //set global variable to primary adapter
+ padapter->ph2c_fwcmd_mutex = &pci_drvpriv.h2c_fwcmd_mutex;
+ padapter->psetch_mutex = &pci_drvpriv.setch_mutex;
+ padapter->psetbw_mutex = &pci_drvpriv.setbw_mutex;
+#endif
+
+
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+ DBG_871X("wlan link up\n");
+ rtd2885_wlan_netlink_sendMsg("linkup", "8712");
+#endif
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(rtw_drv_if2_init(padapter, NULL)==_FAIL)
+ {
+ goto error;
+ }
+#endif
+
+ return 0;
+
+error:
+
+ pci_set_drvdata(pdev, NULL);
+
+ if (pdvobjpriv->irq_alloc) {
+ free_irq(pdev->irq, padapter);
+ pdvobjpriv->irq_alloc = 0;
+ }
+
+ if (pdvobjpriv->pci_mem_start != 0) {
+ pci_iounmap(pdev, (void *)pdvobjpriv->pci_mem_start);
+ }
+
+ pci_dvobj_deinit(padapter);
+
+ if (pnetdev)
+ {
+ //unregister_netdev(pnetdev);
+ rtw_free_netdev(pnetdev);
+ }
+
+fail2:
+ pci_release_regions(pdev);
+
+fail1:
+ pci_disable_device(pdev);
+
+ DBG_871X("-871x_pci - drv_init, fail!\n");
+
+ return err;
+}
+
+/*
+ * dev_remove() - our device is being removed
+*/
+//rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both
+static void rtw_dev_remove(struct pci_dev *pdev)
+{
+ struct net_device *pnetdev=pci_get_drvdata(pdev);
+ _adapter *padapter = (_adapter*)rtw_netdev_priv(pnetdev);
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+#ifdef CONFIG_IOCTL_CFG80211
+ struct wireless_dev *wdev;
+#endif //CONFIG_IOCTL_CFG80211
+
+_func_exit_;
+
+ if (unlikely(!padapter)) {
+ return;
+ }
+
+#ifdef CONFIG_IOCTL_CFG80211
+ wdev = padapter->rtw_wdev;
+#endif //CONFIG_IOCTL_CFG80211
+
+ DBG_871X("+rtw_dev_remove\n");
+
+#if defined(CONFIG_HAS_EARLYSUSPEND ) || defined(CONFIG_ANDROID_POWER)
+ rtw_unregister_early_suspend(&padapter->pwrctrlpriv);
+#endif
+
+ LeaveAllPowerSaveMode(padapter);
+// padapter->intf_stop(padapter);
+
+
+#ifdef RTK_DMP_PLATFORM
+ padapter->bSurpriseRemoved = _FALSE; // always trate as device exists
+ // this will let the driver to disable it's interrupt
+#else
+ if(pci_drvpriv.drv_registered == _TRUE)
+ {
+ //DBG_871X("r871xu_dev_remove():padapter->bSurpriseRemoved == _TRUE\n");
+ padapter->bSurpriseRemoved = _TRUE;
+ }
+ /*else
+ {
+ //DBG_871X("r871xu_dev_remove():module removed\n");
+ padapter->hw_init_completed = _FALSE;
+ }*/
+#endif
+
+
+#ifdef CONFIG_AP_MODE
+ free_mlme_ap_info(padapter);
+#ifdef CONFIG_HOSTAPD_MLME
+ hostapd_mode_unload(padapter);
+#endif //CONFIG_HOSTAPD_MLME
+#endif //CONFIG_AP_MODE
+
+#ifdef CONFIG_CONCURRENT_MODE
+ rtw_drv_if2_free(padapter);
+#endif //CONFIG_CONCURRENT_MODE
+ if(pnetdev){
+ unregister_netdev(pnetdev); //will call netdev_close()
+#ifdef CONFIG_PROC_DEBUG
+ rtw_proc_remove_one(pnetdev);
+#endif
+ }
+
+ rtw_cancel_all_timer(padapter);
+
+ rtw_dev_unload(padapter);
+
+ DBG_871X("+r871xu_dev_remove, hw_init_completed=%d\n", padapter->hw_init_completed);
+
+ if (pdvobjpriv->irq_alloc) {
+ free_irq(pdev->irq, padapter);
+ pdvobjpriv->irq_alloc = 0;
+ }
+
+ if (pdvobjpriv->pci_mem_start != 0) {
+ pci_iounmap(pdev, (void *)pdvobjpriv->pci_mem_start);
+ pci_release_regions(pdev);
+ }
+
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ padapter->HalFunc.inirp_deinit(padapter);
+ //s6.
+ if(padapter->dvobj_deinit)
+ {
+ padapter->dvobj_deinit(padapter);
+ }
+ else
+ {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("Initialize hcipriv.hci_priv_init error!!!\n"));
+ }
+
+ rtw_free_drv_sw(padapter);
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_wdev_free(wdev);
+#endif //CONFIG_IOCTL_CFG80211
+
+ DBG_871X("-r871xu_dev_remove, done\n");
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+ DBG_871X("wlan link down\n");
+ rtd2885_wlan_netlink_sendMsg("linkdown", "8712");
+#endif
+
+_func_exit_;
+
+ return;
+
+}
+
+
+static int __init rtw_drv_entry(void)
+{
+ int ret = 0;
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_drv_entry\n"));
+ DBG_871X("rtw driver version=%s\n", DRIVERVERSION);
+ DBG_871X("Build at: %s %s\n", __DATE__, __TIME__);
+ pci_drvpriv.drv_registered = _TRUE;
+
+
+
+ rtw_suspend_lock_init();
+
+ _rtw_mutex_init(&pci_drvpriv.hw_init_mutex);
+#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
+ //init global variable
+ _rtw_mutex_init(&pci_drvpriv.h2c_fwcmd_mutex);
+ _rtw_mutex_init(&pci_drvpriv.setch_mutex);
+ _rtw_mutex_init(&pci_drvpriv.setbw_mutex);
+#endif
+ ret = pci_register_driver(&pci_drvpriv.rtw_pci_drv);
+ if (ret) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, (": No device found\n"));
+ }
+
+ return ret;
+}
+
+static void __exit rtw_drv_halt(void)
+{
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_drv_halt\n"));
+ DBG_871X("+rtw_drv_halt\n");
+ rtw_suspend_lock_uninit();
+ pci_drvpriv.drv_registered = _FALSE;
+
+ _rtw_mutex_free(&pci_drvpriv.hw_init_mutex);
+#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
+ _rtw_mutex_free(&pci_drvpriv.h2c_fwcmd_mutex);
+ _rtw_mutex_free(&pci_drvpriv.setch_mutex);
+ _rtw_mutex_free(&pci_drvpriv.setbw_mutex);
+#endif
+ pci_unregister_driver(&pci_drvpriv.rtw_pci_drv);
+
+ DBG_871X("-rtw_drv_halt\n");
+}
+
+
+module_init(rtw_drv_entry);
+module_exit(rtw_drv_halt);
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/pci_ops_linux.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/pci_ops_linux.c
new file mode 100755
index 000000000000..7d671df3932c
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/pci_ops_linux.c
@@ -0,0 +1,24 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 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 _PCI_OPS_LINUX_C_
+
+#include <drv_types.h>
+
+
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/recv_linux.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/recv_linux.c
new file mode 100755
index 000000000000..8d11a3fdb538
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/recv_linux.c
@@ -0,0 +1,451 @@
+/******************************************************************************
+ *
+ * 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 _RECV_OSDEP_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#include <wifi.h>
+#include <recv_osdep.h>
+
+#include <osdep_intf.h>
+#include <ethernet.h>
+
+#ifdef CONFIG_USB_HCI
+#include <usb_ops.h>
+#endif
+
+//init os related resource in struct recv_priv
+int rtw_os_recv_resource_init(struct recv_priv *precvpriv, _adapter *padapter)
+{
+ int res=_SUCCESS;
+
+ return res;
+}
+
+//alloc os related resource in union recv_frame
+int rtw_os_recv_resource_alloc(_adapter *padapter, union recv_frame *precvframe)
+{
+ int res=_SUCCESS;
+
+ precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL;
+
+ return res;
+
+}
+
+//free os related resource in union recv_frame
+void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
+{
+
+}
+
+
+//alloc os related resource in struct recv_buf
+int rtw_os_recvbuf_resource_alloc(_adapter *padapter, struct recv_buf *precvbuf)
+{
+ int res=_SUCCESS;
+
+#ifdef CONFIG_USB_HCI
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct usb_device *pusbd = pdvobjpriv->pusbdev;
+
+ precvbuf->irp_pending = _FALSE;
+ precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
+ if(precvbuf->purb == NULL){
+ res = _FAIL;
+ }
+
+ precvbuf->pskb = NULL;
+
+ precvbuf->reuse = _FALSE;
+
+ precvbuf->pallocated_buf = precvbuf->pbuf = NULL;
+
+ precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pend = NULL;
+
+ precvbuf->transfer_len = 0;
+
+ precvbuf->len = 0;
+
+ #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+ precvbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)precvbuf->alloc_sz, GFP_ATOMIC, &precvbuf->dma_transfer_addr);
+ precvbuf->pbuf = precvbuf->pallocated_buf;
+ if(precvbuf->pallocated_buf == NULL)
+ return _FAIL;
+ #endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
+
+#endif //CONFIG_USB_HCI
+
+ return res;
+}
+
+//free os related resource in struct recv_buf
+int rtw_os_recvbuf_resource_free(_adapter *padapter, struct recv_buf *precvbuf)
+{
+ int ret = _SUCCESS;
+
+#ifdef CONFIG_USB_HCI
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct usb_device *pusbd = pdvobjpriv->pusbdev;
+
+ rtw_usb_buffer_free(pusbd, (size_t)precvbuf->alloc_sz, precvbuf->pallocated_buf, precvbuf->dma_transfer_addr);
+ precvbuf->pallocated_buf = NULL;
+ precvbuf->dma_transfer_addr = 0;
+
+#endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
+
+ if(precvbuf->purb)
+ {
+ //usb_kill_urb(precvbuf->purb);
+ usb_free_urb(precvbuf->purb);
+ }
+
+#endif //CONFIG_USB_HCI
+
+
+ if(precvbuf->pskb)
+ dev_kfree_skb_any(precvbuf->pskb);
+
+
+ return ret;
+
+}
+
+void rtw_handle_tkip_mic_err(_adapter *padapter,u8 bgroup)
+{
+#ifdef CONFIG_IOCTL_CFG80211
+ enum nl80211_key_type key_type;
+#endif
+ union iwreq_data wrqu;
+ struct iw_michaelmicfailure ev;
+ struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u32 cur_time = 0;
+
+ if( psecuritypriv->last_mic_err_time == 0 )
+ {
+ psecuritypriv->last_mic_err_time = rtw_get_current_time();
+ }
+ else
+ {
+ cur_time = rtw_get_current_time();
+
+ if( cur_time - psecuritypriv->last_mic_err_time < 60*HZ )
+ {
+ psecuritypriv->btkip_countermeasure = _TRUE;
+ psecuritypriv->last_mic_err_time = 0;
+ psecuritypriv->btkip_countermeasure_time = cur_time;
+ }
+ else
+ {
+ psecuritypriv->last_mic_err_time = rtw_get_current_time();
+ }
+ }
+
+#ifdef CONFIG_IOCTL_CFG80211
+ if ( bgroup )
+ {
+ key_type |= NL80211_KEYTYPE_GROUP;
+ }
+ else
+ {
+ key_type |= NL80211_KEYTYPE_PAIRWISE;
+ }
+
+ cfg80211_michael_mic_failure(padapter->pnetdev, (u8 *)&pmlmepriv->assoc_bssid[ 0 ], key_type, -1,
+ NULL, GFP_ATOMIC);
+#endif
+
+ _rtw_memset( &ev, 0x00, sizeof( ev ) );
+ if ( bgroup )
+ {
+ ev.flags |= IW_MICFAILURE_GROUP;
+ }
+ else
+ {
+ ev.flags |= IW_MICFAILURE_PAIRWISE;
+ }
+
+ ev.src_addr.sa_family = ARPHRD_ETHER;
+ _rtw_memcpy( ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+
+ _rtw_memset( &wrqu, 0x00, sizeof( wrqu ) );
+ wrqu.data.length = sizeof( ev );
+
+ wireless_send_event( padapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu, (char*) &ev );
+}
+
+void rtw_hostapd_mlme_rx(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_HOSTAPD_MLME
+ _pkt *skb;
+ struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
+ struct net_device *pmgnt_netdev = phostapdpriv->pmgnt_netdev;
+
+ RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("+rtw_hostapd_mlme_rx\n"));
+
+ skb = precv_frame->u.hdr.pkt;
+
+ if (skb == NULL)
+ return;
+
+ skb->data = precv_frame->u.hdr.rx_data;
+ skb->tail = precv_frame->u.hdr.rx_tail;
+ skb->len = precv_frame->u.hdr.len;
+
+ //pskb_copy = skb_copy(skb, GFP_ATOMIC);
+// if(skb == NULL) goto _exit;
+
+ skb->dev = pmgnt_netdev;
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->pkt_type = PACKET_OTHERHOST;
+ //skb->protocol = __constant_htons(0x0019); /*ETH_P_80211_RAW*/
+ skb->protocol = __constant_htons(0x0003); /*ETH_P_80211_RAW*/
+
+ //DBG_871X("(1)data=0x%x, head=0x%x, tail=0x%x, mac_header=0x%x, len=%d\n", skb->data, skb->head, skb->tail, skb->mac_header, skb->len);
+
+ //skb->mac.raw = skb->data;
+ skb_reset_mac_header(skb);
+
+ //skb_pull(skb, 24);
+ _rtw_memset(skb->cb, 0, sizeof(skb->cb));
+
+ netif_rx(skb);
+
+ precv_frame->u.hdr.pkt = NULL; // set pointer to NULL before rtw_free_recvframe() if call netif_rx()
+#endif
+}
+
+int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame)
+{
+ struct recv_priv *precvpriv;
+ _queue *pfree_recv_queue;
+ _pkt *skb;
+ struct mlme_priv*pmlmepriv = &padapter->mlmepriv;
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+#endif
+
+#ifdef CONFIG_BR_EXT
+ void *br_port = NULL;
+#endif
+
+_func_enter_;
+
+ precvpriv = &(padapter->recvpriv);
+ pfree_recv_queue = &(precvpriv->free_recv_queue);
+
+#ifdef CONFIG_DRVEXT_MODULE
+ if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS)
+ {
+ goto _recv_indicatepkt_drop;
+ }
+#endif
+
+ skb = precv_frame->u.hdr.pkt;
+ if(skb == NULL)
+ {
+ RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n"));
+ goto _recv_indicatepkt_drop;
+ }
+
+ RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n"));
+ RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head=%p precv_frame->hdr.rx_data=%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data));
+ RT_TRACE(_module_recv_osdep_c_,_drv_info_,("precv_frame->hdr.rx_tail=%p precv_frame->u.hdr.rx_end=%p precv_frame->hdr.len=%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len));
+
+ skb->data = precv_frame->u.hdr.rx_data;
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+ skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
+#else
+ skb->tail = precv_frame->u.hdr.rx_tail;
+#endif
+
+ skb->len = precv_frame->u.hdr.len;
+
+ RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n skb->head=%p skb->data=%p skb->tail=%p skb->end=%p skb->len=%d\n", skb->head, skb->data, skb->tail, skb->end, skb->len));
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+ {
+ _pkt *pskb2=NULL;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+ int bmcast = IS_MCAST(pattrib->dst);
+
+ //DBG_871X("bmcast=%d\n", bmcast);
+
+ if(_rtw_memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)==_FALSE)
+ {
+ //DBG_871X("not ap psta=%p, addr=%pM\n", psta, pattrib->dst);
+
+ if(bmcast)
+ {
+ psta = rtw_get_bcmc_stainfo(padapter);
+ pskb2 = skb_clone(skb, GFP_ATOMIC);
+ } else {
+ psta = rtw_get_stainfo(pstapriv, pattrib->dst);
+ }
+
+ if(psta)
+ {
+ //DBG_871X("directly forwarding to the rtw_xmit_entry\n");
+
+ //skb->ip_summed = CHECKSUM_NONE;
+ //skb->protocol = eth_type_trans(skb, pnetdev);
+
+ skb->dev = padapter->pnetdev;
+ rtw_xmit_entry(skb, padapter->pnetdev);
+
+ if(bmcast)
+ skb = pskb2;
+ else
+ goto _recv_indicatepkt_end;
+ }
+
+
+ }
+ else// to APself
+ {
+ //DBG_871X("to APSelf\n");
+ }
+ }
+
+
+#ifdef CONFIG_BR_EXT
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+ br_port = padapter->pnetdev->br_port;
+#else // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+ rcu_read_lock();
+ br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
+ rcu_read_unlock();
+#endif // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+
+ if( br_port && (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) )
+ {
+ int nat25_handle_frame(_adapter *priv, struct sk_buff *skb);
+ if (nat25_handle_frame(padapter, skb) == -1) {
+ //priv->ext_stats.rx_data_drops++;
+ //DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n");
+ //return FAIL;
+#if 1
+ // bypass this frame to upper layer!!
+#else
+ goto _recv_indicatepkt_drop;
+#endif
+ }
+ }
+
+#endif // CONFIG_BR_EXT
+
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
+ if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ //DBG_871X("CHECKSUM_UNNECESSARY \n");
+ } else {
+ skb->ip_summed = CHECKSUM_NONE;
+ //DBG_871X("CHECKSUM_NONE(%d, %d) \n", pattrib->tcpchk_valid, pattrib->tcp_chkrpt);
+ }
+#else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+#endif
+
+ skb->dev = padapter->pnetdev;
+ skb->protocol = eth_type_trans(skb, padapter->pnetdev);
+
+ netif_rx(skb);
+
+_recv_indicatepkt_end:
+
+ precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe()
+
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+ RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after netif_rx!!!!\n"));
+
+_func_exit_;
+
+ return _SUCCESS;
+
+_recv_indicatepkt_drop:
+
+ //enqueue back to free_recv_queue
+ if(precv_frame)
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+
+ precvpriv->rx_drop++;
+
+ return _FAIL;
+
+_func_exit_;
+
+}
+
+void rtw_os_read_port(_adapter *padapter, struct recv_buf *precvbuf)
+{
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+#ifdef CONFIG_USB_HCI
+
+ precvbuf->ref_cnt--;
+
+ //free skb in recv_buf
+ dev_kfree_skb_any(precvbuf->pskb);
+
+ precvbuf->pskb = NULL;
+ precvbuf->reuse = _FALSE;
+
+ if(precvbuf->irp_pending == _FALSE)
+ {
+ rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+ }
+
+
+#endif
+#ifdef CONFIG_SDIO_HCI
+ precvbuf->pskb = NULL;
+#endif
+
+}
+void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext);
+void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext)
+{
+ struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)FunctionContext;
+ rtw_reordering_ctrl_timeout_handler(preorder_ctrl);
+}
+
+void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
+{
+ _adapter *padapter = preorder_ctrl->padapter;
+
+ _init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, _rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
+
+}
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/rtw_android.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/rtw_android.c
new file mode 100755
index 000000000000..35d415526856
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/rtw_android.c
@@ -0,0 +1,804 @@
+/******************************************************************************
+ *
+ * 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
+ *
+ *
+ ******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+
+#include <rtw_android.h>
+#include <osdep_service.h>
+#include <rtw_debug.h>
+#include <ioctl_cfg80211.h>
+#include <rtw_ioctl_set.h>
+
+
+#if defined(CONFIG_WIFI_CONTROL_FUNC) && 0
+#include <linux/platform_device.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+#include <linux/wlan_plat.h>
+#else
+#include <linux/wifi_tiwlan.h>
+#endif
+#endif /* CONFIG_WIFI_CONTROL_FUNC */
+
+const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
+ "START",
+ "STOP",
+ "SCAN-ACTIVE",
+ "SCAN-PASSIVE",
+ "RSSI",
+ "LINKSPEED",
+ "RXFILTER-START",
+ "RXFILTER-STOP",
+ "RXFILTER-ADD",
+ "RXFILTER-REMOVE",
+ "BTCOEXSCAN-START",
+ "BTCOEXSCAN-STOP",
+ "BTCOEXMODE",
+ "SETSUSPENDOPT",
+ "P2P_DEV_ADDR",
+ "SETFWPATH",
+ "SETBAND",
+ "GETBAND",
+ "COUNTRY",
+ "P2P_SET_NOA",
+ "P2P_GET_NOA",
+ "P2P_SET_PS",
+ "SET_AP_WPS_P2P_IE",
+#ifdef PNO_SUPPORT
+ "PNOSSIDCLR",
+ "PNOSETUP ",
+ "PNOFORCE",
+ "PNODEBUG",
+#endif
+
+ "MACADDR",
+
+ "BLOCK",
+ "WFD-ENABLE",
+ "WFD-DISABLE",
+ "WFD-SET-TCPPORT",
+ "WFD-SET-MAXTPUT",
+ "WFD-SET-DEVTYPE",
+};
+
+#ifdef PNO_SUPPORT
+#define PNO_TLV_PREFIX 'S'
+#define PNO_TLV_VERSION '1'
+#define PNO_TLV_SUBVERSION '2'
+#define PNO_TLV_RESERVED '0'
+#define PNO_TLV_TYPE_SSID_IE 'S'
+#define PNO_TLV_TYPE_TIME 'T'
+#define PNO_TLV_FREQ_REPEAT 'R'
+#define PNO_TLV_FREQ_EXPO_MAX 'M'
+
+typedef struct cmd_tlv {
+ char prefix;
+ char version;
+ char subver;
+ char reserved;
+} cmd_tlv_t;
+#endif /* PNO_SUPPORT */
+
+typedef struct android_wifi_priv_cmd {
+ char *buf;
+ int used_len;
+ int total_len;
+} android_wifi_priv_cmd;
+
+
+/**
+ * Local (static) functions and variables
+ */
+
+/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
+ * time (only) in dhd_open, subsequential wifi on will be handled by
+ * wl_android_wifi_on
+ */
+static int g_wifi_on = _TRUE;
+
+
+#ifdef PNO_SUPPORT
+static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
+{
+ wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+ int res = -1;
+ int nssid = 0;
+ cmd_tlv_t *cmd_tlv_temp;
+ char *str_ptr;
+ int tlv_size_left;
+ int pno_time = 0;
+ int pno_repeat = 0;
+ int pno_freq_expo_max = 0;
+
+#ifdef PNO_SET_DEBUG
+ int i;
+ char pno_in_example[] = {
+ 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
+ 'S', '1', '2', '0',
+ 'S',
+ 0x05,
+ 'd', 'l', 'i', 'n', 'k',
+ 'S',
+ 0x04,
+ 'G', 'O', 'O', 'G',
+ 'T',
+ '0', 'B',
+ 'R',
+ '2',
+ 'M',
+ '2',
+ 0x00
+ };
+#endif /* PNO_SET_DEBUG */
+
+ DHD_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
+
+ if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
+ DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
+ goto exit_proc;
+ }
+
+#ifdef PNO_SET_DEBUG
+ memcpy(command, pno_in_example, sizeof(pno_in_example));
+ for (i = 0; i < sizeof(pno_in_example); i++)
+ printf("%02X ", command[i]);
+ printf("\n");
+ total_len = sizeof(pno_in_example);
+#endif
+
+ str_ptr = command + strlen(CMD_PNOSETUP_SET);
+ tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
+
+ cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
+ memset(ssids_local, 0, sizeof(ssids_local));
+
+ if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
+ (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
+ (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
+
+ str_ptr += sizeof(cmd_tlv_t);
+ tlv_size_left -= sizeof(cmd_tlv_t);
+
+ if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
+ MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
+ DHD_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
+ goto exit_proc;
+ } else {
+ if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
+ DHD_ERROR(("%s scan duration corrupted field size %d\n",
+ __FUNCTION__, tlv_size_left));
+ goto exit_proc;
+ }
+ str_ptr++;
+ pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
+ DHD_INFO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
+
+ if (str_ptr[0] != 0) {
+ if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
+ DHD_ERROR(("%s pno repeat : corrupted field\n",
+ __FUNCTION__));
+ goto exit_proc;
+ }
+ str_ptr++;
+ pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
+ DHD_INFO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
+ if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
+ DHD_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n",
+ __FUNCTION__));
+ goto exit_proc;
+ }
+ str_ptr++;
+ pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
+ DHD_INFO(("%s: pno_freq_expo_max=%d\n",
+ __FUNCTION__, pno_freq_expo_max));
+ }
+ }
+ } else {
+ DHD_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
+ goto exit_proc;
+ }
+
+ res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
+
+exit_proc:
+ return res;
+}
+#endif /* PNO_SUPPORT */
+
+int rtw_android_cmdstr_to_num(char *cmdstr)
+{
+ int cmd_num;
+ for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
+ if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
+ break;
+
+ return cmd_num;
+}
+
+int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_network *pcur_network = &pmlmepriv->cur_network;
+ int bytes_written = 0;
+
+ if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
+ bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
+ pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
+ }
+
+ return bytes_written;
+}
+
+int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_network *pcur_network = &pmlmepriv->cur_network;
+ int bytes_written = 0;
+ u16 link_speed = 0;
+
+ link_speed = rtw_get_cur_max_rate(padapter)/10;
+ bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
+
+ return bytes_written;
+}
+
+int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
+{
+ _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+ int bytes_written = 0;
+
+ bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
+ return bytes_written;
+}
+
+int rtw_android_set_country(struct net_device *net, char *command, int total_len)
+{
+ _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+ char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
+ int ret;
+
+ ret = rtw_set_country(adapter, country_code);
+
+ return (ret==_SUCCESS)?0:-1;
+}
+
+int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
+{
+ int ret;
+ int bytes_written = 0;
+
+ //We use the same address as our HW MAC address
+ _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
+
+ bytes_written = ETH_ALEN;
+ return bytes_written;
+}
+
+int rtw_android_set_block(struct net_device *net, char *command, int total_len)
+{
+ int ret;
+ _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+ char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
+
+ #ifdef CONFIG_IOCTL_CFG80211
+ wdev_to_priv(adapter->rtw_wdev)->block = (*block_value=='0')?_FALSE:_TRUE;
+ #endif
+
+ return 0;
+}
+
+int get_int_from_command( char* pcmd )
+{
+ int i = 0;
+
+ for( i = 0; i < strlen( pcmd ); i++ )
+ {
+ if ( pcmd[ i ] == '=' )
+ {
+ // Skip the '=' and space characters.
+ i += 2;
+ break;
+ }
+ }
+ return ( rtw_atoi( pcmd + i ) );
+}
+
+int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+ int ret = 0;
+ char *command = NULL;
+ int cmd_num;
+ int bytes_written = 0;
+ android_wifi_priv_cmd priv_cmd;
+
+ rtw_lock_suspend();
+
+ if (!ifr->ifr_data) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
+ ret = -EFAULT;
+ goto exit;
+ }
+ command = kmalloc(priv_cmd.total_len, GFP_KERNEL);
+ if (!command)
+ {
+ DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
+ ret = -ENOMEM;
+ goto exit;
+ }
+ if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ DBG_871X("%s: Android private cmd \"%s\" on %s\n"
+ , __FUNCTION__, command, ifr->ifr_name);
+
+ cmd_num = rtw_android_cmdstr_to_num(command);
+
+ switch(cmd_num) {
+ case ANDROID_WIFI_CMD_START:
+ //bytes_written = wl_android_wifi_on(net);
+ goto response;
+ case ANDROID_WIFI_CMD_SETFWPATH:
+ goto response;
+ }
+
+ if (!g_wifi_on) {
+ DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
+ ,__FUNCTION__, command, ifr->ifr_name);
+ ret = 0;
+ goto exit;
+ }
+
+ switch(cmd_num) {
+
+ case ANDROID_WIFI_CMD_STOP:
+ //bytes_written = wl_android_wifi_off(net);
+ break;
+
+ case ANDROID_WIFI_CMD_SCAN_ACTIVE:
+ rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE);
+#ifdef CONFIG_PLATFORM_MSTAR_TITANIA12
+#ifdef CONFIG_IOCTL_CFG80211
+ (wdev_to_priv(net->ieee80211_ptr))->bandroid_scan = _TRUE;
+#endif //CONFIG_IOCTL_CFG80211
+#endif //CONFIG_PLATFORM_MSTAR_TITANIA12
+ break;
+ case ANDROID_WIFI_CMD_SCAN_PASSIVE:
+ rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
+ break;
+
+ case ANDROID_WIFI_CMD_RSSI:
+ bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_LINKSPEED:
+ bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
+ break;
+
+ case ANDROID_WIFI_CMD_MACADDR:
+ bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
+ break;
+
+ case ANDROID_WIFI_CMD_BLOCK:
+ bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
+ break;
+
+ case ANDROID_WIFI_CMD_RXFILTER_START:
+ //bytes_written = net_os_set_packet_filter(net, 1);
+ break;
+ case ANDROID_WIFI_CMD_RXFILTER_STOP:
+ //bytes_written = net_os_set_packet_filter(net, 0);
+ break;
+ case ANDROID_WIFI_CMD_RXFILTER_ADD:
+ //int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
+ //bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
+ break;
+ case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
+ //int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
+ //bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
+ break;
+
+ case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
+ /* TBD: BTCOEXSCAN-START */
+ break;
+ case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
+ /* TBD: BTCOEXSCAN-STOP */
+ break;
+ case ANDROID_WIFI_CMD_BTCOEXMODE:
+ #if 0
+ uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
+ if (mode == 1)
+ net_os_set_packet_filter(net, 0); /* DHCP starts */
+ else
+ net_os_set_packet_filter(net, 1); /* DHCP ends */
+#ifdef WL_CFG80211
+ bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
+#endif
+ #endif
+ break;
+
+ case ANDROID_WIFI_CMD_SETSUSPENDOPT:
+ //bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
+ break;
+
+ case ANDROID_WIFI_CMD_SETBAND:
+ //uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
+ //bytes_written = wldev_set_band(net, band);
+ break;
+ case ANDROID_WIFI_CMD_GETBAND:
+ //bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
+ break;
+
+ case ANDROID_WIFI_CMD_COUNTRY:
+ bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
+ break;
+
+#ifdef PNO_SUPPORT
+ case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
+ //bytes_written = dhd_dev_pno_reset(net);
+ break;
+ case ANDROID_WIFI_CMD_PNOSETUP_SET:
+ //bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_PNOENABLE_SET:
+ //uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
+ //bytes_written = dhd_dev_pno_enable(net, pfn_enabled);
+ break;
+#endif
+
+ case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
+ bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_P2P_SET_NOA:
+ //int skip = strlen(CMD_P2P_SET_NOA) + 1;
+ //bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip);
+ break;
+ case ANDROID_WIFI_CMD_P2P_GET_NOA:
+ //bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_P2P_SET_PS:
+ //int skip = strlen(CMD_P2P_SET_PS) + 1;
+ //bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip);
+ break;
+
+#ifdef CONFIG_IOCTL_CFG80211
+ case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
+ {
+ int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
+ bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
+ break;
+ }
+#endif //CONFIG_IOCTL_CFG80211
+
+#ifdef CONFIG_WFD
+ case ANDROID_WIFI_CMD_WFD_ENABLE:
+ {
+ // Commented by Albert 2012/07/24
+ // We can enable the WFD function by using the following command:
+ // wpa_cli driver wfd-enable
+
+ struct wifi_display_info *pwfd_info;
+ _adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
+
+ pwfd_info = &padapter->wfd_info;
+ pwfd_info->wfd_enable = _TRUE;
+ break;
+ }
+
+ case ANDROID_WIFI_CMD_WFD_DISABLE:
+ {
+ // Commented by Albert 2012/07/24
+ // We can disable the WFD function by using the following command:
+ // wpa_cli driver wfd-disable
+
+ struct wifi_display_info *pwfd_info;
+ _adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
+
+ pwfd_info = &padapter->wfd_info;
+ pwfd_info->wfd_enable = _FALSE;
+ break;
+ }
+ case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
+ {
+ // Commented by Albert 2012/07/24
+ // We can set the tcp port number by using the following command:
+ // wpa_cli driver wfd-set-tcpport = 554
+
+ struct wifi_display_info *pwfd_info;
+ _adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
+
+ pwfd_info = &padapter->wfd_info;
+ pwfd_info->rtsp_ctrlport = ( u16 ) get_int_from_command( priv_cmd.buf );
+ break;
+ }
+ case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
+ {
+
+
+ break;
+ }
+ case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
+ {
+ // Commented by Albert 2012/08/28
+ // Specify the WFD device type ( WFD source/primary sink )
+
+ struct wifi_display_info *pwfd_info;
+ _adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
+
+ pwfd_info = &padapter->wfd_info;
+ pwfd_info->wfd_device_type = ( u8 ) get_int_from_command( priv_cmd.buf );
+
+ if ( ( WFD_DEVINFO_SOURCE != pwfd_info->wfd_device_type ) && ( WFD_DEVINFO_PSINK != pwfd_info->wfd_device_type ) )
+ {
+ pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
+ }
+
+ break;
+ }
+#endif
+ default:
+ DBG_871X("Unknown PRIVATE command %s - ignored\n", command);
+ snprintf(command, 3, "OK");
+ bytes_written = strlen("OK");
+ }
+
+response:
+ if (bytes_written >= 0) {
+ if ((bytes_written == 0) && (priv_cmd.total_len > 0))
+ command[0] = '\0';
+ if (bytes_written >= priv_cmd.total_len) {
+ DBG_871X("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
+ bytes_written = priv_cmd.total_len;
+ } else {
+ bytes_written++;
+ }
+ priv_cmd.used_len = bytes_written;
+ if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
+ DBG_871X("%s: failed to copy data to user buffer\n", __FUNCTION__);
+ ret = -EFAULT;
+ }
+ }
+ else {
+ ret = bytes_written;
+ }
+
+exit:
+ rtw_unlock_suspend();
+ if (command) {
+ kfree(command);
+ }
+
+ return ret;
+}
+
+
+/**
+ * Functions for Android WiFi card detection
+ */
+#if defined(CONFIG_WIFI_CONTROL_FUNC) && 0
+
+static int g_wifidev_registered = 0;
+static struct semaphore wifi_control_sem;
+static struct wifi_platform_data *wifi_control_data = NULL;
+static struct resource *wifi_irqres = NULL;
+
+static int wifi_add_dev(void);
+static void wifi_del_dev(void);
+
+int wl_android_wifictrl_func_add(void)
+{
+ int ret = 0;
+ sema_init(&wifi_control_sem, 0);
+
+ ret = wifi_add_dev();
+ if (ret) {
+ DHD_ERROR(("%s: platform_driver_register failed\n", __FUNCTION__));
+ return ret;
+ }
+ g_wifidev_registered = 1;
+
+ /* Waiting callback after platform_driver_register is done or exit with error */
+ if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
+ ret = -EINVAL;
+ DHD_ERROR(("%s: platform_driver_register timeout\n", __FUNCTION__));
+ }
+
+ return ret;
+}
+
+void wl_android_wifictrl_func_del(void)
+{
+ if (g_wifidev_registered)
+ {
+ wifi_del_dev();
+ g_wifidev_registered = 0;
+ }
+}
+
+void *wl_android_prealloc(int section, unsigned long size)
+{
+ void *alloc_ptr = NULL;
+ if (wifi_control_data && wifi_control_data->mem_prealloc) {
+ alloc_ptr = wifi_control_data->mem_prealloc(section, size);
+ if (alloc_ptr) {
+ DHD_INFO(("success alloc section %d\n", section));
+ if (size != 0L)
+ bzero(alloc_ptr, size);
+ return alloc_ptr;
+ }
+ }
+
+ DHD_ERROR(("can't alloc section %d\n", section));
+ return NULL;
+}
+
+int wifi_get_irq_number(unsigned long *irq_flags_ptr)
+{
+ if (wifi_irqres) {
+ *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
+ return (int)wifi_irqres->start;
+ }
+#ifdef CUSTOM_OOB_GPIO_NUM
+ return CUSTOM_OOB_GPIO_NUM;
+#else
+ return -1;
+#endif
+}
+
+int wifi_set_power(int on, unsigned long msec)
+{
+ DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
+ if (wifi_control_data && wifi_control_data->set_power) {
+ wifi_control_data->set_power(on);
+ }
+ if (msec)
+ msleep(msec);
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+int wifi_get_mac_addr(unsigned char *buf)
+{
+ DHD_ERROR(("%s\n", __FUNCTION__));
+ if (!buf)
+ return -EINVAL;
+ if (wifi_control_data && wifi_control_data->get_mac_addr) {
+ return wifi_control_data->get_mac_addr(buf);
+ }
+ return -EOPNOTSUPP;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
+void *wifi_get_country_code(char *ccode)
+{
+ DHD_TRACE(("%s\n", __FUNCTION__));
+ if (!ccode)
+ return NULL;
+ if (wifi_control_data && wifi_control_data->get_country_code) {
+ return wifi_control_data->get_country_code(ccode);
+ }
+ return NULL;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
+
+static int wifi_set_carddetect(int on)
+{
+ DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
+ if (wifi_control_data && wifi_control_data->set_carddetect) {
+ wifi_control_data->set_carddetect(on);
+ }
+ return 0;
+}
+
+static int wifi_probe(struct platform_device *pdev)
+{
+ struct wifi_platform_data *wifi_ctrl =
+ (struct wifi_platform_data *)(pdev->dev.platform_data);
+
+ DHD_ERROR(("## %s\n", __FUNCTION__));
+ wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
+ if (wifi_irqres == NULL)
+ wifi_irqres = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "bcm4329_wlan_irq");
+ wifi_control_data = wifi_ctrl;
+
+ wifi_set_power(1, 0); /* Power On */
+ wifi_set_carddetect(1); /* CardDetect (0->1) */
+
+ up(&wifi_control_sem);
+ return 0;
+}
+
+static int wifi_remove(struct platform_device *pdev)
+{
+ struct wifi_platform_data *wifi_ctrl =
+ (struct wifi_platform_data *)(pdev->dev.platform_data);
+
+ DHD_ERROR(("## %s\n", __FUNCTION__));
+ wifi_control_data = wifi_ctrl;
+
+ wifi_set_power(0, 0); /* Power Off */
+ wifi_set_carddetect(0); /* CardDetect (1->0) */
+
+ up(&wifi_control_sem);
+ return 0;
+}
+
+static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
+ bcmsdh_oob_intr_set(0);
+#endif
+ return 0;
+}
+
+static int wifi_resume(struct platform_device *pdev)
+{
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
+ if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
+ bcmsdh_oob_intr_set(1);
+#endif
+ return 0;
+}
+
+static struct platform_driver wifi_device = {
+ .probe = wifi_probe,
+ .remove = wifi_remove,
+ .suspend = wifi_suspend,
+ .resume = wifi_resume,
+ .driver = {
+ .name = "bcmdhd_wlan",
+ }
+};
+
+static struct platform_driver wifi_device_legacy = {
+ .probe = wifi_probe,
+ .remove = wifi_remove,
+ .suspend = wifi_suspend,
+ .resume = wifi_resume,
+ .driver = {
+ .name = "bcm4329_wlan",
+ }
+};
+
+static int wifi_add_dev(void)
+{
+ DHD_TRACE(("## Calling platform_driver_register\n"));
+ platform_driver_register(&wifi_device);
+ platform_driver_register(&wifi_device_legacy);
+ return 0;
+}
+
+static void wifi_del_dev(void)
+{
+ DHD_TRACE(("## Unregister platform_driver_register\n"));
+ platform_driver_unregister(&wifi_device);
+ platform_driver_unregister(&wifi_device_legacy);
+}
+#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/sdio_intf.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/sdio_intf.c
new file mode 100755
index 000000000000..53b9acd0efdb
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/sdio_intf.c
@@ -0,0 +1,742 @@
+/******************************************************************************
+ *
+ * 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 _HCI_INTF_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <xmit_osdep.h>
+#include <rtw_version.h>
+
+#ifndef CONFIG_SDIO_HCI
+#error "CONFIG_SDIO_HCI shall be on!\n"
+#endif
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#ifdef CONFIG_RTL8723A
+#include <rtl8723a_hal.h>
+#endif
+
+#include <hal_init.h>
+#include <sdio_hal.h>
+#include <sdio_ops.h>
+
+
+static const struct sdio_device_id sdio_ids[] = {
+ { SDIO_DEVICE(0x024c, 0x8723) },
+// { SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN) },
+// { /* end: all zeroes */ },
+};
+
+struct sdio_drv_priv {
+ struct sdio_driver r871xs_drv;
+
+ _mutex hw_init_mutex;
+};
+
+static void sd_sync_int_hdl(struct sdio_func *func)
+{
+ struct dvobj_priv *psdpriv;
+
+
+ psdpriv = sdio_get_drvdata(func);
+ sd_int_hdl(psdpriv->padapter);
+}
+
+static u32 sdio_init(PADAPTER padapter)
+{
+ struct dvobj_priv *psddev;
+ PSDIO_DATA psdio_data;
+ struct sdio_func *func;
+ int err;
+
+_func_enter_;
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+sdio_init\n"));
+ if (padapter == NULL) {
+ printk(KERN_ERR "%s: padapter is NULL!\n", __func__);
+ err = -1;
+ goto exit;
+ }
+
+ psddev = &padapter->dvobjpriv;
+ psdio_data = &psddev->intf_data;
+ func = psdio_data->func;
+
+ //3 1. init SDIO bus
+ sdio_claim_host(func);
+
+ err = sdio_enable_func(func);
+ if (err) {
+ printk(KERN_CRIT "%s: sdio_enable_func FAIL(%d)!\n", __func__, err);
+ goto release;
+ }
+
+ err = sdio_set_block_size(func, 512);
+ if (err) {
+ printk(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
+ goto release;
+ }
+ psdio_data->block_transfer_len = 512;
+ psdio_data->tx_block_mode = 1;
+ psdio_data->rx_block_mode = 1;
+
+release:
+ sdio_release_host(func);
+
+exit:
+_func_exit_;
+
+ if (err) return _FAIL;
+ return _SUCCESS;
+}
+
+static void sdio_deinit(PADAPTER padapter)
+{
+ struct dvobj_priv *psddev;
+ struct sdio_func *func;
+ int err;
+
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+sdio_deinit\n"));
+
+ if (padapter == NULL) return;
+ psddev = &padapter->dvobjpriv;
+ func = psddev->intf_data.func;
+
+ if (func) {
+ sdio_claim_host(func);
+ err = sdio_disable_func(func);
+ if (err)
+ printk(KERN_ERR "%s: sdio_disable_func(%d)\n", __func__, err);
+ sdio_release_host(func);
+ }
+}
+
+thread_return rtw_xmit_thread(thread_context context)
+{
+ s32 err;
+ PADAPTER padapter;
+
+
+ err = _SUCCESS;
+ padapter = (PADAPTER)context;
+
+#if 0
+ thread_enter(padapter->pnetdev);
+#else
+// daemonize("%s", padapter->pnetdev->name);
+ daemonize("%s", "RTW_XMIT_THREAD");
+ allow_signal(SIGTERM);
+#endif
+
+ do {
+ err = hal_xmit_handler(padapter);
+ if (signal_pending(current)) {
+ flush_signals(current);
+ }
+ } while (_SUCCESS == err);
+
+ _rtw_up_sema(&padapter->xmitpriv.terminate_xmitthread_sema);
+
+ thread_exit();
+}
+
+static void decide_chip_type_by_device_id(PADAPTER padapter, u32 id)
+{
+ padapter->chip_type = NULL_CHIP_TYPE;
+
+ switch (id)
+ {
+ case 0x8723:
+ padapter->chip_type = RTL8188C_8192C;
+ padapter->HardwareType = HARDWARE_TYPE_RTL8723AS;
+ break;
+ }
+}
+
+static void sd_intf_start(PADAPTER padapter)
+{
+ struct dvobj_priv *psddev;
+ struct sdio_func *func;
+ int err;
+
+ if (padapter == NULL) goto exit;
+
+ psddev = &padapter->dvobjpriv;
+ func = psddev->intf_data.func;
+
+ //os/intf dep
+ if (func) {
+ sdio_claim_host(func);
+
+ //according to practice, this is needed...
+ err = sdio_set_block_size(func, 512);
+ if (err) {
+ printk(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
+ goto release_host;
+ }
+ err = sdio_claim_irq(func, &sd_sync_int_hdl);
+ if (err) {
+ printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
+ goto release_host;
+ }
+
+release_host:
+ sdio_release_host(func);
+ }
+
+ //hal dep
+ if (padapter->HalFunc.enable_interrupt)
+ padapter->HalFunc.enable_interrupt(padapter);
+ else {
+ DBG_871X("%s HalFunc.enable_interrupt is %p\n", __FUNCTION__, padapter->HalFunc.enable_interrupt);
+ goto exit;
+ }
+
+exit:
+ return;
+}
+
+static void sd_intf_stop(PADAPTER padapter)
+{
+ struct dvobj_priv *psddev;
+ struct sdio_func *func;
+ int err;
+
+ if (padapter == NULL) goto exit;
+
+ psddev = &padapter->dvobjpriv;
+ func = psddev->intf_data.func;
+
+ //hal dep
+ if (padapter->HalFunc.disable_interrupt)
+ padapter->HalFunc.disable_interrupt(padapter);
+ else
+ {
+ DBG_871X("%s HalFunc.disable_interrupt is %p\n", __FUNCTION__, padapter->HalFunc.disable_interrupt);
+ goto exit;
+ }
+
+ //os/intf dep
+ if (func) {
+ sdio_claim_host(func);
+
+ err = sdio_release_irq(func);
+ if (err)
+ printk(KERN_ERR "%s: sdio_release_irq(%d)\n", __func__, err);
+
+ sdio_release_host(func);
+ }
+
+exit:
+ return;
+}
+
+/*
+ * drv_init() - a device potentially for us
+ *
+ * notes: drv_init() is called when the bus driver has located a card for us to support.
+ * We accept the new device by returning 0.
+ */
+static int rtw_drv_init(
+ struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ struct net_device *pnetdev;
+ PADAPTER padapter;
+ struct dvobj_priv *pdvobjpriv;
+ PSDIO_DATA psdio;
+
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_info_,
+ ("+rtw_drv_init: vendor=0x%04x device=0x%04x class=0x%02x\n",
+ func->vendor, func->device, func->class));
+
+ //3 1. init network device data
+ pnetdev = rtw_init_netdev(NULL);
+ if (!pnetdev) goto error;
+
+ SET_NETDEV_DEV(pnetdev, &func->dev);
+
+ padapter = rtw_netdev_priv(pnetdev);
+ pdvobjpriv = &padapter->dvobjpriv;
+ pdvobjpriv->padapter = padapter;
+ psdio = &pdvobjpriv->intf_data;
+ psdio->func = func;
+
+ //3 2. set interface private data
+ sdio_set_drvdata(func, pdvobjpriv);
+
+ //3 3. init driver special setting, interface, OS and hardware relative
+ // set interface_type to sdio
+ padapter->interface_type = RTW_SDIO;
+ decide_chip_type_by_device_id(padapter, (u32)func->device);
+
+ //4 3.1 set hardware operation functions
+ padapter->HalData = rtw_zmalloc(sizeof(HAL_DATA_TYPE));
+ if (padapter->HalData == NULL) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("rtw_drv_init: can't alloc memory for HAL DATA\n"));
+ goto error;
+ }
+ set_hal_ops(padapter);
+
+ //3 4. interface init
+ if (sdio_init(padapter) != _SUCCESS) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("rtw_drv_init: initialize device object priv Failed!\n"));
+ goto error;
+ }
+ padapter->intf_start = &sd_intf_start;
+ padapter->intf_stop = &sd_intf_stop;
+
+ //3 5. register I/O operations
+ if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL)
+ {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("rtw_drv_init: Can't init io_priv\n"));
+ goto deinit;
+ }
+
+ //3 6.
+ intf_read_chip_version(padapter);
+
+ //3 7.
+ intf_chip_configure(padapter);
+
+ //3 8. read efuse/eeprom data
+ intf_read_chip_info(padapter);
+
+ //3 9. init driver common data
+ if (rtw_init_drv_sw(padapter) == _FAIL) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("rtw_drv_init: Initialize driver software resource Failed!\n"));
+ goto deinit;
+ }
+
+ //3 10. get WLan MAC address
+ // alloc dev name after read efuse.
+ rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
+
+ rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
+ _rtw_memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
+
+ //3 11. Tell the network stack we exist
+ if (register_netdev(pnetdev) != 0) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("rtw_drv_init: register_netdev() failed\n"));
+ goto deinit;
+ }
+
+
+#ifdef CONFIG_PROC_DEBUG
+#ifdef RTK_DMP_PLATFORM
+ rtw_proc_init_one(pnetdev);
+#endif
+#endif
+
+#ifdef CONFIG_HOSTAPD_MLME
+ hostapd_mode_init(padapter);
+#endif
+
+ padapter->hw_init_mutex = &sdio_drvpriv.hw_init_mutex;
+#ifdef CONFIG_CONCURRENT_MODE
+
+ //set global variable to primary adapter
+ padapter->ph2c_fwcmd_mutex = &sdio_drvpriv.h2c_fwcmd_mutex;
+ padapter->psetch_mutex = &sdio_drvpriv.setch_mutex;
+ padapter->psetbw_mutex = &sdio_drvpriv.setbw_mutex;
+ if(rtw_drv_if2_init(padapter, NULL)==NULL)
+ {
+ goto error;
+ }
+#endif
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+ DBG_871X("wlan link up\n");
+ rtd2885_wlan_netlink_sendMsg("linkup", "8712");
+#endif
+
+
+#ifdef CONFIG_GLOBAL_UI_PID
+ if(ui_pid[1]!=0) {
+ DBG_871X("ui_pid[1]:%d\n",ui_pid[1]);
+ rtw_signal_process(ui_pid[1], SIGUSR2);
+ }
+#endif
+
+ DBG_871X("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
+ ,padapter->bDriverStopped
+ ,padapter->bSurpriseRemoved
+ ,padapter->bup
+ ,padapter->hw_init_completed
+ );
+
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_info_,
+ ("-rtw_drv_init: Success. bDriverStopped=%d bSurpriseRemoved=%d\n",
+ padapter->bDriverStopped, padapter->bSurpriseRemoved));
+
+ return 0;
+
+deinit:
+ sdio_deinit(padapter);
+
+error:
+ if (padapter)
+ {
+ if (padapter->HalData) {
+ rtw_mfree(padapter->HalData, sizeof(HAL_DATA_TYPE));
+ padapter->HalData = NULL;
+ }
+ }
+
+ if (pnetdev)
+ rtw_free_netdev(pnetdev);
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_crit_, ("-rtw_drv_init: FAIL!\n"));
+
+ return -1;
+}
+
+/*
+ * Do deinit job corresponding to netdev_open()
+ */
+static void rtw_dev_unload(PADAPTER padapter)
+{
+ struct net_device *pnetdev = (struct net_device*)padapter->pnetdev;
+
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_unload\n"));
+
+ padapter->bDriverStopped = _TRUE;
+
+ if (padapter->bup == _TRUE)
+ {
+ // stop TX
+// val8 = 0xFF;
+// padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_TXPAUSE,&val8);
+
+#if 0
+ if (padapter->intf_stop)
+ padapter->intf_stop(padapter);
+#else
+ sd_intf_stop(padapter);
+#endif
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("@ rtw_dev_unload: stop intf complete!\n"));
+
+ if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
+ rtw_stop_drv_threads(padapter);
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("@ rtw_dev_unload: stop thread complete!\n"));
+
+ if (padapter->bSurpriseRemoved == _FALSE)
+ {
+#ifdef CONFIG_WOWLAN
+ if (padapter->pwrctrlpriv.bSupportWakeOnWlan == _TRUE) {
+ printk("%s bSupportWakeOnWlan==_TRUE do not run rtw_hal_deinit()\n",__FUNCTION__);
+ }
+ else
+#endif
+ {
+ rtw_hal_deinit(padapter);
+ }
+ padapter->bSurpriseRemoved = _TRUE;
+ }
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("@ rtw_dev_unload: deinit hal complelt!\n"));
+
+ padapter->bup = _FALSE;
+ }
+ else {
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_unload: bup==_FALSE\n"));
+ }
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_unload\n"));
+}
+
+static void rtw_dev_remove(struct sdio_func *func)
+{
+ PADAPTER padapter;
+ struct net_device *pnetdev;
+
+_func_enter_;
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_remove\n"));
+
+ padapter = ((struct dvobj_priv*)sdio_get_drvdata(func))->padapter;
+
+#if defined(CONFIG_HAS_EARLYSUSPEND ) || defined(CONFIG_ANDROID_POWER)
+ rtw_unregister_early_suspend(&padapter->pwrctrlpriv);
+#endif
+
+ if (padapter->bSurpriseRemoved == _FALSE)
+ {
+ // test surprise remove
+ int err;
+
+ sdio_claim_host(func);
+ sdio_readb(func, 0, &err);
+ sdio_release_host(func);
+ if (err == -ENOMEDIUM) {
+ padapter->bSurpriseRemoved = _TRUE;
+ printk(KERN_NOTICE "%s: device had been removed!\n", __func__);
+ }
+ }
+
+#ifdef CONFIG_HOSTAPD_MLME
+ hostapd_mode_unload(padapter);
+#endif
+ LeaveAllPowerSaveMode(padapter);
+
+ pnetdev = (struct net_device*)padapter->pnetdev;
+ if (pnetdev) {
+ unregister_netdev(pnetdev); //will call netdev_close()
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_remove: unregister netdev\n"));
+#ifdef CONFIG_PROC_DEBUG
+ rtw_proc_remove_one(pnetdev);
+#endif
+ } else {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("rtw_dev_remove: NO padapter->pnetdev!\n"));
+ }
+
+ rtw_cancel_all_timer(padapter);
+
+ rtw_dev_unload(padapter);
+
+ // interface deinit
+ sdio_deinit(padapter);
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_remove: deinit intf complete!\n"));
+
+ rtw_free_drv_sw(padapter);
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_remove\n"));
+
+_func_exit_;
+}
+
+static int rtw_sdio_suspend(struct device *dev)
+{
+ struct sdio_func *func =dev_to_sdio_func(dev);
+ struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
+ _adapter *padapter = psdpriv->padapter;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct net_device *pnetdev = padapter->pnetdev;
+ int ret = 0;
+ u32 start_time = rtw_get_current_time();
+
+ _func_enter_;
+
+ DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
+
+ if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved))
+ {
+ DBG_871X("%s bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", __FUNCTION__
+ ,padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved);
+ goto exit;
+ }
+
+ pwrpriv->bInSuspend = _TRUE;
+ rtw_cancel_all_timer(padapter);
+ LeaveAllPowerSaveMode(padapter);
+
+ //padapter->net_closed = _TRUE;
+ //s1.
+ if(pnetdev)
+ {
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+ }
+#ifdef CONFIG_WOWLAN
+ padapter->pwrctrlpriv.bSupportWakeOnWlan=_TRUE;
+#else
+ //s2.
+ //s2-1. issue rtw_disassoc_cmd to fw
+ disconnect_hdl(padapter, NULL);
+ //rtw_disassoc_cmd(padapter);
+#endif
+
+#ifdef CONFIG_LAYER2_ROAMING_RESUME
+ if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) )
+ {
+ DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__,
+ pmlmepriv->cur_network.network.Ssid.Ssid,
+ MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
+ pmlmepriv->cur_network.network.Ssid.SsidLength,
+ pmlmepriv->assoc_ssid.SsidLength);
+
+ pmlmepriv->to_roaming = 1;
+ }
+#endif
+ //s2-2. indicate disconnect to os
+ rtw_indicate_disconnect(padapter);
+ //s2-3.
+ rtw_free_assoc_resources(padapter, 1);
+
+ //s2-4.
+ rtw_free_network_queue(padapter, _TRUE);
+
+ rtw_led_control(padapter, LED_CTL_POWER_OFF);
+
+ rtw_dev_unload(padapter);
+
+exit:
+ DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__
+ , ret, rtw_get_passing_time_ms(start_time));
+
+ _func_exit_;
+ return ret;
+}
+
+extern int pm_netdev_open(struct net_device *pnetdev,u8 bnormal);
+int rtw_resume_process(_adapter *padapter)
+{
+ struct net_device *pnetdev;
+ struct pwrctrl_priv *pwrpriv;
+ u8 is_pwrlock_hold_by_caller;
+ u8 is_directly_called_by_auto_resume;
+ int ret = 0;
+ u32 start_time = rtw_get_current_time();
+
+ _func_enter_;
+
+ DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
+
+ if(padapter) {
+ pnetdev= padapter->pnetdev;
+ pwrpriv = &padapter->pwrctrlpriv;
+ } else {
+ ret =-1;
+ goto exit;
+ }
+
+ rtw_reset_drv_sw(padapter);
+ pwrpriv->bkeepfwalive = _FALSE;
+
+ DBG_871X("bkeepfwalive(%x)\n",pwrpriv->bkeepfwalive);
+ if(pm_netdev_open(pnetdev,_TRUE) != 0) {
+ ret = -1;
+ goto exit;
+ }
+
+ netif_device_attach(pnetdev);
+ netif_carrier_on(pnetdev);
+
+ if( padapter->pid[1]!=0) {
+ DBG_871X("pid[1]:%d\n",padapter->pid[1]);
+ rtw_signal_process(padapter->pid[1], SIGUSR2);
+ }
+
+ #ifdef CONFIG_LAYER2_ROAMING_RESUME
+ rtw_roaming(padapter, NULL);
+ #endif
+
+ #ifdef CONFIG_RESUME_IN_WORKQUEUE
+ rtw_unlock_suspend();
+ #endif //CONFIG_RESUME_IN_WORKQUEUE
+
+exit:
+ DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__
+ , ret, rtw_get_passing_time_ms(start_time));
+
+ _func_exit_;
+
+ return ret;
+}
+
+static int rtw_sdio_resume(struct device *dev)
+{
+ struct sdio_func *func =dev_to_sdio_func(dev);
+ struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
+ _adapter *padapter = psdpriv->padapter;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ int ret = 0;
+
+ if(pwrpriv->bInternalAutoSuspend ){
+ ret = rtw_resume_process(padapter);
+ } else {
+#ifdef CONFIG_RESUME_IN_WORKQUEUE
+ rtw_resume_in_workqueue(pwrpriv);
+#elif defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
+ if(rtw_is_earlysuspend_registered(pwrpriv)) {
+ //jeff: bypass resume here, do in late_resume
+ pwrpriv->do_late_resume = _TRUE;
+ } else {
+ ret = rtw_resume_process(padapter);
+ }
+#else // Normal resume process
+ ret = rtw_resume_process(padapter);
+#endif //CONFIG_RESUME_IN_WORKQUEUE
+ }
+
+ return ret;
+
+}
+
+static const struct dev_pm_ops rtw_sdio_pm_ops = {
+ .suspend = rtw_sdio_suspend,
+ .resume = rtw_sdio_resume,
+};
+
+
+static struct sdio_drv_priv sdio_drvpriv = {
+ .r871xs_drv.probe = rtw_drv_init,
+ .r871xs_drv.remove = rtw_dev_remove,
+ .r871xs_drv.name = (char*)DRV_NAME,
+ .r871xs_drv.id_table = sdio_ids,
+
+ .r871xs_drv.drv = {
+ .pm = &rtw_sdio_pm_ops,
+ }
+};
+
+static int __init rtw_drv_entry(void)
+{
+ int ret;
+
+
+// printk(KERN_INFO "+%s", __func__);
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_drv_entry\n"));
+ printk(KERN_NOTICE DRV_NAME " driver version " DRIVERVERSION "\n");
+
+ _rtw_mutex_init(&sdio_drvpriv.hw_init_mutex);
+ ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv);
+// printk(KERN_INFO "-%s: ret=%d", __func__, ret);
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_drv_entry: ret=%d\n", ret));
+
+ return ret;
+}
+
+static void __exit rtw_drv_halt(void)
+{
+// printk(KERN_INFO "+%s", __func__);
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_drv_halt\n"));
+ sdio_unregister_driver(&sdio_drvpriv.r871xs_drv);
+// printk(KERN_INFO "-%s", __func__);
+ _rtw_mutex_free(&sdio_drvpriv.hw_init_mutex);
+ RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_drv_halt\n"));
+}
+
+
+module_init(rtw_drv_entry);
+module_exit(rtw_drv_halt);
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/sdio_ops_linux.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/sdio_ops_linux.c
new file mode 100755
index 000000000000..7cacc1d3d22a
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/sdio_ops_linux.c
@@ -0,0 +1,438 @@
+/******************************************************************************
+ *
+ * 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 _SDIO_OPS_LINUX_C_
+
+#include <drv_types.h>
+
+#include <linux/mmc/sdio_func.h>
+
+
+u8 sd_f0_read8(PSDIO_DATA psdio, u32 addr, s32 *err)
+{
+ u8 v;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ v = sdio_f0_readb(func, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
+
+_func_exit_;
+
+ return v;
+}
+
+void sd_f0_write8(PSDIO_DATA psdio, u32 addr, u8 v, s32 *err)
+{
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ sdio_f0_writeb(func, v, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, *err, addr, v);
+
+_func_exit_;
+}
+
+/*
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 _sd_cmd52_read(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
+{
+ int err, i;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ err = 0;
+ func = psdio->func;
+
+ for (i = 0; i < cnt; i++) {
+ pdata[i] = sdio_readb(func, addr+i, &err);
+ if (err) {
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr);
+ break;
+ }
+ }
+
+_func_exit_;
+
+ return err;
+}
+
+/*
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 sd_cmd52_read(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
+{
+ int err, i;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ err = 0;
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ err = _sd_cmd52_read(psdio, addr, cnt, pdata);
+ sdio_release_host(func);
+
+_func_exit_;
+
+ return err;
+}
+
+/*
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 _sd_cmd52_write(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
+{
+ int err, i;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ err = 0;
+ func = psdio->func;
+
+ for (i = 0; i < cnt; i++) {
+ sdio_writeb(func, pdata[i], addr+i, &err);
+ if (err) {
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, err, addr, pdata[i]);
+ break;
+ }
+ }
+
+_func_exit_;
+
+ return err;
+}
+
+/*
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 sd_cmd52_write(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
+{
+ int err, i;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ err = 0;
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ err = _sd_cmd52_write(psdio, addr, cnt, pdata);
+ sdio_release_host(func);
+
+_func_exit_;
+
+ return err;
+}
+
+u8 sd_read8(PSDIO_DATA psdio, u32 addr, s32 *err)
+{
+ u8 v;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ v = sdio_readb(func, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
+
+_func_exit_;
+
+ return v;
+}
+
+u16 sd_read16(PSDIO_DATA psdio, u32 addr, s32 *err)
+{
+ u16 v;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ v = sdio_readw(func, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
+
+_func_exit_;
+
+ return v;
+}
+
+u32 sd_read32(PSDIO_DATA psdio, u32 addr, s32 *err)
+{
+ u32 v;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ v = sdio_readl(func, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
+
+_func_exit_;
+
+ return v;
+}
+
+void sd_write8(PSDIO_DATA psdio, u32 addr, u8 v, s32 *err)
+{
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ sdio_writeb(func, v, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, *err, addr, v);
+
+_func_exit_;
+}
+
+void sd_write16(PSDIO_DATA psdio, u32 addr, u16 v, s32 *err)
+{
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ sdio_writew(func, v, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%04x\n", __func__, *err, addr, v);
+
+_func_exit_;
+}
+
+void sd_write32(PSDIO_DATA psdio, u32 addr, u32 v, s32 *err)
+{
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ sdio_writel(func, v, addr, err);
+ sdio_release_host(func);
+ if (err && *err)
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%08x\n", __func__, *err, addr, v);
+
+_func_exit_;
+}
+
+/*
+ * Use CMD53 to read data from SDIO device.
+ * This function MUST be called after sdio_claim_host() or
+ * in SDIO ISR(host had been claimed).
+ *
+ * Parameters:
+ * psdio pointer of SDIO_DATA
+ * addr address to read
+ * cnt amount to read
+ * pdata pointer to put data, this should be a "DMA:able scratch buffer"!
+ *
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 _sd_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
+{
+ int err;
+ struct sdio_func *func;
+
+_func_enter_;
+
+ func = psdio->func;
+
+ if (unlikely((cnt==1) || (cnt==2)))
+ {
+ int i;
+ u8 *pbuf = (u8*)pdata;
+
+ for (i = 0; i < cnt; i++)
+ {
+ *(pbuf+i) = sdio_readb(func, addr+i, &err);
+
+ if (err) {
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr);
+ break;
+ }
+ }
+ return err;
+ }
+
+ err = sdio_memcpy_fromio(func, pdata, addr, cnt);
+ if (err) {
+ printk(KERN_ERR "%s: FAIL(%d)! ADDR=%#x Size=%d\n", __func__, err, addr, cnt);
+ }
+
+_func_exit_;
+
+ return err;
+}
+
+/*
+ * Use CMD53 to read data from SDIO device.
+ *
+ * Parameters:
+ * psdio pointer of SDIO_DATA
+ * addr address to read
+ * cnt amount to read
+ * pdata pointer to put data, this should be a "DMA:able scratch buffer"!
+ *
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 sd_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
+{
+ s32 err;
+ struct sdio_func *func;
+
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ err = _sd_read(psdio, addr, cnt, pdata);
+ sdio_release_host(func);
+
+ return err;
+}
+
+/*
+ * Use CMD53 to write data to SDIO device.
+ * This function MUST be called after sdio_claim_host() or
+ * in SDIO ISR(host had been claimed).
+ *
+ * Parameters:
+ * psdio pointer of SDIO_DATA
+ * addr address to write
+ * cnt amount to write
+ * pdata data pointer, this should be a "DMA:able scratch buffer"!
+ *
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 _sd_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
+{
+ int err;
+ struct sdio_func *func;
+ u32 size;
+
+_func_enter_;
+
+ func = psdio->func;
+// size = sdio_align_size(func, cnt);
+
+ if (unlikely((cnt==1) || (cnt==2)))
+ {
+ int i;
+ u8 *pbuf = (u8*)pdata;
+
+ for (i = 0; i < cnt; i++)
+ {
+ sdio_writeb(func, *(pbuf+i), addr+i, &err);
+ if (err) {
+ printk(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, err, addr, *(pbuf+i));
+ break;
+ }
+ }
+
+ return err;
+ }
+
+ size = cnt;
+ err = sdio_memcpy_toio(func, addr, pdata, size);
+ if (err) {
+ printk(KERN_ERR "%s: FAIL(%d)! ADDR=%#x Size=%d(%d)\n", __func__, err, addr, cnt, size);
+ }
+
+_func_exit_;
+
+ return err;
+}
+
+/*
+ * Use CMD53 to write data to SDIO device.
+ *
+ * Parameters:
+ * psdio pointer of SDIO_DATA
+ * addr address to write
+ * cnt amount to write
+ * pdata data pointer, this should be a "DMA:able scratch buffer"!
+ *
+ * Return:
+ * 0 Success
+ * others Fail
+ */
+s32 sd_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
+{
+ s32 err;
+ struct sdio_func *func;
+
+
+ func = psdio->func;
+
+ sdio_claim_host(func);
+ err = _sd_write(psdio, addr, cnt, pdata);
+ sdio_release_host(func);
+
+ return err;
+}
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/usb_intf.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/usb_intf.c
new file mode 100755
index 000000000000..b8d538288a47
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/usb_intf.c
@@ -0,0 +1,1662 @@
+/******************************************************************************
+ *
+ * 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 _HCI_INTF_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <xmit_osdep.h>
+#include <hal_init.h>
+#include <rtw_version.h>
+
+#ifndef CONFIG_USB_HCI
+
+#error "CONFIG_USB_HCI shall be on!\n"
+
+#endif
+
+#include <usb_vendor_req.h>
+#include <usb_ops.h>
+#include <usb_osintf.h>
+#include <usb_hal.h>
+#ifdef CONFIG_PLATFORM_RTK_DMP
+#include <asm/io.h>
+#endif
+
+#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
+
+#error "Shall be Linux or Windows, but not both!\n"
+
+#endif
+
+#ifdef CONFIG_80211N_HT
+extern int rtw_ht_enable;
+extern int rtw_cbw40_enable;
+extern int rtw_ampdu_enable;//for enable tx_ampdu
+#endif
+
+#ifdef CONFIG_GLOBAL_UI_PID
+int ui_pid[3] = {0, 0, 0};
+#endif
+
+
+extern int pm_netdev_open(struct net_device *pnetdev,u8 bnormal);
+static int rtw_suspend(struct usb_interface *intf, pm_message_t message);
+static int rtw_resume(struct usb_interface *intf);
+int rtw_resume_process(_adapter *padapter);
+
+
+static int rtw_drv_init(struct usb_interface *pusb_intf,const struct usb_device_id *pdid);
+static void rtw_dev_remove(struct usb_interface *pusb_intf);
+
+#define USB_VENDER_ID_REALTEK 0x0BDA
+
+//DID_USB_v82_20110808
+static struct usb_device_id rtw_usb_id_tbl[] ={
+#ifdef CONFIG_RTL8192C
+ /*=== Realtek demoboard ===*/
+ {USB_DEVICE(0x0BDA, 0x8191)},//Default ID
+
+ /****** 8188CUS ********/
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8176)},//8188cu 1*1 dongole
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170)},//8188CE-VAU USB minCard
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817E)},//8188CE-VAU USB minCard
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817A)},//8188cu Slim Solo
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817B)},//8188cu Slim Combo
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817D)},//8188RU High-power USB Dongle
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754)},//8188 Combo for BC4
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817F)},//8188RU
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818A)},//RTL8188CUS-VL
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x018A)},//RTL8188CTV
+
+ /****** 8192CUS ********/
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177)},//8191cu 1*2
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8178)},//8192cu 2*2
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817C)},//8192CE-VAU USB minCard
+
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191)},//8192CU 2*2
+ {USB_DEVICE(0x1058, 0x0631)},//Alpha, 8192CU
+
+ /*=== Customer ID ===*/
+ /****** 8188CUS Dongle ********/
+ {USB_DEVICE(0x2019, 0xED17)},//PCI - Edimax
+ {USB_DEVICE(0x0DF6, 0x0052)},//Sitecom - Edimax
+ {USB_DEVICE(0x7392, 0x7811)},//Edimax - Edimax
+ {USB_DEVICE(0x07B8, 0x8189)},//Abocom - Abocom
+ {USB_DEVICE(0x0EB0, 0x9071)},//NO Brand - Etop
+ {USB_DEVICE(0x06F8, 0xE033)},//Hercules - Edimax
+ {USB_DEVICE(0x103C, 0x1629)},//HP - Lite-On ,8188CUS Slim Combo
+ {USB_DEVICE(0x2001, 0x3308)},//D-Link - Alpha
+ {USB_DEVICE(0x050D, 0x1102)},//Belkin - Edimax
+ {USB_DEVICE(0x2019, 0xAB2A)},//Planex - Abocom
+ {USB_DEVICE(0x20F4, 0x648B)},//TRENDnet - Cameo
+ {USB_DEVICE(0x4855, 0x0090)},// - Feixun
+ {USB_DEVICE(0x13D3, 0x3357)},// - AzureWave
+ {USB_DEVICE(0x0DF6, 0x005C)},//Sitecom - Edimax
+ {USB_DEVICE(0x0BDA, 0x5088)},//Thinkware - CC&C
+ {USB_DEVICE(0x4856, 0x0091)},//NetweeN - Feixun
+ {USB_DEVICE(0x2019, 0x4902)},//Planex - Etop
+ {USB_DEVICE(0x2019, 0xAB2E)},//SW-WF02-AD15 -Abocom
+
+ /****** 8188 RU ********/
+ {USB_DEVICE(0x0BDA, 0x317F)},//Netcore,Netcore
+
+ /****** 8188CE-VAU ********/
+ {USB_DEVICE(0x13D3, 0x3359)},// - Azwave
+ {USB_DEVICE(0x13D3, 0x3358)},// - Azwave
+
+ /****** 8188CUS Slim Solo********/
+ {USB_DEVICE(0x04F2, 0xAFF7)},//XAVI - XAVI
+ {USB_DEVICE(0x04F2, 0xAFF9)},//XAVI - XAVI
+ {USB_DEVICE(0x04F2, 0xAFFA)},//XAVI - XAVI
+
+ /****** 8188CUS Slim Combo ********/
+ {USB_DEVICE(0x04F2, 0xAFF8)},//XAVI - XAVI
+ {USB_DEVICE(0x04F2, 0xAFFB)},//XAVI - XAVI
+ {USB_DEVICE(0x04F2, 0xAFFC)},//XAVI - XAVI
+ {USB_DEVICE(0x2019, 0x1201)},//Planex - Vencer
+
+ /****** 8192CUS Dongle ********/
+ {USB_DEVICE(0x2001, 0x3307)},//D-Link - Cameo
+ {USB_DEVICE(0x2001, 0x330A)},//D-Link - Alpha
+ {USB_DEVICE(0x2001, 0x3309)},//D-Link - Alpha
+ {USB_DEVICE(0x0586, 0x341F)},//Zyxel - Abocom
+ {USB_DEVICE(0x7392, 0x7822)},//Edimax - Edimax
+ {USB_DEVICE(0x2019, 0xAB2B)},//Planex - Abocom
+ {USB_DEVICE(0x07B8, 0x8178)},//Abocom - Abocom
+ {USB_DEVICE(0x07AA, 0x0056)},//ATKK - Gemtek
+ {USB_DEVICE(0x4855, 0x0091)},// - Feixun
+ {USB_DEVICE(0x2001, 0x3307)},//D-Link-Cameo
+ {USB_DEVICE(0x050D, 0x2102)},//Belkin - Sercomm
+ {USB_DEVICE(0x050D, 0x2103)},//Belkin - Edimax
+ {USB_DEVICE(0x20F4, 0x624D)},//TRENDnet
+ {USB_DEVICE(0x0DF6, 0x0061)},//Sitecom - Edimax
+ {USB_DEVICE(0x0B05, 0x17AB)},//ASUS - Edimax
+ {USB_DEVICE(0x0846, 0x9021)},//Netgear - Sercomm
+ {USB_DEVICE(0x0E66, 0x0019)},//Hawking,Edimax
+
+ /****** 8192CE-VAU ********/
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8186)},//Intel-Xavi( Azwave)
+#endif
+#ifdef CONFIG_RTL8192D
+ /*=== Realtek demoboard ===*/
+ /****** 8192DU ********/
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8193)},//8192DU-VC
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8194)},//8192DU-VS
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8111)},//Realtek 5G dongle for WiFi Display
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0193)},//8192DE-VAU
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8171)},//8192DU-VC
+
+ /*=== Customer ID ===*/
+ /****** 8192DU-VC ********/
+ {USB_DEVICE(0x2019, 0xAB2C)},//PCI - Abocm
+ {USB_DEVICE(0x2019, 0x4903)},//PCI - ETOP
+ {USB_DEVICE(0x2019, 0x4904)},//PCI - ETOP
+ {USB_DEVICE(0x07B8, 0x8193)},//Abocom - Abocom
+
+ /****** 8192DU-VS ********/
+ {USB_DEVICE(0x20F4, 0x664B)},//TRENDnet
+ {USB_DEVICE(0x0930, 0x0A0A)},//Toshiba - Liteon
+
+ /****** 8192DU-WiFi Display Dongle ********/
+ {USB_DEVICE(0x2019, 0xAB2D)},//Planex - Abocom ,5G dongle for WiFi Display
+#endif
+ {} /* Terminating entry */
+};
+
+int const rtw_usb_id_len = sizeof(rtw_usb_id_tbl) / sizeof(struct usb_device_id);
+
+static struct specific_device_id specific_device_id_tbl[] = {
+ {.idVendor=USB_VENDER_ID_REALTEK, .idProduct=0x8177, .flags=SPEC_DEV_ID_DISABLE_HT},//8188cu 1*1 dongole, (b/g mode only)
+ {.idVendor=USB_VENDER_ID_REALTEK, .idProduct=0x817E, .flags=SPEC_DEV_ID_DISABLE_HT},//8188CE-VAU USB minCard (b/g mode only)
+ {.idVendor=0x0b05, .idProduct=0x1791, .flags=SPEC_DEV_ID_DISABLE_HT},
+ {.idVendor=0x13D3, .idProduct=0x3311, .flags=SPEC_DEV_ID_DISABLE_HT},
+ {.idVendor=0x13D3, .idProduct=0x3359, .flags=SPEC_DEV_ID_DISABLE_HT},//Russian customer -Azwave (8188CE-VAU g mode)
+#ifdef RTK_DMP_PLATFORM
+ {.idVendor=USB_VENDER_ID_REALTEK, .idProduct=0x8111, .flags=SPEC_DEV_ID_ASSIGN_IFNAME}, // Realtek 5G dongle for WiFi Display
+ {.idVendor=0x2019, .idProduct=0xAB2D, .flags=SPEC_DEV_ID_ASSIGN_IFNAME}, // PCI-Abocom 5G dongle for WiFi Display
+#endif /* RTK_DMP_PLATFORM */
+ {}
+};
+
+struct usb_drv_priv {
+ struct usb_driver rtw_usb_drv;
+ int drv_registered;
+
+ _mutex hw_init_mutex;
+#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
+ //global variable
+ _mutex h2c_fwcmd_mutex;
+ _mutex setch_mutex;
+ _mutex setbw_mutex;
+#endif
+};
+
+
+static struct usb_drv_priv usb_drvpriv = {
+ .rtw_usb_drv.name = (char*)DRV_NAME,
+ .rtw_usb_drv.probe = rtw_drv_init,
+ .rtw_usb_drv.disconnect = rtw_dev_remove,
+ .rtw_usb_drv.id_table = rtw_usb_id_tbl,
+ .rtw_usb_drv.suspend = rtw_suspend,
+ .rtw_usb_drv.resume = rtw_resume,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
+ .rtw_usb_drv.reset_resume = rtw_resume,
+#endif
+#ifdef CONFIG_AUTOSUSPEND
+ .rtw_usb_drv.supports_autosuspend = 1,
+#endif
+};
+
+MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
+
+
+static inline int RT_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+static inline int RT_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+static inline int RT_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT);
+}
+
+static inline int RT_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK);
+}
+
+static inline int RT_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_in(epd));
+}
+
+static inline int RT_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+{
+ return (RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_out(epd));
+}
+
+static inline int RT_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (RT_usb_endpoint_xfer_int(epd) && RT_usb_endpoint_dir_in(epd));
+}
+
+static inline int RT_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
+{
+ return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+}
+
+static u8 rtw_init_intf_priv(struct dvobj_priv *dvobj)
+{
+ u8 rst = _SUCCESS;
+
+ #ifdef CONFIG_USB_VENDOR_REQ_MUTEX
+ _rtw_mutex_init(&dvobj->usb_vendor_req_mutex);
+ #endif
+
+
+ #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC
+ dvobj->usb_alloc_vendor_req_buf = rtw_zmalloc(MAX_USB_IO_CTL_SIZE);
+ if (dvobj->usb_alloc_vendor_req_buf == NULL) {
+ printk("alloc usb_vendor_req_buf failed... /n");
+ rst = _FAIL;
+ goto exit;
+ }
+ dvobj->usb_vendor_req_buf =
+ (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(dvobj->usb_alloc_vendor_req_buf ), ALIGNMENT_UNIT);
+exit:
+ #endif
+
+ return rst;
+
+}
+
+static u8 rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
+{
+ u8 rst = _SUCCESS;
+
+ #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC
+ if(dvobj->usb_vendor_req_buf)
+ rtw_mfree(dvobj->usb_alloc_vendor_req_buf, MAX_USB_IO_CTL_SIZE);
+ #endif
+
+ #ifdef CONFIG_USB_VENDOR_REQ_MUTEX
+ _rtw_mutex_free(&dvobj->usb_vendor_req_mutex);
+ #endif
+
+ return rst;
+}
+
+_adapter *pbuddy_padapter=NULL;
+
+static u32 usb_dvobj_init(_adapter *padapter)
+{
+ int i;
+ u8 val8;
+ int status = _SUCCESS;
+ struct usb_device_descriptor *pdev_desc;
+ struct usb_host_config *phost_conf;
+ struct usb_config_descriptor *pconf_desc;
+ struct usb_host_interface *phost_iface;
+ struct usb_interface_descriptor *piface_desc;
+ struct usb_host_endpoint *phost_endp;
+ struct usb_endpoint_descriptor *pendp_desc;
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct usb_device *pusbd = pdvobjpriv->pusbdev;
+ struct usb_interface *pusb_interface = pdvobjpriv->pusbintf;
+
+_func_enter_;
+
+ pdvobjpriv->padapter = padapter;
+
+ pdvobjpriv->RtNumInPipes = 0;
+ pdvobjpriv->RtNumOutPipes = 0;
+
+ //padapter->EepromAddressSize = 6;
+ //pdvobjpriv->nr_endpoint = 6;
+
+ pdev_desc = &pusbd->descriptor;
+
+#if 0
+ DBG_871X("\n8712_usb_device_descriptor:\n");
+ DBG_871X("bLength=%x\n", pdev_desc->bLength);
+ DBG_871X("bDescriptorType=%x\n", pdev_desc->bDescriptorType);
+ DBG_871X("bcdUSB=%x\n", pdev_desc->bcdUSB);
+ DBG_871X("bDeviceClass=%x\n", pdev_desc->bDeviceClass);
+ DBG_871X("bDeviceSubClass=%x\n", pdev_desc->bDeviceSubClass);
+ DBG_871X("bDeviceProtocol=%x\n", pdev_desc->bDeviceProtocol);
+ DBG_871X("bMaxPacketSize0=%x\n", pdev_desc->bMaxPacketSize0);
+ DBG_871X("idVendor=%x\n", pdev_desc->idVendor);
+ DBG_871X("idProduct=%x\n", pdev_desc->idProduct);
+ DBG_871X("bcdDevice=%x\n", pdev_desc->bcdDevice);
+ DBG_871X("iManufacturer=%x\n", pdev_desc->iManufacturer);
+ DBG_871X("iProduct=%x\n", pdev_desc->iProduct);
+ DBG_871X("iSerialNumber=%x\n", pdev_desc->iSerialNumber);
+ DBG_871X("bNumConfigurations=%x\n", pdev_desc->bNumConfigurations);
+#endif
+
+ phost_conf = pusbd->actconfig;
+ pconf_desc = &phost_conf->desc;
+
+#if 0
+ DBG_871X("\n8712_usb_configuration_descriptor:\n");
+ DBG_871X("bLength=%x\n", pconf_desc->bLength);
+ DBG_871X("bDescriptorType=%x\n", pconf_desc->bDescriptorType);
+ DBG_871X("wTotalLength=%x\n", pconf_desc->wTotalLength);
+ DBG_871X("bNumInterfaces=%x\n", pconf_desc->bNumInterfaces);
+ DBG_871X("bConfigurationValue=%x\n", pconf_desc->bConfigurationValue);
+ DBG_871X("iConfiguration=%x\n", pconf_desc->iConfiguration);
+ DBG_871X("bmAttributes=%x\n", pconf_desc->bmAttributes);
+ DBG_871X("bMaxPower=%x\n", pconf_desc->bMaxPower);
+#endif
+
+ //DBG_871X("\n/****** num of altsetting = (%d) ******/\n", pusb_interface->num_altsetting);
+
+ phost_iface = &pusb_interface->altsetting[0];
+ piface_desc = &phost_iface->desc;
+
+#if 0
+ DBG_871X("\n8712_usb_interface_descriptor:\n");
+ DBG_871X("bLength=%x\n", piface_desc->bLength);
+ DBG_871X("bDescriptorType=%x\n", piface_desc->bDescriptorType);
+ DBG_871X("bInterfaceNumber=%x\n", piface_desc->bInterfaceNumber);
+ DBG_871X("bAlternateSetting=%x\n", piface_desc->bAlternateSetting);
+ DBG_871X("bNumEndpoints=%x\n", piface_desc->bNumEndpoints);
+ DBG_871X("bInterfaceClass=%x\n", piface_desc->bInterfaceClass);
+ DBG_871X("bInterfaceSubClass=%x\n", piface_desc->bInterfaceSubClass);
+ DBG_871X("bInterfaceProtocol=%x\n", piface_desc->bInterfaceProtocol);
+ DBG_871X("iInterface=%x\n", piface_desc->iInterface);
+#endif
+
+ pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
+ pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
+ pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
+
+ //DBG_871X("\ndump usb_endpoint_descriptor:\n");
+
+ for (i = 0; i < pdvobjpriv->nr_endpoint; i++)
+ {
+ phost_endp = phost_iface->endpoint + i;
+ if (phost_endp)
+ {
+ pendp_desc = &phost_endp->desc;
+
+ DBG_871X("\nusb_endpoint_descriptor(%d):\n", i);
+ DBG_871X("bLength=%x\n",pendp_desc->bLength);
+ DBG_871X("bDescriptorType=%x\n",pendp_desc->bDescriptorType);
+ DBG_871X("bEndpointAddress=%x\n",pendp_desc->bEndpointAddress);
+ //DBG_871X("bmAttributes=%x\n",pendp_desc->bmAttributes);
+ //DBG_871X("wMaxPacketSize=%x\n",pendp_desc->wMaxPacketSize);
+ DBG_871X("wMaxPacketSize=%x\n",le16_to_cpu(pendp_desc->wMaxPacketSize));
+ DBG_871X("bInterval=%x\n",pendp_desc->bInterval);
+ //DBG_871X("bRefresh=%x\n",pendp_desc->bRefresh);
+ //DBG_871X("bSynchAddress=%x\n",pendp_desc->bSynchAddress);
+
+ if (RT_usb_endpoint_is_bulk_in(pendp_desc))
+ {
+ DBG_871X("RT_usb_endpoint_is_bulk_in = %x\n", RT_usb_endpoint_num(pendp_desc));
+ pdvobjpriv->RtNumInPipes++;
+ }
+ else if (RT_usb_endpoint_is_int_in(pendp_desc))
+ {
+ DBG_871X("RT_usb_endpoint_is_int_in = %x, Interval = %x\n", RT_usb_endpoint_num(pendp_desc),pendp_desc->bInterval);
+ pdvobjpriv->RtNumInPipes++;
+ }
+ else if (RT_usb_endpoint_is_bulk_out(pendp_desc))
+ {
+ DBG_871X("RT_usb_endpoint_is_bulk_out = %x\n", RT_usb_endpoint_num(pendp_desc));
+ pdvobjpriv->RtNumOutPipes++;
+ }
+ pdvobjpriv->ep_num[i] = RT_usb_endpoint_num(pendp_desc);
+ }
+ }
+
+ DBG_871X("nr_endpoint=%d, in_num=%d, out_num=%d\n\n", pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes, pdvobjpriv->RtNumOutPipes);
+
+ if (pusbd->speed == USB_SPEED_HIGH)
+ {
+ pdvobjpriv->ishighspeed = _TRUE;
+ DBG_871X("USB_SPEED_HIGH\n");
+ }
+ else
+ {
+ pdvobjpriv->ishighspeed = _FALSE;
+ DBG_871X("NON USB_SPEED_HIGH\n");
+ }
+
+ // For SMSP on 92DU-VC, driver do not probe another Interface.
+ if(padapter->dvobjpriv.NumInterfaces == 2 &&
+ padapter->registrypriv.mac_phy_mode == 1 &&
+ padapter->dvobjpriv.InterfaceNumber != 0)
+ {
+ DBG_871X("%s(): Do not init another USB Interface because SMSP\n",__FUNCTION__);
+ status = _FAIL;
+ return status;
+ }
+
+ //.2
+ if ((rtw_init_io_priv(padapter, usb_set_intf_ops)) == _FAIL)
+ {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,(" \n Can't init io_reqs\n"));
+ status = _FAIL;
+ return status;
+ }
+
+ if(rtw_init_intf_priv(pdvobjpriv) == _FAIL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("\n Can't INIT rtw_init_intf_priv\n"));
+ status = _FAIL;
+ return status;
+ }
+
+ //.3 misc
+ _rtw_init_sema(&(padapter->dvobjpriv.usb_suspend_sema), 0);
+
+ intf_read_chip_version(padapter);
+
+ //.4 usb endpoint mapping
+ intf_chip_configure(padapter);
+
+ rtw_reset_continual_urb_error(pdvobjpriv);
+
+ if(pbuddy_padapter == NULL)
+ {
+ pbuddy_padapter = padapter;
+ DBG_871X("%s(): pbuddy_padapter == NULL, Set pbuddy_padapter\n",__FUNCTION__);
+ }
+ else
+ {
+ padapter->pbuddy_adapter = pbuddy_padapter;
+ pbuddy_padapter->pbuddy_adapter = padapter;
+ // clear global value
+ pbuddy_padapter = NULL;
+ DBG_871X("%s(): pbuddy_padapter exist, Exchange Information\n",__FUNCTION__);
+ }
+
+#ifdef CONFIG_DUALMAC_CONCURRENT
+ if(pdvobjpriv->InterfaceNumber == 0)
+ {
+ //set adapter_type/iface type
+ padapter->isprimary = _TRUE;
+ padapter->adapter_type = PRIMARY_ADAPTER;
+
+ padapter->iface_type = IFACE_PORT0;
+
+ DBG_871X("%s(): PRIMARY_ADAPTER\n",__FUNCTION__);
+ }
+ else
+ {
+ //set adapter_type/iface type
+ padapter->isprimary = _FALSE;
+ padapter->adapter_type = SECONDARY_ADAPTER;
+
+ padapter->iface_type = IFACE_PORT1;//
+
+ DBG_871X("%s(): SECONDARY_ADAPTER\n",__FUNCTION__);
+ }
+#endif
+
+_func_exit_;
+
+ return status;
+}
+
+static void usb_dvobj_deinit(_adapter * padapter){
+
+ struct dvobj_priv *pdvobjpriv=&padapter->dvobjpriv;
+
+ _func_enter_;
+
+ pbuddy_padapter = NULL;
+
+ rtw_deinit_intf_priv(pdvobjpriv);
+
+ _func_exit_;
+}
+
+static void decide_chip_type_by_usb_device_id(_adapter *padapter, const struct usb_device_id *pdid)
+{
+ //u32 i;
+ //u16 vid, pid;
+
+ padapter->chip_type = NULL_CHIP_TYPE;
+
+ //vid = pdid->idVendor;
+ //pid = pdid->idProduct;
+
+ //TODO: dynamic judge 92c or 92d according to usb vid and pid.
+#ifdef CONFIG_RTL8192C
+ padapter->chip_type = RTL8188C_8192C;
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192CU;
+ DBG_871X("CHIP TYPE: RTL8188C_8192C\n");
+#endif
+
+#ifdef CONFIG_RTL8192D
+ padapter->chip_type = RTL8192D;
+ padapter->HardwareType = HARDWARE_TYPE_RTL8192DU;
+ DBG_871X("CHIP TYPE: RTL8192D\n");
+#endif
+
+}
+
+static void usb_intf_start(_adapter *padapter)
+{
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+usb_intf_start\n"));
+
+ if(padapter->HalFunc.inirp_init == NULL)
+ {
+ RT_TRACE(_module_os_intfs_c_,_drv_err_,("Initialize dvobjpriv.inirp_init error!!!\n"));
+ }
+ else
+ {
+ padapter->HalFunc.inirp_init(padapter);
+ }
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-usb_intf_start\n"));
+
+}
+
+static void usb_intf_stop(_adapter *padapter)
+{
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+usb_intf_stop\n"));
+
+ //disabel_hw_interrupt
+ if(padapter->bSurpriseRemoved == _FALSE)
+ {
+ //device still exists, so driver can do i/o operation
+ //TODO:
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("SurpriseRemoved==_FALSE\n"));
+ }
+
+ //cancel in irp
+ if(padapter->HalFunc.inirp_deinit !=NULL)
+ {
+ padapter->HalFunc.inirp_deinit(padapter);
+ }
+
+ //cancel out irp
+ rtw_write_port_cancel(padapter);
+
+ //todo:cancel other irps
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-usb_intf_stop\n"));
+
+}
+
+static void rtw_dev_unload(_adapter *padapter)
+{
+ struct net_device *pnetdev= (struct net_device*)padapter->pnetdev;
+ u8 val8;
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_dev_unload\n"));
+
+ if(padapter->bup == _TRUE)
+ {
+ DBG_871X("===> rtw_dev_unload\n");
+
+ padapter->bDriverStopped = _TRUE;
+
+ //s3.
+ if(padapter->intf_stop)
+ {
+ padapter->intf_stop(padapter);
+ }
+
+ //s4.
+ if(!padapter->pwrctrlpriv.bInternalAutoSuspend )
+ rtw_stop_drv_threads(padapter);
+
+
+ //s5.
+ if(padapter->bSurpriseRemoved == _FALSE)
+ {
+ //DBG_871X("r871x_dev_unload()->rtl871x_hal_deinit()\n");
+#ifdef CONFIG_WOWLAN
+ if((padapter->pwrctrlpriv.bSupportRemoteWakeup==_TRUE)&&(padapter->pwrctrlpriv.wowlan_mode==_TRUE)){
+ DBG_871X("%s bSupportWakeOnWlan==_TRUE do not run rtw_hal_deinit()\n",__FUNCTION__);
+ }
+ else
+#endif //CONFIG_WOWLAN
+ {
+ rtw_hal_deinit(padapter);
+ }
+ padapter->bSurpriseRemoved = _TRUE;
+ }
+
+ padapter->bup = _FALSE;
+#ifdef CONFIG_WOWLAN
+ padapter->hw_init_completed=_FALSE;
+#endif //CONFIG_WOWLAN
+ }
+ else
+ {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("r871x_dev_unload():padapter->bup == _FALSE\n" ));
+ }
+
+ DBG_871X("<=== rtw_dev_unload\n");
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-rtw_dev_unload\n"));
+
+}
+
+static void process_spec_devid(const struct usb_device_id *pdid)
+{
+ u16 vid, pid;
+ u32 flags;
+ int i;
+ int num = sizeof(specific_device_id_tbl)/sizeof(struct specific_device_id);
+
+ for(i=0; i<num; i++)
+ {
+ vid = specific_device_id_tbl[i].idVendor;
+ pid = specific_device_id_tbl[i].idProduct;
+ flags = specific_device_id_tbl[i].flags;
+
+#ifdef CONFIG_80211N_HT
+ if((pdid->idVendor==vid) && (pdid->idProduct==pid) && (flags&SPEC_DEV_ID_DISABLE_HT))
+ {
+ rtw_ht_enable = 0;
+ rtw_cbw40_enable = 0;
+ rtw_ampdu_enable = 0;
+ }
+#endif
+
+#ifdef RTK_DMP_PLATFORM
+ // Change the ifname to wlan10 when PC side WFD dongle plugin on DMP platform.
+ // It is used to distinguish between normal and PC-side wifi dongle/module.
+ if((pdid->idVendor==vid) && (pdid->idProduct==pid) && (flags&SPEC_DEV_ID_ASSIGN_IFNAME))
+ {
+ extern char* ifname;
+ strncpy(ifname, "wlan10", 6);
+ //DBG_871X("%s()-%d: ifname=%s, vid=%04X, pid=%04X\n", __FUNCTION__, __LINE__, ifname, vid, pid);
+ }
+#endif /* RTK_DMP_PLATFORM */
+
+ }
+}
+
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+extern u8 disconnect_hdl(_adapter *padapter, u8 *pbuf);
+extern void rtw_os_indicate_disconnect( _adapter *adapter );
+
+int rtw_hw_suspend(_adapter *padapter )
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct usb_interface *pusb_intf = padapter->dvobjpriv.pusbintf;
+ struct net_device *pnetdev = padapter->pnetdev;
+
+ _func_enter_;
+
+ if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved))
+ {
+ DBG_871X("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
+ padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved);
+ goto error_exit;
+ }
+
+ if(padapter)//system suspend
+ {
+ LeaveAllPowerSaveMode(padapter);
+
+ DBG_871X("==> rtw_hw_suspend\n");
+ _enter_pwrlock(&pwrpriv->lock);
+ pwrpriv->bips_processing = _TRUE;
+ //padapter->net_closed = _TRUE;
+ //s1.
+ if(pnetdev)
+ {
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+ }
+
+ //s2.
+ //s2-1. issue rtw_disassoc_cmd to fw
+ //rtw_disassoc_cmd(padapter);//donnot enqueue cmd
+ disconnect_hdl(padapter, NULL);
+
+ //s2-2. indicate disconnect to os
+ //rtw_indicate_disconnect(padapter);
+ {
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if(check_fwstate(pmlmepriv, _FW_LINKED))
+ {
+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+ rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+ rtw_os_indicate_disconnect(padapter);
+
+ #ifdef CONFIG_LPS
+ //donnot enqueue cmd
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
+ #endif
+ }
+
+ }
+ //s2-3.
+ rtw_free_assoc_resources(padapter, 1);
+
+ //s2-4.
+ rtw_free_network_queue(padapter,_TRUE);
+ #ifdef CONFIG_IPS
+ rtw_ips_dev_unload(padapter);
+ #endif
+ pwrpriv->rf_pwrstate = rf_off;
+ pwrpriv->bips_processing = _FALSE;
+
+ _exit_pwrlock(&pwrpriv->lock);
+ }
+ else
+ goto error_exit;
+
+ _func_exit_;
+ return 0;
+
+error_exit:
+ DBG_871X("%s, failed \n",__FUNCTION__);
+ return (-1);
+
+}
+
+int rtw_hw_resume(_adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct usb_interface *pusb_intf = padapter->dvobjpriv.pusbintf;
+ struct net_device *pnetdev = padapter->pnetdev;
+
+ _func_enter_;
+
+ if(padapter)//system resume
+ {
+ DBG_871X("==> rtw_hw_resume\n");
+ _enter_pwrlock(&pwrpriv->lock);
+ pwrpriv->bips_processing = _TRUE;
+ rtw_reset_drv_sw(padapter);
+
+ if(pm_netdev_open(pnetdev,_FALSE) != 0)
+ {
+ _exit_pwrlock(&pwrpriv->lock);
+ goto error_exit;
+ }
+
+ netif_device_attach(pnetdev);
+ netif_carrier_on(pnetdev);
+
+ if(!netif_queue_stopped(pnetdev))
+ netif_start_queue(pnetdev);
+ else
+ netif_wake_queue(pnetdev);
+
+ pwrpriv->bkeepfwalive = _FALSE;
+ pwrpriv->brfoffbyhw = _FALSE;
+
+ pwrpriv->rf_pwrstate = rf_on;
+ pwrpriv->bips_processing = _FALSE;
+
+ _exit_pwrlock(&pwrpriv->lock);
+ }
+ else
+ {
+ goto error_exit;
+ }
+
+ _func_exit_;
+
+ return 0;
+error_exit:
+ DBG_871X("%s, Open net dev failed \n",__FUNCTION__);
+ return (-1);
+}
+#endif
+
+static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ _adapter *padapter = dvobj->padapter;
+ struct net_device *pnetdev = padapter->pnetdev;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct usb_device *usb_dev = interface_to_usbdev(pusb_intf);
+#ifdef CONFIG_WOWLAN
+ struct wowlan_ioctl_param poidparam;
+#endif // CONFIG_WOWLAN
+ _func_enter_;
+
+ if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved))
+ {
+ DBG_871X("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
+ padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved);
+ return 0;
+ }
+
+ DBG_871X("########### rtw_suspend #################\n");
+
+ if(padapter)//system suspend
+ {
+ if(pwrpriv->bInternalAutoSuspend )
+ {
+ #ifdef CONFIG_AUTOSUSPEND
+ #ifdef SUPPORT_HW_RFOFF_DETECTED
+ // The FW command register update must after MAC and FW init ready.
+ if((padapter->bFWReady) && ( padapter->pwrctrlpriv.bHWPwrPindetect ) && (padapter->registrypriv.usbss_enable ))
+ {
+ u8 bOpen = _TRUE;
+ rtw_interface_ps_func(padapter,HAL_USB_SELECT_SUSPEND,&bOpen);
+ //rtl8192c_set_FwSelectSuspend_cmd(padapter,_TRUE ,500);//note fw to support hw power down ping detect
+ }
+ #endif
+ #endif
+ }
+ pwrpriv->bInSuspend = _TRUE;
+ rtw_cancel_all_timer(padapter);
+ LeaveAllPowerSaveMode(padapter);
+
+ _enter_pwrlock(&pwrpriv->lock);
+ //padapter->net_closed = _TRUE;
+ //s1.
+ if(pnetdev)
+ {
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+ }
+#ifdef CONFIG_WOWLAN
+ if(padapter->pwrctrlpriv.bSupportRemoteWakeup==_TRUE&&padapter->pwrctrlpriv.wowlan_mode==_TRUE){
+ u8 ps_mode=PS_MODE_MIN;
+ //set H2C command
+ poidparam.subcode=WOWLAN_ENABLE;
+ padapter->HalFunc.SetHwRegHandler(padapter,HW_VAR_WOWLAN,(u8 *)&poidparam);
+ //padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_H2C_FW_PWRMODE, &ps_mode);
+ //rtw_set_rpwm(padapter, PS_STATE_S2);
+ }
+ else
+#endif //CONFIG_WOWLAN
+ {
+ //s2.
+ //s2-1. issue rtw_disassoc_cmd to fw
+ disconnect_hdl(padapter, NULL);
+ //rtw_disassoc_cmd(padapter);
+ }
+
+#ifdef CONFIG_LAYER2_ROAMING_RESUME
+ if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) )
+ {
+ //printk("%s:%d assoc_ssid:%s\n", __FUNCTION__, __LINE__, pmlmepriv->assoc_ssid.Ssid);
+ DBG_871X("%s:%d %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__, __LINE__,
+ pmlmepriv->cur_network.network.Ssid.Ssid,
+ MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
+ pmlmepriv->cur_network.network.Ssid.SsidLength,
+ pmlmepriv->assoc_ssid.SsidLength);
+
+ pmlmepriv->to_roaming = 1;
+ }
+#endif
+ //s2-2. indicate disconnect to os
+ rtw_indicate_disconnect(padapter);
+ //s2-3.
+ rtw_free_assoc_resources(padapter, 1);
+#ifdef CONFIG_AUTOSUSPEND
+ if(!pwrpriv->bInternalAutoSuspend )
+#endif
+ //s2-4.
+ rtw_free_network_queue(padapter, _TRUE);
+
+ rtw_dev_unload(padapter);
+#ifdef CONFIG_AUTOSUSPEND
+ pwrpriv->rf_pwrstate = rf_off;
+ pwrpriv->bips_processing = _FALSE;
+#endif
+ _exit_pwrlock(&pwrpriv->lock);
+
+ if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ rtw_indicate_scan_done(padapter, 1);
+
+ if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+ rtw_indicate_disconnect(padapter);
+ }
+ else
+ goto error_exit;
+
+ DBG_871X("########### rtw_suspend done #################\n");
+
+ _func_exit_;
+ return 0;
+
+error_exit:
+ DBG_871X("########### rtw_suspend fail !! #################\n");
+ return (-1);
+
+}
+
+static int rtw_resume(struct usb_interface *pusb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ _adapter *padapter = dvobj->padapter;
+ struct net_device *pnetdev = padapter->pnetdev;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ int ret = 0;
+
+ if(pwrpriv->bInternalAutoSuspend ){
+ ret = rtw_resume_process(padapter);
+ } else {
+#ifdef CONFIG_RESUME_IN_WORKQUEUE
+ rtw_resume_in_workqueue(pwrpriv);
+#elif defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
+ if(rtw_is_earlysuspend_registered(pwrpriv)) {
+ //jeff: bypass resume here, do in late_resume
+ pwrpriv->do_late_resume = _TRUE;
+ } else {
+ ret = rtw_resume_process(padapter);
+ }
+#else // Normal resume process
+ ret = rtw_resume_process(padapter);
+#endif //CONFIG_RESUME_IN_WORKQUEUE
+ }
+
+ return ret;
+
+}
+
+int rtw_resume_process(_adapter *padapter)
+{
+ struct net_device *pnetdev;
+ struct pwrctrl_priv *pwrpriv;
+
+ _func_enter_;
+
+ DBG_871X("########### rtw_resume #################\n");
+
+ if(padapter) {
+ pnetdev= padapter->pnetdev;
+ pwrpriv = &padapter->pwrctrlpriv;
+ } else {
+ goto error_exit;
+ }
+
+
+ if(padapter)//system resume
+ {
+ _enter_pwrlock(&pwrpriv->lock);
+ rtw_reset_drv_sw(padapter);
+ pwrpriv->bkeepfwalive = _FALSE;
+
+ DBG_871X("bkeepfwalive(%x)\n",pwrpriv->bkeepfwalive);
+ if(pm_netdev_open(pnetdev,_TRUE) != 0)
+ goto error_exit;
+
+ netif_device_attach(pnetdev);
+ netif_carrier_on(pnetdev);
+
+#ifdef CONFIG_AUTOSUSPEND
+ if(pwrpriv->bInternalAutoSuspend )
+ {
+ #ifdef CONFIG_AUTOSUSPEND
+ #ifdef SUPPORT_HW_RFOFF_DETECTED
+ // The FW command register update must after MAC and FW init ready.
+ if((padapter->bFWReady) && ( padapter->pwrctrlpriv.bHWPwrPindetect ) && (padapter->registrypriv.usbss_enable ))
+ {
+ //rtl8192c_set_FwSelectSuspend_cmd(padapter,_FALSE ,500);//note fw to support hw power down ping detect
+ u8 bOpen = _FALSE;
+ rtw_interface_ps_func(padapter,HAL_USB_SELECT_SUSPEND,&bOpen);
+ }
+ #endif
+ #endif
+
+ pwrpriv->bInternalAutoSuspend = _FALSE;
+ pwrpriv->brfoffbyhw = _FALSE;
+ {
+ DBG_871X("enc_algorithm(%x),wepkeymask(%x)\n",
+ padapter->securitypriv.dot11PrivacyAlgrthm,pwrpriv->wepkeymask);
+ if( (_WEP40_ == padapter->securitypriv.dot11PrivacyAlgrthm) ||
+ (_WEP104_ == padapter->securitypriv.dot11PrivacyAlgrthm))
+ {
+ sint keyid;
+
+ for(keyid=0;keyid<4;keyid++){
+ if(pwrpriv->wepkeymask & BIT(keyid)) {
+ if(keyid == padapter->securitypriv.dot11PrivacyKeyIndex)
+ rtw_set_key(padapter,&padapter->securitypriv, keyid, 1);
+ else
+ rtw_set_key(padapter,&padapter->securitypriv, keyid, 0);
+ }
+ }
+ }
+ }
+ }
+#endif
+ _exit_pwrlock(&pwrpriv->lock);
+ }
+ else
+ {
+ goto error_exit;
+ }
+
+ if( padapter->pid[1]!=0) {
+ DBG_871X("pid[1]:%d\n",padapter->pid[1]);
+ rtw_signal_process(padapter->pid[1], SIGUSR2);
+ }
+
+ #ifdef CONFIG_LAYER2_ROAMING_RESUME
+ rtw_roaming(padapter, NULL);
+ #endif
+
+ DBG_871X("########### rtw_resume done#################\n");
+
+ #ifdef CONFIG_RESUME_IN_WORKQUEUE
+ rtw_unlock_suspend();
+ #endif //CONFIG_RESUME_IN_WORKQUEUE
+
+ _func_exit_;
+
+ return 0;
+error_exit:
+ DBG_871X("%s, Open net dev failed \n",__FUNCTION__);
+
+ DBG_871X("########### rtw_resume done with error#################\n");
+
+ #ifdef CONFIG_RESUME_IN_WORKQUEUE
+ rtw_unlock_suspend();
+ #endif //CONFIG_RESUME_IN_WORKQUEUE
+
+ _func_exit_;
+
+ return (-1);
+}
+
+#ifdef CONFIG_AUTOSUSPEND
+void autosuspend_enter(_adapter* padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ pwrpriv->bInternalAutoSuspend = _TRUE;
+ pwrpriv->bips_processing = _TRUE;
+
+ DBG_871X("==>autosuspend_enter...........\n");
+
+ if(rf_off == pwrpriv->change_rfpwrstate )
+ {
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+ usb_enable_autosuspend(padapter->dvobjpriv.pusbdev);
+ #else
+ padapter->dvobjpriv.pusbdev->autosuspend_disabled = 0;//autosuspend disabled by the user
+ #endif
+
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,33))
+ usb_autopm_put_interface(padapter->dvobjpriv.pusbintf);
+ #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,20))
+ usb_autopm_enable(padapter->dvobjpriv.pusbintf);
+ #else
+ usb_autosuspend_device(padapter->dvobjpriv.pusbdev, 1);
+ #endif
+ }
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,32))
+ DBG_871X("...pm_usage_cnt(%d).....\n",atomic_read(&(padapter->dvobjpriv.pusbintf->pm_usage_cnt)));
+ #else
+ DBG_871X("...pm_usage_cnt(%d).....\n",padapter->dvobjpriv.pusbintf->pm_usage_cnt);
+ #endif
+
+}
+int autoresume_enter(_adapter* padapter)
+{
+ int result = _SUCCESS;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct security_priv* psecuritypriv=&(padapter->securitypriv);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+
+ DBG_871X("====> autoresume_enter \n");
+
+ if(rf_off == pwrpriv->rf_pwrstate )
+ {
+ pwrpriv->ps_flag = _FALSE;
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,33))
+ if (usb_autopm_get_interface( padapter->dvobjpriv.pusbintf) < 0)
+ {
+ DBG_871X( "can't get autopm: %d\n", result);
+ result = _FAIL;
+ goto error_exit;
+ }
+ #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,20))
+ usb_autopm_disable(padapter->dvobjpriv.pusbintf);
+ #else
+ usb_autoresume_device(padapter->dvobjpriv.pusbdev, 1);
+ #endif
+
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,32))
+ DBG_871X("...pm_usage_cnt(%d).....\n",atomic_read(&(padapter->dvobjpriv.pusbintf->pm_usage_cnt)));
+ #else
+ DBG_871X("...pm_usage_cnt(%d).....\n",padapter->dvobjpriv.pusbintf->pm_usage_cnt);
+ #endif
+ }
+ DBG_871X("<==== autoresume_enter \n");
+error_exit:
+
+ return result;
+}
+#endif
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+extern void rtd2885_wlan_netlink_sendMsg(char *action_string, char *name);
+#endif
+
+#ifdef CONFIG_PLATFORM_ARM_SUN4I
+#include <mach/sys_config.h>
+extern int sw_usb_disable_hcd(__u32 usbc_no);
+extern int sw_usb_enable_hcd(__u32 usbc_no);
+static int usb_wifi_host = 2;
+#endif
+/*
+ * drv_init() - a device potentially for us
+ *
+ * notes: drv_init() is called when the bus driver has located a card for us to support.
+ * We accept the new device by returning 0.
+*/
+
+_adapter *rtw_sw_export = NULL;
+
+static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
+{
+ int i;
+
+ uint status;
+ _adapter *padapter = NULL;
+ struct dvobj_priv *dvobj;
+ struct net_device *pnetdev;
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
+ //DBG_871X("+rtw_drv_init\n");
+
+ //2009.8.13, by Thomas
+ // In this probe function, O.S. will provide the usb interface pointer to driver.
+ // We have to increase the reference count of the usb device structure by using the usb_get_dev function.
+ usb_get_dev(interface_to_usbdev(pusb_intf));
+
+ //step 0.
+ process_spec_devid(pdid);
+
+ //step 1. set USB interface data
+ // init data
+ pnetdev = rtw_init_netdev(NULL);
+ if (!pnetdev)
+ goto error;
+
+ SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
+
+ padapter = rtw_netdev_priv(pnetdev);
+ padapter->bDriverStopped=_TRUE;
+ dvobj = &padapter->dvobjpriv;
+ dvobj->padapter = padapter;
+ dvobj->pusbintf = pusb_intf ;
+ dvobj->pusbdev = interface_to_usbdev(pusb_intf);
+ usb_set_intfdata(pusb_intf, dvobj);
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_wdev_alloc(padapter, &pusb_intf->dev);
+#endif //CONFIG_IOCTL_CFG80211
+
+ //set interface_type to usb
+ padapter->interface_type = RTW_USB;
+
+ //step 1-1., decide the chip_type via vid/pid
+ decide_chip_type_by_usb_device_id(padapter, pdid);
+
+ //step 2.
+ if(padapter->chip_type == RTL8188C_8192C)
+ {
+#ifdef CONFIG_RTL8192C
+ rtl8192cu_set_hal_ops(padapter);
+#endif
+ }
+ else if(padapter->chip_type == RTL8192D)
+ {
+#ifdef CONFIG_RTL8192D
+ rtl8192du_set_hal_ops(padapter);
+#endif
+ }
+ else
+ {
+ DBG_871X("Detect NULL_CHIP_TYPE\n");
+ status = _FAIL;
+ goto error;
+ }
+
+ //step 3. initialize the dvobj_priv
+ padapter->dvobj_init=&usb_dvobj_init;
+ padapter->dvobj_deinit=&usb_dvobj_deinit;
+ padapter->intf_start=&usb_intf_start;
+ padapter->intf_stop=&usb_intf_stop;
+
+ //step 3.
+ //initialize the dvobj_priv ,include Chip version
+ if (padapter->dvobj_init == NULL){
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("\n Initialize dvobjpriv.dvobj_init error!!!\n"));
+ goto error;
+ }
+
+ status = padapter->dvobj_init(padapter);
+ if (status != _SUCCESS) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("initialize device object priv Failed!\n"));
+ goto error;
+ }
+
+ //step 4. read efuse/eeprom data and get mac_addr
+ intf_read_chip_info(padapter);
+
+ //step 5.
+ status = rtw_init_drv_sw(padapter);
+ if(status ==_FAIL){
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("Initialize driver software resource Failed!\n"));
+ goto error;
+ }
+
+#ifdef CONFIG_PM
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+ if(padapter->pwrctrlpriv.bSupportRemoteWakeup)
+ {
+ dvobj->pusbdev->do_remote_wakeup=1;
+ pusb_intf->needs_remote_wakeup = 1;
+ device_init_wakeup(&pusb_intf->dev, 1);
+ DBG_871X("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
+ DBG_871X("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",device_may_wakeup(&pusb_intf->dev));
+ }
+#endif
+#endif
+
+#ifdef CONFIG_AUTOSUSPEND
+ if( padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE )
+ {
+ if(padapter->registrypriv.usbss_enable ){ /* autosuspend (2s delay) */
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
+ dvobj->pusbdev->dev.power.autosuspend_delay = 0 * HZ;//15 * HZ; idle-delay time
+ #else
+ dvobj->pusbdev->autosuspend_delay = 0 * HZ;//15 * HZ; idle-delay time
+ #endif
+
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+ usb_enable_autosuspend(padapter->dvobjpriv.pusbdev);
+ #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
+ padapter->bDisableAutosuspend = padapter->dvobjpriv.pusbdev->autosuspend_disabled ;
+ padapter->dvobjpriv.pusbdev->autosuspend_disabled = 0;//autosuspend disabled by the user
+ #endif
+
+ usb_autopm_get_interface(padapter->dvobjpriv.pusbintf );//init pm_usage_cnt ,let it start from 1
+
+ #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,32))
+ DBG_871X("%s...pm_usage_cnt(%d).....\n",__FUNCTION__,atomic_read(&(dvobj->pusbintf ->pm_usage_cnt)));
+ #else
+ DBG_871X("%s...pm_usage_cnt(%d).....\n",__FUNCTION__,dvobj->pusbintf ->pm_usage_cnt);
+ #endif
+ }
+ }
+#endif
+ // alloc dev name after read efuse.
+ rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
+
+ rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
+
+ _rtw_memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
+ DBG_871X("MAC Address from pnetdev->dev_addr= " MAC_FMT "\n", MAC_ARG(pnetdev->dev_addr));
+
+#ifdef CONFIG_PROC_DEBUG
+#ifdef RTK_DMP_PLATFORM
+ rtw_proc_init_one(pnetdev);
+#endif
+#endif
+
+#ifdef CONFIG_HOSTAPD_MLME
+ hostapd_mode_init(padapter);
+#endif
+
+ padapter->hw_init_mutex = &usb_drvpriv.hw_init_mutex;
+#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
+ //set global variable to primary adapter
+ padapter->ph2c_fwcmd_mutex = &usb_drvpriv.h2c_fwcmd_mutex;
+ padapter->psetch_mutex = &usb_drvpriv.setch_mutex;
+ padapter->psetbw_mutex = &usb_drvpriv.setbw_mutex;
+#endif
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+ DBG_871X("wlan link up\n");
+ rtd2885_wlan_netlink_sendMsg("linkup", "8712");
+#endif
+
+
+#ifdef CONFIG_GLOBAL_UI_PID
+ if(ui_pid[1]!=0) {
+ DBG_871X("ui_pid[1]:%d\n",ui_pid[1]);
+ rtw_signal_process(ui_pid[1], SIGUSR2);
+ }
+#endif
+
+ //step 6.
+ /* Tell the network stack we exist */
+ if (register_netdev(pnetdev) != 0) {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("register_netdev() failed\n"));
+ goto error;
+ }
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-drv_init - Adapter->bDriverStopped=%d, Adapter->bSurpriseRemoved=%d\n",padapter->bDriverStopped, padapter->bSurpriseRemoved));
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-871x_drv - drv_init, success!\n"));
+ //DBG_8192C("-871x_drv - drv_init, success!\n");
+
+
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(rtw_drv_if2_init(padapter, NULL)==NULL)
+ {
+ goto error;
+ }
+#endif
+
+ DBG_871X("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
+ ,padapter->bDriverStopped
+ ,padapter->bSurpriseRemoved
+ ,padapter->bup
+ ,padapter->hw_init_completed
+ );
+
+ return 0;
+
+error:
+
+ usb_put_dev(interface_to_usbdev(pusb_intf));//decrease the reference count of the usb device structure if driver fail on initialzation
+
+ usb_set_intfdata(pusb_intf, NULL);
+
+ usb_dvobj_deinit(padapter);
+
+ if (pnetdev)
+ {
+ //unregister_netdev(pnetdev);
+ rtw_free_netdev(pnetdev);
+ }
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-871x_usb - drv_init, fail!\n"));
+ //DBG_871X("-871x_usb - drv_init, fail!\n");
+
+ return -ENODEV;
+}
+
+/*
+ * dev_remove() - our device is being removed
+*/
+//rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both
+static void rtw_dev_remove(struct usb_interface *pusb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ _adapter *padapter = dvobj->padapter;
+ struct net_device *pnetdev = padapter->pnetdev;
+ struct mlme_priv *pmlmepriv= &padapter->mlmepriv;
+ u8 bResetDevice = _FALSE;
+
+_func_exit_;
+
+ usb_set_intfdata(pusb_intf, NULL);
+
+ if(padapter)
+ {
+
+#ifdef CONFIG_IOCTL_CFG80211
+ struct wireless_dev *wdev = padapter->rtw_wdev;
+#endif //CONFIG_IOCTL_CFG80211
+
+ DBG_871X("+rtw_dev_remove\n");
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+dev_remove()\n"));
+
+#if defined(CONFIG_HAS_EARLYSUSPEND ) || defined(CONFIG_ANDROID_POWER)
+ rtw_unregister_early_suspend(&padapter->pwrctrlpriv);
+#endif
+
+ LeaveAllPowerSaveMode(padapter);
+
+ if(check_fwstate(pmlmepriv, _FW_LINKED))
+ disconnect_hdl(padapter, NULL);
+
+ if(usb_drvpriv.drv_registered == _TRUE)
+ {
+ //DBG_871X("r871xu_dev_remove():padapter->bSurpriseRemoved == _TRUE\n");
+ padapter->bSurpriseRemoved = _TRUE;
+ }
+ /*else
+ {
+ //DBG_871X("r871xu_dev_remove():module removed\n");
+ padapter->hw_init_completed = _FALSE;
+ }*/
+
+#ifdef CONFIG_AP_MODE
+ free_mlme_ap_info(padapter);
+#ifdef CONFIG_HOSTAPD_MLME
+ hostapd_mode_unload(padapter);
+#endif //CONFIG_HOSTAPD_MLME
+#endif //CONFIG_AP_MODE
+
+
+#ifdef CONFIG_CONCURRENT_MODE
+ rtw_drv_if2_free(padapter);
+#endif
+ if(padapter->DriverState != DRIVER_DISAPPEAR)
+ {
+ if(pnetdev) {
+ unregister_netdev(pnetdev); //will call netdev_close()
+#ifdef CONFIG_PROC_DEBUG
+ rtw_proc_remove_one(pnetdev);
+#endif
+ }
+ }
+
+ rtw_cancel_all_timer(padapter);
+#ifdef CONFIG_WOWLAN
+ padapter->pwrctrlpriv.wowlan_mode=_FALSE;
+#endif //CONFIG_WOWLAN
+ rtw_dev_unload(padapter);
+
+ DBG_871X("+r871xu_dev_remove, hw_init_completed=%d\n", padapter->hw_init_completed);
+
+ //Modify condition for 92DU DMDP 2010.11.18, by Thomas
+ //move code to here, avoid access null pointer. 2011.05.25.
+ if(((dvobj->NumInterfaces != 2)&&(dvobj->NumInterfaces != 3)) || (dvobj->InterfaceNumber == 1))
+ bResetDevice = _TRUE;
+
+ //s6.
+ if(padapter->dvobj_deinit)
+ {
+ padapter->dvobj_deinit(padapter);
+ }
+ else
+ {
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("Initialize hcipriv.hci_priv_init error!!!\n"));
+ }
+
+ //after rtw_free_drv_sw(), padapter has beed freed, don't refer to it.
+ rtw_free_drv_sw(padapter);
+
+#ifdef CONFIG_IOCTL_CFG80211
+ rtw_wdev_free(wdev);
+#endif //CONFIG_IOCTL_CFG80211
+ }
+
+ usb_put_dev(interface_to_usbdev(pusb_intf));//decrease the reference count of the usb device structure when disconnect
+
+ //If we didn't unplug usb dongle and remove/insert modlue, driver fails on sitesurvey for the first time when device is up .
+ //Reset usb port for sitesurvey fail issue. 2009.8.13, by Thomas
+ if(_TRUE == bResetDevice)
+ {
+ if(interface_to_usbdev(pusb_intf)->state != USB_STATE_NOTATTACHED)
+ {
+ DBG_871X("usb attached..., try to reset usb device\n");
+ usb_reset_device(interface_to_usbdev(pusb_intf));
+ }
+ }
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-dev_remove()\n"));
+ DBG_871X("-r871xu_dev_remove, done\n");
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+ DBG_871X("wlan link down\n");
+ rtd2885_wlan_netlink_sendMsg("linkdown", "8712");
+#endif
+
+ #ifdef DBG_MEM_ALLOC
+ rtw_dump_mem_stat ();
+ #endif
+_func_exit_;
+
+ return;
+
+}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+extern int console_suspend_enabled;
+#endif
+
+static int __init rtw_drv_entry(void)
+{
+#ifdef CONFIG_PLATFORM_RTK_DMP
+ u32 tmp;
+ tmp=readl((volatile unsigned int*)0xb801a608);
+ tmp &= 0xffffff00;
+ tmp |= 0x55;
+ writel(tmp,(volatile unsigned int*)0xb801a608);//write dummy register for 1055
+#endif
+#ifdef CONFIG_PLATFORM_ARM_SUN4I
+#ifndef CONFIG_RTL8723A
+ int ret = 0;
+ /* ----------get usb_wifi_usbc_num------------- */
+ ret = script_parser_fetch("usb_wifi_para", "usb_wifi_usbc_num", (int *)&usb_wifi_host, 64);
+ if(ret != 0){
+ printk("ERR: script_parser_fetch usb_wifi_usbc_num failed\n");
+ ret = -ENOMEM;
+ return ret;
+ }
+ printk("sw_usb_enable_hcd: usbc_num = %d\n", usb_wifi_host);
+ sw_usb_enable_hcd(usb_wifi_host);
+#endif //CONFIG_RTL8723A
+#endif //CONFIG_PLATFORM_ARM_SUN4I
+
+
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_drv_entry\n"));
+
+ DBG_871X("rtw driver version=%s \n", DRIVERVERSION);
+ DBG_871X("Build at: %s %s\n", __DATE__, __TIME__);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ //console_suspend_enabled=0;
+#endif
+
+ rtw_suspend_lock_init();
+
+ _rtw_mutex_init(&usb_drvpriv.hw_init_mutex);
+#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
+ //init global variable
+ _rtw_mutex_init(&usb_drvpriv.h2c_fwcmd_mutex);
+ _rtw_mutex_init(&usb_drvpriv.setch_mutex);
+ _rtw_mutex_init(&usb_drvpriv.setbw_mutex);
+#endif
+
+ usb_drvpriv.drv_registered = _TRUE;
+ return usb_register(&usb_drvpriv.rtw_usb_drv);
+}
+
+static void __exit rtw_drv_halt(void)
+{
+ RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_drv_halt\n"));
+ DBG_871X("+rtw_drv_halt\n");
+
+ rtw_suspend_lock_uninit();
+
+ usb_drvpriv.drv_registered = _FALSE;
+ usb_deregister(&usb_drvpriv.rtw_usb_drv);
+
+ _rtw_mutex_free(&usb_drvpriv.hw_init_mutex);
+#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
+ _rtw_mutex_free(&usb_drvpriv.h2c_fwcmd_mutex);
+ _rtw_mutex_free(&usb_drvpriv.setch_mutex);
+ _rtw_mutex_free(&usb_drvpriv.setbw_mutex);
+#endif
+#ifdef CONFIG_PLATFORM_ARM_SUN4I
+#ifndef CONFIG_RTL8723A
+ printk("sw_usb_disable_hcd: usbc_num = %d\n", usb_wifi_host);
+ sw_usb_disable_hcd(usb_wifi_host);
+#endif //ifndef CONFIG_RTL8723A
+#endif //CONFIG_PLATFORM_ARM_SUN4I
+ DBG_871X("-rtw_drv_halt\n");
+}
+
+
+module_init(rtw_drv_entry);
+module_exit(rtw_drv_halt);
+
+
+/*
+init (driver module)-> r8712u_drv_entry
+probe (sd device)-> r871xu_drv_init(dev_init)
+open (net_device) ->netdev_open
+close (net_device) ->netdev_close
+remove (sd device) ->r871xu_dev_remove
+exit (driver module)-> r8712u_drv_halt
+*/
+
+
+/*
+r8711s_drv_entry()
+r8711u_drv_entry()
+r8712s_drv_entry()
+r8712u_drv_entry()
+*/
+#ifdef CONFIG_WOWLAN
+#ifdef TOSHIBA_WOWLAN
+
+int rtw_resume_toshiba(PADAPTER Adapter)
+{
+ struct dvobj_priv *pdvobjpriv;
+ pdvobjpriv = &Adapter->dvobjpriv;
+
+ rtw_resume(pdvobjpriv->pusbintf);
+ return 0;
+}
+
+int rtw_suspend_toshiba(PADAPTER Adapter)
+{
+ pm_message_t msg;
+ struct dvobj_priv *pdvobjpriv;
+ pdvobjpriv = &Adapter->dvobjpriv;
+ msg.event=0;
+ //for Toshiba only, they should call rtw_suspend before suspend
+ rtw_suspend(pdvobjpriv->pusbintf, msg);
+ return 0;
+}
+EXPORT_SYMBOL(rtw_suspend_toshiba);
+EXPORT_SYMBOL(rtw_resume_toshiba);
+#endif //TOSHIBA_WOWLAN
+#endif //CONFIG_WOWLAN
+
+#ifdef CONFIG_INTEL_PROXIM
+_adapter *rtw_usb_get_sw_pointer(void)
+{
+ return rtw_sw_export;
+}
+EXPORT_SYMBOL(rtw_usb_get_sw_pointer);
+#endif //CONFIG_INTEL_PROXIM
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/usb_ops_linux.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/usb_ops_linux.c
new file mode 100755
index 000000000000..9878727f40dd
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/usb_ops_linux.c
@@ -0,0 +1,715 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 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 _USB_OPS_LINUX_C_
+
+#include <drv_types.h>
+#include <usb_ops_linux.h>
+#include <rtw_sreset.h>
+
+#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
+static void _usbctrl_vendorreq_async_callback(struct urb *urb, struct pt_regs *regs)
+{
+ if (urb) {
+ if (urb->context) {
+ kfree(urb->context);
+ }
+ usb_free_urb(urb);
+ }
+}
+
+static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
+ u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
+{
+ int rc;
+ unsigned int pipe;
+ u8 reqtype;
+ struct usb_ctrlrequest *dr;
+ struct urb *urb;
+ struct rtl819x_async_write_data {
+ u8 data[VENDOR_CMD_MAX_DATA_LEN];
+ struct usb_ctrlrequest dr;
+ } *buf;
+
+
+ if (requesttype == VENDOR_READ) {
+ pipe = usb_rcvctrlpipe(udev, 0);//read_in
+ reqtype = REALTEK_USB_VENQT_READ;
+ }
+ else {
+ pipe = usb_sndctrlpipe(udev, 0);//write_out
+ reqtype = REALTEK_USB_VENQT_WRITE;
+ }
+
+ buf = (struct rtl819x_async_write_data *)rtw_zmalloc(sizeof(*buf));
+ if (!buf) {
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ rtw_mfree((u8*)buf, sizeof(*buf));
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ dr = &buf->dr;
+
+ dr->bRequestType = reqtype;
+ dr->bRequest = request;
+ dr->wValue = cpu_to_le16(value);
+ dr->wIndex = cpu_to_le16(index);
+ dr->wLength = cpu_to_le16(len);
+
+ _rtw_memcpy(buf, pdata, len);
+
+ usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr, buf, len,
+ _usbctrl_vendorreq_async_callback, buf);
+
+ rc = usb_submit_urb(urb, GFP_ATOMIC);
+ if (rc < 0) {
+ rtw_mfree((u8*)buf, sizeof(*buf));
+ usb_free_urb(urb);
+ }
+
+exit:
+ return rc;
+}
+
+int usb_write_async(struct usb_device *udev, u32 addr, void *pdata, u16 len)
+{
+ u8 request;
+ u8 requesttype;
+ u16 wvalue;
+ u16 index;
+
+ int ret;
+
+ requesttype = VENDOR_WRITE;//write_out
+ request = REALTEK_USB_VENQT_CMD_REQ;
+ index = REALTEK_USB_VENQT_CMD_IDX;//n/a
+
+ wvalue = (u16)(addr&0x0000ffff);
+
+ ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, index, pdata, len, requesttype);
+
+ return ret;
+}
+
+int usb_async_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
+{
+ u8 data;
+ int ret;
+ struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
+ struct usb_device *udev=pdvobjpriv->pusbdev;
+
+ _func_enter_;
+ data = val;
+ ret = usb_write_async(udev, addr, &data, 1);
+ _func_exit_;
+
+ return ret;
+}
+
+int usb_async_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
+{
+ u16 data;
+ int ret;
+ struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
+ struct usb_device *udev=pdvobjpriv->pusbdev;
+
+ _func_enter_;
+ data = val;
+ ret = usb_write_async(udev, addr, &data, 2);
+ _func_exit_;
+
+ return ret;
+}
+
+int usb_async_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
+{
+ u32 data;
+ int ret;
+ struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
+ struct usb_device *udev=pdvobjpriv->pusbdev;
+
+ _func_enter_;
+ data = val;
+ ret = usb_write_async(udev, addr, &data, 4);
+ _func_exit_;
+
+ return ret;
+}
+#endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */
+
+unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
+{
+ unsigned int pipe=0;
+ int ep_num=0;
+ _adapter *padapter = pdvobj->padapter;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+
+ if (addr == RECV_BULK_IN_ADDR) {
+ pipe=usb_rcvbulkpipe(pusbd, pHalData->RtBulkInPipe);
+
+ } else if (addr == RECV_INT_IN_ADDR) {
+ pipe=usb_rcvbulkpipe(pusbd, pHalData->RtIntInPipe);
+
+ } else if (addr < HW_QUEUE_ENTRY) {
+ ep_num = pHalData->Queue2EPNum[addr];
+ pipe = usb_sndbulkpipe(pusbd, ep_num);
+ }
+
+ return pipe;
+}
+
+struct zero_bulkout_context{
+ void *pbuf;
+ void *purb;
+ void *pirp;
+ void *padapter;
+};
+
+static void usb_bulkout_zero_complete(struct urb *purb, struct pt_regs *regs)
+{
+ struct zero_bulkout_context *pcontext = (struct zero_bulkout_context *)purb->context;
+
+ //DBG_8192C("+usb_bulkout_zero_complete\n");
+
+ if(pcontext)
+ {
+ if(pcontext->pbuf)
+ {
+ rtw_mfree(pcontext->pbuf, sizeof(int));
+ }
+
+ if(pcontext->purb && (pcontext->purb==purb))
+ {
+ usb_free_urb(pcontext->purb);
+ }
+
+
+ rtw_mfree((u8*)pcontext, sizeof(struct zero_bulkout_context));
+ }
+
+
+}
+
+static u32 usb_bulkout_zero(struct intf_hdl *pintfhdl, u32 addr)
+{
+ int pipe, status, len;
+ u32 ret;
+ unsigned char *pbuf;
+ struct zero_bulkout_context *pcontext;
+ PURB purb = NULL;
+ _adapter *padapter = (_adapter *)pintfhdl->padapter;
+ struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+
+ //DBG_871X("%s\n", __func__);
+
+
+ if((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||(padapter->pwrctrlpriv.pnp_bstop_trx))
+ {
+ return _FAIL;
+ }
+
+
+ pcontext = (struct zero_bulkout_context *)rtw_zmalloc(sizeof(struct zero_bulkout_context));
+
+ pbuf = (unsigned char *)rtw_zmalloc(sizeof(int));
+ purb = usb_alloc_urb(0, GFP_ATOMIC);
+
+ len = 0;
+ pcontext->pbuf = pbuf;
+ pcontext->purb = purb;
+ pcontext->pirp = NULL;
+ pcontext->padapter = padapter;
+
+
+ //translate DMA FIFO addr to pipehandle
+ //pipe = ffaddr2pipehdl(pdvobj, addr);
+
+ usb_fill_bulk_urb(purb, pusbd, pipe,
+ pbuf,
+ len,
+ usb_bulkout_zero_complete,
+ pcontext);//context is pcontext
+
+ status = usb_submit_urb(purb, GFP_ATOMIC);
+
+ if (!status)
+ {
+ ret= _SUCCESS;
+ }
+ else
+ {
+ ret= _FAIL;
+ }
+
+
+ return _SUCCESS;
+
+}
+
+void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
+{
+
+}
+
+void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+{
+
+}
+
+
+void usb_read_port_cancel(struct intf_hdl *pintfhdl)
+{
+ int i;
+ struct recv_buf *precvbuf;
+ _adapter *padapter = pintfhdl->padapter;
+ precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
+
+ DBG_871X("%s\n", __func__);
+
+ padapter->bReadPortCancel = _TRUE;
+
+ for (i=0; i < NR_RECVBUFF ; i++) {
+
+ precvbuf->reuse = _TRUE;
+ if (precvbuf->purb) {
+ //DBG_8192C("usb_read_port_cancel : usb_kill_urb \n");
+ usb_kill_urb(precvbuf->purb);
+ }
+ precvbuf++;
+ }
+
+#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
+ usb_kill_urb(padapter->recvpriv.int_in_urb);
+#endif
+}
+
+static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+ _irqL irqL;
+ int i;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
+ //struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
+ //_adapter *padapter = pxmitframe->padapter;
+ _adapter *padapter = pxmitbuf->padapter;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ //struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+_func_enter_;
+
+ switch(pxmitbuf->flags)
+ {
+ case XMIT_VO_QUEUE:
+ pxmitpriv->voq_cnt--;
+ break;
+ case XMIT_VI_QUEUE:
+ pxmitpriv->viq_cnt--;
+ break;
+ case XMIT_BE_QUEUE:
+ pxmitpriv->beq_cnt--;
+ break;
+ case XMIT_BK_QUEUE:
+ pxmitpriv->bkq_cnt--;
+ break;
+ case HIGH_QUEUE_INX:
+#ifdef CONFIG_AP_MODE
+ rtw_chk_hi_queue_cmd(padapter);
+#endif
+ break;
+ default:
+ break;
+ }
+
+
+/*
+ _enter_critical(&pxmitpriv->lock, &irqL);
+
+ pxmitpriv->txirp_cnt--;
+
+ switch(pattrib->priority)
+ {
+ case 1:
+ case 2:
+ pxmitpriv->bkq_cnt--;
+ //DBG_8192C("pxmitpriv->bkq_cnt=%d\n", pxmitpriv->bkq_cnt);
+ break;
+ case 4:
+ case 5:
+ pxmitpriv->viq_cnt--;
+ //DBG_8192C("pxmitpriv->viq_cnt=%d\n", pxmitpriv->viq_cnt);
+ break;
+ case 6:
+ case 7:
+ pxmitpriv->voq_cnt--;
+ //DBG_8192C("pxmitpriv->voq_cnt=%d\n", pxmitpriv->voq_cnt);
+ break;
+ case 0:
+ case 3:
+ default:
+ pxmitpriv->beq_cnt--;
+ //DBG_8192C("pxmitpriv->beq_cnt=%d\n", pxmitpriv->beq_cnt);
+ break;
+
+ }
+
+ _exit_critical(&pxmitpriv->lock, &irqL);
+
+
+ if(pxmitpriv->txirp_cnt==0)
+ {
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: txirp_cnt== 0, set allrxreturnevt!\n"));
+ _rtw_up_sema(&(pxmitpriv->tx_retevt));
+ }
+*/
+ //rtw_free_xmitframe_ex(pxmitpriv, pxmitframe);
+
+ if(padapter->bSurpriseRemoved || padapter->bDriverStopped ||padapter->bWritePortCancel)
+ {
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
+ DBG_8192C("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x) \n",
+ __FUNCTION__,padapter->bDriverStopped, padapter->bSurpriseRemoved,padapter->bReadPortCancel,pxmitbuf->ext_tag);
+
+ goto check_completion;
+ }
+
+
+ if (purb->status==0) {
+
+ } else {
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete : purb->status(%d) != 0 \n", purb->status));
+ DBG_871X("###=> urb_write_port_complete status(%d)\n",purb->status);
+ if((purb->status==-EPIPE)||(purb->status==-EPROTO))
+ {
+ //usb_clear_halt(pusbdev, purb->pipe);
+ //msleep(10);
+ sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
+ } else if (purb->status == -EINPROGRESS) {
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: EINPROGESS\n"));
+ goto check_completion;
+
+ } else if (purb->status == -ENOENT) {
+ DBG_871X("%s: -ENOENT\n", __func__);
+ goto check_completion;
+
+ } else if (purb->status == -ECONNRESET) {
+ DBG_871X("%s: -ECONNRESET\n", __func__);
+ goto check_completion;
+
+ } else if (purb->status == -ESHUTDOWN) {
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: ESHUTDOWN\n"));
+ padapter->bDriverStopped=_TRUE;
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped=TRUE\n"));
+
+ goto check_completion;
+ }
+ else
+ {
+ padapter->bSurpriseRemoved=_TRUE;
+ DBG_8192C("bSurpriseRemoved=TRUE\n");
+ //rtl8192cu_trigger_gpio_0(padapter);
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bSurpriseRemoved=TRUE\n"));
+
+ goto check_completion;
+ }
+ }
+
+ #ifdef DBG_CONFIG_ERROR_DETECT
+ {
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ pHalData->srestpriv.last_tx_complete_time = rtw_get_current_time();
+ }
+ #endif
+
+check_completion:
+ if (pxmitbuf->isSync) {
+ pxmitbuf->status = purb->status;
+ complete(&pxmitbuf->done);
+ } else {
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ }
+
+ //if(rtw_txframes_pending(padapter))
+ {
+ tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+ }
+
+_func_exit_;
+
+}
+
+static u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem, int timeout_ms)
+{
+ _irqL irqL;
+ unsigned int pipe;
+ int status;
+ u32 ret, bwritezero = _FALSE;
+ PURB purb = NULL;
+ _adapter *padapter = (_adapter *)pintfhdl->padapter;
+ struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
+ struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+_func_enter_;
+
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("+usb_write_port\n"));
+
+ if((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||(padapter->pwrctrlpriv.pnp_bstop_trx))
+ {
+ #ifdef DBG_TX
+ DBG_871X(" DBG_TX %s:%d bDriverStopped%d, bSurpriseRemoved:%d, pnp_bstop_trx:%d\n",__FUNCTION__, __LINE__
+ ,padapter->bDriverStopped, padapter->bSurpriseRemoved, padapter->pwrctrlpriv.pnp_bstop_trx );
+ #endif
+
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
+ return _FAIL;
+ }
+
+ _enter_critical(&pxmitpriv->lock, &irqL);
+
+ switch(addr)
+ {
+ case VO_QUEUE_INX:
+ pxmitpriv->voq_cnt++;
+ pxmitbuf->flags = XMIT_VO_QUEUE;
+ break;
+ case VI_QUEUE_INX:
+ pxmitpriv->viq_cnt++;
+ pxmitbuf->flags = XMIT_VI_QUEUE;
+ break;
+ case BE_QUEUE_INX:
+ pxmitpriv->beq_cnt++;
+ pxmitbuf->flags = XMIT_BE_QUEUE;
+ break;
+ case BK_QUEUE_INX:
+ pxmitpriv->bkq_cnt++;
+ pxmitbuf->flags = XMIT_BK_QUEUE;
+ break;
+ case HIGH_QUEUE_INX:
+ pxmitbuf->flags = HIGH_QUEUE_INX;
+ break;
+ default:
+ pxmitbuf->flags = XMIT_VO_QUEUE;
+ break;
+ }
+
+ _exit_critical(&pxmitpriv->lock, &irqL);
+
+/*
+ _enter_critical(&pxmitpriv->lock, &irqL);
+
+ //total irp
+ pxmitpriv->txirp_cnt++;
+
+ //per ac irp
+ switch(pattrib->priority)
+ {
+ case 1:
+ case 2:
+ pxmitpriv->bkq_cnt++;
+ break;
+ case 4:
+ case 5:
+ pxmitpriv->viq_cnt++;
+ break;
+ case 6:
+ case 7:
+ pxmitpriv->voq_cnt++;
+ break;
+ case 0:
+ case 3:
+ default:
+ pxmitpriv->beq_cnt++;
+ break;
+ }
+
+
+ _exit_critical(&pxmitpriv->lock, &irqL);
+*/
+
+ purb = pxmitbuf->pxmit_urb[0];
+
+#if 0
+ if(pdvobj->ishighspeed)
+ {
+ if(cnt> 0 && cnt%512 == 0)
+ {
+ //DBG_8192C("ishighspeed, cnt=%d\n", cnt);
+ bwritezero = _TRUE;
+ }
+ }
+ else
+ {
+ if(cnt > 0 && cnt%64 == 0)
+ {
+ //DBG_8192C("cnt=%d\n", cnt);
+ bwritezero = _TRUE;
+ }
+ }
+#endif
+
+ //translate DMA FIFO addr to pipehandle
+ pipe = ffaddr2pipehdl(pdvobj, addr);
+
+#ifdef CONFIG_REDUCE_USB_TX_INT
+ if ( (pxmitpriv->free_xmitbuf_cnt%NR_XMITBUFF == 0)
+ || (pxmitbuf->ext_tag == _TRUE) )
+ {
+ purb->transfer_flags &= (~URB_NO_INTERRUPT);
+ } else {
+ purb->transfer_flags |= URB_NO_INTERRUPT;
+ //DBG_8192C("URB_NO_INTERRUPT ");
+ }
+#endif
+
+
+ usb_fill_bulk_urb(purb, pusbd, pipe,
+ pxmitframe->buf_addr, //= pxmitbuf->pbuf
+ cnt,
+ usb_write_port_complete,
+ pxmitbuf);//context is pxmitbuf
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
+ purb->transfer_dma = pxmitbuf->dma_transfer_addr;
+ purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ purb->transfer_flags |= URB_ZERO_PACKET;
+#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
+
+#if 0
+ if (bwritezero)
+ {
+ purb->transfer_flags |= URB_ZERO_PACKET;
+ }
+#endif
+
+ if (timeout_ms >= 0) {
+ init_completion(&pxmitbuf->done);
+ pxmitbuf->isSync = _TRUE;
+ } else {
+ pxmitbuf->isSync = _FALSE;
+ }
+ pxmitbuf->status = 0;
+
+ status = usb_submit_urb(purb, GFP_ATOMIC);
+ if (!status)
+ {
+ ret= _SUCCESS;
+ #ifdef DBG_CONFIG_ERROR_DETECT
+ {
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ pHalData->srestpriv.last_tx_time = rtw_get_current_time();
+ }
+ #endif
+ }
+ else
+ {
+ DBG_871X("usb_write_port, status=%d\n", status);
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port(): usb_submit_urb, status=%x\n", status));
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ ret= _FAIL;
+ }
+
+// Commented by Albert 2009/10/13
+// We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically.
+/*
+ if(bwritezero == _TRUE)
+ {
+ usb_bulkout_zero(pintfhdl, addr);
+ }
+*/
+
+ // synchronous write handling
+ if(pxmitbuf->isSync == _TRUE && ret == _SUCCESS) {
+ unsigned long expire = timeout_ms ? msecs_to_jiffies(timeout_ms) : MAX_SCHEDULE_TIMEOUT;
+ int status;
+
+ if (!wait_for_completion_timeout(&pxmitbuf->done, expire)) {
+ usb_kill_urb(purb);
+ status = (pxmitbuf->status == -ENOENT ? -ETIMEDOUT : pxmitbuf->status);
+ } else {
+ status = pxmitbuf->status;
+ }
+
+ if (!status) {
+ ret= _SUCCESS;
+ } else {
+ DBG_871X("usb_write_port sync, status=%d\n", status);
+ ret = _FAIL;
+ }
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ }
+
+ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("-usb_write_port\n"));
+
+_func_exit_;
+
+ return ret;
+
+}
+
+inline u32 usb_write_port_async(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+{
+ return usb_write_port(pintfhdl, addr, cnt, wmem, -1);
+}
+
+inline int usb_write_port_sync(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+{
+ return usb_write_port(pintfhdl, addr, cnt, wmem, RTW_USB_BULKOUT_TIMEOUT);
+}
+
+void usb_write_port_cancel(struct intf_hdl *pintfhdl)
+{
+ int i, j;
+ _adapter *padapter = pintfhdl->padapter;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
+
+ DBG_871X("%s \n", __func__);
+
+ padapter->bWritePortCancel = _TRUE;
+
+ for (i=0; i<NR_XMITBUFF; i++) {
+ for (j=0; j<8; j++) {
+ if (pxmitbuf->pxmit_urb[j]) {
+ usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+ }
+ }
+ pxmitbuf++;
+ }
+
+ pxmitbuf = (struct xmit_buf*)padapter->xmitpriv.pxmit_extbuf;
+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
+ for (j=0; j<8; j++) {
+ if(pxmitbuf->pxmit_urb[j]) {
+ usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+ }
+ }
+ pxmitbuf++;
+ }
+}
+
diff --git a/drivers/net/wireless/rtl8192ce/os_dep/linux/xmit_linux.c b/drivers/net/wireless/rtl8192ce/os_dep/linux/xmit_linux.c
new file mode 100755
index 000000000000..84812a6dc0ce
--- /dev/null
+++ b/drivers/net/wireless/rtl8192ce/os_dep/linux/xmit_linux.c
@@ -0,0 +1,404 @@
+/******************************************************************************
+ *
+ * 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 _XMIT_OSDEP_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#include <if_ether.h>
+#include <ip.h>
+#include <rtw_byteorder.h>
+#include <wifi.h>
+#include <mlme_osdep.h>
+#include <xmit_osdep.h>
+#include <osdep_intf.h>
+#include <circ_buf.h>
+
+
+uint rtw_remainder_len(struct pkt_file *pfile)
+{
+ return (pfile->buf_len - ((SIZE_PTR)(pfile->cur_addr) - (SIZE_PTR)(pfile->buf_start)));
+}
+
+void _rtw_open_pktfile (_pkt *pktptr, struct pkt_file *pfile)
+{
+_func_enter_;
+
+ pfile->pkt = pktptr;
+ pfile->cur_addr = pfile->buf_start = pktptr->data;
+ pfile->pkt_len = pfile->buf_len = pktptr->len;
+
+ pfile->cur_buffer = pfile->buf_start ;
+
+_func_exit_;
+}
+
+uint _rtw_pktfile_read (struct pkt_file *pfile, u8 *rmem, uint rlen)
+{
+ uint len = 0;
+
+_func_enter_;
+
+ len = rtw_remainder_len(pfile);
+ len = (rlen > len)? len: rlen;
+
+ if(rmem)
+ skb_copy_bits(pfile->pkt, pfile->buf_len-pfile->pkt_len, rmem, len);
+
+ pfile->cur_addr += len;
+ pfile->pkt_len -= len;
+
+_func_exit_;
+
+ return len;
+}
+
+sint rtw_endofpktfile(struct pkt_file *pfile)
+{
+_func_enter_;
+
+ if (pfile->pkt_len == 0) {
+_func_exit_;
+ return _TRUE;
+ }
+
+_func_exit_;
+
+ return _FALSE;
+}
+
+void rtw_set_tx_chksum_offload(_pkt *pkt, struct pkt_attrib *pattrib)
+{
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
+ struct sk_buff *skb = (struct sk_buff *)pkt;
+ pattrib->hw_tcp_csum = 0;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (skb_shinfo(skb)->nr_frags == 0)
+ {
+ const struct iphdr *ip = ip_hdr(skb);
+ if (ip->protocol == IPPROTO_TCP) {
+ // TCP checksum offload by HW
+ DBG_871X("CHECKSUM_PARTIAL TCP\n");
+ pattrib->hw_tcp_csum = 1;
+ //skb_checksum_help(skb);
+ } else if (ip->protocol == IPPROTO_UDP) {
+ //DBG_871X("CHECKSUM_PARTIAL UDP\n");
+#if 1
+ skb_checksum_help(skb);
+#else
+ // Set UDP checksum = 0 to skip checksum check
+ struct udphdr *udp = skb_transport_header(skb);
+ udp->check = 0;
+#endif
+ } else {
+ DBG_871X("%s-%d TCP CSUM offload Error!!\n", __FUNCTION__, __LINE__);
+ WARN_ON(1); /* we need a WARN() */
+ }
+ }
+ else { // IP fragmentation case
+ DBG_871X("%s-%d nr_frags != 0, using skb_checksum_help(skb);!!\n", __FUNCTION__, __LINE__);
+ skb_checksum_help(skb);
+ }
+ }
+#endif
+
+}
+
+int rtw_os_xmit_resource_alloc(_adapter *padapter, struct xmit_buf *pxmitbuf,u32 alloc_sz)
+{
+#ifdef CONFIG_USB_HCI
+ int i;
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct usb_device *pusbd = pdvobjpriv->pusbdev;
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
+ pxmitbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)alloc_sz, GFP_ATOMIC, &pxmitbuf->dma_transfer_addr);
+ pxmitbuf->pbuf = pxmitbuf->pallocated_buf;
+ if(pxmitbuf->pallocated_buf == NULL)
+ return _FAIL;
+#else // CONFIG_USE_USB_BUFFER_ALLOC_TX
+
+ pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
+ if (pxmitbuf->pallocated_buf == NULL)
+ {
+ return _FAIL;
+ }
+
+ pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
+ pxmitbuf->dma_transfer_addr = 0;
+
+#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
+
+ for(i=0; i<8; i++)
+ {
+ pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if(pxmitbuf->pxmit_urb[i] == NULL)
+ {
+ DBG_871X("pxmitbuf->pxmit_urb[i]==NULL");
+ return _FAIL;
+ }
+
+ }
+#endif
+#if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI)
+ pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
+ if (pxmitbuf->pallocated_buf == NULL)
+ {
+ return _FAIL;
+ }
+
+ pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
+#endif
+
+ return _SUCCESS;
+}
+
+void rtw_os_xmit_resource_free(_adapter *padapter, struct xmit_buf *pxmitbuf,u32 free_sz)
+{
+#ifdef CONFIG_USB_HCI
+ int i;
+ struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
+ struct usb_device *pusbd = pdvobjpriv->pusbdev;
+
+
+ for(i=0; i<8; i++)
+ {
+ if(pxmitbuf->pxmit_urb[i])
+ {
+ //usb_kill_urb(pxmitbuf->pxmit_urb[i]);
+ usb_free_urb(pxmitbuf->pxmit_urb[i]);
+ }
+ }
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
+ rtw_usb_buffer_free(pusbd, (size_t)free_sz, pxmitbuf->pallocated_buf, pxmitbuf->dma_transfer_addr);
+ pxmitbuf->pallocated_buf = NULL;
+ pxmitbuf->dma_transfer_addr = 0;
+#else // CONFIG_USE_USB_BUFFER_ALLOC_TX
+ if(pxmitbuf->pallocated_buf)
+ rtw_mfree(pxmitbuf->pallocated_buf, free_sz);
+#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
+
+#endif
+#if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI)
+ if(pxmitbuf->pallocated_buf)
+ rtw_mfree(pxmitbuf->pallocated_buf, free_sz);
+#endif
+}
+
+void rtw_os_pkt_complete(_adapter *padapter, _pkt *pkt)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+ u16 queue;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ queue = skb_get_queue_mapping(pkt);
+ if(__netif_subqueue_stopped(padapter->pnetdev, queue) &&
+ (pxmitpriv->hwxmits[queue].accnt < NR_XMITFRAME/2))
+ {
+ netif_wake_subqueue(padapter->pnetdev, queue);
+ }
+#else
+ if (netif_queue_stopped(padapter->pnetdev))
+ netif_wake_queue(padapter->pnetdev);
+#endif
+
+ dev_kfree_skb_any(pkt);
+}
+
+void rtw_os_xmit_complete(_adapter *padapter, struct xmit_frame *pxframe)
+{
+ if(pxframe->pkt)
+ {
+ //RT_TRACE(_module_xmit_osdep_c_,_drv_err_,("linux : rtw_os_xmit_complete, dev_kfree_skb()\n"));
+
+ //dev_kfree_skb_any(pxframe->pkt);
+ rtw_os_pkt_complete(padapter, pxframe->pkt);
+
+ }
+
+ pxframe->pkt = NULL;
+}
+
+void rtw_os_xmit_schedule(_adapter *padapter)
+{
+#ifdef CONFIG_SDIO_HCI
+ if(!padapter)
+ return;
+
+ if (rtw_txframes_pending(padapter))
+ _rtw_up_sema(&padapter->xmitpriv.xmit_sema);
+#else
+ _irqL irqL;
+ struct xmit_priv *pxmitpriv;
+
+ if(!padapter)
+ return;
+
+ pxmitpriv = &padapter->xmitpriv;
+
+ _enter_critical_bh(&pxmitpriv->lock, &irqL);
+
+ if(rtw_txframes_pending(padapter))
+ {
+ tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+ }
+
+ _exit_critical_bh(&pxmitpriv->lock, &irqL);
+#endif
+}
+
+
+
+#ifdef CONFIG_TX_MCAST2UNI
+int rtw_mlcst2unicst(_adapter *padapter, struct sk_buff *skb)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ _irqL irqL;
+ _list *phead, *plist;
+ struct sk_buff *newskb;
+ struct sta_info *psta = NULL;
+ s32 res;
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ 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);
+
+ /* avoid come from STA1 and send back STA1 */
+ if (!memcmp(psta->hwaddr, &skb->data[6], 6))
+ continue;
+
+ newskb = skb_copy(skb, GFP_ATOMIC);
+
+ if (newskb) {
+ memcpy(newskb->data, psta->hwaddr, 6);
+ res = rtw_xmit(padapter, &newskb);
+ if (res < 0) {
+ DBG_871X("%s()-%d: rtw_xmit() return error!\n", __FUNCTION__, __LINE__);
+ pxmitpriv->tx_drop++;
+ dev_kfree_skb_any(newskb);
+ } else
+ pxmitpriv->tx_pkts++;
+ } else {
+ DBG_871X("%s-%d: skb_copy() failed!\n", __FUNCTION__, __LINE__);
+ pxmitpriv->tx_drop++;
+
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ //dev_kfree_skb_any(skb);
+ return _FALSE; // Caller shall tx this multicast frame via normal way.
+ }
+ }
+
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ dev_kfree_skb_any(skb);
+ return _TRUE;
+}
+#endif // CONFIG_TX_MCAST2UNI
+
+
+int rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
+{
+ _adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+#ifdef CONFIG_TX_MCAST2UNI
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ extern int rtw_mc2u_disable;
+#endif // CONFIG_TX_MCAST2UNI
+ s32 res = 0;
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+ u16 queue;
+#endif
+
+_func_enter_;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
+
+ if (rtw_if_up(padapter) == _FALSE) {
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit_entry: rtw_if_up fail\n"));
+ #ifdef DBG_TX_DROP_FRAME
+ DBG_871X("DBG_TX_DROP_FRAME %s if_up fail\n", __FUNCTION__);
+ #endif
+ goto drop_packet;
+ }
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+ queue = skb_get_queue_mapping(pkt);
+ /* No free space for Tx, tx_worker is too slow */
+ if (pxmitpriv->hwxmits[queue].accnt > NR_XMITFRAME/2) {
+ //DBG_871X("%s(): stop netif_subqueue[%d]\n", __FUNCTION__, queue);
+ netif_stop_subqueue(padapter->pnetdev, queue);
+ return NETDEV_TX_BUSY;
+ }
+#endif
+
+#ifdef CONFIG_TX_MCAST2UNI
+ if ( !rtw_mc2u_disable
+ && check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE
+ && ( IP_MCAST_MAC(pkt->data)
+ || ICMPV6_MCAST_MAC(pkt->data) )
+ )
+ {
+ if ( pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME/4) ) {
+ res = rtw_mlcst2unicst(padapter, pkt);
+ if (res == _TRUE) {
+ goto exit;
+ }
+ } else {
+ //DBG_871X("Stop M2U(%d, %d)! ", pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmitbuf_cnt);
+ //DBG_871X("!m2u );
+ }
+ }
+#endif // CONFIG_TX_MCAST2UNI
+
+ res = rtw_xmit(padapter, &pkt);
+ if (res < 0) {
+ #ifdef DBG_TX_DROP_FRAME
+ DBG_871X("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __FUNCTION__);
+ #endif
+ goto drop_packet;
+ }
+
+ pxmitpriv->tx_pkts++;
+ RT_TRACE(_module_xmit_osdep_c_, _drv_info_, ("rtw_xmit_entry: tx_pkts=%d\n", (u32)pxmitpriv->tx_pkts));
+ goto exit;
+
+drop_packet:
+ pxmitpriv->tx_drop++;
+ dev_kfree_skb_any(pkt);
+ RT_TRACE(_module_xmit_osdep_c_, _drv_notice_, ("rtw_xmit_entry: drop, tx_drop=%d\n", (u32)pxmitpriv->tx_drop));
+
+exit:
+
+_func_exit_;
+
+ return 0;
+}
+