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 #ifdef CONFIG_GPIO_WAKEUP
37 #include <linux/interrupt.h>
38 #include <linux/irq.h>
41 extern void macstr2num(u8 *dst, u8 *src);
43 const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
70 #ifdef CONFIG_PNO_SUPPORT
86 "HOSTAPD_SET_MACADDR_ACL",
87 "HOSTAPD_ACL_ADD_STA",
88 "HOSTAPD_ACL_REMOVE_STA",
91 #endif //CONFIG_GTK_OL
92 /* Private command for P2P disable*/
96 #ifdef CONFIG_PNO_SUPPORT
97 #define PNO_TLV_PREFIX 'S'
98 #define PNO_TLV_VERSION '1'
99 #define PNO_TLV_SUBVERSION '2'
100 #define PNO_TLV_RESERVED '0'
101 #define PNO_TLV_TYPE_SSID_IE 'S'
102 #define PNO_TLV_TYPE_TIME 'T'
103 #define PNO_TLV_FREQ_REPEAT 'R'
104 #define PNO_TLV_FREQ_EXPO_MAX 'M'
106 typedef struct cmd_tlv {
113 #ifdef CONFIG_PNO_SET_DEBUG
114 char pno_in_example[] = {
115 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
119 'd', 'l', 'i', 'n', 'k',
122 'B', 'U', 'F', 'B', 'U','F',
125 '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', '!', '@', '#', '$', '%', '^',
128 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
137 #endif /* CONFIG_PNO_SET_DEBUG */
138 #endif /* PNO_SUPPORT */
140 typedef struct android_wifi_priv_cmd {
144 } android_wifi_priv_cmd;
147 typedef struct compat_android_wifi_priv_cmd {
151 } compat_android_wifi_priv_cmd;
152 #endif /* CONFIG_COMPAT */
155 * Local (static) functions and variables
158 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
159 * time (only) in dhd_open, subsequential wifi on will be handled by
162 static int g_wifi_on = _TRUE;
164 unsigned int oob_irq = 0;
165 unsigned int oob_gpio = 0;
167 #ifdef CONFIG_PNO_SUPPORT
169 * rtw_android_pno_setup
171 * This is used for private command.
175 * command: parameters from private command
176 * total_len: the length of the command.
179 static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len) {
180 pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
183 cmd_tlv_t *cmd_tlv_temp;
188 int pno_freq_expo_max = 0;
189 int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1;
191 #ifdef CONFIG_PNO_SET_DEBUG
196 total_len = sizeof(pno_in_example);
197 str_ptr = p + cmdlen;
199 str_ptr = command + cmdlen;
202 if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
203 DBG_871X("%s argument=%d less min size\n", __func__, total_len);
207 tlv_size_left = total_len - cmdlen;
209 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
210 memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
212 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
213 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
214 (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
216 str_ptr += sizeof(cmd_tlv_t);
217 tlv_size_left -= sizeof(cmd_tlv_t);
219 if ((nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
220 MAX_PNO_LIST_COUNT, &tlv_size_left)) <= 0) {
221 DBG_871X("SSID is not presented or corrupted ret=%d\n", nssid);
224 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
225 DBG_871X("%s scan duration corrupted field size %d\n",
226 __func__, tlv_size_left);
230 pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
231 DBG_871X("%s: pno_time=%d\n", __func__, pno_time);
233 if (str_ptr[0] != 0) {
234 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
235 DBG_871X("%s pno repeat : corrupted field\n",
240 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
241 DBG_871X("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat);
242 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
243 DBG_871X("%s FREQ_EXPO_MAX corrupted field size\n",
248 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
249 DBG_871X("%s: pno_freq_expo_max=%d\n",
250 __func__, pno_freq_expo_max);
254 DBG_871X("%s get wrong TLV command\n", __FUNCTION__);
258 res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
260 #ifdef CONFIG_PNO_SET_DEBUG
261 rtw_dev_pno_debug(net);
269 * rtw_android_cfg80211_pno_setup
271 * This is used for cfg80211 sched_scan.
275 * request: cfg80211_request
278 int rtw_android_cfg80211_pno_setup(struct net_device *net,
279 struct cfg80211_ssid *ssids, int n_ssids, int interval) {
284 int pno_freq_expo_max = 0;
286 pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
288 if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
289 DBG_871X("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
293 memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
297 for (index = 0 ; index < nssid ; index++) {
298 pno_ssids_local[index].SSID_len = ssids[index].ssid_len;
299 memcpy(pno_ssids_local[index].SSID, ssids[index].ssid,
300 ssids[index].ssid_len);
303 pno_time = (interval / 1000);
305 DBG_871X("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
307 res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
308 pno_repeat, pno_freq_expo_max);
314 int rtw_android_pno_enable(struct net_device *net, int pno_enable) {
315 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
316 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
319 pwrctl->wowlan_pno_enable = pno_enable;
320 DBG_871X("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
321 if (pwrctl->wowlan_pno_enable == 0) {
322 if (pwrctl->pnlo_info != NULL) {
323 rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
324 pwrctl->pnlo_info = NULL;
326 if (pwrctl->pno_ssid_list != NULL) {
327 rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
328 pwrctl->pno_ssid_list = NULL;
330 if (pwrctl->pscan_info != NULL) {
331 rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
332 pwrctl->pscan_info = NULL;
340 #endif //CONFIG_PNO_SUPPORT
342 int rtw_android_cmdstr_to_num(char *cmdstr)
345 for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
346 if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
352 int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
354 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
355 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
356 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
357 int bytes_written = 0;
359 if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
360 bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
361 pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
364 return bytes_written;
367 int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
369 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
370 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
371 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
372 int bytes_written = 0;
375 link_speed = rtw_get_cur_max_rate(padapter)/10;
376 bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
378 return bytes_written;
381 int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
383 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
384 int bytes_written = 0;
386 bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
387 return bytes_written;
390 int rtw_android_set_country(struct net_device *net, char *command, int total_len)
392 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
393 char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
396 ret = rtw_set_country(adapter, country_code);
398 return (ret==_SUCCESS)?0:-1;
401 int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
403 int bytes_written = 0;
405 //We use the same address as our HW MAC address
406 _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
408 bytes_written = ETH_ALEN;
409 return bytes_written;
412 int rtw_android_set_block(struct net_device *net, char *command, int total_len)
414 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
415 char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
417 #ifdef CONFIG_IOCTL_CFG80211
418 adapter_wdev_data(adapter)->block = (*block_value=='0')?_FALSE:_TRUE;
424 int rtw_android_setband(struct net_device *net, char *command, int total_len)
426 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
427 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
431 sscanf(arg, "%u", &band);
432 ret = rtw_set_band(adapter, band);
434 return (ret==_SUCCESS)?0:-1;
437 int rtw_android_getband(struct net_device *net, char *command, int total_len)
439 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
440 int bytes_written = 0;
442 bytes_written = snprintf(command, total_len, "%u", adapter->setband);
444 return bytes_written;
448 MIRACAST_DISABLED = 0,
454 static const char *miracast_mode_str[] = {
461 static const char *get_miracast_mode_str(int mode)
463 if (mode < MIRACAST_DISABLED || mode >= MIRACAST_INVALID)
464 mode = MIRACAST_INVALID;
466 return miracast_mode_str[mode];
469 int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
471 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
472 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
477 num = sscanf(arg, "%hhu", &mode);
480 DBG_871X("Miracast mode: %s(%u)\n", get_miracast_mode_str(mode), mode);
484 return (ret==_SUCCESS)?0:-1;
487 int get_int_from_command( char* pcmd )
491 for( i = 0; i < strlen( pcmd ); i++ )
493 if ( pcmd[ i ] == '=' )
495 // Skip the '=' and space characters.
500 return ( rtw_atoi( pcmd + i ) );
504 int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
507 //u8 *cmd_ptr = priv_cmd.buf;
508 struct sta_info * psta;
509 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
510 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
511 struct sta_priv *pstapriv = &padapter->stapriv;
512 struct security_priv* psecuritypriv=&(padapter->securitypriv);
513 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
518 DBG_8192C("%s, : Obtain Sta_info fail \n", __func__);
522 //string command length of "GTK_REKEY_OFFLOAD"
525 _rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
526 cmd_ptr += RTW_KEK_LEN;
528 printk("supplicant KEK: ");
529 for(i=0;i<RTW_KEK_LEN; i++)
530 printk(" %02x ", psta->kek[i]);
531 printk("\n supplicant KCK: ");
533 _rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
534 cmd_ptr += RTW_KCK_LEN;
536 for(i=0;i<RTW_KEK_LEN; i++)
537 printk(" %02x ", psta->kck[i]);
539 _rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
540 psecuritypriv->binstallKCK_KEK = _TRUE;
542 //printk("\nREPLAY_CTR: ");
543 //for(i=0;i<RTW_REPLAY_CTR_LEN; i++)
544 //printk(" %02x ", psta->replay_ctr[i]);
549 #endif //CONFIG_GTK_OL
551 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
554 char *command = NULL;
556 int bytes_written = 0;
557 #ifdef CONFIG_PNO_SUPPORT
561 android_wifi_priv_cmd priv_cmd;
562 _adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
564 struct wifi_display_info *pwfd_info;
569 if (!ifr->ifr_data) {
574 if (is_compat_task()) {
575 /* User space is 32-bit, use compat ioctl */
576 compat_android_wifi_priv_cmd compat_priv_cmd;
578 if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
582 priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
583 priv_cmd.used_len = compat_priv_cmd.used_len;
584 priv_cmd.total_len = compat_priv_cmd.total_len;
586 #endif /* CONFIG_COMPAT */
587 if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
591 if ( padapter->registrypriv.mp_mode == 1) {
595 //DBG_871X("%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);
596 command = rtw_zmalloc(priv_cmd.total_len);
599 DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
604 if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
605 DBG_871X("%s: failed to access memory\n", __FUNCTION__);
609 if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
614 DBG_871X("%s: Android private cmd \"%s\" on %s\n"
615 , __FUNCTION__, command, ifr->ifr_name);
617 cmd_num = rtw_android_cmdstr_to_num(command);
620 case ANDROID_WIFI_CMD_START:
621 //bytes_written = wl_android_wifi_on(net);
623 case ANDROID_WIFI_CMD_SETFWPATH:
628 DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
629 ,__FUNCTION__, command, ifr->ifr_name);
636 case ANDROID_WIFI_CMD_STOP:
637 //bytes_written = wl_android_wifi_off(net);
640 case ANDROID_WIFI_CMD_SCAN_ACTIVE:
641 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE);
642 #ifdef CONFIG_PLATFORM_MSTAR
643 #ifdef CONFIG_IOCTL_CFG80211
644 adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = _TRUE;
645 #endif //CONFIG_IOCTL_CFG80211
646 #endif //CONFIG_PLATFORM_MSTAR
648 case ANDROID_WIFI_CMD_SCAN_PASSIVE:
649 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
652 case ANDROID_WIFI_CMD_RSSI:
653 bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
655 case ANDROID_WIFI_CMD_LINKSPEED:
656 bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
659 case ANDROID_WIFI_CMD_MACADDR:
660 bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
663 case ANDROID_WIFI_CMD_BLOCK:
664 bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
667 case ANDROID_WIFI_CMD_RXFILTER_START:
668 //bytes_written = net_os_set_packet_filter(net, 1);
670 case ANDROID_WIFI_CMD_RXFILTER_STOP:
671 //bytes_written = net_os_set_packet_filter(net, 0);
673 case ANDROID_WIFI_CMD_RXFILTER_ADD:
674 //int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
675 //bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
677 case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
678 //int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
679 //bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
682 case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
683 /* TBD: BTCOEXSCAN-START */
685 case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
686 /* TBD: BTCOEXSCAN-STOP */
688 case ANDROID_WIFI_CMD_BTCOEXMODE:
690 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
692 net_os_set_packet_filter(net, 0); /* DHCP starts */
694 net_os_set_packet_filter(net, 1); /* DHCP ends */
696 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
701 case ANDROID_WIFI_CMD_SETSUSPENDOPT:
702 //bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
705 case ANDROID_WIFI_CMD_SETBAND:
706 bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
709 case ANDROID_WIFI_CMD_GETBAND:
710 bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
713 case ANDROID_WIFI_CMD_MIRACAST:
714 bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
717 case ANDROID_WIFI_CMD_COUNTRY:
718 bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
721 #ifdef CONFIG_PNO_SUPPORT
722 case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
723 //bytes_written = dhd_dev_pno_reset(net);
725 case ANDROID_WIFI_CMD_PNOSETUP_SET:
726 bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
728 case ANDROID_WIFI_CMD_PNOENABLE_SET:
729 cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
730 pno_enable = *(command + cmdlen + 1) - '0';
731 bytes_written = rtw_android_pno_enable(net, pno_enable);
735 case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
736 bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
738 case ANDROID_WIFI_CMD_P2P_SET_NOA:
739 //int skip = strlen(CMD_P2P_SET_NOA) + 1;
740 //bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip);
742 case ANDROID_WIFI_CMD_P2P_GET_NOA:
743 //bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
745 case ANDROID_WIFI_CMD_P2P_SET_PS:
746 //int skip = strlen(CMD_P2P_SET_PS) + 1;
747 //bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip);
750 #ifdef CONFIG_IOCTL_CFG80211
751 case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
753 int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
754 bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
757 #endif //CONFIG_IOCTL_CFG80211
760 case ANDROID_WIFI_CMD_WFD_ENABLE:
762 // Commented by Albert 2012/07/24
763 // We can enable the WFD function by using the following command:
764 // wpa_cli driver wfd-enable
766 pwfd_info = &padapter->wfd_info;
767 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
768 pwfd_info->wfd_enable = _TRUE;
772 case ANDROID_WIFI_CMD_WFD_DISABLE:
774 // Commented by Albert 2012/07/24
775 // We can disable the WFD function by using the following command:
776 // wpa_cli driver wfd-disable
778 pwfd_info = &padapter->wfd_info;
779 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
780 pwfd_info->wfd_enable = _FALSE;
783 case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
785 // Commented by Albert 2012/07/24
786 // We can set the tcp port number by using the following command:
787 // wpa_cli driver wfd-set-tcpport = 554
789 pwfd_info = &padapter->wfd_info;
790 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
792 pwfd_info->rtsp_ctrlport = ( u16 ) get_int_from_command( priv_cmd.buf );
796 case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
800 case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
802 // Commented by Albert 2012/08/28
803 // Specify the WFD device type ( WFD source/primary sink )
805 pwfd_info = &padapter->wfd_info;
806 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
808 pwfd_info->wfd_device_type = ( u8 ) get_int_from_command( priv_cmd.buf );
809 pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
814 case ANDROID_WIFI_CMD_CHANGE_DTIM:
818 u8 *ptr =(u8 *) &priv_cmd.buf;
820 ptr += 9;//string command length of "SET_DTIM";
822 dtim = rtw_atoi(ptr);
824 DBG_871X("DTIM=%d\n", dtim);
826 rtw_lps_change_dtim_cmd(padapter, dtim);
830 case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL:
832 padapter->stapriv.acl_list.mode = ( u8 ) get_int_from_command(command);
833 DBG_871X("%s ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL mode:%d\n", __FUNCTION__, padapter->stapriv.acl_list.mode);
836 case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA:
838 u8 addr[ETH_ALEN] = {0x00};
839 macstr2num(addr, command+strlen("HOSTAPD_ACL_ADD_STA")+3); // 3 is space bar + "=" + space bar these 3 chars
840 rtw_acl_add_sta(padapter, addr);
843 case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA:
845 u8 addr[ETH_ALEN] = {0x00};
846 macstr2num(addr, command+strlen("HOSTAPD_ACL_REMOVE_STA")+3); // 3 is space bar + "=" + space bar these 3 chars
847 rtw_acl_remove_sta(padapter, addr);
851 case ANDROID_WIFI_CMD_GTK_REKEY_OFFLOAD:
852 rtw_gtk_offload(net, (u8*)command);
854 #endif //CONFIG_GTK_OL
855 case ANDROID_WIFI_CMD_P2P_DISABLE:
858 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
859 u8 channel, ch_offset;
862 rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
867 DBG_871X("Unknown PRIVATE command %s - ignored\n", command);
868 snprintf(command, 3, "OK");
869 bytes_written = strlen("OK");
873 if (bytes_written >= 0) {
874 if ((bytes_written == 0) && (priv_cmd.total_len > 0))
876 if (bytes_written >= priv_cmd.total_len) {
877 DBG_871X("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
878 bytes_written = priv_cmd.total_len;
882 priv_cmd.used_len = bytes_written;
883 if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
884 DBG_871X("%s: failed to copy data to user buffer\n", __FUNCTION__);
893 rtw_unlock_suspend();
895 rtw_mfree(command, priv_cmd.total_len);
903 * Functions for Android WiFi card detection
905 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
907 static int g_wifidev_registered = 0;
908 static struct semaphore wifi_control_sem;
909 static struct wifi_platform_data *wifi_control_data = NULL;
910 static struct resource *wifi_irqres = NULL;
912 static int wifi_add_dev(void);
913 static void wifi_del_dev(void);
915 int rtw_android_wifictrl_func_add(void)
918 sema_init(&wifi_control_sem, 0);
920 ret = wifi_add_dev();
922 DBG_871X("%s: platform_driver_register failed\n", __FUNCTION__);
925 g_wifidev_registered = 1;
927 /* Waiting callback after platform_driver_register is done or exit with error */
928 if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
930 DBG_871X("%s: platform_driver_register timeout\n", __FUNCTION__);
936 void rtw_android_wifictrl_func_del(void)
938 if (g_wifidev_registered)
941 g_wifidev_registered = 0;
945 void *wl_android_prealloc(int section, unsigned long size)
947 void *alloc_ptr = NULL;
948 if (wifi_control_data && wifi_control_data->mem_prealloc) {
949 alloc_ptr = wifi_control_data->mem_prealloc(section, size);
951 DBG_871X("success alloc section %d\n", section);
953 memset(alloc_ptr, 0, size);
958 DBG_871X("can't alloc section %d\n", section);
962 int wifi_get_irq_number(unsigned long *irq_flags_ptr)
965 *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
966 return (int)wifi_irqres->start;
968 #ifdef CUSTOM_OOB_GPIO_NUM
969 return CUSTOM_OOB_GPIO_NUM;
975 int wifi_set_power(int on, unsigned long msec)
977 DBG_871X("%s = %d\n", __FUNCTION__, on);
978 if (wifi_control_data && wifi_control_data->set_power) {
979 wifi_control_data->set_power(on);
986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
987 int wifi_get_mac_addr(unsigned char *buf)
989 DBG_871X("%s\n", __FUNCTION__);
992 if (wifi_control_data && wifi_control_data->get_mac_addr) {
993 return wifi_control_data->get_mac_addr(buf);
997 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
999 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
1000 void *wifi_get_country_code(char *ccode)
1002 DBG_871X("%s\n", __FUNCTION__);
1005 if (wifi_control_data && wifi_control_data->get_country_code) {
1006 return wifi_control_data->get_country_code(ccode);
1010 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
1012 static int wifi_set_carddetect(int on)
1014 DBG_871X("%s = %d\n", __FUNCTION__, on);
1015 if (wifi_control_data && wifi_control_data->set_carddetect) {
1016 wifi_control_data->set_carddetect(on);
1021 static int wifi_probe(struct platform_device *pdev)
1023 struct wifi_platform_data *wifi_ctrl =
1024 (struct wifi_platform_data *)(pdev->dev.platform_data);
1025 int wifi_wake_gpio = 0;
1027 DBG_871X("## %s\n", __FUNCTION__);
1028 wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
1030 if (wifi_irqres == NULL)
1031 wifi_irqres = platform_get_resource_byname(pdev,
1032 IORESOURCE_IRQ, "bcm4329_wlan_irq");
1034 wifi_wake_gpio = wifi_irqres->start;
1036 #ifdef CONFIG_GPIO_WAKEUP
1037 printk("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
1038 wifi_irqres->start, wifi_wake_gpio);
1040 if (wifi_wake_gpio > 0) {
1041 #ifdef CONFIG_PLATFORM_INTEL_BYT
1042 wifi_configure_gpio();
1043 #else //CONFIG_PLATFORM_INTEL_BYT
1044 gpio_request(wifi_wake_gpio, "oob_irq");
1045 gpio_direction_input(wifi_wake_gpio);
1046 oob_irq = gpio_to_irq(wifi_wake_gpio);
1047 #endif //CONFIG_PLATFORM_INTEL_BYT
1048 printk("%s oob_irq:%d\n", __func__, oob_irq);
1050 else if(wifi_irqres)
1052 oob_irq = wifi_irqres->start;
1053 printk("%s oob_irq:%d\n", __func__, oob_irq);
1056 wifi_control_data = wifi_ctrl;
1058 wifi_set_power(1, 0); /* Power On */
1059 wifi_set_carddetect(1); /* CardDetect (0->1) */
1061 up(&wifi_control_sem);
1065 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1066 extern PADAPTER g_test_adapter;
1068 static void shutdown_card(void)
1073 if (NULL == g_test_adapter)
1075 DBG_871X("%s: padapter==NULL\n", __FUNCTION__);
1079 #ifdef CONFIG_FWLPS_IN_IPS
1080 LeaveAllPowerSaveMode(g_test_adapter);
1081 #endif // CONFIG_FWLPS_IN_IPS
1083 // Leave SDIO HCI Suspend
1085 rtw_write8(g_test_adapter, addr, 0);
1087 tmp8 = rtw_read8(g_test_adapter, addr);
1089 DBG_871X(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n",
1090 FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt);
1097 DBG_871X(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
1098 FUNC_ADPT_ARG(g_test_adapter), addr);
1105 // unlock register I/O
1106 rtw_write8(g_test_adapter, 0x1C, 0);
1108 // enable power down function
1112 tmp8 = rtw_read8(g_test_adapter, addr);
1114 rtw_write8(g_test_adapter, addr, tmp8);
1115 DBG_871X(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1116 FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1119 tmp8 = rtw_read8(g_test_adapter, addr);
1121 rtw_write8(g_test_adapter, addr, tmp8);
1122 DBG_871X(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1123 FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1125 // lock register page0 0x0~0xB read/write
1126 rtw_write8(g_test_adapter, 0x1C, 0x0E);
1128 g_test_adapter->bSurpriseRemoved = _TRUE;
1129 DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=%d\n",
1130 FUNC_ADPT_ARG(g_test_adapter), g_test_adapter->bSurpriseRemoved);
1131 #ifdef CONFIG_CONCURRENT_MODE
1132 if (g_test_adapter->pbuddy_adapter)
1135 pbuddy = g_test_adapter->pbuddy_adapter;
1136 pbuddy->bSurpriseRemoved = _TRUE;
1137 DBG_871X(FUNC_ADPT_FMT ": buddy(" ADPT_FMT ") bSurpriseRemoved=%d\n",
1138 FUNC_ADPT_ARG(g_test_adapter), ADPT_ARG(pbuddy), pbuddy->bSurpriseRemoved);
1140 #endif // CONFIG_CONCURRENT_MODE
1142 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1144 static int wifi_remove(struct platform_device *pdev)
1146 struct wifi_platform_data *wifi_ctrl =
1147 (struct wifi_platform_data *)(pdev->dev.platform_data);
1149 DBG_871X("## %s\n", __FUNCTION__);
1150 wifi_control_data = wifi_ctrl;
1152 wifi_set_power(0, 0); /* Power Off */
1153 wifi_set_carddetect(0); /* CardDetect (1->0) */
1155 up(&wifi_control_sem);
1159 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1160 static void wifi_shutdown(struct platform_device *pdev)
1162 struct wifi_platform_data *wifi_ctrl =
1163 (struct wifi_platform_data *)(pdev->dev.platform_data);
1166 DBG_871X("## %s\n", __FUNCTION__);
1168 wifi_control_data = wifi_ctrl;
1171 wifi_set_power(0, 0); /* Power Off */
1172 wifi_set_carddetect(0); /* CardDetect (1->0) */
1174 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1176 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
1178 DBG_871X("##> %s\n", __FUNCTION__);
1179 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1180 bcmsdh_oob_intr_set(0);
1185 static int wifi_resume(struct platform_device *pdev)
1187 DBG_871X("##> %s\n", __FUNCTION__);
1188 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1189 if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
1190 bcmsdh_oob_intr_set(1);
1195 /* temporarily use these two */
1196 static struct platform_driver wifi_device = {
1197 .probe = wifi_probe,
1198 .remove = wifi_remove,
1199 .suspend = wifi_suspend,
1200 .resume = wifi_resume,
1201 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1202 .shutdown = wifi_shutdown,
1203 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1205 .name = "bcmdhd_wlan",
1209 static struct platform_driver wifi_device_legacy = {
1210 .probe = wifi_probe,
1211 .remove = wifi_remove,
1212 .suspend = wifi_suspend,
1213 .resume = wifi_resume,
1215 .name = "bcm4329_wlan",
1219 static int wifi_add_dev(void)
1221 DBG_871X("## Calling platform_driver_register\n");
1222 platform_driver_register(&wifi_device);
1223 platform_driver_register(&wifi_device_legacy);
1227 static void wifi_del_dev(void)
1229 DBG_871X("## Unregister platform_driver_register\n");
1230 platform_driver_unregister(&wifi_device);
1231 platform_driver_unregister(&wifi_device_legacy);
1233 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
1235 #ifdef CONFIG_GPIO_WAKEUP
1236 #ifdef CONFIG_PLATFORM_INTEL_BYT
1237 int wifi_configure_gpio(void)
1239 if (gpio_request(oob_gpio, "oob_irq")) {
1240 DBG_871X("## %s Cannot request GPIO\n", __FUNCTION__);
1243 gpio_export(oob_gpio, 0);
1244 if (gpio_direction_input(oob_gpio)) {
1245 DBG_871X("## %s Cannot set GPIO direction input\n", __FUNCTION__);
1248 if ((oob_irq = gpio_to_irq(oob_gpio)) < 0) {
1249 DBG_871X("## %s Cannot convert GPIO to IRQ\n", __FUNCTION__);
1253 DBG_871X("## %s OOB_IRQ=%d\n", __FUNCTION__, oob_irq);
1257 #endif //CONFIG_PLATFORM_INTEL_BYT
1258 void wifi_free_gpio(unsigned int gpio)
1260 #ifdef CONFIG_PLATFORM_INTEL_BYT
1263 #endif //CONFIG_PLATFORM_INTEL_BYT
1265 #endif //CONFIG_GPIO_WAKEUP