blob: ce9aaf71d06b48a7eb42aa52c3129b9281122f0b [file] [log] [blame]
/*
* hidl interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "hidl_manager.h"
#include "hidl_return_util.h"
#include "iface_config_utils.h"
#include "misc_utils.h"
#include "p2p_iface.h"
extern "C" {
#include "wps_supplicant.h"
#include "wifi_display.h"
}
namespace {
const char kConfigMethodStrPbc[] = "pbc";
const char kConfigMethodStrDisplay[] = "display";
const char kConfigMethodStrKeypad[] = "keypad";
constexpr char kSetMiracastMode[] = "MIRACAST ";
constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
using android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
uint8_t convertHidlMiracastModeToInternal(
ISupplicantP2pIface::MiracastMode mode)
{
switch (mode) {
case ISupplicantP2pIface::MiracastMode::DISABLED:
return 0;
case ISupplicantP2pIface::MiracastMode::SOURCE:
return 1;
case ISupplicantP2pIface::MiracastMode::SINK:
return 2;
};
WPA_ASSERT(false);
}
} // namespace
namespace android {
namespace hardware {
namespace wifi {
namespace supplicant {
namespace V1_0 {
namespace implementation {
using hidl_return_util::validateAndCall;
P2pIface::P2pIface(struct wpa_global* wpa_global, const char ifname[])
: wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
{
}
void P2pIface::invalidate() { is_valid_ = false; }
bool P2pIface::isValid()
{
return (is_valid_ && (retrieveIfacePtr() != nullptr));
}
Return<void> P2pIface::getName(getName_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::getNameInternal, _hidl_cb);
}
Return<void> P2pIface::getType(getType_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::getTypeInternal, _hidl_cb);
}
Return<void> P2pIface::addNetwork(addNetwork_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::addNetworkInternal, _hidl_cb);
}
Return<void> P2pIface::removeNetwork(
SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::removeNetworkInternal, _hidl_cb, id);
}
Return<void> P2pIface::getNetwork(
SupplicantNetworkId id, getNetwork_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::getNetworkInternal, _hidl_cb, id);
}
Return<void> P2pIface::listNetworks(listNetworks_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::listNetworksInternal, _hidl_cb);
}
Return<void> P2pIface::registerCallback(
const sp<ISupplicantP2pIfaceCallback>& callback,
registerCallback_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::registerCallbackInternal, _hidl_cb, callback);
}
Return<void> P2pIface::getDeviceAddress(getDeviceAddress_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::getDeviceAddressInternal, _hidl_cb);
}
Return<void> P2pIface::setSsidPostfix(
const hidl_vec<uint8_t>& postfix, setSsidPostfix_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setSsidPostfixInternal, _hidl_cb, postfix);
}
Return<void> P2pIface::setGroupIdle(
const hidl_string& group_ifname, uint32_t timeout_in_sec,
setGroupIdle_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setGroupIdleInternal, _hidl_cb, group_ifname,
timeout_in_sec);
}
Return<void> P2pIface::setPowerSave(
const hidl_string& group_ifname, bool enable, setPowerSave_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setPowerSaveInternal, _hidl_cb, group_ifname, enable);
}
Return<void> P2pIface::find(uint32_t timeout_in_sec, find_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::findInternal, _hidl_cb, timeout_in_sec);
}
Return<void> P2pIface::stopFind(stopFind_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::stopFindInternal, _hidl_cb);
}
Return<void> P2pIface::flush(flush_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::flushInternal, _hidl_cb);
}
Return<void> P2pIface::connect(
const hidl_array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method,
const hidl_string& pre_selected_pin, bool join_existing_group,
bool persistent, uint32_t go_intent, connect_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::connectInternal, _hidl_cb, peer_address,
provision_method, pre_selected_pin, join_existing_group, persistent,
go_intent);
}
Return<void> P2pIface::cancelConnect(cancelConnect_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::cancelConnectInternal, _hidl_cb);
}
Return<void> P2pIface::provisionDiscovery(
const hidl_array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method,
provisionDiscovery_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::provisionDiscoveryInternal, _hidl_cb, peer_address,
provision_method);
}
Return<void> P2pIface::addGroup(
bool persistent, SupplicantNetworkId persistent_network_id,
addGroup_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::addGroupInternal, _hidl_cb, persistent,
persistent_network_id);
}
Return<void> P2pIface::removeGroup(
const hidl_string& group_ifname, removeGroup_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::removeGroupInternal, _hidl_cb, group_ifname);
}
Return<void> P2pIface::reject(
const hidl_array<uint8_t, 6>& peer_address, reject_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::rejectInternal, _hidl_cb, peer_address);
}
Return<void> P2pIface::invite(
const hidl_string& group_ifname,
const hidl_array<uint8_t, 6>& go_device_address,
const hidl_array<uint8_t, 6>& peer_address, invite_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::inviteInternal, _hidl_cb, group_ifname,
go_device_address, peer_address);
}
Return<void> P2pIface::reinvoke(
SupplicantNetworkId persistent_network_id,
const hidl_array<uint8_t, 6>& peer_address, reinvoke_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::reinvokeInternal, _hidl_cb, persistent_network_id,
peer_address);
}
Return<void> P2pIface::configureExtListen(
uint32_t period_in_millis, uint32_t interval_in_millis,
configureExtListen_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::configureExtListenInternal, _hidl_cb, period_in_millis,
interval_in_millis);
}
Return<void> P2pIface::setListenChannel(
uint32_t channel, uint32_t operating_class, setListenChannel_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setListenChannelInternal, _hidl_cb, channel,
operating_class);
}
Return<void> P2pIface::setDisallowedFrequencies(
const hidl_vec<FreqRange>& ranges, setDisallowedFrequencies_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setDisallowedFrequenciesInternal, _hidl_cb, ranges);
}
Return<void> P2pIface::getSsid(
const hidl_array<uint8_t, 6>& peer_address, getSsid_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::getSsidInternal, _hidl_cb, peer_address);
}
Return<void> P2pIface::getGroupCapability(
const hidl_array<uint8_t, 6>& peer_address, getGroupCapability_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::getGroupCapabilityInternal, _hidl_cb, peer_address);
}
Return<void> P2pIface::addBonjourService(
const hidl_vec<uint8_t>& query, const hidl_vec<uint8_t>& response,
addBonjourService_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::addBonjourServiceInternal, _hidl_cb, query, response);
}
Return<void> P2pIface::removeBonjourService(
const hidl_vec<uint8_t>& query, removeBonjourService_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::removeBonjourServiceInternal, _hidl_cb, query);
}
Return<void> P2pIface::addUpnpService(
uint32_t version, const hidl_string& service_name,
addUpnpService_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::addUpnpServiceInternal, _hidl_cb, version, service_name);
}
Return<void> P2pIface::removeUpnpService(
uint32_t version, const hidl_string& service_name,
removeUpnpService_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::removeUpnpServiceInternal, _hidl_cb, version,
service_name);
}
Return<void> P2pIface::flushServices(flushServices_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::flushServicesInternal, _hidl_cb);
}
Return<void> P2pIface::requestServiceDiscovery(
const hidl_array<uint8_t, 6>& peer_address, const hidl_vec<uint8_t>& query,
requestServiceDiscovery_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::requestServiceDiscoveryInternal, _hidl_cb, peer_address,
query);
}
Return<void> P2pIface::cancelServiceDiscovery(
uint64_t identifier, cancelServiceDiscovery_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::cancelServiceDiscoveryInternal, _hidl_cb, identifier);
}
Return<void> P2pIface::setMiracastMode(
ISupplicantP2pIface::MiracastMode mode, setMiracastMode_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setMiracastModeInternal, _hidl_cb, mode);
}
Return<void> P2pIface::startWpsPbc(
const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
startWpsPbc_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::startWpsPbcInternal, _hidl_cb, group_ifname, bssid);
}
Return<void> P2pIface::startWpsPinKeypad(
const hidl_string& group_ifname, const hidl_string& pin,
startWpsPinKeypad_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::startWpsPinKeypadInternal, _hidl_cb, group_ifname, pin);
}
Return<void> P2pIface::startWpsPinDisplay(
const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
startWpsPinDisplay_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::startWpsPinDisplayInternal, _hidl_cb, group_ifname,
bssid);
}
Return<void> P2pIface::cancelWps(
const hidl_string& group_ifname, cancelWps_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::cancelWpsInternal, _hidl_cb, group_ifname);
}
Return<void> P2pIface::setWpsDeviceName(
const hidl_string& name, setWpsDeviceName_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWpsDeviceNameInternal, _hidl_cb, name);
}
Return<void> P2pIface::setWpsDeviceType(
const hidl_array<uint8_t, 8>& type, setWpsDeviceType_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWpsDeviceTypeInternal, _hidl_cb, type);
}
Return<void> P2pIface::setWpsManufacturer(
const hidl_string& manufacturer, setWpsManufacturer_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
}
Return<void> P2pIface::setWpsModelName(
const hidl_string& model_name, setWpsModelName_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWpsModelNameInternal, _hidl_cb, model_name);
}
Return<void> P2pIface::setWpsModelNumber(
const hidl_string& model_number, setWpsModelNumber_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWpsModelNumberInternal, _hidl_cb, model_number);
}
Return<void> P2pIface::setWpsSerialNumber(
const hidl_string& serial_number, setWpsSerialNumber_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
}
Return<void> P2pIface::setWpsConfigMethods(
uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
}
Return<void> P2pIface::enableWfd(bool enable, enableWfd_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::enableWfdInternal, _hidl_cb, enable);
}
Return<void> P2pIface::setWfdDeviceInfo(
const hidl_array<uint8_t, 8>& info, setWfdDeviceInfo_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::setWfdDeviceInfoInternal, _hidl_cb, info);
}
Return<void> P2pIface::createNfcHandoverRequestMessage(
createNfcHandoverRequestMessage_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::createNfcHandoverRequestMessageInternal, _hidl_cb);
}
Return<void> P2pIface::createNfcHandoverSelectMessage(
createNfcHandoverSelectMessage_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::createNfcHandoverSelectMessageInternal, _hidl_cb);
}
Return<void> P2pIface::reportNfcHandoverResponse(
const hidl_vec<uint8_t>& request, reportNfcHandoverResponse_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::reportNfcHandoverResponseInternal, _hidl_cb, request);
}
Return<void> P2pIface::reportNfcHandoverInitiation(
const hidl_vec<uint8_t>& select, reportNfcHandoverInitiation_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::reportNfcHandoverInitiationInternal, _hidl_cb, select);
}
Return<void> P2pIface::saveConfig(saveConfig_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&P2pIface::saveConfigInternal, _hidl_cb);
}
std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
{
return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
}
std::pair<SupplicantStatus, IfaceType> P2pIface::getTypeInternal()
{
return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
}
std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
P2pIface::addNetworkInternal()
{
android::sp<ISupplicantP2pNetwork> network;
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
struct wpa_ssid* ssid = wpa_supplicant_add_network(wpa_s);
if (!ssid) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
}
HidlManager* hidl_manager = HidlManager::getInstance();
if (!hidl_manager ||
hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
wpa_s->ifname, ssid->id, &network)) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
}
return {{SupplicantStatusCode::SUCCESS, ""}, network};
}
SupplicantStatus P2pIface::removeNetworkInternal(SupplicantNetworkId id)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
int result = wpa_supplicant_remove_network(wpa_s, id);
if (result == -1) {
return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
}
if (result != 0) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
P2pIface::getNetworkInternal(SupplicantNetworkId id)
{
android::sp<ISupplicantP2pNetwork> network;
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
struct wpa_ssid* ssid = wpa_config_get_network(wpa_s->conf, id);
if (!ssid) {
return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
network};
}
HidlManager* hidl_manager = HidlManager::getInstance();
if (!hidl_manager ||
hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
wpa_s->ifname, ssid->id, &network)) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
}
return {{SupplicantStatusCode::SUCCESS, ""}, network};
}
std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
P2pIface::listNetworksInternal()
{
std::vector<SupplicantNetworkId> network_ids;
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
for (struct wpa_ssid* wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
wpa_ssid = wpa_ssid->next) {
network_ids.emplace_back(wpa_ssid->id);
}
return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
}
SupplicantStatus P2pIface::registerCallbackInternal(
const sp<ISupplicantP2pIfaceCallback>& callback)
{
HidlManager* hidl_manager = HidlManager::getInstance();
if (!hidl_manager ||
hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
std::pair<SupplicantStatus, std::array<uint8_t, 6>>
P2pIface::getDeviceAddressInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
std::array<uint8_t, 6> addr;
static_assert(ETH_ALEN == addr.size(), "Size mismatch");
os_memcpy(addr.data(), wpa_s->global->p2p_dev_addr, ETH_ALEN);
return {{SupplicantStatusCode::SUCCESS, ""}, {}};
}
SupplicantStatus P2pIface::setSsidPostfixInternal(
const std::vector<uint8_t>& postfix)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (p2p_set_ssid_postfix(
wpa_s->global->p2p, postfix.data(), postfix.size())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::setGroupIdleInternal(
const std::string& group_ifname, uint32_t timeout_in_sec)
{
struct wpa_supplicant* wpa_group_s =
retrieveGroupIfacePtr(group_ifname);
if (!wpa_group_s) {
return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
}
wpa_group_s->conf->p2p_group_idle = timeout_in_sec;
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::setPowerSaveInternal(
const std::string& group_ifname, bool enable)
{
struct wpa_supplicant* wpa_group_s =
retrieveGroupIfacePtr(group_ifname);
if (!wpa_group_s) {
return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
}
if (wpa_drv_set_p2p_powersave(wpa_group_s, enable, -1, -1)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::findInternal(uint32_t timeout_in_sec)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
}
uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
if (wpas_p2p_find(
wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
nullptr, search_delay, 0, nullptr, 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::stopFindInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
}
wpas_p2p_stop_find(wpa_s);
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::flushInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
wpa_s->force_long_sd = 0;
wpas_p2p_stop_find(wpa_s);
wpa_s->parent->p2ps_method_config_any = 0;
if (wpa_s->global->p2p)
p2p_flush(wpa_s->global->p2p);
return {SupplicantStatusCode::SUCCESS, ""};
}
// This method only implements support for subset (needed by Android framework)
// of parameters that can be specified for connect.
std::pair<SupplicantStatus, std::string> P2pIface::connectInternal(
const std::array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method,
const std::string& pre_selected_pin, bool join_existing_group,
bool persistent, uint32_t go_intent)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (go_intent > 15) {
return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
}
p2p_wps_method wps_method = {};
switch (provision_method) {
case WpsProvisionMethod::PBC:
wps_method = WPS_PBC;
break;
case WpsProvisionMethod::DISPLAY:
wps_method = WPS_PIN_DISPLAY;
break;
case WpsProvisionMethod::KEYPAD:
wps_method = WPS_PIN_KEYPAD;
break;
}
int new_pin = wpas_p2p_connect(
wpa_s, peer_address.data(), pre_selected_pin.data(), wps_method,
persistent, false, join_existing_group, false, go_intent, 0, 0, -1,
false, false, false, VHT_CHANWIDTH_USE_HT, nullptr, 0);
if (new_pin < 0) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
std::string pin_ret;
if (provision_method == WpsProvisionMethod::DISPLAY &&
pre_selected_pin.empty()) {
pin_ret = misc_utils::convertWpsPinToString(new_pin);
}
return {{SupplicantStatusCode::SUCCESS, ""}, pin_ret};
}
SupplicantStatus P2pIface::cancelConnectInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpas_p2p_cancel(wpa_s)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::provisionDiscoveryInternal(
const std::array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
p2ps_provision* prov_param;
const char* config_method_str = nullptr;
switch (provision_method) {
case WpsProvisionMethod::PBC:
config_method_str = kConfigMethodStrPbc;
break;
case WpsProvisionMethod::DISPLAY:
config_method_str = kConfigMethodStrDisplay;
break;
case WpsProvisionMethod::KEYPAD:
config_method_str = kConfigMethodStrKeypad;
break;
}
if (wpas_p2p_prov_disc(
wpa_s, peer_address.data(), config_method_str,
WPAS_P2P_PD_FOR_GO_NEG, nullptr)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::addGroupInternal(
bool persistent, SupplicantNetworkId persistent_network_id)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
struct wpa_ssid* ssid =
wpa_config_get_network(wpa_s->conf, persistent_network_id);
if (ssid == NULL) {
if (wpas_p2p_group_add(
wpa_s, persistent, 0, 0, ht40, vht,
VHT_CHANWIDTH_USE_HT)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
} else {
return {SupplicantStatusCode::SUCCESS, ""};
}
} else if (ssid->disabled == 2) {
if (wpas_p2p_group_add_persistent(
wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
VHT_CHANWIDTH_USE_HT, NULL, 0, 0)) {
return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
""};
} else {
return {SupplicantStatusCode::SUCCESS, ""};
}
}
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
SupplicantStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
{
struct wpa_supplicant* wpa_group_s =
retrieveGroupIfacePtr(group_ifname);
if (!wpa_group_s) {
return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
}
if (wpas_p2p_group_remove(wpa_group_s, group_ifname.c_str())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::rejectInternal(
const std::array<uint8_t, 6>& peer_address)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
}
if (wpas_p2p_reject(wpa_s, peer_address.data())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::inviteInternal(
const std::string& group_ifname,
const std::array<uint8_t, 6>& go_device_address,
const std::array<uint8_t, 6>& peer_address)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpas_p2p_invite_group(
wpa_s, group_ifname.c_str(), peer_address.data(),
go_device_address.data())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::reinvokeInternal(
SupplicantNetworkId persistent_network_id,
const std::array<uint8_t, 6>& peer_address)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
struct wpa_ssid* ssid =
wpa_config_get_network(wpa_s->conf, persistent_network_id);
if (ssid == NULL || ssid->disabled != 2) {
return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
}
if (wpas_p2p_invite(
wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
VHT_CHANWIDTH_USE_HT, 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::configureExtListenInternal(
uint32_t period_in_millis, uint32_t interval_in_millis)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpas_p2p_ext_listen(wpa_s, period_in_millis, interval_in_millis)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::setListenChannelInternal(
uint32_t channel, uint32_t operating_class)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (p2p_set_listen_channel(
wpa_s->global->p2p, operating_class, channel, 1)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::setDisallowedFrequenciesInternal(
const std::vector<FreqRange>& ranges)
{
if (ranges.size() == 0) {
return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
}
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
using DestT = struct wpa_freq_range_list::wpa_freq_range;
DestT* freq_ranges =
static_cast<DestT*>(os_malloc(sizeof(DestT) * ranges.size()));
if (!freq_ranges) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
uint32_t i = 0;
for (const auto& range : ranges) {
freq_ranges[i].min = range.min;
freq_ranges[i].max = range.max;
i++;
}
os_free(wpa_s->global->p2p_disallow_freq.range);
wpa_s->global->p2p_disallow_freq.range = freq_ranges;
wpa_s->global->p2p_disallow_freq.num = ranges.size();
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
return {SupplicantStatusCode::SUCCESS, ""};
}
std::pair<SupplicantStatus, std::vector<uint8_t>> P2pIface::getSsidInternal(
const std::array<uint8_t, 6>& peer_address)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
const struct p2p_peer_info* info =
p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
if (!info) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
const struct p2p_device* dev =
reinterpret_cast<const struct p2p_device*>(
(reinterpret_cast<const uint8_t*>(info)) -
offsetof(struct p2p_device, info));
std::vector<uint8_t> ssid;
if (dev && dev->oper_ssid_len) {
ssid.assign(
dev->oper_ssid, dev->oper_ssid + dev->oper_ssid_len);
}
return {{SupplicantStatusCode::SUCCESS, ""}, ssid};
}
std::pair<SupplicantStatus, uint32_t> P2pIface::getGroupCapabilityInternal(
const std::array<uint8_t, 6>& peer_address)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
const struct p2p_peer_info* info =
p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
if (!info) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
return {{SupplicantStatusCode::SUCCESS, ""}, info->group_capab};
}
SupplicantStatus P2pIface::addBonjourServiceInternal(
const std::vector<uint8_t>& query, const std::vector<uint8_t>& response)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
auto query_buf = misc_utils::convertVectorToWpaBuf(query);
auto response_buf = misc_utils::convertVectorToWpaBuf(response);
if (!query_buf || !response_buf) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
if (wpas_p2p_service_add_bonjour(
wpa_s, query_buf.get(), response_buf.get())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
// If successful, the wpabuf is referenced internally and hence should
// not be freed.
query_buf.release();
response_buf.release();
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::removeBonjourServiceInternal(
const std::vector<uint8_t>& query)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
auto query_buf = misc_utils::convertVectorToWpaBuf(query);
if (!query_buf) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
if (wpas_p2p_service_del_bonjour(wpa_s, query_buf.get())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::addUpnpServiceInternal(
uint32_t version, const std::string& service_name)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpas_p2p_service_add_upnp(wpa_s, version, service_name.c_str())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::removeUpnpServiceInternal(
uint32_t version, const std::string& service_name)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpas_p2p_service_del_upnp(wpa_s, version, service_name.c_str())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::flushServicesInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
wpas_p2p_service_flush(wpa_s);
return {SupplicantStatusCode::SUCCESS, ""};
}
std::pair<SupplicantStatus, uint64_t> P2pIface::requestServiceDiscoveryInternal(
const std::array<uint8_t, 6>& peer_address,
const std::vector<uint8_t>& query)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
auto query_buf = misc_utils::convertVectorToWpaBuf(query);
if (!query_buf) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
uint64_t identifier =
wpas_p2p_sd_request(wpa_s, peer_address.data(), query_buf.get());
if (identifier == 0) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
return {{SupplicantStatusCode::SUCCESS, ""}, identifier};
}
SupplicantStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::setMiracastModeInternal(
ISupplicantP2pIface::MiracastMode mode)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
uint8_t mode_internal = convertHidlMiracastModeToInternal(mode);
const std::string cmd_str =
kSetMiracastMode + std::to_string(mode_internal);
std::vector<char> cmd(
cmd_str.c_str(), cmd_str.c_str() + cmd_str.size() + 1);
char driver_cmd_reply_buf[4096] = {};
if (wpa_drv_driver_cmd(
wpa_s, cmd.data(), driver_cmd_reply_buf,
sizeof(driver_cmd_reply_buf))) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::startWpsPbcInternal(
const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
{
struct wpa_supplicant* wpa_group_s =
retrieveGroupIfacePtr(group_ifname);
if (!wpa_group_s) {
return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
}
const uint8_t* bssid_addr =
is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
if (wpas_wps_start_pbc(wpa_group_s, bssid_addr, 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::startWpsPinKeypadInternal(
const std::string& group_ifname, const std::string& pin)
{
struct wpa_supplicant* wpa_group_s =
retrieveGroupIfacePtr(group_ifname);
if (!wpa_group_s) {
return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
}
if (wpas_wps_start_pin(
wpa_group_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
std::pair<SupplicantStatus, std::string> P2pIface::startWpsPinDisplayInternal(
const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
{
struct wpa_supplicant* wpa_group_s =
retrieveGroupIfacePtr(group_ifname);
if (!wpa_group_s) {
return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""}, ""};
}
const uint8_t* bssid_addr =
is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
int pin = wpas_wps_start_pin(
wpa_group_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
if (pin < 0) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
}
return {{SupplicantStatusCode::SUCCESS, ""},
misc_utils::convertWpsPinToString(pin)};
}
SupplicantStatus P2pIface::cancelWpsInternal(const std::string& group_ifname)
{
struct wpa_supplicant* wpa_group_s =
retrieveGroupIfacePtr(group_ifname);
if (!wpa_group_s) {
return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
}
if (wpas_wps_cancel(wpa_group_s)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::setWpsDeviceNameInternal(const std::string& name)
{
return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
}
SupplicantStatus P2pIface::setWpsDeviceTypeInternal(
const std::array<uint8_t, 8>& type)
{
return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
}
SupplicantStatus P2pIface::setWpsManufacturerInternal(
const std::string& manufacturer)
{
return iface_config_utils::setWpsManufacturer(
retrieveIfacePtr(), manufacturer);
}
SupplicantStatus P2pIface::setWpsModelNameInternal(
const std::string& model_name)
{
return iface_config_utils::setWpsModelName(
retrieveIfacePtr(), model_name);
}
SupplicantStatus P2pIface::setWpsModelNumberInternal(
const std::string& model_number)
{
return iface_config_utils::setWpsModelNumber(
retrieveIfacePtr(), model_number);
}
SupplicantStatus P2pIface::setWpsSerialNumberInternal(
const std::string& serial_number)
{
return iface_config_utils::setWpsSerialNumber(
retrieveIfacePtr(), serial_number);
}
SupplicantStatus P2pIface::setWpsConfigMethodsInternal(uint16_t config_methods)
{
return iface_config_utils::setWpsConfigMethods(
retrieveIfacePtr(), config_methods);
}
SupplicantStatus P2pIface::enableWfdInternal(bool enable)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
wifi_display_enable(wpa_s->global, enable);
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::setWfdDeviceInfoInternal(
const std::array<uint8_t, 8>& info)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
uint32_t wfd_device_info_hex_len = info.size() * 2 + 1;
std::vector<char> wfd_device_info_hex(wfd_device_info_hex_len);
wpa_snprintf_hex(
wfd_device_info_hex.data(), wfd_device_info_hex.size(), info.data(),
info.size());
std::string wfd_device_info_set_cmd_str =
std::to_string(kWfdDeviceInfoSubelemId) + " " +
wfd_device_info_hex.data();
std::vector<char> wfd_device_info_set_cmd(
wfd_device_info_set_cmd_str.c_str(),
wfd_device_info_set_cmd_str.c_str() +
wfd_device_info_set_cmd_str.size() + 1);
if (wifi_display_subelem_set(
wpa_s->global, wfd_device_info_set_cmd.data())) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
std::pair<SupplicantStatus, std::vector<uint8_t>>
P2pIface::createNfcHandoverRequestMessageInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
auto buf = misc_utils::createWpaBufUniquePtr(
wpas_p2p_nfc_handover_req(wpa_s, 1));
if (!buf) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
return {{SupplicantStatusCode::SUCCESS, ""},
misc_utils::convertWpaBufToVector(buf.get())};
}
std::pair<SupplicantStatus, std::vector<uint8_t>>
P2pIface::createNfcHandoverSelectMessageInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
auto buf = misc_utils::createWpaBufUniquePtr(
wpas_p2p_nfc_handover_sel(wpa_s, 1, 0));
if (!buf) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
return {{SupplicantStatusCode::SUCCESS, ""},
misc_utils::convertWpaBufToVector(buf.get())};
}
SupplicantStatus P2pIface::reportNfcHandoverResponseInternal(
const std::vector<uint8_t>& request)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
auto req = misc_utils::convertVectorToWpaBuf(request);
auto sel = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
if (!req || !sel) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
if (wpas_p2p_nfc_report_handover(wpa_s, 0, req.get(), sel.get(), 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::reportNfcHandoverInitiationInternal(
const std::vector<uint8_t>& select)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
auto req = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
auto sel = misc_utils::convertVectorToWpaBuf(select);
if (!req || !sel) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
if (wpas_p2p_nfc_report_handover(wpa_s, 1, req.get(), sel.get(), 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::saveConfigInternal()
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
if (!wpa_s->conf->update_config) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
}
/**
* Retrieve the underlying |wpa_supplicant| struct
* pointer for this iface.
* If the underlying iface is removed, then all RPC method calls on this object
* will return failure.
*/
wpa_supplicant* P2pIface::retrieveIfacePtr()
{
return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
}
/**
* Retrieve the underlying |wpa_supplicant| struct
* pointer for this group iface.
*/
wpa_supplicant* P2pIface::retrieveGroupIfacePtr(const std::string& group_ifname)
{
return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
}
} // namespace implementation
} // namespace V1_0
} // namespace wifi
} // namespace supplicant
} // namespace hardware
} // namespace android