Apply state changing depending on current status and events.
---
plugins/wifi.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 110 insertions(+), 11 deletions(-)
diff --git a/plugins/wifi.c b/plugins/wifi.c
index c1b4cfd..0d5d51d 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -120,6 +120,7 @@ struct wifi_data {
GSupplicantScanParams *scan_params;
unsigned int p2p_find_timeout;
unsigned int p2p_connection_timeout;
+ struct connman_peer *pending_peer;
bool p2p_connecting;
bool p2p_device;
};
@@ -190,12 +191,24 @@ static struct wifi_data *get_pending_wifi_data(const char
*ifname)
return NULL;
}
+static void peer_cancel_timeout(struct wifi_data *wifi)
+{
+ if (wifi->p2p_connection_timeout > 0)
+ g_source_remove(wifi->p2p_connection_timeout);
+ wifi->p2p_connection_timeout = 0;
+ wifi->p2p_connecting = false;
+ connman_peer_unref(wifi->pending_peer);
+ wifi->pending_peer = NULL;
+}
+
static gboolean peer_connect_timeout(gpointer data)
{
struct wifi_data *wifi = data;
- wifi->p2p_connection_timeout = 0;
- wifi->p2p_connecting = false;
+ if (wifi->p2p_connecting)
+ connman_peer_set_state(wifi->pending_peer,
+ CONNMAN_PEER_STATE_FAILURE);
+ peer_cancel_timeout(wifi);
return FALSE;
}
@@ -203,13 +216,20 @@ static gboolean peer_connect_timeout(gpointer data)
static void peer_connect_callback(int result, GSupplicantInterface *interface,
void *user_data)
{
- struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
- struct connman_peer *peer = user_data;
+ struct wifi_data *wifi = user_data;
+ struct connman_peer *peer = wifi->pending_peer;
DBG("peer %p - %d", peer, result);
- if (result < 0)
+ if (!peer)
+ return;
+
+ if (result < 0) {
+ connman_peer_set_state(peer, CONNMAN_PEER_STATE_FAILURE);
return;
+ }
+
+ connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
wifi->p2p_connection_timeout = g_timeout_add_seconds(
P2P_CONNECTION_TIMEOUT,
@@ -220,7 +240,6 @@ static int peer_connect(struct connman_peer *peer)
{
struct connman_device *device = connman_peer_get_device(peer);
GSupplicantPeerParams *peer_params;
- GSupplicantInterface *interface;
struct wifi_data *wifi;
int ret;
@@ -240,21 +259,38 @@ static int peer_connect(struct connman_peer *peer)
if (!peer_params)
return -ENOMEM;
- interface = wifi->interface;
-
peer_params->identifier = connman_peer_get_identifier(peer);
- ret = g_supplicant_interface_p2p_connect(interface, peer_params,
+ ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
peer_connect_callback, wifi);
- if (ret == -EINPROGRESS)
+ if (ret == -EINPROGRESS) {
+ wifi->pending_peer = connman_peer_ref(peer);
wifi->p2p_connecting = true;
+ } else if (ret < 0)
+ g_free(peer_params);
return ret;
}
static int peer_disconnect(struct connman_peer *peer)
{
- return 0;
+ struct connman_device *device = connman_peer_get_device(peer);
+ GSupplicantPeerParams peer_params = {};
+ struct wifi_data *wifi;
+
+ DBG("peer %p", peer);
+
+ if (!device)
+ return -ENODEV;
+
+ wifi = connman_device_get_data(device);
+ if (!wifi)
+ return -ENODEV;
+
+ peer_params.identifier = connman_peer_get_identifier(peer);
+
+ return g_supplicant_interface_p2p_disconnect(wifi->interface,
+ &peer_params);
}
static struct connman_peer_driver peer_driver = {
@@ -2261,11 +2297,73 @@ static void peer_lost(GSupplicantPeer *peer)
connman_peer = connman_peer_get(wifi->device, identifier);
if (connman_peer) {
+ if (wifi->p2p_connecting &&
+ wifi->pending_peer == connman_peer) {
+ connman_peer_set_state(connman_peer,
+ CONNMAN_PEER_STATE_FAILURE);
+ peer_cancel_timeout(wifi);
+ }
connman_peer_unregister(connman_peer);
connman_peer_unref(connman_peer);
}
}
+static void peer_changed(GSupplicantPeer *peer,
+ GSupplicantPeerGroupState state)
+{
+ GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
+ struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
+ enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
+ struct connman_peer *connman_peer;
+ const char *identifier;
+
+ identifier = g_supplicant_peer_get_identifier(peer);
+
+ DBG("ident: %s", identifier);
+
+ connman_peer = connman_peer_get(wifi->device, identifier);
+ if (!connman_peer)
+ return;
+
+ switch (state) {
+ case G_SUPPLICANT_PEER_GROUP_CHANGED:
+ if (!g_supplicant_peer_is_in_a_group(peer))
+ p_state = CONNMAN_PEER_STATE_IDLE;
+ break;
+ case G_SUPPLICANT_PEER_GROUP_STARTED:
+ p_state = CONNMAN_PEER_STATE_CONFIGURATION;
+ break;
+ case G_SUPPLICANT_PEER_GROUP_FINISHED:
+ p_state = CONNMAN_PEER_STATE_IDLE;
+ break;
+ case G_SUPPLICANT_PEER_GROUP_JOINED:
+ if (!g_supplicant_peer_is_in_a_group(peer))
+ break;
+ p_state = CONNMAN_PEER_STATE_READY;
+ break;
+ case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
+ p_state = CONNMAN_PEER_STATE_IDLE;
+ break;
+ case G_SUPPLICANT_PEER_GROUP_FAILED:
+ p_state = CONNMAN_PEER_STATE_FAILURE;
+ break;
+ }
+
+ if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
+ p_state == CONNMAN_PEER_STATE_FAILURE) {
+ if (wifi->p2p_connecting
+ && connman_peer == wifi->pending_peer)
+ peer_cancel_timeout(wifi);
+ else
+ p_state = CONNMAN_PEER_STATE_UNKNOWN;
+ }
+
+ if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
+ return;
+
+ connman_peer_set_state(connman_peer, p_state);
+}
+
static void debug(const char *str)
{
if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
@@ -2286,6 +2384,7 @@ static const GSupplicantCallbacks callbacks = {
.network_changed = network_changed,
.peer_found = peer_found,
.peer_lost = peer_lost,
+ .peer_changed = peer_changed,
.debug = debug,
};
--
1.8.5.5
_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman