[PATCH] Connman : Add initial support for P2P listen mode in ConnMan
Shailesh Rathod/LGSI Connectivity Team <[email protected]> Mon, 7 Jul 2025 07:00:37 +0000
| Newsgroups | dev.linux.lists.connman |
|---|---|
| Message-ID | <SE1P216MB264723B08F4D99FF50554FB3F04FA@SE1P216MB2647.KORP216.PROD.OUTLOOK.COM> |
From c8dafb2ffcd7f68b0e68725838095b755e5139d3 Mon Sep 17 00:00:00 2001 From: shailesh rathod <[email protected]> Date: Fri, 30 May 2025 14:19:57 +0900 Subject: [PATCH] Add initial support for P2P listen mode in ConnMan - Introduce P2P listen functionality for Wi-Fi Direct (P2P) via new D-Bus property "P2PListen" on the technology interface. - Add technology driver callback set_p2p_listen and implement it in the WiFi plugin. - Implement GSupplicantP2PExtendedListenParams and related API to trigger the ExtendedListen method in wpa_supplicant. - Update technology and wifi plugin logic to handle enabling/disabling P2P listen state. - Expose the P2PListen property in D-Bus technology properties and allow it to be set via D-Bus. - Ensure proper error handling and state management for repeated or unsupported requests. --- gsupplicant/gsupplicant.h | 12 +++++++ gsupplicant/supplicant.c | 29 +++++++++++++++ include/technology.h | 1 + plugins/wifi.c | 35 ++++++++++++++++++ src/technology.c | 74 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 150 insertions(+), 1 deletion(-) diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h index eab6293..77c2d46 100644 --- a/gsupplicant/gsupplicant.h +++ b/gsupplicant/gsupplicant.h @@ -312,6 +312,18 @@ GSupplicantPeer *g_supplicant_interface_peer_lookup(GSupplicantInterface *interf const char *identifier); bool g_supplicant_interface_is_p2p_finding(GSupplicantInterface *interface); +struct _GSupplicantP2PExtendedListenParams { + int period; + int interval; +}; + +typedef struct _GSupplicantP2PExtendedListenParams GSupplicantP2PExtendedListenParams; + +int g_supplicant_interface_p2p_extended_listen(GSupplicantInterface *interface, + GSupplicantP2PExtendedListenParams *extended_listen_data, + GSupplicantInterfaceCallback callback, + void *user_data); + /* Network and Peer API */ struct _GSupplicantNetwork; struct _GSupplicantGroup; diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index f3be9e7..7facfe8 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -4009,6 +4009,35 @@ done: interface_create_data_free(data); } +static void extended_listen_append_args(DBusMessageIter *iter, GSupplicantP2PExtendedListenParams *params) +{ + //struct GSupplicantP2PExtendedListenParams *params = user_data; + DBusMessageIter dict; + + supplicant_dbus_dict_open(iter, &dict); + if (params) { + supplicant_dbus_dict_append_basic(&dict, "period", DBUS_TYPE_INT32, ¶ms->period); + supplicant_dbus_dict_append_basic(&dict, "interval", DBUS_TYPE_INT32, ¶ms->interval); + } + supplicant_dbus_dict_close(iter, &dict); +} +int g_supplicant_interface_p2p_extended_listen(GSupplicantInterface *interface, + GSupplicantP2PExtendedListenParams *params, + GSupplicantInterfaceCallback callback, + void *user_data) +{ + if (!interface) + return -EINVAL; + + +return supplicant_dbus_method_call(interface->path, + SUPPLICANT_INTERFACE ".Interface.P2PDevice", + "ExtendedListen", + extended_listen_append_args, + NULL, // or NULL if no reply handler needed + params, + NULL); +} static void interface_create_params(DBusMessageIter *iter, void *user_data) { struct interface_create_data *data = user_data; diff --git a/include/technology.h b/include/technology.h index fcd658e..fd7b87a 100644 --- a/include/technology.h +++ b/include/technology.h @@ -65,6 +65,7 @@ struct connman_technology_driver { const char *bridge, bool enabled); int (*set_regdom) (struct connman_technology *technology, const char *alpha2); + int (*set_p2p_listen) (struct connman_technology *technology, bool enable); }; int connman_technology_driver_register(struct connman_technology_driver *driver); diff --git a/plugins/wifi.c b/plugins/wifi.c index 12389fa..cbfcf5d 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -184,6 +184,7 @@ static bool wfd_service_registered = false; static void start_autoscan(struct connman_device *device); static int tech_set_tethering(struct connman_technology *technology, const char *bridge, bool enabled); +static int tech_set_p2p_listen(struct connman_technology *technology, bool enable); static int p2p_tech_probe(struct connman_technology *technology) { @@ -3663,6 +3664,7 @@ static struct connman_technology_driver tech_driver = { .remove = tech_remove, .set_tethering = tech_set_tethering, .set_regdom = tech_set_regdom, + .set_p2p_listen = tech_set_p2p_listen, }; static int wifi_init(void) @@ -3700,5 +3702,38 @@ static void wifi_exit(void) connman_network_driver_unregister(&network_driver); } +static int p2p_enter_listen_state(GSupplicantInterface *interface) +{ + GSupplicantP2PExtendedListenParams params = { + .period = 50, // ms + .interval = 100 // ms + }; + + return g_supplicant_interface_p2p_extended_listen(interface, ¶ms, NULL, NULL); +} + +static int tech_set_p2p_listen(struct connman_technology *technology, bool enable) +{ + GList *list; + struct wifi_data *wifi = NULL; + GSupplicantInterface *interface; + int err; + + for (list = iface_list; list; list = list->next) { + wifi = list->data; + interface = wifi->interface; + + if (interface == NULL) + continue; + + if (wifi->interface){ + err = p2p_enter_listen_state(wifi->interface); + return err; + } + } + + return -EOPNOTSUPP; +} + CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION, CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit) diff --git a/src/technology.c b/src/technology.c index 1bcd184..3f3b022 100644 --- a/src/technology.c +++ b/src/technology.c @@ -85,6 +85,7 @@ struct connman_technology { bool softblocked; bool hardblocked; bool dbus_registered; + bool p2p_listen; }; static GSList *driver_list = NULL; @@ -647,6 +648,10 @@ static void append_properties(DBusMessageIter *iter, DBUS_TYPE_INT32, &technology->tethering_freq); + connman_dbus_dict_append_basic(&dict, "P2PListen", + DBUS_TYPE_BOOLEAN, + &technology->p2p_listen); + connman_dbus_dict_close(iter, &dict); } @@ -957,6 +962,61 @@ make_reply: return reply; } +static DBusMessage *set_p2p_listen(struct connman_technology *technology, + DBusMessage *msg, bool enable) +{ + DBusMessage *reply = NULL; + int err = 0; + GSList *tech_drivers; + + __sync_synchronize(); + if (technology->enabled == FALSE) { + err = -EOPNOTSUPP; + goto make_reply; + } + + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) { + err = -EOPNOTSUPP; + goto make_reply; + } + + if (technology->p2p_listen == enable) { + err = -EALREADY; + goto make_reply; + } + + for (tech_drivers = technology->driver_list; tech_drivers != NULL; + tech_drivers = g_slist_next(tech_drivers)) { + struct connman_technology_driver *driver = tech_drivers->data; + + if (driver == NULL || driver->set_p2p_listen == NULL) + continue; + + err = driver->set_p2p_listen(technology, enable); + if (err < 0) + break; + } + + if (err >= 0) + technology->p2p_listen = enable; + + make_reply: + if (err == -EINPROGRESS) + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + else if (err == -EALREADY) { + if (enable == TRUE) + reply = __connman_error_already_enabled(msg); + else + reply = __connman_error_already_disabled(msg); + } else if (err < 0) + reply = __connman_error_failed(msg, -err); + else + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + return reply; +} + + static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -1148,7 +1208,19 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &enable); return set_powered(technology, msg, enable); - } else + } else if (g_str_equal(name, "P2PListen") == TRUE) { + bool enable; + + if (type != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) + return __connman_error_not_supported(msg); + + dbus_message_iter_get_basic(&value, &enable); + + return set_p2p_listen(technology, msg, enable); +} else return __connman_error_invalid_property(msg); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);