ARM: debug: qcom: add UART addresses to Kconfig help for APQ8084
[pandora-kernel.git] / drivers / staging / rtl8188eu / os_dep / ioctl_linux.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _IOCTL_LINUX_C_
21
22 #include <osdep_service.h>
23 #include <drv_types.h>
24 #include <wlan_bssdef.h>
25 #include <rtw_debug.h>
26 #include <wifi.h>
27 #include <rtw_mlme.h>
28 #include <rtw_mlme_ext.h>
29 #include <rtw_ioctl.h>
30 #include <rtw_ioctl_set.h>
31 #include <rtw_mp_ioctl.h>
32 #include <usb_ops.h>
33 #include <rtw_version.h>
34 #include <rtl8188e_hal.h>
35
36 #include <rtw_mp.h>
37 #include <rtw_iol.h>
38 #include <linux/vmalloc.h>
39
40 #define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV + 30)
41
42 #define SCAN_ITEM_SIZE 768
43 #define MAX_CUSTOM_LEN 64
44 #define RATE_COUNT 4
45
46 /*  combo scan */
47 #define WEXT_CSCAN_AMOUNT 9
48 #define WEXT_CSCAN_BUF_LEN              360
49 #define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
50 #define WEXT_CSCAN_HEADER_SIZE          12
51 #define WEXT_CSCAN_SSID_SECTION         'S'
52 #define WEXT_CSCAN_CHANNEL_SECTION      'C'
53 #define WEXT_CSCAN_NPROBE_SECTION       'N'
54 #define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
55 #define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
56 #define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
57 #define WEXT_CSCAN_TYPE_SECTION         'T'
58
59 static struct mp_ioctl_handler mp_ioctl_hdl[] = {
60 /*0*/   GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_start_test_hdl, OID_RT_PRO_START_TEST)
61         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_stop_test_hdl, OID_RT_PRO_STOP_TEST)
62
63         GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_read_register_hdl, OID_RT_PRO_READ_REGISTER)
64         GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_write_register_hdl, OID_RT_PRO_WRITE_REGISTER)
65         GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_read_bb_reg_hdl, OID_RT_PRO_READ_BB_REG)
66 /*5*/   GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_write_bb_reg_hdl, OID_RT_PRO_WRITE_BB_REG)
67         GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_read_rf_reg_hdl, OID_RT_PRO_RF_READ_REGISTRY)
68         GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_write_rf_reg_hdl, OID_RT_PRO_RF_WRITE_REGISTRY)
69
70         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl, OID_RT_PRO_SET_CHANNEL_DIRECT_CALL)
71         GEN_HANDLER(sizeof(struct txpower_param), rtl8188eu_oid_rt_pro_set_tx_power_control_hdl, OID_RT_PRO_SET_TX_POWER_CONTROL)
72 /*10*/  GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_data_rate_hdl, OID_RT_PRO_SET_DATA_RATE)
73         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_bandwidth_hdl, OID_RT_SET_BANDWIDTH)
74         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_antenna_bb_hdl, OID_RT_PRO_SET_ANTENNA_BB)
75
76         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_continuous_tx_hdl, OID_RT_PRO_SET_CONTINUOUS_TX)
77         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl, OID_RT_PRO_SET_SINGLE_CARRIER_TX)
78 /*15*/  GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl, OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX)
79         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl, OID_RT_PRO_SET_SINGLE_TONE_TX)
80
81         EXT_MP_IOCTL_HANDLER(0, xmit_packet, 0)
82
83         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_rx_packet_type_hdl, OID_RT_SET_RX_PACKET_TYPE)
84         GEN_HANDLER(0, rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl, OID_RT_RESET_PHY_RX_PACKET_COUNT)
85 /*20*/  GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl, OID_RT_GET_PHY_RX_PACKET_RECEIVED)
86         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl, OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR)
87
88         GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
89         GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
90         GEN_HANDLER(sizeof(struct efuse_access_struct), rtl8188eu_oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE)
91 /*25*/  GEN_HANDLER(0, rtl8188eu_oid_rt_pro_efuse_map_hdl, OID_RT_PRO_EFUSE_MAP)
92         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_max_size_hdl, OID_RT_GET_EFUSE_MAX_SIZE)
93         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_current_size_hdl, OID_RT_GET_EFUSE_CURRENT_SIZE)
94
95         GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_thermal_meter_hdl, OID_RT_PRO_GET_THERMAL_METER)
96         GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_pro_set_power_tracking_hdl, OID_RT_PRO_SET_POWER_TRACKING)
97 /*30*/  GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_set_power_down_hdl, OID_RT_SET_POWER_DOWN)
98 /*31*/  GEN_HANDLER(0, rtl8188eu_oid_rt_pro_trigger_gpio_hdl, 0)
99 };
100
101 static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
102         6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
103         48000000, 54000000};
104
105 static const char * const iw_operation_mode[] = {
106         "Auto", "Ad-Hoc", "Managed",  "Master", "Repeater",
107         "Secondary", "Monitor"
108 };
109
110 static int hex2num_i(char c)
111 {
112         if (c >= '0' && c <= '9')
113                 return c - '0';
114         if (c >= 'a' && c <= 'f')
115                 return c - 'a' + 10;
116         if (c >= 'A' && c <= 'F')
117                 return c - 'A' + 10;
118         return -1;
119 }
120
121 /**
122  * hwaddr_aton - Convert ASCII string to MAC address
123  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
124  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
125  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
126  */
127 static int hwaddr_aton_i(const char *txt, u8 *addr)
128 {
129         int i;
130
131         for (i = 0; i < 6; i++) {
132                 int a, b;
133
134                 a = hex2num_i(*txt++);
135                 if (a < 0)
136                         return -1;
137                 b = hex2num_i(*txt++);
138                 if (b < 0)
139                         return -1;
140                 *addr++ = (a << 4) | b;
141                 if (i < 5 && *txt++ != ':')
142                         return -1;
143         }
144
145         return 0;
146 }
147
148 void indicate_wx_scan_complete_event(struct adapter *padapter)
149 {
150         union iwreq_data wrqu;
151
152         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
153         wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
154 }
155
156 void rtw_indicate_wx_assoc_event(struct adapter *padapter)
157 {
158         union iwreq_data wrqu;
159         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
160
161         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
162
163         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
164
165         memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
166
167         DBG_88E_LEVEL(_drv_always_, "assoc success\n");
168         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
169 }
170
171 void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
172 {
173         union iwreq_data wrqu;
174
175         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
176
177         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
178         _rtw_memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
179
180         DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
181         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
182 }
183
184 static char *translate_scan(struct adapter *padapter,
185                             struct iw_request_info *info,
186                             struct wlan_network *pnetwork,
187                             char *start, char *stop)
188 {
189         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
190         struct iw_event iwe;
191         u16 cap;
192         __le16 le_tmp;
193         u32 ht_ielen = 0;
194         char custom[MAX_CUSTOM_LEN];
195         char *p;
196         u16 max_rate = 0, rate, ht_cap = false;
197         u32 i = 0;
198         u8 bw_40MHz = 0, short_GI = 0;
199         u16 mcs_rate = 0;
200         u8 ss, sq;
201 #ifdef CONFIG_88EU_P2P
202         struct wifidirect_info *pwdinfo = &padapter->wdinfo;
203
204         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
205                 u32     blnGotP2PIE = false;
206
207                 /*      User is doing the P2P device discovery */
208                 /*      The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
209                 /*      If not, the driver should ignore this AP and go to the next AP. */
210
211                 /*      Verifying the SSID */
212                 if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
213                         u32     p2pielen = 0;
214
215                         if (pnetwork->network.Reserved[0] == 2) {/*  Probe Request */
216                                 /*      Verifying the P2P IE */
217                                 if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen))
218                                         blnGotP2PIE = true;
219                         } else {/*  Beacon or Probe Respones */
220                                 /*      Verifying the P2P IE */
221                                 if (rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen))
222                                         blnGotP2PIE = true;
223                         }
224                 }
225
226                 if (!blnGotP2PIE)
227                         return start;
228         }
229 #endif /* CONFIG_88EU_P2P */
230
231         /*  AP MAC address  */
232         iwe.cmd = SIOCGIWAP;
233         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
234
235         memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
236         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
237
238         /* Add the ESSID */
239         iwe.cmd = SIOCGIWESSID;
240         iwe.u.data.flags = 1;
241         iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32);
242         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
243
244         /* parsing HT_CAP_IE */
245         p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
246
247         if (p && ht_ielen > 0) {
248                 struct rtw_ieee80211_ht_cap *pht_capie;
249                 ht_cap = true;
250                 pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
251                 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
252                 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
253                 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
254         }
255
256         /* Add the protocol name */
257         iwe.cmd = SIOCGIWNAME;
258         if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
259                 if (ht_cap)
260                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
261                 else
262                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
263         } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
264                 if (ht_cap)
265                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
266                 else
267                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
268         } else {
269                 if (pnetwork->network.Configuration.DSConfig > 14) {
270                         if (ht_cap)
271                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
272                         else
273                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
274                 } else {
275                         if (ht_cap)
276                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
277                         else
278                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
279                 }
280         }
281
282         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
283
284           /* Add mode */
285         iwe.cmd = SIOCGIWMODE;
286         memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
287
288         cap = le16_to_cpu(le_tmp);
289
290         if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
291                 if (cap & WLAN_CAPABILITY_BSS)
292                         iwe.u.mode = IW_MODE_MASTER;
293                 else
294                         iwe.u.mode = IW_MODE_ADHOC;
295
296                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
297         }
298
299         if (pnetwork->network.Configuration.DSConfig < 1)
300                 pnetwork->network.Configuration.DSConfig = 1;
301
302          /* Add frequency/channel */
303         iwe.cmd = SIOCGIWFREQ;
304         iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
305         iwe.u.freq.e = 1;
306         iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
307         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
308
309         /* Add encryption capability */
310         iwe.cmd = SIOCGIWENCODE;
311         if (cap & WLAN_CAPABILITY_PRIVACY)
312                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
313         else
314                 iwe.u.data.flags = IW_ENCODE_DISABLED;
315         iwe.u.data.length = 0;
316         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
317
318         /*Add basic and extended rates */
319         max_rate = 0;
320         p = custom;
321         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
322         while (pnetwork->network.SupportedRates[i] != 0) {
323                 rate = pnetwork->network.SupportedRates[i]&0x7F;
324                 if (rate > max_rate)
325                         max_rate = rate;
326                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
327                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
328                 i++;
329         }
330
331         if (ht_cap) {
332                 if (mcs_rate&0x8000)/* MCS15 */
333                         max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
334                 else if (mcs_rate&0x0080)/* MCS7 */
335                         ;
336                 else/* default MCS7 */
337                         max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
338
339                 max_rate = max_rate*2;/* Mbps/2; */
340         }
341
342         iwe.cmd = SIOCGIWRATE;
343         iwe.u.bitrate.fixed = 0;
344         iwe.u.bitrate.disabled = 0;
345         iwe.u.bitrate.value = max_rate * 500000;
346         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
347
348         /* parsing WPA/WPA2 IE */
349         {
350                 u8 buf[MAX_WPA_IE_LEN];
351                 u8 wpa_ie[255], rsn_ie[255];
352                 u16 wpa_len = 0, rsn_len = 0;
353                 u8 *p;
354
355                 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
356                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid));
357                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
358
359                 if (wpa_len > 0) {
360                         p = buf;
361                         _rtw_memset(buf, 0, MAX_WPA_IE_LEN);
362                         p += sprintf(p, "wpa_ie =");
363                         for (i = 0; i < wpa_len; i++)
364                                 p += sprintf(p, "%02x", wpa_ie[i]);
365
366                         _rtw_memset(&iwe, 0, sizeof(iwe));
367                         iwe.cmd = IWEVCUSTOM;
368                         iwe.u.data.length = strlen(buf);
369                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
370
371                         _rtw_memset(&iwe, 0, sizeof(iwe));
372                         iwe.cmd = IWEVGENIE;
373                         iwe.u.data.length = wpa_len;
374                         start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
375                 }
376                 if (rsn_len > 0) {
377                         p = buf;
378                         _rtw_memset(buf, 0, MAX_WPA_IE_LEN);
379                         p += sprintf(p, "rsn_ie =");
380                         for (i = 0; i < rsn_len; i++)
381                                 p += sprintf(p, "%02x", rsn_ie[i]);
382                         _rtw_memset(&iwe, 0, sizeof(iwe));
383                         iwe.cmd = IWEVCUSTOM;
384                         iwe.u.data.length = strlen(buf);
385                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
386
387                         _rtw_memset(&iwe, 0, sizeof(iwe));
388                         iwe.cmd = IWEVGENIE;
389                         iwe.u.data.length = rsn_len;
390                         start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
391                 }
392         }
393
394         {/* parsing WPS IE */
395                 uint cnt = 0, total_ielen;
396                 u8 *wpsie_ptr = NULL;
397                 uint wps_ielen = 0;
398
399                 u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
400                 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
401
402                 while (cnt < total_ielen) {
403                         if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
404                                 wpsie_ptr = &ie_ptr[cnt];
405                                 iwe.cmd = IWEVGENIE;
406                                 iwe.u.data.length = (u16)wps_ielen;
407                                 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
408                         }
409                         cnt += ie_ptr[cnt+1]+2; /* goto next */
410                 }
411         }
412
413         /* Add quality statistics */
414         iwe.cmd = IWEVQUAL;
415         iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
416
417         if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
418             is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
419                 ss = padapter->recvpriv.signal_strength;
420                 sq = padapter->recvpriv.signal_qual;
421         } else {
422                 ss = pnetwork->network.PhyInfo.SignalStrength;
423                 sq = pnetwork->network.PhyInfo.SignalQuality;
424         }
425
426         iwe.u.qual.level = (u8)ss;
427         iwe.u.qual.qual = (u8)sq;   /*  signal quality */
428         iwe.u.qual.noise = 0; /*  noise level */
429         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
430         return start;
431 }
432
433 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
434 {
435         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
436         int ret = 0;
437
438         if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
439                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
440                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
441                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
442                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
443         } else if (value & AUTH_ALG_SHARED_KEY) {
444                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY  [value:0x%x]\n", value);
445                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
446
447                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
448                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
449         } else if (value & AUTH_ALG_OPEN_SYSTEM) {
450                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
451                 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
452                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
453                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
454                 }
455         } else if (value & AUTH_ALG_LEAP) {
456                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
457         } else {
458                 DBG_88E("wpa_set_auth_algs, error!\n");
459                 ret = -EINVAL;
460         }
461         return ret;
462 }
463
464 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
465 {
466         int ret = 0;
467         u32 wep_key_idx, wep_key_len, wep_total_len;
468         struct ndis_802_11_wep   *pwep = NULL;
469         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
470         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
471         struct security_priv *psecuritypriv = &padapter->securitypriv;
472 #ifdef CONFIG_88EU_P2P
473         struct wifidirect_info *pwdinfo = &padapter->wdinfo;
474 #endif /* CONFIG_88EU_P2P */
475
476         param->u.crypt.err = 0;
477         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
478
479         if (param_len < (u32) ((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
480                 ret =  -EINVAL;
481                 goto exit;
482         }
483
484         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
485             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
486             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
487                 if (param->u.crypt.idx >= WEP_KEYS) {
488                         ret = -EINVAL;
489                         goto exit;
490                 }
491         } else {
492                 ret = -EINVAL;
493                 goto exit;
494         }
495
496         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
497                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
498                 DBG_88E("wpa_set_encryption, crypt.alg = WEP\n");
499
500                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
501                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
502                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
503
504                 wep_key_idx = param->u.crypt.idx;
505                 wep_key_len = param->u.crypt.key_len;
506
507                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
508                 DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx);
509
510                 if (wep_key_idx > WEP_KEYS)
511                         return -EINVAL;
512
513                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
514
515                 if (wep_key_len > 0) {
516                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
517                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
518                         pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
519                         if (pwep == NULL) {
520                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
521                                 goto exit;
522                         }
523                         _rtw_memset(pwep, 0, wep_total_len);
524                         pwep->KeyLength = wep_key_len;
525                         pwep->Length = wep_total_len;
526                         if (wep_key_len == 13) {
527                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
528                                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
529                         }
530                 } else {
531                         ret = -EINVAL;
532                         goto exit;
533                 }
534                 pwep->KeyIndex = wep_key_idx;
535                 pwep->KeyIndex |= 0x80000000;
536                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
537                 if (param->u.crypt.set_tx) {
538                         DBG_88E("wep, set_tx = 1\n");
539                         if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
540                                 ret = -EOPNOTSUPP;
541                 } else {
542                         DBG_88E("wep, set_tx = 0\n");
543                         if (wep_key_idx >= WEP_KEYS) {
544                                 ret = -EOPNOTSUPP;
545                                 goto exit;
546                         }
547                       memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
548                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
549                         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
550                 }
551                 goto exit;
552         }
553
554         if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
555                 struct sta_info *psta, *pbcmc_sta;
556                 struct sta_priv *pstapriv = &padapter->stapriv;
557
558                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */
559                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
560                         if (psta == NULL) {
561                                 ;
562                         } else {
563                                 if (strcmp(param->u.crypt.alg, "none") != 0)
564                                         psta->ieee8021x_blocked = false;
565
566                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
567                                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
568                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
569
570                                 if (param->u.crypt.set_tx == 1) { /* pairwise key */
571                                         memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
572
573                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
574                                                 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
575                                                 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
576                                                 padapter->securitypriv.busetkipkey = false;
577                                         }
578
579                                         DBG_88E(" ~~~~set sta key:unicastkey\n");
580
581                                         rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
582                                 } else { /* group key */
583                                         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));
584                                         memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
585                                         memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
586                                         padapter->securitypriv.binstallGrpkey = true;
587                                         DBG_88E(" ~~~~set sta key:groupkey\n");
588
589                                         padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
590
591                                         rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
592 #ifdef CONFIG_88EU_P2P
593                                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
594                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
595 #endif /* CONFIG_88EU_P2P */
596                                 }
597                         }
598                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
599                         if (pbcmc_sta == NULL) {
600                                 ;
601                         } else {
602                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
603                                 if (strcmp(param->u.crypt.alg, "none") != 0)
604                                         pbcmc_sta->ieee8021x_blocked = false;
605
606                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
607                                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
608                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
609                         }
610                 }
611         }
612
613 exit:
614
615         kfree(pwep);
616         return ret;
617 }
618
619 static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
620 {
621         u8 *buf = NULL;
622         int group_cipher = 0, pairwise_cipher = 0;
623         int ret = 0;
624 #ifdef CONFIG_88EU_P2P
625         struct wifidirect_info *pwdinfo = &padapter->wdinfo;
626 #endif /* CONFIG_88EU_P2P */
627
628         if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
629                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
630                 if (pie == NULL)
631                         return ret;
632                 else
633                         return -EINVAL;
634         }
635
636         if (ielen) {
637                 buf = rtw_zmalloc(ielen);
638                 if (buf == NULL) {
639                         ret =  -ENOMEM;
640                         goto exit;
641                 }
642
643                 memcpy(buf, pie, ielen);
644
645                 /* dump */
646                 {
647                         int i;
648                         DBG_88E("\n wpa_ie(length:%d):\n", ielen);
649                         for (i = 0; i < ielen; i += 8)
650                                 DBG_88E("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]);
651                 }
652
653                 if (ielen < RSN_HEADER_LEN) {
654                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
655                         ret  = -1;
656                         goto exit;
657                 }
658
659                 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
660                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
661                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
662                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
663                 }
664
665                 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
666                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
667                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
668                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
669                 }
670
671                 switch (group_cipher) {
672                 case WPA_CIPHER_NONE:
673                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
674                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
675                         break;
676                 case WPA_CIPHER_WEP40:
677                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
678                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
679                         break;
680                 case WPA_CIPHER_TKIP:
681                         padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
682                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
683                         break;
684                 case WPA_CIPHER_CCMP:
685                         padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
686                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
687                         break;
688                 case WPA_CIPHER_WEP104:
689                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
690                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
691                         break;
692                 }
693
694                 switch (pairwise_cipher) {
695                 case WPA_CIPHER_NONE:
696                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
697                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
698                         break;
699                 case WPA_CIPHER_WEP40:
700                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
701                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
702                         break;
703                 case WPA_CIPHER_TKIP:
704                         padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
705                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
706                         break;
707                 case WPA_CIPHER_CCMP:
708                         padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
709                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
710                         break;
711                 case WPA_CIPHER_WEP104:
712                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
713                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
714                         break;
715                 }
716
717                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
718                 {/* set wps_ie */
719                         u16 cnt = 0;
720                         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
721
722                         while (cnt < ielen) {
723                                 eid = buf[cnt];
724                                 if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
725                                         DBG_88E("SET WPS_IE\n");
726
727                                         padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2) : (MAX_WPA_IE_LEN<<2);
728
729                                         memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
730
731                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
732 #ifdef CONFIG_88EU_P2P
733                                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
734                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
735 #endif /* CONFIG_88EU_P2P */
736                                         cnt += buf[cnt+1]+2;
737                                         break;
738                                 } else {
739                                         cnt += buf[cnt+1]+2; /* goto next */
740                                 }
741                         }
742                 }
743         }
744
745         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
746                  ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
747                  pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
748 exit:
749         kfree(buf);
750         return ret;
751 }
752
753 typedef unsigned char   NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
754
755 static int rtw_wx_get_name(struct net_device *dev,
756                              struct iw_request_info *info,
757                              union iwreq_data *wrqu, char *extra)
758 {
759         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
760         u32 ht_ielen = 0;
761         char *p;
762         u8 ht_cap = false;
763         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
764         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
765         NDIS_802_11_RATES_EX *prates = NULL;
766
767         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
768
769         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
770                 /* parsing HT_CAP_IE */
771                 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
772                 if (p && ht_ielen > 0)
773                         ht_cap = true;
774
775                 prates = &pcur_bss->SupportedRates;
776
777                 if (rtw_is_cckratesonly_included((u8 *)prates) == true) {
778                         if (ht_cap)
779                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
780                         else
781                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
782                 } else if ((rtw_is_cckrates_included((u8 *)prates)) == true) {
783                         if (ht_cap)
784                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
785                         else
786                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
787                 } else {
788                         if (pcur_bss->Configuration.DSConfig > 14) {
789                                 if (ht_cap)
790                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
791                                 else
792                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
793                         } else {
794                                 if (ht_cap)
795                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
796                                 else
797                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
798                         }
799                 }
800         } else {
801                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
802         }
803         return 0;
804 }
805
806 static int rtw_wx_set_freq(struct net_device *dev,
807                              struct iw_request_info *info,
808                              union iwreq_data *wrqu, char *extra)
809 {
810         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
811         return 0;
812 }
813
814 static int rtw_wx_get_freq(struct net_device *dev,
815                              struct iw_request_info *info,
816                              union iwreq_data *wrqu, char *extra)
817 {
818         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
819         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
820         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
821
822         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
823                 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
824                 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
825                 wrqu->freq.e = 1;
826                 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
827         } else {
828                 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
829                 wrqu->freq.e = 1;
830                 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
831         }
832
833         return 0;
834 }
835
836 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
837                              union iwreq_data *wrqu, char *b)
838 {
839         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
840         enum ndis_802_11_network_infra networkType;
841         int ret = 0;
842
843         if (_FAIL == rtw_pwr_wakeup(padapter)) {
844                 ret = -EPERM;
845                 goto exit;
846         }
847
848         if (!padapter->hw_init_completed) {
849                 ret = -EPERM;
850                 goto exit;
851         }
852
853         switch (wrqu->mode) {
854         case IW_MODE_AUTO:
855                 networkType = Ndis802_11AutoUnknown;
856                 DBG_88E("set_mode = IW_MODE_AUTO\n");
857                 break;
858         case IW_MODE_ADHOC:
859                 networkType = Ndis802_11IBSS;
860                 DBG_88E("set_mode = IW_MODE_ADHOC\n");
861                 break;
862         case IW_MODE_MASTER:
863                 networkType = Ndis802_11APMode;
864                 DBG_88E("set_mode = IW_MODE_MASTER\n");
865                 break;
866         case IW_MODE_INFRA:
867                 networkType = Ndis802_11Infrastructure;
868                 DBG_88E("set_mode = IW_MODE_INFRA\n");
869                 break;
870         default:
871                 ret = -EINVAL;
872                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode]));
873                 goto exit;
874         }
875         if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
876                 ret = -EPERM;
877                 goto exit;
878         }
879         rtw_setopmode_cmd(padapter, networkType);
880 exit:
881         return ret;
882 }
883
884 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
885                              union iwreq_data *wrqu, char *b)
886 {
887         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
888         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
889
890         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
891
892         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
893                 wrqu->mode = IW_MODE_INFRA;
894         else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
895                   (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
896                 wrqu->mode = IW_MODE_ADHOC;
897         else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
898                 wrqu->mode = IW_MODE_MASTER;
899         else
900                 wrqu->mode = IW_MODE_AUTO;
901
902         return 0;
903 }
904
905 static int rtw_wx_set_pmkid(struct net_device *dev,
906                             struct iw_request_info *a,
907                             union iwreq_data *wrqu, char *extra)
908 {
909         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
910         u8   j, blInserted = false;
911         int  ret = false;
912         struct security_priv *psecuritypriv = &padapter->securitypriv;
913         struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
914         u8     strZeroMacAddress[ETH_ALEN] = {0x00};
915         u8     strIssueBssid[ETH_ALEN] = {0x00};
916
917         memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
918         if (pPMK->cmd == IW_PMKSA_ADD) {
919                 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
920                 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
921                         return ret;
922                 else
923                         ret = true;
924                 blInserted = false;
925
926                 /* overwrite PMKID */
927                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
928                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
929                                 /*  BSSID is matched, the same AP => rewrite with new PMKID. */
930                                 DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
931                                 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
932                                 psecuritypriv->PMKIDList[j].bUsed = true;
933                                 psecuritypriv->PMKIDIndex = j+1;
934                                 blInserted = true;
935                                 break;
936                         }
937                 }
938
939                 if (!blInserted) {
940                         /*  Find a new entry */
941                         DBG_88E("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
942                                 psecuritypriv->PMKIDIndex);
943
944                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
945                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
946
947                         psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
948                         psecuritypriv->PMKIDIndex++;
949                         if (psecuritypriv->PMKIDIndex == 16)
950                                 psecuritypriv->PMKIDIndex = 0;
951                 }
952         } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
953                 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
954                 ret = true;
955                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
956                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
957                                 /*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
958                                 _rtw_memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
959                                 psecuritypriv->PMKIDList[j].bUsed = false;
960                                 break;
961                         }
962                }
963         } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
964                 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
965                 _rtw_memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
966                 psecuritypriv->PMKIDIndex = 0;
967                 ret = true;
968         }
969         return ret;
970 }
971
972 static int rtw_wx_get_sens(struct net_device *dev,
973                              struct iw_request_info *info,
974                              union iwreq_data *wrqu, char *extra)
975 {
976         wrqu->sens.value = 0;
977         wrqu->sens.fixed = 0;   /* no auto select */
978         wrqu->sens.disabled = 1;
979         return 0;
980 }
981
982 static int rtw_wx_get_range(struct net_device *dev,
983                                 struct iw_request_info *info,
984                                 union iwreq_data *wrqu, char *extra)
985 {
986         struct iw_range *range = (struct iw_range *)extra;
987         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
988         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
989
990         u16 val;
991         int i;
992
993         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
994
995         wrqu->data.length = sizeof(*range);
996         _rtw_memset(range, 0, sizeof(*range));
997
998         /* Let's try to keep this struct in the same order as in
999          * linux/include/wireless.h
1000          */
1001
1002         /* TODO: See what values we can set, and remove the ones we can't
1003          * set, or fill them with some default data.
1004          */
1005
1006         /* ~5 Mb/s real (802.11b) */
1007         range->throughput = 5 * 1000 * 1000;
1008
1009         /* signal level threshold range */
1010
1011         /* percent values between 0 and 100. */
1012         range->max_qual.qual = 100;
1013         range->max_qual.level = 100;
1014         range->max_qual.noise = 100;
1015         range->max_qual.updated = 7; /* Updated all three */
1016
1017         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
1018         /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
1019         range->avg_qual.level = 178; /* -78 dBm */
1020         range->avg_qual.noise = 0;
1021         range->avg_qual.updated = 7; /* Updated all three */
1022
1023         range->num_bitrates = RATE_COUNT;
1024
1025         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
1026                 range->bitrate[i] = rtw_rates[i];
1027
1028         range->min_frag = MIN_FRAG_THRESHOLD;
1029         range->max_frag = MAX_FRAG_THRESHOLD;
1030
1031         range->pm_capa = 0;
1032
1033         range->we_version_compiled = WIRELESS_EXT;
1034         range->we_version_source = 16;
1035
1036         for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
1037                 /*  Include only legal frequencies for some countries */
1038                 if (pmlmeext->channel_set[i].ChannelNum != 0) {
1039                         range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
1040                         range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
1041                         range->freq[val].e = 1;
1042                         val++;
1043                 }
1044
1045                 if (val == IW_MAX_FREQUENCIES)
1046                         break;
1047         }
1048
1049         range->num_channels = val;
1050         range->num_frequency = val;
1051
1052 /*  The following code will proivde the security capability to network manager. */
1053 /*  If the driver doesn't provide this capability to network manager, */
1054 /*  the WPA/WPA2 routers can't be chosen in the network manager. */
1055
1056 /*
1057 #define IW_SCAN_CAPA_NONE               0x00
1058 #define IW_SCAN_CAPA_ESSID              0x01
1059 #define IW_SCAN_CAPA_BSSID              0x02
1060 #define IW_SCAN_CAPA_CHANNEL            0x04
1061 #define IW_SCAN_CAPA_MODE               0x08
1062 #define IW_SCAN_CAPA_RATE               0x10
1063 #define IW_SCAN_CAPA_TYPE               0x20
1064 #define IW_SCAN_CAPA_TIME               0x40
1065 */
1066
1067         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1068                           IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1069
1070         range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
1071                            IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
1072                            IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
1073         return 0;
1074 }
1075
1076 /* set bssid flow */
1077 /* s1. rtw_set_802_11_infrastructure_mode() */
1078 /* s2. rtw_set_802_11_authentication_mode() */
1079 /* s3. set_802_11_encryption_mode() */
1080 /* s4. rtw_set_802_11_bssid() */
1081 static int rtw_wx_set_wap(struct net_device *dev,
1082                          struct iw_request_info *info,
1083                          union iwreq_data *awrq,
1084                          char *extra)
1085 {
1086         uint ret = 0;
1087         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1088         struct sockaddr *temp = (struct sockaddr *)awrq;
1089         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1090         struct list_head *phead;
1091         u8 *dst_bssid, *src_bssid;
1092         struct __queue *queue   = &(pmlmepriv->scanned_queue);
1093         struct  wlan_network    *pnetwork = NULL;
1094         enum ndis_802_11_auth_mode      authmode;
1095
1096         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1097                 ret = -1;
1098                 goto exit;
1099         }
1100
1101         if (!padapter->bup) {
1102                 ret = -1;
1103                 goto exit;
1104         }
1105
1106         if (temp->sa_family != ARPHRD_ETHER) {
1107                 ret = -EINVAL;
1108                 goto exit;
1109         }
1110
1111         authmode = padapter->securitypriv.ndisauthtype;
1112         spin_lock_bh(&queue->lock);
1113         phead = get_list_head(queue);
1114         pmlmepriv->pscanned = phead->next;
1115
1116         while (1) {
1117                 if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == true)
1118                         break;
1119
1120                 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1121
1122                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1123
1124                 dst_bssid = pnetwork->network.MacAddress;
1125
1126                 src_bssid = temp->sa_data;
1127
1128                 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
1129                         if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1130                                 ret = -1;
1131                                 spin_unlock_bh(&queue->lock);
1132                                 goto exit;
1133                         }
1134
1135                                 break;
1136                 }
1137         }
1138         spin_unlock_bh(&queue->lock);
1139
1140         rtw_set_802_11_authentication_mode(padapter, authmode);
1141         /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1142         if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
1143                 ret = -1;
1144                 goto exit;
1145         }
1146
1147 exit:
1148
1149         return ret;
1150 }
1151
1152 static int rtw_wx_get_wap(struct net_device *dev,
1153                             struct iw_request_info *info,
1154                             union iwreq_data *wrqu, char *extra)
1155 {
1156         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1157         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1158         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1159
1160         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1161
1162         _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1163
1164         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
1165
1166         if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
1167             ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
1168             ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true))
1169                 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1170         else
1171                 _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1172         return 0;
1173 }
1174
1175 static int rtw_wx_set_mlme(struct net_device *dev,
1176                              struct iw_request_info *info,
1177                              union iwreq_data *wrqu, char *extra)
1178 {
1179         int ret = 0;
1180         u16 reason;
1181         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1182         struct iw_mlme *mlme = (struct iw_mlme *)extra;
1183
1184         if (mlme == NULL)
1185                 return -1;
1186
1187         DBG_88E("%s\n", __func__);
1188
1189         reason = mlme->reason_code;
1190
1191         DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
1192
1193         switch (mlme->cmd) {
1194         case IW_MLME_DEAUTH:
1195                 if (!rtw_set_802_11_disassociate(padapter))
1196                         ret = -1;
1197                 break;
1198         case IW_MLME_DISASSOC:
1199                 if (!rtw_set_802_11_disassociate(padapter))
1200                         ret = -1;
1201                 break;
1202         default:
1203                 return -EOPNOTSUPP;
1204         }
1205         return ret;
1206 }
1207
1208 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1209                              union iwreq_data *wrqu, char *extra)
1210 {
1211         u8 _status = false;
1212         int ret = 0;
1213         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1214         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1215         struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1216 #ifdef CONFIG_88EU_P2P
1217         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1218 #endif /* CONFIG_88EU_P2P */
1219         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
1220
1221         if (padapter->registrypriv.mp_mode == 1) {
1222                 if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
1223                         ret = -1;
1224                         goto exit;
1225                 }
1226         }
1227         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1228                 ret = -1;
1229                 goto exit;
1230         }
1231
1232         if (padapter->bDriverStopped) {
1233                 DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped);
1234                 ret = -1;
1235                 goto exit;
1236         }
1237
1238         if (!padapter->bup) {
1239                 ret = -1;
1240                 goto exit;
1241         }
1242
1243         if (!padapter->hw_init_completed) {
1244                 ret = -1;
1245                 goto exit;
1246         }
1247
1248         /*  When Busy Traffic, driver do not site survey. So driver return success. */
1249         /*  wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1250         /*  modify by thomas 2011-02-22. */
1251         if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
1252                 indicate_wx_scan_complete_event(padapter);
1253                 goto exit;
1254         }
1255
1256         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1257                 indicate_wx_scan_complete_event(padapter);
1258                 goto exit;
1259         }
1260
1261 /*      For the DMP WiFi Display project, the driver won't to scan because */
1262 /*      the pmlmepriv->scan_interval is always equal to 3. */
1263 /*      So, the wpa_supplicant won't find out the WPS SoftAP. */
1264
1265 #ifdef CONFIG_88EU_P2P
1266         if (pwdinfo->p2p_state != P2P_STATE_NONE) {
1267                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
1268                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
1269                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
1270                 rtw_free_network_queue(padapter, true);
1271         }
1272 #endif /* CONFIG_88EU_P2P */
1273
1274         _rtw_memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
1275
1276         if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1277                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1278
1279                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1280                         int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1281
1282                         memcpy(ssid[0].Ssid, req->essid, len);
1283                         ssid[0].SsidLength = len;
1284
1285                         DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
1286
1287                         spin_lock_bh(&pmlmepriv->lock);
1288
1289                         _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1290
1291                         spin_unlock_bh(&pmlmepriv->lock);
1292                 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
1293                         DBG_88E("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
1294                 }
1295         } else {
1296                 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
1297                     !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1298                         int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
1299                         char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1300                         char section;
1301                         char sec_len;
1302                         int ssid_index = 0;
1303
1304                         while (len >= 1) {
1305                                 section = *(pos++);
1306                                 len -= 1;
1307
1308                                 switch (section) {
1309                                 case WEXT_CSCAN_SSID_SECTION:
1310                                         if (len < 1) {
1311                                                 len = 0;
1312                                                 break;
1313                                         }
1314                                         sec_len = *(pos++); len -= 1;
1315                                         if (sec_len > 0 && sec_len <= len) {
1316                                                 ssid[ssid_index].SsidLength = sec_len;
1317                                                 memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
1318                                                 ssid_index++;
1319                                         }
1320                                         pos += sec_len;
1321                                         len -= sec_len;
1322                                         break;
1323                                 case WEXT_CSCAN_TYPE_SECTION:
1324                                 case WEXT_CSCAN_CHANNEL_SECTION:
1325                                         pos += 1;
1326                                         len -= 1;
1327                                         break;
1328                                 case WEXT_CSCAN_PASV_DWELL_SECTION:
1329                                 case WEXT_CSCAN_HOME_DWELL_SECTION:
1330                                 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1331                                         pos += 2;
1332                                         len -= 2;
1333                                         break;
1334                                 default:
1335                                         len = 0; /*  stop parsing */
1336                                 }
1337                         }
1338
1339                         /* it has still some scan parameter to parse, we only do this now... */
1340                         _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1341                 } else {
1342                         _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1343                 }
1344         }
1345
1346         if (!_status)
1347                 ret = -1;
1348
1349 exit:
1350
1351         return ret;
1352 }
1353
1354 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1355                              union iwreq_data *wrqu, char *extra)
1356 {
1357         struct list_head *plist, *phead;
1358         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1359         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1360         struct __queue *queue   = &(pmlmepriv->scanned_queue);
1361         struct  wlan_network    *pnetwork = NULL;
1362         char *ev = extra;
1363         char *stop = ev + wrqu->data.length;
1364         u32 ret = 0;
1365         u32 cnt = 0;
1366         u32 wait_for_surveydone;
1367         int wait_status;
1368 #ifdef CONFIG_88EU_P2P
1369         struct  wifidirect_info *pwdinfo = &padapter->wdinfo;
1370 #endif /* CONFIG_88EU_P2P */
1371         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
1372         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1373
1374         if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
1375                 ret = -EINVAL;
1376                 goto exit;
1377         }
1378
1379 #ifdef CONFIG_88EU_P2P
1380         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1381                 /*      P2P is enabled */
1382                 wait_for_surveydone = 200;
1383         } else {
1384                 /*      P2P is disabled */
1385                 wait_for_surveydone = 100;
1386         }
1387 #else
1388         {
1389                 wait_for_surveydone = 100;
1390         }
1391 #endif /* CONFIG_88EU_P2P */
1392
1393         wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1394
1395         while (check_fwstate(pmlmepriv, wait_status)) {
1396                 msleep(30);
1397                 cnt++;
1398                 if (cnt > wait_for_surveydone)
1399                         break;
1400         }
1401
1402         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1403
1404         phead = get_list_head(queue);
1405         plist = phead->next;
1406
1407         while (1) {
1408                 if (rtw_end_of_queue_search(phead, plist))
1409                         break;
1410
1411                 if ((stop - ev) < SCAN_ITEM_SIZE) {
1412                         ret = -E2BIG;
1413                         break;
1414                 }
1415
1416                 pnetwork = container_of(plist, struct wlan_network, list);
1417
1418                 /* report network only if the current channel set contains the channel to which this network belongs */
1419                 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
1420                         ev = translate_scan(padapter, a, pnetwork, ev, stop);
1421
1422                 plist = plist->next;
1423         }
1424
1425         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1426
1427         wrqu->data.length = ev-extra;
1428         wrqu->data.flags = 0;
1429
1430 exit:
1431         return ret;
1432 }
1433
1434 /* set ssid flow */
1435 /* s1. rtw_set_802_11_infrastructure_mode() */
1436 /* s2. set_802_11_authenticaion_mode() */
1437 /* s3. set_802_11_encryption_mode() */
1438 /* s4. rtw_set_802_11_ssid() */
1439 static int rtw_wx_set_essid(struct net_device *dev,
1440                               struct iw_request_info *a,
1441                               union iwreq_data *wrqu, char *extra)
1442 {
1443         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1444         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1445         struct __queue *queue = &pmlmepriv->scanned_queue;
1446         struct list_head *phead;
1447         struct wlan_network *pnetwork = NULL;
1448         enum ndis_802_11_auth_mode authmode;
1449         struct ndis_802_11_ssid ndis_ssid;
1450         u8 *dst_ssid, *src_ssid;
1451
1452         uint ret = 0, len;
1453
1454
1455         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1456                  ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1457         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1458                 ret = -1;
1459                 goto exit;
1460         }
1461
1462         if (!padapter->bup) {
1463                 ret = -1;
1464                 goto exit;
1465         }
1466
1467         if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1468                 ret = -E2BIG;
1469                 goto exit;
1470         }
1471
1472         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1473                 ret = -1;
1474                 goto exit;
1475         }
1476
1477         authmode = padapter->securitypriv.ndisauthtype;
1478         DBG_88E("=>%s\n", __func__);
1479         if (wrqu->essid.flags && wrqu->essid.length) {
1480                 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1481
1482                 if (wrqu->essid.length != 33)
1483                         DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1484
1485                 _rtw_memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1486                 ndis_ssid.SsidLength = len;
1487                 memcpy(ndis_ssid.Ssid, extra, len);
1488                 src_ssid = ndis_ssid.Ssid;
1489
1490                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
1491                 spin_lock_bh(&queue->lock);
1492                phead = get_list_head(queue);
1493               pmlmepriv->pscanned = phead->next;
1494
1495                 while (1) {
1496                         if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == true) {
1497                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
1498                                          ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
1499
1500                                 break;
1501                         }
1502
1503                         pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1504
1505                         pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1506
1507                         dst_ssid = pnetwork->network.Ssid.Ssid;
1508
1509                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1510                                  ("rtw_wx_set_essid: dst_ssid =%s\n",
1511                                   pnetwork->network.Ssid.Ssid));
1512
1513                         if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
1514                             (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
1515                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1516                                          ("rtw_wx_set_essid: find match, set infra mode\n"));
1517
1518                                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
1519                                         if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1520                                                 continue;
1521                                 }
1522
1523                                 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1524                                         ret = -1;
1525                                         spin_unlock_bh(&queue->lock);
1526                                         goto exit;
1527                                 }
1528
1529                                 break;
1530                         }
1531                 }
1532                 spin_unlock_bh(&queue->lock);
1533                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1534                          ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1535                 rtw_set_802_11_authentication_mode(padapter, authmode);
1536                 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1537                         ret = -1;
1538                         goto exit;
1539                 }
1540         }
1541
1542 exit:
1543
1544         DBG_88E("<=%s, ret %d\n", __func__, ret);
1545
1546
1547         return ret;
1548 }
1549
1550 static int rtw_wx_get_essid(struct net_device *dev,
1551                               struct iw_request_info *a,
1552                               union iwreq_data *wrqu, char *extra)
1553 {
1554         u32 len, ret = 0;
1555         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1556         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1557         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1558
1559         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
1560
1561
1562         if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
1563             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
1564                 len = pcur_bss->Ssid.SsidLength;
1565
1566                 wrqu->essid.length = len;
1567
1568                 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1569
1570                 wrqu->essid.flags = 1;
1571         } else {
1572                 ret = -1;
1573                 goto exit;
1574         }
1575
1576 exit:
1577
1578
1579         return ret;
1580 }
1581
1582 static int rtw_wx_set_rate(struct net_device *dev,
1583                               struct iw_request_info *a,
1584                               union iwreq_data *wrqu, char *extra)
1585 {
1586         int i, ret = 0;
1587         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1588         u8 datarates[NumRates];
1589         u32     target_rate = wrqu->bitrate.value;
1590         u32     fixed = wrqu->bitrate.fixed;
1591         u32     ratevalue = 0;
1592          u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1593
1594
1595         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
1596         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1597
1598         if (target_rate == -1) {
1599                 ratevalue = 11;
1600                 goto set_rate;
1601         }
1602         target_rate = target_rate/100000;
1603
1604         switch (target_rate) {
1605         case 10:
1606                 ratevalue = 0;
1607                 break;
1608         case 20:
1609                 ratevalue = 1;
1610                 break;
1611         case 55:
1612                 ratevalue = 2;
1613                 break;
1614         case 60:
1615                 ratevalue = 3;
1616                 break;
1617         case 90:
1618                 ratevalue = 4;
1619                 break;
1620         case 110:
1621                 ratevalue = 5;
1622                 break;
1623         case 120:
1624                 ratevalue = 6;
1625                 break;
1626         case 180:
1627                 ratevalue = 7;
1628                 break;
1629         case 240:
1630                 ratevalue = 8;
1631                 break;
1632         case 360:
1633                 ratevalue = 9;
1634                 break;
1635         case 480:
1636                 ratevalue = 10;
1637                 break;
1638         case 540:
1639                 ratevalue = 11;
1640                 break;
1641         default:
1642                 ratevalue = 11;
1643                 break;
1644         }
1645
1646 set_rate:
1647
1648         for (i = 0; i < NumRates; i++) {
1649                 if (ratevalue == mpdatarate[i]) {
1650                         datarates[i] = mpdatarate[i];
1651                         if (fixed == 0)
1652                                 break;
1653                 } else {
1654                         datarates[i] = 0xff;
1655                 }
1656
1657                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1658         }
1659
1660         if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
1661                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n"));
1662                 ret = -1;
1663         }
1664
1665
1666         return ret;
1667 }
1668
1669 static int rtw_wx_get_rate(struct net_device *dev,
1670                              struct iw_request_info *info,
1671                              union iwreq_data *wrqu, char *extra)
1672 {
1673         u16 max_rate = 0;
1674
1675         max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1676
1677         if (max_rate == 0)
1678                 return -EPERM;
1679
1680         wrqu->bitrate.fixed = 0;        /* no auto select */
1681         wrqu->bitrate.value = max_rate * 100000;
1682
1683         return 0;
1684 }
1685
1686 static int rtw_wx_set_rts(struct net_device *dev,
1687                              struct iw_request_info *info,
1688                              union iwreq_data *wrqu, char *extra)
1689 {
1690         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1691
1692
1693         if (wrqu->rts.disabled) {
1694                 padapter->registrypriv.rts_thresh = 2347;
1695         } else {
1696                 if (wrqu->rts.value < 0 ||
1697                     wrqu->rts.value > 2347)
1698                         return -EINVAL;
1699
1700                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1701         }
1702
1703         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1704
1705
1706         return 0;
1707 }
1708
1709 static int rtw_wx_get_rts(struct net_device *dev,
1710                              struct iw_request_info *info,
1711                              union iwreq_data *wrqu, char *extra)
1712 {
1713         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1714
1715
1716         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1717
1718         wrqu->rts.value = padapter->registrypriv.rts_thresh;
1719         wrqu->rts.fixed = 0;    /* no auto select */
1720         /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1721
1722
1723         return 0;
1724 }
1725
1726 static int rtw_wx_set_frag(struct net_device *dev,
1727                              struct iw_request_info *info,
1728                              union iwreq_data *wrqu, char *extra)
1729 {
1730         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1731
1732
1733         if (wrqu->frag.disabled) {
1734                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1735         } else {
1736                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1737                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
1738                         return -EINVAL;
1739
1740                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1741         }
1742
1743         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1744
1745
1746         return 0;
1747 }
1748
1749 static int rtw_wx_get_frag(struct net_device *dev,
1750                              struct iw_request_info *info,
1751                              union iwreq_data *wrqu, char *extra)
1752 {
1753         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1754
1755
1756         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1757
1758         wrqu->frag.value = padapter->xmitpriv.frag_len;
1759         wrqu->frag.fixed = 0;   /* no auto select */
1760
1761
1762         return 0;
1763 }
1764
1765 static int rtw_wx_get_retry(struct net_device *dev,
1766                              struct iw_request_info *info,
1767                              union iwreq_data *wrqu, char *extra)
1768 {
1769         wrqu->retry.value = 7;
1770         wrqu->retry.fixed = 0;  /* no auto select */
1771         wrqu->retry.disabled = 1;
1772
1773         return 0;
1774 }
1775
1776 static int rtw_wx_set_enc(struct net_device *dev,
1777                             struct iw_request_info *info,
1778                             union iwreq_data *wrqu, char *keybuf)
1779 {
1780         u32 key, ret = 0;
1781         u32 keyindex_provided;
1782         struct ndis_802_11_wep   wep;
1783         enum ndis_802_11_auth_mode authmode;
1784
1785         struct iw_point *erq = &(wrqu->encoding);
1786         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1787         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1788         DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
1789
1790         _rtw_memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1791
1792         key = erq->flags & IW_ENCODE_INDEX;
1793
1794
1795         if (erq->flags & IW_ENCODE_DISABLED) {
1796                 DBG_88E("EncryptionDisabled\n");
1797                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1798                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1799                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1800                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1801                 authmode = Ndis802_11AuthModeOpen;
1802                 padapter->securitypriv.ndisauthtype = authmode;
1803
1804                 goto exit;
1805         }
1806
1807         if (key) {
1808                 if (key > WEP_KEYS)
1809                         return -EINVAL;
1810                 key--;
1811                 keyindex_provided = 1;
1812         } else {
1813                 keyindex_provided = 0;
1814                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1815                 DBG_88E("rtw_wx_set_enc, key =%d\n", key);
1816         }
1817
1818         /* set authentication mode */
1819         if (erq->flags & IW_ENCODE_OPEN) {
1820                 DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
1821                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1822                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1823                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1824                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1825                 authmode = Ndis802_11AuthModeOpen;
1826                 padapter->securitypriv.ndisauthtype = authmode;
1827         } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1828                 DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
1829                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1830                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1831                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1832                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1833                 authmode = Ndis802_11AuthModeShared;
1834                 padapter->securitypriv.ndisauthtype = authmode;
1835         } else {
1836                 DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
1837
1838                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1839                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1840                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1841                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1842                 authmode = Ndis802_11AuthModeOpen;
1843                 padapter->securitypriv.ndisauthtype = authmode;
1844         }
1845
1846         wep.KeyIndex = key;
1847         if (erq->length > 0) {
1848                 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1849
1850                 wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
1851         } else {
1852                 wep.KeyLength = 0;
1853
1854                 if (keyindex_provided == 1) {
1855                         /*  set key_id only, no given KeyMaterial(erq->length == 0). */
1856                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
1857
1858                         DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1859
1860                         switch (padapter->securitypriv.dot11DefKeylen[key]) {
1861                         case 5:
1862                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1863                                 break;
1864                         case 13:
1865                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1866                                 break;
1867                         default:
1868                                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1869                                 break;
1870                         }
1871
1872                         goto exit;
1873                 }
1874         }
1875
1876         wep.KeyIndex |= 0x80000000;
1877
1878         memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1879
1880         if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
1881                 if (rf_on == pwrpriv->rf_pwrstate)
1882                         ret = -EOPNOTSUPP;
1883                 goto exit;
1884         }
1885
1886 exit:
1887
1888
1889         return ret;
1890 }
1891
1892 static int rtw_wx_get_enc(struct net_device *dev,
1893                             struct iw_request_info *info,
1894                             union iwreq_data *wrqu, char *keybuf)
1895 {
1896         uint key, ret = 0;
1897         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1898         struct iw_point *erq = &(wrqu->encoding);
1899         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1900
1901
1902         if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1903                 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1904                         erq->length = 0;
1905                         erq->flags |= IW_ENCODE_DISABLED;
1906                         return 0;
1907                 }
1908         }
1909
1910         key = erq->flags & IW_ENCODE_INDEX;
1911
1912         if (key) {
1913                 if (key > WEP_KEYS)
1914                         return -EINVAL;
1915                 key--;
1916         } else {
1917                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1918         }
1919
1920         erq->flags = key + 1;
1921
1922         switch (padapter->securitypriv.ndisencryptstatus) {
1923         case Ndis802_11EncryptionNotSupported:
1924         case Ndis802_11EncryptionDisabled:
1925                 erq->length = 0;
1926                 erq->flags |= IW_ENCODE_DISABLED;
1927                 break;
1928         case Ndis802_11Encryption1Enabled:
1929                 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1930                 if (erq->length) {
1931                         memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1932
1933                         erq->flags |= IW_ENCODE_ENABLED;
1934
1935                         if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1936                                 erq->flags |= IW_ENCODE_OPEN;
1937                         else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1938                                 erq->flags |= IW_ENCODE_RESTRICTED;
1939                 } else {
1940                         erq->length = 0;
1941                         erq->flags |= IW_ENCODE_DISABLED;
1942                 }
1943                 break;
1944         case Ndis802_11Encryption2Enabled:
1945         case Ndis802_11Encryption3Enabled:
1946                 erq->length = 16;
1947                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1948                 break;
1949         default:
1950                 erq->length = 0;
1951                 erq->flags |= IW_ENCODE_DISABLED;
1952                 break;
1953         }
1954
1955         return ret;
1956 }
1957
1958 static int rtw_wx_get_power(struct net_device *dev,
1959                              struct iw_request_info *info,
1960                              union iwreq_data *wrqu, char *extra)
1961 {
1962         wrqu->power.value = 0;
1963         wrqu->power.fixed = 0;  /* no auto select */
1964         wrqu->power.disabled = 1;
1965
1966         return 0;
1967 }
1968
1969 static int rtw_wx_set_gen_ie(struct net_device *dev,
1970                              struct iw_request_info *info,
1971                              union iwreq_data *wrqu, char *extra)
1972 {
1973         int ret;
1974         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1975
1976         ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1977         return ret;
1978 }
1979
1980 static int rtw_wx_set_auth(struct net_device *dev,
1981                              struct iw_request_info *info,
1982                              union iwreq_data *wrqu, char *extra)
1983 {
1984         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1985         struct iw_param *param = (struct iw_param *)&(wrqu->param);
1986         int ret = 0;
1987
1988         switch (param->flags & IW_AUTH_INDEX) {
1989         case IW_AUTH_WPA_VERSION:
1990                 break;
1991         case IW_AUTH_CIPHER_PAIRWISE:
1992
1993                 break;
1994         case IW_AUTH_CIPHER_GROUP:
1995
1996                 break;
1997         case IW_AUTH_KEY_MGMT:
1998                 /*
1999                  *  ??? does not use these parameters
2000                  */
2001                 break;
2002         case IW_AUTH_TKIP_COUNTERMEASURES:
2003                 if (param->value) {
2004                         /*  wpa_supplicant is enabling the tkip countermeasure. */
2005                         padapter->securitypriv.btkip_countermeasure = true;
2006                 } else {
2007                         /*  wpa_supplicant is disabling the tkip countermeasure. */
2008                         padapter->securitypriv.btkip_countermeasure = false;
2009                 }
2010                 break;
2011         case IW_AUTH_DROP_UNENCRYPTED:
2012                 /* HACK:
2013                  *
2014                  * wpa_supplicant calls set_wpa_enabled when the driver
2015                  * is loaded and unloaded, regardless of if WPA is being
2016                  * used.  No other calls are made which can be used to
2017                  * determine if encryption will be used or not prior to
2018                  * association being expected.  If encryption is not being
2019                  * used, drop_unencrypted is set to false, else true -- we
2020                  * can use this to determine if the CAP_PRIVACY_ON bit should
2021                  * be set.
2022                  */
2023
2024                 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
2025                         break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
2026                                         /*  then it needn't reset it; */
2027
2028                 if (param->value) {
2029                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
2030                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2031                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
2032                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
2033                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
2034                 }
2035
2036                 break;
2037         case IW_AUTH_80211_AUTH_ALG:
2038                 /*
2039                  *  It's the starting point of a link layer connection using wpa_supplicant
2040                 */
2041                 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2042                         LeaveAllPowerSaveMode(padapter);
2043                         rtw_disassoc_cmd(padapter, 500, false);
2044                         DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
2045                         rtw_indicate_disconnect(padapter);
2046                         rtw_free_assoc_resources(padapter, 1);
2047                 }
2048                 ret = wpa_set_auth_algs(dev, (u32)param->value);
2049                 break;
2050         case IW_AUTH_WPA_ENABLED:
2051                 break;
2052         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2053                 break;
2054         case IW_AUTH_PRIVACY_INVOKED:
2055                 break;
2056         default:
2057                 return -EOPNOTSUPP;
2058         }
2059
2060         return ret;
2061 }
2062
2063 static int rtw_wx_set_enc_ext(struct net_device *dev,
2064                              struct iw_request_info *info,
2065                              union iwreq_data *wrqu, char *extra)
2066 {
2067         char *alg_name;
2068         u32 param_len;
2069         struct ieee_param *param = NULL;
2070         struct iw_point *pencoding = &wrqu->encoding;
2071         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
2072         int ret = 0;
2073
2074         param_len = sizeof(struct ieee_param) + pext->key_len;
2075         param = (struct ieee_param *)rtw_malloc(param_len);
2076         if (param == NULL)
2077                 return -1;
2078
2079         _rtw_memset(param, 0, param_len);
2080
2081         param->cmd = IEEE_CMD_SET_ENCRYPTION;
2082         _rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
2083
2084         switch (pext->alg) {
2085         case IW_ENCODE_ALG_NONE:
2086                 /* todo: remove key */
2087                 /* remove = 1; */
2088                 alg_name = "none";
2089                 break;
2090         case IW_ENCODE_ALG_WEP:
2091                 alg_name = "WEP";
2092                 break;
2093         case IW_ENCODE_ALG_TKIP:
2094                 alg_name = "TKIP";
2095                 break;
2096         case IW_ENCODE_ALG_CCMP:
2097                 alg_name = "CCMP";
2098                 break;
2099         default:
2100                 return -1;
2101         }
2102
2103         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
2104
2105         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2106                 param->u.crypt.set_tx = 1;
2107
2108         /* cliW: WEP does not have group key
2109          * just not checking GROUP key setting
2110          */
2111         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
2112             (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
2113                 param->u.crypt.set_tx = 0;
2114
2115         param->u.crypt.idx = (pencoding->flags&0x00FF) - 1;
2116
2117         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
2118                 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
2119
2120         if (pext->key_len) {
2121                 param->u.crypt.key_len = pext->key_len;
2122                 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
2123         }
2124
2125         ret =  wpa_set_encryption(dev, param, param_len);
2126
2127         kfree(param);
2128         return ret;
2129 }
2130
2131 static int rtw_wx_get_nick(struct net_device *dev,
2132                            struct iw_request_info *info,
2133                            union iwreq_data *wrqu, char *extra)
2134 {
2135         if (extra) {
2136                 wrqu->data.length = 14;
2137                 wrqu->data.flags = 1;
2138                 memcpy(extra, "<WIFI@REALTEK>", 14);
2139         }
2140
2141         /* dump debug info here */
2142         return 0;
2143 }
2144
2145 static int rtw_wx_read32(struct net_device *dev,
2146                             struct iw_request_info *info,
2147                             union iwreq_data *wrqu, char *extra)
2148 {
2149         struct adapter *padapter;
2150         struct iw_point *p;
2151         u16 len;
2152         u32 addr;
2153         u32 data32;
2154         u32 bytes;
2155         u8 *ptmp;
2156         int rv;
2157
2158         padapter = (struct adapter *)rtw_netdev_priv(dev);
2159         p = &wrqu->data;
2160         len = p->length;
2161         ptmp = (u8 *)rtw_malloc(len);
2162         if (NULL == ptmp)
2163                 return -ENOMEM;
2164
2165         if (copy_from_user(ptmp, p->pointer, len)) {
2166                 kfree(ptmp);
2167                 return -EFAULT;
2168         }
2169
2170         bytes = 0;
2171         addr = 0;
2172         rv = sscanf(ptmp, "%d,%x", &bytes, &addr);
2173         if (rv != 2) {
2174                 kfree(ptmp);
2175                 return -EINVAL;
2176         }
2177
2178         switch (bytes) {
2179         case 1:
2180                 data32 = rtw_read8(padapter, addr);
2181                 sprintf(extra, "0x%02X", data32);
2182                 break;
2183         case 2:
2184                 data32 = rtw_read16(padapter, addr);
2185                 sprintf(extra, "0x%04X", data32);
2186                 break;
2187         case 4:
2188                 data32 = rtw_read32(padapter, addr);
2189                 sprintf(extra, "0x%08X", data32);
2190                 break;
2191         default:
2192                 DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
2193                 return -EINVAL;
2194         }
2195         DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
2196
2197         kfree(ptmp);
2198         return 0;
2199 }
2200
2201 static int rtw_wx_write32(struct net_device *dev,
2202                             struct iw_request_info *info,
2203                             union iwreq_data *wrqu, char *extra)
2204 {
2205         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2206         int rv;
2207
2208         u32 addr;
2209         u32 data32;
2210         u32 bytes;
2211
2212         bytes = 0;
2213         addr = 0;
2214         data32 = 0;
2215         rv = sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
2216         if (rv != 3)
2217                 return -EINVAL;
2218
2219         switch (bytes) {
2220         case 1:
2221                 rtw_write8(padapter, addr, (u8)data32);
2222                 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
2223                 break;
2224         case 2:
2225                 rtw_write16(padapter, addr, (u16)data32);
2226                 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
2227                 break;
2228         case 4:
2229                 rtw_write32(padapter, addr, data32);
2230                 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
2231                 break;
2232         default:
2233                 DBG_88E(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
2234                 return -EINVAL;
2235         }
2236
2237         return 0;
2238 }
2239
2240 static int rtw_wx_read_rf(struct net_device *dev,
2241                             struct iw_request_info *info,
2242                             union iwreq_data *wrqu, char *extra)
2243 {
2244         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2245         u32 path, addr, data32;
2246
2247         path = *(u32 *)extra;
2248         addr = *((u32 *)extra + 1);
2249         data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
2250         /*
2251          * IMPORTANT!!
2252          * Only when wireless private ioctl is at odd order,
2253          * "extra" would be copied to user space.
2254          */
2255         sprintf(extra, "0x%05x", data32);
2256
2257         return 0;
2258 }
2259
2260 static int rtw_wx_write_rf(struct net_device *dev,
2261                             struct iw_request_info *info,
2262                             union iwreq_data *wrqu, char *extra)
2263 {
2264         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2265         u32 path, addr, data32;
2266
2267         path = *(u32 *)extra;
2268         addr = *((u32 *)extra + 1);
2269         data32 = *((u32 *)extra + 2);
2270         rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
2271
2272         return 0;
2273 }
2274
2275 static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
2276                  union iwreq_data *wrqu, char *b)
2277 {
2278         return -1;
2279 }
2280
2281 static int dummy(struct net_device *dev, struct iw_request_info *a,
2282                  union iwreq_data *wrqu, char *b)
2283 {
2284         return -1;
2285 }
2286
2287 static int rtw_wx_set_channel_plan(struct net_device *dev,
2288                                struct iw_request_info *info,
2289                                union iwreq_data *wrqu, char *extra)
2290 {
2291         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2292         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2293         u8 channel_plan_req = (u8) (*((int *)wrqu));
2294
2295         if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1))
2296                 DBG_88E("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan);
2297         else
2298                 return -EPERM;
2299
2300         return 0;
2301 }
2302
2303 static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
2304                 struct iw_request_info *a,
2305                 union iwreq_data *wrqu, char *b)
2306 {
2307         return 0;
2308 }
2309
2310 static int rtw_wx_get_sensitivity(struct net_device *dev,
2311                                 struct iw_request_info *info,
2312                                 union iwreq_data *wrqu, char *buf)
2313 {
2314         return 0;
2315 }
2316
2317 static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
2318                                 struct iw_request_info *info,
2319                                 union iwreq_data *wrqu, char *extra)
2320 {
2321         return 0;
2322 }
2323
2324 /*
2325  *      For all data larger than 16 octets, we need to use a
2326  *      pointer to memory allocated in user space.
2327  */
2328 static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
2329                                                 union iwreq_data *wrqu, char *extra)
2330 {
2331         return 0;
2332 }
2333
2334 static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 len)
2335 {
2336         struct mp_rw_reg *RegRWStruct;
2337         struct rf_reg_param *prfreg;
2338         u8 path;
2339         u8 offset;
2340         u32 value;
2341
2342         DBG_88E("%s\n", __func__);
2343
2344         switch (id) {
2345         case GEN_MP_IOCTL_SUBCODE(MP_START):
2346                 DBG_88E("871x_driver is only for normal mode, can't enter mp mode\n");
2347                 break;
2348         case GEN_MP_IOCTL_SUBCODE(READ_REG):
2349                 RegRWStruct = (struct mp_rw_reg *)pdata;
2350                 switch (RegRWStruct->width) {
2351                 case 1:
2352                         RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
2353                         break;
2354                 case 2:
2355                         RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
2356                         break;
2357                 case 4:
2358                         RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
2359                         break;
2360                 default:
2361                         break;
2362                 }
2363
2364                 break;
2365         case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
2366                 RegRWStruct = (struct mp_rw_reg *)pdata;
2367                 switch (RegRWStruct->width) {
2368                 case 1:
2369                         rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
2370                         break;
2371                 case 2:
2372                         rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
2373                         break;
2374                 case 4:
2375                         rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
2376                         break;
2377                 default:
2378                         break;
2379                 }
2380
2381                 break;
2382         case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
2383
2384                 prfreg = (struct rf_reg_param *)pdata;
2385
2386                 path = (u8)prfreg->path;
2387                 offset = (u8)prfreg->offset;
2388
2389                 value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
2390
2391                 prfreg->value = value;
2392
2393                 break;
2394         case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
2395
2396                 prfreg = (struct rf_reg_param *)pdata;
2397
2398                 path = (u8)prfreg->path;
2399                 offset = (u8)prfreg->offset;
2400                 value = prfreg->value;
2401
2402                 rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
2403
2404                 break;
2405         case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
2406                 DBG_88E("==> trigger gpio 0\n");
2407                 rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL);
2408                 break;
2409         case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
2410                 *pdata = rtw_hal_sreset_get_wifi_status(padapter);
2411                 break;
2412         default:
2413                 break;
2414         }
2415 }
2416
2417 static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
2418                                                 union iwreq_data *wrqu, char *extra)
2419 {
2420         int ret = 0;
2421         u32 BytesRead, BytesWritten, BytesNeeded;
2422         struct oid_par_priv     oid_par;
2423         struct mp_ioctl_handler *phandler;
2424         struct mp_ioctl_param   *poidparam;
2425         uint status = 0;
2426         u16 len;
2427         u8 *pparmbuf = NULL, bset;
2428         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2429         struct iw_point *p = &wrqu->data;
2430
2431         if ((!p->length) || (!p->pointer)) {
2432                 ret = -EINVAL;
2433                 goto _rtw_mp_ioctl_hdl_exit;
2434         }
2435         pparmbuf = NULL;
2436         bset = (u8)(p->flags & 0xFFFF);
2437         len = p->length;
2438         pparmbuf = (u8 *)rtw_malloc(len);
2439         if (pparmbuf == NULL) {
2440                 ret = -ENOMEM;
2441                 goto _rtw_mp_ioctl_hdl_exit;
2442         }
2443
2444         if (copy_from_user(pparmbuf, p->pointer, len)) {
2445                 ret = -EFAULT;
2446                 goto _rtw_mp_ioctl_hdl_exit;
2447         }
2448
2449         poidparam = (struct mp_ioctl_param *)pparmbuf;
2450         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2451                  ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
2452                   poidparam->subcode, poidparam->len, len));
2453
2454         if (poidparam->subcode >= ARRAY_SIZE(mp_ioctl_hdl)) {
2455                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
2456                 ret = -EINVAL;
2457                 goto _rtw_mp_ioctl_hdl_exit;
2458         }
2459
2460         if (padapter->registrypriv.mp_mode == 1) {
2461                 phandler = mp_ioctl_hdl + poidparam->subcode;
2462
2463                 if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
2464                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
2465                                  ("no matching drvext param size %d vs %d\r\n",
2466                                   poidparam->len, phandler->paramsize));
2467                         ret = -EINVAL;
2468                         goto _rtw_mp_ioctl_hdl_exit;
2469                 }
2470
2471                 if (phandler->handler) {
2472                         oid_par.adapter_context = padapter;
2473                         oid_par.oid = phandler->oid;
2474                         oid_par.information_buf = poidparam->data;
2475                         oid_par.information_buf_len = poidparam->len;
2476                         oid_par.dbg = 0;
2477
2478                         BytesWritten = 0;
2479                         BytesNeeded = 0;
2480
2481                         if (bset) {
2482                                 oid_par.bytes_rw = &BytesRead;
2483                                 oid_par.bytes_needed = &BytesNeeded;
2484                                 oid_par.type_of_oid = SET_OID;
2485                         } else {
2486                                 oid_par.bytes_rw = &BytesWritten;
2487                                 oid_par.bytes_needed = &BytesNeeded;
2488                                 oid_par.type_of_oid = QUERY_OID;
2489                         }
2490
2491                         status = phandler->handler(&oid_par);
2492                 } else {
2493                         DBG_88E("rtw_mp_ioctl_hdl(): err!, subcode =%d, oid =%d, handler =%p\n",
2494                                 poidparam->subcode, phandler->oid, phandler->handler);
2495                         ret = -EFAULT;
2496                         goto _rtw_mp_ioctl_hdl_exit;
2497                 }
2498         } else {
2499                 rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
2500         }
2501
2502         if (bset == 0x00) {/* query info */
2503                 if (copy_to_user(p->pointer, pparmbuf, len))
2504                         ret = -EFAULT;
2505         }
2506
2507         if (status) {
2508                 ret = -EFAULT;
2509                 goto _rtw_mp_ioctl_hdl_exit;
2510         }
2511
2512 _rtw_mp_ioctl_hdl_exit:
2513
2514         kfree(pparmbuf);
2515         return ret;
2516 }
2517
2518 static int rtw_get_ap_info(struct net_device *dev,
2519                                struct iw_request_info *info,
2520                                union iwreq_data *wrqu, char *extra)
2521 {
2522         int ret = 0;
2523         u32 cnt = 0, wpa_ielen;
2524         struct list_head *plist, *phead;
2525         unsigned char *pbuf;
2526         u8 bssid[ETH_ALEN];
2527         char data[32];
2528         struct wlan_network *pnetwork = NULL;
2529         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2530         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2531         struct __queue *queue = &(pmlmepriv->scanned_queue);
2532         struct iw_point *pdata = &wrqu->data;
2533
2534         DBG_88E("+rtw_get_aplist_info\n");
2535
2536         if ((padapter->bDriverStopped) || (pdata == NULL)) {
2537                 ret = -EINVAL;
2538                 goto exit;
2539         }
2540
2541         while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) {
2542                 msleep(30);
2543                 cnt++;
2544                 if (cnt > 100)
2545                         break;
2546         }
2547         pdata->flags = 0;
2548         if (pdata->length >= 32) {
2549                 if (copy_from_user(data, pdata->pointer, 32)) {
2550                         ret = -EINVAL;
2551                         goto exit;
2552                 }
2553         } else {
2554                 ret = -EINVAL;
2555                 goto exit;
2556         }
2557
2558         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2559
2560         phead = get_list_head(queue);
2561         plist = phead->next;
2562
2563         while (1) {
2564                 if (rtw_end_of_queue_search(phead, plist) == true)
2565                         break;
2566
2567                 pnetwork = container_of(plist, struct wlan_network, list);
2568
2569                 if (hwaddr_aton_i(data, bssid)) {
2570                         DBG_88E("Invalid BSSID '%s'.\n", (u8 *)data);
2571                         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2572                         return -EINVAL;
2573                 }
2574
2575                 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2576                         /* BSSID match, then check if supporting wpa/wpa2 */
2577                         DBG_88E("BSSID:%pM\n", (bssid));
2578
2579                         pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2580                         if (pbuf && (wpa_ielen > 0)) {
2581                                 pdata->flags = 1;
2582                                 break;
2583                         }
2584
2585                         pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2586                         if (pbuf && (wpa_ielen > 0)) {
2587                                 pdata->flags = 2;
2588                                 break;
2589                         }
2590                 }
2591
2592                 plist = plist->next;
2593         }
2594
2595         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2596
2597         if (pdata->length >= 34) {
2598                 if (copy_to_user(pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
2599                         ret = -EINVAL;
2600                         goto exit;
2601                 }
2602         }
2603
2604 exit:
2605
2606         return ret;
2607 }
2608
2609 static int rtw_set_pid(struct net_device *dev,
2610                                struct iw_request_info *info,
2611                                union iwreq_data *wrqu, char *extra)
2612 {
2613         int ret = 0;
2614         struct adapter *padapter = rtw_netdev_priv(dev);
2615         int *pdata = (int *)wrqu;
2616         int selector;
2617
2618         if ((padapter->bDriverStopped) || (pdata == NULL)) {
2619                 ret = -EINVAL;
2620                 goto exit;
2621         }
2622
2623         selector = *pdata;
2624         if (selector < 3 && selector >= 0) {
2625                 padapter->pid[selector] = *(pdata+1);
2626                 ui_pid[selector] = *(pdata+1);
2627                 DBG_88E("%s set pid[%d] =%d\n", __func__, selector, padapter->pid[selector]);
2628         } else {
2629                 DBG_88E("%s selector %d error\n", __func__, selector);
2630         }
2631 exit:
2632         return ret;
2633 }
2634
2635 static int rtw_wps_start(struct net_device *dev,
2636                          struct iw_request_info *info,
2637                          union iwreq_data *wrqu, char *extra)
2638 {
2639         int ret = 0;
2640         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2641         struct iw_point *pdata = &wrqu->data;
2642         u32   u32wps_start = 0;
2643
2644         if ((padapter->bDriverStopped) || (pdata == NULL)) {
2645                 ret = -EINVAL;
2646                 goto exit;
2647         }
2648
2649         ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
2650         if (ret) {
2651                 ret = -EINVAL;
2652                 goto exit;
2653         }
2654
2655         if (u32wps_start == 0)
2656                 u32wps_start = *extra;
2657
2658         DBG_88E("[%s] wps_start = %d\n", __func__, u32wps_start);
2659
2660         if (u32wps_start == 1) /*  WPS Start */
2661                 rtw_led_control(padapter, LED_CTL_START_WPS);
2662         else if (u32wps_start == 2) /*  WPS Stop because of wps success */
2663                 rtw_led_control(padapter, LED_CTL_STOP_WPS);
2664         else if (u32wps_start == 3) /*  WPS Stop because of wps fail */
2665                 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
2666
2667 exit:
2668         return ret;
2669 }
2670
2671 #ifdef CONFIG_88EU_P2P
2672 static int rtw_wext_p2p_enable(struct net_device *dev,
2673                                struct iw_request_info *info,
2674                                union iwreq_data *wrqu, char *extra)
2675 {
2676         int ret = 0;
2677         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2678         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2679         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2680         enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
2681
2682         if (*extra == '0')
2683                 init_role = P2P_ROLE_DISABLE;
2684         else if (*extra == '1')
2685                 init_role = P2P_ROLE_DEVICE;
2686         else if (*extra == '2')
2687                 init_role = P2P_ROLE_CLIENT;
2688         else if (*extra == '3')
2689                 init_role = P2P_ROLE_GO;
2690
2691         if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
2692                 ret = -EFAULT;
2693                 goto exit;
2694         }
2695
2696         /* set channel/bandwidth */
2697         if (init_role != P2P_ROLE_DISABLE) {
2698                 u8 channel, ch_offset;
2699                 u16 bwmode;
2700
2701                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
2702                         /*      Stay at the listen state and wait for discovery. */
2703                         channel = pwdinfo->listen_channel;
2704                         pwdinfo->operating_channel = pwdinfo->listen_channel;
2705                         ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2706                         bwmode = HT_CHANNEL_WIDTH_20;
2707                 } else {
2708                         pwdinfo->operating_channel = pmlmeext->cur_channel;
2709
2710                         channel = pwdinfo->operating_channel;
2711                         ch_offset = pmlmeext->cur_ch_offset;
2712                         bwmode = pmlmeext->cur_bwmode;
2713                 }
2714
2715                 set_channel_bwmode(padapter, channel, ch_offset, bwmode);
2716         }
2717
2718 exit:
2719         return ret;
2720 }
2721
2722 static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
2723                                struct iw_request_info *info,
2724                                union iwreq_data *wrqu, char *extra)
2725 {
2726         int ret = 0;
2727         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2728         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2729
2730         DBG_88E("[%s] ssid = %s, len = %zu\n", __func__, extra, strlen(extra));
2731         memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
2732         pwdinfo->nego_ssidlen = strlen(extra);
2733
2734         return ret;
2735 }
2736
2737 static int rtw_p2p_set_intent(struct net_device *dev,
2738                               struct iw_request_info *info,
2739                               union iwreq_data *wrqu, char *extra)
2740 {
2741         int ret = 0;
2742         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2743         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2744         u8 intent = pwdinfo->intent;
2745
2746         switch (wrqu->data.length) {
2747         case 1:
2748                 intent = extra[0] - '0';
2749                 break;
2750         case 2:
2751                 intent = str_2char2num(extra[0], extra[1]);
2752                 break;
2753         }
2754         if (intent <= 15)
2755                 pwdinfo->intent = intent;
2756         else
2757                 ret = -1;
2758         DBG_88E("[%s] intent = %d\n", __func__, intent);
2759         return ret;
2760 }
2761
2762 static int rtw_p2p_set_listen_ch(struct net_device *dev,
2763                                struct iw_request_info *info,
2764                                union iwreq_data *wrqu, char *extra)
2765 {
2766         int ret = 0;
2767         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2768         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2769         u8 listen_ch = pwdinfo->listen_channel; /*      Listen channel number */
2770
2771         switch (wrqu->data.length) {
2772         case 1:
2773                 listen_ch = extra[0] - '0';
2774                 break;
2775         case 2:
2776                 listen_ch = str_2char2num(extra[0], extra[1]);
2777                 break;
2778         }
2779
2780         if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
2781                 pwdinfo->listen_channel = listen_ch;
2782                 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2783         } else {
2784                 ret = -1;
2785         }
2786
2787         DBG_88E("[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel);
2788
2789         return ret;
2790 }
2791
2792 static int rtw_p2p_set_op_ch(struct net_device *dev,
2793                                struct iw_request_info *info,
2794                                union iwreq_data *wrqu, char *extra)
2795 {
2796 /*      Commented by Albert 20110524 */
2797 /*      This function is used to set the operating channel if the driver will become the group owner */
2798
2799         int ret = 0;
2800         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2801         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2802         u8 op_ch = pwdinfo->operating_channel;  /*      Operating channel number */
2803
2804         switch (wrqu->data.length) {
2805         case 1:
2806                 op_ch = extra[0] - '0';
2807                 break;
2808         case 2:
2809                 op_ch = str_2char2num(extra[0], extra[1]);
2810                 break;
2811         }
2812
2813         if (op_ch > 0)
2814                 pwdinfo->operating_channel = op_ch;
2815         else
2816                 ret = -1;
2817
2818         DBG_88E("[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel);
2819
2820         return ret;
2821 }
2822
2823 static int rtw_p2p_profilefound(struct net_device *dev,
2824                                struct iw_request_info *info,
2825                                union iwreq_data *wrqu, char *extra)
2826 {
2827         int ret = 0;
2828         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2829         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2830
2831         /*      Comment by Albert 2010/10/13 */
2832         /*      Input data format: */
2833         /*      Ex:  0 */
2834         /*      Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
2835         /*      0 => Reflush the profile record list. */
2836         /*      1 => Add the profile list */
2837         /*      XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */
2838         /*      YY => SSID Length */
2839         /*      SSID => SSID for persistence group */
2840
2841         DBG_88E("[%s] In value = %s, len = %d\n", __func__, extra, wrqu->data.length - 1);
2842
2843         /*      The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
2844                 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
2845                         if (extra[0] == '0') {
2846                         /*      Remove all the profile information of wifidirect_info structure. */
2847                         _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
2848                         pwdinfo->profileindex = 0;
2849                 } else {
2850                         if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) {
2851                                 ret = -1;
2852                         } else {
2853                                 int jj, kk;
2854
2855                                 /*      Add this profile information into pwdinfo->profileinfo */
2856                                 /*      Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
2857                                 for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
2858                                         pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2859
2860                                 pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0');
2861                                 memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen);
2862                                 pwdinfo->profileindex++;
2863                         }
2864                 }
2865         }
2866
2867         return ret;
2868 }
2869
2870 static int rtw_p2p_setDN(struct net_device *dev,
2871                                struct iw_request_info *info,
2872                                union iwreq_data *wrqu, char *extra)
2873 {
2874         int ret = 0;
2875         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2876         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2877
2878         DBG_88E("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
2879         _rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
2880         memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
2881         pwdinfo->device_name_len = wrqu->data.length - 1;
2882
2883         return ret;
2884 }
2885
2886 static int rtw_p2p_get_status(struct net_device *dev,
2887                                struct iw_request_info *info,
2888                                union iwreq_data *wrqu, char *extra)
2889 {
2890         int ret = 0;
2891         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2892         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2893
2894         if (padapter->bShowGetP2PState)
2895                 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2896                         pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
2897                         pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
2898
2899         /*      Commented by Albert 2010/10/12 */
2900         /*      Because of the output size limitation, I had removed the "Role" information. */
2901         /*      About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
2902         sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo));
2903         wrqu->data.length = strlen(extra);
2904
2905         return ret;
2906 }
2907
2908 /*      Commented by Albert 20110520 */
2909 /*      This function will return the config method description */
2910 /*      This config method description will show us which config method the remote P2P device is intended to use */
2911 /*      by sending the provisioning discovery request frame. */
2912
2913 static int rtw_p2p_get_req_cm(struct net_device *dev,
2914                                struct iw_request_info *info,
2915                                union iwreq_data *wrqu, char *extra)
2916 {
2917         int ret = 0;
2918         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2919         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2920
2921         sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
2922         wrqu->data.length = strlen(extra);
2923         return ret;
2924 }
2925
2926 static int rtw_p2p_get_role(struct net_device *dev,
2927                                struct iw_request_info *info,
2928                                union iwreq_data *wrqu, char *extra)
2929 {
2930         int ret = 0;
2931         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2932         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2933
2934         DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2935                         pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
2936                         pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
2937
2938         sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo));
2939         wrqu->data.length = strlen(extra);
2940         return ret;
2941 }
2942
2943 static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
2944                                struct iw_request_info *info,
2945                                union iwreq_data *wrqu, char *extra)
2946 {
2947         int ret = 0;
2948         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2949         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2950
2951         DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
2952                 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2953                 pwdinfo->p2p_peer_interface_addr);
2954         sprintf(extra, "\nMAC %pM",
2955                 pwdinfo->p2p_peer_interface_addr);
2956         wrqu->data.length = strlen(extra);
2957         return ret;
2958 }
2959
2960 static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
2961                                struct iw_request_info *info,
2962                                union iwreq_data *wrqu, char *extra)
2963
2964 {
2965         int ret = 0;
2966         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2967         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2968
2969         DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
2970                 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2971                 pwdinfo->rx_prov_disc_info.peerDevAddr);
2972         sprintf(extra, "\n%pM",
2973                 pwdinfo->rx_prov_disc_info.peerDevAddr);
2974         wrqu->data.length = strlen(extra);
2975         return ret;
2976 }
2977
2978 static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
2979                                struct iw_request_info *info,
2980                                union iwreq_data *wrqu, char *extra)
2981
2982 {
2983         int ret = 0;
2984         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2985         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2986
2987         DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n",
2988                 __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2989                 pwdinfo->p2p_peer_device_addr);
2990         sprintf(extra, "\nMAC %pM",
2991                 pwdinfo->p2p_peer_device_addr);
2992         wrqu->data.length = strlen(extra);
2993         return ret;
2994 }
2995
2996 static int rtw_p2p_get_groupid(struct net_device *dev,
2997                                struct iw_request_info *info,
2998                                union iwreq_data *wrqu, char *extra)
2999
3000 {
3001         int ret = 0;
3002         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3003         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3004
3005         sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
3006                 pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
3007                 pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
3008                 pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
3009                 pwdinfo->groupid_info.ssid);
3010         wrqu->data.length = strlen(extra);
3011         return ret;
3012 }
3013
3014 static int rtw_p2p_get_op_ch(struct net_device *dev,
3015                                struct iw_request_info *info,
3016                                union iwreq_data *wrqu, char *extra)
3017
3018 {
3019         int ret = 0;
3020         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3021         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3022
3023         DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
3024
3025         sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel);
3026         wrqu->data.length = strlen(extra);
3027         return ret;
3028 }
3029
3030 static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
3031                                struct iw_request_info *info,
3032                                union iwreq_data *wrqu, char *extra)
3033 {
3034         int ret = 0;
3035         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3036         u8 peerMAC[ETH_ALEN] = {0x00};
3037         int jj, kk;
3038         u8 peerMACStr[17] = {0x00};
3039         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
3040         struct list_head *plist, *phead;
3041         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3042         struct  wlan_network    *pnetwork = NULL;
3043         u8 blnMatch = 0;
3044         u16     attr_content = 0;
3045         uint attr_contentlen = 0;
3046         /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
3047         u8 attr_content_str[6 + 17] = {0x00};
3048
3049         /*      Commented by Albert 20110727 */
3050         /*      The input data is the MAC address which the application wants to know its WPS config method. */
3051         /*      After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
3052         /*      Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
3053
3054         DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3055         if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17))
3056                 return -EFAULT;
3057
3058         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3059                 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3060
3061         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3062
3063         phead = get_list_head(queue);
3064         plist = phead->next;
3065
3066         while (1) {
3067                 if (rtw_end_of_queue_search(phead, plist) == true)
3068                         break;
3069
3070                 pnetwork = container_of(plist, struct wlan_network, list);
3071                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3072                         u8 *wpsie;
3073                         uint wpsie_len = 0;
3074                         __be16 be_tmp;
3075
3076                         /*  The mac address is matched. */
3077                         wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
3078                         if (wpsie) {
3079                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen);
3080                                 if (attr_contentlen) {
3081                                         attr_content = be16_to_cpu(be_tmp);
3082                                         sprintf(attr_content_str, "\n\nM =%.4d", attr_content);
3083                                         blnMatch = 1;
3084                                 }
3085                         }
3086                         break;
3087                 }
3088                 plist = plist->next;
3089         }
3090
3091         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3092
3093         if (!blnMatch)
3094                 sprintf(attr_content_str, "\n\nM = 0000");
3095
3096         if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
3097                 return -EFAULT;
3098         return ret;
3099 }
3100
3101 static int rtw_p2p_get_go_device_address(struct net_device *dev,
3102                                struct iw_request_info *info,
3103                                union iwreq_data *wrqu, char *extra)
3104 {
3105         int ret = 0;
3106         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3107         u8 peerMAC[ETH_ALEN] = {0x00};
3108         int jj, kk;
3109         u8 peerMACStr[17] = {0x00};
3110         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
3111         struct list_head *plist, *phead;
3112         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3113         struct  wlan_network    *pnetwork = NULL;
3114         u8 blnMatch = 0;
3115         u8 *p2pie;
3116         uint p2pielen = 0, attr_contentlen = 0;
3117         u8 attr_content[100] = {0x00};
3118         u8 go_devadd_str[17 + 12] = {};
3119
3120         /*      Commented by Albert 20121209 */
3121         /*      The input data is the GO's interface address which the application wants to know its device address. */
3122         /*      Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */
3123
3124         DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3125         if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17))
3126                 return -EFAULT;
3127
3128         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3129                 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3130
3131         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3132
3133         phead = get_list_head(queue);
3134         plist = phead->next;
3135
3136         while (1) {
3137                 if (rtw_end_of_queue_search(phead, plist) == true)
3138                         break;
3139
3140                 pnetwork = container_of(plist, struct wlan_network, list);
3141                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3142                         /*      Commented by Albert 2011/05/18 */
3143                         /*      Match the device address located in the P2P IE */
3144                         /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
3145
3146                         p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3147                         if (p2pie) {
3148                                 while (p2pie) {
3149                                         /*      The P2P Device ID attribute is included in the Beacon frame. */
3150                                         /*      The P2P Device Info attribute is included in the probe response frame. */
3151
3152                                         _rtw_memset(attr_content, 0x00, 100);
3153                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3154                                                 /*      Handle the P2P Device ID attribute of Beacon first */
3155                                                 blnMatch = 1;
3156                                                 break;
3157                                         } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3158                                                 /*      Handle the P2P Device Info attribute of probe response */
3159                                                 blnMatch = 1;
3160                                                 break;
3161                                         }
3162
3163                                         /* Get the next P2P IE */
3164                                         p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3165                                 }
3166                         }
3167              }
3168
3169                 plist = plist->next;
3170         }
3171
3172         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3173
3174         if (!blnMatch)
3175                 snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL");
3176         else
3177                 snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
3178                         attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
3179
3180         if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
3181                 return -EFAULT;
3182         return ret;
3183 }
3184
3185 static int rtw_p2p_get_device_type(struct net_device *dev,
3186                                struct iw_request_info *info,
3187                                union iwreq_data *wrqu, char *extra)
3188 {
3189         int ret = 0;
3190         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3191         u8 peerMAC[ETH_ALEN] = {0x00};
3192         int jj, kk;
3193         u8 peerMACStr[17] = {0x00};
3194         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
3195         struct list_head *plist, *phead;
3196         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3197         struct  wlan_network    *pnetwork = NULL;
3198         u8 blnMatch = 0;
3199         u8 dev_type[8] = {0x00};
3200         uint dev_type_len = 0;
3201         u8 dev_type_str[17 + 9] = {0x00};       /*  +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */
3202
3203         /*      Commented by Albert 20121209 */
3204         /*      The input data is the MAC address which the application wants to know its device type. */
3205         /*      Such user interface could know the device type. */
3206         /*      Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */
3207
3208         DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3209         if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17))
3210                 return -EFAULT;
3211
3212         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3213                 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3214
3215         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3216
3217         phead = get_list_head(queue);
3218         plist = phead->next;
3219
3220         while (1) {
3221                 if (rtw_end_of_queue_search(phead, plist) == true)
3222                         break;
3223
3224                 pnetwork = container_of(plist, struct wlan_network, list);
3225                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3226                         u8 *wpsie;
3227                         uint wpsie_len = 0;
3228
3229                 /*      The mac address is matched. */
3230
3231                         wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12],
3232                                                pnetwork->network.IELength - 12,
3233                                                NULL, &wpsie_len);
3234                         if (wpsie) {
3235                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
3236                                 if (dev_type_len) {
3237                                         u16     type = 0;
3238                                         __be16 be_tmp;
3239
3240                                         memcpy(&be_tmp, dev_type, 2);
3241                                         type = be16_to_cpu(be_tmp);
3242                                         sprintf(dev_type_str, "\n\nN =%.2d", type);
3243                                         blnMatch = 1;
3244                                 }
3245                         }
3246                         break;
3247              }
3248
3249                 plist = plist->next;
3250         }
3251
3252         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3253
3254         if (!blnMatch)
3255                 sprintf(dev_type_str, "\n\nN = 00");
3256
3257         if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
3258                 return -EFAULT;
3259         }
3260
3261         return ret;
3262 }
3263
3264 static int rtw_p2p_get_device_name(struct net_device *dev,
3265                                struct iw_request_info *info,
3266                                union iwreq_data *wrqu, char *extra)
3267 {
3268         int ret = 0;
3269         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3270         u8 peerMAC[ETH_ALEN] = {0x00};
3271         int jj, kk;
3272         u8 peerMACStr[17] = {0x00};
3273         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
3274         struct list_head *plist, *phead;
3275         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3276         struct  wlan_network    *pnetwork = NULL;
3277         u8 blnMatch = 0;
3278         u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
3279         uint dev_len = 0;
3280         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 */
3281
3282         /*      Commented by Albert 20121225 */
3283         /*      The input data is the MAC address which the application wants to know its device name. */
3284         /*      Such user interface could show peer device's device name instead of ssid. */
3285         /*      Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */
3286
3287         DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3288         if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17))
3289                 return -EFAULT;
3290
3291         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3292                 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3293
3294         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3295
3296         phead = get_list_head(queue);
3297         plist = phead->next;
3298
3299         while (1) {
3300                 if (rtw_end_of_queue_search(phead, plist) == true)
3301                         break;
3302
3303                 pnetwork = container_of(plist, struct wlan_network, list);
3304                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3305                         u8 *wpsie;
3306                         uint wpsie_len = 0;
3307
3308                         /*      The mac address is matched. */
3309                         wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
3310                         if (wpsie) {
3311                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
3312                                 if (dev_len) {
3313                                         sprintf(dev_name_str, "\n\nN =%s", dev_name);
3314                                         blnMatch = 1;
3315                                 }
3316                         }
3317                         break;
3318                 }
3319
3320                 plist = plist->next;
3321         }
3322
3323         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3324
3325         if (!blnMatch)
3326                 sprintf(dev_name_str, "\n\nN = 0000");
3327
3328         if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
3329                 return -EFAULT;
3330         return ret;
3331 }
3332
3333 static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
3334                                struct iw_request_info *info,
3335                                union iwreq_data *wrqu, char *extra)
3336 {
3337         int ret = 0;
3338         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3339         u8 peerMAC[ETH_ALEN] = {0x00};
3340         int jj, kk;
3341         u8 peerMACStr[17] = {0x00};
3342         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
3343         struct list_head *plist, *phead;
3344         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3345         struct  wlan_network    *pnetwork = NULL;
3346         u8 blnMatch = 0;
3347         u8 *p2pie;
3348         uint p2pielen = 0, attr_contentlen = 0;
3349         u8 attr_content[2] = {0x00};
3350
3351         u8 inv_proc_str[17 + 8] = {0x00};
3352         /*  +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
3353
3354         /*      Commented by Ouden 20121226 */
3355         /*      The application wants to know P2P initiation procedure is supported or not. */
3356         /*      Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
3357
3358         DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3359         if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17))
3360                 return -EFAULT;
3361
3362         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3363                 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3364
3365         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3366
3367         phead = get_list_head(queue);
3368         plist = phead->next;
3369
3370         while (1) {
3371                 if (rtw_end_of_queue_search(phead, plist) == true)
3372                         break;
3373
3374                 pnetwork = container_of(plist, struct wlan_network, list);
3375                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3376                         /*      Commented by Albert 20121226 */
3377                         /*      Match the device address located in the P2P IE */
3378                         /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
3379
3380                         p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3381                         if (p2pie) {
3382                                 while (p2pie) {
3383                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
3384                                                 /*      Handle the P2P capability attribute */
3385                                                 blnMatch = 1;
3386                                                 break;
3387                                         }
3388
3389                                         /* Get the next P2P IE */
3390                                         p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3391                                 }
3392                         }
3393                 }
3394                 plist = plist->next;
3395         }
3396
3397         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3398
3399         if (!blnMatch) {
3400                 sprintf(inv_proc_str, "\nIP =-1");
3401         } else {
3402                 if (attr_content[0] & 0x20)
3403                         sprintf(inv_proc_str, "\nIP = 1");
3404                 else
3405                         sprintf(inv_proc_str, "\nIP = 0");
3406         }
3407         if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
3408                 return -EFAULT;
3409         return ret;
3410 }
3411
3412 static int rtw_p2p_connect(struct net_device *dev,
3413                                struct iw_request_info *info,
3414                                union iwreq_data *wrqu, char *extra)
3415 {
3416         int ret = 0;
3417         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3418         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3419         u8 peerMAC[ETH_ALEN] = {0x00};
3420         int jj, kk;
3421         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
3422         struct list_head *plist, *phead;
3423         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3424         struct  wlan_network    *pnetwork = NULL;
3425         uint uintPeerChannel = 0;
3426
3427         /*      Commented by Albert 20110304 */
3428         /*      The input data contains two informations. */
3429         /*      1. First information is the MAC address which wants to formate with */
3430         /*      2. Second information is the WPS PINCode or "pbc" string for push button method */
3431         /*      Format: 00:E0:4C:00:00:05 */
3432         /*      Format: 00:E0:4C:00:00:05 */
3433
3434         DBG_88E("[%s] data = %s\n", __func__, extra);
3435
3436         if (pwdinfo->p2p_state == P2P_STATE_NONE) {
3437                 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3438                 return ret;
3439         }
3440
3441         if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
3442                 return -1;
3443
3444         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3445                 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3446
3447         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3448
3449         phead = get_list_head(queue);
3450         plist = phead->next;
3451
3452         while (1) {
3453                 if (rtw_end_of_queue_search(phead, plist) == true)
3454                         break;
3455
3456                 pnetwork = container_of(plist, struct wlan_network, list);
3457                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3458                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3459                         break;
3460                 }
3461
3462                 plist = plist->next;
3463         }
3464
3465         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3466
3467         if (uintPeerChannel) {
3468                 _rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
3469                 _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3470
3471                 pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
3472                 memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
3473                 pwdinfo->nego_req_info.benable = true;
3474
3475                 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3476                 if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
3477                         /*      Restore to the listen state if the current p2p state is not nego OK */
3478                         rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3479                 }
3480
3481                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3482                 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
3483
3484                 DBG_88E("[%s] Start PreTx Procedure!\n", __func__);
3485                 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3486                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
3487         } else {
3488                 DBG_88E("[%s] Not Found in Scanning Queue~\n", __func__);
3489                 ret = -1;
3490         }
3491         return ret;
3492 }
3493
3494 static int rtw_p2p_invite_req(struct net_device *dev,
3495                               struct iw_request_info *info,
3496                               union iwreq_data *wrqu, char *extra)
3497 {
3498         int ret = 0;
3499         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3500         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3501         int jj, kk;
3502         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
3503         struct list_head *plist, *phead;
3504         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3505         struct  wlan_network    *pnetwork = NULL;
3506         uint uintPeerChannel = 0;
3507         u8 attr_content[50] = {0x00};
3508         u8 *p2pie;
3509         uint p2pielen = 0, attr_contentlen = 0;
3510         struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info;
3511
3512         /*      The input data contains two informations. */
3513         /*      1. First information is the P2P device address which you want to send to. */
3514         /*      2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
3515         /*      Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
3516         /*      Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
3517
3518         DBG_88E("[%s] data = %s\n", __func__, extra);
3519
3520         if (wrqu->data.length <=  37) {
3521                 DBG_88E("[%s] Wrong format!\n", __func__);
3522                 return ret;
3523         }
3524
3525         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3526                 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3527                 return ret;
3528         } else {
3529                 /*      Reset the content of struct tx_invite_req_info */
3530                 pinvite_req_info->benable = false;
3531                 _rtw_memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
3532                 _rtw_memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
3533                 pinvite_req_info->ssidlen = 0x00;
3534                 pinvite_req_info->operating_ch = pwdinfo->operating_channel;
3535                 _rtw_memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
3536                 pinvite_req_info->token = 3;
3537         }
3538
3539         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3540                 pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3541
3542         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3543
3544         phead = get_list_head(queue);
3545         plist = phead->next;
3546
3547         while (1) {
3548                 if (rtw_end_of_queue_search(phead, plist) == true)
3549                         break;
3550
3551                 pnetwork = container_of(plist, struct wlan_network, list);
3552
3553                 /*      Commented by Albert 2011/05/18 */
3554                 /*      Match the device address located in the P2P IE */
3555                 /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
3556
3557                 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3558                 if (p2pie) {
3559                         /*      The P2P Device ID attribute is included in the Beacon frame. */
3560                         /*      The P2P Device Info attribute is included in the probe response frame. */
3561
3562                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3563                                 /*      Handle the P2P Device ID attribute of Beacon first */
3564                                 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
3565                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3566                                         break;
3567                                 }
3568                         } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3569                                 /*      Handle the P2P Device Info attribute of probe response */
3570                                 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
3571                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3572                                         break;
3573                                 }
3574                         }
3575                 }
3576                 plist = plist->next;
3577         }
3578
3579         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3580
3581         if (uintPeerChannel) {
3582                 /*      Store the GO's bssid */
3583                 for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
3584                         pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3585
3586                 /*      Store the GO's ssid */
3587                 pinvite_req_info->ssidlen = wrqu->data.length - 36;
3588                 memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen);
3589                 pinvite_req_info->benable = true;
3590                 pinvite_req_info->peer_ch = uintPeerChannel;
3591
3592                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3593                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
3594
3595                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3596
3597                 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3598
3599                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
3600         } else {
3601                 DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
3602         }
3603         return ret;
3604 }
3605
3606 static int rtw_p2p_set_persistent(struct net_device *dev,
3607                                struct iw_request_info *info,
3608                                union iwreq_data *wrqu, char *extra)
3609 {
3610         int ret = 0;
3611         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3612         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3613
3614         /*      The input data is 0 or 1 */
3615         /*      0: disable persistent group functionality */
3616         /*      1: enable persistent group founctionality */
3617
3618         DBG_88E("[%s] data = %s\n", __func__, extra);
3619
3620         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3621                 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3622                 return ret;
3623         } else {
3624                 if (extra[0] == '0')    /*      Disable the persistent group function. */
3625                         pwdinfo->persistent_supported = false;
3626                 else if (extra[0] == '1')       /*      Enable the persistent group function. */
3627                         pwdinfo->persistent_supported = true;
3628                 else
3629                         pwdinfo->persistent_supported = false;
3630         }
3631         pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported);
3632         return ret;
3633 }
3634
3635 static int rtw_p2p_prov_disc(struct net_device *dev,
3636                                struct iw_request_info *info,
3637                                union iwreq_data *wrqu, char *extra)
3638 {
3639         int ret = 0;
3640         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3641         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3642         u8 peerMAC[ETH_ALEN] = {0x00};
3643         int jj, kk;
3644         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
3645         struct list_head *plist, *phead;
3646         struct __queue *queue   = &(pmlmepriv->scanned_queue);
3647         struct  wlan_network    *pnetwork = NULL;
3648         uint uintPeerChannel = 0;
3649         u8 attr_content[100] = {0x00};
3650         u8 *p2pie;
3651         uint p2pielen = 0, attr_contentlen = 0;
3652
3653         /*      The input data contains two informations. */
3654         /*      1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
3655         /*      2. Second information is the WPS configuration method which wants to discovery */
3656         /*      Format: 00:E0:4C:00:00:05_display */
3657         /*      Format: 00:E0:4C:00:00:05_keypad */
3658         /*      Format: 00:E0:4C:00:00:05_pbc */
3659         /*      Format: 00:E0:4C:00:00:05_label */
3660
3661         DBG_88E("[%s] data = %s\n", __func__, extra);
3662
3663         if (pwdinfo->p2p_state == P2P_STATE_NONE) {
3664                 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3665                 return ret;
3666         } else {
3667                 /*      Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
3668                 _rtw_memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
3669                 _rtw_memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
3670                 _rtw_memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid));
3671                 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
3672                 pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
3673                 pwdinfo->tx_prov_disc_info.benable = false;
3674         }
3675
3676         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3677                 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3678
3679         if (!memcmp(&extra[18], "display", 7)) {
3680                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
3681         } else if (!memcmp(&extra[18], "keypad", 7)) {
3682                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
3683         } else if (!memcmp(&extra[18], "pbc", 3)) {
3684                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
3685         } else if (!memcmp(&extra[18], "label", 5)) {
3686                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
3687         } else {
3688                 DBG_88E("[%s] Unknown WPS config methodn", __func__);
3689                 return ret;
3690         }
3691
3692         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3693
3694         phead = get_list_head(queue);
3695         plist = phead->next;
3696
3697         while (1) {
3698                 if (rtw_end_of_queue_search(phead, plist) == true)
3699                         break;
3700
3701                 if (uintPeerChannel != 0)
3702                         break;
3703
3704                 pnetwork = container_of(plist, struct wlan_network, list);
3705
3706                 /*      Commented by Albert 2011/05/18 */
3707                 /*      Match the device address located in the P2P IE */
3708                 /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
3709
3710                 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3711                 if (p2pie) {
3712                         while (p2pie) {
3713                                 /*      The P2P Device ID attribute is included in the Beacon frame. */
3714                                 /*      The P2P Device Info attribute is included in the probe response frame. */
3715
3716                                 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3717                                         /*      Handle the P2P Device ID attribute of Beacon first */
3718                                         if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
3719                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3720                                                 break;
3721                                         }
3722                                 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3723                                         /*      Handle the P2P Device Info attribute of probe response */
3724                                         if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
3725                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3726                                                 break;
3727                                         }
3728                                 }
3729
3730                                 /* Get the next P2P IE */
3731                                 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3732                         }
3733                 }
3734
3735                 plist = plist->next;
3736         }
3737
3738         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3739
3740         if (uintPeerChannel) {
3741                 DBG_88E("[%s] peer channel: %d!\n", __func__, uintPeerChannel);
3742                 memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
3743                 memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
3744                 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel;
3745                 pwdinfo->tx_prov_disc_info.benable = true;
3746                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3747                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
3748
3749                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
3750                         memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
3751                 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3752                         memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3753                         pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
3754                 }
3755
3756                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3757
3758                 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3759
3760                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
3761         } else {
3762                 DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
3763         }
3764         return ret;
3765 }
3766
3767 /*      This function is used to inform the driver the user had specified the pin code value or pbc */
3768 /*      to application. */
3769
3770 static int rtw_p2p_got_wpsinfo(struct net_device *dev,
3771                                struct iw_request_info *info,
3772                                union iwreq_data *wrqu, char *extra)
3773 {
3774         int ret = 0;
3775         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3776         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3777
3778         DBG_88E("[%s] data = %s\n", __func__, extra);
3779         /*      Added by Albert 20110328 */
3780         /*      if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
3781         /*      if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
3782         /*      if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
3783         /*      if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
3784
3785         if (*extra == '0')
3786                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3787         else if (*extra == '1')
3788                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
3789         else if (*extra == '2')
3790                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
3791         else if (*extra == '3')
3792                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
3793         else
3794                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3795         return ret;
3796 }
3797
3798 #endif /* CONFIG_88EU_P2P */
3799
3800 static int rtw_p2p_set(struct net_device *dev,
3801                                struct iw_request_info *info,
3802                                union iwreq_data *wrqu, char *extra)
3803 {
3804         int ret = 0;
3805
3806 #ifdef CONFIG_88EU_P2P
3807         DBG_88E("[%s] extra = %s\n", __func__, extra);
3808         if (!memcmp(extra, "enable =", 7)) {
3809                 rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
3810         } else if (!memcmp(extra, "setDN =", 6)) {
3811                 wrqu->data.length -= 6;
3812                 rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
3813         } else if (!memcmp(extra, "profilefound =", 13)) {
3814                 wrqu->data.length -= 13;
3815                 rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
3816         } else if (!memcmp(extra, "prov_disc =", 10)) {
3817                 wrqu->data.length -= 10;
3818                 rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
3819         } else if (!memcmp(extra, "nego =", 5)) {
3820                 wrqu->data.length -= 5;
3821                 rtw_p2p_connect(dev, info, wrqu, &extra[5]);
3822         } else if (!memcmp(extra, "intent =", 7)) {
3823                 /*      Commented by Albert 2011/03/23 */
3824                 /*      The wrqu->data.length will include the null character */
3825                 /*      So, we will decrease 7 + 1 */
3826                 wrqu->data.length -= 8;
3827                 rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
3828         } else if (!memcmp(extra, "ssid =", 5)) {
3829                 wrqu->data.length -= 5;
3830                 rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
3831         } else if (!memcmp(extra, "got_wpsinfo =", 12)) {
3832                 wrqu->data.length -= 12;
3833                 rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
3834         } else if (!memcmp(extra, "listen_ch =", 10)) {
3835                 /*      Commented by Albert 2011/05/24 */
3836                 /*      The wrqu->data.length will include the null character */
3837                 /*      So, we will decrease (10 + 1) */
3838                 wrqu->data.length -= 11;
3839                 rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
3840         } else if (!memcmp(extra, "op_ch =", 6)) {
3841                 /*      Commented by Albert 2011/05/24 */
3842                 /*      The wrqu->data.length will include the null character */
3843                 /*      So, we will decrease (6 + 1) */
3844                 wrqu->data.length -= 7;
3845                 rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
3846         } else if (!memcmp(extra, "invite =", 7)) {
3847                 wrqu->data.length -= 8;
3848                 rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
3849         } else if (!memcmp(extra, "persistent =", 11)) {
3850                 wrqu->data.length -= 11;
3851                 rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
3852         }
3853 #endif /* CONFIG_88EU_P2P */
3854
3855         return ret;
3856 }
3857
3858 static int rtw_p2p_get(struct net_device *dev,
3859                                struct iw_request_info *info,
3860                                union iwreq_data *wrqu, char *extra)
3861 {
3862         int ret = 0;
3863
3864 #ifdef CONFIG_88EU_P2P
3865         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3866
3867         if (padapter->bShowGetP2PState)
3868                 DBG_88E("[%s] extra = %s\n", __func__,
3869                         (char __user *)wrqu->data.pointer);
3870         if (!memcmp((__force const char *)wrqu->data.pointer,
3871                         "status", 6)) {
3872                 rtw_p2p_get_status(dev, info, wrqu, extra);
3873         } else if (!memcmp((__force const char *)wrqu->data.pointer,
3874                         "role", 4)) {
3875                 rtw_p2p_get_role(dev, info, wrqu, extra);
3876         } else if (!memcmp((__force const char *)wrqu->data.pointer,
3877                         "peer_ifa", 8)) {
3878                 rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
3879         } else if (!memcmp((__force const char *)wrqu->data.pointer,
3880                         "req_cm", 6)) {
3881                 rtw_p2p_get_req_cm(dev, info, wrqu, extra);
3882         } else if (!memcmp((__force const char *)wrqu->data.pointer,
3883                         "peer_deva", 9)) {
3884                 /*      Get the P2P device address when receiving the provision discovery request frame. */
3885                 rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
3886         } else if (!memcmp((__force const char *)wrqu->data.pointer,
3887                         "group_id", 8)) {
3888                 rtw_p2p_get_groupid(dev, info, wrqu, extra);
3889         } else if (!memcmp((__force const char *)wrqu->data.pointer,
3890                         "peer_deva_inv", 9)) {
3891                 /*      Get the P2P device address when receiving the P2P Invitation request frame. */
3892                 rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
3893         } else if (!memcmp((__force const char *)wrqu->data.pointer,
3894                         "op_ch", 5)) {
3895                 rtw_p2p_get_op_ch(dev, info, wrqu, extra);
3896         }
3897 #endif /* CONFIG_88EU_P2P */
3898         return ret;
3899 }
3900
3901 static int rtw_p2p_get2(struct net_device *dev,
3902                                struct iw_request_info *info,
3903                                union iwreq_data *wrqu, char *extra)
3904 {
3905         int ret = 0;
3906
3907 #ifdef CONFIG_88EU_P2P
3908         DBG_88E("[%s] extra = %s\n", __func__,
3909                         (char __user *)wrqu->data.pointer);
3910         if (!memcmp(extra, "wpsCM =", 6)) {
3911                 wrqu->data.length -= 6;
3912                 rtw_p2p_get_wps_configmethod(dev, info, wrqu,  &extra[6]);
3913         } else if (!memcmp(extra, "devN =", 5)) {
3914                 wrqu->data.length -= 5;
3915                 rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]);
3916         } else if (!memcmp(extra, "dev_type =", 9)) {
3917                 wrqu->data.length -= 9;
3918                 rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]);
3919         } else if (!memcmp(extra, "go_devadd =", 10)) {
3920                 wrqu->data.length -= 10;
3921                 rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]);
3922         } else if (!memcmp(extra, "InvProc =", 8)) {
3923                 wrqu->data.length -= 8;
3924                 rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]);
3925         }
3926
3927 #endif /* CONFIG_88EU_P2P */
3928
3929         return ret;
3930 }
3931
3932 static int rtw_cta_test_start(struct net_device *dev,
3933                               struct iw_request_info *info,
3934                               union iwreq_data *wrqu, char *extra)
3935 {
3936         int ret = 0;
3937         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3938         DBG_88E("%s %s\n", __func__, extra);
3939         if (!strcmp(extra, "1"))
3940                 padapter->in_cta_test = 1;
3941         else
3942                 padapter->in_cta_test = 0;
3943
3944         if (padapter->in_cta_test) {
3945                 u32 v = rtw_read32(padapter, REG_RCR);
3946                 v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
3947                 rtw_write32(padapter, REG_RCR, v);
3948                 DBG_88E("enable RCR_ADF\n");
3949         } else {
3950                 u32 v = rtw_read32(padapter, REG_RCR);
3951                 v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;/*  RCR_ADF */
3952                 rtw_write32(padapter, REG_RCR, v);
3953                 DBG_88E("disable RCR_ADF\n");
3954         }
3955         return ret;
3956 }
3957
3958 static int rtw_rereg_nd_name(struct net_device *dev,
3959                                struct iw_request_info *info,
3960                                union iwreq_data *wrqu, char *extra)
3961 {
3962         int ret = 0;
3963         struct adapter *padapter = rtw_netdev_priv(dev);
3964         struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
3965         char new_ifname[IFNAMSIZ];
3966
3967         if (rereg_priv->old_ifname[0] == 0) {
3968                 char *reg_ifname;
3969                 reg_ifname = padapter->registrypriv.if2name;
3970
3971                 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
3972                 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
3973         }
3974
3975         if (wrqu->data.length > IFNAMSIZ)
3976                 return -EFAULT;
3977
3978         if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
3979                 return -EFAULT;
3980
3981         if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
3982                 return ret;
3983
3984         DBG_88E("%s new_ifname:%s\n", __func__, new_ifname);
3985         ret = rtw_change_ifname(padapter, new_ifname);
3986         if (0 != ret)
3987                 goto exit;
3988
3989         if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
3990                 padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
3991                 rtw_hal_sw_led_init(padapter);
3992                 rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
3993         }
3994
3995         strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
3996         rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
3997
3998         if (!memcmp(new_ifname, "disable%d", 9)) {
3999                 DBG_88E("%s disable\n", __func__);
4000                 /*  free network queue for Android's timming issue */
4001                 rtw_free_network_queue(padapter, true);
4002
4003                 /*  close led */
4004                 rtw_led_control(padapter, LED_CTL_POWER_OFF);
4005                 rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
4006                 padapter->ledpriv.bRegUseLed = false;
4007                 rtw_hal_sw_led_deinit(padapter);
4008
4009                 /*  the interface is being "disabled", we can do deeper IPS */
4010                 rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
4011                 rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
4012         }
4013 exit:
4014         return ret;
4015 }
4016
4017 static void mac_reg_dump(struct adapter *padapter)
4018 {
4019         int i, j = 1;
4020         pr_info("\n ======= MAC REG =======\n");
4021         for (i = 0x0; i < 0x300; i += 4) {
4022                 if (j%4 == 1)
4023                         pr_info("0x%02x", i);
4024                 pr_info(" 0x%08x ", rtw_read32(padapter, i));
4025                 if ((j++)%4 == 0)
4026                         pr_info("\n");
4027         }
4028         for (i = 0x400; i < 0x800; i += 4) {
4029                 if (j%4 == 1)
4030                         pr_info("0x%02x", i);
4031                 pr_info(" 0x%08x ", rtw_read32(padapter, i));
4032                 if ((j++)%4 == 0)
4033                         pr_info("\n");
4034         }
4035 }
4036
4037 static void bb_reg_dump(struct adapter *padapter)
4038 {
4039         int i, j = 1;
4040         pr_info("\n ======= BB REG =======\n");
4041         for (i = 0x800; i < 0x1000; i += 4) {
4042                 if (j%4 == 1)
4043                         pr_info("0x%02x", i);
4044
4045                 pr_info(" 0x%08x ", rtw_read32(padapter, i));
4046                 if ((j++)%4 == 0)
4047                         pr_info("\n");
4048         }
4049 }
4050
4051 static void rf_reg_dump(struct adapter *padapter)
4052 {
4053         int i, j = 1, path;
4054         u32 value;
4055         u8 rf_type, path_nums = 0;
4056         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
4057
4058         pr_info("\n ======= RF REG =======\n");
4059         if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
4060                 path_nums = 1;
4061         else
4062                 path_nums = 2;
4063
4064         for (path = 0; path < path_nums; path++) {
4065                 pr_info("\nRF_Path(%x)\n", path);
4066                 for (i = 0; i < 0x100; i++) {
4067                         value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
4068                         if (j%4 == 1)
4069                                 pr_info("0x%02x ", i);
4070                         pr_info(" 0x%08x ", value);
4071                         if ((j++)%4 == 0)
4072                                 pr_info("\n");
4073                 }
4074         }
4075 }
4076
4077 static int rtw_dbg_port(struct net_device *dev,
4078                                struct iw_request_info *info,
4079                                union iwreq_data *wrqu, char *extra)
4080 {
4081         int ret = 0;
4082         u8 major_cmd, minor_cmd;
4083         u16 arg;
4084         s32 extra_arg;
4085         u32 *pdata, val32;
4086         struct sta_info *psta;
4087         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4088         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4089         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4090         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4091         struct security_priv *psecuritypriv = &padapter->securitypriv;
4092         struct wlan_network *cur_network = &(pmlmepriv->cur_network);
4093         struct sta_priv *pstapriv = &padapter->stapriv;
4094
4095         pdata = (u32 *)&wrqu->data;
4096
4097         val32 = *pdata;
4098         arg = (u16)(val32 & 0x0000ffff);
4099         major_cmd = (u8)(val32 >> 24);
4100         minor_cmd = (u8)((val32 >> 16) & 0x00ff);
4101
4102         extra_arg = *(pdata+1);
4103
4104         switch (major_cmd) {
4105         case 0x70:/* read_reg */
4106                 switch (minor_cmd) {
4107                 case 1:
4108                         DBG_88E("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
4109                         break;
4110                 case 2:
4111                         DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
4112                         break;
4113                 case 4:
4114                         DBG_88E("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
4115                         break;
4116                 }
4117                 break;
4118         case 0x71:/* write_reg */
4119                 switch (minor_cmd) {
4120                 case 1:
4121                         rtw_write8(padapter, arg, extra_arg);
4122                         DBG_88E("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
4123                         break;
4124                 case 2:
4125                         rtw_write16(padapter, arg, extra_arg);
4126                         DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
4127                         break;
4128                 case 4:
4129                         rtw_write32(padapter, arg, extra_arg);
4130                         DBG_88E("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
4131                         break;
4132                 }
4133                 break;
4134         case 0x72:/* read_bb */
4135                 DBG_88E("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
4136                 break;
4137         case 0x73:/* write_bb */
4138                 rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
4139                 DBG_88E("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
4140                 break;
4141         case 0x74:/* read_rf */
4142                 DBG_88E("read RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
4143                 break;
4144         case 0x75:/* write_rf */
4145                 rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
4146                 DBG_88E("write RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
4147                 break;
4148
4149         case 0x76:
4150                 switch (minor_cmd) {
4151                 case 0x00: /* normal mode, */
4152                         padapter->recvpriv.is_signal_dbg = 0;
4153                         break;
4154                 case 0x01: /* dbg mode */
4155                         padapter->recvpriv.is_signal_dbg = 1;
4156                         extra_arg = extra_arg > 100 ? 100 : extra_arg;
4157                         extra_arg = extra_arg < 0 ? 0 : extra_arg;
4158                         padapter->recvpriv.signal_strength_dbg = extra_arg;
4159                         break;
4160                 }
4161                 break;
4162         case 0x78: /* IOL test */
4163                 switch (minor_cmd) {
4164                 case 0x04: /* LLT table initialization test */
4165                 {
4166                         u8 page_boundary = 0xf9;
4167                         struct xmit_frame       *xmit_frame;
4168
4169                         xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4170                         if (xmit_frame == NULL) {
4171                                 ret = -ENOMEM;
4172                                 break;
4173                         }
4174
4175                         rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
4176
4177                         if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
4178                                 ret = -EPERM;
4179                 }
4180                         break;
4181                 case 0x05: /* blink LED test */
4182                 {
4183                         u16 reg = 0x4c;
4184                         u32 blink_num = 50;
4185                         u32 blink_delay_ms = 200;
4186                         int i;
4187                         struct xmit_frame       *xmit_frame;
4188
4189                         xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4190                         if (xmit_frame == NULL) {
4191                                 ret = -ENOMEM;
4192                                 break;
4193                         }
4194
4195                         for (i = 0; i < blink_num; i++) {
4196                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
4197                                 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
4198                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
4199                                 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
4200                         }
4201                         if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200, 0))
4202                                 ret = -EPERM;
4203                 }
4204                         break;
4205
4206                 case 0x06: /* continuous write byte test */
4207                 {
4208                         u16 reg = arg;
4209                         u16 start_value = 0;
4210                         u32 write_num = extra_arg;
4211                         int i;
4212                         u8 final;
4213                         struct xmit_frame       *xmit_frame;
4214
4215                         xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4216                         if (xmit_frame == NULL) {
4217                                 ret = -ENOMEM;
4218                                 break;
4219                         }
4220
4221                         for (i = 0; i < write_num; i++)
4222                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value, 0xFF);
4223                         if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4224                                 ret = -EPERM;
4225
4226                         final = rtw_read8(padapter, reg);
4227                         if (start_value+write_num-1 == final)
4228                                 DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
4229                         else
4230                                 DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
4231                 }
4232                         break;
4233
4234                 case 0x07: /* continuous write word test */
4235                 {
4236                         u16 reg = arg;
4237                         u16 start_value = 200;
4238                         u32 write_num = extra_arg;
4239
4240                         int i;
4241                         u16 final;
4242                         struct xmit_frame       *xmit_frame;
4243
4244                         xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4245                         if (xmit_frame == NULL) {
4246                                 ret = -ENOMEM;
4247                                 break;
4248                         }
4249
4250                         for (i = 0; i < write_num; i++)
4251                                 rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value, 0xFFFF);
4252                         if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4253                                 ret = -EPERM;
4254
4255                         final = rtw_read16(padapter, reg);
4256                         if (start_value+write_num-1 == final)
4257                                 DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
4258                         else
4259                                 DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
4260                 }
4261                         break;
4262                 case 0x08: /* continuous write dword test */
4263                 {
4264                         u16 reg = arg;
4265                         u32 start_value = 0x110000c7;
4266                         u32 write_num = extra_arg;
4267
4268                         int i;
4269                         u32 final;
4270                         struct xmit_frame       *xmit_frame;
4271
4272                         xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4273                         if (xmit_frame == NULL) {
4274                                 ret = -ENOMEM;
4275                                 break;
4276                         }
4277
4278                         for (i = 0; i < write_num; i++)
4279                                 rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value, 0xFFFFFFFF);
4280                         if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4281                                 ret = -EPERM;
4282
4283                         final = rtw_read32(padapter, reg);
4284                         if (start_value+write_num-1 == final)
4285                                 DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n",
4286                                         reg, write_num, start_value, final);
4287                         else
4288                                 DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n",
4289                                         reg, write_num, start_value, final);
4290                 }
4291                         break;
4292                 }
4293                 break;
4294         case 0x79:
4295                 {
4296                         /*
4297                         * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
4298                         * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
4299                         */
4300                         u8 value =  extra_arg & 0x0f;
4301                         u8 sign = minor_cmd;
4302                         u16 write_value = 0;
4303
4304                         DBG_88E("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
4305
4306                         if (sign)
4307                                 value = value | 0x10;
4308
4309                         write_value = value | (value << 5);
4310                         rtw_write16(padapter, 0x6d9, write_value);
4311                 }
4312                 break;
4313         case 0x7a:
4314                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress
4315                         , WLAN_REASON_EXPIRATION_CHK);
4316                 break;
4317         case 0x7F:
4318                 switch (minor_cmd) {
4319                 case 0x0:
4320                         DBG_88E("fwstate = 0x%x\n", get_fwstate(pmlmepriv));
4321                         break;
4322                 case 0x01:
4323                         DBG_88E("auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n",
4324                                 psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
4325                                 psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
4326                         break;
4327                 case 0x02:
4328                         DBG_88E("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
4329                         break;
4330                 case 0x03:
4331                         DBG_88E("qos_option =%d\n", pmlmepriv->qospriv.qos_option);
4332                         DBG_88E("ht_option =%d\n", pmlmepriv->htpriv.ht_option);
4333                         break;
4334                 case 0x04:
4335                         DBG_88E("cur_ch =%d\n", pmlmeext->cur_channel);
4336                         DBG_88E("cur_bw =%d\n", pmlmeext->cur_bwmode);
4337                         DBG_88E("cur_ch_off =%d\n", pmlmeext->cur_ch_offset);
4338                         break;
4339                 case 0x05:
4340                         psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
4341                         if (psta) {
4342                                 int i;
4343                                 struct recv_reorder_ctrl *preorder_ctrl;
4344
4345                                 DBG_88E("SSID =%s\n", cur_network->network.Ssid.Ssid);
4346                                 DBG_88E("sta's macaddr: %pM\n", psta->hwaddr);
4347                                 DBG_88E("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
4348                                 DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
4349                                 DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
4350                                 DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
4351                                 DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
4352                                 DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
4353                                 DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
4354                                 for (i = 0; i < 16; i++) {
4355                                         preorder_ctrl = &psta->recvreorder_ctrl[i];
4356                                         if (preorder_ctrl->enable)
4357                                                 DBG_88E("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
4358                                 }
4359                         } else {
4360                                 DBG_88E("can't get sta's macaddr, cur_network's macaddr:%pM\n", (cur_network->network.MacAddress));
4361                         }
4362                         break;
4363                 case 0x06:
4364                         {
4365                                 u32     ODMFlag;
4366                                 rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
4367                                 DBG_88E("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg);
4368                                 ODMFlag = (u32)(0x0f&arg);
4369                                 DBG_88E("(A)DMFlag = 0x%x\n", ODMFlag);
4370                                 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
4371                         }
4372                         break;
4373                 case 0x07:
4374                         DBG_88E("bSurpriseRemoved =%d, bDriverStopped =%d\n",
4375                                 padapter->bSurpriseRemoved, padapter->bDriverStopped);
4376                         break;
4377                 case 0x08:
4378                         {
4379                                 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4380                                 struct recv_priv  *precvpriv = &padapter->recvpriv;
4381
4382                                 DBG_88E("free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d, free_xmit_extbuf_cnt =%d\n",
4383                                         pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt);
4384                                 DBG_88E("rx_urb_pending_cn =%d\n", precvpriv->rx_pending_cnt);
4385                         }
4386                         break;
4387                 case 0x09:
4388                         {
4389                                 int i, j;
4390                                 struct list_head *plist, *phead;
4391                                 struct recv_reorder_ctrl *preorder_ctrl;
4392
4393 #ifdef CONFIG_88EU_AP_MODE
4394                                 DBG_88E("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
4395 #endif
4396                                 spin_lock_bh(&pstapriv->sta_hash_lock);
4397
4398                                 for (i = 0; i < NUM_STA; i++) {
4399                                         phead = &(pstapriv->sta_hash[i]);
4400                                         plist = phead->next;
4401
4402                                         while ((rtw_end_of_queue_search(phead, plist)) == false) {
4403                                                 psta = container_of(plist, struct sta_info, hash_list);
4404
4405                                                 plist = plist->next;
4406
4407                                                 if (extra_arg == psta->aid) {
4408                                                         DBG_88E("sta's macaddr:%pM\n", (psta->hwaddr));
4409                                                         DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
4410                                                         DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
4411                                                         DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
4412                                                         DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
4413                                                         DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
4414                                                         DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
4415
4416 #ifdef CONFIG_88EU_AP_MODE
4417                                                         DBG_88E("capability = 0x%x\n", psta->capability);
4418                                                         DBG_88E("flags = 0x%x\n", psta->flags);
4419                                                         DBG_88E("wpa_psk = 0x%x\n", psta->wpa_psk);
4420                                                         DBG_88E("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher);
4421                                                         DBG_88E("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher);
4422                                                         DBG_88E("qos_info = 0x%x\n", psta->qos_info);
4423 #endif
4424                                                         DBG_88E("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy);
4425
4426                                                         for (j = 0; j < 16; j++) {
4427                                                                 preorder_ctrl = &psta->recvreorder_ctrl[j];
4428                                                                 if (preorder_ctrl->enable)
4429                                                                         DBG_88E("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq);
4430                                                         }
4431                                                 }
4432                                         }
4433                                 }
4434                                 spin_unlock_bh(&pstapriv->sta_hash_lock);
4435                         }
4436                         break;
4437                 case 0x0c:/* dump rx/tx packet */
4438                         if (arg == 0) {
4439                                 DBG_88E("dump rx packet (%d)\n", extra_arg);
4440                                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
4441                         } else if (arg == 1) {
4442                                 DBG_88E("dump tx packet (%d)\n", extra_arg);
4443                                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
4444                         }
4445                         break;
4446                 case 0x0f:
4447                         if (extra_arg == 0) {
4448                                 DBG_88E("###### silent reset test.......#####\n");
4449                                 rtw_hal_sreset_reset(padapter);
4450                         }
4451                         break;
4452                 case 0x15:
4453                         {
4454                                 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
4455                                 DBG_88E("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
4456                         }
4457                         break;
4458                 case 0x10:/*  driver version display */
4459                         DBG_88E("rtw driver version =%s\n", DRIVERVERSION);
4460                         break;
4461                 case 0x11:
4462                         DBG_88E("turn %s Rx RSSI display function\n", (extra_arg == 1) ? "on" : "off");
4463                         padapter->bRxRSSIDisplay = extra_arg;
4464                         rtw_hal_set_def_var(padapter, HW_DEF_FA_CNT_DUMP, &extra_arg);
4465                         break;
4466                 case 0x12: /* set rx_stbc */
4467                 {
4468                         struct registry_priv    *pregpriv = &padapter->registrypriv;
4469                         /*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
4470                         /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
4471                         if (!pregpriv)
4472                                 break;
4473                         if (extra_arg >= 0 && extra_arg <= 3) {
4474                                 pregpriv->rx_stbc = extra_arg;
4475                                 DBG_88E("set rx_stbc =%d\n", pregpriv->rx_stbc);
4476                         } else {
4477                                 DBG_88E("get rx_stbc =%d\n", pregpriv->rx_stbc);
4478                         }
4479                 }
4480                         break;
4481                 case 0x13: /* set ampdu_enable */
4482                 {
4483                         struct registry_priv    *pregpriv = &padapter->registrypriv;
4484                         /*  0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
4485                         if (!pregpriv)
4486                                 break;
4487                         if (extra_arg >= 0 && extra_arg < 3) {
4488                                 pregpriv->ampdu_enable = extra_arg;
4489                                 DBG_88E("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
4490                         } else {
4491                                 DBG_88E("get ampdu_enable =%d\n", pregpriv->ampdu_enable);
4492                         }
4493                 }
4494                         break;
4495                 case 0x14: /* get wifi_spec */
4496                 {
4497                         struct registry_priv    *pregpriv = &padapter->registrypriv;
4498                         DBG_88E("get wifi_spec =%d\n", pregpriv->wifi_spec);
4499                 }
4500                         break;
4501                 case 0x16:
4502                         if (arg == 0xff) {
4503                                 pr_info("ODM_COMP_DIG\t\tBIT0\n");
4504                                 pr_info("ODM_COMP_RA_MASK\t\tBIT1\n");
4505                                 pr_info("ODM_COMP_DYNAMIC_TXPWR\tBIT2\n");
4506                                 pr_info("ODM_COMP_FA_CNT\t\tBIT3\n");
4507                                 pr_info("ODM_COMP_RSSI_MONITOR\tBIT4\n");
4508                                 pr_info("ODM_COMP_CCK_PD\t\tBIT5\n");
4509                                 pr_info("ODM_COMP_ANT_DIV\t\tBIT6\n");
4510                                 pr_info("ODM_COMP_PWR_SAVE\t\tBIT7\n");
4511                                 pr_info("ODM_COMP_PWR_TRAIN\tBIT8\n");
4512                                 pr_info("ODM_COMP_RATE_ADAPTIVE\tBIT9\n");
4513                                 pr_info("ODM_COMP_PATH_DIV\t\tBIT10\n");
4514                                 pr_info("ODM_COMP_PSD   \tBIT11\n");
4515                                 pr_info("ODM_COMP_DYNAMIC_PRICCA\tBIT12\n");
4516                                 pr_info("ODM_COMP_RXHP\t\tBIT13\n");
4517                                 pr_info("ODM_COMP_EDCA_TURBO\tBIT16\n");
4518                                 pr_info("ODM_COMP_EARLY_MODE\tBIT17\n");
4519                                 pr_info("ODM_COMP_TX_PWR_TRACK\tBIT24\n");
4520                                 pr_info("ODM_COMP_RX_GAIN_TRACK\tBIT25\n");
4521                                 pr_info("ODM_COMP_CALIBRATION\tBIT26\n");
4522                                 rtw_hal_get_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
4523                         } else {
4524                                 rtw_hal_set_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
4525                         }
4526                         break;
4527                 case 0x23:
4528                         DBG_88E("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
4529                         padapter->bNotifyChannelChange = extra_arg;
4530                         break;
4531                 case 0x24:
4532 #ifdef CONFIG_88EU_P2P
4533                         DBG_88E("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
4534                         padapter->bShowGetP2PState = extra_arg;
4535 #endif /*  CONFIG_88EU_P2P */
4536                         break;
4537                 case 0xaa:
4538                         if (extra_arg > 0x13)
4539                                 extra_arg = 0xFF;
4540                         DBG_88E("chang data rate to :0x%02x\n", extra_arg);
4541                         padapter->fix_rate = extra_arg;
4542                         break;
4543                 case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */
4544                         if (extra_arg == 0)
4545                                 mac_reg_dump(padapter);
4546                         else if (extra_arg == 1)
4547                                 bb_reg_dump(padapter);
4548                         else if (extra_arg == 2)
4549                                 rf_reg_dump(padapter);
4550                         break;
4551                 case 0xee:/* turn on/off dynamic funcs */
4552                         {
4553                                 u32 odm_flag;
4554
4555                                 if (0xf == extra_arg) {
4556                                         rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
4557                                         DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
4558                                         DBG_88E("extra_arg = 0  - disable all dynamic func\n");
4559                                         DBG_88E("extra_arg = 1  - disable DIG- BIT(0)\n");
4560                                         DBG_88E("extra_arg = 2  - disable High power - BIT(1)\n");
4561                                         DBG_88E("extra_arg = 3  - disable tx power tracking - BIT(2)\n");
4562                                         DBG_88E("extra_arg = 4  - disable BT coexistence - BIT(3)\n");
4563                                         DBG_88E("extra_arg = 5  - disable antenna diversity - BIT(4)\n");
4564                                         DBG_88E("extra_arg = 6  - enable all dynamic func\n");
4565                                 } else {
4566                                         /*      extra_arg = 0  - disable all dynamic func
4567                                                 extra_arg = 1  - disable DIG
4568                                                 extra_arg = 2  - disable tx power tracking
4569                                                 extra_arg = 3  - turn on all dynamic func
4570                                         */
4571                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
4572                                         rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
4573                                         DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
4574                                 }
4575                         }
4576                         break;
4577
4578                 case 0xfd:
4579                         rtw_write8(padapter, 0xc50, arg);
4580                         DBG_88E("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
4581                         rtw_write8(padapter, 0xc58, arg);
4582                         DBG_88E("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
4583                         break;
4584                 case 0xfe:
4585                         DBG_88E("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
4586                         DBG_88E("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
4587                         break;
4588                 case 0xff:
4589                         DBG_88E("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210));
4590                         DBG_88E("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608));
4591                         DBG_88E("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280));
4592                         DBG_88E("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284));
4593                         DBG_88E("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288));
4594
4595                         DBG_88E("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664));
4596
4597                         DBG_88E("\n");
4598
4599                         DBG_88E("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430));
4600                         DBG_88E("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438));
4601
4602                         DBG_88E("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440));
4603
4604                         DBG_88E("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458));
4605
4606                         DBG_88E("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484));
4607                         DBG_88E("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488));
4608
4609                         DBG_88E("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444));
4610                         DBG_88E("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448));
4611                         DBG_88E("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c));
4612                         DBG_88E("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450));
4613                         break;
4614                 }
4615                 break;
4616         default:
4617                 DBG_88E("error dbg cmd!\n");
4618                 break;
4619         }
4620         return ret;
4621 }
4622
4623 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
4624 {
4625         uint ret = 0;
4626         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4627
4628         switch (name) {
4629         case IEEE_PARAM_WPA_ENABLED:
4630                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
4631                 switch ((value)&0xff) {
4632                 case 1: /* WPA */
4633                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
4634                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
4635                         break;
4636                 case 2: /* WPA2 */
4637                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
4638                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4639                         break;
4640                 }
4641                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
4642                          ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
4643                 break;
4644         case IEEE_PARAM_TKIP_COUNTERMEASURES:
4645                 break;
4646         case IEEE_PARAM_DROP_UNENCRYPTED: {
4647                 /* HACK:
4648                  *
4649                  * wpa_supplicant calls set_wpa_enabled when the driver
4650                  * is loaded and unloaded, regardless of if WPA is being
4651                  * used.  No other calls are made which can be used to
4652                  * determine if encryption will be used or not prior to
4653                  * association being expected.  If encryption is not being
4654                  * used, drop_unencrypted is set to false, else true -- we
4655                  * can use this to determine if the CAP_PRIVACY_ON bit should
4656                  * be set.
4657                  */
4658
4659                 break;
4660         }
4661         case IEEE_PARAM_PRIVACY_INVOKED:
4662                 break;
4663
4664         case IEEE_PARAM_AUTH_ALGS:
4665                 ret = wpa_set_auth_algs(dev, value);
4666                 break;
4667         case IEEE_PARAM_IEEE_802_1X:
4668                 break;
4669         case IEEE_PARAM_WPAX_SELECT:
4670                 break;
4671         default:
4672                 ret = -EOPNOTSUPP;
4673                 break;
4674         }
4675         return ret;
4676 }
4677
4678 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
4679 {
4680         int ret = 0;
4681         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4682
4683         switch (command) {
4684         case IEEE_MLME_STA_DEAUTH:
4685                 if (!rtw_set_802_11_disassociate(padapter))
4686                         ret = -1;
4687                 break;
4688         case IEEE_MLME_STA_DISASSOC:
4689                 if (!rtw_set_802_11_disassociate(padapter))
4690                         ret = -1;
4691                 break;
4692         default:
4693                 ret = -EOPNOTSUPP;
4694                 break;
4695         }
4696
4697         return ret;
4698 }
4699
4700 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
4701 {
4702         struct ieee_param *param;
4703         uint ret = 0;
4704
4705         if (p->length < sizeof(struct ieee_param) || !p->pointer) {
4706                 ret = -EINVAL;
4707                 goto out;
4708         }
4709
4710         param = (struct ieee_param *)rtw_malloc(p->length);
4711         if (param == NULL) {
4712                 ret = -ENOMEM;
4713                 goto out;
4714         }
4715
4716         if (copy_from_user(param, p->pointer, p->length)) {
4717                 kfree(param);
4718                 ret = -EFAULT;
4719                 goto out;
4720         }
4721
4722         switch (param->cmd) {
4723         case IEEE_CMD_SET_WPA_PARAM:
4724                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
4725                 break;
4726
4727         case IEEE_CMD_SET_WPA_IE:
4728                 ret =  rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev),
4729                                       (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
4730                 break;
4731
4732         case IEEE_CMD_SET_ENCRYPTION:
4733                 ret = wpa_set_encryption(dev, param, p->length);
4734                 break;
4735
4736         case IEEE_CMD_MLME:
4737                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
4738                 break;
4739
4740         default:
4741                 DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
4742                 ret = -EOPNOTSUPP;
4743                 break;
4744         }
4745
4746         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
4747                 ret = -EFAULT;
4748
4749         kfree(param);
4750
4751 out:
4752
4753         return ret;
4754 }
4755
4756 #ifdef CONFIG_88EU_AP_MODE
4757 static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
4758 {
4759         struct cmd_obj *ph2c;
4760         struct set_stakey_parm  *psetstakey_para;
4761         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4762         u8 res = _SUCCESS;
4763
4764         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4765         if (ph2c == NULL) {
4766                 res = _FAIL;
4767                 goto exit;
4768         }
4769
4770         psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
4771         if (psetstakey_para == NULL) {
4772                 kfree(ph2c);
4773                 res = _FAIL;
4774                 goto exit;
4775         }
4776
4777         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
4778
4779         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
4780
4781         memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
4782
4783         memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
4784
4785         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4786
4787 exit:
4788
4789         return res;
4790 }
4791
4792 static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
4793 {
4794         u8 keylen;
4795         struct cmd_obj *pcmd;
4796         struct setkey_parm *psetkeyparm;
4797         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
4798         int res = _SUCCESS;
4799
4800         DBG_88E("%s\n", __func__);
4801
4802         pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct      cmd_obj));
4803         if (pcmd == NULL) {
4804                 res = _FAIL;
4805                 goto exit;
4806         }
4807         psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
4808         if (psetkeyparm == NULL) {
4809                 kfree(pcmd);
4810                 res = _FAIL;
4811                 goto exit;
4812         }
4813
4814         _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
4815
4816         psetkeyparm->keyid = (u8)keyid;
4817
4818         psetkeyparm->algorithm = alg;
4819
4820         psetkeyparm->set_tx = 1;
4821
4822         switch (alg) {
4823         case _WEP40_:
4824                 keylen = 5;
4825                 break;
4826         case _WEP104_:
4827                 keylen = 13;
4828                 break;
4829         case _TKIP_:
4830         case _TKIP_WTMIC_:
4831         case _AES_:
4832         default:
4833                 keylen = 16;
4834         }
4835
4836         memcpy(&(psetkeyparm->key[0]), key, keylen);
4837
4838         pcmd->cmdcode = _SetKey_CMD_;
4839         pcmd->parmbuf = (u8 *)psetkeyparm;
4840         pcmd->cmdsz =  (sizeof(struct setkey_parm));
4841         pcmd->rsp = NULL;
4842         pcmd->rspsz = 0;
4843
4844         _rtw_init_listhead(&pcmd->list);
4845
4846         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
4847
4848 exit:
4849
4850         return res;
4851 }
4852
4853 static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
4854 {
4855         u8 alg;
4856
4857         switch (keylen) {
4858         case 5:
4859                 alg = _WEP40_;
4860                 break;
4861         case 13:
4862                 alg = _WEP104_;
4863                 break;
4864         default:
4865                 alg = _NO_PRIVACY_;
4866         }
4867
4868         return set_group_key(padapter, key, alg, keyid);
4869 }
4870
4871 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
4872 {
4873         int ret = 0;
4874         u32 wep_key_idx, wep_key_len, wep_total_len;
4875         struct ndis_802_11_wep   *pwep = NULL;
4876         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
4877         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4878         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
4879         struct security_priv *psecuritypriv = &(padapter->securitypriv);
4880         struct sta_priv *pstapriv = &padapter->stapriv;
4881
4882         DBG_88E("%s\n", __func__);
4883         param->u.crypt.err = 0;
4884         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
4885         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
4886                 ret =  -EINVAL;
4887                 goto exit;
4888         }
4889         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4890             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
4891             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
4892                 if (param->u.crypt.idx >= WEP_KEYS) {
4893                         ret = -EINVAL;
4894                         goto exit;
4895                 }
4896         } else {
4897                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
4898                 if (!psta) {
4899                         DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
4900                         goto exit;
4901                 }
4902         }
4903
4904         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
4905                 /* todo:clear default encryption keys */
4906
4907                 DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
4908                 goto exit;
4909         }
4910         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
4911                 DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
4912                 wep_key_idx = param->u.crypt.idx;
4913                 wep_key_len = param->u.crypt.key_len;
4914                 DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
4915                 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
4916                         ret = -EINVAL;
4917                         goto exit;
4918                 }
4919
4920                 if (wep_key_len > 0) {
4921                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
4922                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
4923                         pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
4924                         if (pwep == NULL) {
4925                                 DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
4926                                 goto exit;
4927                         }
4928
4929                         _rtw_memset(pwep, 0, wep_total_len);
4930
4931                         pwep->KeyLength = wep_key_len;
4932                         pwep->Length = wep_total_len;
4933                 }
4934
4935                 pwep->KeyIndex = wep_key_idx;
4936
4937                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
4938
4939                 if (param->u.crypt.set_tx) {
4940                         DBG_88E("wep, set_tx = 1\n");
4941
4942                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
4943                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
4944                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
4945
4946                         if (pwep->KeyLength == 13) {
4947                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
4948                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
4949                         }
4950
4951                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
4952
4953                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
4954
4955                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
4956
4957                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
4958                 } else {
4959                         DBG_88E("wep, set_tx = 0\n");
4960
4961                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
4962                         /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
4963
4964                       memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
4965
4966                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
4967
4968                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
4969                 }
4970
4971                 goto exit;
4972         }
4973
4974         if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
4975                 if (param->u.crypt.set_tx == 1) {
4976                         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
4977                                 DBG_88E("%s, set group_key, WEP\n", __func__);
4978
4979                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4980                                             param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4981
4982                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
4983                                 if (param->u.crypt.key_len == 13)
4984                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
4985                         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
4986                                 DBG_88E("%s, set group_key, TKIP\n", __func__);
4987                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
4988                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4989                                             param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4990                                 /* set mic key */
4991                                 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
4992                                 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
4993
4994                                 psecuritypriv->busetkipkey = true;
4995                         } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
4996                                 DBG_88E("%s, set group_key, CCMP\n", __func__);
4997                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
4998                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4999                                             param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5000                         } else {
5001                                 DBG_88E("%s, set group_key, none\n", __func__);
5002                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
5003                         }
5004                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
5005                         psecuritypriv->binstallGrpkey = true;
5006                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
5007                         set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
5008                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
5009                         if (pbcmc_sta) {
5010                                 pbcmc_sta->ieee8021x_blocked = false;
5011                                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
5012                         }
5013                 }
5014                 goto exit;
5015         }
5016
5017         if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
5018                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
5019                         if (param->u.crypt.set_tx == 1) {
5020                                 memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5021
5022                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
5023                                         DBG_88E("%s, set pairwise key, WEP\n", __func__);
5024
5025                                         psta->dot118021XPrivacy = _WEP40_;
5026                                         if (param->u.crypt.key_len == 13)
5027                                                 psta->dot118021XPrivacy = _WEP104_;
5028                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
5029                                         DBG_88E("%s, set pairwise key, TKIP\n", __func__);
5030
5031                                         psta->dot118021XPrivacy = _TKIP_;
5032
5033                                         /* set mic key */
5034                                         memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
5035                                         memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
5036
5037                                         psecuritypriv->busetkipkey = true;
5038                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
5039                                         DBG_88E("%s, set pairwise key, CCMP\n", __func__);
5040
5041                                         psta->dot118021XPrivacy = _AES_;
5042                                 } else {
5043                                         DBG_88E("%s, set pairwise key, none\n", __func__);
5044
5045                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
5046                                 }
5047
5048                                 set_pairwise_key(padapter, psta);
5049
5050                                 psta->ieee8021x_blocked = false;
5051                         } else { /* group key??? */
5052                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
5053                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5054                                                     param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5055                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
5056                                         if (param->u.crypt.key_len == 13)
5057                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
5058                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
5059                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
5060
5061                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5062                                                     param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5063
5064                                         /* set mic key */
5065                                         memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
5066                                         memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
5067
5068                                         psecuritypriv->busetkipkey = true;
5069                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
5070                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
5071
5072                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5073                                                     param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5074                                 } else {
5075                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
5076                                 }
5077
5078                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
5079
5080                                 psecuritypriv->binstallGrpkey = true;
5081
5082                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
5083
5084                                 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
5085
5086                                 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
5087                                 if (pbcmc_sta) {
5088                                         pbcmc_sta->ieee8021x_blocked = false;
5089                                         pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
5090                                 }
5091                         }
5092                 }
5093         }
5094
5095 exit:
5096
5097         kfree(pwep);
5098
5099         return ret;
5100 }
5101
5102 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
5103 {
5104         int ret = 0;
5105         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5106         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5107         struct sta_priv *pstapriv = &padapter->stapriv;
5108         unsigned char *pbuf = param->u.bcn_ie.buf;
5109
5110         DBG_88E("%s, len =%d\n", __func__, len);
5111
5112         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5113                 return -EINVAL;
5114
5115         memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
5116
5117         if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
5118                 pstapriv->max_num_sta = NUM_STA;
5119
5120         if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
5121                 ret = 0;
5122         else
5123                 ret = -EINVAL;
5124
5125         return ret;
5126 }
5127
5128 static int rtw_hostapd_sta_flush(struct net_device *dev)
5129 {
5130         int ret = 0;
5131         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5132
5133         DBG_88E("%s\n", __func__);
5134
5135         flush_all_cam_entry(padapter);  /* clear CAM */
5136
5137         ret = rtw_sta_flush(padapter);
5138
5139         return ret;
5140 }
5141
5142 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
5143 {
5144         int ret = 0;
5145         struct sta_info *psta = NULL;
5146         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5147         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5148         struct sta_priv *pstapriv = &padapter->stapriv;
5149
5150         DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
5151
5152         if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
5153                 return -EINVAL;
5154
5155         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5156             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5157             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5158                 return -EINVAL;
5159
5160         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5161         if (psta) {
5162                 int flags = param->u.add_sta.flags;
5163
5164                 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
5165
5166                 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
5167
5168                 /* check wmm cap. */
5169                 if (WLAN_STA_WME&flags)
5170                         psta->qos_option = 1;
5171                 else
5172                         psta->qos_option = 0;
5173
5174                 if (pmlmepriv->qospriv.qos_option == 0)
5175                         psta->qos_option = 0;
5176
5177                 /* chec 802.11n ht cap. */
5178                 if (WLAN_STA_HT&flags) {
5179                         psta->htpriv.ht_option = true;
5180                         psta->qos_option = 1;
5181                         memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
5182                 } else {
5183                         psta->htpriv.ht_option = false;
5184                 }
5185
5186                 if (pmlmepriv->htpriv.ht_option == false)
5187                         psta->htpriv.ht_option = false;
5188
5189                 update_sta_info_apmode(padapter, psta);
5190         } else {
5191                 ret = -ENOMEM;
5192         }
5193
5194         return ret;
5195 }
5196
5197 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
5198 {
5199         int ret = 0;
5200         struct sta_info *psta = NULL;
5201         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5202         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5203         struct sta_priv *pstapriv = &padapter->stapriv;
5204         int updated = 0;
5205
5206         DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
5207
5208         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5209                 return -EINVAL;
5210
5211         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5212             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5213             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5214                 return -EINVAL;
5215
5216         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5217         if (psta) {
5218                 spin_lock_bh(&pstapriv->asoc_list_lock);
5219                 if (!rtw_is_list_empty(&psta->asoc_list)) {
5220                         rtw_list_delete(&psta->asoc_list);
5221                         pstapriv->asoc_list_cnt--;
5222                         updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
5223                 }
5224                 spin_unlock_bh(&pstapriv->asoc_list_lock);
5225                 associated_clients_update(padapter, updated);
5226                 psta = NULL;
5227         } else {
5228                 DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
5229         }
5230
5231         return ret;
5232 }
5233
5234 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
5235 {
5236         int ret = 0;
5237         struct sta_info *psta = NULL;
5238         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5239         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5240         struct sta_priv *pstapriv = &padapter->stapriv;
5241         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
5242         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
5243
5244         DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
5245
5246         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5247                 return -EINVAL;
5248
5249         if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
5250             param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
5251             param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
5252                 return -EINVAL;
5253
5254         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
5255         if (psta) {
5256                 psta_data->aid = (u16)psta->aid;
5257                 psta_data->capability = psta->capability;
5258                 psta_data->flags = psta->flags;
5259
5260 /*
5261                 nonerp_set : BIT(0)
5262                 no_short_slot_time_set : BIT(1)
5263                 no_short_preamble_set : BIT(2)
5264                 no_ht_gf_set : BIT(3)
5265                 no_ht_set : BIT(4)
5266                 ht_20mhz_set : BIT(5)
5267 */
5268
5269                 psta_data->sta_set = ((psta->nonerp_set) |
5270                                       (psta->no_short_slot_time_set << 1) |
5271                                       (psta->no_short_preamble_set << 2) |
5272                                       (psta->no_ht_gf_set << 3) |
5273                                       (psta->no_ht_set << 4) |
5274                                       (psta->ht_20mhz_set << 5));
5275                 psta_data->tx_supp_rates_len =  psta->bssratelen;
5276                 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
5277                 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
5278                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
5279                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
5280                 psta_data->rx_drops = psta->sta_stats.rx_drops;
5281                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
5282                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
5283                 psta_data->tx_drops = psta->sta_stats.tx_drops;
5284         } else {
5285                 ret = -1;
5286         }
5287
5288         return ret;
5289 }
5290
5291 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
5292 {
5293         int ret = 0;
5294         struct sta_info *psta = NULL;
5295         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5296         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5297         struct sta_priv *pstapriv = &padapter->stapriv;
5298
5299         DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
5300
5301         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5302                 return -EINVAL;
5303
5304         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5305             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5306             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5307                 return -EINVAL;
5308
5309         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5310         if (psta) {
5311                 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
5312                         int wpa_ie_len;
5313                         int copy_len;
5314
5315                         wpa_ie_len = psta->wpa_ie[1];
5316                         copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len+2);
5317                         param->u.wpa_ie.len = copy_len;
5318                         memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
5319                 } else {
5320                         DBG_88E("sta's wpa_ie is NONE\n");
5321                 }
5322         } else {
5323                 ret = -1;
5324         }
5325
5326         return ret;
5327 }
5328
5329 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
5330 {
5331         int ret = 0;
5332         unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
5333         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5334         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5335         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5336         int ie_len;
5337
5338         DBG_88E("%s, len =%d\n", __func__, len);
5339
5340         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5341                 return -EINVAL;
5342
5343         ie_len = len-12-2;/*  12 = param header, 2:no packed */
5344
5345         if (pmlmepriv->wps_beacon_ie) {
5346                 kfree(pmlmepriv->wps_beacon_ie);
5347                 pmlmepriv->wps_beacon_ie = NULL;
5348         }
5349
5350         if (ie_len > 0) {
5351                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
5352                 pmlmepriv->wps_beacon_ie_len = ie_len;
5353                 if (pmlmepriv->wps_beacon_ie == NULL) {
5354                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5355                         return -EINVAL;
5356                 }
5357
5358                 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
5359
5360                 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
5361
5362                 pmlmeext->bstart_bss = true;
5363         }
5364
5365         return ret;
5366 }
5367
5368 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
5369 {
5370         int ret = 0;
5371         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5372         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5373         int ie_len;
5374
5375         DBG_88E("%s, len =%d\n", __func__, len);
5376
5377         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5378                 return -EINVAL;
5379
5380         ie_len = len-12-2;/*  12 = param header, 2:no packed */
5381
5382         if (pmlmepriv->wps_probe_resp_ie) {
5383                 kfree(pmlmepriv->wps_probe_resp_ie);
5384                 pmlmepriv->wps_probe_resp_ie = NULL;
5385         }
5386
5387         if (ie_len > 0) {
5388                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
5389                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
5390                 if (pmlmepriv->wps_probe_resp_ie == NULL) {
5391                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5392                         return -EINVAL;
5393                 }
5394                 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
5395         }
5396
5397         return ret;
5398 }
5399
5400 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
5401 {
5402         int ret = 0;
5403         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5404         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5405         int ie_len;
5406
5407         DBG_88E("%s, len =%d\n", __func__, len);
5408
5409         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5410                 return -EINVAL;
5411
5412         ie_len = len-12-2;/*  12 = param header, 2:no packed */
5413
5414         if (pmlmepriv->wps_assoc_resp_ie) {
5415                 kfree(pmlmepriv->wps_assoc_resp_ie);
5416                 pmlmepriv->wps_assoc_resp_ie = NULL;
5417         }
5418
5419         if (ie_len > 0) {
5420                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
5421                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
5422                 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
5423                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5424                         return -EINVAL;
5425                 }
5426
5427                 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
5428         }
5429
5430         return ret;
5431 }
5432
5433 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
5434 {
5435         int ret = 0;
5436         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5437         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5438         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5439         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5440
5441         u8 value;
5442
5443         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5444                 return -EINVAL;
5445
5446         if (param->u.wpa_param.name != 0) /* dummy test... */
5447                 DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
5448         value = param->u.wpa_param.value;
5449
5450         /* use the same definition of hostapd's ignore_broadcast_ssid */
5451         if (value != 1 && value != 2)
5452                 value = 0;
5453         DBG_88E("%s value(%u)\n", __func__, value);
5454         pmlmeinfo->hidden_ssid_mode = value;
5455         return ret;
5456 }
5457
5458 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
5459 {
5460         int ret = 0;
5461         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5462         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5463
5464         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5465                 return -EINVAL;
5466
5467         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5468             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5469             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5470                 return -EINVAL;
5471         ret = rtw_acl_remove_sta(padapter, param->sta_addr);
5472         return ret;
5473 }
5474
5475 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
5476 {
5477         int ret = 0;
5478         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5479         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5480
5481         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5482                 return -EINVAL;
5483
5484         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5485             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5486             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5487                 return -EINVAL;
5488         ret = rtw_acl_add_sta(padapter, param->sta_addr);
5489         return ret;
5490 }
5491
5492 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
5493 {
5494         int ret = 0;
5495         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5496         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5497
5498         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5499                 return -EINVAL;
5500
5501         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
5502
5503         return ret;
5504 }
5505
5506 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
5507 {
5508         struct ieee_param *param;
5509         int ret = 0;
5510         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5511
5512         /*
5513         * this function is expect to call in master mode, which allows no power saving
5514         * so, we just check hw_init_completed
5515         */
5516
5517         if (!padapter->hw_init_completed) {
5518                 ret = -EPERM;
5519                 goto out;
5520         }
5521
5522         if (!p->pointer) {
5523                 ret = -EINVAL;
5524                 goto out;
5525         }
5526
5527         param = (struct ieee_param *)rtw_malloc(p->length);
5528         if (param == NULL) {
5529                 ret = -ENOMEM;
5530                 goto out;
5531         }
5532
5533         if (copy_from_user(param, p->pointer, p->length)) {
5534                 kfree(param);
5535                 ret = -EFAULT;
5536                 goto out;
5537         }
5538
5539         switch (param->cmd) {
5540         case RTL871X_HOSTAPD_FLUSH:
5541                 ret = rtw_hostapd_sta_flush(dev);
5542                 break;
5543         case RTL871X_HOSTAPD_ADD_STA:
5544                 ret = rtw_add_sta(dev, param);
5545                 break;
5546         case RTL871X_HOSTAPD_REMOVE_STA:
5547                 ret = rtw_del_sta(dev, param);
5548                 break;
5549         case RTL871X_HOSTAPD_SET_BEACON:
5550                 ret = rtw_set_beacon(dev, param, p->length);
5551                 break;
5552         case RTL871X_SET_ENCRYPTION:
5553                 ret = rtw_set_encryption(dev, param, p->length);
5554                 break;
5555         case RTL871X_HOSTAPD_GET_WPAIE_STA:
5556                 ret = rtw_get_sta_wpaie(dev, param);
5557                 break;
5558         case RTL871X_HOSTAPD_SET_WPS_BEACON:
5559                 ret = rtw_set_wps_beacon(dev, param, p->length);
5560                 break;
5561         case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
5562                 ret = rtw_set_wps_probe_resp(dev, param, p->length);
5563                 break;
5564         case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
5565                 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
5566                 break;
5567         case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
5568                 ret = rtw_set_hidden_ssid(dev, param, p->length);
5569                 break;
5570         case RTL871X_HOSTAPD_GET_INFO_STA:
5571                 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
5572                 break;
5573         case RTL871X_HOSTAPD_SET_MACADDR_ACL:
5574                 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
5575                 break;
5576         case RTL871X_HOSTAPD_ACL_ADD_STA:
5577                 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
5578                 break;
5579         case RTL871X_HOSTAPD_ACL_REMOVE_STA:
5580                 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
5581                 break;
5582         default:
5583                 DBG_88E("Unknown hostapd request: %d\n", param->cmd);
5584                 ret = -EOPNOTSUPP;
5585                 break;
5586         }
5587
5588         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
5589                 ret = -EFAULT;
5590         kfree(param);
5591 out:
5592         return ret;
5593 }
5594 #endif
5595
5596 #include <rtw_android.h>
5597 static int rtw_wx_set_priv(struct net_device *dev,
5598                                 struct iw_request_info *info,
5599                                 union iwreq_data *awrq,
5600                                 char *extra)
5601 {
5602         int ret = 0;
5603         int len = 0;
5604         char *ext;
5605         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5606         struct iw_point *dwrq = (struct iw_point *)awrq;
5607
5608         if (dwrq->length == 0)
5609                 return -EFAULT;
5610
5611         len = dwrq->length;
5612         ext = vmalloc(len);
5613         if (!ext)
5614                 return -ENOMEM;
5615
5616         if (copy_from_user(ext, dwrq->pointer, len)) {
5617                 vfree(ext);
5618                 return -EFAULT;
5619         }
5620
5621         /* added for wps2.0 @20110524 */
5622         if (dwrq->flags == 0x8766 && len > 8) {
5623                 u32 cp_sz;
5624                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5625                 u8 *probereq_wpsie = ext;
5626                 int probereq_wpsie_len = len;
5627                 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
5628
5629                 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
5630                     (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
5631                         cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
5632
5633                         pmlmepriv->wps_probe_req_ie_len = 0;
5634                         kfree(pmlmepriv->wps_probe_req_ie);
5635                         pmlmepriv->wps_probe_req_ie = NULL;
5636
5637                         pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
5638                         if (pmlmepriv->wps_probe_req_ie == NULL) {
5639                                 pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5640                                 ret =  -EINVAL;
5641                                 goto FREE_EXT;
5642                         }
5643                         memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
5644                         pmlmepriv->wps_probe_req_ie_len = cp_sz;
5645                 }
5646                 goto FREE_EXT;
5647         }
5648
5649         if (len >= WEXT_CSCAN_HEADER_SIZE &&
5650             !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
5651                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
5652                 goto FREE_EXT;
5653         }
5654
5655 FREE_EXT:
5656
5657         vfree(ext);
5658
5659         return ret;
5660 }
5661
5662 static int rtw_pm_set(struct net_device *dev,
5663                                struct iw_request_info *info,
5664                                union iwreq_data *wrqu, char *extra)
5665 {
5666         int ret = 0;
5667         unsigned        mode = 0;
5668         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5669
5670         DBG_88E("[%s] extra = %s\n", __func__, extra);
5671
5672         if (!memcmp(extra, "lps =", 4)) {
5673                 ret = sscanf(extra+4, "%u", &mode);
5674                 if (ret != 1)
5675                         return -EINVAL;
5676                 ret = rtw_pm_set_lps(padapter, mode);
5677         } else if (!memcmp(extra, "ips =", 4)) {
5678                 ret = sscanf(extra+4, "%u", &mode);
5679                 if (ret != 1)
5680                         return -EINVAL;
5681                 ret = rtw_pm_set_ips(padapter, mode);
5682         } else {
5683                 ret = -EINVAL;
5684         }
5685
5686         return ret;
5687 }
5688
5689 static int rtw_mp_efuse_get(struct net_device *dev,
5690                         struct iw_request_info *info,
5691                         union iwreq_data *wdata, char *extra)
5692 {
5693         struct adapter *padapter = rtw_netdev_priv(dev);
5694         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
5695         struct hal_data_8188e *haldata = GET_HAL_DATA(padapter);
5696         struct efuse_hal *pEfuseHal;
5697         struct iw_point *wrqu;
5698
5699         u8 *PROMContent = pEEPROM->efuse_eeprom_data;
5700         u8 ips_mode = 0, lps_mode = 0;
5701         struct pwrctrl_priv *pwrctrlpriv;
5702         u8 *data = NULL;
5703         u8 *rawdata = NULL;
5704         char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
5705         u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
5706         u16 max_available_size = 0, raw_cursize = 0, raw_maxsize = 0;
5707         int err;
5708         u8 org_fw_iol = padapter->registrypriv.fw_iol;/*  0:Disable, 1:enable, 2:by usb speed */
5709
5710         wrqu = (struct iw_point *)wdata;
5711         pwrctrlpriv = &padapter->pwrctrlpriv;
5712         pEfuseHal = &haldata->EfuseHal;
5713
5714         err = 0;
5715         data = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
5716         if (data == NULL) {
5717                 err = -ENOMEM;
5718                 goto exit;
5719         }
5720         rawdata = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
5721         if (rawdata == NULL) {
5722                 err = -ENOMEM;
5723                 goto exit;
5724         }
5725
5726         if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
5727                 err = -EFAULT;
5728                 goto exit;
5729         }
5730         lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
5731         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
5732
5733         ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
5734         rtw_pm_set_ips(padapter, IPS_NONE);
5735
5736         pch = extra;
5737         DBG_88E("%s: in =%s\n", __func__, extra);
5738
5739         i = 0;
5740         /* mac 16 "00e04c871200" rmap, 00, 2 */
5741         while ((token = strsep(&pch, ",")) != NULL) {
5742                 if (i > 2)
5743                         break;
5744                 tmp[i] = token;
5745                 i++;
5746         }
5747         padapter->registrypriv.fw_iol = 0;/*  0:Disable, 1:enable, 2:by usb speed */
5748
5749         if (strcmp(tmp[0], "status") == 0) {
5750                 sprintf(extra, "Load File efuse =%s, Load File MAC =%s", (pEEPROM->bloadfile_fail_flag ? "FAIL" : "OK"), (pEEPROM->bloadmac_fail_flag ? "FAIL" : "OK"));
5751
5752                   goto exit;
5753         } else if (strcmp(tmp[0], "filemap") == 0) {
5754                 mapLen = EFUSE_MAP_SIZE;
5755
5756                 sprintf(extra, "\n");
5757                 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5758                         sprintf(extra, "%s0x%02x\t", extra, i);
5759                         for (j = 0; j < 8; j++)
5760                                 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
5761                         sprintf(extra, "%s\t", extra);
5762                         for (; j < 16; j++)
5763                                 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
5764                         sprintf(extra, "%s\n", extra);
5765                 }
5766         } else if (strcmp(tmp[0], "realmap") == 0) {
5767                 mapLen = EFUSE_MAP_SIZE;
5768                 if (rtw_efuse_map_read(padapter, 0, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL) {
5769                         DBG_88E("%s: read realmap Fail!!\n", __func__);
5770                         err = -EFAULT;
5771                         goto exit;
5772                 }
5773
5774                 sprintf(extra, "\n");
5775                 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5776                         sprintf(extra, "%s0x%02x\t", extra, i);
5777                         for (j = 0; j < 8; j++)
5778                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
5779                         sprintf(extra, "%s\t", extra);
5780                         for (; j < 16; j++)
5781                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
5782                         sprintf(extra, "%s\n", extra);
5783                 }
5784         } else if (strcmp(tmp[0], "rmap") == 0) {
5785                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
5786                         DBG_88E("%s: rmap Fail!! Parameters error!\n", __func__);
5787                         err = -EINVAL;
5788                         goto exit;
5789                 }
5790
5791                 /*  rmap addr cnts */
5792                 addr = simple_strtoul(tmp[1], &ptmp, 16);
5793                 DBG_88E("%s: addr =%x\n", __func__, addr);
5794
5795                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
5796                 if (cnts == 0) {
5797                         DBG_88E("%s: rmap Fail!! cnts error!\n", __func__);
5798                         err = -EINVAL;
5799                         goto exit;
5800                 }
5801                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
5802
5803                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5804                 if ((addr + cnts) > max_available_size) {
5805                         DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5806                         err = -EINVAL;
5807                         goto exit;
5808                 }
5809
5810                 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5811                         DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
5812                         err = -EFAULT;
5813                         goto exit;
5814                 }
5815
5816                 *extra = 0;
5817                 for (i = 0; i < cnts; i++)
5818                         sprintf(extra, "%s0x%02X ", extra, data[i]);
5819         } else if (strcmp(tmp[0], "realraw") == 0) {
5820                 addr = 0;
5821                 mapLen = EFUSE_MAX_SIZE;
5822                 if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) {
5823                         DBG_88E("%s: rtw_efuse_access Fail!!\n", __func__);
5824                         err = -EFAULT;
5825                         goto exit;
5826                 }
5827
5828                 sprintf(extra, "\n");
5829                 for (i = 0; i < mapLen; i++) {
5830                         sprintf(extra, "%s%02X", extra, rawdata[i]);
5831
5832                         if ((i & 0xF) == 0xF)
5833                                 sprintf(extra, "%s\n", extra);
5834                         else if ((i & 0x7) == 0x7)
5835                                 sprintf(extra, "%s\t", extra);
5836                         else
5837                                 sprintf(extra, "%s ", extra);
5838                 }
5839         } else if (strcmp(tmp[0], "mac") == 0) {
5840                 cnts = 6;
5841
5842                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5843                 if ((addr + cnts) > max_available_size) {
5844                         DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5845                         err = -EFAULT;
5846                         goto exit;
5847                 }
5848
5849                 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5850                         DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
5851                         err = -EFAULT;
5852                         goto exit;
5853                 }
5854
5855                 *extra = 0;
5856                 for (i = 0; i < cnts; i++) {
5857                         sprintf(extra, "%s%02X", extra, data[i]);
5858                         if (i != (cnts-1))
5859                                 sprintf(extra, "%s:", extra);
5860                 }
5861         } else if (strcmp(tmp[0], "vidpid") == 0) {
5862                 cnts = 4;
5863
5864                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5865                 if ((addr + cnts) > max_available_size) {
5866                         DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5867                         err = -EFAULT;
5868                         goto exit;
5869                 }
5870                 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5871                         DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
5872                         err = -EFAULT;
5873                         goto exit;
5874                 }
5875
5876                 *extra = 0;
5877                 for (i = 0; i < cnts; i++) {
5878                         sprintf(extra, "%s0x%02X", extra, data[i]);
5879                         if (i != (cnts-1))
5880                                 sprintf(extra, "%s,", extra);
5881                 }
5882         } else if (strcmp(tmp[0], "ableraw") == 0) {
5883                 efuse_GetCurrentSize(padapter, &raw_cursize);
5884                 raw_maxsize = efuse_GetMaxSize(padapter);
5885                 sprintf(extra, "[available raw size] = %d bytes", raw_maxsize-raw_cursize);
5886         } else if (strcmp(tmp[0], "btfmap") == 0) {
5887                 mapLen = EFUSE_BT_MAX_MAP_LEN;
5888                 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
5889                         DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
5890                         err = -EFAULT;
5891                         goto exit;
5892                 }
5893
5894                 sprintf(extra, "\n");
5895                 for (i = 0; i < 512; i += 16) {
5896                         /*  set 512 because the iwpriv's extra size have limit 0x7FF */
5897                         sprintf(extra, "%s0x%03x\t", extra, i);
5898                         for (j = 0; j < 8; j++)
5899                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5900                         sprintf(extra, "%s\t", extra);
5901                         for (; j < 16; j++)
5902                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5903                         sprintf(extra, "%s\n", extra);
5904                 }
5905         } else if (strcmp(tmp[0], "btbmap") == 0) {
5906                 mapLen = EFUSE_BT_MAX_MAP_LEN;
5907                 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
5908                         DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
5909                         err = -EFAULT;
5910                         goto exit;
5911                 }
5912
5913                 sprintf(extra, "\n");
5914                 for (i = 512; i < 1024; i += 16) {
5915                         sprintf(extra, "%s0x%03x\t", extra, i);
5916                         for (j = 0; j < 8; j++)
5917                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5918                         sprintf(extra, "%s\t", extra);
5919                         for (; j < 16; j++)
5920                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5921                         sprintf(extra, "%s\n", extra);
5922                 }
5923         } else if (strcmp(tmp[0], "btrmap") == 0) {
5924                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
5925                         err = -EINVAL;
5926                         goto exit;
5927                 }
5928
5929                 /*  rmap addr cnts */
5930                 addr = simple_strtoul(tmp[1], &ptmp, 16);
5931                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
5932
5933                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
5934                 if (cnts == 0) {
5935                         DBG_88E("%s: btrmap Fail!! cnts error!\n", __func__);
5936                         err = -EINVAL;
5937                         goto exit;
5938                 }
5939                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
5940
5941                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5942                 if ((addr + cnts) > max_available_size) {
5943                         DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5944                         err = -EFAULT;
5945                         goto exit;
5946                 }
5947
5948                 if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5949                         DBG_88E("%s: rtw_BT_efuse_map_read error!!\n", __func__);
5950                         err = -EFAULT;
5951                         goto exit;
5952                 }
5953
5954                 *extra = 0;
5955                 for (i = 0; i < cnts; i++)
5956                         sprintf(extra, "%s 0x%02X ", extra, data[i]);
5957         } else if (strcmp(tmp[0], "btffake") == 0) {
5958                 sprintf(extra, "\n");
5959                 for (i = 0; i < 512; i += 16) {
5960                         sprintf(extra, "%s0x%03x\t", extra, i);
5961                         for (j = 0; j < 8; j++)
5962                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5963                         sprintf(extra, "%s\t", extra);
5964                         for (; j < 16; j++)
5965                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5966                         sprintf(extra, "%s\n", extra);
5967                 }
5968         } else if (strcmp(tmp[0], "btbfake") == 0) {
5969                 sprintf(extra, "\n");
5970                 for (i = 512; i < 1024; i += 16) {
5971                         sprintf(extra, "%s0x%03x\t", extra, i);
5972                         for (j = 0; j < 8; j++)
5973                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5974                         sprintf(extra, "%s\t", extra);
5975                         for (; j < 16; j++)
5976                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5977                         sprintf(extra, "%s\n", extra);
5978                 }
5979         } else if (strcmp(tmp[0], "wlrfkmap") == 0) {
5980                 sprintf(extra, "\n");
5981                 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5982                         sprintf(extra, "%s0x%02x\t", extra, i);
5983                         for (j = 0; j < 8; j++)
5984                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
5985                         sprintf(extra, "%s\t", extra);
5986                         for (; j < 16; j++)
5987                                 sprintf(extra, "%s %02X", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
5988                         sprintf(extra, "%s\n", extra);
5989                 }
5990         } else {
5991                  sprintf(extra, "Command not found!");
5992         }
5993
5994 exit:
5995         kfree(data);
5996         kfree(rawdata);
5997         if (!err)
5998                 wrqu->length = strlen(extra);
5999
6000         rtw_pm_set_ips(padapter, ips_mode);
6001         rtw_pm_set_lps(padapter, lps_mode);
6002         padapter->registrypriv.fw_iol = org_fw_iol;/*  0:Disable, 1:enable, 2:by usb speed */
6003         return err;
6004 }
6005
6006 static int rtw_mp_efuse_set(struct net_device *dev,
6007                         struct iw_request_info *info,
6008                         union iwreq_data *wdata, char *extra)
6009 {
6010         struct adapter *padapter;
6011         struct pwrctrl_priv *pwrctrlpriv;
6012         struct hal_data_8188e *haldata;
6013         struct efuse_hal *pEfuseHal;
6014
6015         u8 ips_mode = 0, lps_mode = 0;
6016         u32 i, jj, kk;
6017         u8 *setdata = NULL;
6018         u8 *ShadowMapBT = NULL;
6019         u8 *ShadowMapWiFi = NULL;
6020         u8 *setrawdata = NULL;
6021         char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
6022         u16 addr = 0, cnts = 0, max_available_size = 0;
6023         int err;
6024
6025         padapter = rtw_netdev_priv(dev);
6026         pwrctrlpriv = &padapter->pwrctrlpriv;
6027         haldata = GET_HAL_DATA(padapter);
6028         pEfuseHal = &haldata->EfuseHal;
6029         err = 0;
6030         setdata = _rtw_zmalloc(1024);
6031         if (setdata == NULL) {
6032                 err = -ENOMEM;
6033                 goto exit;
6034         }
6035         ShadowMapBT = _rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
6036         if (ShadowMapBT == NULL) {
6037                 err = -ENOMEM;
6038                 goto exit;
6039         }
6040         ShadowMapWiFi = _rtw_malloc(EFUSE_MAP_SIZE);
6041         if (ShadowMapWiFi == NULL) {
6042                 err = -ENOMEM;
6043                 goto exit;
6044         }
6045         setrawdata = _rtw_malloc(EFUSE_MAX_SIZE);
6046         if (setrawdata == NULL) {
6047                 err = -ENOMEM;
6048                 goto exit;
6049         }
6050
6051         lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
6052         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
6053
6054         ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
6055         rtw_pm_set_ips(padapter, IPS_NONE);
6056
6057         pch = extra;
6058         DBG_88E("%s: in =%s\n", __func__, extra);
6059
6060         i = 0;
6061         while ((token = strsep(&pch, ",")) != NULL) {
6062                 if (i > 2)
6063                         break;
6064                 tmp[i] = token;
6065                 i++;
6066         }
6067
6068         /*  tmp[0],[1],[2] */
6069         /*  wmap, addr, 00e04c871200 */
6070         if (strcmp(tmp[0], "wmap") == 0) {
6071                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6072                         err = -EINVAL;
6073                         goto exit;
6074                 }
6075
6076                 addr = simple_strtoul(tmp[1], &ptmp, 16);
6077                 addr &= 0xFFF;
6078
6079                 cnts = strlen(tmp[2]);
6080                 if (cnts%2) {
6081                         err = -EINVAL;
6082                         goto exit;
6083                 }
6084                 cnts /= 2;
6085                 if (cnts == 0) {
6086                         err = -EINVAL;
6087                         goto exit;
6088                 }
6089
6090                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6091                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6092                 DBG_88E("%s: map data =%s\n", __func__, tmp[2]);
6093
6094                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6095                         setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6096                 /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
6097                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
6098                 if ((addr+cnts) > max_available_size) {
6099                         DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6100                         err = -EFAULT;
6101                         goto exit;
6102                 }
6103
6104                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6105                         DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6106                         err = -EFAULT;
6107                         goto exit;
6108                 }
6109         } else if (strcmp(tmp[0], "wraw") == 0) {
6110                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6111                         err = -EINVAL;
6112                         goto exit;
6113                 }
6114
6115                 addr = simple_strtoul(tmp[1], &ptmp, 16);
6116                 addr &= 0xFFF;
6117
6118                 cnts = strlen(tmp[2]);
6119                 if (cnts%2) {
6120                         err = -EINVAL;
6121                         goto exit;
6122                 }
6123                 cnts /= 2;
6124                 if (cnts == 0) {
6125                         err = -EINVAL;
6126                         goto exit;
6127                 }
6128
6129                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6130                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6131                 DBG_88E("%s: raw data =%s\n", __func__, tmp[2]);
6132
6133                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6134                         setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6135
6136                 if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
6137                         DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
6138                         err = -EFAULT;
6139                         goto exit;
6140                 }
6141         } else if (strcmp(tmp[0], "mac") == 0) {
6142                 if (tmp[1] == NULL) {
6143                         err = -EINVAL;
6144                         goto exit;
6145                 }
6146
6147                 /* mac, 00e04c871200 */
6148                 addr = EEPROM_MAC_ADDR_88EU;
6149                 cnts = strlen(tmp[1]);
6150                 if (cnts%2) {
6151                         err = -EINVAL;
6152                         goto exit;
6153                 }
6154                 cnts /= 2;
6155                 if (cnts == 0) {
6156                         err = -EINVAL;
6157                         goto exit;
6158                 }
6159                 if (cnts > 6) {
6160                         DBG_88E("%s: error data for mac addr =\"%s\"\n", __func__, tmp[1]);
6161                         err = -EFAULT;
6162                         goto exit;
6163                 }
6164
6165                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6166                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6167                 DBG_88E("%s: MAC address =%s\n", __func__, tmp[1]);
6168
6169                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6170                         setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
6171                 /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
6172                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
6173                 if ((addr+cnts) > max_available_size) {
6174                         DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6175                         err = -EFAULT;
6176                         goto exit;
6177                 }
6178
6179                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6180                         DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6181                         err = -EFAULT;
6182                         goto exit;
6183                 }
6184         } else if (strcmp(tmp[0], "vidpid") == 0) {
6185                 if (tmp[1] == NULL) {
6186                         err = -EINVAL;
6187                         goto exit;
6188                 }
6189
6190                 /*  pidvid, da0b7881 */
6191                 addr = EEPROM_VID_88EE;
6192                 cnts = strlen(tmp[1]);
6193                 if (cnts%2) {
6194                         err = -EINVAL;
6195                         goto exit;
6196                 }
6197                 cnts /= 2;
6198                 if (cnts == 0) {
6199                         err = -EINVAL;
6200                         goto exit;
6201                 }
6202
6203                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6204                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6205                 DBG_88E("%s: VID/PID =%s\n", __func__, tmp[1]);
6206
6207                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6208                         setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
6209
6210                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6211                 if ((addr+cnts) > max_available_size) {
6212                         DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6213                         err = -EFAULT;
6214                         goto exit;
6215                 }
6216
6217                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6218                         DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6219                         err = -EFAULT;
6220                         goto exit;
6221                 }
6222         } else if (strcmp(tmp[0], "btwmap") == 0) {
6223                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6224                         err = -EINVAL;
6225                         goto exit;
6226                 }
6227
6228                 addr = simple_strtoul(tmp[1], &ptmp, 16);
6229                 addr &= 0xFFF;
6230
6231                 cnts = strlen(tmp[2]);
6232                 if (cnts%2) {
6233                         err = -EINVAL;
6234                         goto exit;
6235                 }
6236                 cnts /= 2;
6237                 if (cnts == 0) {
6238                         err = -EINVAL;
6239                         goto exit;
6240                 }
6241
6242                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6243                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6244                 DBG_88E("%s: BT data =%s\n", __func__, tmp[2]);
6245
6246                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6247                         setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6248
6249                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6250                 if ((addr+cnts) > max_available_size) {
6251                         DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6252                         err = -EFAULT;
6253                         goto exit;
6254                 }
6255
6256                 if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6257                         DBG_88E("%s: rtw_BT_efuse_map_write error!!\n", __func__);
6258                         err = -EFAULT;
6259                         goto exit;
6260                 }
6261         } else if (strcmp(tmp[0], "btwfake") == 0) {
6262                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6263                         err = -EINVAL;
6264                         goto exit;
6265                 }
6266
6267                 addr = simple_strtoul(tmp[1], &ptmp, 16);
6268                 addr &= 0xFFF;
6269
6270                 cnts = strlen(tmp[2]);
6271                 if (cnts%2) {
6272                         err = -EINVAL;
6273                         goto exit;
6274                 }
6275                 cnts /= 2;
6276                 if (cnts == 0) {
6277                         err = -EINVAL;
6278                         goto exit;
6279                 }
6280
6281                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6282                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6283                 DBG_88E("%s: BT tmp data =%s\n", __func__, tmp[2]);
6284
6285                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6286                         pEfuseHal->fakeBTEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6287         } else if (strcmp(tmp[0], "btdumpfake") == 0) {
6288                 if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS) {
6289                         DBG_88E("%s: BT read all map success\n", __func__);
6290                 } else {
6291                         DBG_88E("%s: BT read all map Fail!\n", __func__);
6292                         err = -EFAULT;
6293                 }
6294         } else if (strcmp(tmp[0], "wldumpfake") == 0) {
6295                 if (rtw_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN,  pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS) {
6296                         DBG_88E("%s: BT read all map success\n", __func__);
6297                 } else {
6298                         DBG_88E("%s: BT read all map  Fail\n", __func__);
6299                         err = -EFAULT;
6300                 }
6301         } else if (strcmp(tmp[0], "btfk2map") == 0) {
6302                 memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
6303
6304                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6305                 if (max_available_size < 1) {
6306                         err = -EFAULT;
6307                         goto exit;
6308                 }
6309
6310                 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) {
6311                         DBG_88E("%s: rtw_BT_efuse_map_write error!\n", __func__);
6312                         err = -EFAULT;
6313                         goto exit;
6314                 }
6315         } else if (strcmp(tmp[0], "wlfk2map") == 0) {
6316                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6317                 if (max_available_size < 1) {
6318                         err = -EFAULT;
6319                         goto exit;
6320                 }
6321
6322                 if (rtw_efuse_map_write(padapter, 0x00, EFUSE_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
6323                         DBG_88E("%s: rtw_efuse_map_write error!\n", __func__);
6324                         err = -EFAULT;
6325                         goto exit;
6326                 }
6327         } else if (strcmp(tmp[0], "wlwfake") == 0) {
6328                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6329                         err = -EINVAL;
6330                         goto exit;
6331                 }
6332
6333                 addr = simple_strtoul(tmp[1], &ptmp, 16);
6334                 addr &= 0xFFF;
6335
6336                 cnts = strlen(tmp[2]);
6337                 if (cnts%2) {
6338                         err = -EINVAL;
6339                         goto exit;
6340                 }
6341                 cnts /= 2;
6342                 if (cnts == 0) {
6343                         err = -EINVAL;
6344                         goto exit;
6345                 }
6346
6347                 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6348                 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6349                 DBG_88E("%s: map tmp data =%s\n", __func__, tmp[2]);
6350
6351                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6352                         pEfuseHal->fakeEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6353         }
6354
6355 exit:
6356         kfree(setdata);
6357         kfree(ShadowMapBT);
6358         kfree(ShadowMapWiFi);
6359         kfree(setrawdata);
6360
6361         rtw_pm_set_ips(padapter, ips_mode);
6362         rtw_pm_set_lps(padapter, lps_mode);
6363
6364         return err;
6365 }
6366
6367 /*
6368  * Input Format: %s,%d,%d
6369  *      %s is width, could be
6370  *              "b" for 1 byte
6371  *              "w" for WORD (2 bytes)
6372  *              "dw" for DWORD (4 bytes)
6373  *      1st %d is address(offset)
6374  *      2st %d is data to write
6375  */
6376 static int rtw_mp_write_reg(struct net_device *dev,
6377                         struct iw_request_info *info,
6378                         struct iw_point *wrqu, char *extra)
6379 {
6380         char *pch, *pnext, *ptmp;
6381         char *width_str;
6382         char width;
6383         u32 addr, data;
6384         int ret;
6385         struct adapter *padapter = rtw_netdev_priv(dev);
6386
6387         pch = extra;
6388         pnext = strpbrk(pch, ",.-");
6389         if (pnext == NULL)
6390                 return -EINVAL;
6391         *pnext = 0;
6392         width_str = pch;
6393
6394         pch = pnext + 1;
6395         pnext = strpbrk(pch, ",.-");
6396         if (pnext == NULL)
6397                 return -EINVAL;
6398         *pnext = 0;
6399         addr = simple_strtoul(pch, &ptmp, 16);
6400         if (addr > 0x3FFF)
6401                 return -EINVAL;
6402
6403         pch = pnext + 1;
6404         if ((pch - extra) >= wrqu->length)
6405                 return -EINVAL;
6406         data = simple_strtoul(pch, &ptmp, 16);
6407
6408         ret = 0;
6409         width = width_str[0];
6410         switch (width) {
6411         case 'b':
6412                 /*  1 byte */
6413                 if (data > 0xFF) {
6414                         ret = -EINVAL;
6415                         break;
6416                 }
6417                 rtw_write8(padapter, addr, data);
6418                 break;
6419         case 'w':
6420                 /*  2 bytes */
6421                 if (data > 0xFFFF) {
6422                         ret = -EINVAL;
6423                         break;
6424                 }
6425                 rtw_write16(padapter, addr, data);
6426                 break;
6427         case 'd':
6428                 /*  4 bytes */
6429                 rtw_write32(padapter, addr, data);
6430                 break;
6431         default:
6432                 ret = -EINVAL;
6433                 break;
6434         }
6435
6436         return ret;
6437 }
6438
6439 /*
6440  * Input Format: %s,%d
6441  *      %s is width, could be
6442  *              "b" for 1 byte
6443  *              "w" for WORD (2 bytes)
6444  *              "dw" for DWORD (4 bytes)
6445  *      %d is address(offset)
6446  *
6447  * Return:
6448  *      %d for data readed
6449  */
6450 static int rtw_mp_read_reg(struct net_device *dev,
6451                         struct iw_request_info *info,
6452                         struct iw_point *wrqu, char *extra)
6453 {
6454         struct adapter *padapter = rtw_netdev_priv(dev);
6455         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
6456         char *pch, *pnext, *ptmp;
6457         char *width_str;
6458         char width;
6459         char data[20], tmp[20];
6460         u32 addr;
6461         u32 ret, i = 0, j = 0, strtout = 0;
6462
6463         if (!input)
6464                 return -ENOMEM;
6465         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6466                 kfree(input);
6467                 return -EFAULT;
6468         }
6469         _rtw_memset(data, 0, 20);
6470         _rtw_memset(tmp, 0, 20);
6471         _rtw_memset(extra, 0, wrqu->length);
6472
6473         pch = input;
6474         pnext = strpbrk(pch, ",.-");
6475         if (pnext == NULL) {
6476                 kfree(input);
6477                 return -EINVAL;
6478         }
6479         *pnext = 0;
6480         width_str = pch;
6481
6482         pch = pnext + 1;
6483         if ((pch - input) >= wrqu->length) {
6484                 kfree(input);
6485                 return -EINVAL;
6486         }
6487         kfree(input);
6488         addr = simple_strtoul(pch, &ptmp, 16);
6489         if (addr > 0x3FFF)
6490                 return -EINVAL;
6491
6492         ret = 0;
6493         width = width_str[0];
6494         switch (width) {
6495         case 'b':
6496                 /*  1 byte */
6497                 sprintf(extra, "%d\n",  rtw_read8(padapter, addr));
6498                 wrqu->length = strlen(extra);
6499                 break;
6500         case 'w':
6501                 /*  2 bytes */
6502                 sprintf(data, "%04x\n", rtw_read16(padapter, addr));
6503                 for (i = 0; i <= strlen(data); i++) {
6504                         if (i%2 == 0) {
6505                                 tmp[j] = ' ';
6506                                 j++;
6507                         }
6508                         if (data[i] != '\0')
6509                                 tmp[j] = data[i];
6510                         j++;
6511                 }
6512                 pch = tmp;
6513                 DBG_88E("pch =%s", pch);
6514
6515                 while (*pch != '\0') {
6516                         pnext = strpbrk(pch, " ");
6517                         if (!pnext)
6518                                 break;
6519
6520                         pnext++;
6521                         if (*pnext != '\0') {
6522                                   strtout = simple_strtoul(pnext, &ptmp, 16);
6523                                   sprintf(extra, "%s %d", extra, strtout);
6524                         } else {
6525                                   break;
6526                         }
6527                         pch = pnext;
6528                 }
6529                 wrqu->length = 6;
6530                 break;
6531         case 'd':
6532                 /*  4 bytes */
6533                 sprintf(data, "%08x", rtw_read32(padapter, addr));
6534                 /* add read data format blank */
6535                 for (i = 0; i <= strlen(data); i++) {
6536                         if (i%2 == 0) {
6537                                 tmp[j] = ' ';
6538                                 j++;
6539                         }
6540                         if (data[i] != '\0')
6541                                 tmp[j] = data[i];
6542
6543                         j++;
6544                 }
6545                 pch = tmp;
6546                 DBG_88E("pch =%s", pch);
6547
6548                 while (*pch != '\0') {
6549                         pnext = strpbrk(pch, " ");
6550                         if (!pnext)
6551                                 break;
6552                         pnext++;
6553                         if (*pnext != '\0') {
6554                                 strtout = simple_strtoul(pnext, &ptmp, 16);
6555                                 sprintf(extra, "%s %d", extra, strtout);
6556                         } else {
6557                                 break;
6558                         }
6559                         pch = pnext;
6560                 }
6561                 wrqu->length = strlen(extra);
6562                 break;
6563         default:
6564                 wrqu->length = 0;
6565                 ret = -EINVAL;
6566                 break;
6567         }
6568
6569         return ret;
6570 }
6571
6572 /*
6573  * Input Format: %d,%x,%x
6574  *      %d is RF path, should be smaller than MAX_RF_PATH_NUMS
6575  *      1st %x is address(offset)
6576  *      2st %x is data to write
6577  */
6578  static int rtw_mp_write_rf(struct net_device *dev,
6579                             struct iw_request_info *info,
6580                             struct iw_point *wrqu, char *extra)
6581 {
6582         u32 path, addr, data;
6583         int ret;
6584         struct adapter *padapter = rtw_netdev_priv(dev);
6585
6586         ret = sscanf(extra, "%d,%x,%x", &path, &addr, &data);
6587         if (ret < 3)
6588                 return -EINVAL;
6589
6590         if (path >= MAX_RF_PATH_NUMS)
6591                 return -EINVAL;
6592         if (addr > 0xFF)
6593                 return -EINVAL;
6594         if (data > 0xFFFFF)
6595                 return -EINVAL;
6596
6597         _rtw_memset(extra, 0, wrqu->length);
6598
6599         write_rfreg(padapter, path, addr, data);
6600
6601         sprintf(extra, "write_rf completed\n");
6602         wrqu->length = strlen(extra);
6603
6604         return 0;
6605 }
6606
6607 /*
6608  * Input Format: %d,%x
6609  *      %d is RF path, should be smaller than MAX_RF_PATH_NUMS
6610  *      %x is address(offset)
6611  *
6612  * Return:
6613  *      %d for data readed
6614  */
6615 static int rtw_mp_read_rf(struct net_device *dev,
6616                         struct iw_request_info *info,
6617                         struct iw_point *wrqu, char *extra)
6618 {
6619         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
6620         char *pch, *pnext, *ptmp;
6621         char data[20], tmp[20];
6622         u32 path, addr;
6623         u32 ret, i = 0, j = 0, strtou = 0;
6624         struct adapter *padapter = rtw_netdev_priv(dev);
6625
6626         if (!input)
6627                 return -ENOMEM;
6628         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6629                 kfree(input);
6630                 return -EFAULT;
6631         }
6632         ret = sscanf(input, "%d,%x", &path, &addr);
6633         kfree(input);
6634         if (ret < 2)
6635                 return -EINVAL;
6636
6637         if (path >= MAX_RF_PATH_NUMS)
6638                 return -EINVAL;
6639         if (addr > 0xFF)
6640                 return -EINVAL;
6641
6642         _rtw_memset(extra, 0, wrqu->length);
6643
6644         sprintf(data, "%08x", read_rfreg(padapter, path, addr));
6645         /* add read data format blank */
6646         for (i = 0; i <= strlen(data); i++) {
6647                 if (i%2 == 0) {
6648                         tmp[j] = ' ';
6649                         j++;
6650                 }
6651                 tmp[j] = data[i];
6652                 j++;
6653         }
6654         pch = tmp;
6655         DBG_88E("pch =%s", pch);
6656
6657         while (*pch != '\0') {
6658                 pnext = strpbrk(pch, " ");
6659                 pnext++;
6660                 if (*pnext != '\0') {
6661                           strtou = simple_strtoul(pnext, &ptmp, 16);
6662                           sprintf(extra, "%s %d", extra, strtou);
6663                 } else {
6664                           break;
6665                 }
6666                 pch = pnext;
6667         }
6668         wrqu->length = strlen(extra);
6669         return 0;
6670 }
6671
6672 static int rtw_mp_start(struct net_device *dev,
6673                         struct iw_request_info *info,
6674                         struct iw_point *wrqu, char *extra)
6675 {
6676         struct adapter *padapter = rtw_netdev_priv(dev);
6677
6678         if (padapter->registrypriv.mp_mode == 0) {
6679                 padapter->registrypriv.mp_mode = 1;
6680
6681                 rtw_pm_set_ips(padapter, IPS_NONE);
6682                 LeaveAllPowerSaveMode(padapter);
6683
6684                 MPT_InitializeAdapter(padapter, 1);
6685         }
6686         if (padapter->registrypriv.mp_mode == 0)
6687                 return -EPERM;
6688         if (padapter->mppriv.mode == MP_OFF) {
6689                 if (mp_start_test(padapter) == _FAIL)
6690                         return -EPERM;
6691                 padapter->mppriv.mode = MP_ON;
6692         }
6693         return 0;
6694 }
6695
6696 static int rtw_mp_stop(struct net_device *dev,
6697                         struct iw_request_info *info,
6698                         struct iw_point *wrqu, char *extra)
6699 {
6700         struct adapter *padapter = rtw_netdev_priv(dev);
6701
6702         if (padapter->registrypriv.mp_mode == 1) {
6703                 MPT_DeInitAdapter(padapter);
6704                 padapter->registrypriv.mp_mode = 0;
6705         }
6706
6707         if (padapter->mppriv.mode != MP_OFF) {
6708                 mp_stop_test(padapter);
6709                 padapter->mppriv.mode = MP_OFF;
6710         }
6711
6712         return 0;
6713 }
6714
6715 extern int wifirate2_ratetbl_inx(unsigned char rate);
6716
6717 static int rtw_mp_rate(struct net_device *dev,
6718                         struct iw_request_info *info,
6719                         struct iw_point *wrqu, char *extra)
6720 {
6721         u32 rate = MPT_RATE_1M;
6722         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
6723         struct adapter *padapter = rtw_netdev_priv(dev);
6724
6725         if (!input)
6726                 return -ENOMEM;
6727         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6728                 kfree(input);
6729                 return -EFAULT;
6730         }
6731         rate = rtw_atoi(input);
6732         sprintf(extra, "Set data rate to %d", rate);
6733         kfree(input);
6734         if (rate <= 0x7f)
6735                 rate = wifirate2_ratetbl_inx((u8)rate);
6736         else
6737                 rate = (rate-0x80+MPT_RATE_MCS0);
6738
6739         if (rate >= MPT_RATE_LAST)
6740                 return -EINVAL;
6741
6742         padapter->mppriv.rateidx = rate;
6743         Hal_SetDataRate(padapter);
6744
6745         wrqu->length = strlen(extra) + 1;
6746         return 0;
6747 }
6748
6749 static int rtw_mp_channel(struct net_device *dev,
6750                         struct iw_request_info *info,
6751                         struct iw_point *wrqu, char *extra)
6752 {
6753         struct adapter *padapter = rtw_netdev_priv(dev);
6754         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
6755         u32     channel = 1;
6756
6757         if (!input)
6758                 return -ENOMEM;
6759         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6760                 kfree(input);
6761                 return -EFAULT;
6762         }
6763         channel = rtw_atoi(input);
6764         sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel, channel);
6765
6766         padapter->mppriv.channel = channel;
6767         Hal_SetChannel(padapter);
6768
6769         wrqu->length = strlen(extra) + 1;
6770         kfree(input);
6771         return 0;
6772 }
6773
6774 static int rtw_mp_bandwidth(struct net_device *dev,
6775                         struct iw_request_info *info,
6776                         struct iw_point *wrqu, char *extra)
6777 {
6778         u32 bandwidth = 0, sg = 0;
6779         struct adapter *padapter = rtw_netdev_priv(dev);
6780         int rv;
6781
6782         rv = sscanf(extra, "40M =%d, shortGI =%d", &bandwidth, &sg);
6783         if (rv != 2)
6784                 return -EINVAL;
6785
6786         if (bandwidth != HT_CHANNEL_WIDTH_40)
6787                 bandwidth = HT_CHANNEL_WIDTH_20;
6788
6789         padapter->mppriv.bandwidth = (u8)bandwidth;
6790         padapter->mppriv.preamble = sg;
6791
6792         SetBandwidth(padapter);
6793
6794         return 0;
6795 }
6796
6797 static int rtw_mp_txpower(struct net_device *dev,
6798                         struct iw_request_info *info,
6799                         struct iw_point *wrqu, char *extra)
6800 {
6801         u32             idx_a = 0, idx_b = 0;
6802         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
6803         struct adapter *padapter = rtw_netdev_priv(dev);
6804         int rv;
6805
6806         if (!input)
6807                 return -ENOMEM;
6808         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6809                 kfree(input);
6810                 return -EFAULT;
6811         }
6812         rv = sscanf(input, "patha =%d, pathb =%d", &idx_a, &idx_b);
6813         if (rv != 2) {
6814                 kfree(input);
6815                 return -EINVAL;
6816         }
6817
6818         sprintf(extra, "Set power level path_A:%d path_B:%d", idx_a, idx_b);
6819         padapter->mppriv.txpoweridx = (u8)idx_a;
6820         padapter->mppriv.txpoweridx_b = (u8)idx_b;
6821         padapter->mppriv.bSetTxPower = 1;
6822         Hal_SetAntennaPathPower(padapter);
6823
6824         wrqu->length = strlen(extra) + 1;
6825         kfree(input);
6826         return 0;
6827 }
6828
6829 static int rtw_mp_ant_tx(struct net_device *dev,
6830                         struct iw_request_info *info,
6831                         struct iw_point *wrqu, char *extra)
6832 {
6833         u8 i;
6834         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
6835         u16 antenna = 0;
6836         struct adapter *padapter = rtw_netdev_priv(dev);
6837
6838         if (!input)
6839                 return -ENOMEM;
6840         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6841                 kfree(input);
6842                 return -EFAULT;
6843         }
6844
6845         sprintf(extra, "switch Tx antenna to %s", input);
6846
6847         for (i = 0; i < strlen(input); i++) {
6848                 switch (input[i]) {
6849                 case 'a':
6850                         antenna |= ANTENNA_A;
6851                         break;
6852                 case 'b':
6853                         antenna |= ANTENNA_B;
6854                         break;
6855                 }
6856         }
6857         padapter->mppriv.antenna_tx = antenna;
6858
6859         Hal_SetAntenna(padapter);
6860
6861         wrqu->length = strlen(extra) + 1;
6862         kfree(input);
6863         return 0;
6864 }
6865
6866 static int rtw_mp_ant_rx(struct net_device *dev,
6867                         struct iw_request_info *info,
6868                         struct iw_point *wrqu, char *extra)
6869 {
6870         u8 i;
6871         u16 antenna = 0;
6872         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
6873         struct adapter *padapter = rtw_netdev_priv(dev);
6874
6875         if (!input)
6876                 return -ENOMEM;
6877         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6878                 kfree(input);
6879                 return -EFAULT;
6880         }
6881         _rtw_memset(extra, 0, wrqu->length);
6882
6883         sprintf(extra, "switch Rx antenna to %s", input);
6884
6885         for (i = 0; i < strlen(input); i++) {
6886                 switch (input[i]) {
6887                 case 'a':
6888                         antenna |= ANTENNA_A;
6889                         break;
6890                 case 'b':
6891                         antenna |= ANTENNA_B;
6892                         break;
6893                 }
6894         }
6895
6896         padapter->mppriv.antenna_rx = antenna;
6897         Hal_SetAntenna(padapter);
6898         wrqu->length = strlen(extra);
6899         kfree(input);
6900         return 0;
6901 }
6902
6903 static int rtw_mp_ctx(struct net_device *dev,
6904                         struct iw_request_info *info,
6905                         struct iw_point *wrqu, char *extra)
6906 {
6907         u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
6908         u32 bStartTest = 1;
6909         u32 count = 0;
6910         int rv;
6911         struct mp_priv *pmp_priv;
6912         struct pkt_attrib *pattrib;
6913
6914         struct adapter *padapter = rtw_netdev_priv(dev);
6915
6916         pmp_priv = &padapter->mppriv;
6917
6918         if (copy_from_user(extra, wrqu->pointer, wrqu->length))
6919                         return -EFAULT;
6920
6921         DBG_88E("%s: in =%s\n", __func__, extra);
6922
6923         countPkTx = strncmp(extra, "count =", 5); /*  strncmp true is 0 */
6924         cotuTx = strncmp(extra, "background", 20);
6925         CarrSprTx = strncmp(extra, "background, cs", 20);
6926         scTx = strncmp(extra, "background, sc", 20);
6927         sgleTx = strncmp(extra, "background, stone", 20);
6928         pkTx = strncmp(extra, "background, pkt", 20);
6929         stop = strncmp(extra, "stop", 4);
6930         rv = sscanf(extra, "count =%d, pkt", &count);
6931         if (rv != 2)
6932                 return -EINVAL;
6933
6934         _rtw_memset(extra, '\0', sizeof(*extra));
6935
6936         if (stop == 0) {
6937                 bStartTest = 0; /*  To set Stop */
6938                 pmp_priv->tx.stop = 1;
6939                 sprintf(extra, "Stop continuous Tx");
6940         } else {
6941                 bStartTest = 1;
6942                 if (pmp_priv->mode != MP_ON) {
6943                         if (pmp_priv->tx.stop != 1) {
6944                                 DBG_88E("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
6945                                 return  -EFAULT;
6946                         }
6947                 }
6948         }
6949
6950         if (pkTx == 0 || countPkTx == 0)
6951                 pmp_priv->mode = MP_PACKET_TX;
6952         if (sgleTx == 0)
6953                 pmp_priv->mode = MP_SINGLE_TONE_TX;
6954         if (cotuTx == 0)
6955                 pmp_priv->mode = MP_CONTINUOUS_TX;
6956         if (CarrSprTx == 0)
6957                 pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
6958         if (scTx == 0)
6959                 pmp_priv->mode = MP_SINGLE_CARRIER_TX;
6960
6961         switch (pmp_priv->mode) {
6962         case MP_PACKET_TX:
6963                 if (bStartTest == 0) {
6964                         pmp_priv->tx.stop = 1;
6965                         pmp_priv->mode = MP_ON;
6966                         sprintf(extra, "Stop continuous Tx");
6967                 } else if (pmp_priv->tx.stop == 1) {
6968                         sprintf(extra, "Start continuous DA = ffffffffffff len = 1500 count =%u,\n", count);
6969                         pmp_priv->tx.stop = 0;
6970                         pmp_priv->tx.count = count;
6971                         pmp_priv->tx.payload = 2;
6972                         pattrib = &pmp_priv->tx.attrib;
6973                         pattrib->pktlen = 1500;
6974                         _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
6975                         SetPacketTx(padapter);
6976                 } else {
6977                         return -EFAULT;
6978                 }
6979                         wrqu->length = strlen(extra);
6980                         return 0;
6981         case MP_SINGLE_TONE_TX:
6982                 if (bStartTest != 0)
6983                         sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6984                 Hal_SetSingleToneTx(padapter, (u8)bStartTest);
6985                 break;
6986         case MP_CONTINUOUS_TX:
6987                 if (bStartTest != 0)
6988                         sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6989                 Hal_SetContinuousTx(padapter, (u8)bStartTest);
6990                 break;
6991         case MP_CARRIER_SUPPRISSION_TX:
6992                 if (bStartTest != 0) {
6993                         if (pmp_priv->rateidx <= MPT_RATE_11M) {
6994                                 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6995                                 Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
6996                         } else {
6997                                 sprintf(extra, "Specify carrier suppression but not CCK rate");
6998                         }
6999                 }
7000                 break;
7001         case MP_SINGLE_CARRIER_TX:
7002                 if (bStartTest != 0)
7003                         sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
7004                 Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
7005                 break;
7006         default:
7007                 sprintf(extra, "Error! Continuous-Tx is not on-going.");
7008                 return -EFAULT;
7009         }
7010
7011         if (bStartTest == 1 && pmp_priv->mode != MP_ON) {
7012                 struct mp_priv *pmp_priv = &padapter->mppriv;
7013                 if (pmp_priv->tx.stop == 0) {
7014                         pmp_priv->tx.stop = 1;
7015                         msleep(5);
7016                 }
7017                 pmp_priv->tx.stop = 0;
7018                 pmp_priv->tx.count = 1;
7019                 SetPacketTx(padapter);
7020         } else {
7021                 pmp_priv->mode = MP_ON;
7022         }
7023
7024         wrqu->length = strlen(extra);
7025         return 0;
7026 }
7027
7028 static int rtw_mp_arx(struct net_device *dev,
7029                         struct iw_request_info *info,
7030                         struct iw_point *wrqu, char *extra)
7031 {
7032         u8 bStartRx = 0, bStopRx = 0, bQueryPhy;
7033         u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0;
7034         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
7035         struct adapter *padapter = rtw_netdev_priv(dev);
7036
7037         if (!input)
7038                 return -ENOMEM;
7039
7040         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7041                 kfree(input);
7042                 return -EFAULT;
7043         }
7044         DBG_88E("%s: %s\n", __func__, input);
7045
7046         bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /*  strncmp true is 0 */
7047         bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /*  strncmp true is 0 */
7048         bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /*  strncmp true is 0 */
7049
7050         if (bStartRx) {
7051                 sprintf(extra, "start");
7052                 SetPacketRx(padapter, bStartRx);
7053         } else if (bStopRx) {
7054                 SetPacketRx(padapter, 0);
7055                 sprintf(extra, "Received packet OK:%d CRC error:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount);
7056         } else if (bQueryPhy) {
7057                 /*
7058                 OFDM FA
7059                 RegCF0[15:0]
7060                 RegCF2[31:16]
7061                 RegDA0[31:16]
7062                 RegDA4[15:0]
7063                 RegDA4[31:16]
7064                 RegDA8[15:0]
7065                 CCK FA
7066                 (RegA5B<<8) | RegA5C
7067                 */
7068                 cckok = read_bbreg(padapter, 0xf88, 0xffffffff);
7069                 cckcrc = read_bbreg(padapter, 0xf84, 0xffffffff);
7070                 ofdmok = read_bbreg(padapter, 0xf94, 0x0000FFFF);
7071                 ofdmcrc = read_bbreg(padapter, 0xf94, 0xFFFF0000);
7072                 htok = read_bbreg(padapter, 0xf90, 0x0000FFFF);
7073                 htcrc = read_bbreg(padapter, 0xf90, 0xFFFF0000);
7074
7075                 OFDM_FA = read_bbreg(padapter, 0xcf0, 0x0000FFFF);
7076                 OFDM_FA = read_bbreg(padapter, 0xcf2, 0xFFFF0000);
7077                 OFDM_FA = read_bbreg(padapter, 0xda0, 0xFFFF0000);
7078                 OFDM_FA = read_bbreg(padapter, 0xda4, 0x0000FFFF);
7079                 OFDM_FA = read_bbreg(padapter, 0xda4, 0xFFFF0000);
7080                 OFDM_FA = read_bbreg(padapter, 0xda8, 0x0000FFFF);
7081                 CCK_FA = (rtw_read8(padapter, 0xa5b)<<8) | (rtw_read8(padapter, 0xa5c));
7082
7083                 sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", cckok+ofdmok+htok, cckcrc+ofdmcrc+htcrc, OFDM_FA+CCK_FA);
7084         }
7085         wrqu->length = strlen(extra) + 1;
7086         kfree(input);
7087         return 0;
7088 }
7089
7090 static int rtw_mp_trx_query(struct net_device *dev,
7091                         struct iw_request_info *info,
7092                         struct iw_point *wrqu, char *extra)
7093 {
7094         u32 txok, txfail, rxok, rxfail;
7095         struct adapter *padapter = rtw_netdev_priv(dev);
7096
7097         txok = padapter->mppriv.tx.sended;
7098         txfail = 0;
7099         rxok = padapter->mppriv.rx_pktcount;
7100         rxfail = padapter->mppriv.rx_crcerrpktcount;
7101
7102         _rtw_memset(extra, '\0', 128);
7103
7104         sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ", txok, txfail, rxok, rxfail);
7105
7106         wrqu->length = strlen(extra)+1;
7107
7108         return 0;
7109 }
7110
7111 static int rtw_mp_pwrtrk(struct net_device *dev,
7112                         struct iw_request_info *info,
7113                         struct iw_point *wrqu, char *extra)
7114 {
7115         u8 enable;
7116         u32 thermal;
7117         s32 ret;
7118         struct adapter *padapter = rtw_netdev_priv(dev);
7119         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
7120
7121         if (!input)
7122                 return -ENOMEM;
7123         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7124                 kfree(input);
7125                 return -EFAULT;
7126         }
7127         _rtw_memset(extra, 0, wrqu->length);
7128
7129         enable = 1;
7130         if (wrqu->length > 1) {/*  not empty string */
7131                 if (strncmp(input, "stop", 4) == 0) {
7132                         enable = 0;
7133                         sprintf(extra, "mp tx power tracking stop");
7134                 } else if (sscanf(input, "ther =%d", &thermal)) {
7135                                 ret = Hal_SetThermalMeter(padapter, (u8)thermal);
7136                                 if (ret == _FAIL)
7137                                         return -EPERM;
7138                                 sprintf(extra, "mp tx power tracking start, target value =%d ok ", thermal);
7139                 } else {
7140                         kfree(input);
7141                         return -EINVAL;
7142                 }
7143         }
7144
7145         kfree(input);
7146         ret = Hal_SetPowerTracking(padapter, enable);
7147         if (ret == _FAIL)
7148                 return -EPERM;
7149
7150         wrqu->length = strlen(extra);
7151         return 0;
7152 }
7153
7154 static int rtw_mp_psd(struct net_device *dev,
7155                         struct iw_request_info *info,
7156                         struct iw_point *wrqu, char *extra)
7157 {
7158         struct adapter *padapter = rtw_netdev_priv(dev);
7159         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
7160
7161         if (!input)
7162                 return -ENOMEM;
7163         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7164                 kfree(input);
7165                 return -EFAULT;
7166         }
7167
7168         strcpy(extra, input);
7169
7170         wrqu->length = mp_query_psd(padapter, extra);
7171         kfree(input);
7172         return 0;
7173 }
7174
7175 static int rtw_mp_thermal(struct net_device *dev,
7176                           struct iw_request_info *info,
7177                           struct iw_point *wrqu, char *extra)
7178 {
7179         u8 val;
7180         u16 bwrite = 1;
7181         u16 addr = EEPROM_THERMAL_METER_88E;
7182
7183         u16 cnt = 1;
7184         u16 max_available_size = 0;
7185         struct adapter *padapter = rtw_netdev_priv(dev);
7186
7187         if (copy_from_user(extra, wrqu->pointer, wrqu->length))
7188                 return -EFAULT;
7189
7190         bwrite = strncmp(extra, "write", 6); /*  strncmp true is 0 */
7191
7192         Hal_GetThermalMeter(padapter, &val);
7193
7194         if (bwrite == 0) {
7195                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
7196                 if (2 > max_available_size) {
7197                         DBG_88E("no available efuse!\n");
7198                         return -EFAULT;
7199                 }
7200                 if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) {
7201                         DBG_88E("rtw_efuse_map_write error\n");
7202                         return -EFAULT;
7203                 } else {
7204                          sprintf(extra, " efuse write ok :%d", val);
7205                 }
7206         } else {
7207                  sprintf(extra, "%d", val);
7208         }
7209         wrqu->length = strlen(extra);
7210
7211         return 0;
7212 }
7213
7214 static int rtw_mp_reset_stats(struct net_device *dev,
7215                         struct iw_request_info *info,
7216                         struct iw_point *wrqu, char *extra)
7217 {
7218         struct mp_priv *pmp_priv;
7219         struct adapter *padapter = rtw_netdev_priv(dev);
7220
7221         pmp_priv = &padapter->mppriv;
7222
7223         pmp_priv->tx.sended = 0;
7224         pmp_priv->tx_pktcount = 0;
7225         pmp_priv->rx_pktcount = 0;
7226         pmp_priv->rx_crcerrpktcount = 0;
7227
7228         /* reset phy counter */
7229         write_bbreg(padapter, 0xf14, BIT16, 0x1);
7230         msleep(10);
7231         write_bbreg(padapter, 0xf14, BIT16, 0x0);
7232
7233         return 0;
7234 }
7235
7236 static int rtw_mp_dump(struct net_device *dev,
7237                        struct iw_request_info *info,
7238                        struct iw_point *wrqu, char *extra)
7239 {
7240         u32 value;
7241         u8 rf_type, path_nums = 0;
7242         u32 i, j = 1, path;
7243         struct adapter *padapter = rtw_netdev_priv(dev);
7244
7245         if (strncmp(extra, "all", 4) == 0) {
7246                 DBG_88E("\n ======= MAC REG =======\n");
7247                 for (i = 0x0; i < 0x300; i += 4) {
7248                         if (j%4 == 1)
7249                                 DBG_88E("0x%02x", i);
7250                         DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
7251                         if ((j++)%4 == 0)
7252                                 DBG_88E("\n");
7253                 }
7254                 for (i = 0x400; i < 0x1000; i += 4) {
7255                         if (j%4 == 1)
7256                                 DBG_88E("0x%02x", i);
7257                         DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
7258                         if ((j++)%4 == 0)
7259                                 DBG_88E("\n");
7260                 }
7261
7262                 j = 1;
7263                 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
7264
7265                 DBG_88E("\n ======= RF REG =======\n");
7266                 if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
7267                         path_nums = 1;
7268                 else
7269                         path_nums = 2;
7270
7271                 for (path = 0; path < path_nums; path++) {
7272                         for (i = 0; i < 0x34; i++) {
7273                                 value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
7274                                 if (j%4 == 1)
7275                                         DBG_88E("0x%02x ", i);
7276                                 DBG_88E(" 0x%08x ", value);
7277                                 if ((j++)%4 == 0)
7278                                         DBG_88E("\n");
7279                         }
7280                 }
7281         }
7282         return 0;
7283 }
7284
7285 static int rtw_mp_phypara(struct net_device *dev,
7286                         struct iw_request_info *info,
7287                         struct iw_point *wrqu, char *extra)
7288 {
7289         char    *input = kmalloc(wrqu->length, GFP_KERNEL);
7290         u32             valxcap;
7291         int rv;
7292
7293         if (!input)
7294                 return -ENOMEM;
7295         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7296                 kfree(input);
7297                 return -EFAULT;
7298         }
7299
7300         DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7301
7302         rv = sscanf(input, "xcap =%d", &valxcap);
7303         if (rv != 1) {
7304                 kfree(input);
7305                 return -EINVAL;
7306         }
7307
7308         kfree(input);
7309         return 0;
7310 }
7311
7312 static int rtw_mp_SetRFPath(struct net_device *dev,
7313                         struct iw_request_info *info,
7314                         union iwreq_data *wrqu, char *extra)
7315 {
7316         struct adapter *padapter = rtw_netdev_priv(dev);
7317         char    *input = kmalloc(wrqu->data.length, GFP_KERNEL);
7318         u8 bMain = 1, bTurnoff = 1;
7319
7320         if (!input)
7321                 return -ENOMEM;
7322         if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
7323                         return -EFAULT;
7324         DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7325
7326         bMain = strncmp(input, "1", 2); /*  strncmp true is 0 */
7327         bTurnoff = strncmp(input, "0", 3); /*  strncmp true is 0 */
7328
7329         if (bMain == 0) {
7330                 MP_PHY_SetRFPathSwitch(padapter, true);
7331                 DBG_88E("%s:PHY_SetRFPathSwitch = true\n", __func__);
7332         } else if (bTurnoff == 0) {
7333                 MP_PHY_SetRFPathSwitch(padapter, false);
7334                 DBG_88E("%s:PHY_SetRFPathSwitch = false\n", __func__);
7335         }
7336         kfree(input);
7337         return 0;
7338 }
7339
7340 static int rtw_mp_QueryDrv(struct net_device *dev,
7341                         struct iw_request_info *info,
7342                         union iwreq_data *wrqu, char *extra)
7343 {
7344         struct adapter *padapter = rtw_netdev_priv(dev);
7345         char    *input = kmalloc(wrqu->data.length, GFP_KERNEL);
7346         u8 qAutoLoad = 1;
7347         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
7348
7349         if (!input)
7350                 return -ENOMEM;
7351
7352         if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
7353                         return -EFAULT;
7354         DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7355
7356         qAutoLoad = strncmp(input, "autoload", 8); /*  strncmp true is 0 */
7357
7358         if (qAutoLoad == 0) {
7359                 DBG_88E("%s:qAutoLoad\n", __func__);
7360
7361                 if (pEEPROM->bautoload_fail_flag)
7362                         sprintf(extra, "fail");
7363                 else
7364                 sprintf(extra, "ok");
7365         }
7366         wrqu->data.length = strlen(extra) + 1;
7367         kfree(input);
7368         return 0;
7369 }
7370
7371 static int rtw_mp_set(struct net_device *dev,
7372                       struct iw_request_info *info,
7373                       union iwreq_data *wdata, char *extra)
7374 {
7375         struct iw_point *wrqu = (struct iw_point *)wdata;
7376         u32 subcmd = wrqu->flags;
7377         struct adapter *padapter = rtw_netdev_priv(dev);
7378
7379         if (padapter == NULL)
7380                 return -ENETDOWN;
7381
7382         if (extra == NULL) {
7383                 wrqu->length = 0;
7384                 return -EIO;
7385         }
7386
7387         switch (subcmd) {
7388         case MP_START:
7389                 DBG_88E("set case mp_start\n");
7390                 rtw_mp_start(dev, info, wrqu, extra);
7391                  break;
7392         case MP_STOP:
7393                 DBG_88E("set case mp_stop\n");
7394                 rtw_mp_stop(dev, info, wrqu, extra);
7395                  break;
7396         case MP_BANDWIDTH:
7397                 DBG_88E("set case mp_bandwidth\n");
7398                 rtw_mp_bandwidth(dev, info, wrqu, extra);
7399                 break;
7400         case MP_RESET_STATS:
7401                 DBG_88E("set case MP_RESET_STATS\n");
7402                 rtw_mp_reset_stats(dev, info, wrqu, extra);
7403                 break;
7404         case MP_SetRFPathSwh:
7405                 DBG_88E("set MP_SetRFPathSwitch\n");
7406                 rtw_mp_SetRFPath(dev, info, wdata, extra);
7407                 break;
7408         case CTA_TEST:
7409                 DBG_88E("set CTA_TEST\n");
7410                 rtw_cta_test_start(dev, info, wdata, extra);
7411                 break;
7412         }
7413
7414         return 0;
7415 }
7416
7417 static int rtw_mp_get(struct net_device *dev,
7418                         struct iw_request_info *info,
7419                         union iwreq_data *wdata, char *extra)
7420 {
7421         struct iw_point *wrqu = (struct iw_point *)wdata;
7422         u32 subcmd = wrqu->flags;
7423         struct adapter *padapter = rtw_netdev_priv(dev);
7424
7425         if (padapter == NULL)
7426                 return -ENETDOWN;
7427         if (extra == NULL) {
7428                 wrqu->length = 0;
7429                 return -EIO;
7430         }
7431
7432         switch (subcmd) {
7433         case WRITE_REG:
7434                 rtw_mp_write_reg(dev, info, wrqu, extra);
7435                  break;
7436         case WRITE_RF:
7437                 rtw_mp_write_rf(dev, info, wrqu, extra);
7438                  break;
7439         case MP_PHYPARA:
7440                 DBG_88E("mp_get  MP_PHYPARA\n");
7441                 rtw_mp_phypara(dev, info, wrqu, extra);
7442                 break;
7443         case MP_CHANNEL:
7444                 DBG_88E("set case mp_channel\n");
7445                 rtw_mp_channel(dev, info, wrqu, extra);
7446                 break;
7447         case READ_REG:
7448                 DBG_88E("mp_get  READ_REG\n");
7449                 rtw_mp_read_reg(dev, info, wrqu, extra);
7450                  break;
7451         case READ_RF:
7452                 DBG_88E("mp_get  READ_RF\n");
7453                 rtw_mp_read_rf(dev, info, wrqu, extra);
7454                 break;
7455         case MP_RATE:
7456                 DBG_88E("set case mp_rate\n");
7457                 rtw_mp_rate(dev, info, wrqu, extra);
7458                 break;
7459         case MP_TXPOWER:
7460                 DBG_88E("set case MP_TXPOWER\n");
7461                 rtw_mp_txpower(dev, info, wrqu, extra);
7462                 break;
7463         case MP_ANT_TX:
7464                 DBG_88E("set case MP_ANT_TX\n");
7465                 rtw_mp_ant_tx(dev, info, wrqu, extra);
7466                 break;
7467         case MP_ANT_RX:
7468                 DBG_88E("set case MP_ANT_RX\n");
7469                 rtw_mp_ant_rx(dev, info, wrqu, extra);
7470                 break;
7471         case MP_QUERY:
7472                 rtw_mp_trx_query(dev, info, wrqu, extra);
7473                 break;
7474         case MP_CTX:
7475                 DBG_88E("set case MP_CTX\n");
7476                 rtw_mp_ctx(dev, info, wrqu, extra);
7477                 break;
7478         case MP_ARX:
7479                 DBG_88E("set case MP_ARX\n");
7480                 rtw_mp_arx(dev, info, wrqu, extra);
7481                 break;
7482         case EFUSE_GET:
7483                 DBG_88E("efuse get EFUSE_GET\n");
7484                 rtw_mp_efuse_get(dev, info, wdata, extra);
7485                  break;
7486         case MP_DUMP:
7487                 DBG_88E("set case MP_DUMP\n");
7488                 rtw_mp_dump(dev, info, wrqu, extra);
7489                  break;
7490         case MP_PSD:
7491                 DBG_88E("set case MP_PSD\n");
7492                 rtw_mp_psd(dev, info, wrqu, extra);
7493                 break;
7494         case MP_THER:
7495                 DBG_88E("set case MP_THER\n");
7496                 rtw_mp_thermal(dev, info, wrqu, extra);
7497                 break;
7498         case MP_QueryDrvStats:
7499                 DBG_88E("mp_get MP_QueryDrvStats\n");
7500                 rtw_mp_QueryDrv (dev, info, wdata, extra);
7501                 break;
7502         case MP_PWRTRK:
7503                 DBG_88E("set case MP_PWRTRK\n");
7504                 rtw_mp_pwrtrk(dev, info, wrqu, extra);
7505                 break;
7506         case EFUSE_SET:
7507                 DBG_88E("set case efuse set\n");
7508                 rtw_mp_efuse_set(dev, info, wdata, extra);
7509                 break;
7510         }
7511
7512         msleep(10); /* delay 5ms for sending pkt before exit adb shell operation */
7513         return 0;
7514 }
7515
7516 static int rtw_tdls(struct net_device *dev,
7517                     struct iw_request_info *info,
7518                     union iwreq_data *wrqu, char *extra)
7519 {
7520         return 0;
7521 }
7522
7523 static int rtw_tdls_get(struct net_device *dev,
7524                                 struct iw_request_info *info,
7525                                 union iwreq_data *wrqu, char *extra)
7526 {
7527         return 0;
7528 }
7529
7530 static int rtw_test(
7531         struct net_device *dev,
7532         struct iw_request_info *info,
7533         union iwreq_data *wrqu, char *extra)
7534 {
7535         u32 len;
7536         u8 *pbuf, *pch;
7537         char *ptmp;
7538         u8 *delim = ",";
7539
7540         DBG_88E("+%s\n", __func__);
7541         len = wrqu->data.length;
7542
7543         pbuf = (u8 *)rtw_zmalloc(len);
7544         if (pbuf == NULL) {
7545                 DBG_88E("%s: no memory!\n", __func__);
7546                 return -ENOMEM;
7547         }
7548
7549         if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
7550                 kfree(pbuf);
7551                 DBG_88E("%s: copy from user fail!\n", __func__);
7552                 return -EFAULT;
7553         }
7554         DBG_88E("%s: string =\"%s\"\n", __func__, pbuf);
7555
7556         ptmp = (char *)pbuf;
7557         pch = strsep(&ptmp, delim);
7558         if ((pch == NULL) || (strlen(pch) == 0)) {
7559                 kfree(pbuf);
7560                 DBG_88E("%s: parameter error(level 1)!\n", __func__);
7561                 return -EFAULT;
7562         }
7563         kfree(pbuf);
7564         return 0;
7565 }
7566
7567 static iw_handler rtw_handlers[] = {
7568         NULL,                                   /* SIOCSIWCOMMIT */
7569         rtw_wx_get_name,                /* SIOCGIWNAME */
7570         dummy,                                  /* SIOCSIWNWID */
7571         dummy,                                  /* SIOCGIWNWID */
7572         rtw_wx_set_freq,                /* SIOCSIWFREQ */
7573         rtw_wx_get_freq,                /* SIOCGIWFREQ */
7574         rtw_wx_set_mode,                /* SIOCSIWMODE */
7575         rtw_wx_get_mode,                /* SIOCGIWMODE */
7576         dummy,                                  /* SIOCSIWSENS */
7577         rtw_wx_get_sens,                /* SIOCGIWSENS */
7578         NULL,                                   /* SIOCSIWRANGE */
7579         rtw_wx_get_range,               /* SIOCGIWRANGE */
7580         rtw_wx_set_priv,                /* SIOCSIWPRIV */
7581         NULL,                                   /* SIOCGIWPRIV */
7582         NULL,                                   /* SIOCSIWSTATS */
7583         NULL,                                   /* SIOCGIWSTATS */
7584         dummy,                                  /* SIOCSIWSPY */
7585         dummy,                                  /* SIOCGIWSPY */
7586         NULL,                                   /* SIOCGIWTHRSPY */
7587         NULL,                                   /* SIOCWIWTHRSPY */
7588         rtw_wx_set_wap,         /* SIOCSIWAP */
7589         rtw_wx_get_wap,         /* SIOCGIWAP */
7590         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
7591         dummy,                                  /* SIOCGIWAPLIST -- depricated */
7592         rtw_wx_set_scan,                /* SIOCSIWSCAN */
7593         rtw_wx_get_scan,                /* SIOCGIWSCAN */
7594         rtw_wx_set_essid,               /* SIOCSIWESSID */
7595         rtw_wx_get_essid,               /* SIOCGIWESSID */
7596         dummy,                                  /* SIOCSIWNICKN */
7597         rtw_wx_get_nick,                /* SIOCGIWNICKN */
7598         NULL,                                   /* -- hole -- */
7599         NULL,                                   /* -- hole -- */
7600         rtw_wx_set_rate,                /* SIOCSIWRATE */
7601         rtw_wx_get_rate,                /* SIOCGIWRATE */
7602         rtw_wx_set_rts,                 /* SIOCSIWRTS */
7603         rtw_wx_get_rts,                 /* SIOCGIWRTS */
7604         rtw_wx_set_frag,                /* SIOCSIWFRAG */
7605         rtw_wx_get_frag,                /* SIOCGIWFRAG */
7606         dummy,                                  /* SIOCSIWTXPOW */
7607         dummy,                                  /* SIOCGIWTXPOW */
7608         dummy,                                  /* SIOCSIWRETRY */
7609         rtw_wx_get_retry,               /* SIOCGIWRETRY */
7610         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
7611         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
7612         dummy,                                  /* SIOCSIWPOWER */
7613         rtw_wx_get_power,               /* SIOCGIWPOWER */
7614         NULL,                                   /*---hole---*/
7615         NULL,                                   /*---hole---*/
7616         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
7617         NULL,                                   /* SIOCGWGENIE */
7618         rtw_wx_set_auth,                /* SIOCSIWAUTH */
7619         NULL,                                   /* SIOCGIWAUTH */
7620         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
7621         NULL,                                   /* SIOCGIWENCODEEXT */
7622         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
7623         NULL,                                   /*---hole---*/
7624 };
7625
7626 static const struct iw_priv_args rtw_private_args[] = {
7627         {
7628                 SIOCIWFIRSTPRIV + 0x0,
7629                 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
7630         },
7631         {
7632                 SIOCIWFIRSTPRIV + 0x1,
7633                 IW_PRIV_TYPE_CHAR | 0x7FF,
7634                 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
7635         },
7636         {
7637                 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
7638         },
7639         {
7640                 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
7641         },
7642         {
7643                 SIOCIWFIRSTPRIV + 0x4,
7644                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
7645         },
7646         {
7647                 SIOCIWFIRSTPRIV + 0x5,
7648                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
7649         },
7650         {
7651                 SIOCIWFIRSTPRIV + 0x6,
7652                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
7653         },
7654         {
7655                 SIOCIWFIRSTPRIV + 0x7,
7656                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
7657         },
7658         {
7659                 SIOCIWFIRSTPRIV + 0x8,
7660                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
7661         },
7662         {
7663                 SIOCIWFIRSTPRIV + 0x9,
7664                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
7665         },
7666
7667         {
7668                 SIOCIWFIRSTPRIV + 0xA,
7669                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
7670         },
7671
7672         {
7673                 SIOCIWFIRSTPRIV + 0xB,
7674                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
7675         },
7676         {
7677                 SIOCIWFIRSTPRIV + 0xC,
7678                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
7679         },
7680         {
7681                 SIOCIWFIRSTPRIV + 0xD,
7682                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
7683         },
7684         {
7685                 SIOCIWFIRSTPRIV + 0x10,
7686                 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
7687         },
7688         {
7689                 SIOCIWFIRSTPRIV + 0x11,
7690                 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get"
7691         },
7692         {
7693                 SIOCIWFIRSTPRIV + 0x12,
7694                 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2"
7695         },
7696         {SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0, "NULL"},
7697         {
7698                 SIOCIWFIRSTPRIV + 0x14,
7699                 IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
7700         },
7701         {
7702                 SIOCIWFIRSTPRIV + 0x15,
7703                 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "tdls_get"
7704         },
7705         {
7706                 SIOCIWFIRSTPRIV + 0x16,
7707                 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
7708         },
7709
7710         {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
7711
7712         {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
7713         {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
7714         {SIOCIWFIRSTPRIV + 0x1D, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
7715         },
7716
7717         {SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0, ""},  /* set */
7718         {SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, ""},/* get */
7719 /* --- sub-ioctls definitions --- */
7720
7721         {MP_START, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start"}, /* set */
7722         {MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara"},/* get */
7723         {MP_STOP, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop"}, /* set */
7724         {MP_CHANNEL, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel"},/* get */
7725         {MP_BANDWIDTH, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, /* set */
7726         {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},/* get */
7727         {MP_RESET_STATS, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
7728         {MP_QUERY, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_query"}, /* get */
7729         {READ_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg"},
7730         {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},
7731         {READ_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf"},
7732         {MP_PSD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
7733         {MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump"},
7734         {MP_TXPOWER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
7735         {MP_ANT_TX, IW_PRIV_TYPE_CHAR | 1024,  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
7736         {MP_ANT_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
7737         {WRITE_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg"},
7738         {WRITE_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf"},
7739         {MP_CTX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
7740         {MP_ARX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
7741         {MP_THER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
7742         {EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set"},
7743         {EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
7744         {MP_PWRTRK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
7745         {MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery"},
7746         {MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, /*  mp_ioctl */
7747         {MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath"},
7748         {CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
7749 };
7750
7751 static iw_handler rtw_private_handler[] = {
7752 rtw_wx_write32,                         /* 0x00 */
7753 rtw_wx_read32,                          /* 0x01 */
7754 rtw_drvext_hdl,                         /* 0x02 */
7755 rtw_mp_ioctl_hdl,                       /* 0x03 */
7756
7757 /*  for MM DTV platform */
7758         rtw_get_ap_info,                /* 0x04 */
7759
7760         rtw_set_pid,                    /* 0x05 */
7761         rtw_wps_start,                  /* 0x06 */
7762
7763         rtw_wx_get_sensitivity,         /* 0x07 */
7764         rtw_wx_set_mtk_wps_probe_ie,    /* 0x08 */
7765         rtw_wx_set_mtk_wps_ie,          /* 0x09 */
7766
7767 /*  Set Channel depend on the country code */
7768         rtw_wx_set_channel_plan,        /* 0x0A */
7769
7770         rtw_dbg_port,                   /* 0x0B */
7771         rtw_wx_write_rf,                /* 0x0C */
7772         rtw_wx_read_rf,                 /* 0x0D */
7773
7774         rtw_mp_set,                     /* 0x0E */
7775         rtw_mp_get,                     /* 0x0F */
7776         rtw_p2p_set,                    /* 0x10 */
7777         rtw_p2p_get,                    /* 0x11 */
7778         rtw_p2p_get2,                   /* 0x12 */
7779
7780         NULL,                           /* 0x13 */
7781         rtw_tdls,                       /* 0x14 */
7782         rtw_tdls_get,                   /* 0x15 */
7783
7784         rtw_pm_set,                     /* 0x16 */
7785         rtw_wx_priv_null,               /* 0x17 */
7786         rtw_rereg_nd_name,              /* 0x18 */
7787         rtw_wx_priv_null,               /* 0x19 */
7788
7789         rtw_mp_efuse_set,               /* 0x1A */
7790         rtw_mp_efuse_get,               /* 0x1B */
7791         NULL,                           /*  0x1C is reserved for hostapd */
7792         rtw_test,                       /*  0x1D */
7793 };
7794
7795 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
7796 {
7797         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
7798         struct iw_statistics *piwstats = &padapter->iwstats;
7799         int tmp_level = 0;
7800         int tmp_qual = 0;
7801         int tmp_noise = 0;
7802
7803         if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
7804                 piwstats->qual.qual = 0;
7805                 piwstats->qual.level = 0;
7806                 piwstats->qual.noise = 0;
7807         } else {
7808                 tmp_level = padapter->recvpriv.signal_strength;
7809                 tmp_qual = padapter->recvpriv.signal_qual;
7810                 tmp_noise = padapter->recvpriv.noise;
7811
7812                 piwstats->qual.level = tmp_level;
7813                 piwstats->qual.qual = tmp_qual;
7814                 piwstats->qual.noise = tmp_noise;
7815         }
7816         piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
7817         return &padapter->iwstats;
7818 }
7819
7820 struct iw_handler_def rtw_handlers_def = {
7821         .standard = rtw_handlers,
7822         .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
7823         .private = rtw_private_handler,
7824         .private_args = (struct iw_priv_args *)rtw_private_args,
7825         .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
7826         .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
7827         .get_wireless_stats = rtw_get_wireless_stats,
7828 };
7829
7830 /*  copy from net/wireless/wext.c start */
7831 /* ---------------------------------------------------------------- */
7832 /*
7833  * Calculate size of private arguments
7834  */
7835 static const char iw_priv_type_size[] = {
7836         0,                            /* IW_PRIV_TYPE_NONE */
7837         1,                            /* IW_PRIV_TYPE_BYTE */
7838         1,                            /* IW_PRIV_TYPE_CHAR */
7839         0,                            /* Not defined */
7840         sizeof(__u32),            /* IW_PRIV_TYPE_INT */
7841         sizeof(struct iw_freq),  /* IW_PRIV_TYPE_FLOAT */
7842         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
7843         0,                            /* Not defined */
7844 };
7845
7846 static int get_priv_size(__u16 args)
7847 {
7848         int num = args & IW_PRIV_SIZE_MASK;
7849         int type = (args & IW_PRIV_TYPE_MASK) >> 12;
7850
7851         return num * iw_priv_type_size[type];
7852 }
7853 /*  copy from net/wireless/wext.c end */
7854
7855 static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
7856 {
7857         int err = 0;
7858         u8 *input = NULL;
7859         u32 input_len = 0;
7860         const char delim[] = " ";
7861         u8 *output = NULL;
7862         u32 output_len = 0;
7863         u32 count = 0;
7864         u8 *buffer = NULL;
7865         u32 buffer_len = 0;
7866         char *ptr = NULL;
7867         u8 cmdname[17] = {0}; /*  IFNAMSIZ+1 */
7868         u32 cmdlen;
7869         s32 len;
7870         u8 *extra = NULL;
7871         u32 extra_size = 0;
7872         int rv;
7873
7874         s32 k;
7875         const iw_handler *priv;         /* Private ioctl */
7876         const struct iw_priv_args *priv_args;   /* Private ioctl description */
7877         u32 num_priv_args;                      /* Number of descriptions */
7878         iw_handler handler;
7879         int temp;
7880         int subcmd = 0;                         /* sub-ioctl index */
7881         int offset = 0;                         /* Space for sub-ioctl index */
7882
7883         union iwreq_data wdata;
7884
7885         memcpy(&wdata, wrq_data, sizeof(wdata));
7886
7887         input_len = wdata.data.length;
7888         input = rtw_zmalloc(input_len);
7889         if (NULL == input)
7890                 return -ENOMEM;
7891         if (copy_from_user(input, wdata.data.pointer, input_len)) {
7892                 err = -EFAULT;
7893                 goto exit;
7894         }
7895         ptr = input;
7896         len = input_len;
7897
7898         rv = sscanf(ptr, "%16s", cmdname);
7899         if (rv != 1) {
7900                 err = -EINVAL;
7901                 goto exit;
7902         }
7903         cmdlen = strlen(cmdname);
7904         DBG_88E("%s: cmd =%s\n", __func__, cmdname);
7905
7906         /*  skip command string */
7907         if (cmdlen > 0)
7908                 cmdlen += 1; /*  skip one space */
7909         ptr += cmdlen;
7910         len -= cmdlen;
7911         DBG_88E("%s: parameters =%s\n", __func__, ptr);
7912
7913         priv = rtw_private_handler;
7914         priv_args = rtw_private_args;
7915         num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
7916
7917         if (num_priv_args == 0) {
7918                 err = -EOPNOTSUPP;
7919                 goto exit;
7920         }
7921
7922         /* Search the correct ioctl */
7923         k = -1;
7924         while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
7925
7926         /* If not found... */
7927         if (k == num_priv_args) {
7928                 err = -EOPNOTSUPP;
7929                 goto exit;
7930         }
7931
7932         /* Watch out for sub-ioctls ! */
7933         if (priv_args[k].cmd < SIOCDEVPRIVATE) {
7934                 int j = -1;
7935
7936                 /* Find the matching *real* ioctl */
7937                 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
7938                         (priv_args[j].set_args != priv_args[k].set_args) ||
7939                         (priv_args[j].get_args != priv_args[k].get_args)));
7940
7941                 /* If not found... */
7942                 if (j == num_priv_args) {
7943                         err = -EINVAL;
7944                         goto exit;
7945                 }
7946
7947                 /* Save sub-ioctl number */
7948                 subcmd = priv_args[k].cmd;
7949                 /* Reserve one int (simplify alignment issues) */
7950                 offset = sizeof(__u32);
7951                 /* Use real ioctl definition from now on */
7952                 k = j;
7953         }
7954
7955         buffer = rtw_zmalloc(4096);
7956         if (NULL == buffer) {
7957                 err = -ENOMEM;
7958                 goto exit;
7959         }
7960
7961         /* If we have to set some data */
7962         if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
7963             (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
7964                 u8 *str;
7965
7966                 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
7967                 case IW_PRIV_TYPE_BYTE:
7968                         /* Fetch args */
7969                         count = 0;
7970                         do {
7971                                 str = strsep(&ptr, delim);
7972                                 if (NULL == str)
7973                                         break;
7974                                 sscanf(str, "%i", &temp);
7975                                 buffer[count++] = (u8)temp;
7976                         } while (1);
7977                         buffer_len = count;
7978                         /* Number of args to fetch */
7979                         wdata.data.length = count;
7980                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7981                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7982                         break;
7983                 case IW_PRIV_TYPE_INT:
7984                         /* Fetch args */
7985                         count = 0;
7986                         do {
7987                                 str = strsep(&ptr, delim);
7988                                 if (NULL == str)
7989                                         break;
7990                                 sscanf(str, "%i", &temp);
7991                                 ((s32 *)buffer)[count++] = (s32)temp;
7992                         } while (1);
7993                         buffer_len = count * sizeof(s32);
7994                         /* Number of args to fetch */
7995                         wdata.data.length = count;
7996                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7997                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7998                         break;
7999                 case IW_PRIV_TYPE_CHAR:
8000                         if (len > 0) {
8001                                 /* Size of the string to fetch */
8002                                 wdata.data.length = len;
8003                                 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
8004                                         wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
8005
8006                                 /* Fetch string */
8007                                 memcpy(buffer, ptr, wdata.data.length);
8008                         } else {
8009                                 wdata.data.length = 1;
8010                                 buffer[0] = '\0';
8011                         }
8012                         buffer_len = wdata.data.length;
8013                         break;
8014                 default:
8015                         DBG_88E("%s: Not yet implemented...\n", __func__);
8016                         err = -1;
8017                         goto exit;
8018                 }
8019
8020                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
8021                     (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
8022                         DBG_88E("%s: The command %s needs exactly %d argument(s)...\n",
8023                                 __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
8024                         err = -EINVAL;
8025                         goto exit;
8026                 }
8027         } else {
8028                 /* if args to set */
8029                 wdata.data.length = 0L;
8030         }
8031
8032         /* Those two tests are important. They define how the driver
8033         * will have to handle the data */
8034         if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
8035             ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
8036                 /* First case : all SET args fit within wrq */
8037                 if (offset)
8038                         wdata.mode = subcmd;
8039                 memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
8040         } else {
8041                 if ((priv_args[k].set_args == 0) &&
8042                     (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
8043                     (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
8044                         /* Second case : no SET args, GET args fit within wrq */
8045                         if (offset)
8046                                 wdata.mode = subcmd;
8047                 } else {
8048                         /* Third case : args won't fit in wrq, or variable number of args */
8049                         if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
8050                                 err = -EFAULT;
8051                                 goto exit;
8052                         }
8053                         wdata.data.flags = subcmd;
8054                 }
8055         }
8056
8057         kfree(input);
8058         input = NULL;
8059
8060         extra_size = 0;
8061         if (IW_IS_SET(priv_args[k].cmd)) {
8062                 /* Size of set arguments */
8063                 extra_size = get_priv_size(priv_args[k].set_args);
8064
8065                 /* Does it fits in iwr ? */
8066                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
8067                     ((extra_size + offset) <= IFNAMSIZ))
8068                         extra_size = 0;
8069         } else {
8070                 /* Size of get arguments */
8071                 extra_size = get_priv_size(priv_args[k].get_args);
8072
8073                 /* Does it fits in iwr ? */
8074                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
8075                     (extra_size <= IFNAMSIZ))
8076                         extra_size = 0;
8077         }
8078
8079         if (extra_size == 0) {
8080                 extra = (u8 *)&wdata;
8081                 kfree(buffer);
8082                 buffer = NULL;
8083         } else {
8084                 extra = buffer;
8085         }
8086
8087         handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
8088         err = handler(dev, NULL, &wdata, extra);
8089
8090         /* If we have to get some data */
8091         if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
8092             (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
8093                 int j;
8094                 int n = 0;      /* number of args */
8095                 u8 str[20] = {0};
8096
8097                 /* Check where is the returned data */
8098                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
8099                     (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
8100                         n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
8101                 else
8102                         n = wdata.data.length;
8103
8104                 output = rtw_zmalloc(4096);
8105                 if (NULL == output) {
8106                         err =  -ENOMEM;
8107                         goto exit;
8108                 }
8109                 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
8110                 case IW_PRIV_TYPE_BYTE:
8111                         /* Display args */
8112                         for (j = 0; j < n; j++) {
8113                                 sprintf(str, "%d  ", extra[j]);
8114                                 len = strlen(str);
8115                                 output_len = strlen(output);
8116                                 if ((output_len + len + 1) > 4096) {
8117                                         err = -E2BIG;
8118                                         goto exit;
8119                                 }
8120                                 memcpy(output+output_len, str, len);
8121                         }
8122                         break;
8123                 case IW_PRIV_TYPE_INT:
8124                         /* Display args */
8125                         for (j = 0; j < n; j++) {
8126                                 sprintf(str, "%d  ", ((__s32 *)extra)[j]);
8127                                 len = strlen(str);
8128                                 output_len = strlen(output);
8129                                 if ((output_len + len + 1) > 4096) {
8130                                         err = -E2BIG;
8131                                         goto exit;
8132                                 }
8133                                 memcpy(output+output_len, str, len);
8134                         }
8135                         break;
8136                 case IW_PRIV_TYPE_CHAR:
8137                         /* Display args */
8138                         memcpy(output, extra, n);
8139                         break;
8140                 default:
8141                         DBG_88E("%s: Not yet implemented...\n", __func__);
8142                         err = -1;
8143                         goto exit;
8144                 }
8145
8146                 output_len = strlen(output) + 1;
8147                 wrq_data->data.length = output_len;
8148                 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
8149                         err = -EFAULT;
8150                         goto exit;
8151                 }
8152         } else {
8153                 /* if args to set */
8154                 wrq_data->data.length = 0;
8155         }
8156
8157 exit:
8158         kfree(input);
8159         kfree(buffer);
8160         kfree(output);
8161         return err;
8162 }
8163
8164 #include <rtw_android.h>
8165 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
8166 {
8167         struct iwreq *wrq = (struct iwreq *)rq;
8168         int ret = 0;
8169
8170         switch (cmd) {
8171         case RTL_IOCTL_WPA_SUPPLICANT:
8172                 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
8173                 break;
8174 #ifdef CONFIG_88EU_AP_MODE
8175         case RTL_IOCTL_HOSTAPD:
8176                 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
8177                 break;
8178 #endif /*  CONFIG_88EU_AP_MODE */
8179         case SIOCDEVPRIVATE:
8180                 ret = rtw_ioctl_wext_private(dev, &wrq->u);
8181                 break;
8182         case (SIOCDEVPRIVATE+1):
8183                 ret = rtw_android_priv_cmd(dev, rq, cmd);
8184                 break;
8185         default:
8186                 ret = -EOPNOTSUPP;
8187                 break;
8188         }
8189         return ret;
8190 }