1 /*
2  * hidl interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 
10 #include "hidl_manager.h"
11 #include "hidl_return_util.h"
12 #include "iface_config_utils.h"
13 #include "misc_utils.h"
14 #include "sta_iface.h"
15 
16 extern "C" {
17 #include "utils/eloop.h"
18 #include "gas_query.h"
19 #include "interworking.h"
20 #include "hs20_supplicant.h"
21 #include "wps_supplicant.h"
22 }
23 
24 namespace {
25 using android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
26 using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
27 using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
28 using android::hardware::wifi::supplicant::V1_0::implementation::HidlManager;
29 
30 constexpr uint32_t kMaxAnqpElems = 100;
31 constexpr char kGetMacAddress[] = "MACADDR";
32 constexpr char kStartRxFilter[] = "RXFILTER-START";
33 constexpr char kStopRxFilter[] = "RXFILTER-STOP";
34 constexpr char kAddRxFilter[] = "RXFILTER-ADD";
35 constexpr char kRemoveRxFilter[] = "RXFILTER-REMOVE";
36 constexpr char kSetBtCoexistenceMode[] = "BTCOEXMODE";
37 constexpr char kSetBtCoexistenceScanStart[] = "BTCOEXSCAN-START";
38 constexpr char kSetBtCoexistenceScanStop[] = "BTCOEXSCAN-STOP";
39 constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
40 constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
41 constexpr char kSetCountryCode[] = "COUNTRY";
42 constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec = static_cast<uint32_t>(
43     ISupplicantStaIface::ExtRadioWorkDefaults::TIMEOUT_IN_SECS);
44 constexpr char kExtRadioWorkNamePrefix[] = "ext:";
45 
convertHidlRxFilterTypeToInternal(ISupplicantStaIface::RxFilterType type)46 uint8_t convertHidlRxFilterTypeToInternal(
47     ISupplicantStaIface::RxFilterType type)
48 {
49 	switch (type) {
50 	case ISupplicantStaIface::RxFilterType::V4_MULTICAST:
51 		return 2;
52 	case ISupplicantStaIface::RxFilterType::V6_MULTICAST:
53 		return 3;
54 	};
55 	WPA_ASSERT(false);
56 }
57 
convertHidlBtCoexModeToInternal(ISupplicantStaIface::BtCoexistenceMode mode)58 uint8_t convertHidlBtCoexModeToInternal(
59     ISupplicantStaIface::BtCoexistenceMode mode)
60 {
61 	switch (mode) {
62 	case ISupplicantStaIface::BtCoexistenceMode::ENABLED:
63 		return 0;
64 	case ISupplicantStaIface::BtCoexistenceMode::DISABLED:
65 		return 1;
66 	case ISupplicantStaIface::BtCoexistenceMode::SENSE:
67 		return 2;
68 	};
69 	WPA_ASSERT(false);
70 }
71 
doZeroArgDriverCommand(struct wpa_supplicant * wpa_s,const char * cmd)72 SupplicantStatus doZeroArgDriverCommand(
73     struct wpa_supplicant *wpa_s, const char *cmd)
74 {
75 	std::vector<char> cmd_vec(cmd, cmd + strlen(cmd) + 1);
76 	char driver_cmd_reply_buf[4096] = {};
77 	if (wpa_drv_driver_cmd(
78 		wpa_s, cmd_vec.data(), driver_cmd_reply_buf,
79 		sizeof(driver_cmd_reply_buf))) {
80 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
81 	}
82 	return {SupplicantStatusCode::SUCCESS, ""};
83 }
84 
doOneArgDriverCommand(struct wpa_supplicant * wpa_s,const char * cmd,uint8_t arg)85 SupplicantStatus doOneArgDriverCommand(
86     struct wpa_supplicant *wpa_s, const char *cmd, uint8_t arg)
87 {
88 	std::string cmd_str = std::string(cmd) + " " + std::to_string(arg);
89 	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
90 }
91 
doOneArgDriverCommand(struct wpa_supplicant * wpa_s,const char * cmd,const std::string & arg)92 SupplicantStatus doOneArgDriverCommand(
93     struct wpa_supplicant *wpa_s, const char *cmd, const std::string &arg)
94 {
95 	std::string cmd_str = std::string(cmd) + " " + arg;
96 	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
97 }
98 
endExtRadioWork(struct wpa_radio_work * work)99 void endExtRadioWork(struct wpa_radio_work *work)
100 {
101 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
102 	work->wpa_s->ext_work_in_progress = 0;
103 	radio_work_done(work);
104 	os_free(ework);
105 }
106 
extRadioWorkTimeoutCb(void * eloop_ctx,void * timeout_ctx)107 void extRadioWorkTimeoutCb(void *eloop_ctx, void *timeout_ctx)
108 {
109 	auto *work = static_cast<struct wpa_radio_work *>(eloop_ctx);
110 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
111 	wpa_dbg(
112 	    work->wpa_s, MSG_DEBUG, "Timing out external radio work %u (%s)",
113 	    ework->id, work->type);
114 
115 	HidlManager *hidl_manager = HidlManager::getInstance();
116 	WPA_ASSERT(hidl_manager);
117 	hidl_manager->notifyExtRadioWorkTimeout(work->wpa_s, ework->id);
118 
119 	endExtRadioWork(work);
120 }
121 
startExtRadioWork(struct wpa_radio_work * work)122 void startExtRadioWork(struct wpa_radio_work *work)
123 {
124 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
125 	work->wpa_s->ext_work_in_progress = 1;
126 	if (!ework->timeout) {
127 		ework->timeout = kExtRadioWorkDefaultTimeoutInSec;
128 	}
129 	eloop_register_timeout(
130 	    ework->timeout, 0, extRadioWorkTimeoutCb, work, nullptr);
131 }
132 
extRadioWorkStartCb(struct wpa_radio_work * work,int deinit)133 void extRadioWorkStartCb(struct wpa_radio_work *work, int deinit)
134 {
135 	// deinit==1 is invoked during interface removal. Since the HIDL
136 	// interface does not support interface addition/removal, we don't
137 	// need to handle this scenario.
138 	WPA_ASSERT(!deinit);
139 
140 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
141 	wpa_dbg(
142 	    work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
143 	    ework->id, ework->type);
144 
145 	HidlManager *hidl_manager = HidlManager::getInstance();
146 	WPA_ASSERT(hidl_manager);
147 	hidl_manager->notifyExtRadioWorkStart(work->wpa_s, ework->id);
148 
149 	startExtRadioWork(work);
150 }
151 
152 }  // namespace
153 
154 namespace android {
155 namespace hardware {
156 namespace wifi {
157 namespace supplicant {
158 namespace V1_0 {
159 namespace implementation {
160 using hidl_return_util::validateAndCall;
161 
StaIface(struct wpa_global * wpa_global,const char ifname[])162 StaIface::StaIface(struct wpa_global *wpa_global, const char ifname[])
163     : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
164 {
165 }
166 
invalidate()167 void StaIface::invalidate() { is_valid_ = false; }
isValid()168 bool StaIface::isValid()
169 {
170 	return (is_valid_ && (retrieveIfacePtr() != nullptr));
171 }
172 
getName(getName_cb _hidl_cb)173 Return<void> StaIface::getName(getName_cb _hidl_cb)
174 {
175 	return validateAndCall(
176 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
177 	    &StaIface::getNameInternal, _hidl_cb);
178 }
179 
getType(getType_cb _hidl_cb)180 Return<void> StaIface::getType(getType_cb _hidl_cb)
181 {
182 	return validateAndCall(
183 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
184 	    &StaIface::getTypeInternal, _hidl_cb);
185 }
186 
addNetwork(addNetwork_cb _hidl_cb)187 Return<void> StaIface::addNetwork(addNetwork_cb _hidl_cb)
188 {
189 	return validateAndCall(
190 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
191 	    &StaIface::addNetworkInternal, _hidl_cb);
192 }
193 
removeNetwork(SupplicantNetworkId id,removeNetwork_cb _hidl_cb)194 Return<void> StaIface::removeNetwork(
195     SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
196 {
197 	return validateAndCall(
198 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
199 	    &StaIface::removeNetworkInternal, _hidl_cb, id);
200 }
201 
getNetwork(SupplicantNetworkId id,getNetwork_cb _hidl_cb)202 Return<void> StaIface::getNetwork(
203     SupplicantNetworkId id, getNetwork_cb _hidl_cb)
204 {
205 	return validateAndCall(
206 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
207 	    &StaIface::getNetworkInternal, _hidl_cb, id);
208 }
209 
listNetworks(listNetworks_cb _hidl_cb)210 Return<void> StaIface::listNetworks(listNetworks_cb _hidl_cb)
211 {
212 	return validateAndCall(
213 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
214 	    &StaIface::listNetworksInternal, _hidl_cb);
215 }
216 
registerCallback(const sp<ISupplicantStaIfaceCallback> & callback,registerCallback_cb _hidl_cb)217 Return<void> StaIface::registerCallback(
218     const sp<ISupplicantStaIfaceCallback> &callback,
219     registerCallback_cb _hidl_cb)
220 {
221 	return validateAndCall(
222 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
223 	    &StaIface::registerCallbackInternal, _hidl_cb, callback);
224 }
225 
reassociate(reassociate_cb _hidl_cb)226 Return<void> StaIface::reassociate(reassociate_cb _hidl_cb)
227 {
228 	return validateAndCall(
229 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
230 	    &StaIface::reassociateInternal, _hidl_cb);
231 }
232 
reconnect(reconnect_cb _hidl_cb)233 Return<void> StaIface::reconnect(reconnect_cb _hidl_cb)
234 {
235 	return validateAndCall(
236 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
237 	    &StaIface::reconnectInternal, _hidl_cb);
238 }
239 
disconnect(disconnect_cb _hidl_cb)240 Return<void> StaIface::disconnect(disconnect_cb _hidl_cb)
241 {
242 	return validateAndCall(
243 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
244 	    &StaIface::disconnectInternal, _hidl_cb);
245 }
246 
setPowerSave(bool enable,setPowerSave_cb _hidl_cb)247 Return<void> StaIface::setPowerSave(bool enable, setPowerSave_cb _hidl_cb)
248 {
249 	return validateAndCall(
250 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
251 	    &StaIface::setPowerSaveInternal, _hidl_cb, enable);
252 }
253 
initiateTdlsDiscover(const hidl_array<uint8_t,6> & mac_address,initiateTdlsDiscover_cb _hidl_cb)254 Return<void> StaIface::initiateTdlsDiscover(
255     const hidl_array<uint8_t, 6> &mac_address, initiateTdlsDiscover_cb _hidl_cb)
256 {
257 	return validateAndCall(
258 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
259 	    &StaIface::initiateTdlsDiscoverInternal, _hidl_cb, mac_address);
260 }
261 
initiateTdlsSetup(const hidl_array<uint8_t,6> & mac_address,initiateTdlsSetup_cb _hidl_cb)262 Return<void> StaIface::initiateTdlsSetup(
263     const hidl_array<uint8_t, 6> &mac_address, initiateTdlsSetup_cb _hidl_cb)
264 {
265 	return validateAndCall(
266 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
267 	    &StaIface::initiateTdlsSetupInternal, _hidl_cb, mac_address);
268 }
269 
initiateTdlsTeardown(const hidl_array<uint8_t,6> & mac_address,initiateTdlsTeardown_cb _hidl_cb)270 Return<void> StaIface::initiateTdlsTeardown(
271     const hidl_array<uint8_t, 6> &mac_address, initiateTdlsTeardown_cb _hidl_cb)
272 {
273 	return validateAndCall(
274 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
275 	    &StaIface::initiateTdlsTeardownInternal, _hidl_cb, mac_address);
276 }
initiateAnqpQuery(const hidl_array<uint8_t,6> & mac_address,const hidl_vec<ISupplicantStaIface::AnqpInfoId> & info_elements,const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> & sub_types,initiateAnqpQuery_cb _hidl_cb)277 Return<void> StaIface::initiateAnqpQuery(
278     const hidl_array<uint8_t, 6> &mac_address,
279     const hidl_vec<ISupplicantStaIface::AnqpInfoId> &info_elements,
280     const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types,
281     initiateAnqpQuery_cb _hidl_cb)
282 {
283 	return validateAndCall(
284 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
285 	    &StaIface::initiateAnqpQueryInternal, _hidl_cb, mac_address,
286 	    info_elements, sub_types);
287 }
288 
initiateHs20IconQuery(const hidl_array<uint8_t,6> & mac_address,const hidl_string & file_name,initiateHs20IconQuery_cb _hidl_cb)289 Return<void> StaIface::initiateHs20IconQuery(
290     const hidl_array<uint8_t, 6> &mac_address, const hidl_string &file_name,
291     initiateHs20IconQuery_cb _hidl_cb)
292 {
293 	return validateAndCall(
294 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
295 	    &StaIface::initiateHs20IconQueryInternal, _hidl_cb, mac_address,
296 	    file_name);
297 }
298 
getMacAddress(getMacAddress_cb _hidl_cb)299 Return<void> StaIface::getMacAddress(getMacAddress_cb _hidl_cb)
300 {
301 	return validateAndCall(
302 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
303 	    &StaIface::getMacAddressInternal, _hidl_cb);
304 }
305 
startRxFilter(startRxFilter_cb _hidl_cb)306 Return<void> StaIface::startRxFilter(startRxFilter_cb _hidl_cb)
307 {
308 	return validateAndCall(
309 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
310 	    &StaIface::startRxFilterInternal, _hidl_cb);
311 }
312 
stopRxFilter(stopRxFilter_cb _hidl_cb)313 Return<void> StaIface::stopRxFilter(stopRxFilter_cb _hidl_cb)
314 {
315 	return validateAndCall(
316 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
317 	    &StaIface::stopRxFilterInternal, _hidl_cb);
318 }
319 
addRxFilter(ISupplicantStaIface::RxFilterType type,addRxFilter_cb _hidl_cb)320 Return<void> StaIface::addRxFilter(
321     ISupplicantStaIface::RxFilterType type, addRxFilter_cb _hidl_cb)
322 {
323 	return validateAndCall(
324 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
325 	    &StaIface::addRxFilterInternal, _hidl_cb, type);
326 }
327 
removeRxFilter(ISupplicantStaIface::RxFilterType type,removeRxFilter_cb _hidl_cb)328 Return<void> StaIface::removeRxFilter(
329     ISupplicantStaIface::RxFilterType type, removeRxFilter_cb _hidl_cb)
330 {
331 	return validateAndCall(
332 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
333 	    &StaIface::removeRxFilterInternal, _hidl_cb, type);
334 }
335 
setBtCoexistenceMode(ISupplicantStaIface::BtCoexistenceMode mode,setBtCoexistenceMode_cb _hidl_cb)336 Return<void> StaIface::setBtCoexistenceMode(
337     ISupplicantStaIface::BtCoexistenceMode mode,
338     setBtCoexistenceMode_cb _hidl_cb)
339 {
340 	return validateAndCall(
341 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
342 	    &StaIface::setBtCoexistenceModeInternal, _hidl_cb, mode);
343 }
344 
setBtCoexistenceScanModeEnabled(bool enable,setBtCoexistenceScanModeEnabled_cb _hidl_cb)345 Return<void> StaIface::setBtCoexistenceScanModeEnabled(
346     bool enable, setBtCoexistenceScanModeEnabled_cb _hidl_cb)
347 {
348 	return validateAndCall(
349 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
350 	    &StaIface::setBtCoexistenceScanModeEnabledInternal, _hidl_cb,
351 	    enable);
352 }
353 
setSuspendModeEnabled(bool enable,setSuspendModeEnabled_cb _hidl_cb)354 Return<void> StaIface::setSuspendModeEnabled(
355     bool enable, setSuspendModeEnabled_cb _hidl_cb)
356 {
357 	return validateAndCall(
358 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
359 	    &StaIface::setSuspendModeEnabledInternal, _hidl_cb, enable);
360 }
361 
setCountryCode(const hidl_array<int8_t,2> & code,setCountryCode_cb _hidl_cb)362 Return<void> StaIface::setCountryCode(
363     const hidl_array<int8_t, 2> &code, setCountryCode_cb _hidl_cb)
364 {
365 	return validateAndCall(
366 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
367 	    &StaIface::setCountryCodeInternal, _hidl_cb, code);
368 }
369 
startWpsRegistrar(const hidl_array<uint8_t,6> & bssid,const hidl_string & pin,startWpsRegistrar_cb _hidl_cb)370 Return<void> StaIface::startWpsRegistrar(
371     const hidl_array<uint8_t, 6> &bssid, const hidl_string &pin,
372     startWpsRegistrar_cb _hidl_cb)
373 {
374 	return validateAndCall(
375 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
376 	    &StaIface::startWpsRegistrarInternal, _hidl_cb, bssid, pin);
377 }
378 
startWpsPbc(const hidl_array<uint8_t,6> & bssid,startWpsPbc_cb _hidl_cb)379 Return<void> StaIface::startWpsPbc(
380     const hidl_array<uint8_t, 6> &bssid, startWpsPbc_cb _hidl_cb)
381 {
382 	return validateAndCall(
383 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
384 	    &StaIface::startWpsPbcInternal, _hidl_cb, bssid);
385 }
386 
startWpsPinKeypad(const hidl_string & pin,startWpsPinKeypad_cb _hidl_cb)387 Return<void> StaIface::startWpsPinKeypad(
388     const hidl_string &pin, startWpsPinKeypad_cb _hidl_cb)
389 {
390 	return validateAndCall(
391 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
392 	    &StaIface::startWpsPinKeypadInternal, _hidl_cb, pin);
393 }
394 
startWpsPinDisplay(const hidl_array<uint8_t,6> & bssid,startWpsPinDisplay_cb _hidl_cb)395 Return<void> StaIface::startWpsPinDisplay(
396     const hidl_array<uint8_t, 6> &bssid, startWpsPinDisplay_cb _hidl_cb)
397 {
398 	return validateAndCall(
399 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
400 	    &StaIface::startWpsPinDisplayInternal, _hidl_cb, bssid);
401 }
402 
cancelWps(cancelWps_cb _hidl_cb)403 Return<void> StaIface::cancelWps(cancelWps_cb _hidl_cb)
404 {
405 	return validateAndCall(
406 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
407 	    &StaIface::cancelWpsInternal, _hidl_cb);
408 }
409 
setWpsDeviceName(const hidl_string & name,setWpsDeviceName_cb _hidl_cb)410 Return<void> StaIface::setWpsDeviceName(
411     const hidl_string &name, setWpsDeviceName_cb _hidl_cb)
412 {
413 	return validateAndCall(
414 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
415 	    &StaIface::setWpsDeviceNameInternal, _hidl_cb, name);
416 }
417 
setWpsDeviceType(const hidl_array<uint8_t,8> & type,setWpsDeviceType_cb _hidl_cb)418 Return<void> StaIface::setWpsDeviceType(
419     const hidl_array<uint8_t, 8> &type, setWpsDeviceType_cb _hidl_cb)
420 {
421 	return validateAndCall(
422 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
423 	    &StaIface::setWpsDeviceTypeInternal, _hidl_cb, type);
424 }
425 
setWpsManufacturer(const hidl_string & manufacturer,setWpsManufacturer_cb _hidl_cb)426 Return<void> StaIface::setWpsManufacturer(
427     const hidl_string &manufacturer, setWpsManufacturer_cb _hidl_cb)
428 {
429 	return validateAndCall(
430 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
431 	    &StaIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
432 }
433 
setWpsModelName(const hidl_string & model_name,setWpsModelName_cb _hidl_cb)434 Return<void> StaIface::setWpsModelName(
435     const hidl_string &model_name, setWpsModelName_cb _hidl_cb)
436 {
437 	return validateAndCall(
438 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
439 	    &StaIface::setWpsModelNameInternal, _hidl_cb, model_name);
440 }
441 
setWpsModelNumber(const hidl_string & model_number,setWpsModelNumber_cb _hidl_cb)442 Return<void> StaIface::setWpsModelNumber(
443     const hidl_string &model_number, setWpsModelNumber_cb _hidl_cb)
444 {
445 	return validateAndCall(
446 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
447 	    &StaIface::setWpsModelNumberInternal, _hidl_cb, model_number);
448 }
449 
setWpsSerialNumber(const hidl_string & serial_number,setWpsSerialNumber_cb _hidl_cb)450 Return<void> StaIface::setWpsSerialNumber(
451     const hidl_string &serial_number, setWpsSerialNumber_cb _hidl_cb)
452 {
453 	return validateAndCall(
454 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
455 	    &StaIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
456 }
457 
setWpsConfigMethods(uint16_t config_methods,setWpsConfigMethods_cb _hidl_cb)458 Return<void> StaIface::setWpsConfigMethods(
459     uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
460 {
461 	return validateAndCall(
462 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
463 	    &StaIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
464 }
465 
setExternalSim(bool useExternalSim,setExternalSim_cb _hidl_cb)466 Return<void> StaIface::setExternalSim(
467     bool useExternalSim, setExternalSim_cb _hidl_cb)
468 {
469 	return validateAndCall(
470 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
471 	    &StaIface::setExternalSimInternal, _hidl_cb, useExternalSim);
472 }
473 
addExtRadioWork(const hidl_string & name,uint32_t freq_in_mhz,uint32_t timeout_in_sec,addExtRadioWork_cb _hidl_cb)474 Return<void> StaIface::addExtRadioWork(
475     const hidl_string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec,
476     addExtRadioWork_cb _hidl_cb)
477 {
478 	return validateAndCall(
479 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
480 	    &StaIface::addExtRadioWorkInternal, _hidl_cb, name, freq_in_mhz,
481 	    timeout_in_sec);
482 }
483 
removeExtRadioWork(uint32_t id,removeExtRadioWork_cb _hidl_cb)484 Return<void> StaIface::removeExtRadioWork(
485     uint32_t id, removeExtRadioWork_cb _hidl_cb)
486 {
487 	return validateAndCall(
488 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
489 	    &StaIface::removeExtRadioWorkInternal, _hidl_cb, id);
490 }
491 
enableAutoReconnect(bool enable,enableAutoReconnect_cb _hidl_cb)492 Return<void> StaIface::enableAutoReconnect(
493     bool enable, enableAutoReconnect_cb _hidl_cb)
494 {
495 	return validateAndCall(
496 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
497 	    &StaIface::enableAutoReconnectInternal, _hidl_cb, enable);
498 }
499 
getNameInternal()500 std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
501 {
502 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
503 }
504 
getTypeInternal()505 std::pair<SupplicantStatus, IfaceType> StaIface::getTypeInternal()
506 {
507 	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::STA};
508 }
509 
510 std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
addNetworkInternal()511 StaIface::addNetworkInternal()
512 {
513 	android::sp<ISupplicantStaNetwork> network;
514 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
515 	struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
516 	if (!ssid) {
517 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
518 	}
519 	HidlManager *hidl_manager = HidlManager::getInstance();
520 	if (!hidl_manager ||
521 	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
522 		wpa_s->ifname, ssid->id, &network)) {
523 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
524 	}
525 	return {{SupplicantStatusCode::SUCCESS, ""}, network};
526 }
527 
removeNetworkInternal(SupplicantNetworkId id)528 SupplicantStatus StaIface::removeNetworkInternal(SupplicantNetworkId id)
529 {
530 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
531 	int result = wpa_supplicant_remove_network(wpa_s, id);
532 	if (result == -1) {
533 		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
534 	}
535 	if (result != 0) {
536 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
537 	}
538 	return {SupplicantStatusCode::SUCCESS, ""};
539 }
540 
541 std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
getNetworkInternal(SupplicantNetworkId id)542 StaIface::getNetworkInternal(SupplicantNetworkId id)
543 {
544 	android::sp<ISupplicantStaNetwork> network;
545 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
546 	struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);
547 	if (!ssid) {
548 		return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
549 			network};
550 	}
551 	HidlManager *hidl_manager = HidlManager::getInstance();
552 	if (!hidl_manager ||
553 	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
554 		wpa_s->ifname, ssid->id, &network)) {
555 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
556 	}
557 	return {{SupplicantStatusCode::SUCCESS, ""}, network};
558 }
559 
560 std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
listNetworksInternal()561 StaIface::listNetworksInternal()
562 {
563 	std::vector<SupplicantNetworkId> network_ids;
564 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
565 	for (struct wpa_ssid *wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
566 	     wpa_ssid = wpa_ssid->next) {
567 		network_ids.emplace_back(wpa_ssid->id);
568 	}
569 	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
570 }
571 
registerCallbackInternal(const sp<ISupplicantStaIfaceCallback> & callback)572 SupplicantStatus StaIface::registerCallbackInternal(
573     const sp<ISupplicantStaIfaceCallback> &callback)
574 {
575 	HidlManager *hidl_manager = HidlManager::getInstance();
576 	if (!hidl_manager ||
577 	    hidl_manager->addStaIfaceCallbackHidlObject(ifname_, callback)) {
578 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
579 	}
580 	return {SupplicantStatusCode::SUCCESS, ""};
581 }
582 
reassociateInternal()583 SupplicantStatus StaIface::reassociateInternal()
584 {
585 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
586 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
587 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
588 	}
589 	wpas_request_connection(wpa_s);
590 	return {SupplicantStatusCode::SUCCESS, ""};
591 }
592 
reconnectInternal()593 SupplicantStatus StaIface::reconnectInternal()
594 {
595 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
596 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
597 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
598 	}
599 	if (!wpa_s->disconnected) {
600 		return {SupplicantStatusCode::FAILURE_IFACE_NOT_DISCONNECTED,
601 			""};
602 	}
603 	wpas_request_connection(wpa_s);
604 	return {SupplicantStatusCode::SUCCESS, ""};
605 }
606 
disconnectInternal()607 SupplicantStatus StaIface::disconnectInternal()
608 {
609 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
610 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
611 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
612 	}
613 	wpas_request_disconnection(wpa_s);
614 	return {SupplicantStatusCode::SUCCESS, ""};
615 }
616 
setPowerSaveInternal(bool enable)617 SupplicantStatus StaIface::setPowerSaveInternal(bool enable)
618 {
619 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
620 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
621 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
622 	}
623 	if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
624 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
625 	}
626 	return {SupplicantStatusCode::SUCCESS, ""};
627 }
628 
initiateTdlsDiscoverInternal(const std::array<uint8_t,6> & mac_address)629 SupplicantStatus StaIface::initiateTdlsDiscoverInternal(
630     const std::array<uint8_t, 6> &mac_address)
631 {
632 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
633 	int ret;
634 	const u8 *peer = mac_address.data();
635 	if (wpa_tdls_is_external_setup(wpa_s->wpa)) {
636 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
637 	} else {
638 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
639 	}
640 	if (ret) {
641 		wpa_printf(MSG_INFO, "StaIface: TDLS discover failed: %d", ret);
642 	}
643 	return {SupplicantStatusCode::SUCCESS, ""};
644 }
645 
initiateTdlsSetupInternal(const std::array<uint8_t,6> & mac_address)646 SupplicantStatus StaIface::initiateTdlsSetupInternal(
647     const std::array<uint8_t, 6> &mac_address)
648 {
649 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
650 	int ret;
651 	const u8 *peer = mac_address.data();
652 	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
653 	    !(wpa_s->conf->tdls_external_control)) {
654 		wpa_tdls_remove(wpa_s->wpa, peer);
655 		ret = wpa_tdls_start(wpa_s->wpa, peer);
656 	} else {
657 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
658 	}
659 	if (ret) {
660 		wpa_printf(MSG_INFO, "StaIface: TDLS setup failed: %d", ret);
661 	}
662 	return {SupplicantStatusCode::SUCCESS, ""};
663 }
664 
initiateTdlsTeardownInternal(const std::array<uint8_t,6> & mac_address)665 SupplicantStatus StaIface::initiateTdlsTeardownInternal(
666     const std::array<uint8_t, 6> &mac_address)
667 {
668 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
669 	int ret;
670 	const u8 *peer = mac_address.data();
671 	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
672 	    !(wpa_s->conf->tdls_external_control)) {
673 		ret = wpa_tdls_teardown_link(
674 		    wpa_s->wpa, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
675 	} else {
676 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
677 	}
678 	if (ret) {
679 		wpa_printf(MSG_INFO, "StaIface: TDLS teardown failed: %d", ret);
680 	}
681 	return {SupplicantStatusCode::SUCCESS, ""};
682 }
683 
initiateAnqpQueryInternal(const std::array<uint8_t,6> & mac_address,const std::vector<ISupplicantStaIface::AnqpInfoId> & info_elements,const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> & sub_types)684 SupplicantStatus StaIface::initiateAnqpQueryInternal(
685     const std::array<uint8_t, 6> &mac_address,
686     const std::vector<ISupplicantStaIface::AnqpInfoId> &info_elements,
687     const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types)
688 {
689 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
690 	if (info_elements.size() > kMaxAnqpElems) {
691 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
692 	}
693 	uint16_t info_elems_buf[kMaxAnqpElems];
694 	uint32_t num_info_elems = 0;
695 	for (const auto &info_element : info_elements) {
696 		info_elems_buf[num_info_elems++] =
697 		    static_cast<std::underlying_type<
698 			ISupplicantStaIface::AnqpInfoId>::type>(info_element);
699 	}
700 	uint32_t sub_types_bitmask = 0;
701 	for (const auto &type : sub_types) {
702 		sub_types_bitmask |= BIT(
703 		    static_cast<std::underlying_type<
704 			ISupplicantStaIface::Hs20AnqpSubtypes>::type>(type));
705 	}
706 	if (anqp_send_req(
707 		wpa_s, mac_address.data(), info_elems_buf, num_info_elems,
708 		sub_types_bitmask, false)) {
709 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
710 	}
711 	return {SupplicantStatusCode::SUCCESS, ""};
712 }
713 
initiateHs20IconQueryInternal(const std::array<uint8_t,6> & mac_address,const std::string & file_name)714 SupplicantStatus StaIface::initiateHs20IconQueryInternal(
715     const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
716 {
717 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
718 	wpa_s->fetch_osu_icon_in_progress = 0;
719 	if (hs20_anqp_send_req(
720 		wpa_s, mac_address.data(), BIT(HS20_STYPE_ICON_REQUEST),
721 		reinterpret_cast<const uint8_t *>(file_name.c_str()),
722 		file_name.size(), true)) {
723 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
724 	}
725 	return {SupplicantStatusCode::SUCCESS, ""};
726 }
727 
728 std::pair<SupplicantStatus, std::array<uint8_t, 6>>
getMacAddressInternal()729 StaIface::getMacAddressInternal()
730 {
731 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
732 	std::vector<char> cmd(
733 	    kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
734 	char driver_cmd_reply_buf[4096] = {};
735 	int ret = wpa_drv_driver_cmd(
736 	    wpa_s, cmd.data(), driver_cmd_reply_buf,
737 	    sizeof(driver_cmd_reply_buf));
738 	// Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
739 	std::string reply_str = driver_cmd_reply_buf;
740 	if (ret < 0 || reply_str.empty() ||
741 	    reply_str.find("=") == std::string::npos) {
742 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
743 	}
744 	// Remove all whitespace first and then split using the delimiter "=".
745 	reply_str.erase(
746 	    remove_if(reply_str.begin(), reply_str.end(), isspace),
747 	    reply_str.end());
748 	std::string mac_addr_str =
749 	    reply_str.substr(reply_str.find("=") + 1, reply_str.size());
750 	std::array<uint8_t, 6> mac_addr;
751 	if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
752 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
753 	}
754 	return {{SupplicantStatusCode::SUCCESS, ""}, mac_addr};
755 }
756 
startRxFilterInternal()757 SupplicantStatus StaIface::startRxFilterInternal()
758 {
759 	return doZeroArgDriverCommand(retrieveIfacePtr(), kStartRxFilter);
760 }
761 
stopRxFilterInternal()762 SupplicantStatus StaIface::stopRxFilterInternal()
763 {
764 	return doZeroArgDriverCommand(retrieveIfacePtr(), kStopRxFilter);
765 }
766 
addRxFilterInternal(ISupplicantStaIface::RxFilterType type)767 SupplicantStatus StaIface::addRxFilterInternal(
768     ISupplicantStaIface::RxFilterType type)
769 {
770 	return doOneArgDriverCommand(
771 	    retrieveIfacePtr(), kAddRxFilter,
772 	    convertHidlRxFilterTypeToInternal(type));
773 }
774 
removeRxFilterInternal(ISupplicantStaIface::RxFilterType type)775 SupplicantStatus StaIface::removeRxFilterInternal(
776     ISupplicantStaIface::RxFilterType type)
777 {
778 	return doOneArgDriverCommand(
779 	    retrieveIfacePtr(), kRemoveRxFilter,
780 	    convertHidlRxFilterTypeToInternal(type));
781 }
782 
setBtCoexistenceModeInternal(ISupplicantStaIface::BtCoexistenceMode mode)783 SupplicantStatus StaIface::setBtCoexistenceModeInternal(
784     ISupplicantStaIface::BtCoexistenceMode mode)
785 {
786 	return doOneArgDriverCommand(
787 	    retrieveIfacePtr(), kSetBtCoexistenceMode,
788 	    convertHidlBtCoexModeToInternal(mode));
789 }
790 
setBtCoexistenceScanModeEnabledInternal(bool enable)791 SupplicantStatus StaIface::setBtCoexistenceScanModeEnabledInternal(bool enable)
792 {
793 	const char *cmd;
794 	if (enable) {
795 		cmd = kSetBtCoexistenceScanStart;
796 	} else {
797 		cmd = kSetBtCoexistenceScanStop;
798 	}
799 	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
800 }
801 
setSuspendModeEnabledInternal(bool enable)802 SupplicantStatus StaIface::setSuspendModeEnabledInternal(bool enable)
803 {
804 	const char *cmd;
805 	if (enable) {
806 		cmd = kSetSupendModeEnabled;
807 	} else {
808 		cmd = kSetSupendModeDisabled;
809 	}
810 	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
811 }
812 
setCountryCodeInternal(const std::array<int8_t,2> & code)813 SupplicantStatus StaIface::setCountryCodeInternal(
814     const std::array<int8_t, 2> &code)
815 {
816 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
817 	SupplicantStatus status = doOneArgDriverCommand(
818 	    wpa_s, kSetCountryCode,
819 	    std::string(std::begin(code), std::end(code)));
820 	if (status.code != SupplicantStatusCode::SUCCESS) {
821 		return status;
822 	}
823 	struct p2p_data *p2p = wpa_s->global->p2p;
824 	if (p2p) {
825 		char country[3];
826 		country[0] = code[0];
827 		country[1] = code[1];
828 		country[2] = 0x04;
829 		p2p_set_country(p2p, country);
830 	}
831 	return {SupplicantStatusCode::SUCCESS, ""};
832 }
833 
startWpsRegistrarInternal(const std::array<uint8_t,6> & bssid,const std::string & pin)834 SupplicantStatus StaIface::startWpsRegistrarInternal(
835     const std::array<uint8_t, 6> &bssid, const std::string &pin)
836 {
837 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
838 	if (wpas_wps_start_reg(wpa_s, bssid.data(), pin.c_str(), nullptr)) {
839 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
840 	}
841 	return {SupplicantStatusCode::SUCCESS, ""};
842 }
843 
startWpsPbcInternal(const std::array<uint8_t,6> & bssid)844 SupplicantStatus StaIface::startWpsPbcInternal(
845     const std::array<uint8_t, 6> &bssid)
846 {
847 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
848 	const uint8_t *bssid_addr =
849 	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
850 	if (wpas_wps_start_pbc(wpa_s, bssid_addr, 0)) {
851 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
852 	}
853 	return {SupplicantStatusCode::SUCCESS, ""};
854 }
855 
startWpsPinKeypadInternal(const std::string & pin)856 SupplicantStatus StaIface::startWpsPinKeypadInternal(const std::string &pin)
857 {
858 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
859 	if (wpas_wps_start_pin(
860 		wpa_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
861 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
862 	}
863 	return {SupplicantStatusCode::SUCCESS, ""};
864 }
865 
startWpsPinDisplayInternal(const std::array<uint8_t,6> & bssid)866 std::pair<SupplicantStatus, std::string> StaIface::startWpsPinDisplayInternal(
867     const std::array<uint8_t, 6> &bssid)
868 {
869 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
870 	const uint8_t *bssid_addr =
871 	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
872 	int pin =
873 	    wpas_wps_start_pin(wpa_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
874 	if (pin < 0) {
875 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
876 	}
877 	return {{SupplicantStatusCode::SUCCESS, ""},
878 		misc_utils::convertWpsPinToString(pin)};
879 }
880 
cancelWpsInternal()881 SupplicantStatus StaIface::cancelWpsInternal()
882 {
883 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
884 	if (wpas_wps_cancel(wpa_s)) {
885 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
886 	}
887 	return {SupplicantStatusCode::SUCCESS, ""};
888 }
889 
setWpsDeviceNameInternal(const std::string & name)890 SupplicantStatus StaIface::setWpsDeviceNameInternal(const std::string &name)
891 {
892 	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
893 }
894 
setWpsDeviceTypeInternal(const std::array<uint8_t,8> & type)895 SupplicantStatus StaIface::setWpsDeviceTypeInternal(
896     const std::array<uint8_t, 8> &type)
897 {
898 	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
899 }
900 
setWpsManufacturerInternal(const std::string & manufacturer)901 SupplicantStatus StaIface::setWpsManufacturerInternal(
902     const std::string &manufacturer)
903 {
904 	return iface_config_utils::setWpsManufacturer(
905 	    retrieveIfacePtr(), manufacturer);
906 }
907 
setWpsModelNameInternal(const std::string & model_name)908 SupplicantStatus StaIface::setWpsModelNameInternal(
909     const std::string &model_name)
910 {
911 	return iface_config_utils::setWpsModelName(
912 	    retrieveIfacePtr(), model_name);
913 }
914 
setWpsModelNumberInternal(const std::string & model_number)915 SupplicantStatus StaIface::setWpsModelNumberInternal(
916     const std::string &model_number)
917 {
918 	return iface_config_utils::setWpsModelNumber(
919 	    retrieveIfacePtr(), model_number);
920 }
921 
setWpsSerialNumberInternal(const std::string & serial_number)922 SupplicantStatus StaIface::setWpsSerialNumberInternal(
923     const std::string &serial_number)
924 {
925 	return iface_config_utils::setWpsSerialNumber(
926 	    retrieveIfacePtr(), serial_number);
927 }
928 
setWpsConfigMethodsInternal(uint16_t config_methods)929 SupplicantStatus StaIface::setWpsConfigMethodsInternal(uint16_t config_methods)
930 {
931 	return iface_config_utils::setWpsConfigMethods(
932 	    retrieveIfacePtr(), config_methods);
933 }
934 
setExternalSimInternal(bool useExternalSim)935 SupplicantStatus StaIface::setExternalSimInternal(bool useExternalSim)
936 {
937 	return iface_config_utils::setExternalSim(
938 	    retrieveIfacePtr(), useExternalSim);
939 }
940 
addExtRadioWorkInternal(const std::string & name,uint32_t freq_in_mhz,uint32_t timeout_in_sec)941 std::pair<SupplicantStatus, uint32_t> StaIface::addExtRadioWorkInternal(
942     const std::string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec)
943 {
944 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
945 	auto *ework = static_cast<struct wpa_external_work *>(
946 	    os_zalloc(sizeof(struct wpa_external_work)));
947 	if (!ework) {
948 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
949 			UINT32_MAX};
950 	}
951 
952 	std::string radio_work_name = kExtRadioWorkNamePrefix + name;
953 	os_strlcpy(ework->type, radio_work_name.c_str(), sizeof(ework->type));
954 	ework->timeout = timeout_in_sec;
955 	wpa_s->ext_work_id++;
956 	if (wpa_s->ext_work_id == 0) {
957 		wpa_s->ext_work_id++;
958 	}
959 	ework->id = wpa_s->ext_work_id;
960 
961 	if (radio_add_work(
962 		wpa_s, freq_in_mhz, ework->type, 0, extRadioWorkStartCb,
963 		ework)) {
964 		os_free(ework);
965 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
966 			UINT32_MAX};
967 	}
968 	return {SupplicantStatus{SupplicantStatusCode::SUCCESS, ""}, ework->id};
969 }
970 
removeExtRadioWorkInternal(uint32_t id)971 SupplicantStatus StaIface::removeExtRadioWorkInternal(uint32_t id)
972 {
973 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
974 	struct wpa_radio_work *work;
975 	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
976 	{
977 		if (os_strncmp(
978 			work->type, kExtRadioWorkNamePrefix,
979 			sizeof(kExtRadioWorkNamePrefix)) != 0)
980 			continue;
981 
982 		auto *ework =
983 		    static_cast<struct wpa_external_work *>(work->ctx);
984 		if (ework->id != id)
985 			continue;
986 
987 		wpa_dbg(
988 		    wpa_s, MSG_DEBUG, "Completed external radio work %u (%s)",
989 		    ework->id, ework->type);
990 		eloop_cancel_timeout(extRadioWorkTimeoutCb, work, NULL);
991 		endExtRadioWork(work);
992 
993 		return {SupplicantStatusCode::SUCCESS, ""};
994 	}
995 	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
996 }
997 
enableAutoReconnectInternal(bool enable)998 SupplicantStatus StaIface::enableAutoReconnectInternal(bool enable)
999 {
1000 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
1001 	wpa_s->auto_reconnect_disabled = enable ? 0 : 1;
1002 	return {SupplicantStatusCode::SUCCESS, ""};
1003 }
1004 
1005 /**
1006  * Retrieve the underlying |wpa_supplicant| struct
1007  * pointer for this iface.
1008  * If the underlying iface is removed, then all RPC method calls on this object
1009  * will return failure.
1010  */
retrieveIfacePtr()1011 wpa_supplicant *StaIface::retrieveIfacePtr()
1012 {
1013 	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
1014 }
1015 }  // namespace implementation
1016 }  // namespace V1_0
1017 }  // namespace wifi
1018 }  // namespace supplicant
1019 }  // namespace hardware
1020 }  // namespace android
1021