1 /*
2 * Linux cfg80211 driver - Android related functions
3 *
4 * Copyright (C) 2020, Broadcom.
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 *
21 * <<Broadcom-WL-IPTag/Dual:>>
22 */
23
24 #include <linux/module.h>
25 #include <linux/netdevice.h>
26 #include <net/netlink.h>
27 #ifdef CONFIG_COMPAT
28 #include <linux/compat.h>
29 #endif
30
31 #include <wl_android.h>
32 #include <wldev_common.h>
33 #include <wlioctl.h>
34 #include <wlioctl_utils.h>
35 #include <bcmutils.h>
36 #include <bcmstdlib_s.h>
37 #include <linux_osl.h>
38 #include <dhd_dbg.h>
39 #include <dngl_stats.h>
40 #include <dhd.h>
41 #include <dhd_config.h>
42 #include <bcmip.h>
43 #ifdef PNO_SUPPORT
44 #include <dhd_pno.h>
45 #endif
46 #ifdef BCMSDIO
47 #include <bcmsdbus.h>
48 #endif
49 #ifdef WL_CFG80211
50 #include <wl_cfg80211.h>
51 #include <wl_cfgscan.h>
52 #include <wl_cfgvif.h>
53 #endif
54 #ifdef WL_NAN
55 #include <wl_cfgnan.h>
56 #endif /* WL_NAN */
57 #ifdef DHDTCPACK_SUPPRESS
58 #include <dhd_ip.h>
59 #endif /* DHDTCPACK_SUPPRESS */
60 #include <bcmwifi_rspec.h>
61 #include <dhd_linux.h>
62 #include <bcmiov.h>
63 #ifdef DHD_PKT_LOGGING
64 #include <dhd_pktlog.h>
65 #endif /* DHD_PKT_LOGGING */
66 #ifdef WL_BCNRECV
67 #include <wl_cfgvendor.h>
68 #include <brcm_nl80211.h>
69 #endif /* WL_BCNRECV */
70 #ifdef WL_MBO
71 #include <mbo.h>
72 #endif /* WL_MBO */
73 #ifdef RTT_SUPPORT
74 #include <dhd_rtt.h>
75 #endif /* RTT_SUPPORT */
76 #ifdef DHD_EVENT_LOG_FILTER
77 #include <dhd_event_log_filter.h>
78 #endif /* DHD_EVENT_LOG_FILTER */
79 #ifdef WL_ESCAN
80 #include <wl_escan.h>
81 #endif
82
83 #ifdef WL_TWT
84 #include <802.11ah.h>
85 #endif /* WL_TWT */
86
87 #ifdef WL_STATIC_IF
88 #define WL_BSSIDX_MAX 16
89 #endif /* WL_STATIC_IF */
90
91 uint android_msg_level = ANDROID_ERROR_LEVEL | ANDROID_MSG_LEVEL;
92
93 #define ANDROID_ERROR_MSG(x, args...) \
94 do { \
95 if (android_msg_level & ANDROID_ERROR_LEVEL) { \
96 printf("ANDROID-ERROR) " x, ## args); \
97 } \
98 } while (0)
99 #define ANDROID_TRACE_MSG(x, args...) \
100 do { \
101 if (android_msg_level & ANDROID_TRACE_LEVEL) { \
102 printf("ANDROID-TRACE) " x, ## args); \
103 } \
104 } while (0)
105 #define ANDROID_INFO_MSG(x, args...) \
106 do { \
107 if (android_msg_level & ANDROID_INFO_LEVEL) { \
108 printf("ANDROID-INFO) " x, ## args); \
109 } \
110 } while (0)
111 #define ANDROID_ERROR(x) ANDROID_ERROR_MSG x
112 #define ANDROID_TRACE(x) ANDROID_TRACE_MSG x
113 #define ANDROID_INFO(x) ANDROID_INFO_MSG x
114
115 /*
116 * Android private command strings, PLEASE define new private commands here
117 * so they can be updated easily in the future (if needed)
118 */
119
120 #define CMD_START "START"
121 #define CMD_STOP "STOP"
122 #define CMD_SCAN_ACTIVE "SCAN-ACTIVE"
123 #define CMD_SCAN_PASSIVE "SCAN-PASSIVE"
124 #define CMD_RSSI "RSSI"
125 #define CMD_LINKSPEED "LINKSPEED"
126 #define CMD_RXFILTER_START "RXFILTER-START"
127 #define CMD_RXFILTER_STOP "RXFILTER-STOP"
128 #define CMD_RXFILTER_ADD "RXFILTER-ADD"
129 #define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE"
130 #define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START"
131 #define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP"
132 #define CMD_BTCOEXMODE "BTCOEXMODE"
133 #define CMD_SETSUSPENDOPT "SETSUSPENDOPT"
134 #define CMD_SETSUSPENDMODE "SETSUSPENDMODE"
135 #define CMD_SETDTIM_IN_SUSPEND "SET_DTIM_IN_SUSPEND"
136 #define CMD_MAXDTIM_IN_SUSPEND "MAX_DTIM_IN_SUSPEND"
137 #define CMD_DISDTIM_IN_SUSPEND "DISABLE_DTIM_IN_SUSPEND"
138 #define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR"
139 #define CMD_SETFWPATH "SETFWPATH"
140 #define CMD_SETBAND "SETBAND"
141 #define CMD_GETBAND "GETBAND"
142 #define CMD_COUNTRY "COUNTRY"
143 #define CMD_P2P_SET_NOA "P2P_SET_NOA"
144 #if !defined WL_ENABLE_P2P_IF
145 #define CMD_P2P_GET_NOA "P2P_GET_NOA"
146 #endif /* WL_ENABLE_P2P_IF */
147 #define CMD_P2P_SD_OFFLOAD "P2P_SD_"
148 #define CMD_P2P_LISTEN_OFFLOAD "P2P_LO_"
149 #define CMD_P2P_SET_PS "P2P_SET_PS"
150 #define CMD_P2P_ECSA "P2P_ECSA"
151 #define CMD_P2P_INC_BW "P2P_INCREASE_BW"
152 #define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE"
153 #define CMD_SETROAMMODE "SETROAMMODE"
154 #define CMD_SETIBSSBEACONOUIDATA "SETIBSSBEACONOUIDATA"
155 #define CMD_MIRACAST "MIRACAST"
156 #ifdef WL_NAN
157 #define CMD_NAN "NAN_"
158 #endif /* WL_NAN */
159 #define CMD_COUNTRY_DELIMITER "/"
160
161 #if defined (WL_SUPPORT_AUTO_CHANNEL)
162 #define CMD_GET_BEST_CHANNELS "GET_BEST_CHANNELS"
163 #endif /* WL_SUPPORT_AUTO_CHANNEL */
164
165 #define CMD_80211_MODE "MODE" /* 802.11 mode a/b/g/n/ac */
166 #define CMD_CHANSPEC "CHANSPEC"
167 #define CMD_DATARATE "DATARATE"
168 #define CMD_ASSOC_CLIENTS "ASSOCLIST"
169 #define CMD_SET_CSA "SETCSA"
170 #ifdef WL_SUPPORT_AUTO_CHANNEL
171 #define CMD_SET_HAPD_AUTO_CHANNEL "HAPD_AUTO_CHANNEL"
172 #endif /* WL_SUPPORT_AUTO_CHANNEL */
173 #ifdef CUSTOMER_HW4_PRIVATE_CMD
174 #ifdef WL_WTC
175 #define CMD_WTC_CONFIG "SETWTCMODE"
176 #endif /* WL_WTC */
177 #ifdef SUPPORT_HIDDEN_AP
178 /* Hostapd private command */
179 #define CMD_SET_HAPD_MAX_NUM_STA "HAPD_MAX_NUM_STA"
180 #define CMD_SET_HAPD_SSID "HAPD_SSID"
181 #define CMD_SET_HAPD_HIDE_SSID "HAPD_HIDE_SSID"
182 #endif /* SUPPORT_HIDDEN_AP */
183 #ifdef SUPPORT_SOFTAP_SINGL_DISASSOC
184 #define CMD_HAPD_STA_DISASSOC "HAPD_STA_DISASSOC"
185 #endif /* SUPPORT_SOFTAP_SINGL_DISASSOC */
186 #ifdef SUPPORT_SET_LPC
187 #define CMD_HAPD_LPC_ENABLED "HAPD_LPC_ENABLED"
188 #endif /* SUPPORT_SET_LPC */
189 #ifdef SUPPORT_TRIGGER_HANG_EVENT
190 #define CMD_TEST_FORCE_HANG "TEST_FORCE_HANG"
191 #endif /* SUPPORT_TRIGGER_HANG_EVENT */
192 #ifdef SUPPORT_LTECX
193 #define CMD_LTECX_SET "LTECOEX"
194 #endif /* SUPPORT_LTECX */
195 #ifdef TEST_TX_POWER_CONTROL
196 #define CMD_TEST_SET_TX_POWER "TEST_SET_TX_POWER"
197 #define CMD_TEST_GET_TX_POWER "TEST_GET_TX_POWER"
198 #endif /* TEST_TX_POWER_CONTROL */
199 #define CMD_SARLIMIT_TX_CONTROL "SET_TX_POWER_CALLING"
200 #ifdef SUPPORT_SET_TID
201 #define CMD_SET_TID "SET_TID"
202 #define CMD_GET_TID "GET_TID"
203 #endif /* SUPPORT_SET_TID */
204 #define CMD_ROAM_VSIE_ENAB_SET "SET_ROAMING_REASON_ENABLED"
205 #define CMD_ROAM_VSIE_ENAB_GET "GET_ROAMING_REASON_ENABLED"
206 #define CMD_BR_VSIE_ENAB_SET "SET_BR_ERR_REASON_ENABLED"
207 #define CMD_BR_VSIE_ENAB_GET "GET_BR_ERR_REASON_ENABLED"
208 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
209 #define CMD_KEEP_ALIVE "KEEPALIVE"
210
211 #ifdef PNO_SUPPORT
212 #define CMD_PNOSSIDCLR_SET "PNOSSIDCLR"
213 #define CMD_PNOSETUP_SET "PNOSETUP "
214 #define CMD_PNOENABLE_SET "PNOFORCE"
215 #define CMD_PNODEBUG_SET "PNODEBUG"
216 #define CMD_WLS_BATCHING "WLS_BATCHING"
217 #endif /* PNO_SUPPORT */
218
219 #define CMD_HAPD_SET_AX_MODE "HAPD_SET_AX_MODE"
220
221 #define CMD_HAPD_MAC_FILTER "HAPD_MAC_FILTER"
222
223 #if defined(SUPPORT_RANDOM_MAC_SCAN)
224 #define ENABLE_RANDOM_MAC "ENABLE_RANDOM_MAC"
225 #define DISABLE_RANDOM_MAC "DISABLE_RANDOM_MAC"
226 #endif /* SUPPORT_RANDOM_MAC_SCAN */
227 #define CMD_GET_FACTORY_MAC "FACTORY_MAC"
228 #ifdef CUSTOMER_HW4_PRIVATE_CMD
229
230 #ifdef ROAM_API
231 #define CMD_ROAMTRIGGER_SET "SETROAMTRIGGER"
232 #define CMD_ROAMTRIGGER_GET "GETROAMTRIGGER"
233 #define CMD_ROAMDELTA_SET "SETROAMDELTA"
234 #define CMD_ROAMDELTA_GET "GETROAMDELTA"
235 #define CMD_ROAMSCANPERIOD_SET "SETROAMSCANPERIOD"
236 #define CMD_ROAMSCANPERIOD_GET "GETROAMSCANPERIOD"
237 #define CMD_FULLROAMSCANPERIOD_SET "SETFULLROAMSCANPERIOD"
238 #define CMD_FULLROAMSCANPERIOD_GET "GETFULLROAMSCANPERIOD"
239 #define CMD_COUNTRYREV_SET "SETCOUNTRYREV"
240 #define CMD_COUNTRYREV_GET "GETCOUNTRYREV"
241 #endif /* ROAM_API */
242
243 #if defined(SUPPORT_NAN_RANGING_TEST_BW)
244 #define CMD_NAN_RANGING_SET_BW "NAN_RANGING_SET_BW"
245 #endif /* SUPPORT_NAN_RANGING_TEST_BW */
246
247 #ifdef WES_SUPPORT
248 #define CMD_GETSCANCHANNELTIMELEGACY "GETSCANCHANNELTIME_LEGACY"
249 #define CMD_SETSCANCHANNELTIMELEGACY "SETSCANCHANNELTIME_LEGACY"
250 #define CMD_GETSCANUNASSOCTIMELEGACY "GETSCANUNASSOCTIME_LEGACY"
251 #define CMD_SETSCANUNASSOCTIMELEGACY "SETSCANUNASSOCTIME_LEGACY"
252 #define CMD_GETSCANPASSIVETIMELEGACY "GETSCANPASSIVETIME_LEGACY"
253 #define CMD_SETSCANPASSIVETIMELEGACY "SETSCANPASSIVETIME_LEGACY"
254 #define CMD_GETSCANHOMETIMELEGACY "GETSCANHOMETIME_LEGACY"
255 #define CMD_SETSCANHOMETIMELEGACY "SETSCANHOMETIME_LEGACY"
256 #define CMD_GETSCANHOMEAWAYTIMELEGACY "GETSCANHOMEAWAYTIME_LEGACY"
257 #define CMD_SETSCANHOMEAWAYTIMELEGACY "SETSCANHOMEAWAYTIME_LEGACY"
258 #define CMD_GETROAMSCANCHLEGACY "GETROAMSCANCHANNELS_LEGACY"
259 #define CMD_ADDROAMSCANCHLEGACY "ADDROAMSCANCHANNELS_LEGACY"
260 #define CMD_GETROAMSCANFQLEGACY "GETROAMSCANFREQUENCIES_LEGACY"
261 #define CMD_ADDROAMSCANFQLEGACY "ADDROAMSCANFREQUENCIES_LEGACY"
262 #define CMD_GETROAMTRIGLEGACY "GETROAMTRIGGER_LEGACY"
263 #define CMD_SETROAMTRIGLEGACY "SETROAMTRIGGER_LEGACY"
264 #define CMD_REASSOCLEGACY "REASSOC_LEGACY"
265
266 #define CMD_GETROAMSCANCONTROL "GETROAMSCANCONTROL"
267 #define CMD_SETROAMSCANCONTROL "SETROAMSCANCONTROL"
268 #define CMD_GETROAMSCANCHANNELS "GETROAMSCANCHANNELS"
269 #define CMD_SETROAMSCANCHANNELS "SETROAMSCANCHANNELS"
270 #define CMD_ADDROAMSCANCHANNELS "ADDROAMSCANCHANNELS"
271 #define CMD_GETROAMSCANFREQS "GETROAMSCANFREQUENCIES"
272 #define CMD_SETROAMSCANFREQS "SETROAMSCANFREQUENCIES"
273 #define CMD_ADDROAMSCANFREQS "ADDROAMSCANFREQUENCIES"
274 #define CMD_GETSCANCHANNELTIME "GETSCANCHANNELTIME"
275 #define CMD_SETSCANCHANNELTIME "SETSCANCHANNELTIME"
276 #define CMD_GETSCANUNASSOCTIME "GETSCANUNASSOCTIME"
277 #define CMD_SETSCANUNASSOCTIME "SETSCANUNASSOCTIME"
278 #define CMD_GETSCANPASSIVETIME "GETSCANPASSIVETIME"
279 #define CMD_SETSCANPASSIVETIME "SETSCANPASSIVETIME"
280 #define CMD_GETSCANHOMETIME "GETSCANHOMETIME"
281 #define CMD_SETSCANHOMETIME "SETSCANHOMETIME"
282 #define CMD_GETSCANHOMEAWAYTIME "GETSCANHOMEAWAYTIME"
283 #define CMD_SETSCANHOMEAWAYTIME "SETSCANHOMEAWAYTIME"
284 #define CMD_GETSCANNPROBES "GETSCANNPROBES"
285 #define CMD_SETSCANNPROBES "SETSCANNPROBES"
286 #define CMD_GETDFSSCANMODE "GETDFSSCANMODE"
287 #define CMD_SETDFSSCANMODE "SETDFSSCANMODE"
288 #define CMD_SETJOINPREFER "SETJOINPREFER"
289
290 #define CMD_SENDACTIONFRAME "SENDACTIONFRAME"
291 #define CMD_REASSOC "REASSOC"
292
293 #define CMD_GETWESMODE "GETWESMODE"
294 #define CMD_SETWESMODE "SETWESMODE"
295 #define CMD_GETNCHOMODE "GETNCHOMODE"
296 #define CMD_SETNCHOMODE "SETNCHOMODE"
297
298 /* Customer requested to Remove OKCMODE command */
299 #define CMD_GETOKCMODE "GETOKCMODE"
300 #define CMD_SETOKCMODE "SETOKCMODE"
301
302 #define CMD_OKC_SET_PMK "SET_PMK"
303 #define CMD_OKC_ENABLE "OKC_ENABLE"
304
305 typedef struct android_wifi_reassoc_params {
306 unsigned char bssid[18];
307 int channel;
308 } android_wifi_reassoc_params_t;
309
310 #define ANDROID_WIFI_REASSOC_PARAMS_SIZE sizeof(struct android_wifi_reassoc_params)
311
312 #define ANDROID_WIFI_ACTION_FRAME_SIZE 1040
313
314 typedef struct android_wifi_af_params {
315 unsigned char bssid[18];
316 int channel;
317 int dwell_time;
318 int len;
319 unsigned char data[ANDROID_WIFI_ACTION_FRAME_SIZE];
320 } android_wifi_af_params_t;
321
322 #define ANDROID_WIFI_AF_PARAMS_SIZE sizeof(struct android_wifi_af_params)
323 #endif /* WES_SUPPORT */
324 #ifdef SUPPORT_AMPDU_MPDU_CMD
325 #define CMD_AMPDU_MPDU "AMPDU_MPDU"
326 #endif /* SUPPORT_AMPDU_MPDU_CMD */
327
328 #define CMD_CHANGE_RL "CHANGE_RL"
329 #define CMD_RESTORE_RL "RESTORE_RL"
330
331 #define CMD_SET_RMC_ENABLE "SETRMCENABLE"
332 #define CMD_SET_RMC_TXRATE "SETRMCTXRATE"
333 #define CMD_SET_RMC_ACTPERIOD "SETRMCACTIONPERIOD"
334 #define CMD_SET_RMC_IDLEPERIOD "SETRMCIDLEPERIOD"
335 #define CMD_SET_RMC_LEADER "SETRMCLEADER"
336 #define CMD_SET_RMC_EVENT "SETRMCEVENT"
337
338 #define CMD_SET_SCSCAN "SETSINGLEANT"
339 #define CMD_GET_SCSCAN "GETSINGLEANT"
340 #ifdef WLTDLS
341 #define CMD_TDLS_RESET "TDLS_RESET"
342 #endif /* WLTDLS */
343
344 #ifdef CONFIG_SILENT_ROAM
345 #define CMD_SROAM_TURN_ON "SROAMTURNON"
346 #define CMD_SROAM_SET_INFO "SROAMSETINFO"
347 #define CMD_SROAM_GET_INFO "SROAMGETINFO"
348 #endif /* CONFIG_SILENT_ROAM */
349
350 #ifdef CONFIG_ROAM_RSSI_LIMIT
351 #define CMD_ROAM_RSSI_LMT "ROAMRSSILIMIT"
352 #endif /* CONFIG_ROAM_RSSI_LIMIT */
353 #ifdef CONFIG_ROAM_MIN_DELTA
354 #define CMD_ROAM_MIN_DELTA "ROAMMINSCOREDELTA"
355 #endif /* CONFIG_ROAM_MIN_DELTA */
356
357 #define CMD_SET_DISCONNECT_IES "SET_DISCONNECT_IES"
358
359 #ifdef FCC_PWR_LIMIT_2G
360 #define CMD_GET_FCC_PWR_LIMIT_2G "GET_FCC_CHANNEL"
361 #define CMD_SET_FCC_PWR_LIMIT_2G "SET_FCC_CHANNEL"
362 /* CUSTOMER_HW4's value differs from BRCM FW value for enable/disable */
363 #define CUSTOMER_HW4_ENABLE 0
364 #define CUSTOMER_HW4_DISABLE -1
365 #endif /* FCC_PWR_LIMIT_2G */
366 #define CUSTOMER_HW4_EN_CONVERT(i) (i += 1)
367 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
368
369 #ifdef WLFBT
370 #define CMD_GET_FTKEY "GET_FTKEY"
371 #endif
372
373 #ifdef WLAIBSS
374 #define CMD_SETIBSSTXFAILEVENT "SETIBSSTXFAILEVENT"
375 #define CMD_GET_IBSS_PEER_INFO "GETIBSSPEERINFO"
376 #define CMD_GET_IBSS_PEER_INFO_ALL "GETIBSSPEERINFOALL"
377 #define CMD_SETIBSSROUTETABLE "SETIBSSROUTETABLE"
378 #define CMD_SETIBSSAMPDU "SETIBSSAMPDU"
379 #define CMD_SETIBSSANTENNAMODE "SETIBSSANTENNAMODE"
380 #endif /* WLAIBSS */
381
382 #define CMD_ROAM_OFFLOAD "SETROAMOFFLOAD"
383 #define CMD_INTERFACE_CREATE "INTERFACE_CREATE"
384 #define CMD_INTERFACE_DELETE "INTERFACE_DELETE"
385 #define CMD_GET_LINK_STATUS "GETLINKSTATUS"
386
387 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
388 #define CMD_GET_BSS_INFO "GETBSSINFO"
389 #define CMD_GET_ASSOC_REJECT_INFO "GETASSOCREJECTINFO"
390 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
391 #define CMD_GET_STA_INFO "GETSTAINFO"
392
393 /* related with CMD_GET_LINK_STATUS */
394 #define WL_ANDROID_LINK_VHT 0x01
395 #define WL_ANDROID_LINK_MIMO 0x02
396 #define WL_ANDROID_LINK_AP_VHT_SUPPORT 0x04
397 #define WL_ANDROID_LINK_AP_MIMO_SUPPORT 0x08
398
399 #ifdef P2PRESP_WFDIE_SRC
400 #define CMD_P2P_SET_WFDIE_RESP "P2P_SET_WFDIE_RESP"
401 #define CMD_P2P_GET_WFDIE_RESP "P2P_GET_WFDIE_RESP"
402 #endif /* P2PRESP_WFDIE_SRC */
403
404 #define CMD_DFS_AP_MOVE "DFS_AP_MOVE"
405 #define CMD_WBTEXT_ENABLE "WBTEXT_ENABLE"
406 #define CMD_WBTEXT_PROFILE_CONFIG "WBTEXT_PROFILE_CONFIG"
407 #define CMD_WBTEXT_WEIGHT_CONFIG "WBTEXT_WEIGHT_CONFIG"
408 #define CMD_WBTEXT_TABLE_CONFIG "WBTEXT_TABLE_CONFIG"
409 #define CMD_WBTEXT_DELTA_CONFIG "WBTEXT_DELTA_CONFIG"
410 #define CMD_WBTEXT_BTM_TIMER_THRESHOLD "WBTEXT_BTM_TIMER_THRESHOLD"
411 #define CMD_WBTEXT_BTM_DELTA "WBTEXT_BTM_DELTA"
412 #define CMD_WBTEXT_ESTM_ENABLE "WBTEXT_ESTM_ENABLE"
413
414 #ifdef WBTEXT
415 #define CMD_WBTEXT_PROFILE_CONFIG "WBTEXT_PROFILE_CONFIG"
416 #define CMD_WBTEXT_WEIGHT_CONFIG "WBTEXT_WEIGHT_CONFIG"
417 #define CMD_WBTEXT_TABLE_CONFIG "WBTEXT_TABLE_CONFIG"
418 #define CMD_WBTEXT_DELTA_CONFIG "WBTEXT_DELTA_CONFIG"
419 #define DEFAULT_WBTEXT_PROFILE_A_V2 "a -70 -75 70 10 -75 -128 0 10"
420 #define DEFAULT_WBTEXT_PROFILE_B_V2 "b -60 -75 70 10 -75 -128 0 10"
421 #define DEFAULT_WBTEXT_PROFILE_A_V3 "a -70 -75 70 10 -75 -128 0 10"
422 #define DEFAULT_WBTEXT_PROFILE_B_V3 "b -60 -75 70 10 -75 -128 0 10"
423 #define DEFAULT_WBTEXT_WEIGHT_RSSI_A "RSSI a 65"
424 #define DEFAULT_WBTEXT_WEIGHT_RSSI_B "RSSI b 65"
425 #define DEFAULT_WBTEXT_WEIGHT_CU_A "CU a 35"
426 #define DEFAULT_WBTEXT_WEIGHT_CU_B "CU b 35"
427 #define DEFAULT_WBTEXT_WEIGHT_ESTM_DL_A "ESTM_DL a 70"
428 #define DEFAULT_WBTEXT_WEIGHT_ESTM_DL_B "ESTM_DL b 70"
429 #define DEFAULT_WBTEXT_CU_RSSI_TRIG_A -70
430 #define DEFAULT_WBTEXT_CU_RSSI_TRIG_B -60
431 #ifdef WBTEXT_SCORE_V2
432 #define DEFAULT_WBTEXT_TABLE_RSSI_A "RSSI a 0 55 100 55 60 90 \
433 60 70 60 70 80 20 80 90 0 90 128 0"
434 #define DEFAULT_WBTEXT_TABLE_RSSI_B "RSSI b 0 55 100 55 60 90 \
435 60 70 60 70 80 20 80 90 0 90 128 0"
436 #define DEFAULT_WBTEXT_TABLE_CU_A "CU a 0 30 100 30 80 20 \
437 80 100 20"
438 #define DEFAULT_WBTEXT_TABLE_CU_B "CU b 0 10 100 10 70 20 \
439 70 100 20"
440 #else
441 #define DEFAULT_WBTEXT_TABLE_RSSI_A "RSSI a 0 55 100 55 60 90 \
442 60 65 70 65 70 50 70 128 20"
443 #define DEFAULT_WBTEXT_TABLE_RSSI_B "RSSI b 0 55 100 55 60 90 \
444 60 65 70 65 70 50 70 128 20"
445 #define DEFAULT_WBTEXT_TABLE_CU_A "CU a 0 30 100 30 50 90 \
446 50 60 70 60 80 50 80 100 20"
447 #define DEFAULT_WBTEXT_TABLE_CU_B "CU b 0 10 100 10 25 90 \
448 25 40 70 40 70 50 70 100 20"
449 #endif /* WBTEXT_SCORE_V2 */
450 #endif /* WBTEXT */
451
452 #define BUFSZ 8
453 #define BUFSZN BUFSZ + 1
454
455 #define _S(x) #x
456 #define S(x) _S(x)
457
458 #define MAXBANDS 2 /**< Maximum #of bands */
459 #define BAND_2G_INDEX 1
460 #define BAND_5G_INDEX 0
461
462 typedef union {
463 wl_roam_prof_band_v1_t v1;
464 wl_roam_prof_band_v2_t v2;
465 wl_roam_prof_band_v3_t v3;
466 wl_roam_prof_band_v4_t v4;
467 } wl_roamprof_band_t;
468
469 #ifdef WLWFDS
470 #define CMD_ADD_WFDS_HASH "ADD_WFDS_HASH"
471 #define CMD_DEL_WFDS_HASH "DEL_WFDS_HASH"
472 #endif /* WLWFDS */
473
474 #ifdef BT_WIFI_HANDOVER
475 #define CMD_TBOW_TEARDOWN "TBOW_TEARDOWN"
476 #endif /* BT_WIFI_HANDOVER */
477
478 #define CMD_MURX_BFE_CAP "MURX_BFE_CAP"
479
480 #ifdef SUPPORT_RSSI_SUM_REPORT
481 #define CMD_SET_RSSI_LOGGING "SET_RSSI_LOGGING"
482 #define CMD_GET_RSSI_LOGGING "GET_RSSI_LOGGING"
483 #define CMD_GET_RSSI_PER_ANT "GET_RSSI_PER_ANT"
484 #endif /* SUPPORT_RSSI_SUM_REPORT */
485
486 #define CMD_GET_SNR "GET_SNR"
487
488 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
489 #define CMD_SET_AP_BEACONRATE "SET_AP_BEACONRATE"
490 #define CMD_GET_AP_BASICRATE "GET_AP_BASICRATE"
491 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
492
493 #ifdef SUPPORT_AP_RADIO_PWRSAVE
494 #define CMD_SET_AP_RPS "SET_AP_RPS"
495 #define CMD_GET_AP_RPS "GET_AP_RPS"
496 #define CMD_SET_AP_RPS_PARAMS "SET_AP_RPS_PARAMS"
497 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
498
499 #ifdef SUPPORT_AP_SUSPEND
500 #define CMD_SET_AP_SUSPEND "SET_AP_SUSPEND"
501 #endif /* SUPPORT_AP_SUSPEND */
502
503 #ifdef SUPPORT_AP_BWCTRL
504 #define CMD_SET_AP_BW "SET_AP_BW"
505 #define CMD_GET_AP_BW "GET_AP_BW"
506 #endif /* SUPPORT_AP_BWCTRL */
507
508 /* miracast related definition */
509 #define MIRACAST_MODE_OFF 0
510 #define MIRACAST_MODE_SOURCE 1
511 #define MIRACAST_MODE_SINK 2
512
513 #ifdef CONNECTION_STATISTICS
514 #define CMD_GET_CONNECTION_STATS "GET_CONNECTION_STATS"
515
516 struct connection_stats {
517 u32 txframe;
518 u32 txbyte;
519 u32 txerror;
520 u32 rxframe;
521 u32 rxbyte;
522 u32 txfail;
523 u32 txretry;
524 u32 txretrie;
525 u32 txrts;
526 u32 txnocts;
527 u32 txexptime;
528 u32 txrate;
529 u8 chan_idle;
530 };
531 #endif /* CONNECTION_STATISTICS */
532
533 #ifdef SUPPORT_LQCM
534 #define CMD_SET_LQCM_ENABLE "SET_LQCM_ENABLE"
535 #define CMD_GET_LQCM_REPORT "GET_LQCM_REPORT"
536 #endif
537
538 static LIST_HEAD(miracast_resume_list);
539 #ifdef WL_CFG80211
540 static u8 miracast_cur_mode;
541 #endif /* WL_CFG80211 */
542
543 #ifdef DHD_LOG_DUMP
544 #define CMD_NEW_DEBUG_PRINT_DUMP "DEBUG_DUMP"
545 #define SUBCMD_UNWANTED "UNWANTED"
546 #define SUBCMD_DISCONNECTED "DISCONNECTED"
547 void dhd_log_dump_trigger(dhd_pub_t *dhdp, int subcmd);
548 #endif /* DHD_LOG_DUMP */
549
550 #ifdef DHD_STATUS_LOGGING
551 #define CMD_DUMP_STATUS_LOG "DUMP_STAT_LOG"
552 #define CMD_QUERY_STATUS_LOG "QUERY_STAT_LOG"
553 #endif /* DHD_STATUS_LOGGING */
554
555 #ifdef DHD_HANG_SEND_UP_TEST
556 #define CMD_MAKE_HANG "MAKE_HANG"
557 #endif /* CMD_DHD_HANG_SEND_UP_TEST */
558 #ifdef DHD_DEBUG_UART
559 extern bool dhd_debug_uart_is_running(struct net_device *dev);
560 #endif /* DHD_DEBUG_UART */
561
562 #ifdef RTT_GEOFENCE_INTERVAL
563 #if defined (RTT_SUPPORT) && defined(WL_NAN)
564 #define CMD_GEOFENCE_INTERVAL "GEOFENCE_INT"
565 #endif /* RTT_SUPPORT && WL_NAN */
566 #endif /* RTT_GEOFENCE_INTERVAL */
567
568 struct io_cfg {
569 s8 *iovar;
570 s32 param;
571 u32 ioctl;
572 void *arg;
573 u32 len;
574 struct list_head list;
575 };
576
577 #if defined(BCMFW_ROAM_ENABLE)
578 #define CMD_SET_ROAMPREF "SET_ROAMPREF"
579
580 #define MAX_NUM_SUITES 10
581 #define WIDTH_AKM_SUITE 8
582 #define JOIN_PREF_RSSI_LEN 0x02
583 #define JOIN_PREF_RSSI_SIZE 4 /* RSSI pref header size in bytes */
584 #define JOIN_PREF_WPA_HDR_SIZE 4 /* WPA pref header size in bytes */
585 #define JOIN_PREF_WPA_TUPLE_SIZE 12 /* Tuple size in bytes */
586 #define JOIN_PREF_MAX_WPA_TUPLES 16
587 #define MAX_BUF_SIZE (JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE + \
588 (JOIN_PREF_WPA_TUPLE_SIZE * JOIN_PREF_MAX_WPA_TUPLES))
589 #endif /* BCMFW_ROAM_ENABLE */
590
591 #if defined(CONFIG_TIZEN)
592 /*
593 * adding these private commands corresponding to atd-server's implementation
594 * __atd_control_pm_state()
595 */
596 #define CMD_POWERSAVEMODE_SET "SETPOWERSAVEMODE"
597 #define CMD_POWERSAVEMODE_GET "GETPOWERSAVEMODE"
598 #endif /* CONFIG_TIZEN */
599
600 #define CMD_DEBUG_VERBOSE "DEBUG_VERBOSE"
601 #ifdef WL_NATOE
602
603 #define CMD_NATOE "NATOE"
604
605 #define NATOE_MAX_PORT_NUM 65535
606
607 /* natoe command info structure */
608 typedef struct wl_natoe_cmd_info {
609 uint8 *command; /* pointer to the actual command */
610 uint16 tot_len; /* total length of the command */
611 uint16 bytes_written; /* Bytes written for get response */
612 } wl_natoe_cmd_info_t;
613
614 typedef struct wl_natoe_sub_cmd wl_natoe_sub_cmd_t;
615 typedef int (natoe_cmd_handler_t)(struct net_device *dev,
616 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
617
618 struct wl_natoe_sub_cmd {
619 char *name;
620 uint8 version; /* cmd version */
621 uint16 id; /* id for the dongle f/w switch/case */
622 uint16 type; /* base type of argument */
623 natoe_cmd_handler_t *handler; /* cmd handler */
624 };
625
626 #define WL_ANDROID_NATOE_FUNC(suffix) wl_android_natoe_subcmd_ ##suffix
627 static int wl_android_process_natoe_cmd(struct net_device *dev,
628 char *command, int total_len);
629 static int wl_android_natoe_subcmd_enable(struct net_device *dev,
630 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
631 static int wl_android_natoe_subcmd_config_ips(struct net_device *dev,
632 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
633 static int wl_android_natoe_subcmd_config_ports(struct net_device *dev,
634 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
635 static int wl_android_natoe_subcmd_dbg_stats(struct net_device *dev,
636 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
637 static int wl_android_natoe_subcmd_tbl_cnt(struct net_device *dev,
638 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info);
639
640 static const wl_natoe_sub_cmd_t natoe_cmd_list[] = {
641 /* wl natoe enable [0/1] or new: "wl natoe [0/1]" */
642 {"enable", 0x01, WL_NATOE_CMD_ENABLE,
643 IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(enable)
644 },
645 {"config_ips", 0x01, WL_NATOE_CMD_CONFIG_IPS,
646 IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(config_ips)
647 },
648 {"config_ports", 0x01, WL_NATOE_CMD_CONFIG_PORTS,
649 IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(config_ports)
650 },
651 {"stats", 0x01, WL_NATOE_CMD_DBG_STATS,
652 IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(dbg_stats)
653 },
654 {"tbl_cnt", 0x01, WL_NATOE_CMD_TBL_CNT,
655 IOVT_BUFFER, WL_ANDROID_NATOE_FUNC(tbl_cnt)
656 },
657 {NULL, 0, 0, 0, NULL}
658 };
659
660 #endif /* WL_NATOE */
661
662 #ifdef SET_PCIE_IRQ_CPU_CORE
663 #define CMD_PCIE_IRQ_CORE "PCIE_IRQ_CORE"
664 #endif /* SET_PCIE_IRQ_CPU_CORE */
665
666 #ifdef WLADPS_PRIVATE_CMD
667 #define CMD_SET_ADPS "SET_ADPS"
668 #define CMD_GET_ADPS "GET_ADPS"
669 #ifdef WLADPS_ENERGY_GAIN
670 #define CMD_GET_GAIN_ADPS "GET_GAIN_ADPS"
671 #define CMD_RESET_GAIN_ADPS "RESET_GAIN_ADPS"
672 #ifndef ADPS_GAIN_2G_PM0_IDLE
673 #define ADPS_GAIN_2G_PM0_IDLE 0
674 #endif
675 #ifndef ADPS_GAIN_5G_PM0_IDLE
676 #define ADPS_GAIN_5G_PM0_IDLE 0
677 #endif
678 #ifndef ADPS_GAIN_2G_TX_PSPOLL
679 #define ADPS_GAIN_2G_TX_PSPOLL 0
680 #endif
681 #ifndef ADPS_GAIN_5G_TX_PSPOLL
682 #define ADPS_GAIN_5G_TX_PSPOLL 0
683 #endif
684 #endif /* WLADPS_ENERGY_GAIN */
685 #endif /* WLADPS_PRIVATE_CMD */
686
687 #ifdef DHD_PKT_LOGGING
688 #define CMD_PKTLOG_FILTER_ENABLE "PKTLOG_FILTER_ENABLE"
689 #define CMD_PKTLOG_FILTER_DISABLE "PKTLOG_FILTER_DISABLE"
690 #define CMD_PKTLOG_FILTER_PATTERN_ENABLE "PKTLOG_FILTER_PATTERN_ENABLE"
691 #define CMD_PKTLOG_FILTER_PATTERN_DISABLE "PKTLOG_FILTER_PATTERN_DISABLE"
692 #define CMD_PKTLOG_FILTER_ADD "PKTLOG_FILTER_ADD"
693 #define CMD_PKTLOG_FILTER_DEL "PKTLOG_FILTER_DEL"
694 #define CMD_PKTLOG_FILTER_INFO "PKTLOG_FILTER_INFO"
695 #define CMD_PKTLOG_START "PKTLOG_START"
696 #define CMD_PKTLOG_STOP "PKTLOG_STOP"
697 #define CMD_PKTLOG_FILTER_EXIST "PKTLOG_FILTER_EXIST"
698 #define CMD_PKTLOG_MINMIZE_ENABLE "PKTLOG_MINMIZE_ENABLE"
699 #define CMD_PKTLOG_MINMIZE_DISABLE "PKTLOG_MINMIZE_DISABLE"
700 #define CMD_PKTLOG_CHANGE_SIZE "PKTLOG_CHANGE_SIZE"
701 #define CMD_PKTLOG_DEBUG_DUMP "PKTLOG_DEBUG_DUMP"
702 #endif /* DHD_PKT_LOGGING */
703
704 #ifdef DHD_EVENT_LOG_FILTER
705 #define CMD_EWP_FILTER "EWP_FILTER"
706 #endif /* DHD_EVENT_LOG_FILTER */
707
708 #ifdef WL_BCNRECV
709 #define CMD_BEACON_RECV "BEACON_RECV"
710 #endif /* WL_BCNRECV */
711 #ifdef WL_CAC_TS
712 #define CMD_CAC_TSPEC "CAC_TSPEC"
713 #endif /* WL_CAC_TS */
714 #ifdef WL_GET_CU
715 #define CMD_GET_CHAN_UTIL "GET_CU"
716 #endif /* WL_GET_CU */
717
718 #ifdef SUPPORT_SOFTAP_ELNA_BYPASS
719 #define CMD_SET_SOFTAP_ELNA_BYPASS "SET_SOFTAP_ELNA_BYPASS"
720 #define CMD_GET_SOFTAP_ELNA_BYPASS "GET_SOFTAP_ELNA_BYPASS"
721 #endif /* SUPPORT_SOFTAP_ELNA_BYPASS */
722
723 #ifdef WL_NAN
724 #define CMD_GET_NAN_STATUS "GET_NAN_STATUS"
725 #endif /* WL_NAN */
726
727 #ifdef WL_TWT
728 #define CMD_TWT_SETUP "TWT_SETUP"
729 #define CMD_TWT_TEARDOWN "TWT_TEARDOWN"
730 #define CMD_TWT_INFO "TWT_INFO_FRM"
731 #define CMD_TWT_STATUS_QUERY "TWT_STATUS"
732 #define CMD_TWT_CAPABILITY "TWT_CAP"
733 #endif /* WL_TWT */
734
735 /* drv command info structure */
736 typedef struct wl_drv_cmd_info {
737 uint8 *command; /* pointer to the actual command */
738 uint16 tot_len; /* total length of the command */
739 uint16 bytes_written; /* Bytes written for get response */
740 } wl_drv_cmd_info_t;
741
742 typedef struct wl_drv_sub_cmd wl_drv_sub_cmd_t;
743 typedef int (drv_cmd_handler_t)(struct net_device *dev,
744 const wl_drv_sub_cmd_t *cmd, char *command, wl_drv_cmd_info_t *cmd_info);
745
746 struct wl_drv_sub_cmd {
747 char *name;
748 uint8 version; /* cmd version */
749 uint16 id; /* id for the dongle f/w switch/case */
750 uint16 type; /* base type of argument */
751 drv_cmd_handler_t *handler; /* cmd handler */
752 };
753
754 #ifdef WL_MBO
755
756 #define CMD_MBO "MBO"
757 enum {
758 WL_MBO_CMD_NON_CHAN_PREF = 1,
759 WL_MBO_CMD_CELL_DATA_CAP = 2
760 };
761 #define WL_ANDROID_MBO_FUNC(suffix) wl_android_mbo_subcmd_ ##suffix
762
763 static int wl_android_process_mbo_cmd(struct net_device *dev,
764 char *command, int total_len);
765 static int wl_android_mbo_subcmd_cell_data_cap(struct net_device *dev,
766 const wl_drv_sub_cmd_t *cmd, char *command, wl_drv_cmd_info_t *cmd_info);
767 static int wl_android_mbo_subcmd_non_pref_chan(struct net_device *dev,
768 const wl_drv_sub_cmd_t *cmd, char *command, wl_drv_cmd_info_t *cmd_info);
769
770 static const wl_drv_sub_cmd_t mbo_cmd_list[] = {
771 {"non_pref_chan", 0x01, WL_MBO_CMD_NON_CHAN_PREF,
772 IOVT_BUFFER, WL_ANDROID_MBO_FUNC(non_pref_chan)
773 },
774 {"cell_data_cap", 0x01, WL_MBO_CMD_CELL_DATA_CAP,
775 IOVT_BUFFER, WL_ANDROID_MBO_FUNC(cell_data_cap)
776 },
777 {NULL, 0, 0, 0, NULL}
778 };
779
780 #endif /* WL_MBO */
781
782 #ifdef WL_GENL
783 static s32 wl_genl_handle_msg(struct sk_buff *skb, struct genl_info *info);
784 static int wl_genl_init(void);
785 static int wl_genl_deinit(void);
786
787 extern struct net init_net;
788 /* attribute policy: defines which attribute has which type (e.g int, char * etc)
789 * possible values defined in net/netlink.h
790 */
791 static struct nla_policy wl_genl_policy[BCM_GENL_ATTR_MAX + 1] = {
792 [BCM_GENL_ATTR_STRING] = { .type = NLA_NUL_STRING },
793 [BCM_GENL_ATTR_MSG] = { .type = NLA_BINARY },
794 };
795
796 #define WL_GENL_VER 1
797 /* family definition */
798 static struct genl_family wl_genl_family = {
799 .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */
800 .hdrsize = 0,
801 .name = "bcm-genl", /* Netlink I/F for Android */
802 .version = WL_GENL_VER, /* Version Number */
803 .maxattr = BCM_GENL_ATTR_MAX,
804 };
805
806 /* commands: mapping between the command enumeration and the actual function */
807 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
808 struct genl_ops wl_genl_ops[] = {
809 {
810 .cmd = BCM_GENL_CMD_MSG,
811 .flags = 0,
812 .policy = wl_genl_policy,
813 .doit = wl_genl_handle_msg,
814 .dumpit = NULL,
815 },
816 };
817 #else
818 struct genl_ops wl_genl_ops = {
819 .cmd = BCM_GENL_CMD_MSG,
820 .flags = 0,
821 .policy = wl_genl_policy,
822 .doit = wl_genl_handle_msg,
823 .dumpit = NULL,
824
825 };
826 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */
827
828 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
829 static struct genl_multicast_group wl_genl_mcast[] = {
830 { .name = "bcm-genl-mcast", },
831 };
832 #else
833 static struct genl_multicast_group wl_genl_mcast = {
834 .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */
835 .name = "bcm-genl-mcast",
836 };
837 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */
838 #endif /* WL_GENL */
839
840 #ifdef SUPPORT_LQCM
841 #define LQCM_ENAB_MASK 0x000000FF /* LQCM enable flag mask */
842 #define LQCM_TX_INDEX_MASK 0x0000FF00 /* LQCM tx index mask */
843 #define LQCM_RX_INDEX_MASK 0x00FF0000 /* LQCM rx index mask */
844
845 #define LQCM_TX_INDEX_SHIFT 8 /* LQCM tx index shift */
846 #define LQCM_RX_INDEX_SHIFT 16 /* LQCM rx index shift */
847 #endif /* SUPPORT_LQCM */
848
849 #ifdef DHD_SEND_HANG_PRIVCMD_ERRORS
850 #define NUMBER_SEQUENTIAL_PRIVCMD_ERRORS 7
851 static int priv_cmd_errors = 0;
852 #endif /* DHD_SEND_HANG_PRIVCMD_ERRORS */
853
854 #ifdef WL_P2P_6G
855 #define CMD_ENABLE_6G_P2P "ENABLE_6G_P2P"
856 #endif /* WL_P2P_6G */
857
858 /**
859 * Extern function declarations (TODO: move them to dhd_linux.h)
860 */
861 int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
862 int dhd_dev_init_ioctl(struct net_device *dev);
863 #ifdef WL_CFG80211
864 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
865 int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command);
866 #ifdef WES_SUPPORT
867 int wl_cfg80211_set_wes_mode(struct net_device *dev, int mode);
868 int wl_cfg80211_get_wes_mode(struct net_device *dev);
869 int wl_cfg80211_set_ncho_mode(struct net_device *dev, int mode);
870 int wl_cfg80211_get_ncho_mode(struct net_device *dev);
871 #endif /* WES_SUPPORT */
872 #else
wl_cfg80211_get_p2p_dev_addr(struct net_device * net,struct ether_addr * p2pdev_addr)873 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
874 { return 0; }
wl_cfg80211_set_p2p_noa(struct net_device * net,char * buf,int len)875 int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
876 { return 0; }
wl_cfg80211_get_p2p_noa(struct net_device * net,char * buf,int len)877 int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
878 { return 0; }
wl_cfg80211_set_p2p_ps(struct net_device * net,char * buf,int len)879 int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
880 { return 0; }
wl_cfg80211_set_p2p_ecsa(struct net_device * net,char * buf,int len)881 int wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
882 { return 0; }
wl_cfg80211_increase_p2p_bw(struct net_device * net,char * buf,int len)883 int wl_cfg80211_increase_p2p_bw(struct net_device *net, char* buf, int len)
884 { return 0; }
885 #endif /* WL_CFG80211 */
886 #if defined(WL_WTC) && defined(CUSTOMER_HW4_PRIVATE_CMD)
887 static int wl_android_wtc_config(struct net_device *dev, char *command, int total_len);
888 #endif /* WL_WTC && CUSTOMER_HW4_PRIVATE_CMD */
889 #ifdef WBTEXT
890 static int wl_android_wbtext(struct net_device *dev, char *command, int total_len);
891 static int wl_cfg80211_wbtext_btm_timer_threshold(struct net_device *dev,
892 char *command, int total_len);
893 static int wl_cfg80211_wbtext_btm_delta(struct net_device *dev,
894 char *command, int total_len);
895 static int wl_cfg80211_wbtext_estm_enable(struct net_device *dev,
896 char *command, int total_len);
897 static int wlc_wbtext_get_roam_prof(struct net_device *ndev, wl_roamprof_band_t *rp,
898 uint8 band, uint8 *roam_prof_ver, uint8 *roam_prof_size);
899 static int wl_android_wbtext_enable(struct net_device *dev, int mode);
900 #endif /* WBTEXT */
901 #ifdef WES_SUPPORT
902 /* wl_roam.c */
903 extern int get_roamscan_mode(struct net_device *dev, int *mode);
904 extern int set_roamscan_mode(struct net_device *dev, int mode);
905 extern int get_roamscan_chanspec_list(struct net_device *dev, chanspec_t *chanspecs);
906 extern int set_roamscan_chanspec_list(struct net_device *dev, uint n, chanspec_t *chanspecs);
907 extern int add_roamscan_chanspec_list(struct net_device *dev, uint n, chanspec_t *chanspecs);
908
909 static char* legacy_cmdlist[] =
910 {
911 CMD_GETROAMSCANCHLEGACY, CMD_ADDROAMSCANCHLEGACY,
912 CMD_GETROAMSCANFQLEGACY, CMD_ADDROAMSCANFQLEGACY,
913 CMD_GETROAMTRIGLEGACY, CMD_SETROAMTRIGLEGACY,
914 CMD_REASSOCLEGACY,
915 CMD_GETSCANCHANNELTIMELEGACY, CMD_SETSCANCHANNELTIMELEGACY,
916 CMD_GETSCANUNASSOCTIMELEGACY, CMD_SETSCANUNASSOCTIMELEGACY,
917 CMD_GETSCANPASSIVETIMELEGACY, CMD_SETSCANPASSIVETIMELEGACY,
918 CMD_GETSCANHOMETIMELEGACY, CMD_SETSCANHOMETIMELEGACY,
919 CMD_GETSCANHOMEAWAYTIMELEGACY, CMD_SETSCANHOMEAWAYTIMELEGACY,
920 "\0"
921 };
922
923 static char* ncho_cmdlist[] =
924 {
925 CMD_ROAMTRIGGER_GET, CMD_ROAMTRIGGER_SET,
926 CMD_ROAMDELTA_GET, CMD_ROAMDELTA_SET,
927 CMD_ROAMSCANPERIOD_GET, CMD_ROAMSCANPERIOD_SET,
928 CMD_FULLROAMSCANPERIOD_GET, CMD_FULLROAMSCANPERIOD_SET,
929 CMD_COUNTRYREV_GET, CMD_COUNTRYREV_SET,
930 CMD_GETROAMSCANCONTROL, CMD_SETROAMSCANCONTROL,
931 CMD_GETROAMSCANCHANNELS, CMD_SETROAMSCANCHANNELS, CMD_ADDROAMSCANCHANNELS,
932 CMD_GETROAMSCANFREQS, CMD_SETROAMSCANFREQS, CMD_ADDROAMSCANFREQS,
933 CMD_SENDACTIONFRAME,
934 CMD_REASSOC,
935 CMD_GETSCANCHANNELTIME, CMD_SETSCANCHANNELTIME,
936 CMD_GETSCANUNASSOCTIME, CMD_SETSCANUNASSOCTIME,
937 CMD_GETSCANPASSIVETIME, CMD_SETSCANPASSIVETIME,
938 CMD_GETSCANHOMETIME, CMD_SETSCANHOMETIME,
939 CMD_GETSCANHOMEAWAYTIME, CMD_SETSCANHOMEAWAYTIME,
940 CMD_GETSCANNPROBES, CMD_SETSCANNPROBES,
941 CMD_GETDFSSCANMODE, CMD_SETDFSSCANMODE,
942 CMD_SETJOINPREFER,
943 CMD_GETWESMODE, CMD_SETWESMODE,
944 "\0"
945 };
946 #endif /* WES_SUPPORT */
947 #ifdef ROAM_CHANNEL_CACHE
948 extern void wl_update_roamscan_cache_by_band(struct net_device *dev, int band);
949 #endif /* ROAM_CHANNEL_CACHE */
950
951 int wl_android_priority_roam_enable(struct net_device *dev, int mode);
952 #ifdef CONFIG_SILENT_ROAM
953 int wl_android_sroam_turn_on(struct net_device *dev, int mode);
954 #endif /* CONFIG_SILENT_ROAM */
955 int wl_android_rcroam_turn_on(struct net_device *dev, int mode);
956
957 #ifdef ENABLE_4335BT_WAR
958 extern int bcm_bt_lock(int cookie);
959 extern void bcm_bt_unlock(int cookie);
960 static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24; /* cookie is "WiFi" */
961 #endif /* ENABLE_4335BT_WAR */
962
963 extern bool ap_fw_loaded;
964 extern char iface_name[IFNAMSIZ];
965 #ifdef DHD_PM_CONTROL_FROM_FILE
966 extern bool g_pm_control;
967 #endif /* DHD_PM_CONTROL_FROM_FILE */
968
969 /* private command support for restoring roam/scan parameters */
970 #if defined(SUPPORT_RESTORE_SCAN_PARAMS) || defined(WES_SUPPORT)
971 #define CMD_RESTORE_SCAN_PARAMS "RESTORE_SCAN_PARAMS"
972
973 typedef int (*PRIV_CMD_HANDLER) (struct net_device *dev, char *command);
974 typedef int (*PRIV_CMD_HANDLER_WITH_LEN) (struct net_device *dev, char *command, int total_len);
975
976 enum {
977 RESTORE_TYPE_UNSPECIFIED = 0,
978 RESTORE_TYPE_PRIV_CMD = 1,
979 RESTORE_TYPE_PRIV_CMD_WITH_LEN = 2
980 };
981
982 typedef struct android_restore_scan_params {
983 char command[64];
984 int parameter;
985 int cmd_type;
986 union {
987 PRIV_CMD_HANDLER cmd_handler;
988 PRIV_CMD_HANDLER_WITH_LEN cmd_handler_w_len;
989 };
990 } android_restore_scan_params_t;
991
992 /* function prototypes of private command handler */
993 static int wl_android_default_set_scan_params(struct net_device *dev, char *command, int total_len);
994 static int wl_android_set_roam_trigger(struct net_device *dev, char* command);
995 int wl_android_set_roam_delta(struct net_device *dev, char* command);
996 int wl_android_set_roam_scan_period(struct net_device *dev, char* command);
997 int wl_android_set_full_roam_scan_period(struct net_device *dev, char* command);
998 int wl_android_set_roam_scan_control(struct net_device *dev, char *command);
999 int wl_android_set_scan_channel_time(struct net_device *dev, char *command);
1000 int wl_android_set_scan_home_time(struct net_device *dev, char *command);
1001 int wl_android_set_scan_home_away_time(struct net_device *dev, char *command);
1002 int wl_android_set_scan_nprobes(struct net_device *dev, char *command);
1003 static int wl_android_set_band(struct net_device *dev, char *command);
1004 int wl_android_set_scan_dfs_channel_mode(struct net_device *dev, char *command);
1005 int wl_android_set_wes_mode(struct net_device *dev, char *command);
1006 int wl_android_set_okc_mode(struct net_device *dev, char *command);
1007
1008 /* default values */
1009 #ifdef ROAM_API
1010 #define DEFAULT_ROAM_TIRGGER -75
1011 #define DEFAULT_ROAM_DELTA 10
1012 #define DEFAULT_ROAMSCANPERIOD 10
1013 #define DEFAULT_FULLROAMSCANPERIOD_SET 120
1014 #endif /* ROAM_API */
1015 #ifdef WES_SUPPORT
1016 #define DEFAULT_ROAMSCANCONTROL 0
1017 #define DEFAULT_SCANCHANNELTIME 40
1018 #ifdef BCM4361_CHIP
1019 #define DEFAULT_SCANHOMETIME 60
1020 #else
1021 #define DEFAULT_SCANHOMETIME 45
1022 #endif /* BCM4361_CHIP */
1023 #define DEFAULT_SCANHOMEAWAYTIME 100
1024 #define DEFAULT_SCANPROBES 2
1025 #define DEFAULT_DFSSCANMODE 1
1026 #define DEFAULT_WESMODE 0
1027 #define DEFAULT_OKCMODE 1
1028 #endif /* WES_SUPPORT */
1029 #define DEFAULT_BAND 0
1030 #ifdef WBTEXT
1031 #define DEFAULT_WBTEXT_ENABLE 1
1032 #endif /* WBTEXT */
1033
1034 /* restoring parameter list, please don't change order */
1035 static android_restore_scan_params_t restore_params[] =
1036 {
1037 /* wbtext need to be disabled while updating roam/scan parameters */
1038 #ifdef WBTEXT
1039 { CMD_WBTEXT_ENABLE, 0, RESTORE_TYPE_PRIV_CMD_WITH_LEN,
1040 .cmd_handler_w_len = wl_android_wbtext},
1041 #endif /* WBTEXT */
1042 #ifdef ROAM_API
1043 { CMD_ROAMTRIGGER_SET, DEFAULT_ROAM_TIRGGER,
1044 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_roam_trigger},
1045 { CMD_ROAMDELTA_SET, DEFAULT_ROAM_DELTA,
1046 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_roam_delta},
1047 { CMD_ROAMSCANPERIOD_SET, DEFAULT_ROAMSCANPERIOD,
1048 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_roam_scan_period},
1049 { CMD_FULLROAMSCANPERIOD_SET, DEFAULT_FULLROAMSCANPERIOD_SET,
1050 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_full_roam_scan_period},
1051 #endif /* ROAM_API */
1052 #ifdef WES_SUPPORT
1053 { CMD_SETROAMSCANCONTROL, DEFAULT_ROAMSCANCONTROL,
1054 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_roam_scan_control},
1055 { CMD_SETSCANCHANNELTIME, DEFAULT_SCANCHANNELTIME,
1056 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_scan_channel_time},
1057 { CMD_SETSCANHOMETIME, DEFAULT_SCANHOMETIME,
1058 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_scan_home_time},
1059 { CMD_GETSCANHOMEAWAYTIME, DEFAULT_SCANHOMEAWAYTIME,
1060 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_scan_home_away_time},
1061 { CMD_SETSCANNPROBES, DEFAULT_SCANPROBES,
1062 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_scan_nprobes},
1063 { CMD_SETDFSSCANMODE, DEFAULT_DFSSCANMODE,
1064 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_scan_dfs_channel_mode},
1065 { CMD_SETWESMODE, DEFAULT_WESMODE,
1066 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_wes_mode},
1067 #endif /* WES_SUPPORT */
1068 { CMD_SETBAND, DEFAULT_BAND,
1069 RESTORE_TYPE_PRIV_CMD, .cmd_handler = wl_android_set_band},
1070 #ifdef WBTEXT
1071 { CMD_WBTEXT_ENABLE, DEFAULT_WBTEXT_ENABLE,
1072 RESTORE_TYPE_PRIV_CMD_WITH_LEN, .cmd_handler_w_len = wl_android_wbtext},
1073 #endif /* WBTEXT */
1074 { "\0", 0, RESTORE_TYPE_UNSPECIFIED, .cmd_handler = NULL}
1075 };
1076 #endif /* SUPPORT_RESTORE_SCAN_PARAMS || WES_SUPPORT */
1077
1078 #ifdef SUPPORT_LATENCY_CRITICAL_DATA
1079 #define CMD_GET_LATENCY_CRITICAL_DATA "GET_LATENCY_CRT_DATA"
1080 #define CMD_SET_LATENCY_CRITICAL_DATA "SET_LATENCY_CRT_DATA"
1081 #endif /* SUPPORT_LATENCY_CRITICAL_DATA */
1082
1083 typedef struct android_priv_cmd_log_cfg_table {
1084 char command[64];
1085 int enable;
1086 } android_priv_cmd_log_cfg_table_t;
1087
1088 static android_priv_cmd_log_cfg_table_t loging_params[] = {
1089 {CMD_GET_SNR, FALSE},
1090 #ifdef SUPPORT_LQCM
1091 {CMD_GET_LQCM_REPORT, FALSE},
1092 #endif
1093 #ifdef WL_GET_CU
1094 {CMD_GET_CHAN_UTIL, FALSE},
1095 #endif
1096 {"\0", FALSE}
1097 };
1098
1099 /**
1100 * Local (static) functions and variables
1101 */
1102
1103 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
1104 * time (only) in dhd_open, subsequential wifi on will be handled by
1105 * wl_android_wifi_on
1106 */
1107 int g_wifi_on = TRUE;
1108
1109 /**
1110 * Local (static) function definitions
1111 */
1112
wl_android_get_band_str(u16 band)1113 static char* wl_android_get_band_str(u16 band)
1114 {
1115 switch (band) {
1116 #ifdef WL_6G_BAND
1117 case WLC_BAND_6G:
1118 return "6G";
1119 #endif /* WL_6G_BAND */
1120 case WLC_BAND_5G:
1121 return "5G";
1122 case WLC_BAND_2G:
1123 return "2G";
1124 default:
1125 ANDROID_ERROR(("Unkown band: %d \n", band));
1126 return "Unknown band";
1127 }
1128 }
1129
1130 #ifdef WBTEXT
wl_android_bandstr_to_fwband(char * band,u8 * fw_band)1131 static int wl_android_bandstr_to_fwband(char *band, u8 *fw_band)
1132 {
1133 int err = BCME_OK;
1134
1135 if (!strcasecmp(band, "a")) {
1136 *fw_band = WLC_BAND_5G;
1137 } else if (!strcasecmp(band, "b")) {
1138 *fw_band = WLC_BAND_2G;
1139 #ifdef WL_6G_BAND
1140 } else if (!strcasecmp(band, "6g")) {
1141 *fw_band = WLC_BAND_6G;
1142 #endif /* WL_6G_BAND */
1143 } else if (!strcasecmp(band, "all")) {
1144 *fw_band = WLC_BAND_ALL;
1145 } else {
1146 err = BCME_BADBAND;
1147 }
1148
1149 return err;
1150 }
1151 #endif /* WBTEXT */
1152
1153 #ifdef WLWFDS
wl_android_set_wfds_hash(struct net_device * dev,char * command,bool enable)1154 static int wl_android_set_wfds_hash(
1155 struct net_device *dev, char *command, bool enable)
1156 {
1157 int error = 0;
1158 wl_p2p_wfds_hash_t *wfds_hash = NULL;
1159 char *smbuf = NULL;
1160 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1161
1162 smbuf = (char *)MALLOC(cfg->osh, WLC_IOCTL_MAXLEN);
1163 if (smbuf == NULL) {
1164 ANDROID_ERROR(("wl_android_set_wfds_hash: failed to allocated memory %d bytes\n",
1165 WLC_IOCTL_MAXLEN));
1166 return -ENOMEM;
1167 }
1168
1169 if (enable) {
1170 wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_ADD_WFDS_HASH) + 1);
1171 error = wldev_iovar_setbuf(dev, "p2p_add_wfds_hash", wfds_hash,
1172 sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
1173 }
1174 else {
1175 wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_DEL_WFDS_HASH) + 1);
1176 error = wldev_iovar_setbuf(dev, "p2p_del_wfds_hash", wfds_hash,
1177 sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
1178 }
1179
1180 if (error) {
1181 ANDROID_ERROR(("wl_android_set_wfds_hash: failed to %s, error=%d\n", command, error));
1182 }
1183
1184 if (smbuf) {
1185 MFREE(cfg->osh, smbuf, WLC_IOCTL_MAXLEN);
1186 }
1187 return error;
1188 }
1189 #endif /* WLWFDS */
1190
wl_android_get_link_speed(struct net_device * net,char * command,int total_len)1191 static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len)
1192 {
1193 int link_speed;
1194 int bytes_written;
1195 int error;
1196
1197 error = wldev_get_link_speed(net, &link_speed);
1198 if (error) {
1199 ANDROID_ERROR(("Get linkspeed failed \n"));
1200 return -1;
1201 }
1202
1203 /* Convert Kbps to Android Mbps */
1204 link_speed = link_speed / 1000;
1205 bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
1206 ANDROID_INFO(("wl_android_get_link_speed: command result is %s\n", command));
1207 return bytes_written;
1208 }
1209
wl_android_get_rssi(struct net_device * net,char * command,int total_len)1210 static int wl_android_get_rssi(struct net_device *net, char *command, int total_len)
1211 {
1212 wlc_ssid_t ssid = {0, {0}};
1213 int bytes_written = 0;
1214 int error = 0;
1215 scb_val_t scbval;
1216 char *delim = NULL;
1217 struct net_device *target_ndev = net;
1218 #ifdef WL_VIRTUAL_APSTA
1219 char *pos = NULL;
1220 struct bcm_cfg80211 *cfg;
1221 #endif /* WL_VIRTUAL_APSTA */
1222
1223 delim = strchr(command, ' ');
1224 /* For Ap mode rssi command would be
1225 * driver rssi <sta_mac_addr>
1226 * for STA/GC mode
1227 * driver rssi
1228 */
1229 if (delim) {
1230 /* Ap/GO mode
1231 * driver rssi <sta_mac_addr>
1232 */
1233 ANDROID_TRACE(("wl_android_get_rssi: cmd:%s\n", delim));
1234 /* skip space from delim after finding char */
1235 delim++;
1236 if (!(bcm_ether_atoe((delim), &scbval.ea))) {
1237 ANDROID_ERROR(("wl_android_get_rssi: address err\n"));
1238 return -1;
1239 }
1240 scbval.val = htod32(0);
1241 ANDROID_TRACE(("wl_android_get_rssi: address:"MACDBG, MAC2STRDBG(scbval.ea.octet)));
1242 #ifdef WL_VIRTUAL_APSTA
1243 /* RSDB AP may have another virtual interface
1244 * In this case, format of private command is as following,
1245 * DRIVER rssi <sta_mac_addr> <AP interface name>
1246 */
1247
1248 /* Current position is start of MAC address string */
1249 pos = delim;
1250 delim = strchr(pos, ' ');
1251 if (delim) {
1252 /* skip space from delim after finding char */
1253 delim++;
1254 if (strnlen(delim, IFNAMSIZ)) {
1255 cfg = wl_get_cfg(net);
1256 target_ndev = wl_get_ap_netdev(cfg, delim);
1257 if (target_ndev == NULL)
1258 target_ndev = net;
1259 }
1260 }
1261 #endif /* WL_VIRTUAL_APSTA */
1262 }
1263 else {
1264 /* STA/GC mode */
1265 bzero(&scbval, sizeof(scb_val_t));
1266 }
1267
1268 error = wldev_get_rssi(target_ndev, &scbval);
1269 if (error)
1270 return -1;
1271 #if defined(RSSIOFFSET)
1272 scbval.val = wl_update_rssi_offset(net, scbval.val);
1273 #endif
1274
1275 error = wldev_get_ssid(target_ndev, &ssid);
1276 if (error)
1277 return -1;
1278 if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
1279 ANDROID_ERROR(("wl_android_get_rssi: wldev_get_ssid failed\n"));
1280 } else if (total_len <= ssid.SSID_len) {
1281 return -ENOMEM;
1282 } else {
1283 memcpy(command, ssid.SSID, ssid.SSID_len);
1284 bytes_written = ssid.SSID_len;
1285 }
1286 if ((total_len - bytes_written) < (strlen(" rssi -XXX") + 1))
1287 return -ENOMEM;
1288
1289 bytes_written += scnprintf(&command[bytes_written], total_len - bytes_written,
1290 " rssi %d", scbval.val);
1291 command[bytes_written] = '\0';
1292
1293 ANDROID_TRACE(("wl_android_get_rssi: command result is %s (%d)\n", command, bytes_written));
1294 return bytes_written;
1295 }
1296
wl_android_set_suspendopt(struct net_device * dev,char * command)1297 static int wl_android_set_suspendopt(struct net_device *dev, char *command)
1298 {
1299 int suspend_flag;
1300 int ret_now;
1301 int ret = 0;
1302
1303 suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0';
1304
1305 if (suspend_flag != 0) {
1306 suspend_flag = 1;
1307 }
1308 ret_now = net_os_set_suspend_disable(dev, suspend_flag);
1309
1310 if (ret_now != suspend_flag) {
1311 if (!(ret = net_os_set_suspend(dev, ret_now, 1))) {
1312 ANDROID_INFO(("wl_android_set_suspendopt: Suspend Flag %d -> %d\n",
1313 ret_now, suspend_flag));
1314 } else {
1315 ANDROID_ERROR(("wl_android_set_suspendopt: failed %d\n", ret));
1316 }
1317 }
1318
1319 return ret;
1320 }
1321
wl_android_set_suspendmode(struct net_device * dev,char * command)1322 static int wl_android_set_suspendmode(struct net_device *dev, char *command)
1323 {
1324 int ret = 0;
1325
1326 #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
1327 int suspend_flag;
1328
1329 suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0';
1330 if (suspend_flag != 0)
1331 suspend_flag = 1;
1332
1333 if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
1334 ANDROID_INFO(("wl_android_set_suspendmode: Suspend Mode %d\n", suspend_flag));
1335 else
1336 ANDROID_ERROR(("wl_android_set_suspendmode: failed %d\n", ret));
1337 #endif
1338
1339 return ret;
1340 }
1341
1342 #ifdef WL_CFG80211
wl_android_get_80211_mode(struct net_device * dev,char * command,int total_len)1343 int wl_android_get_80211_mode(struct net_device *dev, char *command, int total_len)
1344 {
1345 uint8 mode[5];
1346 int error = 0;
1347 int bytes_written = 0;
1348
1349 error = wldev_get_mode(dev, mode, sizeof(mode));
1350 if (error)
1351 return -1;
1352
1353 ANDROID_INFO(("wl_android_get_80211_mode: mode:%s\n", mode));
1354 bytes_written = snprintf(command, total_len, "%s %s", CMD_80211_MODE, mode);
1355 ANDROID_INFO(("wl_android_get_80211_mode: command:%s EXIT\n", command));
1356 return bytes_written;
1357
1358 }
1359
1360 extern chanspec_t
1361 wl_chspec_driver_to_host(chanspec_t chanspec);
wl_android_get_chanspec(struct net_device * dev,char * command,int total_len)1362 int wl_android_get_chanspec(struct net_device *dev, char *command, int total_len)
1363 {
1364 int error = 0;
1365 int bytes_written = 0;
1366 int chsp = {0};
1367 uint16 band = 0;
1368 uint16 bw = 0;
1369 uint16 channel = 0;
1370 u32 sb = 0;
1371 chanspec_t chanspec;
1372
1373 /* command is
1374 * driver chanspec
1375 */
1376 error = wldev_iovar_getint(dev, "chanspec", &chsp);
1377 if (error)
1378 return -1;
1379
1380 chanspec = wl_chspec_driver_to_host(chsp);
1381 ANDROID_INFO(("wl_android_get_80211_mode: return value of chanspec:%x\n", chanspec));
1382
1383 channel = chanspec & WL_CHANSPEC_CHAN_MASK;
1384 band = chanspec & WL_CHANSPEC_BAND_MASK;
1385 bw = chanspec & WL_CHANSPEC_BW_MASK;
1386
1387 ANDROID_INFO(("wl_android_get_80211_mode: channel:%d band:%d bandwidth:%d\n",
1388 channel, band, bw));
1389
1390 if (bw == WL_CHANSPEC_BW_160) {
1391 bw = WL_CH_BANDWIDTH_160MHZ;
1392 } else if (bw == WL_CHANSPEC_BW_80) {
1393 bw = WL_CH_BANDWIDTH_80MHZ;
1394 } else if (bw == WL_CHANSPEC_BW_40) {
1395 bw = WL_CH_BANDWIDTH_40MHZ;
1396 } else if (bw == WL_CHANSPEC_BW_20) {
1397 bw = WL_CH_BANDWIDTH_20MHZ;
1398 } else {
1399 bw = WL_CH_BANDWIDTH_20MHZ;
1400 }
1401
1402 if (bw == WL_CH_BANDWIDTH_40MHZ) {
1403 if (CHSPEC_SB_UPPER(chanspec)) {
1404 channel += CH_10MHZ_APART;
1405 } else {
1406 channel -= CH_10MHZ_APART;
1407 }
1408 }
1409 else if (bw == WL_CH_BANDWIDTH_80MHZ) {
1410 sb = chanspec & WL_CHANSPEC_CTL_SB_MASK;
1411 if (sb == WL_CHANSPEC_CTL_SB_LL) {
1412 channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
1413 } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
1414 channel -= CH_10MHZ_APART;
1415 } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
1416 channel += CH_10MHZ_APART;
1417 } else {
1418 /* WL_CHANSPEC_CTL_SB_UU */
1419 channel += (CH_10MHZ_APART + CH_20MHZ_APART);
1420 }
1421 } else if (bw == WL_CH_BANDWIDTH_160MHZ) {
1422 channel = wf_chspec_primary20_chan(chanspec);
1423 }
1424 bytes_written = snprintf(command, total_len, "%s channel %d band %s bw %d", CMD_CHANSPEC,
1425 channel, wl_android_get_band_str(CHSPEC2WLC_BAND(chanspec)), bw);
1426
1427 ANDROID_INFO(("wl_android_get_chanspec: command:%s EXIT\n", command));
1428 return bytes_written;
1429
1430 }
1431 #endif /* WL_CFG80211 */
1432
1433 /* returns current datarate datarate returned from firmware are in 500kbps */
wl_android_get_datarate(struct net_device * dev,char * command,int total_len)1434 int wl_android_get_datarate(struct net_device *dev, char *command, int total_len)
1435 {
1436 int error = 0;
1437 int datarate = 0;
1438 int bytes_written = 0;
1439
1440 error = wldev_get_datarate(dev, &datarate);
1441 if (error)
1442 return -1;
1443
1444 ANDROID_INFO(("wl_android_get_datarate: datarate:%d\n", datarate));
1445
1446 bytes_written = snprintf(command, total_len, "%s %d", CMD_DATARATE, (datarate/2));
1447 return bytes_written;
1448 }
wl_android_get_assoclist(struct net_device * dev,char * command,int total_len)1449 int wl_android_get_assoclist(struct net_device *dev, char *command, int total_len)
1450 {
1451 int error = 0;
1452 int bytes_written = 0;
1453 uint i;
1454 int len = 0;
1455 char mac_buf[MAX_NUM_OF_ASSOCLIST *
1456 sizeof(struct ether_addr) + sizeof(uint)] = {0};
1457 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
1458
1459 ANDROID_TRACE(("wl_android_get_assoclist: ENTER\n"));
1460
1461 assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
1462
1463 error = wldev_ioctl_get(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf));
1464 if (error)
1465 return -1;
1466
1467 assoc_maclist->count = dtoh32(assoc_maclist->count);
1468 bytes_written = snprintf(command, total_len, "%s listcount: %d Stations:",
1469 CMD_ASSOC_CLIENTS, assoc_maclist->count);
1470
1471 for (i = 0; i < assoc_maclist->count; i++) {
1472 len = snprintf(command + bytes_written, total_len - bytes_written, " " MACDBG,
1473 MAC2STRDBG(assoc_maclist->ea[i].octet));
1474 /* A return value of '(total_len - bytes_written)' or more means that the
1475 * output was truncated
1476 */
1477 if ((len > 0) && (len < (total_len - bytes_written))) {
1478 bytes_written += len;
1479 } else {
1480 ANDROID_ERROR(("wl_android_get_assoclist: Insufficient buffer %d,"
1481 " bytes_written %d\n",
1482 total_len, bytes_written));
1483 bytes_written = -1;
1484 break;
1485 }
1486 }
1487 return bytes_written;
1488 }
1489
1490 #ifdef WL_CFG80211
1491 extern chanspec_t
1492 wl_chspec_host_to_driver(chanspec_t chanspec);
wl_android_set_csa(struct net_device * dev,char * command)1493 static int wl_android_set_csa(struct net_device *dev, char *command)
1494 {
1495 int error = 0;
1496 char smbuf[WLC_IOCTL_SMLEN];
1497 wl_chan_switch_t csa_arg;
1498 u32 chnsp = 0;
1499 int err = 0;
1500
1501 ANDROID_INFO(("wl_android_set_csa: command:%s\n", command));
1502
1503 command = (command + strlen(CMD_SET_CSA));
1504 /* Order is mode, count channel */
1505 if (!*++command) {
1506 ANDROID_ERROR(("wl_android_set_csa:error missing arguments\n"));
1507 return -1;
1508 }
1509 csa_arg.mode = bcm_atoi(command);
1510
1511 if (csa_arg.mode != 0 && csa_arg.mode != 1) {
1512 ANDROID_ERROR(("Invalid mode\n"));
1513 return -1;
1514 }
1515
1516 if (!*++command) {
1517 ANDROID_ERROR(("wl_android_set_csa: error missing count\n"));
1518 return -1;
1519 }
1520 command++;
1521 csa_arg.count = bcm_atoi(command);
1522
1523 csa_arg.reg = 0;
1524 csa_arg.chspec = 0;
1525 command += 2;
1526 if (!*command) {
1527 ANDROID_ERROR(("wl_android_set_csa: error missing channel\n"));
1528 return -1;
1529 }
1530
1531 chnsp = wf_chspec_aton(command);
1532 if (chnsp == 0) {
1533 ANDROID_ERROR(("wl_android_set_csa:chsp is not correct\n"));
1534 return -1;
1535 }
1536 chnsp = wl_chspec_host_to_driver(chnsp);
1537 csa_arg.chspec = chnsp;
1538
1539 if (chnsp & WL_CHANSPEC_BAND_5G) {
1540 u32 chanspec = chnsp;
1541 err = wldev_iovar_getint(dev, "per_chan_info", &chanspec);
1542 if (!err) {
1543 if ((chanspec & WL_CHAN_RADAR) || (chanspec & WL_CHAN_PASSIVE)) {
1544 ANDROID_ERROR(("Channel is radar sensitive\n"));
1545 return -1;
1546 }
1547 if (chanspec == 0) {
1548 ANDROID_ERROR(("Invalid hw channel\n"));
1549 return -1;
1550 }
1551 } else {
1552 ANDROID_ERROR(("does not support per_chan_info\n"));
1553 return -1;
1554 }
1555 ANDROID_INFO(("non radar sensitivity\n"));
1556 }
1557 error = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(csa_arg),
1558 smbuf, sizeof(smbuf), NULL);
1559 if (error) {
1560 ANDROID_ERROR(("wl_android_set_csa:set csa failed:%d\n", error));
1561 return -1;
1562 }
1563 return 0;
1564 }
1565 #endif /* WL_CFG80211 */
1566
1567 static int
wl_android_set_bcn_li_dtim(struct net_device * dev,char * command)1568 wl_android_set_bcn_li_dtim(struct net_device *dev, char *command)
1569 {
1570 int ret = 0;
1571 int dtim;
1572
1573 dtim = *(command + strlen(CMD_SETDTIM_IN_SUSPEND) + 1) - '0';
1574
1575 if (dtim > (MAX_DTIM_ALLOWED_INTERVAL / MAX_DTIM_SKIP_BEACON_INTERVAL)) {
1576 ANDROID_ERROR(("%s: failed, invalid dtim %d\n",
1577 __FUNCTION__, dtim));
1578 return BCME_ERROR;
1579 }
1580
1581 if (!(ret = net_os_set_suspend_bcn_li_dtim(dev, dtim))) {
1582 ANDROID_TRACE(("%s: SET bcn_li_dtim in suspend %d\n",
1583 __FUNCTION__, dtim));
1584 } else {
1585 ANDROID_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
1586 }
1587
1588 return ret;
1589 }
1590
1591 static int
wl_android_set_max_dtim(struct net_device * dev,char * command)1592 wl_android_set_max_dtim(struct net_device *dev, char *command)
1593 {
1594 int ret = 0;
1595 int dtim_flag;
1596
1597 dtim_flag = *(command + strlen(CMD_MAXDTIM_IN_SUSPEND) + 1) - '0';
1598
1599 if (!(ret = net_os_set_max_dtim_enable(dev, dtim_flag))) {
1600 ANDROID_TRACE(("wl_android_set_max_dtim: use Max bcn_li_dtim in suspend %s\n",
1601 (dtim_flag ? "Enable" : "Disable")));
1602 } else {
1603 ANDROID_ERROR(("wl_android_set_max_dtim: failed %d\n", ret));
1604 }
1605
1606 return ret;
1607 }
1608
1609 #ifdef DISABLE_DTIM_IN_SUSPEND
1610 static int
wl_android_set_disable_dtim_in_suspend(struct net_device * dev,char * command)1611 wl_android_set_disable_dtim_in_suspend(struct net_device *dev, char *command)
1612 {
1613 int ret = 0;
1614 int dtim_flag;
1615
1616 dtim_flag = *(command + strlen(CMD_DISDTIM_IN_SUSPEND) + 1) - '0';
1617
1618 if (!(ret = net_os_set_disable_dtim_in_suspend(dev, dtim_flag))) {
1619 ANDROID_TRACE(("wl_android_set_disable_dtim_in_suspend: "
1620 "use Disable bcn_li_dtim in suspend %s\n",
1621 (dtim_flag ? "Enable" : "Disable")));
1622 } else {
1623 ANDROID_ERROR(("wl_android_set_disable_dtim_in_suspend: failed %d\n", ret));
1624 }
1625
1626 return ret;
1627 }
1628 #endif /* DISABLE_DTIM_IN_SUSPEND */
1629
wl_android_get_band(struct net_device * dev,char * command,int total_len)1630 static int wl_android_get_band(struct net_device *dev, char *command, int total_len)
1631 {
1632 uint band;
1633 int bytes_written;
1634 int error = BCME_OK;
1635
1636 error = wldev_iovar_getint(dev, "if_band", &band);
1637 if (error == BCME_UNSUPPORTED) {
1638 error = wldev_get_band(dev, &band);
1639 if (error) {
1640 return error;
1641 }
1642 }
1643 bytes_written = snprintf(command, total_len, "Band %d", band);
1644 return bytes_written;
1645 }
1646
1647 #ifdef WL_CFG80211
1648 static int
wl_android_set_band(struct net_device * dev,char * command)1649 wl_android_set_band(struct net_device *dev, char *command)
1650 {
1651 int error = 0;
1652 uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
1653 #ifdef WL_HOST_BAND_MGMT
1654 int ret = 0;
1655 if ((ret = wl_cfg80211_set_band(dev, band)) < 0) {
1656 if (ret == BCME_UNSUPPORTED) {
1657 /* If roam_var is unsupported, fallback to the original method */
1658 ANDROID_ERROR(("WL_HOST_BAND_MGMT defined, "
1659 "but roam_band iovar unsupported in the firmware\n"));
1660 } else {
1661 error = -1;
1662 }
1663 }
1664 if (((ret == 0) && (band == WLC_BAND_AUTO)) || (ret == BCME_UNSUPPORTED)) {
1665 /* Apply if roam_band iovar is not supported or band setting is AUTO */
1666 error = wldev_set_band(dev, band);
1667 }
1668 #else
1669 error = wl_cfg80211_set_if_band(dev, band);
1670 #endif /* WL_HOST_BAND_MGMT */
1671 #ifdef ROAM_CHANNEL_CACHE
1672 wl_update_roamscan_cache_by_band(dev, band);
1673 #endif /* ROAM_CHANNEL_CACHE */
1674 return error;
1675 }
1676 #endif /* WL_CFG80211 */
1677
1678 #ifdef CUSTOMER_HW4_PRIVATE_CMD
1679 #ifdef ROAM_API
1680 #ifdef WBTEXT
wl_android_check_wbtext_support(struct net_device * dev)1681 static bool wl_android_check_wbtext_support(struct net_device *dev)
1682 {
1683 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
1684 return dhdp->wbtext_support;
1685 }
1686 #endif /* WBTEXT */
1687
1688 static bool
wl_android_check_wbtext_policy(struct net_device * dev)1689 wl_android_check_wbtext_policy(struct net_device *dev)
1690 {
1691 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
1692 if (dhdp->wbtext_policy == WL_BSSTRANS_POLICY_PRODUCT_WBTEXT) {
1693 return TRUE;
1694 }
1695
1696 return FALSE;
1697 }
1698
1699 static int
wl_android_set_roam_trigger(struct net_device * dev,char * command)1700 wl_android_set_roam_trigger(struct net_device *dev, char* command)
1701 {
1702 int roam_trigger[2] = {0, 0};
1703 int error;
1704
1705 #ifdef WBTEXT
1706 if (wl_android_check_wbtext_policy(dev)) {
1707 ANDROID_ERROR(("blocked to set roam trigger. try with setting roam profile\n"));
1708 return BCME_ERROR;
1709 }
1710 #endif /* WBTEXT */
1711
1712 sscanf(command, "%*s %10d", &roam_trigger[0]);
1713 if (roam_trigger[0] >= 0) {
1714 ANDROID_ERROR(("wrong roam trigger value (%d)\n", roam_trigger[0]));
1715 return BCME_ERROR;
1716 }
1717
1718 roam_trigger[1] = WLC_BAND_ALL;
1719 error = wldev_ioctl_set(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
1720 sizeof(roam_trigger));
1721 if (error != BCME_OK) {
1722 ANDROID_ERROR(("failed to set roam trigger (%d)\n", error));
1723 return BCME_ERROR;
1724 }
1725
1726 return BCME_OK;
1727 }
1728
1729 static int
wl_android_get_roam_trigger(struct net_device * dev,char * command,int total_len)1730 wl_android_get_roam_trigger(struct net_device *dev, char *command, int total_len)
1731 {
1732 int bytes_written, error;
1733 int roam_trigger[2] = {0, 0};
1734 uint16 band = 0;
1735 int chsp = {0};
1736 chanspec_t chanspec;
1737 #ifdef WBTEXT
1738 int i;
1739 wl_roamprof_band_t rp;
1740 uint8 roam_prof_ver = 0, roam_prof_size = 0;
1741 #endif /* WBTEXT */
1742
1743 error = wldev_iovar_getint(dev, "chanspec", &chsp);
1744 if (error != BCME_OK) {
1745 ANDROID_ERROR(("failed to get chanspec (%d)\n", error));
1746 return BCME_ERROR;
1747 }
1748
1749 chanspec = wl_chspec_driver_to_host(chsp);
1750 band = CHSPEC2WLC_BAND(chanspec);
1751
1752 if (wl_android_check_wbtext_policy(dev)) {
1753 #ifdef WBTEXT
1754 memset_s(&rp, sizeof(rp), 0, sizeof(rp));
1755 if ((error = wlc_wbtext_get_roam_prof(dev, &rp, band, &roam_prof_ver,
1756 &roam_prof_size))) {
1757 ANDROID_ERROR(("Getting roam_profile failed with err=%d \n", error));
1758 return -EINVAL;
1759 }
1760 switch (roam_prof_ver) {
1761 case WL_ROAM_PROF_VER_1:
1762 {
1763 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
1764 if (rp.v2.roam_prof[i].channel_usage == 0) {
1765 roam_trigger[0] = rp.v2.roam_prof[i].roam_trigger;
1766 break;
1767 }
1768 }
1769 }
1770 break;
1771 case WL_ROAM_PROF_VER_2:
1772 {
1773 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
1774 if (rp.v3.roam_prof[i].channel_usage == 0) {
1775 roam_trigger[0] = rp.v3.roam_prof[i].roam_trigger;
1776 break;
1777 }
1778 }
1779 }
1780 break;
1781 case WL_ROAM_PROF_VER_3:
1782 {
1783 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
1784 if (rp.v4.roam_prof[i].channel_usage == 0) {
1785 roam_trigger[0] = rp.v4.roam_prof[i].roam_trigger;
1786 break;
1787 }
1788 }
1789 }
1790 break;
1791 default:
1792 ANDROID_ERROR(("bad version = %d \n", roam_prof_ver));
1793 return BCME_VERSION;
1794 }
1795 #endif /* WBTEXT */
1796 if (roam_trigger[0] == 0) {
1797 ANDROID_ERROR(("roam trigger was not set properly\n"));
1798 return BCME_ERROR;
1799 }
1800 } else {
1801 roam_trigger[1] = band;
1802 error = wldev_ioctl_get(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
1803 sizeof(roam_trigger));
1804 if (error != BCME_OK) {
1805 ANDROID_ERROR(("failed to get roam trigger (%d)\n", error));
1806 return BCME_ERROR;
1807 }
1808 }
1809
1810 bytes_written = snprintf(command, total_len, "%s %d",
1811 CMD_ROAMTRIGGER_GET, roam_trigger[0]);
1812
1813 return bytes_written;
1814 }
1815
1816 #ifdef WBTEXT
1817 s32
wl_cfg80211_wbtext_roam_trigger_config(struct net_device * ndev,int roam_trigger)1818 wl_cfg80211_wbtext_roam_trigger_config(struct net_device *ndev, int roam_trigger)
1819 {
1820 char *commandp = NULL;
1821 s32 ret = BCME_OK;
1822 char *data;
1823 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
1824 uint8 bandidx = 0;
1825
1826 commandp = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_SMLEN);
1827 if (unlikely(!commandp)) {
1828 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
1829 ret = -ENOMEM;
1830 goto exit;
1831 }
1832
1833 ANDROID_INFO(("roam trigger %d\n", roam_trigger));
1834 if (roam_trigger > 0) {
1835 ANDROID_ERROR(("Invalid roam trigger value %d\n", roam_trigger));
1836 goto exit;
1837 }
1838
1839 for (bandidx = 0; bandidx < MAXBANDS; bandidx++) {
1840 char *band;
1841 int tri0, tri1, low0, low1, cu0, cu1, dur0, dur1;
1842 int tri0_dflt;
1843 if (bandidx == BAND_5G_INDEX) {
1844 band = "a";
1845 tri0_dflt = DEFAULT_WBTEXT_CU_RSSI_TRIG_A;
1846 } else {
1847 band = "b";
1848 tri0_dflt = DEFAULT_WBTEXT_CU_RSSI_TRIG_B;
1849 }
1850
1851 /* Get ROAM Profile
1852 * WBTEXT_PROFILE_CONFIG band
1853 */
1854 bzero(commandp, WLC_IOCTL_SMLEN);
1855 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
1856 CMD_WBTEXT_PROFILE_CONFIG, band);
1857 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
1858 wl_cfg80211_wbtext_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
1859
1860 /* Set ROAM Profile
1861 * WBTEXT_PROFILE_CONFIG band -70 roam_trigger 70 10 roam_trigger -128 0 10
1862 */
1863 sscanf(commandp, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)"
1864 "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)",
1865 &tri0, &low0, &cu0, &dur0, &tri1, &low1, &cu1, &dur1);
1866
1867 if (tri0_dflt <= roam_trigger) {
1868 tri0 = roam_trigger + 1;
1869 } else {
1870 tri0 = tri0_dflt;
1871 }
1872
1873 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
1874 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s %d %d %d %d %d %d %d %d",
1875 CMD_WBTEXT_PROFILE_CONFIG, band,
1876 tri0, roam_trigger, cu0, dur0, roam_trigger, low1, cu1, dur1);
1877
1878 ret = wl_cfg80211_wbtext_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
1879 if (ret != BCME_OK) {
1880 ANDROID_ERROR(("Failed to set roam_prof %s error = %d\n", data, ret));
1881 goto exit;
1882 }
1883 }
1884
1885 exit:
1886 if (commandp) {
1887 MFREE(cfg->osh, commandp, WLC_IOCTL_SMLEN);
1888 }
1889 return ret;
1890 }
1891 #endif /* WBTEXT */
1892
1893 static int
wl_android_set_roam_trigger_legacy(struct net_device * dev,char * command)1894 wl_android_set_roam_trigger_legacy(struct net_device *dev, char* command)
1895 {
1896 int roam_trigger[2] = {0, 0};
1897 int error;
1898
1899 sscanf(command, "%*s %10d", &roam_trigger[0]);
1900 if (roam_trigger[0] >= 0) {
1901 ANDROID_ERROR(("wrong roam trigger value (%d)\n", roam_trigger[0]));
1902 return BCME_ERROR;
1903 }
1904
1905 if (wl_android_check_wbtext_policy(dev)) {
1906 #ifdef WBTEXT
1907 error = wl_cfg80211_wbtext_roam_trigger_config(dev, roam_trigger[0]);
1908 if (error != BCME_OK) {
1909 ANDROID_ERROR(("failed to set roam prof trigger (%d)\n", error));
1910 return BCME_ERROR;
1911 }
1912 #endif /* WBTEXT */
1913 } else {
1914 if (roam_trigger[0] >= 0) {
1915 ANDROID_ERROR(("wrong roam trigger value (%d)\n", roam_trigger[0]));
1916 return BCME_ERROR;
1917 }
1918
1919 roam_trigger[1] = WLC_BAND_ALL;
1920 error = wldev_ioctl_set(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
1921 sizeof(roam_trigger));
1922 if (error != BCME_OK) {
1923 ANDROID_ERROR(("failed to set roam trigger (%d)\n", error));
1924 return BCME_ERROR;
1925 }
1926 }
1927
1928 return BCME_OK;
1929 }
1930
wl_android_set_roam_delta(struct net_device * dev,char * command)1931 int wl_android_set_roam_delta(
1932 struct net_device *dev, char* command)
1933 {
1934 int roam_delta[2];
1935
1936 sscanf(command, "%*s %10d", &roam_delta[0]);
1937 roam_delta[1] = WLC_BAND_ALL;
1938
1939 return wldev_ioctl_set(dev, WLC_SET_ROAM_DELTA, roam_delta,
1940 sizeof(roam_delta));
1941 }
1942
wl_android_get_roam_delta(struct net_device * dev,char * command,int total_len)1943 static int wl_android_get_roam_delta(
1944 struct net_device *dev, char *command, int total_len)
1945 {
1946 int bytes_written;
1947 int roam_delta[2] = {0, 0};
1948
1949 roam_delta[1] = WLC_BAND_2G;
1950 if (wldev_ioctl_get(dev, WLC_GET_ROAM_DELTA, roam_delta,
1951 sizeof(roam_delta))) {
1952 roam_delta[1] = WLC_BAND_5G;
1953 #ifdef WL_6G_BAND
1954 if (wldev_ioctl_get(dev, WLC_GET_ROAM_DELTA, roam_delta,
1955 sizeof(roam_delta))) {
1956 roam_delta[1] = WLC_BAND_6G;
1957 #endif /* WL_6G_BAND */
1958 if (wldev_ioctl_get(dev, WLC_GET_ROAM_DELTA, roam_delta,
1959 sizeof(roam_delta))) {
1960 return -1;
1961 }
1962 #ifdef WL_6G_BAND
1963 }
1964 #endif /* WL_6G_BAND */
1965 }
1966
1967 bytes_written = snprintf(command, total_len, "%s %d",
1968 CMD_ROAMDELTA_GET, roam_delta[0]);
1969
1970 return bytes_written;
1971 }
1972
wl_android_set_roam_scan_period(struct net_device * dev,char * command)1973 int wl_android_set_roam_scan_period(
1974 struct net_device *dev, char* command)
1975 {
1976 int roam_scan_period = 0;
1977
1978 sscanf(command, "%*s %10d", &roam_scan_period);
1979 return wldev_ioctl_set(dev, WLC_SET_ROAM_SCAN_PERIOD, &roam_scan_period,
1980 sizeof(roam_scan_period));
1981 }
1982
wl_android_get_roam_scan_period(struct net_device * dev,char * command,int total_len)1983 static int wl_android_get_roam_scan_period(
1984 struct net_device *dev, char *command, int total_len)
1985 {
1986 int bytes_written;
1987 int roam_scan_period = 0;
1988
1989 if (wldev_ioctl_get(dev, WLC_GET_ROAM_SCAN_PERIOD, &roam_scan_period,
1990 sizeof(roam_scan_period)))
1991 return -1;
1992
1993 bytes_written = snprintf(command, total_len, "%s %d",
1994 CMD_ROAMSCANPERIOD_GET, roam_scan_period);
1995
1996 return bytes_written;
1997 }
1998
wl_android_set_full_roam_scan_period(struct net_device * dev,char * command)1999 int wl_android_set_full_roam_scan_period(
2000 struct net_device *dev, char* command)
2001 {
2002 int error = 0;
2003 int full_roam_scan_period = 0;
2004 char smbuf[WLC_IOCTL_SMLEN];
2005
2006 sscanf(command+sizeof("SETFULLROAMSCANPERIOD"), "%d", &full_roam_scan_period);
2007 WL_TRACE(("fullroamperiod = %d\n", full_roam_scan_period));
2008
2009 error = wldev_iovar_setbuf(dev, "fullroamperiod", &full_roam_scan_period,
2010 sizeof(full_roam_scan_period), smbuf, sizeof(smbuf), NULL);
2011 if (error) {
2012 ANDROID_ERROR(("Failed to set full roam scan period, error = %d\n", error));
2013 }
2014
2015 return error;
2016 }
2017
wl_android_get_full_roam_scan_period(struct net_device * dev,char * command,int total_len)2018 static int wl_android_get_full_roam_scan_period(
2019 struct net_device *dev, char *command, int total_len)
2020 {
2021 int error;
2022 int bytes_written;
2023 int full_roam_scan_period = 0;
2024
2025 error = wldev_iovar_getint(dev, "fullroamperiod", &full_roam_scan_period);
2026
2027 if (error) {
2028 ANDROID_ERROR(("%s: get full roam scan period failed code %d\n",
2029 __func__, error));
2030 return -1;
2031 } else {
2032 ANDROID_INFO(("%s: get full roam scan period %d\n", __func__, full_roam_scan_period));
2033 }
2034
2035 bytes_written = snprintf(command, total_len, "%s %d",
2036 CMD_FULLROAMSCANPERIOD_GET, full_roam_scan_period);
2037
2038 return bytes_written;
2039 }
2040
wl_android_set_country_rev(struct net_device * dev,char * command)2041 int wl_android_set_country_rev(
2042 struct net_device *dev, char* command)
2043 {
2044 int error = 0;
2045 wl_country_t cspec = {{0}, 0, {0} };
2046 char country_code[WLC_CNTRY_BUF_SZ];
2047 char smbuf[WLC_IOCTL_SMLEN];
2048 int rev = 0;
2049
2050 bzero(country_code, sizeof(country_code));
2051 sscanf(command+sizeof("SETCOUNTRYREV"), "%3s %10d", country_code, &rev);
2052 WL_TRACE(("country_code = %s, rev = %d\n", country_code, rev));
2053
2054 memcpy(cspec.country_abbrev, country_code, sizeof(country_code));
2055 memcpy(cspec.ccode, country_code, sizeof(country_code));
2056 cspec.rev = rev;
2057
2058 error = wldev_iovar_setbuf(dev, "country", (char *)&cspec,
2059 sizeof(cspec), smbuf, sizeof(smbuf), NULL);
2060
2061 if (error) {
2062 ANDROID_ERROR(("wl_android_set_country_rev: set country '%s/%d' failed code %d\n",
2063 cspec.ccode, cspec.rev, error));
2064 } else {
2065 dhd_bus_country_set(dev, &cspec, true);
2066 ANDROID_INFO(("wl_android_set_country_rev: set country '%s/%d'\n",
2067 cspec.ccode, cspec.rev));
2068 }
2069
2070 return error;
2071 }
2072
wl_android_get_country_rev(struct net_device * dev,char * command,int total_len)2073 static int wl_android_get_country_rev(
2074 struct net_device *dev, char *command, int total_len)
2075 {
2076 int error;
2077 int bytes_written;
2078 char smbuf[WLC_IOCTL_SMLEN];
2079 wl_country_t cspec;
2080
2081 error = wldev_iovar_getbuf(dev, "country", NULL, 0, smbuf,
2082 sizeof(smbuf), NULL);
2083
2084 if (error) {
2085 ANDROID_ERROR(("wl_android_get_country_rev: get country failed code %d\n",
2086 error));
2087 return -1;
2088 } else {
2089 memcpy(&cspec, smbuf, sizeof(cspec));
2090 ANDROID_INFO(("wl_android_get_country_rev: get country '%c%c %d'\n",
2091 cspec.ccode[0], cspec.ccode[1], cspec.rev));
2092 }
2093
2094 bytes_written = snprintf(command, total_len, "%s %c%c %d",
2095 CMD_COUNTRYREV_GET, cspec.ccode[0], cspec.ccode[1], cspec.rev);
2096
2097 return bytes_written;
2098 }
2099 #endif /* ROAM_API */
2100
2101 #ifdef WES_SUPPORT
wl_android_get_roam_scan_control(struct net_device * dev,char * command,int total_len)2102 int wl_android_get_roam_scan_control(struct net_device *dev, char *command, int total_len)
2103 {
2104 int error = 0;
2105 int bytes_written = 0;
2106 int mode = 0;
2107
2108 error = get_roamscan_mode(dev, &mode);
2109 if (error) {
2110 ANDROID_ERROR(("wl_android_get_roam_scan_control: Failed to get Scan Control,"
2111 " error = %d\n", error));
2112 return -1;
2113 }
2114
2115 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETROAMSCANCONTROL, mode);
2116
2117 return bytes_written;
2118 }
2119
wl_android_set_roam_scan_control(struct net_device * dev,char * command)2120 int wl_android_set_roam_scan_control(struct net_device *dev, char *command)
2121 {
2122 int error = 0;
2123 int mode = 0;
2124
2125 if (sscanf(command, "%*s %d", &mode) != 1) {
2126 ANDROID_ERROR(("wl_android_set_roam_scan_control: Failed to get Parameter\n"));
2127 return -1;
2128 }
2129
2130 error = set_roamscan_mode(dev, mode);
2131 if (error) {
2132 ANDROID_ERROR(("wl_android_set_roam_scan_control: Failed to set Scan Control %d,"
2133 " error = %d\n",
2134 mode, error));
2135 return -1;
2136 }
2137
2138 return 0;
2139 }
2140
2141 int
wl_android_get_roam_scan_channels(struct net_device * dev,char * command,int total_len,char * cmd)2142 wl_android_get_roam_scan_channels(struct net_device *dev, char *command, int total_len, char *cmd)
2143 {
2144 int bytes_written = 0;
2145 chanspec_t chanspecs[MAX_ROAM_CHANNEL] = {0};
2146 int nchan = 0, i = 0;
2147 int buf_avail, len;
2148
2149 nchan = get_roamscan_chanspec_list(dev, chanspecs);
2150 if (nchan < 0) {
2151 ANDROID_ERROR(("Failed to Set roamscan channels, n_chan = %d\n", nchan));
2152 return BCME_ERROR;
2153 }
2154
2155 bytes_written = snprintf(command, total_len, "%s %d", cmd, nchan);
2156
2157 buf_avail = total_len - bytes_written;
2158 for (i = 0; i < nchan; i++) {
2159 /* A return value of 'buf_avail' or more means that the output was truncated */
2160 len = snprintf(command + bytes_written, buf_avail, " %d",
2161 CHSPEC_CHANNEL(chanspecs[i]));
2162 if (len >= buf_avail) {
2163 ANDROID_ERROR(("Insufficient memory, %d bytes\n", total_len));
2164 ANDROID_ERROR(("Insufficient memory, %d bytes\n", total_len));
2165 bytes_written = -1;
2166 break;
2167 }
2168 /* 'buf_avail' decremented by number of bytes written */
2169 buf_avail -= len;
2170 bytes_written += len;
2171 }
2172 ANDROID_INFO(("%s\n", command));
2173 return bytes_written;
2174 }
2175
2176 #define CHANNEL_IDX 1
2177 int
wl_android_set_roam_scan_channels(struct net_device * dev,char * command)2178 wl_android_set_roam_scan_channels(struct net_device *dev, char *command)
2179 {
2180 int error = BCME_OK, i;
2181 unsigned char *p = (unsigned char *)(command + strlen(CMD_SETROAMSCANCHANNELS) + 1);
2182 uint16 nchan = 0, channel = 0;
2183 chanspec_t chanspecs[MAX_ROAM_CHANNEL] = {0};
2184
2185 nchan = p[0];
2186 if (nchan > MAX_ROAM_CHANNEL) {
2187 ANDROID_ERROR(("Failed to Set roamscan channnels, n_chan = %d\n", nchan));
2188 return BCME_BADARG;
2189 }
2190
2191 for (i = 0; i < nchan; i++) {
2192 channel = p[i + CHANNEL_IDX];
2193 /* Convert chanspec from channel */
2194 chanspecs[i] = wf_channel2chspec(channel, WL_CHANSPEC_BW_20);
2195 }
2196
2197 error = set_roamscan_chanspec_list(dev, nchan, chanspecs);
2198 if (error) {
2199 ANDROID_ERROR(("Failed to Set Scan Channels %d, error = %d\n", p[0], error));
2200 return error;
2201 }
2202
2203 return error;
2204 }
2205
2206 int
wl_android_add_roam_scan_channels(struct net_device * dev,char * command,uint cmdlen)2207 wl_android_add_roam_scan_channels(struct net_device *dev, char *command, uint cmdlen)
2208 {
2209 int i, error = BCME_OK;
2210 char *pcmd, *token;
2211 uint16 nchan = 0, channel = 0;
2212 chanspec_t chanspecs[MAX_ROAM_CHANNEL] = {0};
2213
2214 pcmd = (command + cmdlen + 1);
2215 /* Parse roam channel count */
2216 token = bcmstrtok(&pcmd, " ", NULL);
2217 if (!token) {
2218 ANDROID_ERROR(("Bad argument!\n"));
2219 return BCME_BADARG;
2220 }
2221 nchan = bcm_atoi(token);
2222 if (nchan > MAX_ROAM_CHANNEL) {
2223 ANDROID_ERROR(("Failed to Add roamscan channnels, n_chan = %d\n", nchan));
2224 return BCME_BADARG;
2225 }
2226
2227 for (i = 0; i < nchan; i++) {
2228 /* Parse roam channel list */
2229 token = bcmstrtok(&pcmd, " ", NULL);
2230 if (!token) {
2231 ANDROID_ERROR(("Bad argument!\n"));
2232 return BCME_BADARG;
2233 }
2234 channel = bcm_atoi(token);
2235 /* Convert chanspec from channel */
2236 if (channel > 0) {
2237 chanspecs[i] = wf_channel2chspec(channel, WL_CHANSPEC_BW_20);
2238 }
2239 }
2240
2241 error = add_roamscan_chanspec_list(dev, nchan, chanspecs);
2242 if (error) {
2243 ANDROID_ERROR(("Failed to add Scan Channels %s, error = %d\n", pcmd, error));
2244 }
2245
2246 return error;
2247 }
2248
2249 int
wl_android_get_roam_scan_freqs(struct net_device * dev,char * command,int total_len,char * cmd)2250 wl_android_get_roam_scan_freqs(struct net_device *dev, char *command, int total_len, char *cmd)
2251 {
2252 int bytes_written = 0;
2253 chanspec_t chanspecs[MAX_ROAM_CHANNEL] = {0};
2254 int nchan = 0, i = 0;
2255 int buf_avail, len;
2256 u32 freq = 0;
2257 uint start_factor = 0;
2258
2259 nchan = get_roamscan_chanspec_list(dev, chanspecs);
2260 if (nchan < 0) {
2261 ANDROID_ERROR(("Failed to Get roamscan frequencies, n_chan = %d\n", nchan));
2262 return BCME_ERROR;
2263 }
2264
2265 bytes_written = snprintf(command, total_len, "%s %d", cmd, nchan);
2266
2267 buf_avail = total_len - bytes_written;
2268 for (i = 0; i < nchan; i++) {
2269 start_factor = WF_CHAN_FACTOR_2_4_G;
2270 if (CHSPEC_BAND(chanspecs[i]) == WL_CHANSPEC_BAND_5G) {
2271 start_factor = WF_CHAN_FACTOR_5_G;
2272 } else if (CHSPEC_BAND(chanspecs[i]) == WL_CHANSPEC_BAND_6G) {
2273 start_factor = WF_CHAN_FACTOR_6_G;
2274 }
2275 freq = wf_channel2mhz(CHSPEC_CHANNEL(chanspecs[i]), start_factor);
2276 /* A return value of 'buf_avail' or more means that the output was truncated */
2277 len = snprintf(command + bytes_written, buf_avail, " %d", freq);
2278 if (len >= buf_avail) {
2279 ANDROID_ERROR(("Insufficient memory, %d bytes\n", total_len));
2280 bytes_written = -1;
2281 break;
2282 }
2283 /* 'buf_avail' decremented by number of bytes written */
2284 buf_avail -= len;
2285 bytes_written += len;
2286 }
2287 ANDROID_INFO(("%s\n", command));
2288 return bytes_written;
2289 }
2290
2291 int
wl_android_set_roam_scan_freqs(struct net_device * dev,char * command)2292 wl_android_set_roam_scan_freqs(struct net_device *dev, char *command)
2293 {
2294 int error = BCME_OK, i;
2295 char *pcmd, *token;
2296 uint16 nchan = 0, freq = 0;
2297 chanspec_t chanspecs[MAX_ROAM_CHANNEL] = {0};
2298
2299 pcmd = (command + strlen(CMD_SETROAMSCANFREQS) + 1);
2300 /* Parse roam channel count */
2301 token = bcmstrtok(&pcmd, " ", NULL);
2302 if (!token) {
2303 ANDROID_ERROR(("Bad argument!\n"));
2304 return BCME_BADARG;
2305 }
2306 nchan = bcm_atoi(token);
2307 if (nchan > MAX_ROAM_CHANNEL) {
2308 ANDROID_ERROR(("Failed to Set roamscan frequencies, n_chan = %d\n", nchan));
2309 return BCME_BADARG;
2310 }
2311
2312 for (i = 0; i < nchan; i++) {
2313 /* Parse roam channel list */
2314 token = bcmstrtok(&pcmd, " ", NULL);
2315 if (!token) {
2316 ANDROID_ERROR(("Bad argument!\n"));
2317 return BCME_BADARG;
2318 }
2319 freq = bcm_atoi(token);
2320 /* Convert chanspec from frequency */
2321 chanspecs[i] = wl_freq_to_chanspec(freq);
2322 }
2323
2324 error = set_roamscan_chanspec_list(dev, nchan, chanspecs);
2325 if (error) {
2326 ANDROID_ERROR(("Failed to set Scan Channels %d, error = %d\n", nchan, error));
2327 return error;
2328 }
2329
2330 return error;
2331 }
2332
2333 int
wl_android_add_roam_scan_freqs(struct net_device * dev,char * command,uint cmdlen)2334 wl_android_add_roam_scan_freqs(struct net_device *dev, char *command, uint cmdlen)
2335 {
2336 int i, error = BCME_OK;
2337 char *pcmd, *token;
2338 uint16 nchan = 0, freq = 0;
2339 chanspec_t chanspecs[MAX_ROAM_CHANNEL] = {0};
2340
2341 pcmd = (command + cmdlen + 1);
2342 /* Parse roam channel count */
2343 token = bcmstrtok(&pcmd, " ", NULL);
2344 if (!token) {
2345 ANDROID_ERROR(("Bad argument!\n"));
2346 return BCME_BADARG;
2347 }
2348 nchan = bcm_atoi(token);
2349 if (nchan > MAX_ROAM_CHANNEL) {
2350 ANDROID_ERROR(("Failed to Add roamscan frequencies, n_chan = %d\n", nchan));
2351 return BCME_BADARG;
2352 }
2353
2354 for (i = 0; i < nchan; i++) {
2355 /* Parse roam channel list */
2356 token = bcmstrtok(&pcmd, " ", NULL);
2357 if (!token) {
2358 ANDROID_ERROR(("Bad argument!\n"));
2359 return BCME_BADARG;
2360 }
2361 freq = bcm_atoi(token);
2362 /* Convert chanspec from channel */
2363 if (freq > 0) {
2364 chanspecs[i] = wl_freq_to_chanspec(freq);
2365 }
2366 }
2367
2368 error = add_roamscan_chanspec_list(dev, nchan, chanspecs);
2369 if (error) {
2370 ANDROID_ERROR(("Failed to add Scan Channels %s, error = %d\n", pcmd, error));
2371 }
2372
2373 return error;
2374 }
2375
2376 int
wl_android_get_scan_channel_time(struct net_device * dev,char * command,int total_len)2377 wl_android_get_scan_channel_time(struct net_device *dev, char *command, int total_len)
2378 {
2379 int error = BCME_OK;
2380 int bytes_written = 0;
2381 int time = 0;
2382
2383 error = wldev_ioctl_get(dev, WLC_GET_SCAN_CHANNEL_TIME, &time, sizeof(time));
2384 if (error) {
2385 ANDROID_ERROR(("Failed to get Scan Channel Time, error = %d\n", error));
2386 return BCME_ERROR;
2387 }
2388
2389 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETSCANCHANNELTIME, time);
2390
2391 return bytes_written;
2392 }
2393
2394 int
wl_android_set_scan_channel_time(struct net_device * dev,char * command)2395 wl_android_set_scan_channel_time(struct net_device *dev, char *command)
2396 {
2397 int error = BCME_OK;
2398 int time = 0;
2399
2400 if (sscanf(command, "%*s %d", &time) != 1) {
2401 ANDROID_ERROR(("Failed to get Parameter\n"));
2402 return BCME_ERROR;
2403 }
2404
2405 if (time == 0) {
2406 /* Set default value when Private param is 0. */
2407 time = DHD_SCAN_ASSOC_ACTIVE_TIME;
2408 }
2409 #ifdef CUSTOMER_SCAN_TIMEOUT_SETTING
2410 wl_cfg80211_custom_scan_time(dev, WL_CUSTOM_SCAN_CHANNEL_TIME, time);
2411 error = wldev_ioctl_set(dev, WLC_SET_SCAN_CHANNEL_TIME, &time, sizeof(time));
2412 #endif /* CUSTOMER_SCAN_TIMEOUT_SETTING */
2413 if (error) {
2414 ANDROID_ERROR(("Failed to set Scan Channel Time %d, error = %d\n", time, error));
2415 return BCME_ERROR;
2416 }
2417
2418 return error;
2419 }
2420
2421 int
wl_android_get_scan_unassoc_time(struct net_device * dev,char * command,int total_len)2422 wl_android_get_scan_unassoc_time(struct net_device *dev, char *command, int total_len)
2423 {
2424 int error = BCME_OK;
2425 int bytes_written = 0;
2426 int time = 0;
2427
2428 error = wldev_ioctl_get(dev, WLC_GET_SCAN_UNASSOC_TIME, &time, sizeof(time));
2429 if (error) {
2430 ANDROID_ERROR(("Failed to get Scan Unassoc Time, error = %d\n", error));
2431 return BCME_ERROR;
2432 }
2433
2434 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETSCANUNASSOCTIME, time);
2435
2436 return bytes_written;
2437 }
2438
2439 int
wl_android_set_scan_unassoc_time(struct net_device * dev,char * command)2440 wl_android_set_scan_unassoc_time(struct net_device *dev, char *command)
2441 {
2442 int error = BCME_OK;
2443 int time = 0;
2444
2445 if (sscanf(command, "%*s %d", &time) != 1) {
2446 ANDROID_ERROR(("Failed to get Parameter\n"));
2447 return BCME_ERROR;
2448 }
2449 if (time == 0) {
2450 /* Set default value when Private param is 0. */
2451 time = DHD_SCAN_UNASSOC_ACTIVE_TIME;
2452 }
2453 #ifdef CUSTOMER_SCAN_TIMEOUT_SETTING
2454 wl_cfg80211_custom_scan_time(dev, WL_CUSTOM_SCAN_UNASSOC_TIME, time);
2455 error = wldev_ioctl_set(dev, WLC_SET_SCAN_UNASSOC_TIME, &time, sizeof(time));
2456 #endif /* CUSTOMER_SCAN_TIMEOUT_SETTING */
2457 if (error) {
2458 ANDROID_ERROR(("Failed to set Scan Unassoc Time %d, error = %d\n", time, error));
2459 return BCME_ERROR;
2460 }
2461
2462 return error;
2463 }
2464
2465 int
wl_android_get_scan_passive_time(struct net_device * dev,char * command,int total_len)2466 wl_android_get_scan_passive_time(struct net_device *dev, char *command, int total_len)
2467 {
2468 int error = BCME_OK;
2469 int bytes_written = 0;
2470 int time = 0;
2471
2472 error = wldev_ioctl_get(dev, WLC_GET_SCAN_PASSIVE_TIME, &time, sizeof(time));
2473 if (error) {
2474 ANDROID_ERROR(("Failed to get Scan Passive Time, error = %d\n", error));
2475 return BCME_ERROR;
2476 }
2477
2478 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETSCANPASSIVETIME, time);
2479
2480 return bytes_written;
2481 }
2482
2483 int
wl_android_set_scan_passive_time(struct net_device * dev,char * command)2484 wl_android_set_scan_passive_time(struct net_device *dev, char *command)
2485 {
2486 int error = BCME_OK;
2487 int time = 0;
2488
2489 if (sscanf(command, "%*s %d", &time) != 1) {
2490 ANDROID_ERROR(("Failed to get Parameter\n"));
2491 return BCME_ERROR;
2492 }
2493 if (time == 0) {
2494 /* Set default value when Private param is 0. */
2495 time = DHD_SCAN_PASSIVE_TIME;
2496 }
2497 #ifdef CUSTOMER_SCAN_TIMEOUT_SETTING
2498 wl_cfg80211_custom_scan_time(dev, WL_CUSTOM_SCAN_PASSIVE_TIME, time);
2499 error = wldev_ioctl_set(dev, WLC_SET_SCAN_PASSIVE_TIME, &time, sizeof(time));
2500 #endif /* CUSTOMER_SCAN_TIMEOUT_SETTING */
2501 if (error) {
2502 ANDROID_ERROR(("Failed to set Scan Passive Time %d, error = %d\n", time, error));
2503 return BCME_ERROR;
2504 }
2505
2506 return error;
2507 }
2508
2509 int
wl_android_get_scan_home_time(struct net_device * dev,char * command,int total_len)2510 wl_android_get_scan_home_time(struct net_device *dev, char *command, int total_len)
2511 {
2512 int error = BCME_OK;
2513 int bytes_written = 0;
2514 int time = 0;
2515
2516 error = wldev_ioctl_get(dev, WLC_GET_SCAN_HOME_TIME, &time, sizeof(time));
2517 if (error) {
2518 ANDROID_ERROR(("Failed to get Scan Home Time, error = %d\n", error));
2519 return BCME_ERROR;
2520 }
2521
2522 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETSCANHOMETIME, time);
2523
2524 return bytes_written;
2525 }
2526
wl_android_set_scan_home_time(struct net_device * dev,char * command)2527 int wl_android_set_scan_home_time(struct net_device *dev, char *command)
2528 {
2529 int error = BCME_OK;
2530 int time = 0;
2531
2532 if (sscanf(command, "%*s %d", &time) != 1) {
2533 ANDROID_ERROR(("Failed to get Parameter\n"));
2534 return BCME_ERROR;
2535 }
2536 if (time == 0) {
2537 /* Set default value when Private param is 0. */
2538 time = DHD_SCAN_HOME_TIME;
2539 }
2540 #ifdef CUSTOMER_SCAN_TIMEOUT_SETTING
2541 wl_cfg80211_custom_scan_time(dev, WL_CUSTOM_SCAN_HOME_TIME, time);
2542 error = wldev_ioctl_set(dev, WLC_SET_SCAN_HOME_TIME, &time, sizeof(time));
2543 #endif /* CUSTOMER_SCAN_TIMEOUT_SETTING */
2544 if (error) {
2545 ANDROID_ERROR(("Failed to set Scan Home Time %d, error = %d\n", time, error));
2546 return BCME_ERROR;
2547 }
2548
2549 return error;
2550 }
2551
2552 int
wl_android_get_scan_home_away_time(struct net_device * dev,char * command,int total_len)2553 wl_android_get_scan_home_away_time(struct net_device *dev, char *command, int total_len)
2554 {
2555 int error = BCME_OK;
2556 int bytes_written = 0;
2557 int time = 0;
2558
2559 error = wldev_iovar_getint(dev, "scan_home_away_time", &time);
2560 if (error) {
2561 ANDROID_ERROR(("Failed to get Scan Home Away Time, error = %d\n", error));
2562 return BCME_ERROR;
2563 }
2564
2565 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETSCANHOMEAWAYTIME, time);
2566
2567 return bytes_written;
2568 }
2569
2570 int
wl_android_set_scan_home_away_time(struct net_device * dev,char * command)2571 wl_android_set_scan_home_away_time(struct net_device *dev, char *command)
2572 {
2573 int error = BCME_OK;
2574 int time = 0;
2575
2576 if (sscanf(command, "%*s %d", &time) != 1) {
2577 ANDROID_ERROR(("Failed to get Parameter\n"));
2578 return BCME_ERROR;
2579 }
2580 if (time == 0) {
2581 /* Set default value when Private param is 0. */
2582 time = DHD_SCAN_HOME_AWAY_TIME;
2583 }
2584 #ifdef CUSTOMER_SCAN_TIMEOUT_SETTING
2585 wl_cfg80211_custom_scan_time(dev, WL_CUSTOM_SCAN_HOME_AWAY_TIME, time);
2586 error = wldev_iovar_setint(dev, "scan_home_away_time", time);
2587 #endif /* CUSTOMER_SCAN_TIMEOUT_SETTING */
2588 if (error) {
2589 ANDROID_ERROR(("Failed to set Scan Home Away Time %d, error = %d\n", time, error));
2590 return BCME_ERROR;
2591 }
2592
2593 return error;
2594 }
2595
2596 int
wl_android_get_scan_nprobes(struct net_device * dev,char * command,int total_len)2597 wl_android_get_scan_nprobes(struct net_device *dev, char *command, int total_len)
2598 {
2599 int error = BCME_OK;
2600 int bytes_written = 0;
2601 int num = 0;
2602
2603 error = wldev_ioctl_get(dev, WLC_GET_SCAN_NPROBES, &num, sizeof(num));
2604 if (error) {
2605 ANDROID_ERROR(("Failed to get Scan NProbes, error = %d\n", error));
2606 return BCME_ERROR;
2607 }
2608
2609 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETSCANNPROBES, num);
2610
2611 return bytes_written;
2612 }
2613
2614 int
wl_android_set_scan_nprobes(struct net_device * dev,char * command)2615 wl_android_set_scan_nprobes(struct net_device *dev, char *command)
2616 {
2617 int error = BCME_OK;
2618 int num = 0;
2619
2620 if (sscanf(command, "%*s %d", &num) != 1) {
2621 ANDROID_ERROR(("Failed to get Parameter\n"));
2622 return BCME_ERROR;
2623 }
2624
2625 error = wldev_ioctl_set(dev, WLC_SET_SCAN_NPROBES, &num, sizeof(num));
2626 if (error) {
2627 ANDROID_ERROR(("Failed to set Scan NProbes %d, error = %d\n", num, error));
2628 return BCME_ERROR;
2629 }
2630
2631 return error;
2632 }
2633
2634 int
wl_android_get_scan_dfs_channel_mode(struct net_device * dev,char * command,int total_len)2635 wl_android_get_scan_dfs_channel_mode(struct net_device *dev, char *command, int total_len)
2636 {
2637 int error = BCME_OK;
2638 int bytes_written = 0;
2639 int mode = 0;
2640 int scan_passive_time = 0;
2641
2642 error = wldev_iovar_getint(dev, "scan_passive_time", &scan_passive_time);
2643 if (error) {
2644 ANDROID_ERROR(("Failed to get Passive Time, error = %d\n", error));
2645 return BCME_ERROR;
2646 }
2647
2648 if (scan_passive_time == 0) {
2649 mode = 0;
2650 } else {
2651 mode = 1;
2652 }
2653
2654 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETDFSSCANMODE, mode);
2655
2656 return bytes_written;
2657 }
2658
2659 int
wl_android_set_scan_dfs_channel_mode(struct net_device * dev,char * command)2660 wl_android_set_scan_dfs_channel_mode(struct net_device *dev, char *command)
2661 {
2662 int error = BCME_OK;
2663 int mode = 0;
2664 int scan_passive_time = 0;
2665
2666 if (sscanf(command, "%*s %d", &mode) != 1) {
2667 ANDROID_ERROR(("Failed to get Parameter\n"));
2668 return BCME_ERROR;
2669 }
2670
2671 if (mode == 1) {
2672 scan_passive_time = DHD_SCAN_PASSIVE_TIME;
2673 } else if (mode == 0) {
2674 scan_passive_time = 0;
2675 } else {
2676 ANDROID_ERROR(("Failed to set Scan DFS channel mode %d\n", mode));
2677 return BCME_ERROR;
2678 }
2679 error = wldev_iovar_setint(dev, "scan_passive_time", scan_passive_time);
2680 if (error) {
2681 ANDROID_ERROR(("Failed to set Scan Passive Time %d, error = %d\n",
2682 scan_passive_time, error));
2683 return BCME_ERROR;
2684 }
2685
2686 return error;
2687 }
2688
2689 #define JOINPREFFER_BUF_SIZE 12
2690
2691 static int
wl_android_set_join_prefer(struct net_device * dev,char * command)2692 wl_android_set_join_prefer(struct net_device *dev, char *command)
2693 {
2694 int error = BCME_OK;
2695 char smbuf[WLC_IOCTL_SMLEN];
2696 uint8 buf[JOINPREFFER_BUF_SIZE];
2697 char *pcmd;
2698 int total_len_left;
2699 int i;
2700 char hex[] = "XX";
2701 #ifdef WBTEXT
2702 int turn_on = OFF;
2703 char clear[] = { 0x01, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00 };
2704 #endif /* WBTEXT */
2705
2706 pcmd = command + strlen(CMD_SETJOINPREFER) + 1;
2707 total_len_left = strlen(pcmd);
2708
2709 bzero(buf, sizeof(buf));
2710
2711 if (total_len_left != JOINPREFFER_BUF_SIZE << 1) {
2712 ANDROID_ERROR(("wl_android_set_join_prefer: Failed to get Parameter\n"));
2713 return BCME_ERROR;
2714 }
2715
2716 /* Store the MSB first, as required by join_pref */
2717 for (i = 0; i < JOINPREFFER_BUF_SIZE; i++) {
2718 hex[0] = *pcmd++;
2719 hex[1] = *pcmd++;
2720 buf[i] = (uint8)simple_strtoul(hex, NULL, 16);
2721 }
2722
2723 #ifdef WBTEXT
2724 /* Set WBTEXT mode */
2725 turn_on = memcmp(buf, clear, sizeof(buf)) == 0 ? TRUE : FALSE;
2726 error = wl_android_wbtext_enable(dev, turn_on);
2727 if (error) {
2728 ANDROID_ERROR(("Failed to set WBTEXT(%d) = %s\n",
2729 error, (turn_on ? "Enable" : "Disable")));
2730 }
2731 #endif /* WBTEXT */
2732
2733 prhex("join pref", (uint8 *)buf, JOINPREFFER_BUF_SIZE);
2734 error = wldev_iovar_setbuf(dev, "join_pref", buf, JOINPREFFER_BUF_SIZE,
2735 smbuf, sizeof(smbuf), NULL);
2736 if (error) {
2737 ANDROID_ERROR(("Failed to set join_pref, error = %d\n", error));
2738 }
2739
2740 return error;
2741 }
2742
wl_android_send_action_frame(struct net_device * dev,char * command,int total_len)2743 int wl_android_send_action_frame(struct net_device *dev, char *command, int total_len)
2744 {
2745 int error = -1;
2746 android_wifi_af_params_t *params = NULL;
2747 wl_action_frame_t *action_frame = NULL;
2748 wl_af_params_t *af_params = NULL;
2749 char *smbuf = NULL;
2750 struct ether_addr tmp_bssid;
2751 int tmp_channel = 0;
2752 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2753
2754 if (total_len <
2755 (strlen(CMD_SENDACTIONFRAME) + 1 + sizeof(android_wifi_af_params_t))) {
2756 ANDROID_ERROR(("wl_android_send_action_frame: Invalid parameters \n"));
2757 goto send_action_frame_out;
2758 }
2759
2760 params = (android_wifi_af_params_t *)(command + strlen(CMD_SENDACTIONFRAME) + 1);
2761
2762 if ((uint16)params->len > ANDROID_WIFI_ACTION_FRAME_SIZE) {
2763 ANDROID_ERROR(("wl_android_send_action_frame: Requested action frame len"
2764 " was out of range(%d)\n",
2765 params->len));
2766 goto send_action_frame_out;
2767 }
2768
2769 smbuf = (char *)MALLOC(cfg->osh, WLC_IOCTL_MAXLEN);
2770 if (smbuf == NULL) {
2771 ANDROID_ERROR(("wl_android_send_action_frame: failed to allocated memory %d bytes\n",
2772 WLC_IOCTL_MAXLEN));
2773 goto send_action_frame_out;
2774 }
2775
2776 af_params = (wl_af_params_t *)MALLOCZ(cfg->osh, WL_WIFI_AF_PARAMS_SIZE);
2777 if (af_params == NULL) {
2778 ANDROID_ERROR(("wl_android_send_action_frame: unable to allocate frame\n"));
2779 goto send_action_frame_out;
2780 }
2781
2782 bzero(&tmp_bssid, ETHER_ADDR_LEN);
2783 if (bcm_ether_atoe((const char *)params->bssid, (struct ether_addr *)&tmp_bssid) == 0) {
2784 bzero(&tmp_bssid, ETHER_ADDR_LEN);
2785
2786 error = wldev_ioctl_get(dev, WLC_GET_BSSID, &tmp_bssid, ETHER_ADDR_LEN);
2787 if (error) {
2788 bzero(&tmp_bssid, ETHER_ADDR_LEN);
2789 ANDROID_ERROR(("wl_android_send_action_frame: failed to get bssid,"
2790 " error=%d\n", error));
2791 goto send_action_frame_out;
2792 }
2793 }
2794
2795 if (params->channel < 0) {
2796 struct channel_info ci;
2797 bzero(&ci, sizeof(ci));
2798 error = wldev_ioctl_get(dev, WLC_GET_CHANNEL, &ci, sizeof(ci));
2799 if (error) {
2800 ANDROID_ERROR(("wl_android_send_action_frame: failed to get channel,"
2801 " error=%d\n", error));
2802 goto send_action_frame_out;
2803 }
2804
2805 tmp_channel = ci.hw_channel;
2806 }
2807 else {
2808 tmp_channel = params->channel;
2809 }
2810
2811 af_params->channel = tmp_channel;
2812 af_params->dwell_time = params->dwell_time;
2813 memcpy(&af_params->BSSID, &tmp_bssid, ETHER_ADDR_LEN);
2814 action_frame = &af_params->action_frame;
2815
2816 action_frame->packetId = 0;
2817 memcpy(&action_frame->da, &tmp_bssid, ETHER_ADDR_LEN);
2818 action_frame->len = (uint16)params->len;
2819 memcpy(action_frame->data, params->data, action_frame->len);
2820
2821 error = wldev_iovar_setbuf(dev, "actframe", af_params,
2822 sizeof(wl_af_params_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
2823 if (error) {
2824 ANDROID_ERROR(("wl_android_send_action_frame: failed to set action frame,"
2825 " error=%d\n", error));
2826 }
2827
2828 send_action_frame_out:
2829 if (af_params) {
2830 MFREE(cfg->osh, af_params, WL_WIFI_AF_PARAMS_SIZE);
2831 }
2832
2833 if (smbuf) {
2834 MFREE(cfg->osh, smbuf, WLC_IOCTL_MAXLEN);
2835 }
2836
2837 if (error)
2838 return -1;
2839 else
2840 return 0;
2841 }
2842
2843 int
wl_android_reassoc(struct net_device * dev,char * command,int total_len)2844 wl_android_reassoc(struct net_device *dev, char *command, int total_len)
2845 {
2846 int error = BCME_OK;
2847 android_wifi_reassoc_params_t *params = NULL;
2848 chanspec_t channel;
2849 u32 params_size;
2850 wl_reassoc_params_t reassoc_params;
2851 char pcmd[WL_PRIV_CMD_LEN + 1];
2852
2853 sscanf(command, "%"S(WL_PRIV_CMD_LEN)"s *", pcmd);
2854 if (total_len < (strlen(pcmd) + 1 + sizeof(android_wifi_reassoc_params_t))) {
2855 ANDROID_ERROR(("Invalid parameters %s\n", command));
2856 return BCME_ERROR;
2857 }
2858 params = (android_wifi_reassoc_params_t *)(command + strlen(pcmd) + 1);
2859
2860 bzero(&reassoc_params, WL_REASSOC_PARAMS_FIXED_SIZE);
2861
2862 if (bcm_ether_atoe((const char *)params->bssid,
2863 (struct ether_addr *)&reassoc_params.bssid) == 0) {
2864 ANDROID_ERROR(("Invalid bssid \n"));
2865 return BCME_BADARG;
2866 }
2867
2868 if (params->channel < 0) {
2869 ANDROID_ERROR(("Invalid Channel %d\n", params->channel));
2870 return BCME_BADARG;
2871 }
2872
2873 reassoc_params.chanspec_num = 1;
2874
2875 channel = params->channel;
2876 if (CHANNEL_IS_2G(channel) || CHANNEL_IS_5G(channel)) {
2877 /* If reassoc Param is BSSID and Channel */
2878 reassoc_params.chanspec_list[0] = wf_channel2chspec(channel, WL_CHANSPEC_BW_20);
2879 } else {
2880 /* If reassoc Param is BSSID and Frequency */
2881 reassoc_params.chanspec_list[0] = wl_freq_to_chanspec(channel);
2882 }
2883 params_size = WL_REASSOC_PARAMS_FIXED_SIZE + sizeof(chanspec_t);
2884
2885 error = wldev_ioctl_set(dev, WLC_REASSOC, &reassoc_params, params_size);
2886 if (error) {
2887 ANDROID_ERROR(("failed to reassoc, error=%d\n", error));
2888 return error;
2889 }
2890 return error;
2891 }
2892
wl_android_get_wes_mode(struct net_device * dev,char * command,int total_len)2893 int wl_android_get_wes_mode(struct net_device *dev, char *command, int total_len)
2894 {
2895 int bytes_written = 0;
2896 int mode = 0;
2897
2898 mode = wl_cfg80211_get_wes_mode(dev);
2899
2900 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETWESMODE, mode);
2901
2902 return bytes_written;
2903 }
2904
wl_android_set_wes_mode(struct net_device * dev,char * command)2905 int wl_android_set_wes_mode(struct net_device *dev, char *command)
2906 {
2907 int error = 0;
2908 int mode = 0;
2909
2910 if (sscanf(command, "%*s %d", &mode) != 1) {
2911 ANDROID_ERROR(("wl_android_set_wes_mode: Failed to get Parameter\n"));
2912 return -1;
2913 }
2914
2915 error = wl_cfg80211_set_wes_mode(dev, mode);
2916 if (error) {
2917 ANDROID_ERROR(("wl_android_set_wes_mode: Failed to set WES Mode %d, error = %d\n",
2918 mode, error));
2919 return -1;
2920 }
2921
2922 return 0;
2923 }
2924
2925 int
wl_android_get_ncho_mode(struct net_device * dev,char * command,int total_len)2926 wl_android_get_ncho_mode(struct net_device *dev, char *command, int total_len)
2927 {
2928 int bytes_written = 0;
2929 int mode = 0;
2930
2931 mode = wl_cfg80211_get_ncho_mode(dev);
2932
2933 bytes_written = snprintf(command, total_len, "%s %d", CMD_GETNCHOMODE, mode);
2934
2935 return bytes_written;
2936 }
2937
2938 int
wl_android_set_ncho_mode(struct net_device * dev,int mode)2939 wl_android_set_ncho_mode(struct net_device *dev, int mode)
2940 {
2941 char cmd[WLC_IOCTL_SMLEN];
2942 int error = BCME_OK;
2943
2944 #ifdef WBTEXT
2945 /* Set WBTEXT mode */
2946 error = wl_android_wbtext_enable(dev, !mode);
2947 if (error) {
2948 ANDROID_ERROR(("Failed to set WBTEXT(%d) = %s\n",
2949 error, (mode ? "Disable" : "Enable")));
2950 }
2951 #endif /* WBTEXT */
2952 /* Set Piority roam mode */
2953 error = wl_android_priority_roam_enable(dev, !mode);
2954 if (error) {
2955 ANDROID_ERROR(("Failed to set Priority Roam(%d) = %s\n",
2956 error, (mode ? "Disable" : "Enable")));
2957 }
2958 #ifdef CONFIG_SILENT_ROAM
2959 /* Set Silent roam mode */
2960 error = wl_android_sroam_turn_on(dev, !mode);
2961 if (error) {
2962 ANDROID_ERROR(("Failed to set SROAM(%d) = %s\n",
2963 error, (mode ? "Disable" : "Enable")));
2964 }
2965 #endif /* CONFIG_SILENT_ROAM */
2966 /* Set RCROAM(ROAMEXT) mode */
2967 error = wl_android_rcroam_turn_on(dev, !mode);
2968 if (error) {
2969 ANDROID_ERROR(("Failed to set RCROAM(%d) = %s\n",
2970 error, (mode ? "Disable" : "Enable")));
2971 }
2972
2973 if (mode == OFF) {
2974 /* restore NCHO set parameters */
2975 bzero(cmd, WLC_IOCTL_SMLEN);
2976 snprintf(cmd, WLC_IOCTL_SMLEN, "%s", CMD_RESTORE_SCAN_PARAMS);
2977 error = wl_android_default_set_scan_params(dev, cmd, WLC_IOCTL_SMLEN);
2978 if (error) {
2979 ANDROID_ERROR(("Failed to set RESTORE_SCAN_PARAMS(%d)\n", error));
2980 }
2981
2982 wl_cfg80211_set_wes_mode(dev, OFF);
2983 set_roamscan_mode(dev, ROAMSCAN_MODE_NORMAL);
2984 }
2985
2986 error = wl_cfg80211_set_ncho_mode(dev, mode);
2987 if (error) {
2988 ANDROID_ERROR(("Failed to set NCHO Mode %d, error = %d\n", mode, error));
2989 }
2990
2991 return error;
2992 }
2993
2994 static int
wl_android_set_pmk(struct net_device * dev,char * command,int total_len)2995 wl_android_set_pmk(struct net_device *dev, char *command, int total_len)
2996 {
2997 uchar pmk[33];
2998 int error = 0;
2999 char smbuf[WLC_IOCTL_SMLEN];
3000 dhd_pub_t *dhdp;
3001 #ifdef OKC_DEBUG
3002 int i = 0;
3003 #endif
3004
3005 if (total_len < (strlen("SET_PMK ") + 32)) {
3006 ANDROID_ERROR(("wl_android_set_pmk: Invalid argument\n"));
3007 return -1;
3008 }
3009
3010 dhdp = wl_cfg80211_get_dhdp(dev);
3011 if (!dhdp) {
3012 ANDROID_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
3013 return -1;
3014 }
3015
3016 bzero(pmk, sizeof(pmk));
3017 DHD_STATLOG_CTRL(dhdp, ST(INSTALL_OKC_PMK), dhd_net2idx(dhdp->info, dev), 0);
3018 memcpy((char *)pmk, command + strlen("SET_PMK "), 32);
3019 error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL);
3020 if (error) {
3021 ANDROID_ERROR(("Failed to set PMK for OKC, error = %d\n", error));
3022 }
3023 #ifdef OKC_DEBUG
3024 ANDROID_ERROR(("PMK is "));
3025 for (i = 0; i < 32; i++)
3026 ANDROID_ERROR(("%02X ", pmk[i]));
3027
3028 ANDROID_ERROR(("\n"));
3029 #endif
3030 return error;
3031 }
3032
3033 static int
wl_android_okc_enable(struct net_device * dev,char * command)3034 wl_android_okc_enable(struct net_device *dev, char *command)
3035 {
3036 int error = 0;
3037 char okc_enable = 0;
3038
3039 okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0';
3040 error = wldev_iovar_setint(dev, "okc_enable", okc_enable);
3041 if (error) {
3042 ANDROID_ERROR(("Failed to %s OKC, error = %d\n",
3043 okc_enable ? "enable" : "disable", error));
3044 }
3045
3046 return error;
3047 }
3048
3049 static int
wl_android_legacy_check_command(struct net_device * dev,char * command)3050 wl_android_legacy_check_command(struct net_device *dev, char *command)
3051 {
3052 int cnt = 0;
3053
3054 while (strlen(legacy_cmdlist[cnt]) > 0) {
3055 if (strnicmp(command, legacy_cmdlist[cnt], strlen(legacy_cmdlist[cnt])) == 0) {
3056 char cmd[WL_PRIV_CMD_LEN + 1];
3057 sscanf(command, "%"S(WL_PRIV_CMD_LEN)"s ", cmd);
3058 if (strlen(legacy_cmdlist[cnt]) == strlen(cmd)) {
3059 return TRUE;
3060 }
3061 }
3062 cnt++;
3063 }
3064 return FALSE;
3065 }
3066
3067 static int
wl_android_legacy_private_command(struct net_device * net,char * command,int total_len)3068 wl_android_legacy_private_command(struct net_device *net, char *command, int total_len)
3069 {
3070 int bytes_written = 0;
3071 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
3072
3073 if (cfg->ncho_mode == ON) {
3074 ANDROID_ERROR(("Enabled NCHO mode\n"));
3075 /* In order to avoid Sequential error HANG event. */
3076 return BCME_UNSUPPORTED;
3077 }
3078
3079 /* ROAMSCAN CHANNELS Add, Get Command */
3080 if (strnicmp(command, CMD_ADDROAMSCANCHLEGACY, strlen(CMD_ADDROAMSCANCHLEGACY)) == 0) {
3081 bytes_written = wl_android_add_roam_scan_channels(net, command,
3082 strlen(CMD_ADDROAMSCANCHLEGACY));
3083 }
3084 else if (strnicmp(command, CMD_GETROAMSCANCHLEGACY, strlen(CMD_GETROAMSCANCHLEGACY)) == 0) {
3085 bytes_written = wl_android_get_roam_scan_channels(net, command, total_len,
3086 CMD_GETROAMSCANCHLEGACY);
3087 }
3088 /* ROAMSCAN FREQUENCIES Add, Get Command */
3089 else if (strnicmp(command, CMD_ADDROAMSCANFQLEGACY, strlen(CMD_ADDROAMSCANFQLEGACY)) == 0) {
3090 bytes_written = wl_android_add_roam_scan_freqs(net, command,
3091 strlen(CMD_ADDROAMSCANFQLEGACY));
3092 }
3093 else if (strnicmp(command, CMD_GETROAMSCANFQLEGACY, strlen(CMD_GETROAMSCANFQLEGACY)) == 0) {
3094 bytes_written = wl_android_get_roam_scan_freqs(net, command, total_len,
3095 CMD_GETROAMSCANFQLEGACY);
3096 }
3097 else if (strnicmp(command, CMD_GETROAMTRIGLEGACY, strlen(CMD_GETROAMTRIGLEGACY)) == 0) {
3098 bytes_written = wl_android_get_roam_trigger(net, command, total_len);
3099 }
3100 else if (strnicmp(command, CMD_SETROAMTRIGLEGACY, strlen(CMD_SETROAMTRIGLEGACY)) == 0) {
3101 bytes_written = wl_android_set_roam_trigger_legacy(net, command);
3102 }
3103 else if (strnicmp(command, CMD_REASSOCLEGACY, strlen(CMD_REASSOCLEGACY)) == 0) {
3104 bytes_written = wl_android_reassoc(net, command, total_len);
3105 }
3106 else if (strnicmp(command, CMD_GETSCANCHANNELTIMELEGACY,
3107 strlen(CMD_GETSCANCHANNELTIMELEGACY)) == 0) {
3108 bytes_written = wl_android_get_scan_channel_time(net, command, total_len);
3109 }
3110 else if (strnicmp(command, CMD_SETSCANCHANNELTIMELEGACY,
3111 strlen(CMD_SETSCANCHANNELTIMELEGACY)) == 0) {
3112 bytes_written = wl_android_set_scan_channel_time(net, command);
3113 }
3114 else if (strnicmp(command, CMD_GETSCANUNASSOCTIMELEGACY,
3115 strlen(CMD_GETSCANUNASSOCTIMELEGACY)) == 0) {
3116 bytes_written = wl_android_get_scan_unassoc_time(net, command, total_len);
3117 }
3118 else if (strnicmp(command, CMD_SETSCANUNASSOCTIMELEGACY,
3119 strlen(CMD_SETSCANUNASSOCTIMELEGACY)) == 0) {
3120 bytes_written = wl_android_set_scan_unassoc_time(net, command);
3121 }
3122 else if (strnicmp(command, CMD_GETSCANPASSIVETIMELEGACY,
3123 strlen(CMD_GETSCANPASSIVETIMELEGACY)) == 0) {
3124 bytes_written = wl_android_get_scan_passive_time(net, command, total_len);
3125 }
3126 else if (strnicmp(command, CMD_SETSCANPASSIVETIMELEGACY,
3127 strlen(CMD_SETSCANPASSIVETIMELEGACY)) == 0) {
3128 bytes_written = wl_android_set_scan_passive_time(net, command);
3129 }
3130 else if (strnicmp(command, CMD_GETSCANHOMETIMELEGACY,
3131 strlen(CMD_GETSCANHOMETIMELEGACY)) == 0) {
3132 bytes_written = wl_android_get_scan_home_time(net, command, total_len);
3133 }
3134 else if (strnicmp(command, CMD_SETSCANHOMETIMELEGACY,
3135 strlen(CMD_SETSCANHOMETIMELEGACY)) == 0) {
3136 bytes_written = wl_android_set_scan_home_time(net, command);
3137 }
3138 else if (strnicmp(command, CMD_GETSCANHOMEAWAYTIMELEGACY,
3139 strlen(CMD_GETSCANHOMEAWAYTIMELEGACY)) == 0) {
3140 bytes_written = wl_android_get_scan_home_away_time(net, command, total_len);
3141 }
3142 else if (strnicmp(command, CMD_SETSCANHOMEAWAYTIMELEGACY,
3143 strlen(CMD_SETSCANHOMEAWAYTIMELEGACY)) == 0) {
3144 bytes_written = wl_android_set_scan_home_away_time(net, command);
3145 }
3146 else {
3147 ANDROID_ERROR(("Unknown NCHO PRIVATE command %s - ignored\n", command));
3148 bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
3149 }
3150
3151 return bytes_written;
3152 }
3153
3154 static int
wl_android_ncho_check_command(struct net_device * dev,char * command)3155 wl_android_ncho_check_command(struct net_device *dev, char *command)
3156 {
3157 int cnt = 0;
3158
3159 while (strlen(ncho_cmdlist[cnt]) > 0) {
3160 if (strnicmp(command, ncho_cmdlist[cnt], strlen(ncho_cmdlist[cnt])) == 0) {
3161 char cmd[WL_PRIV_CMD_LEN + 1];
3162 sscanf(command, "%"S(WL_PRIV_CMD_LEN)"s ", cmd);
3163 if (strlen(ncho_cmdlist[cnt]) == strlen(cmd)) {
3164 return TRUE;
3165 }
3166 }
3167 cnt++;
3168 }
3169 return FALSE;
3170 }
3171
3172 static int
wl_android_ncho_private_command(struct net_device * net,char * command,int total_len)3173 wl_android_ncho_private_command(struct net_device *net, char *command, int total_len)
3174 {
3175 int bytes_written = 0;
3176 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
3177
3178 if (cfg->ncho_mode == OFF) {
3179 ANDROID_ERROR(("Disable NCHO mode\n"));
3180 /* In order to avoid Sequential error HANG event. */
3181 return BCME_UNSUPPORTED;
3182 }
3183
3184 #ifdef ROAM_API
3185 if (strnicmp(command, CMD_ROAMTRIGGER_SET, strlen(CMD_ROAMTRIGGER_SET)) == 0) {
3186 bytes_written = wl_android_set_roam_trigger(net, command);
3187 } else if (strnicmp(command, CMD_ROAMTRIGGER_GET, strlen(CMD_ROAMTRIGGER_GET)) == 0) {
3188 bytes_written = wl_android_get_roam_trigger(net, command, total_len);
3189 } else if (strnicmp(command, CMD_ROAMDELTA_SET, strlen(CMD_ROAMDELTA_SET)) == 0) {
3190 bytes_written = wl_android_set_roam_delta(net, command);
3191 } else if (strnicmp(command, CMD_ROAMDELTA_GET, strlen(CMD_ROAMDELTA_GET)) == 0) {
3192 bytes_written = wl_android_get_roam_delta(net, command, total_len);
3193 } else if (strnicmp(command, CMD_ROAMSCANPERIOD_SET,
3194 strlen(CMD_ROAMSCANPERIOD_SET)) == 0) {
3195 bytes_written = wl_android_set_roam_scan_period(net, command);
3196 } else if (strnicmp(command, CMD_ROAMSCANPERIOD_GET,
3197 strlen(CMD_ROAMSCANPERIOD_GET)) == 0) {
3198 bytes_written = wl_android_get_roam_scan_period(net, command, total_len);
3199 } else if (strnicmp(command, CMD_FULLROAMSCANPERIOD_SET,
3200 strlen(CMD_FULLROAMSCANPERIOD_SET)) == 0) {
3201 bytes_written = wl_android_set_full_roam_scan_period(net, command);
3202 } else if (strnicmp(command, CMD_FULLROAMSCANPERIOD_GET,
3203 strlen(CMD_FULLROAMSCANPERIOD_GET)) == 0) {
3204 bytes_written = wl_android_get_full_roam_scan_period(net, command, total_len);
3205 } else if (strnicmp(command, CMD_COUNTRYREV_SET, strlen(CMD_COUNTRYREV_SET)) == 0) {
3206 bytes_written = wl_android_set_country_rev(net, command);
3207 #ifdef FCC_PWR_LIMIT_2G
3208 if (wldev_iovar_setint(net, "fccpwrlimit2g", FALSE)) {
3209 ANDROID_ERROR(("fccpwrlimit2g deactivation is failed\n"));
3210 } else {
3211 ANDROID_ERROR(("fccpwrlimit2g is deactivated\n"));
3212 }
3213 #endif /* FCC_PWR_LIMIT_2G */
3214 } else if (strnicmp(command, CMD_COUNTRYREV_GET, strlen(CMD_COUNTRYREV_GET)) == 0) {
3215 bytes_written = wl_android_get_country_rev(net, command, total_len);
3216 } else
3217 #endif /* ROAM_API */
3218 if (strnicmp(command, CMD_GETROAMSCANCONTROL, strlen(CMD_GETROAMSCANCONTROL)) == 0) {
3219 bytes_written = wl_android_get_roam_scan_control(net, command, total_len);
3220 }
3221 else if (strnicmp(command, CMD_SETROAMSCANCONTROL, strlen(CMD_SETROAMSCANCONTROL)) == 0) {
3222 bytes_written = wl_android_set_roam_scan_control(net, command);
3223 }
3224 /* ROAMSCAN CHANNELS Add, Get, Set Command */
3225 else if (strnicmp(command, CMD_ADDROAMSCANCHANNELS, strlen(CMD_ADDROAMSCANCHANNELS)) == 0) {
3226 bytes_written = wl_android_add_roam_scan_channels(net, command,
3227 strlen(CMD_ADDROAMSCANCHANNELS));
3228 }
3229 else if (strnicmp(command, CMD_GETROAMSCANCHANNELS, strlen(CMD_GETROAMSCANCHANNELS)) == 0) {
3230 bytes_written = wl_android_get_roam_scan_channels(net, command, total_len,
3231 CMD_GETROAMSCANCHANNELS);
3232 }
3233 else if (strnicmp(command, CMD_SETROAMSCANCHANNELS, strlen(CMD_SETROAMSCANCHANNELS)) == 0) {
3234 bytes_written = wl_android_set_roam_scan_channels(net, command);
3235 }
3236 /* ROAMSCAN FREQUENCIES Add, Get, Set Command */
3237 else if (strnicmp(command, CMD_ADDROAMSCANFREQS, strlen(CMD_ADDROAMSCANFREQS)) == 0) {
3238 bytes_written = wl_android_add_roam_scan_freqs(net, command,
3239 strlen(CMD_ADDROAMSCANFREQS));
3240 }
3241 else if (strnicmp(command, CMD_GETROAMSCANFREQS, strlen(CMD_GETROAMSCANFREQS)) == 0) {
3242 bytes_written = wl_android_get_roam_scan_freqs(net, command, total_len,
3243 CMD_GETROAMSCANFREQS);
3244 }
3245 else if (strnicmp(command, CMD_SETROAMSCANFREQS, strlen(CMD_SETROAMSCANFREQS)) == 0) {
3246 bytes_written = wl_android_set_roam_scan_freqs(net, command);
3247 }
3248 else if (strnicmp(command, CMD_SENDACTIONFRAME, strlen(CMD_SENDACTIONFRAME)) == 0) {
3249 bytes_written = wl_android_send_action_frame(net, command, total_len);
3250 }
3251 else if (strnicmp(command, CMD_REASSOC, strlen(CMD_REASSOC)) == 0) {
3252 bytes_written = wl_android_reassoc(net, command, total_len);
3253 }
3254 else if (strnicmp(command, CMD_GETSCANCHANNELTIME, strlen(CMD_GETSCANCHANNELTIME)) == 0) {
3255 bytes_written = wl_android_get_scan_channel_time(net, command, total_len);
3256 }
3257 else if (strnicmp(command, CMD_SETSCANCHANNELTIME, strlen(CMD_SETSCANCHANNELTIME)) == 0) {
3258 bytes_written = wl_android_set_scan_channel_time(net, command);
3259 }
3260 else if (strnicmp(command, CMD_GETSCANUNASSOCTIME, strlen(CMD_GETSCANUNASSOCTIME)) == 0) {
3261 bytes_written = wl_android_get_scan_unassoc_time(net, command, total_len);
3262 }
3263 else if (strnicmp(command, CMD_SETSCANUNASSOCTIME, strlen(CMD_SETSCANUNASSOCTIME)) == 0) {
3264 bytes_written = wl_android_set_scan_unassoc_time(net, command);
3265 }
3266 else if (strnicmp(command, CMD_GETSCANPASSIVETIME, strlen(CMD_GETSCANPASSIVETIME)) == 0) {
3267 bytes_written = wl_android_get_scan_passive_time(net, command, total_len);
3268 }
3269 else if (strnicmp(command, CMD_SETSCANPASSIVETIME, strlen(CMD_SETSCANPASSIVETIME)) == 0) {
3270 bytes_written = wl_android_set_scan_passive_time(net, command);
3271 }
3272 else if (strnicmp(command, CMD_GETSCANHOMETIME, strlen(CMD_GETSCANHOMETIME)) == 0) {
3273 bytes_written = wl_android_get_scan_home_time(net, command, total_len);
3274 }
3275 else if (strnicmp(command, CMD_SETSCANHOMETIME, strlen(CMD_SETSCANHOMETIME)) == 0) {
3276 bytes_written = wl_android_set_scan_home_time(net, command);
3277 }
3278 else if (strnicmp(command, CMD_GETSCANHOMEAWAYTIME, strlen(CMD_GETSCANHOMEAWAYTIME)) == 0) {
3279 bytes_written = wl_android_get_scan_home_away_time(net, command, total_len);
3280 }
3281 else if (strnicmp(command, CMD_SETSCANHOMEAWAYTIME, strlen(CMD_SETSCANHOMEAWAYTIME)) == 0) {
3282 bytes_written = wl_android_set_scan_home_away_time(net, command);
3283 }
3284 else if (strnicmp(command, CMD_GETSCANNPROBES, strlen(CMD_GETSCANNPROBES)) == 0) {
3285 bytes_written = wl_android_get_scan_nprobes(net, command, total_len);
3286 }
3287 else if (strnicmp(command, CMD_SETSCANNPROBES, strlen(CMD_SETSCANNPROBES)) == 0) {
3288 bytes_written = wl_android_set_scan_nprobes(net, command);
3289 }
3290 else if (strnicmp(command, CMD_GETDFSSCANMODE, strlen(CMD_GETDFSSCANMODE)) == 0) {
3291 bytes_written = wl_android_get_scan_dfs_channel_mode(net, command, total_len);
3292 }
3293 else if (strnicmp(command, CMD_SETDFSSCANMODE, strlen(CMD_SETDFSSCANMODE)) == 0) {
3294 bytes_written = wl_android_set_scan_dfs_channel_mode(net, command);
3295 }
3296 else if (strnicmp(command, CMD_SETJOINPREFER, strlen(CMD_SETJOINPREFER)) == 0) {
3297 bytes_written = wl_android_set_join_prefer(net, command);
3298 }
3299 else if (strnicmp(command, CMD_GETWESMODE, strlen(CMD_GETWESMODE)) == 0) {
3300 bytes_written = wl_android_get_wes_mode(net, command, total_len);
3301 }
3302 else if (strnicmp(command, CMD_SETWESMODE, strlen(CMD_SETWESMODE)) == 0) {
3303 bytes_written = wl_android_set_wes_mode(net, command);
3304 }
3305 else {
3306 ANDROID_ERROR(("Unknown NCHO PRIVATE command %s - ignored\n", command));
3307 bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
3308 }
3309
3310 return bytes_written;
3311 }
3312 #endif /* WES_SUPPORT */
3313
3314 #if defined(SUPPORT_RESTORE_SCAN_PARAMS) || defined(WES_SUPPORT)
3315 static int
wl_android_default_set_scan_params(struct net_device * dev,char * command,int total_len)3316 wl_android_default_set_scan_params(struct net_device *dev, char *command, int total_len)
3317 {
3318 int error = 0;
3319 uint error_cnt = 0;
3320 int cnt = 0;
3321 char restore_command[WLC_IOCTL_SMLEN];
3322
3323 while (strlen(restore_params[cnt].command) > 0 && restore_params[cnt].cmd_handler) {
3324 snprintf(restore_command, WLC_IOCTL_SMLEN, "%s %d",
3325 restore_params[cnt].command, restore_params[cnt].parameter);
3326 if (restore_params[cnt].cmd_type == RESTORE_TYPE_PRIV_CMD) {
3327 error = restore_params[cnt].cmd_handler(dev, restore_command);
3328 } else if (restore_params[cnt].cmd_type == RESTORE_TYPE_PRIV_CMD_WITH_LEN) {
3329 error = restore_params[cnt].cmd_handler_w_len(dev,
3330 restore_command, total_len);
3331 } else {
3332 ANDROID_ERROR(("Unknown restore command handler\n"));
3333 error = -1;
3334 }
3335 if (error) {
3336 ANDROID_ERROR(("Failed to restore scan parameters %s, error : %d\n",
3337 restore_command, error));
3338 error_cnt++;
3339 }
3340 cnt++;
3341 }
3342 if (error_cnt > 0) {
3343 ANDROID_ERROR(("Got %d error(s) while restoring scan parameters\n",
3344 error_cnt));
3345 error = -1;
3346 }
3347 return error;
3348 }
3349 #endif /* SUPPORT_RESTORE_SCAN_PARAMS || WES_SUPPORT */
3350
3351 #ifdef WLTDLS
wl_android_tdls_reset(struct net_device * dev)3352 int wl_android_tdls_reset(struct net_device *dev)
3353 {
3354 int ret = 0;
3355 ret = dhd_tdls_enable(dev, false, false, NULL);
3356 if (ret < 0) {
3357 ANDROID_ERROR(("Disable tdls failed. %d\n", ret));
3358 return ret;
3359 }
3360 ret = dhd_tdls_enable(dev, true, true, NULL);
3361 if (ret < 0) {
3362 ANDROID_ERROR(("enable tdls failed. %d\n", ret));
3363 return ret;
3364 }
3365 return 0;
3366 }
3367 #endif /* WLTDLS */
3368
3369 int
wl_android_rcroam_turn_on(struct net_device * dev,int rcroam_enab)3370 wl_android_rcroam_turn_on(struct net_device *dev, int rcroam_enab)
3371 {
3372 int ret = BCME_OK;
3373 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3374 u8 ioctl_buf[WLC_IOCTL_SMLEN];
3375 wlc_rcroam_t *prcroam;
3376 wlc_rcroam_info_v1_t *rcroam;
3377 uint rcroamlen = sizeof(*rcroam) + RCROAM_HDRLEN;
3378
3379 ANDROID_INFO(("RCROAM mode %s\n", rcroam_enab ? "enable" : "disable"));
3380
3381 prcroam = (wlc_rcroam_t *)MALLOCZ(dhdp->osh, rcroamlen);
3382 if (!prcroam) {
3383 ANDROID_ERROR(("Fail to malloc buffer\n"));
3384 return BCME_NOMEM;
3385 }
3386
3387 /* Get RCROAM param */
3388 ret = wldev_iovar_getbuf(dev, "rcroam", NULL, 0, prcroam, rcroamlen, NULL);
3389 if (ret) {
3390 ANDROID_ERROR(("Failed to get RCROAM info(%d)\n", ret));
3391 goto done;
3392 }
3393
3394 if (prcroam->ver != WLC_RC_ROAM_CUR_VER) {
3395 ret = BCME_VERSION;
3396 ANDROID_ERROR(("Ver(%d:%d). mismatch RCROAM info(%d)\n",
3397 prcroam->ver, WLC_RC_ROAM_CUR_VER, ret));
3398 goto done;
3399 }
3400
3401 /* Set RCROAM param */
3402 rcroam = (wlc_rcroam_info_v1_t *)prcroam->data;
3403 prcroam->ver = WLC_RC_ROAM_CUR_VER;
3404 prcroam->len = sizeof(*rcroam);
3405 rcroam->enab = rcroam_enab;
3406
3407 ret = wldev_iovar_setbuf(dev, "rcroam", prcroam, rcroamlen,
3408 ioctl_buf, sizeof(ioctl_buf), NULL);
3409 if (ret) {
3410 ANDROID_ERROR(("Failed to set RCROAM %s(%d)\n",
3411 rcroam_enab ? "Enable" : "Disable", ret));
3412 goto done;
3413 }
3414 done:
3415 if (prcroam) {
3416 MFREE(dhdp->osh, prcroam, rcroamlen);
3417 }
3418
3419 return ret;
3420 }
3421
3422 #ifdef CONFIG_SILENT_ROAM
3423 int
wl_android_sroam_turn_on(struct net_device * dev,int sroam_mode)3424 wl_android_sroam_turn_on(struct net_device *dev, int sroam_mode)
3425 {
3426 int ret = BCME_OK;
3427 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3428
3429 dhdp->sroam_turn_on = sroam_mode;
3430 ANDROID_INFO(("%s Silent mode %s\n", __FUNCTION__,
3431 sroam_mode ? "enable" : "disable"));
3432
3433 if (!sroam_mode) {
3434 ret = dhd_sroam_set_mon(dhdp, FALSE);
3435 if (ret) {
3436 ANDROID_ERROR(("%s Failed to Set sroam %d\n",
3437 __FUNCTION__, ret));
3438 }
3439 }
3440
3441 return ret;
3442 }
3443
3444 int
wl_android_sroam_set_info(struct net_device * dev,char * data,char * command,int total_len)3445 wl_android_sroam_set_info(struct net_device *dev, char *data,
3446 char *command, int total_len)
3447 {
3448 int ret = BCME_OK;
3449 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3450 size_t slen = strlen(data);
3451 u8 ioctl_buf[WLC_IOCTL_SMLEN];
3452 wlc_sroam_t *psroam;
3453 wlc_sroam_info_t *sroam;
3454 uint sroamlen = sizeof(*sroam) + SROAM_HDRLEN;
3455
3456 data[slen] = '\0';
3457 psroam = (wlc_sroam_t *)MALLOCZ(dhdp->osh, sroamlen);
3458 if (!psroam) {
3459 ANDROID_ERROR(("%s Fail to malloc buffer\n", __FUNCTION__));
3460 ret = BCME_NOMEM;
3461 goto done;
3462 }
3463
3464 psroam->ver = WLC_SILENT_ROAM_CUR_VER;
3465 psroam->len = sizeof(*sroam);
3466 sroam = (wlc_sroam_info_t *)psroam->data;
3467
3468 sroam->sroam_on = FALSE;
3469 if (*data && *data != '\0') {
3470 sroam->sroam_min_rssi = simple_strtol(data, &data, 10);
3471 ANDROID_INFO(("1.Minimum RSSI %d\n", sroam->sroam_min_rssi));
3472 data++;
3473 }
3474 if (*data && *data != '\0') {
3475 sroam->sroam_rssi_range = simple_strtol(data, &data, 10);
3476 ANDROID_INFO(("2.RSSI Range %d\n", sroam->sroam_rssi_range));
3477 data++;
3478 }
3479 if (*data && *data != '\0') {
3480 sroam->sroam_score_delta = simple_strtol(data, &data, 10);
3481 ANDROID_INFO(("3.Score Delta %d\n", sroam->sroam_score_delta));
3482 data++;
3483 }
3484 if (*data && *data != '\0') {
3485 sroam->sroam_period_time = simple_strtol(data, &data, 10);
3486 ANDROID_INFO(("4.Sroam period %d\n", sroam->sroam_period_time));
3487 data++;
3488 }
3489 if (*data && *data != '\0') {
3490 sroam->sroam_band = simple_strtol(data, &data, 10);
3491 ANDROID_INFO(("5.Sroam Band %d\n", sroam->sroam_band));
3492 data++;
3493 }
3494 if (*data && *data != '\0') {
3495 sroam->sroam_inact_cnt = simple_strtol(data, &data, 10);
3496 ANDROID_INFO(("6.Inactivity Count %d\n", sroam->sroam_inact_cnt));
3497 data++;
3498 }
3499
3500 if (*data != '\0') {
3501 ret = BCME_BADARG;
3502 goto done;
3503 }
3504
3505 ret = wldev_iovar_setbuf(dev, "sroam", psroam, sroamlen, ioctl_buf,
3506 sizeof(ioctl_buf), NULL);
3507 if (ret) {
3508 ANDROID_ERROR(("Failed to set silent roam info(%d)\n", ret));
3509 goto done;
3510 }
3511 done:
3512 if (psroam) {
3513 MFREE(dhdp->osh, psroam, sroamlen);
3514 }
3515
3516 return ret;
3517 }
3518
3519 int
wl_android_sroam_get_info(struct net_device * dev,char * command,int total_len)3520 wl_android_sroam_get_info(struct net_device *dev, char *command, int total_len)
3521 {
3522 int ret = BCME_OK;
3523 int bytes_written = 0;
3524 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3525 wlc_sroam_t *psroam;
3526 wlc_sroam_info_t *sroam;
3527 uint sroamlen = sizeof(*sroam) + SROAM_HDRLEN;
3528
3529 psroam = (wlc_sroam_t *)MALLOCZ(dhdp->osh, sroamlen);
3530 if (!psroam) {
3531 ANDROID_ERROR(("%s Fail to malloc buffer\n", __FUNCTION__));
3532 ret = BCME_NOMEM;
3533 goto done;
3534 }
3535
3536 ret = wldev_iovar_getbuf(dev, "sroam", NULL, 0, psroam, sroamlen, NULL);
3537 if (ret) {
3538 ANDROID_ERROR(("Failed to get silent roam info(%d)\n", ret));
3539 goto done;
3540 }
3541
3542 if (psroam->ver != WLC_SILENT_ROAM_CUR_VER) {
3543 ret = BCME_VERSION;
3544 ANDROID_ERROR(("Ver(%d:%d). mismatch silent roam info(%d)\n",
3545 psroam->ver, WLC_SILENT_ROAM_CUR_VER, ret));
3546 goto done;
3547 }
3548
3549 sroam = (wlc_sroam_info_t *)psroam->data;
3550 bytes_written = snprintf(command, total_len,
3551 "%s %d %d %d %d %d %d %d\n",
3552 CMD_SROAM_GET_INFO, sroam->sroam_on, sroam->sroam_min_rssi, sroam->sroam_rssi_range,
3553 sroam->sroam_score_delta, sroam->sroam_period_time, sroam->sroam_band,
3554 sroam->sroam_inact_cnt);
3555 ret = bytes_written;
3556
3557 ANDROID_INFO(("%s", command));
3558 done:
3559 if (psroam) {
3560 MFREE(dhdp->osh, psroam, sroamlen);
3561 }
3562
3563 return ret;
3564 }
3565 #endif /* CONFIG_SILENT_ROAM */
3566
3567 int
wl_android_priority_roam_enable(struct net_device * dev,int mode)3568 wl_android_priority_roam_enable(struct net_device *dev, int mode)
3569 {
3570 int error = BCME_OK;
3571 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3572 u8 ioctl_buf[WLC_IOCTL_SMLEN];
3573 wl_prio_roam_prof_v1_t *prio_roam;
3574 uint buf_len = sizeof(wl_prio_roam_prof_v1_t) + (uint)strlen("priority_roam") + 1;
3575
3576 prio_roam = (wl_prio_roam_prof_v1_t *)MALLOCZ(dhdp->osh, buf_len);
3577 if (!prio_roam) {
3578 ANDROID_ERROR(("%s Fail to malloc buffer\n", __FUNCTION__));
3579 error = BCME_NOMEM;
3580 goto done;
3581 }
3582
3583 error = wldev_iovar_getbuf(dev, "priority_roam", NULL, 0, prio_roam, buf_len, NULL);
3584 if (error == BCME_UNSUPPORTED) {
3585 ANDROID_ERROR(("Priority Roam Unsupport\n"));
3586 error = BCME_OK;
3587 goto done;
3588 } else if (prio_roam->version != WL_PRIO_ROAM_PROF_V1) {
3589 ANDROID_ERROR(("Priority Roam Version mismatch\n"));
3590 goto done;
3591 } else if (prio_roam->prio_roam_mode == mode) {
3592 ANDROID_INFO(("Priority Roam already set(mode:%d)\n", mode));
3593 goto done;
3594 }
3595
3596 prio_roam->version = WL_PRIO_ROAM_PROF_V1;
3597 prio_roam->length = sizeof(wl_prio_roam_prof_v1_t);
3598 prio_roam->prio_roam_mode = mode;
3599
3600 error = wldev_iovar_setbuf(dev, "priority_roam", prio_roam,
3601 sizeof(wl_prio_roam_prof_v1_t), ioctl_buf, sizeof(ioctl_buf), NULL);
3602 if (error) {
3603 ANDROID_ERROR(("Failed to set Priority Roam %s(%d)\n",
3604 mode ? "Enable" : "Disable", error));
3605 goto done;
3606 }
3607 done:
3608 if (prio_roam) {
3609 MFREE(dhdp->osh, prio_roam, sizeof(wl_prio_roam_prof_v1_t));
3610 }
3611
3612 return error;
3613 }
3614
3615 #ifdef CONFIG_ROAM_RSSI_LIMIT
3616 int
wl_android_roam_rssi_limit(struct net_device * dev,char * command,int total_len)3617 wl_android_roam_rssi_limit(struct net_device *dev, char *command, int total_len)
3618 {
3619 int ret = BCME_OK;
3620 int argc, bytes_written = 0;
3621 int lmt2g, lmt5g;
3622 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3623
3624 argc = sscanf(command, CMD_ROAM_RSSI_LMT " %d %d\n", &lmt2g, &lmt5g);
3625
3626 if (!argc) {
3627 ret = dhd_roam_rssi_limit_get(dhdp, &lmt2g, &lmt5g);
3628 if (ret) {
3629 ANDROID_ERROR(("Failed to Get roam_rssi_limit (%d)\n", ret));
3630 return ret;
3631 }
3632 bytes_written = snprintf(command, total_len, "%d, %d\n", lmt2g, lmt5g);
3633 /* Get roam rssi limit */
3634 return bytes_written;
3635 } else {
3636 /* Set roam rssi limit */
3637 ret = dhd_roam_rssi_limit_set(dhdp, lmt2g, lmt5g);
3638 if (ret) {
3639 ANDROID_ERROR(("Failed to Set roam_rssi_limit (%d)\n", ret));
3640 return ret;
3641 }
3642 }
3643
3644 return ret;
3645 }
3646 #endif /* CONFIG_ROAM_RSSI_LIMIT */
3647
3648 #ifdef CONFIG_ROAM_MIN_DELTA
3649 int
wl_android_roam_min_delta(struct net_device * dev,char * command,int total_len)3650 wl_android_roam_min_delta(struct net_device *dev, char *command, int total_len)
3651 {
3652 int ret = BCME_OK;
3653 int argc, bytes_written = 0;
3654 uint32 delta2g = 0, delta5g = 0, delta = 0;
3655 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3656
3657 argc = sscanf(command, CMD_ROAM_MIN_DELTA " %d\n", &delta);
3658
3659 if (!argc) {
3660 /* Get Minimum ROAM score delta */
3661 ret = dhd_roam_min_delta_get(dhdp, &delta2g, &delta5g);
3662 if (ret) {
3663 ANDROID_ERROR(("Failed to Get roam_min_delta (%d)\n", ret));
3664 return ret;
3665 }
3666 bytes_written = snprintf(command, total_len, "%d, %d\n", delta2g, delta5g);
3667 return bytes_written;
3668 } else {
3669 /* Set Minimum ROAM score delta
3670 * Framework set one parameter # wpa_cli driver ROAMMINSCOREDELTA <value>
3671 */
3672 ret = dhd_roam_min_delta_set(dhdp, delta, delta);
3673 if (ret) {
3674 ANDROID_ERROR(("Failed to Set roam_min_delta (%d)\n", ret));
3675 return ret;
3676 }
3677 }
3678
3679 return ret;
3680 }
3681 #endif /* CONFIG_ROAM_MIN_DELTA */
3682
3683 static int
get_int_bytes(uchar * oui_str,uchar * oui,int len)3684 get_int_bytes(uchar *oui_str, uchar *oui, int len)
3685 {
3686 int idx;
3687 uchar val;
3688 uchar *src, *dest;
3689 char hexstr[3];
3690
3691 if ((oui_str == NULL) || (oui == NULL) || (len == 0)) {
3692 return BCME_BADARG;
3693 }
3694 src = oui_str;
3695 dest = oui;
3696
3697 for (idx = 0; idx < len; idx++) {
3698 if (*src == '\0') {
3699 *dest = '\0';
3700 break;
3701 }
3702 hexstr[0] = src[0];
3703 hexstr[1] = src[1];
3704 hexstr[2] = '\0';
3705
3706 val = (uchar)bcm_strtoul(hexstr, NULL, 16);
3707 if (val == (uchar)-1) {
3708 return BCME_ERROR;
3709 }
3710 *dest++ = val;
3711 src += 2;
3712 }
3713 return BCME_OK;
3714 }
3715
3716 #define TAG_BYTE 0
3717 static int
wl_android_set_disconnect_ies(struct net_device * dev,char * command)3718 wl_android_set_disconnect_ies(struct net_device *dev, char *command)
3719 {
3720 int cmd_prefix_len = 0;
3721 char ie_len = 0;
3722 int hex_ie_len = 0;
3723 int total_len = 0;
3724 int max_len = 0;
3725 int cmd_len = 0;
3726 uchar disassoc_ie[VNDR_IE_MAX_LEN] = {0};
3727 s32 bssidx = 0;
3728 struct bcm_cfg80211 *cfg = NULL;
3729 s32 ret = 0;
3730 cfg = wl_get_cfg(dev);
3731
3732 cmd_prefix_len = strlen("SET_DISCONNECT_IES ");
3733 cmd_len = strlen(command);
3734 /*
3735 * <CMD> + <IES in HEX format>
3736 * IES in hex format has to be in following format
3737 * First byte = Tag, Second Byte = len and rest of
3738 * bytes will be value. For ex: SET_DISCONNECT_IES dd0411223344
3739 * tag = dd, len =04. Total IEs len = len + 2
3740 */
3741 ANDROID_INFO(("cmd recv = %s\n", command));
3742 max_len = MIN(cmd_len, VNDR_IE_MAX_LEN);
3743 /* Validate IEs len */
3744 get_int_bytes(&command[cmd_prefix_len + 2], &ie_len, 1);
3745 ANDROID_INFO(("ie_len = %d \n", ie_len));
3746 if (ie_len <= 0 || ie_len > max_len) {
3747 ret = BCME_BADLEN;
3748 return ret;
3749 }
3750
3751 /* Total len in hex is sum of double binary len, tag and len byte */
3752 hex_ie_len = (ie_len * 2) + 4;
3753 total_len = cmd_prefix_len + hex_ie_len;
3754 if (command[total_len] != '\0' || (cmd_len != total_len)) {
3755 ANDROID_ERROR(("command recv not matching with len, command = %s"
3756 "total_len = %d, cmd_len = %d\n", command, total_len, cmd_len));
3757 ret = BCME_BADARG;
3758 return ret;
3759 }
3760
3761 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3762 ANDROID_ERROR(("Find index failed\n"));
3763 ret = -EINVAL;
3764 return ret;
3765 }
3766
3767 /* Tag and len bytes are also part of total len of ies in binary */
3768 ie_len = ie_len + 2;
3769 /* Convert IEs in binary */
3770 get_int_bytes(&command[cmd_prefix_len], disassoc_ie, ie_len);
3771 if (disassoc_ie[TAG_BYTE] != 0xdd) {
3772 ANDROID_ERROR(("Wrong tag recv, tag = 0x%02x\n", disassoc_ie[TAG_BYTE]));
3773 ret = BCME_UNSUPPORTED;
3774 return ret;
3775 }
3776
3777 ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
3778 ndev_to_cfgdev(dev), bssidx, VNDR_IE_DISASSOC_FLAG, disassoc_ie, ie_len);
3779
3780 return ret;
3781 }
3782
3783 #ifdef FCC_PWR_LIMIT_2G
3784 int
wl_android_set_fcc_pwr_limit_2g(struct net_device * dev,char * command)3785 wl_android_set_fcc_pwr_limit_2g(struct net_device *dev, char *command)
3786 {
3787 int error = 0;
3788 int enable = 0;
3789
3790 sscanf(command+sizeof("SET_FCC_CHANNEL"), "%d", &enable);
3791
3792 if ((enable != CUSTOMER_HW4_ENABLE) && (enable != CUSTOMER_HW4_DISABLE)) {
3793 ANDROID_ERROR(("wl_android_set_fcc_pwr_limit_2g: Invalid data\n"));
3794 return BCME_ERROR;
3795 }
3796
3797 CUSTOMER_HW4_EN_CONVERT(enable);
3798
3799 ANDROID_ERROR(("wl_android_set_fcc_pwr_limit_2g: fccpwrlimit2g set (%d)\n", enable));
3800 error = wldev_iovar_setint(dev, "fccpwrlimit2g", enable);
3801 if (error) {
3802 ANDROID_ERROR(("wl_android_set_fcc_pwr_limit_2g: fccpwrlimit2g"
3803 " set returned (%d)\n", error));
3804 return BCME_ERROR;
3805 }
3806
3807 return error;
3808 }
3809
3810 int
wl_android_get_fcc_pwr_limit_2g(struct net_device * dev,char * command,int total_len)3811 wl_android_get_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len)
3812 {
3813 int error = 0;
3814 int enable = 0;
3815 int bytes_written = 0;
3816
3817 error = wldev_iovar_getint(dev, "fccpwrlimit2g", &enable);
3818 if (error) {
3819 ANDROID_ERROR(("wl_android_get_fcc_pwr_limit_2g: fccpwrlimit2g get"
3820 " error (%d)\n", error));
3821 return BCME_ERROR;
3822 }
3823 ANDROID_ERROR(("wl_android_get_fcc_pwr_limit_2g: fccpwrlimit2g get (%d)\n", enable));
3824
3825 bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_FCC_PWR_LIMIT_2G, enable);
3826
3827 return bytes_written;
3828 }
3829 #endif /* FCC_PWR_LIMIT_2G */
3830
3831 /* Additional format of sta_info
3832 * tx_pkts, tx_failures, tx_rate(kbps), rssi(main), rssi(aux), tx_pkts_retried,
3833 * tx_pkts_retry_exhausted, rx_lastpkt_rssi(main), rx_lastpkt_rssi(aux),
3834 * tx_pkts_total, tx_pkts_retries, tx_pkts_fw_total, tx_pkts_fw_retries,
3835 * tx_pkts_fw_retry_exhausted
3836 */
3837 #define STA_INFO_ADD_FMT "%d %d %d %d %d %d %d %d %d %d %d %d %d %d"
3838
3839 #ifdef BIGDATA_SOFTAP
3840 #define BIGDATA_SOFTAP_FMT MACOUI " %d %s %d %d %d %d %d %d"
3841 #endif /* BIGDATA_SOFTAP */
3842
3843 #define STAINFO_BAND_2G 0x0001
3844 #define STAINFO_BAND_5G 0x0002
3845 #define STAINFO_BAND_6G 0x0004
3846 #define STAINFO_BAND_60G 0x0008
3847 s32
wl_cfg80211_get_sta_info(struct net_device * dev,char * command,int total_len)3848 wl_cfg80211_get_sta_info(struct net_device *dev, char* command, int total_len)
3849 {
3850 int bytes_written = -1, ret = 0;
3851 char *pos, *token, *cmdstr;
3852 bool is_macaddr = FALSE;
3853 sta_info_v4_t *sta = NULL;
3854 struct ether_addr mac;
3855 char *iovar_buf = NULL;
3856 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3857 struct net_device *apdev = NULL;
3858 #ifdef BCMDONGLEHOST
3859 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
3860 #endif /* BCMDONGLEHOST */
3861
3862 #ifdef BIGDATA_SOFTAP
3863 void *data = NULL;
3864 wl_ap_sta_data_t *sta_data = NULL;
3865 #endif /* BIGDATA_SOFTAP */
3866
3867 /* Client information */
3868 uint16 cap = 0;
3869 uint32 rxrtry = 0, rxmulti = 0;
3870 uint32 tx_pkts = 0, tx_failures = 0, tx_rate = 0;
3871 uint32 tx_pkts_retried = 0, tx_pkts_retry_exhausted = 0;
3872 uint32 tx_pkts_total = 0, tx_pkts_retries = 0;
3873 uint32 tx_pkts_fw_total = 0, tx_pkts_fw_retries = 0;
3874 uint32 tx_pkts_fw_retry_exhausted = 0;
3875 int8 rssi[WL_STA_ANT_MAX] = {0};
3876 int8 rx_lastpkt_rssi[WL_STA_ANT_MAX] = {0};
3877 wl_if_stats_t *if_stats = NULL;
3878 u16 bands = 0;
3879 u32 sta_flags = 0;
3880 char mac_buf[MAX_NUM_OF_ASSOCLIST *
3881 sizeof(struct ether_addr) + sizeof(uint)] = {0};
3882 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
3883
3884 BCM_REFERENCE(if_stats);
3885 /* This Command used during only SoftAP mode. */
3886 ANDROID_INFO(("%s\n", command));
3887
3888 /* Check the current op_mode */
3889 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
3890 ANDROID_ERROR(("unsupported op mode: %d\n", dhdp->op_mode));
3891 return BCME_NOTAP;
3892 }
3893
3894 /*
3895 * DRIVER GETSTAINFO [client MAC or ALL] [ifname]
3896 */
3897 pos = command;
3898
3899 /* drop command */
3900 token = bcmstrtok(&pos, " ", NULL);
3901
3902 /* Client MAC or ALL */
3903 token = bcmstrtok(&pos, " ", NULL);
3904 if (!token) {
3905 ANDROID_ERROR(("GETSTAINFO subcmd not provided wl_cfg80211_get_sta_info\n"));
3906 return -EINVAL;
3907 }
3908 cmdstr = token;
3909
3910 bzero(&mac, ETHER_ADDR_LEN);
3911 if ((!strncmp(token, "all", 3)) || (!strncmp(token, "ALL", 3))) {
3912 is_macaddr = FALSE;
3913 } else if ((bcm_ether_atoe(token, &mac))) {
3914 is_macaddr = TRUE;
3915 } else {
3916 ANDROID_ERROR(("Failed to get address\n"));
3917 return -EINVAL;
3918 }
3919
3920 /* get the interface name */
3921 token = bcmstrtok(&pos, " ", NULL);
3922 if (!token) {
3923 /* assign requested dev for compatibility */
3924 apdev = dev;
3925 } else {
3926 /* Find a net_device for SoftAP by interface name */
3927 apdev = wl_get_ap_netdev(cfg, token);
3928 if (!apdev) {
3929 ANDROID_ERROR(("cannot find a net_device for SoftAP\n"));
3930 return -EINVAL;
3931 }
3932 }
3933
3934 iovar_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
3935 if (!iovar_buf) {
3936 ANDROID_ERROR(("Failed to allocated memory %d bytes\n",
3937 WLC_IOCTL_MAXLEN));
3938 return BCME_NOMEM;
3939 }
3940
3941 if (is_macaddr) {
3942 int cnt;
3943
3944 /* get the sta info */
3945 ret = wldev_iovar_getbuf(apdev, "sta_info",
3946 (struct ether_addr *)mac.octet, ETHER_ADDR_LEN,
3947 iovar_buf, WLC_IOCTL_MAXLEN, NULL);
3948 if (ret < 0) {
3949 ANDROID_ERROR(("Get sta_info ERR %d\n", ret));
3950
3951 #ifdef BIGDATA_SOFTAP
3952 /* Customer wants to send basic client information
3953 * to the framework even if DHD cannot get the sta_info.
3954 */
3955 goto get_bigdata;
3956 #endif /* BIGDATA_SOFTAP */
3957
3958 #ifndef BIGDATA_SOFTAP
3959 goto error;
3960 #endif /* BIGDATA_SOFTAP */
3961 }
3962
3963 sta = (sta_info_v4_t *)iovar_buf;
3964 if (dtoh16(sta->ver) != WL_STA_VER_4) {
3965 ANDROID_ERROR(("sta_info struct version mismatch, "
3966 "host ver : %d, fw ver : %d\n", WL_STA_VER_4,
3967 dtoh16(sta->ver)));
3968
3969 #ifdef BIGDATA_SOFTAP
3970 /* Customer wants to send basic client information
3971 * to the framework even if DHD cannot get the sta_info.
3972 */
3973 goto get_bigdata;
3974 #endif /* BIGDATA_SOFTAP */
3975
3976 #ifndef BIGDATA_SOFTAP
3977 goto error;
3978 #endif /* BIGDATA_SOFTAP */
3979 }
3980 cap = dtoh16(sta->cap);
3981 rxrtry = dtoh32(sta->rx_pkts_retried);
3982 rxmulti = dtoh32(sta->rx_mcast_pkts);
3983 tx_pkts = dtoh32(sta->tx_pkts);
3984 tx_failures = dtoh32(sta->tx_failures);
3985 tx_rate = dtoh32(sta->tx_rate);
3986 tx_pkts_retried = dtoh32(sta->tx_pkts_retried);
3987 tx_pkts_retry_exhausted = dtoh32(sta->tx_pkts_retry_exhausted);
3988 tx_pkts_total = dtoh32(sta->tx_pkts_total);
3989 tx_pkts_retries = dtoh32(sta->tx_pkts_retries);
3990 tx_pkts_fw_total = dtoh32(sta->tx_pkts_fw_total);
3991 tx_pkts_fw_retries = dtoh32(sta->tx_pkts_fw_retries);
3992 tx_pkts_fw_retry_exhausted = dtoh32(sta->tx_pkts_fw_retry_exhausted);
3993 sta_flags = dtoh32(sta->flags);
3994 if (sta_flags & WL_STA_IS_2G) {
3995 bands |= STAINFO_BAND_2G;
3996 }
3997 if (sta_flags & WL_STA_IS_5G) {
3998 bands |= STAINFO_BAND_5G;
3999 }
4000 if (sta_flags & WL_STA_IS_6G) {
4001 bands |= STAINFO_BAND_6G;
4002 }
4003 for (cnt = WL_ANT_IDX_1; cnt < WL_RSSI_ANT_MAX; cnt++) {
4004 rssi[cnt] = sta->rssi[cnt];
4005 rx_lastpkt_rssi[cnt] = sta->rx_lastpkt_rssi[cnt];
4006 }
4007 } else {
4008 int i;
4009
4010 /* Check if there is an associated STA or not */
4011 assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
4012 ret = wldev_ioctl_get(apdev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf));
4013
4014 if (ret < 0) {
4015 ANDROID_ERROR(("Fail to get assoc list: %d\n", ret));
4016 goto error;
4017 }
4018
4019 assoc_maclist->count = dtoh32(assoc_maclist->count);
4020 ANDROID_INFO(("Assoc count : %d\n", assoc_maclist->count));
4021
4022 for (i = 0; i < assoc_maclist->count; i++) {
4023 /* get the sta info */
4024 ret = wldev_iovar_getbuf(apdev, "sta_info",
4025 (struct ether_addr *)assoc_maclist->ea[i].octet, ETHER_ADDR_LEN,
4026 iovar_buf, WLC_IOCTL_MAXLEN, NULL);
4027
4028 if (ret < 0) {
4029 ANDROID_ERROR(("sta_info err : %d", ret));
4030 continue;
4031 }
4032 sta = (sta_info_v4_t *)iovar_buf;
4033 if (dtoh16(sta->ver) == WL_STA_VER_4) {
4034 rxrtry += dtoh32(sta->rx_pkts_retried);
4035 rxmulti += dtoh32(sta->rx_mcast_pkts);
4036 tx_pkts += dtoh32(sta->tx_pkts);
4037 tx_failures += dtoh32(sta->tx_failures);
4038 tx_pkts_total += dtoh32(sta->tx_pkts_total);
4039 tx_pkts_retries += dtoh32(sta->tx_pkts_retries);
4040 tx_pkts_fw_total += dtoh32(sta->tx_pkts_fw_total);
4041 tx_pkts_fw_retries += dtoh32(sta->tx_pkts_fw_retries);
4042 tx_pkts_fw_retry_exhausted +=
4043 dtoh32(sta->tx_pkts_fw_retry_exhausted);
4044 }
4045 }
4046 }
4047
4048 #ifdef BIGDATA_SOFTAP
4049 get_bigdata:
4050
4051 if (is_macaddr && wl_get_ap_stadata(cfg, &mac, &data) == BCME_OK) {
4052 ANDROID_ERROR(("mac " MACDBG" \n", MAC2STRDBG((char*)&mac)));
4053 sta_data = (wl_ap_sta_data_t *)data;
4054 #ifdef STAINFO_LEGACY
4055 bytes_written = snprintf(command, total_len,
4056 "%s %s Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d "
4057 "CAP=%04x " BIGDATA_SOFTAP_FMT " " STA_INFO_ADD_FMT
4058 "\n", CMD_GET_STA_INFO, cmdstr, rxrtry, rxmulti, cap,
4059 MACOUI2STR((char*)&sta_data->mac),
4060 sta_data->channel, wf_chspec_to_bw_str(sta_data->chanspec),
4061 sta_data->rssi, sta_data->rate, sta_data->mode_80211,
4062 sta_data->nss, sta_data->mimo, sta_data->reason_code,
4063 tx_pkts, tx_failures, tx_rate,
4064 (int32)rssi[WL_ANT_IDX_1], (int32)rssi[WL_ANT_IDX_2],
4065 tx_pkts_retried, tx_pkts_retry_exhausted,
4066 (int32)rx_lastpkt_rssi[WL_ANT_IDX_1],
4067 (int32)rx_lastpkt_rssi[WL_ANT_IDX_2],
4068 tx_pkts_total, tx_pkts_retries, tx_pkts_fw_total,
4069 tx_pkts_fw_retries, tx_pkts_fw_retry_exhausted);
4070 #else
4071 bytes_written = snprintf(command, total_len,
4072 "%s %s Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d "
4073 "CAP=%04x " BIGDATA_SOFTAP_FMT " %d\n",
4074 CMD_GET_STA_INFO, cmdstr, rxrtry, rxmulti, cap,
4075 MACOUI2STR((char*)&sta_data->mac),
4076 sta_data->channel, wf_chspec_to_bw_str(sta_data->chanspec),
4077 sta_data->rssi, sta_data->rate, sta_data->mode_80211,
4078 sta_data->nss, sta_data->mimo, sta_data->reason_code, bands);
4079 #endif /* STAINFO_LEGACY */
4080 } else
4081 #endif /* BIGDATA_SOFTAP */
4082 {
4083 ANDROID_ERROR(("ALL\n"));
4084 bytes_written = snprintf(command, total_len,
4085 "%s %s Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d CAP=%04x "
4086 STA_INFO_ADD_FMT "\n", CMD_GET_STA_INFO, cmdstr, rxrtry, rxmulti, cap,
4087 tx_pkts, tx_failures, tx_rate, (int32)rssi[WL_ANT_IDX_1],
4088 (int32)rssi[WL_ANT_IDX_2], tx_pkts_retried,
4089 tx_pkts_retry_exhausted, (int32)rx_lastpkt_rssi[WL_ANT_IDX_1],
4090 (int32)rx_lastpkt_rssi[WL_ANT_IDX_2], tx_pkts_total,
4091 tx_pkts_retries, tx_pkts_fw_total, tx_pkts_fw_retries,
4092 tx_pkts_fw_retry_exhausted);
4093 }
4094 WL_ERR_KERN(("Command: %s", command));
4095
4096 error:
4097 if (iovar_buf) {
4098 MFREE(cfg->osh, iovar_buf, WLC_IOCTL_MAXLEN);
4099 }
4100 if (if_stats) {
4101 MFREE(cfg->osh, if_stats, sizeof(*if_stats));
4102 }
4103
4104 return bytes_written;
4105 }
4106
4107 #ifdef WL_WTC
4108 /*
4109 * CMD Format
4110 * Enable format for 3 band and 2 band respectively:
4111 * DRIVER SETWTCMODE <mode> <scan_type> <rssi_thresh> <ap_rssi_thresg 2G 5G 6G>
4112 * DRIVER SETWTCMODE 0 1 -80 -70 -65 -60
4113 * DRIVER SETWTCMODE <mode> <scan_type> <rssi_thresh> <ap_rssi_thresg 2G 5G>
4114 * DRIVER SETWTCMODE 0 1 -80 -70 -65
4115 * Disable format for 3 band and 2 band respectively:
4116 * DRIVER SETWTCMODE 1 0 0 0 0 0
4117 * DRIVER SETWTCMODE 1 0 0 0 0
4118 */
4119 #define WL_TRIBAND 3
4120 #define WL_DUALBAND 2
4121
4122 /* For WTC disable, any value >= 1 */
4123 #define WL_WTC_ENABLE 0
4124 static int
wl_android_wtc_config(struct net_device * dev,char * command,int total_len)4125 wl_android_wtc_config(struct net_device *dev, char *command, int total_len)
4126 {
4127 s32 bw;
4128 char *token, *pos;
4129 wlc_wtc_args_t *wtc_params;
4130 wlc_wtcconfig_info_v1_t *wtc_config;
4131 u32 i, wtc_paramslen, maxbands = WL_DUALBAND;
4132 u8 buf[WLC_IOCTL_SMLEN] = {0};
4133 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4134
4135 WL_DBG_MEM(("Enter. cmd:%s\n", command));
4136 #ifdef WL_6G_BAND
4137 if (cfg->band_6g_supported) {
4138 maxbands = WL_TRIBAND;
4139 }
4140 #endif /* WL_6G_BAND */
4141 wtc_paramslen = sizeof(wlc_wtcconfig_info_v1_t) + WLC_WTC_ROAM_CONFIG_HDRLEN;
4142 wtc_params = (wlc_wtc_args_t*)MALLOCZ(cfg->osh, wtc_paramslen);
4143 if (!wtc_params) {
4144 ANDROID_ERROR(("Error allocating wtc_params\n"));
4145 return -ENOMEM;
4146 }
4147
4148 wtc_config = (wlc_wtcconfig_info_v1_t *)wtc_params->data;
4149 /* Get wtc config information and check version compatibility */
4150 bw = wldev_iovar_getbuf(dev, "wnm_wbtext_wtc_config",
4151 (char*)&wtc_params, wtc_paramslen, buf, WLC_IOCTL_SMLEN, 0);
4152 if (bw) {
4153 ANDROID_ERROR(("Error querying wnm_wbtext_wtc_config: %d\n", bw));
4154 goto exit;
4155 }
4156
4157 (void)memcpy_s(wtc_params, wtc_paramslen, buf, wtc_paramslen);
4158 if (wtc_params->ver != WLC_WTC_ROAM_VER_1) {
4159 ANDROID_ERROR(("Wrong version:%d\n", wtc_params->ver));
4160 bw = -EINVAL;
4161 goto exit;
4162 }
4163
4164 if (wtc_params->len != sizeof(wlc_wtcconfig_info_v1_t)) {
4165 ANDROID_ERROR(("Bad len\n"));
4166 bw = -EINVAL;
4167 goto exit;
4168 }
4169
4170 if (strlen(command) == strlen(CMD_WTC_CONFIG)) {
4171 /* No additional arguments given. GET case */
4172 bw += scnprintf(command, (total_len - bw), "%u %u",
4173 wtc_config->mode, wtc_config->scantype);
4174 bw += scnprintf(command + bw, (total_len - bw), " %d",
4175 wtc_config->rssithresh[0]);
4176 for (i = 0; i < maxbands; i++) {
4177 bw += scnprintf(command + bw, (total_len - bw), " %d",
4178 wtc_config->ap_rssithresh[i]);
4179 }
4180 bw += scnprintf(command + bw, (total_len - bw), "\n");
4181 } else {
4182 /* SET */
4183 pos = command + sizeof(CMD_WTC_CONFIG);
4184
4185 /* mode */
4186 token = strsep((char**)&pos, " ");
4187 if (!token) {
4188 ANDROID_ERROR(("No mode present\n"));
4189 bw = -EINVAL;
4190 goto exit;
4191 }
4192 wtc_config->mode = (u8)bcm_atoi(token);
4193
4194 /* scantype */
4195 token = strsep((char**)&pos, " ");
4196 if (!token) {
4197 ANDROID_ERROR(("No scantype present\n"));
4198 bw = -EINVAL;
4199 goto exit;
4200 }
4201 wtc_config->scantype = (u8)bcm_atoi(token);
4202
4203 /* rssithreshold */
4204 token = strsep((char**)&pos, " ");
4205 if (!token) {
4206 ANDROID_ERROR(("Invalid arg for rssi threshold\n"));
4207 bw = -EINVAL;
4208 goto exit;
4209 }
4210 for (i = 0; i < maxbands; i++) {
4211 wtc_config->rssithresh[i] = (s8)bcm_atoi(token);
4212 }
4213
4214 /* AP rssithreshold */
4215 for (i = 0; i < maxbands; i++) {
4216 token = strsep((char**)&pos, " ");
4217 if (!token) {
4218 ANDROID_ERROR(("Invalid arg for ap threshold\n"));
4219 bw = -EINVAL;
4220 goto exit;
4221 }
4222 wtc_config->ap_rssithresh[i] = (s8)bcm_atoi(token);
4223 }
4224
4225 bw = wldev_iovar_setbuf(dev, "wnm_wbtext_wtc_config",
4226 (char*)wtc_params, wtc_paramslen, buf, WLC_IOCTL_SMLEN, NULL);
4227 if (bw) {
4228 ANDROID_ERROR(("wtc config set failed. ret:%d\n", bw));
4229 }
4230 }
4231
4232 exit:
4233 if (wtc_params) {
4234 MFREE(cfg->osh, wtc_params, wtc_paramslen);
4235 }
4236 return bw;
4237 }
4238 #endif /* WL_WTC */
4239 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
4240
4241 #ifdef WBTEXT
wl_android_wbtext(struct net_device * dev,char * command,int total_len)4242 static int wl_android_wbtext(struct net_device *dev, char *command, int total_len)
4243 {
4244 int error = BCME_OK, argc = 0;
4245 int data, bytes_written;
4246 int roam_trigger[2];
4247 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4248
4249 argc = sscanf(command+sizeof(CMD_WBTEXT_ENABLE), "%d", &data);
4250 if (!argc) {
4251 error = wldev_iovar_getint(dev, "wnm_bsstrans_resp", &data);
4252 if (error) {
4253 ANDROID_ERROR(("wl_android_wbtext: Failed to set wbtext error = %d\n",
4254 error));
4255 return error;
4256 }
4257 bytes_written = snprintf(command, total_len, "WBTEXT %s\n",
4258 (data == WL_BSSTRANS_POLICY_PRODUCT_WBTEXT)?
4259 "ENABLED" : "DISABLED");
4260 return bytes_written;
4261 } else {
4262 if (data) {
4263 data = WL_BSSTRANS_POLICY_PRODUCT_WBTEXT;
4264 }
4265
4266 if ((error = wldev_iovar_setint(dev, "wnm_bsstrans_resp", data)) != BCME_OK) {
4267 ANDROID_ERROR(("wl_android_wbtext: Failed to set wbtext error = %d\n",
4268 error));
4269 return error;
4270 }
4271
4272 if (data) {
4273 /* reset roam_prof when wbtext is on */
4274 if ((error = wl_cfg80211_wbtext_set_default(dev)) != BCME_OK) {
4275 return error;
4276 }
4277 } else {
4278 /* reset legacy roam trigger when wbtext is off */
4279 roam_trigger[0] = DEFAULT_ROAM_TRIGGER_VALUE;
4280 roam_trigger[1] = WLC_BAND_ALL;
4281 if ((error = wldev_ioctl_set(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
4282 sizeof(roam_trigger))) != BCME_OK) {
4283 ANDROID_ERROR(("wl_android_wbtext: Failed to reset roam trigger = %d\n",
4284 error));
4285 return error;
4286 }
4287 }
4288 dhdp->wbtext_policy = data;
4289 }
4290 return error;
4291 }
4292
4293 static int
wl_android_wbtext_enable(struct net_device * dev,int mode)4294 wl_android_wbtext_enable(struct net_device *dev, int mode)
4295 {
4296 int error = BCME_OK;
4297 char commandp[WLC_IOCTL_SMLEN];
4298
4299 if (wl_android_check_wbtext_support(dev)) {
4300 bzero(commandp, sizeof(commandp));
4301 snprintf(commandp, WLC_IOCTL_SMLEN, "WBTEXT_ENABLE %d", mode);
4302 error = wl_android_wbtext(dev, commandp, WLC_IOCTL_SMLEN);
4303 if (error) {
4304 ANDROID_ERROR(("Failed to set WBTEXT = %d\n", error));
4305 return error;
4306 }
4307 }
4308
4309 return error;
4310 }
4311
wl_cfg80211_wbtext_btm_timer_threshold(struct net_device * dev,char * command,int total_len)4312 static int wl_cfg80211_wbtext_btm_timer_threshold(struct net_device *dev,
4313 char *command, int total_len)
4314 {
4315 int error = BCME_OK, argc = 0;
4316 int data, bytes_written;
4317
4318 argc = sscanf(command, CMD_WBTEXT_BTM_TIMER_THRESHOLD " %d\n", &data);
4319 if (!argc) {
4320 error = wldev_iovar_getint(dev, "wnm_bsstrans_timer_threshold", &data);
4321 if (error) {
4322 ANDROID_ERROR(("Failed to get wnm_bsstrans_timer_threshold (%d)\n", error));
4323 return error;
4324 }
4325 bytes_written = snprintf(command, total_len, "%d\n", data);
4326 return bytes_written;
4327 } else {
4328 if ((error = wldev_iovar_setint(dev, "wnm_bsstrans_timer_threshold",
4329 data)) != BCME_OK) {
4330 ANDROID_ERROR(("Failed to set wnm_bsstrans_timer_threshold (%d)\n", error));
4331 return error;
4332 }
4333 }
4334 return error;
4335 }
4336
wl_cfg80211_wbtext_btm_delta(struct net_device * dev,char * command,int total_len)4337 static int wl_cfg80211_wbtext_btm_delta(struct net_device *dev,
4338 char *command, int total_len)
4339 {
4340 int error = BCME_OK, argc = 0;
4341 int data = 0, bytes_written;
4342
4343 argc = sscanf(command, CMD_WBTEXT_BTM_DELTA " %d\n", &data);
4344 if (!argc) {
4345 error = wldev_iovar_getint(dev, "wnm_btmdelta", &data);
4346 if (error) {
4347 ANDROID_ERROR(("Failed to get wnm_btmdelta (%d)\n", error));
4348 return error;
4349 }
4350 bytes_written = snprintf(command, total_len, "%d\n", data);
4351 return bytes_written;
4352 } else {
4353 if ((error = wldev_iovar_setint(dev, "wnm_btmdelta",
4354 data)) != BCME_OK) {
4355 ANDROID_ERROR(("Failed to set wnm_btmdelta (%d)\n", error));
4356 return error;
4357 }
4358 }
4359 return error;
4360 }
4361
wl_cfg80211_wbtext_estm_enable(struct net_device * dev,char * command,int total_len)4362 static int wl_cfg80211_wbtext_estm_enable(struct net_device *dev,
4363 char *command, int total_len)
4364 {
4365 int error = BCME_OK;
4366 int data = 0, bytes_written = 0;
4367 int wnmmask = 0;
4368 char *pcmd = command;
4369
4370 bcmstrtok(&pcmd, " ", NULL);
4371
4372 error = wldev_iovar_getint(dev, "wnm", &wnmmask);
4373 if (error) {
4374 ANDROID_ERROR(("Failed to get wnm_btmdelta (%d)\n", error));
4375 return error;
4376 }
4377 ANDROID_INFO(("wnmmask %x\n", wnmmask));
4378 if (*pcmd == WL_IOCTL_ACTION_GET) {
4379 bytes_written = snprintf(command, total_len, "wbtext_estm_enable %d\n",
4380 (wnmmask & WL_WNM_ESTM) ? 1:0);
4381 return bytes_written;
4382 } else {
4383 data = bcm_atoi(pcmd);
4384 if (data == 0) {
4385 wnmmask &= ~WL_WNM_ESTM;
4386 } else {
4387 wnmmask |= WL_WNM_ESTM;
4388 }
4389 ANDROID_INFO(("wnmmask %x\n", wnmmask));
4390 if ((error = wldev_iovar_setint(dev, "wnm", wnmmask)) != BCME_OK) {
4391 ANDROID_ERROR(("Failed to set wnm mask (%d)\n", error));
4392 return error;
4393 }
4394 }
4395 return error;
4396 }
4397 #endif /* WBTEXT */
4398
4399 #ifdef PNO_SUPPORT
4400 #define PNO_PARAM_SIZE 50
4401 #define VALUE_SIZE 50
4402 #define LIMIT_STR_FMT ("%50s %50s")
4403 static int
wls_parse_batching_cmd(struct net_device * dev,char * command,int total_len)4404 wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len)
4405 {
4406 int err = BCME_OK;
4407 uint i, tokens, len_remain;
4408 char *pos, *pos2, *token, *token2, *delim;
4409 char param[PNO_PARAM_SIZE+1], value[VALUE_SIZE+1];
4410 struct dhd_pno_batch_params batch_params;
4411
4412 ANDROID_INFO(("wls_parse_batching_cmd: command=%s, len=%d\n", command, total_len));
4413 len_remain = total_len;
4414 if (len_remain > (strlen(CMD_WLS_BATCHING) + 1)) {
4415 pos = command + strlen(CMD_WLS_BATCHING) + 1;
4416 len_remain -= strlen(CMD_WLS_BATCHING) + 1;
4417 } else {
4418 ANDROID_ERROR(("wls_parse_batching_cmd: No arguments, total_len %d\n", total_len));
4419 err = BCME_ERROR;
4420 goto exit;
4421 }
4422 bzero(&batch_params, sizeof(struct dhd_pno_batch_params));
4423 if (!strncmp(pos, PNO_BATCHING_SET, strlen(PNO_BATCHING_SET))) {
4424 if (len_remain > (strlen(PNO_BATCHING_SET) + 1)) {
4425 pos += strlen(PNO_BATCHING_SET) + 1;
4426 } else {
4427 ANDROID_ERROR(("wls_parse_batching_cmd: %s missing arguments, total_len %d\n",
4428 PNO_BATCHING_SET, total_len));
4429 err = BCME_ERROR;
4430 goto exit;
4431 }
4432 while ((token = strsep(&pos, PNO_PARAMS_DELIMETER)) != NULL) {
4433 bzero(param, sizeof(param));
4434 bzero(value, sizeof(value));
4435 if (token == NULL || !*token)
4436 break;
4437 if (*token == '\0')
4438 continue;
4439 delim = strchr(token, PNO_PARAM_VALUE_DELLIMETER);
4440 if (delim != NULL)
4441 *delim = ' ';
4442
4443 tokens = sscanf(token, LIMIT_STR_FMT, param, value);
4444 if (!strncmp(param, PNO_PARAM_SCANFREQ, strlen(PNO_PARAM_SCANFREQ))) {
4445 batch_params.scan_fr = simple_strtol(value, NULL, 0);
4446 ANDROID_INFO(("scan_freq : %d\n", batch_params.scan_fr));
4447 } else if (!strncmp(param, PNO_PARAM_BESTN, strlen(PNO_PARAM_BESTN))) {
4448 batch_params.bestn = simple_strtol(value, NULL, 0);
4449 ANDROID_INFO(("bestn : %d\n", batch_params.bestn));
4450 } else if (!strncmp(param, PNO_PARAM_MSCAN, strlen(PNO_PARAM_MSCAN))) {
4451 batch_params.mscan = simple_strtol(value, NULL, 0);
4452 ANDROID_INFO(("mscan : %d\n", batch_params.mscan));
4453 } else if (!strncmp(param, PNO_PARAM_CHANNEL, strlen(PNO_PARAM_CHANNEL))) {
4454 i = 0;
4455 pos2 = value;
4456 tokens = sscanf(value, "<%s>", value);
4457 if (tokens != 1) {
4458 err = BCME_ERROR;
4459 ANDROID_ERROR(("wls_parse_batching_cmd: invalid format"
4460 " for channel"
4461 " <> params\n"));
4462 goto exit;
4463 }
4464 while ((token2 = strsep(&pos2,
4465 PNO_PARAM_CHANNEL_DELIMETER)) != NULL) {
4466 if (token2 == NULL || !*token2)
4467 break;
4468 if (*token2 == '\0')
4469 continue;
4470 if (*token2 == 'A' || *token2 == 'B') {
4471 batch_params.band = (*token2 == 'A')?
4472 WLC_BAND_5G : WLC_BAND_2G;
4473 ANDROID_INFO(("band : %s\n",
4474 (*token2 == 'A')? "A" : "B"));
4475 } else {
4476 if ((batch_params.nchan >= WL_NUMCHANNELS) ||
4477 (i >= WL_NUMCHANNELS)) {
4478 ANDROID_ERROR(("Too many nchan %d\n",
4479 batch_params.nchan));
4480 err = BCME_BUFTOOSHORT;
4481 goto exit;
4482 }
4483 batch_params.chan_list[i++] =
4484 simple_strtol(token2, NULL, 0);
4485 batch_params.nchan++;
4486 ANDROID_INFO(("channel :%d\n",
4487 batch_params.chan_list[i-1]));
4488 }
4489 }
4490 } else if (!strncmp(param, PNO_PARAM_RTT, strlen(PNO_PARAM_RTT))) {
4491 batch_params.rtt = simple_strtol(value, NULL, 0);
4492 ANDROID_INFO(("rtt : %d\n", batch_params.rtt));
4493 } else {
4494 ANDROID_ERROR(("wls_parse_batching_cmd : unknown param: %s\n", param));
4495 err = BCME_ERROR;
4496 goto exit;
4497 }
4498 }
4499 err = dhd_dev_pno_set_for_batch(dev, &batch_params);
4500 if (err < 0) {
4501 ANDROID_ERROR(("failed to configure batch scan\n"));
4502 } else {
4503 bzero(command, total_len);
4504 err = snprintf(command, total_len, "%d", err);
4505 }
4506 } else if (!strncmp(pos, PNO_BATCHING_GET, strlen(PNO_BATCHING_GET))) {
4507 err = dhd_dev_pno_get_for_batch(dev, command, total_len);
4508 if (err < 0) {
4509 ANDROID_ERROR(("failed to getting batching results\n"));
4510 } else {
4511 err = strlen(command);
4512 }
4513 } else if (!strncmp(pos, PNO_BATCHING_STOP, strlen(PNO_BATCHING_STOP))) {
4514 err = dhd_dev_pno_stop_for_batch(dev);
4515 if (err < 0) {
4516 ANDROID_ERROR(("failed to stop batching scan\n"));
4517 } else {
4518 bzero(command, total_len);
4519 err = snprintf(command, total_len, "OK");
4520 }
4521 } else {
4522 ANDROID_ERROR(("wls_parse_batching_cmd : unknown command\n"));
4523 err = BCME_ERROR;
4524 goto exit;
4525 }
4526 exit:
4527 return err;
4528 }
4529
4530 #ifndef WL_SCHED_SCAN
wl_android_set_pno_setup(struct net_device * dev,char * command,int total_len)4531 static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
4532 {
4533 wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
4534 int res = -1;
4535 int nssid = 0;
4536 cmd_tlv_t *cmd_tlv_temp;
4537 char *str_ptr;
4538 int tlv_size_left;
4539 int pno_time = 0;
4540 int pno_repeat = 0;
4541 int pno_freq_expo_max = 0;
4542
4543 #ifdef PNO_SET_DEBUG
4544 int i;
4545 char pno_in_example[] = {
4546 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
4547 'S', '1', '2', '0',
4548 'S',
4549 0x05,
4550 'd', 'l', 'i', 'n', 'k',
4551 'S',
4552 0x04,
4553 'G', 'O', 'O', 'G',
4554 'T',
4555 '0', 'B',
4556 'R',
4557 '2',
4558 'M',
4559 '2',
4560 0x00
4561 };
4562 #endif /* PNO_SET_DEBUG */
4563 ANDROID_INFO(("wl_android_set_pno_setup: command=%s, len=%d\n", command, total_len));
4564
4565 if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
4566 ANDROID_ERROR(("wl_android_set_pno_setup: argument=%d less min size\n", total_len));
4567 goto exit_proc;
4568 }
4569 #ifdef PNO_SET_DEBUG
4570 memcpy(command, pno_in_example, sizeof(pno_in_example));
4571 total_len = sizeof(pno_in_example);
4572 #endif
4573 str_ptr = command + strlen(CMD_PNOSETUP_SET);
4574 tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
4575
4576 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
4577 bzero(ssids_local, sizeof(ssids_local));
4578
4579 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
4580 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
4581 (cmd_tlv_temp->subtype == PNO_TLV_SUBTYPE_LEGACY_PNO)) {
4582
4583 str_ptr += sizeof(cmd_tlv_t);
4584 tlv_size_left -= sizeof(cmd_tlv_t);
4585
4586 if ((nssid = wl_parse_ssid_list_tlv(&str_ptr, ssids_local,
4587 MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
4588 ANDROID_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
4589 goto exit_proc;
4590 } else {
4591 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
4592 ANDROID_ERROR(("wl_android_set_pno_setup: scan duration corrupted"
4593 " field size %d\n",
4594 tlv_size_left));
4595 goto exit_proc;
4596 }
4597 str_ptr++;
4598 pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
4599 ANDROID_INFO(("wl_android_set_pno_setup: pno_time=%d\n", pno_time));
4600
4601 if (str_ptr[0] != 0) {
4602 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
4603 ANDROID_ERROR(("wl_android_set_pno_setup: pno repeat:"
4604 " corrupted field\n"));
4605 goto exit_proc;
4606 }
4607 str_ptr++;
4608 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
4609 ANDROID_INFO(("wl_android_set_pno_setup: got pno_repeat=%d\n",
4610 pno_repeat));
4611 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
4612 ANDROID_ERROR(("wl_android_set_pno_setup: FREQ_EXPO_MAX"
4613 " corrupted field size\n"));
4614 goto exit_proc;
4615 }
4616 str_ptr++;
4617 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
4618 ANDROID_INFO(("wl_android_set_pno_setup: pno_freq_expo_max=%d\n",
4619 pno_freq_expo_max));
4620 }
4621 }
4622 } else {
4623 ANDROID_ERROR(("wl_android_set_pno_setup: get wrong TLV command\n"));
4624 goto exit_proc;
4625 }
4626
4627 res = dhd_dev_pno_set_for_ssid(dev, ssids_local, nssid, pno_time, pno_repeat,
4628 pno_freq_expo_max, NULL, 0);
4629 exit_proc:
4630 return res;
4631 }
4632 #endif /* !WL_SCHED_SCAN */
4633 #endif /* PNO_SUPPORT */
4634
wl_android_get_p2p_dev_addr(struct net_device * ndev,char * command,int total_len)4635 static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
4636 {
4637 int ret;
4638 struct ether_addr p2pdev_addr;
4639
4640 #define MAC_ADDR_STR_LEN 18
4641 if (total_len < MAC_ADDR_STR_LEN) {
4642 ANDROID_ERROR(("wl_android_get_p2p_dev_addr: buflen %d is less than p2p dev addr\n",
4643 total_len));
4644 return -1;
4645 }
4646
4647 ret = wl_cfg80211_get_p2p_dev_addr(ndev, &p2pdev_addr);
4648 if (ret) {
4649 ANDROID_ERROR(("wl_android_get_p2p_dev_addr: Failed to get p2p dev addr\n"));
4650 return -1;
4651 }
4652 return (snprintf(command, total_len, MACF, ETHERP_TO_MACF(&p2pdev_addr)));
4653 }
4654
4655 int
wl_android_set_ap_mac_list(struct net_device * dev,int macmode,struct maclist * maclist)4656 wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist)
4657 {
4658 int i, j, match;
4659 int ret = 0;
4660 char mac_buf[MAX_NUM_OF_ASSOCLIST *
4661 sizeof(struct ether_addr) + sizeof(uint)] = {0};
4662 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
4663
4664 /* set filtering mode */
4665 if ((ret = wldev_ioctl_set(dev, WLC_SET_MACMODE, &macmode, sizeof(macmode)) != 0)) {
4666 ANDROID_ERROR(("wl_android_set_ap_mac_list : WLC_SET_MACMODE error=%d\n", ret));
4667 return ret;
4668 }
4669 if (macmode != MACLIST_MODE_DISABLED) {
4670 /* set the MAC filter list */
4671 if ((ret = wldev_ioctl_set(dev, WLC_SET_MACLIST, maclist,
4672 sizeof(int) + sizeof(struct ether_addr) * maclist->count)) != 0) {
4673 ANDROID_ERROR(("wl_android_set_ap_mac_list : WLC_SET_MACLIST error=%d\n", ret));
4674 return ret;
4675 }
4676 /* get the current list of associated STAs */
4677 assoc_maclist->count = MAX_NUM_OF_ASSOCLIST;
4678 if ((ret = wldev_ioctl_get(dev, WLC_GET_ASSOCLIST, assoc_maclist,
4679 sizeof(mac_buf))) != 0) {
4680 ANDROID_ERROR(("wl_android_set_ap_mac_list: WLC_GET_ASSOCLIST error=%d\n",
4681 ret));
4682 return ret;
4683 }
4684 /* do we have any STA associated? */
4685 if (assoc_maclist->count) {
4686 /* iterate each associated STA */
4687 for (i = 0; i < assoc_maclist->count; i++) {
4688 match = 0;
4689 /* compare with each entry */
4690 for (j = 0; j < maclist->count; j++) {
4691 ANDROID_INFO(("wl_android_set_ap_mac_list: associated="MACDBG
4692 "list = "MACDBG "\n",
4693 MAC2STRDBG(assoc_maclist->ea[i].octet),
4694 MAC2STRDBG(maclist->ea[j].octet)));
4695 if (memcmp(assoc_maclist->ea[i].octet,
4696 maclist->ea[j].octet, ETHER_ADDR_LEN) == 0) {
4697 match = 1;
4698 break;
4699 }
4700 }
4701 /* do conditional deauth */
4702 /* "if not in the allow list" or "if in the deny list" */
4703 if ((macmode == MACLIST_MODE_ALLOW && !match) ||
4704 (macmode == MACLIST_MODE_DENY && match)) {
4705 scb_val_t scbval;
4706
4707 scbval.val = htod32(1);
4708 memcpy(&scbval.ea, &assoc_maclist->ea[i],
4709 ETHER_ADDR_LEN);
4710 if ((ret = wldev_ioctl_set(dev,
4711 WLC_SCB_DEAUTHENTICATE_FOR_REASON,
4712 &scbval, sizeof(scb_val_t))) != 0)
4713 ANDROID_ERROR(("wl_android_set_ap_mac_list:"
4714 " WLC_SCB_DEAUTHENTICATE"
4715 " error=%d\n",
4716 ret));
4717 }
4718 }
4719 }
4720 }
4721 return ret;
4722 }
4723
4724 /*
4725 * HAPD_MAC_FILTER mac_mode mac_cnt mac_addr1 mac_addr2
4726 *
4727 */
4728 static int
wl_android_set_mac_address_filter(struct net_device * dev,char * str)4729 wl_android_set_mac_address_filter(struct net_device *dev, char* str)
4730 {
4731 int i;
4732 int ret = 0;
4733 int macnum = 0;
4734 int macmode = MACLIST_MODE_DISABLED;
4735 struct maclist *list;
4736 char eabuf[ETHER_ADDR_STR_LEN];
4737 const char *token;
4738 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4739
4740 /* string should look like below (macmode/macnum/maclist) */
4741 /* 1 2 00:11:22:33:44:55 00:11:22:33:44:ff */
4742
4743 /* get the MAC filter mode */
4744 token = strsep((char**)&str, " ");
4745 if (!token) {
4746 return -1;
4747 }
4748 macmode = bcm_atoi(token);
4749
4750 if (macmode < MACLIST_MODE_DISABLED || macmode > MACLIST_MODE_ALLOW) {
4751 ANDROID_ERROR(("wl_android_set_mac_address_filter: invalid macmode %d\n", macmode));
4752 return -1;
4753 }
4754
4755 token = strsep((char**)&str, " ");
4756 if (!token) {
4757 return -1;
4758 }
4759 macnum = bcm_atoi(token);
4760 if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
4761 ANDROID_ERROR(("wl_android_set_mac_address_filter: invalid number of MAC"
4762 " address entries %d\n",
4763 macnum));
4764 return -1;
4765 }
4766 /* allocate memory for the MAC list */
4767 list = (struct maclist*) MALLOCZ(cfg->osh, sizeof(int) +
4768 sizeof(struct ether_addr) * macnum);
4769 if (!list) {
4770 ANDROID_ERROR(("wl_android_set_mac_address_filter : failed to allocate memory\n"));
4771 return -1;
4772 }
4773 /* prepare the MAC list */
4774 list->count = htod32(macnum);
4775 bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
4776 for (i = 0; i < list->count; i++) {
4777 token = strsep((char**)&str, " ");
4778 if (token == NULL) {
4779 ANDROID_ERROR(("wl_android_set_mac_address_filter : No mac address present\n"));
4780 ret = -EINVAL;
4781 goto exit;
4782 }
4783 strlcpy(eabuf, token, sizeof(eabuf));
4784 if (!(ret = bcm_ether_atoe(eabuf, &list->ea[i]))) {
4785 ANDROID_ERROR(("wl_android_set_mac_address_filter : mac parsing err index=%d,"
4786 " addr=%s\n",
4787 i, eabuf));
4788 list->count = i;
4789 break;
4790 }
4791 ANDROID_INFO(("wl_android_set_mac_address_filter : %d/%d MACADDR=%s",
4792 i, list->count, eabuf));
4793 }
4794 if (i == 0)
4795 goto exit;
4796
4797 /* set the list */
4798 if ((ret = wl_android_set_ap_mac_list(dev, macmode, list)) != 0)
4799 ANDROID_ERROR(("wl_android_set_mac_address_filter: Setting MAC list failed error=%d\n",
4800 ret));
4801
4802 exit:
4803 MFREE(cfg->osh, list, sizeof(int) + sizeof(struct ether_addr) * macnum);
4804
4805 return ret;
4806 }
4807
wl_android_get_factory_mac_addr(struct net_device * ndev,char * command,int total_len)4808 static int wl_android_get_factory_mac_addr(struct net_device *ndev, char *command, int total_len)
4809 {
4810 int ret;
4811 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
4812
4813 if (total_len < ETHER_ADDR_STR_LEN) {
4814 ANDROID_ERROR(("wl_android_get_factory_mac_addr buflen %d"
4815 "is less than factory mac addr\n", total_len));
4816 return BCME_ERROR;
4817 }
4818 ret = snprintf(command, total_len, MACDBG,
4819 MAC2STRDBG(bcmcfg_to_prmry_ndev(cfg)->perm_addr));
4820 return ret;
4821 }
4822
4823 #if defined(WLAN_ACCEL_BOOT)
wl_android_wifi_accel_on(struct net_device * dev,bool force_reg_on)4824 int wl_android_wifi_accel_on(struct net_device *dev, bool force_reg_on)
4825 {
4826 int ret = 0;
4827
4828 ANDROID_ERROR(("%s: force_reg_on = %d\n", __FUNCTION__, force_reg_on));
4829 if (!dev) {
4830 ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
4831 return -EINVAL;
4832 }
4833
4834 if (force_reg_on) {
4835 /* First resume the bus if it is in suspended state */
4836 ret = dhd_net_bus_resume(dev, 0);
4837 if (ret) {
4838 ANDROID_ERROR(("%s: dhd_net_bus_resume failed\n", __FUNCTION__));
4839 }
4840 /* Toggle wl_reg_on */
4841 ret = wl_android_wifi_off(dev, TRUE);
4842 if (ret) {
4843 ANDROID_ERROR(("%s: wl_android_wifi_off failed\n", __FUNCTION__));
4844 }
4845 ret = wl_android_wifi_on(dev);
4846 if (ret) {
4847 ANDROID_ERROR(("%s: wl_android_wifi_on failed\n", __FUNCTION__));
4848 }
4849 } else {
4850 ret = dhd_net_bus_resume(dev, 0);
4851 }
4852
4853 return ret;
4854 }
4855
wl_android_wifi_accel_off(struct net_device * dev,bool force_reg_on)4856 int wl_android_wifi_accel_off(struct net_device *dev, bool force_reg_on)
4857 {
4858 int ret = 0;
4859
4860 ANDROID_ERROR(("%s: force_reg_on = %d\n", __FUNCTION__, force_reg_on));
4861 if (!dev) {
4862 ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
4863 return -EINVAL;
4864 }
4865
4866 if (force_reg_on) {
4867 ANDROID_ERROR(("%s: do nothing as wl_reg_on will be toggled in UP\n",
4868 __FUNCTION__));
4869 } else {
4870 ret = dhd_net_bus_suspend(dev);
4871 }
4872
4873 return ret;
4874 }
4875 #endif /* WLAN_ACCEL_BOOT */
4876
4877 #ifdef WBRC
4878 extern int wbrc_wl2bt_reset(void);
4879 #endif /* WBRC */
4880
4881 /**
4882 * Global function definitions (declared in wl_android.h)
4883 */
4884
wl_android_wifi_on(struct net_device * dev)4885 int wl_android_wifi_on(struct net_device *dev)
4886 {
4887 int ret = 0;
4888 int retry = POWERUP_MAX_RETRY;
4889 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
4890
4891 BCM_REFERENCE(dhdp);
4892 if (!dev) {
4893 ANDROID_ERROR(("wl_android_wifi_on: dev is null\n"));
4894 return -EINVAL;
4895 }
4896
4897 dhd_net_if_lock(dev);
4898 WL_MSG(dev->name, "in g_wifi_on=%d\n", g_wifi_on);
4899 if (!g_wifi_on) {
4900 do {
4901 dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY);
4902 #ifdef BCMSDIO
4903 ret = dhd_net_bus_resume(dev, 0);
4904 if (ret)
4905 goto retry_power;
4906 #endif /* BCMSDIO */
4907 ret = dhd_net_bus_devreset(dev, FALSE);
4908 #ifdef WBRC
4909 if (dhdp->dhd_induce_bh_error == DHD_INDUCE_BH_ON_FAIL_ONCE) {
4910 ANDROID_ERROR(("%s: dhd_induce_bh_error = %d\n",
4911 __FUNCTION__, dhdp->dhd_induce_bh_error));
4912 /* Forcefully set error */
4913 ret = BCME_ERROR;
4914 /* Clear the induced bh error */
4915 dhdp->dhd_induce_bh_error = DHD_INDUCE_ERROR_CLEAR;
4916 }
4917 if (dhdp->dhd_induce_bh_error == DHD_INDUCE_BH_ON_FAIL_ALWAYS) {
4918 ANDROID_ERROR(("%s: dhd_induce_bh_error = %d\n",
4919 __FUNCTION__, dhdp->dhd_induce_bh_error));
4920 /* Forcefully set error */
4921 ret = BCME_ERROR;
4922 }
4923 #endif /* WBRC */
4924 if (ret)
4925 goto retry_power;
4926 #if defined(BCMSDIO) || defined(BCMDBUS)
4927 #ifdef BCMSDIO
4928 dhd_net_bus_resume(dev, 1);
4929 #endif /* BCMSDIO */
4930 ret = dhd_dev_init_ioctl(dev);
4931 if (ret < 0) {
4932 goto retry_bus;
4933 }
4934 #endif /* BCMSDIO || BCMDBUS */
4935 if (ret == 0) {
4936 break;
4937 }
4938 #if defined(BCMSDIO) || defined(BCMDBUS)
4939 retry_bus:
4940 #ifdef BCMSDIO
4941 dhd_net_bus_suspend(dev);
4942 #endif /* BCMSDIO */
4943 #endif /* BCMSDIO || BCMDBUS */
4944 retry_power:
4945 ANDROID_ERROR(("failed to power up wifi chip, retry again (%d left) **\n\n",
4946 retry));
4947 dhd_net_bus_devreset(dev, TRUE);
4948 dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
4949 #ifdef WBRC
4950 /* Inform BT reset which will internally wait till BT reset is done */
4951 if (wbrc_wl2bt_reset()) {
4952 ANDROID_ERROR(("Failed to reset BT, nothing to be done!!!!\n"));
4953 }
4954 #endif /* WBRC */
4955 } while (retry-- > 0);
4956 if (ret != 0) {
4957 ANDROID_ERROR(("failed to power up wifi chip, max retry reached **\n\n"));
4958 #ifdef BCM_DETECT_TURN_ON_FAILURE
4959 BUG_ON(1);
4960 #endif /* BCM_DETECT_TURN_ON_FAILURE */
4961 goto exit;
4962 }
4963 g_wifi_on = TRUE;
4964 }
4965
4966 exit:
4967 if (ret)
4968 WL_MSG(dev->name, "Failed %d\n", ret);
4969 else
4970 WL_MSG(dev->name, "Success\n");
4971 dhd_net_if_unlock(dev);
4972 return ret;
4973 }
4974
wl_android_wifi_off(struct net_device * dev,bool on_failure)4975 int wl_android_wifi_off(struct net_device *dev, bool on_failure)
4976 {
4977 int ret = 0;
4978
4979 if (!dev) {
4980 ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
4981 return -EINVAL;
4982 }
4983
4984 #if defined(BCMPCIE) && defined(DHD_DEBUG_UART)
4985 ret = dhd_debug_uart_is_running(dev);
4986 if (ret) {
4987 ANDROID_ERROR(("wl_android_wifi_off: - Debug UART App is running\n"));
4988 return -EBUSY;
4989 }
4990 #endif /* BCMPCIE && DHD_DEBUG_UART */
4991 dhd_net_if_lock(dev);
4992 WL_MSG(dev->name, "in g_wifi_on=%d, on_failure=%d\n", g_wifi_on, on_failure);
4993 if (g_wifi_on || on_failure) {
4994 #if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMDBUS)
4995 ret = dhd_net_bus_devreset(dev, TRUE);
4996 #ifdef BCMSDIO
4997 dhd_net_bus_suspend(dev);
4998 #endif /* BCMSDIO */
4999 #endif /* BCMSDIO || BCMPCIE || BCMDBUS */
5000 dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
5001 g_wifi_on = FALSE;
5002 }
5003 WL_MSG(dev->name, "out\n");
5004 dhd_net_if_unlock(dev);
5005
5006 return ret;
5007 }
5008
wl_android_set_fwpath(struct net_device * net,char * command,int total_len)5009 static int wl_android_set_fwpath(struct net_device *net, char *command, int total_len)
5010 {
5011 if ((strlen(command) - strlen(CMD_SETFWPATH)) > MOD_PARAM_PATHLEN)
5012 return -1;
5013 return dhd_net_set_fw_path(net, command + strlen(CMD_SETFWPATH) + 1);
5014 }
5015
5016 #ifdef CONNECTION_STATISTICS
5017 static int
wl_chanim_stats(struct net_device * dev,u8 * chan_idle)5018 wl_chanim_stats(struct net_device *dev, u8 *chan_idle)
5019 {
5020 int err;
5021 wl_chanim_stats_t *list;
5022 /* Parameter _and_ returned buffer of chanim_stats. */
5023 wl_chanim_stats_t param;
5024 u8 result[WLC_IOCTL_SMLEN];
5025 chanim_stats_t *stats;
5026
5027 bzero(¶m, sizeof(param));
5028
5029 param.buflen = htod32(sizeof(wl_chanim_stats_t));
5030 param.count = htod32(WL_CHANIM_COUNT_ONE);
5031
5032 if ((err = wldev_iovar_getbuf(dev, "chanim_stats", (char*)¶m, sizeof(wl_chanim_stats_t),
5033 (char*)result, sizeof(result), 0)) < 0) {
5034 ANDROID_ERROR(("Failed to get chanim results %d \n", err));
5035 return err;
5036 }
5037
5038 list = (wl_chanim_stats_t*)result;
5039
5040 list->buflen = dtoh32(list->buflen);
5041 list->version = dtoh32(list->version);
5042 list->count = dtoh32(list->count);
5043
5044 if (list->buflen == 0) {
5045 list->version = 0;
5046 list->count = 0;
5047 } else if (list->version != WL_CHANIM_STATS_VERSION) {
5048 ANDROID_ERROR(("Sorry, firmware has wl_chanim_stats version %d "
5049 "but driver supports only version %d.\n",
5050 list->version, WL_CHANIM_STATS_VERSION));
5051 list->buflen = 0;
5052 list->count = 0;
5053 }
5054
5055 stats = list->stats;
5056 stats->glitchcnt = dtoh32(stats->glitchcnt);
5057 stats->badplcp = dtoh32(stats->badplcp);
5058 stats->chanspec = dtoh16(stats->chanspec);
5059 stats->timestamp = dtoh32(stats->timestamp);
5060 stats->chan_idle = dtoh32(stats->chan_idle);
5061
5062 ANDROID_INFO(("chanspec: 0x%4x glitch: %d badplcp: %d idle: %d timestamp: %d\n",
5063 stats->chanspec, stats->glitchcnt, stats->badplcp, stats->chan_idle,
5064 stats->timestamp));
5065
5066 *chan_idle = stats->chan_idle;
5067
5068 return (err);
5069 }
5070
5071 static int
wl_android_get_connection_stats(struct net_device * dev,char * command,int total_len)5072 wl_android_get_connection_stats(struct net_device *dev, char *command, int total_len)
5073 {
5074 static char iovar_buf[WLC_IOCTL_MAXLEN];
5075 const wl_cnt_wlc_t* wlc_cnt = NULL;
5076 #ifndef DISABLE_IF_COUNTERS
5077 wl_if_stats_t* if_stats = NULL;
5078 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5079 #ifdef BCMDONGLEHOST
5080 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
5081 #endif /* BCMDONGLEHOST */
5082 #endif /* DISABLE_IF_COUNTERS */
5083
5084 int link_speed = 0;
5085 struct connection_stats *output;
5086 unsigned int bufsize = 0;
5087 int bytes_written = -1;
5088 int ret = 0;
5089
5090 ANDROID_INFO(("wl_android_get_connection_stats: enter Get Connection Stats\n"));
5091
5092 if (total_len <= 0) {
5093 ANDROID_ERROR(("wl_android_get_connection_stats: invalid buffer size %d\n", total_len));
5094 goto error;
5095 }
5096
5097 bufsize = total_len;
5098 if (bufsize < sizeof(struct connection_stats)) {
5099 ANDROID_ERROR(("wl_android_get_connection_stats: not enough buffer size, provided=%u,"
5100 " requires=%zu\n",
5101 bufsize,
5102 sizeof(struct connection_stats)));
5103 goto error;
5104 }
5105
5106 output = (struct connection_stats *)command;
5107
5108 #ifndef DISABLE_IF_COUNTERS
5109 if_stats = (wl_if_stats_t *)MALLOCZ(cfg->osh, sizeof(*if_stats));
5110 if (if_stats == NULL) {
5111 ANDROID_ERROR(("wl_android_get_connection_stats: MALLOCZ failed\n"));
5112 goto error;
5113 }
5114 bzero(if_stats, sizeof(*if_stats));
5115
5116 #ifdef BCMDONGLEHOST
5117 if (FW_SUPPORTED(dhdp, ifst)) {
5118 ret = wl_cfg80211_ifstats_counters(dev, if_stats);
5119 } else
5120 #endif /* BCMDONGLEHOST */
5121 {
5122 ret = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
5123 (char *)if_stats, sizeof(*if_stats), NULL);
5124 }
5125
5126 ret = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
5127 (char *)if_stats, sizeof(*if_stats), NULL);
5128 if (ret) {
5129 ANDROID_ERROR(("wl_android_get_connection_stats: if_counters not supported ret=%d\n",
5130 ret));
5131
5132 /* In case if_stats IOVAR is not supported, get information from counters. */
5133 #endif /* DISABLE_IF_COUNTERS */
5134 ret = wldev_iovar_getbuf(dev, "counters", NULL, 0,
5135 iovar_buf, WLC_IOCTL_MAXLEN, NULL);
5136 if (unlikely(ret)) {
5137 ANDROID_ERROR(("counters error (%d) - size = %zu\n", ret, sizeof(wl_cnt_wlc_t)));
5138 goto error;
5139 }
5140 ret = wl_cntbuf_to_xtlv_format(NULL, iovar_buf, WL_CNTBUF_MAX_SIZE, 0);
5141 if (ret != BCME_OK) {
5142 ANDROID_ERROR(("wl_android_get_connection_stats:"
5143 " wl_cntbuf_to_xtlv_format ERR %d\n",
5144 ret));
5145 goto error;
5146 }
5147
5148 if (!(wlc_cnt = GET_WLCCNT_FROM_CNTBUF(iovar_buf))) {
5149 ANDROID_ERROR(("wl_android_get_connection_stats: wlc_cnt NULL!\n"));
5150 goto error;
5151 }
5152
5153 output->txframe = dtoh32(wlc_cnt->txframe);
5154 output->txbyte = dtoh32(wlc_cnt->txbyte);
5155 output->txerror = dtoh32(wlc_cnt->txerror);
5156 output->rxframe = dtoh32(wlc_cnt->rxframe);
5157 output->rxbyte = dtoh32(wlc_cnt->rxbyte);
5158 output->txfail = dtoh32(wlc_cnt->txfail);
5159 output->txretry = dtoh32(wlc_cnt->txretry);
5160 output->txretrie = dtoh32(wlc_cnt->txretrie);
5161 output->txrts = dtoh32(wlc_cnt->txrts);
5162 output->txnocts = dtoh32(wlc_cnt->txnocts);
5163 output->txexptime = dtoh32(wlc_cnt->txexptime);
5164 #ifndef DISABLE_IF_COUNTERS
5165 } else {
5166 /* Populate from if_stats. */
5167 if (dtoh16(if_stats->version) > WL_IF_STATS_T_VERSION) {
5168 ANDROID_ERROR(("wl_android_get_connection_stats: incorrect version of"
5169 " wl_if_stats_t,"
5170 " expected=%u got=%u\n",
5171 WL_IF_STATS_T_VERSION, if_stats->version));
5172 goto error;
5173 }
5174
5175 output->txframe = (uint32)dtoh64(if_stats->txframe);
5176 output->txbyte = (uint32)dtoh64(if_stats->txbyte);
5177 output->txerror = (uint32)dtoh64(if_stats->txerror);
5178 output->rxframe = (uint32)dtoh64(if_stats->rxframe);
5179 output->rxbyte = (uint32)dtoh64(if_stats->rxbyte);
5180 output->txfail = (uint32)dtoh64(if_stats->txfail);
5181 output->txretry = (uint32)dtoh64(if_stats->txretry);
5182 output->txretrie = (uint32)dtoh64(if_stats->txretrie);
5183 if (dtoh16(if_stats->length) > OFFSETOF(wl_if_stats_t, txexptime)) {
5184 output->txexptime = (uint32)dtoh64(if_stats->txexptime);
5185 output->txrts = (uint32)dtoh64(if_stats->txrts);
5186 output->txnocts = (uint32)dtoh64(if_stats->txnocts);
5187 } else {
5188 output->txexptime = 0;
5189 output->txrts = 0;
5190 output->txnocts = 0;
5191 }
5192 }
5193 #endif /* DISABLE_IF_COUNTERS */
5194
5195 /* link_speed is in kbps */
5196 ret = wldev_get_link_speed(dev, &link_speed);
5197 if (ret || link_speed < 0) {
5198 ANDROID_ERROR(("wl_android_get_connection_stats: wldev_get_link_speed()"
5199 " failed, ret=%d, speed=%d\n",
5200 ret, link_speed));
5201 goto error;
5202 }
5203
5204 output->txrate = link_speed;
5205
5206 /* Channel idle ratio. */
5207 if (wl_chanim_stats(dev, &(output->chan_idle)) < 0) {
5208 output->chan_idle = 0;
5209 };
5210
5211 bytes_written = sizeof(struct connection_stats);
5212
5213 error:
5214 #ifndef DISABLE_IF_COUNTERS
5215 if (if_stats) {
5216 MFREE(cfg->osh, if_stats, sizeof(*if_stats));
5217 }
5218 #endif /* DISABLE_IF_COUNTERS */
5219
5220 return bytes_written;
5221 }
5222 #endif /* CONNECTION_STATISTICS */
5223
5224 #ifdef WL_NATOE
5225 static int
wl_android_process_natoe_cmd(struct net_device * dev,char * command,int total_len)5226 wl_android_process_natoe_cmd(struct net_device *dev, char *command, int total_len)
5227 {
5228 int ret = BCME_ERROR;
5229 char *pcmd = command;
5230 char *str = NULL;
5231 wl_natoe_cmd_info_t cmd_info;
5232 const wl_natoe_sub_cmd_t *natoe_cmd = &natoe_cmd_list[0];
5233
5234 /* skip to cmd name after "natoe" */
5235 str = bcmstrtok(&pcmd, " ", NULL);
5236
5237 /* If natoe subcmd name is not provided, return error */
5238 if (*pcmd == '\0') {
5239 ANDROID_ERROR(("natoe subcmd not provided wl_android_process_natoe_cmd\n"));
5240 ret = -EINVAL;
5241 return ret;
5242 }
5243
5244 /* get the natoe command name to str */
5245 str = bcmstrtok(&pcmd, " ", NULL);
5246
5247 while (natoe_cmd->name != NULL) {
5248 if (strcmp(natoe_cmd->name, str) == 0) {
5249 /* dispacth cmd to appropriate handler */
5250 if (natoe_cmd->handler) {
5251 cmd_info.command = command;
5252 cmd_info.tot_len = total_len;
5253 ret = natoe_cmd->handler(dev, natoe_cmd, pcmd, &cmd_info);
5254 }
5255 return ret;
5256 }
5257 natoe_cmd++;
5258 }
5259 return ret;
5260 }
5261
5262 static int
wlu_natoe_set_vars_cbfn(void * ctx,uint8 * data,uint16 type,uint16 len)5263 wlu_natoe_set_vars_cbfn(void *ctx, uint8 *data, uint16 type, uint16 len)
5264 {
5265 int res = BCME_OK;
5266 wl_natoe_cmd_info_t *cmd_info = (wl_natoe_cmd_info_t *)ctx;
5267 uint8 *command = cmd_info->command;
5268 uint16 total_len = cmd_info->tot_len;
5269 uint16 bytes_written = 0;
5270
5271 UNUSED_PARAMETER(len);
5272
5273 switch (type) {
5274
5275 case WL_NATOE_XTLV_ENABLE:
5276 {
5277 bytes_written = snprintf(command, total_len, "natoe: %s\n",
5278 *data?"enabled":"disabled");
5279 cmd_info->bytes_written = bytes_written;
5280 break;
5281 }
5282
5283 case WL_NATOE_XTLV_CONFIG_IPS:
5284 {
5285 wl_natoe_config_ips_t *config_ips;
5286 uint8 buf[16];
5287
5288 config_ips = (wl_natoe_config_ips_t *)data;
5289 bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_ip, buf);
5290 bytes_written = snprintf(command, total_len, "sta ip: %s\n", buf);
5291 bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_netmask, buf);
5292 bytes_written += snprintf(command + bytes_written, total_len,
5293 "sta netmask: %s\n", buf);
5294 bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_router_ip, buf);
5295 bytes_written += snprintf(command + bytes_written, total_len,
5296 "sta router ip: %s\n", buf);
5297 bcm_ip_ntoa((struct ipv4_addr *)&config_ips->sta_dnsip, buf);
5298 bytes_written += snprintf(command + bytes_written, total_len,
5299 "sta dns ip: %s\n", buf);
5300 bcm_ip_ntoa((struct ipv4_addr *)&config_ips->ap_ip, buf);
5301 bytes_written += snprintf(command + bytes_written, total_len,
5302 "ap ip: %s\n", buf);
5303 bcm_ip_ntoa((struct ipv4_addr *)&config_ips->ap_netmask, buf);
5304 bytes_written += snprintf(command + bytes_written, total_len,
5305 "ap netmask: %s\n", buf);
5306 cmd_info->bytes_written = bytes_written;
5307 break;
5308 }
5309
5310 case WL_NATOE_XTLV_CONFIG_PORTS:
5311 {
5312 wl_natoe_ports_config_t *ports_config;
5313
5314 ports_config = (wl_natoe_ports_config_t *)data;
5315 bytes_written = snprintf(command, total_len, "starting port num: %d\n",
5316 dtoh16(ports_config->start_port_num));
5317 bytes_written += snprintf(command + bytes_written, total_len,
5318 "number of ports: %d\n", dtoh16(ports_config->no_of_ports));
5319 cmd_info->bytes_written = bytes_written;
5320 break;
5321 }
5322
5323 case WL_NATOE_XTLV_DBG_STATS:
5324 {
5325 char *stats_dump = (char *)data;
5326
5327 bytes_written = snprintf(command, total_len, "%s\n", stats_dump);
5328 cmd_info->bytes_written = bytes_written;
5329 break;
5330 }
5331
5332 case WL_NATOE_XTLV_TBL_CNT:
5333 {
5334 bytes_written = snprintf(command, total_len, "natoe max tbl entries: %d\n",
5335 dtoh32(*(uint32 *)data));
5336 cmd_info->bytes_written = bytes_written;
5337 break;
5338 }
5339
5340 default:
5341 /* ignore */
5342 break;
5343 }
5344
5345 return res;
5346 }
5347
5348 /*
5349 * --- common for all natoe get commands ----
5350 */
5351 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)5352 wl_natoe_get_ioctl(struct net_device *dev, wl_natoe_ioc_t *natoe_ioc,
5353 uint16 iocsz, uint8 *buf, uint16 buflen, wl_natoe_cmd_info_t *cmd_info)
5354 {
5355 /* for gets we only need to pass ioc header */
5356 wl_natoe_ioc_t *iocresp = (wl_natoe_ioc_t *)buf;
5357 int res;
5358
5359 /* send getbuf natoe iovar */
5360 res = wldev_iovar_getbuf(dev, "natoe", natoe_ioc, iocsz, buf,
5361 buflen, NULL);
5362
5363 /* check the response buff */
5364 if ((res == BCME_OK)) {
5365 /* scans ioctl tlvbuf f& invokes the cbfn for processing */
5366 res = bcm_unpack_xtlv_buf(cmd_info, iocresp->data, iocresp->len,
5367 BCM_XTLV_OPTION_ALIGN32, wlu_natoe_set_vars_cbfn);
5368
5369 if (res == BCME_OK) {
5370 res = cmd_info->bytes_written;
5371 }
5372 }
5373 else
5374 {
5375 ANDROID_ERROR(("wl_natoe_get_ioctl: get command failed code %d\n", res));
5376 res = BCME_ERROR;
5377 }
5378
5379 return res;
5380 }
5381
5382 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)5383 wl_android_natoe_subcmd_enable(struct net_device *dev, const wl_natoe_sub_cmd_t *cmd,
5384 char *command, wl_natoe_cmd_info_t *cmd_info)
5385 {
5386 int ret = BCME_OK;
5387 wl_natoe_ioc_t *natoe_ioc;
5388 char *pcmd = command;
5389 uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
5390 uint16 buflen = WL_NATOE_IOC_BUFSZ;
5391 bcm_xtlv_t *pxtlv = NULL;
5392 char *ioctl_buf = NULL;
5393 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5394
5395 ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
5396 if (!ioctl_buf) {
5397 ANDROID_ERROR(("ioctl memory alloc failed\n"));
5398 return -ENOMEM;
5399 }
5400
5401 /* alloc mem for ioctl headr + tlv data */
5402 natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz);
5403 if (!natoe_ioc) {
5404 ANDROID_ERROR(("ioctl header memory alloc failed\n"));
5405 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5406 return -ENOMEM;
5407 }
5408
5409 /* make up natoe cmd ioctl header */
5410 natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
5411 natoe_ioc->id = htod16(cmd->id);
5412 natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
5413 pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
5414
5415 if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
5416 iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
5417 ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
5418 WLC_IOCTL_MEDLEN, cmd_info);
5419 if (ret != BCME_OK) {
5420 ANDROID_ERROR(("Fail to get iovar wl_android_natoe_subcmd_enable\n"));
5421 ret = -EINVAL;
5422 }
5423 } else { /* set */
5424 uint8 val = bcm_atoi(pcmd);
5425
5426 /* buflen is max tlv data we can write, it will be decremented as we pack */
5427 /* save buflen at start */
5428 uint16 buflen_at_start = buflen;
5429
5430 /* we'll adjust final ioc size at the end */
5431 ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_ENABLE,
5432 sizeof(uint8), &val, BCM_XTLV_OPTION_ALIGN32);
5433
5434 if (ret != BCME_OK) {
5435 ret = -EINVAL;
5436 goto exit;
5437 }
5438
5439 /* adjust iocsz to the end of last data record */
5440 natoe_ioc->len = (buflen_at_start - buflen);
5441 iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
5442
5443 ret = wldev_iovar_setbuf(dev, "natoe",
5444 natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
5445 if (ret != BCME_OK) {
5446 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
5447 ret = -EINVAL;
5448 }
5449 }
5450
5451 exit:
5452 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5453 MFREE(cfg->osh, natoe_ioc, iocsz);
5454
5455 return ret;
5456 }
5457
5458 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)5459 wl_android_natoe_subcmd_config_ips(struct net_device *dev,
5460 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info)
5461 {
5462 int ret = BCME_OK;
5463 wl_natoe_config_ips_t config_ips;
5464 wl_natoe_ioc_t *natoe_ioc;
5465 char *pcmd = command;
5466 char *str;
5467 uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
5468 uint16 buflen = WL_NATOE_IOC_BUFSZ;
5469 bcm_xtlv_t *pxtlv = NULL;
5470 char *ioctl_buf = NULL;
5471 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5472
5473 ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
5474 if (!ioctl_buf) {
5475 ANDROID_ERROR(("ioctl memory alloc failed\n"));
5476 return -ENOMEM;
5477 }
5478
5479 /* alloc mem for ioctl headr + tlv data */
5480 natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz);
5481 if (!natoe_ioc) {
5482 ANDROID_ERROR(("ioctl header memory alloc failed\n"));
5483 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5484 return -ENOMEM;
5485 }
5486
5487 /* make up natoe cmd ioctl header */
5488 natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
5489 natoe_ioc->id = htod16(cmd->id);
5490 natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
5491 pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
5492
5493 if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
5494 iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
5495 ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
5496 WLC_IOCTL_MEDLEN, cmd_info);
5497 if (ret != BCME_OK) {
5498 ANDROID_ERROR(("Fail to get iovar wl_android_natoe_subcmd_config_ips\n"));
5499 ret = -EINVAL;
5500 }
5501 } else { /* set */
5502 /* buflen is max tlv data we can write, it will be decremented as we pack */
5503 /* save buflen at start */
5504 uint16 buflen_at_start = buflen;
5505
5506 bzero(&config_ips, sizeof(config_ips));
5507
5508 str = bcmstrtok(&pcmd, " ", NULL);
5509 if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_ip)) {
5510 ANDROID_ERROR(("Invalid STA IP addr %s\n", str));
5511 ret = -EINVAL;
5512 goto exit;
5513 }
5514
5515 str = bcmstrtok(&pcmd, " ", NULL);
5516 if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_netmask)) {
5517 ANDROID_ERROR(("Invalid STA netmask %s\n", str));
5518 ret = -EINVAL;
5519 goto exit;
5520 }
5521
5522 str = bcmstrtok(&pcmd, " ", NULL);
5523 if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_router_ip)) {
5524 ANDROID_ERROR(("Invalid STA router IP addr %s\n", str));
5525 ret = -EINVAL;
5526 goto exit;
5527 }
5528
5529 str = bcmstrtok(&pcmd, " ", NULL);
5530 if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.sta_dnsip)) {
5531 ANDROID_ERROR(("Invalid STA DNS IP addr %s\n", str));
5532 ret = -EINVAL;
5533 goto exit;
5534 }
5535
5536 str = bcmstrtok(&pcmd, " ", NULL);
5537 if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.ap_ip)) {
5538 ANDROID_ERROR(("Invalid AP IP addr %s\n", str));
5539 ret = -EINVAL;
5540 goto exit;
5541 }
5542
5543 str = bcmstrtok(&pcmd, " ", NULL);
5544 if (!str || !bcm_atoipv4(str, (struct ipv4_addr *)&config_ips.ap_netmask)) {
5545 ANDROID_ERROR(("Invalid AP netmask %s\n", str));
5546 ret = -EINVAL;
5547 goto exit;
5548 }
5549
5550 ret = bcm_pack_xtlv_entry((uint8**)&pxtlv,
5551 &buflen, WL_NATOE_XTLV_CONFIG_IPS, sizeof(config_ips),
5552 &config_ips, BCM_XTLV_OPTION_ALIGN32);
5553
5554 if (ret != BCME_OK) {
5555 ret = -EINVAL;
5556 goto exit;
5557 }
5558
5559 /* adjust iocsz to the end of last data record */
5560 natoe_ioc->len = (buflen_at_start - buflen);
5561 iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
5562
5563 ret = wldev_iovar_setbuf(dev, "natoe",
5564 natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
5565 if (ret != BCME_OK) {
5566 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
5567 ret = -EINVAL;
5568 }
5569 }
5570
5571 exit:
5572 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5573 MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ);
5574
5575 return ret;
5576 }
5577
5578 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)5579 wl_android_natoe_subcmd_config_ports(struct net_device *dev,
5580 const wl_natoe_sub_cmd_t *cmd, char *command, wl_natoe_cmd_info_t *cmd_info)
5581 {
5582 int ret = BCME_OK;
5583 wl_natoe_ports_config_t ports_config;
5584 wl_natoe_ioc_t *natoe_ioc;
5585 char *pcmd = command;
5586 char *str;
5587 uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
5588 uint16 buflen = WL_NATOE_IOC_BUFSZ;
5589 bcm_xtlv_t *pxtlv = NULL;
5590 char *ioctl_buf = NULL;
5591 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5592
5593 ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
5594 if (!ioctl_buf) {
5595 ANDROID_ERROR(("ioctl memory alloc failed\n"));
5596 return -ENOMEM;
5597 }
5598
5599 /* alloc mem for ioctl headr + tlv data */
5600 natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz);
5601 if (!natoe_ioc) {
5602 ANDROID_ERROR(("ioctl header memory alloc failed\n"));
5603 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5604 return -ENOMEM;
5605 }
5606
5607 /* make up natoe cmd ioctl header */
5608 natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
5609 natoe_ioc->id = htod16(cmd->id);
5610 natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
5611 pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
5612
5613 if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
5614 iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
5615 ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
5616 WLC_IOCTL_MEDLEN, cmd_info);
5617 if (ret != BCME_OK) {
5618 ANDROID_ERROR(("Fail to get iovar wl_android_natoe_subcmd_config_ports\n"));
5619 ret = -EINVAL;
5620 }
5621 } else { /* set */
5622 /* buflen is max tlv data we can write, it will be decremented as we pack */
5623 /* save buflen at start */
5624 uint16 buflen_at_start = buflen;
5625
5626 bzero(&ports_config, sizeof(ports_config));
5627
5628 str = bcmstrtok(&pcmd, " ", NULL);
5629 if (!str) {
5630 ANDROID_ERROR(("Invalid port string %s\n", str));
5631 ret = -EINVAL;
5632 goto exit;
5633 }
5634 ports_config.start_port_num = htod16(bcm_atoi(str));
5635
5636 str = bcmstrtok(&pcmd, " ", NULL);
5637 if (!str) {
5638 ANDROID_ERROR(("Invalid port string %s\n", str));
5639 ret = -EINVAL;
5640 goto exit;
5641 }
5642 ports_config.no_of_ports = htod16(bcm_atoi(str));
5643
5644 if ((uint32)(ports_config.start_port_num + ports_config.no_of_ports) >
5645 NATOE_MAX_PORT_NUM) {
5646 ANDROID_ERROR(("Invalid port configuration\n"));
5647 ret = -EINVAL;
5648 goto exit;
5649 }
5650 ret = bcm_pack_xtlv_entry((uint8**)&pxtlv,
5651 &buflen, WL_NATOE_XTLV_CONFIG_PORTS, sizeof(ports_config),
5652 &ports_config, BCM_XTLV_OPTION_ALIGN32);
5653
5654 if (ret != BCME_OK) {
5655 ret = -EINVAL;
5656 goto exit;
5657 }
5658
5659 /* adjust iocsz to the end of last data record */
5660 natoe_ioc->len = (buflen_at_start - buflen);
5661 iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
5662
5663 ret = wldev_iovar_setbuf(dev, "natoe",
5664 natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
5665 if (ret != BCME_OK) {
5666 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
5667 ret = -EINVAL;
5668 }
5669 }
5670
5671 exit:
5672 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5673 MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ);
5674
5675 return ret;
5676 }
5677
5678 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)5679 wl_android_natoe_subcmd_dbg_stats(struct net_device *dev, const wl_natoe_sub_cmd_t *cmd,
5680 char *command, wl_natoe_cmd_info_t *cmd_info)
5681 {
5682 int ret = BCME_OK;
5683 wl_natoe_ioc_t *natoe_ioc;
5684 char *pcmd = command;
5685 uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
5686 uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_DBG_STATS_BUFSZ;
5687 uint16 buflen = WL_NATOE_DBG_STATS_BUFSZ;
5688 bcm_xtlv_t *pxtlv = NULL;
5689 char *ioctl_buf = NULL;
5690 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5691
5692 ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
5693 if (!ioctl_buf) {
5694 ANDROID_ERROR(("ioctl memory alloc failed\n"));
5695 return -ENOMEM;
5696 }
5697
5698 /* alloc mem for ioctl headr + tlv data */
5699 natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz);
5700 if (!natoe_ioc) {
5701 ANDROID_ERROR(("ioctl header memory alloc failed\n"));
5702 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MAXLEN);
5703 return -ENOMEM;
5704 }
5705
5706 /* make up natoe cmd ioctl header */
5707 natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
5708 natoe_ioc->id = htod16(cmd->id);
5709 natoe_ioc->len = htod16(WL_NATOE_DBG_STATS_BUFSZ);
5710 pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
5711
5712 if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
5713 iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
5714 ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
5715 WLC_IOCTL_MAXLEN, cmd_info);
5716 if (ret != BCME_OK) {
5717 ANDROID_ERROR(("Fail to get iovar wl_android_natoe_subcmd_dbg_stats\n"));
5718 ret = -EINVAL;
5719 }
5720 } else { /* set */
5721 uint8 val = bcm_atoi(pcmd);
5722
5723 /* buflen is max tlv data we can write, it will be decremented as we pack */
5724 /* save buflen at start */
5725 uint16 buflen_at_start = buflen;
5726
5727 /* we'll adjust final ioc size at the end */
5728 ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_ENABLE,
5729 sizeof(uint8), &val, BCM_XTLV_OPTION_ALIGN32);
5730
5731 if (ret != BCME_OK) {
5732 ret = -EINVAL;
5733 goto exit;
5734 }
5735
5736 /* adjust iocsz to the end of last data record */
5737 natoe_ioc->len = (buflen_at_start - buflen);
5738 iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
5739
5740 ret = wldev_iovar_setbuf(dev, "natoe",
5741 natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
5742 if (ret != BCME_OK) {
5743 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
5744 ret = -EINVAL;
5745 }
5746 }
5747
5748 exit:
5749 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MAXLEN);
5750 MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_DBG_STATS_BUFSZ);
5751
5752 return ret;
5753 }
5754
5755 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)5756 wl_android_natoe_subcmd_tbl_cnt(struct net_device *dev, const wl_natoe_sub_cmd_t *cmd,
5757 char *command, wl_natoe_cmd_info_t *cmd_info)
5758 {
5759 int ret = BCME_OK;
5760 wl_natoe_ioc_t *natoe_ioc;
5761 char *pcmd = command;
5762 uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
5763 uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
5764 uint16 buflen = WL_NATOE_IOC_BUFSZ;
5765 bcm_xtlv_t *pxtlv = NULL;
5766 char *ioctl_buf = NULL;
5767 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5768
5769 ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
5770 if (!ioctl_buf) {
5771 ANDROID_ERROR(("ioctl memory alloc failed\n"));
5772 return -ENOMEM;
5773 }
5774
5775 /* alloc mem for ioctl headr + tlv data */
5776 natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz);
5777 if (!natoe_ioc) {
5778 ANDROID_ERROR(("ioctl header memory alloc failed\n"));
5779 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5780 return -ENOMEM;
5781 }
5782
5783 /* make up natoe cmd ioctl header */
5784 natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
5785 natoe_ioc->id = htod16(cmd->id);
5786 natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
5787 pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
5788
5789 if(*pcmd == WL_IOCTL_ACTION_GET) { /* get */
5790 iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
5791 ret = wl_natoe_get_ioctl(dev, natoe_ioc, iocsz, ioctl_buf,
5792 WLC_IOCTL_MEDLEN, cmd_info);
5793 if (ret != BCME_OK) {
5794 ANDROID_ERROR(("Fail to get iovar wl_android_natoe_subcmd_tbl_cnt\n"));
5795 ret = -EINVAL;
5796 }
5797 } else { /* set */
5798 uint32 val = bcm_atoi(pcmd);
5799
5800 /* buflen is max tlv data we can write, it will be decremented as we pack */
5801 /* save buflen at start */
5802 uint16 buflen_at_start = buflen;
5803
5804 /* we'll adjust final ioc size at the end */
5805 ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_TBL_CNT,
5806 sizeof(uint32), &val, BCM_XTLV_OPTION_ALIGN32);
5807
5808 if (ret != BCME_OK) {
5809 ret = -EINVAL;
5810 goto exit;
5811 }
5812
5813 /* adjust iocsz to the end of last data record */
5814 natoe_ioc->len = (buflen_at_start - buflen);
5815 iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
5816
5817 ret = wldev_iovar_setbuf(dev, "natoe",
5818 natoe_ioc, iocsz, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
5819 if (ret != BCME_OK) {
5820 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
5821 ret = -EINVAL;
5822 }
5823 }
5824
5825 exit:
5826 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
5827 MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ);
5828
5829 return ret;
5830 }
5831
5832 #endif /* WL_NATOE */
5833
5834 #ifdef WL_MBO
5835 static int
wl_android_process_mbo_cmd(struct net_device * dev,char * command,int total_len)5836 wl_android_process_mbo_cmd(struct net_device *dev, char *command, int total_len)
5837 {
5838 int ret = BCME_ERROR;
5839 char *pcmd = command;
5840 char *str = NULL;
5841 wl_drv_cmd_info_t cmd_info;
5842 const wl_drv_sub_cmd_t *mbo_cmd = &mbo_cmd_list[0];
5843
5844 /* skip to cmd name after "mbo" */
5845 str = bcmstrtok(&pcmd, " ", NULL);
5846
5847 /* If mbo subcmd name is not provided, return error */
5848 if (*pcmd == '\0') {
5849 ANDROID_ERROR(("mbo subcmd not provided %s\n", __FUNCTION__));
5850 ret = -EINVAL;
5851 return ret;
5852 }
5853
5854 /* get the mbo command name to str */
5855 str = bcmstrtok(&pcmd, " ", NULL);
5856
5857 while (mbo_cmd->name != NULL) {
5858 if (strnicmp(mbo_cmd->name, str, strlen(mbo_cmd->name)) == 0) {
5859 /* dispatch cmd to appropriate handler */
5860 if (mbo_cmd->handler) {
5861 cmd_info.command = command;
5862 cmd_info.tot_len = total_len;
5863 ret = mbo_cmd->handler(dev, mbo_cmd, pcmd, &cmd_info);
5864 }
5865 return ret;
5866 }
5867 mbo_cmd++;
5868 }
5869 return ret;
5870 }
5871
5872 static int
wl_android_send_wnm_notif(struct net_device * dev,bcm_iov_buf_t * iov_buf,uint16 iov_buf_len,uint8 * iov_resp,uint16 iov_resp_len,uint8 sub_elem_type)5873 wl_android_send_wnm_notif(struct net_device *dev, bcm_iov_buf_t *iov_buf,
5874 uint16 iov_buf_len, uint8 *iov_resp, uint16 iov_resp_len, uint8 sub_elem_type)
5875 {
5876 int ret = BCME_OK;
5877 uint8 *pxtlv = NULL;
5878 uint16 iovlen = 0;
5879 uint16 buflen = 0, buflen_start = 0;
5880
5881 memset_s(iov_buf, iov_buf_len, 0, iov_buf_len);
5882 iov_buf->version = WL_MBO_IOV_VERSION;
5883 iov_buf->id = WL_MBO_CMD_SEND_NOTIF;
5884 buflen = buflen_start = iov_buf_len - sizeof(bcm_iov_buf_t);
5885 pxtlv = (uint8 *)&iov_buf->data[0];
5886 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_SUB_ELEM_TYPE,
5887 sizeof(sub_elem_type), &sub_elem_type, BCM_XTLV_OPTION_ALIGN32);
5888 if (ret != BCME_OK) {
5889 return ret;
5890 }
5891 iov_buf->len = buflen_start - buflen;
5892 iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
5893 ret = wldev_iovar_setbuf(dev, "mbo",
5894 iov_buf, iovlen, iov_resp, WLC_IOCTL_MAXLEN, NULL);
5895 if (ret != BCME_OK) {
5896 ANDROID_ERROR(("Fail to sent wnm notif %d\n", ret));
5897 }
5898 return ret;
5899 }
5900
5901 static int
wl_android_mbo_resp_parse_cbfn(void * ctx,const uint8 * data,uint16 type,uint16 len)5902 wl_android_mbo_resp_parse_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
5903 {
5904 wl_drv_cmd_info_t *cmd_info = (wl_drv_cmd_info_t *)ctx;
5905 uint8 *command = cmd_info->command;
5906 uint16 total_len = cmd_info->tot_len;
5907 uint16 bytes_written = 0;
5908
5909 UNUSED_PARAMETER(len);
5910 /* TODO: validate data value */
5911 if (data == NULL) {
5912 ANDROID_ERROR(("%s: Bad argument !!\n", __FUNCTION__));
5913 return -EINVAL;
5914 }
5915 switch (type) {
5916 case WL_MBO_XTLV_CELL_DATA_CAP:
5917 {
5918 bytes_written = snprintf(command, total_len, "cell_data_cap: %u\n", *data);
5919 cmd_info->bytes_written = bytes_written;
5920 }
5921 break;
5922 default:
5923 ANDROID_ERROR(("%s: Unknown tlv %u\n", __FUNCTION__, type));
5924 }
5925 return BCME_OK;
5926 }
5927
5928 static int
wl_android_mbo_subcmd_cell_data_cap(struct net_device * dev,const wl_drv_sub_cmd_t * cmd,char * command,wl_drv_cmd_info_t * cmd_info)5929 wl_android_mbo_subcmd_cell_data_cap(struct net_device *dev, const wl_drv_sub_cmd_t *cmd,
5930 char *command, wl_drv_cmd_info_t *cmd_info)
5931 {
5932 int ret = BCME_OK;
5933 uint8 *pxtlv = NULL;
5934 uint16 buflen = 0, buflen_start = 0;
5935 uint16 iovlen = 0;
5936 char *pcmd = command;
5937 bcm_iov_buf_t *iov_buf = NULL;
5938 bcm_iov_buf_t *p_resp = NULL;
5939 uint8 *iov_resp = NULL;
5940 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5941 uint16 version;
5942
5943 /* first get the configured value */
5944 iov_buf = (bcm_iov_buf_t *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
5945 if (iov_buf == NULL) {
5946 ret = -ENOMEM;
5947 ANDROID_ERROR(("iov buf memory alloc exited\n"));
5948 goto exit;
5949 }
5950 iov_resp = (uint8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
5951 if (iov_resp == NULL) {
5952 ret = -ENOMEM;
5953 ANDROID_ERROR(("iov resp memory alloc exited\n"));
5954 goto exit;
5955 }
5956
5957 /* fill header */
5958 iov_buf->version = WL_MBO_IOV_VERSION;
5959 iov_buf->id = WL_MBO_CMD_CELLULAR_DATA_CAP;
5960
5961 ret = wldev_iovar_getbuf(dev, "mbo", iov_buf, WLC_IOCTL_MEDLEN, iov_resp,
5962 WLC_IOCTL_MAXLEN,
5963 NULL);
5964 if (ret != BCME_OK) {
5965 goto exit;
5966 }
5967 p_resp = (bcm_iov_buf_t *)iov_resp;
5968
5969 /* get */
5970 if (*pcmd == WL_IOCTL_ACTION_GET) {
5971 /* Check for version */
5972 version = dtoh16(*(uint16 *)iov_resp);
5973 if (version != WL_MBO_IOV_VERSION) {
5974 ret = -EINVAL;
5975 }
5976 if (p_resp->id == WL_MBO_CMD_CELLULAR_DATA_CAP) {
5977 ret = bcm_unpack_xtlv_buf((void *)cmd_info, (uint8 *)p_resp->data,
5978 p_resp->len, BCM_XTLV_OPTION_ALIGN32,
5979 wl_android_mbo_resp_parse_cbfn);
5980 if (ret == BCME_OK) {
5981 ret = cmd_info->bytes_written;
5982 }
5983 } else {
5984 ret = -EINVAL;
5985 ANDROID_ERROR(("Mismatch: resp id %d req id %d\n", p_resp->id, cmd->id));
5986 goto exit;
5987 }
5988 } else {
5989 uint8 cell_cap = bcm_atoi(pcmd);
5990 const uint8* old_cell_cap = NULL;
5991 uint16 len = 0;
5992
5993 old_cell_cap = bcm_get_data_from_xtlv_buf((uint8 *)p_resp->data, p_resp->len,
5994 WL_MBO_XTLV_CELL_DATA_CAP, &len, BCM_XTLV_OPTION_ALIGN32);
5995 if (old_cell_cap && *old_cell_cap == cell_cap) {
5996 ANDROID_ERROR(("No change is cellular data capability\n"));
5997 /* No change in value */
5998 goto exit;
5999 }
6000
6001 buflen = buflen_start = WLC_IOCTL_MEDLEN - sizeof(bcm_iov_buf_t);
6002
6003 if (cell_cap < MBO_CELL_DATA_CONN_AVAILABLE ||
6004 cell_cap > MBO_CELL_DATA_CONN_NOT_CAPABLE) {
6005 ANDROID_ERROR(("wrong value %u\n", cell_cap));
6006 ret = -EINVAL;
6007 goto exit;
6008 }
6009 pxtlv = (uint8 *)&iov_buf->data[0];
6010 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_CELL_DATA_CAP,
6011 sizeof(cell_cap), &cell_cap, BCM_XTLV_OPTION_ALIGN32);
6012 if (ret != BCME_OK) {
6013 goto exit;
6014 }
6015 iov_buf->len = buflen_start - buflen;
6016 iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
6017 ret = wldev_iovar_setbuf(dev, "mbo",
6018 iov_buf, iovlen, iov_resp, WLC_IOCTL_MAXLEN, NULL);
6019 if (ret != BCME_OK) {
6020 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
6021 ret = -EINVAL;
6022 goto exit;
6023 }
6024 /* Skip for CUSTOMER_HW4 - WNM notification
6025 * for cellular data capability is handled by host
6026 */
6027 #if !defined(CUSTOMER_HW4)
6028 /* send a WNM notification request to associated AP */
6029 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
6030 ANDROID_INFO(("Sending WNM Notif\n"));
6031 ret = wl_android_send_wnm_notif(dev, iov_buf, WLC_IOCTL_MEDLEN,
6032 iov_resp, WLC_IOCTL_MAXLEN, MBO_ATTR_CELL_DATA_CAP);
6033 if (ret != BCME_OK) {
6034 ANDROID_ERROR(("Fail to send WNM notification %d\n", ret));
6035 ret = -EINVAL;
6036 }
6037 }
6038 #endif /* CUSTOMER_HW4 */
6039 }
6040 exit:
6041 if (iov_buf) {
6042 MFREE(cfg->osh, iov_buf, WLC_IOCTL_MEDLEN);
6043 }
6044 if (iov_resp) {
6045 MFREE(cfg->osh, iov_resp, WLC_IOCTL_MAXLEN);
6046 }
6047 return ret;
6048 }
6049
6050 static int
wl_android_mbo_non_pref_chan_parse_cbfn(void * ctx,const uint8 * data,uint16 type,uint16 len)6051 wl_android_mbo_non_pref_chan_parse_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
6052 {
6053 wl_drv_cmd_info_t *cmd_info = (wl_drv_cmd_info_t *)ctx;
6054 uint8 *command = cmd_info->command + cmd_info->bytes_written;
6055 uint16 total_len = cmd_info->tot_len;
6056 uint16 bytes_written = 0;
6057
6058 ANDROID_INFO(("Total bytes written at begining %u\n", cmd_info->bytes_written));
6059 UNUSED_PARAMETER(len);
6060 if (data == NULL) {
6061 ANDROID_ERROR(("%s: Bad argument !!\n", __FUNCTION__));
6062 return -EINVAL;
6063 }
6064 switch (type) {
6065 case WL_MBO_XTLV_OPCLASS:
6066 {
6067 bytes_written = snprintf(command, total_len, "%u:", *data);
6068 ANDROID_ERROR(("wr %u %u\n", bytes_written, *data));
6069 command += bytes_written;
6070 cmd_info->bytes_written += bytes_written;
6071 }
6072 break;
6073 case WL_MBO_XTLV_CHAN:
6074 {
6075 bytes_written = snprintf(command, total_len, "%u:", *data);
6076 ANDROID_ERROR(("wr %u\n", bytes_written));
6077 command += bytes_written;
6078 cmd_info->bytes_written += bytes_written;
6079 }
6080 break;
6081 case WL_MBO_XTLV_PREFERENCE:
6082 {
6083 bytes_written = snprintf(command, total_len, "%u:", *data);
6084 ANDROID_ERROR(("wr %u\n", bytes_written));
6085 command += bytes_written;
6086 cmd_info->bytes_written += bytes_written;
6087 }
6088 break;
6089 case WL_MBO_XTLV_REASON_CODE:
6090 {
6091 bytes_written = snprintf(command, total_len, "%u ", *data);
6092 ANDROID_ERROR(("wr %u\n", bytes_written));
6093 command += bytes_written;
6094 cmd_info->bytes_written += bytes_written;
6095 }
6096 break;
6097 default:
6098 ANDROID_ERROR(("%s: Unknown tlv %u\n", __FUNCTION__, type));
6099 }
6100 ANDROID_INFO(("Total bytes written %u\n", cmd_info->bytes_written));
6101 return BCME_OK;
6102 }
6103
6104 static int
wl_android_mbo_subcmd_non_pref_chan(struct net_device * dev,const wl_drv_sub_cmd_t * cmd,char * command,wl_drv_cmd_info_t * cmd_info)6105 wl_android_mbo_subcmd_non_pref_chan(struct net_device *dev,
6106 const wl_drv_sub_cmd_t *cmd, char *command,
6107 wl_drv_cmd_info_t *cmd_info)
6108 {
6109 int ret = BCME_OK;
6110 uint8 *pxtlv = NULL;
6111 uint16 buflen = 0, buflen_start = 0;
6112 uint16 iovlen = 0;
6113 char *pcmd = command;
6114 bcm_iov_buf_t *iov_buf = NULL;
6115 bcm_iov_buf_t *p_resp = NULL;
6116 uint8 *iov_resp = NULL;
6117 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6118 uint16 version;
6119
6120 ANDROID_ERROR(("%s:%d\n", __FUNCTION__, __LINE__));
6121 iov_buf = (bcm_iov_buf_t *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
6122 if (iov_buf == NULL) {
6123 ret = -ENOMEM;
6124 ANDROID_ERROR(("iov buf memory alloc exited\n"));
6125 goto exit;
6126 }
6127 iov_resp = (uint8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
6128 if (iov_resp == NULL) {
6129 ret = -ENOMEM;
6130 ANDROID_ERROR(("iov resp memory alloc exited\n"));
6131 goto exit;
6132 }
6133 /* get */
6134 if (*pcmd == WL_IOCTL_ACTION_GET) {
6135 /* fill header */
6136 iov_buf->version = WL_MBO_IOV_VERSION;
6137 iov_buf->id = WL_MBO_CMD_LIST_CHAN_PREF;
6138
6139 ret = wldev_iovar_getbuf(dev, "mbo", iov_buf, WLC_IOCTL_MEDLEN, iov_resp,
6140 WLC_IOCTL_MAXLEN, NULL);
6141 if (ret != BCME_OK) {
6142 goto exit;
6143 }
6144 p_resp = (bcm_iov_buf_t *)iov_resp;
6145 /* Check for version */
6146 version = dtoh16(*(uint16 *)iov_resp);
6147 if (version != WL_MBO_IOV_VERSION) {
6148 ANDROID_ERROR(("Version mismatch. returned ver %u expected %u\n",
6149 version, WL_MBO_IOV_VERSION));
6150 ret = -EINVAL;
6151 }
6152 if (p_resp->id == WL_MBO_CMD_LIST_CHAN_PREF) {
6153 ret = bcm_unpack_xtlv_buf((void *)cmd_info, (uint8 *)p_resp->data,
6154 p_resp->len, BCM_XTLV_OPTION_ALIGN32,
6155 wl_android_mbo_non_pref_chan_parse_cbfn);
6156 if (ret == BCME_OK) {
6157 ret = cmd_info->bytes_written;
6158 }
6159 } else {
6160 ret = -EINVAL;
6161 ANDROID_ERROR(("Mismatch: resp id %d req id %d\n", p_resp->id, cmd->id));
6162 goto exit;
6163 }
6164 } else {
6165 char *str = pcmd;
6166 uint opcl = 0, ch = 0, pref = 0, rc = 0;
6167
6168 str = bcmstrtok(&pcmd, " ", NULL);
6169 if (!(strnicmp(str, "set", 3)) || (!strnicmp(str, "clear", 5))) {
6170 /* delete all configurations */
6171 iov_buf->version = WL_MBO_IOV_VERSION;
6172 iov_buf->id = WL_MBO_CMD_DEL_CHAN_PREF;
6173 iov_buf->len = 0;
6174 iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
6175 ret = wldev_iovar_setbuf(dev, "mbo",
6176 iov_buf, iovlen, iov_resp, WLC_IOCTL_MAXLEN, NULL);
6177 if (ret != BCME_OK) {
6178 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
6179 ret = -EINVAL;
6180 goto exit;
6181 }
6182 } else {
6183 ANDROID_ERROR(("Unknown command %s\n", str));
6184 goto exit;
6185 }
6186 /* parse non pref channel list */
6187 if (strnicmp(str, "set", 3) == 0) {
6188 uint8 cnt = 0;
6189 str = bcmstrtok(&pcmd, " ", NULL);
6190 while (str != NULL) {
6191 ret = sscanf(str, "%u:%u:%u:%u", &opcl, &ch, &pref, &rc);
6192 ANDROID_ERROR(("buflen %u op %u, ch %u, pref %u rc %u\n",
6193 buflen, opcl, ch, pref, rc));
6194 if (ret != 4) {
6195 ANDROID_ERROR(("Not all parameter presents\n"));
6196 ret = -EINVAL;
6197 }
6198 /* TODO: add a validation check here */
6199 memset_s(iov_buf, WLC_IOCTL_MEDLEN, 0, WLC_IOCTL_MEDLEN);
6200 buflen = buflen_start = WLC_IOCTL_MEDLEN;
6201 pxtlv = (uint8 *)&iov_buf->data[0];
6202 /* opclass */
6203 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_OPCLASS,
6204 sizeof(uint8), (uint8 *)&opcl, BCM_XTLV_OPTION_ALIGN32);
6205 if (ret != BCME_OK) {
6206 goto exit;
6207 }
6208 /* channel */
6209 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_CHAN,
6210 sizeof(uint8), (uint8 *)&ch, BCM_XTLV_OPTION_ALIGN32);
6211 if (ret != BCME_OK) {
6212 goto exit;
6213 }
6214 /* preference */
6215 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_PREFERENCE,
6216 sizeof(uint8), (uint8 *)&pref, BCM_XTLV_OPTION_ALIGN32);
6217 if (ret != BCME_OK) {
6218 goto exit;
6219 }
6220 /* reason */
6221 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_REASON_CODE,
6222 sizeof(uint8), (uint8 *)&rc, BCM_XTLV_OPTION_ALIGN32);
6223 if (ret != BCME_OK) {
6224 goto exit;
6225 }
6226 ANDROID_ERROR(("len %u\n", (buflen_start - buflen)));
6227 /* Now set the new non pref channels */
6228 iov_buf->version = WL_MBO_IOV_VERSION;
6229 iov_buf->id = WL_MBO_CMD_ADD_CHAN_PREF;
6230 iov_buf->len = buflen_start - buflen;
6231 iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
6232 ret = wldev_iovar_setbuf(dev, "mbo",
6233 iov_buf, iovlen, iov_resp, WLC_IOCTL_MEDLEN, NULL);
6234 if (ret != BCME_OK) {
6235 ANDROID_ERROR(("Fail to set iovar %d\n", ret));
6236 ret = -EINVAL;
6237 goto exit;
6238 }
6239 cnt++;
6240 if (cnt >= MBO_MAX_CHAN_PREF_ENTRIES) {
6241 break;
6242 }
6243 ANDROID_ERROR(("%d cnt %u\n", __LINE__, cnt));
6244 str = bcmstrtok(&pcmd, " ", NULL);
6245 }
6246 }
6247 /* send a WNM notification request to associated AP */
6248 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
6249 ANDROID_INFO(("Sending WNM Notif\n"));
6250 ret = wl_android_send_wnm_notif(dev, iov_buf, WLC_IOCTL_MEDLEN,
6251 iov_resp, WLC_IOCTL_MAXLEN, MBO_ATTR_NON_PREF_CHAN_REPORT);
6252 if (ret != BCME_OK) {
6253 ANDROID_ERROR(("Fail to send WNM notification %d\n", ret));
6254 ret = -EINVAL;
6255 }
6256 }
6257 }
6258 exit:
6259 if (iov_buf) {
6260 MFREE(cfg->osh, iov_buf, WLC_IOCTL_MEDLEN);
6261 }
6262 if (iov_resp) {
6263 MFREE(cfg->osh, iov_resp, WLC_IOCTL_MAXLEN);
6264 }
6265 return ret;
6266 }
6267 #endif /* WL_MBO */
6268
6269 #ifdef CUSTOMER_HW4_PRIVATE_CMD
6270 #ifdef SUPPORT_AMPDU_MPDU_CMD
6271 /* CMD_AMPDU_MPDU */
6272 static int
wl_android_set_ampdu_mpdu(struct net_device * dev,const char * string_num)6273 wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num)
6274 {
6275 int err = 0;
6276 int ampdu_mpdu;
6277
6278 ampdu_mpdu = bcm_atoi(string_num);
6279
6280 if (ampdu_mpdu > 32) {
6281 ANDROID_ERROR(("wl_android_set_ampdu_mpdu : ampdu_mpdu MAX value is 32.\n"));
6282 return -1;
6283 }
6284
6285 ANDROID_ERROR(("wl_android_set_ampdu_mpdu : ampdu_mpdu = %d\n", ampdu_mpdu));
6286 err = wldev_iovar_setint(dev, "ampdu_mpdu", ampdu_mpdu);
6287 if (err < 0) {
6288 ANDROID_ERROR(("wl_android_set_ampdu_mpdu : ampdu_mpdu set error. %d\n", err));
6289 return -1;
6290 }
6291
6292 return 0;
6293 }
6294 #endif /* SUPPORT_AMPDU_MPDU_CMD */
6295 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
6296
6297 #if defined(CONFIG_WLAN_BEYONDX) || defined(CONFIG_SEC_5GMODEL)
6298 extern int wl_cfg80211_send_msg_to_ril(void);
6299 extern void wl_cfg80211_register_dev_ril_bridge_event_notifier(void);
6300 extern void wl_cfg80211_unregister_dev_ril_bridge_event_notifier(void);
6301 extern int g_mhs_chan_for_cpcoex;
6302 #endif /* CONFIG_WLAN_BEYONDX || defined(CONFIG_SEC_5GMODEL) */
6303
6304 #if defined (WL_SUPPORT_AUTO_CHANNEL)
6305 static s32
wl_android_set_auto_channel_scan_state(struct net_device * ndev)6306 wl_android_set_auto_channel_scan_state(struct net_device *ndev)
6307 {
6308 u32 val = 0;
6309 s32 ret = BCME_ERROR;
6310 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
6311 /* Set interface up, explicitly. */
6312 val = 1;
6313
6314 ret = wldev_ioctl_set(ndev, WLC_UP, (void *)&val, sizeof(val));
6315 if (ret < 0) {
6316 ANDROID_ERROR(("set interface up failed, error = %d\n", ret));
6317 goto done;
6318 }
6319
6320 /* Stop all scan explicitly, till auto channel selection complete. */
6321 wl_set_drv_status(cfg, SCANNING, ndev);
6322 if (cfg->escan_info.ndev == NULL) {
6323 ret = BCME_OK;
6324 goto done;
6325 }
6326
6327 wl_cfgscan_cancel_scan(cfg);
6328
6329 done:
6330 return ret;
6331 }
6332
6333 s32
wl_android_get_freq_list_chanspecs(struct net_device * ndev,wl_uint32_list_t * list,s32 buflen,const char * cmd_str,int sta_channel,chanspec_band_t sta_acs_band)6334 wl_android_get_freq_list_chanspecs(struct net_device *ndev, wl_uint32_list_t *list,
6335 s32 buflen, const char* cmd_str, int sta_channel, chanspec_band_t sta_acs_band)
6336 {
6337 u32 freq = 0;
6338 chanspec_t chanspec = 0;
6339 s32 ret = BCME_OK;
6340 int i = 0;
6341 char *pcmd, *token;
6342 int len = buflen;
6343
6344 pcmd = bcmstrstr(cmd_str, FREQ_STR);
6345 pcmd += strlen(FREQ_STR);
6346
6347 len -= sizeof(list->count);
6348
6349 while ((token = strsep(&pcmd, ",")) != NULL) {
6350 if (*token == '\0')
6351 continue;
6352
6353 if (len < sizeof(list->element[i]))
6354 break;
6355
6356 freq = bcm_atoi(token);
6357 /* Convert chanspec from frequency */
6358 if ((freq > 0) &&
6359 ((chanspec = wl_freq_to_chanspec(freq)) != INVCHANSPEC)) {
6360 ANDROID_INFO(("Adding chanspec in list : 0x%x at the index %d\n", chanspec, i));
6361 list->element[i] = chanspec;
6362 len -= sizeof(list->element[i]);
6363 i++;
6364 #ifdef WL_5G_SOFTAP_ONLY_ON_DEF_CHAN
6365 /* Android includes 2g channels even for 5g band configuration. For
6366 * customers using only single channel 5G AP, set the channel and
6367 * return without doing ACS
6368 */
6369 if (CHSPEC_BAND(chanspec) == WL_CHANSPEC_BAND_5G) {
6370 ANDROID_INFO(("Pick default channnel from 5g\n"));
6371 if (!sta_channel) {
6372 list->element[0] = chanspec;
6373 list->count = 1;
6374 return ret;
6375 }
6376 break;
6377 }
6378 #endif /* WL_5G_SOFTAP_ONLY_ON_DEF_CHAN */
6379 }
6380 }
6381
6382 list->count = i;
6383 /* valid chanspec present in the list */
6384 if (list->count && sta_channel) {
6385 /* STA associated case. Can't do ACS.
6386 * Frequency list is order of lower to higher band.
6387 * check with the highest band entry.
6388 */
6389 chanspec = list->element[i-1];
6390 if (CHSPEC_BAND(chanspec) == sta_acs_band) {
6391 /* softap request is for same band. Use SCC
6392 * Convert sta channel to freq
6393 */
6394 freq = wl_channel_to_frequency(sta_channel, sta_acs_band);
6395 list->element[0] =
6396 wl_freq_to_chanspec(freq);
6397 ANDROID_INFO(("Softap on same band as STA."
6398 "Use SCC. chanspec:0x%x\n", chanspec));
6399 } else {
6400 list->element[0] = chanspec;
6401 ANDROID_INFO(("RSDB case chanspec:0x%x\n", chanspec));
6402 }
6403 list->count = 1;
6404 return ret;
6405 }
6406 return ret;
6407 }
6408
6409 s32
wl_android_get_band_chanspecs(struct net_device * ndev,void * buf,s32 buflen,chanspec_band_t band,bool acs_req)6410 wl_android_get_band_chanspecs(struct net_device *ndev, void *buf, s32 buflen,
6411 chanspec_band_t band, bool acs_req)
6412 {
6413 u32 channel = 0;
6414 s32 ret = BCME_ERROR;
6415 s32 i = 0;
6416 s32 j = 0;
6417 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
6418 wl_uint32_list_t *list = NULL;
6419 chanspec_t chanspec = 0;
6420
6421 if (band != 0xff) {
6422 chanspec |= (band | WL_CHANSPEC_BW_20 |
6423 WL_CHANSPEC_CTL_SB_NONE);
6424 chanspec = wl_chspec_host_to_driver(chanspec);
6425 }
6426
6427 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
6428 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
6429 if (ret < 0) {
6430 ANDROID_ERROR(("get 'chanspecs' failed, error = %d\n", ret));
6431 goto done;
6432 }
6433
6434 list = (wl_uint32_list_t *)buf;
6435 /* Skip DFS and inavlid P2P channel. */
6436 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
6437 if (!CHSPEC_IS20(list->element[i])) {
6438 continue;
6439 }
6440 chanspec = (chanspec_t) dtoh32(list->element[i]);
6441 channel = chanspec | WL_CHANSPEC_BW_20;
6442 channel = wl_chspec_host_to_driver(channel);
6443
6444 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
6445 if (ret < 0) {
6446 ANDROID_ERROR(("get 'per_chan_info' failed, error = %d\n", ret));
6447 goto done;
6448 }
6449
6450 if (CHSPEC_IS5G(chanspec) && (CHANNEL_IS_RADAR(channel) ||
6451 #ifndef ALLOW_5G_ACS
6452 ((acs_req == true) && (CHSPEC_CHANNEL(chanspec) != APCS_DEFAULT_5G_CH)) ||
6453 #endif /* !ALLOW_5G_ACS */
6454 (0))) {
6455 continue;
6456 } else if (!(CHSPEC_IS2G(chanspec) || CHSPEC_IS5G(chanspec)) &&
6457 !(CHSPEC_IS_6G_PSC(chanspec))) {
6458 continue;
6459 }
6460 else {
6461 list->element[j] = list->element[i];
6462 ANDROID_INFO(("Adding chanspec in list : %x\n", list->element[j]));
6463 }
6464
6465 j++;
6466 }
6467
6468 list->count = j;
6469
6470 done:
6471 return ret;
6472 }
6473
6474 static s32
wl_android_get_best_channel(struct net_device * ndev,void * buf,int buflen,int * channel)6475 wl_android_get_best_channel(struct net_device *ndev, void *buf, int buflen,
6476 int *channel)
6477 {
6478 s32 ret = BCME_ERROR;
6479 int chosen = 0;
6480 int retry = 0;
6481
6482 /* Start auto channel selection scan. */
6483 ret = wldev_ioctl_set(ndev, WLC_START_CHANNEL_SEL, NULL, 0);
6484 if (ret < 0) {
6485 ANDROID_ERROR(("can't start auto channel scan, error = %d\n", ret));
6486 *channel = 0;
6487 goto done;
6488 }
6489
6490 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
6491 retry = CHAN_SEL_RETRY_COUNT;
6492
6493 while (retry--) {
6494 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
6495 chosen = 0;
6496 ret = wldev_ioctl_get(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
6497 if ((ret == 0) && (dtoh32(chosen) != 0)) {
6498 *channel = (u16)(chosen & 0x00FF);
6499 ANDROID_INFO(("selected channel = %d\n", *channel));
6500 break;
6501 }
6502 ANDROID_INFO(("attempt = %d, ret = %d, chosen = %d\n",
6503 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
6504 }
6505
6506 if (retry <= 0) {
6507 ANDROID_ERROR(("failure, auto channel selection timed out\n"));
6508 *channel = 0;
6509 ret = BCME_ERROR;
6510 }
6511
6512 done:
6513 return ret;
6514 }
6515
6516 static s32
wl_android_restore_auto_channel_scan_state(struct net_device * ndev)6517 wl_android_restore_auto_channel_scan_state(struct net_device *ndev)
6518 {
6519 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
6520 /* Clear scan stop driver status. */
6521 wl_clr_drv_status(cfg, SCANNING, ndev);
6522
6523 return BCME_OK;
6524 }
6525
6526 s32
wl_android_get_best_channels(struct net_device * dev,char * cmd,int total_len)6527 wl_android_get_best_channels(struct net_device *dev, char* cmd, int total_len)
6528 {
6529 int channel = 0;
6530 s32 ret = BCME_ERROR;
6531 u8 *buf = NULL;
6532 char *pos = cmd;
6533 struct bcm_cfg80211 *cfg = NULL;
6534 struct net_device *ndev = NULL;
6535
6536 bzero(cmd, total_len);
6537 cfg = wl_get_cfg(dev);
6538
6539 buf = (u8 *)MALLOC(cfg->osh, CHANSPEC_BUF_SIZE);
6540 if (buf == NULL) {
6541 ANDROID_ERROR(("failed to allocate chanspec buffer\n"));
6542 return -ENOMEM;
6543 }
6544
6545 /*
6546 * Always use primary interface, irrespective of interface on which
6547 * command came.
6548 */
6549 ndev = bcmcfg_to_prmry_ndev(cfg);
6550
6551 /*
6552 * Make sure that FW and driver are in right state to do auto channel
6553 * selection scan.
6554 */
6555 ret = wl_android_set_auto_channel_scan_state(ndev);
6556 if (ret < 0) {
6557 ANDROID_ERROR(("can't set auto channel scan state, error = %d\n", ret));
6558 goto done;
6559 }
6560
6561 /* Best channel selection in 2.4GHz band. */
6562 ret = wl_android_get_band_chanspecs(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
6563 WL_CHANSPEC_BAND_2G, false);
6564 if (ret < 0) {
6565 ANDROID_ERROR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
6566 goto done;
6567 }
6568
6569 ret = wl_android_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
6570 &channel);
6571 if (ret < 0) {
6572 ANDROID_ERROR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
6573 goto done;
6574 }
6575
6576 if (CHANNEL_IS_2G(channel)) {
6577 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
6578 } else {
6579 ANDROID_ERROR(("invalid 2.4GHz channel, channel = %d\n", channel));
6580 channel = 0;
6581 }
6582
6583 pos += snprintf(pos, total_len, "%04d ", channel);
6584
6585 /* Best channel selection in 5GHz band. */
6586 ret = wl_android_get_band_chanspecs(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
6587 WL_CHANSPEC_BAND_5G, false);
6588 if (ret < 0) {
6589 ANDROID_ERROR(("can't get chanspecs in 5GHz, error = %d\n", ret));
6590 goto done;
6591 }
6592
6593 ret = wl_android_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
6594 &channel);
6595 if (ret < 0) {
6596 ANDROID_ERROR(("can't select best channel scan in 5GHz, error = %d\n", ret));
6597 goto done;
6598 }
6599
6600 if (CHANNEL_IS_5G(channel)) {
6601 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
6602 } else {
6603 ANDROID_ERROR(("invalid 5GHz channel, channel = %d\n", channel));
6604 channel = 0;
6605 }
6606
6607 pos += snprintf(pos, total_len - (pos - cmd), "%04d ", channel);
6608
6609 /* Set overall best channel same as 5GHz best channel. */
6610 pos += snprintf(pos, total_len - (pos - cmd), "%04d ", channel);
6611
6612 done:
6613 if (NULL != buf) {
6614 MFREE(cfg->osh, buf, CHANSPEC_BUF_SIZE);
6615 }
6616
6617 /* Restore FW and driver back to normal state. */
6618 ret = wl_android_restore_auto_channel_scan_state(ndev);
6619 if (ret < 0) {
6620 ANDROID_ERROR(("can't restore auto channel scan state, error = %d\n", ret));
6621 }
6622
6623 return (pos - cmd);
6624 }
6625
6626 int
wl_android_set_spect(struct net_device * dev,int spect)6627 wl_android_set_spect(struct net_device *dev, int spect)
6628 {
6629 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6630 int wlc_down = 1;
6631 int wlc_up = 1;
6632 int err = BCME_OK;
6633
6634 if (!wl_get_drv_status_all(cfg, CONNECTED)) {
6635 err = wldev_ioctl_set(dev, WLC_DOWN, &wlc_down, sizeof(wlc_down));
6636 if (err) {
6637 ANDROID_ERROR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
6638 return err;
6639 }
6640
6641 err = wldev_ioctl_set(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect));
6642 if (err) {
6643 ANDROID_ERROR(("%s: error setting spect: code: %d\n", __func__, err));
6644 return err;
6645 }
6646
6647 err = wldev_ioctl_set(dev, WLC_UP, &wlc_up, sizeof(wlc_up));
6648 if (err) {
6649 ANDROID_ERROR(("%s: WLC_UP failed: code: %d\n", __func__, err));
6650 return err;
6651 }
6652 }
6653 return err;
6654 }
6655
6656 static int
wl_android_get_sta_channel(struct bcm_cfg80211 * cfg)6657 wl_android_get_sta_channel(struct bcm_cfg80211 *cfg)
6658 {
6659 chanspec_t *sta_chanspec = NULL;
6660 u32 channel = 0;
6661
6662 if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) {
6663 if ((sta_chanspec = (chanspec_t *)wl_read_prof(cfg,
6664 bcmcfg_to_prmry_ndev(cfg), WL_PROF_CHAN))) {
6665 channel = wf_chspec_ctlchan(*sta_chanspec);
6666 }
6667 }
6668 return channel;
6669 }
6670
6671 static int
wl_cfg80211_get_acs_band(int band)6672 wl_cfg80211_get_acs_band(int band)
6673 {
6674 chanspec_band_t acs_band = WLC_ACS_BAND_INVALID;
6675 switch (band) {
6676 case WLC_BAND_AUTO:
6677 ANDROID_INFO(("ACS full channel scan \n"));
6678 /* Restricting band to 2G in case of hw_mode any */
6679 acs_band = WL_CHANSPEC_BAND_2G;
6680 break;
6681 #ifdef WL_6G_BAND
6682 case WLC_BAND_6G:
6683 ANDROID_INFO(("ACS 6G band scan \n"));
6684 acs_band = WL_CHANSPEC_BAND_6G;
6685 break;
6686 #endif /* WL_6G_BAND */
6687 case WLC_BAND_5G:
6688 ANDROID_INFO(("ACS 5G band scan \n"));
6689 acs_band = WL_CHANSPEC_BAND_5G;
6690 break;
6691 case WLC_BAND_2G:
6692 /*
6693 * If channel argument is not provided/ argument 20 is provided,
6694 * Restrict channel to 2GHz, 20MHz BW, No SB
6695 */
6696 ANDROID_INFO(("ACS 2G band scan \n"));
6697 acs_band = WL_CHANSPEC_BAND_2G;
6698 break;
6699 default:
6700 ANDROID_ERROR(("ACS: No band chosen\n"));
6701 break;
6702 }
6703 ANDROID_INFO(("%s: ACS: band = %d, acs_band = 0x%x\n", __FUNCTION__, band, acs_band));
6704 return acs_band;
6705 }
6706
6707 /* SoftAP feature */
6708 static int
wl_android_set_auto_channel(struct net_device * dev,const char * cmd_str,char * command,int total_len)6709 wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
6710 char* command, int total_len)
6711 {
6712 int channel = 0, sta_channel = 0;
6713 int chosen = 0;
6714 int retry = 0;
6715 int ret = 0;
6716 int spect = 0;
6717 u8 *reqbuf = NULL;
6718 uint32 band = WLC_BAND_INVALID, sta_band = WLC_BAND_INVALID;
6719 chanspec_band_t acs_band = WLC_ACS_BAND_INVALID;
6720 uint32 buf_size;
6721 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6722 bool acs_freq_list_present = false;
6723 char *pcmd;
6724
6725 if (cmd_str) {
6726 ANDROID_INFO(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str)));
6727 pcmd = bcmstrstr(cmd_str, FREQ_STR);
6728 if (pcmd) {
6729 acs_freq_list_present = true;
6730 ANDROID_INFO(("ACS has freq list\n"));
6731 } else if (strnicmp(cmd_str, APCS_BAND_AUTO, strlen(APCS_BAND_AUTO)) == 0) {
6732 band = WLC_BAND_AUTO;
6733 #ifdef WL_6G_BAND
6734 } else if (strnicmp(cmd_str, APCS_BAND_6G, strlen(APCS_BAND_6G)) == 0) {
6735 band = WLC_BAND_6G;
6736 #endif /* WL_6G_BAND */
6737 } else if (strnicmp(cmd_str, APCS_BAND_5G, strlen(APCS_BAND_5G)) == 0) {
6738 band = WLC_BAND_5G;
6739 } else if (strnicmp(cmd_str, APCS_BAND_2G, strlen(APCS_BAND_2G)) == 0) {
6740 band = WLC_BAND_2G;
6741 } else {
6742 /*
6743 * For backward compatibility: Some platforms used to issue argument 20 or 0
6744 * to enforce the 2G channel selection
6745 */
6746 channel = bcm_atoi(cmd_str);
6747 if ((channel == APCS_BAND_2G_LEGACY1) ||
6748 (channel == APCS_BAND_2G_LEGACY2)) {
6749 band = WLC_BAND_2G;
6750 } else {
6751 ANDROID_ERROR(("Invalid argument\n"));
6752 return -EINVAL;
6753 }
6754 }
6755 } else {
6756 /* If no argument is provided, default to 2G */
6757 ANDROID_ERROR(("No argument given default to 2.4G scan\n"));
6758 band = WLC_BAND_2G;
6759 }
6760 ANDROID_INFO(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band));
6761
6762 #if defined(CONFIG_WLAN_BEYONDX) || defined(CONFIG_SEC_5GMODEL)
6763 wl_cfg80211_register_dev_ril_bridge_event_notifier();
6764 if (band == WLC_BAND_2G) {
6765 wl_cfg80211_send_msg_to_ril();
6766
6767 if (g_mhs_chan_for_cpcoex) {
6768 channel = g_mhs_chan_for_cpcoex;
6769 g_mhs_chan_for_cpcoex = 0;
6770 goto done2;
6771 }
6772 }
6773 wl_cfg80211_unregister_dev_ril_bridge_event_notifier();
6774 #endif /* CONFIG_WLAN_BEYONDX || defined(CONFIG_SEC_5GMODEL) */
6775
6776 /* If STA is connected, return is STA channel, else ACS can be issued,
6777 * set spect to 0 and proceed with ACS
6778 */
6779 sta_channel = wl_android_get_sta_channel(cfg);
6780 sta_band = WL_GET_BAND(sta_channel);
6781 if (sta_channel && (band != WLC_BAND_INVALID)) {
6782 switch (sta_band) {
6783 case (WLC_BAND_5G):
6784 #ifdef WL_6G_BAND
6785 case (WLC_BAND_6G):
6786 #endif /* WL_6G_BAND */
6787 {
6788 if (band == WLC_BAND_2G || band == WLC_BAND_AUTO) {
6789 channel = APCS_DEFAULT_2G_CH;
6790 } else if (band == WLC_BAND_5G) {
6791 channel = sta_channel;
6792 }
6793 break;
6794 }
6795 case (WLC_BAND_2G): {
6796 if (band == WLC_BAND_5G) {
6797 channel = APCS_DEFAULT_5G_CH;
6798 } else if (band == WLC_BAND_2G) {
6799 channel = sta_channel;
6800 }
6801 #ifdef WL_6G_BAND
6802 else if (band == WLC_BAND_6G) {
6803 channel = APCS_DEFAULT_6G_CH;
6804 }
6805 #endif /* WL_6G_BAND */
6806 break;
6807 }
6808 default:
6809 /* Intentional fall through to use same sta channel for softap */
6810 channel = sta_channel;
6811 break;
6812 }
6813 WL_MSG(dev->name, "band=%d, sta_band=%d, channel=%d\n", band, sta_band, channel);
6814 goto done2;
6815 }
6816
6817 /* If AP is started on wlan0 iface,
6818 * do not issue any iovar to fw and choose default ACS channel for softap
6819 */
6820 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
6821 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
6822 ANDROID_INFO(("Softap started on primary iface\n"));
6823 goto done;
6824 }
6825 }
6826
6827 channel = wl_ext_autochannel(dev, ACS_DRV_BIT, band);
6828 if (channel) {
6829 acs_band = CHSPEC_BAND(channel);
6830 goto done2;
6831 } else
6832 goto done;
6833
6834 ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
6835 if (ret) {
6836 ANDROID_ERROR(("ACS: error getting the spect, ret=%d\n", ret));
6837 goto done;
6838 }
6839
6840 if (spect > 0) {
6841 ret = wl_android_set_spect(dev, 0);
6842 if (ret < 0) {
6843 ANDROID_ERROR(("ACS: error while setting spect, ret=%d\n", ret));
6844 goto done;
6845 }
6846 }
6847
6848 reqbuf = (u8 *)MALLOCZ(cfg->osh, CHANSPEC_BUF_SIZE);
6849 if (reqbuf == NULL) {
6850 ANDROID_ERROR(("failed to allocate chanspec buffer\n"));
6851 return -ENOMEM;
6852 }
6853
6854 if (acs_freq_list_present) {
6855 wl_uint32_list_t *list = NULL;
6856 bzero(reqbuf, sizeof(*reqbuf));
6857 list = (wl_uint32_list_t *)reqbuf;
6858
6859 ret = wl_android_get_freq_list_chanspecs(dev, list, CHANSPEC_BUF_SIZE,
6860 cmd_str, sta_channel, wl_cfg80211_get_acs_band(sta_band));
6861 if (ret < 0) {
6862 ANDROID_ERROR(("ACS chanspec set failed!\n"));
6863 goto done;
6864 }
6865
6866 /* skip ACS for single channel case */
6867 if (list->count == 1) {
6868 cfg->acs_chspec = (chanspec_t)list->element[0];
6869 channel = wf_chspec_ctlchan((chanspec_t)list->element[0]);
6870 acs_band = CHSPEC_BAND((chanspec_t)list->element[0]);
6871 goto done2;
6872 }
6873 } else {
6874 acs_band = wl_cfg80211_get_acs_band(band);
6875 if (acs_band == WLC_ACS_BAND_INVALID) {
6876 ANDROID_ERROR(("ACS: No band chosen\n"));
6877 goto done2;
6878 }
6879
6880 if ((ret = wl_android_get_band_chanspecs(dev, reqbuf, CHANSPEC_BUF_SIZE,
6881 acs_band, true)) < 0) {
6882 ANDROID_ERROR(("ACS chanspec retrieval failed! \n"));
6883 goto done;
6884 }
6885 }
6886
6887 buf_size = CHANSPEC_BUF_SIZE;
6888 ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
6889 buf_size);
6890 if (ret < 0) {
6891 ANDROID_ERROR(("can't start auto channel scan, err = %d\n", ret));
6892 channel = 0;
6893 goto done;
6894 }
6895
6896 /* Wait for auto channel selection, max 3000 ms */
6897 if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G) || (band == WLC_BAND_6G)) {
6898 OSL_SLEEP(500);
6899 } else {
6900 /*
6901 * Full channel scan at the minimum takes 1.2secs
6902 * even with parallel scan. max wait time: 3500ms
6903 */
6904 OSL_SLEEP(1000);
6905 }
6906
6907 retry = APCS_MAX_RETRY;
6908 while (retry--) {
6909 ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &chosen,
6910 sizeof(chosen));
6911 if (ret < 0) {
6912 chosen = 0;
6913 } else {
6914 chosen = dtoh32(chosen);
6915 }
6916
6917 if (chosen) {
6918 /* Update chanspec which can be used during softAP bringup with right BW */
6919 cfg->acs_chspec = chosen;
6920 channel = wf_chspec_ctlchan(chosen);
6921 acs_band = CHSPEC_BAND(chosen);
6922 break;
6923 }
6924 ANDROID_INFO(("%d tried, ret = %d, chosen = 0x%x, acs_band = 0x%x\n",
6925 (APCS_MAX_RETRY - retry), ret, chosen, acs_band));
6926 OSL_SLEEP(250);
6927 }
6928
6929 done:
6930 if ((retry == 0) || (ret < 0)) {
6931 /* On failure, fallback to a default channel */
6932 if (band == WLC_BAND_5G) {
6933 channel = APCS_DEFAULT_5G_CH;
6934 #ifdef WL_6G_BAND
6935 } else if (band == WLC_BAND_6G) {
6936 channel = APCS_DEFAULT_6G_CH;
6937 #endif /* WL_6G_BAND */
6938 } else {
6939 channel = APCS_DEFAULT_2G_CH;
6940 }
6941 ANDROID_ERROR(("ACS failed. Fall back to default channel (%d) \n", channel));
6942 }
6943 done2:
6944 if (spect > 0) {
6945 if ((ret = wl_android_set_spect(dev, spect) < 0)) {
6946 ANDROID_ERROR(("ACS: error while setting spect\n"));
6947 }
6948 }
6949
6950 if (reqbuf) {
6951 MFREE(cfg->osh, reqbuf, CHANSPEC_BUF_SIZE);
6952 }
6953
6954 if (channel) {
6955 ret = snprintf(command, total_len, "%d", channel);
6956 ANDROID_INFO(("command result is %s \n", command));
6957 }
6958
6959 return ret;
6960 }
6961 #endif /* WL_SUPPORT_AUTO_CHANNEL */
6962
6963 #ifdef CUSTOMER_HW4_PRIVATE_CMD
6964 static int
wl_android_set_roam_vsie_enab(struct net_device * dev,const char * cmd,u32 cmd_len)6965 wl_android_set_roam_vsie_enab(struct net_device *dev, const char *cmd, u32 cmd_len)
6966 {
6967 s32 err = BCME_OK;
6968 u32 roam_vsie_enable = 0;
6969 u32 cmd_str_len = (u32)strlen(CMD_ROAM_VSIE_ENAB_SET);
6970 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6971
6972 /* <CMD><SPACE><VAL> */
6973 if (!cmd || (cmd_len < (cmd_str_len + 1))) {
6974 ANDROID_ERROR(("wrong arg\n"));
6975 err = -EINVAL;
6976 goto exit;
6977 }
6978
6979 if (dev != bcmcfg_to_prmry_ndev(cfg)) {
6980 ANDROID_ERROR(("config not supported on non primary i/f\n"));
6981 err = -ENODEV;
6982 goto exit;
6983 }
6984
6985 roam_vsie_enable = cmd[(cmd_str_len + 1)] - '0';
6986 if (roam_vsie_enable > 1) {
6987 roam_vsie_enable = 1;
6988 }
6989
6990 WL_DBG_MEM(("set roam vsie %d\n", roam_vsie_enable));
6991 err = wldev_iovar_setint(dev, "roam_vsie", roam_vsie_enable);
6992 if (unlikely(err)) {
6993 ANDROID_ERROR(("set roam vsie enable failed. ret:%d\n", err));
6994 }
6995
6996 exit:
6997 return err;
6998 }
6999
7000 static int
wl_android_get_roam_vsie_enab(struct net_device * dev,char * cmd,u32 cmd_len)7001 wl_android_get_roam_vsie_enab(struct net_device *dev, char *cmd, u32 cmd_len)
7002 {
7003 s32 err = BCME_OK;
7004 u32 roam_vsie_enable = 0;
7005 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
7006 int bytes_written;
7007
7008 /* <CMD> */
7009 if (!cmd) {
7010 ANDROID_ERROR(("wrong arg\n"));
7011 return -1;
7012 }
7013
7014 if (dev != bcmcfg_to_prmry_ndev(cfg)) {
7015 ANDROID_ERROR(("config not supported on non primary i/f\n"));
7016 return -1;
7017 }
7018
7019 err = wldev_iovar_getint(dev, "roam_vsie", &roam_vsie_enable);
7020 if (unlikely(err)) {
7021 ANDROID_ERROR(("get roam vsie enable failed. ret:%d\n", err));
7022 return -1;
7023 }
7024 ANDROID_INFO(("get roam vsie %d\n", roam_vsie_enable));
7025
7026 bytes_written = snprintf(cmd, cmd_len, "%s %d",
7027 CMD_ROAM_VSIE_ENAB_GET, roam_vsie_enable);
7028
7029 return bytes_written;
7030 }
7031
7032 static int
wl_android_set_bcn_rpt_vsie_enab(struct net_device * dev,const char * cmd,u32 cmd_len)7033 wl_android_set_bcn_rpt_vsie_enab(struct net_device *dev, const char *cmd, u32 cmd_len)
7034 {
7035 s32 err;
7036 u32 bcn_vsie_enable = 0;
7037 u32 cmd_str_len = (u32)strlen(CMD_BR_VSIE_ENAB_SET);
7038 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
7039
7040 /* <CMD><SPACE><VAL> */
7041 if (!cmd || (cmd_len < (cmd_str_len + 1))) {
7042 ANDROID_ERROR(("invalid arg\n"));
7043 err = -EINVAL;
7044 goto exit;
7045 }
7046
7047 if (dev != bcmcfg_to_prmry_ndev(cfg)) {
7048 ANDROID_ERROR(("config not supported on non primary i/f\n"));
7049 err = -ENODEV;
7050 goto exit;
7051 }
7052
7053 bcn_vsie_enable = cmd[cmd_str_len + 1] - '0';
7054 if (bcn_vsie_enable > 1) {
7055 bcn_vsie_enable = 1;
7056 }
7057
7058 WL_DBG_MEM(("set bcn report vsie %d\n", bcn_vsie_enable));
7059 err = wldev_iovar_setint(dev, "bcnrpt_vsie_en", bcn_vsie_enable);
7060 if (unlikely(err)) {
7061 ANDROID_ERROR(("set bcn vsie failed. ret:%d\n", err));
7062 }
7063
7064 exit:
7065 return err;
7066 }
7067
7068 static int
wl_android_get_bcn_rpt_vsie_enab(struct net_device * dev,char * cmd,u32 cmd_len)7069 wl_android_get_bcn_rpt_vsie_enab(struct net_device *dev, char *cmd, u32 cmd_len)
7070 {
7071 s32 err = BCME_OK;
7072 u32 bcn_vsie_enable = 0;
7073 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
7074 int bytes_written;
7075
7076 /* <CMD> */
7077 if (!cmd) {
7078 ANDROID_ERROR(("wrong arg\n"));
7079 return -1;
7080 }
7081
7082 if (dev != bcmcfg_to_prmry_ndev(cfg)) {
7083 ANDROID_ERROR(("config not supported on non primary i/f\n"));
7084 return -1;
7085 }
7086
7087 err = wldev_iovar_getint(dev, "bcnrpt_vsie_en", &bcn_vsie_enable);
7088 if (unlikely(err)) {
7089 ANDROID_ERROR(("get bcn vsie failed. ret:%d\n", err));
7090 return -1;
7091 }
7092 ANDROID_INFO(("get bcn report vsie %d\n", bcn_vsie_enable));
7093
7094 bytes_written = snprintf(cmd, cmd_len, "%s %d",
7095 CMD_BR_VSIE_ENAB_GET, bcn_vsie_enable);
7096
7097 return bytes_written;
7098 }
7099
7100 #ifdef SUPPORT_HIDDEN_AP
7101 static int
wl_android_set_max_num_sta(struct net_device * dev,const char * string_num)7102 wl_android_set_max_num_sta(struct net_device *dev, const char* string_num)
7103 {
7104 int err = BCME_ERROR;
7105 int max_assoc;
7106
7107 max_assoc = bcm_atoi(string_num);
7108 ANDROID_INFO(("wl_android_set_max_num_sta : HAPD_MAX_NUM_STA = %d\n", max_assoc));
7109
7110 err = wldev_iovar_setint(dev, "maxassoc", max_assoc);
7111 if (err < 0) {
7112 ANDROID_ERROR(("failed to set maxassoc, error:%d\n", err));
7113 }
7114
7115 return err;
7116 }
7117
7118 static int
wl_android_set_ssid(struct net_device * dev,const char * hapd_ssid)7119 wl_android_set_ssid(struct net_device *dev, const char* hapd_ssid)
7120 {
7121 wlc_ssid_t ssid;
7122 s32 ret;
7123
7124 ssid.SSID_len = strlen(hapd_ssid);
7125 if (ssid.SSID_len == 0) {
7126 ANDROID_ERROR(("wl_android_set_ssids : No SSID\n"));
7127 return -1;
7128 }
7129 if (ssid.SSID_len > DOT11_MAX_SSID_LEN) {
7130 ssid.SSID_len = DOT11_MAX_SSID_LEN;
7131 ANDROID_ERROR(("wl_android_set_ssid : Too long SSID Length %zu\n", strlen(hapd_ssid)));
7132 }
7133 bcm_strncpy_s(ssid.SSID, sizeof(ssid.SSID), hapd_ssid, ssid.SSID_len);
7134 ANDROID_INFO(("wl_android_set_ssid: HAPD_SSID = %s\n", ssid.SSID));
7135 ret = wldev_ioctl_set(dev, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t));
7136 if (ret < 0) {
7137 ANDROID_ERROR(("wl_android_set_ssid : WLC_SET_SSID Error:%d\n", ret));
7138 }
7139 return 1;
7140
7141 }
7142
7143 static int
wl_android_set_hide_ssid(struct net_device * dev,const char * string_num)7144 wl_android_set_hide_ssid(struct net_device *dev, const char* string_num)
7145 {
7146 int hide_ssid;
7147 int enable = 0;
7148 int err = BCME_ERROR;
7149
7150 hide_ssid = bcm_atoi(string_num);
7151 ANDROID_INFO(("wl_android_set_hide_ssid: HAPD_HIDE_SSID = %d\n", hide_ssid));
7152 if (hide_ssid) {
7153 enable = 1;
7154 }
7155
7156 err = wldev_iovar_setint(dev, "closednet", enable);
7157 if (err < 0) {
7158 ANDROID_ERROR(("failed to set closednet, error:%d\n", err));
7159 }
7160
7161 return err;
7162 }
7163 #endif /* SUPPORT_HIDDEN_AP */
7164
7165 #ifdef SUPPORT_SOFTAP_SINGL_DISASSOC
7166 static int
wl_android_sta_diassoc(struct net_device * dev,const char * straddr)7167 wl_android_sta_diassoc(struct net_device *dev, const char* straddr)
7168 {
7169 scb_val_t scbval;
7170 int error = 0;
7171
7172 ANDROID_INFO(("wl_android_sta_diassoc: deauth STA %s\n", straddr));
7173
7174 /* Unspecified reason */
7175 scbval.val = htod32(1);
7176
7177 if (bcm_ether_atoe(straddr, &scbval.ea) == 0) {
7178 ANDROID_ERROR(("wl_android_sta_diassoc: Invalid station MAC Address!!!\n"));
7179 return -1;
7180 }
7181
7182 ANDROID_ERROR(("wl_android_sta_diassoc: deauth STA: "MACDBG " scb_val.val %d\n",
7183 MAC2STRDBG(scbval.ea.octet), scbval.val));
7184
7185 error = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
7186 sizeof(scb_val_t));
7187 if (error) {
7188 ANDROID_ERROR(("Fail to DEAUTH station, error = %d\n", error));
7189 }
7190
7191 return 1;
7192 }
7193 #endif /* SUPPORT_SOFTAP_SINGL_DISASSOC */
7194
7195 #ifdef SUPPORT_SET_LPC
7196 static int
wl_android_set_lpc(struct net_device * dev,const char * string_num)7197 wl_android_set_lpc(struct net_device *dev, const char* string_num)
7198 {
7199 int lpc_enabled, ret;
7200 s32 val = 1;
7201
7202 lpc_enabled = bcm_atoi(string_num);
7203 ANDROID_INFO(("wl_android_set_lpc: HAPD_LPC_ENABLED = %d\n", lpc_enabled));
7204
7205 ret = wldev_ioctl_set(dev, WLC_DOWN, &val, sizeof(s32));
7206 if (ret < 0)
7207 ANDROID_ERROR(("WLC_DOWN error %d\n", ret));
7208
7209 wldev_iovar_setint(dev, "lpc", lpc_enabled);
7210
7211 ret = wldev_ioctl_set(dev, WLC_UP, &val, sizeof(s32));
7212 if (ret < 0)
7213 ANDROID_ERROR(("WLC_UP error %d\n", ret));
7214
7215 return 1;
7216 }
7217 #endif /* SUPPORT_SET_LPC */
7218
7219 static int
wl_android_ch_res_rl(struct net_device * dev,bool change)7220 wl_android_ch_res_rl(struct net_device *dev, bool change)
7221 {
7222 int error = 0;
7223 s32 srl = 7;
7224 s32 lrl = 4;
7225 ANDROID_ERROR(("wl_android_ch_res_rl: enter\n"));
7226 if (change) {
7227 srl = 4;
7228 lrl = 2;
7229 }
7230
7231 BCM_REFERENCE(lrl);
7232
7233 error = wldev_ioctl_set(dev, WLC_SET_SRL, &srl, sizeof(s32));
7234 if (error) {
7235 ANDROID_ERROR(("Failed to set SRL, error = %d\n", error));
7236 }
7237 #ifndef CUSTOM_LONG_RETRY_LIMIT
7238 error = wldev_ioctl_set(dev, WLC_SET_LRL, &lrl, sizeof(s32));
7239 if (error) {
7240 ANDROID_ERROR(("Failed to set LRL, error = %d\n", error));
7241 }
7242 #endif /* CUSTOM_LONG_RETRY_LIMIT */
7243 return error;
7244 }
7245
7246 #ifdef SUPPORT_LTECX
7247 #define DEFAULT_WLANRX_PROT 1
7248 #define DEFAULT_LTERX_PROT 0
7249 #define DEFAULT_LTETX_ADV 1200
7250
7251 static int
wl_android_set_ltecx(struct net_device * dev,const char * string_num)7252 wl_android_set_ltecx(struct net_device *dev, const char* string_num)
7253 {
7254 uint16 chan_bitmap;
7255 int ret;
7256
7257 chan_bitmap = bcm_strtoul(string_num, NULL, 16);
7258
7259 ANDROID_INFO(("wl_android_set_ltecx: LTECOEX 0x%x\n", chan_bitmap));
7260
7261 if (chan_bitmap) {
7262 ret = wldev_iovar_setint(dev, "mws_coex_bitmap", chan_bitmap);
7263 if (ret < 0) {
7264 ANDROID_ERROR(("mws_coex_bitmap error %d\n", ret));
7265 }
7266
7267 ret = wldev_iovar_setint(dev, "mws_wlanrx_prot", DEFAULT_WLANRX_PROT);
7268 if (ret < 0) {
7269 ANDROID_ERROR(("mws_wlanrx_prot error %d\n", ret));
7270 }
7271
7272 ret = wldev_iovar_setint(dev, "mws_lterx_prot", DEFAULT_LTERX_PROT);
7273 if (ret < 0) {
7274 ANDROID_ERROR(("mws_lterx_prot error %d\n", ret));
7275 }
7276
7277 ret = wldev_iovar_setint(dev, "mws_ltetx_adv", DEFAULT_LTETX_ADV);
7278 if (ret < 0) {
7279 ANDROID_ERROR(("mws_ltetx_adv error %d\n", ret));
7280 }
7281 } else {
7282 ret = wldev_iovar_setint(dev, "mws_coex_bitmap", chan_bitmap);
7283 if (ret < 0) {
7284 if (ret == BCME_UNSUPPORTED) {
7285 ANDROID_ERROR(("LTECX_CHAN_BITMAP is UNSUPPORTED\n"));
7286 } else {
7287 ANDROID_ERROR(("LTECX_CHAN_BITMAP error %d\n", ret));
7288 }
7289 }
7290 }
7291 return 1;
7292 }
7293 #endif /* SUPPORT_LTECX */
7294
7295 #ifdef WL_RELMCAST
7296 static int
wl_android_rmc_enable(struct net_device * net,int rmc_enable)7297 wl_android_rmc_enable(struct net_device *net, int rmc_enable)
7298 {
7299 int err;
7300
7301 err = wldev_iovar_setint(net, "rmc_ackreq", rmc_enable);
7302 if (err != BCME_OK) {
7303 ANDROID_ERROR(("wl_android_rmc_enable: rmc_ackreq, error = %d\n", err));
7304 }
7305 return err;
7306 }
7307
7308 static int
wl_android_rmc_set_leader(struct net_device * dev,const char * straddr)7309 wl_android_rmc_set_leader(struct net_device *dev, const char* straddr)
7310 {
7311 int error = BCME_OK;
7312 char smbuf[WLC_IOCTL_SMLEN];
7313 wl_rmc_entry_t rmc_entry;
7314 ANDROID_INFO(("wl_android_rmc_set_leader: Set new RMC leader %s\n", straddr));
7315
7316 bzero(&rmc_entry, sizeof(wl_rmc_entry_t));
7317 if (!bcm_ether_atoe(straddr, &rmc_entry.addr)) {
7318 if (strlen(straddr) == 1 && bcm_atoi(straddr) == 0) {
7319 ANDROID_INFO(("wl_android_rmc_set_leader: Set auto leader selection mode\n"));
7320 bzero(&rmc_entry, sizeof(wl_rmc_entry_t));
7321 } else {
7322 ANDROID_ERROR(("wl_android_rmc_set_leader: No valid mac address provided\n"));
7323 return BCME_ERROR;
7324 }
7325 }
7326
7327 error = wldev_iovar_setbuf(dev, "rmc_ar", &rmc_entry, sizeof(wl_rmc_entry_t),
7328 smbuf, sizeof(smbuf), NULL);
7329
7330 if (error != BCME_OK) {
7331 ANDROID_ERROR(("wl_android_rmc_set_leader: Unable to set RMC leader, error = %d\n",
7332 error));
7333 }
7334
7335 return error;
7336 }
7337
wl_android_set_rmc_event(struct net_device * dev,char * command)7338 static int wl_android_set_rmc_event(struct net_device *dev, char *command)
7339 {
7340 int err = 0;
7341 int pid = 0;
7342
7343 if (sscanf(command, CMD_SET_RMC_EVENT " %d", &pid) <= 0) {
7344 ANDROID_ERROR(("Failed to get Parameter from : %s\n", command));
7345 return -1;
7346 }
7347
7348 /* set pid, and if the event was happened, let's send a notification through netlink */
7349 wl_cfg80211_set_rmc_pid(dev, pid);
7350
7351 ANDROID_INFO(("RMC pid=%d\n", pid));
7352
7353 return err;
7354 }
7355 #endif /* WL_RELMCAST */
7356
wl_android_get_singlecore_scan(struct net_device * dev,char * command,int total_len)7357 int wl_android_get_singlecore_scan(struct net_device *dev, char *command, int total_len)
7358 {
7359 int error = 0;
7360 int bytes_written = 0;
7361 int mode = 0;
7362
7363 error = wldev_iovar_getint(dev, "scan_ps", &mode);
7364 if (error) {
7365 ANDROID_ERROR(("wl_android_get_singlecore_scan: Failed to get single core scan Mode,"
7366 " error = %d\n",
7367 error));
7368 return -1;
7369 }
7370
7371 bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_SCSCAN, mode);
7372
7373 return bytes_written;
7374 }
7375
wl_android_set_singlecore_scan(struct net_device * dev,char * command)7376 int wl_android_set_singlecore_scan(struct net_device *dev, char *command)
7377 {
7378 int error = 0;
7379 int mode = 0;
7380
7381 if (sscanf(command, "%*s %d", &mode) != 1) {
7382 ANDROID_ERROR(("wl_android_set_singlecore_scan: Failed to get Parameter\n"));
7383 return -1;
7384 }
7385
7386 error = wldev_iovar_setint(dev, "scan_ps", mode);
7387 if (error) {
7388 ANDROID_ERROR(("wl_android_set_singlecore_scan[1]: Failed to set Mode %d, error = %d\n",
7389 mode, error));
7390 return -1;
7391 }
7392
7393 return error;
7394 }
7395 #ifdef TEST_TX_POWER_CONTROL
7396 static int
wl_android_set_tx_power(struct net_device * dev,const char * string_num)7397 wl_android_set_tx_power(struct net_device *dev, const char* string_num)
7398 {
7399 int err = 0;
7400 s32 dbm;
7401 enum nl80211_tx_power_setting type;
7402
7403 dbm = bcm_atoi(string_num);
7404
7405 if (dbm < -1) {
7406 ANDROID_ERROR(("wl_android_set_tx_power: dbm is negative...\n"));
7407 return -EINVAL;
7408 }
7409
7410 if (dbm == -1)
7411 type = NL80211_TX_POWER_AUTOMATIC;
7412 else
7413 type = NL80211_TX_POWER_FIXED;
7414
7415 err = wl_set_tx_power(dev, type, dbm);
7416 if (unlikely(err)) {
7417 ANDROID_ERROR(("wl_android_set_tx_power: error (%d)\n", err));
7418 return err;
7419 }
7420
7421 return 1;
7422 }
7423
7424 static int
wl_android_get_tx_power(struct net_device * dev,char * command,int total_len)7425 wl_android_get_tx_power(struct net_device *dev, char *command, int total_len)
7426 {
7427 int err;
7428 int bytes_written;
7429 s32 dbm = 0;
7430
7431 err = wl_get_tx_power(dev, &dbm);
7432 if (unlikely(err)) {
7433 ANDROID_ERROR(("wl_android_get_tx_power: error (%d)\n", err));
7434 return err;
7435 }
7436
7437 bytes_written = snprintf(command, total_len, "%s %d",
7438 CMD_TEST_GET_TX_POWER, dbm);
7439
7440 ANDROID_ERROR(("wl_android_get_tx_power: GET_TX_POWER: dBm=%d\n", dbm));
7441
7442 return bytes_written;
7443 }
7444 #endif /* TEST_TX_POWER_CONTROL */
7445
7446 static int
wl_android_set_sarlimit_txctrl(struct net_device * dev,const char * string_num)7447 wl_android_set_sarlimit_txctrl(struct net_device *dev, const char* string_num)
7448 {
7449 int err = BCME_ERROR;
7450 int setval = 0;
7451 s32 mode = bcm_atoi(string_num);
7452 s32 mode_bit = 0;
7453 int enab = 0;
7454
7455 /* As Samsung specific and their requirement,
7456 * the mode set as the following form.
7457 * -1 : HEAD SAR disabled
7458 * 0 : HEAD SAR enabled
7459 * 1 : GRIP SAR disabled
7460 * 2 : GRIP SAR enabled
7461 * 3 : NR mmWave SAR disabled
7462 * 4 : NR mmWave SAR enabled
7463 * 5 : NR Sub6 SAR disabled
7464 * 6 : NR Sub6 SAR enabled
7465 * 7 : SAR BACKOFF disabled all
7466 * The 'SAR BACKOFF disabled all' index should be the end of the mode.
7467 */
7468 if ((mode < HEAD_SAR_BACKOFF_DISABLE) || (mode > SAR_BACKOFF_DISABLE_ALL)) {
7469 ANDROID_ERROR(("%s: Request for Unsupported:%d\n", __FUNCTION__, bcm_atoi(string_num)));
7470 err = BCME_RANGE;
7471 goto error;
7472 }
7473
7474 mode_bit = mode + 1;
7475 enab = mode_bit % 2;
7476 mode_bit = mode_bit / 2;
7477
7478 err = wldev_iovar_getint(dev, "sar_enable", &setval);
7479 if (unlikely(err)) {
7480 ANDROID_ERROR(("%s: Failed to get sar_enable - error (%d)\n", __FUNCTION__, err));
7481 goto error;
7482 }
7483
7484 if (mode == SAR_BACKOFF_DISABLE_ALL) {
7485 ANDROID_ERROR(("%s: SAR limit control all mode disable!\n", __FUNCTION__));
7486 setval = 0;
7487 } else {
7488 ANDROID_ERROR(("%s: SAR limit control mode %d enab %d\n",
7489 __FUNCTION__, mode_bit, enab));
7490 if (enab) {
7491 setval |= (1 << mode_bit);
7492 } else {
7493 setval &= ~(1 << mode_bit);
7494 }
7495 }
7496
7497 err = wldev_iovar_setint(dev, "sar_enable", setval);
7498 if (unlikely(err)) {
7499 ANDROID_ERROR(("%s: Failed to set sar_enable - error (%d)\n", __FUNCTION__, err));
7500 goto error;
7501 }
7502 err = BCME_OK;
7503 error:
7504 return err;
7505 }
7506
7507 #ifdef SUPPORT_SET_TID
7508 static int
wl_android_set_tid(struct net_device * dev,char * command)7509 wl_android_set_tid(struct net_device *dev, char* command)
7510 {
7511 int err = BCME_ERROR;
7512 char *pos = command;
7513 char *token = NULL;
7514 uint8 mode = 0;
7515 uint32 uid = 0;
7516 uint8 prio = 0;
7517 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
7518
7519 if (!dhdp) {
7520 ANDROID_ERROR(("dhd is NULL\n"));
7521 return err;
7522 }
7523
7524 ANDROID_INFO(("%s: command[%s]\n", __FUNCTION__, command));
7525
7526 /* drop command */
7527 token = bcmstrtok(&pos, " ", NULL);
7528
7529 token = bcmstrtok(&pos, " ", NULL);
7530 if (!token) {
7531 ANDROID_ERROR(("Invalid arguments\n"));
7532 return err;
7533 }
7534
7535 mode = bcm_atoi(token);
7536
7537 if (mode < SET_TID_OFF || mode > SET_TID_BASED_ON_UID) {
7538 ANDROID_ERROR(("Invalid arguments, mode %d\n", mode));
7539 return err;
7540 }
7541
7542 if (mode) {
7543 token = bcmstrtok(&pos, " ", NULL);
7544 if (!token) {
7545 ANDROID_ERROR(("Invalid arguments for target uid\n"));
7546 return err;
7547 }
7548
7549 uid = bcm_atoi(token);
7550
7551 token = bcmstrtok(&pos, " ", NULL);
7552 if (!token) {
7553 ANDROID_ERROR(("Invalid arguments for target tid\n"));
7554 return err;
7555 }
7556
7557 prio = bcm_atoi(token);
7558 if (prio >= 0 && prio <= MAXPRIO) {
7559 dhdp->tid_mode = mode;
7560 dhdp->target_uid = uid;
7561 dhdp->target_tid = prio;
7562 } else {
7563 ANDROID_ERROR(("Invalid arguments, prio %d\n", prio));
7564 return err;
7565 }
7566 } else {
7567 dhdp->tid_mode = SET_TID_OFF;
7568 dhdp->target_uid = 0;
7569 dhdp->target_tid = 0;
7570 }
7571
7572 ANDROID_INFO(("%s mode [%d], uid [%d], tid [%d]\n", __FUNCTION__,
7573 dhdp->tid_mode, dhdp->target_uid, dhdp->target_tid));
7574
7575 err = BCME_OK;
7576 return err;
7577 }
7578
7579 static int
wl_android_get_tid(struct net_device * dev,char * command,int total_len)7580 wl_android_get_tid(struct net_device *dev, char* command, int total_len)
7581 {
7582 int bytes_written = BCME_ERROR;
7583 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
7584
7585 if (!dhdp) {
7586 ANDROID_ERROR(("dhd is NULL\n"));
7587 return bytes_written;
7588 }
7589
7590 bytes_written = snprintf(command, total_len, "mode %d uid %d tid %d",
7591 dhdp->tid_mode, dhdp->target_uid, dhdp->target_tid);
7592
7593 ANDROID_INFO(("%s: command results %s\n", __FUNCTION__, command));
7594
7595 return bytes_written;
7596 }
7597 #endif /* SUPPORT_SET_TID */
7598 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
7599
wl_android_set_roam_mode(struct net_device * dev,char * command)7600 int wl_android_set_roam_mode(struct net_device *dev, char *command)
7601 {
7602 int error = 0;
7603 int mode = 0;
7604
7605 if (sscanf(command, "%*s %d", &mode) != 1) {
7606 ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
7607 return -1;
7608 }
7609
7610 error = wldev_iovar_setint(dev, "roam_off", mode);
7611 if (error) {
7612 ANDROID_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n",
7613 __FUNCTION__, mode, error));
7614 return -1;
7615 }
7616 else
7617 ANDROID_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n",
7618 __FUNCTION__, mode, error));
7619 return 0;
7620 }
7621
7622 #ifdef WL_CFG80211
wl_android_set_ibss_beacon_ouidata(struct net_device * dev,char * command,int total_len)7623 int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, int total_len)
7624 {
7625 char ie_buf[VNDR_IE_MAX_LEN];
7626 char *ioctl_buf = NULL;
7627 char hex[] = "XX";
7628 char *pcmd = NULL;
7629 int ielen = 0, datalen = 0, idx = 0, tot_len = 0;
7630 vndr_ie_setbuf_t *vndr_ie = NULL;
7631 s32 iecount;
7632 uint32 pktflag;
7633 s32 err = BCME_OK, bssidx;
7634 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
7635
7636 /* Check the VSIE (Vendor Specific IE) which was added.
7637 * If exist then send IOVAR to delete it
7638 */
7639 if (wl_cfg80211_ibss_vsie_delete(dev) != BCME_OK) {
7640 return -EINVAL;
7641 }
7642
7643 if (total_len < (strlen(CMD_SETIBSSBEACONOUIDATA) + 1)) {
7644 ANDROID_ERROR(("error. total_len:%d\n", total_len));
7645 return -EINVAL;
7646 }
7647
7648 pcmd = command + strlen(CMD_SETIBSSBEACONOUIDATA) + 1;
7649 for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
7650 if (*pcmd == '\0') {
7651 ANDROID_ERROR(("error while parsing OUI.\n"));
7652 return -EINVAL;
7653 }
7654 hex[0] = *pcmd++;
7655 hex[1] = *pcmd++;
7656 ie_buf[idx] = (uint8)simple_strtoul(hex, NULL, 16);
7657 }
7658 pcmd++;
7659 while ((*pcmd != '\0') && (idx < VNDR_IE_MAX_LEN)) {
7660 hex[0] = *pcmd++;
7661 hex[1] = *pcmd++;
7662 ie_buf[idx++] = (uint8)simple_strtoul(hex, NULL, 16);
7663 datalen++;
7664 }
7665
7666 if (datalen <= 0) {
7667 ANDROID_ERROR(("error. vndr ie len:%d\n", datalen));
7668 return -EINVAL;
7669 }
7670
7671 tot_len = (int)(sizeof(vndr_ie_setbuf_t) + (datalen - 1));
7672 vndr_ie = (vndr_ie_setbuf_t *)MALLOCZ(cfg->osh, tot_len);
7673 if (!vndr_ie) {
7674 ANDROID_ERROR(("IE memory alloc failed\n"));
7675 return -ENOMEM;
7676 }
7677 /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
7678 strlcpy(vndr_ie->cmd, "add", sizeof(vndr_ie->cmd));
7679
7680 /* Set the IE count - the buffer contains only 1 IE */
7681 iecount = htod32(1);
7682 memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
7683
7684 /* Set packet flag to indicate that BEACON's will contain this IE */
7685 pktflag = htod32(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG);
7686 memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
7687 sizeof(u32));
7688 /* Set the IE ID */
7689 vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
7690
7691 memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, &ie_buf,
7692 DOT11_OUI_LEN);
7693 memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data,
7694 &ie_buf[DOT11_OUI_LEN], datalen);
7695
7696 ielen = DOT11_OUI_LEN + datalen;
7697 vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
7698
7699 ioctl_buf = (char *)MALLOC(cfg->osh, WLC_IOCTL_MEDLEN);
7700 if (!ioctl_buf) {
7701 ANDROID_ERROR(("ioctl memory alloc failed\n"));
7702 if (vndr_ie) {
7703 MFREE(cfg->osh, vndr_ie, tot_len);
7704 }
7705 return -ENOMEM;
7706 }
7707 bzero(ioctl_buf, WLC_IOCTL_MEDLEN); /* init the buffer */
7708 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
7709 ANDROID_ERROR(("Find index failed\n"));
7710 err = BCME_ERROR;
7711 goto end;
7712 }
7713 err = wldev_iovar_setbuf_bsscfg(dev, "vndr_ie", vndr_ie, tot_len, ioctl_buf,
7714 WLC_IOCTL_MEDLEN, bssidx, &cfg->ioctl_buf_sync);
7715 end:
7716 if (err != BCME_OK) {
7717 err = -EINVAL;
7718 if (vndr_ie) {
7719 MFREE(cfg->osh, vndr_ie, tot_len);
7720 }
7721 }
7722 else {
7723 /* do NOT free 'vndr_ie' for the next process */
7724 wl_cfg80211_ibss_vsie_set_buffer(dev, vndr_ie, tot_len);
7725 }
7726
7727 if (ioctl_buf) {
7728 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
7729 }
7730
7731 return err;
7732 }
7733 #endif /* WL_CFG80211 */
7734
7735 #if defined(BCMFW_ROAM_ENABLE)
7736 static int
wl_android_set_roampref(struct net_device * dev,char * command,int total_len)7737 wl_android_set_roampref(struct net_device *dev, char *command, int total_len)
7738 {
7739 int error = 0;
7740 char smbuf[WLC_IOCTL_SMLEN];
7741 uint8 buf[MAX_BUF_SIZE];
7742 uint8 *pref = buf;
7743 char *pcmd;
7744 int num_ucipher_suites = 0;
7745 int num_akm_suites = 0;
7746 wpa_suite_t ucipher_suites[MAX_NUM_SUITES];
7747 wpa_suite_t akm_suites[MAX_NUM_SUITES];
7748 int num_tuples = 0;
7749 int total_bytes = 0;
7750 int total_len_left;
7751 int i, j;
7752 char hex[] = "XX";
7753
7754 pcmd = command + strlen(CMD_SET_ROAMPREF) + 1;
7755 total_len_left = total_len - strlen(CMD_SET_ROAMPREF) + 1;
7756
7757 num_akm_suites = simple_strtoul(pcmd, NULL, 16);
7758 if (num_akm_suites > MAX_NUM_SUITES) {
7759 ANDROID_ERROR(("too many AKM suites = %d\n", num_akm_suites));
7760 return -1;
7761 }
7762
7763 /* Increment for number of AKM suites field + space */
7764 pcmd += 3;
7765 total_len_left -= 3;
7766
7767 /* check to make sure pcmd does not overrun */
7768 if (total_len_left < (num_akm_suites * WIDTH_AKM_SUITE))
7769 return -1;
7770
7771 bzero(buf, sizeof(buf));
7772 bzero(akm_suites, sizeof(akm_suites));
7773 bzero(ucipher_suites, sizeof(ucipher_suites));
7774
7775 /* Save the AKM suites passed in the command */
7776 for (i = 0; i < num_akm_suites; i++) {
7777 /* Store the MSB first, as required by join_pref */
7778 for (j = 0; j < 4; j++) {
7779 hex[0] = *pcmd++;
7780 hex[1] = *pcmd++;
7781 buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
7782 }
7783 memcpy((uint8 *)&akm_suites[i], buf, sizeof(uint32));
7784 }
7785
7786 total_len_left -= (num_akm_suites * WIDTH_AKM_SUITE);
7787 num_ucipher_suites = simple_strtoul(pcmd, NULL, 16);
7788 /* Increment for number of cipher suites field + space */
7789 pcmd += 3;
7790 total_len_left -= 3;
7791
7792 if (total_len_left < (num_ucipher_suites * WIDTH_AKM_SUITE))
7793 return -1;
7794
7795 /* Save the cipher suites passed in the command */
7796 for (i = 0; i < num_ucipher_suites; i++) {
7797 /* Store the MSB first, as required by join_pref */
7798 for (j = 0; j < 4; j++) {
7799 hex[0] = *pcmd++;
7800 hex[1] = *pcmd++;
7801 buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
7802 }
7803 memcpy((uint8 *)&ucipher_suites[i], buf, sizeof(uint32));
7804 }
7805
7806 /* Join preference for RSSI
7807 * Type : 1 byte (0x01)
7808 * Length : 1 byte (0x02)
7809 * Value : 2 bytes (reserved)
7810 */
7811 *pref++ = WL_JOIN_PREF_RSSI;
7812 *pref++ = JOIN_PREF_RSSI_LEN;
7813 *pref++ = 0;
7814 *pref++ = 0;
7815
7816 /* Join preference for WPA
7817 * Type : 1 byte (0x02)
7818 * Length : 1 byte (not used)
7819 * Value : (variable length)
7820 * reserved: 1 byte
7821 * count : 1 byte (no of tuples)
7822 * Tuple1 : 12 bytes
7823 * akm[4]
7824 * ucipher[4]
7825 * mcipher[4]
7826 * Tuple2 : 12 bytes
7827 * Tuplen : 12 bytes
7828 */
7829 num_tuples = num_akm_suites * num_ucipher_suites;
7830 if (num_tuples != 0) {
7831 if (num_tuples <= JOIN_PREF_MAX_WPA_TUPLES) {
7832 *pref++ = WL_JOIN_PREF_WPA;
7833 *pref++ = 0;
7834 *pref++ = 0;
7835 *pref++ = (uint8)num_tuples;
7836 total_bytes = JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE +
7837 (JOIN_PREF_WPA_TUPLE_SIZE * num_tuples);
7838 } else {
7839 ANDROID_ERROR(("%s: Too many wpa configs for join_pref \n", __FUNCTION__));
7840 return -1;
7841 }
7842 } else {
7843 /* No WPA config, configure only RSSI preference */
7844 total_bytes = JOIN_PREF_RSSI_SIZE;
7845 }
7846
7847 /* akm-ucipher-mcipher tuples in the format required for join_pref */
7848 for (i = 0; i < num_ucipher_suites; i++) {
7849 for (j = 0; j < num_akm_suites; j++) {
7850 memcpy(pref, (uint8 *)&akm_suites[j], WPA_SUITE_LEN);
7851 pref += WPA_SUITE_LEN;
7852 memcpy(pref, (uint8 *)&ucipher_suites[i], WPA_SUITE_LEN);
7853 pref += WPA_SUITE_LEN;
7854 /* Set to 0 to match any available multicast cipher */
7855 bzero(pref, WPA_SUITE_LEN);
7856 pref += WPA_SUITE_LEN;
7857 }
7858 }
7859
7860 prhex("join pref", (uint8 *)buf, total_bytes);
7861 error = wldev_iovar_setbuf(dev, "join_pref", buf, total_bytes, smbuf, sizeof(smbuf), NULL);
7862 if (error) {
7863 ANDROID_ERROR(("Failed to set join_pref, error = %d\n", error));
7864 }
7865 return error;
7866 }
7867 #endif /* defined(BCMFW_ROAM_ENABLE */
7868
7869 #ifdef WL_CFG80211
7870 static int
wl_android_iolist_add(struct net_device * dev,struct list_head * head,struct io_cfg * config)7871 wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_cfg *config)
7872 {
7873 struct io_cfg *resume_cfg;
7874 s32 ret;
7875 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
7876
7877 resume_cfg = (struct io_cfg *)MALLOCZ(cfg->osh, sizeof(struct io_cfg));
7878 if (!resume_cfg)
7879 return -ENOMEM;
7880
7881 if (config->iovar) {
7882 ret = wldev_iovar_getint(dev, config->iovar, &resume_cfg->param);
7883 if (ret) {
7884 ANDROID_ERROR(("%s: Failed to get current %s value\n",
7885 __FUNCTION__, config->iovar));
7886 goto error;
7887 }
7888
7889 ret = wldev_iovar_setint(dev, config->iovar, config->param);
7890 if (ret) {
7891 ANDROID_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
7892 config->iovar, config->param));
7893 goto error;
7894 }
7895
7896 resume_cfg->iovar = config->iovar;
7897 } else {
7898 resume_cfg->arg = MALLOCZ(cfg->osh, config->len);
7899 if (!resume_cfg->arg) {
7900 ret = -ENOMEM;
7901 goto error;
7902 }
7903 ret = wldev_ioctl_get(dev, config->ioctl, resume_cfg->arg, config->len);
7904 if (ret) {
7905 ANDROID_ERROR(("%s: Failed to get ioctl %d\n", __FUNCTION__,
7906 config->ioctl));
7907 goto error;
7908 }
7909 ret = wldev_ioctl_set(dev, config->ioctl + 1, config->arg, config->len);
7910 if (ret) {
7911 ANDROID_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
7912 config->iovar, config->param));
7913 goto error;
7914 }
7915 if (config->ioctl + 1 == WLC_SET_PM)
7916 wl_cfg80211_update_power_mode(dev);
7917 resume_cfg->ioctl = config->ioctl;
7918 resume_cfg->len = config->len;
7919 }
7920
7921 /* assuming only one active user and no list protection */
7922 list_add(&resume_cfg->list, head);
7923
7924 return 0;
7925 error:
7926 MFREE(cfg->osh, resume_cfg->arg, config->len);
7927 MFREE(cfg->osh, resume_cfg, sizeof(struct io_cfg));
7928 return ret;
7929 }
7930
7931 static void
wl_android_iolist_resume(struct net_device * dev,struct list_head * head)7932 wl_android_iolist_resume(struct net_device *dev, struct list_head *head)
7933 {
7934 struct io_cfg *config;
7935 struct list_head *cur, *q;
7936 s32 ret = 0;
7937 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
7938 GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
7939 list_for_each_safe(cur, q, head) {
7940 config = list_entry(cur, struct io_cfg, list);
7941 GCC_DIAGNOSTIC_POP();
7942 if (config->iovar) {
7943 if (!ret)
7944 ret = wldev_iovar_setint(dev, config->iovar,
7945 config->param);
7946 } else {
7947 if (!ret)
7948 ret = wldev_ioctl_set(dev, config->ioctl + 1,
7949 config->arg, config->len);
7950 if (config->ioctl + 1 == WLC_SET_PM)
7951 wl_cfg80211_update_power_mode(dev);
7952 MFREE(cfg->osh, config->arg, config->len);
7953 }
7954 list_del(cur);
7955 MFREE(cfg->osh, config, sizeof(struct io_cfg));
7956 }
7957 }
7958
7959 static int
wl_android_set_miracast(struct net_device * dev,char * command)7960 wl_android_set_miracast(struct net_device *dev, char *command)
7961 {
7962 int mode, val = 0;
7963 int ret = 0;
7964 struct io_cfg config;
7965
7966 if (sscanf(command, "%*s %d", &mode) != 1) {
7967 ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
7968 return -1;
7969 }
7970
7971 ANDROID_INFO(("%s: enter miracast mode %d\n", __FUNCTION__, mode));
7972
7973 if (miracast_cur_mode == mode) {
7974 return 0;
7975 }
7976
7977 wl_android_iolist_resume(dev, &miracast_resume_list);
7978 miracast_cur_mode = MIRACAST_MODE_OFF;
7979
7980 bzero((void *)&config, sizeof(config));
7981 switch (mode) {
7982 case MIRACAST_MODE_SOURCE:
7983 #ifdef MIRACAST_MCHAN_ALGO
7984 /* setting mchan_algo to platform specific value */
7985 config.iovar = "mchan_algo";
7986
7987 /* check for station's beacon interval(BI)
7988 * If BI is over 100ms, don't use mchan_algo
7989 */
7990 ret = wldev_ioctl_get(dev, WLC_GET_BCNPRD, &val, sizeof(int));
7991 if (!ret && val > 100) {
7992 config.param = 0;
7993 ANDROID_ERROR(("%s: Connected station's beacon interval: "
7994 "%d and set mchan_algo to %d \n",
7995 __FUNCTION__, val, config.param));
7996 } else {
7997 config.param = MIRACAST_MCHAN_ALGO;
7998 }
7999 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8000 if (ret) {
8001 goto resume;
8002 }
8003 #endif /* MIRACAST_MCHAN_ALGO */
8004
8005 #ifdef MIRACAST_MCHAN_BW
8006 /* setting mchan_bw to platform specific value */
8007 config.iovar = "mchan_bw";
8008 config.param = MIRACAST_MCHAN_BW;
8009 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8010 if (ret) {
8011 goto resume;
8012 }
8013 #endif /* MIRACAST_MCHAN_BW */
8014
8015 #ifdef MIRACAST_AMPDU_SIZE
8016 /* setting apmdu to platform specific value */
8017 config.iovar = "ampdu_mpdu";
8018 config.param = MIRACAST_AMPDU_SIZE;
8019 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8020 if (ret) {
8021 goto resume;
8022 }
8023 #endif /* MIRACAST_AMPDU_SIZE */
8024 /* FALLTROUGH */
8025 /* Source mode shares most configurations with sink mode.
8026 * Fall through here to avoid code duplication
8027 */
8028 case MIRACAST_MODE_SINK:
8029 /* disable internal roaming */
8030 config.iovar = "roam_off";
8031 config.param = 1;
8032 config.arg = NULL;
8033 config.len = 0;
8034 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8035 if (ret) {
8036 goto resume;
8037 }
8038
8039 #ifdef CUSTOMER_HW10
8040 /* [CSP#812738] Change scan engine parameters to reduce scan time
8041 * and guarantee more times to mirroring.
8042 */
8043 val = 10;
8044 config.iovar = NULL;
8045 config.ioctl = WLC_GET_SCAN_CHANNEL_TIME;
8046 config.arg = &val;
8047 config.len = sizeof(int);
8048 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8049 if (ret)
8050 goto resume;
8051
8052 val = 180;
8053 config.iovar = NULL;
8054 config.ioctl = WLC_GET_SCAN_HOME_TIME;
8055 config.arg = &val;
8056 config.len = sizeof(int);
8057 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8058 if (ret)
8059 goto resume;
8060
8061 #if defined(BCM4339_CHIP)
8062 config.iovar = "phy_watchdog";
8063 config.param = 0;
8064 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8065 ANDROID_INFO(("%s: do iovar cmd=%s (ret=%d)\n",
8066 __FUNCTION__, config.iovar, ret));
8067 #endif
8068 #endif /* CUSTOMER_HW10 */
8069
8070 #ifndef CUSTOMER_HW10
8071
8072 /* tunr off pm */
8073 ret = wldev_ioctl_get(dev, WLC_GET_PM, &val, sizeof(val));
8074 if (ret) {
8075 goto resume;
8076 }
8077
8078 if (val != PM_OFF) {
8079 val = PM_OFF;
8080 config.iovar = NULL;
8081 config.ioctl = WLC_GET_PM;
8082 config.arg = &val;
8083 config.len = sizeof(int);
8084 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
8085 if (ret) {
8086 goto resume;
8087 }
8088 }
8089 #endif /* CUSTOMER_HW10 */
8090 break;
8091 case MIRACAST_MODE_OFF:
8092 default:
8093 break;
8094 }
8095 miracast_cur_mode = mode;
8096
8097 return 0;
8098
8099 resume:
8100 ANDROID_ERROR(("%s: turnoff miracast mode because of err%d\n", __FUNCTION__, ret));
8101 wl_android_iolist_resume(dev, &miracast_resume_list);
8102 return ret;
8103 }
8104 #endif /* WL_CFG80211 */
8105
8106 #ifdef WL_RELMCAST
8107 #define NETLINK_OXYGEN 30
8108 #define AIBSS_BEACON_TIMEOUT 10
8109
8110 static struct sock *nl_sk = NULL;
8111
wl_netlink_recv(struct sk_buff * skb)8112 static void wl_netlink_recv(struct sk_buff *skb)
8113 {
8114 ANDROID_ERROR(("netlink_recv called\n"));
8115 }
8116
wl_netlink_init(void)8117 static int wl_netlink_init(void)
8118 {
8119 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8120 struct netlink_kernel_cfg cfg = {
8121 .input = wl_netlink_recv,
8122 };
8123 #endif
8124
8125 if (nl_sk != NULL) {
8126 ANDROID_ERROR(("nl_sk already exist\n"));
8127 return BCME_ERROR;
8128 }
8129
8130 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
8131 nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN,
8132 0, wl_netlink_recv, NULL, THIS_MODULE);
8133 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
8134 nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, THIS_MODULE, &cfg);
8135 #else
8136 nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, &cfg);
8137 #endif
8138
8139 if (nl_sk == NULL) {
8140 ANDROID_ERROR(("nl_sk is not ready\n"));
8141 return BCME_ERROR;
8142 }
8143
8144 return BCME_OK;
8145 }
8146
wl_netlink_deinit(void)8147 static void wl_netlink_deinit(void)
8148 {
8149 if (nl_sk) {
8150 netlink_kernel_release(nl_sk);
8151 nl_sk = NULL;
8152 }
8153 }
8154
8155 s32
wl_netlink_send_msg(int pid,int type,int seq,const void * data,size_t size)8156 wl_netlink_send_msg(int pid, int type, int seq, const void *data, size_t size)
8157 {
8158 struct sk_buff *skb = NULL;
8159 struct nlmsghdr *nlh = NULL;
8160 int ret = -1;
8161
8162 if (nl_sk == NULL) {
8163 ANDROID_ERROR(("nl_sk was not initialized\n"));
8164 goto nlmsg_failure;
8165 }
8166
8167 skb = alloc_skb(NLMSG_SPACE(size), GFP_ATOMIC);
8168 if (skb == NULL) {
8169 ANDROID_ERROR(("failed to allocate memory\n"));
8170 goto nlmsg_failure;
8171 }
8172
8173 nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
8174 if (nlh == NULL) {
8175 ANDROID_ERROR(("failed to build nlmsg, skb_tailroom:%d, nlmsg_total_size:%d\n",
8176 skb_tailroom(skb), nlmsg_total_size(size)));
8177 dev_kfree_skb(skb);
8178 goto nlmsg_failure;
8179 }
8180
8181 memcpy(nlmsg_data(nlh), data, size);
8182 nlh->nlmsg_seq = seq;
8183 nlh->nlmsg_type = type;
8184
8185 /* netlink_unicast() takes ownership of the skb and frees it itself. */
8186 ret = netlink_unicast(nl_sk, skb, pid, 0);
8187 ANDROID_INFO(("netlink_unicast() pid=%d, ret=%d\n", pid, ret));
8188
8189 nlmsg_failure:
8190 return ret;
8191 }
8192 #endif /* WL_RELMCAST */
8193
8194 #ifdef WLAIBSS
wl_android_set_ibss_txfail_event(struct net_device * dev,char * command,int total_len)8195 static int wl_android_set_ibss_txfail_event(struct net_device *dev, char *command, int total_len)
8196 {
8197 int err = 0;
8198 int retry = 0;
8199 int pid = 0;
8200 aibss_txfail_config_t txfail_config = {0, 0, 0, 0, 0};
8201 char smbuf[WLC_IOCTL_SMLEN];
8202
8203 if (sscanf(command, CMD_SETIBSSTXFAILEVENT " %d %d", &retry, &pid) <= 0) {
8204 ANDROID_ERROR(("Failed to get Parameter from : %s\n", command));
8205 return -1;
8206 }
8207
8208 /* set pid, and if the event was happened, let's send a notification through netlink */
8209 wl_cfg80211_set_txfail_pid(dev, pid);
8210
8211 #ifdef WL_RELMCAST
8212 /* using same pid for RMC, AIBSS shares same pid with RMC and it is set once */
8213 wl_cfg80211_set_rmc_pid(dev, pid);
8214 #endif /* WL_RELMCAST */
8215
8216 /* If retry value is 0, it disables the functionality for TX Fail. */
8217 if (retry > 0) {
8218 txfail_config.max_tx_retry = retry;
8219 txfail_config.bcn_timeout = 0; /* 0 : disable tx fail from beacon */
8220 }
8221 txfail_config.version = AIBSS_TXFAIL_CONFIG_VER_0;
8222 txfail_config.len = sizeof(txfail_config);
8223
8224 err = wldev_iovar_setbuf(dev, "aibss_txfail_config", (void *) &txfail_config,
8225 sizeof(aibss_txfail_config_t), smbuf, WLC_IOCTL_SMLEN, NULL);
8226 ANDROID_INFO(("retry=%d, pid=%d, err=%d\n", retry, pid, err));
8227
8228 return ((err == 0)?total_len:err);
8229 }
8230
wl_android_get_ibss_peer_info(struct net_device * dev,char * command,int total_len,bool bAll)8231 static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command,
8232 int total_len, bool bAll)
8233 {
8234 int error;
8235 int bytes_written = 0;
8236 void *buf = NULL;
8237 bss_peer_list_info_t peer_list_info;
8238 bss_peer_info_t *peer_info;
8239 int i;
8240 bool found = false;
8241 struct ether_addr mac_ea;
8242 char *str = command;
8243 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8244
8245 ANDROID_INFO(("get ibss peer info(%s)\n", bAll?"true":"false"));
8246
8247 if (!bAll) {
8248 if (bcmstrtok(&str, " ", NULL) == NULL) {
8249 ANDROID_ERROR(("invalid command\n"));
8250 return -1;
8251 }
8252
8253 if (!str || !bcm_ether_atoe(str, &mac_ea)) {
8254 ANDROID_ERROR(("invalid MAC address\n"));
8255 return -1;
8256 }
8257 }
8258
8259 if ((buf = MALLOC(cfg->osh, WLC_IOCTL_MAXLEN)) == NULL) {
8260 ANDROID_ERROR(("kmalloc failed\n"));
8261 return -1;
8262 }
8263
8264 error = wldev_iovar_getbuf(dev, "bss_peer_info", NULL, 0, buf, WLC_IOCTL_MAXLEN, NULL);
8265 if (unlikely(error)) {
8266 ANDROID_ERROR(("could not get ibss peer info (%d)\n", error));
8267 MFREE(cfg->osh, buf, WLC_IOCTL_MAXLEN);
8268 return -1;
8269 }
8270
8271 memcpy(&peer_list_info, buf, sizeof(peer_list_info));
8272 peer_list_info.version = htod16(peer_list_info.version);
8273 peer_list_info.bss_peer_info_len = htod16(peer_list_info.bss_peer_info_len);
8274 peer_list_info.count = htod32(peer_list_info.count);
8275
8276 ANDROID_INFO(("ver:%d, len:%d, count:%d\n", peer_list_info.version,
8277 peer_list_info.bss_peer_info_len, peer_list_info.count));
8278
8279 if (peer_list_info.count > 0) {
8280 if (bAll)
8281 bytes_written += snprintf(&command[bytes_written], total_len, "%u ",
8282 peer_list_info.count);
8283
8284 peer_info = (bss_peer_info_t *) ((char *)buf + BSS_PEER_LIST_INFO_FIXED_LEN);
8285
8286 for (i = 0; i < peer_list_info.count; i++) {
8287
8288 ANDROID_INFO(("index:%d rssi:%d, tx:%u, rx:%u\n", i, peer_info->rssi,
8289 peer_info->tx_rate, peer_info->rx_rate));
8290
8291 if (!bAll &&
8292 memcmp(&mac_ea, &peer_info->ea, sizeof(struct ether_addr)) == 0) {
8293 found = true;
8294 }
8295
8296 if (bAll || found) {
8297 bytes_written += snprintf(&command[bytes_written],
8298 total_len - bytes_written,
8299 MACF" %u %d ", ETHER_TO_MACF(peer_info->ea),
8300 peer_info->tx_rate/1000, peer_info->rssi);
8301 if (bytes_written >= total_len) {
8302 ANDROID_ERROR(("wl_android_get_ibss_peer_info: Insufficient"
8303 " memory, %d bytes\n",
8304 total_len));
8305 bytes_written = -1;
8306 break;
8307 }
8308 }
8309
8310 if (found)
8311 break;
8312
8313 peer_info = (bss_peer_info_t *)((char *)peer_info+sizeof(bss_peer_info_t));
8314 }
8315 }
8316 else {
8317 ANDROID_ERROR(("could not get ibss peer info : no item\n"));
8318 }
8319 ANDROID_INFO(("command(%u):%s\n", total_len, command));
8320 ANDROID_INFO(("bytes_written:%d\n", bytes_written));
8321
8322 MFREE(cfg->osh, buf, WLC_IOCTL_MAXLEN);
8323 return bytes_written;
8324 }
8325
wl_android_set_ibss_routetable(struct net_device * dev,char * command)8326 int wl_android_set_ibss_routetable(struct net_device *dev, char *command)
8327 {
8328
8329 char *pcmd = command;
8330 char *str = NULL;
8331 ibss_route_tbl_t *route_tbl = NULL;
8332 char *ioctl_buf = NULL;
8333 s32 err = BCME_OK;
8334 uint32 route_tbl_len;
8335 uint32 entries;
8336 char *endptr;
8337 uint32 i = 0;
8338 struct ipv4_addr dipaddr;
8339 struct ether_addr ea;
8340 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8341
8342 route_tbl_len = sizeof(ibss_route_tbl_t) +
8343 (MAX_IBSS_ROUTE_TBL_ENTRY - 1) * sizeof(ibss_route_entry_t);
8344 route_tbl = (ibss_route_tbl_t *)MALLOCZ(cfg->osh, route_tbl_len);
8345 if (!route_tbl) {
8346 ANDROID_ERROR(("Route TBL alloc failed\n"));
8347 return -ENOMEM;
8348 }
8349 ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
8350 if (!ioctl_buf) {
8351 ANDROID_ERROR(("ioctl memory alloc failed\n"));
8352 if (route_tbl) {
8353 MFREE(cfg->osh, route_tbl, route_tbl_len);
8354 }
8355 return -ENOMEM;
8356 }
8357 bzero(ioctl_buf, WLC_IOCTL_MEDLEN);
8358
8359 /* drop command */
8360 str = bcmstrtok(&pcmd, " ", NULL);
8361
8362 /* get count */
8363 str = bcmstrtok(&pcmd, " ", NULL);
8364 if (!str) {
8365 ANDROID_ERROR(("Invalid number parameter %s\n", str));
8366 err = -EINVAL;
8367 goto exit;
8368 }
8369 entries = bcm_strtoul(str, &endptr, 0);
8370 if (*endptr != '\0') {
8371 ANDROID_ERROR(("Invalid number parameter %s\n", str));
8372 err = -EINVAL;
8373 goto exit;
8374 }
8375 if (entries > MAX_IBSS_ROUTE_TBL_ENTRY) {
8376 ANDROID_ERROR(("Invalid entries number %u\n", entries));
8377 err = -EINVAL;
8378 goto exit;
8379 }
8380
8381 ANDROID_INFO(("Routing table count:%u\n", entries));
8382 route_tbl->num_entry = entries;
8383
8384 for (i = 0; i < entries; i++) {
8385 str = bcmstrtok(&pcmd, " ", NULL);
8386 if (!str || !bcm_atoipv4(str, &dipaddr)) {
8387 ANDROID_ERROR(("Invalid ip string %s\n", str));
8388 err = -EINVAL;
8389 goto exit;
8390 }
8391
8392 str = bcmstrtok(&pcmd, " ", NULL);
8393 if (!str || !bcm_ether_atoe(str, &ea)) {
8394 ANDROID_ERROR(("Invalid ethernet string %s\n", str));
8395 err = -EINVAL;
8396 goto exit;
8397 }
8398 bcopy(&dipaddr, &route_tbl->route_entry[i].ipv4_addr, IPV4_ADDR_LEN);
8399 bcopy(&ea, &route_tbl->route_entry[i].nexthop, ETHER_ADDR_LEN);
8400 }
8401
8402 route_tbl_len = sizeof(ibss_route_tbl_t) +
8403 ((!entries?0:(entries - 1)) * sizeof(ibss_route_entry_t));
8404 err = wldev_iovar_setbuf(dev, "ibss_route_tbl",
8405 route_tbl, route_tbl_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
8406 if (err != BCME_OK) {
8407 ANDROID_ERROR(("Fail to set iovar %d\n", err));
8408 err = -EINVAL;
8409 }
8410
8411 exit:
8412 if (route_tbl) {
8413 MFREE(cfg->osh, route_tbl, sizeof(ibss_route_tbl_t) +
8414 (MAX_IBSS_ROUTE_TBL_ENTRY - 1) * sizeof(ibss_route_entry_t));
8415 }
8416 if (ioctl_buf) {
8417 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
8418 }
8419 return err;
8420
8421 }
8422
8423 int
wl_android_set_ibss_ampdu(struct net_device * dev,char * command,int total_len)8424 wl_android_set_ibss_ampdu(struct net_device *dev, char *command, int total_len)
8425 {
8426 char *pcmd = command;
8427 char *str = NULL, *endptr = NULL;
8428 struct ampdu_aggr aggr;
8429 char smbuf[WLC_IOCTL_SMLEN];
8430 int idx;
8431 int err = 0;
8432 int wme_AC2PRIO[AC_COUNT][2] = {
8433 {PRIO_8021D_VO, PRIO_8021D_NC}, /* AC_VO - 3 */
8434 {PRIO_8021D_CL, PRIO_8021D_VI}, /* AC_VI - 2 */
8435 {PRIO_8021D_BK, PRIO_8021D_NONE}, /* AC_BK - 1 */
8436 {PRIO_8021D_BE, PRIO_8021D_EE}}; /* AC_BE - 0 */
8437
8438 ANDROID_INFO(("set ibss ampdu:%s\n", command));
8439
8440 bzero(&aggr, sizeof(aggr));
8441 /* Cofigure all priorities */
8442 aggr.conf_TID_bmap = NBITMASK(NUMPRIO);
8443
8444 /* acquire parameters */
8445 /* drop command */
8446 str = bcmstrtok(&pcmd, " ", NULL);
8447
8448 for (idx = 0; idx < AC_COUNT; idx++) {
8449 bool on;
8450 str = bcmstrtok(&pcmd, " ", NULL);
8451 if (!str) {
8452 ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
8453 return -EINVAL;
8454 }
8455 on = bcm_strtoul(str, &endptr, 0) ? TRUE : FALSE;
8456 if (*endptr != '\0') {
8457 ANDROID_ERROR(("Invalid number format %s\n", str));
8458 return -EINVAL;
8459 }
8460 if (on) {
8461 setbit(&aggr.enab_TID_bmap, wme_AC2PRIO[idx][0]);
8462 setbit(&aggr.enab_TID_bmap, wme_AC2PRIO[idx][1]);
8463 }
8464 }
8465
8466 err = wldev_iovar_setbuf(dev, "ampdu_txaggr", (void *)&aggr,
8467 sizeof(aggr), smbuf, WLC_IOCTL_SMLEN, NULL);
8468
8469 return ((err == 0) ? total_len : err);
8470 }
8471
wl_android_set_ibss_antenna(struct net_device * dev,char * command,int total_len)8472 int wl_android_set_ibss_antenna(struct net_device *dev, char *command, int total_len)
8473 {
8474 char *pcmd = command;
8475 char *str = NULL;
8476 int txchain, rxchain;
8477 int err = 0;
8478
8479 ANDROID_INFO(("set ibss antenna:%s\n", command));
8480
8481 /* acquire parameters */
8482 /* drop command */
8483 str = bcmstrtok(&pcmd, " ", NULL);
8484
8485 /* TX chain */
8486 str = bcmstrtok(&pcmd, " ", NULL);
8487 if (!str) {
8488 ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
8489 return -EINVAL;
8490 }
8491 txchain = bcm_atoi(str);
8492
8493 /* RX chain */
8494 str = bcmstrtok(&pcmd, " ", NULL);
8495 if (!str) {
8496 ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
8497 return -EINVAL;
8498 }
8499 rxchain = bcm_atoi(str);
8500
8501 err = wldev_iovar_setint(dev, "txchain", txchain);
8502 if (err != 0)
8503 return err;
8504 err = wldev_iovar_setint(dev, "rxchain", rxchain);
8505 return ((err == 0)?total_len:err);
8506 }
8507 #endif /* WLAIBSS */
8508
wl_keep_alive_set(struct net_device * dev,char * extra)8509 int wl_keep_alive_set(struct net_device *dev, char* extra)
8510 {
8511 wl_mkeep_alive_pkt_t mkeep_alive_pkt;
8512 int ret;
8513 uint period_msec = 0;
8514 char *buf;
8515 dhd_pub_t *dhd = dhd_get_pub(dev);
8516
8517 if (extra == NULL) {
8518 ANDROID_ERROR(("%s: extra is NULL\n", __FUNCTION__));
8519 return -1;
8520 }
8521 if (sscanf(extra, "%d", &period_msec) != 1) {
8522 ANDROID_ERROR(("%s: sscanf error. check period_msec value\n", __FUNCTION__));
8523 return -EINVAL;
8524 }
8525 ANDROID_ERROR(("%s: period_msec is %d\n", __FUNCTION__, period_msec));
8526
8527 bzero(&mkeep_alive_pkt, sizeof(wl_mkeep_alive_pkt_t));
8528
8529 mkeep_alive_pkt.period_msec = period_msec;
8530 mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
8531 mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
8532
8533 /* Setup keep alive zero for null packet generation */
8534 mkeep_alive_pkt.keep_alive_id = 0;
8535 mkeep_alive_pkt.len_bytes = 0;
8536
8537 buf = (char *)MALLOC(dhd->osh, WLC_IOCTL_SMLEN);
8538 if (!buf) {
8539 ANDROID_ERROR(("%s: buffer alloc failed\n", __FUNCTION__));
8540 return BCME_NOMEM;
8541 }
8542 ret = wldev_iovar_setbuf(dev, "mkeep_alive", (char *)&mkeep_alive_pkt,
8543 WL_MKEEP_ALIVE_FIXED_LEN, buf, WLC_IOCTL_SMLEN, NULL);
8544 if (ret < 0)
8545 ANDROID_ERROR(("%s:keep_alive set failed:%d\n", __FUNCTION__, ret));
8546 else
8547 ANDROID_TRACE(("%s:keep_alive set ok\n", __FUNCTION__));
8548 MFREE(dhd->osh, buf, WLC_IOCTL_SMLEN);
8549 return ret;
8550 }
8551
8552 #ifdef P2PRESP_WFDIE_SRC
wl_android_get_wfdie_resp(struct net_device * dev,char * command,int total_len)8553 static int wl_android_get_wfdie_resp(struct net_device *dev, char *command, int total_len)
8554 {
8555 int error = 0;
8556 int bytes_written = 0;
8557 int only_resp_wfdsrc = 0;
8558
8559 error = wldev_iovar_getint(dev, "p2p_only_resp_wfdsrc", &only_resp_wfdsrc);
8560 if (error) {
8561 ANDROID_ERROR(("%s: Failed to get the mode for only_resp_wfdsrc, error = %d\n",
8562 __FUNCTION__, error));
8563 return -1;
8564 }
8565
8566 bytes_written = snprintf(command, total_len, "%s %d",
8567 CMD_P2P_GET_WFDIE_RESP, only_resp_wfdsrc);
8568
8569 return bytes_written;
8570 }
8571
wl_android_set_wfdie_resp(struct net_device * dev,int only_resp_wfdsrc)8572 static int wl_android_set_wfdie_resp(struct net_device *dev, int only_resp_wfdsrc)
8573 {
8574 int error = 0;
8575
8576 error = wldev_iovar_setint(dev, "p2p_only_resp_wfdsrc", only_resp_wfdsrc);
8577 if (error) {
8578 ANDROID_ERROR(("%s: Failed to set only_resp_wfdsrc %d, error = %d\n",
8579 __FUNCTION__, only_resp_wfdsrc, error));
8580 return -1;
8581 }
8582
8583 return 0;
8584 }
8585 #endif /* P2PRESP_WFDIE_SRC */
8586
8587 #ifdef BT_WIFI_HANDOVER
8588 static int
wl_tbow_teardown(struct net_device * dev)8589 wl_tbow_teardown(struct net_device *dev)
8590 {
8591 int err = BCME_OK;
8592 char buf[WLC_IOCTL_SMLEN];
8593 tbow_setup_netinfo_t netinfo;
8594 bzero(&netinfo, sizeof(netinfo));
8595 netinfo.opmode = TBOW_HO_MODE_TEARDOWN;
8596
8597 err = wldev_iovar_setbuf_bsscfg(dev, "tbow_doho", &netinfo,
8598 sizeof(tbow_setup_netinfo_t), buf, WLC_IOCTL_SMLEN, 0, NULL);
8599 if (err < 0) {
8600 ANDROID_ERROR(("tbow_doho iovar error %d\n", err));
8601 return err;
8602 }
8603 return err;
8604 }
8605 #endif /* BT_WIFI_HANOVER */
8606
wl_android_get_link_status(struct net_device * dev,char * command,int total_len)8607 static int wl_android_get_link_status(struct net_device *dev, char *command,
8608 int total_len)
8609 {
8610 int bytes_written, error, result = 0, single_stream, stf = -1, i, nss = 0, mcs_map;
8611 uint32 rspec;
8612 uint encode, txexp;
8613 wl_bss_info_t *bi;
8614 int datalen = sizeof(uint32) + sizeof(wl_bss_info_t);
8615 char buf[WLC_IOCTL_SMLEN];
8616
8617 if (datalen > WLC_IOCTL_SMLEN) {
8618 ANDROID_ERROR(("data too big\n"));
8619 return -1;
8620 }
8621
8622 bzero(buf, datalen);
8623 /* get BSS information */
8624 *(u32 *) buf = htod32(datalen);
8625 error = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, (void *)buf, datalen);
8626 if (unlikely(error)) {
8627 ANDROID_ERROR(("Could not get bss info %d\n", error));
8628 return -1;
8629 }
8630
8631 bi = (wl_bss_info_t*) (buf + sizeof(uint32));
8632
8633 for (i = 0; i < ETHER_ADDR_LEN; i++) {
8634 if (bi->BSSID.octet[i] > 0) {
8635 break;
8636 }
8637 }
8638
8639 if (i == ETHER_ADDR_LEN) {
8640 ANDROID_INFO(("No BSSID\n"));
8641 return -1;
8642 }
8643
8644 /* check VHT capability at beacon */
8645 if (bi->vht_cap) {
8646 if (CHSPEC_IS5G(bi->chanspec)) {
8647 result |= WL_ANDROID_LINK_AP_VHT_SUPPORT;
8648 }
8649 }
8650
8651 /* get a rspec (radio spectrum) rate */
8652 error = wldev_iovar_getint(dev, "nrate", &rspec);
8653 if (unlikely(error) || rspec == 0) {
8654 ANDROID_ERROR(("get link status error (%d)\n", error));
8655 return -1;
8656 }
8657
8658 /* referred wl_nrate_print() for the calculation */
8659 encode = (rspec & WL_RSPEC_ENCODING_MASK);
8660 txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
8661
8662 switch (encode) {
8663 case WL_RSPEC_ENCODE_HT:
8664 /* check Rx MCS Map for HT */
8665 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
8666 int8 bitmap = 0xFF;
8667 if (i == MAX_STREAMS_SUPPORTED-1) {
8668 bitmap = 0x7F;
8669 }
8670 if (bi->basic_mcs[i] & bitmap) {
8671 nss++;
8672 }
8673 }
8674 break;
8675 case WL_RSPEC_ENCODE_VHT:
8676 /* check Rx MCS Map for VHT */
8677 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
8678 mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
8679 if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
8680 nss++;
8681 }
8682 }
8683 break;
8684 }
8685
8686 /* check MIMO capability with nss in beacon */
8687 if (nss > 1) {
8688 result |= WL_ANDROID_LINK_AP_MIMO_SUPPORT;
8689 }
8690
8691 /* Legacy rates WL_RSPEC_ENCODE_RATE are single stream, and
8692 * HT rates for mcs 0-7 are single stream.
8693 * In case of VHT NSS comes from rspec.
8694 */
8695 single_stream = (encode == WL_RSPEC_ENCODE_RATE) ||
8696 ((encode == WL_RSPEC_ENCODE_HT) && (rspec & WL_RSPEC_HT_MCS_MASK) < 8) ||
8697 ((encode == WL_RSPEC_ENCODE_VHT) &&
8698 ((rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT) == 1);
8699
8700 if (txexp == 0) {
8701 if ((rspec & WL_RSPEC_STBC) && single_stream) {
8702 stf = OLD_NRATE_STF_STBC;
8703 } else {
8704 stf = (single_stream) ? OLD_NRATE_STF_SISO : OLD_NRATE_STF_SDM;
8705 }
8706 } else if (txexp == 1 && single_stream) {
8707 stf = OLD_NRATE_STF_CDD;
8708 }
8709
8710 /* check 11ac (VHT) */
8711 if (encode == WL_RSPEC_ENCODE_VHT) {
8712 if (CHSPEC_IS5G(bi->chanspec)) {
8713 result |= WL_ANDROID_LINK_VHT;
8714 }
8715 }
8716
8717 /* check MIMO */
8718 if (result & WL_ANDROID_LINK_AP_MIMO_SUPPORT) {
8719 switch (stf) {
8720 case OLD_NRATE_STF_SISO:
8721 break;
8722 case OLD_NRATE_STF_CDD:
8723 case OLD_NRATE_STF_STBC:
8724 result |= WL_ANDROID_LINK_MIMO;
8725 break;
8726 case OLD_NRATE_STF_SDM:
8727 if (!single_stream) {
8728 result |= WL_ANDROID_LINK_MIMO;
8729 }
8730 break;
8731 }
8732 }
8733
8734 ANDROID_INFO(("%s:result=%d, stf=%d, single_stream=%d, mcs map=%d\n",
8735 __FUNCTION__, result, stf, single_stream, nss));
8736
8737 bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_LINK_STATUS, result);
8738
8739 return bytes_written;
8740 }
8741
8742 #ifdef P2P_LISTEN_OFFLOADING
8743
8744 s32
wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 * cfg)8745 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
8746 {
8747 s32 bssidx;
8748 int ret = 0;
8749 int p2plo_pause = 0;
8750 dhd_pub_t *dhd = NULL;
8751 if (!cfg || !cfg->p2p) {
8752 ANDROID_ERROR(("Wl %p or cfg->p2p %p is null\n",
8753 cfg, cfg ? cfg->p2p : 0));
8754 return 0;
8755 }
8756
8757 dhd = (dhd_pub_t *)(cfg->pub);
8758 if (!dhd->up) {
8759 ANDROID_ERROR(("bus is already down\n"));
8760 return ret;
8761 }
8762
8763 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
8764 ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
8765 "p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
8766 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
8767 if (ret < 0) {
8768 ANDROID_ERROR(("p2po_stop Failed :%d\n", ret));
8769 }
8770
8771 return ret;
8772 }
8773 s32
wl_cfg80211_p2plo_listen_start(struct net_device * dev,u8 * buf,int len)8774 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len)
8775 {
8776 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8777 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
8778 wl_p2plo_listen_t p2plo_listen;
8779 int ret = -EAGAIN;
8780 int channel = 0;
8781 int period = 0;
8782 int interval = 0;
8783 int count = 0;
8784 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
8785 ANDROID_ERROR(("Sending Action Frames. Try it again.\n"));
8786 goto exit;
8787 }
8788
8789 if (wl_get_drv_status_all(cfg, SCANNING)) {
8790 ANDROID_ERROR(("Scanning already\n"));
8791 goto exit;
8792 }
8793
8794 if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
8795 ANDROID_ERROR(("Scanning being aborted\n"));
8796 goto exit;
8797 }
8798
8799 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
8800 ANDROID_ERROR(("p2p listen offloading already running\n"));
8801 goto exit;
8802 }
8803
8804 /* Just in case if it is not enabled */
8805 if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
8806 ANDROID_ERROR(("cfgp2p_enable discovery failed"));
8807 goto exit;
8808 }
8809
8810 bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
8811
8812 if (len) {
8813 sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
8814 if ((channel == 0) || (period == 0) ||
8815 (interval == 0) || (count == 0)) {
8816 ANDROID_ERROR(("Wrong argument %d/%d/%d/%d \n",
8817 channel, period, interval, count));
8818 ret = -EAGAIN;
8819 goto exit;
8820 }
8821 p2plo_listen.period = period;
8822 p2plo_listen.interval = interval;
8823 p2plo_listen.count = count;
8824
8825 ANDROID_ERROR(("channel:%d period:%d, interval:%d count:%d\n",
8826 channel, period, interval, count));
8827 } else {
8828 ANDROID_ERROR(("Argument len is wrong.\n"));
8829 ret = -EAGAIN;
8830 goto exit;
8831 }
8832
8833 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
8834 sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
8835 bssidx, &cfg->ioctl_buf_sync)) < 0) {
8836 ANDROID_ERROR(("p2po_listen_channel Failed :%d\n", ret));
8837 goto exit;
8838 }
8839
8840 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
8841 sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
8842 bssidx, &cfg->ioctl_buf_sync)) < 0) {
8843 ANDROID_ERROR(("p2po_listen Failed :%d\n", ret));
8844 goto exit;
8845 }
8846
8847 wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
8848 exit :
8849 return ret;
8850 }
8851 s32
wl_cfg80211_p2plo_listen_stop(struct net_device * dev)8852 wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
8853 {
8854 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8855 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
8856 int ret = -EAGAIN;
8857
8858 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
8859 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
8860 bssidx, &cfg->ioctl_buf_sync)) < 0) {
8861 ANDROID_ERROR(("p2po_stop Failed :%d\n", ret));
8862 goto exit;
8863 }
8864
8865 exit:
8866 return ret;
8867 }
8868
8869 s32
wl_cfg80211_p2plo_offload(struct net_device * dev,char * cmd,char * buf,int len)8870 wl_cfg80211_p2plo_offload(struct net_device *dev, char *cmd, char* buf, int len)
8871 {
8872 int ret = 0;
8873
8874 ANDROID_ERROR(("Entry cmd:%s arg_len:%d \n", cmd, len));
8875
8876 if (strncmp(cmd, "P2P_LO_START", strlen("P2P_LO_START")) == 0) {
8877 ret = wl_cfg80211_p2plo_listen_start(dev, buf, len);
8878 } else if (strncmp(cmd, "P2P_LO_STOP", strlen("P2P_LO_STOP")) == 0) {
8879 ret = wl_cfg80211_p2plo_listen_stop(dev);
8880 } else {
8881 ANDROID_ERROR(("Request for Unsupported CMD:%s \n", buf));
8882 ret = -EINVAL;
8883 }
8884 return ret;
8885 }
8886 void
wl_cfg80211_cancel_p2plo(struct bcm_cfg80211 * cfg)8887 wl_cfg80211_cancel_p2plo(struct bcm_cfg80211 *cfg)
8888 {
8889 struct wireless_dev *wdev;
8890 if (!cfg) {
8891 return;
8892 }
8893
8894 wdev = bcmcfg_to_p2p_wdev(cfg);
8895
8896 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
8897 ANDROID_INFO(("P2P_FIND: Discovery offload is already in progress."
8898 "it aborted\n"));
8899 wl_clr_p2p_status(cfg, DISC_IN_PROGRESS);
8900 if (wdev != NULL) {
8901 #if defined(WL_CFG80211_P2P_DEV_IF)
8902 cfg80211_remain_on_channel_expired(wdev,
8903 cfg->last_roc_id,
8904 &cfg->remain_on_chan, GFP_KERNEL);
8905 #else
8906 cfg80211_remain_on_channel_expired(wdev,
8907 cfg->last_roc_id,
8908 &cfg->remain_on_chan,
8909 cfg->remain_on_chan_type, GFP_KERNEL);
8910 #endif /* WL_CFG80211_P2P_DEV_IF */
8911 }
8912 wl_cfg80211_p2plo_deinit(cfg);
8913 }
8914 }
8915 #endif /* P2P_LISTEN_OFFLOADING */
8916
8917 #ifdef WL_MURX
8918 int
wl_android_murx_bfe_cap(struct net_device * dev,int val)8919 wl_android_murx_bfe_cap(struct net_device *dev, int val)
8920 {
8921 int err = BCME_OK;
8922 int iface_count = wl_cfg80211_iface_count(dev);
8923 struct ether_addr bssid;
8924 wl_reassoc_params_t params;
8925
8926 if (iface_count > 1) {
8927 ANDROID_ERROR(("murx_bfe_cap change is not allowed when "
8928 "there are multiple interfaces\n"));
8929 return -EINVAL;
8930 }
8931 /* Now there is only single interface */
8932 err = wldev_iovar_setint(dev, "murx_bfe_cap", val);
8933 if (unlikely(err)) {
8934 ANDROID_ERROR(("Failed to set murx_bfe_cap IOVAR to %d,"
8935 "error %d\n", val, err));
8936 return err;
8937 }
8938
8939 /* If successful intiate a reassoc */
8940 bzero(&bssid, ETHER_ADDR_LEN);
8941 if ((err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN)) < 0) {
8942 ANDROID_ERROR(("Failed to get bssid, error=%d\n", err));
8943 return err;
8944 }
8945
8946 bzero(¶ms, sizeof(wl_reassoc_params_t));
8947 memcpy(¶ms.bssid, &bssid, ETHER_ADDR_LEN);
8948
8949 if ((err = wldev_ioctl_set(dev, WLC_REASSOC, ¶ms,
8950 sizeof(wl_reassoc_params_t))) < 0) {
8951 ANDROID_ERROR(("reassoc failed err:%d \n", err));
8952 } else {
8953 ANDROID_INFO(("reassoc issued successfully\n"));
8954 }
8955
8956 return err;
8957 }
8958 #endif /* WL_MURX */
8959
8960 #ifdef SUPPORT_RSSI_SUM_REPORT
8961 int
wl_android_get_rssi_per_ant(struct net_device * dev,char * command,int total_len)8962 wl_android_get_rssi_per_ant(struct net_device *dev, char *command, int total_len)
8963 {
8964 wl_rssi_ant_mimo_t rssi_ant_mimo;
8965 char *ifname = NULL;
8966 char *peer_mac = NULL;
8967 char *mimo_cmd = "mimo";
8968 char *pos, *token;
8969 int err = BCME_OK;
8970 int bytes_written = 0;
8971 bool mimo_rssi = FALSE;
8972
8973 bzero(&rssi_ant_mimo, sizeof(wl_rssi_ant_mimo_t));
8974 /*
8975 * STA I/F: DRIVER GET_RSSI_PER_ANT <ifname> <mimo>
8976 * AP/GO I/F: DRIVER GET_RSSI_PER_ANT <ifname> <Peer MAC addr> <mimo>
8977 */
8978 pos = command;
8979
8980 /* drop command */
8981 token = bcmstrtok(&pos, " ", NULL);
8982
8983 /* get the interface name */
8984 token = bcmstrtok(&pos, " ", NULL);
8985 if (!token) {
8986 ANDROID_ERROR(("Invalid arguments\n"));
8987 return -EINVAL;
8988 }
8989 ifname = token;
8990
8991 /* Optional: Check the MIMO RSSI mode or peer MAC address */
8992 token = bcmstrtok(&pos, " ", NULL);
8993 if (token) {
8994 /* Check the MIMO RSSI mode */
8995 if (strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) {
8996 mimo_rssi = TRUE;
8997 } else {
8998 peer_mac = token;
8999 }
9000 }
9001
9002 /* Optional: Check the MIMO RSSI mode - RSSI sum across antennas */
9003 token = bcmstrtok(&pos, " ", NULL);
9004 if (token && strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) {
9005 mimo_rssi = TRUE;
9006 }
9007
9008 err = wl_get_rssi_per_ant(dev, ifname, peer_mac, &rssi_ant_mimo);
9009 if (unlikely(err)) {
9010 ANDROID_ERROR(("Failed to get RSSI info, err=%d\n", err));
9011 return err;
9012 }
9013
9014 /* Parse the results */
9015 ANDROID_INFO(("ifname %s, version %d, count %d, mimo rssi %d\n",
9016 ifname, rssi_ant_mimo.version, rssi_ant_mimo.count, mimo_rssi));
9017 if (mimo_rssi) {
9018 ANDROID_INFO(("MIMO RSSI: %d\n", rssi_ant_mimo.rssi_sum));
9019 bytes_written = snprintf(command, total_len, "%s MIMO %d",
9020 CMD_GET_RSSI_PER_ANT, rssi_ant_mimo.rssi_sum);
9021 } else {
9022 int cnt;
9023 bytes_written = snprintf(command, total_len, "%s PER_ANT ", CMD_GET_RSSI_PER_ANT);
9024 for (cnt = 0; cnt < rssi_ant_mimo.count; cnt++) {
9025 ANDROID_INFO(("RSSI[%d]: %d\n", cnt, rssi_ant_mimo.rssi_ant[cnt]));
9026 bytes_written = snprintf(command, total_len, "%d ",
9027 rssi_ant_mimo.rssi_ant[cnt]);
9028 }
9029 }
9030
9031 return bytes_written;
9032 }
9033
9034 int
wl_android_set_rssi_logging(struct net_device * dev,char * command,int total_len)9035 wl_android_set_rssi_logging(struct net_device *dev, char *command, int total_len)
9036 {
9037 rssilog_set_param_t set_param;
9038 char *pos, *token;
9039 int err = BCME_OK;
9040
9041 bzero(&set_param, sizeof(rssilog_set_param_t));
9042 /*
9043 * DRIVER SET_RSSI_LOGGING <enable/disable> <RSSI Threshold> <Time Threshold>
9044 */
9045 pos = command;
9046
9047 /* drop command */
9048 token = bcmstrtok(&pos, " ", NULL);
9049
9050 /* enable/disable */
9051 token = bcmstrtok(&pos, " ", NULL);
9052 if (!token) {
9053 ANDROID_ERROR(("Invalid arguments\n"));
9054 return -EINVAL;
9055 }
9056 set_param.enable = bcm_atoi(token);
9057
9058 /* RSSI Threshold */
9059 token = bcmstrtok(&pos, " ", NULL);
9060 if (!token) {
9061 ANDROID_ERROR(("Invalid arguments\n"));
9062 return -EINVAL;
9063 }
9064 set_param.rssi_threshold = bcm_atoi(token);
9065
9066 /* Time Threshold */
9067 token = bcmstrtok(&pos, " ", NULL);
9068 if (!token) {
9069 ANDROID_ERROR(("Invalid arguments\n"));
9070 return -EINVAL;
9071 }
9072 set_param.time_threshold = bcm_atoi(token);
9073
9074 ANDROID_INFO(("enable %d, RSSI threshold %d, Time threshold %d\n", set_param.enable,
9075 set_param.rssi_threshold, set_param.time_threshold));
9076
9077 err = wl_set_rssi_logging(dev, (void *)&set_param);
9078 if (unlikely(err)) {
9079 ANDROID_ERROR(("Failed to configure RSSI logging: enable %d, RSSI Threshold %d,"
9080 " Time Threshold %d\n", set_param.enable, set_param.rssi_threshold,
9081 set_param.time_threshold));
9082 }
9083
9084 return err;
9085 }
9086
9087 int
wl_android_get_rssi_logging(struct net_device * dev,char * command,int total_len)9088 wl_android_get_rssi_logging(struct net_device *dev, char *command, int total_len)
9089 {
9090 rssilog_get_param_t get_param;
9091 int err = BCME_OK;
9092 int bytes_written = 0;
9093
9094 err = wl_get_rssi_logging(dev, (void *)&get_param);
9095 if (unlikely(err)) {
9096 ANDROID_ERROR(("Failed to get RSSI logging info\n"));
9097 return BCME_ERROR;
9098 }
9099
9100 ANDROID_INFO(("report_count %d, enable %d, rssi_threshold %d, time_threshold %d\n",
9101 get_param.report_count, get_param.enable, get_param.rssi_threshold,
9102 get_param.time_threshold));
9103
9104 /* Parse the parameter */
9105 if (!get_param.enable) {
9106 ANDROID_INFO(("RSSI LOGGING: Feature is disables\n"));
9107 bytes_written = snprintf(command, total_len,
9108 "%s FEATURE DISABLED\n", CMD_GET_RSSI_LOGGING);
9109 } else if (get_param.enable &
9110 (RSSILOG_FLAG_FEATURE_SW | RSSILOG_FLAG_REPORT_READY)) {
9111 if (!get_param.report_count) {
9112 ANDROID_INFO(("[PASS] RSSI difference across antennas is within"
9113 " threshold limits\n"));
9114 bytes_written = snprintf(command, total_len, "%s PASS\n",
9115 CMD_GET_RSSI_LOGGING);
9116 } else {
9117 ANDROID_INFO(("[FAIL] RSSI difference across antennas found "
9118 "to be greater than %3d dB\n", get_param.rssi_threshold));
9119 ANDROID_INFO(("[FAIL] RSSI difference check have failed for "
9120 "%d out of %d times\n", get_param.report_count,
9121 get_param.time_threshold));
9122 ANDROID_INFO(("[FAIL] RSSI difference is being monitored once "
9123 "per second, for a %d secs window\n", get_param.time_threshold));
9124 bytes_written = snprintf(command, total_len, "%s FAIL - RSSI Threshold "
9125 "%d dBm for %d out of %d times\n", CMD_GET_RSSI_LOGGING,
9126 get_param.rssi_threshold, get_param.report_count,
9127 get_param.time_threshold);
9128 }
9129 } else {
9130 ANDROID_INFO(("[BUSY] Reprot is not ready\n"));
9131 bytes_written = snprintf(command, total_len, "%s BUSY - NOT READY\n",
9132 CMD_GET_RSSI_LOGGING);
9133 }
9134
9135 return bytes_written;
9136 }
9137 #endif /* SUPPORT_RSSI_SUM_REPORT */
9138
9139 #ifdef SET_PCIE_IRQ_CPU_CORE
9140 void
wl_android_set_irq_cpucore(struct net_device * net,int affinity_cmd)9141 wl_android_set_irq_cpucore(struct net_device *net, int affinity_cmd)
9142 {
9143 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(net);
9144 if (!dhdp) {
9145 ANDROID_ERROR(("dhd is NULL\n"));
9146 return;
9147 }
9148
9149 dhd_set_irq_cpucore(dhdp, affinity_cmd);
9150 }
9151 #endif /* SET_PCIE_IRQ_CPU_CORE */
9152
9153 #ifdef SUPPORT_LQCM
9154 static int
wl_android_lqcm_enable(struct net_device * net,int lqcm_enable)9155 wl_android_lqcm_enable(struct net_device *net, int lqcm_enable)
9156 {
9157 int err = 0;
9158
9159 err = wldev_iovar_setint(net, "lqcm", lqcm_enable);
9160 if (err != BCME_OK) {
9161 ANDROID_ERROR(("failed to set lqcm enable %d, error = %d\n", lqcm_enable, err));
9162 return -EIO;
9163 }
9164 return err;
9165 }
9166
9167 static int
wl_android_get_lqcm_report(struct net_device * dev,char * command,int total_len)9168 wl_android_get_lqcm_report(struct net_device *dev, char *command, int total_len)
9169 {
9170 int bytes_written, err = 0;
9171 uint32 lqcm_report = 0;
9172 uint32 lqcm_enable, tx_lqcm_idx, rx_lqcm_idx;
9173
9174 err = wldev_iovar_getint(dev, "lqcm", &lqcm_report);
9175 if (err != BCME_OK) {
9176 ANDROID_ERROR(("failed to get lqcm report, error = %d\n", err));
9177 return -EIO;
9178 }
9179 lqcm_enable = lqcm_report & LQCM_ENAB_MASK;
9180 tx_lqcm_idx = (lqcm_report & LQCM_TX_INDEX_MASK) >> LQCM_TX_INDEX_SHIFT;
9181 rx_lqcm_idx = (lqcm_report & LQCM_RX_INDEX_MASK) >> LQCM_RX_INDEX_SHIFT;
9182
9183 ANDROID_INFO(("lqcm report EN:%d, TX:%d, RX:%d\n", lqcm_enable, tx_lqcm_idx, rx_lqcm_idx));
9184
9185 bytes_written = snprintf(command, total_len, "%s %d",
9186 CMD_GET_LQCM_REPORT, lqcm_report);
9187
9188 return bytes_written;
9189 }
9190 #endif /* SUPPORT_LQCM */
9191
9192 int
wl_android_get_snr(struct net_device * dev,char * command,int total_len)9193 wl_android_get_snr(struct net_device *dev, char *command, int total_len)
9194 {
9195 int bytes_written, error = 0;
9196 s32 snr = 0;
9197
9198 error = wldev_iovar_getint(dev, "snr", &snr);
9199 if (error) {
9200 ANDROID_ERROR(("%s: Failed to get SNR %d, error = %d\n",
9201 __FUNCTION__, snr, error));
9202 return -EIO;
9203 }
9204
9205 bytes_written = snprintf(command, total_len, "snr %d", snr);
9206 ANDROID_INFO(("%s: command result is %s\n", __FUNCTION__, command));
9207 return bytes_written;
9208 }
9209
9210 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
9211 int
wl_android_set_ap_beaconrate(struct net_device * dev,char * command)9212 wl_android_set_ap_beaconrate(struct net_device *dev, char *command)
9213 {
9214 int rate = 0;
9215 char *pos, *token;
9216 char *ifname = NULL;
9217 int err = BCME_OK;
9218
9219 /*
9220 * DRIVER SET_AP_BEACONRATE <rate> <ifname>
9221 */
9222 pos = command;
9223
9224 /* drop command */
9225 token = bcmstrtok(&pos, " ", NULL);
9226
9227 /* Rate */
9228 token = bcmstrtok(&pos, " ", NULL);
9229 if (!token)
9230 return -EINVAL;
9231 rate = bcm_atoi(token);
9232
9233 /* get the interface name */
9234 token = bcmstrtok(&pos, " ", NULL);
9235 if (!token)
9236 return -EINVAL;
9237 ifname = token;
9238
9239 ANDROID_INFO(("rate %d, ifacename %s\n", rate, ifname));
9240
9241 err = wl_set_ap_beacon_rate(dev, rate, ifname);
9242 if (unlikely(err)) {
9243 ANDROID_ERROR(("Failed to set ap beacon rate to %d, error = %d\n", rate, err));
9244 }
9245
9246 return err;
9247 }
9248
wl_android_get_ap_basicrate(struct net_device * dev,char * command,int total_len)9249 int wl_android_get_ap_basicrate(struct net_device *dev, char *command, int total_len)
9250 {
9251 char *pos, *token;
9252 char *ifname = NULL;
9253 int bytes_written = 0;
9254 /*
9255 * DRIVER GET_AP_BASICRATE <ifname>
9256 */
9257 pos = command;
9258
9259 /* drop command */
9260 token = bcmstrtok(&pos, " ", NULL);
9261
9262 /* get the interface name */
9263 token = bcmstrtok(&pos, " ", NULL);
9264 if (!token)
9265 return -EINVAL;
9266 ifname = token;
9267
9268 ANDROID_INFO(("ifacename %s\n", ifname));
9269
9270 bytes_written = wl_get_ap_basic_rate(dev, command, ifname, total_len);
9271 if (bytes_written < 1) {
9272 ANDROID_ERROR(("Failed to get ap basic rate, error = %d\n", bytes_written));
9273 return -EPROTO;
9274 }
9275
9276 return bytes_written;
9277 }
9278 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
9279
9280 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9281 int
wl_android_get_ap_rps(struct net_device * dev,char * command,int total_len)9282 wl_android_get_ap_rps(struct net_device *dev, char *command, int total_len)
9283 {
9284 char *pos, *token;
9285 char *ifname = NULL;
9286 int bytes_written = 0;
9287 char name[IFNAMSIZ];
9288 /*
9289 * DRIVER GET_AP_RPS <ifname>
9290 */
9291 pos = command;
9292
9293 /* drop command */
9294 token = bcmstrtok(&pos, " ", NULL);
9295
9296 /* get the interface name */
9297 token = bcmstrtok(&pos, " ", NULL);
9298 if (!token)
9299 return -EINVAL;
9300 ifname = token;
9301
9302 strlcpy(name, ifname, sizeof(name));
9303 ANDROID_INFO(("ifacename %s\n", name));
9304
9305 bytes_written = wl_get_ap_rps(dev, command, name, total_len);
9306 if (bytes_written < 1) {
9307 ANDROID_ERROR(("Failed to get rps, error = %d\n", bytes_written));
9308 return -EPROTO;
9309 }
9310
9311 return bytes_written;
9312
9313 }
9314
9315 int
wl_android_set_ap_rps(struct net_device * dev,char * command,int total_len)9316 wl_android_set_ap_rps(struct net_device *dev, char *command, int total_len)
9317 {
9318 int enable = 0;
9319 char *pos, *token;
9320 char *ifname = NULL;
9321 int err = BCME_OK;
9322 char name[IFNAMSIZ];
9323
9324 /*
9325 * DRIVER SET_AP_RPS <0/1> <ifname>
9326 */
9327 pos = command;
9328
9329 /* drop command */
9330 token = bcmstrtok(&pos, " ", NULL);
9331
9332 /* Enable */
9333 token = bcmstrtok(&pos, " ", NULL);
9334 if (!token)
9335 return -EINVAL;
9336 enable = bcm_atoi(token);
9337
9338 /* get the interface name */
9339 token = bcmstrtok(&pos, " ", NULL);
9340 if (!token)
9341 return -EINVAL;
9342 ifname = token;
9343
9344 strlcpy(name, ifname, sizeof(name));
9345 ANDROID_INFO(("enable %d, ifacename %s\n", enable, name));
9346
9347 err = wl_set_ap_rps(dev, enable? TRUE: FALSE, name);
9348 if (unlikely(err)) {
9349 ANDROID_ERROR(("Failed to set rps, enable %d, error = %d\n", enable, err));
9350 }
9351
9352 return err;
9353 }
9354
9355 int
wl_android_set_ap_rps_params(struct net_device * dev,char * command,int total_len)9356 wl_android_set_ap_rps_params(struct net_device *dev, char *command, int total_len)
9357 {
9358 ap_rps_info_t rps;
9359 char *pos, *token;
9360 char *ifname = NULL;
9361 int err = BCME_OK;
9362 char name[IFNAMSIZ];
9363
9364 bzero(&rps, sizeof(rps));
9365 /*
9366 * DRIVER SET_AP_RPS_PARAMS <pps> <level> <quiettime> <assoccheck> <ifname>
9367 */
9368 pos = command;
9369
9370 /* drop command */
9371 token = bcmstrtok(&pos, " ", NULL);
9372
9373 /* pps */
9374 token = bcmstrtok(&pos, " ", NULL);
9375 if (!token)
9376 return -EINVAL;
9377 rps.pps = bcm_atoi(token);
9378
9379 /* level */
9380 token = bcmstrtok(&pos, " ", NULL);
9381 if (!token)
9382 return -EINVAL;
9383 rps.level = bcm_atoi(token);
9384
9385 /* quiettime */
9386 token = bcmstrtok(&pos, " ", NULL);
9387 if (!token)
9388 return -EINVAL;
9389 rps.quiet_time = bcm_atoi(token);
9390
9391 /* sta assoc check */
9392 token = bcmstrtok(&pos, " ", NULL);
9393 if (!token)
9394 return -EINVAL;
9395 rps.sta_assoc_check = bcm_atoi(token);
9396
9397 /* get the interface name */
9398 token = bcmstrtok(&pos, " ", NULL);
9399 if (!token)
9400 return -EINVAL;
9401 ifname = token;
9402 strlcpy(name, ifname, sizeof(name));
9403
9404 ANDROID_INFO(("pps %d, level %d, quiettime %d, sta_assoc_check %d, "
9405 "ifacename %s\n", rps.pps, rps.level, rps.quiet_time,
9406 rps.sta_assoc_check, name));
9407
9408 err = wl_update_ap_rps_params(dev, &rps, name);
9409 if (unlikely(err)) {
9410 ANDROID_ERROR(("Failed to update rps, pps %d, level %d, quiettime %d, "
9411 "sta_assoc_check %d, err = %d\n", rps.pps, rps.level, rps.quiet_time,
9412 rps.sta_assoc_check, err));
9413 }
9414
9415 return err;
9416 }
9417 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9418
9419 #if defined(DHD_HANG_SEND_UP_TEST)
9420 void
wl_android_make_hang_with_reason(struct net_device * dev,const char * string_num)9421 wl_android_make_hang_with_reason(struct net_device *dev, const char *string_num)
9422 {
9423 dhd_make_hang_with_reason(dev, string_num);
9424 }
9425 #endif /* DHD_HANG_SEND_UP_TEST */
9426
9427 #ifdef DHD_SEND_HANG_PRIVCMD_ERRORS
9428 static void
wl_android_check_priv_cmd_errors(struct net_device * dev)9429 wl_android_check_priv_cmd_errors(struct net_device *dev)
9430 {
9431 dhd_pub_t *dhdp;
9432 int memdump_mode;
9433
9434 if (!dev) {
9435 ANDROID_ERROR(("dev is NULL\n"));
9436 return;
9437 }
9438
9439 dhdp = wl_cfg80211_get_dhdp(dev);
9440 if (!dhdp) {
9441 ANDROID_ERROR(("dhdp is NULL\n"));
9442 return;
9443 }
9444
9445 #ifdef DHD_FW_COREDUMP
9446 memdump_mode = dhdp->memdump_enabled;
9447 #else
9448 /* Default enable if DHD doesn't support SOCRAM dump */
9449 memdump_mode = 1;
9450 #endif /* DHD_FW_COREDUMP */
9451
9452 if (report_hang_privcmd_err) {
9453 priv_cmd_errors++;
9454 } else {
9455 priv_cmd_errors = 0;
9456 }
9457
9458 /* Trigger HANG event only if memdump mode is enabled
9459 * due to customer's request
9460 */
9461 if (memdump_mode == DUMP_MEMFILE_BUGON &&
9462 (priv_cmd_errors > NUMBER_SEQUENTIAL_PRIVCMD_ERRORS)) {
9463 ANDROID_ERROR(("Send HANG event due to sequential private cmd errors\n"));
9464 priv_cmd_errors = 0;
9465 #ifdef DHD_FW_COREDUMP
9466 /* Take a SOCRAM dump */
9467 dhdp->memdump_type = DUMP_TYPE_SEQUENTIAL_PRIVCMD_ERROR;
9468 dhd_common_socram_dump(dhdp);
9469 #endif /* DHD_FW_COREDUMP */
9470 /* Send the HANG event to upper layer */
9471 dhdp->hang_reason = HANG_REASON_SEQUENTIAL_PRIVCMD_ERROR;
9472 dhd_os_check_hang(dhdp, 0, -EREMOTEIO);
9473 }
9474 }
9475 #endif /* DHD_SEND_HANG_PRIVCMD_ERRORS */
9476
9477 #ifdef DHD_PKT_LOGGING
9478 static int
wl_android_pktlog_filter_enable(struct net_device * dev,char * command,int total_len)9479 wl_android_pktlog_filter_enable(struct net_device *dev, char *command, int total_len)
9480 {
9481 int bytes_written = 0;
9482 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9483 dhd_pktlog_filter_t *filter;
9484 int err = BCME_OK;
9485
9486 if (!dhdp || !dhdp->pktlog) {
9487 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9488 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9489 return -EINVAL;
9490 }
9491
9492 filter = dhdp->pktlog->pktlog_filter;
9493
9494 err = dhd_pktlog_filter_enable(filter, PKTLOG_TXPKT_CASE, TRUE);
9495 err = dhd_pktlog_filter_enable(filter, PKTLOG_TXSTATUS_CASE, TRUE);
9496 err = dhd_pktlog_filter_enable(filter, PKTLOG_RXPKT_CASE, TRUE);
9497
9498 if (err == BCME_OK) {
9499 bytes_written = snprintf(command, total_len, "OK");
9500 ANDROID_ERROR(("%s: pktlog filter enable success\n", __FUNCTION__));
9501 } else {
9502 ANDROID_ERROR(("%s: pktlog filter enable fail\n", __FUNCTION__));
9503 return BCME_ERROR;
9504 }
9505
9506 return bytes_written;
9507 }
9508
9509 static int
wl_android_pktlog_filter_disable(struct net_device * dev,char * command,int total_len)9510 wl_android_pktlog_filter_disable(struct net_device *dev, char *command, int total_len)
9511 {
9512 int bytes_written = 0;
9513 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9514 dhd_pktlog_filter_t *filter;
9515 int err = BCME_OK;
9516
9517 if (!dhdp || !dhdp->pktlog) {
9518 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9519 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9520 return -EINVAL;
9521 }
9522
9523 filter = dhdp->pktlog->pktlog_filter;
9524
9525 err = dhd_pktlog_filter_enable(filter, PKTLOG_TXPKT_CASE, FALSE);
9526 err = dhd_pktlog_filter_enable(filter, PKTLOG_TXSTATUS_CASE, FALSE);
9527 err = dhd_pktlog_filter_enable(filter, PKTLOG_RXPKT_CASE, FALSE);
9528
9529 if (err == BCME_OK) {
9530 bytes_written = snprintf(command, total_len, "OK");
9531 ANDROID_ERROR(("%s: pktlog filter disable success\n", __FUNCTION__));
9532 } else {
9533 ANDROID_ERROR(("%s: pktlog filter disable fail\n", __FUNCTION__));
9534 return BCME_ERROR;
9535 }
9536
9537 return bytes_written;
9538 }
9539
9540 static int
wl_android_pktlog_filter_pattern_enable(struct net_device * dev,char * command,int total_len)9541 wl_android_pktlog_filter_pattern_enable(struct net_device *dev, char *command, int total_len)
9542 {
9543 int bytes_written = 0;
9544 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9545 dhd_pktlog_filter_t *filter;
9546 int err = BCME_OK;
9547
9548 if (!dhdp || !dhdp->pktlog) {
9549 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9550 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9551 return -EINVAL;
9552 }
9553
9554 filter = dhdp->pktlog->pktlog_filter;
9555
9556 if (strlen(CMD_PKTLOG_FILTER_PATTERN_ENABLE) + 1 > total_len) {
9557 return BCME_ERROR;
9558 }
9559
9560 err = dhd_pktlog_filter_pattern_enable(filter,
9561 command + strlen(CMD_PKTLOG_FILTER_PATTERN_ENABLE) + 1, TRUE);
9562
9563 if (err == BCME_OK) {
9564 bytes_written = snprintf(command, total_len, "OK");
9565 ANDROID_ERROR(("%s: pktlog filter pattern enable success\n", __FUNCTION__));
9566 } else {
9567 ANDROID_ERROR(("%s: pktlog filter pattern enable fail\n", __FUNCTION__));
9568 return BCME_ERROR;
9569 }
9570
9571 return bytes_written;
9572 }
9573
9574 static int
wl_android_pktlog_filter_pattern_disable(struct net_device * dev,char * command,int total_len)9575 wl_android_pktlog_filter_pattern_disable(struct net_device *dev, char *command, int total_len)
9576 {
9577 int bytes_written = 0;
9578 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9579 dhd_pktlog_filter_t *filter;
9580 int err = BCME_OK;
9581
9582 if (!dhdp || !dhdp->pktlog) {
9583 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9584 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9585 return -EINVAL;
9586 }
9587
9588 filter = dhdp->pktlog->pktlog_filter;
9589
9590 if (strlen(CMD_PKTLOG_FILTER_PATTERN_DISABLE) + 1 > total_len) {
9591 return BCME_ERROR;
9592 }
9593
9594 err = dhd_pktlog_filter_pattern_enable(filter,
9595 command + strlen(CMD_PKTLOG_FILTER_PATTERN_DISABLE) + 1, FALSE);
9596
9597 if (err == BCME_OK) {
9598 bytes_written = snprintf(command, total_len, "OK");
9599 ANDROID_ERROR(("%s: pktlog filter pattern disable success\n", __FUNCTION__));
9600 } else {
9601 ANDROID_ERROR(("%s: pktlog filter pattern disable fail\n", __FUNCTION__));
9602 return BCME_ERROR;
9603 }
9604
9605 return bytes_written;
9606 }
9607
9608 static int
wl_android_pktlog_filter_add(struct net_device * dev,char * command,int total_len)9609 wl_android_pktlog_filter_add(struct net_device *dev, char *command, int total_len)
9610 {
9611 int bytes_written = 0;
9612 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9613 dhd_pktlog_filter_t *filter;
9614 int err = BCME_OK;
9615
9616 if (!dhdp || !dhdp->pktlog) {
9617 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9618 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9619 return -EINVAL;
9620 }
9621
9622 filter = dhdp->pktlog->pktlog_filter;
9623
9624 if (strlen(CMD_PKTLOG_FILTER_ADD) + 1 > total_len) {
9625 return BCME_ERROR;
9626 }
9627
9628 err = dhd_pktlog_filter_add(filter, command + strlen(CMD_PKTLOG_FILTER_ADD) + 1);
9629
9630 if (err == BCME_OK) {
9631 bytes_written = snprintf(command, total_len, "OK");
9632 ANDROID_ERROR(("%s: pktlog filter add success\n", __FUNCTION__));
9633 } else {
9634 ANDROID_ERROR(("%s: pktlog filter add fail\n", __FUNCTION__));
9635 return BCME_ERROR;
9636 }
9637
9638 return bytes_written;
9639 }
9640
9641 static int
wl_android_pktlog_filter_del(struct net_device * dev,char * command,int total_len)9642 wl_android_pktlog_filter_del(struct net_device *dev, char *command, int total_len)
9643 {
9644 int bytes_written = 0;
9645 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9646 dhd_pktlog_filter_t *filter;
9647 int err = BCME_OK;
9648
9649 if (!dhdp || !dhdp->pktlog) {
9650 ANDROID_ERROR(("%s(): dhdp=%p pktlog=%p\n",
9651 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9652 return -EINVAL;
9653 }
9654
9655 filter = dhdp->pktlog->pktlog_filter;
9656
9657 if (strlen(CMD_PKTLOG_FILTER_DEL) + 1 > total_len) {
9658 DHD_PKT_LOG(("%s(): wrong cmd length %d found\n",
9659 __FUNCTION__, (int)strlen(CMD_PKTLOG_FILTER_DEL)));
9660 return BCME_ERROR;
9661 }
9662
9663 err = dhd_pktlog_filter_del(filter, command + strlen(CMD_PKTLOG_FILTER_DEL) + 1);
9664 if (err == BCME_OK) {
9665 bytes_written = snprintf(command, total_len, "OK");
9666 ANDROID_ERROR(("%s: pktlog filter del success\n", __FUNCTION__));
9667 } else {
9668 ANDROID_ERROR(("%s: pktlog filter del fail\n", __FUNCTION__));
9669 return BCME_ERROR;
9670 }
9671
9672 return bytes_written;
9673 }
9674
9675 static int
wl_android_pktlog_filter_info(struct net_device * dev,char * command,int total_len)9676 wl_android_pktlog_filter_info(struct net_device *dev, char *command, int total_len)
9677 {
9678 int bytes_written = 0;
9679 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9680 dhd_pktlog_filter_t *filter;
9681 int err = BCME_OK;
9682
9683 if (!dhdp || !dhdp->pktlog) {
9684 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9685 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9686 return -EINVAL;
9687 }
9688
9689 filter = dhdp->pktlog->pktlog_filter;
9690
9691 err = dhd_pktlog_filter_info(filter);
9692
9693 if (err == BCME_OK) {
9694 bytes_written = snprintf(command, total_len, "OK");
9695 ANDROID_ERROR(("%s: pktlog filter info success\n", __FUNCTION__));
9696 } else {
9697 ANDROID_ERROR(("%s: pktlog filter info fail\n", __FUNCTION__));
9698 return BCME_ERROR;
9699 }
9700
9701 return bytes_written;
9702 }
9703
9704 static int
wl_android_pktlog_start(struct net_device * dev,char * command,int total_len)9705 wl_android_pktlog_start(struct net_device *dev, char *command, int total_len)
9706 {
9707 int bytes_written = 0;
9708 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9709
9710 if (!dhdp || !dhdp->pktlog) {
9711 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9712 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9713 return -EINVAL;
9714 }
9715
9716 if (!dhdp->pktlog->pktlog_ring) {
9717 DHD_PKT_LOG(("%s(): pktlog_ring=%p\n",
9718 __FUNCTION__, dhdp->pktlog->pktlog_ring));
9719 return -EINVAL;
9720 }
9721
9722 atomic_set(&dhdp->pktlog->pktlog_ring->start, TRUE);
9723
9724 bytes_written = snprintf(command, total_len, "OK");
9725
9726 ANDROID_ERROR(("%s: pktlog start success\n", __FUNCTION__));
9727
9728 return bytes_written;
9729 }
9730
9731 static int
wl_android_pktlog_stop(struct net_device * dev,char * command,int total_len)9732 wl_android_pktlog_stop(struct net_device *dev, char *command, int total_len)
9733 {
9734 int bytes_written = 0;
9735 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9736
9737 if (!dhdp || !dhdp->pktlog) {
9738 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9739 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9740 return -EINVAL;
9741 }
9742
9743 if (!dhdp->pktlog->pktlog_ring) {
9744 DHD_PKT_LOG(("%s(): _pktlog_ring=%p\n",
9745 __FUNCTION__, dhdp->pktlog->pktlog_ring));
9746 return -EINVAL;
9747 }
9748
9749 atomic_set(&dhdp->pktlog->pktlog_ring->start, FALSE);
9750
9751 bytes_written = snprintf(command, total_len, "OK");
9752
9753 ANDROID_ERROR(("%s: pktlog stop success\n", __FUNCTION__));
9754
9755 return bytes_written;
9756 }
9757
9758 static int
wl_android_pktlog_filter_exist(struct net_device * dev,char * command,int total_len)9759 wl_android_pktlog_filter_exist(struct net_device *dev, char *command, int total_len)
9760 {
9761 int bytes_written = 0;
9762 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9763 dhd_pktlog_filter_t *filter;
9764 uint32 id;
9765 bool exist = FALSE;
9766
9767 if (!dhdp || !dhdp->pktlog) {
9768 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9769 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9770 return -EINVAL;
9771 }
9772
9773 filter = dhdp->pktlog->pktlog_filter;
9774
9775 if (strlen(CMD_PKTLOG_FILTER_EXIST) + 1 > total_len) {
9776 return BCME_ERROR;
9777 }
9778
9779 exist = dhd_pktlog_filter_existed(filter, command + strlen(CMD_PKTLOG_FILTER_EXIST) + 1,
9780 &id);
9781
9782 if (exist) {
9783 bytes_written = snprintf(command, total_len, "TRUE");
9784 ANDROID_ERROR(("%s: pktlog filter pattern id: %d is existed\n", __FUNCTION__, id));
9785 } else {
9786 bytes_written = snprintf(command, total_len, "FALSE");
9787 ANDROID_ERROR(("%s: pktlog filter pattern id: %d is not existed\n", __FUNCTION__, id));
9788 }
9789
9790 return bytes_written;
9791 }
9792
9793 static int
wl_android_pktlog_minmize_enable(struct net_device * dev,char * command,int total_len)9794 wl_android_pktlog_minmize_enable(struct net_device *dev, char *command, int total_len)
9795 {
9796 int bytes_written = 0;
9797 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9798
9799 if (!dhdp || !dhdp->pktlog) {
9800 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9801 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9802 return -EINVAL;
9803 }
9804
9805 if (!dhdp->pktlog->pktlog_ring) {
9806 DHD_PKT_LOG(("%s(): pktlog_ring=%p\n",
9807 __FUNCTION__, dhdp->pktlog->pktlog_ring));
9808 return -EINVAL;
9809 }
9810
9811 dhdp->pktlog->pktlog_ring->pktlog_minmize = TRUE;
9812
9813 bytes_written = snprintf(command, total_len, "OK");
9814
9815 ANDROID_ERROR(("%s: pktlog pktlog_minmize enable\n", __FUNCTION__));
9816
9817 return bytes_written;
9818 }
9819
9820 static int
wl_android_pktlog_minmize_disable(struct net_device * dev,char * command,int total_len)9821 wl_android_pktlog_minmize_disable(struct net_device *dev, char *command, int total_len)
9822 {
9823 int bytes_written = 0;
9824 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9825
9826 if (!dhdp || !dhdp->pktlog) {
9827 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9828 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9829 return -EINVAL;
9830 }
9831
9832 if (!dhdp->pktlog->pktlog_ring) {
9833 DHD_PKT_LOG(("%s(): pktlog_ring=%p\n",
9834 __FUNCTION__, dhdp->pktlog->pktlog_ring));
9835 return -EINVAL;
9836 }
9837
9838 dhdp->pktlog->pktlog_ring->pktlog_minmize = FALSE;
9839
9840 bytes_written = snprintf(command, total_len, "OK");
9841
9842 ANDROID_ERROR(("%s: pktlog pktlog_minmize disable\n", __FUNCTION__));
9843
9844 return bytes_written;
9845 }
9846
9847 static int
wl_android_pktlog_change_size(struct net_device * dev,char * command,int total_len)9848 wl_android_pktlog_change_size(struct net_device *dev, char *command, int total_len)
9849 {
9850 int bytes_written = 0;
9851 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9852 int err = BCME_OK;
9853 int size;
9854
9855 if (!dhdp || !dhdp->pktlog) {
9856 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9857 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9858 return -EINVAL;
9859 }
9860
9861 if (strlen(CMD_PKTLOG_CHANGE_SIZE) + 1 > total_len) {
9862 return BCME_ERROR;
9863 }
9864
9865 size = bcm_strtoul(command + strlen(CMD_PKTLOG_CHANGE_SIZE) + 1, NULL, 0);
9866
9867 dhdp->pktlog->pktlog_ring =
9868 dhd_pktlog_ring_change_size(dhdp->pktlog->pktlog_ring, size);
9869 if (!dhdp->pktlog->pktlog_ring) {
9870 err = BCME_ERROR;
9871 }
9872
9873 if (err == BCME_OK) {
9874 bytes_written = snprintf(command, total_len, "OK");
9875 ANDROID_ERROR(("%s: pktlog change size success\n", __FUNCTION__));
9876 } else {
9877 ANDROID_ERROR(("%s: pktlog change size fail\n", __FUNCTION__));
9878 return BCME_ERROR;
9879 }
9880
9881 return bytes_written;
9882 }
9883
9884 static int
wl_android_pktlog_dbg_dump(struct net_device * dev,char * command,int total_len)9885 wl_android_pktlog_dbg_dump(struct net_device *dev, char *command, int total_len)
9886 {
9887 int bytes_written = 0;
9888 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9889 int err = BCME_OK;
9890
9891 if (!dhdp || !dhdp->pktlog) {
9892 DHD_PKT_LOG(("%s(): dhdp=%p pktlog=%p\n",
9893 __FUNCTION__, dhdp, (dhdp ? dhdp->pktlog : NULL)));
9894 return -EINVAL;
9895 }
9896
9897 if (strlen(CMD_PKTLOG_DEBUG_DUMP) + 1 > total_len) {
9898 return BCME_ERROR;
9899 }
9900
9901 err = dhd_pktlog_debug_dump(dhdp);
9902 if (err == BCME_OK) {
9903 bytes_written = snprintf(command, total_len, "OK");
9904 ANDROID_INFO(("%s: pktlog dbg dump success\n", __FUNCTION__));
9905 } else {
9906 ANDROID_ERROR(("%s: pktlog dbg dump fail\n", __FUNCTION__));
9907 return BCME_ERROR;
9908 }
9909
9910 return bytes_written;
9911 }
9912 #endif /* DHD_PKT_LOGGING */
9913
9914 #if defined(CONFIG_TIZEN)
wl_android_set_powersave_mode(struct net_device * dev,char * command,int total_len)9915 static int wl_android_set_powersave_mode(
9916 struct net_device *dev, char* command, int total_len)
9917 {
9918 int pm;
9919
9920 int err = BCME_OK;
9921 #ifdef DHD_PM_OVERRIDE
9922 extern bool g_pm_override;
9923 #endif /* DHD_PM_OVERRIDE */
9924 sscanf(command, "%*s %10d", &pm);
9925 if (pm < PM_OFF || pm > PM_FAST) {
9926 ANDROID_ERROR(("check pm=%d\n", pm));
9927 return BCME_ERROR;
9928 }
9929
9930 #ifdef DHD_PM_OVERRIDE
9931 if (pm > PM_OFF) {
9932 g_pm_override = FALSE;
9933 }
9934 #endif /* DHD_PM_OVERRIDE */
9935
9936 err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
9937
9938 #ifdef DHD_PM_OVERRIDE
9939 if (pm == PM_OFF) {
9940 g_pm_override = TRUE;
9941 }
9942
9943 ANDROID_ERROR(("%s: PM:%d, pm_override=%d\n", __FUNCTION__, pm, g_pm_override));
9944 #endif /* DHD_PM_OVERRIDE */
9945 return err;
9946 }
9947
wl_android_get_powersave_mode(struct net_device * dev,char * command,int total_len)9948 static int wl_android_get_powersave_mode(
9949 struct net_device *dev, char *command, int total_len)
9950 {
9951 int err, bytes_written;
9952 int pm;
9953
9954 err = wldev_ioctl_get(dev, WLC_GET_PM, &pm, sizeof(pm));
9955 if (err != BCME_OK) {
9956 ANDROID_ERROR(("failed to get pm (%d)", err));
9957 return err;
9958 }
9959
9960 bytes_written = snprintf(command, total_len, "%s %d",
9961 CMD_POWERSAVEMODE_GET, pm);
9962
9963 return bytes_written;
9964 }
9965 #endif /* CONFIG_TIZEN */
9966
9967 #ifdef DHD_EVENT_LOG_FILTER
9968 uint32 dhd_event_log_filter_serialize(dhd_pub_t *dhdp, char *buf, uint32 tot_len, int type);
9969
9970 #ifdef DHD_EWPR_VER2
9971 uint32 dhd_event_log_filter_serialize_bit(dhd_pub_t *dhdp, char *buf, uint32 tot_len,
9972 int index1, int index2, int index3);
9973 #endif
9974
9975 static int
wl_android_ewp_filter(struct net_device * dev,char * command,uint32 tot_len)9976 wl_android_ewp_filter(struct net_device *dev, char *command, uint32 tot_len)
9977 {
9978 uint32 bytes_written = 0;
9979 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
9980 #ifdef DHD_EWPR_VER2
9981 int index1 = 0, index2 = 0, index3 = 0;
9982 unsigned char *index_str = (unsigned char *)(command +
9983 strlen(CMD_EWP_FILTER) + 1);
9984 #else
9985 int type = 0;
9986 #endif
9987
9988 if (!dhdp || !command) {
9989 ANDROID_ERROR(("%s(): dhdp=%p \n", __FUNCTION__, dhdp));
9990 return -EINVAL;
9991 }
9992
9993 if (!FW_SUPPORTED(dhdp, ecounters)) {
9994 ANDROID_ERROR(("does not support ecounters!\n"));
9995 return BCME_UNSUPPORTED;
9996 }
9997
9998 #ifdef DHD_EWPR_VER2
9999 if (strlen(command) > strlen(CMD_EWP_FILTER) + 1) {
10000 sscanf(index_str, "%10d %10d %10d", &index1, &index2, &index3);
10001 ANDROID_TRACE(("%s(): get index request: %d %d %d\n", __FUNCTION__,
10002 index1, index2, index3));
10003 }
10004 bytes_written += dhd_event_log_filter_serialize_bit(dhdp,
10005 &command[bytes_written], tot_len - bytes_written, index1, index2, index3);
10006 #else
10007 /* NEED TO GET TYPE if EXIST */
10008 type = 0;
10009
10010 bytes_written += dhd_event_log_filter_serialize(dhdp,
10011 &command[bytes_written], tot_len - bytes_written, type);
10012 #endif
10013
10014 return (int)bytes_written;
10015 }
10016 #endif /* DHD_EVENT_LOG_FILTER */
10017
10018 #ifdef SUPPORT_AP_SUSPEND
10019 int
wl_android_set_ap_suspend(struct net_device * dev,char * command,int total_len)10020 wl_android_set_ap_suspend(struct net_device *dev, char *command, int total_len)
10021 {
10022 int suspend = 0;
10023 char *pos, *token;
10024 char *ifname = NULL;
10025 int err = BCME_OK;
10026 char name[IFNAMSIZ];
10027
10028 /*
10029 * DRIVER SET_AP_SUSPEND <0/1> <ifname>
10030 */
10031 pos = command;
10032
10033 /* drop command */
10034 token = bcmstrtok(&pos, " ", NULL);
10035
10036 /* Enable */
10037 token = bcmstrtok(&pos, " ", NULL);
10038 if (!token) {
10039 return -EINVAL;
10040 }
10041 suspend = bcm_atoi(token);
10042
10043 /* get the interface name */
10044 token = bcmstrtok(&pos, " ", NULL);
10045 if (!token) {
10046 return -EINVAL;
10047 }
10048 ifname = token;
10049
10050 strlcpy(name, ifname, sizeof(name));
10051 ANDROID_INFO(("suspend %d, ifacename %s\n", suspend, name));
10052
10053 err = wl_set_ap_suspend(dev, suspend? TRUE: FALSE, name);
10054 if (unlikely(err)) {
10055 ANDROID_ERROR(("Failed to set suspend, suspend %d, error = %d\n", suspend, err));
10056 }
10057
10058 return err;
10059 }
10060 #endif /* SUPPORT_AP_SUSPEND */
10061
10062 #ifdef SUPPORT_AP_BWCTRL
10063 int
wl_android_set_ap_bw(struct net_device * dev,char * command,int total_len)10064 wl_android_set_ap_bw(struct net_device *dev, char *command, int total_len)
10065 {
10066 int bw = DOT11_OPER_MODE_20MHZ;
10067 char *pos, *token;
10068 char *ifname = NULL;
10069 int err = BCME_OK;
10070 char name[IFNAMSIZ];
10071
10072 /*
10073 * DRIVER SET_AP_BW <0/1/2> <ifname>
10074 * 0 : 20MHz, 1 : 40MHz, 2 : 80MHz 3: 80+80 or 160MHz
10075 * This is from operating mode field
10076 * in 8.4.1.50 of 802.11ac-2013
10077 */
10078 pos = command;
10079
10080 /* drop command */
10081 token = bcmstrtok(&pos, " ", NULL);
10082
10083 /* BW */
10084 token = bcmstrtok(&pos, " ", NULL);
10085 if (!token) {
10086 return -EINVAL;
10087 }
10088 bw = bcm_atoi(token);
10089
10090 /* get the interface name */
10091 token = bcmstrtok(&pos, " ", NULL);
10092 if (!token) {
10093 return -EINVAL;
10094 }
10095 ifname = token;
10096
10097 strlcpy(name, ifname, sizeof(name));
10098 ANDROID_INFO(("bw %d, ifacename %s\n", bw, name));
10099
10100 err = wl_set_ap_bw(dev, bw, name);
10101 if (unlikely(err)) {
10102 ANDROID_ERROR(("Failed to set bw, bw %d, error = %d\n", bw, err));
10103 }
10104
10105 return err;
10106 }
10107
10108 int
wl_android_get_ap_bw(struct net_device * dev,char * command,int total_len)10109 wl_android_get_ap_bw(struct net_device *dev, char *command, int total_len)
10110 {
10111 char *pos, *token;
10112 char *ifname = NULL;
10113 int bytes_written = 0;
10114 char name[IFNAMSIZ];
10115
10116 /*
10117 * DRIVER GET_AP_BW <ifname>
10118 * returns 0 : 20MHz, 1 : 40MHz, 2 : 80MHz 3: 80+80 or 160MHz
10119 * This is from operating mode field
10120 * in 8.4.1.50 of 802.11ac-2013
10121 */
10122 pos = command;
10123
10124 /* drop command */
10125 token = bcmstrtok(&pos, " ", NULL);
10126
10127 /* get the interface name */
10128 token = bcmstrtok(&pos, " ", NULL);
10129 if (!token) {
10130 return -EINVAL;
10131 }
10132 ifname = token;
10133
10134 strlcpy(name, ifname, sizeof(name));
10135 ANDROID_INFO(("ifacename %s\n", name));
10136
10137 bytes_written = wl_get_ap_bw(dev, command, name, total_len);
10138 if (bytes_written < 1) {
10139 ANDROID_ERROR(("Failed to get bw, error = %d\n", bytes_written));
10140 return -EPROTO;
10141 }
10142
10143 return bytes_written;
10144
10145 }
10146 #endif /* SUPPORT_AP_BWCTRL */
10147
10148 static int
wl_android_priv_cmd_log_enable_check(char * cmd)10149 wl_android_priv_cmd_log_enable_check(char* cmd)
10150 {
10151 int cnt = 0;
10152
10153 while (strlen(loging_params[cnt].command) > 0) {
10154 if (!strnicmp(cmd, loging_params[cnt].command,
10155 strlen(loging_params[cnt].command))) {
10156 return loging_params[cnt].enable;
10157 }
10158
10159 cnt++;
10160 }
10161
10162 return FALSE;
10163 }
10164
wl_android_priv_cmd(struct net_device * net,struct ifreq * ifr)10165 int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr)
10166 {
10167 #define PRIVATE_COMMAND_MAX_LEN 8192
10168 #define PRIVATE_COMMAND_DEF_LEN 4096
10169 int ret = 0;
10170 char *command = NULL;
10171 int bytes_written = 0;
10172 android_wifi_priv_cmd priv_cmd;
10173 int buf_size = 0;
10174 dhd_pub_t *dhd = dhd_get_pub(net);
10175
10176 net_os_wake_lock(net);
10177
10178 if (!capable(CAP_NET_ADMIN)) {
10179 ret = -EPERM;
10180 goto exit;
10181 }
10182
10183 if (!ifr->ifr_data) {
10184 ret = -EINVAL;
10185 goto exit;
10186 }
10187
10188 #ifdef CONFIG_COMPAT
10189 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
10190 if (in_compat_syscall())
10191 #else
10192 if (is_compat_task())
10193 #endif
10194 {
10195 compat_android_wifi_priv_cmd compat_priv_cmd;
10196 if (copy_from_user(&compat_priv_cmd, ifr->ifr_data,
10197 sizeof(compat_android_wifi_priv_cmd))) {
10198 ret = -EFAULT;
10199 goto exit;
10200
10201 }
10202 priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
10203 priv_cmd.used_len = compat_priv_cmd.used_len;
10204 priv_cmd.total_len = compat_priv_cmd.total_len;
10205 } else
10206 #endif /* CONFIG_COMPAT */
10207 {
10208 if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
10209 ret = -EFAULT;
10210 goto exit;
10211 }
10212 }
10213 if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) {
10214 ANDROID_ERROR(("%s: buf length invalid:%d\n", __FUNCTION__,
10215 priv_cmd.total_len));
10216 ret = -EINVAL;
10217 goto exit;
10218 }
10219
10220 buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN);
10221 command = (char *)MALLOC(dhd->osh, (buf_size + 1));
10222 if (!command) {
10223 ANDROID_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
10224 ret = -ENOMEM;
10225 goto exit;
10226 }
10227 if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
10228 ret = -EFAULT;
10229 goto exit;
10230 }
10231 command[priv_cmd.total_len] = '\0';
10232
10233 if (wl_android_priv_cmd_log_enable_check(command)) {
10234 ANDROID_ERROR(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__,
10235 command, ifr->ifr_name));
10236 }
10237 else {
10238 ANDROID_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name));
10239
10240 }
10241
10242 bytes_written = wl_handle_private_cmd(net, command, priv_cmd.total_len);
10243 if (bytes_written >= 0) {
10244 if ((bytes_written == 0) && (priv_cmd.total_len > 0)) {
10245 command[0] = '\0';
10246 }
10247 if (bytes_written >= priv_cmd.total_len) {
10248 ANDROID_ERROR(("%s: err. bytes_written:%d >= total_len:%d, buf_size:%d\n",
10249 __FUNCTION__, bytes_written, priv_cmd.total_len, buf_size));
10250
10251 ret = BCME_BUFTOOSHORT;
10252 goto exit;
10253 }
10254 bytes_written++;
10255 priv_cmd.used_len = bytes_written;
10256 if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
10257 ANDROID_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
10258 ret = -EFAULT;
10259 }
10260 }
10261 else {
10262 /* Propagate the error */
10263 ret = bytes_written;
10264 }
10265
10266 exit:
10267 #ifdef DHD_SEND_HANG_PRIVCMD_ERRORS
10268 if (ret) {
10269 /* Avoid incrementing priv_cmd_errors in case of unsupported feature */
10270 if (ret != BCME_UNSUPPORTED) {
10271 wl_android_check_priv_cmd_errors(net);
10272 }
10273 } else {
10274 priv_cmd_errors = 0;
10275 }
10276 #endif /* DHD_SEND_HANG_PRIVCMD_ERRORS */
10277 net_os_wake_unlock(net);
10278 MFREE(dhd->osh, command, (buf_size + 1));
10279 return ret;
10280 }
10281
10282 #ifdef WLADPS_PRIVATE_CMD
10283 static int
wl_android_set_adps_mode(struct net_device * dev,const char * string_num)10284 wl_android_set_adps_mode(struct net_device *dev, const char* string_num)
10285 {
10286 int err = 0, adps_mode;
10287 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
10288 #ifdef DHD_PM_CONTROL_FROM_FILE
10289 if (g_pm_control) {
10290 return -EPERM;
10291 }
10292 #endif /* DHD_PM_CONTROL_FROM_FILE */
10293
10294 adps_mode = bcm_atoi(string_num);
10295 ANDROID_ERROR(("%s: SET_ADPS %d\n", __FUNCTION__, adps_mode));
10296
10297 if (!(adps_mode == 0 || adps_mode == 1)) {
10298 ANDROID_ERROR(("wl_android_set_adps_mode: Invalid value %d.\n", adps_mode));
10299 return -EINVAL;
10300 }
10301
10302 err = dhd_enable_adps(dhdp, adps_mode);
10303 if (err != BCME_OK) {
10304 ANDROID_ERROR(("failed to set adps mode %d, error = %d\n", adps_mode, err));
10305 return -EIO;
10306 }
10307 return err;
10308 }
10309 static int
wl_android_get_adps_mode(struct net_device * dev,char * command,int total_len)10310 wl_android_get_adps_mode(
10311 struct net_device *dev, char *command, int total_len)
10312 {
10313 int bytes_written, err = 0;
10314 uint len;
10315 char buf[WLC_IOCTL_SMLEN];
10316
10317 bcm_iov_buf_t iov_buf;
10318 bcm_iov_buf_t *ptr = NULL;
10319 wl_adps_params_v1_t *data = NULL;
10320
10321 uint8 *pdata = NULL;
10322 uint8 band, mode = 0;
10323
10324 bzero(&iov_buf, sizeof(iov_buf));
10325
10326 len = OFFSETOF(bcm_iov_buf_t, data) + sizeof(band);
10327
10328 iov_buf.version = WL_ADPS_IOV_VER;
10329 iov_buf.len = sizeof(band);
10330 iov_buf.id = WL_ADPS_IOV_MODE;
10331
10332 pdata = (uint8 *)&iov_buf.data;
10333
10334 for (band = 1; band <= MAX_BANDS; band++) {
10335 pdata[0] = band;
10336 err = wldev_iovar_getbuf(dev, "adps", &iov_buf, len,
10337 buf, WLC_IOCTL_SMLEN, NULL);
10338 if (err != BCME_OK) {
10339 ANDROID_ERROR(("wl_android_get_adps_mode fail to get adps band %d(%d).\n",
10340 band, err));
10341 return -EIO;
10342 }
10343 ptr = (bcm_iov_buf_t *) buf;
10344 data = (wl_adps_params_v1_t *) ptr->data;
10345 mode = data->mode;
10346 if (mode != OFF) {
10347 break;
10348 }
10349 }
10350
10351 bytes_written = snprintf(command, total_len, "%s %d",
10352 CMD_GET_ADPS, mode);
10353 return bytes_written;
10354 }
10355
10356 #ifdef WLADPS_ENERGY_GAIN
10357 static int
wl_android_get_gain_adps(struct net_device * dev,char * command,int total_len)10358 wl_android_get_gain_adps(
10359 struct net_device *dev, char *command, int total_len)
10360 {
10361 int bytes_written;
10362
10363 int ret = 0;
10364 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
10365
10366 ret = dhd_event_log_filter_adps_energy_gain(dhdp);
10367 if (ret < 0) {
10368 return ret;
10369 }
10370
10371 ANDROID_INFO(("%s ADPS Energy Gain: %d uAh\n", __FUNCTION__, ret));
10372
10373 bytes_written = snprintf(command, total_len, "%s %d uAm",
10374 CMD_GET_GAIN_ADPS, ret);
10375
10376 return bytes_written;
10377 }
10378
10379 static int
wl_android_reset_gain_adps(struct net_device * dev,char * command)10380 wl_android_reset_gain_adps(
10381 struct net_device *dev, char *command)
10382 {
10383 int ret = BCME_OK;
10384
10385 bcm_iov_buf_t iov_buf;
10386 char buf[WLC_IOCTL_SMLEN] = {0, };
10387
10388 iov_buf.version = WL_ADPS_IOV_VER;
10389 iov_buf.id = WL_ADPS_IOV_RESET_GAIN;
10390 iov_buf.len = 0;
10391
10392 if ((ret = wldev_iovar_setbuf(dev, "adps", &iov_buf, sizeof(iov_buf),
10393 buf, sizeof(buf), NULL)) < 0) {
10394 ANDROID_ERROR(("%s fail to reset adps gain (%d)\n", __FUNCTION__, ret));
10395 }
10396
10397 return ret;
10398 }
10399 #endif /* WLADPS_ENERGY_GAIN */
10400 #endif /* WLADPS_PRIVATE_CMD */
10401
10402 #ifdef WL_BCNRECV
10403 #define BCNRECV_ATTR_HDR_LEN 30
10404 int
wl_android_bcnrecv_event(struct net_device * ndev,uint attr_type,uint status,uint reason,uint8 * data,uint data_len)10405 wl_android_bcnrecv_event(struct net_device *ndev, uint attr_type,
10406 uint status, uint reason, uint8 *data, uint data_len)
10407 {
10408 s32 err = BCME_OK;
10409 struct sk_buff *skb;
10410 gfp_t kflags;
10411 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
10412 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10413 uint len;
10414
10415 len = BCNRECV_ATTR_HDR_LEN + data_len;
10416
10417 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
10418 skb = CFG80211_VENDOR_EVENT_ALLOC(wiphy, ndev_to_wdev(ndev), len,
10419 BRCM_VENDOR_EVENT_BEACON_RECV, kflags);
10420 if (!skb) {
10421 ANDROID_ERROR(("skb alloc failed"));
10422 return -ENOMEM;
10423 }
10424 if ((attr_type == BCNRECV_ATTR_BCNINFO) && (data)) {
10425 /* send bcn info to upper layer */
10426 nla_put(skb, BCNRECV_ATTR_BCNINFO, data_len, data);
10427 } else if (attr_type == BCNRECV_ATTR_STATUS) {
10428 nla_put_u32(skb, BCNRECV_ATTR_STATUS, status);
10429 if (reason) {
10430 nla_put_u32(skb, BCNRECV_ATTR_REASON, reason);
10431 }
10432 } else {
10433 ANDROID_ERROR(("UNKNOWN ATTR_TYPE. attr_type:%d\n", attr_type));
10434 kfree_skb(skb);
10435 return -EINVAL;
10436 }
10437 cfg80211_vendor_event(skb, kflags);
10438 return err;
10439 }
10440
10441 static int
_wl_android_bcnrecv_start(struct bcm_cfg80211 * cfg,struct net_device * ndev,bool user_trigger)10442 _wl_android_bcnrecv_start(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool user_trigger)
10443 {
10444 s32 err = BCME_OK;
10445 struct net_device *pdev = bcmcfg_to_prmry_ndev(cfg);
10446
10447 /* check any scan is in progress before beacon recv scan trigger IOVAR */
10448 if (wl_get_drv_status_all(cfg, SCANNING)) {
10449 err = BCME_UNSUPPORTED;
10450 ANDROID_ERROR(("Scan in progress, Aborting beacon recv start, "
10451 "error:%d\n", err));
10452 goto exit;
10453 }
10454
10455 if (wl_get_p2p_status(cfg, SCANNING)) {
10456 err = BCME_UNSUPPORTED;
10457 ANDROID_ERROR(("P2P Scan in progress, Aborting beacon recv start, "
10458 "error:%d\n", err));
10459 goto exit;
10460 }
10461
10462 if (wl_get_drv_status(cfg, REMAINING_ON_CHANNEL, ndev)) {
10463 err = BCME_UNSUPPORTED;
10464 ANDROID_ERROR(("P2P remain on channel, Aborting beacon recv start, "
10465 "error:%d\n", err));
10466 goto exit;
10467 }
10468
10469 /* check STA is in connected state, Beacon recv required connected state
10470 * else exit from beacon recv scan
10471 */
10472 if (!wl_get_drv_status(cfg, CONNECTED, ndev)) {
10473 err = BCME_UNSUPPORTED;
10474 ANDROID_ERROR(("STA is in not associated state error:%d\n", err));
10475 goto exit;
10476 }
10477
10478 #ifdef WL_NAN
10479 /* Check NAN is enabled, if enabled exit else continue */
10480 if (wl_cfgnan_is_enabled(cfg)) {
10481 err = BCME_UNSUPPORTED;
10482 ANDROID_ERROR(("Nan is enabled, NAN+STA+FAKEAP concurrency is not supported\n"));
10483 goto exit;
10484 }
10485 #endif /* WL_NAN */
10486
10487 /* Triggering an sendup_bcn iovar */
10488 err = wldev_iovar_setint(pdev, "sendup_bcn", 1);
10489 if (unlikely(err)) {
10490 ANDROID_ERROR(("sendup_bcn failed to set, error:%d\n", err));
10491 } else {
10492 cfg->bcnrecv_info.bcnrecv_state = BEACON_RECV_STARTED;
10493 ANDROID_INFO(("bcnrecv started. user_trigger:%d ifindex:%d\n",
10494 user_trigger, ndev->ifindex));
10495 if (user_trigger) {
10496 if ((err = wl_android_bcnrecv_event(pdev, BCNRECV_ATTR_STATUS,
10497 WL_BCNRECV_STARTED, 0, NULL, 0)) != BCME_OK) {
10498 ANDROID_ERROR(("failed to send bcnrecv event, error:%d\n", err));
10499 }
10500 }
10501 }
10502 exit:
10503 /*
10504 * BCNRECV start request can be rejected from dongle
10505 * in various conditions.
10506 * Error code need to be overridden to BCME_UNSUPPORTED
10507 * to avoid hang event from continous private
10508 * command error
10509 */
10510 if (err) {
10511 err = BCME_UNSUPPORTED;
10512 }
10513 return err;
10514 }
10515
10516 int
_wl_android_bcnrecv_stop(struct bcm_cfg80211 * cfg,struct net_device * ndev,uint reason)10517 _wl_android_bcnrecv_stop(struct bcm_cfg80211 *cfg, struct net_device *ndev, uint reason)
10518 {
10519 s32 err = BCME_OK;
10520 u32 status;
10521 struct net_device *pdev = bcmcfg_to_prmry_ndev(cfg);
10522
10523 /* Stop bcnrx except for fw abort event case */
10524 if (reason != WL_BCNRECV_ROAMABORT) {
10525 err = wldev_iovar_setint(pdev, "sendup_bcn", 0);
10526 if (unlikely(err)) {
10527 ANDROID_ERROR(("sendup_bcn failed to set error:%d\n", err));
10528 goto exit;
10529 }
10530 }
10531
10532 /* Send notification for all cases */
10533 if (reason == WL_BCNRECV_SUSPEND) {
10534 cfg->bcnrecv_info.bcnrecv_state = BEACON_RECV_SUSPENDED;
10535 status = WL_BCNRECV_SUSPENDED;
10536 } else {
10537 cfg->bcnrecv_info.bcnrecv_state = BEACON_RECV_STOPPED;
10538 ANDROID_INFO(("bcnrecv stopped. reason:%d ifindex:%d\n",
10539 reason, ndev->ifindex));
10540 if (reason == WL_BCNRECV_USER_TRIGGER) {
10541 status = WL_BCNRECV_STOPPED;
10542 } else {
10543 status = WL_BCNRECV_ABORTED;
10544 }
10545 }
10546 if ((err = wl_android_bcnrecv_event(pdev, BCNRECV_ATTR_STATUS, status,
10547 reason, NULL, 0)) != BCME_OK) {
10548 ANDROID_ERROR(("failed to send bcnrecv event, error:%d\n", err));
10549 }
10550 exit:
10551 return err;
10552 }
10553
10554 static int
wl_android_bcnrecv_start(struct bcm_cfg80211 * cfg,struct net_device * ndev)10555 wl_android_bcnrecv_start(struct bcm_cfg80211 *cfg, struct net_device *ndev)
10556 {
10557 s32 err = BCME_OK;
10558
10559 /* Adding scan_sync mutex to avoid race condition in b/w scan_req and bcn recv */
10560 mutex_lock(&cfg->scan_sync);
10561 mutex_lock(&cfg->bcn_sync);
10562 err = _wl_android_bcnrecv_start(cfg, ndev, true);
10563 mutex_unlock(&cfg->bcn_sync);
10564 mutex_unlock(&cfg->scan_sync);
10565 return err;
10566 }
10567
10568 int
wl_android_bcnrecv_stop(struct net_device * ndev,uint reason)10569 wl_android_bcnrecv_stop(struct net_device *ndev, uint reason)
10570 {
10571 s32 err = BCME_OK;
10572 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
10573
10574 mutex_lock(&cfg->bcn_sync);
10575 if ((cfg->bcnrecv_info.bcnrecv_state == BEACON_RECV_STARTED) ||
10576 (cfg->bcnrecv_info.bcnrecv_state == BEACON_RECV_SUSPENDED)) {
10577 err = _wl_android_bcnrecv_stop(cfg, ndev, reason);
10578 }
10579 mutex_unlock(&cfg->bcn_sync);
10580 return err;
10581 }
10582
10583 int
wl_android_bcnrecv_suspend(struct net_device * ndev)10584 wl_android_bcnrecv_suspend(struct net_device *ndev)
10585 {
10586 s32 ret = BCME_OK;
10587 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
10588
10589 mutex_lock(&cfg->bcn_sync);
10590 if (cfg->bcnrecv_info.bcnrecv_state == BEACON_RECV_STARTED) {
10591 ANDROID_INFO(("bcnrecv suspend\n"));
10592 ret = _wl_android_bcnrecv_stop(cfg, ndev, WL_BCNRECV_SUSPEND);
10593 }
10594 mutex_unlock(&cfg->bcn_sync);
10595 return ret;
10596 }
10597
10598 int
wl_android_bcnrecv_resume(struct net_device * ndev)10599 wl_android_bcnrecv_resume(struct net_device *ndev)
10600 {
10601 s32 ret = BCME_OK;
10602 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
10603
10604 /* Adding scan_sync mutex to avoid race condition in b/w scan_req and bcn recv */
10605 mutex_lock(&cfg->scan_sync);
10606 mutex_lock(&cfg->bcn_sync);
10607 if (cfg->bcnrecv_info.bcnrecv_state == BEACON_RECV_SUSPENDED) {
10608 ANDROID_INFO(("bcnrecv resume\n"));
10609 ret = _wl_android_bcnrecv_start(cfg, ndev, false);
10610 }
10611 mutex_unlock(&cfg->bcn_sync);
10612 mutex_unlock(&cfg->scan_sync);
10613 return ret;
10614 }
10615
10616 /* Beacon recv functionality code implementation */
10617 int
wl_android_bcnrecv_config(struct net_device * ndev,char * cmd_argv,int total_len)10618 wl_android_bcnrecv_config(struct net_device *ndev, char *cmd_argv, int total_len)
10619 {
10620 struct bcm_cfg80211 *cfg = NULL;
10621 uint err = BCME_OK;
10622
10623 if (!ndev) {
10624 ANDROID_ERROR(("ndev is NULL\n"));
10625 return -EINVAL;
10626 }
10627
10628 cfg = wl_get_cfg(ndev);
10629 if (!cfg) {
10630 ANDROID_ERROR(("cfg is NULL\n"));
10631 return -EINVAL;
10632 }
10633
10634 /* sync commands from user space */
10635 mutex_lock(&cfg->usr_sync);
10636 if (strncmp(cmd_argv, "start", strlen("start")) == 0) {
10637 ANDROID_INFO(("BCNRECV start\n"));
10638 err = wl_android_bcnrecv_start(cfg, ndev);
10639 if (err != BCME_OK) {
10640 ANDROID_ERROR(("Failed to process the start command, error:%d\n", err));
10641 goto exit;
10642 }
10643 } else if (strncmp(cmd_argv, "stop", strlen("stop")) == 0) {
10644 ANDROID_INFO(("BCNRECV stop\n"));
10645 err = wl_android_bcnrecv_stop(ndev, WL_BCNRECV_USER_TRIGGER);
10646 if (err != BCME_OK) {
10647 ANDROID_ERROR(("Failed to stop the bcn recv, error:%d\n", err));
10648 goto exit;
10649 }
10650 } else {
10651 err = BCME_ERROR;
10652 }
10653 exit:
10654 mutex_unlock(&cfg->usr_sync);
10655 return err;
10656 }
10657 #endif /* WL_BCNRECV */
10658
10659 #ifdef SUPPORT_LATENCY_CRITICAL_DATA
10660 static int
wl_android_set_latency_crt_data(struct net_device * dev,int mode)10661 wl_android_set_latency_crt_data(struct net_device *dev, int mode)
10662 {
10663 int ret;
10664 #ifdef DHD_GRO_ENABLE_HOST_CTRL
10665 dhd_pub_t *dhdp = NULL;
10666 #endif /* DHD_GRO_ENABLE_HOST_CTRL */
10667 if (mode >= LATENCY_CRT_DATA_MODE_LAST) {
10668 return BCME_BADARG;
10669 }
10670 #ifdef DHD_GRO_ENABLE_HOST_CTRL
10671 dhdp = wl_cfg80211_get_dhdp(dev);
10672 if (mode != LATENCY_CRT_DATA_MODE_OFF) {
10673 ANDROID_ERROR(("Not permitted GRO by framework\n"));
10674 dhdp->permitted_gro = FALSE;
10675 } else {
10676 ANDROID_ERROR(("Permitted GRO by framework\n"));
10677 dhdp->permitted_gro = TRUE;
10678 }
10679 #endif /* DHD_GRO_ENABLE_HOST_CTRL */
10680 ret = wldev_iovar_setint(dev, "latency_critical_data", mode);
10681 if (ret != BCME_OK) {
10682 ANDROID_ERROR(("failed to set latency_critical_data mode %d, error = %d\n",
10683 mode, ret));
10684 return ret;
10685 }
10686
10687 return ret;
10688 }
10689
10690 static int
wl_android_get_latency_crt_data(struct net_device * dev,char * command,int total_len)10691 wl_android_get_latency_crt_data(struct net_device *dev, char *command, int total_len)
10692 {
10693 int ret;
10694 int mode = LATENCY_CRT_DATA_MODE_OFF;
10695 int bytes_written;
10696
10697 ret = wldev_iovar_getint(dev, "latency_critical_data", &mode);
10698 if (ret != BCME_OK) {
10699 ANDROID_ERROR(("failed to get latency_critical_data error = %d\n", ret));
10700 return ret;
10701 }
10702
10703 bytes_written = snprintf(command, total_len, "%s %d",
10704 CMD_GET_LATENCY_CRITICAL_DATA, mode);
10705
10706 return bytes_written;
10707 }
10708 #endif /* SUPPORT_LATENCY_CRITICAL_DATA */
10709
10710 #ifdef WL_CAC_TS
10711 /* CAC TSPEC functionality code implementation */
10712 static void
wl_android_update_tsinfo(uint8 access_category,tspec_arg_t * tspec_arg)10713 wl_android_update_tsinfo(uint8 access_category, tspec_arg_t *tspec_arg)
10714 {
10715 uint8 tspec_id;
10716 /* Using direction as bidirectional by default */
10717 uint8 direction = TSPEC_BI_DIRECTION;
10718 /* Using U-APSD as the default power save mode */
10719 uint8 user_psb = TSPEC_UAPSD_PSB;
10720 uint8 ADDTS_AC2PRIO[4] = {PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_VI, PRIO_8021D_VO};
10721
10722 /* Map tspec_id from access category */
10723 tspec_id = ADDTS_AC2PRIO[access_category];
10724
10725 /* Update the tsinfo */
10726 tspec_arg->tsinfo.octets[0] = (uint8)(TSPEC_EDCA_ACCESS | direction |
10727 (tspec_id << TSPEC_TSINFO_TID_SHIFT));
10728 tspec_arg->tsinfo.octets[1] = (uint8)((tspec_id << TSPEC_TSINFO_PRIO_SHIFT) |
10729 user_psb);
10730 tspec_arg->tsinfo.octets[2] = 0x00;
10731 }
10732
10733 static s32
wl_android_handle_cac_action(struct bcm_cfg80211 * cfg,struct net_device * ndev,char * argv)10734 wl_android_handle_cac_action(struct bcm_cfg80211 * cfg, struct net_device * ndev, char * argv)
10735 {
10736 tspec_arg_t tspec_arg;
10737 s32 err = BCME_ERROR;
10738 u8 ts_cmd[12] = "cac_addts";
10739 uint8 access_category;
10740 s32 bssidx;
10741
10742 /* Following handling is done only for the primary interface */
10743 memset_s(&tspec_arg, sizeof(tspec_arg), 0, sizeof(tspec_arg));
10744 if (strncmp(argv, "addts", strlen("addts")) == 0) {
10745 tspec_arg.version = TSPEC_ARG_VERSION;
10746 tspec_arg.length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
10747 /* Read the params passed */
10748 sscanf(argv, "%*s %hhu %hu %hu", &access_category,
10749 &tspec_arg.nom_msdu_size, &tspec_arg.surplus_bw);
10750 if ((access_category > TSPEC_MAX_ACCESS_CATEGORY) ||
10751 ((tspec_arg.surplus_bw < TSPEC_MIN_SURPLUS_BW) ||
10752 (tspec_arg.surplus_bw > TSPEC_MAX_SURPLUS_BW)) ||
10753 (tspec_arg.nom_msdu_size > TSPEC_MAX_MSDU_SIZE)) {
10754 ANDROID_ERROR(("Invalid params access_category %hhu nom_msdu_size %hu"
10755 " surplus BW %hu\n", access_category, tspec_arg.nom_msdu_size,
10756 tspec_arg.surplus_bw));
10757 return BCME_USAGE_ERROR;
10758 }
10759
10760 /* Update tsinfo */
10761 wl_android_update_tsinfo(access_category, &tspec_arg);
10762 /* Update other tspec parameters */
10763 tspec_arg.dialog_token = TSPEC_DEF_DIALOG_TOKEN;
10764 tspec_arg.mean_data_rate = TSPEC_DEF_MEAN_DATA_RATE;
10765 tspec_arg.min_phy_rate = TSPEC_DEF_MIN_PHY_RATE;
10766 } else if (strncmp(argv, "delts", strlen("delts")) == 0) {
10767 snprintf(ts_cmd, sizeof(ts_cmd), "cac_delts");
10768 tspec_arg.length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
10769 tspec_arg.version = TSPEC_ARG_VERSION;
10770 /* Read the params passed */
10771 sscanf(argv, "%*s %hhu", &access_category);
10772
10773 if (access_category > TSPEC_MAX_ACCESS_CATEGORY) {
10774 ANDROID_INFO(("Invalide param, access_category %hhu\n", access_category));
10775 return BCME_USAGE_ERROR;
10776 }
10777 /* Update tsinfo */
10778 wl_android_update_tsinfo(access_category, &tspec_arg);
10779 }
10780
10781 if ((bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr)) < 0) {
10782 ANDROID_ERROR(("Find index failed\n"));
10783 err = BCME_ERROR;
10784 return err;
10785 }
10786 err = wldev_iovar_setbuf_bsscfg(ndev, ts_cmd, &tspec_arg, sizeof(tspec_arg),
10787 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
10788 if (unlikely(err)) {
10789 ANDROID_ERROR(("%s error (%d)\n", ts_cmd, err));
10790 }
10791
10792 return err;
10793 }
10794
10795 static s32
wl_android_cac_ts_config(struct net_device * ndev,char * cmd_argv,int total_len)10796 wl_android_cac_ts_config(struct net_device *ndev, char *cmd_argv, int total_len)
10797 {
10798 struct bcm_cfg80211 *cfg = NULL;
10799 s32 err = BCME_OK;
10800
10801 if (!ndev) {
10802 ANDROID_ERROR(("ndev is NULL\n"));
10803 return -EINVAL;
10804 }
10805
10806 cfg = wl_get_cfg(ndev);
10807 if (!cfg) {
10808 ANDROID_ERROR(("cfg is NULL\n"));
10809 return -EINVAL;
10810 }
10811
10812 /* Request supported only for primary interface */
10813 if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
10814 ANDROID_ERROR(("Request on non-primary interface\n"));
10815 return -1;
10816 }
10817
10818 /* sync commands from user space */
10819 mutex_lock(&cfg->usr_sync);
10820 err = wl_android_handle_cac_action(cfg, ndev, cmd_argv);
10821 mutex_unlock(&cfg->usr_sync);
10822
10823 return err;
10824 }
10825 #endif /* WL_CAC_TS */
10826
10827 #ifdef WL_GET_CU
10828 /* Implementation to get channel usage from framework */
10829 static s32
wl_android_get_channel_util(struct net_device * ndev,char * command,int total_len)10830 wl_android_get_channel_util(struct net_device *ndev, char *command, int total_len)
10831 {
10832 s32 bytes_written, err = 0;
10833 wl_bssload_t bssload;
10834 u8 smbuf[WLC_IOCTL_SMLEN];
10835 u8 chan_use_percentage = 0;
10836
10837 if ((err = wldev_iovar_getbuf(ndev, "bssload_report", NULL,
10838 0, smbuf, WLC_IOCTL_SMLEN, NULL))) {
10839 ANDROID_ERROR(("Getting bssload report failed with err=%d \n", err));
10840 return err;
10841 }
10842
10843 (void)memcpy_s(&bssload, sizeof(wl_bssload_t), smbuf, sizeof(wl_bssload_t));
10844 /* Convert channel usage to percentage value */
10845 chan_use_percentage = (bssload.chan_util * 100) / 255;
10846
10847 bytes_written = snprintf(command, total_len, "CU %hhu",
10848 chan_use_percentage);
10849 ANDROID_INFO(("Channel Utilization %u %u\n", bssload.chan_util, chan_use_percentage));
10850
10851 return bytes_written;
10852 }
10853 #endif /* WL_GET_CU */
10854
10855 #ifdef RTT_GEOFENCE_INTERVAL
10856 #if defined (RTT_SUPPORT) && defined(WL_NAN)
10857 static void
wl_android_set_rtt_geofence_interval(struct net_device * ndev,char * command)10858 wl_android_set_rtt_geofence_interval(struct net_device *ndev, char *command)
10859 {
10860 int rtt_interval = 0;
10861 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(ndev);
10862 char *rtt_intp = command + strlen(CMD_GEOFENCE_INTERVAL) + 1;
10863
10864 rtt_interval = bcm_atoi(rtt_intp);
10865 dhd_rtt_set_geofence_rtt_interval(dhdp, rtt_interval);
10866 }
10867 #endif /* RTT_SUPPORT && WL_NAN */
10868 #endif /* RTT_GEOFENCE_INTERVAL */
10869
10870 #ifdef SUPPORT_SOFTAP_ELNA_BYPASS
10871 int
wl_android_set_softap_elna_bypass(struct net_device * dev,char * command,int total_len)10872 wl_android_set_softap_elna_bypass(struct net_device *dev, char *command, int total_len)
10873 {
10874 char *ifname = NULL;
10875 char *pos, *token;
10876 int err = BCME_OK;
10877 int enable = FALSE;
10878
10879 /*
10880 * STA/AP/GO I/F: DRIVER SET_SOFTAP_ELNA_BYPASS <ifname> <enable/disable>
10881 * the enable/disable format follows Samsung specific rules as following
10882 * Enable : 0
10883 * Disable :-1
10884 */
10885 pos = command;
10886
10887 /* drop command */
10888 token = bcmstrtok(&pos, " ", NULL);
10889
10890 /* get the interface name */
10891 token = bcmstrtok(&pos, " ", NULL);
10892 if (!token) {
10893 ANDROID_ERROR(("%s: Invalid arguments about interface name\n", __FUNCTION__));
10894 return -EINVAL;
10895 }
10896 ifname = token;
10897
10898 /* get enable/disable flag */
10899 token = bcmstrtok(&pos, " ", NULL);
10900 if (!token) {
10901 ANDROID_ERROR(("%s: Invalid arguments about Enable/Disable\n", __FUNCTION__));
10902 return -EINVAL;
10903 }
10904 enable = bcm_atoi(token);
10905
10906 CUSTOMER_HW4_EN_CONVERT(enable);
10907 err = wl_set_softap_elna_bypass(dev, ifname, enable);
10908 if (unlikely(err)) {
10909 ANDROID_ERROR(("%s: Failed to set ELNA Bypass of SoftAP mode, err=%d\n",
10910 __FUNCTION__, err));
10911 return err;
10912 }
10913
10914 return err;
10915 }
10916
10917 int
wl_android_get_softap_elna_bypass(struct net_device * dev,char * command,int total_len)10918 wl_android_get_softap_elna_bypass(struct net_device *dev, char *command, int total_len)
10919 {
10920 char *ifname = NULL;
10921 char *pos, *token;
10922 int err = BCME_OK;
10923 int bytes_written = 0;
10924 int softap_elnabypass = 0;
10925
10926 /*
10927 * STA/AP/GO I/F: DRIVER GET_SOFTAP_ELNA_BYPASS <ifname>
10928 */
10929 pos = command;
10930
10931 /* drop command */
10932 token = bcmstrtok(&pos, " ", NULL);
10933
10934 /* get the interface name */
10935 token = bcmstrtok(&pos, " ", NULL);
10936 if (!token) {
10937 ANDROID_ERROR(("%s: Invalid arguments about interface name\n", __FUNCTION__));
10938 return -EINVAL;
10939 }
10940 ifname = token;
10941
10942 err = wl_get_softap_elna_bypass(dev, ifname, &softap_elnabypass);
10943 if (unlikely(err)) {
10944 ANDROID_ERROR(("%s: Failed to get ELNA Bypass of SoftAP mode, err=%d\n",
10945 __FUNCTION__, err));
10946 return err;
10947 } else {
10948 softap_elnabypass--; //Convert format to Customer HW4
10949 ANDROID_INFO(("%s: eLNA Bypass feature enable status is %d\n",
10950 __FUNCTION__, softap_elnabypass));
10951 bytes_written = snprintf(command, total_len, "%s %d",
10952 CMD_GET_SOFTAP_ELNA_BYPASS, softap_elnabypass);
10953 }
10954
10955 return bytes_written;
10956 }
10957 #endif /* SUPPORT_SOFTAP_ELNA_BYPASS */
10958
10959 #ifdef WL_NAN
10960 int
wl_android_get_nan_status(struct net_device * dev,char * command,int total_len)10961 wl_android_get_nan_status(struct net_device *dev, char *command, int total_len)
10962 {
10963 int bytes_written = 0;
10964 int error = BCME_OK;
10965 wl_nan_conf_status_t nstatus;
10966
10967 error = wl_cfgnan_get_status(dev, &nstatus);
10968 if (error) {
10969 ANDROID_ERROR(("Failed to get nan status (%d)\n", error));
10970 return error;
10971 }
10972
10973 bytes_written = snprintf(command, total_len,
10974 "EN:%d Role:%d EM:%d CID:"MACF" NMI:"MACF" SC(2G):%d SC(5G):%d "
10975 "MR:"NMRSTR" AMR:"NMRSTR" IMR:"NMRSTR
10976 "HC:%d AMBTT:%04x TSF[%04x:%04x]\n",
10977 nstatus.enabled,
10978 nstatus.role,
10979 nstatus.election_mode,
10980 ETHERP_TO_MACF(&(nstatus.cid)),
10981 ETHERP_TO_MACF(&(nstatus.nmi)),
10982 nstatus.social_chans[0],
10983 nstatus.social_chans[1],
10984 NMR2STR(nstatus.mr),
10985 NMR2STR(nstatus.amr),
10986 NMR2STR(nstatus.imr),
10987 nstatus.hop_count,
10988 nstatus.ambtt,
10989 nstatus.cluster_tsf_h,
10990 nstatus.cluster_tsf_l);
10991 return bytes_written;
10992 }
10993 #endif /* WL_NAN */
10994
10995 #ifdef SUPPORT_NAN_RANGING_TEST_BW
10996 enum {
10997 NAN_RANGING_5G_BW20 = 1,
10998 NAN_RANGING_5G_BW40,
10999 NAN_RANGING_5G_BW80
11000 };
11001
11002 int
wl_nan_ranging_bw(struct net_device * net,int bw,char * command)11003 wl_nan_ranging_bw(struct net_device *net, int bw, char *command)
11004 {
11005 int bytes_written, err = BCME_OK;
11006 u8 ioctl_buf[WLC_IOCTL_SMLEN];
11007 s32 val = 1;
11008 struct {
11009 u32 band;
11010 u32 bw_cap;
11011 } param = {0, 0};
11012
11013 if (bw < NAN_RANGING_5G_BW20 || bw > NAN_RANGING_5G_BW80) {
11014 ANDROID_ERROR(("Wrong BW cmd:%d, %s\n", bw, __FUNCTION__));
11015 bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
11016 return bytes_written;
11017 }
11018
11019 switch (bw) {
11020 case NAN_RANGING_5G_BW20:
11021 ANDROID_ERROR(("NAN_RANGING 5G/BW20\n"));
11022 param.band = WLC_BAND_5G;
11023 param.bw_cap = 0x1;
11024 break;
11025 case NAN_RANGING_5G_BW40:
11026 ANDROID_ERROR(("NAN_RANGING 5G/BW40\n"));
11027 param.band = WLC_BAND_5G;
11028 param.bw_cap = 0x3;
11029 break;
11030 case NAN_RANGING_5G_BW80:
11031 ANDROID_ERROR(("NAN_RANGING 5G/BW80\n"));
11032 param.band = WLC_BAND_5G;
11033 param.bw_cap = 0x7;
11034 break;
11035 }
11036
11037 err = wldev_ioctl_set(net, WLC_DOWN, &val, sizeof(s32));
11038 if (err) {
11039 ANDROID_ERROR(("WLC_DOWN error %d\n", err));
11040 bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
11041 } else {
11042 err = wldev_iovar_setbuf(net, "bw_cap", ¶m, sizeof(param),
11043 ioctl_buf, sizeof(ioctl_buf), NULL);
11044
11045 if (err) {
11046 ANDROID_ERROR(("BW set failed\n"));
11047 bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
11048 } else {
11049 ANDROID_ERROR(("BW set done\n"));
11050 bytes_written = scnprintf(command, sizeof("OK"), "OK");
11051 }
11052
11053 err = wldev_ioctl_set(net, WLC_UP, &val, sizeof(s32));
11054 if (err < 0) {
11055 ANDROID_ERROR(("WLC_UP error %d\n", err));
11056 bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
11057 }
11058 }
11059 return bytes_written;
11060 }
11061 #endif /* SUPPORT_NAN_RANGING_TEST_BW */
11062
11063 static int
wl_android_set_softap_ax_mode(struct net_device * dev,const char * cmd_str)11064 wl_android_set_softap_ax_mode(struct net_device *dev, const char* cmd_str)
11065 {
11066 int enable = 0;
11067 int err = 0;
11068 s32 bssidx = 0;
11069 struct bcm_cfg80211 *cfg = NULL;
11070
11071 if (!dev) {
11072 err = -EINVAL;
11073 goto exit;
11074 }
11075
11076 cfg = wl_get_cfg(dev);
11077 if (!cfg) {
11078 err = -EINVAL;
11079 goto exit;
11080 }
11081
11082 if (cmd_str) {
11083 enable = bcm_atoi(cmd_str);
11084 } else {
11085 ANDROID_ERROR(("failed due to wrong received parameter\n"));
11086 err = -EINVAL;
11087 goto exit;
11088 }
11089
11090 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
11091 ANDROID_ERROR(("find softap index from wdev failed\n"));
11092 err = -EINVAL;
11093 goto exit;
11094 }
11095
11096 ANDROID_INFO(("HAPD_SET_AX_MODE = %d\n", enable));
11097 err = wl_cfg80211_set_he_mode(dev, cfg, bssidx, WL_HE_FEATURES_HE_AP, (bool)enable);
11098 if (err) {
11099 ANDROID_ERROR(("failed to set softap ax mode(%d)\n", enable));
11100
11101 }
11102 exit :
11103 return err;
11104 }
11105
11106 #ifdef WL_P2P_6G
11107 #define WL_HE_FEATURES_P2P_6G 0x0200u
11108 static int
wl_android_enable_p2p_6g(struct net_device * dev,int enable)11109 wl_android_enable_p2p_6g(struct net_device *dev, int enable)
11110 {
11111 s32 err = 0;
11112 s32 bssidx = 0;
11113 struct bcm_cfg80211 *cfg = NULL;
11114
11115 if (!dev) {
11116 err = -EINVAL;
11117 return err;
11118 }
11119
11120 cfg = wl_get_cfg(dev);
11121 if (!cfg) {
11122 err = -EINVAL;
11123 return err;
11124 }
11125
11126 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
11127 ANDROID_ERROR(("find softap index from wdev failed\n"));
11128 err = -EINVAL;
11129 return err;
11130 }
11131
11132 /* Enable/disable for P2P 6G, both P2P and P2P_6G needs to be handled together */
11133 err = wl_cfg80211_set_he_mode(dev, cfg, bssidx, (WL_HE_FEATURES_HE_P2P |
11134 WL_HE_FEATURES_P2P_6G), (bool)enable);
11135 if (err == BCME_OK) {
11136 /* Set P2P 6G support flag */
11137 if (enable) {
11138 cfg->p2p_6g_enabled = TRUE;
11139 } else {
11140 cfg->p2p_6g_enabled = FALSE;
11141 }
11142 }
11143
11144 return err;
11145 }
11146 #endif /* WL_P2P_6G */
11147
11148 #ifdef WL_TWT
11149
11150 static int
wl_android_twt_setup(struct net_device * ndev,char * command,int total_len)11151 wl_android_twt_setup(struct net_device *ndev, char *command, int total_len)
11152 {
11153 wl_twt_config_t val;
11154 s32 bw;
11155 char *token, *pos;
11156 u8 mybuf[WLC_IOCTL_SMLEN] = {0};
11157 u8 resp_buf[WLC_IOCTL_SMLEN] = {0};
11158 u64 twt;
11159 uint8 *rem = mybuf;
11160 uint16 rem_len = sizeof(mybuf);
11161 int32 val32;
11162
11163 WL_DBG_MEM(("Enter. cmd:%s\n", command));
11164
11165 if (strlen(command) == strlen(CMD_TWT_SETUP)) {
11166 ANDROID_ERROR(("Error, twt_setup cmd missing params\n"));
11167 bw = -EINVAL;
11168 goto exit;
11169 }
11170
11171 bzero(&val, sizeof(val));
11172 val.version = WL_TWT_SETUP_VER;
11173 val.length = sizeof(val.version) + sizeof(val.length);
11174
11175 /* Default values, Overide Below */
11176 val.desc.wake_time_h = 0xFFFFFFFF;
11177 val.desc.wake_time_l = 0xFFFFFFFF;
11178 val.desc.wake_int_min = 0xFFFFFFFF;
11179 val.desc.wake_int_max = 0xFFFFFFFF;
11180 val.desc.wake_dur_min = 0xFFFFFFFF;
11181 val.desc.wake_dur_max = 0xFFFFFFFF;
11182 val.desc.avg_pkt_num = 0xFFFFFFFF;
11183
11184 pos = command + sizeof(CMD_TWT_SETUP);
11185
11186 /* negotiation_type */
11187 token = strsep((char**)&pos, " ");
11188 if (!token) {
11189 ANDROID_ERROR(("Mandatory param negotiation type not present\n"));
11190 bw = -EINVAL;
11191 goto exit;
11192 }
11193 val.desc.negotiation_type = htod32((u32)bcm_atoi(token));
11194
11195 /* Wake Duration */
11196 token = strsep((char**)&pos, " ");
11197 if (!token) {
11198 ANDROID_ERROR(("Mandatory param wake Duration not present\n"));
11199 bw = -EINVAL;
11200 goto exit;
11201 }
11202 val.desc.wake_dur = htod32((u32)bcm_atoi(token));
11203
11204 /* Wake interval */
11205 token = strsep((char**)&pos, " ");
11206 if (!token) {
11207 ANDROID_ERROR(("Mandaory param Wake Interval not present\n"));
11208 bw = -EINVAL;
11209 goto exit;
11210 }
11211 val.desc.wake_int = htod32((u32)bcm_atoi(token));
11212
11213 /* Wake Time parameter */
11214 token = strsep((char**)&pos, " ");
11215 if (!token) {
11216 ANDROID_ERROR(("No Wake Time parameter provided, using default\n"));
11217 } else {
11218 twt = (u64)bcm_atoi(token);
11219 val32 = htod32((u32)(twt >> 32));
11220 if ((val32 != -1) && ((int32)(htod32((u32)twt)) != -1)) {
11221 val.desc.wake_time_h = htod32((u32)(twt >> 32));
11222 val.desc.wake_time_l = htod32((u32)twt);
11223 }
11224 }
11225
11226 /* Minimum allowed Wake interval */
11227 token = strsep((char**)&pos, " ");
11228 if (!token) {
11229 ANDROID_ERROR(("No Minimum allowed Wake interval provided, using default\n"));
11230 } else {
11231 val32 = htod32((u32)bcm_atoi(token));
11232 if (val32 != -1) {
11233 val.desc.wake_int_min = htod32((u32)bcm_atoi(token));
11234 }
11235 }
11236
11237 /* Max Allowed Wake interval */
11238 token = strsep((char**)&pos, " ");
11239 if (!token) {
11240 ANDROID_ERROR(("Maximum allowed Wake interval not provided, using default\n"));
11241 } else {
11242 val32 = htod32((u32)bcm_atoi(token));
11243 if (val32 != -1) {
11244 val.desc.wake_int_max = htod32((u32)bcm_atoi(token));
11245 }
11246 }
11247
11248 /* Minimum allowed Wake duration */
11249 token = strsep((char**)&pos, " ");
11250 if (!token) {
11251 ANDROID_ERROR(("Maximum allowed Wake duration not provided, using default\n"));
11252 } else {
11253 val32 = htod32((u32)bcm_atoi(token));
11254 if (val32 != -1) {
11255 val.desc.wake_dur_min = htod32((u32)bcm_atoi(token));
11256 }
11257 }
11258
11259 /* Maximum allowed Wake duration */
11260 token = strsep((char**)&pos, " ");
11261 if (!token) {
11262 ANDROID_ERROR(("Maximum allowed Wake duration not provided, using default\n"));
11263 } else {
11264 val32 = htod32((u32)bcm_atoi(token));
11265 if (val32 != -1) {
11266 val.desc.wake_dur_max = htod32((u32)bcm_atoi(token));
11267 }
11268 }
11269
11270 /* Average number of packets */
11271 token = strsep((char**)&pos, " ");
11272 if (!token) {
11273 ANDROID_ERROR(("Average number of packets not provided, using default\n"));
11274 } else {
11275 val32 = htod32((u32)bcm_atoi(token));
11276 if (val32 != -1) {
11277 val.desc.avg_pkt_num = htod32((u32)bcm_atoi(token));
11278 }
11279 }
11280
11281 /* a peer_address */
11282 token = strsep((char**)&pos, " ");
11283 if (!token) {
11284 ANDROID_ERROR(("Average number of packets not provided, using default\n"));
11285 } else {
11286 /* get peer mac */
11287 if (!bcm_ether_atoe(token, &val.peer)) {
11288 ANDROID_ERROR(("%s : Malformed peer addr\n", __FUNCTION__));
11289 bw = BCME_ERROR;
11290 goto exit;
11291 }
11292 }
11293
11294 bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_CONFIG,
11295 sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
11296 if (bw != BCME_OK) {
11297 goto exit;
11298 }
11299
11300 bw = wldev_iovar_setbuf(ndev, "twt",
11301 mybuf, sizeof(mybuf) - rem_len, resp_buf, WLC_IOCTL_SMLEN, NULL);
11302 if (bw < 0) {
11303 ANDROID_ERROR(("twt config set failed. ret:%d\n", bw));
11304 }
11305 exit:
11306 return bw;
11307 }
11308
11309 static int
wl_android_twt_display_cap(wl_twt_cap_t * result,char * command,int total_len)11310 wl_android_twt_display_cap(wl_twt_cap_t *result, char *command, int total_len)
11311 {
11312 int rem_len = 0, bytes_written = 0;
11313
11314 rem_len = total_len;
11315 bytes_written = scnprintf(command, rem_len, "Device TWT Capabilities:\n");
11316 command += bytes_written;
11317 rem_len -= bytes_written;
11318
11319 bytes_written = scnprintf(command, rem_len, "Requester Support %d, \t",
11320 !!(result->device_cap & WL_TWT_CAP_FLAGS_REQ_SUPPORT));
11321 command += bytes_written;
11322 rem_len -= bytes_written;
11323
11324 bytes_written = scnprintf(command, rem_len, "Responder Support %d, \t",
11325 !!(result->device_cap & WL_TWT_CAP_FLAGS_RESP_SUPPORT));
11326 command += bytes_written;
11327 rem_len -= bytes_written;
11328
11329 bytes_written = scnprintf(command, rem_len, "Broadcast TWT Support %d, \t",
11330 !!(result->device_cap & WL_TWT_CAP_FLAGS_BTWT_SUPPORT));
11331 command += bytes_written;
11332 rem_len -= bytes_written;
11333
11334 bytes_written = scnprintf(command, rem_len, "Flexible TWT Support %d, \t",
11335 !!(result->device_cap & WL_TWT_CAP_FLAGS_FLEX_SUPPORT));
11336 command += bytes_written;
11337 rem_len -= bytes_written;
11338
11339 bytes_written = scnprintf(command, rem_len, "TWT Required by peer %d, \n",
11340 !!(result->device_cap & WL_TWT_CAP_FLAGS_TWT_REQUIRED));
11341 command += bytes_written;
11342 rem_len -= bytes_written;
11343
11344 /* Peer capabilities */
11345 bytes_written = scnprintf(command, rem_len, "\nPeer TWT Capabilities:\n");
11346 command += bytes_written;
11347 rem_len -= bytes_written;
11348
11349 bytes_written = scnprintf(command, rem_len, "Requester Support %d, \t",
11350 !!(result->peer_cap & WL_TWT_CAP_FLAGS_REQ_SUPPORT));
11351 command += bytes_written;
11352 rem_len -= bytes_written;
11353
11354 bytes_written = scnprintf(command, rem_len, "Responder Support %d, \t",
11355 !!(result->peer_cap & WL_TWT_CAP_FLAGS_RESP_SUPPORT));
11356 command += bytes_written;
11357 rem_len -= bytes_written;
11358
11359 bytes_written = scnprintf(command, rem_len, "Broadcast TWT Support %d, \t",
11360 !!(result->peer_cap & WL_TWT_CAP_FLAGS_BTWT_SUPPORT));
11361 command += bytes_written;
11362 rem_len -= bytes_written;
11363
11364 bytes_written = scnprintf(command, rem_len, "Flexible TWT Support %d, \t",
11365 !!(result->peer_cap & WL_TWT_CAP_FLAGS_FLEX_SUPPORT));
11366 command += bytes_written;
11367 rem_len -= bytes_written;
11368
11369 bytes_written = scnprintf(command, rem_len, "TWT Required by peer %d, \n",
11370 !!(result->peer_cap & WL_TWT_CAP_FLAGS_TWT_REQUIRED));
11371 command += bytes_written;
11372 rem_len -= bytes_written;
11373
11374 bytes_written = scnprintf(command, rem_len, "\t------------"
11375 "---------------------------------------------------\n\n");
11376 command += bytes_written;
11377 rem_len -= bytes_written;
11378 ANDROID_INFO(("Device TWT Capabilities:\n"));
11379 ANDROID_INFO(("Requester Support %d, \t",
11380 !!(result->device_cap & WL_TWT_CAP_FLAGS_REQ_SUPPORT)));
11381 ANDROID_INFO(("Responder Support %d, \t",
11382 !!(result->device_cap & WL_TWT_CAP_FLAGS_RESP_SUPPORT)));
11383 ANDROID_INFO(("Broadcast TWT Support %d, \t",
11384 !!(result->device_cap & WL_TWT_CAP_FLAGS_BTWT_SUPPORT)));
11385 ANDROID_INFO(("Flexible TWT Support %d, \t",
11386 !!(result->device_cap & WL_TWT_CAP_FLAGS_FLEX_SUPPORT)));
11387 ANDROID_INFO(("TWT Required by peer %d, \n",
11388 !!(result->device_cap & WL_TWT_CAP_FLAGS_TWT_REQUIRED)));
11389 /* Peer capabilities */
11390 ANDROID_INFO(("\nPeer TWT Capabilities:\n"));
11391 ANDROID_INFO(("Requester Support %d, \t",
11392 !!(result->peer_cap & WL_TWT_CAP_FLAGS_REQ_SUPPORT)));
11393 ANDROID_INFO(("Responder Support %d, \t",
11394 !!(result->peer_cap & WL_TWT_CAP_FLAGS_RESP_SUPPORT)));
11395 ANDROID_INFO(("Broadcast TWT Support %d, \t",
11396 !!(result->peer_cap & WL_TWT_CAP_FLAGS_BTWT_SUPPORT)));
11397 ANDROID_INFO(("Flexible TWT Support %d, \t",
11398 !!(result->peer_cap & WL_TWT_CAP_FLAGS_FLEX_SUPPORT)));
11399 ANDROID_INFO(("TWT Required by peer %d, \n",
11400 !!(result->peer_cap & WL_TWT_CAP_FLAGS_TWT_REQUIRED)));
11401 ANDROID_INFO(("\t-----------------------------------------------------------------\n\n"));
11402
11403 if ((total_len - rem_len) > 0) {
11404 return (total_len - rem_len);
11405 } else {
11406 return BCME_ERROR;
11407 }
11408 }
11409
11410 static int
wl_android_twt_cap(struct net_device * dev,char * command,int total_len)11411 wl_android_twt_cap(struct net_device *dev, char *command, int total_len)
11412 {
11413 int ret = BCME_OK;
11414 char iovbuf[WLC_IOCTL_SMLEN] = {0, };
11415 uint8 *pxtlv = NULL;
11416 uint8 *iovresp = NULL;
11417 wl_twt_cap_cmd_t cmd_cap;
11418 wl_twt_cap_t result;
11419
11420 uint16 buflen = 0, bufstart = 0;
11421 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
11422
11423 bzero(&cmd_cap, sizeof(cmd_cap));
11424
11425 cmd_cap.version = WL_TWT_CAP_CMD_VERSION_1;
11426 cmd_cap.length = sizeof(cmd_cap) - OFFSETOF(wl_twt_cap_cmd_t, peer);
11427
11428 iovresp = (uint8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
11429 if (iovresp == NULL) {
11430 ANDROID_ERROR(("%s: iov resp memory alloc exited\n", __FUNCTION__));
11431 goto exit;
11432 }
11433
11434 buflen = bufstart = WLC_IOCTL_SMLEN;
11435 pxtlv = (uint8 *)iovbuf;
11436
11437 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_TWT_CMD_CAP,
11438 sizeof(cmd_cap), (uint8 *)&cmd_cap, BCM_XTLV_OPTION_ALIGN32);
11439 if (ret != BCME_OK) {
11440 ANDROID_ERROR(("%s : Error return during pack xtlv :%d\n", __FUNCTION__, ret));
11441 goto exit;
11442 }
11443
11444 if ((ret = wldev_iovar_getbuf(dev, "twt", iovbuf, bufstart-buflen,
11445 iovresp, WLC_IOCTL_MEDLEN, NULL))) {
11446 ANDROID_ERROR(("Getting twt status failed with err=%d \n", ret));
11447 goto exit;
11448 }
11449 if (ret) {
11450 ANDROID_ERROR(("%s : Error return during twt iovar set :%d\n", __FUNCTION__, ret));
11451 }
11452
11453 (void)memcpy_s(&result, sizeof(result), iovresp, sizeof(result));
11454
11455 if (dtoh16(result.version) == WL_TWT_CAP_CMD_VERSION_1) {
11456 ANDROID_ERROR(("capability ver %d, \n", dtoh16(result.version)));
11457 ret = wl_android_twt_display_cap(&result, command, total_len);
11458 return ret;
11459 } else {
11460 ret = BCME_UNSUPPORTED;
11461 ANDROID_ERROR(("Version 1 unsupported. ver %d, \n", dtoh16(result.version)));
11462 goto exit;
11463 }
11464
11465 exit:
11466 if (iovresp) {
11467 MFREE(cfg->osh, iovresp, WLC_IOCTL_MEDLEN);
11468 }
11469
11470 return ret;
11471 }
11472
11473 static int
wl_android_twt_status_display_v1(wl_twt_status_v1_t * status,char * command,int total_len)11474 wl_android_twt_status_display_v1(wl_twt_status_v1_t *status, char *command, int total_len)
11475 {
11476 uint i;
11477 wl_twt_sdesc_t *desc = NULL;
11478 int rem_len = 0, bytes_written = 0;
11479
11480 rem_len = total_len;
11481
11482 ANDROID_ERROR(("\nNumber of Individual TWTs: %d\n", status->num_fid));
11483 bytes_written = scnprintf(command, rem_len,
11484 "\nNumber of Individual TWTs: %d\n", status->num_fid);
11485 command += bytes_written;
11486 rem_len -= bytes_written;
11487 bytes_written = scnprintf(command, rem_len,
11488 "Number of Broadcast TWTs: %d\n", status->num_bid);
11489 command += bytes_written;
11490 rem_len -= bytes_written;
11491 bytes_written = scnprintf(command, rem_len,
11492 "TWT SPPS Enabled %d \t STA Wake Status %d \t Wake Override %d\n",
11493 !!(status->status_flags & WL_TWT_STATUS_FLAG_SPPS_ENAB),
11494 !!(status->status_flags & WL_TWT_STATUS_FLAG_WAKE_STATE),
11495 !!(status->status_flags & WL_TWT_STATUS_FLAG_WAKE_OVERRIDE));
11496 command += bytes_written;
11497 rem_len -= bytes_written;
11498 ANDROID_INFO(("Number of Broadcast TWTs: %d\n", status->num_bid));
11499 ANDROID_INFO(("TWT SPPS Enabled %d \t STA Wake Status %d \t Wake Override %d\n",
11500 !!(status->status_flags & WL_TWT_STATUS_FLAG_SPPS_ENAB),
11501 !!(status->status_flags & WL_TWT_STATUS_FLAG_WAKE_STATE),
11502 !!(status->status_flags & WL_TWT_STATUS_FLAG_WAKE_OVERRIDE)));
11503 ANDROID_INFO(("\t---------------- Individual TWT list-------------------\n"));
11504 bytes_written = scnprintf(command, rem_len,
11505 "\t---------------- Individual TWT list-------------------\n");
11506 command += bytes_written;
11507 rem_len -= bytes_written;
11508
11509 for (i = 0; i < WL_TWT_MAX_ITWT; i ++) {
11510 if ((status->itwt_status[i].state == WL_TWT_ACTIVE) ||
11511 (status->itwt_status[i].state == WL_TWT_SUSPEND)) {
11512 desc = &status->itwt_status[i].desc;
11513 bytes_written = scnprintf(command, rem_len, "\tFlow ID %d \tState %d\t",
11514 desc->flow_id,
11515 status->itwt_status[i].state);
11516 command += bytes_written;
11517 rem_len -= bytes_written;
11518
11519 bytes_written = scnprintf(command, rem_len,
11520 "peer: "MACF"\n",
11521 ETHER_TO_MACF(status->itwt_status[i].peer));
11522 command += bytes_written;
11523 rem_len -= bytes_written;
11524
11525 bytes_written = scnprintf(command, rem_len,
11526 "Unannounced %d\tTriggered %d\tProtection %d\t"
11527 "Info Frame Disabled %d\n",
11528 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_UNANNOUNCED),
11529 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_TRIGGER),
11530 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_PROTECT),
11531 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_INFO_FRM_DISABLED));
11532 command += bytes_written;
11533 rem_len -= bytes_written;
11534
11535 bytes_written = scnprintf(command, rem_len,
11536 "target wake time: 0x%08x%08x\t",
11537 desc->wake_time_h, desc->wake_time_l);
11538 command += bytes_written;
11539 rem_len -= bytes_written;
11540
11541 bytes_written = scnprintf(command, rem_len,
11542 "wake duration: %u\t", desc->wake_dur);
11543 command += bytes_written;
11544 rem_len -= bytes_written;
11545
11546 bytes_written = scnprintf(command, rem_len,
11547 "wake interval: %u\t", desc->wake_int);
11548 command += bytes_written;
11549 rem_len -= bytes_written;
11550
11551 bytes_written = scnprintf(command, rem_len,
11552 "TWT channel: %u\n", desc->channel);
11553 command += bytes_written;
11554 rem_len -= bytes_written;
11555 ANDROID_INFO(("\tFlow ID %d \tState %d\t",
11556 desc->flow_id,
11557 status->itwt_status[i].state));
11558 ANDROID_INFO(("peer: "MACF"\n", ETHER_TO_MACF(status->itwt_status[i].peer)));
11559 ANDROID_INFO(("Unannounced %d\tTriggered %d\tProtection %d\t"
11560 "Info Frame Disabled %d\n",
11561 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_UNANNOUNCED),
11562 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_TRIGGER),
11563 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_PROTECT),
11564 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_INFO_FRM_DISABLED)));
11565 ANDROID_INFO(("target wake time: 0x%08x%08x\t",
11566 desc->wake_time_h, desc->wake_time_l));
11567 ANDROID_INFO(("wake duration: %u\t", desc->wake_dur));
11568 ANDROID_INFO(("wake interval: %u\t", desc->wake_int));
11569 ANDROID_INFO(("TWT channel: %u\n", desc->channel));
11570 }
11571 }
11572
11573 ANDROID_INFO(("\t---------------- Broadcast TWT list-------------------\n"));
11574 bytes_written = scnprintf(command, rem_len,
11575 "\t---------------- Broadcast TWT list-------------------\n");
11576 command += bytes_written;
11577 rem_len -= bytes_written;
11578 for (i = 0; i < WL_TWT_MAX_BTWT; i ++) {
11579 if ((status->btwt_status[i].state == WL_TWT_ACTIVE) ||
11580 (status->btwt_status[i].state == WL_TWT_SUSPEND)) {
11581 desc = &status->btwt_status[i].desc;
11582 bytes_written = scnprintf(command, rem_len,
11583 "Broadcast ID %d \tState %d\t",
11584 desc->bid, status->btwt_status[i].state);
11585 command += bytes_written;
11586 rem_len -= bytes_written;
11587
11588 bytes_written = scnprintf(command, rem_len,
11589 "peer: "MACF"\n",
11590 ETHER_TO_MACF(status->btwt_status[i].peer));
11591 command += bytes_written;
11592 rem_len -= bytes_written;
11593
11594 bytes_written = scnprintf(command, rem_len,
11595 "Unannounced %d\tTriggered %d\tProtection %d\t"
11596 "Info Frame Disabled %d\t",
11597 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_UNANNOUNCED),
11598 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_TRIGGER),
11599 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_PROTECT),
11600 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_INFO_FRM_DISABLED));
11601 command += bytes_written;
11602 rem_len -= bytes_written;
11603
11604 bytes_written = scnprintf(command, rem_len,
11605 "Frame Recommendation %d\tBTWT Persistence %d\n",
11606 desc->frame_recomm, desc->btwt_persistence);
11607 command += bytes_written;
11608 rem_len -= bytes_written;
11609
11610 bytes_written = scnprintf(command, rem_len,
11611 "target wake time: 0x%08x%08x\t",
11612 desc->wake_time_h, desc->wake_time_l);
11613 command += bytes_written;
11614 rem_len -= bytes_written;
11615 bytes_written = scnprintf(command, rem_len,
11616 "wake duration: %u\t", desc->wake_dur);
11617 command += bytes_written;
11618 rem_len -= bytes_written;
11619
11620 bytes_written = scnprintf(command, rem_len,
11621 "wake interval: %u\t", desc->wake_int);
11622 command += bytes_written;
11623 rem_len -= bytes_written;
11624
11625 bytes_written = scnprintf(command, rem_len,
11626 "TWT channel: %u\n", desc->channel);
11627 command += bytes_written;
11628 rem_len -= bytes_written;
11629 ANDROID_INFO(("Broadcast ID %d \tState %d\t",
11630 desc->bid, status->btwt_status[i].state));
11631 ANDROID_INFO(("peer: "MACF"\n", ETHER_TO_MACF(status->btwt_status[i].peer)));
11632 ANDROID_INFO(("Unannounced %d\tTriggered %d\tProtection %d\t"
11633 "Info Frame Disabled %d\t",
11634 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_UNANNOUNCED),
11635 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_TRIGGER),
11636 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_PROTECT),
11637 !!(desc->flow_flags & WL_TWT_FLOW_FLAG_INFO_FRM_DISABLED)));
11638 ANDROID_INFO(("Frame Recommendation %d\tBTWT Persistence %d\n",
11639 desc->frame_recomm, desc->btwt_persistence));
11640 ANDROID_INFO(("target wake time: 0x%08x%08x\t",
11641 desc->wake_time_h, desc->wake_time_l));
11642 ANDROID_INFO(("wake duration: %u\t", desc->wake_dur));
11643 ANDROID_INFO(("wake interval: %u\t", desc->wake_int));
11644 ANDROID_INFO(("TWT channel: %u\n", desc->channel));
11645 }
11646 }
11647
11648 if ((total_len - rem_len) > 0) {
11649 return (total_len - rem_len);
11650 } else {
11651 return BCME_ERROR;
11652 }
11653 }
11654
11655 static int
wl_android_twt_status_query(struct net_device * dev,char * command,int total_len)11656 wl_android_twt_status_query(struct net_device *dev, char *command, int total_len)
11657 {
11658 int ret = BCME_OK;
11659 char iovbuf[WLC_IOCTL_SMLEN] = {0, };
11660 uint8 *pxtlv = NULL;
11661 uint8 *iovresp = NULL;
11662 wl_twt_status_cmd_v1_t status_cmd;
11663 wl_twt_status_v1_t result;
11664
11665 uint16 buflen = 0, bufstart = 0;
11666 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
11667
11668 bzero(&status_cmd, sizeof(status_cmd));
11669
11670 status_cmd.version = WL_TWT_CMD_STATUS_VERSION_1;
11671 status_cmd.length = sizeof(status_cmd) - OFFSETOF(wl_twt_status_cmd_v1_t, peer);
11672
11673 iovresp = (uint8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
11674 if (iovresp == NULL) {
11675 ANDROID_ERROR(("%s: iov resp memory alloc exited\n", __FUNCTION__));
11676 goto exit;
11677 }
11678
11679 buflen = bufstart = WLC_IOCTL_SMLEN;
11680 pxtlv = (uint8 *)iovbuf;
11681
11682 ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_TWT_CMD_STATUS,
11683 sizeof(status_cmd), (uint8 *)&status_cmd, BCM_XTLV_OPTION_ALIGN32);
11684 if (ret != BCME_OK) {
11685 ANDROID_ERROR(("%s : Error return during pack xtlv :%d\n", __FUNCTION__, ret));
11686 goto exit;
11687 }
11688
11689 if ((ret = wldev_iovar_getbuf(dev, "twt", iovbuf, bufstart-buflen,
11690 iovresp, WLC_IOCTL_MEDLEN, NULL))) {
11691 ANDROID_ERROR(("Getting twt status failed with err=%d \n", ret));
11692 goto exit;
11693 }
11694 if (ret) {
11695 ANDROID_ERROR(("%s : Error return during twt iovar set :%d\n", __FUNCTION__, ret));
11696 }
11697
11698 (void)memcpy_s(&result, sizeof(result), iovresp, sizeof(result));
11699
11700 if (dtoh16(result.version) == WL_TWT_CMD_STATUS_VERSION_1) {
11701 ANDROID_ERROR(("status query ver %d, \n", dtoh16(result.version)));
11702 ret = wl_android_twt_status_display_v1(&result, command, total_len);
11703 return ret;
11704 } else {
11705 ret = BCME_UNSUPPORTED;
11706 ANDROID_ERROR(("Version 1 unsupported. ver %d, \n", dtoh16(result.version)));
11707 goto exit;
11708 }
11709
11710 exit:
11711 if (iovresp) {
11712 MFREE(cfg->osh, iovresp, WLC_IOCTL_MEDLEN);
11713 }
11714
11715 return ret;
11716 }
11717
11718 static int
wl_android_twt_info(struct net_device * ndev,char * command,int total_len)11719 wl_android_twt_info(struct net_device *ndev, char *command, int total_len)
11720 {
11721 wl_twt_info_t val;
11722 s32 bw;
11723 char *token, *pos;
11724 u8 mybuf[WLC_IOCTL_SMLEN] = {0};
11725 u8 res_buf[WLC_IOCTL_SMLEN] = {0};
11726 u64 twt;
11727 uint8 *rem = mybuf;
11728 uint16 rem_len = sizeof(mybuf);
11729 int32 val32;
11730
11731 WL_DBG_MEM(("Enter. cmd:%s\n", command));
11732
11733 if (strlen(command) == strlen(CMD_TWT_INFO)) {
11734 ANDROID_ERROR(("Error, twt teardown cmd missing params\n"));
11735 bw = -EINVAL;
11736 goto exit;
11737 }
11738
11739 bzero(&val, sizeof(val));
11740 val.version = WL_TWT_INFO_VER;
11741 val.length = sizeof(val.version) + sizeof(val.length);
11742
11743 /* Default values, Overide Below */
11744 val.infodesc.flow_id = 0xFF;
11745 val.desc.next_twt_h = 0xFFFFFFFF;
11746 val.desc.next_twt_l = 0xFFFFFFFF;
11747
11748 pos = command + sizeof(CMD_TWT_TEARDOWN);
11749
11750 /* (all TWT) */
11751 token = strsep((char**)&pos, " ");
11752 if (!token) {
11753 ANDROID_ERROR(("Mandatory all TWT type not present\n"));
11754 bw = -EINVAL;
11755 goto exit;
11756 }
11757 if (htod32((u32)bcm_atoi(token)) == 1) {
11758 val.infodesc.flow_flags |= WL_TWT_INFO_FLAG_ALL_TWT;
11759 }
11760
11761 /* Flow ID */
11762 token = strsep((char**)&pos, " ");
11763 if (!token) {
11764 ANDROID_ERROR(("flow ID not provided, using default\n"));
11765 } else {
11766 val32 = htod32((u32)bcm_atoi(token));
11767 if (val32 != -1) {
11768 val.infodesc.flow_id = htod32((u32)bcm_atoi(token));
11769 }
11770 }
11771
11772 /* resume offset */
11773 token = strsep((char**)&pos, " ");
11774 if (!token) {
11775 ANDROID_ERROR(("resume offset not provided, using default\n"));
11776 } else {
11777 twt = (u64)bcm_atoi(token);
11778 val32 = htod32((u32)(twt >> 32));
11779 if ((val32 != -1) && ((int32)(htod32((u32)twt)) != -1)) {
11780 val.infodesc.next_twt_h = htod32((u32)(twt >> 32));
11781 val.infodesc.next_twt_l = htod32((u32)twt);
11782 val.infodesc.flow_flags |= WL_TWT_INFO_FLAG_RESUME;
11783 }
11784 }
11785
11786 /* peer_address */
11787 token = strsep((char**)&pos, " ");
11788 if (!token) {
11789 ANDROID_ERROR(("Peer Addr not provided, using default\n"));
11790 } else {
11791 /* get peer mac */
11792 if (!bcm_ether_atoe(token, &val.peer)) {
11793 ANDROID_ERROR(("%s : Malformed peer addr\n", __FUNCTION__));
11794 bw = BCME_ERROR;
11795 goto exit;
11796 }
11797 }
11798
11799 bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_INFO,
11800 sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
11801 if (bw != BCME_OK) {
11802 goto exit;
11803 }
11804
11805 bw = wldev_iovar_setbuf(ndev, "twt",
11806 mybuf, sizeof(mybuf) - rem_len, res_buf, WLC_IOCTL_SMLEN, NULL);
11807 if (bw < 0) {
11808 ANDROID_ERROR(("twt teardown failed. ret:%d\n", bw));
11809 }
11810 exit:
11811 return bw;
11812
11813 }
11814
11815 static int
wl_android_twt_teardown(struct net_device * ndev,char * command,int total_len)11816 wl_android_twt_teardown(struct net_device *ndev, char *command, int total_len)
11817 {
11818 wl_twt_teardown_t val;
11819 s32 bw;
11820 char *token, *pos;
11821 u8 mybuf[WLC_IOCTL_SMLEN] = {0};
11822 u8 res_buf[WLC_IOCTL_SMLEN] = {0};
11823 uint8 *rem = mybuf;
11824 uint16 rem_len = sizeof(mybuf);
11825 int32 val32;
11826
11827 WL_DBG_MEM(("Enter. cmd:%s\n", command));
11828
11829 if (strlen(command) == strlen(CMD_TWT_TEARDOWN)) {
11830 ANDROID_ERROR(("Error, twt teardown cmd missing params\n"));
11831 bw = -EINVAL;
11832 goto exit;
11833 }
11834
11835 bzero(&val, sizeof(val));
11836 val.version = WL_TWT_TEARDOWN_VER;
11837 val.length = sizeof(val.version) + sizeof(val.length);
11838
11839 /* Default values, Overide Below */
11840 val.teardesc.flow_id = 0xFF;
11841 val.teardesc.bid = 0xFF;
11842
11843 pos = command + sizeof(CMD_TWT_TEARDOWN);
11844
11845 /* negotiation_type */
11846 token = strsep((char**)&pos, " ");
11847 if (!token) {
11848 ANDROID_ERROR(("Mandatory param negotiation type not present\n"));
11849 bw = -EINVAL;
11850 goto exit;
11851 }
11852 val.teardesc.negotiation_type = htod32((u32)bcm_atoi(token));
11853
11854 /* (all TWT) */
11855 token = strsep((char**)&pos, " ");
11856 if (!token) {
11857 ANDROID_ERROR(("Mandatory all TWT type not present\n"));
11858 bw = -EINVAL;
11859 goto exit;
11860 }
11861 val.teardesc.alltwt = htod32((u32)bcm_atoi(token));
11862
11863 /* Flow ID */
11864 token = strsep((char**)&pos, " ");
11865 if (!token) {
11866 ANDROID_ERROR(("flow ID not provided, using default\n"));
11867 } else {
11868 val32 = htod32((u32)bcm_atoi(token));
11869 if (val32 != -1) {
11870 val.teardesc.flow_id = htod32((u32)bcm_atoi(token));
11871 }
11872 }
11873
11874 /* Broadcas ID */
11875 token = strsep((char**)&pos, " ");
11876 if (!token) {
11877 ANDROID_ERROR(("flow ID not provided, using default\n"));
11878 } else {
11879 val32 = htod32((u32)bcm_atoi(token));
11880 if (val32 != -1) {
11881 val.teardesc.bid = htod32((u32)bcm_atoi(token));
11882 }
11883 }
11884
11885 /* peer_address */
11886 token = strsep((char**)&pos, " ");
11887 if (!token) {
11888 ANDROID_ERROR(("Peer Addr not provided, using default\n"));
11889 } else {
11890 /* get peer mac */
11891 if (!bcm_ether_atoe(token, &val.peer)) {
11892 ANDROID_ERROR(("%s : Malformed peer addr\n", __FUNCTION__));
11893 bw = BCME_ERROR;
11894 goto exit;
11895 }
11896 }
11897
11898 bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_TEARDOWN,
11899 sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
11900 if (bw != BCME_OK) {
11901 goto exit;
11902 }
11903
11904 bw = wldev_iovar_setbuf(ndev, "twt",
11905 mybuf, sizeof(mybuf) - rem_len, res_buf, WLC_IOCTL_SMLEN, NULL);
11906 if (bw < 0) {
11907 ANDROID_ERROR(("twt teardown failed. ret:%d\n", bw));
11908 }
11909 exit:
11910 return bw;
11911 }
11912 #endif /* WL_TWT */
11913
11914 int
wl_handle_private_cmd(struct net_device * net,char * command,u32 cmd_len)11915 wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
11916 {
11917 int bytes_written = 0;
11918 android_wifi_priv_cmd priv_cmd;
11919
11920 bzero(&priv_cmd, sizeof(android_wifi_priv_cmd));
11921 priv_cmd.total_len = cmd_len;
11922
11923 if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
11924 ANDROID_INFO(("%s, Received regular START command\n", __FUNCTION__));
11925 #ifdef SUPPORT_DEEP_SLEEP
11926 trigger_deep_sleep = 1;
11927 #else
11928 #ifdef BT_OVER_SDIO
11929 bytes_written = dhd_net_bus_get(net);
11930 #else
11931 bytes_written = wl_android_wifi_on(net);
11932 #endif /* BT_OVER_SDIO */
11933 #endif /* SUPPORT_DEEP_SLEEP */
11934 }
11935 else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) {
11936 bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len);
11937 }
11938
11939 if (!g_wifi_on) {
11940 ANDROID_ERROR(("%s: Ignore private cmd \"%s\" - iface is down\n",
11941 __FUNCTION__, command));
11942 return 0;
11943 }
11944
11945 if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
11946 #ifdef SUPPORT_DEEP_SLEEP
11947 trigger_deep_sleep = 1;
11948 #else
11949 #ifdef BT_OVER_SDIO
11950 bytes_written = dhd_net_bus_put(net);
11951 #else
11952 bytes_written = wl_android_wifi_off(net, FALSE);
11953 #endif /* BT_OVER_SDIO */
11954 #endif /* SUPPORT_DEEP_SLEEP */
11955 }
11956 #ifdef WL_CFG80211
11957 else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) {
11958 wl_cfg80211_set_passive_scan(net, command);
11959 }
11960 else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) {
11961 wl_cfg80211_set_passive_scan(net, command);
11962 }
11963 #endif /* WL_CFG80211 */
11964 else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
11965 bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len);
11966 }
11967 else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) {
11968 bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len);
11969 }
11970 #ifdef PKT_FILTER_SUPPORT
11971 else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) {
11972 bytes_written = net_os_enable_packet_filter(net, 1);
11973 }
11974 else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) {
11975 bytes_written = net_os_enable_packet_filter(net, 0);
11976 }
11977 else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) {
11978 int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
11979 bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
11980 }
11981 else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) {
11982 int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
11983 bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
11984 }
11985 #endif /* PKT_FILTER_SUPPORT */
11986 else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) {
11987 /* TBD: BTCOEXSCAN-START */
11988 }
11989 else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) {
11990 /* TBD: BTCOEXSCAN-STOP */
11991 }
11992 else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) {
11993 #ifdef WL_CFG80211
11994 void *dhdp = wl_cfg80211_get_dhdp(net);
11995 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, dhdp, command);
11996 #else
11997 #ifdef PKT_FILTER_SUPPORT
11998 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
11999
12000 if (mode == 1)
12001 net_os_enable_packet_filter(net, 0); /* DHCP starts */
12002 else
12003 net_os_enable_packet_filter(net, 1); /* DHCP ends */
12004 #endif /* PKT_FILTER_SUPPORT */
12005 #endif /* WL_CFG80211 */
12006 }
12007 else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
12008 bytes_written = wl_android_set_suspendopt(net, command);
12009 }
12010 else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) {
12011 bytes_written = wl_android_set_suspendmode(net, command);
12012 }
12013 else if (strnicmp(command, CMD_SETDTIM_IN_SUSPEND, strlen(CMD_SETDTIM_IN_SUSPEND)) == 0) {
12014 bytes_written = wl_android_set_bcn_li_dtim(net, command);
12015 }
12016 else if (strnicmp(command, CMD_MAXDTIM_IN_SUSPEND, strlen(CMD_MAXDTIM_IN_SUSPEND)) == 0) {
12017 bytes_written = wl_android_set_max_dtim(net, command);
12018 }
12019 #ifdef DISABLE_DTIM_IN_SUSPEND
12020 else if (strnicmp(command, CMD_DISDTIM_IN_SUSPEND, strlen(CMD_DISDTIM_IN_SUSPEND)) == 0) {
12021 bytes_written = wl_android_set_disable_dtim_in_suspend(net, command);
12022 }
12023 #endif /* DISABLE_DTIM_IN_SUSPEND */
12024 #ifdef WL_CFG80211
12025 else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
12026 bytes_written = wl_android_set_band(net, command);
12027 }
12028 #endif /* WL_CFG80211 */
12029 else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
12030 bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
12031 }
12032 #ifdef WL_CFG80211
12033 else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
12034 bytes_written = wl_android_set_csa(net, command);
12035 } else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
12036 bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
12037 } else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
12038 bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
12039 }
12040 #endif /* WL_CFG80211 */
12041 #ifndef CUSTOMER_SET_COUNTRY
12042 /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
12043 else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
12044 /*
12045 * Usage examples:
12046 * DRIVER COUNTRY US
12047 * DRIVER COUNTRY US/7
12048 * Wrong revinfo should be filtered:
12049 * DRIVER COUNTRY US/-1
12050 */
12051 char *country_code = command + strlen(CMD_COUNTRY) + 1;
12052 char *rev_info_delim = country_code + 2; /* 2 bytes of country code */
12053 int revinfo = -1;
12054 #if defined(DHD_BLOB_EXISTENCE_CHECK)
12055 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(net);
12056 #endif /* DHD_BLOB_EXISTENCE_CHECK */
12057 if ((rev_info_delim) &&
12058 (strnicmp(rev_info_delim, CMD_COUNTRY_DELIMITER,
12059 strlen(CMD_COUNTRY_DELIMITER)) == 0) &&
12060 (rev_info_delim + 1)) {
12061 revinfo = bcm_atoi(rev_info_delim + 1);
12062 } else {
12063 revinfo = 0;
12064 }
12065
12066 if (revinfo < 0) {
12067 ANDROID_ERROR(("%s:failed due to wrong revinfo %d\n", __FUNCTION__, revinfo));
12068 return BCME_BADARG;
12069 }
12070
12071 #if defined(DHD_BLOB_EXISTENCE_CHECK)
12072 if (dhdp->is_blob) {
12073 revinfo = 0;
12074 }
12075 #endif /* DHD_BLOB_EXISTENCE_CHECK */
12076
12077 #ifdef WL_CFG80211
12078 bytes_written = wl_cfg80211_set_country_code(net, country_code,
12079 true, true, revinfo);
12080 #ifdef CUSTOMER_HW4_PRIVATE_CMD
12081 #ifdef FCC_PWR_LIMIT_2G
12082 if (wldev_iovar_setint(net, "fccpwrlimit2g", FALSE)) {
12083 ANDROID_ERROR(("%s: fccpwrlimit2g deactivation is failed\n", __FUNCTION__));
12084 } else {
12085 ANDROID_ERROR(("%s: fccpwrlimit2g is deactivated\n", __FUNCTION__));
12086 }
12087 #endif /* FCC_PWR_LIMIT_2G */
12088 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
12089 #else
12090 bytes_written = wldev_set_country(net, country_code, true, true, revinfo);
12091 #endif /* WL_CFG80211 */
12092 }
12093 #endif /* CUSTOMER_SET_COUNTRY */
12094 else if (strnicmp(command, CMD_DATARATE, strlen(CMD_DATARATE)) == 0) {
12095 bytes_written = wl_android_get_datarate(net, command, priv_cmd.total_len);
12096 } else if (strnicmp(command, CMD_ASSOC_CLIENTS, strlen(CMD_ASSOC_CLIENTS)) == 0) {
12097 bytes_written = wl_android_get_assoclist(net, command, priv_cmd.total_len);
12098 }
12099
12100 #ifdef CUSTOMER_HW4_PRIVATE_CMD
12101 else if (strnicmp(command, CMD_ROAM_VSIE_ENAB_SET, strlen(CMD_ROAM_VSIE_ENAB_SET)) == 0) {
12102 bytes_written = wl_android_set_roam_vsie_enab(net, command, priv_cmd.total_len);
12103 } else if (strnicmp(command, CMD_ROAM_VSIE_ENAB_GET, strlen(CMD_ROAM_VSIE_ENAB_GET)) == 0) {
12104 bytes_written = wl_android_get_roam_vsie_enab(net, command, priv_cmd.total_len);
12105 } else if (strnicmp(command, CMD_BR_VSIE_ENAB_SET, strlen(CMD_BR_VSIE_ENAB_SET)) == 0) {
12106 bytes_written = wl_android_set_bcn_rpt_vsie_enab(net, command, priv_cmd.total_len);
12107 } else if (strnicmp(command, CMD_BR_VSIE_ENAB_GET, strlen(CMD_BR_VSIE_ENAB_GET)) == 0) {
12108 bytes_written = wl_android_get_bcn_rpt_vsie_enab(net, command, priv_cmd.total_len);
12109 }
12110 #ifdef WES_SUPPORT
12111 else if (strnicmp(command, CMD_GETNCHOMODE, strlen(CMD_GETNCHOMODE)) == 0) {
12112 bytes_written = wl_android_get_ncho_mode(net, command, priv_cmd.total_len);
12113 }
12114 else if (strnicmp(command, CMD_SETNCHOMODE, strlen(CMD_SETNCHOMODE)) == 0) {
12115 int mode;
12116 sscanf(command, "%*s %d", &mode);
12117 bytes_written = wl_android_set_ncho_mode(net, mode);
12118 }
12119 else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0) {
12120 bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len);
12121 }
12122 else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0) {
12123 bytes_written = wl_android_okc_enable(net, command);
12124 }
12125 else if (wl_android_legacy_check_command(net, command)) {
12126 bytes_written = wl_android_legacy_private_command(net, command, priv_cmd.total_len);
12127 }
12128 else if (wl_android_ncho_check_command(net, command)) {
12129 bytes_written = wl_android_ncho_private_command(net, command, priv_cmd.total_len);
12130 }
12131 #endif /* WES_SUPPORT */
12132 #if defined(SUPPORT_RESTORE_SCAN_PARAMS) || defined(WES_SUPPORT)
12133 else if (strnicmp(command, CMD_RESTORE_SCAN_PARAMS, strlen(CMD_RESTORE_SCAN_PARAMS)) == 0) {
12134 bytes_written = wl_android_default_set_scan_params(net, command,
12135 priv_cmd.total_len);
12136 }
12137 #endif /* SUPPORT_RESTORE_SCAN_PARAMS || WES_SUPPORT */
12138 #ifdef WLTDLS
12139 else if (strnicmp(command, CMD_TDLS_RESET, strlen(CMD_TDLS_RESET)) == 0) {
12140 bytes_written = wl_android_tdls_reset(net);
12141 }
12142 #endif /* WLTDLS */
12143 #ifdef CONFIG_SILENT_ROAM
12144 else if (strnicmp(command, CMD_SROAM_TURN_ON, strlen(CMD_SROAM_TURN_ON)) == 0) {
12145 int mode = *(command + strlen(CMD_SROAM_TURN_ON) + 1) - '0';
12146 bytes_written = wl_android_sroam_turn_on(net, mode);
12147 }
12148 else if (strnicmp(command, CMD_SROAM_SET_INFO, strlen(CMD_SROAM_SET_INFO)) == 0) {
12149 char *data = (command + strlen(CMD_SROAM_SET_INFO) + 1);
12150 bytes_written = wl_android_sroam_set_info(net, data, command, priv_cmd.total_len);
12151 }
12152 else if (strnicmp(command, CMD_SROAM_GET_INFO, strlen(CMD_SROAM_GET_INFO)) == 0) {
12153 bytes_written = wl_android_sroam_get_info(net, command, priv_cmd.total_len);
12154 }
12155 #endif /* CONFIG_SILENT_ROAM */
12156 #ifdef CONFIG_ROAM_RSSI_LIMIT
12157 else if (strnicmp(command, CMD_ROAM_RSSI_LMT, strlen(CMD_ROAM_RSSI_LMT)) == 0) {
12158 bytes_written = wl_android_roam_rssi_limit(net, command, priv_cmd.total_len);
12159 }
12160 #endif /* CONFIG_ROAM_RSSI_LIMIT */
12161 #ifdef CONFIG_ROAM_MIN_DELTA
12162 else if (strnicmp(command, CMD_ROAM_MIN_DELTA, strlen(CMD_ROAM_MIN_DELTA)) == 0) {
12163 bytes_written = wl_android_roam_min_delta(net, command, priv_cmd.total_len);
12164 }
12165 #endif /* CONFIG_ROAM_MIN_DELTA */
12166 else if (strnicmp(command, CMD_SET_DISCONNECT_IES, strlen(CMD_SET_DISCONNECT_IES)) == 0) {
12167 bytes_written = wl_android_set_disconnect_ies(net, command);
12168 }
12169 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
12170
12171 #ifdef PNO_SUPPORT
12172 else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
12173 bytes_written = dhd_dev_pno_stop_for_ssid(net);
12174 }
12175 #ifndef WL_SCHED_SCAN
12176 else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) {
12177 bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
12178 }
12179 #endif /* !WL_SCHED_SCAN */
12180 else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
12181 int enable = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
12182 bytes_written = (enable)? 0 : dhd_dev_pno_stop_for_ssid(net);
12183 }
12184 else if (strnicmp(command, CMD_WLS_BATCHING, strlen(CMD_WLS_BATCHING)) == 0) {
12185 bytes_written = wls_parse_batching_cmd(net, command, priv_cmd.total_len);
12186 }
12187 #endif /* PNO_SUPPORT */
12188 else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
12189 bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
12190 }
12191 else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
12192 int skip = strlen(CMD_P2P_SET_NOA) + 1;
12193 bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
12194 priv_cmd.total_len - skip);
12195 }
12196 #ifdef WL_SDO
12197 else if (strnicmp(command, CMD_P2P_SD_OFFLOAD, strlen(CMD_P2P_SD_OFFLOAD)) == 0) {
12198 u8 *buf = command;
12199 u8 *cmd_id = NULL;
12200 int len;
12201
12202 cmd_id = strsep((char **)&buf, " ");
12203 if (!cmd_id) {
12204 /* Propagate the error */
12205 bytes_written = -EINVAL;
12206 } else {
12207 /* if buf == NULL, means no arg */
12208 if (buf == NULL) {
12209 len = 0;
12210 } else {
12211 len = strlen(buf);
12212 }
12213 bytes_written = wl_cfg80211_sd_offload(net, cmd_id, buf, len);
12214 }
12215 }
12216 #endif /* WL_SDO */
12217 #ifdef P2P_LISTEN_OFFLOADING
12218 else if (strnicmp(command, CMD_P2P_LISTEN_OFFLOAD, strlen(CMD_P2P_LISTEN_OFFLOAD)) == 0) {
12219 u8 *sub_command = strchr(command, ' ');
12220 bytes_written = wl_cfg80211_p2plo_offload(net, command, sub_command,
12221 sub_command ? strlen(sub_command) : 0);
12222 }
12223 #endif /* P2P_LISTEN_OFFLOADING */
12224 #if !defined WL_ENABLE_P2P_IF
12225 else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
12226 bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
12227 }
12228 #endif /* WL_ENABLE_P2P_IF */
12229 else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
12230 int skip = strlen(CMD_P2P_SET_PS) + 1;
12231 bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
12232 priv_cmd.total_len - skip);
12233 }
12234 else if (strnicmp(command, CMD_P2P_ECSA, strlen(CMD_P2P_ECSA)) == 0) {
12235 int skip = strlen(CMD_P2P_ECSA) + 1;
12236 bytes_written = wl_cfg80211_set_p2p_ecsa(net, command + skip,
12237 priv_cmd.total_len - skip);
12238 }
12239 /* This command is not for normal VSDB operation but for only specific P2P operation.
12240 * Ex) P2P OTA backup operation
12241 */
12242 else if (strnicmp(command, CMD_P2P_INC_BW, strlen(CMD_P2P_INC_BW)) == 0) {
12243 int skip = strlen(CMD_P2P_INC_BW) + 1;
12244 bytes_written = wl_cfg80211_increase_p2p_bw(net,
12245 command + skip, priv_cmd.total_len - skip);
12246 }
12247 #ifdef WL_CFG80211
12248 else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE,
12249 strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) {
12250 int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3;
12251 bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
12252 priv_cmd.total_len - skip, *(command + skip - 2) - '0');
12253 }
12254 #ifdef WLFBT
12255 else if (strnicmp(command, CMD_GET_FTKEY, strlen(CMD_GET_FTKEY)) == 0) {
12256 bytes_written = wl_cfg80211_get_fbt_key(net, command, priv_cmd.total_len);
12257 }
12258 #endif /* WLFBT */
12259 #endif /* WL_CFG80211 */
12260 #if defined (WL_SUPPORT_AUTO_CHANNEL)
12261 else if (strnicmp(command, CMD_GET_BEST_CHANNELS,
12262 strlen(CMD_GET_BEST_CHANNELS)) == 0) {
12263 bytes_written = wl_android_get_best_channels(net, command,
12264 priv_cmd.total_len);
12265 }
12266 #endif /* WL_SUPPORT_AUTO_CHANNEL */
12267 #if defined (WL_SUPPORT_AUTO_CHANNEL)
12268 else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL,
12269 strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) {
12270 int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 1;
12271 bytes_written = wl_android_set_auto_channel(net, (const char*)command+skip, command,
12272 priv_cmd.total_len);
12273 }
12274 #endif /* WL_SUPPORT_AUTO_CHANNEL */
12275 #ifdef CUSTOMER_HW4_PRIVATE_CMD
12276 #ifdef SUPPORT_AMPDU_MPDU_CMD
12277 /* CMD_AMPDU_MPDU */
12278 else if (strnicmp(command, CMD_AMPDU_MPDU, strlen(CMD_AMPDU_MPDU)) == 0) {
12279 int skip = strlen(CMD_AMPDU_MPDU) + 1;
12280 bytes_written = wl_android_set_ampdu_mpdu(net, (const char*)command+skip);
12281 }
12282 #endif /* SUPPORT_AMPDU_MPDU_CMD */
12283 #if defined (SUPPORT_HIDDEN_AP)
12284 else if (strnicmp(command, CMD_SET_HAPD_MAX_NUM_STA,
12285 strlen(CMD_SET_HAPD_MAX_NUM_STA)) == 0) {
12286 int skip = strlen(CMD_SET_HAPD_MAX_NUM_STA) + 3;
12287 wl_android_set_max_num_sta(net, (const char*)command+skip);
12288 }
12289 else if (strnicmp(command, CMD_SET_HAPD_SSID,
12290 strlen(CMD_SET_HAPD_SSID)) == 0) {
12291 int skip = strlen(CMD_SET_HAPD_SSID) + 3;
12292 wl_android_set_ssid(net, (const char*)command+skip);
12293 }
12294 else if (strnicmp(command, CMD_SET_HAPD_HIDE_SSID,
12295 strlen(CMD_SET_HAPD_HIDE_SSID)) == 0) {
12296 int skip = strlen(CMD_SET_HAPD_HIDE_SSID) + 3;
12297 wl_android_set_hide_ssid(net, (const char*)command+skip);
12298 }
12299 #endif /* SUPPORT_HIDDEN_AP */
12300 #ifdef SUPPORT_SOFTAP_SINGL_DISASSOC
12301 else if (strnicmp(command, CMD_HAPD_STA_DISASSOC,
12302 strlen(CMD_HAPD_STA_DISASSOC)) == 0) {
12303 int skip = strlen(CMD_HAPD_STA_DISASSOC) + 1;
12304 wl_android_sta_diassoc(net, (const char*)command+skip);
12305 }
12306 #endif /* SUPPORT_SOFTAP_SINGL_DISASSOC */
12307 #ifdef SUPPORT_SET_LPC
12308 else if (strnicmp(command, CMD_HAPD_LPC_ENABLED,
12309 strlen(CMD_HAPD_LPC_ENABLED)) == 0) {
12310 int skip = strlen(CMD_HAPD_LPC_ENABLED) + 3;
12311 wl_android_set_lpc(net, (const char*)command+skip);
12312 }
12313 #endif /* SUPPORT_SET_LPC */
12314 #ifdef SUPPORT_TRIGGER_HANG_EVENT
12315 else if (strnicmp(command, CMD_TEST_FORCE_HANG,
12316 strlen(CMD_TEST_FORCE_HANG)) == 0) {
12317 int skip = strlen(CMD_TEST_FORCE_HANG) + 1;
12318 net_os_send_hang_message_reason(net, (const char*)command+skip);
12319 }
12320 #endif /* SUPPORT_TRIGGER_HANG_EVENT */
12321 else if (strnicmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0)
12322 bytes_written = wl_android_ch_res_rl(net, true);
12323 else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0)
12324 bytes_written = wl_android_ch_res_rl(net, false);
12325 #ifdef SUPPORT_LTECX
12326 else if (strnicmp(command, CMD_LTECX_SET, strlen(CMD_LTECX_SET)) == 0) {
12327 int skip = strlen(CMD_LTECX_SET) + 1;
12328 bytes_written = wl_android_set_ltecx(net, (const char*)command+skip);
12329 }
12330 #endif /* SUPPORT_LTECX */
12331 #ifdef WL_RELMCAST
12332 else if (strnicmp(command, CMD_SET_RMC_ENABLE, strlen(CMD_SET_RMC_ENABLE)) == 0) {
12333 int rmc_enable = *(command + strlen(CMD_SET_RMC_ENABLE) + 1) - '0';
12334 bytes_written = wl_android_rmc_enable(net, rmc_enable);
12335 }
12336 else if (strnicmp(command, CMD_SET_RMC_TXRATE, strlen(CMD_SET_RMC_TXRATE)) == 0) {
12337 int rmc_txrate;
12338 sscanf(command, "%*s %10d", &rmc_txrate);
12339 bytes_written = wldev_iovar_setint(net, "rmc_txrate", rmc_txrate * 2);
12340 }
12341 else if (strnicmp(command, CMD_SET_RMC_ACTPERIOD, strlen(CMD_SET_RMC_ACTPERIOD)) == 0) {
12342 int actperiod;
12343 sscanf(command, "%*s %10d", &actperiod);
12344 bytes_written = wldev_iovar_setint(net, "rmc_actf_time", actperiod);
12345 }
12346 else if (strnicmp(command, CMD_SET_RMC_IDLEPERIOD, strlen(CMD_SET_RMC_IDLEPERIOD)) == 0) {
12347 int acktimeout;
12348 sscanf(command, "%*s %10d", &acktimeout);
12349 acktimeout *= 1000;
12350 bytes_written = wldev_iovar_setint(net, "rmc_acktmo", acktimeout);
12351 }
12352 else if (strnicmp(command, CMD_SET_RMC_LEADER, strlen(CMD_SET_RMC_LEADER)) == 0) {
12353 int skip = strlen(CMD_SET_RMC_LEADER) + 1;
12354 bytes_written = wl_android_rmc_set_leader(net, (const char*)command+skip);
12355 }
12356 else if (strnicmp(command, CMD_SET_RMC_EVENT,
12357 strlen(CMD_SET_RMC_EVENT)) == 0) {
12358 bytes_written = wl_android_set_rmc_event(net, command);
12359 }
12360 #endif /* WL_RELMCAST */
12361 else if (strnicmp(command, CMD_GET_SCSCAN, strlen(CMD_GET_SCSCAN)) == 0) {
12362 bytes_written = wl_android_get_singlecore_scan(net, command, priv_cmd.total_len);
12363 }
12364 else if (strnicmp(command, CMD_SET_SCSCAN, strlen(CMD_SET_SCSCAN)) == 0) {
12365 bytes_written = wl_android_set_singlecore_scan(net, command);
12366 }
12367 #ifdef TEST_TX_POWER_CONTROL
12368 else if (strnicmp(command, CMD_TEST_SET_TX_POWER,
12369 strlen(CMD_TEST_SET_TX_POWER)) == 0) {
12370 int skip = strlen(CMD_TEST_SET_TX_POWER) + 1;
12371 wl_android_set_tx_power(net, (const char*)command+skip);
12372 }
12373 else if (strnicmp(command, CMD_TEST_GET_TX_POWER,
12374 strlen(CMD_TEST_GET_TX_POWER)) == 0) {
12375 wl_android_get_tx_power(net, command, priv_cmd.total_len);
12376 }
12377 #endif /* TEST_TX_POWER_CONTROL */
12378 else if (strnicmp(command, CMD_SARLIMIT_TX_CONTROL,
12379 strlen(CMD_SARLIMIT_TX_CONTROL)) == 0) {
12380 int skip = strlen(CMD_SARLIMIT_TX_CONTROL) + 1;
12381 bytes_written = wl_android_set_sarlimit_txctrl(net, (const char*)command+skip);
12382 }
12383 #ifdef SUPPORT_SET_TID
12384 else if (strnicmp(command, CMD_SET_TID, strlen(CMD_SET_TID)) == 0) {
12385 bytes_written = wl_android_set_tid(net, command);
12386 }
12387 else if (strnicmp(command, CMD_GET_TID, strlen(CMD_GET_TID)) == 0) {
12388 bytes_written = wl_android_get_tid(net, command, priv_cmd.total_len);
12389 }
12390 #endif /* SUPPORT_SET_TID */
12391 #ifdef WL_WTC
12392 else if (strnicmp(command, CMD_WTC_CONFIG, strlen(CMD_WTC_CONFIG)) == 0) {
12393 bytes_written = wl_android_wtc_config(net, command, priv_cmd.total_len);
12394 }
12395 #endif /* WL_WTC */
12396 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
12397 else if (strnicmp(command, CMD_HAPD_MAC_FILTER, strlen(CMD_HAPD_MAC_FILTER)) == 0) {
12398 int skip = strlen(CMD_HAPD_MAC_FILTER) + 1;
12399 wl_android_set_mac_address_filter(net, command+skip);
12400 }
12401 else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0)
12402 bytes_written = wl_android_set_roam_mode(net, command);
12403 #if defined(BCMFW_ROAM_ENABLE)
12404 else if (strnicmp(command, CMD_SET_ROAMPREF, strlen(CMD_SET_ROAMPREF)) == 0) {
12405 bytes_written = wl_android_set_roampref(net, command, priv_cmd.total_len);
12406 }
12407 #endif /* BCMFW_ROAM_ENABLE */
12408 #ifdef WL_CFG80211
12409 else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)
12410 bytes_written = wl_android_set_miracast(net, command);
12411 else if (strnicmp(command, CMD_SETIBSSBEACONOUIDATA, strlen(CMD_SETIBSSBEACONOUIDATA)) == 0)
12412 bytes_written = wl_android_set_ibss_beacon_ouidata(net,
12413 command, priv_cmd.total_len);
12414 #endif /* WL_CFG80211 */
12415 #ifdef WLAIBSS
12416 else if (strnicmp(command, CMD_SETIBSSTXFAILEVENT,
12417 strlen(CMD_SETIBSSTXFAILEVENT)) == 0)
12418 bytes_written = wl_android_set_ibss_txfail_event(net, command, priv_cmd.total_len);
12419 else if (strnicmp(command, CMD_GET_IBSS_PEER_INFO_ALL,
12420 strlen(CMD_GET_IBSS_PEER_INFO_ALL)) == 0)
12421 bytes_written = wl_android_get_ibss_peer_info(net, command, priv_cmd.total_len,
12422 TRUE);
12423 else if (strnicmp(command, CMD_GET_IBSS_PEER_INFO,
12424 strlen(CMD_GET_IBSS_PEER_INFO)) == 0)
12425 bytes_written = wl_android_get_ibss_peer_info(net, command, priv_cmd.total_len,
12426 FALSE);
12427 else if (strnicmp(command, CMD_SETIBSSROUTETABLE,
12428 strlen(CMD_SETIBSSROUTETABLE)) == 0)
12429 bytes_written = wl_android_set_ibss_routetable(net, command);
12430 else if (strnicmp(command, CMD_SETIBSSAMPDU, strlen(CMD_SETIBSSAMPDU)) == 0)
12431 bytes_written = wl_android_set_ibss_ampdu(net, command, priv_cmd.total_len);
12432 else if (strnicmp(command, CMD_SETIBSSANTENNAMODE, strlen(CMD_SETIBSSANTENNAMODE)) == 0)
12433 bytes_written = wl_android_set_ibss_antenna(net, command, priv_cmd.total_len);
12434 #endif /* WLAIBSS */
12435 else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) {
12436 int skip = strlen(CMD_KEEP_ALIVE) + 1;
12437 bytes_written = wl_keep_alive_set(net, command + skip);
12438 }
12439 #ifdef WL_CFG80211
12440 else if (strnicmp(command, CMD_ROAM_OFFLOAD, strlen(CMD_ROAM_OFFLOAD)) == 0) {
12441 int enable = *(command + strlen(CMD_ROAM_OFFLOAD) + 1) - '0';
12442 bytes_written = wl_cfg80211_enable_roam_offload(net, enable);
12443 }
12444 else if (strnicmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) {
12445 char *name = (command + strlen(CMD_INTERFACE_CREATE) +1);
12446 ANDROID_INFO(("Creating %s interface\n", name));
12447 if (wl_cfg80211_add_if(wl_get_cfg(net), net, WL_IF_TYPE_STA,
12448 name, NULL) == NULL) {
12449 bytes_written = -ENODEV;
12450 } else {
12451 /* Return success */
12452 bytes_written = 0;
12453 }
12454 }
12455 else if (strnicmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) {
12456 char *name = (command + strlen(CMD_INTERFACE_DELETE) +1);
12457 ANDROID_INFO(("Deleteing %s interface\n", name));
12458 bytes_written = wl_cfg80211_del_if(wl_get_cfg(net), net, NULL, name);
12459 }
12460 #endif /* WL_CFG80211 */
12461 else if (strnicmp(command, CMD_GET_LINK_STATUS, strlen(CMD_GET_LINK_STATUS)) == 0) {
12462 bytes_written = wl_android_get_link_status(net, command, priv_cmd.total_len);
12463 }
12464 #ifdef P2PRESP_WFDIE_SRC
12465 else if (strnicmp(command, CMD_P2P_SET_WFDIE_RESP,
12466 strlen(CMD_P2P_SET_WFDIE_RESP)) == 0) {
12467 int mode = *(command + strlen(CMD_P2P_SET_WFDIE_RESP) + 1) - '0';
12468 bytes_written = wl_android_set_wfdie_resp(net, mode);
12469 } else if (strnicmp(command, CMD_P2P_GET_WFDIE_RESP,
12470 strlen(CMD_P2P_GET_WFDIE_RESP)) == 0) {
12471 bytes_written = wl_android_get_wfdie_resp(net, command, priv_cmd.total_len);
12472 }
12473 #endif /* P2PRESP_WFDIE_SRC */
12474 #ifdef WL_CFG80211
12475 else if (strnicmp(command, CMD_DFS_AP_MOVE, strlen(CMD_DFS_AP_MOVE)) == 0) {
12476 char *data = (command + strlen(CMD_DFS_AP_MOVE) +1);
12477 bytes_written = wl_cfg80211_dfs_ap_move(net, data, command, priv_cmd.total_len);
12478 }
12479 #endif /* WL_CFG80211 */
12480 #ifdef WBTEXT
12481 else if (strnicmp(command, CMD_WBTEXT_ENABLE, strlen(CMD_WBTEXT_ENABLE)) == 0) {
12482 bytes_written = wl_android_wbtext(net, command, priv_cmd.total_len);
12483 }
12484 else if (strnicmp(command, CMD_WBTEXT_PROFILE_CONFIG,
12485 strlen(CMD_WBTEXT_PROFILE_CONFIG)) == 0) {
12486 char *data = (command + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
12487 bytes_written = wl_cfg80211_wbtext_config(net, data, command, priv_cmd.total_len);
12488 }
12489 else if (strnicmp(command, CMD_WBTEXT_WEIGHT_CONFIG,
12490 strlen(CMD_WBTEXT_WEIGHT_CONFIG)) == 0) {
12491 char *data = (command + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
12492 bytes_written = wl_cfg80211_wbtext_weight_config(net, data,
12493 command, priv_cmd.total_len);
12494 }
12495 else if (strnicmp(command, CMD_WBTEXT_TABLE_CONFIG,
12496 strlen(CMD_WBTEXT_TABLE_CONFIG)) == 0) {
12497 char *data = (command + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
12498 bytes_written = wl_cfg80211_wbtext_table_config(net, data,
12499 command, priv_cmd.total_len);
12500 }
12501 else if (strnicmp(command, CMD_WBTEXT_DELTA_CONFIG,
12502 strlen(CMD_WBTEXT_DELTA_CONFIG)) == 0) {
12503 char *data = (command + strlen(CMD_WBTEXT_DELTA_CONFIG) + 1);
12504 bytes_written = wl_cfg80211_wbtext_delta_config(net, data,
12505 command, priv_cmd.total_len);
12506 }
12507 else if (strnicmp(command, CMD_WBTEXT_BTM_TIMER_THRESHOLD,
12508 strlen(CMD_WBTEXT_BTM_TIMER_THRESHOLD)) == 0) {
12509 bytes_written = wl_cfg80211_wbtext_btm_timer_threshold(net, command,
12510 priv_cmd.total_len);
12511 }
12512 else if (strnicmp(command, CMD_WBTEXT_BTM_DELTA,
12513 strlen(CMD_WBTEXT_BTM_DELTA)) == 0) {
12514 bytes_written = wl_cfg80211_wbtext_btm_delta(net, command,
12515 priv_cmd.total_len);
12516 }
12517 else if (strnicmp(command, CMD_WBTEXT_ESTM_ENABLE,
12518 strlen(CMD_WBTEXT_ESTM_ENABLE)) == 0) {
12519 bytes_written = wl_cfg80211_wbtext_estm_enable(net, command,
12520 priv_cmd.total_len);
12521 }
12522 #endif /* WBTEXT */
12523 #ifdef WLWFDS
12524 else if (strnicmp(command, CMD_ADD_WFDS_HASH, strlen(CMD_ADD_WFDS_HASH)) == 0) {
12525 bytes_written = wl_android_set_wfds_hash(net, command, 1);
12526 }
12527 else if (strnicmp(command, CMD_DEL_WFDS_HASH, strlen(CMD_DEL_WFDS_HASH)) == 0) {
12528 bytes_written = wl_android_set_wfds_hash(net, command, 0);
12529 }
12530 #endif /* WLWFDS */
12531 #ifdef BT_WIFI_HANDOVER
12532 else if (strnicmp(command, CMD_TBOW_TEARDOWN, strlen(CMD_TBOW_TEARDOWN)) == 0) {
12533 bytes_written = wl_tbow_teardown(net);
12534 }
12535 #endif /* BT_WIFI_HANDOVER */
12536 #ifdef CUSTOMER_HW4_PRIVATE_CMD
12537 #ifdef FCC_PWR_LIMIT_2G
12538 else if (strnicmp(command, CMD_GET_FCC_PWR_LIMIT_2G,
12539 strlen(CMD_GET_FCC_PWR_LIMIT_2G)) == 0) {
12540 bytes_written = wl_android_get_fcc_pwr_limit_2g(net, command, priv_cmd.total_len);
12541 }
12542 else if (strnicmp(command, CMD_SET_FCC_PWR_LIMIT_2G,
12543 strlen(CMD_SET_FCC_PWR_LIMIT_2G)) == 0) {
12544 bytes_written = wl_android_set_fcc_pwr_limit_2g(net, command);
12545 }
12546 #endif /* FCC_PWR_LIMIT_2G */
12547 else if (strnicmp(command, CMD_GET_STA_INFO, strlen(CMD_GET_STA_INFO)) == 0) {
12548 bytes_written = wl_cfg80211_get_sta_info(net, command, priv_cmd.total_len);
12549 }
12550 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
12551 else if (strnicmp(command, CMD_MURX_BFE_CAP,
12552 strlen(CMD_MURX_BFE_CAP)) == 0) {
12553 #ifdef WL_MURX
12554 uint val = *(command + strlen(CMD_MURX_BFE_CAP) + 1) - '0';
12555 bytes_written = wl_android_murx_bfe_cap(net, val);
12556 #else
12557 return BCME_UNSUPPORTED;
12558 #endif /* WL_MURX */
12559 }
12560 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
12561 else if (strnicmp(command, CMD_GET_AP_BASICRATE, strlen(CMD_GET_AP_BASICRATE)) == 0) {
12562 bytes_written = wl_android_get_ap_basicrate(net, command, priv_cmd.total_len);
12563 }
12564 else if (strnicmp(command, CMD_SET_AP_BEACONRATE, strlen(CMD_SET_AP_BEACONRATE)) == 0) {
12565 bytes_written = wl_android_set_ap_beaconrate(net, command);
12566 }
12567 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
12568 #ifdef SUPPORT_AP_RADIO_PWRSAVE
12569 else if (strnicmp(command, CMD_SET_AP_RPS_PARAMS, strlen(CMD_SET_AP_RPS_PARAMS)) == 0) {
12570 bytes_written = wl_android_set_ap_rps_params(net, command, priv_cmd.total_len);
12571 }
12572 else if (strnicmp(command, CMD_SET_AP_RPS, strlen(CMD_SET_AP_RPS)) == 0) {
12573 bytes_written = wl_android_set_ap_rps(net, command, priv_cmd.total_len);
12574 }
12575 else if (strnicmp(command, CMD_GET_AP_RPS, strlen(CMD_GET_AP_RPS)) == 0) {
12576 bytes_written = wl_android_get_ap_rps(net, command, priv_cmd.total_len);
12577 }
12578 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
12579 #ifdef SUPPORT_AP_SUSPEND
12580 else if (strnicmp(command, CMD_SET_AP_SUSPEND, strlen(CMD_SET_AP_SUSPEND)) == 0) {
12581 bytes_written = wl_android_set_ap_suspend(net, command, priv_cmd.total_len);
12582 }
12583 #endif /* SUPPORT_AP_SUSPEND */
12584 #ifdef SUPPORT_AP_BWCTRL
12585 else if (strnicmp(command, CMD_SET_AP_BW, strlen(CMD_SET_AP_BW)) == 0) {
12586 bytes_written = wl_android_set_ap_bw(net, command, priv_cmd.total_len);
12587 }
12588 else if (strnicmp(command, CMD_GET_AP_BW, strlen(CMD_GET_AP_BW)) == 0) {
12589 bytes_written = wl_android_get_ap_bw(net, command, priv_cmd.total_len);
12590 }
12591 #endif /* SUPPORT_AP_BWCTRL */
12592 #ifdef SUPPORT_RSSI_SUM_REPORT
12593 else if (strnicmp(command, CMD_SET_RSSI_LOGGING, strlen(CMD_SET_RSSI_LOGGING)) == 0) {
12594 bytes_written = wl_android_set_rssi_logging(net, command, priv_cmd.total_len);
12595 }
12596 else if (strnicmp(command, CMD_GET_RSSI_LOGGING, strlen(CMD_GET_RSSI_LOGGING)) == 0) {
12597 bytes_written = wl_android_get_rssi_logging(net, command, priv_cmd.total_len);
12598 }
12599 else if (strnicmp(command, CMD_GET_RSSI_PER_ANT, strlen(CMD_GET_RSSI_PER_ANT)) == 0) {
12600 bytes_written = wl_android_get_rssi_per_ant(net, command, priv_cmd.total_len);
12601 }
12602 #endif /* SUPPORT_RSSI_SUM_REPORT */
12603 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12604 else if (strnicmp(command, CMD_GET_BSS_INFO, strlen(CMD_GET_BSS_INFO)) == 0) {
12605 bytes_written = wl_cfg80211_get_bss_info(net, command, priv_cmd.total_len);
12606 }
12607 else if (strnicmp(command, CMD_GET_ASSOC_REJECT_INFO, strlen(CMD_GET_ASSOC_REJECT_INFO))
12608 == 0) {
12609 bytes_written = wl_cfg80211_get_connect_failed_status(net, command,
12610 priv_cmd.total_len);
12611 }
12612 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12613 #if defined(SUPPORT_RANDOM_MAC_SCAN)
12614 else if (strnicmp(command, ENABLE_RANDOM_MAC, strlen(ENABLE_RANDOM_MAC)) == 0) {
12615 bytes_written = wl_cfg80211_set_random_mac(net, TRUE);
12616 } else if (strnicmp(command, DISABLE_RANDOM_MAC, strlen(DISABLE_RANDOM_MAC)) == 0) {
12617 bytes_written = wl_cfg80211_set_random_mac(net, FALSE);
12618 }
12619 #endif /* SUPPORT_RANDOM_MAC_SCAN */
12620 #ifdef WL_NATOE
12621 else if (strnicmp(command, CMD_NATOE, strlen(CMD_NATOE)) == 0) {
12622 bytes_written = wl_android_process_natoe_cmd(net, command,
12623 priv_cmd.total_len);
12624 }
12625 #endif /* WL_NATOE */
12626 #ifdef CONNECTION_STATISTICS
12627 else if (strnicmp(command, CMD_GET_CONNECTION_STATS,
12628 strlen(CMD_GET_CONNECTION_STATS)) == 0) {
12629 bytes_written = wl_android_get_connection_stats(net, command,
12630 priv_cmd.total_len);
12631 }
12632 #endif
12633 #ifdef DHD_LOG_DUMP
12634 else if (strnicmp(command, CMD_NEW_DEBUG_PRINT_DUMP,
12635 strlen(CMD_NEW_DEBUG_PRINT_DUMP)) == 0) {
12636 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(net);
12637 /* check whether it has more command */
12638 if (strnicmp(command + strlen(CMD_NEW_DEBUG_PRINT_DUMP), " ", 1) == 0) {
12639 /* compare unwanted/disconnected command */
12640 if (strnicmp(command + strlen(CMD_NEW_DEBUG_PRINT_DUMP) + 1,
12641 SUBCMD_UNWANTED, strlen(SUBCMD_UNWANTED)) == 0) {
12642 dhd_log_dump_trigger(dhdp, CMD_UNWANTED);
12643 } else if (strnicmp(command + strlen(CMD_NEW_DEBUG_PRINT_DUMP) + 1,
12644 SUBCMD_DISCONNECTED, strlen(SUBCMD_DISCONNECTED)) == 0) {
12645 dhd_log_dump_trigger(dhdp, CMD_DISCONNECTED);
12646 } else {
12647 dhd_log_dump_trigger(dhdp, CMD_DEFAULT);
12648 }
12649 } else {
12650 dhd_log_dump_trigger(dhdp, CMD_DEFAULT);
12651 }
12652 }
12653 #endif /* DHD_LOG_DUMP */
12654 #ifdef DHD_STATUS_LOGGING
12655 else if (strnicmp(command, CMD_DUMP_STATUS_LOG, strlen(CMD_DUMP_STATUS_LOG)) == 0) {
12656 dhd_statlog_dump_scr(wl_cfg80211_get_dhdp(net));
12657 }
12658 else if (strnicmp(command, CMD_QUERY_STATUS_LOG, strlen(CMD_QUERY_STATUS_LOG)) == 0) {
12659 dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(net);
12660 bytes_written = dhd_statlog_query(dhdp, command, priv_cmd.total_len);
12661 }
12662 #endif /* DHD_STATUS_LOGGING */
12663 #if defined(CONFIG_TIZEN)
12664 else if (strnicmp(command, CMD_POWERSAVEMODE_SET,
12665 strlen(CMD_POWERSAVEMODE_SET)) == 0) {
12666 bytes_written = wl_android_set_powersave_mode(net, command,
12667 priv_cmd.total_len);
12668 }
12669 else if (strnicmp(command, CMD_POWERSAVEMODE_GET,
12670 strlen(CMD_POWERSAVEMODE_GET)) == 0) {
12671 bytes_written = wl_android_get_powersave_mode(net, command,
12672 priv_cmd.total_len);
12673 }
12674 #endif /* CONFIG_TIZEN */
12675 #ifdef SET_PCIE_IRQ_CPU_CORE
12676 else if (strnicmp(command, CMD_PCIE_IRQ_CORE, strlen(CMD_PCIE_IRQ_CORE)) == 0) {
12677 int affinity_cmd = *(command + strlen(CMD_PCIE_IRQ_CORE) + 1) - '0';
12678 wl_android_set_irq_cpucore(net, affinity_cmd);
12679 }
12680 #endif /* SET_PCIE_IRQ_CPU_CORE */
12681 #if defined(DHD_HANG_SEND_UP_TEST)
12682 else if (strnicmp(command, CMD_MAKE_HANG, strlen(CMD_MAKE_HANG)) == 0) {
12683 int skip = strlen(CMD_MAKE_HANG) + 1;
12684 wl_android_make_hang_with_reason(net, (const char*)command+skip);
12685 }
12686 #endif /* DHD_HANG_SEND_UP_TEST */
12687 #ifdef SUPPORT_LQCM
12688 else if (strnicmp(command, CMD_SET_LQCM_ENABLE, strlen(CMD_SET_LQCM_ENABLE)) == 0) {
12689 int lqcm_enable = *(command + strlen(CMD_SET_LQCM_ENABLE) + 1) - '0';
12690 bytes_written = wl_android_lqcm_enable(net, lqcm_enable);
12691 }
12692 else if (strnicmp(command, CMD_GET_LQCM_REPORT,
12693 strlen(CMD_GET_LQCM_REPORT)) == 0) {
12694 bytes_written = wl_android_get_lqcm_report(net, command,
12695 priv_cmd.total_len);
12696 }
12697 #endif
12698 else if (strnicmp(command, CMD_GET_SNR, strlen(CMD_GET_SNR)) == 0) {
12699 bytes_written = wl_android_get_snr(net, command, priv_cmd.total_len);
12700 }
12701 #ifdef WLADPS_PRIVATE_CMD
12702 else if (strnicmp(command, CMD_SET_ADPS, strlen(CMD_SET_ADPS)) == 0) {
12703 int skip = strlen(CMD_SET_ADPS) + 1;
12704 bytes_written = wl_android_set_adps_mode(net, (const char*)command+skip);
12705 }
12706 else if (strnicmp(command, CMD_GET_ADPS, strlen(CMD_GET_ADPS)) == 0) {
12707 bytes_written = wl_android_get_adps_mode(net, command, priv_cmd.total_len);
12708 }
12709 #ifdef WLADPS_ENERGY_GAIN
12710 else if (strnicmp(command, CMD_GET_GAIN_ADPS, strlen(CMD_GET_GAIN_ADPS)) == 0) {
12711 bytes_written = wl_android_get_gain_adps(net, command, priv_cmd.total_len);
12712 }
12713 else if (strnicmp(command, CMD_RESET_GAIN_ADPS, strlen(CMD_RESET_GAIN_ADPS)) == 0) {
12714 bytes_written = wl_android_reset_gain_adps(net, command);
12715 }
12716 #endif /* WLADPS_ENERGY_GAIN */
12717 #endif /* WLADPS_PRIVATE_CMD */
12718 #ifdef DHD_PKT_LOGGING
12719 else if (strnicmp(command, CMD_PKTLOG_FILTER_ENABLE,
12720 strlen(CMD_PKTLOG_FILTER_ENABLE)) == 0) {
12721 bytes_written = wl_android_pktlog_filter_enable(net, command, priv_cmd.total_len);
12722 }
12723 else if (strnicmp(command, CMD_PKTLOG_FILTER_DISABLE,
12724 strlen(CMD_PKTLOG_FILTER_DISABLE)) == 0) {
12725 bytes_written = wl_android_pktlog_filter_disable(net, command, priv_cmd.total_len);
12726 }
12727 else if (strnicmp(command, CMD_PKTLOG_FILTER_PATTERN_ENABLE,
12728 strlen(CMD_PKTLOG_FILTER_PATTERN_ENABLE)) == 0) {
12729 bytes_written =
12730 wl_android_pktlog_filter_pattern_enable(net, command, priv_cmd.total_len);
12731 }
12732 else if (strnicmp(command, CMD_PKTLOG_FILTER_PATTERN_DISABLE,
12733 strlen(CMD_PKTLOG_FILTER_PATTERN_DISABLE)) == 0) {
12734 bytes_written =
12735 wl_android_pktlog_filter_pattern_disable(net, command, priv_cmd.total_len);
12736 }
12737 else if (strnicmp(command, CMD_PKTLOG_FILTER_ADD, strlen(CMD_PKTLOG_FILTER_ADD)) == 0) {
12738 bytes_written = wl_android_pktlog_filter_add(net, command, priv_cmd.total_len);
12739 }
12740 else if (strnicmp(command, CMD_PKTLOG_FILTER_DEL, strlen(CMD_PKTLOG_FILTER_DEL)) == 0) {
12741 bytes_written = wl_android_pktlog_filter_del(net, command, priv_cmd.total_len);
12742 }
12743 else if (strnicmp(command, CMD_PKTLOG_FILTER_INFO, strlen(CMD_PKTLOG_FILTER_INFO)) == 0) {
12744 bytes_written = wl_android_pktlog_filter_info(net, command, priv_cmd.total_len);
12745 }
12746 else if (strnicmp(command, CMD_PKTLOG_START, strlen(CMD_PKTLOG_START)) == 0) {
12747 bytes_written = wl_android_pktlog_start(net, command, priv_cmd.total_len);
12748 }
12749 else if (strnicmp(command, CMD_PKTLOG_STOP, strlen(CMD_PKTLOG_STOP)) == 0) {
12750 bytes_written = wl_android_pktlog_stop(net, command, priv_cmd.total_len);
12751 }
12752 else if (strnicmp(command, CMD_PKTLOG_FILTER_EXIST, strlen(CMD_PKTLOG_FILTER_EXIST)) == 0) {
12753 bytes_written = wl_android_pktlog_filter_exist(net, command, priv_cmd.total_len);
12754 }
12755 else if (strnicmp(command, CMD_PKTLOG_MINMIZE_ENABLE,
12756 strlen(CMD_PKTLOG_MINMIZE_ENABLE)) == 0) {
12757 bytes_written = wl_android_pktlog_minmize_enable(net, command, priv_cmd.total_len);
12758 }
12759 else if (strnicmp(command, CMD_PKTLOG_MINMIZE_DISABLE,
12760 strlen(CMD_PKTLOG_MINMIZE_DISABLE)) == 0) {
12761 bytes_written = wl_android_pktlog_minmize_disable(net, command, priv_cmd.total_len);
12762 }
12763 else if (strnicmp(command, CMD_PKTLOG_CHANGE_SIZE,
12764 strlen(CMD_PKTLOG_CHANGE_SIZE)) == 0) {
12765 bytes_written = wl_android_pktlog_change_size(net, command, priv_cmd.total_len);
12766 }
12767 else if (strnicmp(command, CMD_PKTLOG_DEBUG_DUMP, strlen(CMD_PKTLOG_DEBUG_DUMP)) == 0) {
12768 bytes_written = wl_android_pktlog_dbg_dump(net, command, priv_cmd.total_len);
12769 }
12770 #endif /* DHD_PKT_LOGGING */
12771 #ifdef WL_CFG80211
12772 else if (strnicmp(command, CMD_DEBUG_VERBOSE, strlen(CMD_DEBUG_VERBOSE)) == 0) {
12773 int verbose_level = *(command + strlen(CMD_DEBUG_VERBOSE) + 1) - '0';
12774 bytes_written = wl_cfg80211_set_dbg_verbose(net, verbose_level);
12775 }
12776 #endif /* WL_CFG80211 */
12777 #ifdef DHD_EVENT_LOG_FILTER
12778 else if (strnicmp(command, CMD_EWP_FILTER,
12779 strlen(CMD_EWP_FILTER)) == 0) {
12780 bytes_written = wl_android_ewp_filter(net, command, priv_cmd.total_len);
12781 }
12782 #endif /* DHD_EVENT_LOG_FILTER */
12783 #ifdef WL_BCNRECV
12784 else if (strnicmp(command, CMD_BEACON_RECV,
12785 strlen(CMD_BEACON_RECV)) == 0) {
12786 char *data = (command + strlen(CMD_BEACON_RECV) + 1);
12787 bytes_written = wl_android_bcnrecv_config(net,
12788 data, priv_cmd.total_len);
12789 }
12790 #endif /* WL_BCNRECV */
12791 #ifdef WL_MBO
12792 else if (strnicmp(command, CMD_MBO, strlen(CMD_MBO)) == 0) {
12793 bytes_written = wl_android_process_mbo_cmd(net, command,
12794 priv_cmd.total_len);
12795 }
12796 #endif /* WL_MBO */
12797 #ifdef WL_CAC_TS
12798 else if (strnicmp(command, CMD_CAC_TSPEC,
12799 strlen(CMD_CAC_TSPEC)) == 0) {
12800 char *data = (command + strlen(CMD_CAC_TSPEC) + 1);
12801 bytes_written = wl_android_cac_ts_config(net,
12802 data, priv_cmd.total_len);
12803 }
12804 #endif /* WL_CAC_TS */
12805 #ifdef WL_GET_CU
12806 else if (strnicmp(command, CMD_GET_CHAN_UTIL,
12807 strlen(CMD_GET_CHAN_UTIL)) == 0) {
12808 bytes_written = wl_android_get_channel_util(net,
12809 command, priv_cmd.total_len);
12810 }
12811 #endif /* WL_GET_CU */
12812 #ifdef RTT_GEOFENCE_INTERVAL
12813 #if defined (RTT_SUPPORT) && defined(WL_NAN)
12814 else if (strnicmp(command, CMD_GEOFENCE_INTERVAL,
12815 strlen(CMD_GEOFENCE_INTERVAL)) == 0) {
12816 (void)wl_android_set_rtt_geofence_interval(net, command);
12817 }
12818 #endif /* RTT_SUPPORT && WL_NAN */
12819 #endif /* RTT_GEOFENCE_INTERVAL */
12820 #ifdef SUPPORT_SOFTAP_ELNA_BYPASS
12821 else if (strnicmp(command, CMD_SET_SOFTAP_ELNA_BYPASS,
12822 strlen(CMD_SET_SOFTAP_ELNA_BYPASS)) == 0) {
12823 bytes_written =
12824 wl_android_set_softap_elna_bypass(net, command, priv_cmd.total_len);
12825 }
12826 else if (strnicmp(command, CMD_GET_SOFTAP_ELNA_BYPASS,
12827 strlen(CMD_GET_SOFTAP_ELNA_BYPASS)) == 0) {
12828 bytes_written =
12829 wl_android_get_softap_elna_bypass(net, command, priv_cmd.total_len);
12830 }
12831 #endif /* SUPPORT_SOFTAP_ELNA_BYPASS */
12832 #ifdef WL_NAN
12833 else if (strnicmp(command, CMD_GET_NAN_STATUS,
12834 strlen(CMD_GET_NAN_STATUS)) == 0) {
12835 bytes_written =
12836 wl_android_get_nan_status(net, command, priv_cmd.total_len);
12837 }
12838 #endif /* WL_NAN */
12839 #if defined(SUPPORT_NAN_RANGING_TEST_BW)
12840 else if (strnicmp(command, CMD_NAN_RANGING_SET_BW, strlen(CMD_NAN_RANGING_SET_BW)) == 0) {
12841 int bw_cmd = *(command + strlen(CMD_NAN_RANGING_SET_BW) + 1) - '0';
12842 bytes_written = wl_nan_ranging_bw(net, bw_cmd, command);
12843 }
12844 #endif /* SUPPORT_NAN_RANGING_TEST_BW */
12845 else if (strnicmp(command, CMD_GET_FACTORY_MAC, strlen(CMD_GET_FACTORY_MAC)) == 0) {
12846 bytes_written = wl_android_get_factory_mac_addr(net, command, priv_cmd.total_len);
12847 }
12848 else if (strnicmp(command, CMD_HAPD_SET_AX_MODE, strlen(CMD_HAPD_SET_AX_MODE)) == 0) {
12849 int skip = strlen(CMD_HAPD_SET_AX_MODE) + 1;
12850 bytes_written = wl_android_set_softap_ax_mode(net, command + skip);
12851 }
12852 #ifdef SUPPORT_LATENCY_CRITICAL_DATA
12853 else if (strnicmp(command, CMD_SET_LATENCY_CRITICAL_DATA,
12854 strlen(CMD_SET_LATENCY_CRITICAL_DATA)) == 0) {
12855 int enable = *(command + strlen(CMD_SET_LATENCY_CRITICAL_DATA) + 1) - '0';
12856 bytes_written = wl_android_set_latency_crt_data(net, enable);
12857 }
12858 else if (strnicmp(command, CMD_GET_LATENCY_CRITICAL_DATA,
12859 strlen(CMD_GET_LATENCY_CRITICAL_DATA)) == 0) {
12860 bytes_written = wl_android_get_latency_crt_data(net, command, priv_cmd.total_len);
12861 }
12862 #endif /* SUPPORT_LATENCY_CRITICAL_DATA */
12863 #ifdef WL_TWT
12864 else if (strnicmp(command, CMD_TWT_SETUP, strlen(CMD_TWT_SETUP)) == 0) {
12865 bytes_written = wl_android_twt_setup(net, command, priv_cmd.total_len);
12866 }
12867 else if (strnicmp(command, CMD_TWT_TEARDOWN, strlen(CMD_TWT_TEARDOWN)) == 0) {
12868 bytes_written = wl_android_twt_teardown(net, command, priv_cmd.total_len);
12869 }
12870 else if (strnicmp(command, CMD_TWT_INFO, strlen(CMD_TWT_INFO)) == 0) {
12871 bytes_written = wl_android_twt_info(net, command, priv_cmd.total_len);
12872 }
12873 else if (strnicmp(command, CMD_TWT_STATUS_QUERY, strlen(CMD_TWT_STATUS_QUERY)) == 0) {
12874 bytes_written = wl_android_twt_status_query(net, command, priv_cmd.total_len);
12875 }
12876 else if (strnicmp(command, CMD_TWT_CAPABILITY, strlen(CMD_TWT_CAPABILITY)) == 0) {
12877 bytes_written = wl_android_twt_cap(net, command, priv_cmd.total_len);
12878 }
12879 #endif /* WL_TWT */
12880 #ifdef WL_P2P_6G
12881 else if (strnicmp(command, CMD_ENABLE_6G_P2P, strlen(CMD_ENABLE_6G_P2P)) == 0) {
12882 int enable = *(command + strlen(CMD_ENABLE_6G_P2P) + 1) - '0';
12883 bytes_written = wl_android_enable_p2p_6g(net, enable);
12884 }
12885 #endif /* WL_P2P_6G */
12886 else if (wl_android_ext_priv_cmd(net, command, priv_cmd.total_len, &bytes_written) == 0) {
12887 }
12888 else {
12889 ANDROID_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
12890 bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
12891 }
12892
12893 return bytes_written;
12894 }
12895
12896 /*
12897 * ENABLE_INSMOD_NO_FW_LOAD X O O O
12898 * ENABLE_INSMOD_NO_POWER_OFF X X O O
12899 * NO_POWER_OFF_AFTER_OPEN X X X O
12900 * after insmod H L H H
12901 * wlan0 down H L L H
12902 * fw trap trigger wlan0 down H L L L
12903 */
12904
wl_android_init(void)12905 int wl_android_init(void)
12906 {
12907 int ret = 0;
12908
12909 #ifdef ENABLE_INSMOD_NO_POWER_OFF
12910 dhd_download_fw_on_driverload = TRUE;
12911 #elif defined(ENABLE_INSMOD_NO_FW_LOAD) || defined(BUS_POWER_RESTORE)
12912 dhd_download_fw_on_driverload = FALSE;
12913 #endif /* ENABLE_INSMOD_NO_FW_LOAD */
12914 if (!iface_name[0]) {
12915 bzero(iface_name, IFNAMSIZ);
12916 bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
12917 }
12918
12919 #ifdef CUSTOMER_HW4_DEBUG
12920 /* No Kernel Panic from ASSERT() on customer platform. */
12921 g_assert_type = 1;
12922 #endif /* CUSTOMER_HW4_DEBUG */
12923
12924 #ifdef WL_GENL
12925 wl_genl_init();
12926 #endif
12927 #ifdef WL_RELMCAST
12928 wl_netlink_init();
12929 #endif /* WL_RELMCAST */
12930
12931 return ret;
12932 }
12933
wl_android_exit(void)12934 int wl_android_exit(void)
12935 {
12936 int ret = 0;
12937 struct io_cfg *cur, *q;
12938
12939 #ifdef WL_GENL
12940 wl_genl_deinit();
12941 #endif /* WL_GENL */
12942 #ifdef WL_RELMCAST
12943 wl_netlink_deinit();
12944 #endif /* WL_RELMCAST */
12945
12946 GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
12947 list_for_each_entry_safe(cur, q, &miracast_resume_list, list) {
12948 GCC_DIAGNOSTIC_POP();
12949 list_del(&cur->list);
12950 kfree(cur);
12951 }
12952
12953 return ret;
12954 }
12955
wl_android_post_init(void)12956 void wl_android_post_init(void)
12957 {
12958
12959 #ifdef ENABLE_4335BT_WAR
12960 bcm_bt_unlock(lock_cookie_wifi);
12961 ANDROID_ERROR(("%s: btlock released\n", __FUNCTION__));
12962 #endif /* ENABLE_4335BT_WAR */
12963
12964 if (!dhd_download_fw_on_driverload) {
12965 g_wifi_on = FALSE;
12966 }
12967 }
12968
12969 #ifdef WL_GENL
12970 /* Generic Netlink Initializaiton */
wl_genl_init(void)12971 static int wl_genl_init(void)
12972 {
12973 int ret;
12974
12975 ANDROID_INFO(("GEN Netlink Init\n\n"));
12976
12977 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
12978 /* register new family */
12979 ret = genl_register_family(&wl_genl_family);
12980 if (ret != 0)
12981 goto failure;
12982
12983 /* register functions (commands) of the new family */
12984 ret = genl_register_ops(&wl_genl_family, &wl_genl_ops);
12985 if (ret != 0) {
12986 ANDROID_ERROR(("register ops failed: %i\n", ret));
12987 genl_unregister_family(&wl_genl_family);
12988 goto failure;
12989 }
12990
12991 ret = genl_register_mc_group(&wl_genl_family, &wl_genl_mcast);
12992 #else
12993 ret = genl_register_family_with_ops_groups(&wl_genl_family, wl_genl_ops, wl_genl_mcast);
12994 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
12995 if (ret != 0) {
12996 ANDROID_ERROR(("register mc_group failed: %i\n", ret));
12997 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
12998 genl_unregister_ops(&wl_genl_family, &wl_genl_ops);
12999 #endif
13000 genl_unregister_family(&wl_genl_family);
13001 goto failure;
13002 }
13003
13004 return 0;
13005
13006 failure:
13007 ANDROID_ERROR(("Registering Netlink failed!!\n"));
13008 return -1;
13009 }
13010
13011 /* Generic netlink deinit */
wl_genl_deinit(void)13012 static int wl_genl_deinit(void)
13013 {
13014
13015 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
13016 if (genl_unregister_ops(&wl_genl_family, &wl_genl_ops) < 0)
13017 ANDROID_ERROR(("Unregister wl_genl_ops failed\n"));
13018 #endif
13019 if (genl_unregister_family(&wl_genl_family) < 0)
13020 ANDROID_ERROR(("Unregister wl_genl_ops failed\n"));
13021
13022 return 0;
13023 }
13024
wl_event_to_bcm_event(u16 event_type)13025 s32 wl_event_to_bcm_event(u16 event_type)
13026 {
13027 /* When you add any new event, please mention the
13028 * version of BCM supplicant supporting it
13029 */
13030 u16 event = -1;
13031
13032 switch (event_type) {
13033 case WLC_E_SERVICE_FOUND:
13034 event = BCM_E_SVC_FOUND;
13035 break;
13036 case WLC_E_P2PO_ADD_DEVICE:
13037 event = BCM_E_DEV_FOUND;
13038 break;
13039 case WLC_E_P2PO_DEL_DEVICE:
13040 event = BCM_E_DEV_LOST;
13041 break;
13042 /* Above events are supported from BCM Supp ver 47 Onwards */
13043 #ifdef BT_WIFI_HANDOVER
13044 case WLC_E_BT_WIFI_HANDOVER_REQ:
13045 event = BCM_E_DEV_BT_WIFI_HO_REQ;
13046 break;
13047 #endif /* BT_WIFI_HANDOVER */
13048
13049 default:
13050 ANDROID_ERROR(("Event not supported\n"));
13051 }
13052
13053 return event;
13054 }
13055
13056 s32
wl_genl_send_msg(struct net_device * ndev,u32 event_type,const u8 * buf,u16 len,u8 * subhdr,u16 subhdr_len)13057 wl_genl_send_msg(
13058 struct net_device *ndev,
13059 u32 event_type,
13060 const u8 *buf,
13061 u16 len,
13062 u8 *subhdr,
13063 u16 subhdr_len)
13064 {
13065 int ret = 0;
13066 struct sk_buff *skb;
13067 void *msg;
13068 u32 attr_type = 0;
13069 bcm_event_hdr_t *hdr = NULL;
13070 int mcast = 1; /* By default sent as mutlicast type */
13071 int pid = 0;
13072 u8 *ptr = NULL, *p = NULL;
13073 u32 tot_len = sizeof(bcm_event_hdr_t) + subhdr_len + len;
13074 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
13075 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
13076
13077 ANDROID_INFO(("Enter \n"));
13078
13079 /* Decide between STRING event and Data event */
13080 if (event_type == 0)
13081 attr_type = BCM_GENL_ATTR_STRING;
13082 else
13083 attr_type = BCM_GENL_ATTR_MSG;
13084
13085 skb = genlmsg_new(NLMSG_GOODSIZE, kflags);
13086 if (skb == NULL) {
13087 ret = -ENOMEM;
13088 goto out;
13089 }
13090
13091 msg = genlmsg_put(skb, 0, 0, &wl_genl_family, 0, BCM_GENL_CMD_MSG);
13092 if (msg == NULL) {
13093 ret = -ENOMEM;
13094 goto out;
13095 }
13096
13097 if (attr_type == BCM_GENL_ATTR_STRING) {
13098 /* Add a BCM_GENL_MSG attribute. Since it is specified as a string.
13099 * make sure it is null terminated
13100 */
13101 if (subhdr || subhdr_len) {
13102 ANDROID_ERROR(("No sub hdr support for the ATTR STRING type \n"));
13103 ret = -EINVAL;
13104 goto out;
13105 }
13106
13107 ret = nla_put_string(skb, BCM_GENL_ATTR_STRING, buf);
13108 if (ret != 0) {
13109 ANDROID_ERROR(("nla_put_string failed\n"));
13110 goto out;
13111 }
13112 } else {
13113 /* ATTR_MSG */
13114
13115 /* Create a single buffer for all */
13116 p = ptr = (u8 *)MALLOCZ(cfg->osh, tot_len);
13117 if (!ptr) {
13118 ret = -ENOMEM;
13119 ANDROID_ERROR(("ENOMEM!!\n"));
13120 goto out;
13121 }
13122
13123 /* Include the bcm event header */
13124 hdr = (bcm_event_hdr_t *)ptr;
13125 hdr->event_type = wl_event_to_bcm_event(event_type);
13126 hdr->len = len + subhdr_len;
13127 ptr += sizeof(bcm_event_hdr_t);
13128
13129 /* Copy subhdr (if any) */
13130 if (subhdr && subhdr_len) {
13131 memcpy(ptr, subhdr, subhdr_len);
13132 ptr += subhdr_len;
13133 }
13134
13135 /* Copy the data */
13136 if (buf && len) {
13137 memcpy(ptr, buf, len);
13138 }
13139
13140 ret = nla_put(skb, BCM_GENL_ATTR_MSG, tot_len, p);
13141 if (ret != 0) {
13142 ANDROID_ERROR(("nla_put_string failed\n"));
13143 goto out;
13144 }
13145 }
13146
13147 if (mcast) {
13148 int err = 0;
13149 /* finalize the message */
13150 genlmsg_end(skb, msg);
13151 /* NETLINK_CB(skb).dst_group = 1; */
13152
13153 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
13154 if ((err = genlmsg_multicast(skb, 0, wl_genl_mcast.id, GFP_ATOMIC)) < 0)
13155 #else
13156 if ((err = genlmsg_multicast(&wl_genl_family, skb, 0, 0, GFP_ATOMIC)) < 0)
13157 #endif
13158 ANDROID_ERROR(("genlmsg_multicast for attr(%d) failed. Error:%d \n",
13159 attr_type, err));
13160 else
13161 ANDROID_INFO(("Multicast msg sent successfully. attr_type:%d len:%d \n",
13162 attr_type, tot_len));
13163 } else {
13164 NETLINK_CB(skb).dst_group = 0; /* Not in multicast group */
13165
13166 /* finalize the message */
13167 genlmsg_end(skb, msg);
13168
13169 /* send the message back */
13170 if (genlmsg_unicast(&init_net, skb, pid) < 0)
13171 ANDROID_ERROR(("genlmsg_unicast failed\n"));
13172 }
13173
13174 out:
13175 if (p) {
13176 MFREE(cfg->osh, p, tot_len);
13177 }
13178 if (ret)
13179 nlmsg_free(skb);
13180
13181 return ret;
13182 }
13183
13184 static s32
wl_genl_handle_msg(struct sk_buff * skb,struct genl_info * info)13185 wl_genl_handle_msg(
13186 struct sk_buff *skb,
13187 struct genl_info *info)
13188 {
13189 struct nlattr *na;
13190 u8 *data = NULL;
13191
13192 ANDROID_INFO(("Enter \n"));
13193
13194 if (info == NULL) {
13195 return -EINVAL;
13196 }
13197
13198 na = info->attrs[BCM_GENL_ATTR_MSG];
13199 if (!na) {
13200 ANDROID_ERROR(("nlattribute NULL\n"));
13201 return -EINVAL;
13202 }
13203
13204 data = (char *)nla_data(na);
13205 if (!data) {
13206 ANDROID_ERROR(("Invalid data\n"));
13207 return -EINVAL;
13208 } else {
13209 /* Handle the data */
13210 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) || \
13211 defined(WL_COMPAT_WIRELESS)
13212 ANDROID_INFO(("%s: Data received from pid (%d) \n", __func__,
13213 info->snd_pid));
13214 #else
13215 ANDROID_INFO(("%s: Data received from pid (%d) \n", __func__,
13216 info->snd_portid));
13217 #endif /* (LINUX_VERSION < VERSION(3, 7, 0) || WL_COMPAT_WIRELESS */
13218 }
13219
13220 return 0;
13221 }
13222 #endif /* WL_GENL */
13223
wl_fatal_error(void * wl,int rc)13224 int wl_fatal_error(void * wl, int rc)
13225 {
13226 return FALSE;
13227 }
13228
13229 void
wl_android_set_wifi_on_flag(bool enable)13230 wl_android_set_wifi_on_flag(bool enable)
13231 {
13232 ANDROID_ERROR(("%s: %d\n", __FUNCTION__, enable));
13233 g_wifi_on = enable;
13234 }
13235
13236 #ifdef WL_STATIC_IF
13237 #include <dhd_linux_priv.h>
13238 struct net_device *
wl_cfg80211_register_static_if(struct bcm_cfg80211 * cfg,u16 iftype,char * ifname,int static_ifidx)13239 wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifname,
13240 int static_ifidx)
13241 {
13242 #if defined(CUSTOM_MULTI_MAC) || defined(WL_EXT_IAPSTA)
13243 dhd_pub_t *dhd = cfg->pub;
13244 #endif
13245 struct net_device *ndev;
13246 struct wireless_dev *wdev = NULL;
13247 int ifidx = WL_STATIC_IFIDX; /* Register ndev with a reserved ifidx */
13248 u8 mac_addr[ETH_ALEN];
13249 struct net_device *primary_ndev;
13250 #ifdef DHD_USE_RANDMAC
13251 struct ether_addr ea_addr;
13252 #endif /* DHD_USE_RANDMAC */
13253 #ifdef CUSTOM_MULTI_MAC
13254 char hw_ether[62];
13255 #endif
13256
13257 ANDROID_INFO(("[STATIC_IF] Enter (%s) iftype:%d\n", ifname, iftype));
13258
13259 if (!cfg) {
13260 ANDROID_ERROR(("cfg null\n"));
13261 return NULL;
13262 }
13263 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
13264
13265 ifidx += static_ifidx;
13266 #ifdef DHD_USE_RANDMAC
13267 wl_cfg80211_generate_mac_addr(&ea_addr);
13268 (void)memcpy_s(mac_addr, ETH_ALEN, ea_addr.octet, ETH_ALEN);
13269 #else
13270 #if defined(CUSTOM_MULTI_MAC)
13271 if (!wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, static_ifidx+1)) {
13272 (void)memcpy_s(mac_addr, ETH_ALEN, hw_ether, ETH_ALEN);
13273 } else
13274 #endif
13275 {
13276 /* Use primary mac with locally admin bit set */
13277 (void)memcpy_s(mac_addr, ETH_ALEN, primary_ndev->dev_addr, ETH_ALEN);
13278 mac_addr[0] |= 0x02;
13279 #ifdef WL_EXT_IAPSTA
13280 wl_ext_iapsta_get_vif_macaddr(dhd, static_ifidx+1, mac_addr);
13281 #endif
13282 }
13283 #endif /* DHD_USE_RANDMAC */
13284
13285 ndev = wl_cfg80211_allocate_if(cfg, ifidx, ifname, mac_addr,
13286 WL_BSSIDX_MAX, NULL);
13287 if (unlikely(!ndev)) {
13288 ANDROID_ERROR(("Failed to allocate static_if\n"));
13289 goto fail;
13290 }
13291 wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
13292 if (unlikely(!wdev)) {
13293 ANDROID_ERROR(("Failed to allocate wdev for static_if\n"));
13294 goto fail;
13295 }
13296
13297 wdev->wiphy = cfg->wdev->wiphy;
13298 wdev->iftype = iftype;
13299
13300 ndev->ieee80211_ptr = wdev;
13301 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
13302 wdev->netdev = ndev;
13303
13304 if (wl_cfg80211_register_if(cfg, ifidx,
13305 ndev, TRUE) != BCME_OK) {
13306 ANDROID_ERROR(("ndev registration failed!\n"));
13307 goto fail;
13308 }
13309
13310 cfg->static_ndev[static_ifidx] = ndev;
13311 cfg->static_ndev_state[static_ifidx] = NDEV_STATE_OS_IF_CREATED;
13312 wl_cfg80211_update_iflist_info(cfg, ndev, ifidx, NULL, WL_BSSIDX_MAX,
13313 ifname, NDEV_STATE_OS_IF_CREATED);
13314 ANDROID_INFO(("Static I/F (%s) Registered\n", ndev->name));
13315 return ndev;
13316
13317 fail:
13318 wl_cfg80211_remove_if(cfg, ifidx, ndev, false);
13319 return NULL;
13320 }
13321
13322 void
wl_cfg80211_unregister_static_if(struct bcm_cfg80211 * cfg)13323 wl_cfg80211_unregister_static_if(struct bcm_cfg80211 *cfg)
13324 {
13325 int i;
13326
13327 ANDROID_INFO(("[STATIC_IF] Enter\n"));
13328 if (!cfg) {
13329 ANDROID_ERROR(("invalid input\n"));
13330 return;
13331 }
13332
13333 /* wdev free will happen from notifier context */
13334 /* free_netdev(cfg->static_ndev);
13335 */
13336 for (i=0; i<DHD_MAX_STATIC_IFS; i++) {
13337 if (cfg->static_ndev[i])
13338 unregister_netdev(cfg->static_ndev[i]);
13339 }
13340 }
13341
13342 s32
wl_cfg80211_static_if_open(struct net_device * net)13343 wl_cfg80211_static_if_open(struct net_device *net)
13344 {
13345 struct wireless_dev *wdev = NULL;
13346 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
13347 struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
13348 u16 iftype = net->ieee80211_ptr ? net->ieee80211_ptr->iftype : 0;
13349 u16 wl_iftype, wl_mode;
13350 #ifdef CUSTOM_MULTI_MAC
13351 dhd_pub_t *dhd = dhd_get_pub(net);
13352 char hw_ether[62];
13353 #endif
13354 int static_ifidx;
13355
13356 ANDROID_INFO(("[STATIC_IF] dev_open ndev %p and wdev %p\n", net, net->ieee80211_ptr));
13357 static_ifidx = wl_cfg80211_static_ifidx(cfg, net);
13358 ASSERT(static_ifidx >= 0);
13359
13360 if (cfg80211_to_wl_iftype(iftype, &wl_iftype, &wl_mode) < 0) {
13361 return BCME_ERROR;
13362 }
13363 if (cfg->static_ndev_state[static_ifidx] != NDEV_STATE_FW_IF_CREATED) {
13364 #ifdef CUSTOM_MULTI_MAC
13365 if (!wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, static_ifidx+1))
13366 dev_addr_set(net, hw_ether);
13367 #endif
13368 wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, net->dev_addr);
13369 if (!wdev) {
13370 ANDROID_ERROR(("[STATIC_IF] wdev is NULL, can't proceed\n"));
13371 return BCME_ERROR;
13372 }
13373 } else {
13374 ANDROID_INFO(("Fw IF for static netdev already created\n"));
13375 }
13376
13377 return BCME_OK;
13378 }
13379
13380 s32
wl_cfg80211_static_if_close(struct net_device * net)13381 wl_cfg80211_static_if_close(struct net_device *net)
13382 {
13383 int ret = BCME_OK;
13384 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
13385 struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
13386 int static_ifidx;
13387
13388 static_ifidx = wl_cfg80211_static_ifidx(cfg, net);
13389
13390 if (cfg->static_ndev_state[static_ifidx] == NDEV_STATE_FW_IF_CREATED) {
13391 if (mutex_is_locked(&cfg->if_sync) == TRUE) {
13392 ret = _wl_cfg80211_del_if(cfg, primary_ndev, net->ieee80211_ptr, net->name);
13393 } else {
13394 ret = wl_cfg80211_del_if(cfg, primary_ndev, net->ieee80211_ptr, net->name);
13395 }
13396
13397 if (unlikely(ret)) {
13398 ANDROID_ERROR(("Del iface failed for static_if %d\n", ret));
13399 }
13400 }
13401
13402 return ret;
13403 }
13404 struct net_device *
wl_cfg80211_post_static_ifcreate(struct bcm_cfg80211 * cfg,wl_if_event_info * event,u8 * addr,s32 iface_type,int static_ifidx)13405 wl_cfg80211_post_static_ifcreate(struct bcm_cfg80211 *cfg,
13406 wl_if_event_info *event, u8 *addr, s32 iface_type, int static_ifidx)
13407 {
13408 struct net_device *new_ndev = NULL;
13409 struct wireless_dev *wdev = NULL;
13410
13411 ANDROID_INFO(("Updating static iface after Fw IF create \n"));
13412 new_ndev = cfg->static_ndev[static_ifidx];
13413
13414 if (new_ndev) {
13415 wdev = new_ndev->ieee80211_ptr;
13416 ASSERT(wdev);
13417 wdev->iftype = iface_type;
13418 dev_addr_set(new_ndev, addr);
13419 }
13420
13421 cfg->static_ndev_state[static_ifidx] = NDEV_STATE_FW_IF_CREATED;
13422 wl_cfg80211_update_iflist_info(cfg, new_ndev, event->ifidx, addr, event->bssidx,
13423 event->name, NDEV_STATE_FW_IF_CREATED);
13424 return new_ndev;
13425 }
13426 s32
wl_cfg80211_post_static_ifdel(struct bcm_cfg80211 * cfg,struct net_device * ndev)13427 wl_cfg80211_post_static_ifdel(struct bcm_cfg80211 *cfg, struct net_device *ndev)
13428 {
13429 int static_ifidx;
13430 int ifidx = WL_STATIC_IFIDX;
13431
13432 static_ifidx = wl_cfg80211_static_ifidx(cfg, ndev);
13433 ifidx += static_ifidx;
13434 cfg->static_ndev_state[static_ifidx] = NDEV_STATE_FW_IF_DELETED;
13435 wl_cfg80211_update_iflist_info(cfg, ndev, ifidx, NULL,
13436 WL_BSSIDX_MAX, NULL, NDEV_STATE_FW_IF_DELETED);
13437 wl_cfg80211_clear_per_bss_ies(cfg, ndev->ieee80211_ptr);
13438 wl_dealloc_netinfo_by_wdev(cfg, ndev->ieee80211_ptr);
13439 return BCME_OK;
13440 }
13441 #endif /* WL_STATIC_IF */
13442
13443 #ifdef WBTEXT
13444 static int
wlc_wbtext_get_roam_prof(struct net_device * ndev,wl_roamprof_band_t * rp,uint8 band,uint8 * roam_prof_ver,uint8 * roam_prof_size)13445 wlc_wbtext_get_roam_prof(struct net_device *ndev, wl_roamprof_band_t *rp,
13446 uint8 band, uint8 *roam_prof_ver, uint8 *roam_prof_size)
13447 {
13448 int err = BCME_OK;
13449 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
13450 u8 *ioctl_buf = NULL;
13451
13452 ioctl_buf = (u8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
13453 if (unlikely(!ioctl_buf)) {
13454 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
13455 err = -ENOMEM;
13456 goto exit;
13457 }
13458 rp->v1.band = band;
13459 rp->v1.len = 0;
13460 /* Getting roam profile from fw */
13461 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
13462 ioctl_buf, WLC_IOCTL_MEDLEN, NULL))) {
13463 ANDROID_ERROR(("Getting roam_profile failed with err=%d \n", err));
13464 goto exit;
13465 }
13466 memcpy_s(rp, sizeof(*rp), ioctl_buf, sizeof(*rp));
13467 /* roam_prof version get */
13468 if (rp->v1.ver > WL_ROAM_PROF_VER_3) {
13469 ANDROID_ERROR(("bad version (=%d) in return data\n", rp->v1.ver));
13470 err = BCME_VERSION;
13471 goto exit;
13472 }
13473 switch (rp->v1.ver) {
13474 case WL_ROAM_PROF_VER_0:
13475 {
13476 *roam_prof_size = sizeof(wl_roam_prof_v1_t);
13477 *roam_prof_ver = WL_ROAM_PROF_VER_0;
13478 }
13479 break;
13480 case WL_ROAM_PROF_VER_1:
13481 {
13482 *roam_prof_size = sizeof(wl_roam_prof_v2_t);
13483 *roam_prof_ver = WL_ROAM_PROF_VER_1;
13484 }
13485 break;
13486 case WL_ROAM_PROF_VER_2:
13487 {
13488 *roam_prof_size = sizeof(wl_roam_prof_v3_t);
13489 *roam_prof_ver = WL_ROAM_PROF_VER_2;
13490 }
13491 break;
13492 case WL_ROAM_PROF_VER_3:
13493 {
13494 *roam_prof_size = sizeof(wl_roam_prof_v4_t);
13495 *roam_prof_ver = WL_ROAM_PROF_VER_3;
13496 }
13497 break;
13498 default:
13499 ANDROID_ERROR(("bad version = %d \n", rp->v1.ver));
13500 err = BCME_VERSION;
13501 goto exit;
13502 }
13503 ANDROID_INFO(("roam prof ver %u size %u\n", *roam_prof_ver, *roam_prof_size));
13504 if ((rp->v1.len % *roam_prof_size) != 0) {
13505 ANDROID_ERROR(("bad length (=%d) in return data\n", rp->v1.len));
13506 err = BCME_BADLEN;
13507 }
13508 exit:
13509 if (ioctl_buf) {
13510 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
13511 }
13512 return err;
13513 }
13514
13515 s32
wl_cfg80211_wbtext_set_default(struct net_device * ndev)13516 wl_cfg80211_wbtext_set_default(struct net_device *ndev)
13517 {
13518 char *commandp = NULL;
13519 s32 ret = BCME_OK;
13520 char *data;
13521 u8 *ioctl_buf = NULL;
13522 wl_roamprof_band_t rp;
13523 uint8 bandidx = 0;
13524 int wnmmask = 0;
13525 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
13526
13527 ANDROID_INFO(("set wbtext to default\n"));
13528
13529 commandp = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_SMLEN);
13530 if (unlikely(!commandp)) {
13531 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
13532 ret = -ENOMEM;
13533 goto exit;
13534 }
13535 ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_SMLEN);
13536 if (unlikely(!ioctl_buf)) {
13537 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
13538 ret = -ENOMEM;
13539 goto exit;
13540 }
13541
13542 rp.v1.band = WLC_BAND_2G;
13543 rp.v1.len = 0;
13544 /* Getting roam profile from fw */
13545 if ((ret = wldev_iovar_getbuf(ndev, "roam_prof", &rp, sizeof(rp),
13546 ioctl_buf, WLC_IOCTL_SMLEN, NULL))) {
13547 ANDROID_ERROR(("Getting roam_profile failed with err=%d \n", ret));
13548 goto exit;
13549 }
13550 memcpy_s(&rp, sizeof(rp), ioctl_buf, sizeof(rp));
13551 for (bandidx = 0; bandidx < MAXBANDS; bandidx++) {
13552 switch (rp.v1.ver) {
13553 case WL_ROAM_PROF_VER_1:
13554 {
13555 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13556 if (bandidx == BAND_5G_INDEX) {
13557 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13558 CMD_WBTEXT_PROFILE_CONFIG,
13559 DEFAULT_WBTEXT_PROFILE_A_V2);
13560 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
13561 } else {
13562 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13563 CMD_WBTEXT_PROFILE_CONFIG,
13564 DEFAULT_WBTEXT_PROFILE_B_V2);
13565 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
13566 }
13567 }
13568 break;
13569 case WL_ROAM_PROF_VER_2:
13570 case WL_ROAM_PROF_VER_3:
13571 {
13572 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13573 if (bandidx == BAND_5G_INDEX) {
13574 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13575 CMD_WBTEXT_PROFILE_CONFIG,
13576 DEFAULT_WBTEXT_PROFILE_A_V3);
13577 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
13578 } else {
13579 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13580 CMD_WBTEXT_PROFILE_CONFIG,
13581 DEFAULT_WBTEXT_PROFILE_B_V3);
13582 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
13583 }
13584 }
13585 break;
13586 default:
13587 ANDROID_ERROR(("No Support for roam prof ver = %d \n", rp.v1.ver));
13588 ret = -EINVAL;
13589 goto exit;
13590 }
13591 /* set roam profile */
13592 ret = wl_cfg80211_wbtext_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13593 if (ret != BCME_OK) {
13594 ANDROID_ERROR(("%s: Failed to set roam_prof %s error = %d\n",
13595 __FUNCTION__, data, ret));
13596 goto exit;
13597 }
13598 }
13599
13600 /* wbtext code for backward compatibility. Newer firmwares set default value
13601 * from fw init
13602 */
13603 /* set RSSI weight */
13604 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13605 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13606 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_RSSI_A);
13607 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
13608 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13609 if (ret != BCME_OK) {
13610 ANDROID_ERROR(("%s: Failed to set weight config %s error = %d\n",
13611 __FUNCTION__, data, ret));
13612 goto exit;
13613 }
13614
13615 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13616 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13617 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_RSSI_B);
13618 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
13619 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13620 if (ret != BCME_OK) {
13621 ANDROID_ERROR(("%s: Failed to set weight config %s error = %d\n",
13622 __FUNCTION__, data, ret));
13623 goto exit;
13624 }
13625
13626 /* set CU weight */
13627 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13628 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13629 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_CU_A);
13630 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
13631 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13632 if (ret != BCME_OK) {
13633 ANDROID_ERROR(("%s: Failed to set weight config %s error = %d\n",
13634 __FUNCTION__, data, ret));
13635 goto exit;
13636 }
13637
13638 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13639 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13640 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_CU_B);
13641 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
13642 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13643 if (ret != BCME_OK) {
13644 ANDROID_ERROR(("%s: Failed to set weight config %s error = %d\n",
13645 __FUNCTION__, data, ret));
13646 goto exit;
13647 }
13648
13649 ret = wldev_iovar_getint(ndev, "wnm", &wnmmask);
13650 if (ret != BCME_OK) {
13651 ANDROID_ERROR(("%s: Failed to get wnmmask error = %d\n", __func__, ret));
13652 goto exit;
13653 }
13654 /* set ESTM DL weight. */
13655 if (wnmmask & WL_WNM_ESTM) {
13656 ANDROID_ERROR(("Setting ESTM wt\n"));
13657 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13658 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13659 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_ESTM_DL_A);
13660 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
13661 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13662 if (ret != BCME_OK) {
13663 ANDROID_ERROR(("%s: Failed to set weight config %s error = %d\n",
13664 __FUNCTION__, data, ret));
13665 goto exit;
13666 }
13667
13668 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13669 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13670 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_ESTM_DL_B);
13671 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
13672 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13673 if (ret != BCME_OK) {
13674 ANDROID_ERROR(("%s: Failed to set weight config %s error = %d\n",
13675 __FUNCTION__, data, ret));
13676 goto exit;
13677 }
13678 }
13679
13680 /* set RSSI table */
13681 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13682 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13683 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_RSSI_A);
13684 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
13685 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13686 if (ret != BCME_OK) {
13687 ANDROID_ERROR(("%s: Failed to set RSSI table %s error = %d\n",
13688 __FUNCTION__, data, ret));
13689 goto exit;
13690 }
13691
13692 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13693 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13694 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_RSSI_B);
13695 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
13696 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13697 if (ret != BCME_OK) {
13698 ANDROID_ERROR(("%s: Failed to set RSSI table %s error = %d\n",
13699 __FUNCTION__, data, ret));
13700 goto exit;
13701 }
13702
13703 /* set CU table */
13704 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13705 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13706 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_CU_A);
13707 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
13708 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13709 if (ret != BCME_OK) {
13710 ANDROID_ERROR(("%s: Failed to set CU table %s error = %d\n",
13711 __FUNCTION__, data, ret));
13712 goto exit;
13713 }
13714
13715 memset_s(commandp, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
13716 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
13717 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_CU_B);
13718 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
13719 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
13720 if (ret != BCME_OK) {
13721 ANDROID_ERROR(("%s: Failed to set CU table %s error = %d\n",
13722 __FUNCTION__, data, ret));
13723 goto exit;
13724 }
13725
13726 exit:
13727 if (commandp) {
13728 MFREE(cfg->osh, commandp, WLC_IOCTL_SMLEN);
13729 }
13730 if (ioctl_buf) {
13731 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_SMLEN);
13732 }
13733 return ret;
13734 }
13735
13736 s32
wl_cfg80211_wbtext_config(struct net_device * ndev,char * data,char * command,int total_len)13737 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
13738 {
13739 uint i = 0;
13740 long int rssi_lower, roam_trigger;
13741 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
13742 wl_roamprof_band_t *rp = NULL;
13743 int err = -EINVAL, bytes_written = 0;
13744 size_t len = strlen(data);
13745 int rp_len = 0;
13746 u8 *ioctl_buf = NULL;
13747 uint8 roam_prof_size = 0, roam_prof_ver = 0, fs_per = 0, prof_cnt = 0;
13748
13749 data[len] = '\0';
13750 ioctl_buf = (u8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
13751 if (unlikely(!ioctl_buf)) {
13752 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
13753 err = -ENOMEM;
13754 goto exit;
13755 }
13756 rp = (wl_roamprof_band_t *)MALLOCZ(cfg->osh, sizeof(*rp));
13757 if (unlikely(!rp)) {
13758 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
13759 err = -ENOMEM;
13760 goto exit;
13761 }
13762 if (*data && (!strncmp(data, "b", 1))) {
13763 rp->v1.band = WLC_BAND_2G;
13764 } else if (*data && (!strncmp(data, "a", 1))) {
13765 rp->v1.band = WLC_BAND_5G;
13766 } else {
13767 err = snprintf(command, total_len, "Missing band\n");
13768 goto exit;
13769 }
13770 data++;
13771 rp->v1.len = 0;
13772 /* Getting roam profile from fw */
13773 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
13774 ioctl_buf, WLC_IOCTL_MEDLEN, NULL))) {
13775 ANDROID_ERROR(("Getting roam_profile failed with err=%d \n", err));
13776 goto exit;
13777 }
13778 memcpy_s(rp, sizeof(*rp), ioctl_buf, sizeof(*rp));
13779 /* roam_prof version get */
13780 if (rp->v1.ver > WL_ROAM_PROF_VER_3) {
13781 ANDROID_ERROR(("bad version (=%d) in return data\n", rp->v1.ver));
13782 err = -EINVAL;
13783 goto exit;
13784 }
13785 switch (rp->v1.ver) {
13786 case WL_ROAM_PROF_VER_0:
13787 {
13788 roam_prof_size = sizeof(wl_roam_prof_v1_t);
13789 roam_prof_ver = WL_ROAM_PROF_VER_0;
13790 }
13791 break;
13792 case WL_ROAM_PROF_VER_1:
13793 {
13794 roam_prof_size = sizeof(wl_roam_prof_v2_t);
13795 roam_prof_ver = WL_ROAM_PROF_VER_1;
13796 }
13797 break;
13798 case WL_ROAM_PROF_VER_2:
13799 {
13800 roam_prof_size = sizeof(wl_roam_prof_v3_t);
13801 roam_prof_ver = WL_ROAM_PROF_VER_2;
13802 }
13803 break;
13804 case WL_ROAM_PROF_VER_3:
13805 {
13806 roam_prof_size = sizeof(wl_roam_prof_v4_t);
13807 roam_prof_ver = WL_ROAM_PROF_VER_3;
13808 }
13809 break;
13810 default:
13811 ANDROID_ERROR(("bad version = %d \n", rp->v1.ver));
13812 goto exit;
13813 }
13814 ANDROID_INFO(("roam prof ver %u size %u\n", roam_prof_ver, roam_prof_size));
13815 if ((rp->v1.len % roam_prof_size) != 0) {
13816 ANDROID_ERROR(("bad length (=%d) in return data\n", rp->v1.len));
13817 err = -EINVAL;
13818 goto exit;
13819 }
13820 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
13821 /* printing contents of roam profile data from fw and exits
13822 * if code hits any of one of the below condtion. If remaining
13823 * length of buffer is less than roam profile size or
13824 * if there is no valid entry.
13825 */
13826 if (((i * roam_prof_size) > rp->v1.len)) {
13827 break;
13828 }
13829 if (roam_prof_ver == WL_ROAM_PROF_VER_0) {
13830 fs_per = rp->v1.roam_prof[i].fullscan_period;
13831 } else if (roam_prof_ver == WL_ROAM_PROF_VER_1) {
13832 fs_per = rp->v2.roam_prof[i].fullscan_period;
13833 } else if (roam_prof_ver == WL_ROAM_PROF_VER_2) {
13834 fs_per = rp->v3.roam_prof[i].fullscan_period;
13835 } else if (roam_prof_ver == WL_ROAM_PROF_VER_3) {
13836 fs_per = rp->v4.roam_prof[i].fullscan_period;
13837 }
13838 if (fs_per == 0) {
13839 break;
13840 }
13841 prof_cnt++;
13842 }
13843
13844 if (!*data) {
13845 for (i = 0; (i < prof_cnt) && (i < WL_MAX_ROAM_PROF_BRACKETS); i++) {
13846 if (roam_prof_ver == WL_ROAM_PROF_VER_1) {
13847 bytes_written += scnprintf(command+bytes_written,
13848 total_len - bytes_written,
13849 "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)",
13850 rp->v2.roam_prof[i].roam_trigger,
13851 rp->v2.roam_prof[i].rssi_lower,
13852 rp->v2.roam_prof[i].channel_usage,
13853 rp->v2.roam_prof[i].cu_avg_calc_dur);
13854 } else if (roam_prof_ver == WL_ROAM_PROF_VER_2) {
13855 bytes_written += scnprintf(command+bytes_written,
13856 total_len - bytes_written,
13857 "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)",
13858 rp->v3.roam_prof[i].roam_trigger,
13859 rp->v3.roam_prof[i].rssi_lower,
13860 rp->v3.roam_prof[i].channel_usage,
13861 rp->v3.roam_prof[i].cu_avg_calc_dur);
13862 } else if (roam_prof_ver == WL_ROAM_PROF_VER_3) {
13863 bytes_written += snprintf(command+bytes_written,
13864 total_len - bytes_written,
13865 "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)",
13866 rp->v4.roam_prof[i].roam_trigger,
13867 rp->v4.roam_prof[i].rssi_lower,
13868 rp->v4.roam_prof[i].channel_usage,
13869 rp->v4.roam_prof[i].cu_avg_calc_dur);
13870 }
13871 }
13872 bytes_written += scnprintf(command+bytes_written, total_len - bytes_written, "\n");
13873 err = bytes_written;
13874 goto exit;
13875 } else {
13876 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
13877 if (prof_cnt != 2) {
13878 ANDROID_ERROR(("FW must have 2 rows to fill roam_prof\n"));
13879 err = -EINVAL;
13880 goto exit;
13881 }
13882 /* setting roam profile to fw */
13883 data++;
13884 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
13885 roam_trigger = simple_strtol(data, &data, 10);
13886 if (roam_trigger >= 0) {
13887 ANDROID_ERROR(("roam trigger[%d] value must be negative\n", i));
13888 err = -EINVAL;
13889 goto exit;
13890 }
13891 data++;
13892 rssi_lower = simple_strtol(data, &data, 10);
13893 if (rssi_lower >= 0) {
13894 ANDROID_ERROR(("rssi lower[%d] value must be negative\n", i));
13895 err = -EINVAL;
13896 goto exit;
13897 }
13898 if (roam_prof_ver == WL_ROAM_PROF_VER_1) {
13899 rp->v2.roam_prof[i].roam_trigger = roam_trigger;
13900 rp->v2.roam_prof[i].rssi_lower = rssi_lower;
13901 data++;
13902 rp->v2.roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
13903 data++;
13904 rp->v2.roam_prof[i].cu_avg_calc_dur =
13905 simple_strtol(data, &data, 10);
13906 }
13907 if (roam_prof_ver == WL_ROAM_PROF_VER_2) {
13908 rp->v3.roam_prof[i].roam_trigger = roam_trigger;
13909 rp->v3.roam_prof[i].rssi_lower = rssi_lower;
13910 data++;
13911 rp->v3.roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
13912 data++;
13913 rp->v3.roam_prof[i].cu_avg_calc_dur =
13914 simple_strtol(data, &data, 10);
13915 }
13916 if (roam_prof_ver == WL_ROAM_PROF_VER_3) {
13917 rp->v4.roam_prof[i].roam_trigger = roam_trigger;
13918 rp->v4.roam_prof[i].rssi_lower = rssi_lower;
13919 data++;
13920 rp->v4.roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
13921 data++;
13922 rp->v4.roam_prof[i].cu_avg_calc_dur =
13923 simple_strtol(data, &data, 10);
13924 }
13925
13926 rp_len += roam_prof_size;
13927
13928 if (*data == '\0') {
13929 break;
13930 }
13931 data++;
13932 }
13933 if (i != 1) {
13934 ANDROID_ERROR(("Only two roam_prof rows supported.\n"));
13935 err = -EINVAL;
13936 goto exit;
13937 }
13938 rp->v1.len = rp_len;
13939 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
13940 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN,
13941 &cfg->ioctl_buf_sync)) < 0) {
13942 ANDROID_ERROR(("seting roam_profile failed with err %d\n", err));
13943 }
13944 }
13945 exit:
13946 if (rp) {
13947 MFREE(cfg->osh, rp, sizeof(*rp));
13948 }
13949 if (ioctl_buf) {
13950 MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
13951 }
13952 return err;
13953 }
13954
wl_cfg80211_wbtext_weight_config(struct net_device * ndev,char * data,char * command,int total_len)13955 int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
13956 char *command, int total_len)
13957 {
13958 int bytes_written = 0, err = -EINVAL, argc = 0;
13959 char rssi[BUFSZN], band[BUFSZN], weight[BUFSZN];
13960 char *endptr = NULL;
13961 wnm_bss_select_weight_cfg_t *bwcfg;
13962 u8 ioctl_buf[WLC_IOCTL_SMLEN];
13963 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
13964
13965 bwcfg = (wnm_bss_select_weight_cfg_t *)MALLOCZ(cfg->osh, sizeof(*bwcfg));
13966 if (unlikely(!bwcfg)) {
13967 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
13968 err = -ENOMEM;
13969 goto exit;
13970 }
13971 bwcfg->version = WNM_BSSLOAD_MONITOR_VERSION;
13972 bwcfg->type = 0;
13973 bwcfg->weight = 0;
13974
13975 argc = sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s %"S(BUFSZ)"s", rssi, band, weight);
13976
13977 if (!strcasecmp(rssi, "rssi"))
13978 bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
13979 else if (!strcasecmp(rssi, "cu"))
13980 bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
13981 else if (!strcasecmp(rssi, "estm_dl"))
13982 bwcfg->type = WNM_BSS_SELECT_TYPE_ESTM_DL;
13983 else {
13984 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu/estm_dl> <band> <weight> */
13985 ANDROID_ERROR(("%s: Command usage error\n", __func__));
13986 goto exit;
13987 }
13988
13989 if (BCME_BADBAND == wl_android_bandstr_to_fwband(band, &bwcfg->band)) {
13990 ANDROID_ERROR(("%s: Command usage error\n", __func__));
13991 goto exit;
13992 }
13993
13994 if (argc == 2) {
13995 /* If there is no data after band, getting wnm_bss_select_weight from fw */
13996 if (bwcfg->band == WLC_BAND_ALL) {
13997 ANDROID_ERROR(("band option \"all\" is for set only, not get\n"));
13998 goto exit;
13999 }
14000 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
14001 sizeof(*bwcfg),
14002 ioctl_buf, sizeof(ioctl_buf), NULL))) {
14003 ANDROID_ERROR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
14004 goto exit;
14005 }
14006 memcpy(bwcfg, ioctl_buf, sizeof(*bwcfg));
14007 bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
14008 (bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" :
14009 (bwcfg->type == WNM_BSS_SELECT_TYPE_CU) ? "CU": "ESTM_DL",
14010 wl_android_get_band_str(bwcfg->band), bwcfg->weight);
14011 err = bytes_written;
14012 goto exit;
14013 } else {
14014 /* if weight is non integer returns command usage error */
14015 bwcfg->weight = simple_strtol(weight, &endptr, 0);
14016 if (*endptr != '\0') {
14017 ANDROID_ERROR(("%s: Command usage error", __func__));
14018 goto exit;
14019 }
14020 /* setting weight for iovar wnm_bss_select_weight to fw */
14021 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
14022 sizeof(*bwcfg),
14023 ioctl_buf, sizeof(ioctl_buf), NULL))) {
14024 ANDROID_ERROR(("setting wnm_bss_select_weight failed with err=%d\n", err));
14025 }
14026 }
14027 exit:
14028 if (bwcfg) {
14029 MFREE(cfg->osh, bwcfg, sizeof(*bwcfg));
14030 }
14031 return err;
14032 }
14033
14034 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
14035 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
14036
wl_cfg80211_wbtext_table_config(struct net_device * ndev,char * data,char * command,int total_len)14037 int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
14038 char *command, int total_len)
14039 {
14040 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
14041 int bytes_written = 0, err = -EINVAL;
14042 char rssi[BUFSZN], band[BUFSZN];
14043 int btcfg_len = 0, i = 0, parsed_len = 0;
14044 wnm_bss_select_factor_cfg_t *btcfg;
14045 size_t slen = strlen(data);
14046 char *start_addr = NULL;
14047 u8 ioctl_buf[WLC_IOCTL_SMLEN];
14048
14049 data[slen] = '\0';
14050 btcfg = (wnm_bss_select_factor_cfg_t *)MALLOCZ(cfg->osh,
14051 (sizeof(*btcfg) + sizeof(*btcfg) * WL_FACTOR_TABLE_MAX_LIMIT));
14052 if (unlikely(!btcfg)) {
14053 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
14054 err = -ENOMEM;
14055 goto exit;
14056 }
14057
14058 btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
14059 btcfg->band = WLC_BAND_AUTO;
14060 btcfg->type = 0;
14061 btcfg->count = 0;
14062
14063 sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s", rssi, band);
14064
14065 if (!strcasecmp(rssi, "rssi")) {
14066 btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
14067 }
14068 else if (!strcasecmp(rssi, "cu")) {
14069 btcfg->type = WNM_BSS_SELECT_TYPE_CU;
14070 }
14071 else {
14072 ANDROID_ERROR(("%s: Command usage error\n", __func__));
14073 goto exit;
14074 }
14075
14076 if (BCME_BADBAND == wl_android_bandstr_to_fwband(band, &btcfg->band)) {
14077 ANDROID_ERROR(("%s: Command usage, Wrong band\n", __func__));
14078 goto exit;
14079 }
14080
14081 if ((slen - 1) == (strlen(rssi) + strlen(band))) {
14082 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
14083 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
14084 sizeof(*btcfg),
14085 ioctl_buf, sizeof(ioctl_buf), NULL))) {
14086 ANDROID_ERROR(("Getting wnm_bss_select_table failed with err=%d \n", err));
14087 goto exit;
14088 }
14089 memcpy(btcfg, ioctl_buf, sizeof(*btcfg));
14090 memcpy(btcfg, ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
14091
14092 bytes_written += snprintf(command + bytes_written, total_len - bytes_written,
14093 "No of entries in table: %d\n", btcfg->count);
14094 bytes_written += snprintf(command + bytes_written, total_len - bytes_written,
14095 "%s factor table\n",
14096 (btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
14097 bytes_written += snprintf(command + bytes_written, total_len - bytes_written,
14098 "low\thigh\tfactor\n");
14099 for (i = 0; i <= btcfg->count-1; i++) {
14100 bytes_written += snprintf(command + bytes_written,
14101 total_len - bytes_written, "%d\t%d\t%d\n", btcfg->params[i].low,
14102 btcfg->params[i].high, btcfg->params[i].factor);
14103 }
14104 err = bytes_written;
14105 goto exit;
14106 } else {
14107 uint16 len = (sizeof(wnm_bss_select_factor_params_t) * WL_FACTOR_TABLE_MAX_LIMIT);
14108 memset_s(btcfg->params, len, 0, len);
14109 data += (strlen(rssi) + strlen(band) + 2);
14110 start_addr = data;
14111 slen = slen - (strlen(rssi) + strlen(band) + 2);
14112 for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
14113 if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
14114 btcfg->params[i].low = simple_strtol(data, &data, 10);
14115 data++;
14116 btcfg->params[i].high = simple_strtol(data, &data, 10);
14117 data++;
14118 btcfg->params[i].factor = simple_strtol(data, &data, 10);
14119 btcfg->count++;
14120 if (*data == '\0') {
14121 break;
14122 }
14123 data++;
14124 parsed_len = data - start_addr;
14125 } else {
14126 ANDROID_ERROR(("%s:Command usage:less no of args\n", __func__));
14127 goto exit;
14128 }
14129 }
14130 btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
14131 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
14132 cfg->ioctl_buf, WLC_IOCTL_MEDLEN, &cfg->ioctl_buf_sync)) < 0) {
14133 ANDROID_ERROR(("seting wnm_bss_select_table failed with err %d\n", err));
14134 goto exit;
14135 }
14136 }
14137 exit:
14138 if (btcfg) {
14139 MFREE(cfg->osh, btcfg,
14140 (sizeof(*btcfg) + sizeof(*btcfg) * WL_FACTOR_TABLE_MAX_LIMIT));
14141 }
14142 return err;
14143 }
14144
14145 s32
wl_cfg80211_wbtext_delta_config(struct net_device * ndev,char * data,char * command,int total_len)14146 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
14147 {
14148 uint i = 0;
14149 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
14150 int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
14151 char delta[BUFSZN], band[BUFSZN], *endptr = NULL;
14152 wl_roamprof_band_t *rp = NULL;
14153 uint8 band_val = 0, roam_prof_size = 0, roam_prof_ver = 0;
14154
14155 rp = (wl_roamprof_band_t *)MALLOCZ(cfg->osh, sizeof(*rp));
14156 if (unlikely(!rp)) {
14157 ANDROID_ERROR(("%s: failed to allocate memory\n", __func__));
14158 err = -ENOMEM;
14159 goto exit;
14160 }
14161
14162 argc = sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s", band, delta);
14163 if (BCME_BADBAND == wl_android_bandstr_to_fwband(band, &band_val)) {
14164 ANDROID_ERROR(("%s: Missing band\n", __func__));
14165 goto exit;
14166 }
14167 if ((err = wlc_wbtext_get_roam_prof(ndev, rp, band_val, &roam_prof_ver,
14168 &roam_prof_size))) {
14169 ANDROID_ERROR(("Getting roam_profile failed with err=%d \n", err));
14170 err = -EINVAL;
14171 goto exit;
14172 }
14173 if (argc == 2) {
14174 /* if delta is non integer returns command usage error */
14175 val = simple_strtol(delta, &endptr, 0);
14176 if (*endptr != '\0') {
14177 ANDROID_ERROR(("%s: Command usage error", __func__));
14178 goto exit;
14179 }
14180 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
14181 /*
14182 * Checking contents of roam profile data from fw and exits
14183 * if code hits below condtion. If remaining length of buffer is
14184 * less than roam profile size or if there is no valid entry.
14185 */
14186 if (len >= rp->v1.len) {
14187 break;
14188 }
14189 if (roam_prof_ver == WL_ROAM_PROF_VER_1) {
14190 if (rp->v2.roam_prof[i].fullscan_period == 0) {
14191 break;
14192 }
14193 if (rp->v2.roam_prof[i].channel_usage != 0) {
14194 rp->v2.roam_prof[i].roam_delta = val;
14195 }
14196 } else if (roam_prof_ver == WL_ROAM_PROF_VER_2) {
14197 if (rp->v3.roam_prof[i].fullscan_period == 0) {
14198 break;
14199 }
14200 if (rp->v3.roam_prof[i].channel_usage != 0) {
14201 rp->v3.roam_prof[i].roam_delta = val;
14202 }
14203 } else if (roam_prof_ver == WL_ROAM_PROF_VER_3) {
14204 if (rp->v4.roam_prof[i].fullscan_period == 0) {
14205 break;
14206 }
14207 if (rp->v4.roam_prof[i].channel_usage != 0) {
14208 rp->v4.roam_prof[i].roam_delta = val;
14209 }
14210 }
14211 len += roam_prof_size;
14212 }
14213 }
14214 else {
14215 if (rp->v2.roam_prof[0].channel_usage != 0) {
14216 bytes_written = snprintf(command, total_len,
14217 "%s Delta %d\n", wl_android_get_band_str(rp->v1.band),
14218 rp->v2.roam_prof[0].roam_delta);
14219 }
14220 err = bytes_written;
14221 goto exit;
14222 }
14223 rp->v1.len = len;
14224 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
14225 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN,
14226 &cfg->ioctl_buf_sync)) < 0) {
14227 ANDROID_ERROR(("seting roam_profile failed with err %d\n", err));
14228 }
14229 exit :
14230 if (rp) {
14231 MFREE(cfg->osh, rp, sizeof(*rp));
14232 }
14233 return err;
14234 }
14235 #endif /* WBTEXT */
14236