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
87 "HOSTAPD_SET_MACADDR_ACL",
88 "HOSTAPD_ACL_ADD_STA",
89 "HOSTAPD_ACL_REMOVE_STA",
90 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
92 #endif //CONFIG_GTK_OL
93 /* Private command for P2P disable*/
97 #ifdef CONFIG_PNO_SUPPORT
98 #define PNO_TLV_PREFIX 'S'
99 #define PNO_TLV_VERSION '1'
100 #define PNO_TLV_SUBVERSION '2'
101 #define PNO_TLV_RESERVED '0'
102 #define PNO_TLV_TYPE_SSID_IE 'S'
103 #define PNO_TLV_TYPE_TIME 'T'
104 #define PNO_TLV_FREQ_REPEAT 'R'
105 #define PNO_TLV_FREQ_EXPO_MAX 'M'
107 typedef struct cmd_tlv {
114 #ifdef CONFIG_PNO_SET_DEBUG
115 char pno_in_example[] = {
116 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
120 'd', 'l', 'i', 'n', 'k',
123 'B', 'U', 'F', 'B', 'U','F',
126 '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', '!', '@', '#', '$', '%', '^',
129 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
138 #endif /* CONFIG_PNO_SET_DEBUG */
139 #endif /* PNO_SUPPORT */
141 typedef struct android_wifi_priv_cmd {
145 } android_wifi_priv_cmd;
148 typedef struct compat_android_wifi_priv_cmd {
152 } compat_android_wifi_priv_cmd;
153 #endif /* CONFIG_COMPAT */
156 * Local (static) functions and variables
159 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
160 * time (only) in dhd_open, subsequential wifi on will be handled by
163 static int g_wifi_on = _TRUE;
165 unsigned int oob_irq = 0;
166 unsigned int oob_gpio = 0;
168 #ifdef CONFIG_PNO_SUPPORT
170 * rtw_android_pno_setup
172 * This is used for private command.
176 * command: parameters from private command
177 * total_len: the length of the command.
180 static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len) {
181 pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
184 cmd_tlv_t *cmd_tlv_temp;
189 int pno_freq_expo_max = 0;
190 int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1;
192 #ifdef CONFIG_PNO_SET_DEBUG
197 total_len = sizeof(pno_in_example);
198 str_ptr = p + cmdlen;
200 str_ptr = command + cmdlen;
203 if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
204 DBG_871X("%s argument=%d less min size\n", __func__, total_len);
208 tlv_size_left = total_len - cmdlen;
210 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
211 memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
213 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
214 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
215 (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
217 str_ptr += sizeof(cmd_tlv_t);
218 tlv_size_left -= sizeof(cmd_tlv_t);
220 if ((nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
221 MAX_PNO_LIST_COUNT, &tlv_size_left)) <= 0) {
222 DBG_871X("SSID is not presented or corrupted ret=%d\n", nssid);
225 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
226 DBG_871X("%s scan duration corrupted field size %d\n",
227 __func__, tlv_size_left);
231 pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
232 DBG_871X("%s: pno_time=%d\n", __func__, pno_time);
234 if (str_ptr[0] != 0) {
235 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
236 DBG_871X("%s pno repeat : corrupted field\n",
241 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
242 DBG_871X("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat);
243 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
244 DBG_871X("%s FREQ_EXPO_MAX corrupted field size\n",
249 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
250 DBG_871X("%s: pno_freq_expo_max=%d\n",
251 __func__, pno_freq_expo_max);
255 DBG_871X("%s get wrong TLV command\n", __FUNCTION__);
259 res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
261 #ifdef CONFIG_PNO_SET_DEBUG
262 rtw_dev_pno_debug(net);
270 * rtw_android_cfg80211_pno_setup
272 * This is used for cfg80211 sched_scan.
276 * request: cfg80211_request
279 int rtw_android_cfg80211_pno_setup(struct net_device *net,
280 struct cfg80211_ssid *ssids, int n_ssids, int interval) {
285 int pno_freq_expo_max = 0;
287 pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
289 if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
290 DBG_871X("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
294 memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
298 for (index = 0 ; index < nssid ; index++) {
299 pno_ssids_local[index].SSID_len = ssids[index].ssid_len;
300 memcpy(pno_ssids_local[index].SSID, ssids[index].ssid,
301 ssids[index].ssid_len);
304 pno_time = (interval / 1000);
306 DBG_871X("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
308 res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
309 pno_repeat, pno_freq_expo_max);
315 int rtw_android_pno_enable(struct net_device *net, int pno_enable) {
316 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
317 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
320 pwrctl->wowlan_pno_enable = pno_enable;
321 DBG_871X("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
322 if (pwrctl->wowlan_pno_enable == 0) {
323 if (pwrctl->pnlo_info != NULL) {
324 rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
325 pwrctl->pnlo_info = NULL;
327 if (pwrctl->pno_ssid_list != NULL) {
328 rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
329 pwrctl->pno_ssid_list = NULL;
331 if (pwrctl->pscan_info != NULL) {
332 rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
333 pwrctl->pscan_info = NULL;
341 #endif //CONFIG_PNO_SUPPORT
343 int rtw_android_cmdstr_to_num(char *cmdstr)
346 for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
347 if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
353 int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
355 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
356 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
357 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
358 int bytes_written = 0;
360 if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
361 bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
362 pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
365 return bytes_written;
368 int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
370 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
371 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
372 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
373 int bytes_written = 0;
376 link_speed = rtw_get_cur_max_rate(padapter)/10;
377 bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
379 return bytes_written;
382 int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
384 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
385 int bytes_written = 0;
387 bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
388 return bytes_written;
391 int rtw_android_set_country(struct net_device *net, char *command, int total_len)
393 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
394 char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
397 ret = rtw_set_country(adapter, country_code);
399 return (ret==_SUCCESS)?0:-1;
402 int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
404 int bytes_written = 0;
406 //We use the same address as our HW MAC address
407 _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
409 bytes_written = ETH_ALEN;
410 return bytes_written;
413 int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
415 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
416 char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
418 #ifdef CONFIG_IOCTL_CFG80211
419 adapter_wdev_data(adapter)->block_scan = (*block_value == '0')?_FALSE:_TRUE;
425 int rtw_android_set_block(struct net_device *net, char *command, int total_len)
427 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
428 char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
430 #ifdef CONFIG_IOCTL_CFG80211
431 adapter_wdev_data(adapter)->block = (*block_value=='0')?_FALSE:_TRUE;
437 int rtw_android_setband(struct net_device *net, char *command, int total_len)
439 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
440 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
441 u32 band = WIFI_FREQUENCY_BAND_AUTO;
444 if (sscanf(arg, "%u", &band) >= 1)
445 ret = rtw_set_band(adapter, band);
447 return (ret==_SUCCESS)?0:-1;
450 int rtw_android_getband(struct net_device *net, char *command, int total_len)
452 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
453 int bytes_written = 0;
455 bytes_written = snprintf(command, total_len, "%u", adapter->setband);
457 return bytes_written;
461 int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
463 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
464 struct wifi_display_info *wfd_info = &adapter->wfd_info;
465 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
470 num = sscanf(arg, "%hhu", &mode);
473 wfd_info->stack_wfd_mode = mode;
474 DBG_871X("Miracast mode: %s(%u)\n", get_miracast_mode_str(wfd_info->stack_wfd_mode), wfd_info->stack_wfd_mode);
478 return (ret == _SUCCESS)?0:-1;
480 #endif /* CONFIG_WFD */
482 int get_int_from_command( char* pcmd )
486 for( i = 0; i < strlen( pcmd ); i++ )
488 if ( pcmd[ i ] == '=' )
490 // Skip the '=' and space characters.
495 return ( rtw_atoi( pcmd + i ) );
498 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
499 int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
502 //u8 *cmd_ptr = priv_cmd.buf;
503 struct sta_info * psta;
504 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
505 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
506 struct sta_priv *pstapriv = &padapter->stapriv;
507 struct security_priv* psecuritypriv=&(padapter->securitypriv);
508 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
513 DBG_8192C("%s, : Obtain Sta_info fail \n", __func__);
517 //string command length of "GTK_REKEY_OFFLOAD"
520 _rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
521 cmd_ptr += RTW_KEK_LEN;
523 printk("supplicant KEK: ");
524 for(i=0;i<RTW_KEK_LEN; i++)
525 printk(" %02x ", psta->kek[i]);
526 printk("\n supplicant KCK: ");
528 _rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
529 cmd_ptr += RTW_KCK_LEN;
531 for(i=0;i<RTW_KEK_LEN; i++)
532 printk(" %02x ", psta->kck[i]);
534 _rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
535 psecuritypriv->binstallKCK_KEK = _TRUE;
537 //printk("\nREPLAY_CTR: ");
538 //for(i=0;i<RTW_REPLAY_CTR_LEN; i++)
539 //printk(" %02x ", psta->replay_ctr[i]);
544 #endif //CONFIG_GTK_OL
546 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
549 char *command = NULL;
551 int bytes_written = 0;
552 #ifdef CONFIG_PNO_SUPPORT
556 android_wifi_priv_cmd priv_cmd;
557 _adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
559 struct wifi_display_info *pwfd_info;
564 if (!ifr->ifr_data) {
569 if (is_compat_task()) {
570 /* User space is 32-bit, use compat ioctl */
571 compat_android_wifi_priv_cmd compat_priv_cmd;
573 if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
577 priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
578 priv_cmd.used_len = compat_priv_cmd.used_len;
579 priv_cmd.total_len = compat_priv_cmd.total_len;
581 #endif /* CONFIG_COMPAT */
582 if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
586 if ( padapter->registrypriv.mp_mode == 1) {
590 //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);
591 command = rtw_zmalloc(priv_cmd.total_len);
594 DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
599 if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
600 DBG_871X("%s: failed to access memory\n", __FUNCTION__);
604 if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
609 DBG_871X("%s: Android private cmd \"%s\" on %s\n"
610 , __FUNCTION__, command, ifr->ifr_name);
612 cmd_num = rtw_android_cmdstr_to_num(command);
615 case ANDROID_WIFI_CMD_START:
616 //bytes_written = wl_android_wifi_on(net);
618 case ANDROID_WIFI_CMD_SETFWPATH:
623 DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
624 ,__FUNCTION__, command, ifr->ifr_name);
631 case ANDROID_WIFI_CMD_STOP:
632 //bytes_written = wl_android_wifi_off(net);
635 case ANDROID_WIFI_CMD_SCAN_ACTIVE:
636 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE);
637 #ifdef CONFIG_PLATFORM_MSTAR
638 #ifdef CONFIG_IOCTL_CFG80211
639 adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = _TRUE;
640 #endif //CONFIG_IOCTL_CFG80211
641 #endif //CONFIG_PLATFORM_MSTAR
643 case ANDROID_WIFI_CMD_SCAN_PASSIVE:
644 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
647 case ANDROID_WIFI_CMD_RSSI:
648 bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
650 case ANDROID_WIFI_CMD_LINKSPEED:
651 bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
654 case ANDROID_WIFI_CMD_MACADDR:
655 bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
658 case ANDROID_WIFI_CMD_BLOCK_SCAN:
659 bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
662 case ANDROID_WIFI_CMD_BLOCK:
663 bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
666 case ANDROID_WIFI_CMD_RXFILTER_START:
667 //bytes_written = net_os_set_packet_filter(net, 1);
669 case ANDROID_WIFI_CMD_RXFILTER_STOP:
670 //bytes_written = net_os_set_packet_filter(net, 0);
672 case ANDROID_WIFI_CMD_RXFILTER_ADD:
673 //int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
674 //bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
676 case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
677 //int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
678 //bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
681 case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
682 /* TBD: BTCOEXSCAN-START */
684 case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
685 /* TBD: BTCOEXSCAN-STOP */
687 case ANDROID_WIFI_CMD_BTCOEXMODE:
689 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
691 net_os_set_packet_filter(net, 0); /* DHCP starts */
693 net_os_set_packet_filter(net, 1); /* DHCP ends */
695 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
700 case ANDROID_WIFI_CMD_SETSUSPENDOPT:
701 //bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
704 case ANDROID_WIFI_CMD_SETBAND:
705 bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
708 case ANDROID_WIFI_CMD_GETBAND:
709 bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
712 case ANDROID_WIFI_CMD_COUNTRY:
713 bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
716 #ifdef CONFIG_PNO_SUPPORT
717 case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
718 //bytes_written = dhd_dev_pno_reset(net);
720 case ANDROID_WIFI_CMD_PNOSETUP_SET:
721 bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
723 case ANDROID_WIFI_CMD_PNOENABLE_SET:
724 cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
725 pno_enable = *(command + cmdlen + 1) - '0';
726 bytes_written = rtw_android_pno_enable(net, pno_enable);
730 case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
731 bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
733 case ANDROID_WIFI_CMD_P2P_SET_NOA:
734 //int skip = strlen(CMD_P2P_SET_NOA) + 1;
735 //bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip);
737 case ANDROID_WIFI_CMD_P2P_GET_NOA:
738 //bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
740 case ANDROID_WIFI_CMD_P2P_SET_PS:
741 //int skip = strlen(CMD_P2P_SET_PS) + 1;
742 //bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip);
745 #ifdef CONFIG_IOCTL_CFG80211
746 case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
748 int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
749 bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
752 #endif //CONFIG_IOCTL_CFG80211
756 case ANDROID_WIFI_CMD_MIRACAST:
757 bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
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);
850 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
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