When enabling tethering, try to first find a device without a network connection that supports AP mode. If none is found, try again but this time ignoring the network connection.
Factor out tethering enabling adding a boolea parameter that tells whether to consider a connected network or not. Reported by citylight2. --- plugins/wifi.c | 90 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/plugins/wifi.c b/plugins/wifi.c index 587dee2..db29090 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -3062,9 +3062,9 @@ static void sta_remove_callback(int result, info); } -static int tech_set_tethering(struct connman_technology *technology, - const char *identifier, const char *passphrase, - const char *bridge, bool enabled) +static int enable_wifi_tethering(struct connman_technology *technology, + const char *bridge, const char *identifier, + const char *passphrase, bool available) { GList *list; GSupplicantInterface *interface; @@ -3074,46 +3074,34 @@ static int tech_set_tethering(struct connman_technology *technology, unsigned int mode; int err; - DBG(""); - - if (!enabled) { - for (list = iface_list; list; list = list->next) { - wifi = list->data; - - if (wifi->tethering) { - wifi->tethering = false; - - connman_inet_remove_from_bridge(wifi->index, - bridge); - wifi->bridged = false; - } - } - - connman_technology_tethering_notify(technology, false); - - return 0; - } - for (list = iface_list; list; list = list->next) { wifi = list->data; + DBG("wifi %p network %p pending_network %p", wifi, + wifi->network, wifi->pending_network); + interface = wifi->interface; if (!interface) continue; - if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) - continue; - ifname = g_supplicant_interface_get_ifname(wifi->interface); + if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) { + DBG("%s does not support AP mode (detected)", ifname); + continue; + } + mode = g_supplicant_interface_get_mode(interface); if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) { wifi->ap_supported = WIFI_AP_NOT_SUPPORTED; - DBG("%s does not support AP mode", ifname); + DBG("%s does not support AP mode (capability)", ifname); continue; } + if (wifi->network && available) + continue; + info = g_try_malloc0(sizeof(struct wifi_tethering_info)); if (!info) return -ENOMEM; @@ -3160,13 +3148,57 @@ static int tech_set_tethering(struct connman_technology *technology, err = g_supplicant_interface_remove(interface, sta_remove_callback, info); - if (err == 0) - return err; + if (err >= 0) { + DBG("tethering wifi %p ifname %s", wifi, ifname); + return 0; + } + } return -EOPNOTSUPP; } +static int tech_set_tethering(struct connman_technology *technology, + const char *identifier, const char *passphrase, + const char *bridge, bool enabled) +{ + GList *list; + struct wifi_data *wifi; + int err; + + DBG(""); + + if (!enabled) { + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (wifi->tethering) { + wifi->tethering = false; + + connman_inet_remove_from_bridge(wifi->index, + bridge); + wifi->bridged = false; + } + } + + connman_technology_tethering_notify(technology, false); + + return 0; + } + + DBG("trying tethering for available devices"); + err = enable_wifi_tethering(technology, bridge, identifier, passphrase, + true); + + if (err < 0) { + DBG("trying tethering for any device"); + err = enable_wifi_tethering(technology, bridge, identifier, + passphrase, false); + } + + return err; +} + static void regdom_callback(int result, const char *alpha2, void *user_data) { DBG(""); -- 2.1.4 _______________________________________________ connman mailing list connman@connman.net https://lists.connman.net/mailman/listinfo/connman