[PATCH] P2P: fix P2P device handling with RF-Kill
Ilan Peer
ilan.peer
Mon Mar 3 04:53:22 PST 2014
From: Moshe Benji <Moshe.Benji at 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 at 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(-)
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);
--
1.7.10.4
More information about the Hostap
mailing list