cooperative scanning patch
- From: Dan Williams <dcbw redhat com>
- To: networkmanager-list gnome org
- Subject: cooperative scanning patch
- Date: Wed, 29 Mar 2006 23:41:06 -0500
Hi,
Here's a reworked patch that makes use of the netlink/wireless event
stuff from about a month ago. It's got a few features:
* Notices driver-provided scan completion events and pulls from them
* Uses wpa_supplicant for scanning when a wireless connection is active
* Works around older drivers that don't send scan completion events
* Doesn't block waiting for scan results
Please test it out (against HEAD) and see if it works for you.
I've noticed one fairly large issue though... wpa_supplicant seems to
get its link state confused and doesn't reconnect. I don't know if this
is due to the driver not sending reconnect events or whether
wpa_supplicant is just dumb. It doesn't appear that wpa_supplicant has
much special logic to 'fake' a connection through a scan, which sucks
for us. More investigation is certainly needed.
Dan
Index: src/nm-device-802-11-wireless.c
===================================================================
RCS file: /cvs/gnome/NetworkManager/src/nm-device-802-11-wireless.c,v
retrieving revision 1.66
diff -u -r1.66 nm-device-802-11-wireless.c
--- src/nm-device-802-11-wireless.c 8 Mar 2006 14:45:14 -0000 1.66
+++ src/nm-device-802-11-wireless.c 30 Mar 2006 04:12:11 -0000
@@ -73,10 +73,12 @@
gint8 num_freqs;
double freqs[IW_MAX_FREQUENCIES];
- GMutex * scan_mutex;
+ gboolean scanning;
NMAccessPointList * ap_list;
guint8 scan_interval; /* seconds */
guint32 last_scan;
+ GSource * scan_timeout;
+ GSource * pending_scan;
struct _Supplicant supplicant;
@@ -97,25 +99,21 @@
guint32 results_len;
} NMWirelessScanResults;
-typedef struct
-{
- NMDevice80211Wireless * dev;
- gboolean force;
-} NMWirelessScanCB;
-
static void nm_device_802_11_wireless_ap_list_clear (NMDevice80211Wireless *self);
static gboolean nm_device_802_11_wireless_scan (gpointer user_data);
+static void cancel_scan_results_timeout (NMDevice80211Wireless *self);
+
+static void cancel_pending_scan (NMDevice80211Wireless *self);
+
+static void request_and_convert_scan_results (NMDevice80211Wireless *self);
+
static gboolean process_scan_results (NMDevice80211Wireless *dev,
const guint8 *res_buf,
guint32 res_buf_len);
-
-static gboolean get_scan_results (NMDevice80211Wireless *dev,
- NMSock *sk,
- guint8 **out_res_buf,
- guint32 *data_len);
+static void schedule_scan (NMDevice80211Wireless *self);
static int wireless_qual_to_percent (const struct iw_quality *qual,
const struct iw_quality *max_qual,
@@ -140,7 +138,7 @@
char *data,
int data_len,
NMDevice80211Wireless *self);
-
+
static guint nm_wireless_scan_interval_to_seconds (NMWirelessScanInterval interval)
{
guint seconds;
@@ -263,9 +261,7 @@
NMSock * sk;
NmNetlinkMonitor * monitor;
- self->priv->scan_mutex = g_mutex_new ();
- nm_register_mutex_desc (self->priv->scan_mutex, "Scan Mutex");
-
+ self->priv->scanning = FALSE;
self->priv->ap_list = nm_ap_list_new (NETWORK_TYPE_DEVICE);
app_data = nm_device_get_app_data (NM_DEVICE (self));
@@ -395,7 +391,10 @@
}
break;
case SIOCGIWSCAN:
- /* Got some scan results */
+nm_info ("(%s) got scan results wireless event.", nm_device_get_iface (NM_DEVICE (self)));
+ cancel_scan_results_timeout (self);
+ request_and_convert_scan_results (self);
+ schedule_scan (self);
break;
}
pos += iwe->len;
@@ -475,16 +474,11 @@
/* Start the scanning timeout for devices that can do scanning */
if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_WIRELESS_SCAN)
{
- NMWirelessScanCB * scan_cb;
-
- scan_cb = g_malloc0 (sizeof (NMWirelessScanCB));
- scan_cb->dev = self;
- scan_cb->force = TRUE;
-
- source = g_idle_source_new ();
- g_source_set_callback (source, nm_device_802_11_wireless_scan, scan_cb, NULL);
- source_id = g_source_attach (source, nm_device_get_main_context (dev));
- g_source_unref (source);
+ self->priv->pending_scan = g_idle_source_new ();
+ g_source_set_callback (self->priv->pending_scan,
+ nm_device_802_11_wireless_scan, self, NULL);
+ source_id = g_source_attach (self->priv->pending_scan,
+ nm_device_get_main_context (dev));
}
/* Peridoically update link status and signal strength */
@@ -616,8 +610,11 @@
{
gboolean have_link = FALSE;
- /* Checking hardware's ESSID during a scan is doesn't work. */
- nm_lock_mutex (self->priv->scan_mutex, __func__);
+ /* Fake a link if we're scanning, we'll drop it later
+ * if it's really dead.
+ */
+ if (self->priv->scanning)
+ return TRUE;
if (is_associated (self))
{
@@ -631,8 +628,6 @@
}
}
- nm_unlock_mutex (self->priv->scan_mutex, __func__);
-
if (!have_link)
{
self->priv->failed_link_count++;
@@ -1261,20 +1256,20 @@
g_return_if_fail (self != NULL);
+ /* Signal strength is pretty meaningless during a scan */
+ if (self->priv->scanning)
+ return;
+
app_data = nm_device_get_app_data (NM_DEVICE (self));
g_assert (app_data);
- /* Grab the scan lock since our strength is meaningless during a scan. */
- if (!nm_try_acquire_mutex (self->priv->scan_mutex, __FUNCTION__))
- return;
-
/* If we aren't the active device, we don't really have a signal strength
* that would mean anything.
*/
if (!nm_device_get_act_request (NM_DEVICE (self)))
{
self->priv->strength = -1;
- goto out;
+ return;
}
if ((sk = nm_dev_sock_open (NM_DEVICE (self), DEV_WIRELESS, __FUNCTION__, NULL)))
@@ -1310,9 +1305,6 @@
nm_dbus_signal_device_strength_change (app_data->dbus_connection, self, percent);
self->priv->strength = percent;
-
-out:
- nm_unlock_mutex (self->priv->scan_mutex, __func__);
}
@@ -1419,6 +1411,7 @@
}
+#if 0
/*
* nm_device_get_frequency
*
@@ -1458,7 +1451,6 @@
return freq;
}
-
/*
* nm_device_set_frequency
*
@@ -1534,7 +1526,7 @@
nm_dev_sock_close (sk);
}
}
-
+#endif
/*
* nm_device_get_bitrate
@@ -1566,7 +1558,7 @@
return ((err >= 0) ? wrq.u.bitrate.value / 1000000 : 0);
}
-
+#if 0
/*
* nm_device_set_bitrate
*
@@ -1611,6 +1603,7 @@
nm_dev_sock_close (sk);
}
}
+#endif
/*
@@ -1738,34 +1731,6 @@
} else nm_warning ("could not get wireless control socket for device %s", iface);
}
-/*
- * nm_device_wireless_schedule_scan
- *
- * Schedule a wireless scan in the /device's/ thread.
- *
- */
-static void
-schedule_scan (NMDevice80211Wireless *self)
-{
- GSource * wscan_source;
- guint wscan_source_id;
- NMWirelessScanCB * scan_cb;
- GMainContext * context;
-
- g_return_if_fail (self != NULL);
-
- scan_cb = g_malloc0 (sizeof (NMWirelessScanCB));
- scan_cb->dev = self;
- scan_cb->force = FALSE;
-
- wscan_source = g_timeout_source_new (self->priv->scan_interval * 1000);
- g_source_set_callback (wscan_source, nm_device_802_11_wireless_scan, scan_cb, NULL);
- context = nm_device_get_main_context (NM_DEVICE (self));
- wscan_source_id = g_source_attach (wscan_source, context);
- g_source_unref (wscan_source);
-}
-
-
static void
free_process_scan_cb_data (NMWirelessScanResults *cb_data)
{
@@ -1780,14 +1745,14 @@
}
/*
- * nm_device_wireless_process_scan_results
+ * convert_scan_results
*
* Process results of an iwscan() into our own AP lists. We're an idle function,
* but we never reschedule ourselves.
*
*/
static gboolean
-handle_scan_results (gpointer user_data)
+convert_scan_results (gpointer user_data)
{
NMWirelessScanResults * cb_data = (NMWirelessScanResults *) user_data;
NMDevice80211Wireless * self;
@@ -1800,6 +1765,7 @@
g_return_val_if_fail (cb_data != NULL, FALSE);
self = NM_DEVICE_802_11_WIRELESS (cb_data->dev);
+nm_info ("(%s) converting scan results.", nm_device_get_iface (NM_DEVICE (self)));
if (!self || !cb_data->results)
{
free_process_scan_cb_data (cb_data);
@@ -1876,37 +1842,198 @@
}
+#define SCAN_SLEEP_CENTISECONDS 10 /* sleep 1/10 of a second, waiting for data */
+static void
+request_and_convert_scan_results (NMDevice80211Wireless *self)
+{
+ NMSock *sk;
+ NMWirelessScanResults *scan_results = NULL;
+ const char *iface;
+ struct iwreq iwr;
+ guint8 tries = 0;
+ gboolean success = FALSE;
+ guint8 *buf = NULL;
+ size_t buflen = IW_SCAN_MAX_DATA;
+
+ g_return_if_fail (self != NULL);
+
+ if (!(sk = nm_dev_sock_open (NM_DEVICE (self), DEV_WIRELESS, __FUNCTION__, NULL)))
+ return;
+
+nm_info ("(%s) request_and_convert called.", nm_device_get_iface (NM_DEVICE (self)));
+ iface = nm_device_get_iface (NM_DEVICE (self));
+ for (;;)
+ {
+ if (!(buf = g_malloc0 (buflen)))
+ break;
+ iwr.u.data.pointer = buf;
+ iwr.u.data.flags = 0;
+ iwr.u.data.length = buflen;
+
+ if (iw_get_ext (nm_dev_sock_get_fd (sk), iface, SIOCGIWSCAN, &iwr) == 0)
+ {
+ /* success */
+ buflen = iwr.u.data.length;
+ success = TRUE;
+ break;
+ }
+
+ g_free (buf);
+ buf = NULL;
+
+ if ((errno == E2BIG) && (buflen < 100000)) /* Buffer not big enough */
+ {
+ buflen *= 2;
+ }
+ else if (errno == EAGAIN) /* Card doesn't have results yet */
+ {
+ /* We've already waited for the scan data, so don't give
+ * drivers too much slack here.
+ */
+ if (tries > 4 * SCAN_SLEEP_CENTISECONDS)
+ {
+ nm_warning ("card took too much time scanning. Get a better one.");
+ break;
+ }
+ g_usleep (G_USEC_PER_SEC / SCAN_SLEEP_CENTISECONDS);
+ tries++;
+ }
+ else if (errno == ENODATA) /* No scan results */
+ {
+ buflen = 0;
+ success = TRUE;
+ break;
+ }
+ else /* Random errors */
+ {
+ nm_warning ("unknown error, or the card returned too much scan info: %s",
+ strerror (errno));
+ break;
+ }
+ }
+ nm_dev_sock_close (sk);
+
+ if (success)
+ {
+ NMData * app_data = nm_device_get_app_data (NM_DEVICE (self));
+ GSource * convert_source = g_idle_source_new ();
+ GTimeVal cur_time;
+
+ /* We run the scan processing function from the main thread, since it must deliver
+ * messages over DBUS. Plus, that way the main thread is the only thread that has
+ * to modify the device's access point list.
+ */
+nm_info ("(%s) scheduling scan request conversion in main context.", nm_device_get_iface (NM_DEVICE (self)));
+ scan_results = g_malloc0 (sizeof (NMWirelessScanResults));
+ g_object_ref (G_OBJECT (self));
+ scan_results->dev = self;
+ scan_results->results = buf;
+ scan_results->results_len = buflen;
+
+ g_source_set_callback (convert_source, convert_scan_results, scan_results, NULL);
+ g_source_attach (convert_source, app_data->main_context);
+ g_source_unref (convert_source);
+ g_get_current_time (&cur_time);
+ self->priv->last_scan = cur_time.tv_sec;
+ }
+}
+
+
+/*
+ * scan_results_timeout
+ *
+ * Request scan results from the card if it has taken more time than
+ * we allow. Also works around drivers that don't send notifications of
+ * completed scans to userspace.
+ */
+static gboolean
+scan_results_timeout (NMDevice80211Wireless *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+nm_info ("(%s) scan_request_timeout called.", nm_device_get_iface (NM_DEVICE (self)));
+ request_and_convert_scan_results (self);
+ schedule_scan (self);
+ g_source_unref (self->priv->scan_timeout); /* Balance g_timeout_source_new() */
+ self->priv->scan_timeout = NULL;
+ return FALSE; /* Balance g_source_attach(), destroyed on return */
+}
+
+
+/*
+ * schedule_scan_results_timeout
+ *
+ * For cards that don't send a wireless event for scan results,
+ * we hit the card after the timeout and explicitly ask for them.
+ *
+ */
+static void
+schedule_scan_results_timeout (NMDevice80211Wireless *self)
+{
+ GMainContext * context;
+
+ g_return_if_fail (self != NULL);
+
+ cancel_scan_results_timeout (self);
+
+ /* Wait 10 seconds for scan results */
+nm_info ("(%s) scheduling scan request timeout.", nm_device_get_iface (NM_DEVICE (self)));
+ self->priv->scan_timeout = g_timeout_source_new (10000);
+ g_source_set_callback (self->priv->scan_timeout,
+ (GSourceFunc) scan_results_timeout, self, NULL);
+ context = nm_device_get_main_context (NM_DEVICE (self));
+ g_source_attach (self->priv->scan_timeout, context);
+}
+
+
+/*
+ * cancel_scan_results_timeout
+ *
+ * Cancel an existing scan results timeout
+ *
+ */
+static void
+cancel_scan_results_timeout (NMDevice80211Wireless *self)
+{
+ g_return_if_fail (self != NULL);
+
+nm_info ("(%s) cancel_scan_results_timeout called.", nm_device_get_iface (NM_DEVICE (self)));
+ if (self->priv->scan_timeout)
+ {
+ g_source_destroy (self->priv->scan_timeout); /* Balance g_source_attach() */
+ g_source_unref (self->priv->scan_timeout); /* Balance g_timeout_source_new() */
+ self->priv->scan_timeout = NULL;
+nm_info ("(%s) cancelled scan request timeout.", nm_device_get_iface (NM_DEVICE (self)));
+ }
+}
+
+
/*
* nm_device_802_11_wireless_scan
*
- * Get a list of access points this device can see.
+ * Trigger a scan request
*
*/
static gboolean
nm_device_802_11_wireless_scan (gpointer user_data)
{
- NMWirelessScanCB * scan_cb = (NMWirelessScanCB *)(user_data);
- NMDevice80211Wireless * self = NULL;
- NMWirelessScanResults * scan_results = NULL;
+ NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
guint32 caps;
NMData * app_data;
+ gboolean success = FALSE;
+ const char * iface;
- g_return_val_if_fail (scan_cb != NULL, FALSE);
+ g_return_val_if_fail (self != NULL, FALSE);
- self = scan_cb->dev;
- if (!self || !nm_device_get_app_data (NM_DEVICE (self)))
- {
- g_free (scan_cb);
- return FALSE;
- }
- app_data = nm_device_get_app_data (NM_DEVICE (self));
+ if (!(app_data = nm_device_get_app_data (NM_DEVICE (self))))
+ goto out;
caps = nm_device_get_capabilities (NM_DEVICE (self));
if (!(caps & NM_DEVICE_CAP_NM_SUPPORTED) || !(caps & NM_DEVICE_CAP_WIRELESS_SCAN))
- {
- g_free (scan_cb);
- return FALSE;
- }
+ goto out;
+
+ g_source_unref (self->priv->pending_scan); /* Balance g_timeout_source_new() */
+ self->priv->pending_scan = NULL;
/* Reschedule ourselves if all wireless is disabled, we're asleep,
* or we are currently activating.
@@ -1916,7 +2043,8 @@
|| (nm_device_is_activating (NM_DEVICE (self)) == TRUE))
{
nm_device_802_11_wireless_set_scan_interval (app_data, self, NM_WIRELESS_SCAN_INTERVAL_INIT);
- goto reschedule;
+ schedule_scan (self);
+ goto out;
}
/*
@@ -1927,115 +2055,102 @@
if ((self->priv->num_freqs > 14) && nm_device_is_activated (NM_DEVICE (self)) == TRUE)
{
nm_device_802_11_wireless_set_scan_interval (app_data, self, NM_WIRELESS_SCAN_INTERVAL_ACTIVE);
- goto reschedule;
+ schedule_scan (self);
+ goto out;
}
- /* Grab the scan mutex */
- if (nm_try_acquire_mutex (self->priv->scan_mutex, __func__))
+nm_info ("(%s) Requesting a scan.", nm_device_get_iface (NM_DEVICE (self)));
+ self->priv->scanning = TRUE;
+
+ /* Device must be up before we can scan */
+ if (nm_device_bring_up_wait (NM_DEVICE (self), 1))
{
- NMSock * sk;
- gboolean devup_err;
- const char * iface;
+ schedule_scan (self);
+ goto out;
+ }
- /* Device must be up before we can scan */
- devup_err = nm_device_bring_up_wait (NM_DEVICE (self), 1);
- if (devup_err)
- {
- nm_unlock_mutex (self->priv->scan_mutex, __func__);
- goto reschedule;
- }
+ /* If we're currently connected to an AP, let wpa_supplicant initiate
+ * the scan request rather than doing it ourselves.
+ */
+ iface = nm_device_get_iface (NM_DEVICE (self));
+ if (self->priv->supplicant.ctrl)
+ {
+ if (nm_utils_supplicant_request_with_check (self->priv->supplicant.ctrl,
+ "OK", __func__, NULL, "SCAN"))
+{
+nm_info ("(%s) triggered supplicant scan.", nm_device_get_iface (NM_DEVICE (self)));
+ success = TRUE;
+}
+ }
+ else
+ {
+ NMSock * sk;
- iface = nm_device_get_iface (NM_DEVICE (self));
if ((sk = nm_dev_sock_open (NM_DEVICE (self), DEV_WIRELESS, __FUNCTION__, NULL)))
{
- int orig_mode;
- double orig_freq = 0;
- int orig_rate = 0;
- struct iwreq wrq;
-
- orig_mode = nm_device_802_11_wireless_get_mode (self);
- if (orig_mode == IW_MODE_ADHOC)
- {
- orig_freq = nm_device_802_11_wireless_get_frequency (self);
- orig_rate = nm_device_802_11_wireless_get_bitrate (self);
- }
-
- /* Must be in infrastructure mode during scan, otherwise we don't get a full
- * list of scan results. Scanning doesn't work well in Ad-Hoc mode :(
- */
- nm_device_802_11_wireless_set_mode (self, IW_MODE_INFRA);
-
- /* We only unlock the frequency if the card is in adhoc mode, in case it is
- * a costly operation for the driver.
- */
- if (orig_mode == IW_MODE_ADHOC)
- nm_device_802_11_wireless_set_frequency (self, 0);
+ struct iwreq wrq;
wrq.u.data.pointer = NULL;
wrq.u.data.flags = 0;
wrq.u.data.length = 0;
- if (iw_set_ext (nm_dev_sock_get_fd (sk), iface, SIOCSIWSCAN, &wrq) < 0)
- {
- nm_warning ("could not trigger wireless scan on device %s: %s",
- iface, strerror (errno));
- }
- else
- {
- guint8 * results = NULL;
- guint32 results_len = 0;
-
- /* Initial pause for card to return data */
- g_usleep (G_USEC_PER_SEC / 4);
-
- if (get_scan_results (self, sk, &results, &results_len))
- {
- scan_results = g_malloc0 (sizeof (NMWirelessScanResults));
- g_object_ref (G_OBJECT (self));
- scan_results->dev = self;
- scan_results->results = results;
- scan_results->results_len = results_len;
- }
- else
- nm_warning ("device %s returned an error.", iface);
- }
-
- nm_device_802_11_wireless_set_mode (self, orig_mode);
- /* Only set frequency if ad-hoc mode */
- if (orig_mode == IW_MODE_ADHOC)
- {
- nm_device_802_11_wireless_set_frequency (self, orig_freq);
- nm_device_802_11_wireless_set_bitrate (self, orig_rate);
- }
-
+ if (iw_set_ext (nm_dev_sock_get_fd (sk), iface, SIOCSIWSCAN, &wrq) == 0)
+{
+nm_info ("(%s) triggered manual scan.", nm_device_get_iface (NM_DEVICE (self)));
+ success = TRUE;
+}
nm_dev_sock_close (sk);
}
- nm_unlock_mutex (self->priv->scan_mutex, __func__);
}
- /* We run the scan processing function from the main thread, since it must deliver
- * messages over DBUS. Plus, that way the main thread is the only thread that has
- * to modify the device's access point list.
- */
- if (scan_results != NULL)
+ if (success)
{
- guint scan_process_source_id = 0;
- GSource * scan_process_source = g_idle_source_new ();
- GTimeVal cur_time;
+ schedule_scan_results_timeout (self);
+ }
+ else
+ {
+ nm_warning ("could not trigger wireless scan on device %s: %s",
+ iface, strerror (errno));
+ schedule_scan (self);
+ }
- g_source_set_callback (scan_process_source, handle_scan_results, scan_results, NULL);
- scan_process_source_id = g_source_attach (scan_process_source, app_data->main_context);
- g_source_unref (scan_process_source);
+out:
+ return FALSE; /* Balance g_source_attach(), destroyed on return */
+}
- g_get_current_time (&cur_time);
- self->priv->last_scan = cur_time.tv_sec;
- }
-reschedule:
- /* Make sure we reschedule ourselves so we keep scanning */
- schedule_scan (self);
+/*
+ * nm_device_wireless_schedule_scan
+ *
+ * Schedule a wireless scan in the /device's/ thread.
+ *
+ */
+static void
+schedule_scan (NMDevice80211Wireless *self)
+{
+ g_return_if_fail (self != NULL);
- g_free (scan_cb);
- return FALSE;
+ cancel_pending_scan (self);
+
+nm_info ("(%s) Scheduling wireless scan.", nm_device_get_iface (NM_DEVICE (self)));
+ self->priv->pending_scan = g_timeout_source_new (self->priv->scan_interval * 1000);
+ g_source_set_callback (self->priv->pending_scan, nm_device_802_11_wireless_scan, self, NULL);
+ g_source_attach (self->priv->pending_scan, nm_device_get_main_context (NM_DEVICE (self)));
+}
+
+
+static void
+cancel_pending_scan (NMDevice80211Wireless *self)
+{
+ g_return_if_fail (self != NULL);
+
+ self->priv->scanning = FALSE;
+ if (self->priv->pending_scan)
+ {
+ g_source_destroy (self->priv->pending_scan); /* Balance g_source_attach() */
+ g_source_unref (self->priv->pending_scan); /* Balance g_timeout_source_new() */
+ self->priv->pending_scan = NULL;
+nm_info ("(%s) cancelled pending scan.", nm_device_get_iface (NM_DEVICE (self)));
+ }
}
@@ -2289,7 +2404,7 @@
static gboolean
link_timeout_cb (gpointer user_data)
{
- NMDevice * dev = NM_DEVICE (user_data);
+ NMDevice * dev = NM_DEVICE (user_data);
g_assert (dev);
@@ -2332,6 +2447,8 @@
wpa_ctrl_recv (ctrl, message, &len);
message[len] = '\0';
+nm_info ("(%s): supplicant said '%s'\n", nm_device_get_iface (NM_DEVICE (self)), message);
+
if (strstr (message, WPA_EVENT_CONNECTED) != NULL)
{
remove_link_timeout (self);
@@ -2357,7 +2474,7 @@
if (nm_device_is_activated (dev) || nm_device_is_activating (dev))
{
/* Start the link timeout so we allow some time for reauthentication */
- if (self->priv->link_timeout == NULL)
+ if ((self->priv->link_timeout == NULL) && !self->priv->scanning)
{
GMainContext * context = nm_device_get_main_context (dev);
self->priv->link_timeout = g_timeout_source_new (8000);
@@ -3032,7 +3149,9 @@
nm_device_802_11_wireless_ap_list_clear (self);
if (self->priv->ap_list)
nm_ap_list_unref (self->priv->ap_list);
- g_mutex_free (self->priv->scan_mutex);
+
+ cancel_scan_results_timeout (self);
+ cancel_pending_scan (self);
g_signal_handler_disconnect (G_OBJECT (data->netlink_monitor),
self->priv->wireless_event_id);
@@ -3162,81 +3281,6 @@
}
return 0;
}
-
-#define SCAN_SLEEP_CENTISECONDS 10 /* sleep 1/10 of a second, waiting for data */
-static gboolean
-get_scan_results (NMDevice80211Wireless *dev,
- NMSock *sk,
- guint8 **out_res_buf,
- guint32 *data_len)
-{
- struct iwreq iwr;
- guint8 *res_buf;
- size_t res_buf_len = IW_SCAN_MAX_DATA;
- guint8 tries = 0;
- gboolean success = FALSE;
-
- g_return_val_if_fail (dev != NULL, FALSE);
- g_return_val_if_fail (sk != NULL, FALSE);
- g_return_val_if_fail (out_res_buf != NULL, FALSE);
- g_return_val_if_fail (*out_res_buf == NULL, FALSE);
- g_return_val_if_fail (data_len != NULL, FALSE);
-
- *data_len = 0;
-
- for (;;)
- {
- res_buf = g_malloc (res_buf_len);
- if (!res_buf)
- break;
- memset (&iwr, 0, sizeof (struct iwreq));
- iwr.u.data.pointer = res_buf;
- iwr.u.data.flags = 0;
- iwr.u.data.length = res_buf_len;
-
- if (iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (NM_DEVICE (dev)), SIOCGIWSCAN, &iwr) == 0)
- {
- /* success */
- *data_len = iwr.u.data.length;
- *out_res_buf = res_buf;
- success = TRUE;
- break;
- }
-
- g_free (res_buf);
- res_buf = NULL;
-
- if ((errno == E2BIG) && (res_buf_len < 100000)) /* Buffer not big enough */
- {
- res_buf_len *= 2;
- }
- else if (errno == EAGAIN) /* Card doesn't have results yet */
- {
- if (tries > 20 * SCAN_SLEEP_CENTISECONDS)
- {
- nm_warning ("card took too much time scanning. Get a better one.");
- break;
- }
-
- g_usleep (G_USEC_PER_SEC / SCAN_SLEEP_CENTISECONDS);
- tries++;
- }
- else if (errno == ENODATA) /* No scan results */
- {
- success = TRUE;
- break;
- }
- else /* Random errors */
- {
- nm_warning ("unknown error, or the card returned too much scan info: %s",
- strerror (errno));
- break;
- }
- }
-
- return success;
-}
-
static void
add_new_ap_to_device_list (NMDevice80211Wireless *dev,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]