ioctl_linux.c revision f578b5d33ee721461921c8e79e5f8b309b2e604d
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		return -1;
2101	}
2102
2103	strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
2104
2105	if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2106		param->u.crypt.set_tx = 1;
2107
2108	/* cliW: WEP does not have group key
2109	 * just not checking GROUP key setting
2110	 */
2111	if ((pext->alg != IW_ENCODE_ALG_WEP) &&
2112	    (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
2113		param->u.crypt.set_tx = 0;
2114
2115	param->u.crypt.idx = (pencoding->flags&0x00FF) - 1;
2116
2117	if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
2118		memcpy(param->u.crypt.seq, pext->rx_seq, 8);
2119
2120	if (pext->key_len) {
2121		param->u.crypt.key_len = pext->key_len;
2122		memcpy(param->u.crypt.key, pext + 1, pext->key_len);
2123	}
2124
2125	ret =  wpa_set_encryption(dev, param, param_len);
2126
2127	kfree(param);
2128	return ret;
2129}
2130
2131static int rtw_wx_get_nick(struct net_device *dev,
2132			   struct iw_request_info *info,
2133			   union iwreq_data *wrqu, char *extra)
2134{
2135	if (extra) {
2136		wrqu->data.length = 14;
2137		wrqu->data.flags = 1;
2138		memcpy(extra, "<WIFI@REALTEK>", 14);
2139	}
2140
2141	/* dump debug info here */
2142	return 0;
2143}
2144
2145static int rtw_wx_read32(struct net_device *dev,
2146			    struct iw_request_info *info,
2147			    union iwreq_data *wrqu, char *extra)
2148{
2149	struct adapter *padapter;
2150	struct iw_point *p;
2151	u16 len;
2152	u32 addr;
2153	u32 data32;
2154	u32 bytes;
2155	u8 *ptmp;
2156
2157	padapter = (struct adapter *)rtw_netdev_priv(dev);
2158	p = &wrqu->data;
2159	len = p->length;
2160	ptmp = (u8 *)rtw_malloc(len);
2161	if (NULL == ptmp)
2162		return -ENOMEM;
2163
2164	if (copy_from_user(ptmp, p->pointer, len)) {
2165		kfree(ptmp);
2166		return -EFAULT;
2167	}
2168
2169	bytes = 0;
2170	addr = 0;
2171	sscanf(ptmp, "%d,%x", &bytes, &addr);
2172
2173	switch (bytes) {
2174	case 1:
2175		data32 = rtw_read8(padapter, addr);
2176		sprintf(extra, "0x%02X", data32);
2177		break;
2178	case 2:
2179		data32 = rtw_read16(padapter, addr);
2180		sprintf(extra, "0x%04X", data32);
2181		break;
2182	case 4:
2183		data32 = rtw_read32(padapter, addr);
2184		sprintf(extra, "0x%08X", data32);
2185		break;
2186	default:
2187		DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
2188		return -EINVAL;
2189	}
2190	DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
2191
2192	kfree(ptmp);
2193	return 0;
2194}
2195
2196static int rtw_wx_write32(struct net_device *dev,
2197			    struct iw_request_info *info,
2198			    union iwreq_data *wrqu, char *extra)
2199{
2200	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2201
2202	u32 addr;
2203	u32 data32;
2204	u32 bytes;
2205
2206	bytes = 0;
2207	addr = 0;
2208	data32 = 0;
2209	sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
2210
2211	switch (bytes) {
2212	case 1:
2213		rtw_write8(padapter, addr, (u8)data32);
2214		DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
2215		break;
2216	case 2:
2217		rtw_write16(padapter, addr, (u16)data32);
2218		DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
2219		break;
2220	case 4:
2221		rtw_write32(padapter, addr, data32);
2222		DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
2223		break;
2224	default:
2225		DBG_88E(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
2226		return -EINVAL;
2227	}
2228
2229	return 0;
2230}
2231
2232static int rtw_wx_read_rf(struct net_device *dev,
2233			    struct iw_request_info *info,
2234			    union iwreq_data *wrqu, char *extra)
2235{
2236	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2237	u32 path, addr, data32;
2238
2239	path = *(u32 *)extra;
2240	addr = *((u32 *)extra + 1);
2241	data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
2242	/*
2243	 * IMPORTANT!!
2244	 * Only when wireless private ioctl is at odd order,
2245	 * "extra" would be copied to user space.
2246	 */
2247	sprintf(extra, "0x%05x", data32);
2248
2249	return 0;
2250}
2251
2252static int rtw_wx_write_rf(struct net_device *dev,
2253			    struct iw_request_info *info,
2254			    union iwreq_data *wrqu, char *extra)
2255{
2256	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2257	u32 path, addr, data32;
2258
2259	path = *(u32 *)extra;
2260	addr = *((u32 *)extra + 1);
2261	data32 = *((u32 *)extra + 2);
2262	rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
2263
2264	return 0;
2265}
2266
2267static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
2268		 union iwreq_data *wrqu, char *b)
2269{
2270	return -1;
2271}
2272
2273static int dummy(struct net_device *dev, struct iw_request_info *a,
2274		 union iwreq_data *wrqu, char *b)
2275{
2276	return -1;
2277}
2278
2279static int rtw_wx_set_channel_plan(struct net_device *dev,
2280			       struct iw_request_info *info,
2281			       union iwreq_data *wrqu, char *extra)
2282{
2283	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2284	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2285	u8 channel_plan_req = (u8) (*((int *)wrqu));
2286
2287	if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1))
2288		DBG_88E("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan);
2289	else
2290		return -EPERM;
2291
2292	return 0;
2293}
2294
2295static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
2296		struct iw_request_info *a,
2297		union iwreq_data *wrqu, char *b)
2298{
2299	return 0;
2300}
2301
2302static int rtw_wx_get_sensitivity(struct net_device *dev,
2303				struct iw_request_info *info,
2304				union iwreq_data *wrqu, char *buf)
2305{
2306	return 0;
2307}
2308
2309static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
2310				struct iw_request_info *info,
2311				union iwreq_data *wrqu, char *extra)
2312{
2313	return 0;
2314}
2315
2316/*
2317 *	For all data larger than 16 octets, we need to use a
2318 *	pointer to memory allocated in user space.
2319 */
2320static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
2321						union iwreq_data *wrqu, char *extra)
2322{
2323	return 0;
2324}
2325
2326static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 len)
2327{
2328	struct mp_rw_reg *RegRWStruct;
2329	struct rf_reg_param *prfreg;
2330	u8 path;
2331	u8 offset;
2332	u32 value;
2333
2334	DBG_88E("%s\n", __func__);
2335
2336	switch (id) {
2337	case GEN_MP_IOCTL_SUBCODE(MP_START):
2338		DBG_88E("871x_driver is only for normal mode, can't enter mp mode\n");
2339		break;
2340	case GEN_MP_IOCTL_SUBCODE(READ_REG):
2341		RegRWStruct = (struct mp_rw_reg *)pdata;
2342		switch (RegRWStruct->width) {
2343		case 1:
2344			RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
2345			break;
2346		case 2:
2347			RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
2348			break;
2349		case 4:
2350			RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
2351			break;
2352		default:
2353			break;
2354		}
2355
2356		break;
2357	case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
2358		RegRWStruct = (struct mp_rw_reg *)pdata;
2359		switch (RegRWStruct->width) {
2360		case 1:
2361			rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
2362			break;
2363		case 2:
2364			rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
2365			break;
2366		case 4:
2367			rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
2368			break;
2369		default:
2370			break;
2371		}
2372
2373		break;
2374	case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
2375
2376		prfreg = (struct rf_reg_param *)pdata;
2377
2378		path = (u8)prfreg->path;
2379		offset = (u8)prfreg->offset;
2380
2381		value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
2382
2383		prfreg->value = value;
2384
2385		break;
2386	case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
2387
2388		prfreg = (struct rf_reg_param *)pdata;
2389
2390		path = (u8)prfreg->path;
2391		offset = (u8)prfreg->offset;
2392		value = prfreg->value;
2393
2394		rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
2395
2396		break;
2397	case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
2398		DBG_88E("==> trigger gpio 0\n");
2399		rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL);
2400		break;
2401	case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
2402		*pdata = rtw_hal_sreset_get_wifi_status(padapter);
2403		break;
2404	default:
2405		break;
2406	}
2407}
2408
2409static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
2410						union iwreq_data *wrqu, char *extra)
2411{
2412	int ret = 0;
2413	u32 BytesRead, BytesWritten, BytesNeeded;
2414	struct oid_par_priv	oid_par;
2415	struct mp_ioctl_handler	*phandler;
2416	struct mp_ioctl_param	*poidparam;
2417	uint status = 0;
2418	u16 len;
2419	u8 *pparmbuf = NULL, bset;
2420	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2421	struct iw_point *p = &wrqu->data;
2422
2423	if ((!p->length) || (!p->pointer)) {
2424		ret = -EINVAL;
2425		goto _rtw_mp_ioctl_hdl_exit;
2426	}
2427	pparmbuf = NULL;
2428	bset = (u8)(p->flags & 0xFFFF);
2429	len = p->length;
2430	pparmbuf = (u8 *)rtw_malloc(len);
2431	if (pparmbuf == NULL) {
2432		ret = -ENOMEM;
2433		goto _rtw_mp_ioctl_hdl_exit;
2434	}
2435
2436	if (copy_from_user(pparmbuf, p->pointer, len)) {
2437		ret = -EFAULT;
2438		goto _rtw_mp_ioctl_hdl_exit;
2439	}
2440
2441	poidparam = (struct mp_ioctl_param *)pparmbuf;
2442	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2443		 ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
2444		  poidparam->subcode, poidparam->len, len));
2445
2446	if (poidparam->subcode >= ARRAY_SIZE(mp_ioctl_hdl)) {
2447		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
2448		ret = -EINVAL;
2449		goto _rtw_mp_ioctl_hdl_exit;
2450	}
2451
2452	if (padapter->registrypriv.mp_mode == 1) {
2453		phandler = mp_ioctl_hdl + poidparam->subcode;
2454
2455		if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
2456			RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
2457				 ("no matching drvext param size %d vs %d\r\n",
2458				  poidparam->len, phandler->paramsize));
2459			ret = -EINVAL;
2460			goto _rtw_mp_ioctl_hdl_exit;
2461		}
2462
2463		if (phandler->handler) {
2464			oid_par.adapter_context = padapter;
2465			oid_par.oid = phandler->oid;
2466			oid_par.information_buf = poidparam->data;
2467			oid_par.information_buf_len = poidparam->len;
2468			oid_par.dbg = 0;
2469
2470			BytesWritten = 0;
2471			BytesNeeded = 0;
2472
2473			if (bset) {
2474				oid_par.bytes_rw = &BytesRead;
2475				oid_par.bytes_needed = &BytesNeeded;
2476				oid_par.type_of_oid = SET_OID;
2477			} else {
2478				oid_par.bytes_rw = &BytesWritten;
2479				oid_par.bytes_needed = &BytesNeeded;
2480				oid_par.type_of_oid = QUERY_OID;
2481			}
2482
2483			status = phandler->handler(&oid_par);
2484		} else {
2485			DBG_88E("rtw_mp_ioctl_hdl(): err!, subcode =%d, oid =%d, handler =%p\n",
2486				poidparam->subcode, phandler->oid, phandler->handler);
2487			ret = -EFAULT;
2488			goto _rtw_mp_ioctl_hdl_exit;
2489		}
2490	} else {
2491		rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
2492	}
2493
2494	if (bset == 0x00) {/* query info */
2495		if (copy_to_user(p->pointer, pparmbuf, len))
2496			ret = -EFAULT;
2497	}
2498
2499	if (status) {
2500		ret = -EFAULT;
2501		goto _rtw_mp_ioctl_hdl_exit;
2502	}
2503
2504_rtw_mp_ioctl_hdl_exit:
2505
2506	kfree(pparmbuf);
2507	return ret;
2508}
2509
2510static int rtw_get_ap_info(struct net_device *dev,
2511			       struct iw_request_info *info,
2512			       union iwreq_data *wrqu, char *extra)
2513{
2514	int ret = 0;
2515	u32 cnt = 0, wpa_ielen;
2516	struct list_head *plist, *phead;
2517	unsigned char *pbuf;
2518	u8 bssid[ETH_ALEN];
2519	char data[32];
2520	struct wlan_network *pnetwork = NULL;
2521	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2522	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2523	struct __queue *queue = &(pmlmepriv->scanned_queue);
2524	struct iw_point *pdata = &wrqu->data;
2525
2526	DBG_88E("+rtw_get_aplist_info\n");
2527
2528	if ((padapter->bDriverStopped) || (pdata == NULL)) {
2529		ret = -EINVAL;
2530		goto exit;
2531	}
2532
2533	while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) {
2534		msleep(30);
2535		cnt++;
2536		if (cnt > 100)
2537			break;
2538	}
2539	pdata->flags = 0;
2540	if (pdata->length >= 32) {
2541		if (copy_from_user(data, pdata->pointer, 32)) {
2542			ret = -EINVAL;
2543			goto exit;
2544		}
2545	} else {
2546		ret = -EINVAL;
2547		goto exit;
2548	}
2549
2550	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2551
2552	phead = get_list_head(queue);
2553	plist = phead->next;
2554
2555	while (1) {
2556		if (rtw_end_of_queue_search(phead, plist) == true)
2557			break;
2558
2559		pnetwork = container_of(plist, struct wlan_network, list);
2560
2561		if (hwaddr_aton_i(data, bssid)) {
2562			DBG_88E("Invalid BSSID '%s'.\n", (u8 *)data);
2563			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2564			return -EINVAL;
2565		}
2566
2567		if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2568			/* BSSID match, then check if supporting wpa/wpa2 */
2569			DBG_88E("BSSID:%pM\n", (bssid));
2570
2571			pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2572			if (pbuf && (wpa_ielen > 0)) {
2573				pdata->flags = 1;
2574				break;
2575			}
2576
2577			pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2578			if (pbuf && (wpa_ielen > 0)) {
2579				pdata->flags = 2;
2580				break;
2581			}
2582		}
2583
2584		plist = plist->next;
2585	}
2586
2587	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2588
2589	if (pdata->length >= 34) {
2590		if (copy_to_user(pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
2591			ret = -EINVAL;
2592			goto exit;
2593		}
2594	}
2595
2596exit:
2597
2598	return ret;
2599}
2600
2601static int rtw_set_pid(struct net_device *dev,
2602			       struct iw_request_info *info,
2603			       union iwreq_data *wrqu, char *extra)
2604{
2605	int ret = 0;
2606	struct adapter *padapter = rtw_netdev_priv(dev);
2607	int *pdata = (int *)wrqu;
2608	int selector;
2609
2610	if ((padapter->bDriverStopped) || (pdata == NULL)) {
2611		ret = -EINVAL;
2612		goto exit;
2613	}
2614
2615	selector = *pdata;
2616	if (selector < 3 && selector >= 0) {
2617		padapter->pid[selector] = *(pdata+1);
2618		ui_pid[selector] = *(pdata+1);
2619		DBG_88E("%s set pid[%d] =%d\n", __func__, selector, padapter->pid[selector]);
2620	} else {
2621		DBG_88E("%s selector %d error\n", __func__, selector);
2622	}
2623exit:
2624	return ret;
2625}
2626
2627static int rtw_wps_start(struct net_device *dev,
2628			 struct iw_request_info *info,
2629			 union iwreq_data *wrqu, char *extra)
2630{
2631	int ret = 0;
2632	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2633	struct iw_point *pdata = &wrqu->data;
2634	u32   u32wps_start = 0;
2635
2636	ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
2637	if (ret) {
2638		ret = -EINVAL;
2639		goto exit;
2640	}
2641
2642	if ((padapter->bDriverStopped) || (pdata == NULL)) {
2643		ret = -EINVAL;
2644		goto exit;
2645	}
2646
2647	if (u32wps_start == 0)
2648		u32wps_start = *extra;
2649
2650	DBG_88E("[%s] wps_start = %d\n", __func__, u32wps_start);
2651
2652	if (u32wps_start == 1) /*  WPS Start */
2653		rtw_led_control(padapter, LED_CTL_START_WPS);
2654	else if (u32wps_start == 2) /*  WPS Stop because of wps success */
2655		rtw_led_control(padapter, LED_CTL_STOP_WPS);
2656	else if (u32wps_start == 3) /*  WPS Stop because of wps fail */
2657		rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
2658
2659exit:
2660	return ret;
2661}
2662
2663#ifdef CONFIG_88EU_P2P
2664static int rtw_wext_p2p_enable(struct net_device *dev,
2665			       struct iw_request_info *info,
2666			       union iwreq_data *wrqu, char *extra)
2667{
2668	int ret = 0;
2669	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2670	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2671	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
2672	enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
2673
2674	if (*extra == '0')
2675		init_role = P2P_ROLE_DISABLE;
2676	else if (*extra == '1')
2677		init_role = P2P_ROLE_DEVICE;
2678	else if (*extra == '2')
2679		init_role = P2P_ROLE_CLIENT;
2680	else if (*extra == '3')
2681		init_role = P2P_ROLE_GO;
2682
2683	if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
2684		ret = -EFAULT;
2685		goto exit;
2686	}
2687
2688	/* set channel/bandwidth */
2689	if (init_role != P2P_ROLE_DISABLE) {
2690		u8 channel, ch_offset;
2691		u16 bwmode;
2692
2693		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
2694			/*	Stay at the listen state and wait for discovery. */
2695			channel = pwdinfo->listen_channel;
2696			pwdinfo->operating_channel = pwdinfo->listen_channel;
2697			ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2698			bwmode = HT_CHANNEL_WIDTH_20;
2699		} else {
2700			pwdinfo->operating_channel = pmlmeext->cur_channel;
2701
2702			channel = pwdinfo->operating_channel;
2703			ch_offset = pmlmeext->cur_ch_offset;
2704			bwmode = pmlmeext->cur_bwmode;
2705		}
2706
2707		set_channel_bwmode(padapter, channel, ch_offset, bwmode);
2708	}
2709
2710exit:
2711	return ret;
2712}
2713
2714static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
2715			       struct iw_request_info *info,
2716			       union iwreq_data *wrqu, char *extra)
2717{
2718	int ret = 0;
2719	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2720	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2721
2722	DBG_88E("[%s] ssid = %s, len = %zu\n", __func__, extra, strlen(extra));
2723	memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
2724	pwdinfo->nego_ssidlen = strlen(extra);
2725
2726	return ret;
2727}
2728
2729static int rtw_p2p_set_intent(struct net_device *dev,
2730			      struct iw_request_info *info,
2731			      union iwreq_data *wrqu, char *extra)
2732{
2733	int ret = 0;
2734	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2735	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2736	u8 intent = pwdinfo->intent;
2737
2738	switch (wrqu->data.length) {
2739	case 1:
2740		intent = extra[0] - '0';
2741		break;
2742	case 2:
2743		intent = str_2char2num(extra[0], extra[1]);
2744		break;
2745	}
2746	if (intent <= 15)
2747		pwdinfo->intent = intent;
2748	else
2749		ret = -1;
2750	DBG_88E("[%s] intent = %d\n", __func__, intent);
2751	return ret;
2752}
2753
2754static int rtw_p2p_set_listen_ch(struct net_device *dev,
2755			       struct iw_request_info *info,
2756			       union iwreq_data *wrqu, char *extra)
2757{
2758	int ret = 0;
2759	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2760	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2761	u8 listen_ch = pwdinfo->listen_channel;	/*	Listen channel number */
2762
2763	switch (wrqu->data.length) {
2764	case 1:
2765		listen_ch = extra[0] - '0';
2766		break;
2767	case 2:
2768		listen_ch = str_2char2num(extra[0], extra[1]);
2769		break;
2770	}
2771
2772	if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
2773		pwdinfo->listen_channel = listen_ch;
2774		set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2775	} else {
2776		ret = -1;
2777	}
2778
2779	DBG_88E("[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel);
2780
2781	return ret;
2782}
2783
2784static int rtw_p2p_set_op_ch(struct net_device *dev,
2785			       struct iw_request_info *info,
2786			       union iwreq_data *wrqu, char *extra)
2787{
2788/*	Commented by Albert 20110524 */
2789/*	This function is used to set the operating channel if the driver will become the group owner */
2790
2791	int ret = 0;
2792	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2793	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2794	u8 op_ch = pwdinfo->operating_channel;	/*	Operating channel number */
2795
2796	switch (wrqu->data.length) {
2797	case 1:
2798		op_ch = extra[0] - '0';
2799		break;
2800	case 2:
2801		op_ch = str_2char2num(extra[0], extra[1]);
2802		break;
2803	}
2804
2805	if (op_ch > 0)
2806		pwdinfo->operating_channel = op_ch;
2807	else
2808		ret = -1;
2809
2810	DBG_88E("[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel);
2811
2812	return ret;
2813}
2814
2815static int rtw_p2p_profilefound(struct net_device *dev,
2816			       struct iw_request_info *info,
2817			       union iwreq_data *wrqu, char *extra)
2818{
2819	int ret = 0;
2820	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2821	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2822
2823	/*	Comment by Albert 2010/10/13 */
2824	/*	Input data format: */
2825	/*	Ex:  0 */
2826	/*	Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
2827	/*	0 => Reflush the profile record list. */
2828	/*	1 => Add the profile list */
2829	/*	XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */
2830	/*	YY => SSID Length */
2831	/*	SSID => SSID for persistence group */
2832
2833	DBG_88E("[%s] In value = %s, len = %d\n", __func__, extra, wrqu->data.length - 1);
2834
2835	/*	The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
2836		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
2837			if (extra[0] == '0') {
2838			/*	Remove all the profile information of wifidirect_info structure. */
2839			_rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
2840			pwdinfo->profileindex = 0;
2841		} else {
2842			if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) {
2843				ret = -1;
2844			} else {
2845				int jj, kk;
2846
2847				/*	Add this profile information into pwdinfo->profileinfo */
2848				/*	Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
2849				for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
2850					pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2851
2852				pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0');
2853				memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen);
2854				pwdinfo->profileindex++;
2855			}
2856		}
2857	}
2858
2859	return ret;
2860}
2861
2862static int rtw_p2p_setDN(struct net_device *dev,
2863			       struct iw_request_info *info,
2864			       union iwreq_data *wrqu, char *extra)
2865{
2866	int ret = 0;
2867	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2868	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2869
2870	DBG_88E("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
2871	_rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
2872	memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
2873	pwdinfo->device_name_len = wrqu->data.length - 1;
2874
2875	return ret;
2876}
2877
2878static int rtw_p2p_get_status(struct net_device *dev,
2879			       struct iw_request_info *info,
2880			       union iwreq_data *wrqu, char *extra)
2881{
2882	int ret = 0;
2883	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2884	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2885
2886	if (padapter->bShowGetP2PState)
2887		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),
2888			pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
2889			pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
2890
2891	/*	Commented by Albert 2010/10/12 */
2892	/*	Because of the output size limitation, I had removed the "Role" information. */
2893	/*	About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
2894	sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo));
2895	wrqu->data.length = strlen(extra);
2896
2897	return ret;
2898}
2899
2900/*	Commented by Albert 20110520 */
2901/*	This function will return the config method description */
2902/*	This config method description will show us which config method the remote P2P device is intended to use */
2903/*	by sending the provisioning discovery request frame. */
2904
2905static int rtw_p2p_get_req_cm(struct net_device *dev,
2906			       struct iw_request_info *info,
2907			       union iwreq_data *wrqu, char *extra)
2908{
2909	int ret = 0;
2910	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2911	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2912
2913	sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
2914	wrqu->data.length = strlen(extra);
2915	return ret;
2916}
2917
2918static int rtw_p2p_get_role(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	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),
2927			pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
2928			pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
2929
2930	sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo));
2931	wrqu->data.length = strlen(extra);
2932	return ret;
2933}
2934
2935static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
2936			       struct iw_request_info *info,
2937			       union iwreq_data *wrqu, char *extra)
2938{
2939	int ret = 0;
2940	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2941	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2942
2943	DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
2944		rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2945		pwdinfo->p2p_peer_interface_addr);
2946	sprintf(extra, "\nMAC %pM",
2947		pwdinfo->p2p_peer_interface_addr);
2948	wrqu->data.length = strlen(extra);
2949	return ret;
2950}
2951
2952static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
2953			       struct iw_request_info *info,
2954			       union iwreq_data *wrqu, char *extra)
2955
2956{
2957	int ret = 0;
2958	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2959	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2960
2961	DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
2962		rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2963		pwdinfo->rx_prov_disc_info.peerDevAddr);
2964	sprintf(extra, "\n%pM",
2965		pwdinfo->rx_prov_disc_info.peerDevAddr);
2966	wrqu->data.length = strlen(extra);
2967	return ret;
2968}
2969
2970static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
2971			       struct iw_request_info *info,
2972			       union iwreq_data *wrqu, char *extra)
2973
2974{
2975	int ret = 0;
2976	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2977	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2978
2979	DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n",
2980		__func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2981		pwdinfo->p2p_peer_device_addr);
2982	sprintf(extra, "\nMAC %pM",
2983		pwdinfo->p2p_peer_device_addr);
2984	wrqu->data.length = strlen(extra);
2985	return ret;
2986}
2987
2988static int rtw_p2p_get_groupid(struct net_device *dev,
2989			       struct iw_request_info *info,
2990			       union iwreq_data *wrqu, char *extra)
2991
2992{
2993	int ret = 0;
2994	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2995	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2996
2997	sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
2998		pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
2999		pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
3000		pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
3001		pwdinfo->groupid_info.ssid);
3002	wrqu->data.length = strlen(extra);
3003	return ret;
3004}
3005
3006static int rtw_p2p_get_op_ch(struct net_device *dev,
3007			       struct iw_request_info *info,
3008			       union iwreq_data *wrqu, char *extra)
3009
3010{
3011	int ret = 0;
3012	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3013	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3014
3015	DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
3016
3017	sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel);
3018	wrqu->data.length = strlen(extra);
3019	return ret;
3020}
3021
3022static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
3023			       struct iw_request_info *info,
3024			       union iwreq_data *wrqu, char *extra)
3025{
3026	int ret = 0;
3027	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3028	u8 peerMAC[ETH_ALEN] = {0x00};
3029	int jj, kk;
3030	u8 peerMACStr[17] = {0x00};
3031	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3032	struct list_head *plist, *phead;
3033	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3034	struct	wlan_network	*pnetwork = NULL;
3035	u8 blnMatch = 0;
3036	u16	attr_content = 0;
3037	uint attr_contentlen = 0;
3038	/* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
3039	u8 attr_content_str[6 + 17] = {0x00};
3040
3041	/*	Commented by Albert 20110727 */
3042	/*	The input data is the MAC address which the application wants to know its WPS config method. */
3043	/*	After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
3044	/*	Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
3045
3046	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3047	if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17))
3048		return -EFAULT;
3049
3050	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3051		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3052
3053	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3054
3055	phead = get_list_head(queue);
3056	plist = phead->next;
3057
3058	while (1) {
3059		if (rtw_end_of_queue_search(phead, plist) == true)
3060			break;
3061
3062		pnetwork = container_of(plist, struct wlan_network, list);
3063		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3064			u8 *wpsie;
3065			uint wpsie_len = 0;
3066			__be16 be_tmp;
3067
3068			/*  The mac address is matched. */
3069			wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
3070			if (wpsie) {
3071				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen);
3072				if (attr_contentlen) {
3073					attr_content = be16_to_cpu(be_tmp);
3074					sprintf(attr_content_str, "\n\nM =%.4d", attr_content);
3075					blnMatch = 1;
3076				}
3077			}
3078			break;
3079		}
3080		plist = plist->next;
3081	}
3082
3083	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3084
3085	if (!blnMatch)
3086		sprintf(attr_content_str, "\n\nM = 0000");
3087
3088	if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
3089		return -EFAULT;
3090	return ret;
3091}
3092
3093static int rtw_p2p_get_go_device_address(struct net_device *dev,
3094			       struct iw_request_info *info,
3095			       union iwreq_data *wrqu, char *extra)
3096{
3097	int ret = 0;
3098	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3099	u8 peerMAC[ETH_ALEN] = {0x00};
3100	int jj, kk;
3101	u8 peerMACStr[17] = {0x00};
3102	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3103	struct list_head *plist, *phead;
3104	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3105	struct	wlan_network	*pnetwork = NULL;
3106	u8 blnMatch = 0;
3107	u8 *p2pie;
3108	uint p2pielen = 0, attr_contentlen = 0;
3109	u8 attr_content[100] = {0x00};
3110	u8 go_devadd_str[17 + 12] = {};
3111
3112	/*	Commented by Albert 20121209 */
3113	/*	The input data is the GO's interface address which the application wants to know its device address. */
3114	/*	Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */
3115
3116	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3117	if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17))
3118		return -EFAULT;
3119
3120	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3121		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3122
3123	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3124
3125	phead = get_list_head(queue);
3126	plist = phead->next;
3127
3128	while (1) {
3129		if (rtw_end_of_queue_search(phead, plist) == true)
3130			break;
3131
3132		pnetwork = container_of(plist, struct wlan_network, list);
3133		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3134			/*	Commented by Albert 2011/05/18 */
3135			/*	Match the device address located in the P2P IE */
3136			/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
3137
3138			p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3139			if (p2pie) {
3140				while (p2pie) {
3141					/*	The P2P Device ID attribute is included in the Beacon frame. */
3142					/*	The P2P Device Info attribute is included in the probe response frame. */
3143
3144					_rtw_memset(attr_content, 0x00, 100);
3145					if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3146						/*	Handle the P2P Device ID attribute of Beacon first */
3147						blnMatch = 1;
3148						break;
3149					} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3150						/*	Handle the P2P Device Info attribute of probe response */
3151						blnMatch = 1;
3152						break;
3153					}
3154
3155					/* Get the next P2P IE */
3156					p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3157				}
3158			}
3159	     }
3160
3161		plist = plist->next;
3162	}
3163
3164	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3165
3166	if (!blnMatch)
3167		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL");
3168	else
3169		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
3170			attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
3171
3172	if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
3173		return -EFAULT;
3174	return ret;
3175}
3176
3177static int rtw_p2p_get_device_type(struct net_device *dev,
3178			       struct iw_request_info *info,
3179			       union iwreq_data *wrqu, char *extra)
3180{
3181	int ret = 0;
3182	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3183	u8 peerMAC[ETH_ALEN] = {0x00};
3184	int jj, kk;
3185	u8 peerMACStr[17] = {0x00};
3186	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3187	struct list_head *plist, *phead;
3188	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3189	struct	wlan_network	*pnetwork = NULL;
3190	u8 blnMatch = 0;
3191	u8 dev_type[8] = {0x00};
3192	uint dev_type_len = 0;
3193	u8 dev_type_str[17 + 9] = {0x00};	/*  +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */
3194
3195	/*	Commented by Albert 20121209 */
3196	/*	The input data is the MAC address which the application wants to know its device type. */
3197	/*	Such user interface could know the device type. */
3198	/*	Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */
3199
3200	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3201	if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17))
3202		return -EFAULT;
3203
3204	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3205		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3206
3207	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3208
3209	phead = get_list_head(queue);
3210	plist = phead->next;
3211
3212	while (1) {
3213		if (rtw_end_of_queue_search(phead, plist) == true)
3214			break;
3215
3216		pnetwork = container_of(plist, struct wlan_network, list);
3217		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3218			u8 *wpsie;
3219			uint wpsie_len = 0;
3220
3221		/*	The mac address is matched. */
3222
3223			wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12],
3224					       pnetwork->network.IELength - 12,
3225					       NULL, &wpsie_len);
3226			if (wpsie) {
3227				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
3228				if (dev_type_len) {
3229					u16	type = 0;
3230					__be16 be_tmp;
3231
3232					memcpy(&be_tmp, dev_type, 2);
3233					type = be16_to_cpu(be_tmp);
3234					sprintf(dev_type_str, "\n\nN =%.2d", type);
3235					blnMatch = 1;
3236				}
3237			}
3238			break;
3239	     }
3240
3241		plist = plist->next;
3242	}
3243
3244	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3245
3246	if (!blnMatch)
3247		sprintf(dev_type_str, "\n\nN = 00");
3248
3249	if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
3250		return -EFAULT;
3251	}
3252
3253	return ret;
3254}
3255
3256static int rtw_p2p_get_device_name(struct net_device *dev,
3257			       struct iw_request_info *info,
3258			       union iwreq_data *wrqu, char *extra)
3259{
3260	int ret = 0;
3261	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3262	u8 peerMAC[ETH_ALEN] = {0x00};
3263	int jj, kk;
3264	u8 peerMACStr[17] = {0x00};
3265	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3266	struct list_head *plist, *phead;
3267	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3268	struct	wlan_network	*pnetwork = NULL;
3269	u8 blnMatch = 0;
3270	u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
3271	uint dev_len = 0;
3272	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 */
3273
3274	/*	Commented by Albert 20121225 */
3275	/*	The input data is the MAC address which the application wants to know its device name. */
3276	/*	Such user interface could show peer device's device name instead of ssid. */
3277	/*	Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */
3278
3279	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3280	if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17))
3281		return -EFAULT;
3282
3283	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3284		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3285
3286	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3287
3288	phead = get_list_head(queue);
3289	plist = phead->next;
3290
3291	while (1) {
3292		if (rtw_end_of_queue_search(phead, plist) == true)
3293			break;
3294
3295		pnetwork = container_of(plist, struct wlan_network, list);
3296		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3297			u8 *wpsie;
3298			uint wpsie_len = 0;
3299
3300			/*	The mac address is matched. */
3301			wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
3302			if (wpsie) {
3303				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
3304				if (dev_len) {
3305					sprintf(dev_name_str, "\n\nN =%s", dev_name);
3306					blnMatch = 1;
3307				}
3308			}
3309			break;
3310		}
3311
3312		plist = plist->next;
3313	}
3314
3315	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3316
3317	if (!blnMatch)
3318		sprintf(dev_name_str, "\n\nN = 0000");
3319
3320	if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
3321		return -EFAULT;
3322	return ret;
3323}
3324
3325static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
3326			       struct iw_request_info *info,
3327			       union iwreq_data *wrqu, char *extra)
3328{
3329	int ret = 0;
3330	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3331	u8 peerMAC[ETH_ALEN] = {0x00};
3332	int jj, kk;
3333	u8 peerMACStr[17] = {0x00};
3334	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3335	struct list_head *plist, *phead;
3336	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3337	struct	wlan_network	*pnetwork = NULL;
3338	u8 blnMatch = 0;
3339	u8 *p2pie;
3340	uint p2pielen = 0, attr_contentlen = 0;
3341	u8 attr_content[2] = {0x00};
3342
3343	u8 inv_proc_str[17 + 8] = {0x00};
3344	/*  +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
3345
3346	/*	Commented by Ouden 20121226 */
3347	/*	The application wants to know P2P initiation procedure is supported or not. */
3348	/*	Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
3349
3350	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3351	if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17))
3352		return -EFAULT;
3353
3354	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3355		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3356
3357	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3358
3359	phead = get_list_head(queue);
3360	plist = phead->next;
3361
3362	while (1) {
3363		if (rtw_end_of_queue_search(phead, plist) == true)
3364			break;
3365
3366		pnetwork = container_of(plist, struct wlan_network, list);
3367		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3368			/*	Commented by Albert 20121226 */
3369			/*	Match the device address located in the P2P IE */
3370			/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
3371
3372			p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3373			if (p2pie) {
3374				while (p2pie) {
3375					if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
3376						/*	Handle the P2P capability attribute */
3377						blnMatch = 1;
3378						break;
3379					}
3380
3381					/* Get the next P2P IE */
3382					p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3383				}
3384			}
3385		}
3386		plist = plist->next;
3387	}
3388
3389	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3390
3391	if (!blnMatch) {
3392		sprintf(inv_proc_str, "\nIP =-1");
3393	} else {
3394		if (attr_content[0] & 0x20)
3395			sprintf(inv_proc_str, "\nIP = 1");
3396		else
3397			sprintf(inv_proc_str, "\nIP = 0");
3398	}
3399	if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
3400		return -EFAULT;
3401	return ret;
3402}
3403
3404static int rtw_p2p_connect(struct net_device *dev,
3405			       struct iw_request_info *info,
3406			       union iwreq_data *wrqu, char *extra)
3407{
3408	int ret = 0;
3409	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3410	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3411	u8 peerMAC[ETH_ALEN] = {0x00};
3412	int jj, kk;
3413	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3414	struct list_head *plist, *phead;
3415	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3416	struct	wlan_network	*pnetwork = NULL;
3417	uint uintPeerChannel = 0;
3418
3419	/*	Commented by Albert 20110304 */
3420	/*	The input data contains two informations. */
3421	/*	1. First information is the MAC address which wants to formate with */
3422	/*	2. Second information is the WPS PINCode or "pbc" string for push button method */
3423	/*	Format: 00:E0:4C:00:00:05 */
3424	/*	Format: 00:E0:4C:00:00:05 */
3425
3426	DBG_88E("[%s] data = %s\n", __func__, extra);
3427
3428	if (pwdinfo->p2p_state == P2P_STATE_NONE) {
3429		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3430		return ret;
3431	}
3432
3433	if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
3434		return -1;
3435
3436	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3437		peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3438
3439	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3440
3441	phead = get_list_head(queue);
3442	plist = phead->next;
3443
3444	while (1) {
3445		if (rtw_end_of_queue_search(phead, plist) == true)
3446			break;
3447
3448		pnetwork = container_of(plist, struct wlan_network, list);
3449		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3450			uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3451			break;
3452		}
3453
3454		plist = plist->next;
3455	}
3456
3457	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3458
3459	if (uintPeerChannel) {
3460		_rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
3461		_rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3462
3463		pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
3464		memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
3465		pwdinfo->nego_req_info.benable = true;
3466
3467		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3468		if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
3469			/*	Restore to the listen state if the current p2p state is not nego OK */
3470			rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3471		}
3472
3473		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3474		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
3475
3476		DBG_88E("[%s] Start PreTx Procedure!\n", __func__);
3477		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3478		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
3479	} else {
3480		DBG_88E("[%s] Not Found in Scanning Queue~\n", __func__);
3481		ret = -1;
3482	}
3483	return ret;
3484}
3485
3486static int rtw_p2p_invite_req(struct net_device *dev,
3487			      struct iw_request_info *info,
3488			      union iwreq_data *wrqu, char *extra)
3489{
3490	int ret = 0;
3491	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3492	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3493	int jj, kk;
3494	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
3495	struct list_head *plist, *phead;
3496	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3497	struct	wlan_network	*pnetwork = NULL;
3498	uint uintPeerChannel = 0;
3499	u8 attr_content[50] = {0x00};
3500	u8 *p2pie;
3501	uint p2pielen = 0, attr_contentlen = 0;
3502	struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info;
3503
3504	/*	The input data contains two informations. */
3505	/*	1. First information is the P2P device address which you want to send to. */
3506	/*	2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
3507	/*	Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
3508	/*	Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
3509
3510	DBG_88E("[%s] data = %s\n", __func__, extra);
3511
3512	if (wrqu->data.length <=  37) {
3513		DBG_88E("[%s] Wrong format!\n", __func__);
3514		return ret;
3515	}
3516
3517	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3518		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3519		return ret;
3520	} else {
3521		/*	Reset the content of struct tx_invite_req_info */
3522		pinvite_req_info->benable = false;
3523		_rtw_memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
3524		_rtw_memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
3525		pinvite_req_info->ssidlen = 0x00;
3526		pinvite_req_info->operating_ch = pwdinfo->operating_channel;
3527		_rtw_memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
3528		pinvite_req_info->token = 3;
3529	}
3530
3531	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3532		pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3533
3534	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3535
3536	phead = get_list_head(queue);
3537	plist = phead->next;
3538
3539	while (1) {
3540		if (rtw_end_of_queue_search(phead, plist) == true)
3541			break;
3542
3543		pnetwork = container_of(plist, struct wlan_network, list);
3544
3545		/*	Commented by Albert 2011/05/18 */
3546		/*	Match the device address located in the P2P IE */
3547		/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
3548
3549		p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3550		if (p2pie) {
3551			/*	The P2P Device ID attribute is included in the Beacon frame. */
3552			/*	The P2P Device Info attribute is included in the probe response frame. */
3553
3554			if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3555				/*	Handle the P2P Device ID attribute of Beacon first */
3556				if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
3557					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3558					break;
3559				}
3560			} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3561				/*	Handle the P2P Device Info attribute of probe response */
3562				if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
3563					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3564					break;
3565				}
3566			}
3567		}
3568		plist = plist->next;
3569	}
3570
3571	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3572
3573	if (uintPeerChannel) {
3574		/*	Store the GO's bssid */
3575		for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
3576			pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3577
3578		/*	Store the GO's ssid */
3579		pinvite_req_info->ssidlen = wrqu->data.length - 36;
3580		memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen);
3581		pinvite_req_info->benable = true;
3582		pinvite_req_info->peer_ch = uintPeerChannel;
3583
3584		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3585		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
3586
3587		set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3588
3589		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3590
3591		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
3592	} else {
3593		DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
3594	}
3595	return ret;
3596}
3597
3598static int rtw_p2p_set_persistent(struct net_device *dev,
3599			       struct iw_request_info *info,
3600			       union iwreq_data *wrqu, char *extra)
3601{
3602	int ret = 0;
3603	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3604	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3605
3606	/*	The input data is 0 or 1 */
3607	/*	0: disable persistent group functionality */
3608	/*	1: enable persistent group founctionality */
3609
3610	DBG_88E("[%s] data = %s\n", __func__, extra);
3611
3612	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3613		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3614		return ret;
3615	} else {
3616		if (extra[0] == '0')	/*	Disable the persistent group function. */
3617			pwdinfo->persistent_supported = false;
3618		else if (extra[0] == '1')	/*	Enable the persistent group function. */
3619			pwdinfo->persistent_supported = true;
3620		else
3621			pwdinfo->persistent_supported = false;
3622	}
3623	pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported);
3624	return ret;
3625}
3626
3627static int rtw_p2p_prov_disc(struct net_device *dev,
3628			       struct iw_request_info *info,
3629			       union iwreq_data *wrqu, char *extra)
3630{
3631	int ret = 0;
3632	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3633	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3634	u8 peerMAC[ETH_ALEN] = {0x00};
3635	int jj, kk;
3636	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3637	struct list_head *plist, *phead;
3638	struct __queue *queue	= &(pmlmepriv->scanned_queue);
3639	struct	wlan_network	*pnetwork = NULL;
3640	uint uintPeerChannel = 0;
3641	u8 attr_content[100] = {0x00};
3642	u8 *p2pie;
3643	uint p2pielen = 0, attr_contentlen = 0;
3644
3645	/*	The input data contains two informations. */
3646	/*	1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
3647	/*	2. Second information is the WPS configuration method which wants to discovery */
3648	/*	Format: 00:E0:4C:00:00:05_display */
3649	/*	Format: 00:E0:4C:00:00:05_keypad */
3650	/*	Format: 00:E0:4C:00:00:05_pbc */
3651	/*	Format: 00:E0:4C:00:00:05_label */
3652
3653	DBG_88E("[%s] data = %s\n", __func__, extra);
3654
3655	if (pwdinfo->p2p_state == P2P_STATE_NONE) {
3656		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3657		return ret;
3658	} else {
3659		/*	Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
3660		_rtw_memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
3661		_rtw_memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
3662		_rtw_memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid));
3663		pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
3664		pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
3665		pwdinfo->tx_prov_disc_info.benable = false;
3666	}
3667
3668	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3669		peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3670
3671	if (!memcmp(&extra[18], "display", 7)) {
3672		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
3673	} else if (!memcmp(&extra[18], "keypad", 7)) {
3674		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
3675	} else if (!memcmp(&extra[18], "pbc", 3)) {
3676		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
3677	} else if (!memcmp(&extra[18], "label", 5)) {
3678		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
3679	} else {
3680		DBG_88E("[%s] Unknown WPS config methodn", __func__);
3681		return ret;
3682	}
3683
3684	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3685
3686	phead = get_list_head(queue);
3687	plist = phead->next;
3688
3689	while (1) {
3690		if (rtw_end_of_queue_search(phead, plist) == true)
3691			break;
3692
3693		if (uintPeerChannel != 0)
3694			break;
3695
3696		pnetwork = container_of(plist, struct wlan_network, list);
3697
3698		/*	Commented by Albert 2011/05/18 */
3699		/*	Match the device address located in the P2P IE */
3700		/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
3701
3702		p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3703		if (p2pie) {
3704			while (p2pie) {
3705				/*	The P2P Device ID attribute is included in the Beacon frame. */
3706				/*	The P2P Device Info attribute is included in the probe response frame. */
3707
3708				if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3709					/*	Handle the P2P Device ID attribute of Beacon first */
3710					if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
3711						uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3712						break;
3713					}
3714				} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3715					/*	Handle the P2P Device Info attribute of probe response */
3716					if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
3717						uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3718						break;
3719					}
3720				}
3721
3722				/* Get the next P2P IE */
3723				p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3724			}
3725		}
3726
3727		plist = plist->next;
3728	}
3729
3730	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3731
3732	if (uintPeerChannel) {
3733		DBG_88E("[%s] peer channel: %d!\n", __func__, uintPeerChannel);
3734		memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
3735		memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
3736		pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel;
3737		pwdinfo->tx_prov_disc_info.benable = true;
3738		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3739		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
3740
3741		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
3742			memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
3743		} else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3744			memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3745			pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
3746		}
3747
3748		set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3749
3750		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3751
3752		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
3753	} else {
3754		DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
3755	}
3756	return ret;
3757}
3758
3759/*	This function is used to inform the driver the user had specified the pin code value or pbc */
3760/*	to application. */
3761
3762static int rtw_p2p_got_wpsinfo(struct net_device *dev,
3763			       struct iw_request_info *info,
3764			       union iwreq_data *wrqu, char *extra)
3765{
3766	int ret = 0;
3767	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3768	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3769
3770	DBG_88E("[%s] data = %s\n", __func__, extra);
3771	/*	Added by Albert 20110328 */
3772	/*	if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
3773	/*	if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
3774	/*	if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
3775	/*	if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
3776
3777	if (*extra == '0')
3778		pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3779	else if (*extra == '1')
3780		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
3781	else if (*extra == '2')
3782		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
3783	else if (*extra == '3')
3784		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
3785	else
3786		pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3787	return ret;
3788}
3789
3790#endif /* CONFIG_88EU_P2P */
3791
3792static int rtw_p2p_set(struct net_device *dev,
3793			       struct iw_request_info *info,
3794			       union iwreq_data *wrqu, char *extra)
3795{
3796	int ret = 0;
3797
3798#ifdef CONFIG_88EU_P2P
3799	DBG_88E("[%s] extra = %s\n", __func__, extra);
3800	if (!memcmp(extra, "enable =", 7)) {
3801		rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
3802	} else if (!memcmp(extra, "setDN =", 6)) {
3803		wrqu->data.length -= 6;
3804		rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
3805	} else if (!memcmp(extra, "profilefound =", 13)) {
3806		wrqu->data.length -= 13;
3807		rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
3808	} else if (!memcmp(extra, "prov_disc =", 10)) {
3809		wrqu->data.length -= 10;
3810		rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
3811	} else if (!memcmp(extra, "nego =", 5)) {
3812		wrqu->data.length -= 5;
3813		rtw_p2p_connect(dev, info, wrqu, &extra[5]);
3814	} else if (!memcmp(extra, "intent =", 7)) {
3815		/*	Commented by Albert 2011/03/23 */
3816		/*	The wrqu->data.length will include the null character */
3817		/*	So, we will decrease 7 + 1 */
3818		wrqu->data.length -= 8;
3819		rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
3820	} else if (!memcmp(extra, "ssid =", 5)) {
3821		wrqu->data.length -= 5;
3822		rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
3823	} else if (!memcmp(extra, "got_wpsinfo =", 12)) {
3824		wrqu->data.length -= 12;
3825		rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
3826	} else if (!memcmp(extra, "listen_ch =", 10)) {
3827		/*	Commented by Albert 2011/05/24 */
3828		/*	The wrqu->data.length will include the null character */
3829		/*	So, we will decrease (10 + 1) */
3830		wrqu->data.length -= 11;
3831		rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
3832	} else if (!memcmp(extra, "op_ch =", 6)) {
3833		/*	Commented by Albert 2011/05/24 */
3834		/*	The wrqu->data.length will include the null character */
3835		/*	So, we will decrease (6 + 1) */
3836		wrqu->data.length -= 7;
3837		rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
3838	} else if (!memcmp(extra, "invite =", 7)) {
3839		wrqu->data.length -= 8;
3840		rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
3841	} else if (!memcmp(extra, "persistent =", 11)) {
3842		wrqu->data.length -= 11;
3843		rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
3844	}
3845#endif /* CONFIG_88EU_P2P */
3846
3847	return ret;
3848}
3849
3850static int rtw_p2p_get(struct net_device *dev,
3851			       struct iw_request_info *info,
3852			       union iwreq_data *wrqu, char *extra)
3853{
3854	int ret = 0;
3855
3856#ifdef CONFIG_88EU_P2P
3857	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3858
3859	if (padapter->bShowGetP2PState)
3860		DBG_88E("[%s] extra = %s\n", __func__, (char *)wrqu->data.pointer);
3861	if (!memcmp(wrqu->data.pointer, "status", 6)) {
3862		rtw_p2p_get_status(dev, info, wrqu, extra);
3863	} else if (!memcmp(wrqu->data.pointer, "role", 4)) {
3864		rtw_p2p_get_role(dev, info, wrqu, extra);
3865	} else if (!memcmp(wrqu->data.pointer, "peer_ifa", 8)) {
3866		rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
3867	} else if (!memcmp(wrqu->data.pointer, "req_cm", 6)) {
3868		rtw_p2p_get_req_cm(dev, info, wrqu, extra);
3869	} else if (!memcmp(wrqu->data.pointer, "peer_deva", 9)) {
3870		/*	Get the P2P device address when receiving the provision discovery request frame. */
3871		rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
3872	} else if (!memcmp(wrqu->data.pointer, "group_id", 8)) {
3873		rtw_p2p_get_groupid(dev, info, wrqu, extra);
3874	} else if (!memcmp(wrqu->data.pointer, "peer_deva_inv", 9)) {
3875		/*	Get the P2P device address when receiving the P2P Invitation request frame. */
3876		rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
3877	} else if (!memcmp(wrqu->data.pointer, "op_ch", 5)) {
3878		rtw_p2p_get_op_ch(dev, info, wrqu, extra);
3879	}
3880#endif /* CONFIG_88EU_P2P */
3881	return ret;
3882}
3883
3884static int rtw_p2p_get2(struct net_device *dev,
3885			       struct iw_request_info *info,
3886			       union iwreq_data *wrqu, char *extra)
3887{
3888	int ret = 0;
3889
3890#ifdef CONFIG_88EU_P2P
3891	DBG_88E("[%s] extra = %s\n", __func__, (char *)wrqu->data.pointer);
3892	if (!memcmp(extra, "wpsCM =", 6)) {
3893		wrqu->data.length -= 6;
3894		rtw_p2p_get_wps_configmethod(dev, info, wrqu,  &extra[6]);
3895	} else if (!memcmp(extra, "devN =", 5)) {
3896		wrqu->data.length -= 5;
3897		rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]);
3898	} else if (!memcmp(extra, "dev_type =", 9)) {
3899		wrqu->data.length -= 9;
3900		rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]);
3901	} else if (!memcmp(extra, "go_devadd =", 10)) {
3902		wrqu->data.length -= 10;
3903		rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]);
3904	} else if (!memcmp(extra, "InvProc =", 8)) {
3905		wrqu->data.length -= 8;
3906		rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]);
3907	}
3908
3909#endif /* CONFIG_88EU_P2P */
3910
3911	return ret;
3912}
3913
3914static int rtw_cta_test_start(struct net_device *dev,
3915			      struct iw_request_info *info,
3916			      union iwreq_data *wrqu, char *extra)
3917{
3918	int ret = 0;
3919	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3920	DBG_88E("%s %s\n", __func__, extra);
3921	if (!strcmp(extra, "1"))
3922		padapter->in_cta_test = 1;
3923	else
3924		padapter->in_cta_test = 0;
3925
3926	if (padapter->in_cta_test) {
3927		u32 v = rtw_read32(padapter, REG_RCR);
3928		v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
3929		rtw_write32(padapter, REG_RCR, v);
3930		DBG_88E("enable RCR_ADF\n");
3931	} else {
3932		u32 v = rtw_read32(padapter, REG_RCR);
3933		v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;/*  RCR_ADF */
3934		rtw_write32(padapter, REG_RCR, v);
3935		DBG_88E("disable RCR_ADF\n");
3936	}
3937	return ret;
3938}
3939
3940static int rtw_rereg_nd_name(struct net_device *dev,
3941			       struct iw_request_info *info,
3942			       union iwreq_data *wrqu, char *extra)
3943{
3944	int ret = 0;
3945	struct adapter *padapter = rtw_netdev_priv(dev);
3946	struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
3947	char new_ifname[IFNAMSIZ];
3948
3949	if (rereg_priv->old_ifname[0] == 0) {
3950		char *reg_ifname;
3951		reg_ifname = padapter->registrypriv.if2name;
3952
3953		strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
3954		rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
3955	}
3956
3957	if (wrqu->data.length > IFNAMSIZ)
3958		return -EFAULT;
3959
3960	if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
3961		return -EFAULT;
3962
3963	if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
3964		return ret;
3965
3966	DBG_88E("%s new_ifname:%s\n", __func__, new_ifname);
3967	ret = rtw_change_ifname(padapter, new_ifname);
3968	if (0 != ret)
3969		goto exit;
3970
3971	if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
3972		padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
3973		rtw_hal_sw_led_init(padapter);
3974		rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
3975	}
3976
3977	strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
3978	rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
3979
3980	if (!memcmp(new_ifname, "disable%d", 9)) {
3981		DBG_88E("%s disable\n", __func__);
3982		/*  free network queue for Android's timming issue */
3983		rtw_free_network_queue(padapter, true);
3984
3985		/*  close led */
3986		rtw_led_control(padapter, LED_CTL_POWER_OFF);
3987		rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
3988		padapter->ledpriv.bRegUseLed = false;
3989		rtw_hal_sw_led_deinit(padapter);
3990
3991		/*  the interface is being "disabled", we can do deeper IPS */
3992		rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
3993		rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
3994	}
3995exit:
3996	return ret;
3997}
3998
3999static void mac_reg_dump(struct adapter *padapter)
4000{
4001	int i, j = 1;
4002	pr_info("\n ======= MAC REG =======\n");
4003	for (i = 0x0; i < 0x300; i += 4) {
4004		if (j%4 == 1)
4005			pr_info("0x%02x", i);
4006		pr_info(" 0x%08x ", rtw_read32(padapter, i));
4007		if ((j++)%4 == 0)
4008			pr_info("\n");
4009	}
4010	for (i = 0x400; i < 0x800; i += 4) {
4011		if (j%4 == 1)
4012			pr_info("0x%02x", i);
4013		pr_info(" 0x%08x ", rtw_read32(padapter, i));
4014		if ((j++)%4 == 0)
4015			pr_info("\n");
4016	}
4017}
4018
4019static void bb_reg_dump(struct adapter *padapter)
4020{
4021	int i, j = 1;
4022	pr_info("\n ======= BB REG =======\n");
4023	for (i = 0x800; i < 0x1000; i += 4) {
4024		if (j%4 == 1)
4025			pr_info("0x%02x", i);
4026
4027		pr_info(" 0x%08x ", rtw_read32(padapter, i));
4028		if ((j++)%4 == 0)
4029			pr_info("\n");
4030	}
4031}
4032
4033static void rf_reg_dump(struct adapter *padapter)
4034{
4035	int i, j = 1, path;
4036	u32 value;
4037	u8 rf_type, path_nums = 0;
4038	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
4039
4040	pr_info("\n ======= RF REG =======\n");
4041	if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
4042		path_nums = 1;
4043	else
4044		path_nums = 2;
4045
4046	for (path = 0; path < path_nums; path++) {
4047		pr_info("\nRF_Path(%x)\n", path);
4048		for (i = 0; i < 0x100; i++) {
4049			value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
4050			if (j%4 == 1)
4051				pr_info("0x%02x ", i);
4052			pr_info(" 0x%08x ", value);
4053			if ((j++)%4 == 0)
4054				pr_info("\n");
4055		}
4056	}
4057}
4058
4059static int rtw_dbg_port(struct net_device *dev,
4060			       struct iw_request_info *info,
4061			       union iwreq_data *wrqu, char *extra)
4062{
4063	int ret = 0;
4064	u8 major_cmd, minor_cmd;
4065	u16 arg;
4066	s32 extra_arg;
4067	u32 *pdata, val32;
4068	struct sta_info *psta;
4069	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4070	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4071	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4072	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4073	struct security_priv *psecuritypriv = &padapter->securitypriv;
4074	struct wlan_network *cur_network = &(pmlmepriv->cur_network);
4075	struct sta_priv *pstapriv = &padapter->stapriv;
4076
4077	pdata = (u32 *)&wrqu->data;
4078
4079	val32 = *pdata;
4080	arg = (u16)(val32 & 0x0000ffff);
4081	major_cmd = (u8)(val32 >> 24);
4082	minor_cmd = (u8)((val32 >> 16) & 0x00ff);
4083
4084	extra_arg = *(pdata+1);
4085
4086	switch (major_cmd) {
4087	case 0x70:/* read_reg */
4088		switch (minor_cmd) {
4089		case 1:
4090			DBG_88E("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
4091			break;
4092		case 2:
4093			DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
4094			break;
4095		case 4:
4096			DBG_88E("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
4097			break;
4098		}
4099		break;
4100	case 0x71:/* write_reg */
4101		switch (minor_cmd) {
4102		case 1:
4103			rtw_write8(padapter, arg, extra_arg);
4104			DBG_88E("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
4105			break;
4106		case 2:
4107			rtw_write16(padapter, arg, extra_arg);
4108			DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
4109			break;
4110		case 4:
4111			rtw_write32(padapter, arg, extra_arg);
4112			DBG_88E("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
4113			break;
4114		}
4115		break;
4116	case 0x72:/* read_bb */
4117		DBG_88E("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
4118		break;
4119	case 0x73:/* write_bb */
4120		rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
4121		DBG_88E("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
4122		break;
4123	case 0x74:/* read_rf */
4124		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));
4125		break;
4126	case 0x75:/* write_rf */
4127		rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
4128		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));
4129		break;
4130
4131	case 0x76:
4132		switch (minor_cmd) {
4133		case 0x00: /* normal mode, */
4134			padapter->recvpriv.is_signal_dbg = 0;
4135			break;
4136		case 0x01: /* dbg mode */
4137			padapter->recvpriv.is_signal_dbg = 1;
4138			extra_arg = extra_arg > 100 ? 100 : extra_arg;
4139			extra_arg = extra_arg < 0 ? 0 : extra_arg;
4140			padapter->recvpriv.signal_strength_dbg = extra_arg;
4141			break;
4142		}
4143		break;
4144	case 0x78: /* IOL test */
4145		switch (minor_cmd) {
4146		case 0x04: /* LLT table initialization test */
4147		{
4148			u8 page_boundary = 0xf9;
4149			struct xmit_frame	*xmit_frame;
4150
4151			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4152			if (xmit_frame == NULL) {
4153				ret = -ENOMEM;
4154				break;
4155			}
4156
4157			rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
4158
4159			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
4160				ret = -EPERM;
4161		}
4162			break;
4163		case 0x05: /* blink LED test */
4164		{
4165			u16 reg = 0x4c;
4166			u32 blink_num = 50;
4167			u32 blink_delay_ms = 200;
4168			int i;
4169			struct xmit_frame	*xmit_frame;
4170
4171			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4172			if (xmit_frame == NULL) {
4173				ret = -ENOMEM;
4174				break;
4175			}
4176
4177			for (i = 0; i < blink_num; i++) {
4178				rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
4179				rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
4180				rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
4181				rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
4182			}
4183			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200, 0))
4184				ret = -EPERM;
4185		}
4186			break;
4187
4188		case 0x06: /* continuous write byte test */
4189		{
4190			u16 reg = arg;
4191			u16 start_value = 0;
4192			u32 write_num = extra_arg;
4193			int i;
4194			u8 final;
4195			struct xmit_frame	*xmit_frame;
4196
4197			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4198			if (xmit_frame == NULL) {
4199				ret = -ENOMEM;
4200				break;
4201			}
4202
4203			for (i = 0; i < write_num; i++)
4204				rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value, 0xFF);
4205			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4206				ret = -EPERM;
4207
4208			final = rtw_read8(padapter, reg);
4209			if (start_value+write_num-1 == final)
4210				DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
4211			else
4212				DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
4213		}
4214			break;
4215
4216		case 0x07: /* continuous write word test */
4217		{
4218			u16 reg = arg;
4219			u16 start_value = 200;
4220			u32 write_num = extra_arg;
4221
4222			int i;
4223			u16 final;
4224			struct xmit_frame	*xmit_frame;
4225
4226			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4227			if (xmit_frame == NULL) {
4228				ret = -ENOMEM;
4229				break;
4230			}
4231
4232			for (i = 0; i < write_num; i++)
4233				rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value, 0xFFFF);
4234			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4235				ret = -EPERM;
4236
4237			final = rtw_read16(padapter, reg);
4238			if (start_value+write_num-1 == final)
4239				DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
4240			else
4241				DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
4242		}
4243			break;
4244		case 0x08: /* continuous write dword test */
4245		{
4246			u16 reg = arg;
4247			u32 start_value = 0x110000c7;
4248			u32 write_num = extra_arg;
4249
4250			int i;
4251			u32 final;
4252			struct xmit_frame	*xmit_frame;
4253
4254			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4255			if (xmit_frame == NULL) {
4256				ret = -ENOMEM;
4257				break;
4258			}
4259
4260			for (i = 0; i < write_num; i++)
4261				rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value, 0xFFFFFFFF);
4262			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4263				ret = -EPERM;
4264
4265			final = rtw_read32(padapter, reg);
4266			if (start_value+write_num-1 == final)
4267				DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n",
4268					reg, write_num, start_value, final);
4269			else
4270				DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n",
4271					reg, write_num, start_value, final);
4272		}
4273			break;
4274		}
4275		break;
4276	case 0x79:
4277		{
4278			/*
4279			* dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
4280			* dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
4281			*/
4282			u8 value =  extra_arg & 0x0f;
4283			u8 sign = minor_cmd;
4284			u16 write_value = 0;
4285
4286			DBG_88E("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
4287
4288			if (sign)
4289				value = value | 0x10;
4290
4291			write_value = value | (value << 5);
4292			rtw_write16(padapter, 0x6d9, write_value);
4293		}
4294		break;
4295	case 0x7a:
4296		receive_disconnect(padapter, pmlmeinfo->network.MacAddress
4297			, WLAN_REASON_EXPIRATION_CHK);
4298		break;
4299	case 0x7F:
4300		switch (minor_cmd) {
4301		case 0x0:
4302			DBG_88E("fwstate = 0x%x\n", get_fwstate(pmlmepriv));
4303			break;
4304		case 0x01:
4305			DBG_88E("auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n",
4306				psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
4307				psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
4308			break;
4309		case 0x02:
4310			DBG_88E("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
4311			break;
4312		case 0x03:
4313			DBG_88E("qos_option =%d\n", pmlmepriv->qospriv.qos_option);
4314			DBG_88E("ht_option =%d\n", pmlmepriv->htpriv.ht_option);
4315			break;
4316		case 0x04:
4317			DBG_88E("cur_ch =%d\n", pmlmeext->cur_channel);
4318			DBG_88E("cur_bw =%d\n", pmlmeext->cur_bwmode);
4319			DBG_88E("cur_ch_off =%d\n", pmlmeext->cur_ch_offset);
4320			break;
4321		case 0x05:
4322			psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
4323			if (psta) {
4324				int i;
4325				struct recv_reorder_ctrl *preorder_ctrl;
4326
4327				DBG_88E("SSID =%s\n", cur_network->network.Ssid.Ssid);
4328				DBG_88E("sta's macaddr: %pM\n", psta->hwaddr);
4329				DBG_88E("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
4330				DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
4331				DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
4332				DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
4333				DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
4334				DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
4335				DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
4336				for (i = 0; i < 16; i++) {
4337					preorder_ctrl = &psta->recvreorder_ctrl[i];
4338					if (preorder_ctrl->enable)
4339						DBG_88E("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
4340				}
4341			} else {
4342				DBG_88E("can't get sta's macaddr, cur_network's macaddr:%pM\n", (cur_network->network.MacAddress));
4343			}
4344			break;
4345		case 0x06:
4346			{
4347				u32	ODMFlag;
4348				rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
4349				DBG_88E("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg);
4350				ODMFlag = (u32)(0x0f&arg);
4351				DBG_88E("(A)DMFlag = 0x%x\n", ODMFlag);
4352				rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
4353			}
4354			break;
4355		case 0x07:
4356			DBG_88E("bSurpriseRemoved =%d, bDriverStopped =%d\n",
4357				padapter->bSurpriseRemoved, padapter->bDriverStopped);
4358			break;
4359		case 0x08:
4360			{
4361				struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4362				struct recv_priv  *precvpriv = &padapter->recvpriv;
4363
4364				DBG_88E("free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d, free_xmit_extbuf_cnt =%d\n",
4365					pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt);
4366				DBG_88E("rx_urb_pending_cn =%d\n", precvpriv->rx_pending_cnt);
4367			}
4368			break;
4369		case 0x09:
4370			{
4371				int i, j;
4372				struct list_head *plist, *phead;
4373				struct recv_reorder_ctrl *preorder_ctrl;
4374
4375#ifdef CONFIG_88EU_AP_MODE
4376				DBG_88E("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
4377#endif
4378				spin_lock_bh(&pstapriv->sta_hash_lock);
4379
4380				for (i = 0; i < NUM_STA; i++) {
4381					phead = &(pstapriv->sta_hash[i]);
4382					plist = phead->next;
4383
4384					while ((rtw_end_of_queue_search(phead, plist)) == false) {
4385						psta = container_of(plist, struct sta_info, hash_list);
4386
4387						plist = plist->next;
4388
4389						if (extra_arg == psta->aid) {
4390							DBG_88E("sta's macaddr:%pM\n", (psta->hwaddr));
4391							DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
4392							DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
4393							DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
4394							DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
4395							DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
4396							DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
4397
4398#ifdef CONFIG_88EU_AP_MODE
4399							DBG_88E("capability = 0x%x\n", psta->capability);
4400							DBG_88E("flags = 0x%x\n", psta->flags);
4401							DBG_88E("wpa_psk = 0x%x\n", psta->wpa_psk);
4402							DBG_88E("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher);
4403							DBG_88E("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher);
4404							DBG_88E("qos_info = 0x%x\n", psta->qos_info);
4405#endif
4406							DBG_88E("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy);
4407
4408							for (j = 0; j < 16; j++) {
4409								preorder_ctrl = &psta->recvreorder_ctrl[j];
4410								if (preorder_ctrl->enable)
4411									DBG_88E("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq);
4412							}
4413						}
4414					}
4415				}
4416				spin_unlock_bh(&pstapriv->sta_hash_lock);
4417			}
4418			break;
4419		case 0x0c:/* dump rx/tx packet */
4420			if (arg == 0) {
4421				DBG_88E("dump rx packet (%d)\n", extra_arg);
4422				rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
4423			} else if (arg == 1) {
4424				DBG_88E("dump tx packet (%d)\n", extra_arg);
4425				rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
4426			}
4427			break;
4428		case 0x0f:
4429			if (extra_arg == 0) {
4430				DBG_88E("###### silent reset test.......#####\n");
4431				rtw_hal_sreset_reset(padapter);
4432			}
4433			break;
4434		case 0x15:
4435			{
4436				struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
4437				DBG_88E("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
4438			}
4439			break;
4440		case 0x10:/*  driver version display */
4441			DBG_88E("rtw driver version =%s\n", DRIVERVERSION);
4442			break;
4443		case 0x11:
4444			DBG_88E("turn %s Rx RSSI display function\n", (extra_arg == 1) ? "on" : "off");
4445			padapter->bRxRSSIDisplay = extra_arg;
4446			rtw_hal_set_def_var(padapter, HW_DEF_FA_CNT_DUMP, &extra_arg);
4447			break;
4448		case 0x12: /* set rx_stbc */
4449		{
4450			struct registry_priv	*pregpriv = &padapter->registrypriv;
4451			/*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
4452			/* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
4453			if (pregpriv &&
4454			    (extra_arg == 0 ||
4455			     extra_arg == 1 ||
4456			     extra_arg == 2 ||
4457			     extra_arg == 3)) {
4458				pregpriv->rx_stbc = extra_arg;
4459				DBG_88E("set rx_stbc =%d\n", pregpriv->rx_stbc);
4460			} else {
4461				DBG_88E("get rx_stbc =%d\n", pregpriv->rx_stbc);
4462			}
4463		}
4464			break;
4465		case 0x13: /* set ampdu_enable */
4466		{
4467			struct registry_priv	*pregpriv = &padapter->registrypriv;
4468			/*  0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
4469			if (pregpriv && extra_arg >= 0 && extra_arg < 3) {
4470				pregpriv->ampdu_enable = extra_arg;
4471				DBG_88E("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
4472			} else {
4473				DBG_88E("get ampdu_enable =%d\n", pregpriv->ampdu_enable);
4474			}
4475		}
4476			break;
4477		case 0x14: /* get wifi_spec */
4478		{
4479			struct registry_priv	*pregpriv = &padapter->registrypriv;
4480			DBG_88E("get wifi_spec =%d\n", pregpriv->wifi_spec);
4481		}
4482			break;
4483		case 0x16:
4484			if (arg == 0xff) {
4485				pr_info("ODM_COMP_DIG\t\tBIT0\n");
4486				pr_info("ODM_COMP_RA_MASK\t\tBIT1\n");
4487				pr_info("ODM_COMP_DYNAMIC_TXPWR\tBIT2\n");
4488				pr_info("ODM_COMP_FA_CNT\t\tBIT3\n");
4489				pr_info("ODM_COMP_RSSI_MONITOR\tBIT4\n");
4490				pr_info("ODM_COMP_CCK_PD\t\tBIT5\n");
4491				pr_info("ODM_COMP_ANT_DIV\t\tBIT6\n");
4492				pr_info("ODM_COMP_PWR_SAVE\t\tBIT7\n");
4493				pr_info("ODM_COMP_PWR_TRAIN\tBIT8\n");
4494				pr_info("ODM_COMP_RATE_ADAPTIVE\tBIT9\n");
4495				pr_info("ODM_COMP_PATH_DIV\t\tBIT10\n");
4496				pr_info("ODM_COMP_PSD	\tBIT11\n");
4497				pr_info("ODM_COMP_DYNAMIC_PRICCA\tBIT12\n");
4498				pr_info("ODM_COMP_RXHP\t\tBIT13\n");
4499				pr_info("ODM_COMP_EDCA_TURBO\tBIT16\n");
4500				pr_info("ODM_COMP_EARLY_MODE\tBIT17\n");
4501				pr_info("ODM_COMP_TX_PWR_TRACK\tBIT24\n");
4502				pr_info("ODM_COMP_RX_GAIN_TRACK\tBIT25\n");
4503				pr_info("ODM_COMP_CALIBRATION\tBIT26\n");
4504				rtw_hal_get_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
4505			} else {
4506				rtw_hal_set_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
4507			}
4508			break;
4509		case 0x23:
4510			DBG_88E("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
4511			padapter->bNotifyChannelChange = extra_arg;
4512			break;
4513		case 0x24:
4514#ifdef CONFIG_88EU_P2P
4515			DBG_88E("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
4516			padapter->bShowGetP2PState = extra_arg;
4517#endif /*  CONFIG_88EU_P2P */
4518			break;
4519		case 0xaa:
4520			if (extra_arg > 0x13)
4521				extra_arg = 0xFF;
4522			DBG_88E("chang data rate to :0x%02x\n", extra_arg);
4523			padapter->fix_rate = extra_arg;
4524			break;
4525		case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */
4526			if (extra_arg == 0)
4527				mac_reg_dump(padapter);
4528			else if (extra_arg == 1)
4529				bb_reg_dump(padapter);
4530			else if (extra_arg == 2)
4531				rf_reg_dump(padapter);
4532			break;
4533		case 0xee:/* turn on/off dynamic funcs */
4534			{
4535				u32 odm_flag;
4536
4537				if (0xf == extra_arg) {
4538					rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
4539					DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
4540					DBG_88E("extra_arg = 0  - disable all dynamic func\n");
4541					DBG_88E("extra_arg = 1  - disable DIG- BIT(0)\n");
4542					DBG_88E("extra_arg = 2  - disable High power - BIT(1)\n");
4543					DBG_88E("extra_arg = 3  - disable tx power tracking - BIT(2)\n");
4544					DBG_88E("extra_arg = 4  - disable BT coexistence - BIT(3)\n");
4545					DBG_88E("extra_arg = 5  - disable antenna diversity - BIT(4)\n");
4546					DBG_88E("extra_arg = 6  - enable all dynamic func\n");
4547				} else {
4548					/*	extra_arg = 0  - disable all dynamic func
4549						extra_arg = 1  - disable DIG
4550						extra_arg = 2  - disable tx power tracking
4551						extra_arg = 3  - turn on all dynamic func
4552					*/
4553					rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
4554					rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
4555					DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
4556				}
4557			}
4558			break;
4559
4560		case 0xfd:
4561			rtw_write8(padapter, 0xc50, arg);
4562			DBG_88E("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
4563			rtw_write8(padapter, 0xc58, arg);
4564			DBG_88E("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
4565			break;
4566		case 0xfe:
4567			DBG_88E("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
4568			DBG_88E("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
4569			break;
4570		case 0xff:
4571			DBG_88E("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210));
4572			DBG_88E("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608));
4573			DBG_88E("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280));
4574			DBG_88E("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284));
4575			DBG_88E("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288));
4576
4577			DBG_88E("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664));
4578
4579			DBG_88E("\n");
4580
4581			DBG_88E("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430));
4582			DBG_88E("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438));
4583
4584			DBG_88E("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440));
4585
4586			DBG_88E("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458));
4587
4588			DBG_88E("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484));
4589			DBG_88E("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488));
4590
4591			DBG_88E("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444));
4592			DBG_88E("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448));
4593			DBG_88E("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c));
4594			DBG_88E("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450));
4595			break;
4596		}
4597		break;
4598	default:
4599		DBG_88E("error dbg cmd!\n");
4600		break;
4601	}
4602	return ret;
4603}
4604
4605static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
4606{
4607	uint ret = 0;
4608	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4609
4610	switch (name) {
4611	case IEEE_PARAM_WPA_ENABLED:
4612		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
4613		switch ((value)&0xff) {
4614		case 1: /* WPA */
4615			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
4616			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
4617			break;
4618		case 2: /* WPA2 */
4619			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
4620			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4621			break;
4622		}
4623		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
4624			 ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
4625		break;
4626	case IEEE_PARAM_TKIP_COUNTERMEASURES:
4627		break;
4628	case IEEE_PARAM_DROP_UNENCRYPTED: {
4629		/* HACK:
4630		 *
4631		 * wpa_supplicant calls set_wpa_enabled when the driver
4632		 * is loaded and unloaded, regardless of if WPA is being
4633		 * used.  No other calls are made which can be used to
4634		 * determine if encryption will be used or not prior to
4635		 * association being expected.  If encryption is not being
4636		 * used, drop_unencrypted is set to false, else true -- we
4637		 * can use this to determine if the CAP_PRIVACY_ON bit should
4638		 * be set.
4639		 */
4640
4641		break;
4642	}
4643	case IEEE_PARAM_PRIVACY_INVOKED:
4644		break;
4645
4646	case IEEE_PARAM_AUTH_ALGS:
4647		ret = wpa_set_auth_algs(dev, value);
4648		break;
4649	case IEEE_PARAM_IEEE_802_1X:
4650		break;
4651	case IEEE_PARAM_WPAX_SELECT:
4652		break;
4653	default:
4654		ret = -EOPNOTSUPP;
4655		break;
4656	}
4657	return ret;
4658}
4659
4660static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
4661{
4662	int ret = 0;
4663	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4664
4665	switch (command) {
4666	case IEEE_MLME_STA_DEAUTH:
4667		if (!rtw_set_802_11_disassociate(padapter))
4668			ret = -1;
4669		break;
4670	case IEEE_MLME_STA_DISASSOC:
4671		if (!rtw_set_802_11_disassociate(padapter))
4672			ret = -1;
4673		break;
4674	default:
4675		ret = -EOPNOTSUPP;
4676		break;
4677	}
4678
4679	return ret;
4680}
4681
4682static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
4683{
4684	struct ieee_param *param;
4685	uint ret = 0;
4686
4687	if (p->length < sizeof(struct ieee_param) || !p->pointer) {
4688		ret = -EINVAL;
4689		goto out;
4690	}
4691
4692	param = (struct ieee_param *)rtw_malloc(p->length);
4693	if (param == NULL) {
4694		ret = -ENOMEM;
4695		goto out;
4696	}
4697
4698	if (copy_from_user(param, p->pointer, p->length)) {
4699		kfree(param);
4700		ret = -EFAULT;
4701		goto out;
4702	}
4703
4704	switch (param->cmd) {
4705	case IEEE_CMD_SET_WPA_PARAM:
4706		ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
4707		break;
4708
4709	case IEEE_CMD_SET_WPA_IE:
4710		ret =  rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev),
4711				      (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
4712		break;
4713
4714	case IEEE_CMD_SET_ENCRYPTION:
4715		ret = wpa_set_encryption(dev, param, p->length);
4716		break;
4717
4718	case IEEE_CMD_MLME:
4719		ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
4720		break;
4721
4722	default:
4723		DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
4724		ret = -EOPNOTSUPP;
4725		break;
4726	}
4727
4728	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
4729		ret = -EFAULT;
4730
4731	kfree(param);
4732
4733out:
4734
4735	return ret;
4736}
4737
4738#ifdef CONFIG_88EU_AP_MODE
4739static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
4740{
4741	struct cmd_obj *ph2c;
4742	struct set_stakey_parm	*psetstakey_para;
4743	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
4744	u8 res = _SUCCESS;
4745
4746	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4747	if (ph2c == NULL) {
4748		res = _FAIL;
4749		goto exit;
4750	}
4751
4752	psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
4753	if (psetstakey_para == NULL) {
4754		kfree(ph2c);
4755		res = _FAIL;
4756		goto exit;
4757	}
4758
4759	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
4760
4761	psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
4762
4763	memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
4764
4765	memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
4766
4767	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4768
4769exit:
4770
4771	return res;
4772}
4773
4774static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
4775{
4776	u8 keylen;
4777	struct cmd_obj *pcmd;
4778	struct setkey_parm *psetkeyparm;
4779	struct cmd_priv	*pcmdpriv = &(padapter->cmdpriv);
4780	int res = _SUCCESS;
4781
4782	DBG_88E("%s\n", __func__);
4783
4784	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
4785	if (pcmd == NULL) {
4786		res = _FAIL;
4787		goto exit;
4788	}
4789	psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
4790	if (psetkeyparm == NULL) {
4791		kfree(pcmd);
4792		res = _FAIL;
4793		goto exit;
4794	}
4795
4796	_rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
4797
4798	psetkeyparm->keyid = (u8)keyid;
4799
4800	psetkeyparm->algorithm = alg;
4801
4802	psetkeyparm->set_tx = 1;
4803
4804	switch (alg) {
4805	case _WEP40_:
4806		keylen = 5;
4807		break;
4808	case _WEP104_:
4809		keylen = 13;
4810		break;
4811	case _TKIP_:
4812	case _TKIP_WTMIC_:
4813	case _AES_:
4814	default:
4815		keylen = 16;
4816	}
4817
4818	memcpy(&(psetkeyparm->key[0]), key, keylen);
4819
4820	pcmd->cmdcode = _SetKey_CMD_;
4821	pcmd->parmbuf = (u8 *)psetkeyparm;
4822	pcmd->cmdsz =  (sizeof(struct setkey_parm));
4823	pcmd->rsp = NULL;
4824	pcmd->rspsz = 0;
4825
4826	_rtw_init_listhead(&pcmd->list);
4827
4828	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
4829
4830exit:
4831
4832	return res;
4833}
4834
4835static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
4836{
4837	u8 alg;
4838
4839	switch (keylen) {
4840	case 5:
4841		alg = _WEP40_;
4842		break;
4843	case 13:
4844		alg = _WEP104_;
4845		break;
4846	default:
4847		alg = _NO_PRIVACY_;
4848	}
4849
4850	return set_group_key(padapter, key, alg, keyid);
4851}
4852
4853static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
4854{
4855	int ret = 0;
4856	u32 wep_key_idx, wep_key_len, wep_total_len;
4857	struct ndis_802_11_wep	 *pwep = NULL;
4858	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
4859	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4860	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
4861	struct security_priv *psecuritypriv = &(padapter->securitypriv);
4862	struct sta_priv *pstapriv = &padapter->stapriv;
4863
4864	DBG_88E("%s\n", __func__);
4865	param->u.crypt.err = 0;
4866	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
4867	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
4868		ret =  -EINVAL;
4869		goto exit;
4870	}
4871	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4872	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
4873	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
4874		if (param->u.crypt.idx >= WEP_KEYS) {
4875			ret = -EINVAL;
4876			goto exit;
4877		}
4878	} else {
4879		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
4880		if (!psta) {
4881			DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
4882			goto exit;
4883		}
4884	}
4885
4886	if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
4887		/* todo:clear default encryption keys */
4888
4889		DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
4890		goto exit;
4891	}
4892	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
4893		DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
4894		wep_key_idx = param->u.crypt.idx;
4895		wep_key_len = param->u.crypt.key_len;
4896		DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
4897		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
4898			ret = -EINVAL;
4899			goto exit;
4900		}
4901
4902		if (wep_key_len > 0) {
4903			wep_key_len = wep_key_len <= 5 ? 5 : 13;
4904			wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
4905			pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
4906			if (pwep == NULL) {
4907				DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
4908				goto exit;
4909			}
4910
4911			_rtw_memset(pwep, 0, wep_total_len);
4912
4913			pwep->KeyLength = wep_key_len;
4914			pwep->Length = wep_total_len;
4915		}
4916
4917		pwep->KeyIndex = wep_key_idx;
4918
4919		memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
4920
4921		if (param->u.crypt.set_tx) {
4922			DBG_88E("wep, set_tx = 1\n");
4923
4924			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
4925			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
4926			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
4927
4928			if (pwep->KeyLength == 13) {
4929				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
4930				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
4931			}
4932
4933			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
4934
4935			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
4936
4937			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
4938
4939			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
4940		} else {
4941			DBG_88E("wep, set_tx = 0\n");
4942
4943			/* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
4944			/* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
4945
4946		      memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
4947
4948			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
4949
4950			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
4951		}
4952
4953		goto exit;
4954	}
4955
4956	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
4957		if (param->u.crypt.set_tx == 1) {
4958			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
4959				DBG_88E("%s, set group_key, WEP\n", __func__);
4960
4961				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4962					    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4963
4964				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
4965				if (param->u.crypt.key_len == 13)
4966						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
4967			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
4968				DBG_88E("%s, set group_key, TKIP\n", __func__);
4969				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
4970				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4971					    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4972				/* set mic key */
4973				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
4974				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
4975
4976				psecuritypriv->busetkipkey = true;
4977			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
4978				DBG_88E("%s, set group_key, CCMP\n", __func__);
4979				psecuritypriv->dot118021XGrpPrivacy = _AES_;
4980				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4981					    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4982			} else {
4983				DBG_88E("%s, set group_key, none\n", __func__);
4984				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
4985			}
4986			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
4987			psecuritypriv->binstallGrpkey = true;
4988			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
4989			set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
4990			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
4991			if (pbcmc_sta) {
4992				pbcmc_sta->ieee8021x_blocked = false;
4993				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
4994			}
4995		}
4996		goto exit;
4997	}
4998
4999	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
5000		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
5001			if (param->u.crypt.set_tx == 1) {
5002				memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5003
5004				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
5005					DBG_88E("%s, set pairwise key, WEP\n", __func__);
5006
5007					psta->dot118021XPrivacy = _WEP40_;
5008					if (param->u.crypt.key_len == 13)
5009						psta->dot118021XPrivacy = _WEP104_;
5010				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
5011					DBG_88E("%s, set pairwise key, TKIP\n", __func__);
5012
5013					psta->dot118021XPrivacy = _TKIP_;
5014
5015					/* set mic key */
5016					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
5017					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
5018
5019					psecuritypriv->busetkipkey = true;
5020				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
5021					DBG_88E("%s, set pairwise key, CCMP\n", __func__);
5022
5023					psta->dot118021XPrivacy = _AES_;
5024				} else {
5025					DBG_88E("%s, set pairwise key, none\n", __func__);
5026
5027					psta->dot118021XPrivacy = _NO_PRIVACY_;
5028				}
5029
5030				set_pairwise_key(padapter, psta);
5031
5032				psta->ieee8021x_blocked = false;
5033			} else { /* group key??? */
5034				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
5035					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5036						    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5037					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
5038					if (param->u.crypt.key_len == 13)
5039						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
5040				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
5041					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
5042
5043					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5044						    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5045
5046					/* set mic key */
5047					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
5048					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
5049
5050					psecuritypriv->busetkipkey = true;
5051				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
5052					psecuritypriv->dot118021XGrpPrivacy = _AES_;
5053
5054					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5055						    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5056				} else {
5057					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
5058				}
5059
5060				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
5061
5062				psecuritypriv->binstallGrpkey = true;
5063
5064				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
5065
5066				set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
5067
5068				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
5069				if (pbcmc_sta) {
5070					pbcmc_sta->ieee8021x_blocked = false;
5071					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
5072				}
5073			}
5074		}
5075	}
5076
5077exit:
5078
5079	kfree(pwep);
5080
5081	return ret;
5082}
5083
5084static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
5085{
5086	int ret = 0;
5087	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5088	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5089	struct sta_priv *pstapriv = &padapter->stapriv;
5090	unsigned char *pbuf = param->u.bcn_ie.buf;
5091
5092	DBG_88E("%s, len =%d\n", __func__, len);
5093
5094	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5095		return -EINVAL;
5096
5097	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
5098
5099	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
5100		pstapriv->max_num_sta = NUM_STA;
5101
5102	if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
5103		ret = 0;
5104	else
5105		ret = -EINVAL;
5106
5107	return ret;
5108}
5109
5110static int rtw_hostapd_sta_flush(struct net_device *dev)
5111{
5112	int ret = 0;
5113	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5114
5115	DBG_88E("%s\n", __func__);
5116
5117	flush_all_cam_entry(padapter);	/* clear CAM */
5118
5119	ret = rtw_sta_flush(padapter);
5120
5121	return ret;
5122}
5123
5124static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
5125{
5126	int ret = 0;
5127	struct sta_info *psta = NULL;
5128	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5129	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5130	struct sta_priv *pstapriv = &padapter->stapriv;
5131
5132	DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
5133
5134	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
5135		return -EINVAL;
5136
5137	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5138	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5139	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5140		return -EINVAL;
5141
5142	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5143	if (psta) {
5144		int flags = param->u.add_sta.flags;
5145
5146		psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
5147
5148		memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
5149
5150		/* check wmm cap. */
5151		if (WLAN_STA_WME&flags)
5152			psta->qos_option = 1;
5153		else
5154			psta->qos_option = 0;
5155
5156		if (pmlmepriv->qospriv.qos_option == 0)
5157			psta->qos_option = 0;
5158
5159		/* chec 802.11n ht cap. */
5160		if (WLAN_STA_HT&flags) {
5161			psta->htpriv.ht_option = true;
5162			psta->qos_option = 1;
5163			memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
5164		} else {
5165			psta->htpriv.ht_option = false;
5166		}
5167
5168		if (pmlmepriv->htpriv.ht_option == false)
5169			psta->htpriv.ht_option = false;
5170
5171		update_sta_info_apmode(padapter, psta);
5172	} else {
5173		ret = -ENOMEM;
5174	}
5175
5176	return ret;
5177}
5178
5179static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
5180{
5181	int ret = 0;
5182	struct sta_info *psta = NULL;
5183	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5184	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5185	struct sta_priv *pstapriv = &padapter->stapriv;
5186	int updated = 0;
5187
5188	DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
5189
5190	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5191		return -EINVAL;
5192
5193	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5194	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5195	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5196		return -EINVAL;
5197
5198	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5199	if (psta) {
5200		spin_lock_bh(&pstapriv->asoc_list_lock);
5201		if (!rtw_is_list_empty(&psta->asoc_list)) {
5202			rtw_list_delete(&psta->asoc_list);
5203			pstapriv->asoc_list_cnt--;
5204			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
5205		}
5206		spin_unlock_bh(&pstapriv->asoc_list_lock);
5207		associated_clients_update(padapter, updated);
5208		psta = NULL;
5209	} else {
5210		DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
5211	}
5212
5213	return ret;
5214}
5215
5216static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
5217{
5218	int ret = 0;
5219	struct sta_info *psta = NULL;
5220	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5221	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5222	struct sta_priv *pstapriv = &padapter->stapriv;
5223	struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
5224	struct sta_data *psta_data = (struct sta_data *)param_ex->data;
5225
5226	DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
5227
5228	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5229		return -EINVAL;
5230
5231	if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
5232	    param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
5233	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
5234		return -EINVAL;
5235
5236	psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
5237	if (psta) {
5238		psta_data->aid = (u16)psta->aid;
5239		psta_data->capability = psta->capability;
5240		psta_data->flags = psta->flags;
5241
5242/*
5243		nonerp_set : BIT(0)
5244		no_short_slot_time_set : BIT(1)
5245		no_short_preamble_set : BIT(2)
5246		no_ht_gf_set : BIT(3)
5247		no_ht_set : BIT(4)
5248		ht_20mhz_set : BIT(5)
5249*/
5250
5251		psta_data->sta_set = ((psta->nonerp_set) |
5252				      (psta->no_short_slot_time_set << 1) |
5253				      (psta->no_short_preamble_set << 2) |
5254				      (psta->no_ht_gf_set << 3) |
5255				      (psta->no_ht_set << 4) |
5256				      (psta->ht_20mhz_set << 5));
5257		psta_data->tx_supp_rates_len =  psta->bssratelen;
5258		memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
5259		memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
5260		psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
5261		psta_data->rx_bytes = psta->sta_stats.rx_bytes;
5262		psta_data->rx_drops = psta->sta_stats.rx_drops;
5263		psta_data->tx_pkts = psta->sta_stats.tx_pkts;
5264		psta_data->tx_bytes = psta->sta_stats.tx_bytes;
5265		psta_data->tx_drops = psta->sta_stats.tx_drops;
5266	} else {
5267		ret = -1;
5268	}
5269
5270	return ret;
5271}
5272
5273static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
5274{
5275	int ret = 0;
5276	struct sta_info *psta = NULL;
5277	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5278	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5279	struct sta_priv *pstapriv = &padapter->stapriv;
5280
5281	DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
5282
5283	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5284		return -EINVAL;
5285
5286	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5287	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5288	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5289		return -EINVAL;
5290
5291	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5292	if (psta) {
5293		if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
5294			int wpa_ie_len;
5295			int copy_len;
5296
5297			wpa_ie_len = psta->wpa_ie[1];
5298			copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len+2);
5299			param->u.wpa_ie.len = copy_len;
5300			memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
5301		} else {
5302			DBG_88E("sta's wpa_ie is NONE\n");
5303		}
5304	} else {
5305		ret = -1;
5306	}
5307
5308	return ret;
5309}
5310
5311static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
5312{
5313	int ret = 0;
5314	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
5315	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5316	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5317	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
5318	int ie_len;
5319
5320	DBG_88E("%s, len =%d\n", __func__, len);
5321
5322	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5323		return -EINVAL;
5324
5325	ie_len = len-12-2;/*  12 = param header, 2:no packed */
5326
5327	if (pmlmepriv->wps_beacon_ie) {
5328		kfree(pmlmepriv->wps_beacon_ie);
5329		pmlmepriv->wps_beacon_ie = NULL;
5330	}
5331
5332	if (ie_len > 0) {
5333		pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
5334		pmlmepriv->wps_beacon_ie_len = ie_len;
5335		if (pmlmepriv->wps_beacon_ie == NULL) {
5336			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5337			return -EINVAL;
5338		}
5339
5340		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
5341
5342		update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
5343
5344		pmlmeext->bstart_bss = true;
5345	}
5346
5347	return ret;
5348}
5349
5350static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
5351{
5352	int ret = 0;
5353	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5354	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5355	int ie_len;
5356
5357	DBG_88E("%s, len =%d\n", __func__, len);
5358
5359	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5360		return -EINVAL;
5361
5362	ie_len = len-12-2;/*  12 = param header, 2:no packed */
5363
5364	if (pmlmepriv->wps_probe_resp_ie) {
5365		kfree(pmlmepriv->wps_probe_resp_ie);
5366		pmlmepriv->wps_probe_resp_ie = NULL;
5367	}
5368
5369	if (ie_len > 0) {
5370		pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
5371		pmlmepriv->wps_probe_resp_ie_len = ie_len;
5372		if (pmlmepriv->wps_probe_resp_ie == NULL) {
5373			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5374			return -EINVAL;
5375		}
5376		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
5377	}
5378
5379	return ret;
5380}
5381
5382static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
5383{
5384	int ret = 0;
5385	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5386	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5387	int ie_len;
5388
5389	DBG_88E("%s, len =%d\n", __func__, len);
5390
5391	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5392		return -EINVAL;
5393
5394	ie_len = len-12-2;/*  12 = param header, 2:no packed */
5395
5396	if (pmlmepriv->wps_assoc_resp_ie) {
5397		kfree(pmlmepriv->wps_assoc_resp_ie);
5398		pmlmepriv->wps_assoc_resp_ie = NULL;
5399	}
5400
5401	if (ie_len > 0) {
5402		pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
5403		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
5404		if (pmlmepriv->wps_assoc_resp_ie == NULL) {
5405			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5406			return -EINVAL;
5407		}
5408
5409		memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
5410	}
5411
5412	return ret;
5413}
5414
5415static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
5416{
5417	int ret = 0;
5418	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5419	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5420	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
5421	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5422
5423	u8 value;
5424
5425	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5426		return -EINVAL;
5427
5428	if (param->u.wpa_param.name != 0) /* dummy test... */
5429		DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
5430	value = param->u.wpa_param.value;
5431
5432	/* use the same definition of hostapd's ignore_broadcast_ssid */
5433	if (value != 1 && value != 2)
5434		value = 0;
5435	DBG_88E("%s value(%u)\n", __func__, value);
5436	pmlmeinfo->hidden_ssid_mode = value;
5437	return ret;
5438}
5439
5440static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
5441{
5442	int ret = 0;
5443	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5444	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5445
5446	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5447		return -EINVAL;
5448
5449	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5450	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5451	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5452		return -EINVAL;
5453	ret = rtw_acl_remove_sta(padapter, param->sta_addr);
5454	return ret;
5455}
5456
5457static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
5458{
5459	int ret = 0;
5460	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5461	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5462
5463	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5464		return -EINVAL;
5465
5466	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5467	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5468	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5469		return -EINVAL;
5470	ret = rtw_acl_add_sta(padapter, param->sta_addr);
5471	return ret;
5472}
5473
5474static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
5475{
5476	int ret = 0;
5477	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5478	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5479
5480	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5481		return -EINVAL;
5482
5483	rtw_set_macaddr_acl(padapter, param->u.mlme.command);
5484
5485	return ret;
5486}
5487
5488static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
5489{
5490	struct ieee_param *param;
5491	int ret = 0;
5492	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5493
5494	/*
5495	* this function is expect to call in master mode, which allows no power saving
5496	* so, we just check hw_init_completed
5497	*/
5498
5499	if (!padapter->hw_init_completed) {
5500		ret = -EPERM;
5501		goto out;
5502	}
5503
5504	if (!p->pointer) {
5505		ret = -EINVAL;
5506		goto out;
5507	}
5508
5509	param = (struct ieee_param *)rtw_malloc(p->length);
5510	if (param == NULL) {
5511		ret = -ENOMEM;
5512		goto out;
5513	}
5514
5515	if (copy_from_user(param, p->pointer, p->length)) {
5516		kfree(param);
5517		ret = -EFAULT;
5518		goto out;
5519	}
5520
5521	switch (param->cmd) {
5522	case RTL871X_HOSTAPD_FLUSH:
5523		ret = rtw_hostapd_sta_flush(dev);
5524		break;
5525	case RTL871X_HOSTAPD_ADD_STA:
5526		ret = rtw_add_sta(dev, param);
5527		break;
5528	case RTL871X_HOSTAPD_REMOVE_STA:
5529		ret = rtw_del_sta(dev, param);
5530		break;
5531	case RTL871X_HOSTAPD_SET_BEACON:
5532		ret = rtw_set_beacon(dev, param, p->length);
5533		break;
5534	case RTL871X_SET_ENCRYPTION:
5535		ret = rtw_set_encryption(dev, param, p->length);
5536		break;
5537	case RTL871X_HOSTAPD_GET_WPAIE_STA:
5538		ret = rtw_get_sta_wpaie(dev, param);
5539		break;
5540	case RTL871X_HOSTAPD_SET_WPS_BEACON:
5541		ret = rtw_set_wps_beacon(dev, param, p->length);
5542		break;
5543	case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
5544		ret = rtw_set_wps_probe_resp(dev, param, p->length);
5545		break;
5546	case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
5547		ret = rtw_set_wps_assoc_resp(dev, param, p->length);
5548		break;
5549	case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
5550		ret = rtw_set_hidden_ssid(dev, param, p->length);
5551		break;
5552	case RTL871X_HOSTAPD_GET_INFO_STA:
5553		ret = rtw_ioctl_get_sta_data(dev, param, p->length);
5554		break;
5555	case RTL871X_HOSTAPD_SET_MACADDR_ACL:
5556		ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
5557		break;
5558	case RTL871X_HOSTAPD_ACL_ADD_STA:
5559		ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
5560		break;
5561	case RTL871X_HOSTAPD_ACL_REMOVE_STA:
5562		ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
5563		break;
5564	default:
5565		DBG_88E("Unknown hostapd request: %d\n", param->cmd);
5566		ret = -EOPNOTSUPP;
5567		break;
5568	}
5569
5570	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
5571		ret = -EFAULT;
5572	kfree(param);
5573out:
5574	return ret;
5575}
5576#endif
5577
5578#include <rtw_android.h>
5579static int rtw_wx_set_priv(struct net_device *dev,
5580				struct iw_request_info *info,
5581				union iwreq_data *awrq,
5582				char *extra)
5583{
5584	int ret = 0;
5585	int len = 0;
5586	char *ext;
5587	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5588	struct iw_point *dwrq = (struct iw_point *)awrq;
5589
5590	if (dwrq->length == 0)
5591		return -EFAULT;
5592
5593	len = dwrq->length;
5594	ext = vmalloc(len);
5595	if (!ext)
5596		return -ENOMEM;
5597
5598	if (copy_from_user(ext, dwrq->pointer, len)) {
5599		vfree(ext);
5600		return -EFAULT;
5601	}
5602
5603	/* added for wps2.0 @20110524 */
5604	if (dwrq->flags == 0x8766 && len > 8) {
5605		u32 cp_sz;
5606		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5607		u8 *probereq_wpsie = ext;
5608		int probereq_wpsie_len = len;
5609		u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
5610
5611		if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
5612		    (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
5613			cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
5614
5615			pmlmepriv->wps_probe_req_ie_len = 0;
5616			kfree(pmlmepriv->wps_probe_req_ie);
5617			pmlmepriv->wps_probe_req_ie = NULL;
5618
5619			pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
5620			if (pmlmepriv->wps_probe_req_ie == NULL) {
5621				pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5622				ret =  -EINVAL;
5623				goto FREE_EXT;
5624			}
5625			memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
5626			pmlmepriv->wps_probe_req_ie_len = cp_sz;
5627		}
5628		goto FREE_EXT;
5629	}
5630
5631	if (len >= WEXT_CSCAN_HEADER_SIZE &&
5632	    !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
5633		ret = rtw_wx_set_scan(dev, info, awrq, ext);
5634		goto FREE_EXT;
5635	}
5636
5637FREE_EXT:
5638
5639	vfree(ext);
5640
5641	return ret;
5642}
5643
5644static int rtw_pm_set(struct net_device *dev,
5645			       struct iw_request_info *info,
5646			       union iwreq_data *wrqu, char *extra)
5647{
5648	int ret = 0;
5649	unsigned	mode = 0;
5650	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5651
5652	DBG_88E("[%s] extra = %s\n", __func__, extra);
5653
5654	if (!memcmp(extra, "lps =", 4)) {
5655		sscanf(extra+4, "%u", &mode);
5656		ret = rtw_pm_set_lps(padapter, mode);
5657	} else if (!memcmp(extra, "ips =", 4)) {
5658		sscanf(extra+4, "%u", &mode);
5659		ret = rtw_pm_set_ips(padapter, mode);
5660	} else {
5661		ret = -EINVAL;
5662	}
5663
5664	return ret;
5665}
5666
5667static int rtw_mp_efuse_get(struct net_device *dev,
5668			struct iw_request_info *info,
5669			union iwreq_data *wdata, char *extra)
5670{
5671	struct adapter *padapter = rtw_netdev_priv(dev);
5672	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
5673	struct hal_data_8188e *haldata = GET_HAL_DATA(padapter);
5674	struct efuse_hal *pEfuseHal;
5675	struct iw_point *wrqu;
5676
5677	u8 *PROMContent = pEEPROM->efuse_eeprom_data;
5678	u8 ips_mode = 0, lps_mode = 0;
5679	struct pwrctrl_priv *pwrctrlpriv;
5680	u8 *data = NULL;
5681	u8 *rawdata = NULL;
5682	char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
5683	u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
5684	u16 max_available_size = 0, raw_cursize = 0, raw_maxsize = 0;
5685	int err;
5686	u8 org_fw_iol = padapter->registrypriv.fw_iol;/*  0:Disable, 1:enable, 2:by usb speed */
5687
5688	wrqu = (struct iw_point *)wdata;
5689	pwrctrlpriv = &padapter->pwrctrlpriv;
5690	pEfuseHal = &haldata->EfuseHal;
5691
5692	err = 0;
5693	data = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
5694	if (data == NULL) {
5695		err = -ENOMEM;
5696		goto exit;
5697	}
5698	rawdata = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
5699	if (rawdata == NULL) {
5700		err = -ENOMEM;
5701		goto exit;
5702	}
5703
5704	if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
5705		err = -EFAULT;
5706		goto exit;
5707	}
5708	lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
5709	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
5710
5711	ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
5712	rtw_pm_set_ips(padapter, IPS_NONE);
5713
5714	pch = extra;
5715	DBG_88E("%s: in =%s\n", __func__, extra);
5716
5717	i = 0;
5718	/* mac 16 "00e04c871200" rmap, 00, 2 */
5719	while ((token = strsep(&pch, ",")) != NULL) {
5720		if (i > 2)
5721			break;
5722		tmp[i] = token;
5723		i++;
5724	}
5725	padapter->registrypriv.fw_iol = 0;/*  0:Disable, 1:enable, 2:by usb speed */
5726
5727	if (strcmp(tmp[0], "status") == 0) {
5728		sprintf(extra, "Load File efuse =%s, Load File MAC =%s", (pEEPROM->bloadfile_fail_flag ? "FAIL" : "OK"), (pEEPROM->bloadmac_fail_flag ? "FAIL" : "OK"));
5729
5730		  goto exit;
5731	} else if (strcmp(tmp[0], "filemap") == 0) {
5732		mapLen = EFUSE_MAP_SIZE;
5733
5734		sprintf(extra, "\n");
5735		for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5736			sprintf(extra, "%s0x%02x\t", extra, i);
5737			for (j = 0; j < 8; j++)
5738				sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
5739			sprintf(extra, "%s\t", extra);
5740			for (; j < 16; j++)
5741				sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
5742			sprintf(extra, "%s\n", extra);
5743		}
5744	} else if (strcmp(tmp[0], "realmap") == 0) {
5745		mapLen = EFUSE_MAP_SIZE;
5746		if (rtw_efuse_map_read(padapter, 0, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL) {
5747			DBG_88E("%s: read realmap Fail!!\n", __func__);
5748			err = -EFAULT;
5749			goto exit;
5750		}
5751
5752		sprintf(extra, "\n");
5753		for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5754			sprintf(extra, "%s0x%02x\t", extra, i);
5755			for (j = 0; j < 8; j++)
5756				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
5757			sprintf(extra, "%s\t", extra);
5758			for (; j < 16; j++)
5759				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
5760			sprintf(extra, "%s\n", extra);
5761		}
5762	} else if (strcmp(tmp[0], "rmap") == 0) {
5763		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
5764			DBG_88E("%s: rmap Fail!! Parameters error!\n", __func__);
5765			err = -EINVAL;
5766			goto exit;
5767		}
5768
5769		/*  rmap addr cnts */
5770		addr = simple_strtoul(tmp[1], &ptmp, 16);
5771		DBG_88E("%s: addr =%x\n", __func__, addr);
5772
5773		cnts = simple_strtoul(tmp[2], &ptmp, 10);
5774		if (cnts == 0) {
5775			DBG_88E("%s: rmap Fail!! cnts error!\n", __func__);
5776			err = -EINVAL;
5777			goto exit;
5778		}
5779		DBG_88E("%s: cnts =%d\n", __func__, cnts);
5780
5781		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5782		if ((addr + cnts) > max_available_size) {
5783			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5784			err = -EINVAL;
5785			goto exit;
5786		}
5787
5788		if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5789			DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
5790			err = -EFAULT;
5791			goto exit;
5792		}
5793
5794		*extra = 0;
5795		for (i = 0; i < cnts; i++)
5796			sprintf(extra, "%s0x%02X ", extra, data[i]);
5797	} else if (strcmp(tmp[0], "realraw") == 0) {
5798		addr = 0;
5799		mapLen = EFUSE_MAX_SIZE;
5800		if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) {
5801			DBG_88E("%s: rtw_efuse_access Fail!!\n", __func__);
5802			err = -EFAULT;
5803			goto exit;
5804		}
5805
5806		sprintf(extra, "\n");
5807		for (i = 0; i < mapLen; i++) {
5808			sprintf(extra, "%s%02X", extra, rawdata[i]);
5809
5810			if ((i & 0xF) == 0xF)
5811				sprintf(extra, "%s\n", extra);
5812			else if ((i & 0x7) == 0x7)
5813				sprintf(extra, "%s\t", extra);
5814			else
5815				sprintf(extra, "%s ", extra);
5816		}
5817	} else if (strcmp(tmp[0], "mac") == 0) {
5818		cnts = 6;
5819
5820		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5821		if ((addr + cnts) > max_available_size) {
5822			DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5823			err = -EFAULT;
5824			goto exit;
5825		}
5826
5827		if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5828			DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
5829			err = -EFAULT;
5830			goto exit;
5831		}
5832
5833		*extra = 0;
5834		for (i = 0; i < cnts; i++) {
5835			sprintf(extra, "%s%02X", extra, data[i]);
5836			if (i != (cnts-1))
5837				sprintf(extra, "%s:", extra);
5838		}
5839	} else if (strcmp(tmp[0], "vidpid") == 0) {
5840		cnts = 4;
5841
5842		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5843		if ((addr + cnts) > max_available_size) {
5844			DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5845			err = -EFAULT;
5846			goto exit;
5847		}
5848		if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5849			DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
5850			err = -EFAULT;
5851			goto exit;
5852		}
5853
5854		*extra = 0;
5855		for (i = 0; i < cnts; i++) {
5856			sprintf(extra, "%s0x%02X", extra, data[i]);
5857			if (i != (cnts-1))
5858				sprintf(extra, "%s,", extra);
5859		}
5860	} else if (strcmp(tmp[0], "ableraw") == 0) {
5861		efuse_GetCurrentSize(padapter, &raw_cursize);
5862		raw_maxsize = efuse_GetMaxSize(padapter);
5863		sprintf(extra, "[available raw size] = %d bytes", raw_maxsize-raw_cursize);
5864	} else if (strcmp(tmp[0], "btfmap") == 0) {
5865		mapLen = EFUSE_BT_MAX_MAP_LEN;
5866		if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
5867			DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
5868			err = -EFAULT;
5869			goto exit;
5870		}
5871
5872		sprintf(extra, "\n");
5873		for (i = 0; i < 512; i += 16) {
5874			/*  set 512 because the iwpriv's extra size have limit 0x7FF */
5875			sprintf(extra, "%s0x%03x\t", extra, i);
5876			for (j = 0; j < 8; j++)
5877				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5878			sprintf(extra, "%s\t", extra);
5879			for (; j < 16; j++)
5880				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5881			sprintf(extra, "%s\n", extra);
5882		}
5883	} else if (strcmp(tmp[0], "btbmap") == 0) {
5884		mapLen = EFUSE_BT_MAX_MAP_LEN;
5885		if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
5886			DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
5887			err = -EFAULT;
5888			goto exit;
5889		}
5890
5891		sprintf(extra, "\n");
5892		for (i = 512; i < 1024; i += 16) {
5893			sprintf(extra, "%s0x%03x\t", extra, i);
5894			for (j = 0; j < 8; j++)
5895				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5896			sprintf(extra, "%s\t", extra);
5897			for (; j < 16; j++)
5898				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
5899			sprintf(extra, "%s\n", extra);
5900		}
5901	} else if (strcmp(tmp[0], "btrmap") == 0) {
5902		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
5903			err = -EINVAL;
5904			goto exit;
5905		}
5906
5907		/*  rmap addr cnts */
5908		addr = simple_strtoul(tmp[1], &ptmp, 16);
5909		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
5910
5911		cnts = simple_strtoul(tmp[2], &ptmp, 10);
5912		if (cnts == 0) {
5913			DBG_88E("%s: btrmap Fail!! cnts error!\n", __func__);
5914			err = -EINVAL;
5915			goto exit;
5916		}
5917		DBG_88E("%s: cnts =%d\n", __func__, cnts);
5918
5919		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
5920		if ((addr + cnts) > max_available_size) {
5921			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5922			err = -EFAULT;
5923			goto exit;
5924		}
5925
5926		if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5927			DBG_88E("%s: rtw_BT_efuse_map_read error!!\n", __func__);
5928			err = -EFAULT;
5929			goto exit;
5930		}
5931
5932		*extra = 0;
5933		for (i = 0; i < cnts; i++)
5934			sprintf(extra, "%s 0x%02X ", extra, data[i]);
5935	} else if (strcmp(tmp[0], "btffake") == 0) {
5936		sprintf(extra, "\n");
5937		for (i = 0; i < 512; i += 16) {
5938			sprintf(extra, "%s0x%03x\t", extra, i);
5939			for (j = 0; j < 8; j++)
5940				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5941			sprintf(extra, "%s\t", extra);
5942			for (; j < 16; j++)
5943				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5944			sprintf(extra, "%s\n", extra);
5945		}
5946	} else if (strcmp(tmp[0], "btbfake") == 0) {
5947		sprintf(extra, "\n");
5948		for (i = 512; i < 1024; i += 16) {
5949			sprintf(extra, "%s0x%03x\t", extra, i);
5950			for (j = 0; j < 8; j++)
5951				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5952			sprintf(extra, "%s\t", extra);
5953			for (; j < 16; j++)
5954				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5955			sprintf(extra, "%s\n", extra);
5956		}
5957	} else if (strcmp(tmp[0], "wlrfkmap") == 0) {
5958		sprintf(extra, "\n");
5959		for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5960			sprintf(extra, "%s0x%02x\t", extra, i);
5961			for (j = 0; j < 8; j++)
5962				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
5963			sprintf(extra, "%s\t", extra);
5964			for (; j < 16; j++)
5965				sprintf(extra, "%s %02X", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
5966			sprintf(extra, "%s\n", extra);
5967		}
5968	} else {
5969		 sprintf(extra, "Command not found!");
5970	}
5971
5972exit:
5973	kfree(data);
5974	kfree(rawdata);
5975	if (!err)
5976		wrqu->length = strlen(extra);
5977
5978	rtw_pm_set_ips(padapter, ips_mode);
5979	rtw_pm_set_lps(padapter, lps_mode);
5980	padapter->registrypriv.fw_iol = org_fw_iol;/*  0:Disable, 1:enable, 2:by usb speed */
5981	return err;
5982}
5983
5984static int rtw_mp_efuse_set(struct net_device *dev,
5985			struct iw_request_info *info,
5986			union iwreq_data *wdata, char *extra)
5987{
5988	struct adapter *padapter;
5989	struct pwrctrl_priv *pwrctrlpriv;
5990	struct hal_data_8188e *haldata;
5991	struct efuse_hal *pEfuseHal;
5992
5993	u8 ips_mode = 0, lps_mode = 0;
5994	u32 i, jj, kk;
5995	u8 *setdata = NULL;
5996	u8 *ShadowMapBT = NULL;
5997	u8 *ShadowMapWiFi = NULL;
5998	u8 *setrawdata = NULL;
5999	char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
6000	u16 addr = 0, cnts = 0, max_available_size = 0;
6001	int err;
6002
6003	padapter = rtw_netdev_priv(dev);
6004	pwrctrlpriv = &padapter->pwrctrlpriv;
6005	haldata = GET_HAL_DATA(padapter);
6006	pEfuseHal = &haldata->EfuseHal;
6007	err = 0;
6008	setdata = _rtw_zmalloc(1024);
6009	if (setdata == NULL) {
6010		err = -ENOMEM;
6011		goto exit;
6012	}
6013	ShadowMapBT = _rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
6014	if (ShadowMapBT == NULL) {
6015		err = -ENOMEM;
6016		goto exit;
6017	}
6018	ShadowMapWiFi = _rtw_malloc(EFUSE_MAP_SIZE);
6019	if (ShadowMapWiFi == NULL) {
6020		err = -ENOMEM;
6021		goto exit;
6022	}
6023	setrawdata = _rtw_malloc(EFUSE_MAX_SIZE);
6024	if (setrawdata == NULL) {
6025		err = -ENOMEM;
6026		goto exit;
6027	}
6028
6029	lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
6030	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
6031
6032	ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
6033	rtw_pm_set_ips(padapter, IPS_NONE);
6034
6035	pch = extra;
6036	DBG_88E("%s: in =%s\n", __func__, extra);
6037
6038	i = 0;
6039	while ((token = strsep(&pch, ",")) != NULL) {
6040		if (i > 2)
6041			break;
6042		tmp[i] = token;
6043		i++;
6044	}
6045
6046	/*  tmp[0],[1],[2] */
6047	/*  wmap, addr, 00e04c871200 */
6048	if (strcmp(tmp[0], "wmap") == 0) {
6049		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6050			err = -EINVAL;
6051			goto exit;
6052		}
6053
6054		addr = simple_strtoul(tmp[1], &ptmp, 16);
6055		addr &= 0xFFF;
6056
6057		cnts = strlen(tmp[2]);
6058		if (cnts%2) {
6059			err = -EINVAL;
6060			goto exit;
6061		}
6062		cnts /= 2;
6063		if (cnts == 0) {
6064			err = -EINVAL;
6065			goto exit;
6066		}
6067
6068		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6069		DBG_88E("%s: cnts =%d\n", __func__, cnts);
6070		DBG_88E("%s: map data =%s\n", __func__, tmp[2]);
6071
6072		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6073			setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6074		/* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
6075		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
6076		if ((addr+cnts) > max_available_size) {
6077			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6078			err = -EFAULT;
6079			goto exit;
6080		}
6081
6082		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6083			DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6084			err = -EFAULT;
6085			goto exit;
6086		}
6087	} else if (strcmp(tmp[0], "wraw") == 0) {
6088		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6089			err = -EINVAL;
6090			goto exit;
6091		}
6092
6093		addr = simple_strtoul(tmp[1], &ptmp, 16);
6094		addr &= 0xFFF;
6095
6096		cnts = strlen(tmp[2]);
6097		if (cnts%2) {
6098			err = -EINVAL;
6099			goto exit;
6100		}
6101		cnts /= 2;
6102		if (cnts == 0) {
6103			err = -EINVAL;
6104			goto exit;
6105		}
6106
6107		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6108		DBG_88E("%s: cnts =%d\n", __func__, cnts);
6109		DBG_88E("%s: raw data =%s\n", __func__, tmp[2]);
6110
6111		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6112			setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6113
6114		if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
6115			DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
6116			err = -EFAULT;
6117			goto exit;
6118		}
6119	} else if (strcmp(tmp[0], "mac") == 0) {
6120		if (tmp[1] == NULL) {
6121			err = -EINVAL;
6122			goto exit;
6123		}
6124
6125		/* mac, 00e04c871200 */
6126		addr = EEPROM_MAC_ADDR_88EU;
6127		cnts = strlen(tmp[1]);
6128		if (cnts%2) {
6129			err = -EINVAL;
6130			goto exit;
6131		}
6132		cnts /= 2;
6133		if (cnts == 0) {
6134			err = -EINVAL;
6135			goto exit;
6136		}
6137		if (cnts > 6) {
6138			DBG_88E("%s: error data for mac addr =\"%s\"\n", __func__, tmp[1]);
6139			err = -EFAULT;
6140			goto exit;
6141		}
6142
6143		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6144		DBG_88E("%s: cnts =%d\n", __func__, cnts);
6145		DBG_88E("%s: MAC address =%s\n", __func__, tmp[1]);
6146
6147		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6148			setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
6149		/* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
6150		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
6151		if ((addr+cnts) > max_available_size) {
6152			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6153			err = -EFAULT;
6154			goto exit;
6155		}
6156
6157		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6158			DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6159			err = -EFAULT;
6160			goto exit;
6161		}
6162	} else if (strcmp(tmp[0], "vidpid") == 0) {
6163		if (tmp[1] == NULL) {
6164			err = -EINVAL;
6165			goto exit;
6166		}
6167
6168		/*  pidvid, da0b7881 */
6169		addr = EEPROM_VID_88EE;
6170		cnts = strlen(tmp[1]);
6171		if (cnts%2) {
6172			err = -EINVAL;
6173			goto exit;
6174		}
6175		cnts /= 2;
6176		if (cnts == 0) {
6177			err = -EINVAL;
6178			goto exit;
6179		}
6180
6181		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6182		DBG_88E("%s: cnts =%d\n", __func__, cnts);
6183		DBG_88E("%s: VID/PID =%s\n", __func__, tmp[1]);
6184
6185		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6186			setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
6187
6188		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6189		if ((addr+cnts) > max_available_size) {
6190			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6191			err = -EFAULT;
6192			goto exit;
6193		}
6194
6195		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6196			DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6197			err = -EFAULT;
6198			goto exit;
6199		}
6200	} else if (strcmp(tmp[0], "btwmap") == 0) {
6201		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6202			err = -EINVAL;
6203			goto exit;
6204		}
6205
6206		addr = simple_strtoul(tmp[1], &ptmp, 16);
6207		addr &= 0xFFF;
6208
6209		cnts = strlen(tmp[2]);
6210		if (cnts%2) {
6211			err = -EINVAL;
6212			goto exit;
6213		}
6214		cnts /= 2;
6215		if (cnts == 0) {
6216			err = -EINVAL;
6217			goto exit;
6218		}
6219
6220		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6221		DBG_88E("%s: cnts =%d\n", __func__, cnts);
6222		DBG_88E("%s: BT data =%s\n", __func__, tmp[2]);
6223
6224		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6225			setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6226
6227		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6228		if ((addr+cnts) > max_available_size) {
6229			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6230			err = -EFAULT;
6231			goto exit;
6232		}
6233
6234		if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6235			DBG_88E("%s: rtw_BT_efuse_map_write error!!\n", __func__);
6236			err = -EFAULT;
6237			goto exit;
6238		}
6239	} else if (strcmp(tmp[0], "btwfake") == 0) {
6240		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6241			err = -EINVAL;
6242			goto exit;
6243		}
6244
6245		addr = simple_strtoul(tmp[1], &ptmp, 16);
6246		addr &= 0xFFF;
6247
6248		cnts = strlen(tmp[2]);
6249		if (cnts%2) {
6250			err = -EINVAL;
6251			goto exit;
6252		}
6253		cnts /= 2;
6254		if (cnts == 0) {
6255			err = -EINVAL;
6256			goto exit;
6257		}
6258
6259		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6260		DBG_88E("%s: cnts =%d\n", __func__, cnts);
6261		DBG_88E("%s: BT tmp data =%s\n", __func__, tmp[2]);
6262
6263		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6264			pEfuseHal->fakeBTEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6265	} else if (strcmp(tmp[0], "btdumpfake") == 0) {
6266		if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS) {
6267			DBG_88E("%s: BT read all map success\n", __func__);
6268		} else {
6269			DBG_88E("%s: BT read all map Fail!\n", __func__);
6270			err = -EFAULT;
6271		}
6272	} else if (strcmp(tmp[0], "wldumpfake") == 0) {
6273		if (rtw_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN,  pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS) {
6274			DBG_88E("%s: BT read all map success\n", __func__);
6275		} else {
6276			DBG_88E("%s: BT read all map  Fail\n", __func__);
6277			err = -EFAULT;
6278		}
6279	} else if (strcmp(tmp[0], "btfk2map") == 0) {
6280		memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
6281
6282		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6283		if (max_available_size < 1) {
6284			err = -EFAULT;
6285			goto exit;
6286		}
6287
6288		if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) {
6289			DBG_88E("%s: rtw_BT_efuse_map_write error!\n", __func__);
6290			err = -EFAULT;
6291			goto exit;
6292		}
6293	} else if (strcmp(tmp[0], "wlfk2map") == 0) {
6294		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
6295		if (max_available_size < 1) {
6296			err = -EFAULT;
6297			goto exit;
6298		}
6299
6300		if (rtw_efuse_map_write(padapter, 0x00, EFUSE_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
6301			DBG_88E("%s: rtw_efuse_map_write error!\n", __func__);
6302			err = -EFAULT;
6303			goto exit;
6304		}
6305	} else if (strcmp(tmp[0], "wlwfake") == 0) {
6306		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6307			err = -EINVAL;
6308			goto exit;
6309		}
6310
6311		addr = simple_strtoul(tmp[1], &ptmp, 16);
6312		addr &= 0xFFF;
6313
6314		cnts = strlen(tmp[2]);
6315		if (cnts%2) {
6316			err = -EINVAL;
6317			goto exit;
6318		}
6319		cnts /= 2;
6320		if (cnts == 0) {
6321			err = -EINVAL;
6322			goto exit;
6323		}
6324
6325		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6326		DBG_88E("%s: cnts =%d\n", __func__, cnts);
6327		DBG_88E("%s: map tmp data =%s\n", __func__, tmp[2]);
6328
6329		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6330			pEfuseHal->fakeEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6331	}
6332
6333exit:
6334	kfree(setdata);
6335	kfree(ShadowMapBT);
6336	kfree(ShadowMapWiFi);
6337	kfree(setrawdata);
6338
6339	rtw_pm_set_ips(padapter, ips_mode);
6340	rtw_pm_set_lps(padapter, lps_mode);
6341
6342	return err;
6343}
6344
6345/*
6346 * Input Format: %s,%d,%d
6347 *	%s is width, could be
6348 *		"b" for 1 byte
6349 *		"w" for WORD (2 bytes)
6350 *		"dw" for DWORD (4 bytes)
6351 *	1st %d is address(offset)
6352 *	2st %d is data to write
6353 */
6354static int rtw_mp_write_reg(struct net_device *dev,
6355			struct iw_request_info *info,
6356			struct iw_point *wrqu, char *extra)
6357{
6358	char *pch, *pnext, *ptmp;
6359	char *width_str;
6360	char width;
6361	u32 addr, data;
6362	int ret;
6363	struct adapter *padapter = rtw_netdev_priv(dev);
6364
6365	pch = extra;
6366	pnext = strpbrk(pch, ",.-");
6367	if (pnext == NULL)
6368		return -EINVAL;
6369	*pnext = 0;
6370	width_str = pch;
6371
6372	pch = pnext + 1;
6373	pnext = strpbrk(pch, ",.-");
6374	if (pnext == NULL)
6375		return -EINVAL;
6376	*pnext = 0;
6377	addr = simple_strtoul(pch, &ptmp, 16);
6378	if (addr > 0x3FFF)
6379		return -EINVAL;
6380
6381	pch = pnext + 1;
6382	if ((pch - extra) >= wrqu->length)
6383		return -EINVAL;
6384	data = simple_strtoul(pch, &ptmp, 16);
6385
6386	ret = 0;
6387	width = width_str[0];
6388	switch (width) {
6389	case 'b':
6390		/*  1 byte */
6391		if (data > 0xFF) {
6392			ret = -EINVAL;
6393			break;
6394		}
6395		rtw_write8(padapter, addr, data);
6396		break;
6397	case 'w':
6398		/*  2 bytes */
6399		if (data > 0xFFFF) {
6400			ret = -EINVAL;
6401			break;
6402		}
6403		rtw_write16(padapter, addr, data);
6404		break;
6405	case 'd':
6406		/*  4 bytes */
6407		rtw_write32(padapter, addr, data);
6408		break;
6409	default:
6410		ret = -EINVAL;
6411		break;
6412	}
6413
6414	return ret;
6415}
6416
6417/*
6418 * Input Format: %s,%d
6419 *	%s is width, could be
6420 *		"b" for 1 byte
6421 *		"w" for WORD (2 bytes)
6422 *		"dw" for DWORD (4 bytes)
6423 *	%d is address(offset)
6424 *
6425 * Return:
6426 *	%d for data readed
6427 */
6428static int rtw_mp_read_reg(struct net_device *dev,
6429			struct iw_request_info *info,
6430			struct iw_point *wrqu, char *extra)
6431{
6432	struct adapter *padapter = rtw_netdev_priv(dev);
6433	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
6434	char *pch, *pnext, *ptmp;
6435	char *width_str;
6436	char width;
6437	char data[20], tmp[20];
6438	u32 addr;
6439	u32 ret, i = 0, j = 0, strtout = 0;
6440
6441	if (!input)
6442		return -ENOMEM;
6443	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6444		kfree(input);
6445		return -EFAULT;
6446	}
6447	_rtw_memset(data, 0, 20);
6448	_rtw_memset(tmp, 0, 20);
6449	_rtw_memset(extra, 0, wrqu->length);
6450
6451	pch = input;
6452	pnext = strpbrk(pch, ",.-");
6453	if (pnext == NULL) {
6454		kfree(input);
6455		return -EINVAL;
6456	}
6457	*pnext = 0;
6458	width_str = pch;
6459
6460	pch = pnext + 1;
6461	if ((pch - input) >= wrqu->length) {
6462		kfree(input);
6463		return -EINVAL;
6464	}
6465	kfree(input);
6466	addr = simple_strtoul(pch, &ptmp, 16);
6467	if (addr > 0x3FFF)
6468		return -EINVAL;
6469
6470	ret = 0;
6471	width = width_str[0];
6472	switch (width) {
6473	case 'b':
6474		/*  1 byte */
6475		sprintf(extra, "%d\n",  rtw_read8(padapter, addr));
6476		wrqu->length = strlen(extra);
6477		break;
6478	case 'w':
6479		/*  2 bytes */
6480		sprintf(data, "%04x\n", rtw_read16(padapter, addr));
6481		for (i = 0; i <= strlen(data); i++) {
6482			if (i%2 == 0) {
6483				tmp[j] = ' ';
6484				j++;
6485			}
6486			if (data[i] != '\0')
6487				tmp[j] = data[i];
6488			j++;
6489		}
6490		pch = tmp;
6491		DBG_88E("pch =%s", pch);
6492
6493		while (*pch != '\0') {
6494			pnext = strpbrk(pch, " ");
6495			if (!pnext)
6496				break;
6497
6498			pnext++;
6499			if (*pnext != '\0') {
6500				  strtout = simple_strtoul(pnext, &ptmp, 16);
6501				  sprintf(extra, "%s %d", extra, strtout);
6502			} else {
6503				  break;
6504			}
6505			pch = pnext;
6506		}
6507		wrqu->length = 6;
6508		break;
6509	case 'd':
6510		/*  4 bytes */
6511		sprintf(data, "%08x", rtw_read32(padapter, addr));
6512		/* add read data format blank */
6513		for (i = 0; i <= strlen(data); i++) {
6514			if (i%2 == 0) {
6515				tmp[j] = ' ';
6516				j++;
6517			}
6518			if (data[i] != '\0')
6519				tmp[j] = data[i];
6520
6521			j++;
6522		}
6523		pch = tmp;
6524		DBG_88E("pch =%s", pch);
6525
6526		while (*pch != '\0') {
6527			pnext = strpbrk(pch, " ");
6528			if (!pnext)
6529				break;
6530			pnext++;
6531			if (*pnext != '\0') {
6532				strtout = simple_strtoul(pnext, &ptmp, 16);
6533				sprintf(extra, "%s %d", extra, strtout);
6534			} else {
6535				break;
6536			}
6537			pch = pnext;
6538		}
6539		wrqu->length = strlen(extra);
6540		break;
6541	default:
6542		wrqu->length = 0;
6543		ret = -EINVAL;
6544		break;
6545	}
6546
6547	return ret;
6548}
6549
6550/*
6551 * Input Format: %d,%x,%x
6552 *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
6553 *	1st %x is address(offset)
6554 *	2st %x is data to write
6555 */
6556 static int rtw_mp_write_rf(struct net_device *dev,
6557			    struct iw_request_info *info,
6558			    struct iw_point *wrqu, char *extra)
6559{
6560	u32 path, addr, data;
6561	int ret;
6562	struct adapter *padapter = rtw_netdev_priv(dev);
6563
6564	ret = sscanf(extra, "%d,%x,%x", &path, &addr, &data);
6565	if (ret < 3)
6566		return -EINVAL;
6567
6568	if (path >= MAX_RF_PATH_NUMS)
6569		return -EINVAL;
6570	if (addr > 0xFF)
6571		return -EINVAL;
6572	if (data > 0xFFFFF)
6573		return -EINVAL;
6574
6575	_rtw_memset(extra, 0, wrqu->length);
6576
6577	write_rfreg(padapter, path, addr, data);
6578
6579	sprintf(extra, "write_rf completed\n");
6580	wrqu->length = strlen(extra);
6581
6582	return 0;
6583}
6584
6585/*
6586 * Input Format: %d,%x
6587 *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
6588 *	%x is address(offset)
6589 *
6590 * Return:
6591 *	%d for data readed
6592 */
6593static int rtw_mp_read_rf(struct net_device *dev,
6594			struct iw_request_info *info,
6595			struct iw_point *wrqu, char *extra)
6596{
6597	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
6598	char *pch, *pnext, *ptmp;
6599	char data[20], tmp[20];
6600	u32 path, addr;
6601	u32 ret, i = 0, j = 0, strtou = 0;
6602	struct adapter *padapter = rtw_netdev_priv(dev);
6603
6604	if (!input)
6605		return -ENOMEM;
6606	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6607		kfree(input);
6608		return -EFAULT;
6609	}
6610	ret = sscanf(input, "%d,%x", &path, &addr);
6611	kfree(input);
6612	if (ret < 2)
6613		return -EINVAL;
6614
6615	if (path >= MAX_RF_PATH_NUMS)
6616		return -EINVAL;
6617	if (addr > 0xFF)
6618		return -EINVAL;
6619
6620	_rtw_memset(extra, 0, wrqu->length);
6621
6622	sprintf(data, "%08x", read_rfreg(padapter, path, addr));
6623	/* add read data format blank */
6624	for (i = 0; i <= strlen(data); i++) {
6625		if (i%2 == 0) {
6626			tmp[j] = ' ';
6627			j++;
6628		}
6629		tmp[j] = data[i];
6630		j++;
6631	}
6632	pch = tmp;
6633	DBG_88E("pch =%s", pch);
6634
6635	while (*pch != '\0') {
6636		pnext = strpbrk(pch, " ");
6637		pnext++;
6638		if (*pnext != '\0') {
6639			  strtou = simple_strtoul(pnext, &ptmp, 16);
6640			  sprintf(extra, "%s %d", extra, strtou);
6641		} else {
6642			  break;
6643		}
6644		pch = pnext;
6645	}
6646	wrqu->length = strlen(extra);
6647	return 0;
6648}
6649
6650static int rtw_mp_start(struct net_device *dev,
6651			struct iw_request_info *info,
6652			struct iw_point *wrqu, char *extra)
6653{
6654	struct adapter *padapter = rtw_netdev_priv(dev);
6655
6656	if (padapter->registrypriv.mp_mode == 0) {
6657		padapter->registrypriv.mp_mode = 1;
6658
6659		rtw_pm_set_ips(padapter, IPS_NONE);
6660		LeaveAllPowerSaveMode(padapter);
6661
6662		MPT_InitializeAdapter(padapter, 1);
6663	}
6664	if (padapter->registrypriv.mp_mode == 0)
6665		return -EPERM;
6666	if (padapter->mppriv.mode == MP_OFF) {
6667		if (mp_start_test(padapter) == _FAIL)
6668			return -EPERM;
6669		padapter->mppriv.mode = MP_ON;
6670	}
6671	return 0;
6672}
6673
6674static int rtw_mp_stop(struct net_device *dev,
6675			struct iw_request_info *info,
6676			struct iw_point *wrqu, char *extra)
6677{
6678	struct adapter *padapter = rtw_netdev_priv(dev);
6679
6680	if (padapter->registrypriv.mp_mode == 1) {
6681		MPT_DeInitAdapter(padapter);
6682		padapter->registrypriv.mp_mode = 0;
6683	}
6684
6685	if (padapter->mppriv.mode != MP_OFF) {
6686		mp_stop_test(padapter);
6687		padapter->mppriv.mode = MP_OFF;
6688	}
6689
6690	return 0;
6691}
6692
6693extern int wifirate2_ratetbl_inx(unsigned char rate);
6694
6695static int rtw_mp_rate(struct net_device *dev,
6696			struct iw_request_info *info,
6697			struct iw_point *wrqu, char *extra)
6698{
6699	u32 rate = MPT_RATE_1M;
6700	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
6701	struct adapter *padapter = rtw_netdev_priv(dev);
6702
6703	if (!input)
6704		return -ENOMEM;
6705	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6706		kfree(input);
6707		return -EFAULT;
6708	}
6709	rate = rtw_atoi(input);
6710	sprintf(extra, "Set data rate to %d", rate);
6711	kfree(input);
6712	if (rate <= 0x7f)
6713		rate = wifirate2_ratetbl_inx((u8)rate);
6714	else
6715		rate = (rate-0x80+MPT_RATE_MCS0);
6716
6717	if (rate >= MPT_RATE_LAST)
6718		return -EINVAL;
6719
6720	padapter->mppriv.rateidx = rate;
6721	Hal_SetDataRate(padapter);
6722
6723	wrqu->length = strlen(extra) + 1;
6724	return 0;
6725}
6726
6727static int rtw_mp_channel(struct net_device *dev,
6728			struct iw_request_info *info,
6729			struct iw_point *wrqu, char *extra)
6730{
6731	struct adapter *padapter = rtw_netdev_priv(dev);
6732	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
6733	u32	channel = 1;
6734
6735	if (!input)
6736		return -ENOMEM;
6737	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6738		kfree(input);
6739		return -EFAULT;
6740	}
6741	channel = rtw_atoi(input);
6742	sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel, channel);
6743
6744	padapter->mppriv.channel = channel;
6745	Hal_SetChannel(padapter);
6746
6747	wrqu->length = strlen(extra) + 1;
6748	kfree(input);
6749	return 0;
6750}
6751
6752static int rtw_mp_bandwidth(struct net_device *dev,
6753			struct iw_request_info *info,
6754			struct iw_point *wrqu, char *extra)
6755{
6756	u32 bandwidth = 0, sg = 0;
6757	struct adapter *padapter = rtw_netdev_priv(dev);
6758
6759	sscanf(extra, "40M =%d, shortGI =%d", &bandwidth, &sg);
6760
6761	if (bandwidth != HT_CHANNEL_WIDTH_40)
6762		bandwidth = HT_CHANNEL_WIDTH_20;
6763
6764	padapter->mppriv.bandwidth = (u8)bandwidth;
6765	padapter->mppriv.preamble = sg;
6766
6767	SetBandwidth(padapter);
6768
6769	return 0;
6770}
6771
6772static int rtw_mp_txpower(struct net_device *dev,
6773			struct iw_request_info *info,
6774			struct iw_point *wrqu, char *extra)
6775{
6776	u32		idx_a = 0, idx_b = 0;
6777	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
6778	struct adapter *padapter = rtw_netdev_priv(dev);
6779
6780	if (!input)
6781		return -ENOMEM;
6782	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6783		kfree(input);
6784		return -EFAULT;
6785	}
6786	sscanf(input, "patha =%d, pathb =%d", &idx_a, &idx_b);
6787
6788	sprintf(extra, "Set power level path_A:%d path_B:%d", idx_a, idx_b);
6789	padapter->mppriv.txpoweridx = (u8)idx_a;
6790	padapter->mppriv.txpoweridx_b = (u8)idx_b;
6791	padapter->mppriv.bSetTxPower = 1;
6792	Hal_SetAntennaPathPower(padapter);
6793
6794	wrqu->length = strlen(extra) + 1;
6795	kfree(input);
6796	return 0;
6797}
6798
6799static int rtw_mp_ant_tx(struct net_device *dev,
6800			struct iw_request_info *info,
6801			struct iw_point *wrqu, char *extra)
6802{
6803	u8 i;
6804	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
6805	u16 antenna = 0;
6806	struct adapter *padapter = rtw_netdev_priv(dev);
6807
6808	if (!input)
6809		return -ENOMEM;
6810	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6811		kfree(input);
6812		return -EFAULT;
6813	}
6814
6815	sprintf(extra, "switch Tx antenna to %s", input);
6816
6817	for (i = 0; i < strlen(input); i++) {
6818		switch (input[i]) {
6819		case 'a':
6820			antenna |= ANTENNA_A;
6821			break;
6822		case 'b':
6823			antenna |= ANTENNA_B;
6824			break;
6825		}
6826	}
6827	padapter->mppriv.antenna_tx = antenna;
6828
6829	Hal_SetAntenna(padapter);
6830
6831	wrqu->length = strlen(extra) + 1;
6832	kfree(input);
6833	return 0;
6834}
6835
6836static int rtw_mp_ant_rx(struct net_device *dev,
6837			struct iw_request_info *info,
6838			struct iw_point *wrqu, char *extra)
6839{
6840	u8 i;
6841	u16 antenna = 0;
6842	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
6843	struct adapter *padapter = rtw_netdev_priv(dev);
6844
6845	if (!input)
6846		return -ENOMEM;
6847	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6848		kfree(input);
6849		return -EFAULT;
6850	}
6851	_rtw_memset(extra, 0, wrqu->length);
6852
6853	sprintf(extra, "switch Rx antenna to %s", input);
6854
6855	for (i = 0; i < strlen(input); i++) {
6856		switch (input[i]) {
6857		case 'a':
6858			antenna |= ANTENNA_A;
6859			break;
6860		case 'b':
6861			antenna |= ANTENNA_B;
6862			break;
6863		}
6864	}
6865
6866	padapter->mppriv.antenna_rx = antenna;
6867	Hal_SetAntenna(padapter);
6868	wrqu->length = strlen(extra);
6869	kfree(input);
6870	return 0;
6871}
6872
6873static int rtw_mp_ctx(struct net_device *dev,
6874			struct iw_request_info *info,
6875			struct iw_point *wrqu, char *extra)
6876{
6877	u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
6878	u32 bStartTest = 1;
6879	u32 count = 0;
6880	struct mp_priv *pmp_priv;
6881	struct pkt_attrib *pattrib;
6882
6883	struct adapter *padapter = rtw_netdev_priv(dev);
6884
6885	pmp_priv = &padapter->mppriv;
6886
6887	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
6888			return -EFAULT;
6889
6890	DBG_88E("%s: in =%s\n", __func__, extra);
6891
6892	countPkTx = strncmp(extra, "count =", 5); /*  strncmp true is 0 */
6893	cotuTx = strncmp(extra, "background", 20);
6894	CarrSprTx = strncmp(extra, "background, cs", 20);
6895	scTx = strncmp(extra, "background, sc", 20);
6896	sgleTx = strncmp(extra, "background, stone", 20);
6897	pkTx = strncmp(extra, "background, pkt", 20);
6898	stop = strncmp(extra, "stop", 4);
6899	sscanf(extra, "count =%d, pkt", &count);
6900
6901	_rtw_memset(extra, '\0', sizeof(*extra));
6902
6903	if (stop == 0) {
6904		bStartTest = 0; /*  To set Stop */
6905		pmp_priv->tx.stop = 1;
6906		sprintf(extra, "Stop continuous Tx");
6907	} else {
6908		bStartTest = 1;
6909		if (pmp_priv->mode != MP_ON) {
6910			if (pmp_priv->tx.stop != 1) {
6911				DBG_88E("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
6912				return  -EFAULT;
6913			}
6914		}
6915	}
6916
6917	if (pkTx == 0 || countPkTx == 0)
6918		pmp_priv->mode = MP_PACKET_TX;
6919	if (sgleTx == 0)
6920		pmp_priv->mode = MP_SINGLE_TONE_TX;
6921	if (cotuTx == 0)
6922		pmp_priv->mode = MP_CONTINUOUS_TX;
6923	if (CarrSprTx == 0)
6924		pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
6925	if (scTx == 0)
6926		pmp_priv->mode = MP_SINGLE_CARRIER_TX;
6927
6928	switch (pmp_priv->mode) {
6929	case MP_PACKET_TX:
6930		if (bStartTest == 0) {
6931			pmp_priv->tx.stop = 1;
6932			pmp_priv->mode = MP_ON;
6933			sprintf(extra, "Stop continuous Tx");
6934		} else if (pmp_priv->tx.stop == 1) {
6935			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500 count =%u,\n", count);
6936			pmp_priv->tx.stop = 0;
6937			pmp_priv->tx.count = count;
6938			pmp_priv->tx.payload = 2;
6939			pattrib = &pmp_priv->tx.attrib;
6940			pattrib->pktlen = 1500;
6941			_rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
6942			SetPacketTx(padapter);
6943		} else {
6944			return -EFAULT;
6945		}
6946			wrqu->length = strlen(extra);
6947			return 0;
6948	case MP_SINGLE_TONE_TX:
6949		if (bStartTest != 0)
6950			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6951		Hal_SetSingleToneTx(padapter, (u8)bStartTest);
6952		break;
6953	case MP_CONTINUOUS_TX:
6954		if (bStartTest != 0)
6955			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6956		Hal_SetContinuousTx(padapter, (u8)bStartTest);
6957		break;
6958	case MP_CARRIER_SUPPRISSION_TX:
6959		if (bStartTest != 0) {
6960			if (pmp_priv->rateidx <= MPT_RATE_11M) {
6961				sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6962				Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
6963			} else {
6964				sprintf(extra, "Specify carrier suppression but not CCK rate");
6965			}
6966		}
6967		break;
6968	case MP_SINGLE_CARRIER_TX:
6969		if (bStartTest != 0)
6970			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6971		Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
6972		break;
6973	default:
6974		sprintf(extra, "Error! Continuous-Tx is not on-going.");
6975		return -EFAULT;
6976	}
6977
6978	if (bStartTest == 1 && pmp_priv->mode != MP_ON) {
6979		struct mp_priv *pmp_priv = &padapter->mppriv;
6980		if (pmp_priv->tx.stop == 0) {
6981			pmp_priv->tx.stop = 1;
6982			msleep(5);
6983		}
6984		pmp_priv->tx.stop = 0;
6985		pmp_priv->tx.count = 1;
6986		SetPacketTx(padapter);
6987	} else {
6988		pmp_priv->mode = MP_ON;
6989	}
6990
6991	wrqu->length = strlen(extra);
6992	return 0;
6993}
6994
6995static int rtw_mp_arx(struct net_device *dev,
6996			struct iw_request_info *info,
6997			struct iw_point *wrqu, char *extra)
6998{
6999	u8 bStartRx = 0, bStopRx = 0, bQueryPhy;
7000	u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0;
7001	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
7002	struct adapter *padapter = rtw_netdev_priv(dev);
7003
7004	if (!input)
7005		return -ENOMEM;
7006
7007	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7008		kfree(input);
7009		return -EFAULT;
7010	}
7011	DBG_88E("%s: %s\n", __func__, input);
7012
7013	bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /*  strncmp true is 0 */
7014	bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /*  strncmp true is 0 */
7015	bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /*  strncmp true is 0 */
7016
7017	if (bStartRx) {
7018		sprintf(extra, "start");
7019		SetPacketRx(padapter, bStartRx);
7020	} else if (bStopRx) {
7021		SetPacketRx(padapter, 0);
7022		sprintf(extra, "Received packet OK:%d CRC error:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount);
7023	} else if (bQueryPhy) {
7024		/*
7025		OFDM FA
7026		RegCF0[15:0]
7027		RegCF2[31:16]
7028		RegDA0[31:16]
7029		RegDA4[15:0]
7030		RegDA4[31:16]
7031		RegDA8[15:0]
7032		CCK FA
7033		(RegA5B<<8) | RegA5C
7034		*/
7035		cckok = read_bbreg(padapter, 0xf88, 0xffffffff);
7036		cckcrc = read_bbreg(padapter, 0xf84, 0xffffffff);
7037		ofdmok = read_bbreg(padapter, 0xf94, 0x0000FFFF);
7038		ofdmcrc = read_bbreg(padapter, 0xf94, 0xFFFF0000);
7039		htok = read_bbreg(padapter, 0xf90, 0x0000FFFF);
7040		htcrc = read_bbreg(padapter, 0xf90, 0xFFFF0000);
7041
7042		OFDM_FA = read_bbreg(padapter, 0xcf0, 0x0000FFFF);
7043		OFDM_FA = read_bbreg(padapter, 0xcf2, 0xFFFF0000);
7044		OFDM_FA = read_bbreg(padapter, 0xda0, 0xFFFF0000);
7045		OFDM_FA = read_bbreg(padapter, 0xda4, 0x0000FFFF);
7046		OFDM_FA = read_bbreg(padapter, 0xda4, 0xFFFF0000);
7047		OFDM_FA = read_bbreg(padapter, 0xda8, 0x0000FFFF);
7048		CCK_FA = (rtw_read8(padapter, 0xa5b)<<8) | (rtw_read8(padapter, 0xa5c));
7049
7050		sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", cckok+ofdmok+htok, cckcrc+ofdmcrc+htcrc, OFDM_FA+CCK_FA);
7051	}
7052	wrqu->length = strlen(extra) + 1;
7053	kfree(input);
7054	return 0;
7055}
7056
7057static int rtw_mp_trx_query(struct net_device *dev,
7058			struct iw_request_info *info,
7059			struct iw_point *wrqu, char *extra)
7060{
7061	u32 txok, txfail, rxok, rxfail;
7062	struct adapter *padapter = rtw_netdev_priv(dev);
7063
7064	txok = padapter->mppriv.tx.sended;
7065	txfail = 0;
7066	rxok = padapter->mppriv.rx_pktcount;
7067	rxfail = padapter->mppriv.rx_crcerrpktcount;
7068
7069	_rtw_memset(extra, '\0', 128);
7070
7071	sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ", txok, txfail, rxok, rxfail);
7072
7073	wrqu->length = strlen(extra)+1;
7074
7075	return 0;
7076}
7077
7078static int rtw_mp_pwrtrk(struct net_device *dev,
7079			struct iw_request_info *info,
7080			struct iw_point *wrqu, char *extra)
7081{
7082	u8 enable;
7083	u32 thermal;
7084	s32 ret;
7085	struct adapter *padapter = rtw_netdev_priv(dev);
7086	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
7087
7088	if (!input)
7089		return -ENOMEM;
7090	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7091		kfree(input);
7092		return -EFAULT;
7093	}
7094	_rtw_memset(extra, 0, wrqu->length);
7095
7096	enable = 1;
7097	if (wrqu->length > 1) {/*  not empty string */
7098		if (strncmp(input, "stop", 4) == 0) {
7099			enable = 0;
7100			sprintf(extra, "mp tx power tracking stop");
7101		} else if (sscanf(input, "ther =%d", &thermal)) {
7102				ret = Hal_SetThermalMeter(padapter, (u8)thermal);
7103				if (ret == _FAIL)
7104					return -EPERM;
7105				sprintf(extra, "mp tx power tracking start, target value =%d ok ", thermal);
7106		} else {
7107			kfree(input);
7108			return -EINVAL;
7109		}
7110	}
7111
7112	kfree(input);
7113	ret = Hal_SetPowerTracking(padapter, enable);
7114	if (ret == _FAIL)
7115		return -EPERM;
7116
7117	wrqu->length = strlen(extra);
7118	return 0;
7119}
7120
7121static int rtw_mp_psd(struct net_device *dev,
7122			struct iw_request_info *info,
7123			struct iw_point *wrqu, char *extra)
7124{
7125	struct adapter *padapter = rtw_netdev_priv(dev);
7126	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
7127
7128	if (!input)
7129		return -ENOMEM;
7130	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7131		kfree(input);
7132		return -EFAULT;
7133	}
7134
7135	strcpy(extra, input);
7136
7137	wrqu->length = mp_query_psd(padapter, extra);
7138	kfree(input);
7139	return 0;
7140}
7141
7142static int rtw_mp_thermal(struct net_device *dev,
7143			  struct iw_request_info *info,
7144			  struct iw_point *wrqu, char *extra)
7145{
7146	u8 val;
7147	u16 bwrite = 1;
7148	u16 addr = EEPROM_THERMAL_METER_88E;
7149
7150	u16 cnt = 1;
7151	u16 max_available_size = 0;
7152	struct adapter *padapter = rtw_netdev_priv(dev);
7153
7154	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
7155		return -EFAULT;
7156
7157	bwrite = strncmp(extra, "write", 6); /*  strncmp true is 0 */
7158
7159	Hal_GetThermalMeter(padapter, &val);
7160
7161	if (bwrite == 0) {
7162		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
7163		if (2 > max_available_size) {
7164			DBG_88E("no available efuse!\n");
7165			return -EFAULT;
7166		}
7167		if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) {
7168			DBG_88E("rtw_efuse_map_write error\n");
7169			return -EFAULT;
7170		} else {
7171			 sprintf(extra, " efuse write ok :%d", val);
7172		}
7173	} else {
7174		 sprintf(extra, "%d", val);
7175	}
7176	wrqu->length = strlen(extra);
7177
7178	return 0;
7179}
7180
7181static int rtw_mp_reset_stats(struct net_device *dev,
7182			struct iw_request_info *info,
7183			struct iw_point *wrqu, char *extra)
7184{
7185	struct mp_priv *pmp_priv;
7186	struct adapter *padapter = rtw_netdev_priv(dev);
7187
7188	pmp_priv = &padapter->mppriv;
7189
7190	pmp_priv->tx.sended = 0;
7191	pmp_priv->tx_pktcount = 0;
7192	pmp_priv->rx_pktcount = 0;
7193	pmp_priv->rx_crcerrpktcount = 0;
7194
7195	/* reset phy counter */
7196	write_bbreg(padapter, 0xf14, BIT16, 0x1);
7197	msleep(10);
7198	write_bbreg(padapter, 0xf14, BIT16, 0x0);
7199
7200	return 0;
7201}
7202
7203static int rtw_mp_dump(struct net_device *dev,
7204		       struct iw_request_info *info,
7205		       struct iw_point *wrqu, char *extra)
7206{
7207	u32 value;
7208	u8 rf_type, path_nums = 0;
7209	u32 i, j = 1, path;
7210	struct adapter *padapter = rtw_netdev_priv(dev);
7211
7212	if (strncmp(extra, "all", 4) == 0) {
7213		DBG_88E("\n ======= MAC REG =======\n");
7214		for (i = 0x0; i < 0x300; i += 4) {
7215			if (j%4 == 1)
7216				DBG_88E("0x%02x", i);
7217			DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
7218			if ((j++)%4 == 0)
7219				DBG_88E("\n");
7220		}
7221		for (i = 0x400; i < 0x1000; i += 4) {
7222			if (j%4 == 1)
7223				DBG_88E("0x%02x", i);
7224			DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
7225			if ((j++)%4 == 0)
7226				DBG_88E("\n");
7227		}
7228
7229		j = 1;
7230		rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
7231
7232		DBG_88E("\n ======= RF REG =======\n");
7233		if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
7234			path_nums = 1;
7235		else
7236			path_nums = 2;
7237
7238		for (path = 0; path < path_nums; path++) {
7239			for (i = 0; i < 0x34; i++) {
7240				value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
7241				if (j%4 == 1)
7242					DBG_88E("0x%02x ", i);
7243				DBG_88E(" 0x%08x ", value);
7244				if ((j++)%4 == 0)
7245					DBG_88E("\n");
7246			}
7247		}
7248	}
7249	return 0;
7250}
7251
7252static int rtw_mp_phypara(struct net_device *dev,
7253			struct iw_request_info *info,
7254			struct iw_point *wrqu, char *extra)
7255{
7256	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
7257	u32		valxcap;
7258
7259	if (!input)
7260		return -ENOMEM;
7261	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7262		kfree(input);
7263		return -EFAULT;
7264	}
7265
7266	DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7267
7268	sscanf(input, "xcap =%d", &valxcap);
7269
7270	kfree(input);
7271	return 0;
7272}
7273
7274static int rtw_mp_SetRFPath(struct net_device *dev,
7275			struct iw_request_info *info,
7276			union iwreq_data *wrqu, char *extra)
7277{
7278	struct adapter *padapter = rtw_netdev_priv(dev);
7279	char	*input = kmalloc(wrqu->data.length, GFP_KERNEL);
7280	u8 bMain = 1, bTurnoff = 1;
7281
7282	if (!input)
7283		return -ENOMEM;
7284	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
7285			return -EFAULT;
7286	DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7287
7288	bMain = strncmp(input, "1", 2); /*  strncmp true is 0 */
7289	bTurnoff = strncmp(input, "0", 3); /*  strncmp true is 0 */
7290
7291	if (bMain == 0) {
7292		MP_PHY_SetRFPathSwitch(padapter, true);
7293		DBG_88E("%s:PHY_SetRFPathSwitch = true\n", __func__);
7294	} else if (bTurnoff == 0) {
7295		MP_PHY_SetRFPathSwitch(padapter, false);
7296		DBG_88E("%s:PHY_SetRFPathSwitch = false\n", __func__);
7297	}
7298	kfree(input);
7299	return 0;
7300}
7301
7302static int rtw_mp_QueryDrv(struct net_device *dev,
7303			struct iw_request_info *info,
7304			union iwreq_data *wrqu, char *extra)
7305{
7306	struct adapter *padapter = rtw_netdev_priv(dev);
7307	char	*input = kmalloc(wrqu->data.length, GFP_KERNEL);
7308	u8 qAutoLoad = 1;
7309	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
7310
7311	if (!input)
7312		return -ENOMEM;
7313
7314	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
7315			return -EFAULT;
7316	DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7317
7318	qAutoLoad = strncmp(input, "autoload", 8); /*  strncmp true is 0 */
7319
7320	if (qAutoLoad == 0) {
7321		DBG_88E("%s:qAutoLoad\n", __func__);
7322
7323		if (pEEPROM->bautoload_fail_flag)
7324			sprintf(extra, "fail");
7325		else
7326		sprintf(extra, "ok");
7327	}
7328	wrqu->data.length = strlen(extra) + 1;
7329	kfree(input);
7330	return 0;
7331}
7332
7333static int rtw_mp_set(struct net_device *dev,
7334		      struct iw_request_info *info,
7335		      union iwreq_data *wdata, char *extra)
7336{
7337	struct iw_point *wrqu = (struct iw_point *)wdata;
7338	u32 subcmd = wrqu->flags;
7339	struct adapter *padapter = rtw_netdev_priv(dev);
7340
7341	if (padapter == NULL)
7342		return -ENETDOWN;
7343
7344	if (extra == NULL) {
7345		wrqu->length = 0;
7346		return -EIO;
7347	}
7348
7349	switch (subcmd) {
7350	case MP_START:
7351		DBG_88E("set case mp_start\n");
7352		rtw_mp_start(dev, info, wrqu, extra);
7353		 break;
7354	case MP_STOP:
7355		DBG_88E("set case mp_stop\n");
7356		rtw_mp_stop(dev, info, wrqu, extra);
7357		 break;
7358	case MP_BANDWIDTH:
7359		DBG_88E("set case mp_bandwidth\n");
7360		rtw_mp_bandwidth(dev, info, wrqu, extra);
7361		break;
7362	case MP_RESET_STATS:
7363		DBG_88E("set case MP_RESET_STATS\n");
7364		rtw_mp_reset_stats(dev, info, wrqu, extra);
7365		break;
7366	case MP_SetRFPathSwh:
7367		DBG_88E("set MP_SetRFPathSwitch\n");
7368		rtw_mp_SetRFPath(dev, info, wdata, extra);
7369		break;
7370	case CTA_TEST:
7371		DBG_88E("set CTA_TEST\n");
7372		rtw_cta_test_start(dev, info, wdata, extra);
7373		break;
7374	}
7375
7376	return 0;
7377}
7378
7379static int rtw_mp_get(struct net_device *dev,
7380			struct iw_request_info *info,
7381			union iwreq_data *wdata, char *extra)
7382{
7383	struct iw_point *wrqu = (struct iw_point *)wdata;
7384	u32 subcmd = wrqu->flags;
7385	struct adapter *padapter = rtw_netdev_priv(dev);
7386
7387	if (padapter == NULL)
7388		return -ENETDOWN;
7389	if (extra == NULL) {
7390		wrqu->length = 0;
7391		return -EIO;
7392	}
7393
7394	switch (subcmd) {
7395	case WRITE_REG:
7396		rtw_mp_write_reg(dev, info, wrqu, extra);
7397		 break;
7398	case WRITE_RF:
7399		rtw_mp_write_rf(dev, info, wrqu, extra);
7400		 break;
7401	case MP_PHYPARA:
7402		DBG_88E("mp_get  MP_PHYPARA\n");
7403		rtw_mp_phypara(dev, info, wrqu, extra);
7404		break;
7405	case MP_CHANNEL:
7406		DBG_88E("set case mp_channel\n");
7407		rtw_mp_channel(dev, info, wrqu, extra);
7408		break;
7409	case READ_REG:
7410		DBG_88E("mp_get  READ_REG\n");
7411		rtw_mp_read_reg(dev, info, wrqu, extra);
7412		 break;
7413	case READ_RF:
7414		DBG_88E("mp_get  READ_RF\n");
7415		rtw_mp_read_rf(dev, info, wrqu, extra);
7416		break;
7417	case MP_RATE:
7418		DBG_88E("set case mp_rate\n");
7419		rtw_mp_rate(dev, info, wrqu, extra);
7420		break;
7421	case MP_TXPOWER:
7422		DBG_88E("set case MP_TXPOWER\n");
7423		rtw_mp_txpower(dev, info, wrqu, extra);
7424		break;
7425	case MP_ANT_TX:
7426		DBG_88E("set case MP_ANT_TX\n");
7427		rtw_mp_ant_tx(dev, info, wrqu, extra);
7428		break;
7429	case MP_ANT_RX:
7430		DBG_88E("set case MP_ANT_RX\n");
7431		rtw_mp_ant_rx(dev, info, wrqu, extra);
7432		break;
7433	case MP_QUERY:
7434		rtw_mp_trx_query(dev, info, wrqu, extra);
7435		break;
7436	case MP_CTX:
7437		DBG_88E("set case MP_CTX\n");
7438		rtw_mp_ctx(dev, info, wrqu, extra);
7439		break;
7440	case MP_ARX:
7441		DBG_88E("set case MP_ARX\n");
7442		rtw_mp_arx(dev, info, wrqu, extra);
7443		break;
7444	case EFUSE_GET:
7445		DBG_88E("efuse get EFUSE_GET\n");
7446		rtw_mp_efuse_get(dev, info, wdata, extra);
7447		 break;
7448	case MP_DUMP:
7449		DBG_88E("set case MP_DUMP\n");
7450		rtw_mp_dump(dev, info, wrqu, extra);
7451		 break;
7452	case MP_PSD:
7453		DBG_88E("set case MP_PSD\n");
7454		rtw_mp_psd(dev, info, wrqu, extra);
7455		break;
7456	case MP_THER:
7457		DBG_88E("set case MP_THER\n");
7458		rtw_mp_thermal(dev, info, wrqu, extra);
7459		break;
7460	case MP_QueryDrvStats:
7461		DBG_88E("mp_get MP_QueryDrvStats\n");
7462		rtw_mp_QueryDrv (dev, info, wdata, extra);
7463		break;
7464	case MP_PWRTRK:
7465		DBG_88E("set case MP_PWRTRK\n");
7466		rtw_mp_pwrtrk(dev, info, wrqu, extra);
7467		break;
7468	case EFUSE_SET:
7469		DBG_88E("set case efuse set\n");
7470		rtw_mp_efuse_set(dev, info, wdata, extra);
7471		break;
7472	}
7473
7474	msleep(10); /* delay 5ms for sending pkt before exit adb shell operation */
7475	return 0;
7476}
7477
7478static int rtw_tdls(struct net_device *dev,
7479		    struct iw_request_info *info,
7480		    union iwreq_data *wrqu, char *extra)
7481{
7482	return 0;
7483}
7484
7485static int rtw_tdls_get(struct net_device *dev,
7486				struct iw_request_info *info,
7487				union iwreq_data *wrqu, char *extra)
7488{
7489	return 0;
7490}
7491
7492static int rtw_test(
7493	struct net_device *dev,
7494	struct iw_request_info *info,
7495	union iwreq_data *wrqu, char *extra)
7496{
7497	u32 len;
7498	u8 *pbuf, *pch;
7499	char *ptmp;
7500	u8 *delim = ",";
7501
7502	DBG_88E("+%s\n", __func__);
7503	len = wrqu->data.length;
7504
7505	pbuf = (u8 *)rtw_zmalloc(len);
7506	if (pbuf == NULL) {
7507		DBG_88E("%s: no memory!\n", __func__);
7508		return -ENOMEM;
7509	}
7510
7511	if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
7512		kfree(pbuf);
7513		DBG_88E("%s: copy from user fail!\n", __func__);
7514		return -EFAULT;
7515	}
7516	DBG_88E("%s: string =\"%s\"\n", __func__, pbuf);
7517
7518	ptmp = (char *)pbuf;
7519	pch = strsep(&ptmp, delim);
7520	if ((pch == NULL) || (strlen(pch) == 0)) {
7521		kfree(pbuf);
7522		DBG_88E("%s: parameter error(level 1)!\n", __func__);
7523		return -EFAULT;
7524	}
7525	kfree(pbuf);
7526	return 0;
7527}
7528
7529static iw_handler rtw_handlers[] = {
7530	NULL,					/* SIOCSIWCOMMIT */
7531	rtw_wx_get_name,		/* SIOCGIWNAME */
7532	dummy,					/* SIOCSIWNWID */
7533	dummy,					/* SIOCGIWNWID */
7534	rtw_wx_set_freq,		/* SIOCSIWFREQ */
7535	rtw_wx_get_freq,		/* SIOCGIWFREQ */
7536	rtw_wx_set_mode,		/* SIOCSIWMODE */
7537	rtw_wx_get_mode,		/* SIOCGIWMODE */
7538	dummy,					/* SIOCSIWSENS */
7539	rtw_wx_get_sens,		/* SIOCGIWSENS */
7540	NULL,					/* SIOCSIWRANGE */
7541	rtw_wx_get_range,		/* SIOCGIWRANGE */
7542	rtw_wx_set_priv,		/* SIOCSIWPRIV */
7543	NULL,					/* SIOCGIWPRIV */
7544	NULL,					/* SIOCSIWSTATS */
7545	NULL,					/* SIOCGIWSTATS */
7546	dummy,					/* SIOCSIWSPY */
7547	dummy,					/* SIOCGIWSPY */
7548	NULL,					/* SIOCGIWTHRSPY */
7549	NULL,					/* SIOCWIWTHRSPY */
7550	rtw_wx_set_wap,		/* SIOCSIWAP */
7551	rtw_wx_get_wap,		/* SIOCGIWAP */
7552	rtw_wx_set_mlme,		/* request MLME operation; uses struct iw_mlme */
7553	dummy,					/* SIOCGIWAPLIST -- depricated */
7554	rtw_wx_set_scan,		/* SIOCSIWSCAN */
7555	rtw_wx_get_scan,		/* SIOCGIWSCAN */
7556	rtw_wx_set_essid,		/* SIOCSIWESSID */
7557	rtw_wx_get_essid,		/* SIOCGIWESSID */
7558	dummy,					/* SIOCSIWNICKN */
7559	rtw_wx_get_nick,		/* SIOCGIWNICKN */
7560	NULL,					/* -- hole -- */
7561	NULL,					/* -- hole -- */
7562	rtw_wx_set_rate,		/* SIOCSIWRATE */
7563	rtw_wx_get_rate,		/* SIOCGIWRATE */
7564	rtw_wx_set_rts,			/* SIOCSIWRTS */
7565	rtw_wx_get_rts,			/* SIOCGIWRTS */
7566	rtw_wx_set_frag,		/* SIOCSIWFRAG */
7567	rtw_wx_get_frag,		/* SIOCGIWFRAG */
7568	dummy,					/* SIOCSIWTXPOW */
7569	dummy,					/* SIOCGIWTXPOW */
7570	dummy,					/* SIOCSIWRETRY */
7571	rtw_wx_get_retry,		/* SIOCGIWRETRY */
7572	rtw_wx_set_enc,			/* SIOCSIWENCODE */
7573	rtw_wx_get_enc,			/* SIOCGIWENCODE */
7574	dummy,					/* SIOCSIWPOWER */
7575	rtw_wx_get_power,		/* SIOCGIWPOWER */
7576	NULL,					/*---hole---*/
7577	NULL,					/*---hole---*/
7578	rtw_wx_set_gen_ie,		/* SIOCSIWGENIE */
7579	NULL,					/* SIOCGWGENIE */
7580	rtw_wx_set_auth,		/* SIOCSIWAUTH */
7581	NULL,					/* SIOCGIWAUTH */
7582	rtw_wx_set_enc_ext,		/* SIOCSIWENCODEEXT */
7583	NULL,					/* SIOCGIWENCODEEXT */
7584	rtw_wx_set_pmkid,		/* SIOCSIWPMKSA */
7585	NULL,					/*---hole---*/
7586};
7587
7588static const struct iw_priv_args rtw_private_args[] = {
7589	{
7590		SIOCIWFIRSTPRIV + 0x0,
7591		IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
7592	},
7593	{
7594		SIOCIWFIRSTPRIV + 0x1,
7595		IW_PRIV_TYPE_CHAR | 0x7FF,
7596		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
7597	},
7598	{
7599		SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
7600	},
7601	{
7602		SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
7603	},
7604	{
7605		SIOCIWFIRSTPRIV + 0x4,
7606		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
7607	},
7608	{
7609		SIOCIWFIRSTPRIV + 0x5,
7610		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
7611	},
7612	{
7613		SIOCIWFIRSTPRIV + 0x6,
7614		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
7615	},
7616	{
7617		SIOCIWFIRSTPRIV + 0x7,
7618		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
7619	},
7620	{
7621		SIOCIWFIRSTPRIV + 0x8,
7622		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
7623	},
7624	{
7625		SIOCIWFIRSTPRIV + 0x9,
7626		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
7627	},
7628
7629	{
7630		SIOCIWFIRSTPRIV + 0xA,
7631		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
7632	},
7633
7634	{
7635		SIOCIWFIRSTPRIV + 0xB,
7636		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
7637	},
7638	{
7639		SIOCIWFIRSTPRIV + 0xC,
7640		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
7641	},
7642	{
7643		SIOCIWFIRSTPRIV + 0xD,
7644		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
7645	},
7646	{
7647		SIOCIWFIRSTPRIV + 0x10,
7648		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
7649	},
7650	{
7651		SIOCIWFIRSTPRIV + 0x11,
7652		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get"
7653	},
7654	{
7655		SIOCIWFIRSTPRIV + 0x12,
7656		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2"
7657	},
7658	{SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0, "NULL"},
7659	{
7660		SIOCIWFIRSTPRIV + 0x14,
7661		IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
7662	},
7663	{
7664		SIOCIWFIRSTPRIV + 0x15,
7665		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "tdls_get"
7666	},
7667	{
7668		SIOCIWFIRSTPRIV + 0x16,
7669		IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
7670	},
7671
7672	{SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
7673
7674	{SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
7675	{SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
7676	{SIOCIWFIRSTPRIV + 0x1D, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
7677	},
7678
7679	{SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0, ""},  /* set */
7680	{SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, ""},/* get */
7681/* --- sub-ioctls definitions --- */
7682
7683	{MP_START, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start"}, /* set */
7684	{MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara"},/* get */
7685	{MP_STOP, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop"}, /* set */
7686	{MP_CHANNEL, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel"},/* get */
7687	{MP_BANDWIDTH, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, /* set */
7688	{MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},/* get */
7689	{MP_RESET_STATS, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
7690	{MP_QUERY, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_query"}, /* get */
7691	{READ_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg"},
7692	{MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},
7693	{READ_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf"},
7694	{MP_PSD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
7695	{MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump"},
7696	{MP_TXPOWER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
7697	{MP_ANT_TX, IW_PRIV_TYPE_CHAR | 1024,  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
7698	{MP_ANT_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
7699	{WRITE_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg"},
7700	{WRITE_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf"},
7701	{MP_CTX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
7702	{MP_ARX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
7703	{MP_THER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
7704	{EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set"},
7705	{EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
7706	{MP_PWRTRK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
7707	{MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery"},
7708	{MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, /*  mp_ioctl */
7709	{MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath"},
7710	{CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
7711};
7712
7713static iw_handler rtw_private_handler[] = {
7714rtw_wx_write32,				/* 0x00 */
7715rtw_wx_read32,				/* 0x01 */
7716rtw_drvext_hdl,				/* 0x02 */
7717rtw_mp_ioctl_hdl,			/* 0x03 */
7718
7719/*  for MM DTV platform */
7720	rtw_get_ap_info,		/* 0x04 */
7721
7722	rtw_set_pid,			/* 0x05 */
7723	rtw_wps_start,			/* 0x06 */
7724
7725	rtw_wx_get_sensitivity,		/* 0x07 */
7726	rtw_wx_set_mtk_wps_probe_ie,	/* 0x08 */
7727	rtw_wx_set_mtk_wps_ie,		/* 0x09 */
7728
7729/*  Set Channel depend on the country code */
7730	rtw_wx_set_channel_plan,	/* 0x0A */
7731
7732	rtw_dbg_port,			/* 0x0B */
7733	rtw_wx_write_rf,		/* 0x0C */
7734	rtw_wx_read_rf,			/* 0x0D */
7735
7736	rtw_mp_set,			/* 0x0E */
7737	rtw_mp_get,			/* 0x0F */
7738	rtw_p2p_set,			/* 0x10 */
7739	rtw_p2p_get,			/* 0x11 */
7740	rtw_p2p_get2,			/* 0x12 */
7741
7742	NULL,				/* 0x13 */
7743	rtw_tdls,			/* 0x14 */
7744	rtw_tdls_get,			/* 0x15 */
7745
7746	rtw_pm_set,			/* 0x16 */
7747	rtw_wx_priv_null,		/* 0x17 */
7748	rtw_rereg_nd_name,		/* 0x18 */
7749	rtw_wx_priv_null,		/* 0x19 */
7750
7751	rtw_mp_efuse_set,		/* 0x1A */
7752	rtw_mp_efuse_get,		/* 0x1B */
7753	NULL,				/*  0x1C is reserved for hostapd */
7754	rtw_test,			/*  0x1D */
7755};
7756
7757static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
7758{
7759	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
7760	struct iw_statistics *piwstats = &padapter->iwstats;
7761	int tmp_level = 0;
7762	int tmp_qual = 0;
7763	int tmp_noise = 0;
7764
7765	if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
7766		piwstats->qual.qual = 0;
7767		piwstats->qual.level = 0;
7768		piwstats->qual.noise = 0;
7769	} else {
7770		tmp_level = padapter->recvpriv.signal_strength;
7771		tmp_qual = padapter->recvpriv.signal_qual;
7772		tmp_noise = padapter->recvpriv.noise;
7773
7774		piwstats->qual.level = tmp_level;
7775		piwstats->qual.qual = tmp_qual;
7776		piwstats->qual.noise = tmp_noise;
7777	}
7778	piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
7779	return &padapter->iwstats;
7780}
7781
7782struct iw_handler_def rtw_handlers_def = {
7783	.standard = rtw_handlers,
7784	.num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
7785	.private = rtw_private_handler,
7786	.private_args = (struct iw_priv_args *)rtw_private_args,
7787	.num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
7788	.num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
7789	.get_wireless_stats = rtw_get_wireless_stats,
7790};
7791
7792/*  copy from net/wireless/wext.c start */
7793/* ---------------------------------------------------------------- */
7794/*
7795 * Calculate size of private arguments
7796 */
7797static const char iw_priv_type_size[] = {
7798	0,			      /* IW_PRIV_TYPE_NONE */
7799	1,			      /* IW_PRIV_TYPE_BYTE */
7800	1,			      /* IW_PRIV_TYPE_CHAR */
7801	0,			      /* Not defined */
7802	sizeof(__u32),		  /* IW_PRIV_TYPE_INT */
7803	sizeof(struct iw_freq),	 /* IW_PRIV_TYPE_FLOAT */
7804	sizeof(struct sockaddr),	/* IW_PRIV_TYPE_ADDR */
7805	0,			      /* Not defined */
7806};
7807
7808static int get_priv_size(__u16 args)
7809{
7810	int num = args & IW_PRIV_SIZE_MASK;
7811	int type = (args & IW_PRIV_TYPE_MASK) >> 12;
7812
7813	return num * iw_priv_type_size[type];
7814}
7815/*  copy from net/wireless/wext.c end */
7816
7817static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
7818{
7819	int err = 0;
7820	u8 *input = NULL;
7821	u32 input_len = 0;
7822	const char delim[] = " ";
7823	u8 *output = NULL;
7824	u32 output_len = 0;
7825	u32 count = 0;
7826	u8 *buffer = NULL;
7827	u32 buffer_len = 0;
7828	char *ptr = NULL;
7829	u8 cmdname[17] = {0}; /*  IFNAMSIZ+1 */
7830	u32 cmdlen;
7831	s32 len;
7832	u8 *extra = NULL;
7833	u32 extra_size = 0;
7834
7835	s32 k;
7836	const iw_handler *priv;		/* Private ioctl */
7837	const struct iw_priv_args *priv_args;	/* Private ioctl description */
7838	u32 num_priv_args;			/* Number of descriptions */
7839	iw_handler handler;
7840	int temp;
7841	int subcmd = 0;				/* sub-ioctl index */
7842	int offset = 0;				/* Space for sub-ioctl index */
7843
7844	union iwreq_data wdata;
7845
7846	memcpy(&wdata, wrq_data, sizeof(wdata));
7847
7848	input_len = wdata.data.length;
7849	input = rtw_zmalloc(input_len);
7850	if (NULL == input)
7851		return -ENOMEM;
7852	if (copy_from_user(input, wdata.data.pointer, input_len)) {
7853		err = -EFAULT;
7854		goto exit;
7855	}
7856	ptr = input;
7857	len = input_len;
7858
7859	sscanf(ptr, "%16s", cmdname);
7860	cmdlen = strlen(cmdname);
7861	DBG_88E("%s: cmd =%s\n", __func__, cmdname);
7862
7863	/*  skip command string */
7864	if (cmdlen > 0)
7865		cmdlen += 1; /*  skip one space */
7866	ptr += cmdlen;
7867	len -= cmdlen;
7868	DBG_88E("%s: parameters =%s\n", __func__, ptr);
7869
7870	priv = rtw_private_handler;
7871	priv_args = rtw_private_args;
7872	num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
7873
7874	if (num_priv_args == 0) {
7875		err = -EOPNOTSUPP;
7876		goto exit;
7877	}
7878
7879	/* Search the correct ioctl */
7880	k = -1;
7881	while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
7882
7883	/* If not found... */
7884	if (k == num_priv_args) {
7885		err = -EOPNOTSUPP;
7886		goto exit;
7887	}
7888
7889	/* Watch out for sub-ioctls ! */
7890	if (priv_args[k].cmd < SIOCDEVPRIVATE) {
7891		int j = -1;
7892
7893		/* Find the matching *real* ioctl */
7894		while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
7895			(priv_args[j].set_args != priv_args[k].set_args) ||
7896			(priv_args[j].get_args != priv_args[k].get_args)));
7897
7898		/* If not found... */
7899		if (j == num_priv_args) {
7900			err = -EINVAL;
7901			goto exit;
7902		}
7903
7904		/* Save sub-ioctl number */
7905		subcmd = priv_args[k].cmd;
7906		/* Reserve one int (simplify alignment issues) */
7907		offset = sizeof(__u32);
7908		/* Use real ioctl definition from now on */
7909		k = j;
7910	}
7911
7912	buffer = rtw_zmalloc(4096);
7913	if (NULL == buffer) {
7914		err = -ENOMEM;
7915		goto exit;
7916	}
7917
7918	/* If we have to set some data */
7919	if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
7920	    (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
7921		u8 *str;
7922
7923		switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
7924		case IW_PRIV_TYPE_BYTE:
7925			/* Fetch args */
7926			count = 0;
7927			do {
7928				str = strsep(&ptr, delim);
7929				if (NULL == str)
7930					break;
7931				sscanf(str, "%i", &temp);
7932				buffer[count++] = (u8)temp;
7933			} while (1);
7934			buffer_len = count;
7935			/* Number of args to fetch */
7936			wdata.data.length = count;
7937			if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7938				wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7939			break;
7940		case IW_PRIV_TYPE_INT:
7941			/* Fetch args */
7942			count = 0;
7943			do {
7944				str = strsep(&ptr, delim);
7945				if (NULL == str)
7946					break;
7947				sscanf(str, "%i", &temp);
7948				((s32 *)buffer)[count++] = (s32)temp;
7949			} while (1);
7950			buffer_len = count * sizeof(s32);
7951			/* Number of args to fetch */
7952			wdata.data.length = count;
7953			if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7954				wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7955			break;
7956		case IW_PRIV_TYPE_CHAR:
7957			if (len > 0) {
7958				/* Size of the string to fetch */
7959				wdata.data.length = len;
7960				if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7961					wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7962
7963				/* Fetch string */
7964				memcpy(buffer, ptr, wdata.data.length);
7965			} else {
7966				wdata.data.length = 1;
7967				buffer[0] = '\0';
7968			}
7969			buffer_len = wdata.data.length;
7970			break;
7971		default:
7972			DBG_88E("%s: Not yet implemented...\n", __func__);
7973			err = -1;
7974			goto exit;
7975		}
7976
7977		if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
7978		    (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
7979			DBG_88E("%s: The command %s needs exactly %d argument(s)...\n",
7980				__func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
7981			err = -EINVAL;
7982			goto exit;
7983		}
7984	} else {
7985		/* if args to set */
7986		wdata.data.length = 0L;
7987	}
7988
7989	/* Those two tests are important. They define how the driver
7990	* will have to handle the data */
7991	if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
7992	    ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
7993		/* First case : all SET args fit within wrq */
7994		if (offset)
7995			wdata.mode = subcmd;
7996		memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
7997	} else {
7998		if ((priv_args[k].set_args == 0) &&
7999		    (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
8000		    (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
8001			/* Second case : no SET args, GET args fit within wrq */
8002			if (offset)
8003				wdata.mode = subcmd;
8004		} else {
8005			/* Third case : args won't fit in wrq, or variable number of args */
8006			if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
8007				err = -EFAULT;
8008				goto exit;
8009			}
8010			wdata.data.flags = subcmd;
8011		}
8012	}
8013
8014	kfree(input);
8015	input = NULL;
8016
8017	extra_size = 0;
8018	if (IW_IS_SET(priv_args[k].cmd)) {
8019		/* Size of set arguments */
8020		extra_size = get_priv_size(priv_args[k].set_args);
8021
8022		/* Does it fits in iwr ? */
8023		if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
8024		    ((extra_size + offset) <= IFNAMSIZ))
8025			extra_size = 0;
8026	} else {
8027		/* Size of get arguments */
8028		extra_size = get_priv_size(priv_args[k].get_args);
8029
8030		/* Does it fits in iwr ? */
8031		if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
8032		    (extra_size <= IFNAMSIZ))
8033			extra_size = 0;
8034	}
8035
8036	if (extra_size == 0) {
8037		extra = (u8 *)&wdata;
8038		kfree(buffer);
8039		buffer = NULL;
8040	} else {
8041		extra = buffer;
8042	}
8043
8044	handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
8045	err = handler(dev, NULL, &wdata, extra);
8046
8047	/* If we have to get some data */
8048	if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
8049	    (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
8050		int j;
8051		int n = 0;	/* number of args */
8052		u8 str[20] = {0};
8053
8054		/* Check where is the returned data */
8055		if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
8056		    (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
8057			n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
8058		else
8059			n = wdata.data.length;
8060
8061		output = rtw_zmalloc(4096);
8062		if (NULL == output) {
8063			err =  -ENOMEM;
8064			goto exit;
8065		}
8066		switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
8067		case IW_PRIV_TYPE_BYTE:
8068			/* Display args */
8069			for (j = 0; j < n; j++) {
8070				sprintf(str, "%d  ", extra[j]);
8071				len = strlen(str);
8072				output_len = strlen(output);
8073				if ((output_len + len + 1) > 4096) {
8074					err = -E2BIG;
8075					goto exit;
8076				}
8077				memcpy(output+output_len, str, len);
8078			}
8079			break;
8080		case IW_PRIV_TYPE_INT:
8081			/* Display args */
8082			for (j = 0; j < n; j++) {
8083				sprintf(str, "%d  ", ((__s32 *)extra)[j]);
8084				len = strlen(str);
8085				output_len = strlen(output);
8086				if ((output_len + len + 1) > 4096) {
8087					err = -E2BIG;
8088					goto exit;
8089				}
8090				memcpy(output+output_len, str, len);
8091			}
8092			break;
8093		case IW_PRIV_TYPE_CHAR:
8094			/* Display args */
8095			memcpy(output, extra, n);
8096			break;
8097		default:
8098			DBG_88E("%s: Not yet implemented...\n", __func__);
8099			err = -1;
8100			goto exit;
8101		}
8102
8103		output_len = strlen(output) + 1;
8104		wrq_data->data.length = output_len;
8105		if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
8106			err = -EFAULT;
8107			goto exit;
8108		}
8109	} else {
8110		/* if args to set */
8111		wrq_data->data.length = 0;
8112	}
8113
8114exit:
8115	kfree(input);
8116	kfree(buffer);
8117	kfree(output);
8118	return err;
8119}
8120
8121#include <rtw_android.h>
8122int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
8123{
8124	struct iwreq *wrq = (struct iwreq *)rq;
8125	int ret = 0;
8126
8127	switch (cmd) {
8128	case RTL_IOCTL_WPA_SUPPLICANT:
8129		ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
8130		break;
8131#ifdef CONFIG_88EU_AP_MODE
8132	case RTL_IOCTL_HOSTAPD:
8133		ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
8134		break;
8135#endif /*  CONFIG_88EU_AP_MODE */
8136	case SIOCDEVPRIVATE:
8137		ret = rtw_ioctl_wext_private(dev, &wrq->u);
8138		break;
8139	case (SIOCDEVPRIVATE+1):
8140		ret = rtw_android_priv_cmd(dev, rq, cmd);
8141		break;
8142	default:
8143		ret = -EOPNOTSUPP;
8144		break;
8145	}
8146	return ret;
8147}
8148