Patchwork P2P: fix P2P device handling with RF-Kill

login
register
mail settings
Submitter Ilan Peer
Date March 3, 2014, 12:53 p.m.
Message ID <1393851204-964-6-git-send-email-ilan.peer@intel.com>
Download mbox | patch
Permalink /patch/325810/
State New
Headers show

Comments

Ilan Peer - March 3, 2014, 12:53 p.m.
From: Moshe Benji <Moshe.Benji@intel.com>

When RF-kill blocked becomes unblocked and vice versa, we should
enable or properly disable the P2P device respectively.

Additionally, when we start with RF-kill blocked, we should disable
the P2P interface. This is needed in cases where there is no netdev
associated with the P2P device.

Signed-off-by: Moshe Benji <Moshe.Benji@intel.com>
---
 src/common/defs.h               |    6 +++++
 src/drivers/driver_nl80211.c    |   46 ++++++++++++++++++++++++---------------
 src/p2p/p2p.c                   |   15 +++++++++++++
 src/p2p/p2p.h                   |    6 +++++
 wpa_supplicant/config.c         |    2 +-
 wpa_supplicant/ctrl_iface.c     |   11 +++++++++-
 wpa_supplicant/events.c         |   10 +++++++++
 wpa_supplicant/p2p_supplicant.c |    9 ++++++++
 wpa_supplicant/p2p_supplicant.h |    1 +
 9 files changed, 86 insertions(+), 20 deletions(-)

Patch

diff --git a/src/common/defs.h b/src/common/defs.h
index d4091e3..2f56b27 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -300,4 +300,10 @@  enum wpa_ctrl_req_type {
 /* Maximum number of EAP methods to store for EAP server user information */
 #define EAP_MAX_METHODS 8
 
+/* P2P Mgmt interface disabled by config or control interface */
+#define WPA_P2P_MGMT_CTRL_DISABLED BIT(0)
+
+/* P2P Mgmt interface disabled since the underlying interface is disabled*/
+#define WPA_P2P_MGMT_IF_DISABLED BIT(1)
+
 #endif /* DEFS_H */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 6df0a84..6790d2c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3997,11 +3997,15 @@  static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
 
 static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
 {
+	struct wpa_driver_nl80211_data *drv = ctx;
 	wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
+
 	/*
-	 * This may be for any interface; use ifdown event to disable
-	 * interface.
+	 * rtnetlink ifdown handler will report interfaces other than the P2P
+	 * Device interface as disabled.
 	 */
+	if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+		wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
 }
 
 
@@ -4014,7 +4018,13 @@  static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
 			   "after rfkill unblock");
 		return;
 	}
-	/* rtnetlink ifup handler will report interface as enabled */
+
+	/*
+	 * rtnetlink ifup handler will report interfaces other than the P2P
+	 * Device interface as enabled.
+	 */
+	if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+		wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
 }
 
 
@@ -4600,7 +4610,14 @@  wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 	wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
 		   bss->ifname, drv->phyname);
 
-	if (set_addr &&
+	if (drv->hostapd)
+		nlmode = NL80211_IFTYPE_AP;
+	else if (bss->if_dynamic)
+		nlmode = nl80211_get_ifmode(bss);
+	else
+		nlmode = NL80211_IFTYPE_STATION;
+
+	if (set_addr && (nlmode != NL80211_IFTYPE_P2P_DEVICE) &&
 	    (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||
 	     linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
 				set_addr)))
@@ -4609,13 +4626,6 @@  wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 	if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
 		drv->start_mode_ap = 1;
 
-	if (drv->hostapd)
-		nlmode = NL80211_IFTYPE_AP;
-	else if (bss->if_dynamic)
-		nlmode = nl80211_get_ifmode(bss);
-	else
-		nlmode = NL80211_IFTYPE_STATION;
-
 	if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
 		return -1;
@@ -4636,19 +4646,19 @@  wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 	} else {
 		wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
 			   "interface '%s' due to rfkill", bss->ifname);
-		if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
-			return 0;
-		drv->if_disabled = 1;
+		if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
+			drv->if_disabled = 1;
 		send_rfkill_event = 1;
 	}
 
-	if (!drv->hostapd)
+	if (!drv->hostapd && (nlmode != NL80211_IFTYPE_P2P_DEVICE))
 		netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
 				       1, IF_OPER_DORMANT);
 
