Connection interface should be the master wifi interface.
Disconnection interface should be the p2p wifi interface createn during
connection.
---
 gsupplicant/gsupplicant.h |  20 +++++-
 gsupplicant/supplicant.c  | 155 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 172 insertions(+), 3 deletions(-)

diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
index df496e0..82c9bc6 100644
--- a/gsupplicant/gsupplicant.h
+++ b/gsupplicant/gsupplicant.h
@@ -168,6 +168,14 @@ struct _GSupplicantScanParams {
 
 typedef struct _GSupplicantScanParams GSupplicantScanParams;
 
+struct _GSupplicantPeerParams {
+       const char *identifier;
+       const char *wps_pin;
+       const char *path;
+};
+
+typedef struct _GSupplicantPeerParams GSupplicantPeerParams;
+
 /* global API */
 typedef void (*GSupplicantCountryCallback) (int result,
                                                const char *alpha2,
@@ -179,8 +187,10 @@ int g_supplicant_set_country(const char *alpha2,
 
 /* Interface API */
 struct _GSupplicantInterface;
+struct _GSupplicantPeer;
 
 typedef struct _GSupplicantInterface GSupplicantInterface;
+typedef struct _GSupplicantPeer GSupplicantPeer;
 
 typedef void (*GSupplicantInterfaceCallback) (int result,
                                        GSupplicantInterface *interface,
@@ -211,6 +221,14 @@ int g_supplicant_interface_p2p_find(GSupplicantInterface 
*interface,
 
 int g_supplicant_interface_p2p_stop_find(GSupplicantInterface *interface);
 
+int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface,
+                                       GSupplicantPeerParams *peer_params,
+                                       GSupplicantInterfaceCallback callback,
+                                       void *user_data);
+
+int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
+                                       GSupplicantPeerParams *peer_params);
+
 int g_supplicant_interface_connect(GSupplicantInterface *interface,
                                        GSupplicantSSID *ssid,
                                        GSupplicantInterfaceCallback callback,
@@ -250,11 +268,9 @@ int 
g_supplicant_interface_set_p2p_device_config(GSupplicantInterface *interface
 
 /* Network and Peer API */
 struct _GSupplicantNetwork;
-struct _GSupplicantPeer;
 struct _GSupplicantGroup;
 
 typedef struct _GSupplicantNetwork GSupplicantNetwork;
-typedef struct _GSupplicantPeer GSupplicantPeer;
 typedef struct _GSupplicantGroup GSupplicantGroup;
 
 GSupplicantInterface *g_supplicant_network_get_interface(GSupplicantNetwork 
*network);
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 27566fe..d5d265d 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -3167,7 +3167,10 @@ struct interface_connect_data {
        GSupplicantInterface *interface;
        char *path;
        GSupplicantInterfaceCallback callback;
-       GSupplicantSSID *ssid;
+       union {
+               GSupplicantSSID *ssid;
+               GSupplicantPeerParams *peer;
+       };
        void *user_data;
 };
 
@@ -4606,6 +4609,156 @@ int 
g_supplicant_interface_p2p_stop_find(GSupplicantInterface *interface)
                NULL, NULL, NULL, NULL);
 }
 
+static void interface_p2p_connect_result(const char *error,
+                                       DBusMessageIter *iter, void *user_data)
+{
+       struct interface_connect_data *data = user_data;
+       int err = 0;
+
+       SUPPLICANT_DBG("");
+
+       if (error)
+               err = parse_supplicant_error(iter);
+
+       if (data->callback)
+               data->callback(err, data->interface, data->user_data);
+
+       g_free(data->path);
+       g_free(data->peer);
+       g_free(data);
+}
+
+static void interface_p2p_connect_params(DBusMessageIter *iter, void 
*user_data)
+{
+       struct interface_connect_data *data = user_data;
+       const char *wps = "pbc";
+       DBusMessageIter dict;
+       int go_intent = 7;
+
+       SUPPLICANT_DBG("");
+
+       supplicant_dbus_dict_open(iter, &dict);
+
+       if (data->peer->wps_pin)
+               wps = "pin";
+
+       supplicant_dbus_dict_append_basic(&dict, "peer",
+                               DBUS_TYPE_OBJECT_PATH, &data->peer->path);
+       supplicant_dbus_dict_append_basic(&dict, "wps_method",
+                               DBUS_TYPE_STRING, &wps);
+       if (data->peer->wps_pin) {
+               supplicant_dbus_dict_append_basic(&dict, "pin",
+                               DBUS_TYPE_STRING, &data->peer->wps_pin);
+       }
+
+       supplicant_dbus_dict_append_basic(&dict, "go_intent",
+                                       DBUS_TYPE_INT32, &go_intent);
+
+       supplicant_dbus_dict_close(iter, &dict);
+}
+
+static gboolean peer_lookup_by_identifier(gpointer key, gpointer value,
+                                                       gpointer user_data)
+{
+       const GSupplicantPeer *peer = value;
+       const char *identifier = user_data;
+
+       if (!g_strcmp0(identifier, peer->identifier))
+               return TRUE;
+
+       return FALSE;
+}
+
+int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface,
+                                       GSupplicantPeerParams *peer_params,
+                                       GSupplicantInterfaceCallback callback,
+                                       void *user_data)
+{
+       struct interface_connect_data *data;
+       int ret;
+
+       SUPPLICANT_DBG("");
+
+       if (!interface->p2p_support)
+               return -ENOTSUP;
+
+       if (!peer_params->path) {
+               GSupplicantPeer *peer;
+
+               peer = g_hash_table_find(interface->peer_table,
+                                       peer_lookup_by_identifier,
+                                       (void *) peer_params->identifier);
+               if (!peer)
+                       return -ENODEV;
+
+               peer_params->path = peer->path;
+       }
+
+       data = dbus_malloc0(sizeof(*data));
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->peer = peer_params;
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(interface->path,
+               SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Connect",
+               interface_p2p_connect_params, interface_p2p_connect_result,
+               data, interface);
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+               return ret;
+       }
+
+       return -EINPROGRESS;
+}
+
+int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
+                                       GSupplicantPeerParams *peer_params)
+{
+       GSupplicantPeer *peer;
+       int count = 0;
+       GSList *list;
+
+       SUPPLICANT_DBG("");
+
+       if (!interface->p2p_support)
+               return -ENOTSUP;
+
+       peer = g_hash_table_find(interface->peer_table,
+                                       peer_lookup_by_identifier,
+                                       (void *) peer_params->identifier);
+       if (!peer)
+               return -ENODEV;
+
+       for (list = peer->groups; list; list = list->next, count++) {
+               const char *group_obj_path = list->data;
+               GSupplicantInterface *g_interface;
+               GSupplicantGroup *group;
+
+               group = g_hash_table_lookup(group_mapping, group_obj_path);
+               if (!group || !group->interface)
+                       continue;
+
+               g_interface = group->interface;
+               supplicant_dbus_method_call(g_interface->path,
+                               SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                               "Disconnect", NULL, NULL, NULL, g_interface);
+       }
+
+       if (count == 0 && peer->current_group_iface) {
+               supplicant_dbus_method_call(peer->current_group_iface->path,
+                               SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                               "Disconnect", NULL, NULL, NULL,
+                               peer->current_group_iface->path);
+       }
+
+       peer->current_group_iface = NULL;
+
+       return -EINPROGRESS;
+}
+
 static const char *g_supplicant_rule0 = "type=signal,"
                                        "path=" DBUS_PATH_DBUS ","
                                        "sender=" DBUS_SERVICE_DBUS ","
-- 
1.8.5.5

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to