Merge branch 'core/speculation' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / drivers / staging / rtl8188eu / os_dep / rtw_android.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10
11 #include <rtw_android.h>
12 #include <osdep_service.h>
13 #include <rtw_debug.h>
14 #include <rtw_ioctl_set.h>
15
16 static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
17         "START",
18         "STOP",
19         "SCAN-ACTIVE",
20         "SCAN-PASSIVE",
21         "RSSI",
22         "LINKSPEED",
23         "RXFILTER-START",
24         "RXFILTER-STOP",
25         "RXFILTER-ADD",
26         "RXFILTER-REMOVE",
27         "BTCOEXSCAN-START",
28         "BTCOEXSCAN-STOP",
29         "BTCOEXMODE",
30         "SETSUSPENDOPT",
31         "P2P_DEV_ADDR",
32         "SETFWPATH",
33         "SETBAND",
34         "GETBAND",
35         "COUNTRY",
36         "P2P_SET_NOA",
37         "P2P_GET_NOA",
38         "P2P_SET_PS",
39         "SET_AP_WPS_P2P_IE",
40         "MACADDR",
41         "BLOCK",
42         "WFD-ENABLE",
43         "WFD-DISABLE",
44         "WFD-SET-TCPPORT",
45         "WFD-SET-MAXTPUT",
46         "WFD-SET-DEVTYPE",
47 };
48
49 struct android_wifi_priv_cmd {
50         const char __user *buf;
51         int used_len;
52         int total_len;
53 };
54
55 /**
56  * Local (static) functions and variables
57  */
58
59 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
60  * time (only) in dhd_open, subsequential wifi on will be handled by
61  * wl_android_wifi_on
62  */
63 static int g_wifi_on = true;
64
65 int rtw_android_cmdstr_to_num(char *cmdstr)
66 {
67         int cmd_num;
68
69         for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
70                 if (0 == strncasecmp(cmdstr, android_wifi_cmd_str[cmd_num],
71                                   strlen(android_wifi_cmd_str[cmd_num])))
72                         break;
73         return cmd_num;
74 }
75
76 static int rtw_android_get_rssi(struct net_device *net, char *command,
77                                 int total_len)
78 {
79         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
80         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
81         struct  wlan_network    *pcur_network = &pmlmepriv->cur_network;
82         int bytes_written = 0;
83
84         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
85                 bytes_written += snprintf(&command[bytes_written], total_len,
86                                           "%s rssi %d",
87                                           pcur_network->network.ssid.ssid,
88                                           padapter->recvpriv.rssi);
89         }
90         return bytes_written;
91 }
92
93 static int rtw_android_get_link_speed(struct net_device *net, char *command,
94                                       int total_len)
95 {
96         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
97         u16 link_speed;
98
99         link_speed = rtw_get_cur_max_rate(padapter) / 10;
100         return snprintf(command, total_len, "LinkSpeed %d",
101                                  link_speed);
102 }
103
104 static int rtw_android_get_macaddr(struct net_device *net, char *command,
105                                    int total_len)
106 {
107         return snprintf(command, total_len, "Macaddr = %pM",
108                                  net->dev_addr);
109 }
110
111 static int android_set_cntry(struct net_device *net, char *command,
112                              int total_len)
113 {
114         struct adapter *adapter = (struct adapter *)rtw_netdev_priv(net);
115         char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
116         int ret;
117
118         ret = rtw_set_country(adapter, country_code);
119         return (ret == _SUCCESS) ? 0 : -1;
120 }
121
122 static int android_get_p2p_addr(struct net_device *net, char *command,
123                                         int total_len)
124 {
125         /* We use the same address as our HW MAC address */
126         memcpy(command, net->dev_addr, ETH_ALEN);
127         return ETH_ALEN;
128 }
129
130 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
131 {
132         int ret = 0;
133         char *command;
134         int cmd_num;
135         int bytes_written = 0;
136         struct android_wifi_priv_cmd priv_cmd;
137
138         if (!ifr->ifr_data)
139                 return -EINVAL;
140         if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(priv_cmd)))
141                 return -EFAULT;
142         if (priv_cmd.total_len < 1)
143                 return -EINVAL;
144         command = memdup_user(priv_cmd.buf, priv_cmd.total_len);
145         if (IS_ERR(command))
146                 return PTR_ERR(command);
147         command[priv_cmd.total_len - 1] = 0;
148         DBG_88E("%s: Android private cmd \"%s\" on %s\n",
149                 __func__, command, ifr->ifr_name);
150         cmd_num = rtw_android_cmdstr_to_num(command);
151         switch (cmd_num) {
152         case ANDROID_WIFI_CMD_START:
153                 goto response;
154         case ANDROID_WIFI_CMD_SETFWPATH:
155                 goto response;
156         }
157         if (!g_wifi_on) {
158                 DBG_88E("%s: Ignore private cmd \"%s\" - iface %s is down\n",
159                         __func__, command, ifr->ifr_name);
160                 ret = 0;
161                 goto free;
162         }
163         switch (cmd_num) {
164         case ANDROID_WIFI_CMD_STOP:
165                 break;
166         case ANDROID_WIFI_CMD_SCAN_ACTIVE:
167                 break;
168         case ANDROID_WIFI_CMD_SCAN_PASSIVE:
169                 break;
170         case ANDROID_WIFI_CMD_RSSI:
171                 bytes_written = rtw_android_get_rssi(net, command,
172                                                      priv_cmd.total_len);
173                 break;
174         case ANDROID_WIFI_CMD_LINKSPEED:
175                 bytes_written = rtw_android_get_link_speed(net, command,
176                                                            priv_cmd.total_len);
177                 break;
178         case ANDROID_WIFI_CMD_MACADDR:
179                 bytes_written = rtw_android_get_macaddr(net, command,
180                                                         priv_cmd.total_len);
181                 break;
182         case ANDROID_WIFI_CMD_BLOCK:
183                 break;
184         case ANDROID_WIFI_CMD_RXFILTER_START:
185                 break;
186         case ANDROID_WIFI_CMD_RXFILTER_STOP:
187                 break;
188         case ANDROID_WIFI_CMD_RXFILTER_ADD:
189                 break;
190         case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
191                 break;
192         case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
193                 /* TBD: BTCOEXSCAN-START */
194                 break;
195         case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
196                 /* TBD: BTCOEXSCAN-STOP */
197                 break;
198         case ANDROID_WIFI_CMD_BTCOEXMODE:
199                 break;
200         case ANDROID_WIFI_CMD_SETSUSPENDOPT:
201                 break;
202         case ANDROID_WIFI_CMD_SETBAND:
203                 break;
204         case ANDROID_WIFI_CMD_GETBAND:
205                 break;
206         case ANDROID_WIFI_CMD_COUNTRY:
207                 bytes_written = android_set_cntry(net, command,
208                                                   priv_cmd.total_len);
209                 break;
210         case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
211                 bytes_written = android_get_p2p_addr(net, command,
212                                                      priv_cmd.total_len);
213                 break;
214         case ANDROID_WIFI_CMD_P2P_SET_NOA:
215                 break;
216         case ANDROID_WIFI_CMD_P2P_GET_NOA:
217                 break;
218         case ANDROID_WIFI_CMD_P2P_SET_PS:
219                 break;
220         default:
221                 DBG_88E("Unknown PRIVATE command %s - ignored\n", command);
222                 snprintf(command, 3, "OK");
223                 bytes_written = strlen("OK");
224         }
225
226 response:
227         if (bytes_written >= 0) {
228                 if ((bytes_written == 0) && (priv_cmd.total_len > 0))
229                         command[0] = '\0';
230                 if (bytes_written >= priv_cmd.total_len) {
231                         DBG_88E("%s: bytes_written = %d\n", __func__,
232                                 bytes_written);
233                         bytes_written = priv_cmd.total_len;
234                 } else {
235                         bytes_written++;
236                 }
237                 priv_cmd.used_len = bytes_written;
238                 if (copy_to_user((char __user *)priv_cmd.buf, command,
239                                  bytes_written)) {
240                         DBG_88E("%s: failed to copy data to user buffer\n",
241                                 __func__);
242                         ret = -EFAULT;
243                 }
244         } else {
245                 ret = bytes_written;
246         }
247 free:
248         kfree(command);
249         return ret;
250 }