8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bu / os_dep / linux / rtw_android.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *                                        
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * 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
17  *
18  *
19  ******************************************************************************/
20
21 #ifdef CONFIG_GPIO_WAKEUP
22 #include <linux/gpio.h>
23 #endif
24
25 #include <drv_types.h>
26
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>
31 #else
32 #include <linux/wifi_tiwlan.h>
33 #endif
34 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
35
36 #ifdef CONFIG_GPIO_WAKEUP
37 #include <linux/interrupt.h>
38 #include <linux/irq.h>
39 #endif
40
41 extern void macstr2num(u8 *dst, u8 *src);
42
43 const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
44         "START",
45         "STOP",
46         "SCAN-ACTIVE",
47         "SCAN-PASSIVE",
48         "RSSI",
49         "LINKSPEED",
50         "RXFILTER-START",
51         "RXFILTER-STOP",
52         "RXFILTER-ADD",
53         "RXFILTER-REMOVE",
54         "BTCOEXSCAN-START",
55         "BTCOEXSCAN-STOP",
56         "BTCOEXMODE",
57         "SETSUSPENDOPT",
58         "P2P_DEV_ADDR",
59         "SETFWPATH",
60         "SETBAND",
61         "GETBAND",
62         "COUNTRY",
63         "P2P_SET_NOA",
64         "P2P_GET_NOA",
65         "P2P_SET_PS",
66         "SET_AP_WPS_P2P_IE",
67
68         "MIRACAST",
69
70 #ifdef CONFIG_PNO_SUPPORT
71         "PNOSSIDCLR",
72         "PNOSETUP",
73         "PNOFORCE",
74         "PNODEBUG",
75 #endif
76
77         "MACADDR",
78
79         "BLOCK_SCAN",
80         "BLOCK",
81         "WFD-ENABLE",
82         "WFD-DISABLE",
83         "WFD-SET-TCPPORT",
84         "WFD-SET-MAXTPUT",
85         "WFD-SET-DEVTYPE",
86         "SET_DTIM",
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))
91         "GTK_REKEY_OFFLOAD",
92 #endif //CONFIG_GTK_OL
93 /*      Private command for     P2P disable*/
94         "P2P_DISABLE"
95 };
96
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'
106
107 typedef struct cmd_tlv {
108         char prefix;
109         char version;
110         char subver;
111         char reserved;
112 } cmd_tlv_t;
113
114 #ifdef CONFIG_PNO_SET_DEBUG
115 char pno_in_example[] = {
116                 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
117                 'S', '1', '2', '0',
118                 'S',    //1
119                 0x05,
120                 'd', 'l', 'i', 'n', 'k',
121                 'S',    //2
122                 0x06,
123                 'B', 'U', 'F', 'B', 'U','F',
124                 'S',    //3
125                 0x20,
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', '!', '@', '#', '$', '%', '^',
127                 'S',    //4
128                 0x0a,
129                 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
130                 'T',
131                 '0', '5',
132                 'R',
133                 '2',
134                 'M',
135                 '2',
136                 0x00
137                 };
138 #endif /* CONFIG_PNO_SET_DEBUG */
139 #endif /* PNO_SUPPORT */
140
141 typedef struct android_wifi_priv_cmd {
142         char *buf;
143         int used_len;
144         int total_len;
145 } android_wifi_priv_cmd;
146
147 #ifdef CONFIG_COMPAT
148 typedef struct compat_android_wifi_priv_cmd {
149         compat_uptr_t buf;
150         int used_len;
151         int total_len;
152 } compat_android_wifi_priv_cmd;
153 #endif /* CONFIG_COMPAT */
154
155 /**
156  * Local (static) functions and variables
157  */
158
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
161  * wl_android_wifi_on
162  */
163 static int g_wifi_on = _TRUE;
164
165 unsigned int oob_irq = 0;
166 unsigned int oob_gpio = 0;
167
168 #ifdef CONFIG_PNO_SUPPORT
169 /* 
170  * rtw_android_pno_setup
171  * Description: 
172  * This is used for private command.
173  * 
174  * Parameter:
175  * net: net_device
176  * command: parameters from private command
177  * total_len: the length of the command.
178  *
179  * */
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];
182         int res = -1;
183         int nssid = 0;
184         cmd_tlv_t *cmd_tlv_temp;
185         char *str_ptr;
186         int tlv_size_left;
187         int pno_time = 0;
188         int pno_repeat = 0;
189         int pno_freq_expo_max = 0;
190         int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1; 
191
192 #ifdef CONFIG_PNO_SET_DEBUG
193         int i;
194         char *p;
195         p = pno_in_example;
196
197         total_len = sizeof(pno_in_example);
198         str_ptr = p + cmdlen;
199 #else
200         str_ptr = command + cmdlen;
201 #endif
202
203         if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
204                 DBG_871X("%s argument=%d less min size\n", __func__, total_len);
205                 goto exit_proc;
206         }
207
208         tlv_size_left = total_len - cmdlen;
209
210         cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
211         memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
212
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)) {
216
217                 str_ptr += sizeof(cmd_tlv_t);
218                 tlv_size_left -= sizeof(cmd_tlv_t);
219
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);
223                         goto exit_proc;
224                 } else {
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);
228                                 goto exit_proc;
229                         }
230                         str_ptr++;
231                         pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
232                         DBG_871X("%s: pno_time=%d\n", __func__, pno_time);
233
234                         if (str_ptr[0] != 0) {
235                                 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
236                                         DBG_871X("%s pno repeat : corrupted field\n",
237                                                 __func__);
238                                         goto exit_proc;
239                                 }
240                                 str_ptr++;
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",
245                                                 __func__);
246                                         goto exit_proc;
247                                 }
248                                 str_ptr++;
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);
252                         }
253                 }
254         } else {
255                 DBG_871X("%s get wrong TLV command\n", __FUNCTION__);
256                 goto exit_proc;
257         }
258
259         res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
260
261 #ifdef CONFIG_PNO_SET_DEBUG
262         rtw_dev_pno_debug(net);
263 #endif
264
265 exit_proc:
266         return res;
267 }
268
269 /* 
270  * rtw_android_cfg80211_pno_setup
271  * Description: 
272  * This is used for cfg80211 sched_scan.
273  * 
274  * Parameter:
275  * net: net_device
276  * request: cfg80211_request
277  * */
278
279 int rtw_android_cfg80211_pno_setup(struct net_device *net,
280                 struct cfg80211_ssid *ssids, int n_ssids, int interval) {
281         int res = -1;
282         int nssid = 0;
283         int pno_time = 0;
284         int pno_repeat = 0;
285         int pno_freq_expo_max = 0;
286         int index = 0;
287         pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
288
289         if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
290                 DBG_871X("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
291                 return -EINVAL;
292         }
293
294         memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
295
296         nssid = n_ssids;
297
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);
302         }
303
304         pno_time = (interval / 1000);
305
306         DBG_871X("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
307
308         res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
309                         pno_repeat, pno_freq_expo_max);
310
311 exit_proc:
312         return res;
313 }
314
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);
318
319         if (pwrctl) {
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;
326                         }
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;
330                         }
331                         if (pwrctl->pscan_info != NULL) {
332                                 rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
333                                 pwrctl->pscan_info = NULL;
334                         }
335                 } 
336                 return 0;
337         } else {
338                 return -1;
339         }
340 }
341 #endif //CONFIG_PNO_SUPPORT
342
343 int rtw_android_cmdstr_to_num(char *cmdstr)
344 {
345         int cmd_num;
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])) )
348                         break;
349
350         return cmd_num;
351 }
352
353 int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
354 {
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;
359
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);
363         }
364
365         return bytes_written;
366 }
367
368 int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
369 {
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;
374         u16 link_speed = 0;
375
376         link_speed = rtw_get_cur_max_rate(padapter)/10;
377         bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
378
379         return bytes_written;
380 }
381
382 int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
383 {
384         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
385         int bytes_written = 0;
386         
387         bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
388         return bytes_written;
389 }
390
391 int rtw_android_set_country(struct net_device *net, char *command, int total_len)
392 {
393         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
394         char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
395         int ret = _FAIL;
396         
397         ret = rtw_set_country(adapter, country_code);
398
399         return (ret==_SUCCESS)?0:-1;
400 }
401
402 int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
403 {
404         int bytes_written = 0;
405
406         //We use the same address as our HW MAC address
407         _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
408         
409         bytes_written = ETH_ALEN;
410         return bytes_written;
411 }
412
413 int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
414 {
415         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
416         char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
417
418         #ifdef CONFIG_IOCTL_CFG80211
419         adapter_wdev_data(adapter)->block_scan = (*block_value == '0')?_FALSE:_TRUE;
420         #endif
421
422         return 0;
423 }
424
425 int rtw_android_set_block(struct net_device *net, char *command, int total_len)
426 {
427         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
428         char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
429
430         #ifdef CONFIG_IOCTL_CFG80211
431         adapter_wdev_data(adapter)->block = (*block_value=='0')?_FALSE:_TRUE;
432         #endif
433         
434         return 0;
435 }
436
437 int rtw_android_setband(struct net_device *net, char *command, int total_len)
438 {
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;
442         int ret = _FAIL;
443
444         if (sscanf(arg, "%u", &band) >= 1)
445                 ret = rtw_set_band(adapter, band);
446
447         return (ret==_SUCCESS)?0:-1;
448 }
449
450 int rtw_android_getband(struct net_device *net, char *command, int total_len)
451 {
452         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
453         int bytes_written = 0;
454
455         bytes_written = snprintf(command, total_len, "%u", adapter->setband);
456
457         return bytes_written;
458 }
459
460 #ifdef CONFIG_WFD
461 int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
462 {
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;
466         u8 mode;
467         int num;
468         int ret = _FAIL;
469
470         num = sscanf(arg, "%hhu", &mode);
471
472         if (num >= 1) {
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);
475                 ret = _SUCCESS;
476         }
477
478         return (ret == _SUCCESS)?0:-1;
479 }
480 #endif /* CONFIG_WFD */
481
482 int get_int_from_command( char* pcmd )
483 {
484         int i = 0;
485
486         for( i = 0; i < strlen( pcmd ); i++ )
487         {
488                 if ( pcmd[ i ] == '=' )
489                 {
490                         //      Skip the '=' and space characters.
491                         i += 2;
492                         break;
493                 }
494         }
495         return ( rtw_atoi( pcmd + i ) );
496 }
497
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)
500 {
501         int i;
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));
509         
510         
511         if (psta == NULL) 
512         {
513                 DBG_8192C("%s, : Obtain Sta_info fail \n", __func__);
514         }
515         else
516         {
517                 //string command length of "GTK_REKEY_OFFLOAD"
518                 cmd_ptr += 18;
519                 
520                 _rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
521                 cmd_ptr += RTW_KEK_LEN;
522                 /*
523                 printk("supplicant KEK: ");
524                 for(i=0;i<RTW_KEK_LEN; i++)
525                         printk(" %02x ", psta->kek[i]);
526                 printk("\n supplicant KCK: ");
527                 */
528                 _rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
529                 cmd_ptr += RTW_KCK_LEN;
530                 /*
531                 for(i=0;i<RTW_KEK_LEN; i++)
532                         printk(" %02x ", psta->kck[i]);
533                 */
534                 _rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
535                 psecuritypriv->binstallKCK_KEK = _TRUE;
536                 
537                 //printk("\nREPLAY_CTR: ");
538                 //for(i=0;i<RTW_REPLAY_CTR_LEN; i++)
539                         //printk(" %02x ", psta->replay_ctr[i]);
540         }
541
542         return _SUCCESS;
543 }
544 #endif //CONFIG_GTK_OL
545
546 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
547 {
548         int ret = 0;
549         char *command = NULL;
550         int cmd_num;
551         int bytes_written = 0;
552 #ifdef CONFIG_PNO_SUPPORT
553         uint cmdlen = 0;
554         uint pno_enable = 0;
555 #endif
556         android_wifi_priv_cmd priv_cmd;
557         _adapter*       padapter = ( _adapter * ) rtw_netdev_priv(net);
558 #ifdef CONFIG_WFD
559         struct wifi_display_info                *pwfd_info;
560 #endif
561
562         rtw_lock_suspend();
563
564         if (!ifr->ifr_data) {
565                 ret = -EINVAL;
566                 goto exit;
567         }
568 #ifdef CONFIG_COMPAT
569         if (is_compat_task()) {
570                 /* User space is 32-bit, use compat ioctl */
571                 compat_android_wifi_priv_cmd compat_priv_cmd;
572
573                 if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
574                         ret = -EFAULT;
575                         goto exit;
576                 }
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;
580         } else
581 #endif /* CONFIG_COMPAT */
582         if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
583                 ret = -EFAULT;
584                 goto exit;
585         }
586         if ( padapter->registrypriv.mp_mode == 1) {
587                 ret = -EFAULT;
588                 goto exit;
589         }
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);
592         if (!command)
593         {
594                 DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
595                 ret = -ENOMEM;
596                 goto exit;
597         }
598
599         if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
600                 DBG_871X("%s: failed to access memory\n", __FUNCTION__);
601                 ret = -EFAULT;
602                 goto exit;
603          }
604         if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
605                 ret = -EFAULT;
606                 goto exit;
607         }
608
609         DBG_871X("%s: Android private cmd \"%s\" on %s\n"
610                 , __FUNCTION__, command, ifr->ifr_name);
611
612         cmd_num = rtw_android_cmdstr_to_num(command);
613         
614         switch(cmd_num) {
615         case ANDROID_WIFI_CMD_START:
616                 //bytes_written = wl_android_wifi_on(net);
617                 goto response;
618         case ANDROID_WIFI_CMD_SETFWPATH:
619                 goto response;
620         }
621
622         if (!g_wifi_on) {
623                 DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
624                         ,__FUNCTION__, command, ifr->ifr_name);
625                 ret = 0;
626                 goto exit;
627         }
628
629         switch(cmd_num) {
630
631         case ANDROID_WIFI_CMD_STOP:
632                 //bytes_written = wl_android_wifi_off(net);
633                 break;
634                 
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
642                 break;
643         case ANDROID_WIFI_CMD_SCAN_PASSIVE:
644                 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
645                 break;
646                 
647         case ANDROID_WIFI_CMD_RSSI:
648                 bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
649                 break;
650         case ANDROID_WIFI_CMD_LINKSPEED:
651                 bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
652                 break;
653
654         case ANDROID_WIFI_CMD_MACADDR:
655                 bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
656                 break;
657
658         case ANDROID_WIFI_CMD_BLOCK_SCAN:
659                 bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
660                 break;
661
662         case ANDROID_WIFI_CMD_BLOCK:
663                 bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
664                 break;
665                 
666         case ANDROID_WIFI_CMD_RXFILTER_START:
667                 //bytes_written = net_os_set_packet_filter(net, 1);
668                 break;
669         case ANDROID_WIFI_CMD_RXFILTER_STOP:
670                 //bytes_written = net_os_set_packet_filter(net, 0);
671                 break;
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);
675                 break;
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);
679                 break;
680                 
681         case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
682                 /* TBD: BTCOEXSCAN-START */
683                 break;
684         case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
685                 /* TBD: BTCOEXSCAN-STOP */
686                 break;
687         case ANDROID_WIFI_CMD_BTCOEXMODE:
688                 #if 0
689                 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
690                 if (mode == 1)
691                         net_os_set_packet_filter(net, 0); /* DHCP starts */
692                 else
693                         net_os_set_packet_filter(net, 1); /* DHCP ends */
694 #ifdef WL_CFG80211
695                 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
696 #endif
697                 #endif
698                 break;
699                 
700         case ANDROID_WIFI_CMD_SETSUSPENDOPT:
701                 //bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
702                 break;
703                 
704         case ANDROID_WIFI_CMD_SETBAND:
705                 bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
706                 break;
707
708         case ANDROID_WIFI_CMD_GETBAND:
709                 bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
710                 break;
711
712         case ANDROID_WIFI_CMD_COUNTRY:
713                 bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
714                 break;
715                 
716 #ifdef CONFIG_PNO_SUPPORT
717         case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
718                 //bytes_written = dhd_dev_pno_reset(net);
719                 break;
720         case ANDROID_WIFI_CMD_PNOSETUP_SET:
721                 bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
722                 break;
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);
727                 break;
728 #endif
729
730         case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
731                 bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
732                 break;
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);
736                 break;
737         case ANDROID_WIFI_CMD_P2P_GET_NOA:
738                 //bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
739                 break;
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);
743                 break;
744                 
745 #ifdef CONFIG_IOCTL_CFG80211
746         case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
747         {
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');
750                 break;
751         }
752 #endif //CONFIG_IOCTL_CFG80211
753
754 #ifdef CONFIG_WFD
755
756         case ANDROID_WIFI_CMD_MIRACAST:
757                 bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
758                 break;
759
760         case ANDROID_WIFI_CMD_WFD_ENABLE:
761         {
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
765
766                 pwfd_info = &padapter->wfd_info;
767                 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
768                         pwfd_info->wfd_enable = _TRUE;
769                 break;
770         }
771
772         case ANDROID_WIFI_CMD_WFD_DISABLE:
773         {
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
777
778                 pwfd_info = &padapter->wfd_info;
779                 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
780                         pwfd_info->wfd_enable = _FALSE;
781                 break;
782         }
783         case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
784         {
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
788
789                 pwfd_info = &padapter->wfd_info;
790                 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
791                 {
792                         pwfd_info->rtsp_ctrlport = ( u16 ) get_int_from_command( priv_cmd.buf );
793         }
794                 break;
795         }
796         case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
797         {
798                 break;
799         }
800         case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
801         {
802                 //      Commented by Albert 2012/08/28
803                 //      Specify the WFD device type ( WFD source/primary sink )
804
805                 pwfd_info = &padapter->wfd_info;
806                 if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
807                 {
808                         pwfd_info->wfd_device_type = ( u8 ) get_int_from_command( priv_cmd.buf );
809                         pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
810                 }
811                 break;
812         }
813 #endif
814         case ANDROID_WIFI_CMD_CHANGE_DTIM:
815                 {
816 #ifdef CONFIG_LPS
817                         u8 dtim;
818                         u8 *ptr =(u8 *) &priv_cmd.buf;
819                         
820                         ptr += 9;//string command length of  "SET_DTIM";
821
822                         dtim = rtw_atoi(ptr);
823
824                         DBG_871X("DTIM=%d\n", dtim);
825
826                         rtw_lps_change_dtim_cmd(padapter, dtim);                        
827 #endif                  
828                 }               
829                 break;
830         case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL:
831         {
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);
834                 break;
835         }
836         case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA:
837         {
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);
841                 break;
842         }
843         case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA:
844         {
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);
848                 break;
849         }
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);
853                 break;
854 #endif //CONFIG_GTK_OL          
855         case ANDROID_WIFI_CMD_P2P_DISABLE:
856         {
857 #ifdef CONFIG_P2P
858                 struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;     
859                 u8 channel, ch_offset;
860                 u16 bwmode;
861
862                 rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
863 #endif // CONFIG_P2P
864                 break;
865         }
866         default:
867                 DBG_871X("Unknown PRIVATE command %s - ignored\n", command);
868                 snprintf(command, 3, "OK");
869                 bytes_written = strlen("OK");
870         }
871
872 response:
873         if (bytes_written >= 0) {
874                 if ((bytes_written == 0) && (priv_cmd.total_len > 0))
875                         command[0] = '\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;
879                 } else {
880                         bytes_written++;
881                 }
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__);
885                         ret = -EFAULT;
886                 }
887         }
888         else {
889                 ret = bytes_written;
890         }
891
892 exit:
893         rtw_unlock_suspend();
894         if (command) {
895                 rtw_mfree(command, priv_cmd.total_len);
896         }
897
898         return ret;
899 }
900
901
902 /**
903  * Functions for Android WiFi card detection
904  */
905 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
906
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;
911
912 static int wifi_add_dev(void);
913 static void wifi_del_dev(void);
914
915 int rtw_android_wifictrl_func_add(void)
916 {
917         int ret = 0;
918         sema_init(&wifi_control_sem, 0);
919
920         ret = wifi_add_dev();
921         if (ret) {
922                 DBG_871X("%s: platform_driver_register failed\n", __FUNCTION__);
923                 return ret;
924         }
925         g_wifidev_registered = 1;
926
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) {
929                 ret = -EINVAL;
930                 DBG_871X("%s: platform_driver_register timeout\n", __FUNCTION__);
931         }
932
933         return ret;
934 }
935
936 void rtw_android_wifictrl_func_del(void)
937 {
938         if (g_wifidev_registered)
939         {
940                 wifi_del_dev();
941                 g_wifidev_registered = 0;
942         }
943 }
944
945 void *wl_android_prealloc(int section, unsigned long size)
946 {
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);
950                 if (alloc_ptr) {
951                         DBG_871X("success alloc section %d\n", section);
952                         if (size != 0L)
953                                 memset(alloc_ptr, 0, size);
954                         return alloc_ptr;
955                 }
956         }
957
958         DBG_871X("can't alloc section %d\n", section);
959         return NULL;
960 }
961
962 int wifi_get_irq_number(unsigned long *irq_flags_ptr)
963 {
964         if (wifi_irqres) {
965                 *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
966                 return (int)wifi_irqres->start;
967         }
968 #ifdef CUSTOM_OOB_GPIO_NUM
969         return CUSTOM_OOB_GPIO_NUM;
970 #else
971         return -1;
972 #endif
973 }
974
975 int wifi_set_power(int on, unsigned long msec)
976 {
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);
980         }
981         if (msec)
982                 msleep(msec);
983         return 0;
984 }
985
986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
987 int wifi_get_mac_addr(unsigned char *buf)
988 {
989         DBG_871X("%s\n", __FUNCTION__);
990         if (!buf)
991                 return -EINVAL;
992         if (wifi_control_data && wifi_control_data->get_mac_addr) {
993                 return wifi_control_data->get_mac_addr(buf);
994         }
995         return -EOPNOTSUPP;
996 }
997 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
998
999 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
1000 void *wifi_get_country_code(char *ccode)
1001 {
1002         DBG_871X("%s\n", __FUNCTION__);
1003         if (!ccode)
1004                 return NULL;
1005         if (wifi_control_data && wifi_control_data->get_country_code) {
1006                 return wifi_control_data->get_country_code(ccode);
1007         }
1008         return NULL;
1009 }
1010 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
1011
1012 static int wifi_set_carddetect(int on)
1013 {
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);
1017         }
1018         return 0;
1019 }
1020
1021 static int wifi_probe(struct platform_device *pdev)
1022 {
1023         struct wifi_platform_data *wifi_ctrl =
1024                 (struct wifi_platform_data *)(pdev->dev.platform_data);
1025         int wifi_wake_gpio = 0;
1026
1027         DBG_871X("## %s\n", __FUNCTION__);
1028         wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
1029
1030         if (wifi_irqres == NULL)
1031                 wifi_irqres = platform_get_resource_byname(pdev,
1032                         IORESOURCE_IRQ, "bcm4329_wlan_irq");
1033         else
1034                 wifi_wake_gpio = wifi_irqres->start;
1035
1036 #ifdef CONFIG_GPIO_WAKEUP
1037         printk("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
1038                         wifi_irqres->start, wifi_wake_gpio);
1039
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);
1049         }
1050         else if(wifi_irqres)
1051         {
1052                 oob_irq = wifi_irqres->start;
1053                 printk("%s oob_irq:%d\n", __func__, oob_irq);
1054         }
1055 #endif
1056         wifi_control_data = wifi_ctrl;
1057
1058         wifi_set_power(1, 0);   /* Power On */
1059         wifi_set_carddetect(1); /* CardDetect (0->1) */
1060
1061         up(&wifi_control_sem);
1062         return 0;
1063 }
1064
1065 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1066 extern PADAPTER g_test_adapter;
1067
1068 static void shutdown_card(void)
1069 {
1070         u32 addr;
1071         u8 tmp8, cnt=0;
1072
1073         if (NULL == g_test_adapter)
1074         {
1075                 DBG_871X("%s: padapter==NULL\n", __FUNCTION__);
1076                 return;
1077         }
1078
1079 #ifdef CONFIG_FWLPS_IN_IPS
1080         LeaveAllPowerSaveMode(g_test_adapter);
1081 #endif // CONFIG_FWLPS_IN_IPS
1082
1083         // Leave SDIO HCI Suspend
1084         addr = 0x10250086;
1085         rtw_write8(g_test_adapter, addr, 0);
1086         do {
1087                 tmp8 = rtw_read8(g_test_adapter, addr);
1088                 cnt++;
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);
1091
1092                 if (tmp8 & BIT(1))
1093                         break;
1094
1095                 if (cnt >= 100)
1096                 {
1097                         DBG_871X(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
1098                                 FUNC_ADPT_ARG(g_test_adapter), addr);
1099                         break;
1100                 }
1101
1102                 rtw_mdelay_os(10);
1103         } while (1);
1104
1105         // unlock register I/O
1106         rtw_write8(g_test_adapter, 0x1C, 0);
1107
1108         // enable power down function
1109         // 0x04[4] = 1
1110         // 0x05[7] = 1
1111         addr = 0x04;
1112         tmp8 = rtw_read8(g_test_adapter, addr);
1113         tmp8 |= BIT(4);
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));
1117
1118         addr = 0x05;
1119         tmp8 = rtw_read8(g_test_adapter, addr);
1120         tmp8 |= BIT(7);
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));
1124
1125         // lock register page0 0x0~0xB read/write
1126         rtw_write8(g_test_adapter, 0x1C, 0x0E);
1127
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)
1133         {
1134                 PADAPTER pbuddy;
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);
1139         }
1140 #endif // CONFIG_CONCURRENT_MODE
1141 }
1142 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1143
1144 static int wifi_remove(struct platform_device *pdev)
1145 {
1146         struct wifi_platform_data *wifi_ctrl =
1147                 (struct wifi_platform_data *)(pdev->dev.platform_data);
1148
1149         DBG_871X("## %s\n", __FUNCTION__);
1150         wifi_control_data = wifi_ctrl;
1151
1152         wifi_set_power(0, 0);   /* Power Off */
1153         wifi_set_carddetect(0); /* CardDetect (1->0) */
1154
1155         up(&wifi_control_sem);
1156         return 0;
1157 }
1158
1159 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1160 static void wifi_shutdown(struct platform_device *pdev)
1161 {
1162         struct wifi_platform_data *wifi_ctrl =
1163                 (struct wifi_platform_data *)(pdev->dev.platform_data);
1164         
1165
1166         DBG_871X("## %s\n", __FUNCTION__);
1167
1168         wifi_control_data = wifi_ctrl;
1169
1170         shutdown_card();
1171         wifi_set_power(0, 0);   /* Power Off */
1172         wifi_set_carddetect(0); /* CardDetect (1->0) */
1173 }
1174 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
1175
1176 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
1177 {
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);
1181 #endif
1182         return 0;
1183 }
1184
1185 static int wifi_resume(struct platform_device *pdev)
1186 {
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);
1191 #endif
1192         return 0;
1193 }
1194
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
1204         .driver         = {
1205         .name   = "bcmdhd_wlan",
1206         }
1207 };
1208
1209 static struct platform_driver wifi_device_legacy = {
1210         .probe          = wifi_probe,
1211         .remove         = wifi_remove,
1212         .suspend        = wifi_suspend,
1213         .resume         = wifi_resume,
1214         .driver         = {
1215         .name   = "bcm4329_wlan",
1216         }
1217 };
1218
1219 static int wifi_add_dev(void)
1220 {
1221         DBG_871X("## Calling platform_driver_register\n");
1222         platform_driver_register(&wifi_device);
1223         platform_driver_register(&wifi_device_legacy);
1224         return 0;
1225 }
1226
1227 static void wifi_del_dev(void)
1228 {
1229         DBG_871X("## Unregister platform_driver_register\n");
1230         platform_driver_unregister(&wifi_device);
1231         platform_driver_unregister(&wifi_device_legacy);
1232 }
1233 #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
1234
1235 #ifdef CONFIG_GPIO_WAKEUP
1236 #ifdef CONFIG_PLATFORM_INTEL_BYT
1237 int wifi_configure_gpio(void)
1238 {
1239         if (gpio_request(oob_gpio, "oob_irq")) {
1240                 DBG_871X("## %s Cannot request GPIO\n", __FUNCTION__);
1241                 return -1;
1242         }
1243         gpio_export(oob_gpio, 0);
1244         if (gpio_direction_input(oob_gpio)) {
1245                 DBG_871X("## %s Cannot set GPIO direction input\n", __FUNCTION__);
1246                 return -1;
1247         }
1248         if ((oob_irq = gpio_to_irq(oob_gpio)) < 0) {
1249                 DBG_871X("## %s Cannot convert GPIO to IRQ\n", __FUNCTION__);
1250                 return -1;
1251         }
1252
1253         DBG_871X("## %s OOB_IRQ=%d\n", __FUNCTION__, oob_irq);
1254
1255         return 0;
1256 }
1257 #endif //CONFIG_PLATFORM_INTEL_BYT
1258 void wifi_free_gpio(unsigned int gpio)
1259 {
1260 #ifdef CONFIG_PLATFORM_INTEL_BYT
1261         if(gpio)
1262                 gpio_free(gpio);
1263 #endif //CONFIG_PLATFORM_INTEL_BYT
1264 }
1265 #endif //CONFIG_GPIO_WAKEUP