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
16extern "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
24namespace {
25using android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
26using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
27using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
28using android::hardware::wifi::supplicant::V1_0::implementation::HidlManager;
29
30constexpr uint32_t kMaxAnqpElems = 100;
31constexpr char kGetMacAddress[] = "MACADDR";
32constexpr char kStartRxFilter[] = "RXFILTER-START";
33constexpr char kStopRxFilter[] = "RXFILTER-STOP";
34constexpr char kAddRxFilter[] = "RXFILTER-ADD";
35constexpr char kRemoveRxFilter[] = "RXFILTER-REMOVE";
36constexpr char kSetBtCoexistenceMode[] = "BTCOEXMODE";
37constexpr char kSetBtCoexistenceScanStart[] = "BTCOEXSCAN-START";
38constexpr char kSetBtCoexistenceScanStop[] = "BTCOEXSCAN-STOP";
39constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
40constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
41constexpr char kSetCountryCode[] = "COUNTRY";
42constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec = static_cast<uint32_t>(
43    ISupplicantStaIface::ExtRadioWorkDefaults::TIMEOUT_IN_SECS);
44constexpr char kExtRadioWorkNamePrefix[] = "ext:";
45
46uint8_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
58uint8_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
72SupplicantStatus 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
85SupplicantStatus 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
92SupplicantStatus 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
99void 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
107void 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
122void 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
133void 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
154namespace android {
155namespace hardware {
156namespace wifi {
157namespace supplicant {
158namespace V1_0 {
159namespace implementation {
160using hidl_return_util::validateAndCall;
161
162StaIface::StaIface(struct wpa_global *wpa_global, const char ifname[])
163    : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
164{
165}
166
167void StaIface::invalidate() { is_valid_ = false; }
168bool StaIface::isValid()
169{
170	return (is_valid_ && (retrieveIfacePtr() != nullptr));
171}
172
173Return<void> StaIface::getName(getName_cb _hidl_cb)
174{
175	return validateAndCall(
176	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
177	    &StaIface::getNameInternal, _hidl_cb);
178}
179
180Return<void> StaIface::getType(getType_cb _hidl_cb)
181{
182	return validateAndCall(
183	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
184	    &StaIface::getTypeInternal, _hidl_cb);
185}
186
187Return<void> StaIface::addNetwork(addNetwork_cb _hidl_cb)
188{
189	return validateAndCall(
190	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
191	    &StaIface::addNetworkInternal, _hidl_cb);
192}
193
194Return<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
202Return<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
210Return<void> StaIface::listNetworks(listNetworks_cb _hidl_cb)
211{
212	return validateAndCall(
213	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
214	    &StaIface::listNetworksInternal, _hidl_cb);
215}
216
217Return<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
226Return<void> StaIface::reassociate(reassociate_cb _hidl_cb)
227{
228	return validateAndCall(
229	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
230	    &StaIface::reassociateInternal, _hidl_cb);
231}
232
233Return<void> StaIface::reconnect(reconnect_cb _hidl_cb)
234{
235	return validateAndCall(
236	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
237	    &StaIface::reconnectInternal, _hidl_cb);
238}
239
240Return<void> StaIface::disconnect(disconnect_cb _hidl_cb)
241{
242	return validateAndCall(
243	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
244	    &StaIface::disconnectInternal, _hidl_cb);
245}
246
247Return<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
254Return<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
262Return<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
270Return<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}
277Return<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
289Return<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
299Return<void> StaIface::getMacAddress(getMacAddress_cb _hidl_cb)
300{
301	return validateAndCall(
302	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
303	    &StaIface::getMacAddressInternal, _hidl_cb);
304}
305
306Return<void> StaIface::startRxFilter(startRxFilter_cb _hidl_cb)
307{
308	return validateAndCall(
309	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
310	    &StaIface::startRxFilterInternal, _hidl_cb);
311}
312
313Return<void> StaIface::stopRxFilter(stopRxFilter_cb _hidl_cb)
314{
315	return validateAndCall(
316	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
317	    &StaIface::stopRxFilterInternal, _hidl_cb);
318}
319
320Return<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
328Return<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
336Return<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
345Return<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
354Return<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
362Return<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
370Return<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
379Return<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
387Return<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
395Return<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
403Return<void> StaIface::cancelWps(cancelWps_cb _hidl_cb)
404{
405	return validateAndCall(
406	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
407	    &StaIface::cancelWpsInternal, _hidl_cb);
408}
409
410Return<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
418Return<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
426Return<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
434Return<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
442Return<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
450Return<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
458Return<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
466Return<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
474Return<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
484Return<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
492Return<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
500std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
501{
502	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
503}
504
505std::pair<SupplicantStatus, IfaceType> StaIface::getTypeInternal()
506{
507	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::STA};
508}
509
510std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
511StaIface::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
528SupplicantStatus 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
541std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
542StaIface::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
560std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
561StaIface::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
572SupplicantStatus 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
583SupplicantStatus 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
593SupplicantStatus 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
607SupplicantStatus 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
617SupplicantStatus 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
629SupplicantStatus 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
646SupplicantStatus 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
665SupplicantStatus 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
684SupplicantStatus 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
714SupplicantStatus 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
728std::pair<SupplicantStatus, std::array<uint8_t, 6>>
729StaIface::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
757SupplicantStatus StaIface::startRxFilterInternal()
758{
759	return doZeroArgDriverCommand(retrieveIfacePtr(), kStartRxFilter);
760}
761
762SupplicantStatus StaIface::stopRxFilterInternal()
763{
764	return doZeroArgDriverCommand(retrieveIfacePtr(), kStopRxFilter);
765}
766
767SupplicantStatus StaIface::addRxFilterInternal(
768    ISupplicantStaIface::RxFilterType type)
769{
770	return doOneArgDriverCommand(
771	    retrieveIfacePtr(), kAddRxFilter,
772	    convertHidlRxFilterTypeToInternal(type));
773}
774
775SupplicantStatus StaIface::removeRxFilterInternal(
776    ISupplicantStaIface::RxFilterType type)
777{
778	return doOneArgDriverCommand(
779	    retrieveIfacePtr(), kRemoveRxFilter,
780	    convertHidlRxFilterTypeToInternal(type));
781}
782
783SupplicantStatus StaIface::setBtCoexistenceModeInternal(
784    ISupplicantStaIface::BtCoexistenceMode mode)
785{
786	return doOneArgDriverCommand(
787	    retrieveIfacePtr(), kSetBtCoexistenceMode,
788	    convertHidlBtCoexModeToInternal(mode));
789}
790
791SupplicantStatus 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
802SupplicantStatus 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
813SupplicantStatus 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
834SupplicantStatus 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
844SupplicantStatus 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
856SupplicantStatus 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
866std::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
881SupplicantStatus 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
890SupplicantStatus StaIface::setWpsDeviceNameInternal(const std::string &name)
891{
892	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
893}
894
895SupplicantStatus StaIface::setWpsDeviceTypeInternal(
896    const std::array<uint8_t, 8> &type)
897{
898	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
899}
900
901SupplicantStatus StaIface::setWpsManufacturerInternal(
902    const std::string &manufacturer)
903{
904	return iface_config_utils::setWpsManufacturer(
905	    retrieveIfacePtr(), manufacturer);
906}
907
908SupplicantStatus StaIface::setWpsModelNameInternal(
909    const std::string &model_name)
910{
911	return iface_config_utils::setWpsModelName(
912	    retrieveIfacePtr(), model_name);
913}
914
915SupplicantStatus StaIface::setWpsModelNumberInternal(
916    const std::string &model_number)
917{
918	return iface_config_utils::setWpsModelNumber(
919	    retrieveIfacePtr(), model_number);
920}
921
922SupplicantStatus StaIface::setWpsSerialNumberInternal(
923    const std::string &serial_number)
924{
925	return iface_config_utils::setWpsSerialNumber(
926	    retrieveIfacePtr(), serial_number);
927}
928
929SupplicantStatus StaIface::setWpsConfigMethodsInternal(uint16_t config_methods)
930{
931	return iface_config_utils::setWpsConfigMethods(
932	    retrieveIfacePtr(), config_methods);
933}
934
935SupplicantStatus StaIface::setExternalSimInternal(bool useExternalSim)
936{
937	return iface_config_utils::setExternalSim(
938	    retrieveIfacePtr(), useExternalSim);
939}
940
941std::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
971SupplicantStatus 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
998SupplicantStatus 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 */
1011wpa_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