d6fe5924452c7c3f1fe3c1606df6df733a5a8db1
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bs / 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",
80         "WFD-ENABLE",
81         "WFD-DISABLE",
82         "WFD-SET-TCPPORT",
83         "WFD-SET-MAXTPUT",
84         "WFD-SET-DEVTYPE",
85         "SET_DTIM",
86         "HOSTAPD_SET_MACADDR_ACL",
87         "HOSTAPD_ACL_ADD_STA",
88         "HOSTAPD_ACL_REMOVE_STA",
89 #ifdef CONFIG_GTK_OL
90         "GTK_REKEY_OFFLOAD",
91 #endif //CONFIG_GTK_OL
92 /*      Private command for     P2P disable*/
93         "P2P_DISABLE"
94 };
95
96 #ifdef CONFIG_PNO_SUPPORT
97 #define PNO_TLV_PREFIX                  'S'
98 #define PNO_TLV_VERSION                 '1'
99 #define PNO_TLV_SUBVERSION              '2'
100 #define PNO_TLV_RESERVED                '0'
101 #define PNO_TLV_TYPE_SSID_IE    'S'
102 #define PNO_TLV_TYPE_TIME               'T'
103 #define PNO_TLV_FREQ_REPEAT             'R'
104 #define PNO_TLV_FREQ_EXPO_MAX   'M'
105
106 typedef struct cmd_tlv {
107         char prefix;
108         char version;
109         char subver;
110         char reserved;
111 } cmd_tlv_t;
112
113 #ifdef CONFIG_PNO_SET_DEBUG
114 char pno_in_example[] = {
115                 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
116                 'S', '1', '2', '0',
117                 'S',    //1
118                 0x05,
119                 'd', 'l', 'i', 'n', 'k',
120                 'S',    //2
121                 0x06,
122                 'B', 'U', 'F', 'B', 'U','F',
123                 'S',    //3
124                 0x20,
125                 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '@', '#', '$', '%', '^',
126                 'S',    //4
127                 0x0a,
128                 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
129                 'T',
130                 '0', '5',
131                 'R',
132                 '2',
133                 'M',
134                 '2',
135                 0x00
136                 };
137 #endif /* CONFIG_PNO_SET_DEBUG */
138 #endif /* PNO_SUPPORT */
139
140 typedef struct android_wifi_priv_cmd {
141         char *buf;
142         int used_len;
143         int total_len;
144 } android_wifi_priv_cmd;
145
146 #ifdef CONFIG_COMPAT
147 typedef struct compat_android_wifi_priv_cmd {
148         compat_uptr_t buf;
149         int used_len;
150         int total_len;
151 } compat_android_wifi_priv_cmd;
152 #endif /* CONFIG_COMPAT */
153
154 /**
155  * Local (static) functions and variables
156  */
157
158 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
159  * time (only) in dhd_open, subsequential wifi on will be handled by
160  * wl_android_wifi_on
161  */
162 static int g_wifi_on = _TRUE;
163
164 unsigned int oob_irq = 0;
165 unsigned int oob_gpio = 0;
166
167 #ifdef CONFIG_PNO_SUPPORT
168 /* 
169  * rtw_android_pno_setup
170  * Description: 
171  * This is used for private command.
172  * 
173  * Parameter:
174  * net: net_device
175  * command: parameters from private command
176  * total_len: the length of the command.
177  *
178  * */
179 static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len) {
180         pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
181         int res = -1;
182         int nssid = 0;
183         cmd_tlv_t *cmd_tlv_temp;
184         char *str_ptr;
185         int tlv_size_left;
186         int pno_time = 0;
187         int pno_repeat = 0;
188         int pno_freq_expo_max = 0;
189         int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1; 
190
191 #ifdef CONFIG_PNO_SET_DEBUG
192         int i;
193         char *p;
194         p = pno_in_example;
195
196         total_len = sizeof(pno_in_example);
197         str_ptr = p + cmdlen;
198 #else
199         str_ptr = command + cmdlen;
200 #endif
201
202         if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
203                 DBG_871X("%s argument=%d less min size\n", __func__, total_len);
204                 goto exit_proc;
205         }
206
207         tlv_size_left = total_len - cmdlen;
208
209         cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
210         memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
211
212         if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
213                 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
214                 (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
215
216                 str_ptr += sizeof(cmd_tlv_t);
217                 tlv_size_left -= sizeof(cmd_tlv_t);
218
219                 if ((nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
220                         MAX_PNO_LIST_COUNT, &tlv_size_left)) <= 0) {
221                         DBG_871X("SSID is not presented or corrupted ret=%d\n", nssid);
222                         goto exit_proc;
223                 } else {
224                         if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
225                                 DBG_871X("%s scan duration corrupted field size %d\n",
226                                         __func__, tlv_size_left);
227                                 goto exit_proc;
228                         }
229                         str_ptr++;
230                         pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
231                         DBG_871X("%s: pno_time=%d\n", __func__, pno_time);
232
233                         if (str_ptr[0] != 0) {
234                                 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
235                                         DBG_871X("%s pno repeat : corrupted field\n",
236                                                 __func__);
237                                         goto exit_proc;
238                                 }
239                                 str_ptr++;
240                                 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
241                                 DBG_871X("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat);
242                                 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
243                                         DBG_871X("%s FREQ_EXPO_MAX corrupted field size\n",
244                                                 __func__);
245                                         goto exit_proc;
246                                 }
247                                 str_ptr++;
248                                 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
249                                 DBG_871X("%s: pno_freq_expo_max=%d\n",
250                                         __func__, pno_freq_expo_max);
251                         }
252                 }
253         } else {
254                 DBG_871X("%s get wrong TLV command\n", __FUNCTION__);
255                 goto exit_proc;
256         }
257
258         res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
259
260 #ifdef CONFIG_PNO_SET_DEBUG
261         rtw_dev_pno_debug(net);
262 #endif
263
264 exit_proc:
265         return res;
266 }
267
268 /* 
269  * rtw_android_cfg80211_pno_setup
270  * Description: 
271  * This is used for cfg80211 sched_scan.
272  * 
273  * Parameter:
274  * net: net_device
275  * request: cfg80211_request
276  * */
277
278 int rtw_android_cfg80211_pno_setup(struct net_device *net,
279                 struct cfg80211_ssid *ssids, int n_ssids, int interval) {
280         int res = -1;
281         int nssid = 0;
282         int pno_time = 0;
283         int pno_repeat = 0;
284         int pno_freq_expo_max = 0;
285         int index = 0;
286         pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
287
288         if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
289                 DBG_871X("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
290                 return -EINVAL;
291         }
292
293         memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
294
295         nssid = n_ssids;
296
297         for (index = 0 ; index < nssid ; index++) {
298                 pno_ssids_local[index].SSID_len = ssids[index].ssid_len;
299                 memcpy(pno_ssids_local[index].SSID, ssids[index].ssid,
300                                 ssids[index].ssid_len);
301         }
302
303         pno_time = (interval / 1000);
304
305         DBG_871X("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
306
307         res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
308                         pno_repeat, pno_freq_expo_max);
309
310 exit_proc:
311         return res;
312 }
313
314 int rtw_android_pno_enable(struct net_device *net, int pno_enable) {
315         _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
316         struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
317
318         if (pwrctl) {
319                 pwrctl->wowlan_pno_enable = pno_enable;
320                 DBG_871X("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
321                 if (pwrctl->wowlan_pno_enable == 0) {
322                         if (pwrctl->pnlo_info != NULL) {
323                                 rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
324                                 pwrctl->pnlo_info = NULL;
325                         }
326                         if (pwrctl->pno_ssid_list != NULL) {
327                                 rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
328                                 pwrctl->pno_ssid_list = NULL;
329                         }
330                         if (pwrctl->pscan_info != NULL) {
331                                 rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
332                                 pwrctl->pscan_info = NULL;
333                         }
334                 } 
335                 return 0;
336         } else {
337                 return -1;
338         }
339 }
340 #endif //CONFIG_PNO_SUPPORT
341
342 int rtw_android_cmdstr_to_num(char *cmdstr)
343 {
344         int cmd_num;
345         for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
346                 if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
347                         break;
348
349         return cmd_num;
350 }
351
352 int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
353 {
354         _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
355         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);     
356         struct  wlan_network    *pcur_network = &pmlmepriv->cur_network;
357         int bytes_written = 0;
358
359         if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {     
360                 bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d", 
361                         pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
362         }
363
364         return bytes_written;
365 }
366
367 int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
368 {
369         _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
370         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);     
371         struct  wlan_network    *pcur_network = &pmlmepriv->cur_network;
372         int bytes_written = 0;
373         u16 link_speed = 0;
374
375         link_speed = rtw_get_cur_max_rate(padapter)/10;
376         bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
377
378         return bytes_written;
379 }
380
381 int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
382 {
383         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
384         int bytes_written = 0;
385         
386         bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
387         return bytes_written;
388 }
389
390 int rtw_android_set_country(struct net_device *net, char *command, int total_len)
391 {
392         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
393         char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
394         int ret = _FAIL;
395         
396         ret = rtw_set_country(adapter, country_code);
397
398         return (ret==_SUCCESS)?0:-1;
399 }
400
401 int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
402 {
403         int bytes_written = 0;
404
405         //We use the same address as our HW MAC address
406         _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
407         
408         bytes_written = ETH_ALEN;
409         return bytes_written;
410 }
411
412 int rtw_android_set_block(struct net_device *net, char *command, int total_len)
413 {
414         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
415         char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
416
417         #ifdef CONFIG_IOCTL_CFG80211
418         adapter_wdev_data(adapter)->block = (*block_value=='0')?_FALSE:_TRUE;
419         #endif
420         
421         return 0;
422 }
423
424 int rtw_android_setband(struct net_device *net, char *command, int total_len)
425 {
426         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
427         char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
428         u32 band = GHZ_MAX;
429         int ret = _FAIL;
430
431         sscanf(arg, "%u", &band);
432         ret = rtw_set_band(adapter, band);
433
434         return (ret==_SUCCESS)?0:-1;
435 }
436
437 int rtw_android_getband(struct net_device *net, char *command, int total_len)
438 {
439         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
440         int bytes_written = 0;
441
442         bytes_written = snprintf(command, total_len, "%u", adapter->setband);
443
444         return bytes_written;
445 }
446
447 enum {
448         MIRACAST_DISABLED = 0,
449         MIRACAST_SOURCE,
450         MIRACAST_SINK,
451         MIRACAST_INVALID,
452 };
453
454 static const char *miracast_mode_str[] = {
455         "DISABLED",
456         "SOURCE",
457         "SINK",
458         "INVALID",
459 };
460
461 static const char *get_miracast_mode_str(int mode)
462 {
463         if (mode < MIRACAST_DISABLED || mode >= MIRACAST_INVALID)
464                 mode = MIRACAST_INVALID;
465
466         return miracast_mode_str[mode];
467 }
468
469 int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
470 {
471         _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
472         char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
473         u8 mode;
474         int num;
475         int ret = _FAIL;
476
477         num = sscanf(arg, "%hhu", &mode);
478
479         if (num >= 1) {
480                 DBG_871X("Miracast mode: %s(%u)\n", get_miracast_mode_str(mode), mode);
481                 ret = _SUCCESS;
482         }
483
484         return (ret==_SUCCESS)?0:-1;
485 }
486
487 int get_int_from_command( char* pcmd )
488 {
489         int i = 0;
490
491         for( i = 0; i < strlen( pcmd ); i++ )
492         {
493                 if ( pcmd[ i ] == '=' )
494                 {
495                         //      Skip the '=' and space characters.
496                         i += 2;
497                         break;
498                 }
499         }
500         return ( rtw_atoi( pcmd + i ) );
501 }
502
503 #ifdef CONFIG_GTK_OL
504 int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
505 {
506         int i;
507         //u8 *cmd_ptr = priv_cmd.buf;
508         struct sta_info * psta;
509         _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
510         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
511         struct sta_priv *pstapriv = &padapter->stapriv;
512         struct security_priv* psecuritypriv=&(padapter->securitypriv);
513         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
514         
515         
516         if (psta == NULL) 
517         {
518                 DBG_8192C("%s, : Obtain Sta_info fail \n", __func__);
519         }
520         else
521         {
522                 //string command length of "GTK_REKEY_OFFLOAD"
523                 cmd_ptr += 18;
524                 
525                 _rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
526                 cmd_ptr += RTW_KEK_LEN;
527                 /*
528                 printk("supplicant KEK: ");
529                 for(i=0;i<RTW_KEK_LEN; i++)
530                         printk(" %02x ", psta->kek[i]);
531                 printk("\n supplicant KCK: ");
532                 */
533                 _rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
534                 cmd_ptr += RTW_KCK_LEN;
535                 /*
536                 for(i=0;i<RTW_KEK_LEN; i++)
537                         printk(" %02x ", psta->kck[i]);
538                 */
539                 _rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
540                 psecuritypriv->binstallKCK_KEK = _TRUE;
541                 
542                 //printk("\nREPLAY_CTR: ");
543                 //for(i=0;i<RTW_REPLAY_CTR_LEN; i++)
544                         //printk(" %02x ", psta->replay_ctr[i]);
545         }
546
547         return _SUCCESS;
548 }
549 #endif //CONFIG_GTK_OL
550
551 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
552 {
553         int ret = 0;
554         char *command = NULL;
555         int cmd_num;
556         int bytes_written = 0;
557 #ifdef CONFIG_PNO_SUPPORT
558         uint cmdlen = 0;
559         uint pno_enable = 0;
560 #endif
561         android_wifi_priv_cmd priv_cmd;
562         _adapter*       padapter = ( _adapter * ) rtw_netdev_priv(net);
563 #ifdef CONFIG_WFD
564         struct wifi_display_info                *pwfd_info;
565 #endif
566
567         rtw_lock_suspend();
568
569         if (!ifr->ifr_data) {
570                 ret = -EINVAL;
571                 goto exit;
572         }
573 #ifdef CONFIG_COMPAT
574         if (is_compat_task()) {
575                 /* User space is 32-bit, use compat ioctl */
576                 compat_android_wifi_priv_cmd compat_priv_cmd;
577
578                 if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
579                         ret = -EFAULT;
580                         goto exit;
581                 }
582                 priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
583                 priv_cmd.used_len = compat_priv_cmd.used_len;
584                 priv_cmd.total_len = compat_priv_cmd.total_len;
585         } else
586 #endif /* CONFIG_COMPAT */
587         if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
588                 ret = -EFAULT;
589                 goto exit;
590         }
591         if ( padapter->registrypriv.mp_mode == 1) {
592                 ret = -EFAULT;
593                 goto exit;
594         }
595         //DBG_871X("%s priv_cmd.buf=%p priv_cmd.total_len=%d  priv_cmd.used_len=%d\n",__func__,priv_cmd.buf,priv_cmd.total_len,priv_cmd.used_len);
596         command = rtw_zmalloc(priv_cmd.total_len);
597         if (!command)
598         {
599                 DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
600                 ret = -ENOMEM;
601                 goto exit;
602         }
603
604         if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
605                 DBG_871X("%s: failed to access memory\n", __FUNCTION__);
606                 ret = -EFAULT;
607                 goto exit;
608          }
609         if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
610                 ret = -EFAULT;
611                 goto exit;
612         }
613
614         DBG_871X("%s: Android private cmd \"%s\" on %s\n"
615                 , __FUNCTION__, command, ifr->ifr_name);
616
617         cmd_num = rtw_android_cmdstr_to_num(command);
618         
619         switch(cmd_num) {
620         case ANDROID_WIFI_CMD_START:
621                 //bytes_written = wl_android_wifi_on(net);
622                 goto response;
623         case ANDROID_WIFI_CMD_SETFWPATH:
624                 goto response;
625         }
626
627         if (!g_wifi_on) {
628                 DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
629                         ,__FUNCTION__, command, ifr->ifr_name);
630                 ret = 0;
631                 goto exit;
632         }
633
634         switch(cmd_num) {
635
636         case ANDROID_WIFI_CMD_STOP:
637                 //bytes_written = wl_android_wifi_off(net);
638                 break;
639                 
640         case ANDROID_WIFI_CMD_SCAN_ACTIVE:
641                 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE);
642 #ifdef CONFIG_PLATFORM_MSTAR
643 #ifdef CONFIG_IOCTL_CFG80211
644                 adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = _TRUE;
645 #endif //CONFIG_IOCTL_CFG80211
646 #endif //CONFIG_PLATFORM_MSTAR
647                 break;
648         case ANDROID_WIFI_CMD_SCAN_PASSIVE:
649                 //rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
650                 break;
651                 
652         case ANDROID_WIFI_CMD_RSSI:
653                 bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
654                 break;
655         case ANDROID_WIFI_CMD_LINKSPEED:
656                 bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
657                 break;
658
659         case ANDROID_WIFI_CMD_MACADDR:
660                 bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
661                 break;
662                 
663         case ANDROID_WIFI_CMD_BLOCK:
664                 bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
665                 break;
666                 
667         case ANDROID_WIFI_CMD_RXFILTER_START:
668                 //bytes_written = net_os_set_packet_filter(net, 1);
669                 break;
670         case ANDROID_WIFI_CMD_RXFILTER_STOP:
671                 //bytes_written = net_os_set_packet_filter(net, 0);
672                 break;
673         case ANDROID_WIFI_CMD_RXFILTER_ADD:
674                 //int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
675                 //bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
676                 break;
677         case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
678                 //int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
679                 //bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
680                 break;
681                 
682         case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
683                 /* TBD: BTCOEXSCAN-START */
684                 break;
685         case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
686                 /* TBD: BTCOEXSCAN-STOP */
687                 break;
688         case ANDROID_WIFI_CMD_BTCOEXMODE:
689                 #if 0
690                 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
691                 if (mode == 1)
692                         net_os_set_packet_filter(net, 0); /* DHCP starts */
693                 else
694                         net_os_set_packet_filter(net, 1); /* DHCP ends */
695 #ifdef WL_CFG80211
696                 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
697 #endif
698                 #endif
699                 break;
700                 
701         case ANDROID_WIFI_CMD_SETSUSPENDOPT:
702                 //bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
703                 break;
704                 
705         case ANDROID_WIFI_CMD_SETBAND:
706                 bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
707                 break;
708
709         case ANDROID_WIFI_CMD_GETBAND:
710                 bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
711                 break;
712
713         case ANDROID_WIFI_CMD_MIRACAST:
714                 bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
715                 break;
716
717         case ANDROID_WIFI_CMD_COUNTRY:
718                 bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
719                 break;
720                 
721 #ifdef CONFIG_PNO_SUPPORT
722         case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
723                 //bytes_written = dhd_dev_pno_reset(net);
724                 break;
725         case ANDROID_WIFI_CMD_PNOSETUP_SET:
726                 bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
727                 break;
728         case ANDROID_WIFI_CMD_PNOENABLE_SET:
729                 cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
730                 pno_enable = *(command + cmdlen + 1) - '0';
731                 bytes_written = rtw_android_pno_enable(net, pno_enable);
732                 break;
733 #endif
734
735         case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
736                 bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
737                 break;
738         case ANDROID_WIFI_CMD_P2P_SET_NOA:
739                 //int skip = strlen(CMD_P2P_SET_NOA) + 1;
740                 //bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip);
741                 break;
742         case ANDROID_WIFI_CMD_P2P_GET_NOA:
743                 //bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
744                 break;
745         case ANDROID_WIFI_CMD_P2P_SET_PS:
746                 //int skip = strlen(CMD_P2P_SET_PS) + 1;
747                 //bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip);
748                 break;
749                 
750 #ifdef CONFIG_IOCTL_CFG80211
751         case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
752         {
753                 int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
754                 bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
755                 break;
756         }
757 #endif //CONFIG_IOCTL_CFG80211
758
759 #ifdef CONFIG_WFD
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 #ifdef CONFIG_GTK_OL
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