GNU Linux-libre 4.19.245-gnu1
[releases.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 static int rtw_android_set_block(struct net_device *net, char *command,
131                                  int total_len)
132 {
133         return 0;
134 }
135
136 int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
137 {
138         int ret = 0;
139         char *command;
140         int cmd_num;
141         int bytes_written = 0;
142         struct android_wifi_priv_cmd priv_cmd;
143
144         if (!ifr->ifr_data)
145                 return -EINVAL;
146         if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(priv_cmd)))
147                 return -EFAULT;
148         if (priv_cmd.total_len < 1)
149                 return -EINVAL;
150         command = memdup_user(priv_cmd.buf, priv_cmd.total_len);
151         if (IS_ERR(command))
152                 return PTR_ERR(command);
153         command[priv_cmd.total_len - 1] = 0;
154         DBG_88E("%s: Android private cmd \"%s\" on %s\n",
155                 __func__, command, ifr->ifr_name);
156         cmd_num = rtw_android_cmdstr_to_num(command);
157         switch (cmd_num) {
158         case ANDROID_WIFI_CMD_START:
159                 goto response;
160         case ANDROID_WIFI_CMD_SETFWPATH:
161                 goto response;
162         }
163         if (!g_wifi_on) {
164                 DBG_88E("%s: Ignore private cmd \"%s\" - iface %s is down\n",
165                         __func__, command, ifr->ifr_name);
166                 ret = 0;
167                 goto free;
168         }
169         switch (cmd_num) {
170         case ANDROID_WIFI_CMD_STOP:
171                 break;
172         case ANDROID_WIFI_CMD_SCAN_ACTIVE:
173                 break;
174         case ANDROID_WIFI_CMD_SCAN_PASSIVE:
175                 break;
176         case ANDROID_WIFI_CMD_RSSI:
177                 bytes_written = rtw_android_get_rssi(net, command,
178                                                      priv_cmd.total_len);
179                 break;
180         case ANDROID_WIFI_CMD_LINKSPEED:
181                 bytes_written = rtw_android_get_link_speed(net, command,
182                                                            priv_cmd.total_len);
183                 break;
184         case ANDROID_WIFI_CMD_MACADDR:
185                 bytes_written = rtw_android_get_macaddr(net, command,
186                                                         priv_cmd.total_len);
187                 break;
188         case ANDROID_WIFI_CMD_BLOCK:
189                 bytes_written = rtw_android_set_block(net, command,
190                                                       priv_cmd.total_len);
191                 break;
192         case ANDROID_WIFI_CMD_RXFILTER_START:
193                 break;
194         case ANDROID_WIFI_CMD_RXFILTER_STOP:
195                 break;
196         case ANDROID_WIFI_CMD_RXFILTER_ADD:
197                 break;
198         case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
199                 break;
200         case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
201                 /* TBD: BTCOEXSCAN-START */
202                 break;
203         case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
204                 /* TBD: BTCOEXSCAN-STOP */
205                 break;
206         case ANDROID_WIFI_CMD_BTCOEXMODE:
207                 break;
208         case ANDROID_WIFI_CMD_SETSUSPENDOPT:
209                 break;
210         case ANDROID_WIFI_CMD_SETBAND:
211                 break;
212         case ANDROID_WIFI_CMD_GETBAND:
213                 break;
214         case ANDROID_WIFI_CMD_COUNTRY:
215                 bytes_written = android_set_cntry(net, command,
216                                                   priv_cmd.total_len);
217                 break;
218         case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
219                 bytes_written = android_get_p2p_addr(net, command,
220                                                      priv_cmd.total_len);
221                 break;
222         case ANDROID_WIFI_CMD_P2P_SET_NOA:
223                 break;
224         case ANDROID_WIFI_CMD_P2P_GET_NOA:
225                 break;
226         case ANDROID_WIFI_CMD_P2P_SET_PS:
227                 break;
228         default:
229                 DBG_88E("Unknown PRIVATE command %s - ignored\n", command);
230                 snprintf(command, 3, "OK");
231                 bytes_written = strlen("OK");
232         }
233
234 response:
235         if (bytes_written >= 0) {
236                 if ((bytes_written == 0) && (priv_cmd.total_len > 0))
237                         command[0] = '\0';
238                 if (bytes_written >= priv_cmd.total_len) {
239                         DBG_88E("%s: bytes_written = %d\n", __func__,
240                                 bytes_written);
241                         bytes_written = priv_cmd.total_len;
242                 } else {
243                         bytes_written++;
244                 }
245                 priv_cmd.used_len = bytes_written;
246                 if (copy_to_user((char __user *)priv_cmd.buf, command,
247                                  bytes_written)) {
248                         DBG_88E("%s: failed to copy data to user buffer\n",
249                                 __func__);
250                         ret = -EFAULT;
251                 }
252         } else {
253                 ret = bytes_written;
254         }
255 free:
256         kfree(command);
257         return ret;
258 }