wpa_supplicant(hidl): Implementation of WPS interfaces

Bug: 34198758
Test: Compiles
Change-Id: Ie3899ac421edd23ba64eb0d434f5705b5642589c
diff --git a/wpa_supplicant/hidl/hidl.cpp b/wpa_supplicant/hidl/hidl.cpp
index b7c1345..e38288b 100644
--- a/wpa_supplicant/hidl/hidl.cpp
+++ b/wpa_supplicant/hidl/hidl.cpp
@@ -288,3 +288,51 @@
 
 	hidl_manager->notifyAssocReject(wpa_s);
 }
+
+void wpas_hidl_notify_wps_event_fail(
+    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+    uint16_t error_indication)
+{
+	if (!wpa_s || !peer_macaddr)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying Wps event fail to hidl control: %d, %d",
+	    config_error, error_indication);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyWpsEventFail(
+	    wpa_s, peer_macaddr, config_error, error_indication);
+}
+
+void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying Wps event success to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyWpsEventSuccess(wpa_s);
+}
+
+void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying Wps event PBC overlap to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyWpsEventPbcOverlap(wpa_s);
+}
diff --git a/wpa_supplicant/hidl/hidl.h b/wpa_supplicant/hidl/hidl.h
index 0e51b3c..b1e8f11 100644
--- a/wpa_supplicant/hidl/hidl.h
+++ b/wpa_supplicant/hidl/hidl.h
@@ -48,6 +48,11 @@
     struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url);
 void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
 void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_wps_event_fail(
+    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+    uint16_t error_indication);
+void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s);
 #else   // CONFIG_CTRL_IFACE_HIDL
 static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
 {
@@ -97,6 +102,14 @@
 }
 static void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s) {}
 static void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_wps_event_fail(
+    struct wpa_supplicant *wpa_s, struct wps_event_fail *fail)
+{
+}
+static void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+}
 #endif  // CONFIG_CTRL_IFACE_HIDL
 
 #ifdef _cplusplus
diff --git a/wpa_supplicant/hidl/hidl_manager.cpp b/wpa_supplicant/hidl/hidl_manager.cpp
index ec6b847..fae9e90 100644
--- a/wpa_supplicant/hidl/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -531,7 +531,7 @@
 	// Invoke the |onStateChanged| method on all registered callbacks.
 	ISupplicantStaIfaceCallback::State hidl_state =
 	    static_cast<ISupplicantStaIfaceCallback::State>(wpa_s->wpa_state);
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), wpa_s->bssid, ETH_ALEN);
 	uint32_t hidl_network_id = UINT32_MAX;
 	std::vector<uint8_t> hidl_ssid;
