typedef struct _GSupplicantCallbacks GSupplicantCallbacks;
#if defined TIZEN_EXT
+void g_supplicant_set_pns_settings(void *pns_setting_info);
void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
#define WLAN_EID_SUPP_RATES 1
#define WLAN_EID_EXT_SUPP_RATES 50
#define COUNTRY_CODE_LENGTH 2
-#endif
-#if defined TIZEN_EXT
#define LAST_CONNECTED_TIMEOUT (5 * 60)
#define ASSOC_REJECT_TIMEOUT 10
#define FREQ_RANGE_24GHZ_CHANNEL_1 2412
};
static struct _GSupplicantINSSettings ins_settings;
+static connman_pns_settings *pns_settings;
static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
return score;
}
+static enum connman_wifi_band get_bss_band(unsigned int frequency)
+{
+ if (frequency > FREQUENCY_6G_BASE)
+ return CONNMAN_WIFI_BAND_6GHZ;
+ else if (frequency > FREQUENCY_5G_BASE)
+ return CONNMAN_WIFI_BAND_5GHZ;
+ else
+ return CONNMAN_WIFI_BAND_2_4GHZ;
+}
+
+static int get_bss_signal_weight(enum connman_wifi_band band)
+{
+ switch (band) {
+ case CONNMAN_WIFI_BAND_2_4GHZ:
+ return pns_settings->signal_weight_2_4ghz;
+ case CONNMAN_WIFI_BAND_5GHZ:
+ return pns_settings->signal_weight_5ghz;
+ case CONNMAN_WIFI_BAND_6GHZ:
+ return pns_settings->signal_weight_6ghz;
+ default:
+ return 0;
+ }
+}
+
+static int compare_bss_with_pns(int freq_a, int signal_a, int freq_b, int signal_b)
+{
+ if (!pns_settings)
+ return signal_b - signal_a;
+
+ enum connman_wifi_band bss_band_a = get_bss_band(freq_a);
+ enum connman_wifi_band bss_band_b = get_bss_band(freq_b);
+ GSList *pref_networks = (GSList *) pns_settings->preferred_networks;
+
+ if (bss_band_a == bss_band_b)
+ return signal_b - signal_a;
+
+ for (; pref_networks; pref_networks = pref_networks->next) {
+ preferred_pns_network *pns_network = pref_networks->data;
+
+ if (pns_network->band == bss_band_a &&
+ pns_network->signal < signal_a)
+ return -1;
+
+ if (pns_network->band == bss_band_b &&
+ pns_network->signal < signal_b)
+ return 1;
+ }
+
+ signal_a += get_bss_signal_weight(bss_band_a);
+ signal_b += get_bss_signal_weight(bss_band_b);
+
+ if (bss_band_a == pns_settings->preferred_band)
+ signal_a++;
+ else if (bss_band_b == pns_settings->preferred_band)
+ signal_b++;
+
+ return signal_b - signal_a;
+}
+
static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
{
struct g_supplicant_bss *bss = value;
struct g_connman_bssids *entry_a = (struct g_connman_bssids *)a;
struct g_connman_bssids *entry_b = (struct g_connman_bssids *)b;
+ if (TIZEN_PNS_ENABLED)
+ return compare_bss_with_pns(entry_a->frequency, entry_a->strength - 120,
+ entry_b->frequency, entry_b->strength - 120);
+
if (entry_a->ins_score > entry_b->ins_score)
return -1;
int score_new;
int score_best;
+ if (bss == best_bss)
+ return false;
+
if (network->best_bss == NULL) {
update_network_with_best_bss(network, bss);
return true;
get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
network->best_bss->frequency, network->best_bss->signal,
network->best_bss->snr, network->best_bss->est_throughput);
+ } else if (TIZEN_PNS_ENABLED) {
+ score_new = 0;
+ score_best = compare_bss_with_pns(bss->frequency, bss->signal,
+ best_bss->frequency, best_bss->signal);
} else {
score_new = bss->signal;
score_best = network->best_bss->signal;
if (network == interface->current_network && bss != network->best_bss)
return;
- if (bss->signal == network->signal)
-#ifndef TIZEN_EXT
- return;
-#else
- {
+#if defined TIZEN_EXT
+ if (bss->signal == network->signal &&
+ !TIZEN_PNS_ENABLED && !TIZEN_INS_ENABLED) {
callback_network_changed(network, "");
return;
}
+#else
+ if (bss->signal == network->signal)
+ return;
#endif
/*
}
#if defined TIZEN_EXT
+void g_supplicant_set_pns_settings(void *pns_setting_info)
+{
+ GSList *pref_networks;
+
+ pns_settings = (connman_pns_settings *) pns_setting_info;
+
+ SUPPLICANT_DBG("signal_weight_2_4ghz [%d]", pns_settings->signal_weight_2_4ghz);
+ SUPPLICANT_DBG("signal_weight_5ghz [%d]", pns_settings->signal_weight_5ghz);
+ SUPPLICANT_DBG("signal_weight_6ghz [%d]", pns_settings->signal_weight_6ghz);
+ SUPPLICANT_DBG("preferred_band [%d]", pns_settings->preferred_band);
+
+ pref_networks = (GSList *) pns_settings->preferred_networks;
+
+ for (; pref_networks; pref_networks = pref_networks->next) {
+ preferred_pns_network *pns_network = pref_networks->data;
+ SUPPLICANT_DBG("preferred_networks: Wi-Fi band [%d], signal [%d]",
+ pns_network->band, pns_network->signal);
+ }
+}
+
void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
#endif
#if defined TIZEN_EXT
+
+#define FREQUENCY_5G_BASE 5000
+#define FREQUENCY_6G_BASE 5925
+
+#define TIZEN_INS_ENABLED \
+ (connman_setting_get_int("ApSelectionMethod") == AP_SELECTION_METHOD_INS)
+
+#define TIZEN_PNS_ENABLED \
+ (connman_setting_get_int("ApSelectionMethod") == AP_SELECTION_METHOD_PNS)
+
/* AP selection method to be used */
-typedef enum {
+enum ap_selection_method {
AP_SELECTION_METHOD_NORMAL = 0,
AP_SELECTION_METHOD_INS = 1,
-} ap_selection_method_e;
+ AP_SELECTION_METHOD_PNS = 2,
+};
-#define TIZEN_INS_ENABLED \
- (connman_setting_get_int("ApSelectionMethod") == AP_SELECTION_METHOD_INS)
+enum connman_wifi_band{
+ CONNMAN_WIFI_BAND_2_4GHZ = 1,
+ CONNMAN_WIFI_BAND_5GHZ,
+ CONNMAN_WIFI_BAND_6GHZ,
+};
+
+typedef struct {
+ enum connman_wifi_band band;
+ int signal;
+} preferred_pns_network;
+
+typedef struct {
+ void *preferred_networks;
+ int signal_weight_2_4ghz;
+ int signal_weight_5ghz;
+ int signal_weight_6ghz;
+ enum connman_wifi_band preferred_band;
+} connman_pns_settings;
+connman_pns_settings *connman_get_pns_settings(void);
int connman_setting_get_int(const char *key);
#endif
DBG("RoamScan Int: %d, Min SNR: %d, Min RSSI: %d(2.4GHz), %d(5GHz)",
roam_scan_interval, min_snr, min_rssi_2_4GHz, min_rssi_5GHz);
+ if (TIZEN_PNS_ENABLED)
+ g_supplicant_set_pns_settings(connman_get_pns_settings());
if (TIZEN_INS_ENABLED)
supp_ins_init();
#if defined TIZEN_EXT
static struct {
+ char **preferred_networks;
+ int signal_weight_2_4ghz;
+ int signal_weight_5ghz;
+ int signal_weight_6ghz;
+ char *preferred_band;
+} connman_pns_settings_conf = {
+ .preferred_networks = NULL,
+ .signal_weight_2_4ghz = 0,
+ .signal_weight_5ghz = 0,
+ .signal_weight_6ghz = 0,
+ .preferred_band = NULL,
+};
+
+static struct {
/* BSSID */
char *ins_preferred_freq_bssid;
bool ins_last_connected_bssid;
#define CONF_WIFI_ROAM_MIN_RSSI_5 "WifiRoamingMinRSSI_5GHz"
#define CONF_WIFI_AUTO_CONNECTION_SCAN "AutoConnectionScan"
#define CONF_WIFI_AP_SELECTION_METHOD "ApSelectionMethod"
-#endif
-#if defined TIZEN_EXT
+#define CONF_PNS_PREFERRED_NETWORKS "PNSPreferredNetworks"
+#define CONF_PNS_SIGNAL_WEIGHT_2_4GHZ "PNSSignalWeight_2_4GHz"
+#define CONF_PNS_SIGNAL_WEIGHT_5GHZ "PNSSignalWeight_5GHz"
+#define CONF_PNS_SIGNAL_WEIGHT_6GHZ "PNSSignalWeight_6GHz"
+#define CONF_PNS_PREFERRED_BAND "PNSPreferredBand"
+
/* BSSID */
#define CONF_INS_PREFERRED_FREQ_BSSID "INSPreferredFreqBSSID"
#define CONF_INS_PREFERRED_FREQ_BSSID_SCORE "INSPreferredFreqBSSIDScore"
};
#if defined TIZEN_EXT
+static const char *supported_pns_options[] = {
+ CONF_PNS_PREFERRED_NETWORKS,
+ CONF_PNS_SIGNAL_WEIGHT_2_4GHZ,
+ CONF_PNS_SIGNAL_WEIGHT_5GHZ,
+ CONF_PNS_SIGNAL_WEIGHT_6GHZ,
+ CONF_PNS_PREFERRED_BAND,
+ NULL
+};
+
static const char *supported_ins_options[] = {
/* BSSID */
CONF_INS_PREFERRED_FREQ_BSSID,
for (j = 0; keys && keys[j]; j++) {
#if defined TIZEN_EXT
if (g_strcmp0(keys[j], "General") != 0 &&
- g_strcmp0(keys[j], "INS") != 0)
+ g_strcmp0(keys[j], "INS") != 0 &&
+ g_strcmp0(keys[j], "PNS") != 0)
#else
if (g_strcmp0(keys[j], "General") != 0)
#endif
g_strfreev(keys);
#if defined TIZEN_EXT
+ keys = g_key_file_get_keys(config, "PNS", NULL, NULL);
+
+ for (j = 0; keys && keys[j]; j++) {
+ bool found;
+ int i;
+
+ found = false;
+ for (i = 0; supported_pns_options[i]; i++) {
+ if (g_strcmp0(keys[j], supported_pns_options[i]) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found && !supported_pns_options[i])
+ connman_warn("Unknown option %s in %s",
+ keys[j], MAINFILE);
+ }
+
+ g_strfreev(keys);
+
keys = g_key_file_get_keys(config, "INS", NULL, NULL);
for (j = 0; keys && keys[j]; j++) {
}
#if defined TIZEN_EXT
+static void check_tizen_pns_configuration(GKeyFile *config)
+{
+ GError *error = NULL;
+ char **pns_string_list;
+ char *pns_string;
+ int integer;
+ gsize len;
+
+ pns_string_list = g_key_file_get_string_list(config, "PNS",
+ CONF_PNS_PREFERRED_NETWORKS, &len, &error);
+
+ if (error == NULL)
+ connman_pns_settings_conf.preferred_networks = pns_string_list;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "PNS",
+ CONF_PNS_SIGNAL_WEIGHT_2_4GHZ, &error);
+ if (!error)
+ connman_pns_settings_conf.signal_weight_2_4ghz = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "PNS",
+ CONF_PNS_SIGNAL_WEIGHT_5GHZ, &error);
+ if (!error)
+ connman_pns_settings_conf.signal_weight_5ghz = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "PNS",
+ CONF_PNS_SIGNAL_WEIGHT_6GHZ, &error);
+ if (!error)
+ connman_pns_settings_conf.signal_weight_6ghz = integer;
+
+ g_clear_error(&error);
+
+ pns_string = __connman_config_get_string(config, "PNS",
+ CONF_PNS_PREFERRED_BAND, &error);
+ if (!error)
+ connman_pns_settings_conf.preferred_band = pns_string;
+
+ g_clear_error(&error);
+}
+
static void check_tizen_ins_configuration(GKeyFile *config)
{
GError *error = NULL;
g_clear_error(&error);
check_tizen_ins_configuration(config);
+ check_tizen_pns_configuration(config);
}
static void set_nofile_inc(void)
if (g_str_equal(key, CONF_WIFI_DEF_IFNAME))
return connman_settings.def_wifi_ifname;
+
+ if (g_str_equal(key, CONF_PNS_PREFERRED_BAND))
+ return connman_pns_settings_conf.preferred_band;
#endif
return NULL;
}
if (g_str_equal(key, CONF_WIFI_ROAM_SCAN_INTERVAL))
return connman_settings.wifi_roam_scan_interval;
+ if (g_str_equal(key, CONF_PNS_SIGNAL_WEIGHT_2_4GHZ))
+ return connman_pns_settings_conf.signal_weight_2_4ghz;
+
+ if (g_str_equal(key, CONF_PNS_SIGNAL_WEIGHT_5GHZ))
+ return connman_pns_settings_conf.signal_weight_5ghz;
+
+ if (g_str_equal(key, CONF_PNS_SIGNAL_WEIGHT_6GHZ))
+ return connman_pns_settings_conf.signal_weight_6ghz;
+
return 0;
}
#endif
#if defined TIZEN_EXT
if (g_str_equal(key, CONF_CELLULAR_INTERFACE))
return connman_settings.cellular_interfaces;
-#endif
-#if defined TIZEN_EXT
if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY))
return connman_ins_settings.ins_security_priority;
+
+ if (g_str_equal(key, CONF_PNS_PREFERRED_NETWORKS))
+ return connman_pns_settings_conf.preferred_networks;
#endif
return NULL;
g_free(connman_ins_settings.ins_preferred_freq);
if (connman_ins_settings.ins_security_priority)
g_strfreev(connman_ins_settings.ins_security_priority);
+
+ g_free(connman_pns_settings_conf.preferred_band);
+ if (connman_pns_settings_conf.preferred_networks)
+ g_strfreev(connman_pns_settings_conf.preferred_networks);
#endif
g_free(option_debug);
# This value indicates which AP selection method to be used.
# 0: Normal(Signal strength)
# 1: INS
+# 2: PNS
ApSelectionMethod = 0
+[PNS]
+# PNS(Preference-based Network Selection) configurations
+
+# List of Preferred Network separated by ",".
+# APs that meet these conditions are selected with the highest priority.
+# Priorities are given in the order written.
+# For example, 5GHz:-68 refers to APs with a signal of -68dBm or higher in the 5GHz band.
+# PNSPreferredNetworks = 5GHz:-55,2.4GHz:-66
+
+# Signal weights for APs in the each band.
+# These values are added to the actual signal strength to calculate priority.
+#
+# For APs that do not meet PNSPreferredNetworks conditions,
+# selection is made in order of signal strength.
+# At this time, the weights below are applied to each band.
+#
+# PNSSignalWeight_2_4GHz = 11
+# PNSSignalWeight_5GHz = 0
+# PNSSignalWeight_6GHz = 0
+
+# Preferred Band(One of 2.4GHz, 5GHz or 6GHz).
+# If the signal strength is the same, the band below is selected.
+# PNSPreferredBand = 2.4GHz
+
+
[INS]
# INS(Intelligent Network Selection) configuration: BSSID Selection.
INSPreferredFreqBSSID = 5GHz
# This value indicates which AP selection method to be used.
# 0: Normal(Signal strength)
# 1: INS
+# 2: PNS
ApSelectionMethod = 0
+[PNS]
+# PNS(Preference-based Network Selection) configurations
+
+# List of Preferred Network separated by ",".
+# APs that meet these conditions are selected with the highest priority.
+# Priorities are given in the order written.
+# For example, 5GHz:-68 refers to APs with a signal of -68dBm or higher in the 5GHz band.
+# PNSPreferredNetworks = 5GHz:-55,2.4GHz:-66
+
+# Signal weights for APs in the each band.
+# These values are added to the actual signal strength to calculate priority.
+#
+# For APs that do not meet PNSPreferredNetworks conditions,
+# selection is made in order of signal strength.
+# At this time, the weights below are applied to each band.
+#
+# PNSSignalWeight_2_4GHz = 11
+# PNSSignalWeight_5GHz = 0
+# PNSSignalWeight_6GHz = 0
+
+# Preferred Band(One of 2.4GHz, 5GHz or 6GHz).
+# If the signal strength is the same, the band below is selected.
+# PNSPreferredBand = 2.4GHz
+
+
[INS]
# INS(Intelligent Network Selection) configuration: BSSID Selection.
INSPreferredFreqBSSID = 5GHz
};
static struct connman_ins_settings ins_settings;
+static connman_pns_settings pns_settings;
#endif /* defined TIZEN_EXT */
struct connman_stats {
service->ins_score = score;
return score;
}
+
+static enum connman_wifi_band get_service_band(unsigned int frequency)
+{
+ if (frequency > FREQUENCY_6G_BASE)
+ return CONNMAN_WIFI_BAND_6GHZ;
+ else if (frequency > FREQUENCY_5G_BASE)
+ return CONNMAN_WIFI_BAND_5GHZ;
+ else
+ return CONNMAN_WIFI_BAND_2_4GHZ;
+}
+
+static int get_signal_weight(enum connman_wifi_band band)
+{
+ switch (band) {
+ case CONNMAN_WIFI_BAND_2_4GHZ:
+ return pns_settings.signal_weight_2_4ghz;
+ case CONNMAN_WIFI_BAND_5GHZ:
+ return pns_settings.signal_weight_5ghz;
+ case CONNMAN_WIFI_BAND_6GHZ:
+ return pns_settings.signal_weight_6ghz;
+ default:
+ return 0;
+ }
+}
+
+static int compare_service_with_pns(struct connman_service *service_a,
+ struct connman_service *service_b)
+{
+ int ret;
+ int strength_a = connman_network_get_strength(service_a->network) - 120;
+ int strength_b = connman_network_get_strength(service_b->network) - 120;
+
+ enum connman_wifi_band band_a = get_service_band(
+ connman_network_get_frequency(service_a->network));
+ enum connman_wifi_band band_b = get_service_band(
+ connman_network_get_frequency(service_b->network));
+
+ GSList *pref_networks = (GSList *) pns_settings.preferred_networks;
+
+ if (band_a == band_b)
+ goto done;
+
+ for (; pref_networks; pref_networks = pref_networks->next) {
+ preferred_pns_network *pns_network = pref_networks->data;
+
+ if (pns_network->band == band_a &&
+ pns_network->signal < strength_a)
+ return -1;
+
+ if (pns_network->band == band_b &&
+ pns_network->signal < strength_b)
+ return 1;
+ }
+
+ strength_a += get_signal_weight(band_a);
+ strength_b += get_signal_weight(band_b);
+
+ if (band_a == pns_settings.preferred_band)
+ strength_a++;
+ else if (band_b == pns_settings.preferred_band)
+ strength_b++;
+
+done:
+ ret = strength_b - strength_a;
+ if (ret)
+ return ret;
+
+ return g_strcmp0(service_a->name, service_b->name);
+}
#endif /* defined TIZEN_EXT */
static gint service_compare(gconstpointer a, gconstpointer b);
if (strength)
return strength;
}
+ } else if (TIZEN_PNS_ENABLED) {
+ return compare_service_with_pns(service_a, service_b);
}
-#else /* defined TIZEN_EXT */
+#endif /* defined TIZEN_EXT */
strength = (gint) service_b->strength - (gint) service_a->strength;
if (strength)
return strength;
-#endif /* defined TIZEN_EXT */
return g_strcmp0(service_a->name, service_b->name);
}
};
#if defined TIZEN_EXT
+static enum connman_wifi_band pns_get_wifi_band(char *band_string)
+{
+ if (!band_string)
+ return 0;
+
+ if (g_ascii_strcasecmp(band_string, "2.4GHz") == 0)
+ return CONNMAN_WIFI_BAND_2_4GHZ;
+ else if (g_ascii_strcasecmp(band_string, "5GHz") == 0)
+ return CONNMAN_WIFI_BAND_5GHZ;
+ else if (g_ascii_strcasecmp(band_string, "6GHz") == 0)
+ return CONNMAN_WIFI_BAND_6GHZ;
+ else
+ return 0;
+}
+
+static bool pns_parse_network_info(char *network_string, GSList **pref_networks)
+{
+ preferred_pns_network *pns_network = NULL;
+ bool ret = false;
+ char *pns_string;
+ char **network_info = g_strsplit(network_string, ":", 0);
+
+ if (!network_info)
+ return false;
+
+ pns_string = network_info[0];
+ if (!pns_string || pns_string[0] == '\0')
+ goto out;
+
+ pns_network = g_try_malloc0(sizeof(preferred_pns_network));
+ if (!pns_network)
+ goto out;
+
+ pns_network->band = pns_get_wifi_band(pns_string);
+ if (pns_network->band == 0)
+ goto out;
+
+ pns_string = network_info[1];
+ if (!pns_string || pns_string[0] == '\0')
+ goto out;
+
+ pns_network->signal = strtol(pns_string, NULL, 10);
+ if (pns_network->signal >= 0 || errno == ERANGE)
+ goto out;
+
+ *pref_networks = g_slist_append(*pref_networks, pns_network);
+ pns_network = NULL;
+ ret = true;
+
+out:
+ g_strfreev(network_info);
+ g_free(pns_network);
+
+ return ret;
+}
+
+static void pns_setting_init(void)
+{
+ int i;
+ char *pns_string;
+ char **network_list;
+ GSList *pref_networks = NULL;
+
+ pns_settings.signal_weight_2_4ghz = connman_setting_get_int("PNSSignalWeight_2_4GHz");
+ pns_settings.signal_weight_5ghz = connman_setting_get_int("PNSSignalWeight_5GHz");
+ pns_settings.signal_weight_6ghz = connman_setting_get_int("PNSSignalWeight_6GHz");
+
+ network_list = connman_setting_get_string_list("PNSPreferredNetworks");
+
+ for (i = 0; network_list && network_list[i]; i++)
+ if (!pns_parse_network_info(network_list[i], &pref_networks))
+ break;
+
+ pns_settings.preferred_networks = pref_networks;
+
+ pns_string = connman_setting_get_string("PNSPreferredBand");
+ if (!pns_string) {
+ pns_settings.preferred_band = 0;
+ return;
+ }
+
+ pns_settings.preferred_band = pns_get_wifi_band(pns_string);
+}
+
+connman_pns_settings *connman_get_pns_settings(void)
+{
+ return &pns_settings;
+}
+
static void ins_setting_init(void)
{
int i;
remove_unprovisioned_services();
#if defined TIZEN_EXT
+ if (TIZEN_PNS_ENABLED)
+ pns_setting_init();
+
if (TIZEN_INS_ENABLED)
ins_setting_init();
+
+ DBG("TIZEN_PNS_ENABLED [%s]", TIZEN_PNS_ENABLED ? "TRUE" : "FALSE");
+ DBG("TIZEN_INS_ENABLED [%s]", TIZEN_INS_ENABLED ? "TRUE" : "FALSE");
#endif /* defined TIZEN_EXT */
return 0;
g_free(services_notify);
dbus_connection_unref(connection);
+
+#if defined TIZEN_EXT
+ if (TIZEN_PNS_ENABLED && pns_settings.preferred_networks) {
+ g_slist_free_full((GSList *) pns_settings.preferred_networks, g_free);
+ pns_settings.preferred_networks = NULL;
+ }
+#endif
}