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