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