Add IEEE 802.11 protocol(b/g/n/a/ac) Modes of APs 13/189913/9
authorMilind Murhekar <m.murhekar@samsung.com>
Fri, 21 Sep 2018 14:06:20 +0000 (19:36 +0530)
committerMilind Murhekar <m.murhekar@samsung.com>
Fri, 5 Oct 2018 09:00:51 +0000 (14:30 +0530)
This patch appends the IEEE 802.11b/g/n/a/ac PHY
protocol modes of scanned Access Points
using internal logic.

Following logic is used to determine WLAN HW protocol:-
1) If “Supported rates” is only till 11 Mbps, and frequency is in
2.4GHz band, then protocol is 802.11B.
2) If “Supported rates” is till 54Mbps or “Extended supported rates”
are present, and frequency is in 2.4GHz band, then protocol is 802.11G.
3) If “Supported rates” is only till 54 Mbps, frequency is in 5GHz
band , then protocol is 802.11A.
4) If “HT capabilities” is supported , then protocol is 802.11N.
5) If “HT capabilities” & “VHT” is supported and frequency is in 5 GHz
band, then protocol is 802.11AC.

Change-Id: I1156ef249cf4a8052a883d31da66788c7d2de22f

gsupplicant/gsupplicant.h
gsupplicant/supplicant.c
include/network.h
plugins/wifi.c
src/connman.h
src/network.c
src/service.c

index 035789e..597fe75 100644 (file)
@@ -135,6 +135,16 @@ typedef enum {
        G_SUPPLICANT_EAP_KEYMGMT_CCKM,
        G_SUPPLICANT_EAP_KEYMGMT_OKC,
 } GSupplicantEapKeymgmt;
+
+typedef enum {
+       G_SUPPLICANT_MODE_IEEE80211_UNKNOWN,
+       G_SUPPLICANT_MODE_IEEE80211B,
+       G_SUPPLICANT_MODE_IEEE80211BG,
+       G_SUPPLICANT_MODE_IEEE80211BGN,
+       G_SUPPLICANT_MODE_IEEE80211A,
+       G_SUPPLICANT_MODE_IEEE80211AN,
+       G_SUPPLICANT_MODE_IEEE80211ANAC,
+} GSupplicantPhy_mode;
 #endif
 
 typedef enum {
@@ -458,6 +468,7 @@ void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network);
 const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
                                                          *network);
 void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network);
+GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network);
 #endif
 
 struct _GSupplicantCallbacks {
index e300f19..e7dfcb2 100644 (file)
 #define IEEE80211_CAP_PRIVACY  0x0010
 
 #if defined TIZEN_EXT
+#define WLAN_EID_HT_CAP 45
+#define WLAN_EID_VHT_CAP 191
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_EXT_SUPP_RATES 50
 #define COUNTRY_CODE_LENGTH    2
 #endif
 
@@ -246,6 +250,7 @@ struct g_supplicant_bss {
        GSList *vsie_list;
        dbus_bool_t hs20;
        unsigned char country_code[COUNTRY_CODE_LENGTH];
+       GSupplicantPhy_mode phy_mode;
 #endif
        unsigned int wps_capabilities;
 #if defined TIZEN_EXT_WIFI_MESH
@@ -277,6 +282,7 @@ struct _GSupplicantNetwork {
        unsigned int keymgmt;
        GSList *vsie_list;
        unsigned char country_code[COUNTRY_CODE_LENGTH];
+       GSupplicantPhy_mode phy_mode;
 #endif
 };
 
@@ -1414,6 +1420,16 @@ dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
        return FALSE;
 }
 
+#ifdef TIZEN_EXT
+GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network)
+{
+       if (!network)
+               return G_SUPPLICANT_MODE_IEEE80211_UNKNOWN;
+
+       return network->phy_mode;
+}
+#endif
+
 GSupplicantInterface *g_supplicant_peer_get_interface(GSupplicantPeer *peer)
 {
        if (!peer)
@@ -2022,6 +2038,7 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
 
        network->isHS20AP = bss->hs20;
        memcpy(network->country_code, bss->country_code, COUNTRY_CODE_LENGTH);
+       network->phy_mode = bss->phy_mode;
 #endif
 
        SUPPLICANT_DBG("New network %s created", network->name);
@@ -2204,6 +2221,50 @@ static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
        return 0;
 }
 
