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