xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/os_dep/linux/rtw_android.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2019 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 
16 #ifdef CONFIG_GPIO_WAKEUP
17 #include <linux/gpio.h>
18 #endif
19 
20 #include <drv_types.h>
21 
22 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
23 #include <linux/platform_device.h>
24 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
25 	#include <linux/wlan_plat.h>
26 #else
27 	#include <linux/wifi_tiwlan.h>
28 #endif
29 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
30 
31 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
32 #define strnicmp	strncasecmp
33 #endif /* Linux kernel >= 4.0.0 */
34 
35 #ifdef CONFIG_GPIO_WAKEUP
36 #include <linux/interrupt.h>
37 #include <linux/irq.h>
38 #endif
39 
40 #include "rtw_version.h"
41 
42 extern void macstr2num(u8 *dst, u8 *src);
43 
44 const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
45 	"START",
46 	"STOP",
47 	"SCAN-ACTIVE",
48 	"SCAN-PASSIVE",
49 	"RSSI",
50 	"LINKSPEED",
51 	"RXFILTER-START",
52 	"RXFILTER-STOP",
53 	"RXFILTER-ADD",
54 	"RXFILTER-REMOVE",
55 	"BTCOEXSCAN-START",
56 	"BTCOEXSCAN-STOP",
57 	"BTCOEXMODE",
58 	"SETSUSPENDMODE",
59 	"SETSUSPENDOPT",
60 	"P2P_DEV_ADDR",
61 	"SETFWPATH",
62 	"SETBAND",
63 	"GETBAND",
64 	"COUNTRY",
65 	"P2P_SET_NOA",
66 	"P2P_GET_NOA",
67 	"P2P_SET_PS",
68 	"SET_AP_WPS_P2P_IE",
69 
70 	"MIRACAST",
71 
72 #ifdef CONFIG_PNO_SUPPORT
73 	"PNOSSIDCLR",
74 	"PNOSETUP",
75 	"PNOFORCE",
76 	"PNODEBUG",
77 #endif
78 
79 	"MACADDR",
80 
81 	"BLOCK_SCAN",
82 	"BLOCK",
83 	"WFD-ENABLE",
84 	"WFD-DISABLE",
85 	"WFD-SET-TCPPORT",
86 	"WFD-SET-MAXTPUT",
87 	"WFD-SET-DEVTYPE",
88 	"SET_DTIM",
89 	"HOSTAPD_SET_MACADDR_ACL",
90 	"HOSTAPD_ACL_ADD_STA",
91 	"HOSTAPD_ACL_REMOVE_STA",
92 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
93 	"GTK_REKEY_OFFLOAD",
94 #endif /* CONFIG_GTK_OL */
95 /*	Private command for	P2P disable*/
96 	"P2P_DISABLE",
97 	"SET_AEK",
98 	"EXT_AUTH_STATUS",
99 	"DRIVER_VERSION"
100 #ifdef ROKU_PRIVATE
101 	,"ROKU_FIND_REMOTE"
102 #endif
103 };
104 
105 typedef struct android_wifi_priv_cmd {
106 	char *buf;
107 	int used_len;
108 	int total_len;
109 } android_wifi_priv_cmd;
110 
111 #ifdef CONFIG_COMPAT
112 typedef struct compat_android_wifi_priv_cmd {
113 	compat_uptr_t buf;
114 	int used_len;
115 	int total_len;
116 } compat_android_wifi_priv_cmd;
117 #endif /* CONFIG_COMPAT */
118 
119 /**
120  * Local (static) functions and variables
121  */
122 
123 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
124  * time (only) in dhd_open, subsequential wifi on will be handled by
125  * wl_android_wifi_on
126  */
127 static int g_wifi_on = _TRUE;
128 
129 unsigned int oob_irq = 0;
130 unsigned int oob_gpio = 0;
131 
rtw_android_cmdstr_to_num(char * cmdstr)132 int rtw_android_cmdstr_to_num(char *cmdstr)
133 {
134 	int cmd_num;
135 	for (cmd_num = 0 ; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
136 		if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])))
137 			break;
138 
139 	return cmd_num;
140 }
141 
rtw_android_get_rssi(struct net_device * net,char * command,int total_len)142 int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
143 {
144 	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
145 	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
146 	struct	wlan_network	*pcur_network = &pmlmepriv->cur_network;
147 	int bytes_written = 0;
148 
149 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
150 		bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
151 			pcur_network->network.Ssid.Ssid, padapter->recvinfo.rssi);
152 	}
153 
154 	return bytes_written;
155 }
156 
rtw_android_get_link_speed(struct net_device * net,char * command,int total_len)157 int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
158 {
159 	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
160 	int bytes_written = 0;
161 	u16 link_speed = 0;
162 
163 	link_speed = rtw_get_cur_max_rate(padapter) / 10;
164 	bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
165 
166 	return bytes_written;
167 }
168 
rtw_android_get_macaddr(struct net_device * net,char * command,int total_len)169 int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
170 {
171 	int bytes_written = 0;
172 
173 	bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
174 	return bytes_written;
175 }
176 
rtw_android_set_country(struct net_device * net,char * command,int total_len)177 int rtw_android_set_country(struct net_device *net, char *command, int total_len)
178 {
179 	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
180 	char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
181 	int ret = _FAIL;
182 
183 	ret = rtw_set_country(adapter, country_code, RTW_REGD_SET_BY_USER);
184 
185 	return (ret == _SUCCESS) ? 0 : -1;
186 }
187 
rtw_android_get_p2p_dev_addr(struct net_device * net,char * command,int total_len)188 int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
189 {
190 	int bytes_written = 0;
191 
192 	/* We use the same address as our HW MAC address */
193 	_rtw_memcpy(command, net->dev_addr, ETH_ALEN);
194 
195 	bytes_written = ETH_ALEN;
196 	return bytes_written;
197 }
198 
rtw_android_set_block_scan(struct net_device * net,char * command,int total_len)199 int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
200 {
201 	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
202 	char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
203 
204 #ifdef CONFIG_IOCTL_CFG80211
205 	adapter_wdev_data(adapter)->block_scan = (*block_value == '0') ? _FALSE : _TRUE;
206 #endif
207 
208 	return 0;
209 }
210 
rtw_android_set_block(struct net_device * net,char * command,int total_len)211 int rtw_android_set_block(struct net_device *net, char *command, int total_len)
212 {
213 	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
214 	char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
215 
216 #ifdef CONFIG_IOCTL_CFG80211
217 	adapter_wdev_data(adapter)->block = (*block_value == '0') ? _FALSE : _TRUE;
218 #endif
219 
220 	return 0;
221 }
222 
rtw_android_setband(struct net_device * net,char * command,int total_len)223 int rtw_android_setband(struct net_device *net, char *command, int total_len)
224 {
225 	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
226 	char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
227 	u32 band = WIFI_FREQUENCY_BAND_AUTO;
228 	int ret = _FAIL;
229 
230 	if (sscanf(arg, "%u", &band) >= 1)
231 		ret = rtw_set_band(adapter, band);
232 
233 	return (ret == _SUCCESS) ? 0 : -1;
234 }
235 
rtw_android_getband(struct net_device * net,char * command,int total_len)236 int rtw_android_getband(struct net_device *net, char *command, int total_len)
237 {
238 	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
239 	int bytes_written = 0;
240 
241 	bytes_written = snprintf(command, total_len, "%u", adapter->setband);
242 
243 	return bytes_written;
244 }
245 
246 #ifdef CONFIG_WFD
rtw_android_set_miracast_mode(struct net_device * net,char * command,int total_len)247 int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
248 {
249 	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
250 	struct wifi_display_info *wfd_info = &adapter->wfd_info;
251 	char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
252 	u8 mode;
253 	int num;
254 	int ret = _FAIL;
255 
256 	num = sscanf(arg, "%hhu", &mode);
257 
258 	if (num < 1)
259 		goto exit;
260 
261 	switch (mode) {
262 	case 1: /* soruce */
263 		mode = MIRACAST_SOURCE;
264 		break;
265 	case 2: /* sink */
266 		mode = MIRACAST_SINK;
267 		break;
268 	case 0: /* disabled */
269 	default:
270 		mode = MIRACAST_DISABLED;
271 		break;
272 	}
273 	wfd_info->stack_wfd_mode = mode;
274 	RTW_INFO("stack miracast mode: %s\n", get_miracast_mode_str(wfd_info->stack_wfd_mode));
275 
276 	ret = _SUCCESS;
277 
278 exit:
279 	return (ret == _SUCCESS) ? 0 : -1;
280 }
281 #endif /* CONFIG_WFD */
282 
get_int_from_command(char * pcmd)283 int get_int_from_command(char *pcmd)
284 {
285 	int i = 0;
286 
287 	for (i = 0; i < strlen(pcmd); i++) {
288 		if (pcmd[i] == '=') {
289 			/*	Skip the '=' and space characters. */
290 			i += 2;
291 			break;
292 		}
293 	}
294 	return rtw_atoi(pcmd + i) ;
295 }
296 
297 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
rtw_gtk_offload(struct net_device * net,u8 * cmd_ptr)298 int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
299 {
300 	int i;
301 	/* u8 *cmd_ptr = priv_cmd.buf; */
302 	struct sta_info *psta;
303 	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
304 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
305 	struct sta_priv *pstapriv = &padapter->stapriv;
306 	struct security_priv *psecuritypriv = &(padapter->securitypriv);
307 	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
308 
309 
310 	if (psta == NULL)
311 		RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
312 	else {
313 		/* string command length of "GTK_REKEY_OFFLOAD" */
314 		cmd_ptr += 18;
315 
316 		_rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
317 		cmd_ptr += RTW_KEK_LEN;
318 		/*
319 		printk("supplicant KEK: ");
320 		for(i=0;i<RTW_KEK_LEN; i++)
321 			printk(" %02x ", psta->kek[i]);
322 		printk("\n supplicant KCK: ");
323 		*/
324 		_rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
325 		cmd_ptr += RTW_KCK_LEN;
326 		/*
327 		for(i=0;i<RTW_KEK_LEN; i++)
328 			printk(" %02x ", psta->kck[i]);
329 		*/
330 		_rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
331 		psecuritypriv->binstallKCK_KEK = _TRUE;
332 
333 		/* printk("\nREPLAY_CTR: "); */
334 		/* for(i=0;i<RTW_REPLAY_CTR_LEN; i++) */
335 		/* printk(" %02x ", psta->replay_ctr[i]); */
336 	}
337 
338 	return _SUCCESS;
339 }
340 #endif /* CONFIG_GTK_OL */
341 
342 #ifdef CONFIG_RTW_MESH_AEK
rtw_android_set_aek(struct net_device * ndev,char * command,int total_len)343 static int rtw_android_set_aek(struct net_device *ndev, char *command, int total_len)
344 {
345 #define SET_AEK_DATA_LEN (ETH_ALEN + 32)
346 
347 	_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
348 	u8 *addr;
349 	u8 *aek;
350 	int err = 0;
351 
352 	if (total_len - strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AEK]) - 1 != SET_AEK_DATA_LEN) {
353 		err = -EINVAL;
354 		goto exit;
355 	}
356 
357 	addr = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AEK]) + 1;
358 	aek = addr + ETH_ALEN;
359 
360 	RTW_PRINT(FUNC_NDEV_FMT" addr="MAC_FMT"\n"
361 		, FUNC_NDEV_ARG(ndev), MAC_ARG(addr));
362 	if (0)
363 		RTW_PRINT(FUNC_NDEV_FMT" aek="KEY_FMT KEY_FMT"\n"
364 			, FUNC_NDEV_ARG(ndev), KEY_ARG(aek), KEY_ARG(aek + 16));
365 
366 	if (rtw_mesh_plink_set_aek(adapter, addr, aek) != _SUCCESS)
367 		err = -ENOENT;
368 
369 exit:
370 	return err;
371 }
372 #endif /* CONFIG_RTW_MESH_AEK */
373 
rtw_android_priv_cmd(struct net_device * net,struct ifreq * ifr,int cmd)374 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
375 {
376 	#define PRIVATE_COMMAND_MAX_LEN		65536
377 	int ret = 0;
378 	char *command = NULL;
379 	int cmd_num;
380 	int bytes_written = 0;
381 	android_wifi_priv_cmd priv_cmd;
382 	_adapter	*padapter = (_adapter *) rtw_netdev_priv(net);
383 #ifdef CONFIG_WFD
384 	struct wifi_display_info		*pwfd_info;
385 #endif
386 
387 	rtw_lock_suspend();
388 
389 	if (!ifr->ifr_data) {
390 		ret = -EINVAL;
391 		goto exit;
392 	}
393 	if (padapter->registrypriv.mp_mode == 1) {
394 		ret = -EINVAL;
395 		goto exit;
396 	}
397 #ifdef CONFIG_COMPAT
398 #if (KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE)
399 	if (is_compat_task()) {
400 #else
401 	if (in_compat_syscall()) {
402 #endif
403 		/* User space is 32-bit, use compat ioctl */
404 		compat_android_wifi_priv_cmd compat_priv_cmd;
405 
406 		if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
407 			ret = -EFAULT;
408 			goto exit;
409 		}
410 		priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
411 		priv_cmd.used_len = compat_priv_cmd.used_len;
412 		priv_cmd.total_len = compat_priv_cmd.total_len;
413 	} else
414 #endif /* CONFIG_COMPAT */
415 		if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
416 			ret = -EFAULT;
417 			goto exit;
418 		}
419 	if (padapter->registrypriv.mp_mode == 1) {
420 		ret = -EFAULT;
421 		goto exit;
422 	}
423 	/*RTW_INFO("%s priv_cmd.buf=%p priv_cmd.total_len=%d  priv_cmd.used_len=%d\n",__func__,priv_cmd.buf,priv_cmd.total_len,priv_cmd.used_len);*/
424 	if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN || priv_cmd.total_len < 0) {
425 		RTW_WARN("%s: invalid private command (%d)\n", __FUNCTION__,
426 			priv_cmd.total_len);
427 		ret = -EFAULT;
428 		goto exit;
429 	}
430 
431 	command = rtw_zmalloc(priv_cmd.total_len+1);
432 	if (!command) {
433 		RTW_INFO("%s: failed to allocate memory\n", __FUNCTION__);
434 		ret = -ENOMEM;
435 		goto exit;
436 	}
437 	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
438 	if (!access_ok(priv_cmd.buf, priv_cmd.total_len)) {
439 	#else
440 	if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
441 	#endif
442 		RTW_INFO("%s: failed to access memory\n", __FUNCTION__);
443 		ret = -EFAULT;
444 		goto exit;
445 	}
446 	if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
447 		ret = -EFAULT;
448 		goto exit;
449 	}
450 	command[priv_cmd.total_len] = '\0';
451 	RTW_INFO("%s: Android private cmd \"%s\" on %s\n"
452 		 , __FUNCTION__, command, ifr->ifr_name);
453 
454 	cmd_num = rtw_android_cmdstr_to_num(command);
455 
456 	switch (cmd_num) {
457 	case ANDROID_WIFI_CMD_START:
458 		/* bytes_written = wl_android_wifi_on(net); */
459 		goto response;
460 	case ANDROID_WIFI_CMD_SETFWPATH:
461 		goto response;
462 	}
463 
464 	if (!g_wifi_on) {
465 		RTW_INFO("%s: Ignore private cmd \"%s\" - iface %s is down\n"
466 			 , __FUNCTION__, command, ifr->ifr_name);
467 		ret = 0;
468 		goto exit;
469 	}
470 
471 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST)) {
472 		switch (cmd_num) {
473 		case ANDROID_WIFI_CMD_WFD_ENABLE:
474 		case ANDROID_WIFI_CMD_WFD_DISABLE:
475 		case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
476 		case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
477 		case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
478 			goto response;
479 		}
480 	}
481 
482 	switch (cmd_num) {
483 
484 	case ANDROID_WIFI_CMD_STOP:
485 		/* bytes_written = wl_android_wifi_off(net); */
486 		break;
487 
488 	case ANDROID_WIFI_CMD_SCAN_ACTIVE:
489 		/* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE); */
490 		break;
491 	case ANDROID_WIFI_CMD_SCAN_PASSIVE:
492 		/* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE); */
493 		break;
494 
495 	case ANDROID_WIFI_CMD_RSSI:
496 		bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
497 		break;
498 	case ANDROID_WIFI_CMD_LINKSPEED:
499 		bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
500 		break;
501 
502 	case ANDROID_WIFI_CMD_MACADDR:
503 		bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
504 		break;
505 
506 	case ANDROID_WIFI_CMD_BLOCK_SCAN:
507 		bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
508 		break;
509 
510 	case ANDROID_WIFI_CMD_BLOCK:
511 		bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
512 		break;
513 
514 	case ANDROID_WIFI_CMD_RXFILTER_START:
515 		/* bytes_written = net_os_set_packet_filter(net, 1); */
516 		break;
517 	case ANDROID_WIFI_CMD_RXFILTER_STOP:
518 		/* bytes_written = net_os_set_packet_filter(net, 0); */
519 		break;
520 	case ANDROID_WIFI_CMD_RXFILTER_ADD:
521 		/* int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; */
522 		/* bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); */
523 		break;
524 	case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
525 		/* int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; */
526 		/* bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); */
527 		break;
528 
529 	case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
530 		/* TBD: BTCOEXSCAN-START */
531 		break;
532 	case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
533 		/* TBD: BTCOEXSCAN-STOP */
534 		break;
535 	case ANDROID_WIFI_CMD_BTCOEXMODE:
536 #if 0
537 		uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
538 		if (mode == 1)
539 			net_os_set_packet_filter(net, 0); /* DHCP starts */
540 		else
541 			net_os_set_packet_filter(net, 1); /* DHCP ends */
542 #ifdef WL_CFG80211
543 		bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
544 #endif
545 #endif
546 		break;
547 
548 	case ANDROID_WIFI_CMD_SETSUSPENDMODE:
549 		break;
550 
551 	case ANDROID_WIFI_CMD_SETSUSPENDOPT:
552 		/* bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); */
553 		break;
554 
555 	case ANDROID_WIFI_CMD_SETBAND:
556 		bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
557 		break;
558 
559 	case ANDROID_WIFI_CMD_GETBAND:
560 		bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
561 		break;
562 
563 	case ANDROID_WIFI_CMD_COUNTRY:
564 		bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
565 		break;
566 
567 #ifdef CONFIG_PNO_SUPPORT
568 	case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
569 		break;
570 	case ANDROID_WIFI_CMD_PNOSETUP_SET:
571 		break;
572 	case ANDROID_WIFI_CMD_PNOENABLE_SET:
573 		break;
574 #endif
575 
576 	case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
577 		bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
578 		break;
579 	case ANDROID_WIFI_CMD_P2P_SET_NOA:
580 		/* int skip = strlen(CMD_P2P_SET_NOA) + 1; */
581 		/* bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); */
582 		break;
583 	case ANDROID_WIFI_CMD_P2P_GET_NOA:
584 		/* bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); */
585 		break;
586 	case ANDROID_WIFI_CMD_P2P_SET_PS:
587 		/* int skip = strlen(CMD_P2P_SET_PS) + 1; */
588 		/* bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); */
589 		break;
590 
591 #ifdef CONFIG_IOCTL_CFG80211
592 	case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE: {
593 		int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
594 		bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
595 
596 		adapter_to_dvobj(padapter)->wpas_type = RTW_WPAS_ANDROID;
597 		break;
598 	}
599 #endif /* CONFIG_IOCTL_CFG80211 */
600 
601 #ifdef CONFIG_WFD
602 
603 	case ANDROID_WIFI_CMD_MIRACAST:
604 		bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
605 		break;
606 
607 	case ANDROID_WIFI_CMD_WFD_ENABLE: {
608 		/*	Commented by Albert 2012/07/24 */
609 		/*	We can enable the WFD function by using the following command: */
610 		/*	wpa_cli driver wfd-enable */
611 
612 		rtw_wfd_enable(padapter, 1);
613 		break;
614 	}
615 
616 	case ANDROID_WIFI_CMD_WFD_DISABLE: {
617 		/*	Commented by Albert 2012/07/24 */
618 		/*	We can disable the WFD function by using the following command: */
619 		/*	wpa_cli driver wfd-disable */
620 
621 		rtw_wfd_enable(padapter, 0);
622 		break;
623 	}
624 	case ANDROID_WIFI_CMD_WFD_SET_TCPPORT: {
625 		/*	Commented by Albert 2012/07/24 */
626 		/*	We can set the tcp port number by using the following command: */
627 		/*	wpa_cli driver wfd-set-tcpport = 554 */
628 
629 		rtw_wfd_set_ctrl_port(padapter, (u16)get_int_from_command(command));
630 		break;
631 	}
632 	case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT: {
633 		break;
634 	}
635 	case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE: {
636 		/*	Commented by Albert 2012/08/28 */
637 		/*	Specify the WFD device type ( WFD source/primary sink ) */
638 
639 		pwfd_info = &padapter->wfd_info;
640 
641 		pwfd_info->wfd_device_type = (u8) get_int_from_command(command);
642 		pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
643 		break;
644 	}
645 #endif
646 	case ANDROID_WIFI_CMD_CHANGE_DTIM: {
647 #ifdef CONFIG_LPS
648 		u8 dtim;
649 		u8 *ptr = (u8 *) command;
650 
651 		ptr += 9;/* string command length of  "SET_DTIM"; */
652 
653 		dtim = rtw_atoi(ptr);
654 
655 		RTW_INFO("DTIM=%d\n", dtim);
656 
657 		rtw_lps_change_dtim_cmd(padapter, dtim);
658 #endif
659 	}
660 	break;
661 
662 #if CONFIG_RTW_MACADDR_ACL
663 	case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL: {
664 		rtw_set_macaddr_acl(padapter, RTW_ACL_PERIOD_BSS, get_int_from_command(command));
665 		break;
666 	}
667 	case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA: {
668 		u8 addr[ETH_ALEN] = {0x00};
669 		macstr2num(addr, command + strlen("HOSTAPD_ACL_ADD_STA") + 3);	/* 3 is space bar + "=" + space bar these 3 chars */
670 		rtw_acl_add_sta(padapter, RTW_ACL_PERIOD_BSS, addr);
671 		break;
672 	}
673 	case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA: {
674 		u8 addr[ETH_ALEN] = {0x00};
675 		macstr2num(addr, command + strlen("HOSTAPD_ACL_REMOVE_STA") + 3);	/* 3 is space bar + "=" + space bar these 3 chars */
676 		rtw_acl_remove_sta(padapter, RTW_ACL_PERIOD_BSS, addr);
677 		break;
678 	}
679 #endif /* CONFIG_RTW_MACADDR_ACL */
680 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
681 	case ANDROID_WIFI_CMD_GTK_REKEY_OFFLOAD:
682 		rtw_gtk_offload(net, (u8 *)command);
683 		break;
684 #endif /* CONFIG_GTK_OL		 */
685 	case ANDROID_WIFI_CMD_P2P_DISABLE: {
686 #ifdef CONFIG_P2P
687 		/* This Android private command is no longer in use */
688 		/* rtw_p2p_enable(padapter, P2P_ROLE_DISABLE); */
689 #endif /* CONFIG_P2P */
690 		break;
691 	}
692 
693 #ifdef CONFIG_RTW_MESH_AEK
694 	case ANDROID_WIFI_CMD_SET_AEK:
695 		bytes_written = rtw_android_set_aek(net, command, priv_cmd.total_len);
696 		break;
697 #endif
698 
699 	case ANDROID_WIFI_CMD_EXT_AUTH_STATUS: {
700 		rtw_set_external_auth_status(padapter,
701 			command + strlen("EXT_AUTH_STATUS "),
702 			priv_cmd.total_len - strlen("EXT_AUTH_STATUS "));
703 		break;
704 	}
705 	case ANDROID_WIFI_CMD_DRIVERVERSION: {
706 		bytes_written = strlen(DRIVERVERSION);
707 		snprintf(command, bytes_written + 1, DRIVERVERSION);
708 		break;
709 	}
710 #ifdef ROKU_PRIVATE
711 	case ANDROID_WIFI_CMD_ROKU_FIND_REMOTE: {
712 		struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
713 		struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
714 		u8 	num, cmdlen;
715 		u8	*ptr,*remote_mac_addr;
716 		int 	i;
717 
718 		cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_ROKU_FIND_REMOTE]);
719 		num = *(command + cmdlen + 1) - '0';
720 
721 		if (num != 0) {
722 			pwdinfo->num_of_remote = num;
723 			remote_mac_addr = pwdinfo->remote_mac_address;
724 			ptr = command + cmdlen + 3;
725 
726 			for (i = 0; i < num; i++) {
727 				macstr2num(remote_mac_addr, ptr);
728 				ptr += 18; /* skip space and go to next mac addr */
729 				remote_mac_addr += 6;
730 			}
731 
732 			set_find_remote_timer(pmlmeext, 1);
733 		}
734 		else
735 			_cancel_timer_ex(&pmlmeext->find_remote_timer);
736 		break;
737 	}
738 #endif
739 	default:
740 		RTW_INFO("Unknown PRIVATE command %s - ignored\n", command);
741 		snprintf(command, 3, "OK");
742 		bytes_written = strlen("OK");
743 	}
744 
745 response:
746 	if (bytes_written >= 0) {
747 		if ((bytes_written == 0) && (priv_cmd.total_len > 0))
748 			command[0] = '\0';
749 		if (bytes_written >= priv_cmd.total_len) {
750 			RTW_INFO("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
751 			bytes_written = priv_cmd.total_len;
752 		} else
753 			bytes_written++;
754 		priv_cmd.used_len = bytes_written;
755 		if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
756 			RTW_INFO("%s: failed to copy data to user buffer\n", __FUNCTION__);
757 			ret = -EFAULT;
758 		}
759 	} else
760 		ret = bytes_written;
761 
762 exit:
763 	rtw_unlock_suspend();
764 	if (command)
765 		rtw_mfree(command, priv_cmd.total_len + 1);
766 
767 	return ret;
768 }
769 
770 
771 /**
772  * Functions for Android WiFi card detection
773  */
774 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
775 
776 static int g_wifidev_registered = 0;
777 static struct semaphore wifi_control_sem;
778 static struct wifi_platform_data *wifi_control_data = NULL;
779 static struct resource *wifi_irqres = NULL;
780 
781 static int wifi_add_dev(void);
782 static void wifi_del_dev(void);
783 
784 int rtw_android_wifictrl_func_add(void)
785 {
786 	int ret = 0;
787 	sema_init(&wifi_control_sem, 0);
788 
789 	ret = wifi_add_dev();
790 	if (ret) {
791 		RTW_INFO("%s: platform_driver_register failed\n", __FUNCTION__);
792 		return ret;
793 	}
794 	g_wifidev_registered = 1;
795 
796 	/* Waiting callback after platform_driver_register is done or exit with error */
797 	if (down_timeout(&wifi_control_sem,  msecs_to_jiffies(1000)) != 0) {
798 		ret = -EINVAL;
799 		RTW_INFO("%s: platform_driver_register timeout\n", __FUNCTION__);
800 	}
801 
802 	return ret;
803 }
804 
805 void rtw_android_wifictrl_func_del(void)
806 {
807 	if (g_wifidev_registered) {
808 		wifi_del_dev();
809 		g_wifidev_registered = 0;
810 	}
811 }
812 
813 void *wl_android_prealloc(int section, unsigned long size)
814 {
815 	void *alloc_ptr = NULL;
816 	if (wifi_control_data && wifi_control_data->mem_prealloc) {
817 		alloc_ptr = wifi_control_data->mem_prealloc(section, size);
818 		if (alloc_ptr) {
819 			RTW_INFO("success alloc section %d\n", section);
820 			if (size != 0L)
821 				memset(alloc_ptr, 0, size);
822 			return alloc_ptr;
823 		}
824 	}
825 
826 	RTW_INFO("can't alloc section %d\n", section);
827 	return NULL;
828 }
829 
830 int wifi_get_irq_number(unsigned long *irq_flags_ptr)
831 {
832 	if (wifi_irqres) {
833 		*irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
834 		return (int)wifi_irqres->start;
835 	}
836 #ifdef CUSTOM_OOB_GPIO_NUM
837 	return CUSTOM_OOB_GPIO_NUM;
838 #else
839 	return -1;
840 #endif
841 }
842 
843 int wifi_set_power(int on, unsigned long msec)
844 {
845 	RTW_INFO("%s = %d\n", __FUNCTION__, on);
846 	if (wifi_control_data && wifi_control_data->set_power)
847 		wifi_control_data->set_power(on);
848 	if (msec)
849 		msleep(msec);
850 	return 0;
851 }
852 
853 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
854 int wifi_get_mac_addr(unsigned char *buf)
855 {
856 	RTW_INFO("%s\n", __FUNCTION__);
857 	if (!buf)
858 		return -EINVAL;
859 	if (wifi_control_data && wifi_control_data->get_mac_addr)
860 		return wifi_control_data->get_mac_addr(buf);
861 	return -EOPNOTSUPP;
862 }
863 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
864 
865 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
866 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
867 void *wifi_get_country_code(char *ccode, u32 flags)
868 #else /* Linux kernel < 3.18 */
869 void *wifi_get_country_code(char *ccode)
870 #endif /* Linux kernel < 3.18 */
871 {
872 	RTW_INFO("%s\n", __FUNCTION__);
873 	if (!ccode)
874 		return NULL;
875 	if (wifi_control_data && wifi_control_data->get_country_code)
876 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
877 		return wifi_control_data->get_country_code(ccode, flags);
878 #else /* Linux kernel < 3.18 */
879 		return wifi_control_data->get_country_code(ccode);
880 #endif /* Linux kernel < 3.18 */
881 	return NULL;
882 }
883 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
884 
885 static int wifi_set_carddetect(int on)
886 {
887 	RTW_INFO("%s = %d\n", __FUNCTION__, on);
888 	if (wifi_control_data && wifi_control_data->set_carddetect)
889 		wifi_control_data->set_carddetect(on);
890 	return 0;
891 }
892 
893 static int wifi_probe(struct platform_device *pdev)
894 {
895 	struct wifi_platform_data *wifi_ctrl =
896 		(struct wifi_platform_data *)(pdev->dev.platform_data);
897 	int wifi_wake_gpio = 0;
898 
899 	RTW_INFO("## %s\n", __FUNCTION__);
900 	wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
901 
902 	if (wifi_irqres == NULL)
903 		wifi_irqres = platform_get_resource_byname(pdev,
904 				IORESOURCE_IRQ, "bcm4329_wlan_irq");
905 	else
906 		wifi_wake_gpio = wifi_irqres->start;
907 
908 #ifdef CONFIG_GPIO_WAKEUP
909 	RTW_INFO("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
910 	       (int)wifi_irqres->start, wifi_wake_gpio);
911 
912 	if (wifi_wake_gpio > 0) {
913 		gpio_request(wifi_wake_gpio, "oob_irq");
914 		gpio_direction_input(wifi_wake_gpio);
915 		oob_irq = gpio_to_irq(wifi_wake_gpio);
916 		RTW_INFO("%s oob_irq:%d\n", __func__, oob_irq);
917 	} else if (wifi_irqres) {
918 		oob_irq = wifi_irqres->start;
919 		RTW_INFO("%s oob_irq:%d\n", __func__, oob_irq);
920 	}
921 
922 	platform_wifi_get_oob_irq(&oob_irq);
923 #endif
924 	wifi_control_data = wifi_ctrl;
925 
926 	wifi_set_power(1, 0);	/* Power On */
927 	wifi_set_carddetect(1);	/* CardDetect (0->1) */
928 
929 	up(&wifi_control_sem);
930 	return 0;
931 }
932 
933 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
934 extern _adapter * g_test_adapter;
935 
936 static void shutdown_card(void)
937 {
938 	u32 addr;
939 	u8 tmp8, cnt = 0;
940 
941 	if (NULL == g_test_adapter) {
942 		RTW_INFO("%s: padapter==NULL\n", __FUNCTION__);
943 		return;
944 	}
945 
946 #ifdef CONFIG_FWLPS_IN_IPS
947 	LeaveAllPowerSaveMode(g_test_adapter);
948 #endif /* CONFIG_FWLPS_IN_IPS */
949 
950 #ifdef CONFIG_WOWLAN
951 #ifdef CONFIG_GPIO_WAKEUP
952 	/*default wake up pin change to BT*/
953 	RTW_INFO("%s:default wake up pin change to BT\n", __FUNCTION__);
954 	/* ToDo: clear pin mux code is not ready
955 	rtw_hal_switch_gpio_wl_ctrl(g_test_adapter, WAKEUP_GPIO_IDX, _FALSE); */
956 #endif /* CONFIG_GPIO_WAKEUP */
957 #endif /* CONFIG_WOWLAN */
958 
959 	/* Leave SDIO HCI Suspend */
960 	#if 0 /*GEORGIA_TODO_REDEFINE_IO*/
961 	addr = 0x10250086;
962 	rtw_write8(g_test_adapter, addr, 0);
963 	do {
964 
965 		tmp8 = rtw_read8(g_test_adapter, addr);
966 		cnt++;
967 		RTW_INFO(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n",
968 			 FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt);
969 
970 		if (tmp8 & BIT(1))
971 			break;
972 
973 		if (cnt >= 100) {
974 			RTW_INFO(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
975 				 FUNC_ADPT_ARG(g_test_adapter), addr);
976 			break;
977 		}
978 
979 		rtw_mdelay_os(10);
980 	} while (1);
981 
982 	/* unlock register I/O */
983 	rtw_write8(g_test_adapter, 0x1C, 0);
984 
985 	/* enable power down function */
986 	/* 0x04[4] = 1 */
987 	/* 0x05[7] = 1 */
988 	addr = 0x04;
989 	tmp8 = rtw_read8(g_test_adapter, addr);
990 	tmp8 |= BIT(4);
991 	rtw_write8(g_test_adapter, addr, tmp8);
992 	RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
993 		FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
994 
995 	addr = 0x05;
996 	tmp8 = rtw_read8(g_test_adapter, addr);
997 	tmp8 |= BIT(7);
998 	rtw_write8(g_test_adapter, addr, tmp8);
999 	RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1000 		FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1001 
1002 	/* lock register page0 0x0~0xB read/write */
1003 	rtw_write8(g_test_adapter, 0x1C, 0x0E);
1004 #else
1005 	rtw_hal_sdio_leave_suspend(g_test_adapter);
1006 #endif
1007 	dev_set_surprise_removed(adapter_to_dvobj(g_test_adapter));
1008 	RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=%s\n",
1009 		FUNC_ADPT_ARG(g_test_adapter),
1010 		dev_is_surprise_removed(adapter_to_dvobj(g_test_adapter)) ? "True" : "False");
1011 }
1012 #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1013 
1014 static int wifi_remove(struct platform_device *pdev)
1015 {
1016 	struct wifi_platform_data *wifi_ctrl =
1017 		(struct wifi_platform_data *)(pdev->dev.platform_data);
1018 
1019 	RTW_INFO("## %s\n", __FUNCTION__);
1020 	wifi_control_data = wifi_ctrl;
1021 
1022 	wifi_set_power(0, 0);	/* Power Off */
1023 	wifi_set_carddetect(0);	/* CardDetect (1->0) */
1024 
1025 	up(&wifi_control_sem);
1026 	return 0;
1027 }
1028 
1029 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1030 static void wifi_shutdown(struct platform_device *pdev)
1031 {
1032 	struct wifi_platform_data *wifi_ctrl =
1033 		(struct wifi_platform_data *)(pdev->dev.platform_data);
1034 
1035 
1036 	RTW_INFO("## %s\n", __FUNCTION__);
1037 
1038 	wifi_control_data = wifi_ctrl;
1039 
1040 	shutdown_card();
1041 	wifi_set_power(0, 0);	/* Power Off */
1042 	wifi_set_carddetect(0);	/* CardDetect (1->0) */
1043 }
1044 #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1045 
1046 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
1047 {
1048 	RTW_INFO("##> %s\n", __FUNCTION__);
1049 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1050 	bcmsdh_oob_intr_set(0);
1051 #endif
1052 	return 0;
1053 }
1054 
1055 static int wifi_resume(struct platform_device *pdev)
1056 {
1057 	RTW_INFO("##> %s\n", __FUNCTION__);
1058 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1059 	if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
1060 		bcmsdh_oob_intr_set(1);
1061 #endif
1062 	return 0;
1063 }
1064 
1065 /* temporarily use these two */
1066 static struct platform_driver wifi_device = {
1067 	.probe          = wifi_probe,
1068 	.remove         = wifi_remove,
1069 	.suspend        = wifi_suspend,
1070 	.resume         = wifi_resume,
1071 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1072 	.shutdown       = wifi_shutdown,
1073 #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1074 	.driver         = {
1075 		.name   = "bcmdhd_wlan",
1076 	}
1077 };
1078 
1079 static struct platform_driver wifi_device_legacy = {
1080 	.probe          = wifi_probe,
1081 	.remove         = wifi_remove,
1082 	.suspend        = wifi_suspend,
1083 	.resume         = wifi_resume,
1084 	.driver         = {
1085 		.name   = "bcm4329_wlan",
1086 	}
1087 };
1088 
1089 static int wifi_add_dev(void)
1090 {
1091 	RTW_INFO("## Calling platform_driver_register\n");
1092 	platform_driver_register(&wifi_device);
1093 	platform_driver_register(&wifi_device_legacy);
1094 	return 0;
1095 }
1096 
1097 static void wifi_del_dev(void)
1098 {
1099 	RTW_INFO("## Unregister platform_driver_register\n");
1100 	platform_driver_unregister(&wifi_device);
1101 	platform_driver_unregister(&wifi_device_legacy);
1102 }
1103 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
1104 
1105 
1106