1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <errno.h>
18
19 #include "common.h"
20 #include "roamcommand.h"
21
RoamCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)22 RoamCommand::RoamCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
23 : WifiVendorCommand(handle, id, vendor_id, subcmd)
24 {
25 }
26
~RoamCommand()27 RoamCommand::~RoamCommand()
28 {
29 }
30
31 /* This function implements creation of Vendor command */
create()32 wifi_error RoamCommand::create() {
33 wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
34 if (ret != WIFI_SUCCESS)
35 return ret;
36
37 /* Insert the oui in the msg */
38 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
39 if (ret != WIFI_SUCCESS)
40 return ret;
41 /* Insert the subcmd in the msg */
42 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
43 if (ret != WIFI_SUCCESS)
44 return ret;
45
46 ALOGV("%s: mVendor_id = %d, Subcmd = %d.",
47 __FUNCTION__, mVendor_id, mSubcmd);
48 return ret;
49 }
50
requestResponse()51 wifi_error RoamCommand::requestResponse()
52 {
53 return WifiCommand::requestResponse(mMsg);
54 }
55
wifi_set_bssid_blacklist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_params params)56 wifi_error wifi_set_bssid_blacklist(wifi_request_id id,
57 wifi_interface_handle iface,
58 wifi_bssid_params params)
59 {
60 wifi_error ret;
61 int i;
62 RoamCommand *roamCommand;
63 struct nlattr *nlData, *nlBssids;
64 interface_info *ifaceInfo = getIfaceInfo(iface);
65 wifi_handle wifiHandle = getWifiHandle(iface);
66 hal_info *info = getHalInfo(wifiHandle);
67
68 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
69 ALOGE("%s: GSCAN is not supported by driver",
70 __FUNCTION__);
71 return WIFI_ERROR_NOT_SUPPORTED;
72 }
73
74 for (i = 0; i < params.num_bssid; i++) {
75 ALOGV("BSSID: %d : %02x:%02x:%02x:%02x:%02x:%02x", i,
76 params.bssids[i][0], params.bssids[i][1],
77 params.bssids[i][2], params.bssids[i][3],
78 params.bssids[i][4], params.bssids[i][5]);
79 }
80
81 roamCommand =
82 new RoamCommand(wifiHandle,
83 id,
84 OUI_QCA,
85 QCA_NL80211_VENDOR_SUBCMD_ROAM);
86 if (roamCommand == NULL) {
87 ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
88 return WIFI_ERROR_UNKNOWN;
89 }
90
91 /* Create the NL message. */
92 ret = roamCommand->create();
93 if (ret != WIFI_SUCCESS)
94 goto cleanup;
95
96 /* Set the interface Id of the message. */
97 ret = roamCommand->set_iface_id(ifaceInfo->name);
98 if (ret != WIFI_SUCCESS)
99 goto cleanup;
100
101 /* Add the vendor specific attributes for the NL command. */
102 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
103 if (!nlData)
104 goto cleanup;
105
106 ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
107 QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID);
108 if (ret != WIFI_SUCCESS)
109 goto cleanup;
110
111 ret = roamCommand->put_u32( QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID, id);
112 if (ret != WIFI_SUCCESS)
113 goto cleanup;
114
115 ret = roamCommand->put_u32(
116 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID,
117 params.num_bssid);
118 if (ret != WIFI_SUCCESS)
119 goto cleanup;
120
121 nlBssids = roamCommand->attr_start(
122 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS);
123 for (i = 0; i < params.num_bssid; i++) {
124 struct nlattr *nl_ssid = roamCommand->attr_start(i);
125
126 ret = roamCommand->put_addr(
127 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID,
128 (u8 *)params.bssids[i]);
129 if (ret != WIFI_SUCCESS)
130 goto cleanup;
131
132 roamCommand->attr_end(nl_ssid);
133 }
134 roamCommand->attr_end(nlBssids);
135
136 roamCommand->attr_end(nlData);
137
138 ret = roamCommand->requestResponse();
139 if (ret != WIFI_SUCCESS)
140 ALOGE("wifi_set_bssid_blacklist(): requestResponse Error:%d", ret);
141
142 cleanup:
143 delete roamCommand;
144 return ret;
145
146 }
147
wifi_set_ssid_white_list(wifi_request_id id,wifi_interface_handle iface,int num_networks,ssid_t * ssid_list)148 wifi_error wifi_set_ssid_white_list(wifi_request_id id, wifi_interface_handle iface,
149 int num_networks, ssid_t *ssid_list)
150 {
151 wifi_error ret;
152 int i;
153 RoamCommand *roamCommand;
154 struct nlattr *nlData, *nlSsids;
155 interface_info *ifaceInfo = getIfaceInfo(iface);
156 wifi_handle wifiHandle = getWifiHandle(iface);
157 char ssid[MAX_SSID_LENGTH + 1];
158
159 ALOGV("%s: Number of SSIDs : %d", __FUNCTION__, num_networks);
160
161 roamCommand = new RoamCommand(
162 wifiHandle,
163 id,
164 OUI_QCA,
165 QCA_NL80211_VENDOR_SUBCMD_ROAM);
166 if (roamCommand == NULL) {
167 ALOGE("%s: Failed to create object of RoamCommand class", __FUNCTION__);
168 return WIFI_ERROR_UNKNOWN;
169 }
170
171 /* Create the NL message. */
172 ret = roamCommand->create();
173 if (ret != WIFI_SUCCESS) {
174 ALOGE("%s: Failed to create NL message, Error: %d", __FUNCTION__, ret);
175 goto cleanup;
176 }
177
178 /* Set the interface Id of the message. */
179 ret = roamCommand->set_iface_id(ifaceInfo->name);
180 if (ret != WIFI_SUCCESS) {
181 ALOGE("%s: Failed to set interface Id of message, Error: %d", __FUNCTION__, ret);
182 goto cleanup;
183 }
184
185 /* Add the vendor specific attributes for the NL command. */
186 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
187 if (!nlData) {
188 goto cleanup;
189 }
190
191 ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
192 QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST);
193 if (ret != WIFI_SUCCESS)
194 goto cleanup;
195 ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID, id);
196 if (ret != WIFI_SUCCESS)
197 goto cleanup;
198 ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
199 num_networks);
200 if (ret != WIFI_SUCCESS)
201 goto cleanup;
202
203 nlSsids = roamCommand->attr_start(QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST);
204 for (i = 0; i < num_networks; i++) {
205 struct nlattr *nl_ssid = roamCommand->attr_start(i);
206
207 memcpy(ssid, ssid_list[i].ssid_str, ssid_list[i].length);
208 ssid[ssid_list[i].length] = '\0';
209 ALOGV("ssid[%d] : %s", i, ssid);
210
211 ret = roamCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID,
212 ssid, (ssid_list[i].length + 1));
213 if (ret != WIFI_SUCCESS) {
214 ALOGE("%s: Failed to add ssid atribute, Error: %d", __FUNCTION__, ret);
215 goto cleanup;
216 }
217
218 roamCommand->attr_end(nl_ssid);
219 }
220 roamCommand->attr_end(nlSsids);
221
222 roamCommand->attr_end(nlData);
223
224 ret = roamCommand->requestResponse();
225 if (ret != WIFI_SUCCESS)
226 ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
227
228 cleanup:
229 delete roamCommand;
230 return ret;
231 }
232
wifi_get_roaming_capabilities(wifi_interface_handle iface,wifi_roaming_capabilities * caps)233 wifi_error wifi_get_roaming_capabilities(wifi_interface_handle iface,
234 wifi_roaming_capabilities *caps)
235 {
236 wifi_handle wifiHandle = getWifiHandle(iface);
237 hal_info *info = getHalInfo(wifiHandle);
238
239 if (!caps) {
240 ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
241 return WIFI_ERROR_INVALID_ARGS;
242 }
243
244 if (!info) {
245 ALOGE("%s: hal_info is NULL", __FUNCTION__);
246 return WIFI_ERROR_INVALID_ARGS;
247 }
248
249 memcpy(caps, &info->capa.roaming_capa, sizeof(wifi_roaming_capabilities));
250
251 return WIFI_SUCCESS;
252 }
253
wifi_configure_roaming(wifi_interface_handle iface,wifi_roaming_config * roaming_config)254 wifi_error wifi_configure_roaming(wifi_interface_handle iface, wifi_roaming_config *roaming_config)
255 {
256 wifi_error ret;
257 int requestId;
258 wifi_bssid_params bssid_params;
259 wifi_handle wifiHandle = getWifiHandle(iface);
260 hal_info *info = getHalInfo(wifiHandle);
261
262 if (!roaming_config) {
263 ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
264 return WIFI_ERROR_INVALID_ARGS;
265 }
266
267 /* No request id from caller, so generate one and pass it on to the driver.
268 * Generate it randomly.
269 */
270 requestId = get_requestid();
271
272 /* Set bssid blacklist */
273 if (roaming_config->num_blacklist_bssid > info->capa.roaming_capa.max_blacklist_size) {
274 ALOGE("%s: Number of blacklist bssids(%d) provided is more than maximum blacklist bssids(%d)"
275 " supported", __FUNCTION__, roaming_config->num_blacklist_bssid,
276 info->capa.roaming_capa.max_blacklist_size);
277 return WIFI_ERROR_NOT_SUPPORTED;
278 }
279 bssid_params.num_bssid = roaming_config->num_blacklist_bssid;
280
281 memcpy(bssid_params.bssids, roaming_config->blacklist_bssid,
282 (bssid_params.num_bssid * sizeof(mac_addr)));
283
284 ret = wifi_set_bssid_blacklist(requestId, iface, bssid_params);
285 if (ret != WIFI_SUCCESS) {
286 ALOGE("%s: Failed to configure blacklist bssids", __FUNCTION__);
287 return WIFI_ERROR_UNKNOWN;
288 }
289
290 /* Set ssid whitelist */
291 if (roaming_config->num_whitelist_ssid > info->capa.roaming_capa.max_whitelist_size) {
292 ALOGE("%s: Number of whitelist ssid(%d) provided is more than maximum whitelist ssids(%d) "
293 "supported", __FUNCTION__, roaming_config->num_whitelist_ssid,
294 info->capa.roaming_capa.max_whitelist_size);
295 return WIFI_ERROR_NOT_SUPPORTED;
296 }
297 ret = wifi_set_ssid_white_list(requestId, iface, roaming_config->num_whitelist_ssid,
298 roaming_config->whitelist_ssid);
299 if (ret != WIFI_SUCCESS)
300 ALOGE("%s: Failed to configure whitelist ssids", __FUNCTION__);
301
302 return ret;
303 }
304
305 /* Enable/disable firmware roaming */
wifi_enable_firmware_roaming(wifi_interface_handle iface,fw_roaming_state_t state)306 wifi_error wifi_enable_firmware_roaming(wifi_interface_handle iface, fw_roaming_state_t state)
307 {
308 int requestId;
309 wifi_error ret;
310 RoamCommand *roamCommand;
311 struct nlattr *nlData;
312 interface_info *ifaceInfo = getIfaceInfo(iface);
313 wifi_handle wifiHandle = getWifiHandle(iface);
314 qca_roaming_policy policy;
315
316 ALOGV("%s: set firmware roam state : %d", __FUNCTION__, state);
317
318 if (state == ROAMING_ENABLE) {
319 policy = QCA_ROAMING_ALLOWED_WITHIN_ESS;
320 } else if(state == ROAMING_DISABLE) {
321 policy = QCA_ROAMING_NOT_ALLOWED;
322 } else {
323 ALOGE("%s: Invalid state provided: %d. Exit \n", __FUNCTION__, state);
324 return WIFI_ERROR_INVALID_ARGS;
325 }
326
327 /* No request id from caller, so generate one and pass it on to the driver.
328 * Generate it randomly.
329 */
330 requestId = get_requestid();
331
332 roamCommand =
333 new RoamCommand(wifiHandle,
334 requestId,
335 OUI_QCA,
336 QCA_NL80211_VENDOR_SUBCMD_ROAMING);
337 if (roamCommand == NULL) {
338 ALOGE("%s: Failed to create object of RoamCommand class", __FUNCTION__);
339 return WIFI_ERROR_UNKNOWN;
340 }
341
342 /* Create the NL message. */
343 ret = roamCommand->create();
344 if (ret != WIFI_SUCCESS) {
345 ALOGE("%s: Failed to create NL message, Error: %d", __FUNCTION__, ret);
346 goto cleanup;
347 }
348
349 /* Set the interface Id of the message. */
350 ret = roamCommand->set_iface_id(ifaceInfo->name);
351 if (ret != WIFI_SUCCESS) {
352 ALOGE("%s: Failed to set interface Id of message, Error: %d", __FUNCTION__, ret);
353 goto cleanup;
354 }
355
356 /* Add the vendor specific attributes for the NL command. */
357 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
358 if (!nlData) {
359 ret = WIFI_ERROR_UNKNOWN;
360 goto cleanup;
361 }
362
363 ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY, policy);
364 if (ret != WIFI_SUCCESS) {
365 ALOGE("%s: Failed to add roaming policy atribute, Error: %d", __FUNCTION__, ret);
366 goto cleanup;
367 }
368
369 roamCommand->attr_end(nlData);
370
371 ret = roamCommand->requestResponse();
372 if (ret != WIFI_SUCCESS)
373 ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
374
375 cleanup:
376 delete roamCommand;
377 return ret;
378 }
379