Home | History | Annotate | Download | only in 1.2
      1 /*
      2  * hidl interface for wpa_supplicant daemon
      3  * Copyright (c) 2004-2016, Jouni Malinen <j (at) w1.fi>
      4  * Copyright (c) 2004-2016, Roshan Pius <rpius (at) 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 {
     18 #include "utils/eloop.h"
     19 #include "gas_query.h"
     20 #include "interworking.h"
     21 #include "hs20_supplicant.h"
     22 #include "wps_supplicant.h"
     23 #include "dpp_supplicant.h"
     24 #include "dpp.h"
     25 }
     26 
     27 namespace {
     28 using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
     29 using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
     30 using android::hardware::wifi::supplicant::V1_2::ISupplicantStaIface;
     31 using android::hardware::wifi::supplicant::V1_2::implementation::HidlManager;
     32 
     33 constexpr uint32_t kMaxAnqpElems = 100;
     34 constexpr char kGetMacAddress[] = "MACADDR";
     35 constexpr char kStartRxFilter[] = "RXFILTER-START";
     36 constexpr char kStopRxFilter[] = "RXFILTER-STOP";
     37 constexpr char kAddRxFilter[] = "RXFILTER-ADD";
     38 constexpr char kRemoveRxFilter[] = "RXFILTER-REMOVE";
     39 constexpr char kSetBtCoexistenceMode[] = "BTCOEXMODE";
     40 constexpr char kSetBtCoexistenceScanStart[] = "BTCOEXSCAN-START";
     41 constexpr char kSetBtCoexistenceScanStop[] = "BTCOEXSCAN-STOP";
     42 constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
     43 constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
     44 constexpr char kSetCountryCode[] = "COUNTRY";
     45 constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec = static_cast<uint32_t>(
     46     ISupplicantStaIface::ExtRadioWorkDefaults::TIMEOUT_IN_SECS);
     47 constexpr char kExtRadioWorkNamePrefix[] = "ext:";
     48 
     49 uint8_t convertHidlRxFilterTypeToInternal(
     50     ISupplicantStaIface::RxFilterType type)
     51 {
     52 	switch (type) {
     53 	case ISupplicantStaIface::RxFilterType::V4_MULTICAST:
     54 		return 2;
     55 	case ISupplicantStaIface::RxFilterType::V6_MULTICAST:
     56 		return 3;
     57 	};
     58 	WPA_ASSERT(false);
     59 }
     60 
     61 uint8_t convertHidlBtCoexModeToInternal(
     62     ISupplicantStaIface::BtCoexistenceMode mode)
     63 {
     64 	switch (mode) {
     65 	case ISupplicantStaIface::BtCoexistenceMode::ENABLED:
     66 		return 0;
     67 	case ISupplicantStaIface::BtCoexistenceMode::DISABLED:
     68 		return 1;
     69 	case ISupplicantStaIface::BtCoexistenceMode::SENSE:
     70 		return 2;
     71 	};
     72 	WPA_ASSERT(false);
     73 }
     74 
     75 SupplicantStatus doZeroArgDriverCommand(
     76     struct wpa_supplicant *wpa_s, const char *cmd)
     77 {
     78 	std::vector<char> cmd_vec(cmd, cmd + strlen(cmd) + 1);
     79 	char driver_cmd_reply_buf[4096] = {};
     80 	if (wpa_drv_driver_cmd(
     81 		wpa_s, cmd_vec.data(), driver_cmd_reply_buf,
     82 		sizeof(driver_cmd_reply_buf))) {
     83 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
     84 	}
     85 	return {SupplicantStatusCode::SUCCESS, ""};
     86 }
     87 
     88 SupplicantStatus doOneArgDriverCommand(
     89     struct wpa_supplicant *wpa_s, const char *cmd, uint8_t arg)
     90 {
     91 	std::string cmd_str = std::string(cmd) + " " + std::to_string(arg);
     92 	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
     93 }
     94 
     95 SupplicantStatus doOneArgDriverCommand(
     96     struct wpa_supplicant *wpa_s, const char *cmd, const std::string &arg)
     97 {
     98 	std::string cmd_str = std::string(cmd) + " " + arg;
     99 	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
    100 }
    101 
    102 void endExtRadioWork(struct wpa_radio_work *work)
    103 {
    104 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
    105 	work->wpa_s->ext_work_in_progress = 0;
    106 	radio_work_done(work);
    107 	os_free(ework);
    108 }
    109 
    110 void extRadioWorkTimeoutCb(void *eloop_ctx, void *timeout_ctx)
    111 {
    112 	auto *work = static_cast<struct wpa_radio_work *>(eloop_ctx);
    113 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
    114 	wpa_dbg(
    115 	    work->wpa_s, MSG_DEBUG, "Timing out external radio work %u (%s)",
    116 	    ework->id, work->type);
    117 
    118 	HidlManager *hidl_manager = HidlManager::getInstance();
    119 	WPA_ASSERT(hidl_manager);
    120 	hidl_manager->notifyExtRadioWorkTimeout(work->wpa_s, ework->id);
    121 
    122 	endExtRadioWork(work);
    123 }
    124 
    125 void startExtRadioWork(struct wpa_radio_work *work)
    126 {
    127 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
    128 	work->wpa_s->ext_work_in_progress = 1;
    129 	if (!ework->timeout) {
    130 		ework->timeout = kExtRadioWorkDefaultTimeoutInSec;
    131 	}
    132 	eloop_register_timeout(
    133 	    ework->timeout, 0, extRadioWorkTimeoutCb, work, nullptr);
    134 }
    135 
    136 void extRadioWorkStartCb(struct wpa_radio_work *work, int deinit)
    137 {
    138 	// deinit==1 is invoked during interface removal. Since the HIDL
    139 	// interface does not support interface addition/removal, we don't
    140 	// need to handle this scenario.
    141 	WPA_ASSERT(!deinit);
    142 
    143 	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
    144 	wpa_dbg(
    145 	    work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
    146 	    ework->id, ework->type);
    147 
    148 	HidlManager *hidl_manager = HidlManager::getInstance();
    149 	WPA_ASSERT(hidl_manager);
    150 	hidl_manager->notifyExtRadioWorkStart(work->wpa_s, ework->id);
    151 
    152 	startExtRadioWork(work);
    153 }
    154 
    155 }  // namespace
    156 
    157 namespace android {
    158 namespace hardware {
    159 namespace wifi {
    160 namespace supplicant {
    161 namespace V1_2 {
    162 namespace implementation {
    163 using hidl_return_util::validateAndCall;
    164 
    165 using namespace android::hardware::wifi::supplicant::V1_0;
    166 using namespace android::hardware::wifi::supplicant::V1_1;
    167 using V1_0::ISupplicantStaIfaceCallback;
    168 
    169 StaIface::StaIface(struct wpa_global *wpa_global, const char ifname[])
    170     : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
    171 {}
    172 
    173 void StaIface::invalidate() { is_valid_ = false; }
    174 bool StaIface::isValid()
    175 {
    176 	return (is_valid_ && (retrieveIfacePtr() != nullptr));
    177 }
    178 
    179 Return<void> StaIface::getName(getName_cb _hidl_cb)
    180 {
    181 	return validateAndCall(
    182 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    183 	    &StaIface::getNameInternal, _hidl_cb);
    184 }
    185 
    186 Return<void> StaIface::getType(getType_cb _hidl_cb)
    187 {
    188 	return validateAndCall(
    189 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    190 	    &StaIface::getTypeInternal, _hidl_cb);
    191 }
    192 
    193 Return<void> StaIface::addNetwork(addNetwork_cb _hidl_cb)
    194 {
    195 	return validateAndCall(
    196 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    197 	    &StaIface::addNetworkInternal, _hidl_cb);
    198 }
    199 
    200 Return<void> StaIface::removeNetwork(
    201     SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
    202 {
    203 	return validateAndCall(
    204 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    205 	    &StaIface::removeNetworkInternal, _hidl_cb, id);
    206 }
    207 
    208 Return<void> StaIface::getNetwork(
    209     SupplicantNetworkId id, getNetwork_cb _hidl_cb)
    210 {
    211 	return validateAndCall(
    212 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    213 	    &StaIface::getNetworkInternal, _hidl_cb, id);
    214 }
    215 
    216 Return<void> StaIface::listNetworks(listNetworks_cb _hidl_cb)
    217 {
    218 	return validateAndCall(
    219 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    220 	    &StaIface::listNetworksInternal, _hidl_cb);
    221 }
    222 
    223 Return<void> StaIface::registerCallback(
    224     const sp<ISupplicantStaIfaceCallback> &callback,
    225     registerCallback_cb _hidl_cb)
    226 {
    227 	return validateAndCall(
    228 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    229 	    &StaIface::registerCallbackInternal, _hidl_cb, callback);
    230 }
    231 
    232 Return<void> StaIface::registerCallback_1_1(
    233     const sp<V1_1::ISupplicantStaIfaceCallback> &callback,
    234     registerCallback_cb _hidl_cb)
    235 {
    236 	sp<V1_0::ISupplicantStaIfaceCallback> callback_1_0 = callback;
    237 	return validateAndCall(
    238 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    239 	    &StaIface::registerCallbackInternal, _hidl_cb, callback_1_0);
    240 }
    241 
    242 Return<void> StaIface::registerCallback_1_2(
    243     const sp<V1_2::ISupplicantStaIfaceCallback> &callback,
    244     registerCallback_cb _hidl_cb)
    245 {
    246 	sp<V1_1::ISupplicantStaIfaceCallback> callback_1_1 = callback;
    247 	return validateAndCall(
    248 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    249 	    &StaIface::registerCallbackInternal, _hidl_cb, callback_1_1);
    250 }
    251 
    252 Return<void> StaIface::reassociate(reassociate_cb _hidl_cb)
    253 {
    254 	return validateAndCall(
    255 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    256 	    &StaIface::reassociateInternal, _hidl_cb);
    257 }
    258 
    259 Return<void> StaIface::reconnect(reconnect_cb _hidl_cb)
    260 {
    261 	return validateAndCall(
    262 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    263 	    &StaIface::reconnectInternal, _hidl_cb);
    264 }
    265 
    266 Return<void> StaIface::disconnect(disconnect_cb _hidl_cb)
    267 {
    268 	return validateAndCall(
    269 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    270 	    &StaIface::disconnectInternal, _hidl_cb);
    271 }
    272 
    273 Return<void> StaIface::setPowerSave(bool enable, setPowerSave_cb _hidl_cb)
    274 {
    275 	return validateAndCall(
    276 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    277 	    &StaIface::setPowerSaveInternal, _hidl_cb, enable);
    278 }
    279 
    280 Return<void> StaIface::initiateTdlsDiscover(
    281     const hidl_array<uint8_t, 6> &mac_address, initiateTdlsDiscover_cb _hidl_cb)
    282 {
    283 	return validateAndCall(
    284 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    285 	    &StaIface::initiateTdlsDiscoverInternal, _hidl_cb, mac_address);
    286 }
    287 
    288 Return<void> StaIface::initiateTdlsSetup(
    289     const hidl_array<uint8_t, 6> &mac_address, initiateTdlsSetup_cb _hidl_cb)
    290 {
    291 	return validateAndCall(
    292 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    293 	    &StaIface::initiateTdlsSetupInternal, _hidl_cb, mac_address);
    294 }
    295 
    296 Return<void> StaIface::initiateTdlsTeardown(
    297     const hidl_array<uint8_t, 6> &mac_address, initiateTdlsTeardown_cb _hidl_cb)
    298 {
    299 	return validateAndCall(
    300 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    301 	    &StaIface::initiateTdlsTeardownInternal, _hidl_cb, mac_address);
    302 }
    303 Return<void> StaIface::initiateAnqpQuery(
    304     const hidl_array<uint8_t, 6> &mac_address,
    305     const hidl_vec<ISupplicantStaIface::AnqpInfoId> &info_elements,
    306     const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types,
    307     initiateAnqpQuery_cb _hidl_cb)
    308 {
    309 	return validateAndCall(
    310 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    311 	    &StaIface::initiateAnqpQueryInternal, _hidl_cb, mac_address,
    312 	    info_elements, sub_types);
    313 }
    314 
    315 Return<void> StaIface::initiateHs20IconQuery(
    316     const hidl_array<uint8_t, 6> &mac_address, const hidl_string &file_name,
    317     initiateHs20IconQuery_cb _hidl_cb)
    318 {
    319 	return validateAndCall(
    320 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    321 	    &StaIface::initiateHs20IconQueryInternal, _hidl_cb, mac_address,
    322 	    file_name);
    323 }
    324 
    325 Return<void> StaIface::getMacAddress(getMacAddress_cb _hidl_cb)
    326 {
    327 	return validateAndCall(
    328 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    329 	    &StaIface::getMacAddressInternal, _hidl_cb);
    330 }
    331 
    332 Return<void> StaIface::startRxFilter(startRxFilter_cb _hidl_cb)
    333 {
    334 	return validateAndCall(
    335 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    336 	    &StaIface::startRxFilterInternal, _hidl_cb);
    337 }
    338 
    339 Return<void> StaIface::stopRxFilter(stopRxFilter_cb _hidl_cb)
    340 {
    341 	return validateAndCall(
    342 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    343 	    &StaIface::stopRxFilterInternal, _hidl_cb);
    344 }
    345 
    346 Return<void> StaIface::addRxFilter(
    347     ISupplicantStaIface::RxFilterType type, addRxFilter_cb _hidl_cb)
    348 {
    349 	return validateAndCall(
    350 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    351 	    &StaIface::addRxFilterInternal, _hidl_cb, type);
    352 }
    353 
    354 Return<void> StaIface::removeRxFilter(
    355     ISupplicantStaIface::RxFilterType type, removeRxFilter_cb _hidl_cb)
    356 {
    357 	return validateAndCall(
    358 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    359 	    &StaIface::removeRxFilterInternal, _hidl_cb, type);
    360 }
    361 
    362 Return<void> StaIface::setBtCoexistenceMode(
    363     ISupplicantStaIface::BtCoexistenceMode mode,
    364     setBtCoexistenceMode_cb _hidl_cb)
    365 {
    366 	return validateAndCall(
    367 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    368 	    &StaIface::setBtCoexistenceModeInternal, _hidl_cb, mode);
    369 }
    370 
    371 Return<void> StaIface::setBtCoexistenceScanModeEnabled(
    372     bool enable, setBtCoexistenceScanModeEnabled_cb _hidl_cb)
    373 {
    374 	return validateAndCall(
    375 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    376 	    &StaIface::setBtCoexistenceScanModeEnabledInternal, _hidl_cb,
    377 	    enable);
    378 }
    379 
    380 Return<void> StaIface::setSuspendModeEnabled(
    381     bool enable, setSuspendModeEnabled_cb _hidl_cb)
    382 {
    383 	return validateAndCall(
    384 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    385 	    &StaIface::setSuspendModeEnabledInternal, _hidl_cb, enable);
    386 }
    387 
    388 Return<void> StaIface::setCountryCode(
    389     const hidl_array<int8_t, 2> &code, setCountryCode_cb _hidl_cb)
    390 {
    391 	return validateAndCall(
    392 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    393 	    &StaIface::setCountryCodeInternal, _hidl_cb, code);
    394 }
    395 
    396 Return<void> StaIface::startWpsRegistrar(
    397     const hidl_array<uint8_t, 6> &bssid, const hidl_string &pin,
    398     startWpsRegistrar_cb _hidl_cb)
    399 {
    400 	return validateAndCall(
    401 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    402 	    &StaIface::startWpsRegistrarInternal, _hidl_cb, bssid, pin);
    403 }
    404 
    405 Return<void> StaIface::startWpsPbc(
    406     const hidl_array<uint8_t, 6> &bssid, startWpsPbc_cb _hidl_cb)
    407 {
    408 	return validateAndCall(
    409 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    410 	    &StaIface::startWpsPbcInternal, _hidl_cb, bssid);
    411 }
    412 
    413 Return<void> StaIface::startWpsPinKeypad(
    414     const hidl_string &pin, startWpsPinKeypad_cb _hidl_cb)
    415 {
    416 	return validateAndCall(
    417 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    418 	    &StaIface::startWpsPinKeypadInternal, _hidl_cb, pin);
    419 }
    420 
    421 Return<void> StaIface::startWpsPinDisplay(
    422     const hidl_array<uint8_t, 6> &bssid, startWpsPinDisplay_cb _hidl_cb)
    423 {
    424 	return validateAndCall(
    425 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    426 	    &StaIface::startWpsPinDisplayInternal, _hidl_cb, bssid);
    427 }
    428 
    429 Return<void> StaIface::cancelWps(cancelWps_cb _hidl_cb)
    430 {
    431 	return validateAndCall(
    432 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    433 	    &StaIface::cancelWpsInternal, _hidl_cb);
    434 }
    435 
    436 Return<void> StaIface::setWpsDeviceName(
    437     const hidl_string &name, setWpsDeviceName_cb _hidl_cb)
    438 {
    439 	return validateAndCall(
    440 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    441 	    &StaIface::setWpsDeviceNameInternal, _hidl_cb, name);
    442 }
    443 
    444 Return<void> StaIface::setWpsDeviceType(
    445     const hidl_array<uint8_t, 8> &type, setWpsDeviceType_cb _hidl_cb)
    446 {
    447 	return validateAndCall(
    448 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    449 	    &StaIface::setWpsDeviceTypeInternal, _hidl_cb, type);
    450 }
    451 
    452 Return<void> StaIface::setWpsManufacturer(
    453     const hidl_string &manufacturer, setWpsManufacturer_cb _hidl_cb)
    454 {
    455 	return validateAndCall(
    456 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    457 	    &StaIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
    458 }
    459 
    460 Return<void> StaIface::setWpsModelName(
    461     const hidl_string &model_name, setWpsModelName_cb _hidl_cb)
    462 {
    463 	return validateAndCall(
    464 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    465 	    &StaIface::setWpsModelNameInternal, _hidl_cb, model_name);
    466 }
    467 
    468 Return<void> StaIface::setWpsModelNumber(
    469     const hidl_string &model_number, setWpsModelNumber_cb _hidl_cb)
    470 {
    471 	return validateAndCall(
    472 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    473 	    &StaIface::setWpsModelNumberInternal, _hidl_cb, model_number);
    474 }
    475 
    476 Return<void> StaIface::setWpsSerialNumber(
    477     const hidl_string &serial_number, setWpsSerialNumber_cb _hidl_cb)
    478 {
    479 	return validateAndCall(
    480 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    481 	    &StaIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
    482 }
    483 
    484 Return<void> StaIface::setWpsConfigMethods(
    485     uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
    486 {
    487 	return validateAndCall(
    488 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    489 	    &StaIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
    490 }
    491 
    492 Return<void> StaIface::setExternalSim(
    493     bool useExternalSim, setExternalSim_cb _hidl_cb)
    494 {
    495 	return validateAndCall(
    496 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    497 	    &StaIface::setExternalSimInternal, _hidl_cb, useExternalSim);
    498 }
    499 
    500 Return<void> StaIface::addExtRadioWork(
    501     const hidl_string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec,
    502     addExtRadioWork_cb _hidl_cb)
    503 {
    504 	return validateAndCall(
    505 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    506 	    &StaIface::addExtRadioWorkInternal, _hidl_cb, name, freq_in_mhz,
    507 	    timeout_in_sec);
    508 }
    509 
    510 Return<void> StaIface::removeExtRadioWork(
    511     uint32_t id, removeExtRadioWork_cb _hidl_cb)
    512 {
    513 	return validateAndCall(
    514 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    515 	    &StaIface::removeExtRadioWorkInternal, _hidl_cb, id);
    516 }
    517 
    518 Return<void> StaIface::enableAutoReconnect(
    519     bool enable, enableAutoReconnect_cb _hidl_cb)
    520 {
    521 	return validateAndCall(
    522 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    523 	    &StaIface::enableAutoReconnectInternal, _hidl_cb, enable);
    524 }
    525 
    526 Return<void> StaIface::getKeyMgmtCapabilities(
    527     getKeyMgmtCapabilities_cb _hidl_cb)
    528 {
    529 	return validateAndCall(
    530 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
    531 	    &StaIface::getKeyMgmtCapabilitiesInternal, _hidl_cb);
    532 }
    533 
    534 Return<void> StaIface::addDppPeerUri(const hidl_string& uri,
    535 		addDppPeerUri_cb _hidl_cb)
    536 {
    537 	return validateAndCall(
    538 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
    539 	    &StaIface::addDppPeerUriInternal, _hidl_cb, uri);
    540 }
    541 
    542 Return<void> StaIface::removeDppUri(uint32_t bootstrap_id,
    543 		removeDppUri_cb _hidl_cb)
    544 {
    545 	return validateAndCall(
    546 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
    547 	    &StaIface::removeDppUriInternal, _hidl_cb, bootstrap_id);
    548 }
    549 
    550 Return<void> StaIface::startDppConfiguratorInitiator(uint32_t peer_bootstrap_id,
    551 		uint32_t own_bootstrap_id, const hidl_string& ssid,
    552 		const hidl_string& password, const hidl_string& psk,
    553 		DppNetRole net_role, DppAkm security_akm,
    554 		startDppConfiguratorInitiator_cb _hidl_cb)
    555 {
    556 	return validateAndCall(
    557 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
    558 	    &StaIface::startDppConfiguratorInitiatorInternal, _hidl_cb, peer_bootstrap_id,
    559 		own_bootstrap_id, ssid, password, psk, net_role, security_akm);
    560 }
    561 
    562 Return<void> StaIface::startDppEnrolleeInitiator(uint32_t peer_bootstrap_id,
    563 		uint32_t own_bootstrap_id, startDppConfiguratorInitiator_cb _hidl_cb)
    564 {
    565 	return validateAndCall(
    566 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
    567 	    &StaIface::startDppEnrolleeInitiatorInternal, _hidl_cb, peer_bootstrap_id,
    568 		own_bootstrap_id);
    569 }
    570 
    571 Return<void> StaIface::stopDppInitiator(stopDppInitiator_cb _hidl_cb)
    572 {
    573 	return validateAndCall(
    574 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
    575 	    &StaIface::stopDppInitiatorInternal, _hidl_cb);
    576 }
    577 
    578 std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
    579 {
    580 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
    581 }
    582 
    583 std::pair<SupplicantStatus, IfaceType> StaIface::getTypeInternal()
    584 {
    585 	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::STA};
    586 }
    587 
    588 std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
    589 StaIface::addNetworkInternal()
    590 {
    591 	android::sp<ISupplicantStaNetwork> network;
    592 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    593 	struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
    594 	if (!ssid) {
    595 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
    596 	}
    597 	HidlManager *hidl_manager = HidlManager::getInstance();
    598 	if (!hidl_manager ||
    599 	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
    600 		wpa_s->ifname, ssid->id, &network)) {
    601 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
    602 	}
    603 	return {{SupplicantStatusCode::SUCCESS, ""}, network};
    604 }
    605 
    606 SupplicantStatus StaIface::removeNetworkInternal(SupplicantNetworkId id)
    607 {
    608 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    609 	int result = wpa_supplicant_remove_network(wpa_s, id);
    610 	if (result == -1) {
    611 		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
    612 	}
    613 	if (result != 0) {
    614 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    615 	}
    616 	return {SupplicantStatusCode::SUCCESS, ""};
    617 }
    618 
    619 std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
    620 StaIface::getNetworkInternal(SupplicantNetworkId id)
    621 {
    622 	android::sp<ISupplicantStaNetwork> network;
    623 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    624 	struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);
    625 	if (!ssid) {
    626 		return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
    627 			network};
    628 	}
    629 	HidlManager *hidl_manager = HidlManager::getInstance();
    630 	if (!hidl_manager ||
    631 	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
    632 		wpa_s->ifname, ssid->id, &network)) {
    633 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
    634 	}
    635 	return {{SupplicantStatusCode::SUCCESS, ""}, network};
    636 }
    637 
    638 std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
    639 StaIface::listNetworksInternal()
    640 {
    641 	std::vector<SupplicantNetworkId> network_ids;
    642 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    643 	for (struct wpa_ssid *wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
    644 	     wpa_ssid = wpa_ssid->next) {
    645 		network_ids.emplace_back(wpa_ssid->id);
    646 	}
    647 	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
    648 }
    649 
    650 SupplicantStatus StaIface::registerCallbackInternal(
    651     const sp<ISupplicantStaIfaceCallback> &callback)
    652 {
    653 	HidlManager *hidl_manager = HidlManager::getInstance();
    654 	if (!hidl_manager ||
    655 	    hidl_manager->addStaIfaceCallbackHidlObject(ifname_, callback)) {
    656 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    657 	}
    658 	return {SupplicantStatusCode::SUCCESS, ""};
    659 }
    660 
    661 SupplicantStatus StaIface::reassociateInternal()
    662 {
    663 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    664 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    665 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
    666 	}
    667 	wpas_request_connection(wpa_s);
    668 	return {SupplicantStatusCode::SUCCESS, ""};
    669 }
    670 
    671 SupplicantStatus StaIface::reconnectInternal()
    672 {
    673 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    674 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    675 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
    676 	}
    677 	if (!wpa_s->disconnected) {
    678 		return {SupplicantStatusCode::FAILURE_IFACE_NOT_DISCONNECTED,
    679 			""};
    680 	}
    681 	wpas_request_connection(wpa_s);
    682 	return {SupplicantStatusCode::SUCCESS, ""};
    683 }
    684 
    685 SupplicantStatus StaIface::disconnectInternal()
    686 {
    687 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    688 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    689 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
    690 	}
    691 	wpas_request_disconnection(wpa_s);
    692 	return {SupplicantStatusCode::SUCCESS, ""};
    693 }
    694 
    695 SupplicantStatus StaIface::setPowerSaveInternal(bool enable)
    696 {
    697 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    698 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    699 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
    700 	}
    701 	if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
    702 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    703 	}
    704 	return {SupplicantStatusCode::SUCCESS, ""};
    705 }
    706 
    707 SupplicantStatus StaIface::initiateTdlsDiscoverInternal(
    708     const std::array<uint8_t, 6> &mac_address)
    709 {
    710 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    711 	int ret;
    712 	const u8 *peer = mac_address.data();
    713 	if (wpa_tdls_is_external_setup(wpa_s->wpa)) {
    714 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
    715 	} else {
    716 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
    717 	}
    718 	if (ret) {
    719 		wpa_printf(MSG_INFO, "StaIface: TDLS discover failed: %d", ret);
    720 	}
    721 	return {SupplicantStatusCode::SUCCESS, ""};
    722 }
    723 
    724 SupplicantStatus StaIface::initiateTdlsSetupInternal(
    725     const std::array<uint8_t, 6> &mac_address)
    726 {
    727 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    728 	int ret;
    729 	const u8 *peer = mac_address.data();
    730 	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
    731 	    !(wpa_s->conf->tdls_external_control)) {
    732 		wpa_tdls_remove(wpa_s->wpa, peer);
    733 		ret = wpa_tdls_start(wpa_s->wpa, peer);
    734 	} else {
    735 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
    736 	}
    737 	if (ret) {
    738 		wpa_printf(MSG_INFO, "StaIface: TDLS setup failed: %d", ret);
    739 	}
    740 	return {SupplicantStatusCode::SUCCESS, ""};
    741 }
    742 
    743 SupplicantStatus StaIface::initiateTdlsTeardownInternal(
    744     const std::array<uint8_t, 6> &mac_address)
    745 {
    746 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    747 	int ret;
    748 	const u8 *peer = mac_address.data();
    749 	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
    750 	    !(wpa_s->conf->tdls_external_control)) {
    751 		ret = wpa_tdls_teardown_link(
    752 		    wpa_s->wpa, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
    753 	} else {
    754 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
    755 	}
    756 	if (ret) {
    757 		wpa_printf(MSG_INFO, "StaIface: TDLS teardown failed: %d", ret);
    758 	}
    759 	return {SupplicantStatusCode::SUCCESS, ""};
    760 }
    761 
    762 SupplicantStatus StaIface::initiateAnqpQueryInternal(
    763     const std::array<uint8_t, 6> &mac_address,
    764     const std::vector<ISupplicantStaIface::AnqpInfoId> &info_elements,
    765     const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types)
    766 {
    767 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    768 	if (info_elements.size() > kMaxAnqpElems) {
    769 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
    770 	}
    771 	uint16_t info_elems_buf[kMaxAnqpElems];
    772 	uint32_t num_info_elems = 0;
    773 	for (const auto &info_element : info_elements) {
    774 		info_elems_buf[num_info_elems++] =
    775 		    static_cast<std::underlying_type<
    776 			ISupplicantStaIface::AnqpInfoId>::type>(info_element);
    777 	}
    778 	uint32_t sub_types_bitmask = 0;
    779 	for (const auto &type : sub_types) {
    780 		sub_types_bitmask |= BIT(
    781 		    static_cast<std::underlying_type<
    782 			ISupplicantStaIface::Hs20AnqpSubtypes>::type>(type));
    783 	}
    784 	if (anqp_send_req(
    785 		wpa_s, mac_address.data(), info_elems_buf, num_info_elems,
    786 		sub_types_bitmask, false)) {
    787 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    788 	}
    789 	return {SupplicantStatusCode::SUCCESS, ""};
    790 }
    791 
    792 SupplicantStatus StaIface::initiateHs20IconQueryInternal(
    793     const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
    794 {
    795 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    796 	wpa_s->fetch_osu_icon_in_progress = 0;
    797 	if (hs20_anqp_send_req(
    798 		wpa_s, mac_address.data(), BIT(HS20_STYPE_ICON_REQUEST),
    799 		reinterpret_cast<const uint8_t *>(file_name.c_str()),
    800 		file_name.size(), true)) {
    801 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    802 	}
    803 	return {SupplicantStatusCode::SUCCESS, ""};
    804 }
    805 
    806 std::pair<SupplicantStatus, std::array<uint8_t, 6>>
    807 StaIface::getMacAddressInternal()
    808 {
    809 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    810 	std::vector<char> cmd(
    811 	    kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
    812 	char driver_cmd_reply_buf[4096] = {};
    813 	int ret = wpa_drv_driver_cmd(
    814 	    wpa_s, cmd.data(), driver_cmd_reply_buf,
    815 	    sizeof(driver_cmd_reply_buf));
    816 	// Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
    817 	std::string reply_str = driver_cmd_reply_buf;
    818 	if (ret < 0 || reply_str.empty() ||
    819 	    reply_str.find("=") == std::string::npos) {
    820 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
    821 	}
    822 	// Remove all whitespace first and then split using the delimiter "=".
    823 	reply_str.erase(
    824 	    remove_if(reply_str.begin(), reply_str.end(), isspace),
    825 	    reply_str.end());
    826 	std::string mac_addr_str =
    827 	    reply_str.substr(reply_str.find("=") + 1, reply_str.size());
    828 	std::array<uint8_t, 6> mac_addr;
    829 	if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
    830 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
    831 	}
    832 	return {{SupplicantStatusCode::SUCCESS, ""}, mac_addr};
    833 }
    834 
    835 SupplicantStatus StaIface::startRxFilterInternal()
    836 {
    837 	return doZeroArgDriverCommand(retrieveIfacePtr(), kStartRxFilter);
    838 }
    839 
    840 SupplicantStatus StaIface::stopRxFilterInternal()
    841 {
    842 	return doZeroArgDriverCommand(retrieveIfacePtr(), kStopRxFilter);
    843 }
    844 
    845 SupplicantStatus StaIface::addRxFilterInternal(
    846     ISupplicantStaIface::RxFilterType type)
    847 {
    848 	return doOneArgDriverCommand(
    849 	    retrieveIfacePtr(), kAddRxFilter,
    850 	    convertHidlRxFilterTypeToInternal(type));
    851 }
    852 
    853 SupplicantStatus StaIface::removeRxFilterInternal(
    854     ISupplicantStaIface::RxFilterType type)
    855 {
    856 	return doOneArgDriverCommand(
    857 	    retrieveIfacePtr(), kRemoveRxFilter,
    858 	    convertHidlRxFilterTypeToInternal(type));
    859 }
    860 
    861 SupplicantStatus StaIface::setBtCoexistenceModeInternal(
    862     ISupplicantStaIface::BtCoexistenceMode mode)
    863 {
    864 	return doOneArgDriverCommand(
    865 	    retrieveIfacePtr(), kSetBtCoexistenceMode,
    866 	    convertHidlBtCoexModeToInternal(mode));
    867 }
    868 
    869 SupplicantStatus StaIface::setBtCoexistenceScanModeEnabledInternal(bool enable)
    870 {
    871 	const char *cmd;
    872 	if (enable) {
    873 		cmd = kSetBtCoexistenceScanStart;
    874 	} else {
    875 		cmd = kSetBtCoexistenceScanStop;
    876 	}
    877 	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
    878 }
    879 
    880 SupplicantStatus StaIface::setSuspendModeEnabledInternal(bool enable)
    881 {
    882 	const char *cmd;
    883 	if (enable) {
    884 		cmd = kSetSupendModeEnabled;
    885 	} else {
    886 		cmd = kSetSupendModeDisabled;
    887 	}
    888 	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
    889 }
    890 
    891 SupplicantStatus StaIface::setCountryCodeInternal(
    892     const std::array<int8_t, 2> &code)
    893 {
    894 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    895 	SupplicantStatus status = doOneArgDriverCommand(
    896 	    wpa_s, kSetCountryCode,
    897 	    std::string(std::begin(code), std::end(code)));
    898 	if (status.code != SupplicantStatusCode::SUCCESS) {
    899 		return status;
    900 	}
    901 	struct p2p_data *p2p = wpa_s->global->p2p;
    902 	if (p2p) {
    903 		char country[3];
    904 		country[0] = code[0];
    905 		country[1] = code[1];
    906 		country[2] = 0x04;
    907 		p2p_set_country(p2p, country);
    908 	}
    909 	return {SupplicantStatusCode::SUCCESS, ""};
    910 }
    911 
    912 SupplicantStatus StaIface::startWpsRegistrarInternal(
    913     const std::array<uint8_t, 6> &bssid, const std::string &pin)
    914 {
    915 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    916 	if (wpas_wps_start_reg(wpa_s, bssid.data(), pin.c_str(), nullptr)) {
    917 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    918 	}
    919 	return {SupplicantStatusCode::SUCCESS, ""};
    920 }
    921 
    922 SupplicantStatus StaIface::startWpsPbcInternal(
    923     const std::array<uint8_t, 6> &bssid)
    924 {
    925 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    926 	const uint8_t *bssid_addr =
    927 	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
    928 	if (wpas_wps_start_pbc(wpa_s, bssid_addr, 0, 0)) {
    929 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    930 	}
    931 	return {SupplicantStatusCode::SUCCESS, ""};
    932 }
    933 
    934 SupplicantStatus StaIface::startWpsPinKeypadInternal(const std::string &pin)
    935 {
    936 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    937 	if (wpas_wps_start_pin(
    938 		wpa_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
    939 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    940 	}
    941 	return {SupplicantStatusCode::SUCCESS, ""};
    942 }
    943 
    944 std::pair<SupplicantStatus, std::string> StaIface::startWpsPinDisplayInternal(
    945     const std::array<uint8_t, 6> &bssid)
    946 {
    947 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    948 	const uint8_t *bssid_addr =
    949 	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
    950 	int pin =
    951 	    wpas_wps_start_pin(wpa_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
    952 	if (pin < 0) {
    953 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
    954 	}
    955 	return {{SupplicantStatusCode::SUCCESS, ""},
    956 		misc_utils::convertWpsPinToString(pin)};
    957 }
    958 
    959 SupplicantStatus StaIface::cancelWpsInternal()
    960 {
    961 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
    962 	if (wpas_wps_cancel(wpa_s)) {
    963 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    964 	}
    965 	return {SupplicantStatusCode::SUCCESS, ""};
    966 }
    967 
    968 SupplicantStatus StaIface::setWpsDeviceNameInternal(const std::string &name)
    969 {
    970 	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
    971 }
    972 
    973 SupplicantStatus StaIface::setWpsDeviceTypeInternal(
    974     const std::array<uint8_t, 8> &type)
    975 {
    976 	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
    977 }
    978 
    979 SupplicantStatus StaIface::setWpsManufacturerInternal(
    980     const std::string &manufacturer)
    981 {
    982 	return iface_config_utils::setWpsManufacturer(
    983 	    retrieveIfacePtr(), manufacturer);
    984 }
    985 
    986 SupplicantStatus StaIface::setWpsModelNameInternal(
    987     const std::string &model_name)
    988 {
    989 	return iface_config_utils::setWpsModelName(
    990 	    retrieveIfacePtr(), model_name);
    991 }
    992 
    993 SupplicantStatus StaIface::setWpsModelNumberInternal(
    994     const std::string &model_number)
    995 {
    996 	return iface_config_utils::setWpsModelNumber(
    997 	    retrieveIfacePtr(), model_number);
    998 }
    999 
   1000 SupplicantStatus StaIface::setWpsSerialNumberInternal(
   1001     const std::string &serial_number)
   1002 {
   1003 	return iface_config_utils::setWpsSerialNumber(
   1004 	    retrieveIfacePtr(), serial_number);
   1005 }
   1006 
   1007 SupplicantStatus StaIface::setWpsConfigMethodsInternal(uint16_t config_methods)
   1008 {
   1009 	return iface_config_utils::setWpsConfigMethods(
   1010 	    retrieveIfacePtr(), config_methods);
   1011 }
   1012 
   1013 SupplicantStatus StaIface::setExternalSimInternal(bool useExternalSim)
   1014 {
   1015 	return iface_config_utils::setExternalSim(
   1016 	    retrieveIfacePtr(), useExternalSim);
   1017 }
   1018 
   1019 std::pair<SupplicantStatus, uint32_t> StaIface::addExtRadioWorkInternal(
   1020     const std::string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec)
   1021 {
   1022 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1023 	auto *ework = static_cast<struct wpa_external_work *>(
   1024 	    os_zalloc(sizeof(struct wpa_external_work)));
   1025 	if (!ework) {
   1026 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
   1027 			UINT32_MAX};
   1028 	}
   1029 
   1030 	std::string radio_work_name = kExtRadioWorkNamePrefix + name;
   1031 	os_strlcpy(ework->type, radio_work_name.c_str(), sizeof(ework->type));
   1032 	ework->timeout = timeout_in_sec;
   1033 	wpa_s->ext_work_id++;
   1034 	if (wpa_s->ext_work_id == 0) {
   1035 		wpa_s->ext_work_id++;
   1036 	}
   1037 	ework->id = wpa_s->ext_work_id;
   1038 
   1039 	if (radio_add_work(
   1040 		wpa_s, freq_in_mhz, ework->type, 0, extRadioWorkStartCb,
   1041 		ework)) {
   1042 		os_free(ework);
   1043 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
   1044 			UINT32_MAX};
   1045 	}
   1046 	return {SupplicantStatus{SupplicantStatusCode::SUCCESS, ""}, ework->id};
   1047 }
   1048 
   1049 SupplicantStatus StaIface::removeExtRadioWorkInternal(uint32_t id)
   1050 {
   1051 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1052 	struct wpa_radio_work *work;
   1053 	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
   1054 	{
   1055 		if (os_strncmp(
   1056 			work->type, kExtRadioWorkNamePrefix,
   1057 			sizeof(kExtRadioWorkNamePrefix)) != 0)
   1058 			continue;
   1059 
   1060 		auto *ework =
   1061 		    static_cast<struct wpa_external_work *>(work->ctx);
   1062 		if (ework->id != id)
   1063 			continue;
   1064 
   1065 		wpa_dbg(
   1066 		    wpa_s, MSG_DEBUG, "Completed external radio work %u (%s)",
   1067 		    ework->id, ework->type);
   1068 		eloop_cancel_timeout(extRadioWorkTimeoutCb, work, NULL);
   1069 		endExtRadioWork(work);
   1070 
   1071 		return {SupplicantStatusCode::SUCCESS, ""};
   1072 	}
   1073 	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1074 }
   1075 
   1076 SupplicantStatus StaIface::enableAutoReconnectInternal(bool enable)
   1077 {
   1078 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1079 	wpa_s->auto_reconnect_disabled = enable ? 0 : 1;
   1080 	return {SupplicantStatusCode::SUCCESS, ""};
   1081 }
   1082 
   1083 std::pair<SupplicantStatus, uint32_t>
   1084 StaIface::getKeyMgmtCapabilitiesInternal()
   1085 {
   1086 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1087 	struct wpa_driver_capa capa;
   1088 	uint32_t mask = 0;
   1089 
   1090 	/* Get capabilities from driver and populate the key management mask */
   1091 	if (wpa_drv_get_capa(wpa_s, &capa) < 0) {
   1092 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, mask};
   1093 	}
   1094 
   1095 	/* Logic from ctrl_iface.c, NONE and IEEE8021X have no capability
   1096 	 * flags and always enabled.
   1097 	 */
   1098 	mask |=
   1099 	    (ISupplicantStaNetwork::KeyMgmtMask::NONE |
   1100 	     ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X);
   1101 
   1102 	if (capa.key_mgmt &
   1103 	    (WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
   1104 		mask |= ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP;
   1105 	}
   1106 
   1107 	if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
   1108 			     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   1109 		mask |= ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK;
   1110 	}
   1111 #ifdef CONFIG_SUITEB192
   1112 	if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
   1113 		mask |= ISupplicantStaNetwork::KeyMgmtMask::SUITE_B_192;
   1114 	}
   1115 #endif /* CONFIG_SUITEB192 */
   1116 #ifdef CONFIG_OWE
   1117 	if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
   1118 		mask |= ISupplicantStaNetwork::KeyMgmtMask::OWE;
   1119 	}
   1120 #endif /* CONFIG_OWE */
   1121 #ifdef CONFIG_SAE
   1122 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
   1123 		mask |= ISupplicantStaNetwork::KeyMgmtMask::SAE;
   1124 	}
   1125 #endif /* CONFIG_SAE */
   1126 #ifdef CONFIG_DPP
   1127 	if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
   1128 		mask |= ISupplicantStaNetwork::KeyMgmtMask::DPP;
   1129 	}
   1130 #endif
   1131 	return {{SupplicantStatusCode::SUCCESS, ""}, mask};
   1132 }
   1133 
   1134 std::pair<SupplicantStatus, uint32_t>
   1135 StaIface::addDppPeerUriInternal(const std::string& uri)
   1136 {
   1137 #ifdef CONFIG_DPP
   1138 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1139 	int32_t id;
   1140 
   1141 	id = wpas_dpp_qr_code(wpa_s, uri.c_str());
   1142 
   1143 	if (id > 0) {
   1144 		return {{SupplicantStatusCode::SUCCESS, ""}, id};
   1145 	}
   1146 #endif
   1147 	return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, -1};
   1148 }
   1149 
   1150 SupplicantStatus StaIface::removeDppUriInternal(uint32_t bootstrap_id)
   1151 {
   1152 #ifdef CONFIG_DPP
   1153 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1154 	std::string bootstrap_id_str;
   1155 
   1156 	if (bootstrap_id == 0) {
   1157 		bootstrap_id_str = "*";
   1158 	}
   1159 	else {
   1160 		bootstrap_id_str = std::to_string(bootstrap_id);
   1161 	}
   1162 
   1163 	if (dpp_bootstrap_remove(wpa_s->dpp, bootstrap_id_str.c_str()) >= 0) {
   1164 		return {SupplicantStatusCode::SUCCESS, ""};
   1165 	}
   1166 #endif
   1167 	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1168 }
   1169 
   1170 SupplicantStatus StaIface::startDppConfiguratorInitiatorInternal(
   1171 		uint32_t peer_bootstrap_id,	uint32_t own_bootstrap_id,
   1172 		const std::string& ssid, const std::string& password,
   1173 		const std::string& psk, DppNetRole net_role, DppAkm security_akm)
   1174 {
   1175 #ifdef CONFIG_DPP
   1176 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1177 	std::string cmd = "";
   1178 
   1179 	if (net_role != DppNetRole::AP &&
   1180 			net_role != DppNetRole::STA) {
   1181 		wpa_printf(MSG_ERROR,
   1182 			   "DPP: Error: Invalid network role specified: %d", net_role);
   1183 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1184 	}
   1185 
   1186 	cmd += " peer=" + std::to_string(peer_bootstrap_id);
   1187 	cmd += (own_bootstrap_id > 0) ?
   1188 			" own=" + std::to_string(own_bootstrap_id) : "";
   1189 
   1190 	/* Check for supported AKMs */
   1191 	if (security_akm != DppAkm::PSK && security_akm != DppAkm::SAE &&
   1192 			security_akm != DppAkm::PSK_SAE) {
   1193 		wpa_printf(MSG_ERROR, "DPP: Error: invalid AKM specified: %d",
   1194 				security_akm);
   1195 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1196 	}
   1197 
   1198 	/* SAE AKM requires SSID and password to be initialized */
   1199 	if ((security_akm == DppAkm::SAE ||
   1200 			security_akm == DppAkm::PSK_SAE) &&
   1201 			(ssid.empty() || password.empty())) {
   1202 		wpa_printf(MSG_ERROR, "DPP: Error: Password or SSID not specified");
   1203 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1204 	} else if (security_akm == DppAkm::PSK ||
   1205 			security_akm == DppAkm::PSK_SAE) {
   1206 		/* PSK AKM requires SSID and password/psk to be initialized */
   1207 		if (ssid.empty()) {
   1208 			wpa_printf(MSG_ERROR, "DPP: Error: SSID not specified");
   1209 			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1210 		}
   1211 		if (password.empty() && psk.empty()) {
   1212 			wpa_printf(MSG_ERROR, "DPP: Error: Password or PSK not specified");
   1213 			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1214 		}
   1215 	}
   1216 
   1217 	cmd += " role=configurator";
   1218 	cmd += (ssid.empty()) ? "" : " ssid=" + ssid;
   1219 
   1220 	if (!psk.empty()) {
   1221 		cmd += " psk=" + psk;
   1222 	} else {
   1223 		cmd += (password.empty()) ? "" : " pass=" + password;
   1224 	}
   1225 
   1226 	std::string role = "";
   1227 	if (net_role == DppNetRole::AP) {
   1228 		role = "ap-";
   1229 	}
   1230 	else {
   1231 		role = "sta-";
   1232 	}
   1233 
   1234 	switch (security_akm) {
   1235 	case DppAkm::PSK:
   1236 		role += "psk";
   1237 		break;
   1238 
   1239 	case DppAkm::SAE:
   1240 		role += "sae";
   1241 		break;
   1242 
   1243 	case DppAkm::PSK_SAE:
   1244 		role += "psk-sae";
   1245 		break;
   1246 
   1247 	default:
   1248 		wpa_printf(MSG_ERROR,
   1249 			   "DPP: Invalid or unsupported security AKM specified: %d", security_akm);
   1250 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1251 	}
   1252 
   1253 	cmd += " conf=";
   1254 	cmd += role;
   1255 
   1256 	wpa_printf(MSG_DEBUG,
   1257 		   "DPP initiator command: %s", cmd.c_str());
   1258 
   1259 	if (wpas_dpp_auth_init(wpa_s, cmd.c_str()) == 0) {
   1260 		return {SupplicantStatusCode::SUCCESS, ""};
   1261 	}
   1262 #endif
   1263 	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1264 }
   1265 
   1266 SupplicantStatus StaIface::startDppEnrolleeInitiatorInternal(uint32_t peer_bootstrap_id,
   1267 			uint32_t own_bootstrap_id) {
   1268 #ifdef CONFIG_DPP
   1269 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1270 	std::string cmd = "";
   1271 
   1272 	/* Report received configuration to HIDL and create an internal profile */
   1273 	wpa_s->conf->dpp_config_processing = 1;
   1274 
   1275 	cmd += " peer=" + std::to_string(peer_bootstrap_id);
   1276 	cmd += (own_bootstrap_id > 0) ?
   1277 			" own=" + std::to_string(own_bootstrap_id) : "";
   1278 
   1279 	cmd += " role=enrollee";
   1280 
   1281 	wpa_printf(MSG_DEBUG,
   1282 		   "DPP initiator command: %s", cmd.c_str());
   1283 
   1284 	if (wpas_dpp_auth_init(wpa_s, cmd.c_str()) == 0) {
   1285 		return {SupplicantStatusCode::SUCCESS, ""};
   1286 	}
   1287 #endif
   1288 	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1289 }
   1290 SupplicantStatus StaIface::stopDppInitiatorInternal()
   1291 {
   1292 #ifdef CONFIG_DPP
   1293 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
   1294 
   1295 	wpas_dpp_stop(wpa_s);
   1296 	return {SupplicantStatusCode::SUCCESS, ""};
   1297 #else
   1298 	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
   1299 #endif
   1300 }
   1301 
   1302 /**
   1303  * Retrieve the underlying |wpa_supplicant| struct
   1304  * pointer for this iface.
   1305  * If the underlying iface is removed, then all RPC method calls on this object
   1306  * will return failure.
   1307  */
   1308 wpa_supplicant *StaIface::retrieveIfacePtr()
   1309 {
   1310 	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
   1311 }
   1312 }  // namespace implementation
   1313 }  // namespace V1_2
   1314 }  // namespace supplicant
   1315 }  // namespace wifi
   1316 }  // namespace hardware
   1317 }  // namespace android
   1318