+#if defined TIZEN_EXT
+static void get_bss_phy_mode(unsigned int max_rate,
+               unsigned int max_ext_rate, bool ht, bool vht, void *data)
+{
+       struct g_supplicant_bss *bss = data;
+       unsigned int freq = bss->frequency;
+
+       /* Following conditions are used to determine
+        * IEEE 802.11 Protocol Modes:-
+        *
+        * 1. If “Supported rates” is only till 11 Mbps,
+        *    and frequency is in 2.4GHz band, then protocol is 11B.
+        * 2. If “Supported rates” is till 54Mbps or
+        *    “Extended supported rates” are present,
+        *    and frequency is in 2.4GHz band, then protocol is 11G.
+        * 3. If “Supported rates” is only till 54 Mbps,
+        *    frequency is in 5GHz band , then protocol is 11A.
+        * 4. If “HT capabilities” is supported , then protocol is 11N.
+        * 5. If “HT capabilities” & “VHT” is supported and
+        *    frequency is in 5 GHz band, then protocol is 11AC.
+        * */
+
+       if (freq >= 2412 && freq <= 2484) { /* 2.4 Ghz Band */
+               if (max_rate <= 11 && max_ext_rate <= 0 && !ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211B;
+               else if ((max_rate <= 54 || max_ext_rate > 0) && !ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BG;
+               else if ((max_rate >= 54 || max_ext_rate > 0) && ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BGN;
+               else
+                       bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
+       } else if (freq >= 5180 && freq <= 5825) { /* 5 Ghz Band */
+               if (max_rate <= 54 && !ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211A;
+               else if ((max_rate >= 54 || max_ext_rate > 0) && ht && !vht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211AN;
+               else if ((max_rate >= 54 || max_ext_rate > 0) && ht && vht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211ANAC;
+               else
+                       bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
+       }
+}
+#endif
+
 static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 {
        struct g_supplicant_bss *bss = user_data;
@@ -2212,6 +2273,15 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        DBusMessageIter array;
        unsigned int value;
        int ie_len;
+#if defined TIZEN_EXT
+       int r_len, j;
+       unsigned char *rates = NULL;
+       unsigned char *ext_rates = NULL;
+       unsigned int max_rate = 0;
+       unsigned int max_ext_rate = 0;
+       bool ht = false;
+       bool vht = false;
+#endif
 
 #define WMM_WPA1_WPS_INFO 221
 #define WPS_INFO_MIN_LEN  6
@@ -2264,6 +2334,44 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
                                continue;
                        }
                }
+
+               if (ie[0] == WLAN_EID_HT_CAP && ie[1]) {
+                       ht = true;
+                       continue;
+               }
+
+               if (ie[0] == WLAN_EID_VHT_CAP && ie[1]) {
+                       vht = true;
+                       continue;
+               }
+
+               if (ie[0] == WLAN_EID_SUPP_RATES && ie[1]) {
+                       r_len = ie[1];
+                       rates = g_malloc0(r_len);
+                       if (!rates)
+                               continue;
+
+                       for (j = 0; ie && j < r_len; j++) {
+                               rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
+                               if (max_rate < rates[j])
+                                       max_rate = rates[j];
+                       }
+                       continue;
+               }
+
+               if (ie[0] == WLAN_EID_EXT_SUPP_RATES && ie[1] > 0) {
+                       r_len = ie[1];
+                       ext_rates = g_malloc0(r_len);
+                       if (!ext_rates)
+                               continue;
+
+                       for (j = 0; ie && j < r_len; j++) {
+                               ext_rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
+                               if (max_ext_rate < ext_rates[j])
+                                       max_ext_rate = ext_rates[j];
+                       }
+                       continue;
+               }
 #endif
                if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
                        memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
@@ -2299,6 +2407,13 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 
                SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
        }
+#ifdef TIZEN_EXT
+       get_bss_phy_mode(max_rate, max_ext_rate, ht, vht, user_data);
+       if (rates)
+               g_free(rates);
+       if (ext_rates)
+               g_free(ext_rates);
+#endif
 }
 
 static void bss_compute_security(struct g_supplicant_bss *bss)
@@ -3253,6 +3368,7 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        supplicant_dbus_property_foreach(iter, bss_property, bss);
 #if defined TIZEN_EXT
        network->frequency = bss->frequency;
+       network->phy_mode = bss->phy_mode;
 #endif
        old_security = network->security;
        bss_compute_security(bss);
index 2c74299..6d067c5 100755 (executable)
@@ -68,6 +68,29 @@ struct connman_bssids {
        uint16_t strength;
        uint16_t frequency;
 };
+
+/* Backward compatible
+ * modes of available network */
+typedef enum {
+       IEEE80211_UNKNOWN,
+       IEEE80211_MODE_B,
+       IEEE80211_MODE_BG,
+       IEEE80211_MODE_BGN,
+       IEEE80211_MODE_A,
+       IEEE80211_MODE_AN,
+       IEEE80211_MODE_ANAC,
+} ieee80211_modes_e;
+
+/* connection mode of connected network
+ * based on current linkspeed */
+typedef enum {
+       CONNECTION_MODE_IEEE80211_UNKNOWN,
+       CONNECTION_MODE_IEEE80211B,
+       CONNECTION_MODE_IEEE80211G,
+       CONNECTION_MODE_IEEE80211N,
+       CONNECTION_MODE_IEEE80211A,
+       CONNECTION_MODE_IEEE80211AC,
+} connection_mode_e;
 #endif
 
 #define CONNMAN_NETWORK_PRIORITY_LOW      -100
@@ -177,6 +200,12 @@ unsigned char *connman_network_get_countrycode(struct connman_network *network);
 int connman_network_set_bssid_list(struct connman_network *network,
                                        GSList *bssids);
 void *connman_network_get_bssid_list(struct connman_network *network);
+int connman_network_set_phy_mode(struct connman_network *network,
+                               ieee80211_modes_e mode);
+ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network);
+int connman_network_set_connection_mode(struct connman_network *network,
+                               connection_mode_e mode);
+connection_mode_e connman_network_get_connection_mode(struct connman_network *network);
 #endif
 
 int connman_network_set_name(struct connman_network *network,
index 92e70f4..33425e0 100644 (file)
@@ -3429,6 +3429,77 @@ static int network_disconnect(struct connman_network *network)
 #if defined TIZEN_EXT
 static unsigned int automaxspeed_timeout = 0;
 
+static void set_connection_mode(struct connman_network *network,
+               int linkspeed)
+{
+       ieee80211_modes_e phy_mode;
+       connection_mode_e conn_mode;
+
+       phy_mode = connman_network_get_phy_mode(network);
+       switch (phy_mode) {
+       case IEEE80211_MODE_B:
+               if (linkspeed > 0 && linkspeed <= 11)
+                       conn_mode = CONNECTION_MODE_IEEE80211B;
+               else
+                       conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+               break;
+       case IEEE80211_MODE_BG:
+               if (linkspeed > 0 && linkspeed <= 11)
+                       conn_mode = CONNECTION_MODE_IEEE80211B;
+               else if (linkspeed > 11 && linkspeed <= 54)
+                       conn_mode = CONNECTION_MODE_IEEE80211G;
+               else
+                       conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+               break;
+       case IEEE80211_MODE_BGN:
+               if (linkspeed > 0 && linkspeed <= 11)
+                       conn_mode = CONNECTION_MODE_IEEE80211B;
+               else if (linkspeed > 11 && linkspeed <= 54)
+                       conn_mode = CONNECTION_MODE_IEEE80211G;
+               else if (linkspeed > 54 && linkspeed <= 450)
+                       conn_mode = CONNECTION_MODE_IEEE80211N;
+               else
+                       conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+               break;
+       case IEEE80211_MODE_A:
+               if (linkspeed > 0 && linkspeed <= 54)
+                       conn_mode = CONNECTION_MODE_IEEE80211A;
+               else
+                       conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+               break;
+       case IEEE80211_MODE_AN:
+               if (linkspeed > 0 && linkspeed <= 54)
+                       conn_mode = CONNECTION_MODE_IEEE80211A;
+               else if (linkspeed > 54 && linkspeed <= 450)
+                       conn_mode = CONNECTION_MODE_IEEE80211N;
+               else
+                       conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+               break;
+       case IEEE80211_MODE_ANAC:
+               if (linkspeed > 0 && linkspeed <= 54)
+                       conn_mode = CONNECTION_MODE_IEEE80211A;
+               else if (linkspeed > 54 && linkspeed <= 450)
+                       conn_mode = CONNECTION_MODE_IEEE80211N;
+               else if (linkspeed > 450 && linkspeed <= 1300)
+                       conn_mode = CONNECTION_MODE_IEEE80211AC;
+               else
+                       conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+               break;
+       default:
+                       conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+               break;
+       }
+
+       DBG("connection mode(%d)", conn_mode);
+       connman_network_set_connection_mode(network, conn_mode);
+}
+
 static void signalpoll_callback(int result, int maxspeed, void *user_data)
 {
        struct connman_network *network = user_data;
@@ -3439,8 +3510,10 @@ static void signalpoll_callback(int result, int maxspeed, void *user_data)
        }
 
        DBG("maxspeed = %d", maxspeed);
-       if (network)
+       if (network) {
                connman_network_set_maxspeed(network, maxspeed);
+               set_connection_mode(network, maxspeed);
+       }
 }
 
 static int network_signalpoll(struct connman_network *network)
@@ -4256,6 +4329,7 @@ static void network_added(GSupplicantNetwork *supplicant_network)
 #if defined TIZEN_EXT
        GSList *vsie_list = NULL;
        const unsigned char *country_code;
+       ieee80211_modes_e phy_mode;
 #endif
 
        mode = g_supplicant_network_get_mode(supplicant_network);
@@ -4320,6 +4394,8 @@ static void network_added(GSupplicantNetwork *supplicant_network)
                DBG("vsie_list is NULL");
        country_code = g_supplicant_network_get_countrycode(supplicant_network);
        connman_network_set_countrycode(network, country_code);
+       phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
+       connman_network_set_phy_mode(network, phy_mode);
 #endif
        connman_network_set_string(network, "WiFi.Security", security);
        connman_network_set_strength(network,
@@ -4453,6 +4529,7 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
        uint16_t frequency;
        bool wps;
        const unsigned char *country_code;
+       ieee80211_modes_e phy_mode;
        GSList *bssid_list;
 #endif
 
@@ -4481,6 +4558,7 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
        maxrate = g_supplicant_network_get_maxrate(network);
        frequency = g_supplicant_network_get_frequency(network);
        wps = g_supplicant_network_get_wps(network);
+       phy_mode = g_supplicant_network_get_phy_mode(network);
 
        connman_network_set_bssid(connman_network, bssid);
        connman_network_set_maxrate(connman_network, maxrate);
@@ -4490,6 +4568,7 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
        connman_network_set_countrycode(connman_network, country_code);
        bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
        connman_network_set_bssid_list(connman_network, bssid_list);
+       connman_network_set_phy_mode(connman_network, phy_mode);
 #endif
 }
 
index 905467e..610f63b 100644 (file)
@@ -26,6 +26,7 @@
 #define CONNMAN_API_SUBJECT_TO_CHANGE
 #if defined TIZEN_EXT
 #define WIFI_COUNTRY_CODE_LEN 2
+#define WIFI_PHY_MODE_LEN 18
 #endif
 
 #include <connman/dbus.h>
index 85eb0fd..b710368 100755 (executable)
@@ -122,6 +122,8 @@ struct connman_network {
                char *phase1;
                unsigned char country_code[WIFI_COUNTRY_CODE_LEN];
                GSList *bssid_list;
+               ieee80211_modes_e phy_mode;
+               connection_mode_e connection_mode;
 #endif
        } wifi;
 
@@ -2130,6 +2132,34 @@ int connman_network_set_bssid_list(struct connman_network *network,
        return 0;
 }
 
+int connman_network_set_phy_mode(struct connman_network *network,
+                                   ieee80211_modes_e mode)
+{
+       DBG("network %p phy mode %d", network, mode);
+       network->wifi.phy_mode = mode;
+
+       return 0;
+}
+
+ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network)
+{
+       return network->wifi.phy_mode;
+}
+
+int connman_network_set_connection_mode(struct connman_network *network,
+                                   connection_mode_e mode)
+{
+       DBG("network %p connection mode %d", network, mode);
+       network->wifi.connection_mode = mode;
+
+       return 0;
+}
+
+connection_mode_e connman_network_get_connection_mode(struct connman_network *network)
+{
+       return network->wifi.connection_mode;
+}
+
 void *connman_network_get_bssid_list(struct connman_network *network)
 {
        return network->wifi.bssid_list;
index 614be70..d6c0322 100644 (file)
@@ -3262,6 +3262,7 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
        char country_code_buff[WIFI_COUNTRY_CODE_LEN + 1] = {0,};
        char *country_code_str = country_code_buff;
        unsigned char *country_code;
+       uint16_t connection_mode;
 
        ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
        bssid = connman_network_get_bssid(network);
@@ -3272,6 +3273,7 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
        passpoint = connman_network_get_bool(network, "WiFi.HS20AP");
        keymgmt = connman_network_get_keymgmt(network);
        country_code = connman_network_get_countrycode(network);
+       connection_mode = connman_network_get_connection_mode(network);
 
        snprintf(bssid_str, WIFI_BSSID_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
                                bssid[0], bssid[1], bssid[2],
@@ -3299,6 +3301,8 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
                                        DBUS_TYPE_UINT32, &keymgmt);
        connman_dbus_dict_append_basic(dict, "Country", DBUS_TYPE_STRING,
                                       &country_code_str);
+       connman_dbus_dict_append_basic(dict, "ConnMode",
+                                       DBUS_TYPE_UINT16, &connection_mode);
 
        str = connman_network_get_string(network, "WiFi.Security");
        if (str != NULL && g_str_equal(str, "ieee8021x") == TRUE) {