@@ -621,7 +621,7 @@
 		    convertWpaBufToVector(anqp->hs20_osu_providers_list);
 	}
 
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 	callWithEachStaIfaceCallback(
 	    wpa_s->ifname, std::bind(
@@ -651,7 +651,7 @@
 		return;
 
 	std::vector<uint8_t> hidl_image(image, image + image_length);
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 	callWithEachStaIfaceCallback(
 	    wpa_s->ifname,
@@ -739,7 +739,7 @@
 	if (is_zero_ether_addr(bssid)) {
 		bssid = wpa_s->pending_bssid;
 	}
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 
 	callWithEachStaIfaceCallback(
@@ -770,7 +770,7 @@
 	if (is_zero_ether_addr(bssid)) {
 		bssid = wpa_s->pending_bssid;
 	}
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 
 	callWithEachStaIfaceCallback(
@@ -780,6 +780,64 @@
 		std::placeholders::_1, hidl_bssid, wpa_s->assoc_status_code));
 }
 
+void HidlManager::notifyWpsEventFail(
+    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+    uint16_t error_indication)
+{
+	if (!wpa_s || !peer_macaddr)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
+	os_memcpy(hidl_bssid.data(), peer_macaddr, ETH_ALEN);
+
+	ISupplicantStaIfaceCallback::WpsConfigError hidl_config_error =
+	    static_cast<ISupplicantStaIfaceCallback::WpsConfigError>(
+		config_error);
+	ISupplicantStaIfaceCallback::WpsErrorIndication hidl_error_indication =
+	    static_cast<ISupplicantStaIfaceCallback::WpsErrorIndication>(
+		error_indication);
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onWpsEventFail,
+			       std::placeholders::_1, hidl_bssid,
+			       hidl_config_error, hidl_error_indication));
+}
+
+void HidlManager::notifyWpsEventSuccess(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onWpsEventSuccess,
+			       std::placeholders::_1));
+}
+
+void HidlManager::notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onWpsEventPbcOverlap,
+			       std::placeholders::_1));
+}
+
 /**
  * Retrieve the |ISupplicantP2pIface| hidl object reference using the provided
  * ifname.
diff --git a/wpa_supplicant/hidl/hidl_manager.h b/wpa_supplicant/hidl/hidl_manager.h
index 8c4aa7f..cbf086f 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -76,6 +76,11 @@
 	    const char *url);
 	void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
 	void notifyAssocReject(struct wpa_supplicant *wpa_s);
+	void notifyWpsEventFail(
+	    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
+	    uint16_t config_error, uint16_t error_indication);
+	void notifyWpsEventSuccess(struct wpa_supplicant *wpa_s);
+	void notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s);
 
 	// Methods called from hidl objects.
 	int getP2pIfaceHidlObjectByIfname(
@@ -375,6 +380,27 @@
     "HS Subtype value mismatch");
 
 static_assert(
+    static_cast<uint16_t>(
+	ISupplicantStaIfaceCallback::WpsConfigError::NO_ERROR) ==
+	WPS_CFG_NO_ERROR,
+    "Wps config error value mismatch");
+static_assert(
+    static_cast<uint16_t>(ISupplicantStaIfaceCallback::WpsConfigError::
+			      PUBLIC_KEY_HASH_MISMATCH) ==
+	WPS_CFG_PUBLIC_KEY_HASH_MISMATCH,
+    "Wps config error value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantStaIfaceCallback::WpsErrorIndication::NO_ERROR) ==
+	WPS_EI_NO_ERROR,
+    "Wps error indication value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantStaIfaceCallback::WpsErrorIndication::AUTH_FAILURE) ==
+	WPS_EI_AUTH_FAILURE,
+    "Wps error indication value mismatch");
+
+static_assert(
     static_cast<uint32_t>(
 	ISupplicantP2pIface::GroupCapabilityMask::GROUP_OWNER) ==
 	P2P_GROUP_CAPAB_GROUP_OWNER,
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
index 857fe1a..f2ec7b9 100644
--- a/wpa_supplicant/hidl/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -11,6 +11,10 @@
 #include "hidl_return_util.h"
 #include "p2p_iface.h"
 
+extern "C" {
+#include "wps_supplicant.h"
+}
+
 namespace {
 const char kConfigMethodStrPbc[] = "pbc";
 const char kConfigMethodStrDisplay[] = "display";
@@ -348,6 +352,42 @@
 	    &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);
+}
+
 std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -876,6 +916,70 @@
 	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, ""}, ""};
+	}
+	std::string pin_str;
+	pin_str.reserve(9);
+	snprintf(&pin_str[0], pin_str.size(), "%08d", pin);
+	return {{SupplicantStatusCode::SUCCESS, ""}, pin_str};
+}
+
+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, ""};
+}
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
index 5c814ae..0170e50 100644
--- a/wpa_supplicant/hidl/p2p_iface.h
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -140,6 +140,17 @@
 	Return<void> setMiracastMode(
 	    ISupplicantP2pIface::MiracastMode mode,
 	    setMiracastMode_cb _hidl_cb) override;
+	Return<void> startWpsPbc(
+	    const hidl_string& groupIfName, const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPbc_cb _hidl_cb) override;
+	Return<void> startWpsPinKeypad(
+	    const hidl_string& groupIfName, const hidl_string& pin,
+	    startWpsPinKeypad_cb _hidl_cb) override;
+	Return<void> startWpsPinDisplay(
+	    const hidl_string& groupIfName, const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPinDisplay_cb _hidl_cb) override;
+	Return<void> cancelWps(
+	    const hidl_string& groupIfName, cancelWps_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -212,6 +223,15 @@
 	SupplicantStatus cancelServiceDiscoveryInternal(uint64_t identifier);
 	SupplicantStatus setMiracastModeInternal(
 	    ISupplicantP2pIface::MiracastMode mode);
+	SupplicantStatus startWpsPbcInternal(
+	    const std::string& group_ifname,
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus startWpsPinKeypadInternal(
+	    const std::string& group_ifname, const std::string& pin);
+	std::pair<SupplicantStatus, std::string> startWpsPinDisplayInternal(
+	    const std::string& group_ifname,
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus cancelWpsInternal(const std::string& group_ifname);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
diff --git a/wpa_supplicant/hidl/sta_iface.cpp b/wpa_supplicant/hidl/sta_iface.cpp
index 4a93b7c..9b05cfb 100644
--- a/wpa_supplicant/hidl/sta_iface.cpp
+++ b/wpa_supplicant/hidl/sta_iface.cpp
@@ -15,6 +15,7 @@
 #include "gas_query.h"
 #include "interworking.h"
 #include "hs20_supplicant.h"
+#include "wps_supplicant.h"
 }
 
 namespace {
@@ -305,6 +306,46 @@
 	    &StaIface::setCountryCodeInternal, _hidl_cb, code);
 }
 
+Return<void> StaIface::startWpsRegistrar(
+    const hidl_array<uint8_t, 6> &bssid, const hidl_string &pin,
+    startWpsRegistrar_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsRegistrarInternal, _hidl_cb, bssid, pin);
+}
+
+Return<void> StaIface::startWpsPbc(
+    const hidl_array<uint8_t, 6> &bssid, startWpsPbc_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsPbcInternal, _hidl_cb, bssid);
+}
+
+Return<void> StaIface::startWpsPinKeypad(
+    const hidl_string &pin, startWpsPinKeypad_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsPinKeypadInternal, _hidl_cb, pin);
+}
+
+Return<void> StaIface::startWpsPinDisplay(
+    const hidl_array<uint8_t, 6> &bssid, startWpsPinDisplay_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsPinDisplayInternal, _hidl_cb, bssid);
+}
+
+Return<void> StaIface::cancelWps(cancelWps_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::cancelWpsInternal, _hidl_cb);
+}
+
 std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -639,6 +680,64 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus StaIface::startWpsRegistrarInternal(
+    const std::array<uint8_t, 6> &bssid, const std::string &pin)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_start_reg(wpa_s, bssid.data(), pin.c_str(), nullptr)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::startWpsPbcInternal(
+    const std::array<uint8_t, 6> &bssid)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	const uint8_t *bssid_addr =
+	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	if (wpas_wps_start_pbc(wpa_s, bssid_addr, 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::startWpsPinKeypadInternal(const std::string &pin)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_start_pin(
+		wpa_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::string> StaIface::startWpsPinDisplayInternal(
+    const std::array<uint8_t, 6> &bssid)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	const uint8_t *bssid_addr =
+	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	int pin =
+	    wpas_wps_start_pin(wpa_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
+	if (pin < 0) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
+	}
+	std::string pin_str;
+	pin_str.reserve(9);
+	snprintf(&pin_str[0], pin_str.size(), "%08d", pin);
+	return {{SupplicantStatusCode::SUCCESS, ""}, pin_str};
+}
+
+SupplicantStatus StaIface::cancelWpsInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_cancel(wpa_s)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/sta_iface.h b/wpa_supplicant/hidl/sta_iface.h
index 3910143..075b2a3 100644
--- a/wpa_supplicant/hidl/sta_iface.h
+++ b/wpa_supplicant/hidl/sta_iface.h
@@ -115,6 +115,18 @@
 	Return<void> setCountryCode(
 	    const hidl_array<int8_t, 2>& code,
 	    setCountryCode_cb _hidl_cb) override;
+	Return<void> startWpsRegistrar(
+	    const hidl_array<uint8_t, 6>& bssid, const hidl_string& pin,
+	    startWpsRegistrar_cb _hidl_cb) override;
+	Return<void> startWpsPbc(
+	    const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPbc_cb _hidl_cb) override;
+	Return<void> startWpsPinKeypad(
+	    const hidl_string& pin, startWpsPinKeypad_cb _hidl_cb) override;
+	Return<void> startWpsPinDisplay(
+	    const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPinDisplay_cb _hidl_cb) override;
+	Return<void> cancelWps(cancelWps_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -161,6 +173,14 @@
 	SupplicantStatus setSuspendModeEnabledInternal(bool enable);
 	SupplicantStatus setCountryCodeInternal(
 	    const std::array<int8_t, 2>& code);
+	SupplicantStatus startWpsRegistrarInternal(
+	    const std::array<uint8_t, 6>& bssid, const std::string& pin);
+	SupplicantStatus startWpsPbcInternal(
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus startWpsPinKeypadInternal(const std::string& pin);
+	std::pair<SupplicantStatus, std::string> startWpsPinDisplayInternal(
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus cancelWpsInternal();
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 5dac806..3fdb36f 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -299,6 +299,10 @@
 
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_fail(wpa_s, fail);
+
+	wpas_hidl_notify_wps_event_fail(wpa_s, fail->peer_macaddr,
+					fail->config_error,
+					fail->error_indication);
 #endif /* CONFIG_WPS */
 }
 
@@ -310,6 +314,8 @@
 
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_success(wpa_s);
+
+	wpas_hidl_notify_wps_event_success(wpa_s);
 #endif /* CONFIG_WPS */
 }
 
@@ -320,6 +326,8 @@
 
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_pbc_overlap(wpa_s);
+
+	wpas_hidl_notify_wps_event_pbc_overlap(wpa_s);
 #endif /* CONFIG_WPS */
 }