Merge changes from topics 'hidl-register-fail-gracefully', 'anqp_hidl', 'supplicant_p2p'
* changes:
wpa_supplicant(hidl): Add network param getters
wpa_supplicant(hidl): Turn on HIDL control interface
wpa_supplicant(hidl): Invoke disconnect/assoc reject calbacks
wpa_supplicant(hidl): Invoke ANQP callbacks
wpa_supplicant: Add notifications for ANQP/HS20 events
wpa_supplicant(hidl): Implement ANQP query requests
wpa_supplicant(hidl): P2P Iface implementation
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 84044fc..2a5c810 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -326,7 +326,7 @@
# Add support for Hidl control interface
# Only applicable for Android platforms.
-# CONFIG_CTRL_IFACE_HIDL=y
+CONFIG_CTRL_IFACE_HIDL=y
# Add support for loading EAP methods dynamically as shared libraries.
# When this option is enabled, each EAP method can be either included
diff --git a/wpa_supplicant/hidl/hidl.cpp b/wpa_supplicant/hidl/hidl.cpp
index 599938d..09f09ce 100644
--- a/wpa_supplicant/hidl/hidl.cpp
+++ b/wpa_supplicant/hidl/hidl.cpp
@@ -181,3 +181,112 @@
return hidl_manager->notifyNetworkRequest(
wpa_s, ssid, rtype, default_txt);
}
+
+void wpas_hidl_notify_anqp_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp)
+{
+ if (!wpa_s || !wpa_s->global->hidl || !bssid || !result || !anqp)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying ANQP query done to hidl control: " MACSTR "result: %s",
+ MAC2STR(bssid), result);
+
+ HidlManager *hidl_manager = HidlManager::getInstance();
+ if (!hidl_manager)
+ return;
+
+ hidl_manager->notifyAnqpQueryDone(wpa_s, bssid, result, anqp);
+}
+
+void wpas_hidl_notify_hs20_icon_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+ const u8 *image, u32 image_length)
+{
+ if (!wpa_s || !wpa_s->global->hidl || !bssid || !file_name || !image)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying HS20 icon query done to hidl control: " MACSTR
+ "file_name: %s",
+ MAC2STR(bssid), file_name);
+
+ HidlManager *hidl_manager = HidlManager::getInstance();
+ if (!hidl_manager)
+ return;
+
+ hidl_manager->notifyHs20IconQueryDone(
+ wpa_s, bssid, file_name, image, image_length);
+}
+
+void wpas_hidl_notify_hs20_rx_subscription_remediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+ if (!wpa_s || !wpa_s->global->hidl || !url)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying HS20 subscription remediation rx to hidl control: %s",
+ url);
+
+ HidlManager *hidl_manager = HidlManager::getInstance();
+ if (!hidl_manager)
+ return;
+
+ hidl_manager->notifyHs20RxSubscriptionRemediation(
+ wpa_s, url, osu_method);
+}
+
+void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+ if (!wpa_s || !wpa_s->global->hidl || !url)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying HS20 deauth imminent notice rx to hidl control: %s",
+ url);
+
+ HidlManager *hidl_manager = HidlManager::getInstance();
+ if (!hidl_manager)
+ return;
+
+ hidl_manager->notifyHs20RxDeauthImminentNotice(
+ wpa_s, code, reauth_delay, url);
+}
+
+void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying disconnect reason to hidl control: %d",
+ wpa_s->disconnect_reason);
+
+ HidlManager *hidl_manager = HidlManager::getInstance();
+ if (!hidl_manager)
+ return;
+
+ hidl_manager->notifyDisconnectReason(wpa_s);
+}
+
+void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying assoc reject to hidl control: %d",
+ wpa_s->assoc_status_code);
+
+ HidlManager *hidl_manager = HidlManager::getInstance();
+ if (!hidl_manager)
+ return;
+
+ hidl_manager->notifyAssocReject(wpa_s);
+}
diff --git a/wpa_supplicant/hidl/hidl.h b/wpa_supplicant/hidl/hidl.h
index ee7cab1..0e51b3c 100644
--- a/wpa_supplicant/hidl/hidl.h
+++ b/wpa_supplicant/hidl/hidl.h
@@ -36,6 +36,18 @@
int wpas_hidl_notify_network_request(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
enum wpa_ctrl_req_type rtype, const char *default_txt);
+void wpas_hidl_notify_anqp_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp);
+void wpas_hidl_notify_hs20_icon_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+ const u8 *image, u32 image_length);
+void wpas_hidl_notify_hs20_rx_subscription_remediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
+ 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);
#else // CONFIG_CTRL_IFACE_HIDL
static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
{
@@ -65,6 +77,26 @@
{
return 0;
}
+static void wpas_hidl_notify_anqp_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp)
+{
+}
+static void wpas_hidl_notify_hs20_icon_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+ const u8 *image, u32 image_length)
+{
+}
+static void wpas_hidl_notify_hs20_rx_subscription_remediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+}
+static void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+}
+static void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_assoc_reject(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 90a0c22..ec6b847 100644
--- a/wpa_supplicant/hidl/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -287,6 +287,16 @@
method(callback);
}
}
+
+std::vector<uint8_t> convertWpaBufToVector(const struct wpabuf *buf)
+{
+ if (buf) {
+ return std::vector<uint8_t>(
+ wpabuf_head_u8(buf), wpabuf_head_u8(buf) + wpabuf_len(buf));
+ } else {
+ return std::vector<uint8_t>();
+ }
+}
} // namespace
namespace android {
@@ -521,7 +531,7 @@
// Invoke the |onStateChanged| method on all registered callbacks.
ISupplicantStaIfaceCallback::State hidl_state =
static_cast<ISupplicantStaIfaceCallback::State>(wpa_s->wpa_state);
- hidl_array<uint8_t, 6> hidl_bssid;
+ std::array<uint8_t, 6> 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;
@@ -567,6 +577,210 @@
}
/**
+ * Notify all listeners about the end of an ANQP query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param result Result of the operation ("SUCCESS" or "FAILURE").
+ * @param anqp |wpa_bss_anqp| ANQP data fetched.
+ */
+void HidlManager::notifyAnqpQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp)
+{
+ if (!wpa_s || !bssid || !result || !anqp)
+ return;
+
+ const std::string ifname(wpa_s->ifname);
+ if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+ return;
+
+ ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
+ ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data;
+ if (std::string(result) == "SUCCESS") {
+ hidl_anqp_data.venueName =
+ convertWpaBufToVector(anqp->venue_name);
+ hidl_anqp_data.roamingConsortium =
+ convertWpaBufToVector(anqp->roaming_consortium);
+ hidl_anqp_data.ipAddrTypeAvailability =
+ convertWpaBufToVector(anqp->ip_addr_type_availability);
+ hidl_anqp_data.naiRealm =
+ convertWpaBufToVector(anqp->nai_realm);
+ hidl_anqp_data.anqp3gppCellularNetwork =
+ convertWpaBufToVector(anqp->anqp_3gpp);
+ hidl_anqp_data.domainName =
+ convertWpaBufToVector(anqp->domain_name);
+
+ hidl_hs20_anqp_data.operatorFriendlyName =
+ convertWpaBufToVector(anqp->hs20_operator_friendly_name);
+ hidl_hs20_anqp_data.wanMetrics =
+ convertWpaBufToVector(anqp->hs20_wan_metrics);
+ hidl_hs20_anqp_data.connectionCapability =
+ convertWpaBufToVector(anqp->hs20_connection_capability);
+ hidl_hs20_anqp_data.osuProvidersList =
+ convertWpaBufToVector(anqp->hs20_osu_providers_list);
+ }
+
+ std::array<uint8_t, 6> hidl_bssid;
+ os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+ callWithEachStaIfaceCallback(
+ wpa_s->ifname, std::bind(
+ &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+ std::placeholders::_1, hidl_bssid,
+ hidl_anqp_data, hidl_hs20_anqp_data));
+}
+
+/**
+ * Notify all listeners about the end of an HS20 icon query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param file_name Name of the icon file.
+ * @param image Raw bytes of the icon file.
+ * @param image_length Size of the the icon file.
+ */
+void HidlManager::notifyHs20IconQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+ const u8 *image, u32 image_length)
+{
+ if (!wpa_s || !bssid || !file_name || !image)
+ return;
+
+ const std::string ifname(wpa_s->ifname);
+ if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+ return;
+
+ std::vector<uint8_t> hidl_image(image, image + image_length);
+ std::array<uint8_t, 6> hidl_bssid;
+ os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+ callWithEachStaIfaceCallback(
+ wpa_s->ifname,
+ std::bind(
+ &ISupplicantStaIfaceCallback::onHs20IconQueryDone,
+ std::placeholders::_1, hidl_bssid, file_name, hidl_image));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 subscription
+ * remediation notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param url URL of the server.
+ * @param osu_method OSU method (OMA_DM or SOAP_XML_SPP).
+ */
+void HidlManager::notifyHs20RxSubscriptionRemediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+ if (!wpa_s || !url)
+ return;
+
+ const std::string ifname(wpa_s->ifname);
+ if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+ return;
+
+ ISupplicantStaIfaceCallback::OsuMethod hidl_osu_method = {};
+ if (osu_method & 0x1) {
+ hidl_osu_method =
+ ISupplicantStaIfaceCallback::OsuMethod::OMA_DM;
+ } else if (osu_method & 0x2) {
+ hidl_osu_method =
+ ISupplicantStaIfaceCallback::OsuMethod::SOAP_XML_SPP;
+ }
+ callWithEachStaIfaceCallback(
+ wpa_s->ifname,
+ std::bind(
+ &ISupplicantStaIfaceCallback::onHs20SubscriptionRemediation,
+ std::placeholders::_1, hidl_osu_method, url));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 immient deauth
+ * notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param code Deauth reason code sent from server.
+ * @param reauth_delay Reauthentication delay in seconds sent from server.
+ * @param url URL of the server.
+ */
+void HidlManager::notifyHs20RxDeauthImminentNotice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+ if (!wpa_s || !url)
+ 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::onHs20DeauthImminentNotice,
+ std::placeholders::_1, code, reauth_delay, url));
+}
+
+/**
+ * Notify all listeners about the reason code for disconnection from the
+ * currently connected network.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void HidlManager::notifyDisconnectReason(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;
+
+ const u8 *bssid = wpa_s->bssid;
+ if (is_zero_ether_addr(bssid)) {
+ bssid = wpa_s->pending_bssid;
+ }
+ std::array<uint8_t, 6> hidl_bssid;
+ os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+
+ callWithEachStaIfaceCallback(
+ wpa_s->ifname,
+ std::bind(
+ &ISupplicantStaIfaceCallback::onDisconnected,
+ std::placeholders::_1, hidl_bssid, wpa_s->disconnect_reason < 0,
+ wpa_s->disconnect_reason));
+}
+
+/**
+ * Notify all listeners about association reject from the access point to which
+ * we are attempting to connect.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void HidlManager::notifyAssocReject(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;
+
+ const u8 *bssid = wpa_s->bssid;
+ if (is_zero_ether_addr(bssid)) {
+ bssid = wpa_s->pending_bssid;
+ }
+ std::array<uint8_t, 6> hidl_bssid;
+ os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+
+ callWithEachStaIfaceCallback(
+ wpa_s->ifname,
+ std::bind(
+ &ISupplicantStaIfaceCallback::onAssociationRejected,
+ std::placeholders::_1, hidl_bssid, wpa_s->assoc_status_code));
+}
+
+/**
* 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 5f1c7b6..8c4aa7f 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -63,6 +63,19 @@
int notifyNetworkRequest(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
const char *param);
+ void notifyAnqpQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp);
+ void notifyHs20IconQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name, const u8 *image, u32 image_length);
+ void notifyHs20RxSubscriptionRemediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+ void notifyHs20RxDeauthImminentNotice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
+ const char *url);
+ void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
+ void notifyAssocReject(struct wpa_supplicant *wpa_s);
// Methods called from hidl objects.
int getP2pIfaceHidlObjectByIfname(
@@ -314,6 +327,88 @@
WPA_COMPLETED,
"State value mismatch");
+static_assert(
+ static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::VENUE_NAME) ==
+ ANQP_VENUE_NAME,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantStaIface::AnqpInfoId::ROAMING_CONSORTIUM) ==
+ ANQP_ROAMING_CONSORTIUM,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::NAI_REALM) ==
+ ANQP_NAI_REALM,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantStaIface::AnqpInfoId::IP_ADDR_TYPE_AVAILABILITY) ==
+ ANQP_IP_ADDR_TYPE_AVAILABILITY,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantStaIface::AnqpInfoId::ANQP_3GPP_CELLULAR_NETWORK) ==
+ ANQP_3GPP_CELLULAR_NETWORK,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::DOMAIN_NAME) ==
+ ANQP_DOMAIN_NAME,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantStaIface::Hs20AnqpSubtypes::OPERATOR_FRIENDLY_NAME) ==
+ HS20_STYPE_OPERATOR_FRIENDLY_NAME,
+ "HS Subtype value mismatch");
+static_assert(
+ static_cast<uint32_t>(ISupplicantStaIface::Hs20AnqpSubtypes::WAN_METRICS) ==
+ HS20_STYPE_WAN_METRICS,
+ "HS Subtype value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantStaIface::Hs20AnqpSubtypes::CONNECTION_CAPABILITY) ==
+ HS20_STYPE_CONNECTION_CAPABILITY,
+ "HS Subtype value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantStaIface::Hs20AnqpSubtypes::OSU_PROVIDERS_LIST) ==
+ HS20_STYPE_OSU_PROVIDERS_LIST,
+ "HS Subtype value mismatch");
+
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantP2pIface::GroupCapabilityMask::GROUP_OWNER) ==
+ P2P_GROUP_CAPAB_GROUP_OWNER,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantP2pIface::GroupCapabilityMask::PERSISTENT_GROUP) ==
+ P2P_GROUP_CAPAB_PERSISTENT_GROUP,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantP2pIface::GroupCapabilityMask::GROUP_LIMIT) ==
+ P2P_GROUP_CAPAB_GROUP_LIMIT,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantP2pIface::GroupCapabilityMask::INTRA_BSS_DIST) ==
+ P2P_GROUP_CAPAB_INTRA_BSS_DIST,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantP2pIface::GroupCapabilityMask::CROSS_CONN) ==
+ P2P_GROUP_CAPAB_CROSS_CONN,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantP2pIface::GroupCapabilityMask::PERSISTENT_RECONN) ==
+ P2P_GROUP_CAPAB_PERSISTENT_RECONN,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ ISupplicantP2pIface::GroupCapabilityMask::GROUP_FORMATION) ==
+ P2P_GROUP_CAPAB_GROUP_FORMATION,
+ "P2P capability value mismatch");
} // namespace implementation
} // namespace V1_0
} // namespace wifi
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
index 9c0b3f4..6ad0696 100644
--- a/wpa_supplicant/hidl/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -11,6 +11,12 @@
#include "hidl_return_util.h"
#include "p2p_iface.h"
+namespace {
+const char kConfigMethodStrPbc[] = "pbc";
+const char kConfigMethodStrDisplay[] = "display";
+const char kConfigMethodStrKeypad[] = "keypad";
+} // namespace
+
namespace android {
namespace hardware {
namespace wifi {
@@ -90,7 +96,7 @@
}
Return<void> P2pIface::setSsidPostfix(
- const hidl_string& postfix, setSsidPostfix_cb _hidl_cb)
+ const hidl_vec<uint8_t>& postfix, setSsidPostfix_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
@@ -98,18 +104,21 @@
}
Return<void> P2pIface::setGroupIdle(
- uint32_t timeout_in_sec, setGroupIdle_cb _hidl_cb)
+ 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, timeout_in_sec);
+ &P2pIface::setGroupIdleInternal, _hidl_cb, group_ifname,
+ timeout_in_sec);
}
-Return<void> P2pIface::setPowerSave(bool enable, setPowerSave_cb _hidl_cb)
+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, enable);
+ &P2pIface::setPowerSaveInternal, _hidl_cb, group_ifname, enable);
}
Return<void> P2pIface::find(uint32_t timeout_in_sec, find_cb _hidl_cb)
@@ -136,7 +145,7 @@
Return<void> P2pIface::connect(
const hidl_array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method,
- const hidl_vec<uint8_t>& pre_selected_pin, bool join_existing_group,
+ const hidl_string& pre_selected_pin, bool join_existing_group,
bool persistent, uint32_t go_intent, connect_cb _hidl_cb)
{
return validateAndCall(
@@ -165,7 +174,8 @@
}
Return<void> P2pIface::addGroup(
- bool persistent, uint32_t persistent_network_id, addGroup_cb _hidl_cb)
+ bool persistent, SupplicantNetworkId persistent_network_id,
+ addGroup_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
@@ -201,8 +211,8 @@
}
Return<void> P2pIface::reinvoke(
- uint32_t persistent_network_id, const hidl_array<uint8_t, 6>& peer_address,
- reinvoke_cb _hidl_cb)
+ SupplicantNetworkId persistent_network_id,
+ const hidl_array<uint8_t, 6>& peer_address, reinvoke_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
@@ -229,6 +239,14 @@
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)
{
@@ -394,59 +412,133 @@
std::pair<SupplicantStatus, std::array<uint8_t, 6>>
P2pIface::getDeviceAddressInternal()
{
- // TODO: Add implementation.
+ 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 hidl_string& postfix)
+SupplicantStatus P2pIface::setSsidPostfixInternal(
+ const std::vector<uint8_t>& postfix)
{
- // TODO: Add implementation.
+ 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(uint32_t timeout_in_sec)
+SupplicantStatus P2pIface::setGroupIdleInternal(
+ const std::string& group_ifname, uint32_t timeout_in_sec)
{
- // TODO: Add implementation.
+ 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(bool enable)
+SupplicantStatus P2pIface::setPowerSaveInternal(
+ const std::string& group_ifname, bool enable)
{
- // TODO: Add implementation.
+ 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)
{
- // TODO: Add implementation.
+ 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()
{
- // TODO: Add implementation.
+ 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()
{
- // TODO: Add implementation.
+ 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, ""};
}
-std::pair<SupplicantStatus, std::vector<uint8_t>> P2pIface::connectInternal(
+// 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::vector<uint8_t>& pre_selected_pin, bool join_existing_group,
+ const std::string& pre_selected_pin, bool join_existing_group,
bool persistent, uint32_t go_intent)
{
- // TODO: Add implementation.
- return {{SupplicantStatusCode::SUCCESS, ""}, {}};
+ 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.reserve(9);
+ snprintf(&pin_ret[0], pin_ret.size(), "%08d", new_pin);
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""}, pin_ret};
}
SupplicantStatus P2pIface::cancelConnectInternal()
{
- // TODO: Add implementation.
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpas_p2p_cancel(wpa_s)) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
return {SupplicantStatusCode::SUCCESS, ""};
}
@@ -454,106 +546,266 @@
const std::array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method)
{
- // TODO: Add implementation.
+ 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, uint32_t persistent_network_id)
+ bool persistent, SupplicantNetworkId persistent_network_id)
{
- // TODO: Add implementation.
- return {SupplicantStatusCode::SUCCESS, ""};
+ 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 hidl_string& group_ifname)
+SupplicantStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
{
- // TODO: Add implementation.
+ 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)
{
- // TODO: Add implementation.
+ 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 hidl_string& group_ifname,
+ const std::string& group_ifname,
const std::array<uint8_t, 6>& go_device_address,
const std::array<uint8_t, 6>& peer_address)
{
- // TODO: Add implementation.
+ 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(
- uint32_t persistent_network_id, const std::array<uint8_t, 6>& peer_address)
+ SupplicantNetworkId persistent_network_id,
+ const std::array<uint8_t, 6>& peer_address)
{
- // TODO: Add implementation.
+ 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(
bool enable, uint32_t period_in_millis, uint32_t interval_in_millis)
{
- // TODO: Add implementation.
+ 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)
{
- // TODO: Add implementation.
+ 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)
{
- // TODO: Add implementation.
- return {{SupplicantStatusCode::SUCCESS, ""}, {}};
+ 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)
{
- // TODO: Add implementation.
- return {{SupplicantStatusCode::SUCCESS, ""}, 0};
+ 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)
{
- // TODO: Add implementation.
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ struct wpabuf* query_buf = wpabuf_alloc(query.size());
+ if (!query_buf) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
+ wpabuf_put_data(query_buf, query.data(), query.size());
+
+ struct wpabuf* response_buf = wpabuf_alloc(response.size());
+ if (!query_buf) {
+ wpabuf_free(query_buf);
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
+ wpabuf_put_data(response_buf, response.data(), response.size());
+
+ if (wpas_p2p_service_add_bonjour(wpa_s, query_buf, response_buf)) {
+ wpabuf_free(query_buf);
+ wpabuf_free(response_buf);
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::removeBonjourServiceInternal(
const std::vector<uint8_t>& query)
{
- // TODO: Add implementation.
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ struct wpabuf* query_buf = wpabuf_alloc(query.size());
+ if (!query_buf) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
+ wpabuf_put_data(query_buf, query.data(), query.size());
+
+ int ret = wpas_p2p_service_del_bonjour(wpa_s, query_buf);
+ wpabuf_free(query_buf);
+ if (ret) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus P2pIface::addUpnpServiceInternal(
- uint32_t version, const hidl_string& service_name)
+ uint32_t version, const std::string& service_name)
{
- // TODO: Add implementation.
+ 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 hidl_string& service_name)
+ uint32_t version, const std::string& service_name)
{
- // TODO: Add implementation.
+ 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(
- uint32_t version, const hidl_string& service_name)
+ uint32_t version, const std::string& service_name)
{
- // TODO: Add implementation.
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ wpas_p2p_service_flush(wpa_s);
return {SupplicantStatusCode::SUCCESS, ""};
}
@@ -561,13 +813,27 @@
const std::array<uint8_t, 6>& peer_address,
const std::vector<uint8_t>& query)
{
- // TODO: Add implementation.
- return {{SupplicantStatusCode::SUCCESS, ""}, 0};
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ struct wpabuf* query_buf = wpabuf_alloc(query.size());
+ if (!query_buf) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ wpabuf_put_data(query_buf, query.data(), query.size());
+ uint64_t identifier =
+ wpas_p2p_sd_request(wpa_s, peer_address.data(), query_buf);
+ wpabuf_free(query_buf);
+ if (identifier == 0) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""}, identifier};
}
SupplicantStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
{
- // TODO: Add implementation.
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
return {SupplicantStatusCode::SUCCESS, ""};
}
@@ -579,8 +845,16 @@
*/
wpa_supplicant* P2pIface::retrieveIfacePtr()
{
- return wpa_supplicant_get_iface(
- (struct wpa_global*)wpa_global_, ifname_.c_str());
+ 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
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
index d340b08..312b8bb 100644
--- a/wpa_supplicant/hidl/p2p_iface.h
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -22,9 +22,11 @@
extern "C" {
#include "utils/common.h"
#include "utils/includes.h"
-#include "wpa_supplicant_i.h"
+#include "p2p/p2p.h"
+#include "p2p/p2p_i.h"
+#include "p2p_supplicant.h"
+#include "p2p_supplicant.h"
#include "config.h"
-#include "driver_i.h"
}
namespace android {
@@ -63,18 +65,21 @@
registerCallback_cb _hidl_cb) override;
Return<void> getDeviceAddress(getDeviceAddress_cb _hidl_cb) override;
Return<void> setSsidPostfix(
- const hidl_string& postfix, setSsidPostfix_cb _hidl_cb) override;
+ const hidl_vec<uint8_t>& postfix,
+ setSsidPostfix_cb _hidl_cb) override;
Return<void> setGroupIdle(
- uint32_t timeout_in_sec, setGroupIdle_cb _hidl_cb) override;
+ const hidl_string& group_ifname, uint32_t timeout_in_sec,
+ setGroupIdle_cb _hidl_cb) override;
Return<void> setPowerSave(
- bool enable, setPowerSave_cb _hidl_cb) override;
+ const hidl_string& group_ifname, bool enable,
+ setPowerSave_cb _hidl_cb) override;
Return<void> find(uint32_t timeout_in_sec, find_cb _hidl_cb) override;
Return<void> stopFind(stopFind_cb _hidl_cb) override;
Return<void> flush(flush_cb _hidl_cb) override;
Return<void> connect(
const hidl_array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method,
- const hidl_vec<uint8_t>& pre_selected_pin, bool join_existing_group,
+ const hidl_string& pre_selected_pin, bool join_existing_group,
bool persistent, uint32_t go_intent, connect_cb _hidl_cb) override;
Return<void> cancelConnect(cancelConnect_cb _hidl_cb) override;
Return<void> provisionDiscovery(
@@ -82,7 +87,7 @@
ISupplicantP2pIface::WpsProvisionMethod provision_method,
provisionDiscovery_cb _hidl_cb) override;
Return<void> addGroup(
- bool persistent, uint32_t persistent_network_id,
+ bool persistent, SupplicantNetworkId persistent_network_id,
addGroup_cb _hidl_cb) override;
Return<void> removeGroup(
const hidl_string& group_ifname, removeGroup_cb _hidl_cb) override;
@@ -95,7 +100,7 @@
const hidl_array<uint8_t, 6>& peer_address,
invite_cb _hidl_cb) override;
Return<void> reinvoke(
- uint32_t persistent_network_id,
+ SupplicantNetworkId persistent_network_id,
const hidl_array<uint8_t, 6>& peer_address,
reinvoke_cb _hidl_cb) override;
Return<void> configureExtListen(
@@ -104,6 +109,9 @@
Return<void> setListenChannel(
uint32_t channel, uint32_t operating_class,
setListenChannel_cb _hidl_cb) override;
+ Return<void> setDisallowedFrequencies(
+ const hidl_vec<FreqRange>& ranges,
+ setDisallowedFrequencies_cb _hidl_cb) override;
Return<void> getSsid(
const hidl_array<uint8_t, 6>& peer_address,
getSsid_cb _hidl_cb) override;
@@ -147,38 +155,43 @@
const sp<ISupplicantP2pIfaceCallback>& callback);
std::pair<SupplicantStatus, std::array<uint8_t, 6>>
getDeviceAddressInternal();
- SupplicantStatus setSsidPostfixInternal(const hidl_string& postfix);
- SupplicantStatus setGroupIdleInternal(uint32_t timeout_in_sec);
- SupplicantStatus setPowerSaveInternal(bool enable);
+ SupplicantStatus setSsidPostfixInternal(
+ const std::vector<uint8_t>& postfix);
+ SupplicantStatus setGroupIdleInternal(
+ const std::string& group_ifname, uint32_t timeout_in_sec);
+ SupplicantStatus setPowerSaveInternal(
+ const std::string& group_ifname, bool enable);
SupplicantStatus findInternal(uint32_t timeout_in_sec);
SupplicantStatus stopFindInternal();
SupplicantStatus flushInternal();
- std::pair<SupplicantStatus, std::vector<uint8_t>> connectInternal(
+ std::pair<SupplicantStatus, std::string> connectInternal(
const std::array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method,
- const std::vector<uint8_t>& pre_selected_pin,
- bool join_existing_group, bool persistent, uint32_t go_intent);
+ const std::string& pre_selected_pin, bool join_existing_group,
+ bool persistent, uint32_t go_intent);
SupplicantStatus cancelConnectInternal();
SupplicantStatus provisionDiscoveryInternal(
const std::array<uint8_t, 6>& peer_address,
ISupplicantP2pIface::WpsProvisionMethod provision_method);
SupplicantStatus addGroupInternal(
- bool persistent, uint32_t persistent_network_id);
- SupplicantStatus removeGroupInternal(const hidl_string& group_ifname);
+ bool persistent, SupplicantNetworkId persistent_network_id);
+ SupplicantStatus removeGroupInternal(const std::string& group_ifname);
SupplicantStatus rejectInternal(
const std::array<uint8_t, 6>& peer_address);
SupplicantStatus inviteInternal(
- const hidl_string& group_ifname,
+ const std::string& group_ifname,
const std::array<uint8_t, 6>& go_device_address,
const std::array<uint8_t, 6>& peer_address);
SupplicantStatus reinvokeInternal(
- uint32_t persistent_network_id,
+ SupplicantNetworkId persistent_network_id,
const std::array<uint8_t, 6>& peer_address);
SupplicantStatus configureExtListenInternal(
bool enable, uint32_t period_in_millis,
uint32_t interval_in_millis);
SupplicantStatus setListenChannelInternal(
uint32_t channel, uint32_t operating_class);
+ SupplicantStatus setDisallowedFrequenciesInternal(
+ const std::vector<FreqRange>& ranges);
std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal(
const std::array<uint8_t, 6>& peer_address);
std::pair<SupplicantStatus, uint32_t> getGroupCapabilityInternal(
@@ -189,21 +202,23 @@
SupplicantStatus removeBonjourServiceInternal(
const std::vector<uint8_t>& query);
SupplicantStatus addUpnpServiceInternal(
- uint32_t version, const hidl_string& service_name);
+ uint32_t version, const std::string& service_name);
SupplicantStatus removeUpnpServiceInternal(
- uint32_t version, const hidl_string& service_name);
+ uint32_t version, const std::string& service_name);
SupplicantStatus flushServicesInternal(
- uint32_t version, const hidl_string& service_name);
+ uint32_t version, const std::string& service_name);
std::pair<SupplicantStatus, uint64_t> requestServiceDiscoveryInternal(
const std::array<uint8_t, 6>& peer_address,
const std::vector<uint8_t>& query);
SupplicantStatus cancelServiceDiscoveryInternal(uint64_t identifier);
struct wpa_supplicant* retrieveIfacePtr();
+ struct wpa_supplicant* retrieveGroupIfacePtr(
+ const std::string& group_ifname);
// Reference to the global wpa_struct. This is assumed to be valid for
// the lifetime of the process.
- const struct wpa_global* wpa_global_;
+ struct wpa_global* wpa_global_;
// Name of the iface this hidl object controls
const std::string ifname_;
bool is_valid_;
diff --git a/wpa_supplicant/hidl/sta_iface.cpp b/wpa_supplicant/hidl/sta_iface.cpp
index 4379dd5..a60267d 100644
--- a/wpa_supplicant/hidl/sta_iface.cpp
+++ b/wpa_supplicant/hidl/sta_iface.cpp
@@ -11,6 +11,16 @@
#include "hidl_return_util.h"
#include "sta_iface.h"
+extern "C" {
+#include "gas_query.h"
+#include "interworking.h"
+#include "hs20_supplicant.h"
+}
+
+namespace {
+constexpr uint32_t kMaxAnqpElems = 100;
+} // namespace
+
namespace android {
namespace hardware {
namespace wifi {
@@ -345,14 +355,46 @@
const std::vector<ISupplicantStaIface::AnqpInfoId> &info_elements,
const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types)
{
- // TODO: Add implementation.
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (info_elements.size() > kMaxAnqpElems) {
+ return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+ }
+ uint16_t *info_elems_buf = static_cast<uint16_t *>(
+ os_malloc(sizeof(uint16_t) * info_elements.size()));
+ if (!info_elems_buf) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
+ uint32_t num_info_elems = 0;
+ for (const auto &info_element : info_elements) {
+ info_elems_buf[num_info_elems++] =
+ static_cast<std::underlying_type<
+ ISupplicantStaIface::AnqpInfoId>::type>(info_element);
+ }
+ uint32_t sub_types_bitmask = 0;
+ for (const auto &type : sub_types) {
+ sub_types_bitmask |= BIT(
+ static_cast<std::underlying_type<
+ ISupplicantStaIface::Hs20AnqpSubtypes>::type>(type));
+ }
+ if (anqp_send_req(
+ wpa_s, mac_address.data(), info_elems_buf, num_info_elems,
+ sub_types_bitmask, false)) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
return {SupplicantStatusCode::SUCCESS, ""};
}
SupplicantStatus StaIface::initiateHs20IconQueryInternal(
const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
{
- // TODO: Add implementation.
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ wpa_s->fetch_osu_icon_in_progress = 0;
+ if (hs20_anqp_send_req(
+ wpa_s, mac_address.data(), BIT(HS20_STYPE_ICON_REQUEST),
+ reinterpret_cast<const uint8_t *>(file_name.c_str()),
+ file_name.size(), true)) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
return {SupplicantStatusCode::SUCCESS, ""};
}
@@ -364,8 +406,7 @@
*/
wpa_supplicant *StaIface::retrieveIfacePtr()
{
- return wpa_supplicant_get_iface(
- (struct wpa_global *)wpa_global_, ifname_.c_str());
+ return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
}
} // namespace implementation
diff --git a/wpa_supplicant/hidl/sta_iface.h b/wpa_supplicant/hidl/sta_iface.h
index a4177aa..01b2b5e 100644
--- a/wpa_supplicant/hidl/sta_iface.h
+++ b/wpa_supplicant/hidl/sta_iface.h
@@ -133,7 +133,7 @@
// Reference to the global wpa_struct. This is assumed to be valid for
// the lifetime of the process.
- const struct wpa_global* wpa_global_;
+ struct wpa_global* wpa_global_;
// Name of the iface this hidl object controls
const std::string ifname_;
bool is_valid_;
diff --git a/wpa_supplicant/hidl/sta_network.cpp b/wpa_supplicant/hidl/sta_network.cpp
index 15e628f..226c1bd 100644
--- a/wpa_supplicant/hidl/sta_network.cpp
+++ b/wpa_supplicant/hidl/sta_network.cpp
@@ -48,6 +48,8 @@
static_cast<uint32_t>(ISupplicantStaNetwork::EapPhase2Method::GTC) + 1;
constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
"NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC"};
+constexpr char kEapPhase2AuthPrefix[] = "auth=";
+constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
} // namespace
namespace android {
@@ -394,6 +396,107 @@
&StaNetwork::getRequirePmfInternal, _hidl_cb);
}
+Return<void> StaNetwork::getEapMethod(getEapMethod_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapMethodInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapPhase2Method(getEapPhase2Method_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapPhase2MethodInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapIdentity(getEapIdentity_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapIdentityInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapAnonymousIdentity(
+ getEapAnonymousIdentity_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapAnonymousIdentityInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapPassword(getEapPassword_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapPasswordInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapCACert(getEapCACert_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapCACertInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapCAPath(getEapCAPath_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapCAPathInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapClientCert(getEapClientCert_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapClientCertInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapPrivateKey(getEapPrivateKey_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapPrivateKeyInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapSubjectMatch(getEapSubjectMatch_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapSubjectMatchInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapAltSubjectMatch(
+ getEapAltSubjectMatch_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapSubjectMatchInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapEngine(getEapEngine_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapEngineInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapEngineID(getEapEngineID_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapEngineIDInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapDomainSuffixMatch(
+ getEapDomainSuffixMatch_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapDomainSuffixMatchInternal, _hidl_cb);
+}
+
Return<void> StaNetwork::enable(bool no_connect, enable_cb _hidl_cb)
{
return validateAndCall(
@@ -662,10 +765,16 @@
SupplicantStatus StaNetwork::setEapMethodInternal(
ISupplicantStaNetwork::EapMethod method)
{
+ uint32_t eap_method_idx = static_cast<
+ std::underlying_type<ISupplicantStaNetwork::EapMethod>::type>(
+ method);
+ if (eap_method_idx >= kEapMethodMax) {
+ return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+ }
+
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
int retrieved_vendor, retrieved_method;
- const char *method_str =
- kEapMethodStrings[static_cast<uint32_t>(method)];
+ const char *method_str = kEapMethodStrings[eap_method_idx];
// This string lookup is needed to check if the device supports the
// corresponding EAP type.
retrieved_method = eap_peer_get_type(method_str, &retrieved_vendor);
@@ -709,10 +818,34 @@
SupplicantStatus StaNetwork::setEapPhase2MethodInternal(
ISupplicantStaNetwork::EapPhase2Method method)
{
+ uint32_t eap_phase2_method_idx = static_cast<
+ std::underlying_type<ISupplicantStaNetwork::EapPhase2Method>::type>(
+ method);
+ if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+ return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+ }
+
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ // EAP method needs to be set for us to construct the eap
+ // phase 2 method string.
+ SupplicantStatus status;
+ ISupplicantStaNetwork::EapMethod eap_method;
+ std::tie(status, eap_method) = getEapMethodInternal();
+ if (status.code != SupplicantStatusCode::SUCCESS) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN,
+ "EAP method not set"};
+ }
+ std::string eap_phase2_str;
+ if (eap_method == ISupplicantStaNetwork::EapMethod::TTLS &&
+ method == ISupplicantStaNetwork::EapPhase2Method::GTC) {
+ eap_phase2_str = kEapPhase2AuthEapPrefix;
+ } else {
+ eap_phase2_str = kEapPhase2AuthPrefix;
+ }
+ eap_phase2_str += kEapPhase2MethodStrings[eap_phase2_method_idx];
if (setStringFieldAndResetState(
- kEapPhase2MethodStrings[static_cast<uint32_t>(method)],
- &(wpa_ssid->eap.phase2), "eap phase2")) {
+ eap_phase2_str.c_str(), &(wpa_ssid->eap.phase2),
+ "eap phase2")) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
@@ -950,10 +1083,201 @@
(wpa_ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)};
}
+std::pair<SupplicantStatus, ISupplicantStaNetwork::EapMethod>
+StaNetwork::getEapMethodInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.eap_methods) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ // wpa_supplicant can support setting multiple eap methods for each
+ // network. But, this is not really used by Android. So, just reading
+ // the first EAP method for each network.
+ const std::string eap_method_str = eap_get_name(
+ wpa_ssid->eap.eap_methods[0].vendor,
+ static_cast<EapType>(wpa_ssid->eap.eap_methods[0].method));
+ size_t eap_method_idx =
+ std::find(
+ std::begin(kEapMethodStrings), std::end(kEapMethodStrings),
+ eap_method_str) -
+ std::begin(kEapMethodStrings);
+ if (eap_method_idx >= kEapMethodMax) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ static_cast<ISupplicantStaNetwork::EapMethod>(eap_method_idx)};
+}
+
+std::pair<SupplicantStatus, ISupplicantStaNetwork::EapPhase2Method>
+StaNetwork::getEapPhase2MethodInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.phase2) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ const std::string eap_phase2_method_str_with_prefix =
+ wpa_ssid->eap.phase2;
+ std::string eap_phase2_method_str;
+ // Strip out the phase 2 method prefix before doing a reverse lookup
+ // of phase 2 string to the Eap Phase 2 type.
+ if (eap_phase2_method_str_with_prefix.find(kEapPhase2AuthPrefix) == 0) {
+ eap_phase2_method_str =
+ eap_phase2_method_str_with_prefix.substr(
+ strlen(kEapPhase2AuthPrefix),
+ eap_phase2_method_str_with_prefix.size());
+ } else if (
+ eap_phase2_method_str_with_prefix.find(kEapPhase2AuthEapPrefix) ==
+ 0) {
+ eap_phase2_method_str =
+ eap_phase2_method_str_with_prefix.substr(
+ strlen(kEapPhase2AuthEapPrefix),
+ eap_phase2_method_str_with_prefix.size());
+ }
+ size_t eap_phase2_method_idx =
+ std::find(
+ std::begin(kEapPhase2MethodStrings),
+ std::end(kEapPhase2MethodStrings), eap_phase2_method_str) -
+ std::begin(kEapPhase2MethodStrings);
+ if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ static_cast<ISupplicantStaNetwork::EapPhase2Method>(
+ eap_phase2_method_idx)};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getEapIdentityInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.identity) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ std::vector<uint8_t>(
+ wpa_ssid->eap.identity,
+ wpa_ssid->eap.identity + wpa_ssid->eap.identity_len)};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getEapAnonymousIdentityInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.anonymous_identity) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ std::vector<uint8_t>(
+ wpa_ssid->eap.anonymous_identity,
+ wpa_ssid->eap.anonymous_identity +
+ wpa_ssid->eap.anonymous_identity_len)};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getEapPasswordInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.password) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ std::vector<uint8_t>(
+ wpa_ssid->eap.password,
+ wpa_ssid->eap.password + wpa_ssid->eap.password_len)};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapCACertInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.ca_cert) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ reinterpret_cast<char *>(wpa_ssid->eap.ca_cert)};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapCAPathInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.ca_path) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ reinterpret_cast<char *>(wpa_ssid->eap.ca_path)};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapClientCertInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.client_cert) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ reinterpret_cast<char *>(wpa_ssid->eap.client_cert)};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapPrivateKeyInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.private_key) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ reinterpret_cast<char *>(wpa_ssid->eap.private_key)};
+}
+
+std::pair<SupplicantStatus, std::string>
+StaNetwork::getEapSubjectMatchInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.subject_match) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ reinterpret_cast<char *>(wpa_ssid->eap.subject_match)};
+}
+
+std::pair<SupplicantStatus, std::string>
+StaNetwork::getEapAltSubjectMatchInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.altsubject_match) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ reinterpret_cast<char *>(wpa_ssid->eap.altsubject_match)};
+}
+
+std::pair<SupplicantStatus, bool> StaNetwork::getEapEngineInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->eap.engine == 1};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapEngineIDInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.engine_id) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""}, {wpa_ssid->eap.engine_id}};
+}
+
+std::pair<SupplicantStatus, std::string>
+StaNetwork::getEapDomainSuffixMatchInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.domain_suffix_match) {
+ return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+ }
+ return {{SupplicantStatusCode::SUCCESS, ""},
+ {wpa_ssid->eap.domain_suffix_match}};
+}
+
SupplicantStatus StaNetwork::enableInternal(bool no_connect)
{
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
- if (wpa_ssid->disabled != 0) {
+ if (wpa_ssid->disabled == 2) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
struct wpa_supplicant *wpa_s = retrieveIfacePtr();
@@ -1118,8 +1442,7 @@
*/
struct wpa_supplicant *StaNetwork::retrieveIfacePtr()
{
- return wpa_supplicant_get_iface(
- (struct wpa_global *)wpa_global_, ifname_.c_str());
+ return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
}
/**
diff --git a/wpa_supplicant/hidl/sta_network.h b/wpa_supplicant/hidl/sta_network.h
index f35f230..68ab139 100644
--- a/wpa_supplicant/hidl/sta_network.h
+++ b/wpa_supplicant/hidl/sta_network.h
@@ -131,6 +131,25 @@
uint32_t key_idx, getWepKey_cb _hidl_cb) override;
Return<void> getWepTxKeyIdx(getWepTxKeyIdx_cb _hidl_cb) override;
Return<void> getRequirePmf(getRequirePmf_cb _hidl_cb) override;
+ Return<void> getEapMethod(getEapMethod_cb _hidl_cb) override;
+ Return<void> getEapPhase2Method(
+ getEapPhase2Method_cb _hidl_cb) override;
+ Return<void> getEapIdentity(getEapIdentity_cb _hidl_cb) override;
+ Return<void> getEapAnonymousIdentity(
+ getEapAnonymousIdentity_cb _hidl_cb) override;
+ Return<void> getEapPassword(getEapPassword_cb _hidl_cb) override;
+ Return<void> getEapCACert(getEapCACert_cb _hidl_cb) override;
+ Return<void> getEapCAPath(getEapCAPath_cb _hidl_cb) override;
+ Return<void> getEapClientCert(getEapClientCert_cb _hidl_cb) override;
+ Return<void> getEapPrivateKey(getEapPrivateKey_cb _hidl_cb) override;
+ Return<void> getEapSubjectMatch(
+ getEapSubjectMatch_cb _hidl_cb) override;
+ Return<void> getEapAltSubjectMatch(
+ getEapAltSubjectMatch_cb _hidl_cb) override;
+ Return<void> getEapEngine(getEapEngine_cb _hidl_cb) override;
+ Return<void> getEapEngineID(getEapEngineID_cb _hidl_cb) override;
+ Return<void> getEapDomainSuffixMatch(
+ getEapDomainSuffixMatch_cb _hidl_cb) override;
Return<void> enable(bool no_connect, enable_cb _hidl_cb) override;
Return<void> disable(disable_cb _hidl_cb) override;
Return<void> select(select_cb _hidl_cb) override;
@@ -201,6 +220,27 @@
uint32_t key_idx);
std::pair<SupplicantStatus, uint32_t> getWepTxKeyIdxInternal();
std::pair<SupplicantStatus, bool> getRequirePmfInternal();
+ std::pair<SupplicantStatus, ISupplicantStaNetwork::EapMethod>
+ getEapMethodInternal();
+ std::pair<SupplicantStatus, ISupplicantStaNetwork::EapPhase2Method>
+ getEapPhase2MethodInternal();
+ std::pair<SupplicantStatus, std::vector<uint8_t>>
+ getEapIdentityInternal();
+ std::pair<SupplicantStatus, std::vector<uint8_t>>
+ getEapAnonymousIdentityInternal();
+ std::pair<SupplicantStatus, std::vector<uint8_t>>
+ getEapPasswordInternal();
+ std::pair<SupplicantStatus, std::string> getEapCACertInternal();
+ std::pair<SupplicantStatus, std::string> getEapCAPathInternal();
+ std::pair<SupplicantStatus, std::string> getEapClientCertInternal();
+ std::pair<SupplicantStatus, std::string> getEapPrivateKeyInternal();
+ std::pair<SupplicantStatus, std::string> getEapSubjectMatchInternal();
+ std::pair<SupplicantStatus, std::string>
+ getEapAltSubjectMatchInternal();
+ std::pair<SupplicantStatus, bool> getEapEngineInternal();
+ std::pair<SupplicantStatus, std::string> getEapEngineIDInternal();
+ std::pair<SupplicantStatus, std::string>
+ getEapDomainSuffixMatchInternal();
SupplicantStatus enableInternal(bool no_connect);
SupplicantStatus disableInternal();
SupplicantStatus selectInternal();
@@ -237,7 +277,7 @@
// Reference to the global wpa_struct. This is assumed to be valid
// for the lifetime of the process.
- const struct wpa_global* wpa_global_;
+ struct wpa_global* wpa_global_;
// Name of the iface this network belongs to.
const std::string ifname_;
// Id of the network this hidl object controls.
diff --git a/wpa_supplicant/hidl/supplicant.cpp b/wpa_supplicant/hidl/supplicant.cpp
index aba4402..409547f 100644
--- a/wpa_supplicant/hidl/supplicant.cpp
+++ b/wpa_supplicant/hidl/supplicant.cpp
@@ -165,7 +165,15 @@
SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
{
- // TODO: Add implementation.
+ if (type == IfaceType::STA) {
+ wpa_global_->conc_pref =
+ wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
+ } else if (type == IfaceType::P2P) {
+ wpa_global_->conc_pref =
+ wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
+ } else {
+ return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+ }
return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""};
}
} // namespace implementation
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index e88f147..858636f 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -20,6 +20,7 @@
#include "driver_i.h"
#include "config.h"
#include "scan.h"
+#include "notify.h"
#include "bss.h"
#include "blacklist.h"
#include "gas_query.h"
@@ -439,6 +440,10 @@
RX_HS20_ICON MACSTR " %s %u",
MAC2STR(sa), icon->file_name,
(unsigned int) icon->image_len);
+ wpas_notify_hs20_icon_query_done(wpa_s, sa,
+ icon->file_name,
+ icon->image,
+ icon->image_len);
return 0;
}
}
@@ -1161,6 +1166,7 @@
osu_method, url);
else
wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION);
+ wpas_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
}
@@ -1174,6 +1180,7 @@
wpa_msg(wpa_s, MSG_INFO, HS20_DEAUTH_IMMINENT_NOTICE "%u %u %s",
code, reauth_delay, url);
+ wpas_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay, url);
if (code == HS20_DEAUTH_REASON_CODE_BSS) {
wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist");
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 1fb40c7..d8368aa 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -3025,6 +3025,7 @@
out:
wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s",
MAC2STR(dst), anqp_result);
+ wpas_notify_anqp_query_done(wpa_s, dst, anqp_result, bss ? bss->anqp : NULL);
}
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index ba96548..5dac806 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -13,7 +13,6 @@
#include "config.h"
#include "wpa_supplicant_i.h"
#include "wps_supplicant.h"
-#include "hidl/hidl.h"
#include "dbus/dbus_common.h"
#include "dbus/dbus_old.h"
#include "dbus/dbus_new.h"
@@ -24,6 +23,7 @@
#include "p2p_supplicant.h"
#include "sme.h"
#include "notify.h"
+#include "hidl/hidl.h"
int wpas_notify_supplicant_initialized(struct wpa_global *global)
{
@@ -144,6 +144,8 @@
return;
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_DISCONNECT_REASON);
+
+ wpas_hidl_notify_assoc_reject(wpa_s);
}
@@ -153,6 +155,8 @@
return;
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ASSOC_STATUS_CODE);
+
+ wpas_hidl_notify_assoc_reject(wpa_s);
}
@@ -863,3 +867,53 @@
}
#endif /* CONFIG_P2P */
}
+
+void wpas_notify_anqp_query_done(struct wpa_supplicant *wpa_s, const u8* bssid,
+ const char *result,
+ const struct wpa_bss_anqp *anqp)
+{
+#ifdef CONFIG_INTERWORKING
+ if (!wpa_s || !bssid || !anqp)
+ return;
+
+ wpas_hidl_notify_anqp_query_done(wpa_s, bssid, result, anqp);
+#endif /* CONFIG_INTERWORKING */
+}
+
+void wpas_notify_hs20_icon_query_done(struct wpa_supplicant *wpa_s, const u8* bssid,
+ const char* file_name, const u8* image,
+ u32 image_length)
+{
+#ifdef CONFIG_HS20
+ if (!wpa_s || !bssid || !file_name || !image)
+ return;
+
+ wpas_hidl_notify_hs20_icon_query_done(wpa_s, bssid, file_name, image,
+ image_length);
+#endif /* CONFIG_HS20 */
+}
+
+void wpas_notify_hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
+ const char* url,
+ u8 osu_method)
+{
+#ifdef CONFIG_HS20
+ if (!wpa_s || !url)
+ return;
+
+ wpas_hidl_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
+#endif /* CONFIG_HS20 */
+}
+
+void wpas_notify_hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s,
+ u8 code, u16 reauth_delay,
+ const char *url)
+{
+#ifdef CONFIG_HS20
+ if (!wpa_s || !url)
+ return;
+
+ wpas_hidl_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay,
+ url);
+#endif /* CONFIG_HS20 */
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index e4d7fbf..2590e9a 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -10,6 +10,7 @@
#define NOTIFY_H
#include "p2p/p2p.h"
+#include "bss.h"
struct wps_credential;
struct wps_event_m2d;
@@ -141,5 +142,16 @@
void wpas_notify_p2p_invitation_received(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *go_dev_addr,
const u8 *bssid, int id, int op_freq);
-
+void wpas_notify_anqp_query_done(struct wpa_supplicant *wpa_s, const u8* bssid,
+ const char* result,
+ const struct wpa_bss_anqp *anqp);
+void wpas_notify_hs20_icon_query_done(struct wpa_supplicant *wpa_s, const u8* bssid,
+ const char* file_name, const u8* image,
+ u32 image_length);
+void wpas_notify_hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
+ const char* url,
+ u8 osu_method);
+void wpas_notify_hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s,
+ u8 code, u16 reauth_delay,
+ const char *url);
#endif /* NOTIFY_H */