|
@@ -46,6 +46,8 @@ static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
|
|
|
const u8 *dev_addr, enum p2p_wps_method wps_method);
|
|
|
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
|
|
|
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
|
|
|
+static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
|
|
|
+static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
|
|
|
|
|
|
|
|
|
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
|
|
@@ -175,6 +177,9 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s)
|
|
|
{
|
|
|
struct wpa_ssid *ssid;
|
|
|
char *gtype;
|
|
|
+ const char *reason;
|
|
|
+
|
|
|
+ eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
|
|
|
|
|
ssid = wpa_s->current_ssid;
|
|
|
if (ssid == NULL) {
|
|
@@ -208,8 +213,19 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s)
|
|
|
P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
|
|
|
wpa_s->ifname, wpa_s->cross_connect_uplink);
|
|
|
}
|
|
|
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_REMOVED "%s %s",
|
|
|
- wpa_s->ifname, gtype);
|
|
|
+ switch (wpa_s->removal_reason) {
|
|
|
+ case P2P_GROUP_REMOVAL_REQUESTED:
|
|
|
+ reason = " reason=REQUESTED";
|
|
|
+ break;
|
|
|
+ case P2P_GROUP_REMOVAL_IDLE_TIMEOUT:
|
|
|
+ reason = " reason=IDLE";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ reason = "";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_REMOVED "%s %s%s",
|
|
|
+ wpa_s->ifname, gtype, reason);
|
|
|
if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
|
|
|
struct wpa_global *global;
|
|
|
char *ifname;
|
|
@@ -451,6 +467,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
|
|
|
MAC2STR(go_dev_addr),
|
|
|
persistent ? " [PERSISTENT]" : "");
|
|
|
wpas_p2p_cross_connect_setup(wpa_s);
|
|
|
+ wpas_p2p_set_group_idle_timeout(wpa_s);
|
|
|
} else {
|
|
|
wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
|
|
|
"%s GO ssid=\"%s\" freq=%d passphrase=\"%s\" "
|
|
@@ -460,6 +477,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
|
|
|
MAC2STR(go_dev_addr),
|
|
|
persistent ? " [PERSISTENT]" : "");
|
|
|
wpas_p2p_cross_connect_setup(wpa_s);
|
|
|
+ wpas_p2p_set_group_idle_timeout(wpa_s);
|
|
|
}
|
|
|
|
|
|
if (persistent)
|
|
@@ -743,6 +761,7 @@ static void p2p_go_configured(void *ctx, void *data)
|
|
|
wpa_s->parent, ssid,
|
|
|
wpa_s->parent->own_addr);
|
|
|
wpas_p2p_cross_connect_setup(wpa_s);
|
|
|
+ wpas_p2p_set_group_idle_timeout(wpa_s);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -822,6 +841,8 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
|
|
|
C(device_type);
|
|
|
C(config_methods);
|
|
|
#undef C
|
|
|
+
|
|
|
+ d->p2p_group_idle = s->p2p_group_idle;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2244,6 +2265,7 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
|
|
|
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
|
|
|
wpa_s->p2p_long_listen = 0;
|
|
|
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
|
|
|
+ eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
|
|
wpas_p2p_remove_pending_group_interface(wpa_s);
|
|
|
|
|
|
/* TODO: remove group interface from the driver if this wpa_s instance
|
|
@@ -2782,6 +2804,7 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname)
|
|
|
while (wpa_s) {
|
|
|
prev = wpa_s;
|
|
|
wpa_s = wpa_s->next;
|
|
|
+ wpa_s->removal_reason = P2P_GROUP_REMOVAL_REQUESTED;
|
|
|
wpas_p2p_group_delete(prev);
|
|
|
}
|
|
|
return 0;
|
|
@@ -2795,6 +2818,7 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname)
|
|
|
if (wpa_s == NULL)
|
|
|
return -1;
|
|
|
|
|
|
+ wpa_s->removal_reason = P2P_GROUP_REMOVAL_REQUESTED;
|
|
|
wpas_p2p_group_delete(wpa_s);
|
|
|
|
|
|
return 0;
|
|
@@ -3001,6 +3025,19 @@ static void wpas_p2p_ie_update(void *ctx, struct wpabuf *beacon_ies,
|
|
|
}
|
|
|
|
|
|
|
|
|
+static void wpas_p2p_idle_update(void *ctx, int idle)
|
|
|
+{
|
|
|
+ struct wpa_supplicant *wpa_s = ctx;
|
|
|
+ if (!wpa_s->ap_iface)
|
|
|
+ return;
|
|
|
+ wpa_printf(MSG_DEBUG, "P2P: GO - group %sidle", idle ? "" : "not ");
|
|
|
+ if (idle)
|
|
|
+ wpas_p2p_set_group_idle_timeout(wpa_s);
|
|
|
+ else
|
|
|
+ eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
|
|
|
int persistent_group,
|
|
|
int group_formation)
|
|
@@ -3021,6 +3058,7 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
|
|
|
cfg->max_clients = wpa_s->conf->max_num_sta;
|
|
|
cfg->cb_ctx = wpa_s;
|
|
|
cfg->ie_update = wpas_p2p_ie_update;
|
|
|
+ cfg->idle_update = wpas_p2p_idle_update;
|
|
|
|
|
|
group = p2p_group_init(wpa_s->global->p2p, cfg);
|
|
|
if (group == NULL)
|
|
@@ -3375,6 +3413,39 @@ int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
|
|
|
}
|
|
|
|
|
|
|
|
|
+static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx)
|
|
|
+{
|
|
|
+ struct wpa_supplicant *wpa_s = eloop_ctx;
|
|
|
+
|
|
|
+ if (wpa_s->conf->p2p_group_idle == 0) {
|
|
|
+ wpa_printf(MSG_DEBUG, "P2P: Ignore group idle timeout - "
|
|
|
+ "disabled");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ wpa_printf(MSG_DEBUG, "P2P: Group idle timeout reached - terminate "
|
|
|
+ "group");
|
|
|
+ wpa_s->removal_reason = P2P_GROUP_REMOVAL_IDLE_TIMEOUT;
|
|
|
+ wpas_p2p_group_delete(wpa_s);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s)
|
|
|
+{
|
|
|
+ eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
|
|
+ if (wpa_s->conf->p2p_group_idle == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (wpa_s->current_ssid == NULL || !wpa_s->current_ssid->p2p_group)
|
|
|
+ return;
|
|
|
+
|
|
|
+ wpa_printf(MSG_DEBUG, "P2P: Set P2P group idle timeout to %u seconds",
|
|
|
+ wpa_s->conf->p2p_group_idle);
|
|
|
+ eloop_register_timeout(wpa_s->conf->p2p_group_idle, 0,
|
|
|
+ wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|
|
u16 reason_code, const u8 *ie, size_t ie_len)
|
|
|
{
|
|
@@ -3557,12 +3628,16 @@ void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s)
|
|
|
wpas_p2p_disable_cross_connect(wpa_s);
|
|
|
else
|
|
|
wpas_p2p_enable_cross_connect(wpa_s);
|
|
|
+ if (!wpa_s->ap_iface)
|
|
|
+ eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
|
|
}
|
|
|
|
|
|
|
|
|
void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s)
|
|
|
{
|
|
|
wpas_p2p_disable_cross_connect(wpa_s);
|
|
|
+ if (!wpa_s->ap_iface)
|
|
|
+ wpas_p2p_set_group_idle_timeout(wpa_s);
|
|
|
}
|
|
|
|
|
|
|