[PATCH] Connman : Initial P2P Invite and P2P Scan Implementation
Shailesh Rathod/LGSI Connectivity Team <[email protected]> Mon, 7 Jul 2025 07:13:13 +0000
| Newsgroups | dev.linux.lists.connman |
|---|---|
| Message-ID | <SE1P216MB2647D406E36999304E431A80F04FA@SE1P216MB2647.KORP216.PROD.OUTLOOK.COM> |
From b8ffe29f0969da98ab09de8bf9592a8777d84e5f Mon Sep 17 00:00:00 2001 From: shailesh <[email protected]> Date: Tue, 24 Jun 2025 13:41:08 +0000 Subject: [PATCH] Initial P2P Invite and P2P Scan Implementation - Added support for P2P Invite operation, including new structures and callbacks in gsupplicant. - Implemented DBus methods and callbacks for handling P2P invitation results and received invitations. - Extended device, peer, and technology interfaces to support P2P scan and invitation flows. - Added new driver hooks and logic in wifi plugin for P2P scanning and invitation handling. --- gsupplicant/gsupplicant.h | 37 ++++ gsupplicant/supplicant.c | 425 +++++++++++++++++++++++++++++++++++++- include/device.h | 2 + include/peer.h | 3 + include/technology.h | 2 + plugins/wifi.c | 160 +++++++++++++- src/connman.h | 2 +- src/device.c | 43 +++- src/group.c | 36 +++- src/peer.c | 36 ++-- src/technology.c | 26 ++- 11 files changed, 739 insertions(+), 33 deletions(-) diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h index 26d5f73..eecad9c 100644 --- a/gsupplicant/gsupplicant.h +++ b/gsupplicant/gsupplicant.h @@ -220,6 +220,37 @@ struct _GSupplicantP2PGroupAddParams { typedef struct _GSupplicantP2PGroupAddParams GSupplicantP2PGroupAddParams; +/** + * Parameters for a P2P Invite operation. + * + * peer: The MAC address of the peer device to invite. + * persistent_group: The identifier for the persistent group to be used for the invitation. + * frequency: The frequency (in MHz) on which to perform the invitation. + */ +struct _GSupplicantP2PInviteParams { + const char *peer; + const char *persistent_group; + int frequency; +}; + +typedef struct _GSupplicantP2PInviteParams GSupplicantP2PInviteParams; + +typedef enum +{ + G_SUPPLICANT_P2P_FIND_START_WITH_FULL, + G_SUPPLICANT_P2P_FIND_ONLY_SOCIAL, + G_SUPPLICANT_P2P_FIND_PROGRESSIVE +} GSupplicantP2PFindType; + +struct _GSupplicantP2PFindParams { + int timeout; + int disc_type; + const char** seek_array; + int frequency; +}; + +typedef struct _GSupplicantP2PFindParams GSupplicantP2PFindParams; + /* global API */ typedef void (*GSupplicantCountryCallback) (int result, const char *alpha2, @@ -295,6 +326,10 @@ int g_supplicant_interface_p2p_add_service(GSupplicantInterface *interface, int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface, GSupplicantP2PServiceParams *p2p_service_params); +int g_supplicant_interface_p2p_invite(GSupplicantInterface *interface, + GSupplicantP2PInviteParams *invite_data, + GSupplicantInterfaceCallback callback, void *user_data); + /* Flushes all P2P peer information and cached data from the given interface. */ int g_supplicant_interface_p2p_flush(GSupplicantInterface *interface, GSupplicantInterfaceCallback callback, void *user_data); @@ -452,6 +487,8 @@ struct _GSupplicantCallbacks { int reasoncode); void (*p2p_group_started)(GSupplicantGroup *group); void (*p2p_group_finished)(GSupplicantInterface *interface); + void (*p2p_invitation_result)(GSupplicantInterface *interface, int status); + void (*p2p_invitation_received) (GSupplicantInterface *interface, GSupplicantPeer *p2p_network, const char *go_dev_addr, bool persistent); }; typedef struct _GSupplicantCallbacks GSupplicantCallbacks; diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index 36159e6..6fd7384 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -146,6 +146,8 @@ static GHashTable *peer_mapping; static GHashTable *group_mapping; static GHashTable *pending_peer_connection; static GHashTable *config_file_table; +static GHashTable *p2p_peer_table; + struct _GSupplicantWpsCredentials { unsigned char ssid[32]; @@ -302,6 +304,13 @@ struct interface_connect_data { }; }; +struct interface_p2p_invite_data { + GSupplicantInterface *interface; + GSupplicantInterfaceCallback callback; + GSupplicantP2PInviteParams *p2p_invite_params; + void *user_data; +}; + struct interface_scan_data { GSupplicantInterface *interface; char *path; @@ -310,6 +319,15 @@ struct interface_scan_data { void *user_data; }; +struct g_supplicant_p2p_inv_recv_info { + GSupplicantInterface *interface; + const char *p2p_go_dev_addr; + const char *src_addr; + bool persistent; +}; + +static int inv_recv_ref = -1; + static int network_remove(struct interface_data *data); void __connman_util_byte_to_string(unsigned char *src, char *dest, int len); @@ -960,6 +978,9 @@ static void remove_peer(gpointer data) if (pending_peer_connection) g_hash_table_remove(pending_peer_connection, peer->path); + if (p2p_peer_table) + g_hash_table_remove(p2p_peer_table, peer->path); + g_free(peer->path); g_free(peer->name); g_free(peer->identifier); @@ -1606,6 +1627,84 @@ bool g_supplicant_peer_is_client(GSupplicantPeer *peer) return false; } +static void interface_p2p_invite_params(DBusMessageIter *iter, void *user_data) +{ + DBusMessageIter dict; + struct interface_p2p_invite_data *data = user_data; + + SUPPLICANT_DBG(""); + + supplicant_dbus_dict_open(iter, &dict); + + if (data && data->p2p_invite_params) { + GSupplicantP2PInviteParams* params = data->p2p_invite_params; + + supplicant_dbus_dict_append_basic(&dict, "peer", + DBUS_TYPE_OBJECT_PATH, ¶ms->peer); + } + + supplicant_dbus_dict_close(iter, &dict); +} + +static void interface_p2p_invite_result(const char *error, + DBusMessageIter *iter, void *user_data) +{ + struct interface_p2p_invite_data *data = user_data; + int err = 0; + + SUPPLICANT_DBG(""); + + if (error) { + SUPPLICANT_DBG("error %s", error); + err = -EIO; + } + + if (data->callback) + data->callback(err, data->interface, data->user_data); + + dbus_free(data); +} + +int g_supplicant_interface_p2p_invite(GSupplicantInterface *interface, + GSupplicantP2PInviteParams *invite_data, + GSupplicantInterfaceCallback callback, void *user_data) +{ + struct interface_p2p_invite_data *data; + int ret; + + SUPPLICANT_DBG(""); + + if (!interface) + return -EINVAL; + + if (!interface->p2p_support) + return -ENOTSUP; + + data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + + data->user_data = user_data; + data->interface = interface; + data->callback = callback; + data->p2p_invite_params = invite_data; + + SUPPLICANT_DBG("interface->path : %s\n", interface->path); + + ret = supplicant_dbus_method_call(interface->path, + SUPPLICANT_INTERFACE ".Interface.P2PDevice", + "Invite", + interface_p2p_invite_params, + interface_p2p_invite_result, data, interface); + + if (ret < 0) { + dbus_free(data); + return ret; + } + + return -EINPROGRESS; +} + bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer) { if (!peer) @@ -2837,6 +2936,7 @@ static void signal_name_owner_changed(const char *path, DBusMessageIter *iter) g_hash_table_remove_all(group_mapping); g_hash_table_remove_all(config_file_table); g_hash_table_remove_all(interface_table); + g_hash_table_remove_all(p2p_peer_table); callback_system_killed(); } @@ -3295,6 +3395,8 @@ static void peer_property(const char *key, DBusMessageIter *iter, return; if (!key) { + if (g_hash_table_lookup(p2p_peer_table, peer->path) == NULL) + return; if (peer->name) { create_peer_identifier(peer); callback_peer_found(peer); @@ -3377,6 +3479,7 @@ static void peer_property(const char *key, DBusMessageIter *iter, static void signal_peer_found(const char *path, DBusMessageIter *iter) { + struct peer_property_data *property_data; GSupplicantInterface *interface; const char *obj_path = NULL; @@ -3404,6 +3507,7 @@ static void signal_peer_found(const char *path, DBusMessageIter *iter) peer->path = g_strdup(obj_path); g_hash_table_insert(interface->peer_table, peer->path, peer); g_hash_table_replace(peer_mapping, peer->path, interface); + g_hash_table_replace(p2p_peer_table, g_strdup(peer->path), peer); property_data = dbus_malloc0(sizeof(struct peer_property_data)); property_data->peer = peer; @@ -3889,6 +3993,282 @@ static void signal_group_request(const char *path, DBusMessageIter *iter) g_hash_table_replace(pending_peer_connection, peer->path, peer); } +static void callback_p2p_invitation_result(GSupplicantInterface *interface, int status) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->p2p_invitation_result) + return; + + callbacks_pointer->p2p_invitation_result(interface, status); +} + +static void interface_p2p_invitation_result(DBusMessageIter *iter, void *user_data) +{ + GSupplicantInterface *interface = user_data; + DBusMessageIter dict, entry, value; + char *key; + int status = 0; + + SUPPLICANT_DBG("interface_p2p_invitation_result"); + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) { + SUPPLICANT_DBG("not array\n"); + return; + } + + dbus_message_iter_recurse(iter, &dict); + if(dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) { + SUPPLICANT_DBG("not dict\n"); + return; + } + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) { + SUPPLICANT_DBG("not string\n"); + return; + } + + dbus_message_iter_get_basic(&entry, &key); + SUPPLICANT_DBG("key : %s\n", key); + if(!g_str_equal(key, "status")) { + SUPPLICANT_DBG("not status\n"); + return; + } + + dbus_message_iter_next(&entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) { + SUPPLICANT_DBG("not variant\n"); + return; + } + + dbus_message_iter_recurse(&entry, &value); + dbus_message_iter_get_basic(&value, &status); + SUPPLICANT_DBG("status : %d\n", status); + + callback_p2p_invitation_result(interface, status); +} + +static void signal_invitation_result(const char *path, DBusMessageIter *iter) +{ + GSupplicantInterface *interface; + + SUPPLICANT_DBG("signal invitation result"); + + interface = g_hash_table_lookup(interface_table, path); + if (!interface) + return; + + interface_p2p_invitation_result(iter, interface); +} + +static void callback_p2p_invitation_received(GSupplicantInterface *interface, GSupplicantPeer *peer, const char *go_dev_addr, bool persistent) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->p2p_invitation_received) + return; + + callbacks_pointer->p2p_invitation_received(interface, peer, go_dev_addr, persistent); +} + +static gboolean check_inv_src_network(gpointer argv) +{ + struct g_supplicant_p2p_inv_recv_info *inv_recv = argv; + GSupplicantInterface *interface = inv_recv->interface; + + GSupplicantPeer *peer = g_supplicant_interface_peer_lookup(interface, inv_recv->src_addr); + + if(!peer) { + inv_recv_ref = g_timeout_add(200, check_inv_src_network, inv_recv); + return FALSE; + } + + callback_p2p_invitation_received(interface, peer, inv_recv->p2p_go_dev_addr, inv_recv->persistent); + + g_free(inv_recv); + inv_recv_ref = -1; + return FALSE; +} + +static void interface_p2p_invitation_received(DBusMessageIter *iter, void *user_data) +{ + GSupplicantInterface *interface = user_data; + DBusMessageIter dict, entry, value, array; + char *key; + int status; + int addr_len = 6; + unsigned char *bssid, *go_dev_addr, *src_addr; + char go_dev_addr_str[13], src_addr_str[13]; + char *p_go_dev_addr, *p_src_addr; + + SUPPLICANT_DBG("interface_p2p_invitation_received"); + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) { + SUPPLICANT_DBG("not array\n"); + return; + } + + dbus_message_iter_recurse(iter, &dict); + if(dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) { + SUPPLICANT_DBG("not dict\n"); + return; + } + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) { + SUPPLICANT_DBG("not string\n"); + return; + } + + dbus_message_iter_get_basic(&entry, &key); + SUPPLICANT_DBG("key : %s\n", key); + if(!g_str_equal(key, "status")) { + SUPPLICANT_DBG("not status\n"); + return; + } + + dbus_message_iter_next(&entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) { + SUPPLICANT_DBG("not variant\n"); + return; + } + + dbus_message_iter_recurse(&entry, &value); + dbus_message_iter_get_basic(&value, &status); + SUPPLICANT_DBG("status : %d\n", status); + + if(status == 0) //Persistent group reinvoke case + g_supplicant_interface_p2p_listen(interface, 0, 0); + + else if(status != 1) + return; + + dbus_message_iter_next(&dict); + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) { + SUPPLICANT_DBG("not string\n"); + return; + } + + dbus_message_iter_get_basic(&entry, &key); + SUPPLICANT_DBG("key : %s\n", key); + if(!g_str_equal(key, "sa")) { + SUPPLICANT_DBG("not sa\n"); + return; + } + + dbus_message_iter_next(&entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) { + SUPPLICANT_DBG("not variant\n"); + return; + } + + dbus_message_iter_recurse(&entry, &value); + dbus_message_iter_recurse(&value, &array); + + dbus_message_iter_get_fixed_array(&array, &src_addr, &addr_len); + + dbus_message_iter_next(&dict); + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) { + SUPPLICANT_DBG("not string\n"); + return; + } + + dbus_message_iter_get_basic(&entry, &key); + SUPPLICANT_DBG("key : %s\n", key); + + if(!g_str_equal(key, "go_dev_addr")) { + SUPPLICANT_DBG("not go_dev_addr\n"); + return; + } + + dbus_message_iter_next(&entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) { + SUPPLICANT_DBG("not variant\n"); + return; + } + + dbus_message_iter_recurse(&entry, &value); + dbus_message_iter_recurse(&value, &array); + + dbus_message_iter_get_fixed_array(&array, &go_dev_addr, &addr_len); + + dbus_message_iter_next(&dict); + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) { + SUPPLICANT_DBG("not string\n"); + return; + } + + dbus_message_iter_get_basic(&entry, &key); + SUPPLICANT_DBG("key : %s\n", key); + if(!g_str_equal(key, "bssid")) { + if(status == 0) + goto go_next; //BSSID is not exist at persistent go case + SUPPLICANT_DBG("not bssid\n"); + return; + } + + dbus_message_iter_next(&entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) { + SUPPLICANT_DBG("not variant\n"); + return; + } + + dbus_message_iter_recurse(&entry, &value); + dbus_message_iter_recurse(&value, &array); + + dbus_message_iter_get_fixed_array(&array, &bssid, &addr_len); + +go_next: + + __connman_util_byte_to_string(go_dev_addr, go_dev_addr_str, 6); + p_go_dev_addr = g_strdup(go_dev_addr_str); + + __connman_util_byte_to_string(src_addr, src_addr_str, 6); + p_src_addr = g_strdup(src_addr_str); + + if (inv_recv_ref != -1) { + g_free(p_src_addr); + g_free(p_go_dev_addr); + return; + } + + struct g_supplicant_p2p_inv_recv_info *inv_recv = g_try_new0(struct g_supplicant_p2p_inv_recv_info, 1); + if (!inv_recv) { + g_free(p_src_addr); + g_free(p_go_dev_addr); + return; + } + + inv_recv->interface = interface; + inv_recv->p2p_go_dev_addr = p_go_dev_addr; + inv_recv->src_addr = p_src_addr; + inv_recv->persistent = !status; + inv_recv_ref = g_timeout_add(500, check_inv_src_network, inv_recv); + return; +} + +static void signal_invitation_received(const char *path, DBusMessageIter *iter) +{ + GSupplicantInterface *interface; + + SUPPLICANT_DBG("signal invitation received"); + + interface = g_hash_table_lookup(interface_table, path); + if (!interface) + return; + + interface_p2p_invitation_received(iter, interface); +} + static void signal_group_peer_joined(const char *path, DBusMessageIter *iter) { const char *peer_path = NULL; @@ -3997,6 +4377,10 @@ static struct { { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupFinished", signal_group_finished }, { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationRequest", signal_group_request }, + { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "InvitationResult", signal_invitation_result }, + { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "InvitationReceived", signal_invitation_received }, + + { SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined }, { SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected }, @@ -5759,27 +6143,38 @@ int g_supplicant_interface_disconnect(GSupplicantInterface *interface, return ret; } +struct interface_p2p_find_data { + GSupplicantInterface *interface; + char *path; + GSupplicantInterfaceCallback callback; + GSupplicantP2PFindParams *p2p_find_params; + void *user_data; +}; + static void interface_p2p_find_result(const char *error, DBusMessageIter *iter, void *user_data) { - struct interface_scan_data *data = user_data; + struct interface_p2p_find_data *data = user_data; int err = 0; - SUPPLICANT_DBG("error %s", error); - - if (error) + if (error != NULL) { + SUPPLICANT_DBG("error %s", error); err = -EIO; - + } if (interface_exists(data->interface, data->path)) { if (!data->interface->ready) err = -ENOLINK; - if (!err) + if (!err) { data->interface->p2p_finding = true; + } } - if (data->callback) + if (data->callback != NULL) data->callback(err, data->interface, data->user_data); + if (data->p2p_find_params) + g_free(data->p2p_find_params); + g_free(data->path); dbus_free(data); } @@ -5787,6 +6182,10 @@ static void interface_p2p_find_result(const char *error, static void interface_p2p_find_params(DBusMessageIter *iter, void *user_data) { DBusMessageIter dict; + struct interface_p2p_find_data *data = user_data; + int timeout = 0; + char *disc_type = "start_with_full"; + int freq = 0; supplicant_dbus_dict_open(iter, &dict); supplicant_dbus_dict_close(iter, &dict); @@ -6706,6 +7105,8 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks) NULL, NULL); config_file_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + p2p_peer_table = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); supplicant_dbus_setup(connection); @@ -6801,6 +7202,16 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks) interface_table = NULL; } + if (p2p_peer_table != NULL){ + g_hash_table_destroy(p2p_peer_table); + p2p_peer_table = NULL; + } + + if (p2p_peer_table != NULL){ + g_hash_table_destroy(p2p_peer_table); + p2p_peer_table = NULL; + } + if (system_available) callback_system_killed(); diff --git a/include/device.h b/include/device.h index 0fc06bd..2a2cc77 100644 --- a/include/device.h +++ b/include/device.h @@ -137,6 +137,8 @@ struct connman_device_driver { struct connman_device *device); int (*set_regdom) (struct connman_device *device, const char *alpha2); + int (*scan_p2p)(enum connman_service_type type, + struct connman_device *device); }; int connman_device_driver_register(struct connman_device_driver *driver); diff --git a/include/peer.h b/include/peer.h index 6fe5e64..f6be3cb 100644 --- a/include/peer.h +++ b/include/peer.h @@ -112,6 +112,9 @@ void connman_peer_driver_unregister(struct connman_peer_driver *driver); struct connman_peer *connman_peer_get_by_path(const char *path); void __connman_peer_get_properties_struct(DBusMessageIter *iter, gpointer user_data); +struct connman_peer *connman_peer_get_by_path(const char *path); +const char *connman_peer_get_identifier(struct connman_peer *peer); + bool connman_peer_service_is_master(void); #ifdef __cplusplus diff --git a/include/technology.h b/include/technology.h index 391b446..965ad49 100644 --- a/include/technology.h +++ b/include/technology.h @@ -75,6 +75,8 @@ int connman_technology_driver_register(struct connman_technology_driver *driver) void connman_technology_driver_unregister(struct connman_technology_driver *driver); void connman_technology_set_p2p_listen(struct connman_technology *technology,bool enabled); bool connman_technology_get_p2p_listen(struct connman_technology *technology); +void __connman_technology_p2p_invitation_result(struct connman_technology *technology, + int status); #ifdef __cplusplus } #endif diff --git a/plugins/wifi.c b/plugins/wifi.c index 9fa22dd..c6629f1 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -61,6 +61,8 @@ #include "src/shared/util.h" +#include "src/connman.h" + #define CLEANUP_TIMEOUT 8 /* in seconds */ #define INACTIVE_TIMEOUT 12 /* in seconds */ #define FAVORITE_MAXIMUM_RETRIES 2 @@ -85,6 +87,10 @@ static int p2p_group_ifindex = -1; static char *p2p_go_identifier = NULL; +static guint p2p_scan_ref = 0; + +static int p2p_find_ref = -1; + #define ASSOC_STATUS_AUTH_TIMEOUT 16 #define ASSOC_STATUS_NO_CLIENT 17 #define LOAD_SHAPING_MAX_RETRIES 3 @@ -177,6 +183,7 @@ struct wifi_data { int servicing; int disconnect_code; int assoc_code; + const char *invited_path; }; struct wifi_network { @@ -1048,6 +1055,12 @@ static void wifi_remove(struct connman_device *device) if (wifi->scan_params) g_supplicant_free_scan_params(wifi->scan_params); + if (p2p_scan_ref) { + g_source_remove(p2p_scan_ref); + p2p_scan_ref = 0; + } + + g_free(wifi->autoscan); g_free(wifi->identifier); g_free(wifi); @@ -1945,6 +1958,22 @@ static gboolean p2p_find_stop(gpointer data) return FALSE; } +static gboolean p2p_find_complete(gpointer argv) +{ + struct connman_device *device = argv; + struct wifi_data *wifi = connman_device_get_data(device); + int ret = 0; + + if(!wifi) { + p2p_find_ref = -1; + return FALSE; + } + + p2p_find_ref = -1; + + return FALSE; +} + static void p2p_find_callback(int result, GSupplicantInterface *interface, void *user_data) { @@ -1969,6 +1998,8 @@ static void p2p_find_callback(int result, GSupplicantInterface *interface, if (!wifi->p2p_find_timeout) goto error; + p2p_find_ref = -1; + return; error: p2p_find_stop(device); @@ -1994,12 +2025,16 @@ static int p2p_find(struct connman_device *device) ret = g_supplicant_interface_p2p_find(wifi->interface, p2p_find_callback, device); + + DBG("p2p_find returned %d", ret); + if (ret) { connman_device_unref(device); start_autoscan(device); } else { connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, true); + p2p_find_ref = g_timeout_add_seconds(wifi->p2p_find_timeout, p2p_find_complete, device); } return ret; @@ -2184,6 +2219,41 @@ static int wifi_set_regdom(struct connman_device *device, const char *alpha2) return ret; } +static gboolean check_wifi_device_connecting(gpointer argv) +{ + struct connman_device *device = argv; + + bool connecting = false; + bool wifi_total = false; + p2p_scan_ref = 0; + + p2p_find(device); + return FALSE; +} + + +static int wifi_scan_p2p(enum connman_service_type type, + struct connman_device *device) +{ + int ret; + + connman_info("wifi_scan_p2p"); + + if (!p2p_technology) + return -ENOTSUP; + + + + if (p2p_scan_ref) { + connman_warn("wifi_scan_p2p p2p_scan_ref=%u", p2p_scan_ref); + return -EALREADY; + } + + p2p_scan_ref = g_timeout_add_full(G_PRIORITY_DEFAULT, 2000, check_wifi_device_connecting, device, NULL); + + return 0; +} + static struct connman_device_driver wifi_ng_driver = { .name = "wifi", .type = CONNMAN_DEVICE_TYPE_WIFI, @@ -2193,10 +2263,16 @@ static struct connman_device_driver wifi_ng_driver = { .enable = wifi_enable, .disable = wifi_disable, .scan = wifi_scan, + .scan_p2p = wifi_scan_p2p, .stop_scan = wifi_stop_scan, .set_regdom = wifi_set_regdom, }; + + + + + static void system_ready(void) { DBG(""); @@ -3215,6 +3291,82 @@ static void network_associated(GSupplicantNetwork *network) interface_state(interface); } +static void p2p_invitation_result(GSupplicantInterface *interface, int status) +{ + struct wifi_data *wifi; + + wifi = g_supplicant_interface_get_data(interface); + + if (!wifi) + return; + + DBG("status %i", status); + + __connman_technology_p2p_invitation_result(p2p_technology, status); +} + +static void p2p_invitation_received(GSupplicantInterface *interface, + GSupplicantPeer *peer, const char *go_dev_addr, bool persistent) +{ + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); + struct connman_peer *connman_peer; + const char *identifier, *path; + const char *go_dev_addr_colon; + + if (!wifi || !wifi->device) + return; + + identifier = g_supplicant_peer_get_identifier(peer); + + DBG("ident: %s", identifier); + + connman_peer = connman_peer_get(wifi->device, identifier); + if (!connman_peer) + return; + + go_dev_addr_colon = __connman_util_insert_colon_to_mac_addr(go_dev_addr); + path = __connman_peer_get_path(connman_peer); + + if (!path) { + g_free(go_dev_addr_colon); + return; + } + + if (!persistent) { + connman_peer_set_state(connman_peer, CONNMAN_PEER_STATE_IDLE); + + /* Invitation received from GO */ + if (g_str_equal(identifier, go_dev_addr)) { + wifi->invited_path = __connman_peer_get_path(connman_peer); + /* Sometimes there is only src address in InvitationReceived signal without GO device address */ + } else if (g_str_equal(go_dev_addr, "000000000000")) { + wifi->invited_path = __connman_peer_get_path(connman_peer); + g_free(go_dev_addr_colon); + go_dev_addr_colon = __connman_util_insert_colon_to_mac_addr(identifier); + } else { + struct connman_network *network_go = connman_device_get_network(wifi->device, go_dev_addr); + + if (network_go) { + struct connman_service *service_go; + + wifi->invited_path = connman_network_get_string(network_go, "Path"); + } + } + + connman_dbus_property_changed_basic(path, CONNMAN_PEER_INTERFACE, + "P2PInvitationReceived", DBUS_TYPE_STRING, &go_dev_addr_colon); + + } else { + p2p_find_stop(wifi->device); + if (connman_technology_get_p2p_listen(wifi_technology)) //already changed to listen off + connman_technology_set_p2p_listen(wifi_technology, false); + + connman_dbus_property_changed_basic(path, CONNMAN_PEER_INTERFACE, + "P2PPersistentReceived", DBUS_TYPE_STRING, &go_dev_addr_colon); + } +} + + static void sta_authorized(GSupplicantInterface *interface, const char *addr) { @@ -3263,11 +3415,15 @@ static void peer_found(GSupplicantPeer *peer) GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer); struct wifi_data *wifi = g_supplicant_interface_get_data(iface); struct connman_peer *connman_peer; - const char *identifier, *name; + const char *identifier, *name,*path; int ret; identifier = g_supplicant_peer_get_identifier(peer); name = g_supplicant_peer_get_name(peer); + path = g_supplicant_peer_get_path(peer); + + DBG("peer_found - ident: %s", identifier); + DBG("ident: %s", identifier); @@ -3546,6 +3702,8 @@ static const GSupplicantCallbacks callbacks = { .assoc_status_code = assoc_status_code, .p2p_group_started = p2p_group_started, .p2p_group_finished = p2p_group_finished, + .p2p_invitation_result = p2p_invitation_result, + .p2p_invitation_received = p2p_invitation_received, }; static int tech_probe(struct connman_technology *technology) diff --git a/src/connman.h b/src/connman.h index 034a990..d9adc48 100644 --- a/src/connman.h +++ b/src/connman.h @@ -627,7 +627,7 @@ void __connman_device_list(DBusMessageIter *iter, void *user_data); enum connman_service_type __connman_device_get_service_type(struct connman_device *device); struct connman_device *__connman_device_find_device(enum connman_service_type type); int __connman_device_request_scan(enum connman_service_type type); -int __connman_device_request_scan_full(enum connman_service_type type); +int __connman_device_request_scan_full(enum connman_service_type type,bool priority); int __connman_device_request_hidden_scan(struct connman_device *device, const char *ssid, unsigned int ssid_len, const char *identity, const char *passphrase, diff --git a/src/device.c b/src/device.c index 5567009..3ab5268 100644 --- a/src/device.c +++ b/src/device.c @@ -174,6 +174,8 @@ static bool device_has_service_type(struct connman_device *device, return service_type == device_service_type; } + + static gboolean device_pending_reset(gpointer user_data) { struct connman_device *device = user_data; @@ -642,7 +644,7 @@ bool connman_device_get_powered(struct connman_device *device) static int device_scan(enum connman_service_type type, struct connman_device *device, - bool force_full_scan) + bool priority) { struct connman_device_scan_params params; @@ -654,9 +656,11 @@ static int device_scan(enum connman_service_type type, memset(¶ms, 0, sizeof(params)); params.type = type; - params.force_full_scan = force_full_scan; - - return device->driver->scan(device, ¶ms); + params.force_full_scan = priority; + if(priority) + return device->driver->scan_p2p(type, device); + else + return device->driver->scan(device, ¶ms); } int __connman_device_disconnect(struct connman_device *device) @@ -1102,7 +1106,7 @@ void connman_device_regdom_notify(struct connman_device *device, } static int connman_device_request_scan(enum connman_service_type type, - bool force_full_scan) + bool priority) { bool success = false; int last_err = -ENOSYS; @@ -1130,7 +1134,7 @@ static int connman_device_request_scan(enum connman_service_type type, if (!device_has_service_type(device, type)) continue; - err = device_scan(type, device, force_full_scan); + err = device_scan(type, device, priority); if (err == 0 || err == -EALREADY || err == -EINPROGRESS) { success = true; } else { @@ -1150,9 +1154,9 @@ int __connman_device_request_scan(enum connman_service_type type) return connman_device_request_scan(type, false); } -int __connman_device_request_scan_full(enum connman_service_type type) +int __connman_device_request_scan_full(enum connman_service_type type,bool priority) { - return connman_device_request_scan(type, true); + return connman_device_request_scan(type, priority); } int __connman_device_request_hidden_scan(struct connman_device *device, @@ -1240,6 +1244,27 @@ static char *index2ident(int index, const char *prefix) return str; } +struct connman_device *connman_get_device_from_interface(const char* device_interface) +{ + GSList *list_h; + int i_h = 0; + + if (!device_interface) + return NULL; + + for (list_h = device_list; list_h; list_h = list_h->next) { + struct connman_device *device = list_h->data; + + if (g_strcmp0(connman_device_get_string(device, "Interface"), device_interface) == 0) { + return device; + } + } + + return NULL; +} + + + static char *index2addr(int index) { struct ifreq ifr; @@ -1283,6 +1308,8 @@ static char *index2addr(int index) return str; } + + struct connman_device *connman_device_create_from_index(int index) { enum connman_device_type type; diff --git a/src/group.c b/src/group.c index 8715d65..84f1619 100644 --- a/src/group.c +++ b/src/group.c @@ -369,6 +369,13 @@ static DBusMessage *p2p_disconnect(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } +static void p2p_invite_callback(int result, + GSupplicantInterface *interface, + void *user_data) +{ + DBG("p2p invite callback %d\n", result); +} + /** * Handles a D-Bus method call to invite a peer to a P2P group. * @@ -385,7 +392,34 @@ static DBusMessage *p2p_disconnect(DBusConnection *conn, static DBusMessage *p2p_invite(DBusConnection *conn, DBusMessage *msg, void *user_data) { - // TODO: Implement the logic for inviting a peer to a P2P group. + struct connman_group *group = user_data; + DBusMessageIter iter; + const char *peer_path; + char *peer_ident; + GSupplicantP2PInviteParams *invite_params = NULL; + struct connman_service *service; + struct connman_network *network; + struct connman_peer *connman_peer; + GSupplicantPeer *gs_peer; + + DBG("group %p", group); + + if (dbus_message_iter_init(msg, &iter) == FALSE) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &peer_path); + + invite_params = g_try_malloc0(sizeof(GSupplicantP2PInviteParams)); + if (!invite_params) + return __connman_error_invalid_arguments(msg); + + invite_params->peer = peer_path; + + g_supplicant_interface_p2p_invite(group->interface, invite_params, p2p_invite_callback, NULL); + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } diff --git a/src/peer.c b/src/peer.c index 03c96c0..e81a038 100644 --- a/src/peer.c +++ b/src/peer.c @@ -68,6 +68,9 @@ struct connman_peer { GDHCPServer *dhcp_server; uint32_t lease_ip; GSList *services; + const char *device_address; + bool is_groupOwner; + int config_methods; }; static void settings_changed(struct connman_peer *peer); @@ -363,6 +366,13 @@ static void append_peer_services(DBusMessageIter *iter, void *user_data) dbus_message_iter_close_container(iter, &container); } +static void append_peer(DBusMessageIter *dict, void *user_data) +{ + //TO-DO: Implement append_peer function + dbus_bool_t val; + struct connman_peer *peer = user_data; +} + static void append_properties(DBusMessageIter *iter, struct connman_peer *peer) { const char *state = state2string(peer->state); @@ -374,6 +384,7 @@ static void append_properties(DBusMessageIter *iter, struct connman_peer *peer) DBUS_TYPE_STRING, &state); connman_dbus_dict_append_basic(&dict, "Name", DBUS_TYPE_STRING, &peer->name); + connman_dbus_dict_append_dict(&dict, "P2P", append_peer, peer); connman_dbus_dict_append_dict(&dict, "IPv4", append_ipv4, peer); connman_dbus_dict_append_array(&dict, "Services", DBUS_TYPE_DICT_ENTRY, @@ -617,8 +628,9 @@ static int peer_connect(struct connman_peer *peer) if (peer_driver->connect){ if(!pin || strlen(pin)==0){ - err = peer_driver->connect(peer, - CONNMAN_PEER_WPS_PBC, NULL); + err = __connman_agent_request_peer_authorization(peer, + request_authorization_cb, true, + get_dbus_sender(peer), NULL); }else{ err = peer_driver->connect(peer, CONNMAN_PEER_WPS_PIN, pin); @@ -687,11 +699,9 @@ static DBusMessage *connect_peer(DBusConnection *conn, g_list_free(start); peer->pending = dbus_message_ref(msg); - err = peer_connect(peer); if (err == -EINPROGRESS) return NULL; - if (err < 0) { dbus_message_unref(peer->pending); peer->pending = NULL; @@ -1202,15 +1212,6 @@ static void disconnect_peer_hash_table(gpointer key, peer_disconnect(peer); } -struct connman_peer *connman_peer_get_by_path(const char *path) -{ - struct connman_peer *peer; - - peer = g_hash_table_lookup(peers_table, path); - - return peer; -} - void __connman_peer_get_properties_struct(DBusMessageIter *iter, gpointer user_data) { struct connman_peer *peer = user_data; @@ -1223,6 +1224,15 @@ void __connman_peer_disconnect_all(void) g_hash_table_foreach(peers_table, disconnect_peer_hash_table, NULL); } +struct connman_peer *connman_peer_get_by_path(const char *path) +{ + struct connman_peer *peer; + + peer = g_hash_table_lookup(peers_table, path); + + return peer; +} + int __connman_peer_init(void) { DBG(""); diff --git a/src/technology.c b/src/technology.c index 10041a1..98c98b2 100644 --- a/src/technology.c +++ b/src/technology.c @@ -969,6 +969,16 @@ make_reply: return reply; } +void __connman_technology_p2p_invitation_result(struct connman_technology *technology, int status) +{ + if(technology->type != CONNMAN_SERVICE_TYPE_P2P) + return; + + connman_dbus_property_changed_basic(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, "P2PInvitationResult", + DBUS_TYPE_INT32, &status); +} + static DBusMessage *set_p2p_listen(struct connman_technology *technology, DBusMessage *msg, bool enable) { @@ -1404,6 +1414,8 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_technology *technology = data; int err; + DBusMessageIter iter; + bool priority = false; DBG("technology %p request from %s", technology, dbus_message_get_sender(msg)); @@ -1412,11 +1424,21 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) !technology->enabled) return __connman_error_permission_denied(msg); + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &priority); + dbus_message_ref(msg); technology->scan_pending = g_slist_prepend(technology->scan_pending, msg); - err = __connman_device_request_scan_full(technology->type); + DBG("technology scan set priority = %s", priority?"HIGH":"LOW"); + + err = __connman_device_request_scan_full(technology->type,priority); if (err < 0) reply_scan_pending(technology, err); @@ -1430,7 +1452,7 @@ static const GDBusMethodTable technology_methods[] = { { GDBUS_ASYNC_METHOD("SetProperty", GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL, set_property) }, - { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) }, + { GDBUS_ASYNC_METHOD("Scan", GDBUS_ARGS({ "priority", "b" }), NULL, scan) }, { }, };