xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd_indep_power/wl_android.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Linux cfg80211 driver - Android related functions
4  *
5  * Copyright (C) 1999-2017, Broadcom Corporation
6  *
7  *      Unless you and Broadcom execute a separate written software license
8  * agreement governing use of this software, this software is licensed to you
9  * under the terms of the GNU General Public License version 2 (the "GPL"),
10  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11  * following added to such license:
12  *
13  *      As a special exception, the copyright holders of this software give you
14  * permission to link this software with independent modules, and to copy and
15  * distribute the resulting executable under terms of your choice, provided that
16  * you also meet, for each linked independent module, the terms and conditions of
17  * the license of that module.  An independent module is a module which is not
18  * derived from this software.  The special exception does not apply to any
19  * modifications of the software.
20  *
21  *      Notwithstanding the above, under no circumstances may you combine this
22  * software in any way with any other Broadcom software provided under a license
23  * other than the GPL, without Broadcom's express prior written consent.
24  *
25  *
26  * <<Broadcom-WL-IPTag/Open:>>
27  *
28  * $Id: wl_android.c 710862 2017-07-14 07:43:59Z $
29  */
30 
31 #include <linux/module.h>
32 #include <linux/netdevice.h>
33 #include <net/netlink.h>
34 #ifdef CONFIG_COMPAT
35 #include <linux/compat.h>
36 #endif
37 
38 #include <wl_android.h>
39 #include <wldev_common.h>
40 #include <wlc_types.h>
41 #include <wlioctl.h>
42 #include <wlioctl_utils.h>
43 #include <bcmutils.h>
44 #include <linux_osl.h>
45 #include <dhd_dbg.h>
46 #include <dngl_stats.h>
47 #include <dhd.h>
48 #include <dhd_config.h>
49 #include <bcmip.h>
50 #ifdef PNO_SUPPORT
51 #include <dhd_pno.h>
52 #endif
53 #ifdef BCMSDIO
54 #include <bcmsdbus.h>
55 #endif
56 #ifdef WL_CFG80211
57 #include <wl_cfg80211.h>
58 #endif
59 #ifdef DHDTCPACK_SUPPRESS
60 #include <dhd_ip.h>
61 #endif /* DHDTCPACK_SUPPRESS */
62 #include <dhd_linux.h>
63 #ifdef DHD_PKT_LOGGING
64 #include <dhd_pktlog.h>
65 #endif /* DHD_PKT_LOGGING */
66 
67 #if defined(STAT_REPORT)
68 #include <wl_statreport.h>
69 #endif /* STAT_REPORT */
70 #ifdef WL_ESCAN
71 #include <wl_escan.h>
72 #endif
73 
74 #ifndef WL_CFG80211
75 #define htod32(i) i
76 #define htod16(i) i
77 #define dtoh32(i) i
78 #define dtoh16(i) i
79 #define htodchanspec(i) i
80 #define dtohchanspec(i) i
81 #endif
82 
83 uint android_msg_level = ANDROID_ERROR_LEVEL | ANDROID_MSG_LEVEL;
84 
85 #define ANDROID_ERROR_MSG(x, args...) \
86 	do { \
87 		if (android_msg_level & ANDROID_ERROR_LEVEL) { \
88 			printk(KERN_ERR "[dhd] ANDROID-ERROR) " x, ## args); \
89 		} \
90 	} while (0)
91 #define ANDROID_TRACE_MSG(x, args...) \
92 	do { \
93 		if (android_msg_level & ANDROID_TRACE_LEVEL) { \
94 			printk(KERN_INFO "[dhd] ANDROID-TRACE) " x, ## args); \
95 		} \
96 	} while (0)
97 #define ANDROID_INFO_MSG(x, args...) \
98 	do { \
99 		if (android_msg_level & ANDROID_INFO_LEVEL) { \
100 			printk(KERN_INFO "[dhd] ANDROID-INFO) " x, ## args); \
101 		} \
102 	} while (0)
103 #define ANDROID_ERROR(x) ANDROID_ERROR_MSG x
104 #define ANDROID_TRACE(x) ANDROID_TRACE_MSG x
105 #define ANDROID_INFO(x) ANDROID_INFO_MSG x
106 
107 /*
108  * Android private command strings, PLEASE define new private commands here
109  * so they can be updated easily in the future (if needed)
110  */
111 
112 #define CMD_START		"START"
113 #define CMD_STOP		"STOP"
114 #define	CMD_SCAN_ACTIVE		"SCAN-ACTIVE"
115 #define	CMD_SCAN_PASSIVE	"SCAN-PASSIVE"
116 #define CMD_RSSI		"RSSI"
117 #define CMD_LINKSPEED		"LINKSPEED"
118 #define CMD_RXFILTER_START	"RXFILTER-START"
119 #define CMD_RXFILTER_STOP	"RXFILTER-STOP"
120 #define CMD_RXFILTER_ADD	"RXFILTER-ADD"
121 #define CMD_RXFILTER_REMOVE	"RXFILTER-REMOVE"
122 #define CMD_BTCOEXSCAN_START	"BTCOEXSCAN-START"
123 #define CMD_BTCOEXSCAN_STOP	"BTCOEXSCAN-STOP"
124 #define CMD_BTCOEXMODE		"BTCOEXMODE"
125 #define CMD_SETSUSPENDOPT	"SETSUSPENDOPT"
126 #define CMD_MAXDTIM_IN_SUSPEND  "MAX_DTIM_IN_SUSPEND"
127 #define CMD_P2P_DEV_ADDR	"P2P_DEV_ADDR"
128 #define CMD_SETFWPATH		"SETFWPATH"
129 #define CMD_SETBAND		"SETBAND"
130 #define CMD_GETBAND		"GETBAND"
131 #define CMD_COUNTRY		"COUNTRY"
132 #ifdef WLMESH_CFG80211
133 #define CMD_SAE_SET_PASSWORD "SAE_SET_PASSWORD"
134 #define CMD_SET_RSDB_MODE "RSDB_MODE"
135 #endif
136 #define CMD_P2P_SET_NOA		"P2P_SET_NOA"
137 #if !defined WL_ENABLE_P2P_IF
138 #define CMD_P2P_GET_NOA			"P2P_GET_NOA"
139 #endif /* WL_ENABLE_P2P_IF */
140 #define CMD_P2P_SD_OFFLOAD		"P2P_SD_"
141 #define CMD_P2P_LISTEN_OFFLOAD		"P2P_LO_"
142 #define CMD_P2P_SET_PS		"P2P_SET_PS"
143 #define CMD_P2P_ECSA		"P2P_ECSA"
144 #define CMD_P2P_INC_BW		"P2P_INCREASE_BW"
145 #define CMD_SET_AP_WPS_P2P_IE 		"SET_AP_WPS_P2P_IE"
146 #define CMD_SETROAMMODE 	"SETROAMMODE"
147 #define CMD_SETIBSSBEACONOUIDATA	"SETIBSSBEACONOUIDATA"
148 #define CMD_MIRACAST		"MIRACAST"
149 #define CMD_COUNTRY_DELIMITER "/"
150 #ifdef WL11ULB
151 #define CMD_ULB_MODE "ULB_MODE"
152 #define CMD_ULB_BW "ULB_BW"
153 #endif /* WL11ULB */
154 #ifdef WLFBT
155 #define CMD_GET_FTKEY      "GET_FTKEY"
156 #endif
157 
158 #if defined(WL_SUPPORT_AUTO_CHANNEL)
159 #define CMD_GET_BEST_CHANNELS	"GET_BEST_CHANNELS"
160 #endif /* WL_SUPPORT_AUTO_CHANNEL */
161 
162 #define CMD_80211_MODE    "MODE"  /* 802.11 mode a/b/g/n/ac */
163 #define CMD_CHANSPEC      "CHANSPEC"
164 #define CMD_DATARATE      "DATARATE"
165 #define CMD_ASSOC_CLIENTS "ASSOCLIST"
166 #define CMD_SET_CSA       "SETCSA"
167 #ifdef WL_SUPPORT_AUTO_CHANNEL
168 #define CMD_SET_HAPD_AUTO_CHANNEL	"HAPD_AUTO_CHANNEL"
169 #endif /* WL_SUPPORT_AUTO_CHANNEL */
170 #ifdef CUSTOMER_HW4_PRIVATE_CMD
171 #ifdef SUPPORT_SET_LPC
172 #define CMD_HAPD_LPC_ENABLED		"HAPD_LPC_ENABLED"
173 #endif /* SUPPORT_SET_LPC */
174 #ifdef SUPPORT_TRIGGER_HANG_EVENT
175 #define CMD_TEST_FORCE_HANG		"TEST_FORCE_HANG"
176 #endif /* SUPPORT_TRIGGER_HANG_EVENT */
177 #ifdef TEST_TX_POWER_CONTROL
178 #define CMD_TEST_SET_TX_POWER		"TEST_SET_TX_POWER"
179 #define CMD_TEST_GET_TX_POWER		"TEST_GET_TX_POWER"
180 #endif /* TEST_TX_POWER_CONTROL */
181 #define CMD_SARLIMIT_TX_CONTROL		"SET_TX_POWER_CALLING"
182 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
183 #define CMD_KEEP_ALIVE		"KEEPALIVE"
184 
185 
186 #ifdef PNO_SUPPORT
187 #define CMD_PNOSSIDCLR_SET	"PNOSSIDCLR"
188 #define CMD_PNOSETUP_SET	"PNOSETUP "
189 #define CMD_PNOENABLE_SET	"PNOFORCE"
190 #define CMD_PNODEBUG_SET	"PNODEBUG"
191 #define CMD_WLS_BATCHING	"WLS_BATCHING"
192 #endif /* PNO_SUPPORT */
193 
194 #define	CMD_HAPD_MAC_FILTER	"HAPD_MAC_FILTER"
195 
196 #ifdef CUSTOMER_HW4_PRIVATE_CMD
197 
198 
199 #if defined(SUPPORT_RANDOM_MAC_SCAN)
200 #define ENABLE_RANDOM_MAC "ENABLE_RANDOM_MAC"
201 #define DISABLE_RANDOM_MAC "DISABLE_RANDOM_MAC"
202 #endif /* SUPPORT_RANDOM_MAC_SCAN */
203 
204 
205 #define CMD_CHANGE_RL 	"CHANGE_RL"
206 #define CMD_RESTORE_RL  "RESTORE_RL"
207 
208 #define CMD_SET_RMC_ENABLE			"SETRMCENABLE"
209 #define CMD_SET_RMC_TXRATE			"SETRMCTXRATE"
210 #define CMD_SET_RMC_ACTPERIOD		"SETRMCACTIONPERIOD"
211 #define CMD_SET_RMC_IDLEPERIOD		"SETRMCIDLEPERIOD"
212 #define CMD_SET_RMC_LEADER			"SETRMCLEADER"
213 #define CMD_SET_RMC_EVENT			"SETRMCEVENT"
214 
215 #define CMD_SET_SCSCAN		"SETSINGLEANT"
216 #define CMD_GET_SCSCAN		"GETSINGLEANT"
217 #ifdef WLTDLS
218 #define CMD_TDLS_RESET "TDLS_RESET"
219 #endif /* WLTDLS */
220 
221 #ifdef FCC_PWR_LIMIT_2G
222 #define CMD_GET_FCC_PWR_LIMIT_2G "GET_FCC_CHANNEL"
223 #define CMD_SET_FCC_PWR_LIMIT_2G "SET_FCC_CHANNEL"
224 /* CUSTOMER_HW4's value differs from BRCM FW value for enable/disable */
225 #define CUSTOMER_HW4_ENABLE		0
226 #define CUSTOMER_HW4_DISABLE	-1
227 #define CUSTOMER_HW4_EN_CONVERT(i)	(i += 1)
228 #endif /* FCC_PWR_LIMIT_2G */
229 
230 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
231 
232 
233 
234 #define CMD_ROAM_OFFLOAD			"SETROAMOFFLOAD"
235 #define CMD_INTERFACE_CREATE			"INTERFACE_CREATE"
236 #define CMD_INTERFACE_DELETE			"INTERFACE_DELETE"
237 #define CMD_GET_LINK_STATUS			"GETLINKSTATUS"
238 
239 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
240 #define CMD_GET_BSS_INFO            "GETBSSINFO"
241 #define CMD_GET_ASSOC_REJECT_INFO   "GETASSOCREJECTINFO"
242 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
243 #define CMD_GET_STA_INFO   "GETSTAINFO"
244 
245 /* related with CMD_GET_LINK_STATUS */
246 #define WL_ANDROID_LINK_VHT					0x01
247 #define WL_ANDROID_LINK_MIMO					0x02
248 #define WL_ANDROID_LINK_AP_VHT_SUPPORT		0x04
249 #define WL_ANDROID_LINK_AP_MIMO_SUPPORT	0x08
250 
251 #ifdef P2PRESP_WFDIE_SRC
252 #define CMD_P2P_SET_WFDIE_RESP      "P2P_SET_WFDIE_RESP"
253 #define CMD_P2P_GET_WFDIE_RESP      "P2P_GET_WFDIE_RESP"
254 #endif /* P2PRESP_WFDIE_SRC */
255 
256 #define CMD_DFS_AP_MOVE			"DFS_AP_MOVE"
257 #define CMD_WBTEXT_ENABLE		"WBTEXT_ENABLE"
258 #define CMD_WBTEXT_PROFILE_CONFIG	"WBTEXT_PROFILE_CONFIG"
259 #define CMD_WBTEXT_WEIGHT_CONFIG	"WBTEXT_WEIGHT_CONFIG"
260 #define CMD_WBTEXT_TABLE_CONFIG		"WBTEXT_TABLE_CONFIG"
261 #define CMD_WBTEXT_DELTA_CONFIG		"WBTEXT_DELTA_CONFIG"
262 #define CMD_WBTEXT_BTM_TIMER_THRESHOLD	"WBTEXT_BTM_TIMER_THRESHOLD"
263 #define CMD_WBTEXT_BTM_DELTA		"WBTEXT_BTM_DELTA"
264 
265 #ifdef WLWFDS
266 #define CMD_ADD_WFDS_HASH	"ADD_WFDS_HASH"
267 #define CMD_DEL_WFDS_HASH	"DEL_WFDS_HASH"
268 #endif /* WLWFDS */
269 
270 #ifdef SET_RPS_CPUS
271 #define CMD_RPSMODE  "RPSMODE"
272 #endif /* SET_RPS_CPUS */
273 
274 #ifdef BT_WIFI_HANDOVER
275 #define CMD_TBOW_TEARDOWN "TBOW_TEARDOWN"
276 #endif /* BT_WIFI_HANDOVER */
277 
278 #define CMD_MURX_BFE_CAP "MURX_BFE_CAP"
279 
280 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
281 #define CMD_SET_AP_BEACONRATE				"SET_AP_BEACONRATE"
282 #define CMD_GET_AP_BASICRATE				"GET_AP_BASICRATE"
283 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
284 
285 #ifdef SUPPORT_AP_RADIO_PWRSAVE
286 #define CMD_SET_AP_RPS						"SET_AP_RPS"
287 #define CMD_GET_AP_RPS						"GET_AP_RPS"
288 #define CMD_SET_AP_RPS_PARAMS				"SET_AP_RPS_PARAMS"
289 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
290 
291 #ifdef SUPPORT_RSSI_LOGGING
292 #define CMD_SET_RSSI_LOGGING				"SET_RSSI_LOGGING"
293 #define CMD_GET_RSSI_LOGGING				"GET_RSSI_LOGGING"
294 #define CMD_GET_RSSI_PER_ANT				"GET_RSSI_PER_ANT"
295 #endif /* SUPPORT_RSSI_LOGGING */
296 
297 #define CMD_GET_SNR							"GET_SNR"
298 
299 /* miracast related definition */
300 #define MIRACAST_MODE_OFF	0
301 #define MIRACAST_MODE_SOURCE	1
302 #define MIRACAST_MODE_SINK	2
303 
304 #ifndef MIRACAST_AMPDU_SIZE
305 #define MIRACAST_AMPDU_SIZE	8
306 #endif
307 
308 #ifndef MIRACAST_MCHAN_ALGO
309 #define MIRACAST_MCHAN_ALGO     1
310 #endif
311 
312 #ifndef MIRACAST_MCHAN_BW
313 #define MIRACAST_MCHAN_BW       25
314 #endif
315 
316 #ifdef CONNECTION_STATISTICS
317 #define CMD_GET_CONNECTION_STATS	"GET_CONNECTION_STATS"
318 
319 struct connection_stats {
320 	u32 txframe;
321 	u32 txbyte;
322 	u32 txerror;
323 	u32 rxframe;
324 	u32 rxbyte;
325 	u32 txfail;
326 	u32 txretry;
327 	u32 txretrie;
328 	u32 txrts;
329 	u32 txnocts;
330 	u32 txexptime;
331 	u32 txrate;
332 	u8	chan_idle;
333 };
334 #endif /* CONNECTION_STATISTICS */
335 
336 #ifdef SUPPORT_LQCM
337 #define CMD_SET_LQCM_ENABLE			"SET_LQCM_ENABLE"
338 #define CMD_GET_LQCM_REPORT			"GET_LQCM_REPORT"
339 #endif
340 
341 static LIST_HEAD(miracast_resume_list);
342 #ifdef WL_CFG80211
343 static u8 miracast_cur_mode;
344 #endif
345 
346 #ifdef DHD_LOG_DUMP
347 #define CMD_NEW_DEBUG_PRINT_DUMP			"DEBUG_DUMP"
348 extern void dhd_schedule_log_dump(dhd_pub_t *dhdp);
349 extern int dhd_bus_mem_dump(dhd_pub_t *dhd);
350 #endif /* DHD_LOG_DUMP */
351 
352 #ifdef DHD_HANG_SEND_UP_TEST
353 #define CMD_MAKE_HANG  "MAKE_HANG"
354 #endif /* CMD_DHD_HANG_SEND_UP_TEST */
355 #ifdef DHD_DEBUG_UART
356 extern bool dhd_debug_uart_is_running(struct net_device *dev);
357 #endif	/* DHD_DEBUG_UART */
358 
359 struct io_cfg {
360 	s8 *iovar;
361 	s32 param;
362 	u32 ioctl;
363 	void *arg;
364 	u32 len;
365 	struct list_head list;
366 };
367 
368 #if defined(BCMFW_ROAM_ENABLE)
369 #define CMD_SET_ROAMPREF	"SET_ROAMPREF"
370 
371 #define MAX_NUM_SUITES		10
372 #define WIDTH_AKM_SUITE		8
373 #define JOIN_PREF_RSSI_LEN		0x02
374 #define JOIN_PREF_RSSI_SIZE		4	/* RSSI pref header size in bytes */
375 #define JOIN_PREF_WPA_HDR_SIZE		4 /* WPA pref header size in bytes */
376 #define JOIN_PREF_WPA_TUPLE_SIZE	12	/* Tuple size in bytes */
377 #define JOIN_PREF_MAX_WPA_TUPLES	16
378 #define MAX_BUF_SIZE		(JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE +	\
379 				           (JOIN_PREF_WPA_TUPLE_SIZE * JOIN_PREF_MAX_WPA_TUPLES))
380 #endif /* BCMFW_ROAM_ENABLE */
381 
382 #ifdef WL_NATOE
383 
384 #define CMD_NATOE		"NATOE"
385 
386 #define NATOE_MAX_PORT_NUM	65535
387 
388 /* natoe command info structure */
389 typedef struct wl_natoe_cmd_info {
390 	uint8  *command;        /* pointer to the actual command */
391 	uint16 tot_len;        /* total length of the command */
392 	uint16 bytes_written;  /* Bytes written for get response */
393 } wl_natoe_cmd_info_t;
394 
395 typedef struct wl_natoe_sub_cmd wl_natoe_sub_cmd_t;
396 typedef int (natoe_cmd_handler_t)(struct net_device *dev,
397 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
398 
399 struct wl_natoe_sub_cmd {
400 	char *name;
401 	uint8  version;              /* cmd  version */
402 	uint16 id;                   /* id for the dongle f/w switch/case */
403 	uint16 type;                 /* base type of argument */
404 	natoe_cmd_handler_t *handler; /* cmd handler  */
405 };
406 
407 #define WL_ANDROID_NATOE_FUNC(suffix) wl_android_natoe_subcmd_ ##suffix
408 static int wl_android_process_natoe_cmd(struct net_device *dev,
409 		char *command, int total_len);
410 static int wl_android_natoe_subcmd_enable(struct net_device *dev,
411 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
412 static int wl_android_natoe_subcmd_config_ips(struct net_device *dev,
413 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
414 static int wl_android_natoe_subcmd_config_ports(struct net_device *dev,
415 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
416 static int wl_android_natoe_subcmd_dbg_stats(struct net_device *dev,
417 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
418 static int wl_android_natoe_subcmd_tbl_cnt(struct net_device *dev,
419 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
420 
421 static const wl_natoe_sub_cmd_t natoe_cmd_list[] = {
422 	/* wl natoe enable [0/1] or new: "wl natoe [0/1]" */
423 	{"enable", 0x01, WL_NATOE_CMD_ENABLE,
424 	IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(enable)
425 	},
426 	{"config_ips", 0x01, WL_NATOE_CMD_CONFIG_IPS,
427 	IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(config_ips)
428 	},
429 	{"config_ports", 0x01, WL_NATOE_CMD_CONFIG_PORTS,
430 	IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(config_ports)
431 	},
432 	{"stats", 0x01, WL_NATOE_CMD_DBG_STATS,
433 	IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(dbg_stats)
434 	},
435 	{"tbl_cnt", 0x01, WL_NATOE_CMD_TBL_CNT,
436 	IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(tbl_cnt)
437 	},
438 	{NULL, 0, 0, 0, NULL}
439 };
440 
441 #endif /* WL_NATOE */
442 
443 #ifdef SET_PCIE_IRQ_CPU_CORE
444 #define CMD_PCIE_IRQ_CORE	"PCIE_IRQ_CORE"
445 #endif /* SET_PCIE_IRQ_CPU_CORE */
446 
447 #ifdef WLADPS_PRIVATE_CMD
448 #define CMD_SET_ADPS	"SET_ADPS"
449 #define CMD_GET_ADPS	"GET_ADPS"
450 #endif /* WLADPS_PRIVATE_CMD */
451 
452 #ifdef DHD_PKT_LOGGING
453 #define CMD_PKTLOG_FILTER_ENABLE	"PKTLOG_FILTER_ENABLE"
454 #define CMD_PKTLOG_FILTER_DISABLE	"PKTLOG_FILTER_DISABLE"
455 #define CMD_PKTLOG_FILTER_PATTERN_ENABLE	"PKTLOG_FILTER_PATTERN_ENABLE"
456 #define CMD_PKTLOG_FILTER_PATTERN_DISABLE	"PKTLOG_FILTER_PATTERN_DISABLE"
457 #define CMD_PKTLOG_FILTER_ADD	"PKTLOG_FILTER_ADD"
458 #define CMD_PKTLOG_FILTER_INFO	"PKTLOG_FILTER_INFO"
459 #define CMD_PKTLOG_START	"PKTLOG_START"
460 #define CMD_PKTLOG_STOP		"PKTLOG_STOP"
461 #define CMD_PKTLOG_FILTER_EXIST "PKTLOG_FILTER_EXIST"
462 #endif /* DHD_PKT_LOGGING */
463 
464 #if defined(STAT_REPORT)
465 #define CMD_STAT_REPORT_GET_START	"STAT_REPORT_GET_START"
466 #define CMD_STAT_REPORT_GET_NEXT	"STAT_REPORT_GET_NEXT"
467 #endif /* STAT_REPORT */
468 
469 
470 #ifdef SUPPORT_LQCM
471 #define LQCM_ENAB_MASK			0x000000FF	/* LQCM enable flag mask */
472 #define LQCM_TX_INDEX_MASK		0x0000FF00	/* LQCM tx index mask */
473 #define LQCM_RX_INDEX_MASK		0x00FF0000	/* LQCM rx index mask */
474 
475 #define LQCM_TX_INDEX_SHIFT		8	/* LQCM tx index shift */
476 #define LQCM_RX_INDEX_SHIFT		16	/* LQCM rx index shift */
477 #endif /* SUPPORT_LQCM */
478 
479 /**
480  * Extern function declarations (TODO: move them to dhd_linux.h)
481  */
482 int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
483 int dhd_dev_init_ioctl(struct net_device *dev);
484 #ifdef WL_CFG80211
485 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
486 int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command);
487 #else
wl_cfg80211_get_p2p_dev_addr(struct net_device * net,struct ether_addr * p2pdev_addr)488 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
489 { return 0; }
wl_cfg80211_set_p2p_noa(struct net_device * net,char * buf,int len)490 int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
491 { return 0; }
wl_cfg80211_get_p2p_noa(struct net_device * net,char * buf,int len)492 int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
493 { return 0; }
wl_cfg80211_set_p2p_ps(struct net_device * net,char * buf,int len)494 int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
495 { return 0; }
wl_cfg80211_set_p2p_ecsa(struct net_device * net,char * buf,int len)496 int wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
497 { return 0; }
wl_cfg80211_increase_p2p_bw(struct net_device * net,char * buf,int len)498 int wl_cfg80211_increase_p2p_bw(struct net_device *net, char* buf, int len)
499 { return 0; }
500 #endif /* WL_CFG80211 */
501 #ifdef WBTEXT
502 static int wl_android_wbtext(struct net_device *dev, char *command, int total_len);
503 static int wl_cfg80211_wbtext_btm_timer_threshold(struct net_device *dev,
504 	char *command, int total_len);
505 static int wl_cfg80211_wbtext_btm_delta(struct net_device *dev,
506 	char *command, int total_len);
507 #endif /* WBTEXT */
508 
509 #ifdef ENABLE_4335BT_WAR
510 extern int bcm_bt_lock(int cookie);
511 extern void bcm_bt_unlock(int cookie);
512 static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24;	/* cookie is "WiFi" */
513 #endif /* ENABLE_4335BT_WAR */
514 
515 extern bool ap_fw_loaded;
516 extern char iface_name[IFNAMSIZ];
517 
518 /**
519  * Local (static) functions and variables
520  */
521 
522 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
523  * time (only) in dhd_open, subsequential wifi on will be handled by
524  * wl_android_wifi_on
525  */
526 int g_wifi_on = TRUE;
527 
528 /**
529  * Local (static) function definitions
530  */
531 
532 #ifdef WLWFDS
wl_android_set_wfds_hash(struct net_device * dev,char * command,int total_len,bool enable)533 static int wl_android_set_wfds_hash(
534 	struct net_device *dev, char *command, int total_len, bool enable)
535 {
536 	int error = 0;
537 	wl_p2p_wfds_hash_t *wfds_hash = NULL;
538 	char *smbuf = NULL;
539 	smbuf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
540 
541 	if (smbuf == NULL) {
542 		ANDROID_ERROR(("%s: failed to allocated memory %d bytes\n",
543 			__FUNCTION__, WLC_IOCTL_MAXLEN));
544 		return -ENOMEM;
545 	}
546 
547 	if (enable) {
548 		wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_ADD_WFDS_HASH) + 1);
549 		error = wldev_iovar_setbuf(dev, "p2p_add_wfds_hash", wfds_hash,
550 			sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
551 	}
552 	else {
553 		wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_DEL_WFDS_HASH) + 1);
554 		error = wldev_iovar_setbuf(dev, "p2p_del_wfds_hash", wfds_hash,
555 			sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
556 	}
557 
558 	if (error) {
559 		ANDROID_ERROR(("%s: failed to %s, error=%d\n", __FUNCTION__, command, error));
560 	}
561 
562 	if (smbuf)
563 		kfree(smbuf);
564 	return error;
565 }
566 #endif /* WLWFDS */
567 
wl_android_get_link_speed(struct net_device * net,char * command,int total_len)568 static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len)
569 {
570 	int link_speed;
571 	int bytes_written;
572 	int error;
573 
574 	error = wldev_get_link_speed(net, &link_speed);
575 	if (error) {
576 		ANDROID_ERROR(("Get linkspeed failed \n"));
577 		return -1;
578 	}
579 
580 	/* Convert Kbps to Android Mbps */
581 	link_speed = link_speed / 1000;
582 	bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
583 	ANDROID_INFO(("%s: command result is %s\n", __FUNCTION__, command));
584 	return bytes_written;
585 }
586 
wl_android_get_rssi(struct net_device * net,char * command,int total_len)587 static int wl_android_get_rssi(struct net_device *net, char *command, int total_len)
588 {
589 	wlc_ssid_t ssid = {0, {0}};
590 	int bytes_written = 0;
591 	int error = 0;
592 	scb_val_t scbval;
593 	char *delim = NULL;
594 	struct net_device *target_ndev = net;
595 #ifdef WL_VIRTUAL_APSTA
596 	char *pos = NULL;
597 	struct bcm_cfg80211 *cfg;
598 #endif /* WL_VIRTUAL_APSTA */
599 
600 	delim = strchr(command, ' ');
601 	/* For Ap mode rssi command would be
602 	 * driver rssi <sta_mac_addr>
603 	 * for STA/GC mode
604 	 * driver rssi
605 	*/
606 	if (delim) {
607 		/* Ap/GO mode
608 		* driver rssi <sta_mac_addr>
609 		*/
610 		ANDROID_TRACE(("%s: cmd:%s\n", __FUNCTION__, delim));
611 		/* skip space from delim after finding char */
612 		delim++;
613 		if (!(bcm_ether_atoe((delim), &scbval.ea)))
614 		{
615 			ANDROID_ERROR(("%s:address err\n", __FUNCTION__));
616 			return -1;
617 		}
618 	        scbval.val = htod32(0);
619 		ANDROID_TRACE(("%s: address:"MACDBG, __FUNCTION__, MAC2STRDBG(scbval.ea.octet)));
620 #ifdef WL_VIRTUAL_APSTA
621 		/* RSDB AP may have another virtual interface
622 		 * In this case, format of private command is as following,
623 		 * DRIVER rssi <sta_mac_addr> <AP interface name>
624 		 */
625 
626 		/* Current position is start of MAC address string */
627 		pos = delim;
628 		delim = strchr(pos, ' ');
629 		if (delim) {
630 			/* skip space from delim after finding char */
631 			delim++;
632 			if (strnlen(delim, IFNAMSIZ)) {
633 				cfg = wl_get_cfg(net);
634 				target_ndev = wl_get_ap_netdev(cfg, delim);
635 				if (target_ndev == NULL)
636 					target_ndev = net;
637 			}
638 		}
639 #endif /* WL_VIRTUAL_APSTA */
640 	}
641 	else {
642 		/* STA/GC mode */
643 		memset(&scbval, 0, sizeof(scb_val_t));
644 	}
645 
646 	error = wldev_get_rssi(target_ndev, &scbval);
647 	if (error)
648 		return -1;
649 #if defined(RSSIOFFSET)
650 	scbval.val = wl_update_rssi_offset(net, scbval.val);
651 #endif
652 
653 	error = wldev_get_ssid(target_ndev, &ssid);
654 	if (error)
655 		return -1;
656 	if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
657 		ANDROID_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__));
658 	} else if (total_len <= ssid.SSID_len) {
659 		return -ENOMEM;
660 	} else {
661 		memcpy(command, ssid.SSID, ssid.SSID_len);
662 		bytes_written = ssid.SSID_len;
663 	}
664 	if ((total_len - bytes_written) < (strlen(" rssi -XXX") + 1))
665 		return -ENOMEM;
666 
667 	bytes_written += scnprintf(&command[bytes_written], total_len - bytes_written,
668 		" rssi %d", scbval.val);
669 	command[bytes_written] = '\0';
670 
671 	ANDROID_TRACE(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
672 	return bytes_written;
673 }
674 
wl_android_set_suspendopt(struct net_device * dev,char * command,int total_len)675 static int wl_android_set_suspendopt(struct net_device *dev, char *command, int total_len)
676 {
677 	int suspend_flag;
678 	int ret_now;
679 	int ret = 0;
680 
681 	suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0';
682 
683 	if (suspend_flag != 0) {
684 		suspend_flag = 1;
685 	}
686 	ret_now = net_os_set_suspend_disable(dev, suspend_flag);
687 
688 	if (ret_now != suspend_flag) {
689 		if (!(ret = net_os_set_suspend(dev, ret_now, 1))) {
690 			ANDROID_INFO(("%s: Suspend Flag %d -> %d\n",
691 				__FUNCTION__, ret_now, suspend_flag));
692 		} else {
693 			ANDROID_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
694 		}
695 	}
696 
697 	return ret;
698 }
699 
700 #ifdef WL_CFG80211
wl_android_get_80211_mode(struct net_device * dev,char * command,int total_len)701 int wl_android_get_80211_mode(struct net_device *dev, char *command, int total_len)
702 {
703 	uint8 mode[5];
704 	int  error = 0;
705 	int bytes_written = 0;
706 
707 	error = wldev_get_mode(dev, mode, sizeof(mode));
708 	if (error)
709 		return -1;
710 
711 	ANDROID_INFO(("%s: mode:%s\n", __FUNCTION__, mode));
712 	bytes_written = snprintf(command, total_len, "%s %s", CMD_80211_MODE, mode);
713 	ANDROID_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
714 	return bytes_written;
715 
716 }
717 
718 extern chanspec_t
719 wl_chspec_driver_to_host(chanspec_t chanspec);
wl_android_get_chanspec(struct net_device * dev,char * command,int total_len)720 int wl_android_get_chanspec(struct net_device *dev, char *command, int total_len)
721 {
722 	int error = 0;
723 	int bytes_written = 0;
724 	int chsp = {0};
725 	uint16 band = 0;
726 	uint16 bw = 0;
727 	uint16 channel = 0;
728 	u32 sb = 0;
729 	chanspec_t chanspec;
730 
731 	/* command is
732 	 * driver chanspec
733 	 */
734 	error = wldev_iovar_getint(dev, "chanspec", &chsp);
735 	if (error)
736 		return -1;
737 
738 	chanspec = wl_chspec_driver_to_host(chsp);
739 	ANDROID_INFO(("%s:return value of chanspec:%x\n", __FUNCTION__, chanspec));
740 
741 	channel = chanspec & WL_CHANSPEC_CHAN_MASK;
742 	band = chanspec & WL_CHANSPEC_BAND_MASK;
743 	bw = chanspec & WL_CHANSPEC_BW_MASK;
744 
745 	ANDROID_INFO(("%s:channel:%d band:%d bandwidth:%d\n", __FUNCTION__, channel, band, bw));
746 
747 	if (bw == WL_CHANSPEC_BW_80)
748 		bw = WL_CH_BANDWIDTH_80MHZ;
749 	else if (bw == WL_CHANSPEC_BW_40)
750 		bw = WL_CH_BANDWIDTH_40MHZ;
751 	else if	(bw == WL_CHANSPEC_BW_20)
752 		bw = WL_CH_BANDWIDTH_20MHZ;
753 	else
754 		bw = WL_CH_BANDWIDTH_20MHZ;
755 
756 	if (bw == WL_CH_BANDWIDTH_40MHZ) {
757 		if (CHSPEC_SB_UPPER(chanspec)) {
758 			channel += CH_10MHZ_APART;
759 		} else {
760 			channel -= CH_10MHZ_APART;
761 		}
762 	}
763 	else if (bw == WL_CH_BANDWIDTH_80MHZ) {
764 		sb = chanspec & WL_CHANSPEC_CTL_SB_MASK;
765 		if (sb == WL_CHANSPEC_CTL_SB_LL) {
766 			channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
767 		} else if (sb == WL_CHANSPEC_CTL_SB_LU) {
768 			channel -= CH_10MHZ_APART;
769 		} else if (sb == WL_CHANSPEC_CTL_SB_UL) {
770 			channel += CH_10MHZ_APART;
771 		} else {
772 			/* WL_CHANSPEC_CTL_SB_UU */
773 			channel += (CH_10MHZ_APART + CH_20MHZ_APART);
774 		}
775 	}
776 	bytes_written = snprintf(command, total_len, "%s channel %d band %s bw %d", CMD_CHANSPEC,
777 		channel, band == WL_CHANSPEC_BAND_5G ? "5G":"2G", bw);
778 
779 	ANDROID_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
780 	return bytes_written;
781 
782 }
783 #endif
784 
785 /* returns current datarate datarate returned from firmware are in 500kbps */
wl_android_get_datarate(struct net_device * dev,char * command,int total_len)786 int wl_android_get_datarate(struct net_device *dev, char *command, int total_len)
787 {
788 	int  error = 0;
789 	int datarate = 0;
790 	int bytes_written = 0;
791 
792 	error = wldev_get_datarate(dev, &datarate);
793 	if (error)
794 		return -1;
795 
796 	ANDROID_INFO(("%s:datarate:%d\n", __FUNCTION__, datarate));
797 
798 	bytes_written = snprintf(command, total_len, "%s %d", CMD_DATARATE, (datarate/2));
799 	return bytes_written;
800 }
wl_android_get_assoclist(struct net_device * dev,char * command,int total_len)801 int wl_android_get_assoclist(struct net_device *dev, char *command, int total_len)
802 {
803 	int  error = 0;
804 	int bytes_written = 0;
805 	uint i;
806 	char mac_buf[MAX_NUM_OF_ASSOCLIST *
807 		sizeof(struct ether_addr) + sizeof(uint)] = {0};
808 	struct maclist *assoc_maclist = (struct maclist *)mac_buf;
809 
810 	ANDROID_TRACE(("%s: ENTER\n", __FUNCTION__));
811 
812 	assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
813 
814 	error = wldev_ioctl_get(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf));
815 	if (error)
816 		return -1;
817 
818 	assoc_maclist->count = dtoh32(assoc_maclist->count);
819 	bytes_written = snprintf(command, total_len, "%s listcount: %d Stations:",
820 		CMD_ASSOC_CLIENTS, assoc_maclist->count);
821 
822 	for (i = 0; i < assoc_maclist->count; i++) {
823 		bytes_written += snprintf(command + bytes_written, total_len, " " MACDBG,
824 			MAC2STRDBG(assoc_maclist->ea[i].octet));
825 	}
826 	return bytes_written;
827 
828 }
829 
830 #ifdef WL_CFG80211
831 extern chanspec_t
832 wl_chspec_host_to_driver(chanspec_t chanspec);
wl_android_set_csa(struct net_device * dev,char * command,int total_len)833 static int wl_android_set_csa(struct net_device *dev, char *command, int total_len)
834 {
835 	int error = 0;
836 	char smbuf[WLC_IOCTL_SMLEN];
837 	wl_chan_switch_t csa_arg;
838 	u32 chnsp = 0;
839 	int err = 0;
840 
841 	ANDROID_INFO(("%s: command:%s\n", __FUNCTION__, command));
842 
843 	command = (command + strlen(CMD_SET_CSA));
844 	/* Order is mode, count channel */
845 	if (!*++command) {
846 		ANDROID_ERROR(("%s:error missing arguments\n", __FUNCTION__));
847 		return -1;
848 	}
849 	csa_arg.mode = bcm_atoi(command);
850 
851 	if (csa_arg.mode != 0 && csa_arg.mode != 1) {
852 		ANDROID_ERROR(("Invalid mode\n"));
853 		return -1;
854 	}
855 
856 	if (!*++command) {
857 		ANDROID_ERROR(("%s:error missing count\n", __FUNCTION__));
858 		return -1;
859 	}
860 	command++;
861 	csa_arg.count = bcm_atoi(command);
862 
863 	csa_arg.reg = 0;
864 	csa_arg.chspec = 0;
865 	command += 2;
866 	if (!*command) {
867 		ANDROID_ERROR(("%s:error missing channel\n", __FUNCTION__));
868 		return -1;
869 	}
870 
871 	chnsp = wf_chspec_aton(command);
872 	if (chnsp == 0)	{
873 		ANDROID_ERROR(("%s:chsp is not correct\n", __FUNCTION__));
874 		return -1;
875 	}
876 	chnsp = wl_chspec_host_to_driver(chnsp);
877 	csa_arg.chspec = chnsp;
878 
879 	if (chnsp & WL_CHANSPEC_BAND_5G) {
880 		u32 chanspec = chnsp;
881 		err = wldev_iovar_getint(dev, "per_chan_info", &chanspec);
882 		if (!err) {
883 			if ((chanspec & WL_CHAN_RADAR) || (chanspec & WL_CHAN_PASSIVE)) {
884 				ANDROID_ERROR(("Channel is radar sensitive\n"));
885 				return -1;
886 			}
887 			if (chanspec == 0) {
888 				ANDROID_ERROR(("Invalid hw channel\n"));
889 				return -1;
890 			}
891 		} else  {
892 			ANDROID_ERROR(("does not support per_chan_info\n"));
893 			return -1;
894 		}
895 		ANDROID_INFO(("non radar sensitivity\n"));
896 	}
897 	error = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(csa_arg),
898 		smbuf, sizeof(smbuf), NULL);
899 	if (error) {
900 		ANDROID_ERROR(("%s:set csa failed:%d\n", __FUNCTION__, error));
901 		return -1;
902 	}
903 	return 0;
904 }
905 #endif
906 
907 static int
wl_android_set_max_dtim(struct net_device * dev,char * command,int total_len)908 wl_android_set_max_dtim(struct net_device *dev, char *command, int total_len)
909 {
910 	int ret = 0;
911 	int dtim_flag;
912 
913 	dtim_flag = *(command + strlen(CMD_MAXDTIM_IN_SUSPEND) + 1) - '0';
914 
915 	if (!(ret = net_os_set_max_dtim_enable(dev, dtim_flag))) {
916 		ANDROID_TRACE(("%s: use Max bcn_li_dtim in suspend %s\n",
917 			__FUNCTION__, (dtim_flag ? "Enable" : "Disable")));
918 	} else {
919 		ANDROID_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
920 	}
921 
922 	return ret;
923 }
924 
wl_android_get_band(struct net_device * dev,char * command,int total_len)925 static int wl_android_get_band(struct net_device *dev, char *command, int total_len)
926 {
927 	uint band;
928 	int bytes_written;
929 	int error;
930 
931 	error = wldev_get_band(dev, &band);
932 	if (error)
933 		return -1;
934 	bytes_written = snprintf(command, total_len, "Band %d", band);
935 	return bytes_written;
936 }
937 
938 #ifdef CUSTOMER_HW4_PRIVATE_CMD
939 
940 #ifdef WLTDLS
wl_android_tdls_reset(struct net_device * dev)941 int wl_android_tdls_reset(struct net_device *dev)
942 {
943 	int ret = 0;
944 	ret = dhd_tdls_enable(dev, false, false, NULL);
945 	if (ret < 0) {
946 		ANDROID_ERROR(("Disable tdls failed. %d\n", ret));
947 		return ret;
948 	}
949 	ret = dhd_tdls_enable(dev, true, true, NULL);
950 	if (ret < 0) {
951 		ANDROID_ERROR(("enable tdls failed. %d\n", ret));
952 		return ret;
953 	}
954 	return 0;
955 }
956 #endif /* WLTDLS */
957 #ifdef FCC_PWR_LIMIT_2G
958 int
wl_android_set_fcc_pwr_limit_2g(struct net_device * dev,char * command,int total_len)959 wl_android_set_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len)
960 {
961 	int error = 0;
962 	int enable = 0;
963 
964 	sscanf(command+sizeof("SET_FCC_CHANNEL"), "%d", &enable);
965 
966 	if ((enable != CUSTOMER_HW4_ENABLE) && (enable != CUSTOMER_HW4_DISABLE)) {
967 		ANDROID_ERROR(("%s: Invalid data\n", __FUNCTION__));
968 		return BCME_ERROR;
969 	}
970 
971 	CUSTOMER_HW4_EN_CONVERT(enable);
972 
973 	ANDROID_ERROR(("%s: fccpwrlimit2g set (%d)\n", __FUNCTION__, enable));
974 	error = wldev_iovar_setint(dev, "fccpwrlimit2g", enable);
975 	if (error) {
976 		ANDROID_ERROR(("%s: fccpwrlimit2g set returned (%d)\n", __FUNCTION__, error));
977 		return BCME_ERROR;
978 	}
979 
980 	return error;
981 }
982 
983 int
wl_android_get_fcc_pwr_limit_2g(struct net_device * dev,char * command,int total_len)984 wl_android_get_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len)
985 {
986 	int error = 0;
987 	int enable = 0;
988 	int bytes_written = 0;
989 
990 	error = wldev_iovar_getint(dev, "fccpwrlimit2g", &enable);
991 	if (error) {
992 		ANDROID_ERROR(("%s: fccpwrlimit2g get error (%d)\n", __FUNCTION__, error));
993 		return BCME_ERROR;
994 	}
995 	ANDROID_ERROR(("%s: fccpwrlimit2g get (%d)\n", __FUNCTION__, enable));
996 
997 	bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_FCC_PWR_LIMIT_2G, enable);
998 
999 	return bytes_written;
1000 }
1001 #endif /* FCC_PWR_LIMIT_2G */
1002 
1003 s32
wl_cfg80211_get_sta_info(struct net_device * dev,char * command,int total_len)1004 wl_cfg80211_get_sta_info(struct net_device *dev, char* command, int total_len)
1005 {
1006 	static char iovar_buf[WLC_IOCTL_MAXLEN];
1007 	int bytes_written = -1, ret = 0;
1008 	char *pcmd = command;
1009 	char *str;
1010 	sta_info_t *sta = NULL;
1011 	wl_cnt_wlc_t* wlc_cnt = NULL;
1012 	struct ether_addr mac;
1013 
1014 	/* Client information */
1015 	uint16 cap = 0;
1016 	uint32 rxrtry = 0;
1017 	uint32 rxmulti = 0;
1018 
1019 	ANDROID_TRACE(("%s\n", command));
1020 	str = bcmstrtok(&pcmd, " ", NULL);
1021 	if (str) {
1022 		str = bcmstrtok(&pcmd, " ", NULL);
1023 		/* If GETSTAINFO subcmd name is not provided, return error */
1024 		if (str == NULL) {
1025 			ANDROID_ERROR(("GETSTAINFO subcmd not provided %s\n", __FUNCTION__));
1026 			goto error;
1027 		}
1028 
1029 		memset(&mac, 0, ETHER_ADDR_LEN);
1030 		if ((bcm_ether_atoe((str), &mac))) {
1031 			/* get the sta info */
1032 			ret = wldev_iovar_getbuf(dev, "sta_info",
1033 				(struct ether_addr *)mac.octet,
1034 				ETHER_ADDR_LEN, iovar_buf, WLC_IOCTL_SMLEN, NULL);
1035 			if (ret < 0) {
1036 				ANDROID_ERROR(("Get sta_info ERR %d\n", ret));
1037 				goto error;
1038 			}
1039 
1040 			sta = (sta_info_t *)iovar_buf;
1041 			cap = dtoh16(sta->cap);
1042 			rxrtry = dtoh32(sta->rx_pkts_retried);
1043 			rxmulti = dtoh32(sta->rx_mcast_pkts);
1044 		} else if ((!strncmp(str, "all", 3)) || (!strncmp(str, "ALL", 3))) {
1045 			/* get counters info */
1046 			ret = wldev_iovar_getbuf(dev, "counters", NULL, 0,
1047 				iovar_buf, WLC_IOCTL_MAXLEN, NULL);
1048 			if (unlikely(ret)) {
1049 				ANDROID_ERROR(("counters error (%d) - size = %zu\n",
1050 					ret, sizeof(wl_cnt_wlc_t)));
1051 				goto error;
1052 			}
1053 			ret = wl_cntbuf_to_xtlv_format(NULL, iovar_buf, WL_CNTBUF_MAX_SIZE, 0);
1054 			if (ret != BCME_OK) {
1055 				ANDROID_ERROR(("wl_cntbuf_to_xtlv_format ERR %d\n", ret));
1056 				goto error;
1057 			}
1058 			if (!(wlc_cnt = GET_WLCCNT_FROM_CNTBUF(iovar_buf))) {
1059 				ANDROID_ERROR(("wlc_cnt NULL!\n"));
1060 				goto error;
1061 			}
1062 
1063 			rxrtry = dtoh32(wlc_cnt->rxrtry);
1064 			rxmulti = dtoh32(wlc_cnt->rxmulti);
1065 		} else {
1066 			ANDROID_ERROR(("Get address fail\n"));
1067 			goto error;
1068 		}
1069 	} else {
1070 		ANDROID_ERROR(("Command ERR\n"));
1071 		goto error;
1072 	}
1073 
1074 	bytes_written = snprintf(command, total_len,
1075 		"%s %s Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d CAP=%04x\n",
1076 		CMD_GET_STA_INFO, str, rxrtry, rxmulti, cap);
1077 
1078 	ANDROID_TRACE(("%s", command));
1079 
1080 error:
1081 	return bytes_written;
1082 }
1083 #endif
1084 
1085 #ifdef WBTEXT
wl_android_wbtext(struct net_device * dev,char * command,int total_len)1086 static int wl_android_wbtext(struct net_device *dev, char *command, int total_len)
1087 {
1088 	int error = BCME_OK, argc = 0;
1089 	int data, bytes_written;
1090 	int roam_trigger[2];
1091 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
1092 
1093 	argc = sscanf(command+sizeof(CMD_WBTEXT_ENABLE), "%d", &data);
1094 	if (!argc) {
1095 		error = wldev_iovar_getint(dev, "wnm_bsstrans_resp", &data);
1096 		if (error) {
1097 			ANDROID_ERROR(("%s: Failed to set wbtext error = %d\n",
1098 				__FUNCTION__, error));
1099 			return error;
1100 		}
1101 		bytes_written = snprintf(command, total_len, "WBTEXT %s\n",
1102 				(data == WL_BSSTRANS_POLICY_PRODUCT_WBTEXT)?
1103 				"ENABLED" : "DISABLED");
1104 		return bytes_written;
1105 	} else {
1106 		if (data) {
1107 			data = WL_BSSTRANS_POLICY_PRODUCT_WBTEXT;
1108 		}
1109 
1110 		if ((error = wldev_iovar_setint(dev, "wnm_bsstrans_resp", data)) != BCME_OK) {
1111 			ANDROID_ERROR(("%s: Failed to set wbtext error = %d\n",
1112 				__FUNCTION__, error));
1113 			return error;
1114 		}
1115 
1116 		if (data) {
1117 			/* reset roam_prof when wbtext is on */
1118 			if ((error = wl_cfg80211_wbtext_set_default(dev)) != BCME_OK) {
1119 				return error;
1120 			}
1121 			dhdp->wbtext_support = TRUE;
1122 		} else {
1123 			/* reset legacy roam trigger when wbtext is off */
1124 			roam_trigger[0] = DEFAULT_ROAM_TRIGGER_VALUE;
1125 			roam_trigger[1] = WLC_BAND_ALL;
1126 			if ((error = wldev_ioctl_set(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
1127 					sizeof(roam_trigger))) != BCME_OK) {
1128 				ANDROID_ERROR(("%s: Failed to reset roam trigger = %d\n",
1129 					__FUNCTION__, error));
1130 				return error;
1131 			}
1132 			dhdp->wbtext_support = FALSE;
1133 		}
1134 	}
1135 	return error;
1136 }
1137 
wl_cfg80211_wbtext_btm_timer_threshold(struct net_device * dev,char * command,int total_len)1138 static int wl_cfg80211_wbtext_btm_timer_threshold(struct net_device *dev,
1139 	char *command, int total_len)
1140 {
1141 	int error = BCME_OK, argc = 0;
1142 	int data, bytes_written;
1143 
1144 	argc = sscanf(command, CMD_WBTEXT_BTM_TIMER_THRESHOLD " %d\n", &data);
1145 	if (!argc) {
1146 		error = wldev_iovar_getint(dev, "wnm_bsstrans_timer_threshold", &data);
1147 		if (error) {
1148 			ANDROID_ERROR(("Failed to get wnm_bsstrans_timer_threshold (%d)\n", error));
1149 			return error;
1150 		}
1151 		bytes_written = snprintf(command, total_len, "%d\n", data);
1152 		return bytes_written;
1153 	} else {
1154 		if ((error = wldev_iovar_setint(dev, "wnm_bsstrans_timer_threshold",
1155 				data)) != BCME_OK) {
1156 			ANDROID_ERROR(("Failed to set wnm_bsstrans_timer_threshold (%d)\n", error));
1157 			return error;
1158 		}
1159 	}
1160 	return error;
1161 }
1162 
wl_cfg80211_wbtext_btm_delta(struct net_device * dev,char * command,int total_len)1163 static int wl_cfg80211_wbtext_btm_delta(struct net_device *dev,
1164 	char *command, int total_len)
1165 {
1166 	int error = BCME_OK, argc = 0;
1167 	int data = 0, bytes_written;
1168 
1169 	argc = sscanf(command, CMD_WBTEXT_BTM_DELTA " %d\n", &data);
1170 	if (!argc) {
1171 		error = wldev_iovar_getint(dev, "wnm_btmdelta", &data);
1172 		if (error) {
1173 			ANDROID_ERROR(("Failed to get wnm_btmdelta (%d)\n", error));
1174 			return error;
1175 		}
1176 		bytes_written = snprintf(command, total_len, "%d\n", data);
1177 		return bytes_written;
1178 	} else {
1179 		if ((error = wldev_iovar_setint(dev, "wnm_btmdelta",
1180 				data)) != BCME_OK) {
1181 			ANDROID_ERROR(("Failed to set wnm_btmdelta (%d)\n", error));
1182 			return error;
1183 		}
1184 	}
1185 	return error;
1186 }
1187 
1188 #endif /* WBTEXT */
1189 
1190 #ifdef PNO_SUPPORT
1191 #define PNO_PARAM_SIZE 50
1192 #define VALUE_SIZE 50
1193 #define LIMIT_STR_FMT  ("%50s %50s")
1194 
1195 static int
wls_parse_batching_cmd(struct net_device * dev,char * command,int total_len)1196 wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len)
1197 {
1198 	int err = BCME_OK;
1199 	uint i, tokens;
1200 	char *pos, *pos2, *token, *token2, *delim;
1201 	char param[PNO_PARAM_SIZE+1], value[VALUE_SIZE+1];
1202 	struct dhd_pno_batch_params batch_params;
1203 
1204 	ANDROID_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
1205 	if (total_len < strlen(CMD_WLS_BATCHING)) {
1206 		ANDROID_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
1207 		err = BCME_ERROR;
1208 		goto exit;
1209 	}
1210 	pos = command + strlen(CMD_WLS_BATCHING) + 1;
1211 	memset(&batch_params, 0, sizeof(struct dhd_pno_batch_params));
1212 
1213 	if (!strncmp(pos, PNO_BATCHING_SET, strlen(PNO_BATCHING_SET))) {
1214 		pos += strlen(PNO_BATCHING_SET) + 1;
1215 		while ((token = strsep(&pos, PNO_PARAMS_DELIMETER)) != NULL) {
1216 			memset(param, 0, sizeof(param));
1217 			memset(value, 0, sizeof(value));
1218 			if (token == NULL || !*token)
1219 				break;
1220 			if (*token == '\0')
1221 				continue;
1222 			delim = strchr(token, PNO_PARAM_VALUE_DELLIMETER);
1223 			if (delim != NULL)
1224 				*delim = ' ';
1225 
1226 			tokens = sscanf(token, LIMIT_STR_FMT, param, value);
1227 			if (!strncmp(param, PNO_PARAM_SCANFREQ, strlen(PNO_PARAM_SCANFREQ))) {
1228 				batch_params.scan_fr = simple_strtol(value, NULL, 0);
1229 				ANDROID_INFO(("scan_freq : %d\n", batch_params.scan_fr));
1230 			} else if (!strncmp(param, PNO_PARAM_BESTN, strlen(PNO_PARAM_BESTN))) {
1231 				batch_params.bestn = simple_strtol(value, NULL, 0);
1232 				ANDROID_INFO(("bestn : %d\n", batch_params.bestn));
1233 			} else if (!strncmp(param, PNO_PARAM_MSCAN, strlen(PNO_PARAM_MSCAN))) {
1234 				batch_params.mscan = simple_strtol(value, NULL, 0);
1235 				ANDROID_INFO(("mscan : %d\n", batch_params.mscan));
1236 			} else if (!strncmp(param, PNO_PARAM_CHANNEL, strlen(PNO_PARAM_CHANNEL))) {
1237 				i = 0;
1238 				pos2 = value;
1239 				tokens = sscanf(value, "<%s>", value);
1240 				if (tokens != 1) {
1241 					err = BCME_ERROR;
1242 					ANDROID_ERROR(("%s : invalid format for channel"
1243 					" <> params\n", __FUNCTION__));
1244 					goto exit;
1245 				}
1246 				while ((token2 = strsep(&pos2,
1247 						PNO_PARAM_CHANNEL_DELIMETER)) != NULL) {
1248 					if (token2 == NULL || !*token2)
1249 						break;
1250 					if (*token2 == '\0')
1251 						continue;
1252 					if (*token2 == 'A' || *token2 == 'B') {
1253 						batch_params.band = (*token2 == 'A')?
1254 							WLC_BAND_5G : WLC_BAND_2G;
1255 						ANDROID_INFO(("band : %s\n",
1256 							(*token2 == 'A')? "A" : "B"));
1257 					} else {
1258 						if ((batch_params.nchan >= WL_NUMCHANNELS) ||
1259 							(i >= WL_NUMCHANNELS)) {
1260 							ANDROID_ERROR(("Too many nchan %d\n",
1261 								batch_params.nchan));
1262 							err = BCME_BUFTOOSHORT;
1263 							goto exit;
1264 						}
1265 						batch_params.chan_list[i++] =
1266 							simple_strtol(token2, NULL, 0);
1267 						batch_params.nchan++;
1268 						ANDROID_INFO(("channel :%d\n",
1269 							batch_params.chan_list[i-1]));
1270 					}
1271 				 }
1272 			} else if (!strncmp(param, PNO_PARAM_RTT, strlen(PNO_PARAM_RTT))) {
1273 				batch_params.rtt = simple_strtol(value, NULL, 0);
1274 				ANDROID_INFO(("rtt : %d\n", batch_params.rtt));
1275 			} else {
1276 				ANDROID_ERROR(("%s : unknown param: %s\n", __FUNCTION__, param));
1277 				err = BCME_ERROR;
1278 				goto exit;
1279 			}
1280 		}
1281 		err = dhd_dev_pno_set_for_batch(dev, &batch_params);
1282 		if (err < 0) {
1283 			ANDROID_ERROR(("failed to configure batch scan\n"));
1284 		} else {
1285 			memset(command, 0, total_len);
1286 			err = snprintf(command, total_len, "%d", err);
1287 		}
1288 	} else if (!strncmp(pos, PNO_BATCHING_GET, strlen(PNO_BATCHING_GET))) {
1289 		err = dhd_dev_pno_get_for_batch(dev, command, total_len);
1290 		if (err < 0) {
1291 			ANDROID_ERROR(("failed to getting batching results\n"));
1292 		} else {
1293 			err = strlen(command);
1294 		}
1295 	} else if (!strncmp(pos, PNO_BATCHING_STOP, strlen(PNO_BATCHING_STOP))) {
1296 		err = dhd_dev_pno_stop_for_batch(dev);
1297 		if (err < 0) {
1298 			ANDROID_ERROR(("failed to stop batching scan\n"));
1299 		} else {
1300 			memset(command, 0, total_len);
1301 			err = snprintf(command, total_len, "OK");
1302 		}
1303 	} else {
1304 		ANDROID_ERROR(("%s : unknown command\n", __FUNCTION__));
1305 		err = BCME_ERROR;
1306 		goto exit;
1307 	}
1308 exit:
1309 	return err;
1310 }
1311 
1312 #ifndef WL_SCHED_SCAN
wl_android_set_pno_setup(struct net_device * dev,char * command,int total_len)1313 static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
1314 {
1315 	wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
1316 	int res = -1;
1317 	int nssid = 0;
1318 	cmd_tlv_t *cmd_tlv_temp;
1319 	char *str_ptr;
1320 	int tlv_size_left;
1321 	int pno_time = 0;
1322 	int pno_repeat = 0;
1323 	int pno_freq_expo_max = 0;
1324 
1325 #ifdef PNO_SET_DEBUG
1326 	int i;
1327 	char pno_in_example[] = {
1328 		'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
1329 		'S', '1', '2', '0',
1330 		'S',
1331 		0x05,
1332 		'd', 'l', 'i', 'n', 'k',
1333 		'S',
1334 		0x04,
1335 		'G', 'O', 'O', 'G',
1336 		'T',
1337 		'0', 'B',
1338 		'R',
1339 		'2',
1340 		'M',
1341 		'2',
1342 		0x00
1343 		};
1344 #endif /* PNO_SET_DEBUG */
1345 	ANDROID_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
1346 
1347 	if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
1348 		ANDROID_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
1349 		goto exit_proc;
1350 	}
1351 #ifdef PNO_SET_DEBUG
1352 	memcpy(command, pno_in_example, sizeof(pno_in_example));
1353 	total_len = sizeof(pno_in_example);
1354 #endif
1355 	str_ptr = command + strlen(CMD_PNOSETUP_SET);
1356 	tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
1357 
1358 	cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
1359 	memset(ssids_local, 0, sizeof(ssids_local));
1360 
1361 	if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
1362 		(cmd_tlv_temp->version == PNO_TLV_VERSION) &&
1363 		(cmd_tlv_temp->subtype == PNO_TLV_SUBTYPE_LEGACY_PNO)) {
1364 
1365 		str_ptr += sizeof(cmd_tlv_t);
1366 		tlv_size_left -= sizeof(cmd_tlv_t);
1367 
1368 		if ((nssid = wl_parse_ssid_list_tlv(&str_ptr, ssids_local,
1369 			MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
1370 			ANDROID_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
1371 			goto exit_proc;
1372 		} else {
1373 			if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
1374 				ANDROID_ERROR(("%s scan duration corrupted field size %d\n",
1375 					__FUNCTION__, tlv_size_left));
1376 				goto exit_proc;
1377 			}
1378 			str_ptr++;
1379 			pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
1380 			ANDROID_INFO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
1381 
1382 			if (str_ptr[0] != 0) {
1383 				if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
1384 					ANDROID_ERROR(("%s pno repeat : corrupted field\n",
1385 						__FUNCTION__));
1386 					goto exit_proc;
1387 				}
1388 				str_ptr++;
1389 				pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
1390 				ANDROID_INFO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
1391 				if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
1392 					ANDROID_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n",
1393 						__FUNCTION__));
1394 					goto exit_proc;
1395 				}
1396 				str_ptr++;
1397 				pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
1398 				ANDROID_INFO(("%s: pno_freq_expo_max=%d\n",
1399 					__FUNCTION__, pno_freq_expo_max));
1400 			}
1401 		}
1402 	} else {
1403 		ANDROID_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
1404 		goto exit_proc;
1405 	}
1406 
1407 	res = dhd_dev_pno_set_for_ssid(dev, ssids_local, nssid, pno_time, pno_repeat,
1408 		pno_freq_expo_max, NULL, 0);
1409 exit_proc:
1410 	return res;
1411 }
1412 #endif /* !WL_SCHED_SCAN */
1413 #endif /* PNO_SUPPORT  */
1414 
wl_android_get_p2p_dev_addr(struct net_device * ndev,char * command,int total_len)1415 static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
1416 {
1417 	int ret;
1418 	int bytes_written = 0;
1419 
1420 	ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command);
1421 	if (ret)
1422 		return 0;
1423 	bytes_written = sizeof(struct ether_addr);
1424 	return bytes_written;
1425 }
1426 
1427 
1428 int
wl_android_set_ap_mac_list(struct net_device * dev,int macmode,struct maclist * maclist)1429 wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist)
1430 {
1431 	int i, j, match;
1432 	int ret	= 0;
1433 	char mac_buf[MAX_NUM_OF_ASSOCLIST *
1434 		sizeof(struct ether_addr) + sizeof(uint)] = {0};
1435 	struct maclist *assoc_maclist = (struct maclist *)mac_buf;
1436 
1437 	/* set filtering mode */
1438 	if ((ret = wldev_ioctl_set(dev, WLC_SET_MACMODE, &macmode, sizeof(macmode)) != 0)) {
1439 		ANDROID_ERROR(("%s : WLC_SET_MACMODE error=%d\n", __FUNCTION__, ret));
1440 		return ret;
1441 	}
1442 	if (macmode != MACLIST_MODE_DISABLED) {
1443 		/* set the MAC filter list */
1444 		if ((ret = wldev_ioctl_set(dev, WLC_SET_MACLIST, maclist,
1445 			sizeof(int) + sizeof(struct ether_addr) * maclist->count)) != 0) {
1446 			ANDROID_ERROR(("%s : WLC_SET_MACLIST error=%d\n", __FUNCTION__, ret));
1447 			return ret;
1448 		}
1449 		/* get the current list of associated STAs */
1450 		assoc_maclist->count = MAX_NUM_OF_ASSOCLIST;
1451 		if ((ret = wldev_ioctl_get(dev, WLC_GET_ASSOCLIST, assoc_maclist,
1452 			sizeof(mac_buf))) != 0) {
1453 			ANDROID_ERROR(("%s : WLC_GET_ASSOCLIST error=%d\n", __FUNCTION__, ret));
1454 			return ret;
1455 		}
1456 		/* do we have any STA associated?  */
1457 		if (assoc_maclist->count) {
1458 			/* iterate each associated STA */
1459 			for (i = 0; i < assoc_maclist->count; i++) {
1460 				match = 0;
1461 				/* compare with each entry */
1462 				for (j = 0; j < maclist->count; j++) {
1463 					ANDROID_INFO(("%s : associated="MACDBG " list="MACDBG "\n",
1464 					__FUNCTION__, MAC2STRDBG(assoc_maclist->ea[i].octet),
1465 					MAC2STRDBG(maclist->ea[j].octet)));
1466 					if (memcmp(assoc_maclist->ea[i].octet,
1467 						maclist->ea[j].octet, ETHER_ADDR_LEN) == 0) {
1468 						match = 1;
1469 						break;
1470 					}
1471 				}
1472 				/* do conditional deauth */
1473 				/*   "if not in the allow list" or "if in the deny list" */
1474 				if ((macmode == MACLIST_MODE_ALLOW && !match) ||
1475 					(macmode == MACLIST_MODE_DENY && match)) {
1476 					scb_val_t scbval;
1477 
1478 					scbval.val = htod32(1);
1479 					memcpy(&scbval.ea, &assoc_maclist->ea[i],
1480 						ETHER_ADDR_LEN);
1481 					if ((ret = wldev_ioctl_set(dev,
1482 						WLC_SCB_DEAUTHENTICATE_FOR_REASON,
1483 						&scbval, sizeof(scb_val_t))) != 0)
1484 						ANDROID_ERROR(("%s WLC_SCB_DEAUTHENTICATE error=%d\n",
1485 							__FUNCTION__, ret));
1486 				}
1487 			}
1488 		}
1489 	}
1490 	return ret;
1491 }
1492 
1493 /*
1494  * HAPD_MAC_FILTER mac_mode mac_cnt mac_addr1 mac_addr2
1495  *
1496  */
1497 static int
wl_android_set_mac_address_filter(struct net_device * dev,char * str)1498 wl_android_set_mac_address_filter(struct net_device *dev, char* str)
1499 {
1500 	int i;
1501 	int ret = 0;
1502 	int macnum = 0;
1503 	int macmode = MACLIST_MODE_DISABLED;
1504 	struct maclist *list;
1505 	char eabuf[ETHER_ADDR_STR_LEN];
1506 	const char *token;
1507 
1508 	/* string should look like below (macmode/macnum/maclist) */
1509 	/*   1 2 00:11:22:33:44:55 00:11:22:33:44:ff  */
1510 
1511 	/* get the MAC filter mode */
1512 	token = strsep((char**)&str, " ");
1513 	if (!token) {
1514 		return -1;
1515 	}
1516 	macmode = bcm_atoi(token);
1517 
1518 	if (macmode < MACLIST_MODE_DISABLED || macmode > MACLIST_MODE_ALLOW) {
1519 		ANDROID_ERROR(("%s : invalid macmode %d\n", __FUNCTION__, macmode));
1520 		return -1;
1521 	}
1522 
1523 	token = strsep((char**)&str, " ");
1524 	if (!token) {
1525 		return -1;
1526 	}
1527 	macnum = bcm_atoi(token);
1528 	if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
1529 		ANDROID_ERROR(("%s : invalid number of MAC address entries %d\n",
1530 			__FUNCTION__, macnum));
1531 		return -1;
1532 	}
1533 	/* allocate memory for the MAC list */
1534 	list = (struct maclist*)kmalloc(sizeof(int) +
1535 		sizeof(struct ether_addr) * macnum, GFP_KERNEL);
1536 	if (!list) {
1537 		ANDROID_ERROR(("%s : failed to allocate memory\n", __FUNCTION__));
1538 		return -1;
1539 	}
1540 	/* prepare the MAC list */
1541 	list->count = htod32(macnum);
1542 	bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
1543 	for (i = 0; i < list->count; i++) {
1544 		strncpy(eabuf, strsep((char**)&str, " "), ETHER_ADDR_STR_LEN - 1);
1545 		if (!(ret = bcm_ether_atoe(eabuf, &list->ea[i]))) {
1546 			ANDROID_ERROR(("%s : mac parsing err index=%d, addr=%s\n",
1547 				__FUNCTION__, i, eabuf));
1548 			list->count--;
1549 			break;
1550 		}
1551 		ANDROID_INFO(("%s : %d/%d MACADDR=%s", __FUNCTION__, i, list->count, eabuf));
1552 	}
1553 	/* set the list */
1554 	if ((ret = wl_android_set_ap_mac_list(dev, macmode, list)) != 0)
1555 		ANDROID_ERROR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
1556 
1557 	kfree(list);
1558 
1559 	return 0;
1560 }
1561 
1562 /**
1563  * Global function definitions (declared in wl_android.h)
1564  */
1565 
wl_android_wifi_on(struct net_device * dev)1566 int wl_android_wifi_on(struct net_device *dev)
1567 {
1568 	int ret = 0;
1569 	int retry = POWERUP_MAX_RETRY;
1570 
1571 	if (!dev) {
1572 		ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
1573 		return -EINVAL;
1574 	}
1575 
1576 	dhd_net_if_lock(dev);
1577 	WL_MSG(dev->name, "in g_wifi_on=%d\n", g_wifi_on);
1578 	if (!g_wifi_on) {
1579 		do {
1580 			if (!dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY)) {
1581 #ifdef BCMSDIO
1582 			ret = dhd_net_bus_resume(dev, 0);
1583 #endif /* BCMSDIO */
1584 			}
1585 #ifdef BCMPCIE
1586 			ret = dhd_net_bus_devreset(dev, FALSE);
1587 #endif /* BCMPCIE */
1588 			if (ret == 0) {
1589 				break;
1590 			}
1591 			ANDROID_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n",
1592 				retry));
1593 #ifdef BCMPCIE
1594 			dhd_net_bus_devreset(dev, TRUE);
1595 #endif /* BCMPCIE */
1596 			dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
1597 		} while (retry-- > 0);
1598 		if (ret != 0) {
1599 			ANDROID_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n"));
1600 			goto exit;
1601 		}
1602 #if defined(BCMSDIO) || defined(BCMDBUS)
1603 		ret = dhd_net_bus_devreset(dev, FALSE);
1604 		if (ret)
1605 			goto err;
1606 #ifdef BCMSDIO
1607 		dhd_net_bus_resume(dev, 1);
1608 #endif /* BCMSDIO */
1609 #endif /* BCMSDIO || BCMDBUS */
1610 #if defined(BCMSDIO) || defined(BCMDBUS)
1611 		if (!ret) {
1612 			if (dhd_dev_init_ioctl(dev) < 0) {
1613 				ret = -EFAULT;
1614 				goto err;
1615 			}
1616 		}
1617 #endif /* BCMSDIO || BCMDBUS */
1618 		g_wifi_on = TRUE;
1619 	}
1620 
1621 exit:
1622 	WL_MSG(dev->name, "Success\n");
1623 	dhd_net_if_unlock(dev);
1624 	return ret;
1625 
1626 #if defined(BCMSDIO) || defined(BCMDBUS)
1627 err:
1628 	dhd_net_bus_devreset(dev, TRUE);
1629 #ifdef BCMSDIO
1630 	dhd_net_bus_suspend(dev);
1631 #endif /* BCMSDIO */
1632 	dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
1633 	WL_MSG(dev->name, "Failed\n");
1634 	dhd_net_if_unlock(dev);
1635 	return ret;
1636 #endif /* BCMSDIO || BCMDBUS */
1637 }
1638 
wl_android_wifi_off(struct net_device * dev,bool on_failure)1639 int wl_android_wifi_off(struct net_device *dev, bool on_failure)
1640 {
1641 	int ret = 0;
1642 
1643 	if (!dev) {
1644 		ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
1645 		return -EINVAL;
1646 	}
1647 
1648 #if defined(BCMPCIE) && defined(DHD_DEBUG_UART)
1649 	ret = dhd_debug_uart_is_running(dev);
1650 	if (ret) {
1651 		ANDROID_ERROR(("%s - Debug UART App is running\n", __FUNCTION__));
1652 		return -EBUSY;
1653 	}
1654 #endif	/* BCMPCIE && DHD_DEBUG_UART */
1655 	dhd_net_if_lock(dev);
1656 	WL_MSG(dev->name, "in g_wifi_on=%d, on_failure=%d\n", g_wifi_on, on_failure);
1657 	if (g_wifi_on || on_failure) {
1658 #if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMDBUS)
1659 		ret = dhd_net_bus_devreset(dev, TRUE);
1660 #if  defined(BCMSDIO)
1661 		dhd_net_bus_suspend(dev);
1662 #endif /* BCMSDIO */
1663 #endif /* BCMSDIO || BCMPCIE || BCMDBUS */
1664 		dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
1665 		g_wifi_on = FALSE;
1666 #ifdef DHD_LOAD_CHIPALIVE
1667 		dhd_chip_alive = FALSE;
1668 #endif
1669 	}
1670 	WL_MSG(dev->name, "out\n");
1671 	dhd_net_if_unlock(dev);
1672 
1673 	return ret;
1674 }
1675 
wl_android_set_fwpath(struct net_device * net,char * command,int total_len)1676 static int wl_android_set_fwpath(struct net_device *net, char *command, int total_len)
1677 {
1678 	if ((strlen(command) - strlen(CMD_SETFWPATH)) > MOD_PARAM_PATHLEN)
1679 		return -1;
1680 	return dhd_net_set_fw_path(net, command + strlen(CMD_SETFWPATH) + 1);
1681 }
1682 
1683 #ifdef CONNECTION_STATISTICS
1684 static int
wl_chanim_stats(struct net_device * dev,u8 * chan_idle)1685 wl_chanim_stats(struct net_device *dev, u8 *chan_idle)
1686 {
1687 	int err;
1688 	wl_chanim_stats_t *list;
1689 	/* Parameter _and_ returned buffer of chanim_stats. */
1690 	wl_chanim_stats_t param;
1691 	u8 result[WLC_IOCTL_SMLEN];
1692 	chanim_stats_t *stats;
1693 
1694 	memset(&param, 0, sizeof(param));
1695 
1696 	param.buflen = htod32(sizeof(wl_chanim_stats_t));
1697 	param.count = htod32(WL_CHANIM_COUNT_ONE);
1698 
1699 	if ((err = wldev_iovar_getbuf(dev, "chanim_stats", (char*)&param, sizeof(wl_chanim_stats_t),
1700 		(char*)result, sizeof(result), 0)) < 0) {
1701 		ANDROID_ERROR(("Failed to get chanim results %d \n", err));
1702 		return err;
1703 	}
1704 
1705 	list = (wl_chanim_stats_t*)result;
1706 
1707 	list->buflen = dtoh32(list->buflen);
1708 	list->version = dtoh32(list->version);
1709 	list->count = dtoh32(list->count);
1710 
1711 	if (list->buflen == 0) {
1712 		list->version = 0;
1713 		list->count = 0;
1714 	} else if (list->version != WL_CHANIM_STATS_VERSION) {
1715 		ANDROID_ERROR(("Sorry, firmware has wl_chanim_stats version %d "
1716 			"but driver supports only version %d.\n",
1717 				list->version, WL_CHANIM_STATS_VERSION));
1718 		list->buflen = 0;
1719 		list->count = 0;
1720 	}
1721 
1722 	stats = list->stats;
1723 	stats->glitchcnt = dtoh32(stats->glitchcnt);
1724 	stats->badplcp = dtoh32(stats->badplcp);
1725 	stats->chanspec = dtoh16(stats->chanspec);
1726 	stats->timestamp = dtoh32(stats->timestamp);
1727 	stats->chan_idle = dtoh32(stats->chan_idle);
1728 
1729 	ANDROID_INFO(("chanspec: 0x%4x glitch: %d badplcp: %d idle: %d timestamp: %d\n",
1730 		stats->chanspec, stats->glitchcnt, stats->badplcp, stats->chan_idle,
1731 		stats->timestamp));
1732 
1733 	*chan_idle = stats->chan_idle;
1734 
1735 	return (err);
1736 }
1737 
1738 static int
wl_android_get_connection_stats(struct net_device * dev,char * command,int total_len)1739 wl_android_get_connection_stats(struct net_device *dev, char *command, int total_len)
1740 {
1741 	static char iovar_buf[WLC_IOCTL_MAXLEN];
1742 	wl_cnt_wlc_t* wlc_cnt = NULL;
1743 #ifndef DISABLE_IF_COUNTERS
1744 	wl_if_stats_t* if_stats = NULL;
1745 #endif /* DISABLE_IF_COUNTERS */
1746 
1747 	int link_speed = 0;
1748 	struct connection_stats *output;
1749 	unsigned int bufsize = 0;
1750 	int bytes_written = -1;
1751 	int ret = 0;
1752 
1753 	ANDROID_INFO(("%s: enter Get Connection Stats\n", __FUNCTION__));
1754 
1755 	if (total_len <= 0) {
1756 		ANDROID_ERROR(("%s: invalid buffer size %d\n", __FUNCTION__, total_len));
1757 		goto error;
1758 	}
1759 
1760 	bufsize = total_len;
1761 	if (bufsize < sizeof(struct connection_stats)) {
1762 		ANDROID_ERROR(("%s: not enough buffer size, provided=%u, requires=%zu\n",
1763 			__FUNCTION__, bufsize,
1764 			sizeof(struct connection_stats)));
1765 		goto error;
1766 	}
1767 
1768 	output = (struct connection_stats *)command;
1769 
1770 #ifndef DISABLE_IF_COUNTERS
1771 	if ((if_stats = kmalloc(sizeof(*if_stats), GFP_KERNEL)) == NULL) {
1772 		ANDROID_ERROR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__));
1773 		goto error;
1774 	}
1775 	memset(if_stats, 0, sizeof(*if_stats));
1776 
1777 	ret = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
1778 		(char *)if_stats, sizeof(*if_stats), NULL);
1779 	if (ret) {
1780 		ANDROID_ERROR(("%s: if_counters not supported ret=%d\n",
1781 			__FUNCTION__, ret));
1782 
1783 		/* In case if_stats IOVAR is not supported, get information from counters. */
1784 #endif /* DISABLE_IF_COUNTERS */
1785 		ret = wldev_iovar_getbuf(dev, "counters", NULL, 0,
1786 			iovar_buf, WLC_IOCTL_MAXLEN, NULL);
1787 		if (unlikely(ret)) {
1788 			ANDROID_ERROR(("counters error (%d) - size = %zu\n", ret, sizeof(wl_cnt_wlc_t)));
1789 			goto error;
1790 		}
1791 		ret = wl_cntbuf_to_xtlv_format(NULL, iovar_buf, WL_CNTBUF_MAX_SIZE, 0);
1792 		if (ret != BCME_OK) {
1793 			ANDROID_ERROR(("%s wl_cntbuf_to_xtlv_format ERR %d\n",
1794 			__FUNCTION__, ret));
1795 			goto error;
1796 		}
1797 
1798 		if (!(wlc_cnt = GET_WLCCNT_FROM_CNTBUF(iovar_buf))) {
1799 			ANDROID_ERROR(("%s wlc_cnt NULL!\n", __FUNCTION__));
1800 			goto error;
1801 		}
1802 
1803 		output->txframe   = dtoh32(wlc_cnt->txframe);
1804 		output->txbyte    = dtoh32(wlc_cnt->txbyte);
1805 		output->txerror   = dtoh32(wlc_cnt->txerror);
1806 		output->rxframe   = dtoh32(wlc_cnt->rxframe);
1807 		output->rxbyte    = dtoh32(wlc_cnt->rxbyte);
1808 		output->txfail    = dtoh32(wlc_cnt->txfail);
1809 		output->txretry   = dtoh32(wlc_cnt->txretry);
1810 		output->txretrie  = dtoh32(wlc_cnt->txretrie);
1811 		output->txrts     = dtoh32(wlc_cnt->txrts);
1812 		output->txnocts   = dtoh32(wlc_cnt->txnocts);
1813 		output->txexptime = dtoh32(wlc_cnt->txexptime);
1814 #ifndef DISABLE_IF_COUNTERS
1815 	} else {
1816 		/* Populate from if_stats. */
1817 		if (dtoh16(if_stats->version) > WL_IF_STATS_T_VERSION) {
1818 			ANDROID_ERROR(("%s: incorrect version of wl_if_stats_t, expected=%u got=%u\n",
1819 				__FUNCTION__,  WL_IF_STATS_T_VERSION, if_stats->version));
1820 			goto error;
1821 		}
1822 
1823 		output->txframe   = (uint32)dtoh64(if_stats->txframe);
1824 		output->txbyte    = (uint32)dtoh64(if_stats->txbyte);
1825 		output->txerror   = (uint32)dtoh64(if_stats->txerror);
1826 		output->rxframe   = (uint32)dtoh64(if_stats->rxframe);
1827 		output->rxbyte    = (uint32)dtoh64(if_stats->rxbyte);
1828 		output->txfail    = (uint32)dtoh64(if_stats->txfail);
1829 		output->txretry   = (uint32)dtoh64(if_stats->txretry);
1830 		output->txretrie  = (uint32)dtoh64(if_stats->txretrie);
1831 		if (dtoh16(if_stats->length) > OFFSETOF(wl_if_stats_t, txexptime)) {
1832 			output->txexptime = (uint32)dtoh64(if_stats->txexptime);
1833 			output->txrts     = (uint32)dtoh64(if_stats->txrts);
1834 			output->txnocts   = (uint32)dtoh64(if_stats->txnocts);
1835 		} else {
1836 			output->txexptime = 0;
1837 			output->txrts     = 0;
1838 			output->txnocts   = 0;
1839 		}
1840 	}
1841 #endif /* DISABLE_IF_COUNTERS */
1842 
1843 	/* link_speed is in kbps */
1844 	ret = wldev_get_link_speed(dev, &link_speed);
1845 	if (ret || link_speed < 0) {
1846 		ANDROID_ERROR(("%s: wldev_get_link_speed() failed, ret=%d, speed=%d\n",
1847 			__FUNCTION__, ret, link_speed));
1848 		goto error;
1849 	}
1850 
1851 	output->txrate    = link_speed;
1852 
1853 	/* Channel idle ratio. */
1854 	if (wl_chanim_stats(dev, &(output->chan_idle)) < 0) {
1855 		output->chan_idle = 0;
1856 	};
1857 
1858 	bytes_written = sizeof(struct connection_stats);
1859 
1860 error:
1861 #ifndef DISABLE_IF_COUNTERS
1862 	if (if_stats) {
1863 		kfree(if_stats);
1864 	}
1865 #endif /* DISABLE_IF_COUNTERS */
1866 
1867 	return bytes_written;
1868 }
1869 #endif /* CONNECTION_STATISTICS */
1870 
1871 #ifdef WL_NATOE
1872 static int
wl_android_process_natoe_cmd(struct net_device * dev,char * command,int total_len)1873 wl_android_process_natoe_cmd(struct net_device *dev, char *command, int total_len)
1874 {
1875 	int ret = BCME_ERROR;
1876 	char *pcmd = command;
1877 	char *str = NULL;
1878 	wl_natoe_cmd_info_t cmd_info;
1879 	const wl_natoe_sub_cmd_t *natoe_cmd = &natoe_cmd_list[0];
1880 
1881 	/* skip to cmd name after "natoe" */
1882 	str = bcmstrtok(&pcmd, " ", NULL);
1883 
1884 	/* If natoe subcmd name is not provided, return error */
1885 	if (*pcmd == '\0') {
1886 		ANDROID_ERROR(("natoe subcmd not provided %s\n", __FUNCTION__));
1887 		ret = -EINVAL;
1888 		return ret;
1889 	}
1890 
1891 	/* get the natoe command name to str */
1892 	str = bcmstrtok(&pcmd, " ", NULL);
1893 
1894 	while (natoe_cmd->name != NULL) {
1895 		if (strcmp(natoe_cmd->name, str) == 0)  {
1896 			/* dispacth cmd to appropriate handler */
1897 			if (natoe_cmd->handler) {
1898 				cmd_info.command = command;
1899 				cmd_info.tot_len = total_len;
1900 				ret = natoe_cmd->handler(dev, natoe_cmd, pcmd, &cmd_info);
1901 			}
1902 			return ret;
1903 		}
1904 		natoe_cmd++;
1905 	}
1906 	return ret;
1907 }
1908 
1909 static int
wlu_natoe_set_vars_cbfn(void * ctx,uint8 * data,uint16 type,uint16 len)1910 wlu_natoe_set_vars_cbfn(void *ctx, uint8 *data, uint16 type, uint16 len)
1911 {
1912 	int res = BCME_OK;
1913 	wl_natoe_cmd_info_t *cmd_info = (wl_natoe_cmd_info_t *)ctx;
1914 	uint8 *command = cmd_info->command;
1915 	uint16 total_len = cmd_info->tot_len;
1916 	uint16 bytes_written = 0;
1917 
1918 	UNUSED_PARAMETER(len);
1919 
1920 	switch (type) {
1921 
1922 	case WL_NATOE_XTLV_ENABLE:
1923 	{
1924 		bytes_written = snprintf(command, total_len, "natoe: %s\n",
1925 				*data?"enabled":"disabled");
1926 		cmd_info->bytes_written = bytes_written;
1927 		break;
1928 	}
1929 
1930 	case WL_NATOE_XTLV_CONFIG_IPS:
1931 	{
1932 		wl_natoe_config_ips_t *config_ips;
1933 		uint8 buf[16];
1934 
1935 		config_ips = (wl_natoe_config_ips_t *)data;
1936 		bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_ip, buf);
1937 		bytes_written = snprintf(command, total_len, "sta ip: %s\n", buf);
1938 		bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_netmask, buf);
1939 		bytes_written += snprintf(command + bytes_written, total_len,
1940 				"sta netmask: %s\n", buf);
1941 		bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_router_ip, buf);
1942 		bytes_written += snprintf(command + bytes_written, total_len,
1943 				"sta router ip: %s\n", buf);
1944 		bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_dnsip, buf);
1945 		bytes_written += snprintf(command + bytes_written, total_len,
1946 				"sta dns ip: %s\n", buf);
1947 		bcm_ip_ntoa((struct ipv4_addr *)&config_ips->ap_ip, buf);
1948 		bytes_written += snprintf(command + bytes_written, total_len,
1949 				"ap ip: %s\n", buf);
1950 		bcm_ip_ntoa((struct ipv4_addr *)&config_ips->ap_netmask, buf);
1951 		bytes_written += snprintf(command + bytes_written, total_len,
1952 				"ap netmask: %s\n", buf);
1953 		cmd_info->bytes_written = bytes_written;
1954 		break;
1955 	}
1956 
1957 	case WL_NATOE_XTLV_CONFIG_PORTS:
1958 	{
1959 		wl_natoe_ports_config_t *ports_config;
1960 
1961 		ports_config = (wl_natoe_ports_config_t *)data;
1962 		bytes_written = snprintf(command, total_len, "starting port num: %d\n",
1963 				dtoh16(ports_config->start_port_num));
1964 		bytes_written += snprintf(command + bytes_written, total_len,
1965 				"number of ports: %d\n", dtoh16(ports_config->no_of_ports));
1966 		cmd_info->bytes_written = bytes_written;
1967 		break;
1968 	}
1969 
1970 	case WL_NATOE_XTLV_DBG_STATS:
1971 	{
1972 		char *stats_dump = (char *)data;
1973 
1974 		bytes_written = snprintf(command, total_len, "%s\n", stats_dump);
1975 		cmd_info->bytes_written = bytes_written;
1976 		break;
1977 	}
1978 
1979 	case WL_NATOE_XTLV_TBL_CNT:
1980 	{
1981 		bytes_written = snprintf(command, total_len, "natoe max tbl entries: %d\n",
1982 				dtoh32(*(uint32 *)data));
1983 		cmd_info->bytes_written = bytes_written;
1984 		break;
1985 	}
1986 
1987 	default:
1988 		/* ignore */
1989 		break;
1990 	}
1991 
1992 	return res;
1993 }
1994 
1995 /*
1996  *   --- common for all natoe get commands ----
1997  */
1998 static int
wl_natoe_get_ioctl(struct net_device * dev,wl_natoe_ioc_t * natoe_ioc,uint16 iocsz,uint8 * buf,uint16 buflen,wl_natoe_cmd_info_t * cmd_info)1999 wl_natoe_get_ioctl(struct net_device *dev, wl_natoe_ioc_t *natoe_ioc,
2000 		uint16 iocsz, uint8 *buf, uint16 buflen, wl_natoe_cmd_info_t *cmd_info)
2001 {
2002 	/* for gets we only need to pass ioc header */
2003 	wl_natoe_ioc_t *iocresp = (wl_natoe_ioc_t *)buf;
2004 	int res;
2005 
2006 	/*  send getbuf natoe iovar */
2007 	res = wldev_iovar_getbuf(dev, "natoe", natoe_ioc, iocsz, buf,
2008 			buflen, NULL);
2009 
2010 	/*  check the response buff  */
2011 	if ((res == BCME_OK)) {
2012 		/* scans ioctl tlvbuf f& invokes the cbfn for processing  */
2013 		res = bcm_unpack_xtlv_buf(cmd_info, iocresp->data, iocresp->len,
2014 				BCM_XTLV_OPTION_ALIGN32, wlu_natoe_set_vars_cbfn);
2015 
2016 		if (res == BCME_OK) {
2017 			res = cmd_info->bytes_written;
2018 		}
2019 	}
2020 	else
2021 	{
2022 		ANDROID_ERROR(("%s: get command failed code %d\n", __FUNCTION__, res));
2023 		res = BCME_ERROR;
2024 	}
2025 
2026 	return res;
2027 }
2028 
2029 static int
wl_android_natoe_subcmd_enable(struct net_device * dev,const wl_natoe_sub_cmd_t * cmd,char * command,wl_natoe_cmd_info_t * cmd_info)2030 wl_android_natoe_subcmd_enable(struct net_device *dev, const wl_natoe_sub_cmd_t *cmd,
2031 		char *command, wl_natoe_cmd_info_t *cmd_info)
2032 {
2033 	int ret = BCME_OK;
2034 	wl_natoe_ioc_t *natoe_ioc;
2035 	char *pcmd = command;
2036 	uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2037 	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
2038 	uint16 buflen = WL_NATOE_IOC_BUFSZ;
2039 	bcm_xtlv_t *pxtlv = NULL;
2040 	char *ioctl_buf = NULL;
2041 
2042 	ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags);
2043 	if (!ioctl_buf) {
2044 		ANDROID_ERROR(("ioctl memory alloc failed\n"));
2045 		return -ENOMEM;
2046 	}
2047 
2048 	/* alloc mem for ioctl headr + tlv data */
2049 	natoe_ioc = kzalloc(iocsz, kflags);
2050 	if (!natoe_ioc) {
2051 		ANDROID_ERROR(("ioctl header memory alloc failed\n"));
2052 		kfree(ioctl_buf);
2053 		return -ENOMEM;
2054 	}
2055 
2056 	/* make up natoe cmd ioctl header */
2057 	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
2058 	natoe_ioc->id = htod16(cmd->id);
2059 	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
2060 	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
2061 
2062 	if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
2063 		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
2064 		ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
2065 				WLC_IOCTL_MEDLEN, cmd_info);
2066 		if (ret != BCME_OK) {
2067 			ANDROID_ERROR(("Fail to get iovar %s\n", __FUNCTION__));
2068 			ret = -EINVAL;
2069 		}
2070 	} else {	/* set */
2071 		uint8 val = bcm_atoi(pcmd);
2072 
2073 		/* buflen is max tlv data we can write, it will be decremented as we pack */
2074 		/* save buflen at start */
2075 		uint16 buflen_at_start = buflen;
2076 
2077 		/* we'll adjust final ioc size at the end */
2078 		ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_ENABLE,
2079 			sizeof(uint8), &val, BCM_XTLV_OPTION_ALIGN32);
2080 
2081 		if (ret != BCME_OK) {
2082 			ret = -EINVAL;
2083 			goto exit;
2084 		}
2085 
2086 		/* adjust iocsz to the end of last data record */
2087 		natoe_ioc->len = (buflen_at_start - buflen);
2088 		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
2089 
2090 		ret = wldev_iovar_setbuf(dev, "natoe",
2091 				natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2092 		if (ret != BCME_OK) {
2093 			ANDROID_ERROR(("Fail to set iovar %d\n", ret));
2094 			ret = -EINVAL;
2095 		}
2096 	}
2097 
2098 exit:
2099 	kfree(ioctl_buf);
2100 	kfree(natoe_ioc);
2101 
2102 	return ret;
2103 }
2104 
2105 static int
wl_android_natoe_subcmd_config_ips(struct net_device * dev,const wl_natoe_sub_cmd_t * cmd,char * command,wl_natoe_cmd_info_t * cmd_info)2106 wl_android_natoe_subcmd_config_ips(struct net_device *dev,
2107 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info)
2108 {
2109 	int ret = BCME_OK;
2110 	wl_natoe_config_ips_t config_ips;
2111 	wl_natoe_ioc_t *natoe_ioc;
2112 	char *pcmd = command;
2113 	char *str;
2114 	uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2115 	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
2116 	uint16 buflen = WL_NATOE_IOC_BUFSZ;
2117 	bcm_xtlv_t *pxtlv = NULL;
2118 	char *ioctl_buf = NULL;
2119 
2120 	ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags);
2121 	if (!ioctl_buf) {
2122 		ANDROID_ERROR(("ioctl memory alloc failed\n"));
2123 		return -ENOMEM;
2124 	}
2125 
2126 	/* alloc mem for ioctl headr + tlv data */
2127 	natoe_ioc = kzalloc(iocsz, kflags);
2128 	if (!natoe_ioc) {
2129 		ANDROID_ERROR(("ioctl header memory alloc failed\n"));
2130 		kfree(ioctl_buf);
2131 		return -ENOMEM;
2132 	}
2133 
2134 	/* make up natoe cmd ioctl header */
2135 	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
2136 	natoe_ioc->id = htod16(cmd->id);
2137 	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
2138 	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
2139 
2140 	if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
2141 		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
2142 		ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
2143 				WLC_IOCTL_MEDLEN, cmd_info);
2144 		if (ret != BCME_OK) {
2145 			ANDROID_ERROR(("Fail to get iovar %s\n", __FUNCTION__));
2146 			ret = -EINVAL;
2147 		}
2148 	} else {	/* set */
2149 		/* buflen is max tlv data we can write, it will be decremented as we pack */
2150 		/* save buflen at start */
2151 		uint16 buflen_at_start = buflen;
2152 
2153 		memset(&config_ips, 0, sizeof(config_ips));
2154 
2155 		str = bcmstrtok(&pcmd, " ", NULL);
2156 		if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_ip)) {
2157 			ANDROID_ERROR(("Invalid STA IP addr %s\n", str));
2158 			ret = -EINVAL;
2159 			goto exit;
2160 		}
2161 
2162 		str = bcmstrtok(&pcmd, " ", NULL);
2163 		if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_netmask)) {
2164 			ANDROID_ERROR(("Invalid STA netmask %s\n", str));
2165 			ret = -EINVAL;
2166 			goto exit;
2167 		}
2168 
2169 		str = bcmstrtok(&pcmd, " ", NULL);
2170 		if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_router_ip)) {
2171 			ANDROID_ERROR(("Invalid STA router IP addr %s\n", str));
2172 			ret = -EINVAL;
2173 			goto exit;
2174 		}
2175 
2176 		str = bcmstrtok(&pcmd, " ", NULL);
2177 		if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_dnsip)) {
2178 			ANDROID_ERROR(("Invalid STA DNS IP addr %s\n", str));
2179 			ret = -EINVAL;
2180 			goto exit;
2181 		}
2182 
2183 		str = bcmstrtok(&pcmd, " ", NULL);
2184 		if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.ap_ip)) {
2185 			ANDROID_ERROR(("Invalid AP IP addr %s\n", str));
2186 			ret = -EINVAL;
2187 			goto exit;
2188 		}
2189 
2190 		str = bcmstrtok(&pcmd, " ", NULL);
2191 		if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.ap_netmask)) {
2192 			ANDROID_ERROR(("Invalid AP netmask %s\n", str));
2193 			ret = -EINVAL;
2194 			goto exit;
2195 		}
2196 
2197 		ret = bcm_pack_xtlv_entry((uint8**)&pxtlv,
2198 				&buflen, WL_NATOE_XTLV_CONFIG_IPS, sizeof(config_ips),
2199 				&config_ips, BCM_XTLV_OPTION_ALIGN32);
2200 
2201 		if (ret != BCME_OK) {
2202 			ret = -EINVAL;
2203 			goto exit;
2204 		}
2205 
2206 		/* adjust iocsz to the end of last data record */
2207 		natoe_ioc->len = (buflen_at_start - buflen);
2208 		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
2209 
2210 		ret = wldev_iovar_setbuf(dev, "natoe",
2211 				natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2212 		if (ret != BCME_OK) {
2213 			ANDROID_ERROR(("Fail to set iovar %d\n", ret));
2214 			ret = -EINVAL;
2215 		}
2216 	}
2217 
2218 exit:
2219 	kfree(ioctl_buf);
2220 	kfree(natoe_ioc);
2221 
2222 	return ret;
2223 }
2224 
2225 static int
wl_android_natoe_subcmd_config_ports(struct net_device * dev,const wl_natoe_sub_cmd_t * cmd,char * command,wl_natoe_cmd_info_t * cmd_info)2226 wl_android_natoe_subcmd_config_ports(struct net_device *dev,
2227 		const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info)
2228 {
2229 	int ret = BCME_OK;
2230 	wl_natoe_ports_config_t ports_config;
2231 	wl_natoe_ioc_t *natoe_ioc;
2232 	char *pcmd = command;
2233 	char *str;
2234 	uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2235 	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
2236 	uint16 buflen = WL_NATOE_IOC_BUFSZ;
2237 	bcm_xtlv_t *pxtlv = NULL;
2238 	char *ioctl_buf = NULL;
2239 
2240 	ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags);
2241 	if (!ioctl_buf) {
2242 		ANDROID_ERROR(("ioctl memory alloc failed\n"));
2243 		return -ENOMEM;
2244 	}
2245 
2246 	/* alloc mem for ioctl headr + tlv data */
2247 	natoe_ioc = kzalloc(iocsz, kflags);
2248 	if (!natoe_ioc) {
2249 		ANDROID_ERROR(("ioctl header memory alloc failed\n"));
2250 		kfree(ioctl_buf);
2251 		return -ENOMEM;
2252 	}
2253 
2254 	/* make up natoe cmd ioctl header */
2255 	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
2256 	natoe_ioc->id = htod16(cmd->id);
2257 	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
2258 	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
2259 
2260 	if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
2261 		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
2262 		ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
2263 				WLC_IOCTL_MEDLEN, cmd_info);
2264 		if (ret != BCME_OK) {
2265 			ANDROID_ERROR(("Fail to get iovar %s\n", __FUNCTION__));
2266 			ret = -EINVAL;
2267 		}
2268 	} else {	/* set */
2269 		/* buflen is max tlv data we can write, it will be decremented as we pack */
2270 		/* save buflen at start */
2271 		uint16 buflen_at_start = buflen;
2272 
2273 		memset(&ports_config, 0, sizeof(ports_config));
2274 
2275 		str = bcmstrtok(&pcmd, " ", NULL);
2276 		if (!str) {
2277 			ANDROID_ERROR(("Invalid port string %s\n", str));
2278 			ret = -EINVAL;
2279 			goto exit;
2280 		}
2281 		ports_config.start_port_num = htod16(bcm_atoi(str));
2282 
2283 		str = bcmstrtok(&pcmd, " ", NULL);
2284 		if (!str) {
2285 			ANDROID_ERROR(("Invalid port string %s\n", str));
2286 			ret = -EINVAL;
2287 			goto exit;
2288 		}
2289 		ports_config.no_of_ports = htod16(bcm_atoi(str));
2290 
2291 		if ((uint32)(ports_config.start_port_num + ports_config.no_of_ports) >
2292 				NATOE_MAX_PORT_NUM) {
2293 			ANDROID_ERROR(("Invalid port configuration\n"));
2294 			ret = -EINVAL;
2295 			goto exit;
2296 		}
2297 		ret = bcm_pack_xtlv_entry((uint8**)&pxtlv,
2298 				&buflen, WL_NATOE_XTLV_CONFIG_PORTS, sizeof(ports_config),
2299 				&ports_config, BCM_XTLV_OPTION_ALIGN32);
2300 
2301 		if (ret != BCME_OK) {
2302 			ret = -EINVAL;
2303 			goto exit;
2304 		}
2305 
2306 		/* adjust iocsz to the end of last data record */
2307 		natoe_ioc->len = (buflen_at_start - buflen);
2308 		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
2309 
2310 		ret = wldev_iovar_setbuf(dev, "natoe",
2311 				natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2312 		if (ret != BCME_OK) {
2313 			ANDROID_ERROR(("Fail to set iovar %d\n", ret));
2314 			ret = -EINVAL;
2315 		}
2316 	}
2317 
2318 exit:
2319 	kfree(ioctl_buf);
2320 	kfree(natoe_ioc);
2321 
2322 	return ret;
2323 }
2324 
2325 static int
wl_android_natoe_subcmd_dbg_stats(struct net_device * dev,const wl_natoe_sub_cmd_t * cmd,char * command,wl_natoe_cmd_info_t * cmd_info)2326 wl_android_natoe_subcmd_dbg_stats(struct net_device *dev, const wl_natoe_sub_cmd_t *cmd,
2327 		char *command, wl_natoe_cmd_info_t *cmd_info)
2328 {
2329 	int ret = BCME_OK;
2330 	wl_natoe_ioc_t *natoe_ioc;
2331 	char *pcmd = command;
2332 	uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2333 	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_DBG_STATS_BUFSZ;
2334 	uint16 buflen = WL_NATOE_DBG_STATS_BUFSZ;
2335 	bcm_xtlv_t *pxtlv = NULL;
2336 	char *ioctl_buf = NULL;
2337 
2338 	ioctl_buf = kzalloc(WLC_IOCTL_MAXLEN, kflags);
2339 	if (!ioctl_buf) {
2340 		ANDROID_ERROR(("ioctl memory alloc failed\n"));
2341 		return -ENOMEM;
2342 	}
2343 
2344 	/* alloc mem for ioctl headr + tlv data */
2345 	natoe_ioc = kzalloc(iocsz, kflags);
2346 	if (!natoe_ioc) {
2347 		ANDROID_ERROR(("ioctl header memory alloc failed\n"));
2348 		kfree(ioctl_buf);
2349 		return -ENOMEM;
2350 	}
2351 
2352 	/* make up natoe cmd ioctl header */
2353 	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
2354 	natoe_ioc->id = htod16(cmd->id);
2355 	natoe_ioc->len = htod16(WL_NATOE_DBG_STATS_BUFSZ);
2356 	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
2357 
2358 	if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
2359 		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
2360 		ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
2361 				WLC_IOCTL_MAXLEN, cmd_info);
2362 		if (ret != BCME_OK) {
2363 			ANDROID_ERROR(("Fail to get iovar %s\n", __FUNCTION__));
2364 			ret = -EINVAL;
2365 		}
2366 	} else {	/* set */
2367 		uint8 val = bcm_atoi(pcmd);
2368 
2369 		/* buflen is max tlv data we can write, it will be decremented as we pack */
2370 		/* save buflen at start */
2371 		uint16 buflen_at_start = buflen;
2372 
2373 		/* we'll adjust final ioc size at the end */
2374 		ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_ENABLE,
2375 			sizeof(uint8), &val, BCM_XTLV_OPTION_ALIGN32);
2376 
2377 		if (ret != BCME_OK) {
2378 			ret = -EINVAL;
2379 			goto exit;
2380 		}
2381 
2382 		/* adjust iocsz to the end of last data record */
2383 		natoe_ioc->len = (buflen_at_start - buflen);
2384 		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
2385 
2386 		ret = wldev_iovar_setbuf(dev, "natoe",
2387 				natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
2388 		if (ret != BCME_OK) {
2389 			ANDROID_ERROR(("Fail to set iovar %d\n", ret));
2390 			ret = -EINVAL;
2391 		}
2392 	}
2393 
2394 exit:
2395 	kfree(ioctl_buf);
2396 	kfree(natoe_ioc);
2397 
2398 	return ret;
2399 }
2400 
2401 static int
wl_android_natoe_subcmd_tbl_cnt(struct net_device * dev,const wl_natoe_sub_cmd_t * cmd,char * command,wl_natoe_cmd_info_t * cmd_info)2402 wl_android_natoe_subcmd_tbl_cnt(struct net_device *dev, const wl_natoe_sub_cmd_t *cmd,
2403 		char *command, wl_natoe_cmd_info_t *cmd_info)
2404 {
2405 	int ret = BCME_OK;
2406 	wl_natoe_ioc_t *natoe_ioc;
2407 	char *pcmd = command;
2408 	uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2409 	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
2410 	uint16 buflen = WL_NATOE_IOC_BUFSZ;
2411 	bcm_xtlv_t *pxtlv = NULL;
2412 	char *ioctl_buf = NULL;
2413 
2414 	ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags);
2415 	if (!ioctl_buf) {
2416 		ANDROID_ERROR(("ioctl memory alloc failed\n"));
2417 		return -ENOMEM;
2418 	}
2419 
2420 	/* alloc mem for ioctl headr + tlv data */
2421 	natoe_ioc = kzalloc(iocsz, kflags);
2422 	if (!natoe_ioc) {
2423 		ANDROID_ERROR(("ioctl header memory alloc failed\n"));
2424 		kfree(ioctl_buf);
2425 		return -ENOMEM;
2426 	}
2427 
2428 	/* make up natoe cmd ioctl header */
2429 	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
2430 	natoe_ioc->id = htod16(cmd->id);
2431 	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
2432 	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
2433 
2434 	if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
2435 		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
2436 		ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
2437 				WLC_IOCTL_MEDLEN, cmd_info);
2438 		if (ret != BCME_OK) {
2439 			ANDROID_ERROR(("Fail to get iovar %s\n", __FUNCTION__));
2440 			ret = -EINVAL;
2441 		}
2442 	} else {	/* set */
2443 		uint32 val = bcm_atoi(pcmd);
2444 
2445 		/* buflen is max tlv data we can write, it will be decremented as we pack */
2446 		/* save buflen at start */
2447 		uint16 buflen_at_start = buflen;
2448 
2449 		/* we'll adjust final ioc size at the end */
2450 		ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_TBL_CNT,
2451 			sizeof(uint32), &val, BCM_XTLV_OPTION_ALIGN32);
2452 
2453 		if (ret != BCME_OK) {
2454 			ret = -EINVAL;
2455 			goto exit;
2456 		}
2457 
2458 		/* adjust iocsz to the end of last data record */
2459 		natoe_ioc->len = (buflen_at_start - buflen);
2460 		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
2461 
2462 		ret = wldev_iovar_setbuf(dev, "natoe",
2463 				natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2464 		if (ret != BCME_OK) {
2465 			ANDROID_ERROR(("Fail to set iovar %d\n", ret));
2466 			ret = -EINVAL;
2467 		}
2468 	}
2469 
2470 exit:
2471 	kfree(ioctl_buf);
2472 	kfree(natoe_ioc);
2473 
2474 	return ret;
2475 }
2476 
2477 #endif /* WL_NATOE */
2478 
2479 #ifdef CUSTOMER_HW4_PRIVATE_CMD
2480 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
2481 
2482 #if defined(WL_SUPPORT_AUTO_CHANNEL)
2483 /* SoftAP feature */
2484 #define APCS_BAND_2G_LEGACY1	20
2485 #define APCS_BAND_2G_LEGACY2	0
2486 #define APCS_BAND_AUTO		"band=auto"
2487 #define APCS_BAND_2G		"band=2g"
2488 #define APCS_BAND_5G		"band=5g"
2489 #define APCS_MAX_2G_CHANNELS	11
2490 #define APCS_MAX_RETRY		10
2491 #define APCS_DEFAULT_2G_CH	1
2492 #define APCS_DEFAULT_5G_CH	149
2493 
2494 static int
wl_android_set_auto_channel(struct net_device * dev,const char * cmd_str,char * command,int total_len)2495 wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
2496 	char* command, int total_len)
2497 {
2498 	int channel = 0;
2499 	int chosen = 0;
2500 	int retry = 0;
2501 	int ret = 0;
2502 	int spect = 0;
2503 	u8 *reqbuf = NULL;
2504 	uint32 band = WLC_BAND_2G, sta_band = WLC_BAND_2G;
2505 	uint32 buf_size;
2506 
2507 	if (cmd_str) {
2508 		ANDROID_INFO(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str)));
2509 		if (strnicmp(cmd_str, APCS_BAND_AUTO, strlen(APCS_BAND_AUTO)) == 0) {
2510 			band = WLC_BAND_AUTO;
2511 		} else if (strnicmp(cmd_str, APCS_BAND_5G, strlen(APCS_BAND_5G)) == 0) {
2512 			band = WLC_BAND_5G;
2513 		} else if (strnicmp(cmd_str, APCS_BAND_2G, strlen(APCS_BAND_2G)) == 0) {
2514 			band = WLC_BAND_2G;
2515 		} else {
2516 			/*
2517 			 * For backward compatibility: Some platforms used to issue argument 20 or 0
2518 			 * to enforce the 2G channel selection
2519 			 */
2520 			channel = bcm_atoi(cmd_str);
2521 			if ((channel == APCS_BAND_2G_LEGACY1) ||
2522 				(channel == APCS_BAND_2G_LEGACY2)) {
2523 				band = WLC_BAND_2G;
2524 			} else {
2525 				ANDROID_ERROR(("Invalid argument\n"));
2526 				return -EINVAL;
2527 			}
2528 		}
2529 	} else {
2530 		/* If no argument is provided, default to 2G */
2531 		ANDROID_ERROR(("No argument given default to 2.4G scan\n"));
2532 		band = WLC_BAND_2G;
2533 	}
2534 	ANDROID_INFO(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band));
2535 
2536 	/* If STA is connected, return is STA channel, else ACS can be issued,
2537 	 * set spect to 0 and proceed with ACS
2538 	 */
2539 	channel = wl_cfg80211_get_sta_channel(dev);
2540 	if (channel) {
2541 		sta_band = WL_GET_BAND(channel);
2542 		switch (sta_band) {
2543 			case (WL_CHANSPEC_BAND_5G): {
2544 				if (band == WLC_BAND_2G || band == WLC_BAND_AUTO) {
2545 					channel = APCS_DEFAULT_2G_CH;
2546 				}
2547 				break;
2548 			}
2549 			case (WL_CHANSPEC_BAND_2G): {
2550 				if (band == WLC_BAND_5G) {
2551 					channel = APCS_DEFAULT_5G_CH;
2552 				}
2553 				break;
2554 			}
2555 			default:
2556 				/* Intentional fall through to use same sta channel for softap */
2557 				break;
2558 		}
2559 		WL_MSG(dev->name, "band=%d, sta_band=%d, channel=%d\n", band, sta_band, channel);
2560 		goto done2;
2561 	}
2562 
2563 	channel = wl_ext_autochannel(dev, ACS_FW_BIT|ACS_DRV_BIT, band);
2564 	if (channel)
2565 		goto done2;
2566 	else
2567 		goto done;
2568 
2569 	if ((ret =
2570 	     wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect))) < 0) {
2571 		ANDROID_ERROR(("ACS: error getting the spect\n"));
2572 		goto done;
2573 	}
2574 
2575 	if (spect > 0) {
2576 		/* If STA is connected, return is STA channel, else ACS can be issued,
2577 		 * set spect to 0 and proceed with ACS
2578 		 */
2579 		channel = wl_cfg80211_get_sta_channel(dev);
2580 		if (channel) {
2581 			channel = (channel <= CH_MAX_2G_CHANNEL) ? channel : APCS_DEFAULT_2G_CH;
2582 			goto done2;
2583 		}
2584 
2585 		if ((ret = wl_cfg80211_set_spect(dev, 0) < 0)) {
2586 			ANDROID_ERROR(("ACS: error while setting spect\n"));
2587 			goto done;
2588 		}
2589 	}
2590 
2591 	reqbuf = kzalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
2592 	if (reqbuf == NULL) {
2593 		ANDROID_ERROR(("failed to allocate chanspec buffer\n"));
2594 		return -ENOMEM;
2595 	}
2596 
2597 	if (band == WLC_BAND_AUTO) {
2598 		ANDROID_INFO(("ACS full channel scan \n"));
2599 		reqbuf[0] = htod32(0);
2600 	} else if (band == WLC_BAND_5G) {
2601 		ANDROID_INFO(("ACS 5G band scan \n"));
2602 		if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
2603 			ANDROID_ERROR(("ACS 5g chanspec retreival failed! \n"));
2604 			goto done;
2605 		}
2606 	} else if (band == WLC_BAND_2G) {
2607 		/*
2608 		 * If channel argument is not provided/ argument 20 is provided,
2609 		 * Restrict channel to 2GHz, 20MHz BW, No SB
2610 		 */
2611 		ANDROID_INFO(("ACS 2G band scan \n"));
2612 		if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
2613 			ANDROID_ERROR(("ACS 2g chanspec retreival failed! \n"));
2614 			goto done;
2615 		}
2616 	} else {
2617 		ANDROID_ERROR(("ACS: No band chosen\n"));
2618 		goto done2;
2619 	}
2620 
2621 	buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
2622 	ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
2623 		buf_size);
2624 	if (ret < 0) {
2625 		ANDROID_ERROR(("can't start auto channel scan, err = %d\n", ret));
2626 		channel = 0;
2627 		goto done;
2628 	}
2629 
2630 	/* Wait for auto channel selection, max 3000 ms */
2631 	if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G)) {
2632 		OSL_SLEEP(500);
2633 	} else {
2634 		/*
2635 		 * Full channel scan at the minimum takes 1.2secs
2636 		 * even with parallel scan. max wait time: 3500ms
2637 		 */
2638 		OSL_SLEEP(1000);
2639 	}
2640 
2641 	retry = APCS_MAX_RETRY;
2642 	while (retry--) {
2643 		ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &chosen,
2644 			sizeof(chosen));
2645 		if (ret < 0) {
2646 			chosen = 0;
2647 		} else {
2648 			chosen = dtoh32(chosen);
2649 		}
2650 
2651 		if (chosen) {
2652 			int chosen_band;
2653 			int apcs_band;
2654 #ifdef D11AC_IOTYPES
2655 			if (wl_cfg80211_get_ioctl_version() == 1) {
2656 				channel = LCHSPEC_CHANNEL((chanspec_t)chosen);
2657 			} else {
2658 				channel = CHSPEC_CHANNEL((chanspec_t)chosen);
2659 			}
2660 #else
2661 			channel = CHSPEC_CHANNEL((chanspec_t)chosen);
2662 #endif /* D11AC_IOTYPES */
2663 			apcs_band = (band == WLC_BAND_AUTO) ? WLC_BAND_2G : band;
2664 			chosen_band = (channel <= CH_MAX_2G_CHANNEL) ? WLC_BAND_2G : WLC_BAND_5G;
2665 			if (apcs_band == chosen_band) {
2666 				WL_MSG(dev->name, "selected channel = %d\n", channel);
2667 				break;
2668 			}
2669 		}
2670 		ANDROID_INFO(("%d tried, ret = %d, chosen = 0x%x\n",
2671 			(APCS_MAX_RETRY - retry), ret, chosen));
2672 		OSL_SLEEP(250);
2673 	}
2674 
2675 done:
2676 	if ((retry == 0) || (ret < 0)) {
2677 		/* On failure, fallback to a default channel */
2678 		if ((band == WLC_BAND_5G)) {
2679 			channel = APCS_DEFAULT_5G_CH;
2680 		} else {
2681 			channel = APCS_DEFAULT_2G_CH;
2682 		}
2683 		ANDROID_ERROR(("ACS failed. Fall back to default channel (%d) \n", channel));
2684 	}
2685 done2:
2686 	if (spect > 0) {
2687 		if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) {
2688 			ANDROID_ERROR(("ACS: error while setting spect\n"));
2689 		}
2690 	}
2691 
2692 	if (reqbuf) {
2693 		kfree(reqbuf);
2694 	}
2695 
2696 	if (channel) {
2697 		snprintf(command, 4, "%d", channel);
2698 		ANDROID_INFO(("command result is %s \n", command));
2699 		return strlen(command);
2700 	} else {
2701 		return ret;
2702 	}
2703 }
2704 #endif /* WL_SUPPORT_AUTO_CHANNEL */
2705 
2706 #ifdef CUSTOMER_HW4_PRIVATE_CMD
2707 
2708 
2709 #ifdef SUPPORT_SET_LPC
2710 static int
wl_android_set_lpc(struct net_device * dev,const char * string_num)2711 wl_android_set_lpc(struct net_device *dev, const char* string_num)
2712 {
2713 	int lpc_enabled, ret;
2714 	s32 val = 1;
2715 
2716 	lpc_enabled = bcm_atoi(string_num);
2717 	ANDROID_INFO(("%s : HAPD_LPC_ENABLED = %d\n", __FUNCTION__, lpc_enabled));
2718 
2719 	ret = wldev_ioctl_set(dev, WLC_DOWN, &val, sizeof(s32));
2720 	if (ret < 0)
2721 		ANDROID_ERROR(("WLC_DOWN error %d\n", ret));
2722 
2723 	wldev_iovar_setint(dev, "lpc", lpc_enabled);
2724 
2725 	ret = wldev_ioctl_set(dev, WLC_UP, &val, sizeof(s32));
2726 	if (ret < 0)
2727 		ANDROID_ERROR(("WLC_UP error %d\n", ret));
2728 
2729 	return 1;
2730 }
2731 #endif /* SUPPORT_SET_LPC */
2732 
2733 static int
wl_android_ch_res_rl(struct net_device * dev,bool change)2734 wl_android_ch_res_rl(struct net_device *dev, bool change)
2735 {
2736 	int error = 0;
2737 	s32 srl = 7;
2738 	s32 lrl = 4;
2739 	printk("%s enter\n", __FUNCTION__);
2740 	if (change) {
2741 		srl = 4;
2742 		lrl = 2;
2743 	}
2744 	error = wldev_ioctl_set(dev, WLC_SET_SRL, &srl, sizeof(s32));
2745 	if (error) {
2746 		ANDROID_ERROR(("Failed to set SRL, error = %d\n", error));
2747 	}
2748 	error = wldev_ioctl_set(dev, WLC_SET_LRL, &lrl, sizeof(s32));
2749 	if (error) {
2750 		ANDROID_ERROR(("Failed to set LRL, error = %d\n", error));
2751 	}
2752 	return error;
2753 }
2754 
2755 
2756 #ifdef WL_RELMCAST
2757 static int
wl_android_rmc_enable(struct net_device * net,int rmc_enable)2758 wl_android_rmc_enable(struct net_device *net, int rmc_enable)
2759 {
2760 	int err;
2761 
2762 	err = wldev_iovar_setint(net, "rmc_ackreq", rmc_enable);
2763 	return err;
2764 }
2765 
2766 static int
wl_android_rmc_set_leader(struct net_device * dev,const char * straddr)2767 wl_android_rmc_set_leader(struct net_device *dev, const char* straddr)
2768 {
2769 	int error  = BCME_OK;
2770 	char smbuf[WLC_IOCTL_SMLEN];
2771 	wl_rmc_entry_t rmc_entry;
2772 	ANDROID_INFO(("%s: Set new RMC leader %s\n", __FUNCTION__, straddr));
2773 
2774 	memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
2775 	if (!bcm_ether_atoe(straddr, &rmc_entry.addr)) {
2776 		if (strlen(straddr) == 1 && bcm_atoi(straddr) == 0) {
2777 			ANDROID_INFO(("%s: Set auto leader selection mode\n", __FUNCTION__));
2778 			memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
2779 		} else {
2780 			ANDROID_ERROR(("%s: No valid mac address provided\n",
2781 				__FUNCTION__));
2782 			return BCME_ERROR;
2783 		}
2784 	}
2785 
2786 	error = wldev_iovar_setbuf(dev, "rmc_ar", &rmc_entry, sizeof(wl_rmc_entry_t),
2787 		smbuf, sizeof(smbuf), NULL);
2788 
2789 	if (error != BCME_OK) {
2790 		ANDROID_ERROR(("%s: Unable to set RMC leader, error = %d\n",
2791 			__FUNCTION__, error));
2792 	}
2793 
2794 	return error;
2795 }
2796 
wl_android_set_rmc_event(struct net_device * dev,char * command,int total_len)2797 static int wl_android_set_rmc_event(struct net_device *dev, char *command, int total_len)
2798 {
2799 	int err = 0;
2800 	int pid = 0;
2801 
2802 	if (sscanf(command, CMD_SET_RMC_EVENT " %d", &pid) <= 0) {
2803 		ANDROID_ERROR(("Failed to get Parameter from : %s\n", command));
2804 		return -1;
2805 	}
2806 
2807 	/* set pid, and if the event was happened, let's send a notification through netlink */
2808 	wl_cfg80211_set_rmc_pid(dev, pid);
2809 
2810 	ANDROID_TRACE(("RMC pid=%d\n", pid));
2811 
2812 	return err;
2813 }
2814 #endif /* WL_RELMCAST */
2815 
wl_android_get_singlecore_scan(struct net_device * dev,char * command,int total_len)2816 int wl_android_get_singlecore_scan(struct net_device *dev, char *command, int total_len)
2817 {
2818 	int error = 0;
2819 	int bytes_written = 0;
2820 	int mode = 0;
2821 
2822 	error = wldev_iovar_getint(dev, "scan_ps", &mode);
2823 	if (error) {
2824 		ANDROID_ERROR(("%s: Failed to get single core scan Mode, error = %d\n",
2825 			__FUNCTION__, error));
2826 		return -1;
2827 	}
2828 
2829 	bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_SCSCAN, mode);
2830 
2831 	return bytes_written;
2832 }
2833 
wl_android_set_singlecore_scan(struct net_device * dev,char * command,int total_len)2834 int wl_android_set_singlecore_scan(struct net_device *dev, char *command, int total_len)
2835 {
2836 	int error = 0;
2837 	int mode = 0;
2838 
2839 	if (sscanf(command, "%*s %d", &mode) != 1) {
2840 		ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
2841 		return -1;
2842 	}
2843 
2844 	error = wldev_iovar_setint(dev, "scan_ps", mode);
2845 	if (error) {
2846 		ANDROID_ERROR(("%s[1]: Failed to set Mode %d, error = %d\n",
2847 		__FUNCTION__, mode, error));
2848 		return -1;
2849 	}
2850 
2851 	return error;
2852 }
2853 #ifdef TEST_TX_POWER_CONTROL
2854 static int
wl_android_set_tx_power(struct net_device * dev,const char * string_num)2855 wl_android_set_tx_power(struct net_device *dev, const char* string_num)
2856 {
2857 	int err = 0;
2858 	s32 dbm;
2859 	enum nl80211_tx_power_setting type;
2860 
2861 	dbm = bcm_atoi(string_num);
2862 
2863 	if (dbm < -1) {
2864 		ANDROID_ERROR(("%s: dbm is negative...\n", __FUNCTION__));
2865 		return -EINVAL;
2866 	}
2867 
2868 	if (dbm == -1)
2869 		type = NL80211_TX_POWER_AUTOMATIC;
2870 	else
2871 		type = NL80211_TX_POWER_FIXED;
2872 
2873 	err = wl_set_tx_power(dev, type, dbm);
2874 	if (unlikely(err)) {
2875 		ANDROID_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
2876 		return err;
2877 	}
2878 
2879 	return 1;
2880 }
2881 
2882 static int
wl_android_get_tx_power(struct net_device * dev,char * command,int total_len)2883 wl_android_get_tx_power(struct net_device *dev, char *command, int total_len)
2884 {
2885 	int err;
2886 	int bytes_written;
2887 	s32 dbm = 0;
2888 
2889 	err = wl_get_tx_power(dev, &dbm);
2890 	if (unlikely(err)) {
2891 		ANDROID_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
2892 		return err;
2893 	}
2894 
2895 	bytes_written = snprintf(command, total_len, "%s %d",
2896 		CMD_TEST_GET_TX_POWER, dbm);
2897 
2898 	ANDROID_ERROR(("%s: GET_TX_POWER: dBm=%d\n", __FUNCTION__, dbm));
2899 
2900 	return bytes_written;
2901 }
2902 #endif /* TEST_TX_POWER_CONTROL */
2903 
2904 static int
wl_android_set_sarlimit_txctrl(struct net_device * dev,const char * string_num)2905 wl_android_set_sarlimit_txctrl(struct net_device *dev, const char* string_num)
2906 {
2907 	int err = 0;
2908 	int setval = 0;
2909 	s32 mode = bcm_atoi(string_num);
2910 
2911 	/* '0' means activate sarlimit
2912 	 * and '-1' means back to normal state (deactivate sarlimit)
2913 	 */
2914 	if (mode == 0) {
2915 		ANDROID_INFO(("%s: SAR limit control activated\n", __FUNCTION__));
2916 		setval = 1;
2917 	} else if (mode == -1) {
2918 		ANDROID_INFO(("%s: SAR limit control deactivated\n", __FUNCTION__));
2919 		setval = 0;
2920 	} else {
2921 		return -EINVAL;
2922 	}
2923 
2924 	err = wldev_iovar_setint(dev, "sar_enable", setval);
2925 	if (unlikely(err)) {
2926 		ANDROID_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
2927 		return err;
2928 	}
2929 	return 1;
2930 }
2931 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
2932 
wl_android_set_roam_mode(struct net_device * dev,char * command,int total_len)2933 int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len)
2934 {
2935 	int error = 0;
2936 	int mode = 0;
2937 
2938 	if (sscanf(command, "%*s %d", &mode) != 1) {
2939 		ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
2940 		return -1;
2941 	}
2942 
2943 	error = wldev_iovar_setint(dev, "roam_off", mode);
2944 	if (error) {
2945 		ANDROID_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n",
2946 		__FUNCTION__, mode, error));
2947 		return -1;
2948 	}
2949 	else
2950 		ANDROID_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n",
2951 		__FUNCTION__, mode, error));
2952 	return 0;
2953 }
2954 
2955 #ifdef WL_CFG80211
wl_android_set_ibss_beacon_ouidata(struct net_device * dev,char * command,int total_len)2956 int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, int total_len)
2957 {
2958 	char ie_buf[VNDR_IE_MAX_LEN];
2959 	char *ioctl_buf = NULL;
2960 	char hex[] = "XX";
2961 	char *pcmd = NULL;
2962 	int ielen = 0, datalen = 0, idx = 0, tot_len = 0;
2963 	vndr_ie_setbuf_t *vndr_ie = NULL;
2964 	s32 iecount;
2965 	uint32 pktflag;
2966 	u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2967 	s32 err = BCME_OK, bssidx;
2968 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2969 
2970 	/* Check the VSIE (Vendor Specific IE) which was added.
2971 	 *  If exist then send IOVAR to delete it
2972 	 */
2973 	if (wl_cfg80211_ibss_vsie_delete(dev) != BCME_OK) {
2974 		return -EINVAL;
2975 	}
2976 
2977 	if (total_len < (strlen(CMD_SETIBSSBEACONOUIDATA) + 1)) {
2978 		ANDROID_ERROR(("error. total_len:%d\n", total_len));
2979 		return -EINVAL;
2980 	}
2981 
2982 	pcmd = command + strlen(CMD_SETIBSSBEACONOUIDATA) + 1;
2983 	for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
2984 		if (*pcmd == '\0') {
2985 			ANDROID_ERROR(("error while parsing OUI.\n"));
2986 			return -EINVAL;
2987 		}
2988 		hex[0] = *pcmd++;
2989 		hex[1] = *pcmd++;
2990 		ie_buf[idx] =  (uint8)simple_strtoul(hex, NULL, 16);
2991 	}
2992 	pcmd++;
2993 	while ((*pcmd != '\0') && (idx < VNDR_IE_MAX_LEN)) {
2994 		hex[0] = *pcmd++;
2995 		hex[1] = *pcmd++;
2996 		ie_buf[idx++] =  (uint8)simple_strtoul(hex, NULL, 16);
2997 		datalen++;
2998 	}
2999 
3000 	if (datalen <= 0) {
3001 		ANDROID_ERROR(("error. vndr ie len:%d\n", datalen));
3002 		return -EINVAL;
3003 	}
3004 
3005 	tot_len = (int)(sizeof(vndr_ie_setbuf_t) + (datalen - 1));
3006 	vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
3007 	if (!vndr_ie) {
3008 		ANDROID_ERROR(("IE memory alloc failed\n"));
3009 		return -ENOMEM;
3010 	}
3011 	/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
3012 	strncpy(vndr_ie->cmd, "add", VNDR_IE_CMD_LEN - 1);
3013 	vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
3014 
3015 	/* Set the IE count - the buffer contains only 1 IE */
3016 	iecount = htod32(1);
3017 	memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
3018 
3019 	/* Set packet flag to indicate that BEACON's will contain this IE */
3020 	pktflag = htod32(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG);
3021 	memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
3022 		sizeof(u32));
3023 	/* Set the IE ID */
3024 	vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
3025 
3026 	memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, &ie_buf,
3027 		DOT11_OUI_LEN);
3028 	memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data,
3029 		&ie_buf[DOT11_OUI_LEN], datalen);
3030 
3031 	ielen = DOT11_OUI_LEN + datalen;
3032 	vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
3033 
3034 	ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
3035 	if (!ioctl_buf) {
3036 		ANDROID_ERROR(("ioctl memory alloc failed\n"));
3037 		if (vndr_ie) {
3038 			kfree(vndr_ie);
3039 		}
3040 		return -ENOMEM;
3041 	}
3042 	memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN);	/* init the buffer */
3043 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3044 		ANDROID_ERROR(("Find index failed\n"));
3045 		err = BCME_ERROR;
3046 		goto end;
3047 	}
3048 	err = wldev_iovar_setbuf_bsscfg(dev, "vndr_ie", vndr_ie, tot_len, ioctl_buf,
3049 		WLC_IOCTL_MEDLEN, bssidx, &cfg->ioctl_buf_sync);
3050 
3051 end:
3052 	if (err != BCME_OK) {
3053 		err = -EINVAL;
3054 		if (vndr_ie) {
3055 			kfree(vndr_ie);
3056 		}
3057 	}
3058 	else {
3059 		/* do NOT free 'vndr_ie' for the next process */
3060 		wl_cfg80211_ibss_vsie_set_buffer(dev, vndr_ie, tot_len);
3061 	}
3062 
3063 	if (ioctl_buf) {
3064 		kfree(ioctl_buf);
3065 	}
3066 
3067 	return err;
3068 }
3069 #endif
3070 
3071 #if defined(BCMFW_ROAM_ENABLE)
3072 static int
wl_android_set_roampref(struct net_device * dev,char * command,int total_len)3073 wl_android_set_roampref(struct net_device *dev, char *command, int total_len)
3074 {
3075 	int error = 0;
3076 	char smbuf[WLC_IOCTL_SMLEN];
3077 	uint8 buf[MAX_BUF_SIZE];
3078 	uint8 *pref = buf;
3079 	char *pcmd;
3080 	int num_ucipher_suites = 0;
3081 	int num_akm_suites = 0;
3082 	wpa_suite_t ucipher_suites[MAX_NUM_SUITES];
3083 	wpa_suite_t akm_suites[MAX_NUM_SUITES];
3084 	int num_tuples = 0;
3085 	int total_bytes = 0;
3086 	int total_len_left;
3087 	int i, j;
3088 	char hex[] = "XX";
3089 
3090 	pcmd = command + strlen(CMD_SET_ROAMPREF) + 1;
3091 	total_len_left = total_len - strlen(CMD_SET_ROAMPREF) + 1;
3092 
3093 	num_akm_suites = simple_strtoul(pcmd, NULL, 16);
3094 	if (num_akm_suites > MAX_NUM_SUITES) {
3095 		ANDROID_ERROR(("too many AKM suites = %d\n", num_akm_suites));
3096 		return -1;
3097 	}
3098 
3099 	/* Increment for number of AKM suites field + space */
3100 	pcmd += 3;
3101 	total_len_left -= 3;
3102 
3103 	/* check to make sure pcmd does not overrun */
3104 	if (total_len_left < (num_akm_suites * WIDTH_AKM_SUITE))
3105 		return -1;
3106 
3107 	memset(buf, 0, sizeof(buf));
3108 	memset(akm_suites, 0, sizeof(akm_suites));
3109 	memset(ucipher_suites, 0, sizeof(ucipher_suites));
3110 
3111 	/* Save the AKM suites passed in the command */
3112 	for (i = 0; i < num_akm_suites; i++) {
3113 		/* Store the MSB first, as required by join_pref */
3114 		for (j = 0; j < 4; j++) {
3115 			hex[0] = *pcmd++;
3116 			hex[1] = *pcmd++;
3117 			buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
3118 		}
3119 		memcpy((uint8 *)&akm_suites[i], buf, sizeof(uint32));
3120 	}
3121 
3122 	total_len_left -= (num_akm_suites * WIDTH_AKM_SUITE);
3123 	num_ucipher_suites = simple_strtoul(pcmd, NULL, 16);
3124 	/* Increment for number of cipher suites field + space */
3125 	pcmd += 3;
3126 	total_len_left -= 3;
3127 
3128 	if (total_len_left < (num_ucipher_suites * WIDTH_AKM_SUITE))
3129 		return -1;
3130 
3131 	/* Save the cipher suites passed in the command */
3132 	for (i = 0; i < num_ucipher_suites; i++) {
3133 		/* Store the MSB first, as required by join_pref */
3134 		for (j = 0; j < 4; j++) {
3135 			hex[0] = *pcmd++;
3136 			hex[1] = *pcmd++;
3137 			buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
3138 		}
3139 		memcpy((uint8 *)&ucipher_suites[i], buf, sizeof(uint32));
3140 	}
3141 
3142 	/* Join preference for RSSI
3143 	 * Type	  : 1 byte (0x01)
3144 	 * Length : 1 byte (0x02)
3145 	 * Value  : 2 bytes	(reserved)
3146 	 */
3147 	*pref++ = WL_JOIN_PREF_RSSI;
3148 	*pref++ = JOIN_PREF_RSSI_LEN;
3149 	*pref++ = 0;
3150 	*pref++ = 0;
3151 
3152 	/* Join preference for WPA
3153 	 * Type	  : 1 byte (0x02)
3154 	 * Length : 1 byte (not used)
3155 	 * Value  : (variable length)
3156 	 *		reserved: 1 byte
3157 	 *      count	: 1 byte (no of tuples)
3158 	 *		Tuple1	: 12 bytes
3159 	 *			akm[4]
3160 	 *			ucipher[4]
3161 	 *			mcipher[4]
3162 	 *		Tuple2	: 12 bytes
3163 	 *		Tuplen	: 12 bytes
3164 	 */
3165 	num_tuples = num_akm_suites * num_ucipher_suites;
3166 	if (num_tuples != 0) {
3167 		if (num_tuples <= JOIN_PREF_MAX_WPA_TUPLES) {
3168 			*pref++ = WL_JOIN_PREF_WPA;
3169 			*pref++ = 0;
3170 			*pref++ = 0;
3171 			*pref++ = (uint8)num_tuples;
3172 			total_bytes = JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE +
3173 				(JOIN_PREF_WPA_TUPLE_SIZE * num_tuples);
3174 		} else {
3175 			ANDROID_ERROR(("%s: Too many wpa configs for join_pref \n", __FUNCTION__));
3176 			return -1;
3177 		}
3178 	} else {
3179 		/* No WPA config, configure only RSSI preference */
3180 		total_bytes = JOIN_PREF_RSSI_SIZE;
3181 	}
3182 
3183 	/* akm-ucipher-mcipher tuples in the format required for join_pref */
3184 	for (i = 0; i < num_ucipher_suites; i++) {
3185 		for (j = 0; j < num_akm_suites; j++) {
3186 			memcpy(pref, (uint8 *)&akm_suites[j], WPA_SUITE_LEN);
3187 			pref += WPA_SUITE_LEN;
3188 			memcpy(pref, (uint8 *)&ucipher_suites[i], WPA_SUITE_LEN);
3189 			pref += WPA_SUITE_LEN;
3190 			/* Set to 0 to match any available multicast cipher */
3191 			memset(pref, 0, WPA_SUITE_LEN);
3192 			pref += WPA_SUITE_LEN;
3193 		}
3194 	}
3195 
3196 	prhex("join pref", (uint8 *)buf, total_bytes);
3197 	error = wldev_iovar_setbuf(dev, "join_pref", buf, total_bytes, smbuf, sizeof(smbuf), NULL);
3198 	if (error) {
3199 		ANDROID_ERROR(("Failed to set join_pref, error = %d\n", error));
3200 	}
3201 	return error;
3202 }
3203 #endif /* defined(BCMFW_ROAM_ENABLE */
3204 
3205 #ifdef WL_CFG80211
3206 static int
wl_android_iolist_add(struct net_device * dev,struct list_head * head,struct io_cfg * config)3207 wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_cfg *config)
3208 {
3209 	struct io_cfg *resume_cfg;
3210 	s32 ret;
3211 
3212 	resume_cfg = kzalloc(sizeof(struct io_cfg), GFP_KERNEL);
3213 	if (!resume_cfg)
3214 		return -ENOMEM;
3215 
3216 	if (config->iovar) {
3217 		ret = wldev_iovar_getint(dev, config->iovar, &resume_cfg->param);
3218 		if (ret) {
3219 			ANDROID_ERROR(("%s: Failed to get current %s value\n",
3220 				__FUNCTION__, config->iovar));
3221 			goto error;
3222 		}
3223 
3224 		ret = wldev_iovar_setint(dev, config->iovar, config->param);
3225 		if (ret) {
3226 			ANDROID_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
3227 				config->iovar, config->param));
3228 			goto error;
3229 		}
3230 
3231 		resume_cfg->iovar = config->iovar;
3232 	} else {
3233 		resume_cfg->arg = kzalloc(config->len, GFP_KERNEL);
3234 		if (!resume_cfg->arg) {
3235 			ret = -ENOMEM;
3236 			goto error;
3237 		}
3238 		ret = wldev_ioctl_get(dev, config->ioctl, resume_cfg->arg, config->len);
3239 		if (ret) {
3240 			ANDROID_ERROR(("%s: Failed to get ioctl %d\n", __FUNCTION__,
3241 				config->ioctl));
3242 			goto error;
3243 		}
3244 		ret = wldev_ioctl_set(dev, config->ioctl + 1, config->arg, config->len);
3245 		if (ret) {
3246 			ANDROID_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
3247 				config->iovar, config->param));
3248 			goto error;
3249 		}
3250 		if (config->ioctl + 1 == WLC_SET_PM)
3251 			wl_cfg80211_update_power_mode(dev);
3252 		resume_cfg->ioctl = config->ioctl;
3253 		resume_cfg->len = config->len;
3254 	}
3255 
3256 	list_add(&resume_cfg->list, head);
3257 
3258 	return 0;
3259 error:
3260 	kfree(resume_cfg->arg);
3261 	kfree(resume_cfg);
3262 	return ret;
3263 }
3264 
3265 static void
wl_android_iolist_resume(struct net_device * dev,struct list_head * head)3266 wl_android_iolist_resume(struct net_device *dev, struct list_head *head)
3267 {
3268 	struct io_cfg *config;
3269 	struct list_head *cur, *q;
3270 	s32 ret = 0;
3271 
3272 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3273 #pragma GCC diagnostic push
3274 #pragma GCC diagnostic ignored "-Wcast-qual"
3275 #endif
3276 	list_for_each_safe(cur, q, head) {
3277 		config = list_entry(cur, struct io_cfg, list);
3278 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3279 #pragma GCC diagnostic pop
3280 #endif
3281 		if (config->iovar) {
3282 			if (!ret)
3283 				ret = wldev_iovar_setint(dev, config->iovar,
3284 					config->param);
3285 		} else {
3286 			if (!ret)
3287 				ret = wldev_ioctl_set(dev, config->ioctl + 1,
3288 					config->arg, config->len);
3289 			if (config->ioctl + 1 == WLC_SET_PM)
3290 				wl_cfg80211_update_power_mode(dev);
3291 			kfree(config->arg);
3292 		}
3293 		list_del(cur);
3294 		kfree(config);
3295 	}
3296 }
3297 #ifdef WL11ULB
3298 static int
wl_android_set_ulb_mode(struct net_device * dev,char * command,int total_len)3299 wl_android_set_ulb_mode(struct net_device *dev, char *command, int total_len)
3300 {
3301 	int mode = 0;
3302 
3303 	ANDROID_INFO(("set ulb mode (%s) \n", command));
3304 	if (sscanf(command, "%*s %d", &mode) != 1) {
3305 		ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
3306 		return -1;
3307 	}
3308 	return wl_cfg80211_set_ulb_mode(dev, mode);
3309 }
3310 static int
wl_android_set_ulb_bw(struct net_device * dev,char * command,int total_len)3311 wl_android_set_ulb_bw(struct net_device *dev, char *command, int total_len)
3312 {
3313 	int bw = 0;
3314 	u8 *pos;
3315 	char *ifname = NULL;
3316 	ANDROID_INFO(("set ulb bw (%s) \n", command));
3317 
3318 	/*
3319 	 * For sta/ap: IFNAME=<ifname> DRIVER ULB_BW <bw> ifname
3320 	 * For p2p:    IFNAME=wlan0 DRIVER ULB_BW <bw> p2p-dev-wlan0
3321 	 */
3322 	if (total_len < strlen(CMD_ULB_BW) + 2)
3323 		return -EINVAL;
3324 
3325 	pos = command + strlen(CMD_ULB_BW) + 1;
3326 	bw = bcm_atoi(pos);
3327 
3328 	if ((strlen(pos) >= 5)) {
3329 		ifname = pos + 2;
3330 	}
3331 
3332 	ANDROID_INFO(("[ULB] ifname:%s ulb_bw:%d \n", ifname, bw));
3333 	return wl_cfg80211_set_ulb_bw(dev, bw, ifname);
3334 }
3335 #endif /* WL11ULB */
3336 
3337 static int
wl_android_set_miracast(struct net_device * dev,char * command,int total_len)3338 wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
3339 {
3340 	int mode, val;
3341 	int ret = 0;
3342 	struct io_cfg config;
3343 
3344 	if (sscanf(command, "%*s %d", &mode) != 1) {
3345 		ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
3346 		return -1;
3347 	}
3348 
3349 	ANDROID_INFO(("%s: enter miracast mode %d\n", __FUNCTION__, mode));
3350 
3351 	if (miracast_cur_mode == mode) {
3352 		return 0;
3353 	}
3354 
3355 	wl_android_iolist_resume(dev, &miracast_resume_list);
3356 	miracast_cur_mode = MIRACAST_MODE_OFF;
3357 
3358 	switch (mode) {
3359 	case MIRACAST_MODE_SOURCE:
3360 		/* setting mchan_algo to platform specific value */
3361 		config.iovar = "mchan_algo";
3362 
3363 		ret = wldev_ioctl_get(dev, WLC_GET_BCNPRD, &val, sizeof(int));
3364 		if (!ret && val > 100) {
3365 			config.param = 0;
3366 			ANDROID_ERROR(("%s: Connected station's beacon interval: "
3367 				"%d and set mchan_algo to %d \n",
3368 				__FUNCTION__, val, config.param));
3369 		} else {
3370 			config.param = MIRACAST_MCHAN_ALGO;
3371 		}
3372 		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
3373 		if (ret) {
3374 			goto resume;
3375 		}
3376 
3377 		/* setting mchan_bw to platform specific value */
3378 		config.iovar = "mchan_bw";
3379 		config.param = MIRACAST_MCHAN_BW;
3380 		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
3381 		if (ret) {
3382 			goto resume;
3383 		}
3384 
3385 		/* setting apmdu to platform specific value */
3386 		config.iovar = "ampdu_mpdu";
3387 		config.param = MIRACAST_AMPDU_SIZE;
3388 		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
3389 		if (ret) {
3390 			goto resume;
3391 		}
3392 		/* FALLTROUGH */
3393 		/* Source mode shares most configurations with sink mode.
3394 		 * Fall through here to avoid code duplication
3395 		 */
3396 	case MIRACAST_MODE_SINK:
3397 		/* disable internal roaming */
3398 		config.iovar = "roam_off";
3399 		config.param = 1;
3400 		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
3401 		if (ret) {
3402 			goto resume;
3403 		}
3404 
3405 		/* tunr off pm */
3406 		ret = wldev_ioctl_get(dev, WLC_GET_PM, &val, sizeof(val));
3407 		if (ret) {
3408 			goto resume;
3409 		}
3410 
3411 		if (val != PM_OFF) {
3412 			val = PM_OFF;
3413 			config.iovar = NULL;
3414 			config.ioctl = WLC_GET_PM;
3415 			config.arg = &val;
3416 			config.len = sizeof(int);
3417 			ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
3418 			if (ret) {
3419 				goto resume;
3420 			}
3421 		}
3422 		break;
3423 	case MIRACAST_MODE_OFF:
3424 	default:
3425 		break;
3426 	}
3427 	miracast_cur_mode = mode;
3428 
3429 	return 0;
3430 
3431 resume:
3432 	ANDROID_ERROR(("%s: turnoff miracast mode because of err%d\n", __FUNCTION__, ret));
3433 	wl_android_iolist_resume(dev, &miracast_resume_list);
3434 	return ret;
3435 }
3436 #endif
3437 
3438 #ifdef WL_RELMCAST
3439 #define NETLINK_OXYGEN     30
3440 #define AIBSS_BEACON_TIMEOUT	10
3441 
3442 static struct sock *nl_sk = NULL;
3443 
wl_netlink_recv(struct sk_buff * skb)3444 static void wl_netlink_recv(struct sk_buff *skb)
3445 {
3446 	ANDROID_ERROR(("netlink_recv called\n"));
3447 }
3448 
wl_netlink_init(void)3449 static int wl_netlink_init(void)
3450 {
3451 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
3452 	struct netlink_kernel_cfg cfg = {
3453 		.input	= wl_netlink_recv,
3454 	};
3455 #endif
3456 
3457 	if (nl_sk != NULL) {
3458 		ANDROID_ERROR(("nl_sk already exist\n"));
3459 		return BCME_ERROR;
3460 	}
3461 
3462 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
3463 	nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN,
3464 		0, wl_netlink_recv, NULL, THIS_MODULE);
3465 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
3466 	nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, THIS_MODULE, &cfg);
3467 #else
3468 	nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, &cfg);
3469 #endif
3470 
3471 	if (nl_sk == NULL) {
3472 		ANDROID_ERROR(("nl_sk is not ready\n"));
3473 		return BCME_ERROR;
3474 	}
3475 
3476 	return BCME_OK;
3477 }
3478 
wl_netlink_deinit(void)3479 static void wl_netlink_deinit(void)
3480 {
3481 	if (nl_sk) {
3482 		netlink_kernel_release(nl_sk);
3483 		nl_sk = NULL;
3484 	}
3485 }
3486 
3487 s32
wl_netlink_send_msg(int pid,int type,int seq,const void * data,size_t size)3488 wl_netlink_send_msg(int pid, int type, int seq, const void *data, size_t size)
3489 {
3490 	struct sk_buff *skb = NULL;
3491 	struct nlmsghdr *nlh = NULL;
3492 	int ret = -1;
3493 
3494 	if (nl_sk == NULL) {
3495 		ANDROID_ERROR(("nl_sk was not initialized\n"));
3496 		goto nlmsg_failure;
3497 	}
3498 
3499 	skb = alloc_skb(NLMSG_SPACE(size), GFP_ATOMIC);
3500 	if (skb == NULL) {
3501 		ANDROID_ERROR(("failed to allocate memory\n"));
3502 		goto nlmsg_failure;
3503 	}
3504 
3505 	nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
3506 	if (nlh == NULL) {
3507 		ANDROID_ERROR(("failed to build nlmsg, skb_tailroom:%d, nlmsg_total_size:%d\n",
3508 			skb_tailroom(skb), nlmsg_total_size(size)));
3509 		dev_kfree_skb(skb);
3510 		goto nlmsg_failure;
3511 	}
3512 
3513 	memcpy(nlmsg_data(nlh), data, size);
3514 	nlh->nlmsg_seq = seq;
3515 	nlh->nlmsg_type = type;
3516 
3517 	/* netlink_unicast() takes ownership of the skb and frees it itself. */
3518 	ret = netlink_unicast(nl_sk, skb, pid, 0);
3519 	ANDROID_TRACE(("netlink_unicast() pid=%d, ret=%d\n", pid, ret));
3520 
3521 nlmsg_failure:
3522 	return ret;
3523 }
3524 #endif /* WL_RELMCAST */
3525 
wl_keep_alive_set(struct net_device * dev,char * extra,int total_len)3526 int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len)
3527 {
3528 	wl_mkeep_alive_pkt_t	mkeep_alive_pkt;
3529 	int ret;
3530 	uint period_msec = 0;
3531 	char *buf;
3532 
3533 	if (extra == NULL) {
3534 		 ANDROID_ERROR(("%s: extra is NULL\n", __FUNCTION__));
3535 		 return -1;
3536 	}
3537 	if (sscanf(extra, "%d", &period_msec) != 1) {
3538 		 ANDROID_ERROR(("%s: sscanf error. check period_msec value\n", __FUNCTION__));
3539 		 return -EINVAL;
3540 	}
3541 	ANDROID_ERROR(("%s: period_msec is %d\n", __FUNCTION__, period_msec));
3542 
3543 	memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t));
3544 
3545 	mkeep_alive_pkt.period_msec = period_msec;
3546 	mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
3547 	mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
3548 
3549 	/* Setup keep alive zero for null packet generation */
3550 	mkeep_alive_pkt.keep_alive_id = 0;
3551 	mkeep_alive_pkt.len_bytes = 0;
3552 
3553 	buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
3554 	if (!buf) {
3555 		ANDROID_ERROR(("%s: buffer alloc failed\n", __FUNCTION__));
3556 		return BCME_NOMEM;
3557 	}
3558 	ret = wldev_iovar_setbuf(dev, "mkeep_alive", (char *)&mkeep_alive_pkt,
3559 			WL_MKEEP_ALIVE_FIXED_LEN, buf, WLC_IOCTL_SMLEN, NULL);
3560 	if (ret < 0)
3561 		ANDROID_ERROR(("%s:keep_alive set failed:%d\n", __FUNCTION__, ret));
3562 	else
3563 		ANDROID_TRACE(("%s:keep_alive set ok\n", __FUNCTION__));
3564 	kfree(buf);
3565 	return ret;
3566 }
3567 
3568 #ifdef P2PRESP_WFDIE_SRC
wl_android_get_wfdie_resp(struct net_device * dev,char * command,int total_len)3569 static int wl_android_get_wfdie_resp(struct net_device *dev, char *command, int total_len)
3570 {
3571 	int error = 0;
3572 	int bytes_written = 0;
3573 	int only_resp_wfdsrc = 0;
3574 
3575 	error = wldev_iovar_getint(dev, "p2p_only_resp_wfdsrc", &only_resp_wfdsrc);
3576 	if (error) {
3577 		ANDROID_ERROR(("%s: Failed to get the mode for only_resp_wfdsrc, error = %d\n",
3578 			__FUNCTION__, error));
3579 		return -1;
3580 	}
3581 
3582 	bytes_written = snprintf(command, total_len, "%s %d",
3583 		CMD_P2P_GET_WFDIE_RESP, only_resp_wfdsrc);
3584 
3585 	return bytes_written;
3586 }
3587 
wl_android_set_wfdie_resp(struct net_device * dev,int only_resp_wfdsrc)3588 static int wl_android_set_wfdie_resp(struct net_device *dev, int only_resp_wfdsrc)
3589 {
3590 	int error = 0;
3591 
3592 	error = wldev_iovar_setint(dev, "p2p_only_resp_wfdsrc", only_resp_wfdsrc);
3593 	if (error) {
3594 		ANDROID_ERROR(("%s: Failed to set only_resp_wfdsrc %d, error = %d\n",
3595 			__FUNCTION__, only_resp_wfdsrc, error));
3596 		return -1;
3597 	}
3598 
3599 	return 0;
3600 }
3601 #endif /* P2PRESP_WFDIE_SRC */
3602 
3603 #ifdef BT_WIFI_HANDOVER
3604 static int
wl_tbow_teardown(struct net_device * dev,char * command,int total_len)3605 wl_tbow_teardown(struct net_device *dev, char *command, int total_len)
3606 {
3607 	int err = BCME_OK;
3608 	char buf[WLC_IOCTL_SMLEN];
3609 	tbow_setup_netinfo_t netinfo;
3610 	memset(&netinfo, 0, sizeof(netinfo));
3611 	netinfo.opmode = TBOW_HO_MODE_TEARDOWN;
3612 
3613 	err = wldev_iovar_setbuf_bsscfg(dev, "tbow_doho", &netinfo,
3614 			sizeof(tbow_setup_netinfo_t), buf, WLC_IOCTL_SMLEN, 0, NULL);
3615 	if (err < 0) {
3616 		ANDROID_ERROR(("tbow_doho iovar error %d\n", err));
3617 			return err;
3618 	}
3619 	return err;
3620 }
3621 #endif /* BT_WIFI_HANOVER */
3622 
3623 #ifdef SET_RPS_CPUS
3624 static int
wl_android_set_rps_cpus(struct net_device * dev,char * command,int total_len)3625 wl_android_set_rps_cpus(struct net_device *dev, char *command, int total_len)
3626 {
3627 	int error, enable;
3628 
3629 	enable = command[strlen(CMD_RPSMODE) + 1] - '0';
3630 	error = dhd_rps_cpus_enable(dev, enable);
3631 
3632 #if defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211)
3633 	if (!error) {
3634 		void *dhdp = wl_cfg80211_get_dhdp(net);
3635 		if (enable) {
3636 			ANDROID_TRACE(("%s : set ack suppress. TCPACK_SUP_HOLD.\n", __FUNCTION__));
3637 			dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_HOLD);
3638 		} else {
3639 			ANDROID_TRACE(("%s : clear ack suppress.\n", __FUNCTION__));
3640 			dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
3641 		}
3642 	}
3643 #endif /* DHDTCPACK_SUPPRESS && BCMPCIE && WL_CFG80211 */
3644 
3645 	return error;
3646 }
3647 #endif /* SET_RPS_CPUS */
3648 
wl_android_get_link_status(struct net_device * dev,char * command,int total_len)3649 static int wl_android_get_link_status(struct net_device *dev, char *command,
3650 	int total_len)
3651 {
3652 	int bytes_written, error, result = 0, single_stream, stf = -1, i, nss = 0, mcs_map;
3653 	uint32 rspec;
3654 	uint encode, rate, txexp;
3655 	struct wl_bss_info *bi;
3656 	int datalen = sizeof(uint32) + sizeof(wl_bss_info_t);
3657 	char buf[datalen];
3658 
3659 	/* get BSS information */
3660 	*(u32 *) buf = htod32(datalen);
3661 	error = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, (void *)buf, datalen);
3662 	if (unlikely(error)) {
3663 		ANDROID_ERROR(("Could not get bss info %d\n", error));
3664 		return -1;
3665 	}
3666 
3667 	bi = (struct wl_bss_info *) (buf + sizeof(uint32));
3668 
3669 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
3670 		if (bi->BSSID.octet[i] > 0) {
3671 			break;
3672 		}
3673 	}
3674 
3675 	if (i == ETHER_ADDR_LEN) {
3676 		ANDROID_TRACE(("No BSSID\n"));
3677 		return -1;
3678 	}
3679 
3680 	/* check VHT capability at beacon */
3681 	if (bi->vht_cap) {
3682 		if (CHSPEC_IS5G(bi->chanspec)) {
3683 			result |= WL_ANDROID_LINK_AP_VHT_SUPPORT;
3684 		}
3685 	}
3686 
3687 	/* get a rspec (radio spectrum) rate */
3688 	error = wldev_iovar_getint(dev, "nrate", &rspec);
3689 	if (unlikely(error) || rspec == 0) {
3690 		ANDROID_ERROR(("get link status error (%d)\n", error));
3691 		return -1;
3692 	}
3693 
3694 	encode = (rspec & WL_RSPEC_ENCODING_MASK);
3695 	rate = (rspec & WL_RSPEC_RATE_MASK);
3696 	txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
3697 
3698 	switch (encode) {
3699 	case WL_RSPEC_ENCODE_HT:
3700 		/* check Rx MCS Map for HT */
3701 		for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
3702 			int8 bitmap = 0xFF;
3703 			if (i == MAX_STREAMS_SUPPORTED-1) {
3704 				bitmap = 0x7F;
3705 			}
3706 			if (bi->basic_mcs[i] & bitmap) {
3707 				nss++;
3708 			}
3709 		}
3710 		break;
3711 	case WL_RSPEC_ENCODE_VHT:
3712 		/* check Rx MCS Map for VHT */
3713 		for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
3714 			mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
3715 			if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
3716 				nss++;
3717 			}
3718 		}
3719 		break;
3720 	}
3721 
3722 	/* check MIMO capability with nss in beacon */
3723 	if (nss > 1) {
3724 		result |= WL_ANDROID_LINK_AP_MIMO_SUPPORT;
3725 	}
3726 
3727 	single_stream = (encode == WL_RSPEC_ENCODE_RATE) ||
3728 		((encode == WL_RSPEC_ENCODE_HT) && rate < 8) ||
3729 		((encode == WL_RSPEC_ENCODE_VHT) &&
3730 		((rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT) == 1);
3731 
3732 	if (txexp == 0) {
3733 		if ((rspec & WL_RSPEC_STBC) && single_stream) {
3734 			stf = OLD_NRATE_STF_STBC;
3735 		} else {
3736 			stf = (single_stream) ? OLD_NRATE_STF_SISO : OLD_NRATE_STF_SDM;
3737 		}
3738 	} else if (txexp == 1 && single_stream) {
3739 		stf = OLD_NRATE_STF_CDD;
3740 	}
3741 
3742 	/* check 11ac (VHT) */
3743 	if (encode == WL_RSPEC_ENCODE_VHT) {
3744 		if (CHSPEC_IS5G(bi->chanspec)) {
3745 			result |= WL_ANDROID_LINK_VHT;
3746 		}
3747 	}
3748 
3749 	/* check MIMO */
3750 	if (result & WL_ANDROID_LINK_AP_MIMO_SUPPORT) {
3751 		switch (stf) {
3752 		case OLD_NRATE_STF_SISO:
3753 			break;
3754 		case OLD_NRATE_STF_CDD:
3755 		case OLD_NRATE_STF_STBC:
3756 			result |= WL_ANDROID_LINK_MIMO;
3757 			break;
3758 		case OLD_NRATE_STF_SDM:
3759 			if (!single_stream) {
3760 				result |= WL_ANDROID_LINK_MIMO;
3761 			}
3762 			break;
3763 		}
3764 	}
3765 
3766 	ANDROID_TRACE(("%s:result=%d, stf=%d, single_stream=%d, mcs map=%d\n",
3767 		__FUNCTION__, result, stf, single_stream, nss));
3768 
3769 	bytes_written = sprintf(command, "%s %d", CMD_GET_LINK_STATUS, result);
3770 
3771 	return bytes_written;
3772 }
3773 
3774 #ifdef P2P_LISTEN_OFFLOADING
3775 s32
wl_cfg80211_p2plo_offload(struct net_device * dev,char * cmd,char * buf,int len)3776 wl_cfg80211_p2plo_offload(struct net_device *dev, char *cmd, char* buf, int len)
3777 {
3778 	int ret = 0;
3779 
3780 	ANDROID_ERROR(("Entry cmd:%s arg_len:%d \n", cmd, len));
3781 
3782 	if (strncmp(cmd, "P2P_LO_START", strlen("P2P_LO_START")) == 0) {
3783 		ret = wl_cfg80211_p2plo_listen_start(dev, buf, len);
3784 	} else if (strncmp(cmd, "P2P_LO_STOP", strlen("P2P_LO_STOP")) == 0) {
3785 		ret = wl_cfg80211_p2plo_listen_stop(dev);
3786 	} else {
3787 		ANDROID_ERROR(("Request for Unsupported CMD:%s \n", buf));
3788 		ret = -EINVAL;
3789 	}
3790 	return ret;
3791 }
3792 #endif /* P2P_LISTEN_OFFLOADING */
3793 
3794 #if defined(BCM4359_CHIP) && defined(WL_CFG80211)
3795 int
wl_android_murx_bfe_cap(struct net_device * dev,int val)3796 wl_android_murx_bfe_cap(struct net_device *dev, int val)
3797 {
3798 	int err = BCME_OK;
3799 	int iface_count = wl_cfg80211_iface_count(dev);
3800 	struct ether_addr bssid;
3801 	wl_reassoc_params_t params;
3802 
3803 	if (iface_count > 1) {
3804 		ANDROID_ERROR(("murx_bfe_cap change is not allowed when "
3805 				"there are multiple interfaces\n"));
3806 		return -EINVAL;
3807 	}
3808 	/* Now there is only single interface */
3809 	err = wldev_iovar_setint(dev, "murx_bfe_cap", val);
3810 	if (unlikely(err)) {
3811 		ANDROID_ERROR(("Failed to set murx_bfe_cap IOVAR to %d,"
3812 				"error %d\n", val, err));
3813 		return err;
3814 	}
3815 
3816 	/* If successful intiate a reassoc */
3817 	memset(&bssid, 0, ETHER_ADDR_LEN);
3818 	if ((err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN)) < 0) {
3819 		ANDROID_ERROR(("Failed to get bssid, error=%d\n", err));
3820 		return err;
3821 	}
3822 
3823 	bzero(&params, sizeof(wl_reassoc_params_t));
3824 	memcpy(&params.bssid, &bssid, ETHER_ADDR_LEN);
3825 
3826 	if ((err = wldev_ioctl_set(dev, WLC_REASSOC, &params,
3827 		sizeof(wl_reassoc_params_t))) < 0) {
3828 		ANDROID_ERROR(("reassoc failed err:%d \n", err));
3829 	} else {
3830 		ANDROID_TRACE(("reassoc issued successfully\n"));
3831 	}
3832 
3833 	return err;
3834 }
3835 #endif /* BCM4359_CHIP */
3836 
3837 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
3838 int
wl_android_set_ap_beaconrate(struct net_device * dev,char * command)3839 wl_android_set_ap_beaconrate(struct net_device *dev, char *command)
3840 {
3841 	int rate = 0;
3842 	char *pos, *token;
3843 	char *ifname = NULL;
3844 	int err = BCME_OK;
3845 
3846 	/*
3847 	 * DRIVER SET_AP_BEACONRATE <rate> <ifname>
3848 	 */
3849 	pos = command;
3850 
3851 	/* drop command */
3852 	token = bcmstrtok(&pos, " ", NULL);
3853 
3854 	/* Rate */
3855 	token = bcmstrtok(&pos, " ", NULL);
3856 	if (!token)
3857 		return -EINVAL;
3858 	rate = bcm_atoi(token);
3859 
3860 	/* get the interface name */
3861 	token = bcmstrtok(&pos, " ", NULL);
3862 	if (!token)
3863 		return -EINVAL;
3864 	ifname = token;
3865 
3866 	ANDROID_TRACE(("rate %d, ifacename %s\n", rate, ifname));
3867 
3868 	err = wl_set_ap_beacon_rate(dev, rate, ifname);
3869 	if (unlikely(err)) {
3870 		ANDROID_ERROR(("Failed to set ap beacon rate to %d, error = %d\n", rate, err));
3871 	}
3872 
3873 	return err;
3874 }
3875 
wl_android_get_ap_basicrate(struct net_device * dev,char * command,int total_len)3876 int wl_android_get_ap_basicrate(struct net_device *dev, char *command, int total_len)
3877 {
3878 	char *pos, *token;
3879 	char *ifname = NULL;
3880 	int bytes_written = 0;
3881 	/*
3882 	 * DRIVER GET_AP_BASICRATE <ifname>
3883 	 */
3884 	pos = command;
3885 
3886 	/* drop command */
3887 	token = bcmstrtok(&pos, " ", NULL);
3888 
3889 	/* get the interface name */
3890 	token = bcmstrtok(&pos, " ", NULL);
3891 	if (!token)
3892 		return -EINVAL;
3893 	ifname = token;
3894 
3895 	ANDROID_TRACE(("ifacename %s\n", ifname));
3896 
3897 	bytes_written = wl_get_ap_basic_rate(dev, command, ifname, total_len);
3898 	if (bytes_written < 1) {
3899 		ANDROID_ERROR(("Failed to get ap basic rate, error = %d\n", bytes_written));
3900 		return -EPROTO;
3901 	}
3902 
3903 	return bytes_written;
3904 
3905 }
3906 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
3907 
3908 #ifdef SUPPORT_AP_RADIO_PWRSAVE
3909 int
wl_android_get_ap_rps(struct net_device * dev,char * command,int total_len)3910 wl_android_get_ap_rps(struct net_device *dev, char *command, int total_len)
3911 {
3912 	char *pos, *token;
3913 	char *ifname = NULL;
3914 	int bytes_written = 0;
3915 	/*
3916 	 * DRIVER GET_AP_RPS <ifname>
3917 	 */
3918 	pos = command;
3919 
3920 	/* drop command */
3921 	token = bcmstrtok(&pos, " ", NULL);
3922 
3923 	/* get the interface name */
3924 	token = bcmstrtok(&pos, " ", NULL);
3925 	if (!token)
3926 		return -EINVAL;
3927 	ifname = token;
3928 
3929 	ANDROID_TRACE(("ifacename %s\n", ifname));
3930 
3931 	bytes_written = wl_get_ap_rps(dev, command, ifname, total_len);
3932 	if (bytes_written < 1) {
3933 		ANDROID_ERROR(("Failed to get rps, error = %d\n", bytes_written));
3934 		return -EPROTO;
3935 	}
3936 
3937 	return bytes_written;
3938 
3939 }
3940 
3941 int
wl_android_set_ap_rps(struct net_device * dev,char * command,int total_len)3942 wl_android_set_ap_rps(struct net_device *dev, char *command, int total_len)
3943 {
3944 	int enable = 0;
3945 	char *pos, *token;
3946 	char *ifname = NULL;
3947 	int err = BCME_OK;
3948 
3949 	/*
3950 	 * DRIVER SET_AP_RPS <0/1> <ifname>
3951 	 */
3952 	pos = command;
3953 
3954 	/* drop command */
3955 	token = bcmstrtok(&pos, " ", NULL);
3956 
3957 	/* Enable */
3958 	token = bcmstrtok(&pos, " ", NULL);
3959 	if (!token)
3960 		return -EINVAL;
3961 	enable = bcm_atoi(token);
3962 
3963 	/* get the interface name */
3964 	token = bcmstrtok(&pos, " ", NULL);
3965 	if (!token)
3966 		return -EINVAL;
3967 	ifname = token;
3968 
3969 	ANDROID_TRACE(("enable %d, ifacename %s\n", enable, ifname));
3970 
3971 	err = wl_set_ap_rps(dev, enable? TRUE: FALSE, ifname);
3972 	if (unlikely(err)) {
3973 		ANDROID_ERROR(("Failed to set rps, enable %d, error = %d\n", enable, err));
3974 	}
3975 
3976 	return err;
3977 }
3978 
3979 int
wl_android_set_ap_rps_params(struct net_device * dev,char * command,int total_len)3980 wl_android_set_ap_rps_params(struct net_device *dev, char *command, int total_len)
3981 {
3982 	ap_rps_info_t rps;
3983 	char *pos, *token;
3984 	char *ifname = NULL;
3985 	int err = BCME_OK;
3986 
3987 	memset(&rps, 0, sizeof(rps));
3988 	/*
3989 	 * DRIVER SET_AP_RPS_PARAMS <pps> <level> <quiettime> <assoccheck> <ifname>
3990 	 */
3991 	pos = command;
3992 
3993 	/* drop command */
3994 	token = bcmstrtok(&pos, " ", NULL);
3995 
3996 	/* pps */
3997 	token = bcmstrtok(&pos, " ", NULL);
3998 	if (!token)
3999 		return -EINVAL;
4000 	rps.pps = bcm_atoi(token);
4001 
4002 	/* level */
4003 	token = bcmstrtok(&pos, " ", NULL);
4004 	if (!token)
4005 		return -EINVAL;
4006 	rps.level = bcm_atoi(token);
4007 
4008 	/* quiettime */
4009 	token = bcmstrtok(&pos, " ", NULL);
4010 	if (!token)
4011 		return -EINVAL;
4012 	rps.quiet_time = bcm_atoi(token);
4013 
4014 	/* sta assoc check */
4015 	token = bcmstrtok(&pos, " ", NULL);
4016 	if (!token)
4017 		return -EINVAL;
4018 	rps.sta_assoc_check = bcm_atoi(token);
4019 
4020 	/* get the interface name */
4021 	token = bcmstrtok(&pos, " ", NULL);
4022 	if (!token)
4023 		return -EINVAL;
4024 	ifname = token;
4025 
4026 	ANDROID_TRACE(("pps %d, level %d, quiettime %d, sta_assoc_check %d, "
4027 		"ifacename %s\n", rps.pps, rps.level, rps.quiet_time,
4028 		rps.sta_assoc_check, ifname));
4029 
4030 	err = wl_update_ap_rps_params(dev, &rps, ifname);
4031 	if (unlikely(err)) {
4032 		ANDROID_ERROR(("Failed to update rps, pps %d, level %d, quiettime %d, "
4033 			"sta_assoc_check %d, err = %d\n", rps.pps, rps.level, rps.quiet_time,
4034 			rps.sta_assoc_check, err));
4035 	}
4036 
4037 	return err;
4038 }
4039 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
4040 
4041 #ifdef SUPPORT_RSSI_LOGGING
4042 int
wl_android_get_rssi_per_ant(struct net_device * dev,char * command,int total_len)4043 wl_android_get_rssi_per_ant(struct net_device *dev, char *command, int total_len)
4044 {
4045 	wl_rssi_ant_mimo_t rssi_ant_mimo;
4046 	char *ifname = NULL;
4047 	char *peer_mac = NULL;
4048 	char *mimo_cmd = "mimo";
4049 	char *pos, *token;
4050 	int err = BCME_OK;
4051 	int bytes_written = 0;
4052 	bool mimo_rssi = FALSE;
4053 
4054 	memset(&rssi_ant_mimo, 0, sizeof(wl_rssi_ant_mimo_t));
4055 	/*
4056 	 * STA I/F: DRIVER GET_RSSI_PER_ANT <ifname> <mimo>
4057 	 * AP/GO I/F: DRIVER GET_RSSI_PER_ANT <ifname> <Peer MAC addr> <mimo>
4058 	 */
4059 	pos = command;
4060 
4061 	/* drop command */
4062 	token = bcmstrtok(&pos, " ", NULL);
4063 
4064 	/* get the interface name */
4065 	token = bcmstrtok(&pos, " ", NULL);
4066 	if (!token) {
4067 		ANDROID_ERROR(("Invalid arguments\n"));
4068 		return -EINVAL;
4069 	}
4070 	ifname = token;
4071 
4072 	/* Optional: Check the MIMO RSSI mode or peer MAC address */
4073 	token = bcmstrtok(&pos, " ", NULL);
4074 	if (token) {
4075 		/* Check the MIMO RSSI mode */
4076 		if (strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) {
4077 			mimo_rssi = TRUE;
4078 		} else {
4079 			peer_mac = token;
4080 		}
4081 	}
4082 
4083 	/* Optional: Check the MIMO RSSI mode - RSSI sum across antennas */
4084 	token = bcmstrtok(&pos, " ", NULL);
4085 	if (token && strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) {
4086 		mimo_rssi = TRUE;
4087 	}
4088 
4089 	err = wl_get_rssi_per_ant(dev, ifname, peer_mac, &rssi_ant_mimo);
4090 	if (unlikely(err)) {
4091 		ANDROID_ERROR(("Failed to get RSSI info, err=%d\n", err));
4092 		return err;
4093 	}
4094 
4095 	/* Parse the results */
4096 	ANDROID_TRACE(("ifname %s, version %d, count %d, mimo rssi %d\n",
4097 		ifname, rssi_ant_mimo.version, rssi_ant_mimo.count, mimo_rssi));
4098 	if (mimo_rssi) {
4099 		ANDROID_TRACE(("MIMO RSSI: %d\n", rssi_ant_mimo.rssi_sum));
4100 		bytes_written = snprintf(command, total_len, "%s MIMO %d",
4101 			CMD_GET_RSSI_PER_ANT, rssi_ant_mimo.rssi_sum);
4102 	} else {
4103 		int cnt;
4104 		bytes_written = snprintf(command, total_len, "%s PER_ANT ", CMD_GET_RSSI_PER_ANT);
4105 		for (cnt = 0; cnt < rssi_ant_mimo.count; cnt++) {
4106 			ANDROID_TRACE(("RSSI[%d]: %d\n", cnt, rssi_ant_mimo.rssi_ant[cnt]));
4107 			bytes_written = snprintf(command, total_len, "%d ",
4108 				rssi_ant_mimo.rssi_ant[cnt]);
4109 		}
4110 	}
4111 
4112 	return bytes_written;
4113 }
4114 
4115 int
wl_android_set_rssi_logging(struct net_device * dev,char * command,int total_len)4116 wl_android_set_rssi_logging(struct net_device *dev, char *command, int total_len)
4117 {
4118 	rssilog_set_param_t set_param;
4119 	char *pos, *token;
4120 	int err = BCME_OK;
4121 
4122 	memset(&set_param, 0, sizeof(rssilog_set_param_t));
4123 	/*
4124 	 * DRIVER SET_RSSI_LOGGING <enable/disable> <RSSI Threshold> <Time Threshold>
4125 	 */
4126 	pos = command;
4127 
4128 	/* drop command */
4129 	token = bcmstrtok(&pos, " ", NULL);
4130 
4131 	/* enable/disable */
4132 	token = bcmstrtok(&pos, " ", NULL);
4133 	if (!token) {
4134 		ANDROID_ERROR(("Invalid arguments\n"));
4135 		return -EINVAL;
4136 	}
4137 	set_param.enable = bcm_atoi(token);
4138 
4139 	/* RSSI Threshold */
4140 	token = bcmstrtok(&pos, " ", NULL);
4141 	if (!token) {
4142 		ANDROID_ERROR(("Invalid arguments\n"));
4143 		return -EINVAL;
4144 	}
4145 	set_param.rssi_threshold = bcm_atoi(token);
4146 
4147 	/* Time Threshold */
4148 	token = bcmstrtok(&pos, " ", NULL);
4149 	if (!token) {
4150 		ANDROID_ERROR(("Invalid arguments\n"));
4151 		return -EINVAL;
4152 	}
4153 	set_param.time_threshold = bcm_atoi(token);
4154 
4155 	ANDROID_TRACE(("enable %d, RSSI threshold %d, Time threshold %d\n", set_param.enable,
4156 		set_param.rssi_threshold, set_param.time_threshold));
4157 
4158 	err = wl_set_rssi_logging(dev, (void *)&set_param);
4159 	if (unlikely(err)) {
4160 		ANDROID_ERROR(("Failed to configure RSSI logging: enable %d, RSSI Threshold %d,"
4161 			" Time Threshold %d\n", set_param.enable, set_param.rssi_threshold,
4162 			set_param.time_threshold));
4163 	}
4164 
4165 	return err;
4166 }
4167 
4168 int
wl_android_get_rssi_logging(struct net_device * dev,char * command,int total_len)4169 wl_android_get_rssi_logging(struct net_device *dev, char *command, int total_len)
4170 {
4171 	rssilog_get_param_t get_param;
4172 	int err = BCME_OK;
4173 	int bytes_written = 0;
4174 
4175 	err = wl_get_rssi_logging(dev, (void *)&get_param);
4176 	if (unlikely(err)) {
4177 		ANDROID_ERROR(("Failed to get RSSI logging info\n"));
4178 		return BCME_ERROR;
4179 	}
4180 
4181 	ANDROID_TRACE(("report_count %d, enable %d, rssi_threshold %d, time_threshold %d\n",
4182 		get_param.report_count, get_param.enable, get_param.rssi_threshold,
4183 		get_param.time_threshold));
4184 
4185 	/* Parse the parameter */
4186 	if (!get_param.enable) {
4187 		ANDROID_TRACE(("RSSI LOGGING: Feature is disables\n"));
4188 		bytes_written = snprintf(command, total_len,
4189 			"%s FEATURE DISABLED\n", CMD_GET_RSSI_LOGGING);
4190 	} else if (get_param.enable &
4191 		(RSSILOG_FLAG_FEATURE_SW | RSSILOG_FLAG_REPORT_READY)) {
4192 		if (!get_param.report_count) {
4193 			ANDROID_TRACE(("[PASS] RSSI difference across antennas is within"
4194 				" threshold limits\n"));
4195 			bytes_written = snprintf(command, total_len, "%s PASS\n",
4196 				CMD_GET_RSSI_LOGGING);
4197 		} else {
4198 			ANDROID_TRACE(("[FAIL] RSSI difference across antennas found "
4199 				"to be greater than %3d dB\n", get_param.rssi_threshold));
4200 			ANDROID_TRACE(("[FAIL] RSSI difference check have failed for "
4201 				"%d out of %d times\n", get_param.report_count,
4202 				get_param.time_threshold));
4203 			ANDROID_TRACE(("[FAIL] RSSI difference is being monitored once "
4204 				"per second, for a %d secs window\n", get_param.time_threshold));
4205 			bytes_written = snprintf(command, total_len, "%s FAIL - RSSI Threshold "
4206 				"%d dBm for %d out of %d times\n", CMD_GET_RSSI_LOGGING,
4207 				get_param.rssi_threshold, get_param.report_count,
4208 				get_param.time_threshold);
4209 		}
4210 	} else {
4211 		ANDROID_TRACE(("[BUSY] Reprot is not ready\n"));
4212 		bytes_written = snprintf(command, total_len, "%s BUSY - NOT READY\n",
4213 			CMD_GET_RSSI_LOGGING);
4214 	}
4215 
4216 	return bytes_written;
4217 }
4218 #endif /* SUPPORT_RSSI_LOGGING */
4219 
4220 #ifdef SET_PCIE_IRQ_CPU_CORE
4221 void
wl_android_set_irq_cpucore(struct net_device * net,int set)4222 wl_android_set_irq_cpucore(struct net_device *net, int set)
4223 {
4224 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(net);
4225 	if (!dhdp) {
4226 		ANDROID_ERROR(("dhd is NULL\n"));
4227 		return;
4228 	}
4229 	dhd_set_irq_cpucore(dhdp, set);
4230 }
4231 #endif /* SET_PCIE_IRQ_CPU_CORE */
4232 
4233 #if defined(DHD_HANG_SEND_UP_TEST)
4234 void
wl_android_make_hang_with_reason(struct net_device * dev,const char * string_num)4235 wl_android_make_hang_with_reason(struct net_device *dev, const char *string_num)
4236 {
4237 	dhd_make_hang_with_reason(dev, string_num);
4238 }
4239 #endif /* DHD_HANG_SEND_UP_TEST */
4240 
4241 #ifdef WL_CFG80211
4242 #ifdef WLMESH_CFG80211
4243 static int
wl_android_set_rsdb_mode(struct net_device * dev,char * command,int total_len)4244 wl_android_set_rsdb_mode(struct net_device *dev, char *command, int total_len)
4245 {
4246 	int ret;
4247 	wl_config_t rsdb_mode_cfg = {-1, 0};
4248 	char smbuf[WLC_IOCTL_SMLEN];
4249 	s32 val = 1;
4250 
4251 	if (sscanf(command, "%*s %d", &rsdb_mode_cfg.config) != 1) {
4252 		DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
4253 		return -1;
4254 	}
4255 	DHD_INFO(("%s : RSDB_MODE = %d\n", __FUNCTION__, rsdb_mode_cfg.config));
4256 
4257 	ret = wldev_ioctl_set(dev, WLC_DOWN, &val, sizeof(s32));
4258 	if (ret < 0)
4259 		DHD_ERROR(("WLC_DOWN error %d\n", ret));
4260 
4261 	ret = wldev_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg, sizeof(rsdb_mode_cfg),
4262 		smbuf, sizeof(smbuf), NULL);
4263 	if (ret < 0)
4264 		DHD_ERROR(("%s : set rsdb_mode error=%d\n", __FUNCTION__, ret));
4265 
4266 	ret = wldev_ioctl_set(dev, WLC_UP, &val, sizeof(s32));
4267 	if (ret < 0)
4268 		DHD_ERROR(("WLC_UP error %d\n", ret));
4269 
4270 	return ret;
4271 }
4272 #endif /* WLMESH */
4273 #endif /* WL_CFG80211 */
4274 
4275 #ifdef SUPPORT_LQCM
4276 static int
wl_android_lqcm_enable(struct net_device * net,int lqcm_enable)4277 wl_android_lqcm_enable(struct net_device *net, int lqcm_enable)
4278 {
4279 	int err = 0;
4280 
4281 	err = wldev_iovar_setint(net, "lqcm", lqcm_enable);
4282 	if (err != BCME_OK) {
4283 		ANDROID_ERROR(("failed to set lqcm enable %d, error = %d\n", lqcm_enable, err));
4284 		return -EIO;
4285 	}
4286 	return err;
4287 }
4288 
wl_android_get_lqcm_report(struct net_device * dev,char * command,int total_len)4289 static int wl_android_get_lqcm_report(
4290 	struct net_device *dev, char *command, int total_len)
4291 {
4292 	int bytes_written, err = 0;
4293 	uint32 lqcm_report = 0;
4294 	uint32 lqcm_enable, tx_lqcm_idx, rx_lqcm_idx;
4295 
4296 	err = wldev_iovar_getint(dev, "lqcm", &lqcm_report);
4297 	if (err != BCME_OK) {
4298 		ANDROID_ERROR(("failed to get lqcm report, error = %d\n", err));
4299 		return -EIO;
4300 	}
4301 	lqcm_enable = lqcm_report & LQCM_ENAB_MASK;
4302 	tx_lqcm_idx = (lqcm_report & LQCM_TX_INDEX_MASK) >> LQCM_TX_INDEX_SHIFT;
4303 	rx_lqcm_idx = (lqcm_report & LQCM_RX_INDEX_MASK) >> LQCM_RX_INDEX_SHIFT;
4304 
4305 	ANDROID_ERROR(("lqcm report EN:%d, TX:%d, RX:%d\n", lqcm_enable, tx_lqcm_idx, rx_lqcm_idx));
4306 
4307 	bytes_written = snprintf(command, total_len, "%s %d",
4308 		CMD_GET_LQCM_REPORT, lqcm_report);
4309 
4310 	return bytes_written;
4311 }
4312 #endif /* SUPPORT_LQCM */
4313 
4314 int
wl_android_get_snr(struct net_device * dev,char * command,int total_len)4315 wl_android_get_snr(struct net_device *dev, char *command, int total_len)
4316 {
4317 	int bytes_written, error = 0;
4318 	s32 snr = 0;
4319 
4320 	error = wldev_iovar_getint(dev, "snr", &snr);
4321 	if (error) {
4322 		ANDROID_ERROR(("%s: Failed to get SNR %d, error = %d\n",
4323 			__FUNCTION__, snr, error));
4324 		return -EIO;
4325 	}
4326 
4327 	bytes_written = snprintf(command, total_len, "snr %d", snr);
4328 	ANDROID_INFO(("%s: command result is %s\n", __FUNCTION__, command));
4329 	return bytes_written;
4330 }
4331 #ifdef WLADPS_PRIVATE_CMD
4332 static int
wl_android_set_adps_mode(struct net_device * dev,const char * string_num)4333 wl_android_set_adps_mode(struct net_device *dev, const char* string_num)
4334 {
4335 	int err = 0, adps_mode;
4336 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4337 
4338 	adps_mode = bcm_atoi(string_num);
4339 
4340 	if ((adps_mode < 0) && (1 < adps_mode)) {
4341 		ANDROID_ERROR(("%s: Invalid value %d.\n", __FUNCTION__, adps_mode));
4342 		return -EINVAL;
4343 	}
4344 
4345 	err = dhd_enable_adps(dhdp, adps_mode);
4346 	if (err != BCME_OK) {
4347 		ANDROID_ERROR(("failed to set adps mode %d, error = %d\n", adps_mode, err));
4348 		return -EIO;
4349 	}
4350 	return err;
4351 }
4352 static int
wl_android_get_adps_mode(struct net_device * dev,char * command,int total_len)4353 wl_android_get_adps_mode(
4354 	struct net_device *dev, char *command, int total_len)
4355 {
4356 	int bytes_written, err = 0;
4357 	int len;
4358 	char buf[WLC_IOCTL_SMLEN];
4359 
4360 	bcm_iov_buf_t iov_buf;
4361 	bcm_iov_buf_t *ptr = NULL;
4362 	wl_adps_params_v1_t *data = NULL;
4363 
4364 	uint8 *pdata = NULL;
4365 	uint8 band, mode = 0;
4366 
4367 	memset(&iov_buf, 0, sizeof(iov_buf));
4368 
4369 	len = OFFSETOF(bcm_iov_buf_t, data) + sizeof(*data);
4370 
4371 	iov_buf.version = WL_ADPS_IOV_VER;
4372 	iov_buf.len = sizeof(band);
4373 	iov_buf.id = WL_ADPS_IOV_MODE;
4374 
4375 	pdata = (uint8 *)&iov_buf.data;
4376 
4377 	for (band = 1; band <= MAX_BANDS; band++) {
4378 		pdata[0] = band;
4379 		err = wldev_iovar_getbuf(dev, "adps", &iov_buf, len,
4380 			buf, WLC_IOCTL_SMLEN, NULL);
4381 		if (err != BCME_OK) {
4382 			ANDROID_ERROR(("%s fail to get adps band %d(%d).\n",
4383 					__FUNCTION__, band, err));
4384 			return -EIO;
4385 		}
4386 		ptr = (bcm_iov_buf_t *) buf;
4387 		data = (wl_adps_params_v1_t *) ptr->data;
4388 		mode = data->mode;
4389 		if (mode != OFF) {
4390 			break;
4391 		}
4392 	}
4393 
4394 	bytes_written = snprintf(command, total_len, "%s %d",
4395 		CMD_GET_ADPS, mode);
4396 	return bytes_written;
4397 }
4398 #endif /* WLADPS_PRIVATE_CMD */
4399 
4400 #ifdef DHD_PKT_LOGGING
4401 static int
wl_android_pktlog_filter_enable(struct net_device * dev,char * command,int total_len)4402 wl_android_pktlog_filter_enable(struct net_device *dev, char *command, int total_len)
4403 {
4404 	int bytes_written = 0;
4405 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4406 	dhd_pktlog_filter_t *filter;
4407 	int err = BCME_OK;
4408 
4409 	if (!dhdp || !dhdp->pktlog) {
4410 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4411 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4412 		return -EINVAL;
4413 	}
4414 
4415 	filter = dhdp->pktlog->pktlog_filter;
4416 
4417 	err = dhd_pktlog_filter_enable(filter, PKTLOG_TXPKT_CASE, TRUE);
4418 	err = dhd_pktlog_filter_enable(filter, PKTLOG_TXSTATUS_CASE, TRUE);
4419 	err = dhd_pktlog_filter_enable(filter, PKTLOG_RXPKT_CASE, TRUE);
4420 
4421 	if (err == BCME_OK) {
4422 		bytes_written = snprintf(command, total_len, "OK");
4423 		ANDROID_ERROR(("%s: pktlog filter enable success\n", __FUNCTION__));
4424 	} else {
4425 		ANDROID_ERROR(("%s: pktlog filter enable fail\n", __FUNCTION__));
4426 		return BCME_ERROR;
4427 	}
4428 
4429 	return bytes_written;
4430 }
4431 
4432 static int
wl_android_pktlog_filter_disable(struct net_device * dev,char * command,int total_len)4433 wl_android_pktlog_filter_disable(struct net_device *dev, char *command, int total_len)
4434 {
4435 	int bytes_written = 0;
4436 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4437 	dhd_pktlog_filter_t *filter;
4438 	int err = BCME_OK;
4439 
4440 	if (!dhdp || !dhdp->pktlog) {
4441 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4442 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4443 		return -EINVAL;
4444 	}
4445 
4446 	filter = dhdp->pktlog->pktlog_filter;
4447 
4448 	err = dhd_pktlog_filter_enable(filter, PKTLOG_TXPKT_CASE, FALSE);
4449 	err = dhd_pktlog_filter_enable(filter, PKTLOG_TXSTATUS_CASE, FALSE);
4450 	err = dhd_pktlog_filter_enable(filter, PKTLOG_RXPKT_CASE, FALSE);
4451 
4452 	if (err == BCME_OK) {
4453 		bytes_written = snprintf(command, total_len, "OK");
4454 		ANDROID_ERROR(("%s: pktlog filter disable success\n", __FUNCTION__));
4455 	} else {
4456 		ANDROID_ERROR(("%s: pktlog filter disable fail\n", __FUNCTION__));
4457 		return BCME_ERROR;
4458 	}
4459 
4460 	return bytes_written;
4461 }
4462 
4463 static int
wl_android_pktlog_filter_pattern_enable(struct net_device * dev,char * command,int total_len)4464 wl_android_pktlog_filter_pattern_enable(struct net_device *dev, char *command, int total_len)
4465 {
4466 	int bytes_written = 0;
4467 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4468 	dhd_pktlog_filter_t *filter;
4469 	int err = BCME_OK;
4470 
4471 	if (!dhdp || !dhdp->pktlog) {
4472 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4473 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4474 		return -EINVAL;
4475 	}
4476 
4477 	filter = dhdp->pktlog->pktlog_filter;
4478 
4479 	if (strlen(CMD_PKTLOG_FILTER_PATTERN_ENABLE) + 1 > total_len) {
4480 		return BCME_ERROR;
4481 	}
4482 
4483 	err = dhd_pktlog_filter_pattern_enable(filter,
4484 			command + strlen(CMD_PKTLOG_FILTER_PATTERN_ENABLE) + 1, TRUE);
4485 
4486 	if (err == BCME_OK) {
4487 		bytes_written = snprintf(command, total_len, "OK");
4488 		ANDROID_ERROR(("%s: pktlog filter pattern enable success\n", __FUNCTION__));
4489 	} else {
4490 		ANDROID_ERROR(("%s: pktlog filter pattern enable fail\n", __FUNCTION__));
4491 		return BCME_ERROR;
4492 	}
4493 
4494 	return bytes_written;
4495 }
4496 
4497 static int
wl_android_pktlog_filter_pattern_disable(struct net_device * dev,char * command,int total_len)4498 wl_android_pktlog_filter_pattern_disable(struct net_device *dev, char *command, int total_len)
4499 {
4500 	int bytes_written = 0;
4501 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4502 	dhd_pktlog_filter_t *filter;
4503 	int err = BCME_OK;
4504 
4505 	if (!dhdp || !dhdp->pktlog) {
4506 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4507 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4508 		return -EINVAL;
4509 	}
4510 
4511 	filter = dhdp->pktlog->pktlog_filter;
4512 
4513 	if (strlen(CMD_PKTLOG_FILTER_PATTERN_DISABLE) + 1 > total_len) {
4514 		return BCME_ERROR;
4515 	}
4516 
4517 	err = dhd_pktlog_filter_pattern_enable(filter,
4518 			command + strlen(CMD_PKTLOG_FILTER_PATTERN_DISABLE) + 1, FALSE);
4519 
4520 	if (err == BCME_OK) {
4521 		bytes_written = snprintf(command, total_len, "OK");
4522 		ANDROID_ERROR(("%s: pktlog filter pattern disable success\n", __FUNCTION__));
4523 	} else {
4524 		ANDROID_ERROR(("%s: pktlog filter pattern disable fail\n", __FUNCTION__));
4525 		return BCME_ERROR;
4526 	}
4527 
4528 	return bytes_written;
4529 }
4530 
4531 static int
wl_android_pktlog_filter_add(struct net_device * dev,char * command,int total_len)4532 wl_android_pktlog_filter_add(struct net_device *dev, char *command, int total_len)
4533 {
4534 	int bytes_written = 0;
4535 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4536 	dhd_pktlog_filter_t *filter;
4537 	int err = BCME_OK;
4538 
4539 	if (!dhdp || !dhdp->pktlog) {
4540 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4541 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4542 		return -EINVAL;
4543 	}
4544 
4545 	filter = dhdp->pktlog->pktlog_filter;
4546 
4547 	if (strlen(CMD_PKTLOG_FILTER_ADD) + 1 > total_len) {
4548 		return BCME_ERROR;
4549 	}
4550 
4551 	err = dhd_pktlog_filter_add(filter, command + strlen(CMD_PKTLOG_FILTER_ADD) + 1);
4552 
4553 	if (err == BCME_OK) {
4554 		bytes_written = snprintf(command, total_len, "OK");
4555 		ANDROID_ERROR(("%s: pktlog filter add success\n", __FUNCTION__));
4556 	} else {
4557 		ANDROID_ERROR(("%s: pktlog filter add fail\n", __FUNCTION__));
4558 		return BCME_ERROR;
4559 	}
4560 
4561 	return bytes_written;
4562 }
4563 
4564 static int
wl_android_pktlog_filter_info(struct net_device * dev,char * command,int total_len)4565 wl_android_pktlog_filter_info(struct net_device *dev, char *command, int total_len)
4566 {
4567 	int bytes_written = 0;
4568 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4569 	dhd_pktlog_filter_t *filter;
4570 	int err = BCME_OK;
4571 
4572 	if (!dhdp || !dhdp->pktlog) {
4573 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4574 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4575 		return -EINVAL;
4576 	}
4577 
4578 	filter = dhdp->pktlog->pktlog_filter;
4579 
4580 	err = dhd_pktlog_filter_info(filter);
4581 
4582 	if (err == BCME_OK) {
4583 		bytes_written = snprintf(command, total_len, "OK");
4584 		ANDROID_ERROR(("%s: pktlog filter info success\n", __FUNCTION__));
4585 	} else {
4586 		ANDROID_ERROR(("%s: pktlog filter info fail\n", __FUNCTION__));
4587 		return BCME_ERROR;
4588 	}
4589 
4590 	return bytes_written;
4591 }
4592 
4593 static int
wl_android_pktlog_start(struct net_device * dev,char * command,int total_len)4594 wl_android_pktlog_start(struct net_device *dev, char *command, int total_len)
4595 {
4596 	int bytes_written = 0;
4597 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4598 
4599 	if (!dhdp || !dhdp->pktlog) {
4600 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4601 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4602 		return -EINVAL;
4603 	}
4604 
4605 	if (!dhdp->pktlog->tx_pktlog_ring || !dhdp->pktlog->rx_pktlog_ring) {
4606 		DHD_PKT_LOG(("%s(): tx_pktlog_ring=%p rx_pktlog_ring=%p\n",
4607 			__FUNCTION__, dhdp->pktlog->tx_pktlog_ring, dhdp->pktlog->rx_pktlog_ring));
4608 		return -EINVAL;
4609 	}
4610 
4611 	dhdp->pktlog->tx_pktlog_ring->start = TRUE;
4612 	dhdp->pktlog->rx_pktlog_ring->start = TRUE;
4613 
4614 	bytes_written = snprintf(command, total_len, "OK");
4615 
4616 	ANDROID_ERROR(("%s: pktlog start success\n", __FUNCTION__));
4617 
4618 	return bytes_written;
4619 }
4620 
4621 static int
wl_android_pktlog_stop(struct net_device * dev,char * command,int total_len)4622 wl_android_pktlog_stop(struct net_device *dev, char *command, int total_len)
4623 {
4624 	int bytes_written = 0;
4625 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4626 
4627 	if (!dhdp || !dhdp->pktlog) {
4628 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4629 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4630 		return -EINVAL;
4631 	}
4632 
4633 	if (!dhdp->pktlog->tx_pktlog_ring || !dhdp->pktlog->rx_pktlog_ring) {
4634 		DHD_PKT_LOG(("%s(): tx_pktlog_ring=%p rx_pktlog_ring=%p\n",
4635 			__FUNCTION__, dhdp->pktlog->tx_pktlog_ring, dhdp->pktlog->rx_pktlog_ring));
4636 		return -EINVAL;
4637 	}
4638 
4639 	dhdp->pktlog->tx_pktlog_ring->start = FALSE;
4640 	dhdp->pktlog->rx_pktlog_ring->start = FALSE;
4641 
4642 	bytes_written = snprintf(command, total_len, "OK");
4643 
4644 	ANDROID_ERROR(("%s: pktlog stop success\n", __FUNCTION__));
4645 
4646 	return bytes_written;
4647 }
4648 
4649 static int
wl_android_pktlog_filter_exist(struct net_device * dev,char * command,int total_len)4650 wl_android_pktlog_filter_exist(struct net_device *dev, char *command, int total_len)
4651 {
4652 	int bytes_written = 0;
4653 	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4654 	dhd_pktlog_filter_t *filter;
4655 	uint32 id;
4656 	bool exist = FALSE;
4657 
4658 	if (!dhdp || !dhdp->pktlog) {
4659 		DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
4660 			__FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
4661 		return -EINVAL;
4662 	}
4663 
4664 	filter = dhdp->pktlog->pktlog_filter;
4665 
4666 	if (strlen(CMD_PKTLOG_FILTER_EXIST) + 1 > total_len) {
4667 		return BCME_ERROR;
4668 	}
4669 
4670 	exist = dhd_pktlog_filter_existed(filter, command + strlen(CMD_PKTLOG_FILTER_EXIST) + 1,
4671 			&id);
4672 
4673 	if (exist) {
4674 		bytes_written = snprintf(command, total_len, "TRUE");
4675 		ANDROID_ERROR(("%s: pktlog filter pattern id: %d is existed\n", __FUNCTION__, id));
4676 	} else {
4677 		bytes_written = snprintf(command, total_len, "FALSE");
4678 		ANDROID_ERROR(("%s: pktlog filter pattern id: %d is not existed\n", __FUNCTION__, id));
4679 	}
4680 
4681 	return bytes_written;
4682 }
4683 #endif /* DHD_PKT_LOGGING */
4684 
wl_android_priv_cmd(struct net_device * net,struct ifreq * ifr,int cmd)4685 int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
4686 {
4687 #define PRIVATE_COMMAND_MAX_LEN	8192
4688 #define PRIVATE_COMMAND_DEF_LEN	4096
4689 	int ret = 0;
4690 	char *command = NULL;
4691 	int bytes_written = 0;
4692 	android_wifi_priv_cmd priv_cmd;
4693 	int buf_size = 0;
4694 
4695 	net_os_wake_lock(net);
4696 
4697 	if (!capable(CAP_NET_ADMIN)) {
4698 		ret = -EPERM;
4699 		goto exit;
4700 	}
4701 
4702 	if (!ifr->ifr_data) {
4703 		ret = -EINVAL;
4704 		goto exit;
4705 	}
4706 
4707 #ifdef CONFIG_COMPAT
4708 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
4709 	if (in_compat_syscall())
4710 #else
4711 	if (is_compat_task())
4712 #endif
4713 	{
4714 		compat_android_wifi_priv_cmd compat_priv_cmd;
4715 		if (copy_from_user(&compat_priv_cmd, ifr->ifr_data,
4716 			sizeof(compat_android_wifi_priv_cmd))) {
4717 			ret = -EFAULT;
4718 			goto exit;
4719 
4720 		}
4721 		priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
4722 		priv_cmd.used_len = compat_priv_cmd.used_len;
4723 		priv_cmd.total_len = compat_priv_cmd.total_len;
4724 	} else
4725 #endif /* CONFIG_COMPAT */
4726 	{
4727 		if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
4728 			ret = -EFAULT;
4729 			goto exit;
4730 		}
4731 	}
4732 	if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) {
4733 		ANDROID_ERROR(("%s: buf length invalid:%d\n", __FUNCTION__,
4734 			priv_cmd.total_len));
4735 		ret = -EINVAL;
4736 		goto exit;
4737 	}
4738 
4739 	buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN);
4740 	command = kmalloc((buf_size + 1), GFP_KERNEL);
4741 
4742 	if (!command)
4743 	{
4744 		ANDROID_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
4745 		ret = -ENOMEM;
4746 		goto exit;
4747 	}
4748 	if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
4749 		ret = -EFAULT;
4750 		goto exit;
4751 	}
4752 	command[priv_cmd.total_len] = '\0';
4753 
4754 	ANDROID_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name));
4755 
4756 	bytes_written = wl_handle_private_cmd(net, command, priv_cmd.total_len);
4757 	if (bytes_written >= 0) {
4758 		if ((bytes_written == 0) && (priv_cmd.total_len > 0)) {
4759 			command[0] = '\0';
4760 		}
4761 		if (bytes_written >= priv_cmd.total_len) {
4762 			ANDROID_ERROR(("%s: err. bytes_written:%d >= total_len:%d, buf_size:%d\n",
4763 				__FUNCTION__, bytes_written, priv_cmd.total_len, buf_size));
4764 			ret = BCME_BUFTOOSHORT;
4765 			goto exit;
4766 		}
4767 		bytes_written++;
4768 		priv_cmd.used_len = bytes_written;
4769 		if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
4770 			ANDROID_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
4771 			ret = -EFAULT;
4772 		}
4773 	}
4774 	else {
4775 		/* Propagate the error */
4776 		ret = bytes_written;
4777 	}
4778 
4779 exit:
4780 	net_os_wake_unlock(net);
4781 	kfree(command);
4782 	return ret;
4783 }
4784 
4785 int
wl_handle_private_cmd(struct net_device * net,char * command,u32 cmd_len)4786 wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
4787 {
4788 	int bytes_written = 0;
4789 	android_wifi_priv_cmd priv_cmd;
4790 
4791 	bzero(&priv_cmd, sizeof(android_wifi_priv_cmd));
4792 	priv_cmd.total_len = cmd_len;
4793 
4794 	if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
4795 		ANDROID_INFO(("%s, Received regular START command\n", __FUNCTION__));
4796 #ifdef  BT_OVER_SDIO
4797 		bytes_written = dhd_net_bus_get(net);
4798 #else
4799 		bytes_written = wl_android_wifi_on(net);
4800 #endif /* BT_OVER_SDIO */
4801 	}
4802 	else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) {
4803 		bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len);
4804 	}
4805 
4806 	if (!g_wifi_on) {
4807 		ANDROID_ERROR(("%s: Ignore private cmd \"%s\" - iface is down\n",
4808 			__FUNCTION__, command));
4809 		return 0;
4810 	}
4811 
4812 	if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
4813 #ifdef  BT_OVER_SDIO
4814 		bytes_written = dhd_net_bus_put(net);
4815 #else
4816 		bytes_written = wl_android_wifi_off(net, FALSE);
4817 #endif /* BT_OVER_SDIO */
4818 	}
4819 #ifdef WL_CFG80211
4820 	else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) {
4821 		wl_cfg80211_set_passive_scan(net, command);
4822 	}
4823 	else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) {
4824 		wl_cfg80211_set_passive_scan(net, command);
4825 	}
4826 #endif
4827 	else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
4828 		bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len);
4829 	}
4830 	else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) {
4831 		bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len);
4832 	}
4833 #ifdef PKT_FILTER_SUPPORT
4834 	else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) {
4835 		bytes_written = net_os_enable_packet_filter(net, 1);
4836 	}
4837 	else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) {
4838 		bytes_written = net_os_enable_packet_filter(net, 0);
4839 	}
4840 	else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) {
4841 		int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
4842 		bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
4843 	}
4844 	else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) {
4845 		int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
4846 		bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
4847 	}
4848 #endif /* PKT_FILTER_SUPPORT */
4849 	else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) {
4850 		/* TBD: BTCOEXSCAN-START */
4851 	}
4852 	else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) {
4853 		/* TBD: BTCOEXSCAN-STOP */
4854 	}
4855 	else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) {
4856 #ifdef WL_CFG80211
4857 		void *dhdp = wl_cfg80211_get_dhdp(net);
4858 		bytes_written = wl_cfg80211_set_btcoex_dhcp(net, dhdp, command);
4859 #else
4860 #ifdef PKT_FILTER_SUPPORT
4861 		uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
4862 
4863 		if (mode == 1)
4864 			net_os_enable_packet_filter(net, 0); /* DHCP starts */
4865 		else
4866 			net_os_enable_packet_filter(net, 1); /* DHCP ends */
4867 #endif /* PKT_FILTER_SUPPORT */
4868 #endif /* WL_CFG80211 */
4869 	}
4870 	else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
4871 		bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
4872 	}
4873 	else if (strnicmp(command, CMD_MAXDTIM_IN_SUSPEND, strlen(CMD_MAXDTIM_IN_SUSPEND)) == 0) {
4874 		bytes_written = wl_android_set_max_dtim(net, command, priv_cmd.total_len);
4875 	}
4876 #ifdef WL_CFG80211
4877 	else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
4878 #ifdef DISABLE_SETBAND
4879 		bytes_written = BCME_DISABLED;
4880 #else	/* DISABLE_SETBAND */
4881 		uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
4882 		if (dhd_conf_get_band(dhd_get_pub(net)) >= WLC_BAND_AUTO) {
4883 			printf("%s: Band is fixed in config.txt\n", __FUNCTION__);
4884 		} else
4885 			bytes_written = wl_cfg80211_set_if_band(net, band);
4886 #endif /* DISABLE_SETBAND */
4887 	}
4888 #endif
4889 	else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
4890 		bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
4891 	}
4892 #ifdef WL_CFG80211
4893 	else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
4894 		bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
4895 	} else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
4896 		bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
4897 	} else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
4898 		bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
4899 	}
4900 #endif /* WL_CFG80211 */
4901 	/* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
4902 	else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
4903 		/*
4904 		 * Usage examples:
4905 		 * DRIVER COUNTRY US
4906 		 * DRIVER COUNTRY US/7
4907 		 */
4908 		char *country_code = command + strlen(CMD_COUNTRY) + 1;
4909 		char *rev_info_delim = country_code + 2; /* 2 bytes of country code */
4910 		int revinfo = -1;
4911 #if defined(DHD_BLOB_EXISTENCE_CHECK)
4912 		dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(net);
4913 
4914 		if (dhdp->is_blob) {
4915 			revinfo = 0;
4916 		} else
4917 #endif /* DHD_BLOB_EXISTENCE_CHECK */
4918 		if ((rev_info_delim) &&
4919 			(strnicmp(rev_info_delim, CMD_COUNTRY_DELIMITER,
4920 			strlen(CMD_COUNTRY_DELIMITER)) == 0) &&
4921 			(rev_info_delim + 1)) {
4922 			revinfo  = bcm_atoi(rev_info_delim + 1);
4923 		}
4924 		bytes_written = wldev_set_country(net, country_code, true, true, revinfo);
4925 #ifdef CUSTOMER_HW4_PRIVATE_CMD
4926 #ifdef FCC_PWR_LIMIT_2G
4927 		if (wldev_iovar_setint(net, "fccpwrlimit2g", FALSE)) {
4928 			ANDROID_ERROR(("%s: fccpwrlimit2g deactivation is failed\n", __FUNCTION__));
4929 		} else {
4930 			ANDROID_ERROR(("%s: fccpwrlimit2g is deactivated\n", __FUNCTION__));
4931 		}
4932 #endif /* FCC_PWR_LIMIT_2G */
4933 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
4934 	}
4935 	else if (strnicmp(command, CMD_DATARATE, strlen(CMD_DATARATE)) == 0) {
4936 		bytes_written = wl_android_get_datarate(net, command, priv_cmd.total_len);
4937 	} else if (strnicmp(command, CMD_ASSOC_CLIENTS,	strlen(CMD_ASSOC_CLIENTS)) == 0) {
4938 		bytes_written = wl_android_get_assoclist(net, command, priv_cmd.total_len);
4939 	}
4940 
4941 #ifdef CUSTOMER_HW4_PRIVATE_CMD
4942 #ifdef WLTDLS
4943 	else if (strnicmp(command, CMD_TDLS_RESET, strlen(CMD_TDLS_RESET)) == 0) {
4944 		bytes_written = wl_android_tdls_reset(net);
4945 	}
4946 #endif /* WLTDLS */
4947 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
4948 
4949 #ifdef PNO_SUPPORT
4950 	else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
4951 		bytes_written = dhd_dev_pno_stop_for_ssid(net);
4952 	}
4953 #ifndef WL_SCHED_SCAN
4954 	else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) {
4955 		bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
4956 	}
4957 #endif /* !WL_SCHED_SCAN */
4958 	else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
4959 		int enable = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
4960 		bytes_written = (enable)? 0 : dhd_dev_pno_stop_for_ssid(net);
4961 	}
4962 	else if (strnicmp(command, CMD_WLS_BATCHING, strlen(CMD_WLS_BATCHING)) == 0) {
4963 		bytes_written = wls_parse_batching_cmd(net, command, priv_cmd.total_len);
4964 	}
4965 #endif /* PNO_SUPPORT */
4966 	else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
4967 		bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
4968 	}
4969 #ifdef WL_CFG80211
4970 #ifdef WLMESH_CFG80211
4971 	else if (strnicmp(command, CMD_SAE_SET_PASSWORD, strlen(CMD_SAE_SET_PASSWORD)) == 0) {
4972 		int skip = strlen(CMD_SAE_SET_PASSWORD) + 1;
4973 		bytes_written = wl_cfg80211_set_sae_password(net, command + skip,
4974 			priv_cmd.total_len - skip);
4975 	}
4976 	else if (strnicmp(command, CMD_SET_RSDB_MODE, strlen(CMD_SET_RSDB_MODE)) == 0) {
4977 		bytes_written = wl_android_set_rsdb_mode(net, command, priv_cmd.total_len);
4978 	}
4979 #endif
4980 #endif /* WL_CFG80211 */
4981 	else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
4982 		int skip = strlen(CMD_P2P_SET_NOA) + 1;
4983 		bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
4984 			priv_cmd.total_len - skip);
4985 	}
4986 #ifdef P2P_LISTEN_OFFLOADING
4987 	else if (strnicmp(command, CMD_P2P_LISTEN_OFFLOAD, strlen(CMD_P2P_LISTEN_OFFLOAD)) == 0) {
4988 		u8 *sub_command = strchr(command, ' ');
4989 		bytes_written = wl_cfg80211_p2plo_offload(net, command, sub_command,
4990 				sub_command ? strlen(sub_command) : 0);
4991 	}
4992 #endif /* P2P_LISTEN_OFFLOADING */
4993 #if !defined WL_ENABLE_P2P_IF
4994 	else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
4995 		bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
4996 	}
4997 #endif /* WL_ENABLE_P2P_IF */
4998 	else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
4999 		int skip = strlen(CMD_P2P_SET_PS) + 1;
5000 		bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
5001 			priv_cmd.total_len - skip);
5002 	}
5003 	else if (strnicmp(command, CMD_P2P_ECSA, strlen(CMD_P2P_ECSA)) == 0) {
5004 		int skip = strlen(CMD_P2P_ECSA) + 1;
5005 		bytes_written = wl_cfg80211_set_p2p_ecsa(net, command + skip,
5006 			priv_cmd.total_len - skip);
5007 	}
5008 	else if (strnicmp(command, CMD_P2P_INC_BW, strlen(CMD_P2P_INC_BW)) == 0) {
5009 		int skip = strlen(CMD_P2P_INC_BW) + 1;
5010 		bytes_written = wl_cfg80211_increase_p2p_bw(net,
5011 				command + skip, priv_cmd.total_len - skip);
5012 	}
5013 #ifdef WL_CFG80211
5014 	else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE,
5015 		strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) {
5016 		int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3;
5017 		bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
5018 			priv_cmd.total_len - skip, *(command + skip - 2) - '0');
5019 	}
5020 #ifdef WLFBT
5021 	else if (strnicmp(command, CMD_GET_FTKEY, strlen(CMD_GET_FTKEY)) == 0) {
5022 		bytes_written = wl_cfg80211_get_fbt_key(net, command, priv_cmd.total_len);
5023 	}
5024 #endif /* WLFBT */
5025 #endif /* WL_CFG80211 */
5026 #if defined(WL_SUPPORT_AUTO_CHANNEL)
5027 	else if (strnicmp(command, CMD_GET_BEST_CHANNELS,
5028 		strlen(CMD_GET_BEST_CHANNELS)) == 0) {
5029 		bytes_written = wl_cfg80211_get_best_channels(net, command,
5030 			priv_cmd.total_len);
5031 	}
5032 #endif /* WL_SUPPORT_AUTO_CHANNEL */
5033 #if defined(WL_SUPPORT_AUTO_CHANNEL)
5034 	else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL,
5035 		strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) {
5036 		int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 1;
5037 		bytes_written = wl_android_set_auto_channel(net, (const char*)command+skip, command,
5038 			priv_cmd.total_len);
5039 	}
5040 #endif /* WL_SUPPORT_AUTO_CHANNEL */
5041 #ifdef CUSTOMER_HW4_PRIVATE_CMD
5042 #ifdef SUPPORT_SET_LPC
5043 	else if (strnicmp(command, CMD_HAPD_LPC_ENABLED,
5044 		strlen(CMD_HAPD_LPC_ENABLED)) == 0) {
5045 		int skip = strlen(CMD_HAPD_LPC_ENABLED) + 3;
5046 		wl_android_set_lpc(net, (const char*)command+skip);
5047 	}
5048 #endif /* SUPPORT_SET_LPC */
5049 #ifdef SUPPORT_TRIGGER_HANG_EVENT
5050 	else if (strnicmp(command, CMD_TEST_FORCE_HANG,
5051 		strlen(CMD_TEST_FORCE_HANG)) == 0) {
5052 		int skip = strlen(CMD_TEST_FORCE_HANG) + 1;
5053 		net_os_send_hang_message_reason(net, (const char*)command+skip);
5054 	}
5055 #endif /* SUPPORT_TRIGGER_HANG_EVENT */
5056 	else if (strnicmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0)
5057 		bytes_written = wl_android_ch_res_rl(net, true);
5058 	else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0)
5059 		bytes_written = wl_android_ch_res_rl(net, false);
5060 #ifdef WL_RELMCAST
5061 	else if (strnicmp(command, CMD_SET_RMC_ENABLE, strlen(CMD_SET_RMC_ENABLE)) == 0) {
5062 		int rmc_enable = *(command + strlen(CMD_SET_RMC_ENABLE) + 1) - '0';
5063 		bytes_written = wl_android_rmc_enable(net, rmc_enable);
5064 	}
5065 	else if (strnicmp(command, CMD_SET_RMC_TXRATE, strlen(CMD_SET_RMC_TXRATE)) == 0) {
5066 		int rmc_txrate;
5067 		sscanf(command, "%*s %10d", &rmc_txrate);
5068 		bytes_written = wldev_iovar_setint(net, "rmc_txrate", rmc_txrate * 2);
5069 	}
5070 	else if (strnicmp(command, CMD_SET_RMC_ACTPERIOD, strlen(CMD_SET_RMC_ACTPERIOD)) == 0) {
5071 		int actperiod;
5072 		sscanf(command, "%*s %10d", &actperiod);
5073 		bytes_written = wldev_iovar_setint(net, "rmc_actf_time", actperiod);
5074 	}
5075 	else if (strnicmp(command, CMD_SET_RMC_IDLEPERIOD, strlen(CMD_SET_RMC_IDLEPERIOD)) == 0) {
5076 		int acktimeout;
5077 		sscanf(command, "%*s %10d", &acktimeout);
5078 		acktimeout *= 1000;
5079 		bytes_written = wldev_iovar_setint(net, "rmc_acktmo", acktimeout);
5080 	}
5081 	else if (strnicmp(command, CMD_SET_RMC_LEADER, strlen(CMD_SET_RMC_LEADER)) == 0) {
5082 		int skip = strlen(CMD_SET_RMC_LEADER) + 1;
5083 		bytes_written = wl_android_rmc_set_leader(net, (const char*)command+skip);
5084 	}
5085 	else if (strnicmp(command, CMD_SET_RMC_EVENT,
5086 		strlen(CMD_SET_RMC_EVENT)) == 0) {
5087 		bytes_written = wl_android_set_rmc_event(net, command, priv_cmd.total_len);
5088 	}
5089 #endif /* WL_RELMCAST */
5090 	else if (strnicmp(command, CMD_GET_SCSCAN, strlen(CMD_GET_SCSCAN)) == 0) {
5091 		bytes_written = wl_android_get_singlecore_scan(net, command, priv_cmd.total_len);
5092 	}
5093 	else if (strnicmp(command, CMD_SET_SCSCAN, strlen(CMD_SET_SCSCAN)) == 0) {
5094 		bytes_written = wl_android_set_singlecore_scan(net, command, priv_cmd.total_len);
5095 	}
5096 #ifdef TEST_TX_POWER_CONTROL
5097 	else if (strnicmp(command, CMD_TEST_SET_TX_POWER,
5098 		strlen(CMD_TEST_SET_TX_POWER)) == 0) {
5099 		int skip = strlen(CMD_TEST_SET_TX_POWER) + 1;
5100 		wl_android_set_tx_power(net, (const char*)command+skip);
5101 	}
5102 	else if (strnicmp(command, CMD_TEST_GET_TX_POWER,
5103 		strlen(CMD_TEST_GET_TX_POWER)) == 0) {
5104 		wl_android_get_tx_power(net, command, priv_cmd.total_len);
5105 	}
5106 #endif /* TEST_TX_POWER_CONTROL */
5107 	else if (strnicmp(command, CMD_SARLIMIT_TX_CONTROL,
5108 		strlen(CMD_SARLIMIT_TX_CONTROL)) == 0) {
5109 		int skip = strlen(CMD_SARLIMIT_TX_CONTROL) + 1;
5110 		wl_android_set_sarlimit_txctrl(net, (const char*)command+skip);
5111 	}
5112 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
5113 	else if (strnicmp(command, CMD_HAPD_MAC_FILTER, strlen(CMD_HAPD_MAC_FILTER)) == 0) {
5114 		int skip = strlen(CMD_HAPD_MAC_FILTER) + 1;
5115 		wl_android_set_mac_address_filter(net, command+skip);
5116 	}
5117 	else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0)
5118 		bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len);
5119 #if defined(BCMFW_ROAM_ENABLE)
5120 	else if (strnicmp(command, CMD_SET_ROAMPREF, strlen(CMD_SET_ROAMPREF)) == 0) {
5121 		bytes_written = wl_android_set_roampref(net, command, priv_cmd.total_len);
5122 	}
5123 #endif /* BCMFW_ROAM_ENABLE */
5124 #ifdef WL_CFG80211
5125 	else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)
5126 		bytes_written = wl_android_set_miracast(net, command, priv_cmd.total_len);
5127 #ifdef WL11ULB
5128 	else if (strnicmp(command, CMD_ULB_MODE, strlen(CMD_ULB_MODE)) == 0)
5129 		bytes_written = wl_android_set_ulb_mode(net, command, priv_cmd.total_len);
5130 	else if (strnicmp(command, CMD_ULB_BW, strlen(CMD_ULB_BW)) == 0)
5131 		bytes_written = wl_android_set_ulb_bw(net, command, priv_cmd.total_len);
5132 #endif /* WL11ULB */
5133 	else if (strnicmp(command, CMD_SETIBSSBEACONOUIDATA, strlen(CMD_SETIBSSBEACONOUIDATA)) == 0)
5134 		bytes_written = wl_android_set_ibss_beacon_ouidata(net,
5135 		command, priv_cmd.total_len);
5136 #endif
5137 	else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) {
5138 		int skip = strlen(CMD_KEEP_ALIVE) + 1;
5139 		bytes_written = wl_keep_alive_set(net, command + skip, priv_cmd.total_len - skip);
5140 	}
5141 #ifdef WL_CFG80211
5142 	else if (strnicmp(command, CMD_ROAM_OFFLOAD, strlen(CMD_ROAM_OFFLOAD)) == 0) {
5143 		int enable = *(command + strlen(CMD_ROAM_OFFLOAD) + 1) - '0';
5144 		bytes_written = wl_cfg80211_enable_roam_offload(net, enable);
5145 	}
5146 #endif
5147 #if defined(WL_VIRTUAL_APSTA)
5148 	else if (strnicmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) {
5149 		char *name = (command + strlen(CMD_INTERFACE_CREATE) +1);
5150 		ANDROID_INFO(("Creating %s interface\n", name));
5151 		bytes_written = wl_cfg80211_interface_create(net, name);
5152 	}
5153 	else if (strnicmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) {
5154 		char *name = (command + strlen(CMD_INTERFACE_DELETE) +1);
5155 		ANDROID_INFO(("Deleteing %s interface\n", name));
5156 		bytes_written = wl_cfg80211_interface_delete(net, name);
5157 	}
5158 #endif /* defined (WL_VIRTUAL_APSTA) */
5159 	else if (strnicmp(command, CMD_GET_LINK_STATUS, strlen(CMD_GET_LINK_STATUS)) == 0) {
5160 		bytes_written = wl_android_get_link_status(net, command, priv_cmd.total_len);
5161 	}
5162 #ifdef P2PRESP_WFDIE_SRC
5163 	else if (strnicmp(command, CMD_P2P_SET_WFDIE_RESP,
5164 		strlen(CMD_P2P_SET_WFDIE_RESP)) == 0) {
5165 		int mode = *(command + strlen(CMD_P2P_SET_WFDIE_RESP) + 1) - '0';
5166 		bytes_written = wl_android_set_wfdie_resp(net, mode);
5167 	} else if (strnicmp(command, CMD_P2P_GET_WFDIE_RESP,
5168 		strlen(CMD_P2P_GET_WFDIE_RESP)) == 0) {
5169 		bytes_written = wl_android_get_wfdie_resp(net, command, priv_cmd.total_len);
5170 	}
5171 #endif /* P2PRESP_WFDIE_SRC */
5172 #ifdef WL_CFG80211
5173 	else if (strnicmp(command, CMD_DFS_AP_MOVE, strlen(CMD_DFS_AP_MOVE)) == 0) {
5174 		char *data = (command + strlen(CMD_DFS_AP_MOVE) +1);
5175 		bytes_written = wl_cfg80211_dfs_ap_move(net, data, command, priv_cmd.total_len);
5176 	}
5177 #endif
5178 #ifdef WBTEXT
5179 	else if (strnicmp(command, CMD_WBTEXT_ENABLE, strlen(CMD_WBTEXT_ENABLE)) == 0) {
5180 		bytes_written = wl_android_wbtext(net, command, priv_cmd.total_len);
5181 	}
5182 #ifdef WL_CFG80211
5183 	else if (strnicmp(command, CMD_WBTEXT_PROFILE_CONFIG,
5184 			strlen(CMD_WBTEXT_PROFILE_CONFIG)) == 0) {
5185 		char *data = (command + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
5186 		bytes_written = wl_cfg80211_wbtext_config(net, data, command, priv_cmd.total_len);
5187 	}
5188 	else if (strnicmp(command, CMD_WBTEXT_WEIGHT_CONFIG,
5189 			strlen(CMD_WBTEXT_WEIGHT_CONFIG)) == 0) {
5190 		char *data = (command + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
5191 		bytes_written = wl_cfg80211_wbtext_weight_config(net, data,
5192 				command, priv_cmd.total_len);
5193 	}
5194 	else if (strnicmp(command, CMD_WBTEXT_TABLE_CONFIG,
5195 			strlen(CMD_WBTEXT_TABLE_CONFIG)) == 0) {
5196 		char *data = (command + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
5197 		bytes_written = wl_cfg80211_wbtext_table_config(net, data,
5198 				command, priv_cmd.total_len);
5199 	}
5200 	else if (strnicmp(command, CMD_WBTEXT_DELTA_CONFIG,
5201 			strlen(CMD_WBTEXT_DELTA_CONFIG)) == 0) {
5202 		char *data = (command + strlen(CMD_WBTEXT_DELTA_CONFIG) + 1);
5203 		bytes_written = wl_cfg80211_wbtext_delta_config(net, data,
5204 				command, priv_cmd.total_len);
5205 	}
5206 #endif
5207 	else if (strnicmp(command, CMD_WBTEXT_BTM_TIMER_THRESHOLD,
5208 			strlen(CMD_WBTEXT_BTM_TIMER_THRESHOLD)) == 0) {
5209 		bytes_written = wl_cfg80211_wbtext_btm_timer_threshold(net, command,
5210 			priv_cmd.total_len);
5211 	}
5212 	else if (strnicmp(command, CMD_WBTEXT_BTM_DELTA,
5213 			strlen(CMD_WBTEXT_BTM_DELTA)) == 0) {
5214 		bytes_written = wl_cfg80211_wbtext_btm_delta(net, command,
5215 			priv_cmd.total_len);
5216 	}
5217 #endif /* WBTEXT */
5218 #ifdef SET_RPS_CPUS
5219 	else if (strnicmp(command, CMD_RPSMODE, strlen(CMD_RPSMODE)) == 0) {
5220 		bytes_written = wl_android_set_rps_cpus(net, command, priv_cmd.total_len);
5221 	}
5222 #endif /* SET_RPS_CPUS */
5223 #ifdef WLWFDS
5224 	else if (strnicmp(command, CMD_ADD_WFDS_HASH, strlen(CMD_ADD_WFDS_HASH)) == 0) {
5225 		bytes_written = wl_android_set_wfds_hash(net, command, priv_cmd.total_len, 1);
5226 	}
5227 	else if (strnicmp(command, CMD_DEL_WFDS_HASH, strlen(CMD_DEL_WFDS_HASH)) == 0) {
5228 		bytes_written = wl_android_set_wfds_hash(net, command, priv_cmd.total_len, 0);
5229 	}
5230 #endif /* WLWFDS */
5231 #ifdef BT_WIFI_HANDOVER
5232 	else if (strnicmp(command, CMD_TBOW_TEARDOWN, strlen(CMD_TBOW_TEARDOWN)) == 0) {
5233 	    bytes_written = wl_tbow_teardown(net, command, priv_cmd.total_len);
5234 	}
5235 #endif /* BT_WIFI_HANDOVER */
5236 #ifdef CUSTOMER_HW4_PRIVATE_CMD
5237 #ifdef FCC_PWR_LIMIT_2G
5238 	else if (strnicmp(command, CMD_GET_FCC_PWR_LIMIT_2G,
5239 		strlen(CMD_GET_FCC_PWR_LIMIT_2G)) == 0) {
5240 		bytes_written = wl_android_get_fcc_pwr_limit_2g(net, command, priv_cmd.total_len);
5241 	}
5242 	else if (strnicmp(command, CMD_SET_FCC_PWR_LIMIT_2G,
5243 		strlen(CMD_SET_FCC_PWR_LIMIT_2G)) == 0) {
5244 		bytes_written = wl_android_set_fcc_pwr_limit_2g(net, command, priv_cmd.total_len);
5245 	}
5246 #endif /* FCC_PWR_LIMIT_2G */
5247 	else if (strnicmp(command, CMD_GET_STA_INFO, strlen(CMD_GET_STA_INFO)) == 0) {
5248 		bytes_written = wl_cfg80211_get_sta_info(net, command, priv_cmd.total_len);
5249 	}
5250 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
5251 	else if (strnicmp(command, CMD_MURX_BFE_CAP,
5252 			strlen(CMD_MURX_BFE_CAP)) == 0) {
5253 #if defined(BCM4359_CHIP) && defined(WL_CFG80211)
5254 		uint val = *(command + strlen(CMD_MURX_BFE_CAP) + 1) - '0';
5255 		bytes_written = wl_android_murx_bfe_cap(net, val);
5256 #else
5257 		return BCME_UNSUPPORTED;
5258 #endif /* BCM4359_CHIP */
5259 	}
5260 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
5261 	else if (strnicmp(command, CMD_GET_AP_BASICRATE, strlen(CMD_GET_AP_BASICRATE)) == 0) {
5262 		bytes_written = wl_android_get_ap_basicrate(net, command, priv_cmd.total_len);
5263 	}
5264 	else if (strnicmp(command, CMD_SET_AP_BEACONRATE, strlen(CMD_SET_AP_BEACONRATE)) == 0) {
5265 		bytes_written = wl_android_set_ap_beaconrate(net, command);
5266 	}
5267 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
5268 #ifdef SUPPORT_AP_RADIO_PWRSAVE
5269 	else if (strnicmp(command, CMD_SET_AP_RPS_PARAMS, strlen(CMD_SET_AP_RPS_PARAMS)) == 0) {
5270 		bytes_written = wl_android_set_ap_rps_params(net, command, priv_cmd.total_len);
5271 	}
5272 	else if (strnicmp(command, CMD_SET_AP_RPS, strlen(CMD_SET_AP_RPS)) == 0) {
5273 		bytes_written = wl_android_set_ap_rps(net, command, priv_cmd.total_len);
5274 	}
5275 	else if (strnicmp(command, CMD_GET_AP_RPS, strlen(CMD_GET_AP_RPS)) == 0) {
5276 		bytes_written = wl_android_get_ap_rps(net, command, priv_cmd.total_len);
5277 	}
5278 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
5279 #ifdef SUPPORT_RSSI_LOGGING
5280 	else if (strnicmp(command, CMD_SET_RSSI_LOGGING, strlen(CMD_SET_RSSI_LOGGING)) == 0) {
5281 		bytes_written = wl_android_set_rssi_logging(net, command, priv_cmd.total_len);
5282 	}
5283 	else if (strnicmp(command, CMD_GET_RSSI_LOGGING, strlen(CMD_GET_RSSI_LOGGING)) == 0) {
5284 		bytes_written = wl_android_get_rssi_logging(net, command, priv_cmd.total_len);
5285 	}
5286 	else if (strnicmp(command, CMD_GET_RSSI_PER_ANT, strlen(CMD_GET_RSSI_PER_ANT)) == 0) {
5287 		bytes_written = wl_android_get_rssi_per_ant(net, command, priv_cmd.total_len);
5288 	}
5289 #endif /* SUPPORT_RSSI_LOGGING */
5290 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
5291 	else if (strnicmp(command, CMD_GET_BSS_INFO, strlen(CMD_GET_BSS_INFO)) == 0) {
5292 		bytes_written = wl_cfg80211_get_bss_info(net, command, priv_cmd.total_len);
5293 	}
5294 	else if (strnicmp(command, CMD_GET_ASSOC_REJECT_INFO, strlen(CMD_GET_ASSOC_REJECT_INFO))
5295 			== 0) {
5296 		bytes_written = wl_cfg80211_get_connect_failed_status(net, command,
5297 				priv_cmd.total_len);
5298 	}
5299 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
5300 #if defined(SUPPORT_RANDOM_MAC_SCAN)
5301 	else if (strnicmp(command, ENABLE_RANDOM_MAC, strlen(ENABLE_RANDOM_MAC)) == 0) {
5302 		bytes_written = wl_cfg80211_set_random_mac(net, TRUE);
5303 	} else if (strnicmp(command, DISABLE_RANDOM_MAC, strlen(DISABLE_RANDOM_MAC)) == 0) {
5304 		bytes_written = wl_cfg80211_set_random_mac(net, FALSE);
5305 	}
5306 #endif /* SUPPORT_RANDOM_MAC_SCAN */
5307 #ifdef WL_NATOE
5308 	else if (strnicmp(command, CMD_NATOE, strlen(CMD_NATOE)) == 0) {
5309 		bytes_written = wl_android_process_natoe_cmd(net, command,
5310 				priv_cmd.total_len);
5311 	}
5312 #endif /* WL_NATOE */
5313 #ifdef CONNECTION_STATISTICS
5314 	else if (strnicmp(command, CMD_GET_CONNECTION_STATS,
5315 		strlen(CMD_GET_CONNECTION_STATS)) == 0) {
5316 		bytes_written = wl_android_get_connection_stats(net, command,
5317 			priv_cmd.total_len);
5318 	}
5319 #endif
5320 #ifdef DHD_LOG_DUMP
5321 	else if (strnicmp(command, CMD_NEW_DEBUG_PRINT_DUMP,
5322 		strlen(CMD_NEW_DEBUG_PRINT_DUMP)) == 0) {
5323 		dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(net);
5324 		dhd_schedule_log_dump(dhdp);
5325 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
5326 		dhdp->memdump_type = DUMP_TYPE_BY_SYSDUMP;
5327 		dhd_bus_mem_dump(dhdp);
5328 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
5329 #ifdef DHD_PKT_LOGGING
5330 		dhd_schedule_pktlog_dump(dhdp);
5331 #endif /* DHD_PKT_LOGGING */
5332 	}
5333 #endif /* DHD_LOG_DUMP */
5334 #ifdef SET_PCIE_IRQ_CPU_CORE
5335 	else if (strnicmp(command, CMD_PCIE_IRQ_CORE, strlen(CMD_PCIE_IRQ_CORE)) == 0) {
5336 		int set = *(command + strlen(CMD_PCIE_IRQ_CORE) + 1) - '0';
5337 		wl_android_set_irq_cpucore(net, set);
5338 	}
5339 #endif /* SET_PCIE_IRQ_CPU_CORE */
5340 #if defined(DHD_HANG_SEND_UP_TEST)
5341 	else if (strnicmp(command, CMD_MAKE_HANG, strlen(CMD_MAKE_HANG)) == 0) {
5342 		int skip = strlen(CMD_MAKE_HANG) + 1;
5343 		wl_android_make_hang_with_reason(net, (const char*)command+skip);
5344 	}
5345 #endif /* DHD_HANG_SEND_UP_TEST */
5346 #ifdef SUPPORT_LQCM
5347 	else if (strnicmp(command, CMD_SET_LQCM_ENABLE, strlen(CMD_SET_LQCM_ENABLE)) == 0) {
5348 		int lqcm_enable = *(command + strlen(CMD_SET_LQCM_ENABLE) + 1) - '0';
5349 		bytes_written = wl_android_lqcm_enable(net, lqcm_enable);
5350 	}
5351 	else if (strnicmp(command, CMD_GET_LQCM_REPORT,
5352 		strlen(CMD_GET_LQCM_REPORT)) == 0) {
5353 		bytes_written = wl_android_get_lqcm_report(net, command,
5354 		priv_cmd.total_len);
5355 	}
5356 #endif
5357 	else if (strnicmp(command, CMD_GET_SNR, strlen(CMD_GET_SNR)) == 0) {
5358 		bytes_written = wl_android_get_snr(net, command, priv_cmd.total_len);
5359 	}
5360 #ifdef WLADPS_PRIVATE_CMD
5361 	else if (strnicmp(command, CMD_SET_ADPS, strlen(CMD_SET_ADPS)) == 0) {
5362 		int skip = strlen(CMD_SET_ADPS) + 1;
5363 		bytes_written = wl_android_set_adps_mode(net, (const char*)command+skip);
5364 	}
5365 	else if (strnicmp(command, CMD_GET_ADPS, strlen(CMD_GET_ADPS)) == 0) {
5366 		bytes_written = wl_android_get_adps_mode(net, command, priv_cmd.total_len);
5367 	}
5368 #endif /* WLADPS_PRIVATE_CMD */
5369 #ifdef DHD_PKT_LOGGING
5370 	else if (strnicmp(command, CMD_PKTLOG_FILTER_ENABLE,
5371 		strlen(CMD_PKTLOG_FILTER_ENABLE)) == 0) {
5372 		bytes_written = wl_android_pktlog_filter_enable(net, command, priv_cmd.total_len);
5373 	}
5374 	else if (strnicmp(command, CMD_PKTLOG_FILTER_DISABLE,
5375 		strlen(CMD_PKTLOG_FILTER_DISABLE)) == 0) {
5376 		bytes_written = wl_android_pktlog_filter_disable(net, command, priv_cmd.total_len);
5377 	}
5378 	else if (strnicmp(command, CMD_PKTLOG_FILTER_PATTERN_ENABLE,
5379 		strlen(CMD_PKTLOG_FILTER_PATTERN_ENABLE)) == 0) {
5380 		bytes_written =
5381 			wl_android_pktlog_filter_pattern_enable(net, command, priv_cmd.total_len);
5382 	}
5383 	else if (strnicmp(command, CMD_PKTLOG_FILTER_PATTERN_DISABLE,
5384 		strlen(CMD_PKTLOG_FILTER_PATTERN_DISABLE)) == 0) {
5385 		bytes_written =
5386 			wl_android_pktlog_filter_pattern_disable(net, command, priv_cmd.total_len);
5387 	}
5388 	else if (strnicmp(command, CMD_PKTLOG_FILTER_ADD, strlen(CMD_PKTLOG_FILTER_ADD)) == 0) {
5389 		bytes_written = wl_android_pktlog_filter_add(net, command, priv_cmd.total_len);
5390 	}
5391 	else if (strnicmp(command, CMD_PKTLOG_FILTER_INFO, strlen(CMD_PKTLOG_FILTER_INFO)) == 0) {
5392 		bytes_written = wl_android_pktlog_filter_info(net, command, priv_cmd.total_len);
5393 	}
5394 	else if (strnicmp(command, CMD_PKTLOG_START, strlen(CMD_PKTLOG_START)) == 0) {
5395 		bytes_written = wl_android_pktlog_start(net, command, priv_cmd.total_len);
5396 	}
5397 	else if (strnicmp(command, CMD_PKTLOG_STOP, strlen(CMD_PKTLOG_STOP)) == 0) {
5398 		bytes_written = wl_android_pktlog_stop(net, command, priv_cmd.total_len);
5399 	}
5400 	else if (strnicmp(command, CMD_PKTLOG_FILTER_EXIST, strlen(CMD_PKTLOG_FILTER_EXIST)) == 0) {
5401 		bytes_written = wl_android_pktlog_filter_exist(net, command, priv_cmd.total_len);
5402 	}
5403 #endif /* DHD_PKT_LOGGING */
5404 #if defined(STAT_REPORT)
5405 	else if (strnicmp(command, CMD_STAT_REPORT_GET_START,
5406 		strlen(CMD_STAT_REPORT_GET_START)) == 0) {
5407 		bytes_written = wl_android_stat_report_get_start(net, command, priv_cmd.total_len);
5408 	} else if (strnicmp(command, CMD_STAT_REPORT_GET_NEXT,
5409 		strlen(CMD_STAT_REPORT_GET_NEXT)) == 0) {
5410 		bytes_written = wl_android_stat_report_get_next(net, command, priv_cmd.total_len);
5411 	}
5412 #endif /* STAT_REPORT */
5413 	else if (wl_android_ext_priv_cmd(net, command, priv_cmd.total_len, &bytes_written) == 0) {
5414 	}
5415 	else {
5416 		ANDROID_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
5417 		bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
5418 	}
5419 
5420 	return bytes_written;
5421 }
5422 
wl_android_init(void)5423 int wl_android_init(void)
5424 {
5425 	int ret = 0;
5426 
5427 #if defined(ENABLE_INSMOD_NO_FW_LOAD) || defined(BUS_POWER_RESTORE)
5428 	dhd_download_fw_on_driverload = FALSE;
5429 #endif /* ENABLE_INSMOD_NO_FW_LOAD */
5430 	if (!iface_name[0]) {
5431 		memset(iface_name, 0, IFNAMSIZ);
5432 		bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
5433 	}
5434 
5435 #ifdef WL_RELMCAST
5436 	wl_netlink_init();
5437 #endif /* WL_RELMCAST */
5438 
5439 	return ret;
5440 }
5441 
wl_android_exit(void)5442 int wl_android_exit(void)
5443 {
5444 	int ret = 0;
5445 	struct io_cfg *cur, *q;
5446 
5447 #ifdef WL_RELMCAST
5448 	wl_netlink_deinit();
5449 #endif
5450 
5451 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
5452 #pragma GCC diagnostic push
5453 #pragma GCC diagnostic ignored "-Wcast-qual"
5454 #endif
5455 	list_for_each_entry_safe(cur, q, &miracast_resume_list, list) {
5456 		list_del(&cur->list);
5457 		kfree(cur);
5458 	}
5459 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
5460 #pragma GCC diagnostic pop
5461 #endif
5462 
5463 	return ret;
5464 }
5465 
wl_android_post_init(void)5466 void wl_android_post_init(void)
5467 {
5468 
5469 #ifdef ENABLE_4335BT_WAR
5470 	bcm_bt_unlock(lock_cookie_wifi);
5471 	printk("%s: btlock released\n", __FUNCTION__);
5472 #endif /* ENABLE_4335BT_WAR */
5473 
5474 	if (!dhd_download_fw_on_driverload)
5475 		g_wifi_on = FALSE;
5476 }
5477 
5478 
5479 
wl_fatal_error(void * wl,int rc)5480 int wl_fatal_error(void * wl, int rc)
5481 {
5482 	return FALSE;
5483 }
5484 
5485 #if defined(BT_OVER_SDIO)
5486 void
wl_android_set_wifi_on_flag(bool enable)5487 wl_android_set_wifi_on_flag(bool enable)
5488 {
5489 	g_wifi_on = enable;
5490 }
5491 #endif /* BT_OVER_SDIO */
5492