-	if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
-			       bss->addr))
-		return -1;
+	if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
+		if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+				       bss->addr))
+				return -1;
 
 	if (send_rfkill_event) {
 		eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 4b90989..7740fb0 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -2452,6 +2452,21 @@  void p2p_deinit(struct p2p_data *p2p)
 }
 
 
+void p2p_reset(struct p2p_data *p2p)
+{
+	if (p2p == NULL)
+		return;
+
+	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
+	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
+	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
+	eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
+
+	p2p_flush(p2p);
+	wpabuf_free(p2p->sd_resp);
+}
+
+
 void p2p_flush(struct p2p_data *p2p)
 {
 	struct p2p_device *dev, *prev;
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 08e7176..7a4717a 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1196,6 +1196,12 @@  u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr);
  */
 void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr);
 
+/**
+ * p2p_reset - cancel timeouts and reset P2P data, state will be set to
+ * P2P_IDLE by p2p_flush()
+ * @p2p: P2P module context from p2p_init()
+ */
+void p2p_reset(struct p2p_data *p2p);
 
 /* Event notifications from lower layer driver operations */
 
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 23aab4b..378d0b9 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3551,7 +3551,7 @@  static const struct global_parse_data global_fields[] = {
 	{ INT_RANGE(p2p_add_cli_chan, 0, 1), 0 },
 	{ INT(p2p_go_ht40), 0 },
 	{ INT(p2p_go_vht), 0 },
-	{ INT(p2p_disabled), 0 },
+	{ INT_RANGE(p2p_disabled, 0, WPA_P2P_MGMT_CTRL_DISABLED), 0 },
 	{ INT(p2p_no_group_iface), 0 },
 	{ INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 },
 	{ IPV4(ip_addr_go), 0 },
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 793faec..16e98e8 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -4643,10 +4643,19 @@  static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
 		return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
 
 	if (os_strcmp(cmd, "disabled") == 0) {
-		wpa_s->global->p2p_disabled = atoi(param);
+		int disabled = atoi(param);
+
+		if (disabled)
+			wpa_s->global->p2p_disabled |=
+				WPA_P2P_MGMT_CTRL_DISABLED;
+		else
+			wpa_s->global->p2p_disabled &=
+				~WPA_P2P_MGMT_CTRL_DISABLED;
+
 		wpa_printf(MSG_DEBUG, "P2P functionality %s",
 			   wpa_s->global->p2p_disabled ?
 			   "disabled" : "enabled");
+
 		if (wpa_s->global->p2p_disabled) {
 			wpas_p2p_stop_find(wpa_s);
 			os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 059ffcb..d98e4a4 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3260,6 +3260,10 @@  void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
 			wpa_supplicant_update_mac_addr(wpa_s);
+			if (wpa_s->p2p_mgmt)
+				wpa_s->global->p2p_disabled &=
+					~WPA_P2P_MGMT_IF_DISABLED;
+
 #ifdef CONFIG_AP
 			if (!wpa_s->ap_iface) {
 				wpa_supplicant_set_state(wpa_s,
@@ -3288,6 +3292,12 @@  void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 			wpas_p2p_disconnect(wpa_s);
 			break;
 		}
+
+		if (wpa_s->p2p_mgmt) {
+			wpas_p2p_reset(wpa_s);
+			wpa_s->global->p2p_disabled |= WPA_P2P_MGMT_IF_DISABLED;
+		}
+
 #endif /* CONFIG_P2P */
 
 		wpa_supplicant_mark_disassoc(wpa_s);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index b878198..8c7bf4b 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -6881,6 +6881,15 @@  static void wpas_p2p_remove_client_go(struct wpa_supplicant *wpa_s,
 }
 
 
+void wpas_p2p_reset(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || wpa_s->global->p2p_disabled || !wpa_s->global->p2p)
+		return;
+
+	p2p_reset(wpa_s->global->p2p);
+}
+
+
 void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
 			    int iface_addr)
 {
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index d3d36b1..0403e3e 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -158,6 +158,7 @@  int wpas_p2p_nfc_report_handover(struct wpa_supplicant *wpa_s, int init,
 				 const struct wpabuf *req,
 				 const struct wpabuf *sel, int forced_freq);
 int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled);
+void wpas_p2p_reset(struct wpa_supplicant *wpa_s);
 
 #ifdef CONFIG_P2P
 int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);