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",
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 {
151 } android_wifi_priv_cmd;
154 * Local (static) functions and variables
157 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
158 * time (only) in dhd_open, subsequential wifi on will be handled by
161 static int g_wifi_on = _TRUE;
163 unsigned int oob_irq;
165 #ifdef CONFIG_PNO_SUPPORT
166 static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len) {
167 pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
170 cmd_tlv_t *cmd_tlv_temp;
175 int pno_freq_expo_max = 0;
176 int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1;
178 #ifdef CONFIG_PNO_SET_DEBUG
183 total_len = sizeof(pno_in_example);
184 str_ptr = p + cmdlen;
186 str_ptr = command + cmdlen;
189 if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
190 DBG_871X("%s argument=%d less min size\n", __func__, total_len);
194 tlv_size_left = total_len - cmdlen;
196 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
197 memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
199 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
200 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
201 (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
203 str_ptr += sizeof(cmd_tlv_t);
204 tlv_size_left -= sizeof(cmd_tlv_t);
206 if ((nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
207 MAX_PNO_LIST_COUNT, &tlv_size_left)) <= 0) {
208 DBG_871X("SSID is not presented or corrupted ret=%d\n", nssid);
211 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
212 DBG_871X("%s scan duration corrupted field size %d\n",
213 __func__, tlv_size_left);
217 pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
218 DBG_871X("%s: pno_time=%d\n", __func__, pno_time);
220 if (str_ptr[0] != 0) {
221 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
222 DBG_871X("%s pno repeat : corrupted field\n",
227 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
228 DBG_871X("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat);
229 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
230 DBG_871X("%s FREQ_EXPO_MAX corrupted field size\n",
235 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
236 DBG_871X("%s: pno_freq_expo_max=%d\n",
237 __func__, pno_freq_expo_max);
241 DBG_871X("%s get wrong TLV command\n", __FUNCTION__);
245 res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
247 #ifdef CONFIG_PNO_SET_DEBUG
248 rtw_dev_pno_debug(net);
255 static int rtw_android_pno_enable(struct net_device *net, int pno_enable) {
256 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
257 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
260 pwrctl->wowlan_pno_enable = pno_enable;
261 DBG_871X("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
262 if (pwrctl->wowlan_pno_enable == 0) {
263 if (pwrctl->pnlo_info != NULL) {
264 rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
265 pwrctl->pnlo_info = NULL;
267 if (pwrctl->pno_ssid_list != NULL) {
268 rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
269 pwrctl->pno_ssid_list = NULL;
271 if (pwrctl->pscan_info != NULL) {
272 rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
273 pwrctl->pscan_info = NULL;
281 #endif //CONFIG_PNO_SUPPORT
283 int rtw_android_cmdstr_to_num(char *cmdstr)
286 for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
287 if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
293 int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
295 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
296 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
297 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
298 int bytes_written = 0;
300 if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
301 bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
302 pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
305 return bytes_written;
308 int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
310 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
311 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
312 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
313 int bytes_written = 0;
316 link_speed = rtw_get_cur_max_rate(padapter)/10;
317 bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
319 return bytes_written;
322 int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
324 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
325 int bytes_written = 0;
327 bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
328 return bytes_written;
331 int rtw_android_set_country(struct net_device *net, char *command, int total_len)
333 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
334 char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
337 ret = rtw_set_country(adapter, country_code);
339 return (ret==_SUCCESS)?0:-1;
342 int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
344 int bytes_written = 0;
346 //We use the same address as our HW MAC address
347 _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
349 bytes_written = ETH_ALEN;
350 return bytes_written;
353 int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
355 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
356 char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
358 #ifdef CONFIG_IOCTL_CFG80211
359 adapter_wdev_data(adapter)->block_scan = (*block_value == '0')?_FALSE:_TRUE;
365 int rtw_android_set_block(struct net_device *net, char *command, int total_len)
367 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
368 char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
370 #ifdef CONFIG_IOCTL_CFG80211
371 adapter_wdev_data(adapter)->block = (*block_value=='0')?_FALSE:_TRUE;
377 int rtw_android_setband(struct net_device *net, char *command, int total_len)
379 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
380 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
384 sscanf(arg, "%u", &band);
385 ret = rtw_set_band(adapter, band);
387 return (ret==_SUCCESS)?0:-1;
390 int rtw_android_getband(struct net_device *net, char *command, int total_len)
392 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
393 int bytes_written = 0;
395 bytes_written = snprintf(command, total_len, "%u", adapter->setband);
397 return bytes_written;
401 int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
403 _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
404 struct wifi_display_info *wfd_info = &adapter->wfd_info;
405 char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
410 num = sscanf(arg, "%hhu", &mode);
413 wfd_info->stack_wfd_mode = mode;
414 DBG_871X("Miracast mode: %s(%u)\n", get_miracast_mode_str(wfd_info->stack_wfd_mode), wfd_info->stack_wfd_mode);
418 return (ret == _SUCCESS)?0:-1;
420 #endif /* CONFIG_WFD */
422 int get_int_from_command( char* pcmd )
426 for( i = 0; i < strlen( pcmd ); i++ )
428 if ( pcmd[ i ] == '=' )
430 // Skip the '=' and space characters.
435 return ( rtw_atoi( pcmd + i ) );
439 int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
442 //u8 *cmd_ptr = priv_cmd.buf;
443 struct sta_info * psta;
444 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
445 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
446 struct sta_priv *pstapriv = &padapter->stapriv;
447 struct security_priv* psecuritypriv=&(padapter->securitypriv);
448 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
453 DBG_8192C("%s, : Obtain Sta_info fail \n", __func__);
457 //string command length of "GTK_REKEY_OFFLOAD"
460 _rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
461 cmd_ptr += RTW_KEK_LEN;
463 printk("supplicant KEK: ");
464 for(i=0;i<RTW_KEK_LEN; i++)
465 printk(" %02x ", psta->kek[i]);
466 printk("\n supplicant KCK: ");
468 _rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
469 cmd_ptr += RTW_KCK_LEN;
471 for(i=0;i<RTW_KEK_LEN; i++)
472 printk(" %02x ", psta->kck[i]);
474 _rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
475 psecuritypriv->binstallKCK_KEK = _TRUE;
477 //printk("\nREPLAY_CTR: ");
478 //for(i=0;i<RTW_REPLAY_CTR_LEN; i++)
479 //printk(" %02x ", psta->replay_ctr[i]);
484 #endif //CONFIG_GTK_OL
486 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
489 char *command = NULL;
491 int bytes_written = 0;
492 #ifdef CONFIG_PNO_SUPPORT
496 android_wifi_priv_cmd priv_cmd;
497 _adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
499 struct wifi_display_info *pwfd_info;
503 if (!ifr->ifr_data) {
507 if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
511 if ( padapter->registrypriv.mp_mode == 1) {
515 //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);
516 command = rtw_zmalloc(priv_cmd.total_len);
519 DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
524 if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
525 DBG_871X("%s: failed to access memory\n", __FUNCTION__);
530 if (copy_from_user(command, compat_ptr(priv_cmd.buf), (unsigned long) priv_cmd.total_len)) {
532 if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
538 DBG_871X("%s: Android private cmd \"%s\" on %s\n"
539 , __FUNCTION__, command, ifr->ifr_name);
541 cmd_num = rtw_android_cmdstr_to_num(command);
544 case ANDROID_WIFI_CMD_START:
545 //bytes_written = wl_android_wifi_on(net);
547 case ANDROID_WIFI_CMD_SETFWPATH:
552 DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
553 ,__FUNCTION__, command, ifr->ifr_name);
560 case ANDROID_WIFI_CMD_STOP:
561 //bytes_written = wl_android_wifi_off(net);
564 case ANDROID_WIFI_CMD_SCAN_ACTIVE:
565 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE);
566 #ifdef CONFIG_PLATFORM_MSTAR
567 #ifdef CONFIG_IOCTL_CFG80211
568 adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = _TRUE;
569 #endif //CONFIG_IOCTL_CFG80211
570 #endif //CONFIG_PLATFORM_MSTAR
572 case ANDROID_WIFI_CMD_SCAN_PASSIVE:
573 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
576 case ANDROID_WIFI_CMD_RSSI:
577 bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
579 case ANDROID_WIFI_CMD_LINKSPEED:
580 bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
583 case ANDROID_WIFI_CMD_MACADDR:
584 bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
587 case ANDROID_WIFI_CMD_BLOCK_SCAN:
588 bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
591 case ANDROID_WIFI_CMD_BLOCK:
592 bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
595 case ANDROID_WIFI_CMD_RXFILTER_START:
596 //bytes_written = net_os_set_packet_filter(net, 1);
598 case ANDROID_WIFI_CMD_RXFILTER_STOP:
599 //bytes_written = net_os_set_packet_filter(net, 0);
601 case ANDROID_WIFI_CMD_RXFILTER_ADD:
602 //int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
603 //bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
605 case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
606 //int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
607 //bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
610 case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
611 /* TBD: BTCOEXSCAN-START */
613 case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
614 /* TBD: BTCOEXSCAN-STOP */
616 case ANDROID_WIFI_CMD_BTCOEXMODE:
618 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
620 net_os_set_packet_filter(net, 0); /* DHCP starts */
622 net_os_set_packet_filter(net, 1); /* DHCP ends */
624 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
629 case ANDROID_WIFI_CMD_SETSUSPENDOPT:
630 //bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
633 case ANDROID_WIFI_CMD_SETBAND:
634 bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
637 case ANDROID_WIFI_CMD_GETBAND:
638 bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
641 case ANDROID_WIFI_CMD_COUNTRY:
642 bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
645 #ifdef CONFIG_PNO_SUPPORT
646 case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
647 //bytes_written = dhd_dev_pno_reset(net);
649 case ANDROID_WIFI_CMD_PNOSETUP_SET:
650 bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
652 case ANDROID_WIFI_CMD_PNOENABLE_SET:
653 cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
654 pno_enable = *(command + cmdlen + 1) - '0';
655 bytes_written = rtw_android_pno_enable(net, pno_enable);
659 case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
660 bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
662 case ANDROID_WIFI_CMD_P2P_SET_NOA:
663 //int skip = strlen(CMD_P2P_SET_NOA) + 1;
664 //bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip);
666 case ANDROID_WIFI_CMD_P2P_GET_NOA:
667 //bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
669 case ANDROID_WIFI_CMD_P2P_SET_PS:
670 //int skip = strlen(CMD_P2P_SET_PS) + 1;
671 //bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip);
674 #ifdef CONFIG_IOCTL_CFG80211
675 case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
677 int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
678 bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
681 #endif //CONFIG_IOCTL_CFG80211
685 case ANDROID_WIFI_CMD_MIRACAST:
686 bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
689 case ANDROID_WIFI_CMD_WFD_ENABLE:
691 // Commented by Albert 2012/07/24
692 // We can enable the WFD function by using the following command:
693 // wpa_cli driver wfd-enable
695 pwfd_info = &padapter->wfd_info;
696 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
697 pwfd_info->wfd_enable = _TRUE;
701 case ANDROID_WIFI_CMD_WFD_DISABLE:
703 // Commented by Albert 2012/07/24
704 // We can disable the WFD function by using the following command:
705 // wpa_cli driver wfd-disable
707 pwfd_info = &padapter->wfd_info;
708 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
709 pwfd_info->wfd_enable = _FALSE;
712 case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
714 // Commented by Albert 2012/07/24
715 // We can set the tcp port number by using the following command:
716 // wpa_cli driver wfd-set-tcpport = 554
718 pwfd_info = &padapter->wfd_info;
719 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
722 pwfd_info->rtsp_ctrlport = ( u16 ) get_int_from_command( compat_ptr(priv_cmd.buf) );
724 pwfd_info->rtsp_ctrlport = ( u16 ) get_int_from_command( priv_cmd.buf );
729 case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
733 case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
735 // Commented by Albert 2012/08/28
736 // Specify the WFD device type ( WFD source/primary sink )
738 pwfd_info = &padapter->wfd_info;
739 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
742 pwfd_info->wfd_device_type = ( u8 ) get_int_from_command( compat_ptr(priv_cmd.buf) );
744 pwfd_info->wfd_device_type = ( u8 ) get_int_from_command( priv_cmd.buf );
747 pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
752 case ANDROID_WIFI_CMD_CHANGE_DTIM:
757 u8 *ptr = compat_ptr(priv_cmd.buf);
759 u8 *ptr = priv_cmd.buf;
761 ptr += 9;//string command length of "SET_DTIM";
763 dtim = rtw_atoi(ptr);
765 DBG_871X("DTIM=%d\n", dtim);
767 rtw_lps_change_dtim_cmd(padapter, dtim);
771 case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL:
773 padapter->stapriv.acl_list.mode = ( u8 ) get_int_from_command(command);
774 DBG_871X("%s ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL mode:%d\n", __FUNCTION__, padapter->stapriv.acl_list.mode);
777 case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA:
779 u8 addr[ETH_ALEN] = {0x00};
780 macstr2num(addr, command+strlen("HOSTAPD_ACL_ADD_STA")+3); // 3 is space bar + "=" + space bar these 3 chars
781 rtw_acl_add_sta(padapter, addr);
784 case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA:
786 u8 addr[ETH_ALEN] = {0x00};
787 macstr2num(addr, command+strlen("HOSTAPD_ACL_REMOVE_STA")+3); // 3 is space bar + "=" + space bar these 3 chars
788 rtw_acl_remove_sta(padapter, addr);
792 case ANDROID_WIFI_CMD_GTK_REKEY_OFFLOAD:
793 rtw_gtk_offload(net, priv_cmd.buf);
795 #endif //CONFIG_GTK_OL
796 case ANDROID_WIFI_CMD_P2P_DISABLE:
798 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
799 struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
800 u8 channel, ch_offset;
803 rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
807 DBG_871X("Unknown PRIVATE command %s - ignored\n", command);
808 snprintf(command, 3, "OK");
809 bytes_written = strlen("OK");
813 if (bytes_written >= 0) {
814 if ((bytes_written == 0) && (priv_cmd.total_len > 0))
816 if (bytes_written >= priv_cmd.total_len) {
817 DBG_871X("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
818 bytes_written = priv_cmd.total_len;
822 priv_cmd.used_len = bytes_written;
824 if (copy_to_user(compat_ptr(priv_cmd.buf), command, bytes_written)) {
826 if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
828 DBG_871X("%s: failed to copy data to user buffer\n", __FUNCTION__);
837 rtw_unlock_suspend();
839 rtw_mfree(command, priv_cmd.total_len);
847 * Functions for Android WiFi card detection
849 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
851 static int g_wifidev_registered = 0;
852 static struct semaphore wifi_control_sem;
853 static struct wifi_platform_data *wifi_control_data = NULL;
854 static struct resource *wifi_irqres = NULL;
856 static int wifi_add_dev(void);
857 static void wifi_del_dev(void);
859 int rtw_android_wifictrl_func_add(void)
862 sema_init(&wifi_control_sem, 0);
864 ret = wifi_add_dev();
866 DBG_871X("%s: platform_driver_register failed\n", __FUNCTION__);
869 g_wifidev_registered = 1;
871 /* Waiting callback after platform_driver_register is done or exit with error */
872 if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
874 DBG_871X("%s: platform_driver_register timeout\n", __FUNCTION__);
880 void rtw_android_wifictrl_func_del(void)
882 if (g_wifidev_registered)
885 g_wifidev_registered = 0;
889 void *wl_android_prealloc(int section, unsigned long size)
891 void *alloc_ptr = NULL;
892 if (wifi_control_data && wifi_control_data->mem_prealloc) {
893 alloc_ptr = wifi_control_data->mem_prealloc(section, size);
895 DBG_871X("success alloc section %d\n", section);
897 memset(alloc_ptr, 0, size);
902 DBG_871X("can't alloc section %d\n", section);
906 int wifi_get_irq_number(unsigned long *irq_flags_ptr)
909 *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
910 return (int)wifi_irqres->start;
912 #ifdef CUSTOM_OOB_GPIO_NUM
913 return CUSTOM_OOB_GPIO_NUM;
919 int wifi_set_power(int on, unsigned long msec)
921 DBG_871X("%s = %d\n", __FUNCTION__, on);
922 if (wifi_control_data && wifi_control_data->set_power) {
923 wifi_control_data->set_power(on);
930 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
931 int wifi_get_mac_addr(unsigned char *buf)
933 DBG_871X("%s\n", __FUNCTION__);
936 if (wifi_control_data && wifi_control_data->get_mac_addr) {
937 return wifi_control_data->get_mac_addr(buf);
941 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
943 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
944 void *wifi_get_country_code(char *ccode)
946 DBG_871X("%s\n", __FUNCTION__);
949 if (wifi_control_data && wifi_control_data->get_country_code) {
950 return wifi_control_data->get_country_code(ccode);
954 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
956 static int wifi_set_carddetect(int on)
958 DBG_871X("%s = %d\n", __FUNCTION__, on);
959 if (wifi_control_data && wifi_control_data->set_carddetect) {
960 wifi_control_data->set_carddetect(on);
965 static int wifi_probe(struct platform_device *pdev)
967 struct wifi_platform_data *wifi_ctrl =
968 (struct wifi_platform_data *)(pdev->dev.platform_data);
969 int wifi_wake_gpio = 0;
971 DBG_871X("## %s\n", __FUNCTION__);
972 wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
974 if (wifi_irqres == NULL)
975 wifi_irqres = platform_get_resource_byname(pdev,
976 IORESOURCE_IRQ, "bcm4329_wlan_irq");
978 wifi_wake_gpio = wifi_irqres->start;
980 #ifdef CONFIG_GPIO_WAKEUP
981 printk("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
982 wifi_irqres->start, wifi_wake_gpio);
984 if (wifi_wake_gpio > 0) {
985 gpio_request(wifi_wake_gpio, "oob_irq");
986 gpio_direction_input(wifi_wake_gpio);
987 oob_irq = gpio_to_irq(wifi_wake_gpio);
988 printk("%s oob_irq:%d\n", __func__, oob_irq);
992 oob_irq = wifi_irqres->start;
993 printk("%s oob_irq:%d\n", __func__, oob_irq);
996 wifi_control_data = wifi_ctrl;
998 wifi_set_power(1, 0); /* Power On */
999 wifi_set_carddetect(1); /* CardDetect (0->1) */
1001 up(&wifi_control_sem);
1005 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1006 extern PADAPTER g_test_adapter;
1008 static void shutdown_card(void)
1013 if (NULL == g_test_adapter)
1015 DBG_871X("%s: padapter==NULL\n", __FUNCTION__);
1019 #ifdef CONFIG_FWLPS_IN_IPS
1020 LeaveAllPowerSaveMode(g_test_adapter);
1021 #endif // CONFIG_FWLPS_IN_IPS
1023 // Leave SDIO HCI Suspend
1025 rtw_write8(g_test_adapter, addr, 0);
1027 tmp8 = rtw_read8(g_test_adapter, addr);
1029 DBG_871X(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n",
1030 FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt);
1037 DBG_871X(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
1038 FUNC_ADPT_ARG(g_test_adapter), addr);
1045 // unlock register I/O
1046 rtw_write8(g_test_adapter, 0x1C, 0);
1048 // enable power down function
1052 tmp8 = rtw_read8(g_test_adapter, addr);
1054 rtw_write8(g_test_adapter, addr, tmp8);
1055 DBG_871X(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1056 FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1059 tmp8 = rtw_read8(g_test_adapter, addr);
1061 rtw_write8(g_test_adapter, addr, tmp8);
1062 DBG_871X(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1063 FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1065 // lock register page0 0x0~0xB read/write
1066 rtw_write8(g_test_adapter, 0x1C, 0x0E);
1068 g_test_adapter->bSurpriseRemoved = _TRUE;
1069 DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=%d\n",
1070 FUNC_ADPT_ARG(g_test_adapter), g_test_adapter->bSurpriseRemoved);
1071 #ifdef CONFIG_CONCURRENT_MODE
1072 if (g_test_adapter->pbuddy_adapter)
1075 pbuddy = g_test_adapter->pbuddy_adapter;
1076 pbuddy->bSurpriseRemoved = _TRUE;
1077 DBG_871X(FUNC_ADPT_FMT ": buddy(" ADPT_FMT ") bSurpriseRemoved=%d\n",
1078 FUNC_ADPT_ARG(g_test_adapter), ADPT_ARG(pbuddy), pbuddy->bSurpriseRemoved);
1080 #endif // CONFIG_CONCURRENT_MODE
1082 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1084 static int wifi_remove(struct platform_device *pdev)
1086 struct wifi_platform_data *wifi_ctrl =
1087 (struct wifi_platform_data *)(pdev->dev.platform_data);
1089 DBG_871X("## %s\n", __FUNCTION__);
1090 wifi_control_data = wifi_ctrl;
1092 wifi_set_power(0, 0); /* Power Off */
1093 wifi_set_carddetect(0); /* CardDetect (1->0) */
1095 up(&wifi_control_sem);
1099 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1100 static void wifi_shutdown(struct platform_device *pdev)
1102 struct wifi_platform_data *wifi_ctrl =
1103 (struct wifi_platform_data *)(pdev->dev.platform_data);
1106 DBG_871X("## %s\n", __FUNCTION__);
1108 wifi_control_data = wifi_ctrl;
1111 wifi_set_power(0, 0); /* Power Off */
1112 wifi_set_carddetect(0); /* CardDetect (1->0) */
1114 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1116 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
1118 DBG_871X("##> %s\n", __FUNCTION__);
1119 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1120 bcmsdh_oob_intr_set(0);
1125 static int wifi_resume(struct platform_device *pdev)
1127 DBG_871X("##> %s\n", __FUNCTION__);
1128 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1129 if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
1130 bcmsdh_oob_intr_set(1);
1135 /* temporarily use these two */
1136 static struct platform_driver wifi_device = {
1137 .probe = wifi_probe,
1138 .remove = wifi_remove,
1139 .suspend = wifi_suspend,
1140 .resume = wifi_resume,
1141 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1142 .shutdown = wifi_shutdown,
1143 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1145 .name = "bcmdhd_wlan",
1149 static struct platform_driver wifi_device_legacy = {
1150 .probe = wifi_probe,
1151 .remove = wifi_remove,
1152 .suspend = wifi_suspend,
1153 .resume = wifi_resume,
1155 .name = "bcm4329_wlan",
1159 static int wifi_add_dev(void)
1161 DBG_871X("## Calling platform_driver_register\n");
1162 platform_driver_register(&wifi_device);
1163 platform_driver_register(&wifi_device_legacy);
1167 static void wifi_del_dev(void)
1169 DBG_871X("## Unregister platform_driver_register\n");
1170 platform_driver_unregister(&wifi_device);
1171 platform_driver_unregister(&wifi_device_legacy);
1173 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */