wifi: Allow max number of scan entries
authorJukka Rissanen <jukka.rissanen@linux.intel.com>
Fri, 4 May 2012 12:24:32 +0000 (15:24 +0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Fri, 4 May 2012 13:17:05 +0000 (16:17 +0300)
Do no limit the scan entries to 4 (G_SUPPLICANT_MAX_FAST_SCAN)
but use the limit given by the driver. The limit is given by wpa_s.
If the supplicant does not return the limit, then use 4 as a max
value.

gsupplicant/gsupplicant.h
gsupplicant/supplicant.c
plugins/wifi.c

index 883de7f..5dc5364 100644 (file)
@@ -73,8 +73,6 @@ extern "C" {
 #define G_SUPPLICANT_PAIRWISE_TKIP     (1 << 1)
 #define G_SUPPLICANT_PAIRWISE_CCMP     (1 << 2)
 
-#define G_SUPPLICANT_MAX_FAST_SCAN     4
-
 #define G_SUPPLICANT_WPS_CONFIGURED     (1 << 0)
 #define G_SUPPLICANT_WPS_PBC            (1 << 1)
 #define G_SUPPLICANT_WPS_PIN            (1 << 2)
@@ -139,15 +137,26 @@ struct _GSupplicantSSID {
 
 typedef struct _GSupplicantSSID GSupplicantSSID;
 
+/*
+ * Max number of SSIDs that can be scanned.
+ * In wpa_s 0.7x the limit is 4.
+ * In wps_s 0.8 or later it is 16.
+ * The value is only used if wpa_supplicant does not return any max limit
+ * for number of scannable SSIDs.
+ */
+#define WPAS_MAX_SCAN_SSIDS 4
+
+struct scan_ssid {
+       unsigned char ssid[32];
+       uint8_t ssid_len;
+};
+
 struct _GSupplicantScanParams {
-       struct scan_ssid {
-               unsigned char ssid[32];
-               uint8_t ssid_len;
-       } ssids[G_SUPPLICANT_MAX_FAST_SCAN];
+       GSList *ssids;
 
        uint8_t num_ssids;
 
-       uint16_t freqs[G_SUPPLICANT_MAX_FAST_SCAN];
+       uint16_t *freqs;
 };
 
 typedef struct _GSupplicantScanParams GSupplicantScanParams;
@@ -250,6 +259,14 @@ typedef struct _GSupplicantCallbacks GSupplicantCallbacks;
 int g_supplicant_register(const GSupplicantCallbacks *callbacks);
 void g_supplicant_unregister(const GSupplicantCallbacks *callbacks);
 
+static inline
+void g_supplicant_free_scan_params(GSupplicantScanParams *scan_params)
+{
+       g_slist_free_full(scan_params->ssids, g_free);
+       g_free(scan_params->freqs);
+       g_free(scan_params);
+}
+
 #ifdef __cplusplus
 }
 #endif
index 58d40c1..867fa02 100644 (file)
@@ -742,6 +742,9 @@ unsigned int g_supplicant_interface_get_max_scan_ssids(
        if (interface == NULL)
                return 0;
 
+       if (interface->max_scan_ssids == 0)
+               return WPAS_MAX_SCAN_SSIDS;
+
        return interface->max_scan_ssids;
 }
 
@@ -2618,7 +2621,7 @@ static void interface_scan_result(const char *error,
        }
 
        if (data != NULL && data->scan_params != NULL)
-               g_free(data->scan_params);
+               g_supplicant_free_scan_params(data->scan_params);
 
        dbus_free(data);
 }
@@ -2643,7 +2646,7 @@ static void add_scan_frequencies(DBusMessageIter *iter,
        unsigned int freq;
        int i;
 
-       for (i = 0; i < G_SUPPLICANT_MAX_FAST_SCAN; i++) {
+       for (i = 0; i < scan_data->num_ssids; i++) {
                freq = scan_data->freqs[i];
                if (!freq)
                        break;
@@ -2668,11 +2671,13 @@ static void append_ssid(DBusMessageIter *iter,
 static void append_ssids(DBusMessageIter *iter, void *user_data)
 {
        GSupplicantScanParams *scan_data = user_data;
-       int i;
+       GSList *list;
 
-       for (i = 0; i < scan_data->num_ssids; i++)
-               append_ssid(iter, scan_data->ssids[i].ssid,
-                                       scan_data->ssids[i].ssid_len);
+       for (list = scan_data->ssids; list; list = list->next) {
+               struct scan_ssid *scan_ssid = list->data;
+
+               append_ssid(iter, scan_ssid->ssid, scan_ssid->ssid_len);
+       }
 }
 
 static void supplicant_add_scan_frequency(DBusMessageIter *dict,
@@ -2683,7 +2688,7 @@ static void supplicant_add_scan_frequency(DBusMessageIter *dict,
        DBusMessageIter entry, value, array;
        const char *key = "Channels";
 
-       if (scan_params->freqs[0] != 0) {
+       if (scan_params->freqs && scan_params->freqs[0] != 0) {
                dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
                                                NULL, &entry);
 
index 6e6bbca..2f1f7a6 100644 (file)
@@ -495,6 +495,7 @@ static int add_scan_param(gchar *hex_ssid, int freq,
                        int driver_max_scan_ssids)
 {
        unsigned int i;
+       struct scan_ssid *scan_ssid;
 
        if (driver_max_scan_ssids > scan_data->num_ssids && hex_ssid != NULL) {
                gchar *ssid;
@@ -510,15 +511,44 @@ static int add_scan_param(gchar *hex_ssid, int freq,
                        ssid[j++] = hex;
                }
 
-               memcpy(scan_data->ssids[scan_data->num_ssids].ssid, ssid, j);
-               scan_data->ssids[scan_data->num_ssids].ssid_len = j;
+               scan_ssid = g_try_new(struct scan_ssid, 1);
+               if (scan_ssid == NULL) {
+                       g_free(ssid);
+                       return -ENOMEM;
+               }
+
+               memcpy(scan_ssid->ssid, ssid, j);
+               scan_ssid->ssid_len = j;
+               scan_data->ssids = g_slist_prepend(scan_data->ssids,
+                                                               scan_ssid);
+
                scan_data->num_ssids++;
 
                g_free(ssid);
+       } else
+               return -EINVAL;
+
+       scan_data->ssids = g_slist_reverse(scan_data->ssids);
+
+       if (scan_data->freqs == NULL) {
+               scan_data->freqs = g_try_malloc0(sizeof(uint16_t) *
+                                               scan_data->num_ssids);
+               if (scan_data->freqs == NULL) {
+                       g_slist_free_full(scan_data->ssids, g_free);
+                       return -ENOMEM;
+               }
+       } else {
+               scan_data->freqs = g_try_realloc(scan_data->freqs,
+                               sizeof(uint16_t) * scan_data->num_ssids);
+               if (scan_data->freqs == NULL) {
+                       g_slist_free_full(scan_data->ssids, g_free);
+                       return -ENOMEM;
+               }
+               scan_data->freqs[scan_data->num_ssids - 1] = 0;
        }
 
        /* Don't add duplicate entries */
-       for (i = 0; i < G_SUPPLICANT_MAX_FAST_SCAN; i++) {
+       for (i = 0; i < scan_data->num_ssids; i++) {
                if (scan_data->freqs[i] == 0) {
                        scan_data->freqs[i] = freq;
                        break;
@@ -639,8 +669,7 @@ static int get_latest_connections(int max_ssids,
 
        g_strfreev(services);
 
-       num_ssids = num_ssids > G_SUPPLICANT_MAX_FAST_SCAN ?
-               G_SUPPLICANT_MAX_FAST_SCAN : num_ssids;
+       num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
 
        iter = g_sequence_get_begin_iter(latest_list);
 
@@ -690,7 +719,7 @@ static int wifi_scan_fast(struct connman_device *device)
 
        ret = get_latest_connections(driver_max_ssids, scan_params);
        if (ret <= 0) {
-               g_free(scan_params);
+               g_supplicant_free_scan_params(scan_params);
                return wifi_scan(device);
        }
 
@@ -702,7 +731,7 @@ static int wifi_scan_fast(struct connman_device *device)
        if (ret == 0)
                connman_device_set_scanning(device, TRUE);
        else {
-               g_free(scan_params);
+               g_supplicant_free_scan_params(scan_params);
                connman_device_unref(device);
        }
 
@@ -715,6 +744,7 @@ static int wifi_scan_hidden(struct connman_device *device,
 {
        struct wifi_data *wifi = connman_device_get_data(device);
        GSupplicantScanParams *scan_params = NULL;
+       struct scan_ssid *scan_ssid;
        struct hidden_params *hidden;
        int ret;
 
@@ -729,8 +759,17 @@ static int wifi_scan_hidden(struct connman_device *device,
        scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
        if (scan_params == NULL)
                return -ENOMEM;
-       memcpy(scan_params->ssids[0].ssid, ssid, ssid_len);
-       scan_params->ssids[0].ssid_len = ssid_len;
+
+       scan_ssid = g_try_new(struct scan_ssid, 1);
+       if (scan_ssid == NULL) {
+               g_free(scan_params);
+               return -ENOMEM;
+       }
+
+       memcpy(scan_ssid->ssid, ssid, ssid_len);
+       scan_ssid->ssid_len = ssid_len;
+       scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
+
        scan_params->num_ssids = 1;
 
        hidden = g_try_new0(struct hidden_params, 1);
@@ -753,7 +792,7 @@ static int wifi_scan_hidden(struct connman_device *device,
                connman_device_set_scanning(device, TRUE);
        else {
                connman_device_unref(device);
-               g_free(scan_params);
+               g_supplicant_free_scan_params(scan_params);
                hidden_free(wifi->hidden);
                wifi->hidden = NULL;
        }