1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
21 #ifdef CONFIG_GPIO_WAKEUP
22 #include <linux/gpio.h>
25 #include <drv_types.h>
27 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
28 #include <linux/platform_device.h>
29 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
30 #include <linux/wlan_plat.h>
32 #include <linux/wifi_tiwlan.h>
34 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
36 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
37 #define strnicmp strncasecmp
38 #endif /* Linux kernel >= 4.0.0 */
40 #ifdef CONFIG_GPIO_WAKEUP
41 #include <linux/interrupt.h>
42 #include <linux/irq.h>
45 #include "rtw_version.h"
47 extern void macstr2num(u8 *dst, u8 *src);
49 const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
76 #ifdef CONFIG_PNO_SUPPORT
93 "HOSTAPD_SET_MACADDR_ACL",
94 "HOSTAPD_ACL_ADD_STA",
95 "HOSTAPD_ACL_REMOVE_STA",
96 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
98 #endif /* CONFIG_GTK_OL */
99 /* Private command for P2P disable*/
104 #ifdef CONFIG_PNO_SUPPORT
105 #define PNO_TLV_PREFIX 'S'
106 #define PNO_TLV_VERSION '1'
107 #define PNO_TLV_SUBVERSION '2'
108 #define PNO_TLV_RESERVED '0'
109 #define PNO_TLV_TYPE_SSID_IE 'S'
110 #define PNO_TLV_TYPE_TIME 'T'
111 #define PNO_TLV_FREQ_REPEAT 'R'
112 #define PNO_TLV_FREQ_EXPO_MAX 'M'
114 typedef struct cmd_tlv {
121 #ifdef CONFIG_PNO_SET_DEBUG
122 char pno_in_example[] = {
123 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
127 'd', 'l', 'i', 'n', 'k',
130 'B', 'U', 'F', 'B', 'U', 'F',
133 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '@', '#', '$', '%', '^',
136 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
145 #endif /* CONFIG_PNO_SET_DEBUG */
146 #endif /* PNO_SUPPORT */
148 typedef struct android_wifi_priv_cmd {
152 } android_wifi_priv_cmd;
155 typedef struct compat_android_wifi_priv_cmd {
159 } compat_android_wifi_priv_cmd;
160 #endif /* CONFIG_COMPAT */
163 * Local (static) functions and variables
166 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
167 * time (only) in dhd_open, subsequential wifi on will be handled by
170 static int g_wifi_on = _TRUE;
172 unsigned int oob_irq = 0;
173 unsigned int oob_gpio = 0;
175 #ifdef CONFIG_PNO_SUPPORT
177 * rtw_android_pno_setup
179 * This is used for private command.
183 * command: parameters from private command
184 * total_len: the length of the command.
187 static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len)
189 pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
192 cmd_tlv_t *cmd_tlv_temp;
197 int pno_freq_expo_max = 0;
198 int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1;
200 #ifdef CONFIG_PNO_SET_DEBUG
205 total_len = sizeof(pno_in_example);
206 str_ptr = p + cmdlen;
208 str_ptr = command + cmdlen;
211 if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
212 RTW_INFO("%s argument=%d less min size\n", __func__, total_len);
216 tlv_size_left = total_len - cmdlen;
218 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
219 memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
221 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
222 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
223 (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
225 str_ptr += sizeof(cmd_tlv_t);
226 tlv_size_left -= sizeof(cmd_tlv_t);
228 nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
229 MAX_PNO_LIST_COUNT, &tlv_size_left);
231 RTW_INFO("SSID is not presented or corrupted ret=%d\n", nssid);
234 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
235 RTW_INFO("%s scan duration corrupted field size %d\n",
236 __func__, tlv_size_left);
240 pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
241 RTW_INFO("%s: pno_time=%d\n", __func__, pno_time);
243 if (str_ptr[0] != 0) {
244 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
245 RTW_INFO("%s pno repeat : corrupted field\n",
250 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
251 RTW_INFO("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat);
252 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
253 RTW_INFO("%s FREQ_EXPO_MAX corrupted field size\n",
258 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
259 RTW_INFO("%s: pno_freq_expo_max=%d\n",
260 __func__, pno_freq_expo_max);
264 RTW_INFO("%s get wrong TLV command\n", __FUNCTION__);
268 res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
270 #ifdef CONFIG_PNO_SET_DEBUG
271 rtw_dev_pno_debug(net);
279 * rtw_android_cfg80211_pno_setup
281 * This is used for cfg80211 sched_scan.
285 * request: cfg80211_request
288 int rtw_android_cfg80211_pno_setup(struct net_device *net,
289 struct cfg80211_ssid *ssids, int n_ssids, int interval)
295 int pno_freq_expo_max = 0;
297 pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
299 if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
300 RTW_INFO("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
304 memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
308 for (index = 0 ; index < nssid ; index++) {
309 pno_ssids_local[index].SSID_len = ssids[index].ssid_len;
310 memcpy(pno_ssids_local[index].SSID, ssids[index].ssid,
311 ssids[index].ssid_len);
314 pno_time = (interval / 1000);
316 RTW_INFO("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
318 res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
319 pno_repeat, pno_freq_expo_max);
321 #ifdef CONFIG_PNO_SET_DEBUG
322 rtw_dev_pno_debug(net);
328 int rtw_android_pno_enable(struct net_device *net, int pno_enable)
330 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
331 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
334 pwrctl->wowlan_pno_enable = pno_enable;
335 RTW_INFO("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
336 if (pwrctl->wowlan_pno_enable == 0) {
337 if (pwrctl->pnlo_info != NULL) {
338 rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
339 pwrctl->pnlo_info = NULL;
341 if (pwrctl->pno_ssid_list != NULL) {
342 rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
343 pwrctl->pno_ssid_list = NULL;
345 if (pwrctl->pscan_info != NULL) {
346 rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
347 pwrctl->pscan_info = NULL;
354 #endif /* CONFIG_PNO_SUPPORT */
356 int rtw_android_cmdstr_to_num(char *cmdstr)
359 for (cmd_num = 0 ; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
360 if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])))
366 int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
368 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
369 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
370 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
371 int bytes_written = 0;
373 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
374 bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
375 pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
378 return bytes_written;
381 int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
383 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
384 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
385 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
386 int bytes_written = 0;
389 link_speed = rtw_get_cur_max_rate(padapter) / 10;
390 bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
392 return bytes_written;
395 int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
397 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
398 int bytes_written = 0;
400 bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
401 return bytes_written;
404 int rtw_android_set_country(struct net_device *net, char *command, int total_len)
406 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
407 char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
410 ret = rtw_set_country(adapter, country_code);
412 return (ret == _SUCCESS) ? 0 : -1;
415 int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
417 int bytes_written = 0;
419 /* We use the same address as our HW MAC address */
420 _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
422 bytes_written = ETH_ALEN;
423 return bytes_written;
426 int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
428 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
429 char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
431 #ifdef CONFIG_IOCTL_CFG80211
432 adapter_wdev_data(adapter)->block_scan = (*block_value == '0') ? _FALSE : _TRUE;
438 int rtw_android_set_block(struct net_device *net, char *command, int total_len)
440 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
441 char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
443 #ifdef CONFIG_IOCTL_CFG80211
444 adapter_wdev_data(adapter)->block = (*block_value == '0') ? _FALSE : _TRUE;
450 int rtw_android_setband(struct net_device *net, char *command, int total_len)
452 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
453 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
454 u32 band = WIFI_FREQUENCY_BAND_AUTO;
457 if (sscanf(arg, "%u", &band) >= 1)
458 ret = rtw_set_band(adapter, band);
460 return (ret == _SUCCESS) ? 0 : -1;
463 int rtw_android_getband(struct net_device *net, char *command, int total_len)
465 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
466 int bytes_written = 0;
468 bytes_written = snprintf(command, total_len, "%u", adapter->setband);
470 return bytes_written;
474 int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
476 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
477 struct wifi_display_info *wfd_info = &adapter->wfd_info;
478 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
483 num = sscanf(arg, "%hhu", &mode);
490 mode = MIRACAST_SOURCE;
493 mode = MIRACAST_SINK;
495 case 0: /* disabled */
497 mode = MIRACAST_DISABLED;
500 wfd_info->stack_wfd_mode = mode;
501 RTW_INFO("stack miracast mode: %s\n", get_miracast_mode_str(wfd_info->stack_wfd_mode));
506 return (ret == _SUCCESS) ? 0 : -1;
508 #endif /* CONFIG_WFD */
510 int get_int_from_command(char *pcmd)
514 for (i = 0; i < strlen(pcmd); i++) {
515 if (pcmd[i] == '=') {
516 /* Skip the '=' and space characters. */
521 return rtw_atoi(pcmd + i) ;
524 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
525 int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
528 /* u8 *cmd_ptr = priv_cmd.buf; */
529 struct sta_info *psta;
530 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
531 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
532 struct sta_priv *pstapriv = &padapter->stapriv;
533 struct security_priv *psecuritypriv = &(padapter->securitypriv);
534 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
538 RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
540 /* string command length of "GTK_REKEY_OFFLOAD" */
543 _rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
544 cmd_ptr += RTW_KEK_LEN;
546 printk("supplicant KEK: ");
547 for(i=0;i<RTW_KEK_LEN; i++)
548 printk(" %02x ", psta->kek[i]);
549 printk("\n supplicant KCK: ");
551 _rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
552 cmd_ptr += RTW_KCK_LEN;
554 for(i=0;i<RTW_KEK_LEN; i++)
555 printk(" %02x ", psta->kck[i]);
557 _rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
558 psecuritypriv->binstallKCK_KEK = _TRUE;
560 /* printk("\nREPLAY_CTR: "); */
561 /* for(i=0;i<RTW_REPLAY_CTR_LEN; i++) */
562 /* printk(" %02x ", psta->replay_ctr[i]); */
567 #endif /* CONFIG_GTK_OL */
569 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
572 char *command = NULL;
574 int bytes_written = 0;
575 #ifdef CONFIG_PNO_SUPPORT
579 android_wifi_priv_cmd priv_cmd;
580 _adapter *padapter = (_adapter *) rtw_netdev_priv(net);
582 struct wifi_display_info *pwfd_info;
587 if (!ifr->ifr_data) {
591 if (padapter->registrypriv.mp_mode == 1) {
596 #if (KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE)
597 if (is_compat_task()) {
599 if (in_compat_syscall()) {
601 /* User space is 32-bit, use compat ioctl */
602 compat_android_wifi_priv_cmd compat_priv_cmd;
604 if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
608 priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
609 priv_cmd.used_len = compat_priv_cmd.used_len;
610 priv_cmd.total_len = compat_priv_cmd.total_len;
612 #endif /* CONFIG_COMPAT */
613 if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
617 if (padapter->registrypriv.mp_mode == 1) {
621 /*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);*/
622 command = rtw_zmalloc(priv_cmd.total_len);
624 RTW_INFO("%s: failed to allocate memory\n", __FUNCTION__);
629 if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
630 RTW_INFO("%s: failed to access memory\n", __FUNCTION__);
634 if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
639 RTW_INFO("%s: Android private cmd \"%s\" on %s\n"
640 , __FUNCTION__, command, ifr->ifr_name);
642 cmd_num = rtw_android_cmdstr_to_num(command);
645 case ANDROID_WIFI_CMD_START:
646 /* bytes_written = wl_android_wifi_on(net); */
648 case ANDROID_WIFI_CMD_SETFWPATH:
653 RTW_INFO("%s: Ignore private cmd \"%s\" - iface %s is down\n"
654 , __FUNCTION__, command, ifr->ifr_name);
659 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
661 case ANDROID_WIFI_CMD_WFD_ENABLE:
662 case ANDROID_WIFI_CMD_WFD_DISABLE:
663 case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
664 case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
665 case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
672 case ANDROID_WIFI_CMD_STOP:
673 /* bytes_written = wl_android_wifi_off(net); */
676 case ANDROID_WIFI_CMD_SCAN_ACTIVE:
677 /* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE); */
678 #ifdef CONFIG_PLATFORM_MSTAR
679 #ifdef CONFIG_IOCTL_CFG80211
680 adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = _TRUE;
681 #endif /* CONFIG_IOCTL_CFG80211 */
682 #endif /* CONFIG_PLATFORM_MSTAR */
684 case ANDROID_WIFI_CMD_SCAN_PASSIVE:
685 /* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE); */
688 case ANDROID_WIFI_CMD_RSSI:
689 bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
691 case ANDROID_WIFI_CMD_LINKSPEED:
692 bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
695 case ANDROID_WIFI_CMD_MACADDR:
696 bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
699 case ANDROID_WIFI_CMD_BLOCK_SCAN:
700 bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
703 case ANDROID_WIFI_CMD_BLOCK:
704 bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
707 case ANDROID_WIFI_CMD_RXFILTER_START:
708 /* bytes_written = net_os_set_packet_filter(net, 1); */
710 case ANDROID_WIFI_CMD_RXFILTER_STOP:
711 /* bytes_written = net_os_set_packet_filter(net, 0); */
713 case ANDROID_WIFI_CMD_RXFILTER_ADD:
714 /* int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; */
715 /* bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); */
717 case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
718 /* int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; */
719 /* bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); */
722 case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
723 /* TBD: BTCOEXSCAN-START */
725 case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
726 /* TBD: BTCOEXSCAN-STOP */
728 case ANDROID_WIFI_CMD_BTCOEXMODE:
730 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
732 net_os_set_packet_filter(net, 0); /* DHCP starts */
734 net_os_set_packet_filter(net, 1); /* DHCP ends */
736 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
741 case ANDROID_WIFI_CMD_SETSUSPENDOPT:
742 /* bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); */
745 case ANDROID_WIFI_CMD_SETBAND:
746 bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
749 case ANDROID_WIFI_CMD_GETBAND:
750 bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
753 case ANDROID_WIFI_CMD_COUNTRY:
754 bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
757 #ifdef CONFIG_PNO_SUPPORT
758 case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
759 /* bytes_written = dhd_dev_pno_reset(net); */
761 case ANDROID_WIFI_CMD_PNOSETUP_SET:
762 bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
764 case ANDROID_WIFI_CMD_PNOENABLE_SET:
765 cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
766 pno_enable = *(command + cmdlen + 1) - '0';
767 bytes_written = rtw_android_pno_enable(net, pno_enable);
771 case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
772 bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
774 case ANDROID_WIFI_CMD_P2P_SET_NOA:
775 /* int skip = strlen(CMD_P2P_SET_NOA) + 1; */
776 /* bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); */
778 case ANDROID_WIFI_CMD_P2P_GET_NOA:
779 /* bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); */
781 case ANDROID_WIFI_CMD_P2P_SET_PS:
782 /* int skip = strlen(CMD_P2P_SET_PS) + 1; */
783 /* bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); */
786 #ifdef CONFIG_IOCTL_CFG80211
787 case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE: {
788 int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
789 bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
792 #endif /* CONFIG_IOCTL_CFG80211 */
796 case ANDROID_WIFI_CMD_MIRACAST:
797 bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
800 case ANDROID_WIFI_CMD_WFD_ENABLE: {
801 /* Commented by Albert 2012/07/24 */
802 /* We can enable the WFD function by using the following command: */
803 /* wpa_cli driver wfd-enable */
805 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
806 rtw_wfd_enable(padapter, 1);
810 case ANDROID_WIFI_CMD_WFD_DISABLE: {
811 /* Commented by Albert 2012/07/24 */
812 /* We can disable the WFD function by using the following command: */
813 /* wpa_cli driver wfd-disable */
815 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
816 rtw_wfd_enable(padapter, 0);
819 case ANDROID_WIFI_CMD_WFD_SET_TCPPORT: {
820 /* Commented by Albert 2012/07/24 */
821 /* We can set the tcp port number by using the following command: */
822 /* wpa_cli driver wfd-set-tcpport = 554 */
824 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
825 rtw_wfd_set_ctrl_port(padapter, (u16)get_int_from_command(priv_cmd.buf));
828 case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT: {
831 case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE: {
832 /* Commented by Albert 2012/08/28 */
833 /* Specify the WFD device type ( WFD source/primary sink ) */
835 pwfd_info = &padapter->wfd_info;
836 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
837 pwfd_info->wfd_device_type = (u8) get_int_from_command(priv_cmd.buf);
838 pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
843 case ANDROID_WIFI_CMD_CHANGE_DTIM: {
846 u8 *ptr = (u8 *) &priv_cmd.buf;
848 ptr += 9;/* string command length of "SET_DTIM"; */
850 dtim = rtw_atoi(ptr);
852 RTW_INFO("DTIM=%d\n", dtim);
854 rtw_lps_change_dtim_cmd(padapter, dtim);
859 #if CONFIG_RTW_MACADDR_ACL
860 case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL: {
861 rtw_set_macaddr_acl(padapter, get_int_from_command(command));
864 case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA: {
865 u8 addr[ETH_ALEN] = {0x00};
866 macstr2num(addr, command + strlen("HOSTAPD_ACL_ADD_STA") + 3); /* 3 is space bar + "=" + space bar these 3 chars */
867 rtw_acl_add_sta(padapter, addr);
870 case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA: {
871 u8 addr[ETH_ALEN] = {0x00};
872 macstr2num(addr, command + strlen("HOSTAPD_ACL_REMOVE_STA") + 3); /* 3 is space bar + "=" + space bar these 3 chars */
873 rtw_acl_remove_sta(padapter, addr);
876 #endif /* CONFIG_RTW_MACADDR_ACL */
877 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
878 case ANDROID_WIFI_CMD_GTK_REKEY_OFFLOAD:
879 rtw_gtk_offload(net, (u8 *)command);
881 #endif /* CONFIG_GTK_OL */
882 case ANDROID_WIFI_CMD_P2P_DISABLE: {
884 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
885 u8 channel, ch_offset;
888 rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
889 #endif /* CONFIG_P2P */
892 case ANDROID_WIFI_CMD_DRIVERVERSION: {
893 bytes_written = strlen(DRIVERVERSION);
894 snprintf(command, bytes_written + 1, DRIVERVERSION);
898 RTW_INFO("Unknown PRIVATE command %s - ignored\n", command);
899 snprintf(command, 3, "OK");
900 bytes_written = strlen("OK");
904 if (bytes_written >= 0) {
905 if ((bytes_written == 0) && (priv_cmd.total_len > 0))
907 if (bytes_written >= priv_cmd.total_len) {
908 RTW_INFO("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
909 bytes_written = priv_cmd.total_len;
912 priv_cmd.used_len = bytes_written;
913 if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
914 RTW_INFO("%s: failed to copy data to user buffer\n", __FUNCTION__);
921 rtw_unlock_suspend();
923 rtw_mfree(command, priv_cmd.total_len);
930 * Functions for Android WiFi card detection
932 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
934 static int g_wifidev_registered = 0;
935 static struct semaphore wifi_control_sem;
936 static struct wifi_platform_data *wifi_control_data = NULL;
937 static struct resource *wifi_irqres = NULL;
939 static int wifi_add_dev(void);
940 static void wifi_del_dev(void);
942 int rtw_android_wifictrl_func_add(void)
945 sema_init(&wifi_control_sem, 0);
947 ret = wifi_add_dev();
949 RTW_INFO("%s: platform_driver_register failed\n", __FUNCTION__);
952 g_wifidev_registered = 1;
954 /* Waiting callback after platform_driver_register is done or exit with error */
955 if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
957 RTW_INFO("%s: platform_driver_register timeout\n", __FUNCTION__);
963 void rtw_android_wifictrl_func_del(void)
965 if (g_wifidev_registered) {
967 g_wifidev_registered = 0;
971 void *wl_android_prealloc(int section, unsigned long size)
973 void *alloc_ptr = NULL;
974 if (wifi_control_data && wifi_control_data->mem_prealloc) {
975 alloc_ptr = wifi_control_data->mem_prealloc(section, size);
977 RTW_INFO("success alloc section %d\n", section);
979 memset(alloc_ptr, 0, size);
984 RTW_INFO("can't alloc section %d\n", section);
988 int wifi_get_irq_number(unsigned long *irq_flags_ptr)
991 *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
992 return (int)wifi_irqres->start;
994 #ifdef CUSTOM_OOB_GPIO_NUM
995 return CUSTOM_OOB_GPIO_NUM;
1001 int wifi_set_power(int on, unsigned long msec)
1003 RTW_INFO("%s = %d\n", __FUNCTION__, on);
1004 if (wifi_control_data && wifi_control_data->set_power)
1005 wifi_control_data->set_power(on);
1011 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
1012 int wifi_get_mac_addr(unsigned char *buf)
1014 RTW_INFO("%s\n", __FUNCTION__);
1017 if (wifi_control_data && wifi_control_data->get_mac_addr)
1018 return wifi_control_data->get_mac_addr(buf);
1021 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
1023 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
1024 void *wifi_get_country_code(char *ccode, u32 flags)
1026 RTW_INFO("%s\n", __FUNCTION__);
1029 if (wifi_control_data && wifi_control_data->get_country_code)
1030 return wifi_control_data->get_country_code(ccode, flags);
1033 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
1035 static int wifi_set_carddetect(int on)
1037 RTW_INFO("%s = %d\n", __FUNCTION__, on);
1038 if (wifi_control_data && wifi_control_data->set_carddetect)
1039 wifi_control_data->set_carddetect(on);
1043 static int wifi_probe(struct platform_device *pdev)
1045 struct wifi_platform_data *wifi_ctrl =
1046 (struct wifi_platform_data *)(pdev->dev.platform_data);
1047 int wifi_wake_gpio = 0;
1049 RTW_INFO("## %s\n", __FUNCTION__);
1050 wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
1052 if (wifi_irqres == NULL)
1053 wifi_irqres = platform_get_resource_byname(pdev,
1054 IORESOURCE_IRQ, "bcm4329_wlan_irq");
1056 wifi_wake_gpio = wifi_irqres->start;
1058 #ifdef CONFIG_GPIO_WAKEUP
1059 printk("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
1060 wifi_irqres->start, wifi_wake_gpio);
1062 if (wifi_wake_gpio > 0) {
1063 #ifdef CONFIG_PLATFORM_INTEL_BYT
1064 wifi_configure_gpio();
1065 #else /* CONFIG_PLATFORM_INTEL_BYT */
1066 gpio_request(wifi_wake_gpio, "oob_irq");
1067 gpio_direction_input(wifi_wake_gpio);
1068 oob_irq = gpio_to_irq(wifi_wake_gpio);
1069 #endif /* CONFIG_PLATFORM_INTEL_BYT */
1070 printk("%s oob_irq:%d\n", __func__, oob_irq);
1071 } else if (wifi_irqres) {
1072 oob_irq = wifi_irqres->start;
1073 printk("%s oob_irq:%d\n", __func__, oob_irq);
1076 wifi_control_data = wifi_ctrl;
1078 wifi_set_power(1, 0); /* Power On */
1079 wifi_set_carddetect(1); /* CardDetect (0->1) */
1081 up(&wifi_control_sem);
1085 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1086 extern PADAPTER g_test_adapter;
1088 static void shutdown_card(void)
1093 if (NULL == g_test_adapter) {
1094 RTW_INFO("%s: padapter==NULL\n", __FUNCTION__);
1098 #ifdef CONFIG_FWLPS_IN_IPS
1099 LeaveAllPowerSaveMode(g_test_adapter);
1100 #endif /* CONFIG_FWLPS_IN_IPS */
1102 /* Leave SDIO HCI Suspend */
1104 rtw_write8(g_test_adapter, addr, 0);
1106 tmp8 = rtw_read8(g_test_adapter, addr);
1108 RTW_INFO(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n",
1109 FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt);
1115 RTW_INFO(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
1116 FUNC_ADPT_ARG(g_test_adapter), addr);
1123 /* unlock register I/O */
1124 rtw_write8(g_test_adapter, 0x1C, 0);
1126 /* enable power down function */
1130 tmp8 = rtw_read8(g_test_adapter, addr);
1132 rtw_write8(g_test_adapter, addr, tmp8);
1133 RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1134 FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1137 tmp8 = rtw_read8(g_test_adapter, addr);
1139 rtw_write8(g_test_adapter, addr, tmp8);
1140 RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1141 FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1143 /* lock register page0 0x0~0xB read/write */
1144 rtw_write8(g_test_adapter, 0x1C, 0x0E);
1146 rtw_set_surprise_removed(g_test_adapter);
1147 RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=%s\n",
1148 FUNC_ADPT_ARG(g_test_adapter), rtw_is_surprise_removed(g_test_adapter) ? "True" : "False");
1150 #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1152 static int wifi_remove(struct platform_device *pdev)
1154 struct wifi_platform_data *wifi_ctrl =
1155 (struct wifi_platform_data *)(pdev->dev.platform_data);
1157 RTW_INFO("## %s\n", __FUNCTION__);
1158 wifi_control_data = wifi_ctrl;
1160 wifi_set_power(0, 0); /* Power Off */
1161 wifi_set_carddetect(0); /* CardDetect (1->0) */
1163 up(&wifi_control_sem);
1167 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1168 static void wifi_shutdown(struct platform_device *pdev)
1170 struct wifi_platform_data *wifi_ctrl =
1171 (struct wifi_platform_data *)(pdev->dev.platform_data);
1174 RTW_INFO("## %s\n", __FUNCTION__);
1176 wifi_control_data = wifi_ctrl;
1179 wifi_set_power(0, 0); /* Power Off */
1180 wifi_set_carddetect(0); /* CardDetect (1->0) */
1182 #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1184 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
1186 RTW_INFO("##> %s\n", __FUNCTION__);
1187 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1188 bcmsdh_oob_intr_set(0);
1193 static int wifi_resume(struct platform_device *pdev)
1195 RTW_INFO("##> %s\n", __FUNCTION__);
1196 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1197 if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
1198 bcmsdh_oob_intr_set(1);
1203 /* temporarily use these two */
1204 static struct platform_driver wifi_device = {
1205 .probe = wifi_probe,
1206 .remove = wifi_remove,
1207 .suspend = wifi_suspend,
1208 .resume = wifi_resume,
1209 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1210 .shutdown = wifi_shutdown,
1211 #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1213 .name = "bcmdhd_wlan",
1217 static struct platform_driver wifi_device_legacy = {
1218 .probe = wifi_probe,
1219 .remove = wifi_remove,
1220 .suspend = wifi_suspend,
1221 .resume = wifi_resume,
1223 .name = "bcm4329_wlan",
1227 static int wifi_add_dev(void)
1229 RTW_INFO("## Calling platform_driver_register\n");
1230 platform_driver_register(&wifi_device);
1231 platform_driver_register(&wifi_device_legacy);
1235 static void wifi_del_dev(void)
1237 RTW_INFO("## Unregister platform_driver_register\n");
1238 platform_driver_unregister(&wifi_device);
1239 platform_driver_unregister(&wifi_device_legacy);
1241 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
1243 #ifdef CONFIG_GPIO_WAKEUP
1244 #ifdef CONFIG_PLATFORM_INTEL_BYT
1245 int wifi_configure_gpio(void)
1247 if (gpio_request(oob_gpio, "oob_irq")) {
1248 RTW_INFO("## %s Cannot request GPIO\n", __FUNCTION__);
1251 gpio_export(oob_gpio, 0);
1252 if (gpio_direction_input(oob_gpio)) {
1253 RTW_INFO("## %s Cannot set GPIO direction input\n", __FUNCTION__);
1256 oob_irq = gpio_to_irq(oob_gpio);
1258 RTW_INFO("## %s Cannot convert GPIO to IRQ\n", __FUNCTION__);
1262 RTW_INFO("## %s OOB_IRQ=%d\n", __FUNCTION__, oob_irq);
1266 #endif /* CONFIG_PLATFORM_INTEL_BYT */
1267 void wifi_free_gpio(unsigned int gpio)
1269 #ifdef CONFIG_PLATFORM_INTEL_BYT
1272 #endif /* CONFIG_PLATFORM_INTEL_BYT */
1274 #endif /* CONFIG_GPIO_WAKEUP */