Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nu11secur1ty
GitHub Repository: nu11secur1ty/Kali-Linux
Path: blob/master/ALFA-W1F1/RTL8814AU/os_dep/linux/rtw_android.c
1307 views
1
/******************************************************************************
2
*
3
* Copyright(c) 2007 - 2017 Realtek Corporation.
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
*****************************************************************************/
15
16
#ifdef CONFIG_GPIO_WAKEUP
17
#include <linux/gpio.h>
18
#endif
19
20
#include <drv_types.h>
21
22
#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
23
#include <linux/platform_device.h>
24
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
25
#include <linux/wlan_plat.h>
26
#else
27
#include <linux/wifi_tiwlan.h>
28
#endif
29
#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
30
31
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
32
#define strnicmp strncasecmp
33
#endif /* Linux kernel >= 4.0.0 */
34
35
#ifdef CONFIG_GPIO_WAKEUP
36
#include <linux/interrupt.h>
37
#include <linux/irq.h>
38
#endif
39
40
#include "rtw_version.h"
41
42
extern void macstr2num(u8 *dst, u8 *src);
43
44
const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
45
"START",
46
"STOP",
47
"SCAN-ACTIVE",
48
"SCAN-PASSIVE",
49
"RSSI",
50
"LINKSPEED",
51
"RXFILTER-START",
52
"RXFILTER-STOP",
53
"RXFILTER-ADD",
54
"RXFILTER-REMOVE",
55
"BTCOEXSCAN-START",
56
"BTCOEXSCAN-STOP",
57
"BTCOEXMODE",
58
"SETSUSPENDMODE",
59
"SETSUSPENDOPT",
60
"P2P_DEV_ADDR",
61
"SETFWPATH",
62
"SETBAND",
63
"GETBAND",
64
"COUNTRY",
65
"P2P_SET_NOA",
66
"P2P_GET_NOA",
67
"P2P_SET_PS",
68
"SET_AP_WPS_P2P_IE",
69
70
"MIRACAST",
71
72
#ifdef CONFIG_PNO_SUPPORT
73
"PNOSSIDCLR",
74
"PNOSETUP",
75
"PNOFORCE",
76
"PNODEBUG",
77
#endif
78
79
"MACADDR",
80
81
"BLOCK_SCAN",
82
"BLOCK",
83
"WFD-ENABLE",
84
"WFD-DISABLE",
85
"WFD-SET-TCPPORT",
86
"WFD-SET-MAXTPUT",
87
"WFD-SET-DEVTYPE",
88
"SET_DTIM",
89
"HOSTAPD_SET_MACADDR_ACL",
90
"HOSTAPD_ACL_ADD_STA",
91
"HOSTAPD_ACL_REMOVE_STA",
92
#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
93
"GTK_REKEY_OFFLOAD",
94
#endif /* CONFIG_GTK_OL */
95
/* Private command for P2P disable*/
96
"P2P_DISABLE",
97
"SET_AEK",
98
"EXT_AUTH_STATUS",
99
"DRIVER_VERSION"
100
};
101
102
#ifdef CONFIG_PNO_SUPPORT
103
#define PNO_TLV_PREFIX 'S'
104
#define PNO_TLV_VERSION '1'
105
#define PNO_TLV_SUBVERSION '2'
106
#define PNO_TLV_RESERVED '0'
107
#define PNO_TLV_TYPE_SSID_IE 'S'
108
#define PNO_TLV_TYPE_TIME 'T'
109
#define PNO_TLV_FREQ_REPEAT 'R'
110
#define PNO_TLV_FREQ_EXPO_MAX 'M'
111
112
typedef struct cmd_tlv {
113
char prefix;
114
char version;
115
char subver;
116
char reserved;
117
} cmd_tlv_t;
118
119
#ifdef CONFIG_PNO_SET_DEBUG
120
char pno_in_example[] = {
121
'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
122
'S', '1', '2', '0',
123
'S', /* 1 */
124
0x05,
125
'd', 'l', 'i', 'n', 'k',
126
'S', /* 2 */
127
0x06,
128
'B', 'U', 'F', 'B', 'U', 'F',
129
'S', /* 3 */
130
0x20,
131
'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', '!', '@', '#', '$', '%', '^',
132
'S', /* 4 */
133
0x0a,
134
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
135
'T',
136
'0', '5',
137
'R',
138
'2',
139
'M',
140
'2',
141
0x00
142
};
143
#endif /* CONFIG_PNO_SET_DEBUG */
144
#endif /* PNO_SUPPORT */
145
146
typedef struct android_wifi_priv_cmd {
147
char *buf;
148
int used_len;
149
int total_len;
150
} android_wifi_priv_cmd;
151
152
#ifdef CONFIG_COMPAT
153
typedef struct compat_android_wifi_priv_cmd {
154
compat_uptr_t buf;
155
int used_len;
156
int total_len;
157
} compat_android_wifi_priv_cmd;
158
#endif /* CONFIG_COMPAT */
159
160
/**
161
* Local (static) functions and variables
162
*/
163
164
/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
165
* time (only) in dhd_open, subsequential wifi on will be handled by
166
* wl_android_wifi_on
167
*/
168
static int g_wifi_on = _TRUE;
169
170
unsigned int oob_irq = 0;
171
unsigned int oob_gpio = 0;
172
173
#ifdef CONFIG_PNO_SUPPORT
174
/*
175
* rtw_android_pno_setup
176
* Description:
177
* This is used for private command.
178
*
179
* Parameter:
180
* net: net_device
181
* command: parameters from private command
182
* total_len: the length of the command.
183
*
184
* */
185
static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len)
186
{
187
pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
188
int res = -1;
189
int nssid = 0;
190
cmd_tlv_t *cmd_tlv_temp;
191
char *str_ptr;
192
int tlv_size_left;
193
int pno_time = 0;
194
int pno_repeat = 0;
195
int pno_freq_expo_max = 0;
196
int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1;
197
198
#ifdef CONFIG_PNO_SET_DEBUG
199
int i;
200
char *p;
201
p = pno_in_example;
202
203
total_len = sizeof(pno_in_example);
204
str_ptr = p + cmdlen;
205
#else
206
str_ptr = command + cmdlen;
207
#endif
208
209
if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
210
RTW_INFO("%s argument=%d less min size\n", __func__, total_len);
211
goto exit_proc;
212
}
213
214
tlv_size_left = total_len - cmdlen;
215
216
cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
217
memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
218
219
if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
220
(cmd_tlv_temp->version == PNO_TLV_VERSION) &&
221
(cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
222
223
str_ptr += sizeof(cmd_tlv_t);
224
tlv_size_left -= sizeof(cmd_tlv_t);
225
226
nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
227
MAX_PNO_LIST_COUNT, &tlv_size_left);
228
if (nssid <= 0) {
229
RTW_INFO("SSID is not presented or corrupted ret=%d\n", nssid);
230
goto exit_proc;
231
} else {
232
if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
233
RTW_INFO("%s scan duration corrupted field size %d\n",
234
__func__, tlv_size_left);
235
goto exit_proc;
236
}
237
str_ptr++;
238
pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
239
RTW_INFO("%s: pno_time=%d\n", __func__, pno_time);
240
241
if (str_ptr[0] != 0) {
242
if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
243
RTW_INFO("%s pno repeat : corrupted field\n",
244
__func__);
245
goto exit_proc;
246
}
247
str_ptr++;
248
pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
249
RTW_INFO("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat);
250
if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
251
RTW_INFO("%s FREQ_EXPO_MAX corrupted field size\n",
252
__func__);
253
goto exit_proc;
254
}
255
str_ptr++;
256
pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
257
RTW_INFO("%s: pno_freq_expo_max=%d\n",
258
__func__, pno_freq_expo_max);
259
}
260
}
261
} else {
262
RTW_INFO("%s get wrong TLV command\n", __FUNCTION__);
263
goto exit_proc;
264
}
265
266
res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
267
268
#ifdef CONFIG_PNO_SET_DEBUG
269
rtw_dev_pno_debug(net);
270
#endif
271
272
exit_proc:
273
return res;
274
}
275
276
/*
277
* rtw_android_cfg80211_pno_setup
278
* Description:
279
* This is used for cfg80211 sched_scan.
280
*
281
* Parameter:
282
* net: net_device
283
* request: cfg80211_request
284
* */
285
286
int rtw_android_cfg80211_pno_setup(struct net_device *net,
287
struct cfg80211_ssid *ssids, int n_ssids, int interval)
288
{
289
int res = -1;
290
int nssid = 0;
291
int pno_time = 0;
292
int pno_repeat = 0;
293
int pno_freq_expo_max = 0;
294
int index = 0;
295
pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
296
297
if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
298
RTW_INFO("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
299
return -EINVAL;
300
}
301
302
memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
303
304
nssid = n_ssids;
305
306
for (index = 0 ; index < nssid ; index++) {
307
pno_ssids_local[index].SSID_len = ssids[index].ssid_len;
308
memcpy(pno_ssids_local[index].SSID, ssids[index].ssid,
309
ssids[index].ssid_len);
310
}
311
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
312
if(ssids)
313
rtw_mfree((u8 *)ssids, (n_ssids * sizeof(struct cfg80211_ssid)));
314
#endif
315
pno_time = (interval / 1000);
316
317
RTW_INFO("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
318
319
res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
320
pno_repeat, pno_freq_expo_max);
321
322
#ifdef CONFIG_PNO_SET_DEBUG
323
rtw_dev_pno_debug(net);
324
#endif
325
exit_proc:
326
return res;
327
}
328
329
int rtw_android_pno_enable(struct net_device *net, int pno_enable)
330
{
331
_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
332
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
333
334
if (pwrctl) {
335
pwrctl->wowlan_pno_enable = pno_enable;
336
RTW_INFO("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
337
if (pwrctl->wowlan_pno_enable == 0) {
338
if (pwrctl->pnlo_info != NULL) {
339
rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
340
pwrctl->pnlo_info = NULL;
341
}
342
if (pwrctl->pno_ssid_list != NULL) {
343
rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
344
pwrctl->pno_ssid_list = NULL;
345
}
346
if (pwrctl->pscan_info != NULL) {
347
rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
348
pwrctl->pscan_info = NULL;
349
}
350
}
351
return 0;
352
} else
353
return -1;
354
}
355
#endif /* CONFIG_PNO_SUPPORT */
356
357
int rtw_android_cmdstr_to_num(char *cmdstr)
358
{
359
int cmd_num;
360
for (cmd_num = 0 ; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
361
if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])))
362
break;
363
364
return cmd_num;
365
}
366
367
int rtw_android_get_rssi(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
374
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
375
bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
376
pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
377
}
378
379
return bytes_written;
380
}
381
382
int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
383
{
384
_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
385
int bytes_written = 0;
386
u16 link_speed = 0;
387
388
link_speed = rtw_get_cur_max_rate(padapter) / 10;
389
bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
390
391
return bytes_written;
392
}
393
394
int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
395
{
396
int bytes_written = 0;
397
398
bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
399
return bytes_written;
400
}
401
402
int rtw_android_set_country(struct net_device *net, char *command, int total_len)
403
{
404
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
405
char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
406
int ret = _FAIL;
407
408
ret = rtw_set_country(adapter, country_code);
409
410
return (ret == _SUCCESS) ? 0 : -1;
411
}
412
413
int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
414
{
415
int bytes_written = 0;
416
417
/* We use the same address as our HW MAC address */
418
_rtw_memcpy(command, net->dev_addr, ETH_ALEN);
419
420
bytes_written = ETH_ALEN;
421
return bytes_written;
422
}
423
424
int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
425
{
426
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
427
char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
428
429
#ifdef CONFIG_IOCTL_CFG80211
430
adapter_wdev_data(adapter)->block_scan = (*block_value == '0') ? _FALSE : _TRUE;
431
#endif
432
433
return 0;
434
}
435
436
int rtw_android_set_block(struct net_device *net, char *command, int total_len)
437
{
438
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
439
char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
440
441
#ifdef CONFIG_IOCTL_CFG80211
442
adapter_wdev_data(adapter)->block = (*block_value == '0') ? _FALSE : _TRUE;
443
#endif
444
445
return 0;
446
}
447
448
int rtw_android_setband(struct net_device *net, char *command, int total_len)
449
{
450
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
451
char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
452
u32 band = WIFI_FREQUENCY_BAND_AUTO;
453
int ret = _FAIL;
454
455
if (sscanf(arg, "%u", &band) >= 1)
456
ret = rtw_set_band(adapter, band);
457
458
return (ret == _SUCCESS) ? 0 : -1;
459
}
460
461
int rtw_android_getband(struct net_device *net, char *command, int total_len)
462
{
463
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
464
int bytes_written = 0;
465
466
bytes_written = snprintf(command, total_len, "%u", adapter->setband);
467
468
return bytes_written;
469
}
470
471
#ifdef CONFIG_WFD
472
int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
473
{
474
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
475
struct wifi_display_info *wfd_info = &adapter->wfd_info;
476
char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
477
u8 mode;
478
int num;
479
int ret = _FAIL;
480
481
num = sscanf(arg, "%hhu", &mode);
482
483
if (num < 1)
484
goto exit;
485
486
switch (mode) {
487
case 1: /* soruce */
488
mode = MIRACAST_SOURCE;
489
break;
490
case 2: /* sink */
491
mode = MIRACAST_SINK;
492
break;
493
case 0: /* disabled */
494
default:
495
mode = MIRACAST_DISABLED;
496
break;
497
}
498
wfd_info->stack_wfd_mode = mode;
499
RTW_INFO("stack miracast mode: %s\n", get_miracast_mode_str(wfd_info->stack_wfd_mode));
500
501
ret = _SUCCESS;
502
503
exit:
504
return (ret == _SUCCESS) ? 0 : -1;
505
}
506
#endif /* CONFIG_WFD */
507
508
int get_int_from_command(char *pcmd)
509
{
510
int i = 0;
511
512
for (i = 0; i < strlen(pcmd); i++) {
513
if (pcmd[i] == '=') {
514
/* Skip the '=' and space characters. */
515
i += 2;
516
break;
517
}
518
}
519
return rtw_atoi(pcmd + i) ;
520
}
521
522
#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
523
int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
524
{
525
int i;
526
/* u8 *cmd_ptr = priv_cmd.buf; */
527
struct sta_info *psta;
528
_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
529
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
530
struct sta_priv *pstapriv = &padapter->stapriv;
531
struct security_priv *psecuritypriv = &(padapter->securitypriv);
532
psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
533
534
535
if (psta == NULL)
536
RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
537
else {
538
/* string command length of "GTK_REKEY_OFFLOAD" */
539
cmd_ptr += 18;
540
541
_rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
542
cmd_ptr += RTW_KEK_LEN;
543
/*
544
printk("supplicant KEK: ");
545
for(i=0;i<RTW_KEK_LEN; i++)
546
printk(" %02x ", psta->kek[i]);
547
printk("\n supplicant KCK: ");
548
*/
549
_rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
550
cmd_ptr += RTW_KCK_LEN;
551
/*
552
for(i=0;i<RTW_KEK_LEN; i++)
553
printk(" %02x ", psta->kck[i]);
554
*/
555
_rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
556
psecuritypriv->binstallKCK_KEK = _TRUE;
557
558
/* printk("\nREPLAY_CTR: "); */
559
/* for(i=0;i<RTW_REPLAY_CTR_LEN; i++) */
560
/* printk(" %02x ", psta->replay_ctr[i]); */
561
}
562
563
return _SUCCESS;
564
}
565
#endif /* CONFIG_GTK_OL */
566
567
#ifdef CONFIG_RTW_MESH_AEK
568
static int rtw_android_set_aek(struct net_device *ndev, char *command, int total_len)
569
{
570
#define SET_AEK_DATA_LEN (ETH_ALEN + 32)
571
572
_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
573
u8 *addr;
574
u8 *aek;
575
int err = 0;
576
577
if (total_len - strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AEK]) - 1 != SET_AEK_DATA_LEN) {
578
err = -EINVAL;
579
goto exit;
580
}
581
582
addr = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AEK]) + 1;
583
aek = addr + ETH_ALEN;
584
585
RTW_PRINT(FUNC_NDEV_FMT" addr="MAC_FMT"\n"
586
, FUNC_NDEV_ARG(ndev), MAC_ARG(addr));
587
if (0)
588
RTW_PRINT(FUNC_NDEV_FMT" aek="KEY_FMT KEY_FMT"\n"
589
, FUNC_NDEV_ARG(ndev), KEY_ARG(aek), KEY_ARG(aek + 16));
590
591
if (rtw_mesh_plink_set_aek(adapter, addr, aek) != _SUCCESS)
592
err = -ENOENT;
593
594
exit:
595
return err;
596
}
597
#endif /* CONFIG_RTW_MESH_AEK */
598
599
int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
600
{
601
#define PRIVATE_COMMAND_MAX_LEN 8192
602
int ret = 0;
603
char *command = NULL;
604
int cmd_num;
605
int bytes_written = 0;
606
#ifdef CONFIG_PNO_SUPPORT
607
uint cmdlen = 0;
608
uint pno_enable = 0;
609
#endif
610
android_wifi_priv_cmd priv_cmd;
611
_adapter *padapter = (_adapter *) rtw_netdev_priv(net);
612
#ifdef CONFIG_WFD
613
struct wifi_display_info *pwfd_info;
614
#endif
615
616
rtw_lock_suspend();
617
618
if (!ifr->ifr_data) {
619
ret = -EINVAL;
620
goto exit;
621
}
622
if (padapter->registrypriv.mp_mode == 1) {
623
ret = -EINVAL;
624
goto exit;
625
}
626
#ifdef CONFIG_COMPAT
627
#if (KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE)
628
if (is_compat_task()) {
629
#else
630
if (in_compat_syscall()) {
631
#endif
632
/* User space is 32-bit, use compat ioctl */
633
compat_android_wifi_priv_cmd compat_priv_cmd;
634
635
if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
636
ret = -EFAULT;
637
goto exit;
638
}
639
priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
640
priv_cmd.used_len = compat_priv_cmd.used_len;
641
priv_cmd.total_len = compat_priv_cmd.total_len;
642
} else
643
#endif /* CONFIG_COMPAT */
644
if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
645
ret = -EFAULT;
646
goto exit;
647
}
648
if (padapter->registrypriv.mp_mode == 1) {
649
ret = -EFAULT;
650
goto exit;
651
}
652
/*RTW_INFO("%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);*/
653
if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN || priv_cmd.total_len < 0) {
654
RTW_WARN("%s: invalid private command (%d)\n", __FUNCTION__,
655
priv_cmd.total_len);
656
ret = -EFAULT;
657
goto exit;
658
}
659
660
command = rtw_zmalloc(priv_cmd.total_len+1);
661
if (!command) {
662
RTW_INFO("%s: failed to allocate memory\n", __FUNCTION__);
663
ret = -ENOMEM;
664
goto exit;
665
}
666
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
667
if (!access_ok(priv_cmd.buf, priv_cmd.total_len)) {
668
#else
669
if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
670
#endif
671
RTW_INFO("%s: failed to access memory\n", __FUNCTION__);
672
ret = -EFAULT;
673
goto exit;
674
}
675
if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
676
ret = -EFAULT;
677
goto exit;
678
}
679
command[priv_cmd.total_len] = '\0';
680
RTW_INFO("%s: Android private cmd \"%s\" on %s\n"
681
, __FUNCTION__, command, ifr->ifr_name);
682
683
cmd_num = rtw_android_cmdstr_to_num(command);
684
685
switch (cmd_num) {
686
case ANDROID_WIFI_CMD_START:
687
/* bytes_written = wl_android_wifi_on(net); */
688
goto response;
689
case ANDROID_WIFI_CMD_SETFWPATH:
690
goto response;
691
}
692
693
if (!g_wifi_on) {
694
RTW_INFO("%s: Ignore private cmd \"%s\" - iface %s is down\n"
695
, __FUNCTION__, command, ifr->ifr_name);
696
ret = 0;
697
goto exit;
698
}
699
700
if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
701
switch (cmd_num) {
702
case ANDROID_WIFI_CMD_WFD_ENABLE:
703
case ANDROID_WIFI_CMD_WFD_DISABLE:
704
case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
705
case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
706
case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
707
goto response;
708
}
709
}
710
711
switch (cmd_num) {
712
713
case ANDROID_WIFI_CMD_STOP:
714
/* bytes_written = wl_android_wifi_off(net); */
715
break;
716
717
case ANDROID_WIFI_CMD_SCAN_ACTIVE:
718
/* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE); */
719
#ifdef CONFIG_PLATFORM_MSTAR
720
#ifdef CONFIG_IOCTL_CFG80211
721
adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = _TRUE;
722
#endif /* CONFIG_IOCTL_CFG80211 */
723
#endif /* CONFIG_PLATFORM_MSTAR */
724
break;
725
case ANDROID_WIFI_CMD_SCAN_PASSIVE:
726
/* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE); */
727
break;
728
729
case ANDROID_WIFI_CMD_RSSI:
730
bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
731
break;
732
case ANDROID_WIFI_CMD_LINKSPEED:
733
bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
734
break;
735
736
case ANDROID_WIFI_CMD_MACADDR:
737
bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
738
break;
739
740
case ANDROID_WIFI_CMD_BLOCK_SCAN:
741
bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
742
break;
743
744
case ANDROID_WIFI_CMD_BLOCK:
745
bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
746
break;
747
748
case ANDROID_WIFI_CMD_RXFILTER_START:
749
/* bytes_written = net_os_set_packet_filter(net, 1); */
750
break;
751
case ANDROID_WIFI_CMD_RXFILTER_STOP:
752
/* bytes_written = net_os_set_packet_filter(net, 0); */
753
break;
754
case ANDROID_WIFI_CMD_RXFILTER_ADD:
755
/* int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; */
756
/* bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); */
757
break;
758
case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
759
/* int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; */
760
/* bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); */
761
break;
762
763
case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
764
/* TBD: BTCOEXSCAN-START */
765
break;
766
case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
767
/* TBD: BTCOEXSCAN-STOP */
768
break;
769
case ANDROID_WIFI_CMD_BTCOEXMODE:
770
#if 0
771
uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
772
if (mode == 1)
773
net_os_set_packet_filter(net, 0); /* DHCP starts */
774
else
775
net_os_set_packet_filter(net, 1); /* DHCP ends */
776
#ifdef WL_CFG80211
777
bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
778
#endif
779
#endif
780
break;
781
782
case ANDROID_WIFI_CMD_SETSUSPENDMODE:
783
break;
784
785
case ANDROID_WIFI_CMD_SETSUSPENDOPT:
786
/* bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); */
787
break;
788
789
case ANDROID_WIFI_CMD_SETBAND:
790
bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
791
break;
792
793
case ANDROID_WIFI_CMD_GETBAND:
794
bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
795
break;
796
797
case ANDROID_WIFI_CMD_COUNTRY:
798
bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
799
break;
800
801
#ifdef CONFIG_PNO_SUPPORT
802
case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
803
/* bytes_written = dhd_dev_pno_reset(net); */
804
break;
805
case ANDROID_WIFI_CMD_PNOSETUP_SET:
806
bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
807
break;
808
case ANDROID_WIFI_CMD_PNOENABLE_SET:
809
cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
810
pno_enable = *(command + cmdlen + 1) - '0';
811
bytes_written = rtw_android_pno_enable(net, pno_enable);
812
break;
813
#endif
814
815
case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
816
bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
817
break;
818
case ANDROID_WIFI_CMD_P2P_SET_NOA:
819
/* int skip = strlen(CMD_P2P_SET_NOA) + 1; */
820
/* bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); */
821
break;
822
case ANDROID_WIFI_CMD_P2P_GET_NOA:
823
/* bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); */
824
break;
825
case ANDROID_WIFI_CMD_P2P_SET_PS:
826
/* int skip = strlen(CMD_P2P_SET_PS) + 1; */
827
/* bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); */
828
break;
829
830
#ifdef CONFIG_IOCTL_CFG80211
831
case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE: {
832
int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
833
bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
834
break;
835
}
836
#endif /* CONFIG_IOCTL_CFG80211 */
837
838
#ifdef CONFIG_WFD
839
840
case ANDROID_WIFI_CMD_MIRACAST:
841
bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
842
break;
843
844
case ANDROID_WIFI_CMD_WFD_ENABLE: {
845
/* Commented by Albert 2012/07/24 */
846
/* We can enable the WFD function by using the following command: */
847
/* wpa_cli driver wfd-enable */
848
849
if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
850
rtw_wfd_enable(padapter, 1);
851
break;
852
}
853
854
case ANDROID_WIFI_CMD_WFD_DISABLE: {
855
/* Commented by Albert 2012/07/24 */
856
/* We can disable the WFD function by using the following command: */
857
/* wpa_cli driver wfd-disable */
858
859
if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
860
rtw_wfd_enable(padapter, 0);
861
break;
862
}
863
case ANDROID_WIFI_CMD_WFD_SET_TCPPORT: {
864
/* Commented by Albert 2012/07/24 */
865
/* We can set the tcp port number by using the following command: */
866
/* wpa_cli driver wfd-set-tcpport = 554 */
867
868
if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
869
rtw_wfd_set_ctrl_port(padapter, (u16)get_int_from_command(command));
870
break;
871
}
872
case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT: {
873
break;
874
}
875
case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE: {
876
/* Commented by Albert 2012/08/28 */
877
/* Specify the WFD device type ( WFD source/primary sink ) */
878
879
pwfd_info = &padapter->wfd_info;
880
if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
881
pwfd_info->wfd_device_type = (u8) get_int_from_command(command);
882
pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
883
}
884
break;
885
}
886
#endif
887
case ANDROID_WIFI_CMD_CHANGE_DTIM: {
888
#ifdef CONFIG_LPS
889
u8 dtim;
890
u8 *ptr = (u8 *) command;
891
892
ptr += 9;/* string command length of "SET_DTIM"; */
893
894
dtim = rtw_atoi(ptr);
895
896
RTW_INFO("DTIM=%d\n", dtim);
897
898
rtw_lps_change_dtim_cmd(padapter, dtim);
899
#endif
900
}
901
break;
902
903
#if CONFIG_RTW_MACADDR_ACL
904
case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL: {
905
rtw_set_macaddr_acl(padapter, RTW_ACL_PERIOD_BSS, get_int_from_command(command));
906
break;
907
}
908
case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA: {
909
u8 addr[ETH_ALEN] = {0x00};
910
macstr2num(addr, command + strlen("HOSTAPD_ACL_ADD_STA") + 3); /* 3 is space bar + "=" + space bar these 3 chars */
911
rtw_acl_add_sta(padapter, RTW_ACL_PERIOD_BSS, addr);
912
break;
913
}
914
case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA: {
915
u8 addr[ETH_ALEN] = {0x00};
916
macstr2num(addr, command + strlen("HOSTAPD_ACL_REMOVE_STA") + 3); /* 3 is space bar + "=" + space bar these 3 chars */
917
rtw_acl_remove_sta(padapter, RTW_ACL_PERIOD_BSS, addr);
918
break;
919
}
920
#endif /* CONFIG_RTW_MACADDR_ACL */
921
#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
922
case ANDROID_WIFI_CMD_GTK_REKEY_OFFLOAD:
923
rtw_gtk_offload(net, (u8 *)command);
924
break;
925
#endif /* CONFIG_GTK_OL */
926
case ANDROID_WIFI_CMD_P2P_DISABLE: {
927
#ifdef CONFIG_P2P
928
rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
929
#endif /* CONFIG_P2P */
930
break;
931
}
932
933
#ifdef CONFIG_RTW_MESH_AEK
934
case ANDROID_WIFI_CMD_SET_AEK:
935
bytes_written = rtw_android_set_aek(net, command, priv_cmd.total_len);
936
break;
937
#endif
938
939
case ANDROID_WIFI_CMD_EXT_AUTH_STATUS: {
940
rtw_set_external_auth_status(padapter,
941
command + strlen("EXT_AUTH_STATUS "),
942
priv_cmd.total_len - strlen("EXT_AUTH_STATUS "));
943
break;
944
}
945
case ANDROID_WIFI_CMD_DRIVERVERSION: {
946
bytes_written = strlen(DRIVERVERSION);
947
snprintf(command, bytes_written + 1, DRIVERVERSION);
948
break;
949
}
950
default:
951
RTW_INFO("Unknown PRIVATE command %s - ignored\n", command);
952
snprintf(command, 3, "OK");
953
bytes_written = strlen("OK");
954
}
955
956
response:
957
if (bytes_written >= 0) {
958
if ((bytes_written == 0) && (priv_cmd.total_len > 0))
959
command[0] = '\0';
960
if (bytes_written >= priv_cmd.total_len) {
961
RTW_INFO("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
962
bytes_written = priv_cmd.total_len;
963
} else
964
bytes_written++;
965
priv_cmd.used_len = bytes_written;
966
if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
967
RTW_INFO("%s: failed to copy data to user buffer\n", __FUNCTION__);
968
ret = -EFAULT;
969
}
970
} else
971
ret = bytes_written;
972
973
exit:
974
rtw_unlock_suspend();
975
if (command)
976
rtw_mfree(command, priv_cmd.total_len + 1);
977
978
return ret;
979
}
980
981
982
/**
983
* Functions for Android WiFi card detection
984
*/
985
#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
986
987
static int g_wifidev_registered = 0;
988
static struct semaphore wifi_control_sem;
989
static struct wifi_platform_data *wifi_control_data = NULL;
990
static struct resource *wifi_irqres = NULL;
991
992
static int wifi_add_dev(void);
993
static void wifi_del_dev(void);
994
995
int rtw_android_wifictrl_func_add(void)
996
{
997
int ret = 0;
998
sema_init(&wifi_control_sem, 0);
999
1000
ret = wifi_add_dev();
1001
if (ret) {
1002
RTW_INFO("%s: platform_driver_register failed\n", __FUNCTION__);
1003
return ret;
1004
}
1005
g_wifidev_registered = 1;
1006
1007
/* Waiting callback after platform_driver_register is done or exit with error */
1008
if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
1009
ret = -EINVAL;
1010
RTW_INFO("%s: platform_driver_register timeout\n", __FUNCTION__);
1011
}
1012
1013
return ret;
1014
}
1015
1016
void rtw_android_wifictrl_func_del(void)
1017
{
1018
if (g_wifidev_registered) {
1019
wifi_del_dev();
1020
g_wifidev_registered = 0;
1021
}
1022
}
1023
1024
void *wl_android_prealloc(int section, unsigned long size)
1025
{
1026
void *alloc_ptr = NULL;
1027
if (wifi_control_data && wifi_control_data->mem_prealloc) {
1028
alloc_ptr = wifi_control_data->mem_prealloc(section, size);
1029
if (alloc_ptr) {
1030
RTW_INFO("success alloc section %d\n", section);
1031
if (size != 0L)
1032
memset(alloc_ptr, 0, size);
1033
return alloc_ptr;
1034
}
1035
}
1036
1037
RTW_INFO("can't alloc section %d\n", section);
1038
return NULL;
1039
}
1040
1041
int wifi_get_irq_number(unsigned long *irq_flags_ptr)
1042
{
1043
if (wifi_irqres) {
1044
*irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
1045
return (int)wifi_irqres->start;
1046
}
1047
#ifdef CUSTOM_OOB_GPIO_NUM
1048
return CUSTOM_OOB_GPIO_NUM;
1049
#else
1050
return -1;
1051
#endif
1052
}
1053
1054
int wifi_set_power(int on, unsigned long msec)
1055
{
1056
RTW_INFO("%s = %d\n", __FUNCTION__, on);
1057
if (wifi_control_data && wifi_control_data->set_power)
1058
wifi_control_data->set_power(on);
1059
if (msec)
1060
msleep(msec);
1061
return 0;
1062
}
1063
1064
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
1065
int wifi_get_mac_addr(unsigned char *buf)
1066
{
1067
RTW_INFO("%s\n", __FUNCTION__);
1068
if (!buf)
1069
return -EINVAL;
1070
if (wifi_control_data && wifi_control_data->get_mac_addr)
1071
return wifi_control_data->get_mac_addr(buf);
1072
return -EOPNOTSUPP;
1073
}
1074
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
1075
1076
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
1077
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
1078
void *wifi_get_country_code(char *ccode, u32 flags)
1079
#else /* Linux kernel < 3.18 */
1080
void *wifi_get_country_code(char *ccode)
1081
#endif /* Linux kernel < 3.18 */
1082
{
1083
RTW_INFO("%s\n", __FUNCTION__);
1084
if (!ccode)
1085
return NULL;
1086
if (wifi_control_data && wifi_control_data->get_country_code)
1087
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
1088
return wifi_control_data->get_country_code(ccode, flags);
1089
#else /* Linux kernel < 3.18 */
1090
return wifi_control_data->get_country_code(ccode);
1091
#endif /* Linux kernel < 3.18 */
1092
return NULL;
1093
}
1094
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
1095
1096
static int wifi_set_carddetect(int on)
1097
{
1098
RTW_INFO("%s = %d\n", __FUNCTION__, on);
1099
if (wifi_control_data && wifi_control_data->set_carddetect)
1100
wifi_control_data->set_carddetect(on);
1101
return 0;
1102
}
1103
1104
static int wifi_probe(struct platform_device *pdev)
1105
{
1106
struct wifi_platform_data *wifi_ctrl =
1107
(struct wifi_platform_data *)(pdev->dev.platform_data);
1108
int wifi_wake_gpio = 0;
1109
1110
RTW_INFO("## %s\n", __FUNCTION__);
1111
wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
1112
1113
if (wifi_irqres == NULL)
1114
wifi_irqres = platform_get_resource_byname(pdev,
1115
IORESOURCE_IRQ, "bcm4329_wlan_irq");
1116
else
1117
wifi_wake_gpio = wifi_irqres->start;
1118
1119
#ifdef CONFIG_GPIO_WAKEUP
1120
RTW_INFO("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
1121
(int)wifi_irqres->start, wifi_wake_gpio);
1122
1123
if (wifi_wake_gpio > 0) {
1124
#ifdef CONFIG_PLATFORM_INTEL_BYT
1125
wifi_configure_gpio();
1126
#else /* CONFIG_PLATFORM_INTEL_BYT */
1127
gpio_request(wifi_wake_gpio, "oob_irq");
1128
gpio_direction_input(wifi_wake_gpio);
1129
oob_irq = gpio_to_irq(wifi_wake_gpio);
1130
#endif /* CONFIG_PLATFORM_INTEL_BYT */
1131
RTW_INFO("%s oob_irq:%d\n", __func__, oob_irq);
1132
} else if (wifi_irqres) {
1133
oob_irq = wifi_irqres->start;
1134
RTW_INFO("%s oob_irq:%d\n", __func__, oob_irq);
1135
}
1136
#endif
1137
wifi_control_data = wifi_ctrl;
1138
1139
wifi_set_power(1, 0); /* Power On */
1140
wifi_set_carddetect(1); /* CardDetect (0->1) */
1141
1142
up(&wifi_control_sem);
1143
return 0;
1144
}
1145
1146
#ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1147
extern PADAPTER g_test_adapter;
1148
1149
static void shutdown_card(void)
1150
{
1151
u32 addr;
1152
u8 tmp8, cnt = 0;
1153
1154
if (NULL == g_test_adapter) {
1155
RTW_INFO("%s: padapter==NULL\n", __FUNCTION__);
1156
return;
1157
}
1158
1159
#ifdef CONFIG_FWLPS_IN_IPS
1160
LeaveAllPowerSaveMode(g_test_adapter);
1161
#endif /* CONFIG_FWLPS_IN_IPS */
1162
1163
#ifdef CONFIG_WOWLAN
1164
#ifdef CONFIG_GPIO_WAKEUP
1165
/*default wake up pin change to BT*/
1166
RTW_INFO("%s:default wake up pin change to BT\n", __FUNCTION__);
1167
rtw_hal_switch_gpio_wl_ctrl(g_test_adapter, WAKEUP_GPIO_IDX, _FALSE);
1168
#endif /* CONFIG_GPIO_WAKEUP */
1169
#endif /* CONFIG_WOWLAN */
1170
1171
/* Leave SDIO HCI Suspend */
1172
addr = 0x10250086;
1173
rtw_write8(g_test_adapter, addr, 0);
1174
do {
1175
tmp8 = rtw_read8(g_test_adapter, addr);
1176
cnt++;
1177
RTW_INFO(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n",
1178
FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt);
1179
1180
if (tmp8 & BIT(1))
1181
break;
1182
1183
if (cnt >= 100) {
1184
RTW_INFO(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
1185
FUNC_ADPT_ARG(g_test_adapter), addr);
1186
break;
1187
}
1188
1189
rtw_mdelay_os(10);
1190
} while (1);
1191
1192
/* unlock register I/O */
1193
rtw_write8(g_test_adapter, 0x1C, 0);
1194
1195
/* enable power down function */
1196
/* 0x04[4] = 1 */
1197
/* 0x05[7] = 1 */
1198
addr = 0x04;
1199
tmp8 = rtw_read8(g_test_adapter, addr);
1200
tmp8 |= BIT(4);
1201
rtw_write8(g_test_adapter, addr, tmp8);
1202
RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1203
FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1204
1205
addr = 0x05;
1206
tmp8 = rtw_read8(g_test_adapter, addr);
1207
tmp8 |= BIT(7);
1208
rtw_write8(g_test_adapter, addr, tmp8);
1209
RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
1210
FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
1211
1212
/* lock register page0 0x0~0xB read/write */
1213
rtw_write8(g_test_adapter, 0x1C, 0x0E);
1214
1215
rtw_set_surprise_removed(g_test_adapter);
1216
RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=%s\n",
1217
FUNC_ADPT_ARG(g_test_adapter), rtw_is_surprise_removed(g_test_adapter) ? "True" : "False");
1218
}
1219
#endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1220
1221
static int wifi_remove(struct platform_device *pdev)
1222
{
1223
struct wifi_platform_data *wifi_ctrl =
1224
(struct wifi_platform_data *)(pdev->dev.platform_data);
1225
1226
RTW_INFO("## %s\n", __FUNCTION__);
1227
wifi_control_data = wifi_ctrl;
1228
1229
wifi_set_power(0, 0); /* Power Off */
1230
wifi_set_carddetect(0); /* CardDetect (1->0) */
1231
1232
up(&wifi_control_sem);
1233
return 0;
1234
}
1235
1236
#ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1237
static void wifi_shutdown(struct platform_device *pdev)
1238
{
1239
struct wifi_platform_data *wifi_ctrl =
1240
(struct wifi_platform_data *)(pdev->dev.platform_data);
1241
1242
1243
RTW_INFO("## %s\n", __FUNCTION__);
1244
1245
wifi_control_data = wifi_ctrl;
1246
1247
shutdown_card();
1248
wifi_set_power(0, 0); /* Power Off */
1249
wifi_set_carddetect(0); /* CardDetect (1->0) */
1250
}
1251
#endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1252
1253
static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
1254
{
1255
RTW_INFO("##> %s\n", __FUNCTION__);
1256
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1257
bcmsdh_oob_intr_set(0);
1258
#endif
1259
return 0;
1260
}
1261
1262
static int wifi_resume(struct platform_device *pdev)
1263
{
1264
RTW_INFO("##> %s\n", __FUNCTION__);
1265
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
1266
if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
1267
bcmsdh_oob_intr_set(1);
1268
#endif
1269
return 0;
1270
}
1271
1272
/* temporarily use these two */
1273
static struct platform_driver wifi_device = {
1274
.probe = wifi_probe,
1275
.remove = wifi_remove,
1276
.suspend = wifi_suspend,
1277
.resume = wifi_resume,
1278
#ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
1279
.shutdown = wifi_shutdown,
1280
#endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
1281
.driver = {
1282
.name = "bcmdhd_wlan",
1283
}
1284
};
1285
1286
static struct platform_driver wifi_device_legacy = {
1287
.probe = wifi_probe,
1288
.remove = wifi_remove,
1289
.suspend = wifi_suspend,
1290
.resume = wifi_resume,
1291
.driver = {
1292
.name = "bcm4329_wlan",
1293
}
1294
};
1295
1296
static int wifi_add_dev(void)
1297
{
1298
RTW_INFO("## Calling platform_driver_register\n");
1299
platform_driver_register(&wifi_device);
1300
platform_driver_register(&wifi_device_legacy);
1301
return 0;
1302
}
1303
1304
static void wifi_del_dev(void)
1305
{
1306
RTW_INFO("## Unregister platform_driver_register\n");
1307
platform_driver_unregister(&wifi_device);
1308
platform_driver_unregister(&wifi_device_legacy);
1309
}
1310
#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
1311
1312
#ifdef CONFIG_GPIO_WAKEUP
1313
#ifdef CONFIG_PLATFORM_INTEL_BYT
1314
int wifi_configure_gpio(void)
1315
{
1316
if (gpio_request(oob_gpio, "oob_irq")) {
1317
RTW_INFO("## %s Cannot request GPIO\n", __FUNCTION__);
1318
return -1;
1319
}
1320
gpio_export(oob_gpio, 0);
1321
if (gpio_direction_input(oob_gpio)) {
1322
RTW_INFO("## %s Cannot set GPIO direction input\n", __FUNCTION__);
1323
return -1;
1324
}
1325
oob_irq = gpio_to_irq(oob_gpio);
1326
if (oob_irq < 0) {
1327
RTW_INFO("## %s Cannot convert GPIO to IRQ\n", __FUNCTION__);
1328
return -1;
1329
}
1330
1331
RTW_INFO("## %s OOB_IRQ=%d\n", __FUNCTION__, oob_irq);
1332
1333
return 0;
1334
}
1335
#endif /* CONFIG_PLATFORM_INTEL_BYT */
1336
void wifi_free_gpio(unsigned int gpio)
1337
{
1338
#ifdef CONFIG_PLATFORM_INTEL_BYT
1339
if (gpio)
1340
gpio_free(gpio);
1341
#endif /* CONFIG_PLATFORM_INTEL_BYT */
1342
}
1343
#endif /* CONFIG_GPIO_WAKEUP */
1344
1345