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