From: "Niu,Bing" <[email protected]>
add new callback function ap_create_fail. supplicant layer will
detect AP creataion fail, and callback wifi plugin. ap_create_fail
will call tech_set_tethering() to try to create AP at next interface.
---
plugins/wifi.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 109 insertions(+), 12 deletions(-)
mode change 100644 => 100755 plugins/wifi.c
diff --git a/plugins/wifi.c b/plugins/wifi.c
old mode 100644
new mode 100755
index 42dd407..a12c210
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -74,6 +74,12 @@
static struct connman_technology *wifi_technology = NULL;
static struct connman_technology *p2p_technology = NULL;
+enum wifi_ap_capability{
+ WIFI_AP_UNKNOWN = 0,
+ WIFI_AP_SUPPORTED = 1,
+ WIFI_AP_NOT_SUPPORTED = 2,
+};
+
struct hidden_params {
char ssid[32];
unsigned int ssid_len;
@@ -95,6 +101,13 @@ struct autoscan_params {
unsigned int timeout;
};
+struct wifi_tethering_info {
+ struct wifi_data *wifi;
+ struct connman_technology *technology;
+ char *ifname;
+ GSupplicantSSID *ssid;
+};
+
struct wifi_data {
char *identifier;
struct connman_device *device;
@@ -106,6 +119,7 @@ struct wifi_data {
bool connected;
bool disconnecting;
bool tethering;
+ enum wifi_ap_capability ap_supported;
bool bridged;
bool interface_ready;
const char *bridge;
@@ -115,6 +129,7 @@ struct wifi_data {
int retries;
struct hidden_params *hidden;
bool postpone_hidden;
+ struct wifi_tethering_info *tethering_param;
/**
* autoscan "emulation".
*/
@@ -137,6 +152,9 @@ static GList *p2p_iface_list = NULL;
bool wfd_service_registered = false;
static void start_autoscan(struct connman_device *device);
+static int tech_set_tethering(struct connman_technology *technology,
+ const char *identifier, const char *passphrase,
+ const char *bridge, bool enabled);
static int p2p_tech_probe(struct connman_technology *technology)
{
@@ -737,6 +755,8 @@ static int wifi_probe(struct connman_device *device)
return -ENOMEM;
wifi->state = G_SUPPLICANT_STATE_INACTIVE;
+ wifi->ap_supported = WIFI_AP_UNKNOWN;
+ wifi->tethering_param = NULL;
connman_device_set_data(device, wifi);
wifi->device = connman_device_ref(device);
@@ -2294,6 +2314,14 @@ static void interface_state(GSupplicantInterface
*interface)
if (!wifi)
return;
+ if (state == G_SUPPLICANT_STATE_COMPLETED) {
+ if (wifi->tethering_param) {
+ g_free(wifi->tethering_param->ssid);
+ g_free(wifi->tethering_param);
+ wifi->tethering_param = NULL;
+ }
+ }
+
device = wifi->device;
if (!device)
return;
@@ -2500,6 +2528,36 @@ static void scan_finished(GSupplicantInterface
*interface)
DBG("");
}
+static void ap_create_fail(GSupplicantInterface *interface)
+{
+ struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
+ int ret;
+
+ if ((wifi->tethering) && (wifi->tethering_param)) {
+ DBG("%s create AP fail \n",
+
g_supplicant_interface_get_ifname(wifi->interface));
+
+ connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
+ wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
+ wifi->tethering = false;
+
+ ret = tech_set_tethering(wifi->tethering_param->technology,
+ wifi->tethering_param->ssid->ssid,
+ wifi->tethering_param->ssid->passphrase,
+ wifi->bridge, true);
+
+ if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
+
connman_technology_tethering_notify(wifi_technology,false);
+ }
+
+ g_free(wifi->tethering_param->ssid);
+ g_free(wifi->tethering_param);
+ wifi->tethering_param = NULL;
+ }
+
+ return;
+}
+
static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
{
unsigned char strength;
@@ -2844,6 +2902,7 @@ static const GSupplicantCallbacks callbacks = {
.p2p_support = p2p_support,
.scan_started = scan_started,
.scan_finished = scan_finished,
+ .ap_create_fail = ap_create_fail,
.network_added = network_added,
.network_removed = network_removed,
.network_changed = network_changed,
@@ -2867,13 +2926,6 @@ static void tech_remove(struct connman_technology
*technology)
wifi_technology = NULL;
}
-struct wifi_tethering_info {
- struct wifi_data *wifi;
- struct connman_technology *technology;
- char *ifname;
- GSupplicantSSID *ssid;
-};
-
static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
{
GSupplicantSSID *ap;
@@ -2910,10 +2962,16 @@ static void ap_start_callback(int result,
GSupplicantInterface *interface,
DBG("result %d index %d bridge %s",
result, info->wifi->index, info->wifi->bridge);
- if (result < 0) {
+ if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
connman_inet_remove_from_bridge(info->wifi->index,
info->wifi->bridge);
- connman_technology_tethering_notify(info->technology, false);
+
+ if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
+ connman_technology_tethering_notify(info->technology,
false);
+ g_free(info->wifi->tethering_param->ssid);
+ g_free(info->wifi->tethering_param);
+ info->wifi->tethering_param = NULL;
+ }
}
g_free(info->ifname);
@@ -2929,10 +2987,17 @@ static void ap_create_callback(int result,
DBG("result %d ifname %s", result,
g_supplicant_interface_get_ifname(interface));
- if (result < 0) {
+ if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
connman_inet_remove_from_bridge(info->wifi->index,
info->wifi->bridge);
- connman_technology_tethering_notify(info->technology, false);
+
+ if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
+ connman_technology_tethering_notify(info->technology,
false);
+ g_free(info->wifi->tethering_param->ssid);
+ g_free(info->wifi->tethering_param);
+ info->wifi->tethering_param = NULL;
+
+ }
g_free(info->ifname);
g_free(info->ssid);
@@ -2959,12 +3024,18 @@ static void sta_remove_callback(int result,
DBG("ifname %s result %d ", info->ifname, result);
- if (result < 0) {
+ if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
info->wifi->tethering = true;
g_free(info->ifname);
g_free(info->ssid);
g_free(info);
+
+ if (info->wifi->ap_supported == WIFI_AP_SUPPORTED){
+ g_free(info->wifi->tethering_param->ssid);
+ g_free(info->wifi->tethering_param);
+ info->wifi->tethering_param = NULL;
+ }
return;
}
@@ -3017,10 +3088,14 @@ static int tech_set_tethering(struct connman_technology
*technology,
if (!interface)
continue;
+ if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
+ continue;
+
ifname = g_supplicant_interface_get_ifname(wifi->interface);
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);
continue;
}
@@ -3029,22 +3104,44 @@ static int tech_set_tethering(struct connman_technology
*technology,
if (!info)
return -ENOMEM;
+ wifi->tethering_param = g_try_malloc0(sizeof(struct
wifi_tethering_info));
+ if (!wifi->tethering_param) {
+ g_free(info);
+ return -ENOMEM;
+ }
+
info->wifi = wifi;
info->technology = technology;
info->wifi->bridge = bridge;
info->ssid = ssid_ap_init(identifier, passphrase);
if (!info->ssid) {
g_free(info);
+ g_free(wifi->tethering_param);
+ wifi->tethering_param = NULL;
continue;
}
info->ifname = g_strdup(ifname);
if (!info->ifname) {
g_free(info->ssid);
+ g_free(wifi->tethering_param);
+ g_free(info);
+ wifi->tethering_param = NULL;
+ continue;
+ }
+
+ wifi->tethering_param->technology = technology;
+ wifi->tethering_param->ssid = ssid_ap_init(identifier,
passphrase);
+ if (!wifi->tethering_param->ssid) {
+ g_free(info->ifname);
+ g_free(info->ssid);
+ g_free(wifi->tethering_param);
g_free(info);
+ wifi->tethering_param = NULL;
continue;
}
info->wifi->tethering = true;
+ info->wifi->ap_supported = WIFI_AP_SUPPORTED;
err = g_supplicant_interface_remove(interface,
sta_remove_callback,
--
1.7.11.7
_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman