Commit c1979229 authored by Dan Williams's avatar Dan Williams
Browse files

2005-03-31 Dan Williams <dcbw@redhat.com>

	Tighten up handling of wireless devices that don't support wireless
	scanning (ie, Orinoco).  Due to restructuring of code, these devices
	hadn't been doing pseudo-scanning for a while either and would just
	spin waiting for an access point.  They are now manual devices where
	the user must choose the access point from the menu every time.  All
	"allowed" access points are listed in the applet's menu regardless
	of whether or not they can be seen by the card, since it can't scan
	anyway.

	* src/NetworkManager.c
		- (nm_wireless_link_state_handle): new function, but only update
			the "best" ap for non-scanning devices when its not activating,
			and when no device is being forced on the card
		- (nm_link_state_monitor): split wireless link state handling out
			into separate function

	* src/NetworkManagerDevice.c
		- (nm_device_copy_allowed_to_dev_list): new function
		- (nm_device_new): populate non-scanning cards' AP lists with
			access points from the "allowed" list
		- (nm_device_new): don't start a scanning timeout for devices that
			can't scan
		- (nm_device_activation_schedule_finish): new parameter, should be
			the AP that failed to be connected to, pass it on to the
			activation finish function in NetworkManagerPolicy.c
		- (nm_device_activate_wireless): don't ever try to get a new AP
			for non-scanning devices, just fail.  The user must choose
			a new access point manually.
		- (nm_device_activate): grab the AP that failed connection and
			pass it on
		- (nm_device_update_best_ap): Clear the best AP if we don't have
			a link to it, user must manually choose a new one
		- (nm_device_do_pseudo_scan): remove function
		- (nm_device_wireless_process_scan_results): remove bits for non-
			scanning cards since they never get here
		- (nm_device_wireless_scan): remove bits for non-scanning devices,
			and fake the scan list for test devices a bit earlier

	* src/NetworkManagerPolicy.c
		- (nm_policy_activation_finish): use the failed_ap that we get
			passed rather than getting the best_ap from the card, which
			may have changed since we were scheduled
		- (nm_policy_allowed_ap_list_update): for non-scanning devices,
			update their scan list directly from the allowed list when
			we get updates to the allowed list from NetworkManagerInfo

	* src/NetworkManagerPolicy.h
		- New member for failed access point in NMActivationResult

  -------------------------------------

	Driver Notification patch: notifies the user when their driver
		sucks.  Gives them the option to ignore further insertions
		of the card that has the sucky driver.

	* NetworkManager.h
		- Remove the SEMI_SUPPORTED member from the NMDriverSupportLevel
			enum and replace it with NO_CARRIER_DETECT and
			NO_WIRELESS_SCAN

	* panel-applet/NMWirelessApplet.[ch]
		- Merge essid.glade -> wireless-applet.glade
		- Implement the "Your driver sucks" notification dialog

	* panel-applet/NMWirelessAppletDbus.c
		- Change stuff from getSupportsCarrierDetect->getDriverSupportLevel
		- Grab hardware address for each device from NM too
		- Check whether the driver for each device sucks or not whenever
			a new device is noticed

	* panel-applet/NMWirelessAppletOtherNetworkDialog.c
		- Deal with stuff being in wireless-applet.glade now rather than essid.glade

	* src/NetworkManager.c
		- Fix a double-unref on device removal

	* src/NetworkManagerUtils.c
		- Set appropriate driver support level on a device that doesn't
			support scanning or carrier detection

	* src/nm-dbus-device.c
		- New "getHWAddress" dbus method on devices
		- getSupportsCarrierDetect -> getDriverSupportLevel


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@534 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
parent 4c4be4c1
2005-03-31 Dan Williams <dcbw@redhat.com>
Tighten up handling of wireless devices that don't support wireless
scanning (ie, Orinoco). Due to restructuring of code, these devices
hadn't been doing pseudo-scanning for a while either and would just
spin waiting for an access point. They are now manual devices where
the user must choose the access point from the menu every time. All
"allowed" access points are listed in the applet's menu regardless
of whether or not they can be seen by the card, since it can't scan
anyway.
* src/NetworkManager.c
- (nm_wireless_link_state_handle): new function, but only update
the "best" ap for non-scanning devices when its not activating,
and when no device is being forced on the card
- (nm_link_state_monitor): split wireless link state handling out
into separate function
* src/NetworkManagerDevice.c
- (nm_device_copy_allowed_to_dev_list): new function
- (nm_device_new): populate non-scanning cards' AP lists with
access points from the "allowed" list
- (nm_device_new): don't start a scanning timeout for devices that
can't scan
- (nm_device_activation_schedule_finish): new parameter, should be
the AP that failed to be connected to, pass it on to the
activation finish function in NetworkManagerPolicy.c
- (nm_device_activate_wireless): don't ever try to get a new AP
for non-scanning devices, just fail. The user must choose
a new access point manually.
- (nm_device_activate): grab the AP that failed connection and
pass it on
- (nm_device_update_best_ap): Clear the best AP if we don't have
a link to it, user must manually choose a new one
- (nm_device_do_pseudo_scan): remove function
- (nm_device_wireless_process_scan_results): remove bits for non-
scanning cards since they never get here
- (nm_device_wireless_scan): remove bits for non-scanning devices,
and fake the scan list for test devices a bit earlier
* src/NetworkManagerPolicy.c
- (nm_policy_activation_finish): use the failed_ap that we get
passed rather than getting the best_ap from the card, which
may have changed since we were scheduled
- (nm_policy_allowed_ap_list_update): for non-scanning devices,
update their scan list directly from the allowed list when
we get updates to the allowed list from NetworkManagerInfo
* src/NetworkManagerPolicy.h
- New member for failed access point in NMActivationResult
-------------------------------------
Driver Notification patch: notifies the user when their driver
sucks. Gives them the option to ignore further insertions
of the card that has the sucky driver.
* NetworkManager.h
- Remove the SEMI_SUPPORTED member from the NMDriverSupportLevel
enum and replace it with NO_CARRIER_DETECT and
NO_WIRELESS_SCAN
* panel-applet/NMWirelessApplet.[ch]
- Merge essid.glade -> wireless-applet.glade
- Implement the "Your driver sucks" notification dialog
* panel-applet/NMWirelessAppletDbus.c
- Change stuff from getSupportsCarrierDetect->getDriverSupportLevel
- Grab hardware address for each device from NM too
- Check whether the driver for each device sucks or not whenever
a new device is noticed
* panel-applet/NMWirelessAppletOtherNetworkDialog.c
- Deal with stuff being in wireless-applet.glade now rather than essid.glade
* src/NetworkManager.c
- Fix a double-unref on device removal
* src/NetworkManagerUtils.c
- Set appropriate driver support level on a device that doesn't
support scanning or carrier detection
* src/nm-dbus-device.c
- New "getHWAddress" dbus method on devices
- getSupportsCarrierDetect -> getDriverSupportLevel
2005-03-31 Dan Williams <dcbw@redhat.com>
* src/NetworkManagerDevice.c
......
......@@ -78,7 +78,8 @@ typedef enum NMEncKeyType
typedef enum NMDriverSupportLevel
{
NM_DRIVER_UNSUPPORTED = 0,
NM_DRIVER_SEMI_SUPPORTED,
NM_DRIVER_NO_CARRIER_DETECT,
NM_DRIVER_NO_WIRELESS_SCAN,
NM_DRIVER_FULLY_SUPPORTED
} NMDriverSupportLevel;
......
......@@ -8,7 +8,7 @@ INCLUDES = -I${top_srcdir} -I${top_srcdir}/utils
noinst_LTLIBRARIES = libnm_notification_applet.la
gladedir = $(datadir)/NetworkManagerNotification
glade_DATA = essid.glade
glade_DATA = wireless-applet.glade
libnm_notification_applet_la_CPPFLAGS = \
$(DBUS_CFLAGS) \
......
......@@ -58,6 +58,7 @@
#include "menu-info.h"
#define CFG_UPDATE_INTERVAL 1
#define NMWA_GCONF_PATH "/apps/NetworkManagerNotification"
/* Compat for GTK 2.4 and lower... */
#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
......@@ -175,6 +176,247 @@ void nmwa_about_cb (NMWirelessApplet *applet)
#endif
}
/*
* nmwa_driver_notify_get_ignored_list
*
* Return list of devices for which we are supposed to ignore driver
* notifications for from GConf.
*
*/
GSList *nmwa_driver_notify_get_ignored_list (NMWirelessApplet *applet)
{
char *key;
GConfValue *value;
GSList *mac_list = NULL;
g_return_val_if_fail (applet != NULL, NULL);
g_return_val_if_fail (applet->gconf_client != NULL, NULL);
/* Get current list of access point MAC addresses for this AP from GConf */
key = g_strdup_printf ("%s/non_notify_cards", NMWA_GCONF_PATH);
value = gconf_client_get (applet->gconf_client, key, NULL);
if (value && (value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (value) == GCONF_VALUE_STRING))
mac_list = gconf_client_get_list (applet->gconf_client, key, GCONF_VALUE_STRING, NULL);
if (value)
gconf_value_free (value);
g_free (key);
return (mac_list);
}
/*
* nmwa_driver_notify_is_device_ignored
*
* Look in GConf and determine whether or not we are supposed to
* ignore driver notifications for a particular device.
*
*/
gboolean nmwa_driver_notify_is_device_ignored (NMWirelessApplet *applet, NetworkDevice *dev)
{
gboolean found = FALSE;
GSList *mac_list = NULL;
GSList *elt;
g_return_val_if_fail (applet != NULL, TRUE);
g_return_val_if_fail (applet->gconf_client != NULL, TRUE);
g_return_val_if_fail (dev != NULL, TRUE);
g_return_val_if_fail (dev->addr != NULL, TRUE);
g_return_val_if_fail (strlen (dev->addr) > 0, TRUE);
mac_list = nmwa_driver_notify_get_ignored_list (applet);
/* Ensure that the MAC isn't already in the list */
for (elt = mac_list; elt; elt = g_slist_next (elt))
{
if (elt->data && !strcmp (dev->addr, elt->data))
{
found = TRUE;
break;
}
}
/* Free the list, since gconf_client_set_list deep-copies it */
g_slist_foreach (mac_list, (GFunc)g_free, NULL);
g_slist_free (mac_list);
return found;
}
/*
* nmwa_driver_notify_ignore_device
*
* Add a device's MAC address to the list of ones that we ignore
* in GConf. Stores user's pref for "Don't remind me".
*
*/
void nmwa_driver_notify_ignore_device (NMWirelessApplet *applet, NetworkDevice *dev)
{
gboolean found = FALSE;
GSList *new_mac_list = NULL;
GSList *elt;
g_return_if_fail (applet != NULL);
g_return_if_fail (applet->gconf_client != NULL);
g_return_if_fail (dev != NULL);
g_return_if_fail (dev->addr != NULL);
g_return_if_fail (strlen (dev->addr) > 0);
new_mac_list = nmwa_driver_notify_get_ignored_list (applet);
/* Ensure that the MAC isn't already in the list */
for (elt = new_mac_list; elt; elt = g_slist_next (elt))
{
if (elt->data && !strcmp (dev->addr, elt->data))
{
found = TRUE;
break;
}
}
/* Add the new MAC address to the end of the list */
if (!found)
{
char *key = g_strdup_printf ("%s/non_notify_cards", NMWA_GCONF_PATH);
new_mac_list = g_slist_append (new_mac_list, g_strdup (dev->addr));
gconf_client_set_list (applet->gconf_client, key, GCONF_VALUE_STRING, new_mac_list, NULL);
g_free (key);
}
/* Free the list, since gconf_client_set_list deep-copies it */
g_slist_foreach (new_mac_list, (GFunc)g_free, NULL);
g_slist_free (new_mac_list);
}
gboolean nmwa_driver_notify_dialog_delete_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
gtk_widget_destroy (widget);
return FALSE;
}
gboolean nmwa_driver_notify_dialog_destroy_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data);
NetworkDevice *dev;
g_return_val_if_fail (cb_data != NULL, FALSE);
g_return_val_if_fail (cb_data->xml != NULL, FALSE);
dev = cb_data->dev;
g_return_val_if_fail (dev != NULL, FALSE);
network_device_unref (dev);
g_object_unref (cb_data->xml);
g_free (cb_data);
return FALSE;
}
gboolean nmwa_driver_notify_ok_cb (GtkButton *button, gpointer user_data)
{
DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data);
NetworkDevice *dev;
NMWirelessApplet *applet;
GtkWidget *dialog;
GtkWidget *checkbox;
g_return_val_if_fail (cb_data != NULL, FALSE);
g_return_val_if_fail (cb_data->xml != NULL, FALSE);
dev = cb_data->dev;
g_return_val_if_fail (dev != NULL, FALSE);
applet = cb_data->applet;
g_return_val_if_fail (applet != NULL, FALSE);
checkbox = glade_xml_get_widget (cb_data->xml, "dont_remind_checkbox");
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox)))
nmwa_driver_notify_ignore_device (applet, dev);
dialog = glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog");
gtk_widget_destroy (dialog);
return FALSE;
}
/*
* nmwa_driver_notify
*
* Notify the user if there's some problem with the driver
* of a specific network device.
*
*/
gboolean nmwa_driver_notify (gpointer user_data)
{
DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data);
NetworkDevice *dev;
NMWirelessApplet *applet;
GtkDialog *dialog;
GtkLabel *label;
char *label_text = NULL;
GtkButton *button;
g_return_val_if_fail (cb_data != NULL, FALSE);
dev = cb_data->dev;
g_return_val_if_fail (dev != NULL, FALSE);
applet = cb_data->applet;
g_return_val_if_fail (applet != NULL, FALSE);
g_return_val_if_fail (applet->glade_file != NULL, FALSE);
/* If the user has already requested that we ignore notifications for
* this device, don't do anything.
*/
if (nmwa_driver_notify_is_device_ignored (applet, dev))
return FALSE;
cb_data->xml = glade_xml_new (applet->glade_file, "driver_sucks_dialog", NULL);
if (cb_data->xml == NULL)
{
show_warning_dialog (TRUE, _("The NetworkManager Applet could not find some required resources (the glade file was not found)."));
return FALSE;
}
dialog = GTK_DIALOG (glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog"));
g_signal_connect (G_OBJECT (dialog), "destroy-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_destroy_cb), cb_data);
g_signal_connect (G_OBJECT (dialog), "delete-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_delete_cb), cb_data);
label = GTK_LABEL (glade_xml_get_widget (cb_data->xml, "driver_sucks_label"));
if (dev->driver_support_level == NM_DRIVER_NO_WIRELESS_SCAN)
{
char *temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support wireless scanning."),
dev->hal_name, dev->nm_name);
label_text = g_strdup_printf (gtk_label_get_label (label), temp);
g_free (temp);
}
if (dev->driver_support_level == NM_DRIVER_NO_CARRIER_DETECT)
{
char *temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support link detection."),
dev->hal_name, dev->nm_name);
label_text = g_strdup_printf (gtk_label_get_label (label), temp);
g_free (temp);
}
if (label_text)
gtk_label_set_markup (label, label_text);
button = GTK_BUTTON (glade_xml_get_widget (cb_data->xml, "ok_button"));
g_signal_connect (G_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (nmwa_driver_notify_ok_cb), cb_data);
gtk_widget_show_all (GTK_WIDGET (dialog));
return (FALSE);
}
/*
* nmwa_update_network_state
......@@ -1274,6 +1516,14 @@ static void nmwa_setup_widgets (NMWirelessApplet *applet)
applet->context_menu = nmwa_context_menu_create (applet);
applet->encryption_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
applet->glade_file = g_build_filename (GLADEDIR, "wireless-applet.glade", NULL);
if (!applet->glade_file || !g_file_test (applet->glade_file, G_FILE_TEST_IS_REGULAR))
{
show_warning_dialog (TRUE, _("The NetworkManager Applet could not find some required resources (the glade file was not found)."));
g_free (applet->glade_file);
applet->glade_file = NULL;
}
}
......@@ -1307,6 +1557,8 @@ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data)
nmwa_free_gui_data_model (applet);
nmwa_free_dbus_data_model (applet);
g_free (applet->glade_file);
}
......
......@@ -32,6 +32,7 @@
#else
#include "eggtrayicon.h"
#endif
#include <net/ethernet.h>
typedef enum
{
......@@ -70,7 +71,8 @@ typedef struct
char *nm_device;
int type;
gboolean link;
gboolean supports_carrier_detect;
guint32 driver_support_level;
char *addr;
char *nm_name;
char *hal_name;
char *udi;
......@@ -78,8 +80,6 @@ typedef struct
GSList *networks;
} NetworkDevice;
#ifdef BUILD_NOTIFICATION_ICON
#define NM_TYPE_WIRELESS_APPLET (nmwa_get_type())
......@@ -107,8 +107,10 @@ typedef struct
DBusConnection *connection;
GConfClient *gconf_client;
GladeXML *ui_resources;
char *glade_file;
guint redraw_timeout_id;
/* dbus thread stuff */
GThread *dbus_thread;
GMainContext *thread_context;
GMainLoop *thread_loop;
......@@ -163,11 +165,18 @@ typedef struct
} NMWirelessApplet;
typedef struct
{
NMWirelessApplet *applet;
NetworkDevice *dev;
GladeXML *xml;
} DriverNotifyCBData;
NetworkDevice *nmwa_get_device_for_nm_device (GSList *dev_list, const char *nm_dev);
WirelessNetwork *nmwa_get_net_for_nm_net (NetworkDevice *dev, const char *net_path);
WirelessNetwork *nmwa_get_net_by_essid (NetworkDevice *dev, const char *essid);
NMWirelessApplet *nmwa_new (void);
void show_warning_dialog (gboolean error, gchar *mesg, ...);
gboolean nmwa_driver_notify (gpointer user_data);
#endif
......@@ -34,6 +34,24 @@
#define DBUS_NO_SERVICE_ERROR "org.freedesktop.DBus.Error.ServiceDoesNotExist"
/*
* nm_null_safe_strcmp
*
* Doesn't freaking segfault if s1/s2 are NULL
*
*/
int nm_null_safe_strcmp (const char *s1, const char *s2)
{
if (!s1 && !s2)
return 0;
if (!s1 && s2)
return -1;
if (s1 && !s2)
return 1;
return (strcmp (s1, s2));
}
/* FIXME: This just seems like a bad idea. The call_nm_method function
* interface should just be changed to handle arrays better.
......@@ -302,7 +320,7 @@ static gboolean nmwa_dbus_get_device_link_active (NMWirelessApplet *applet, char
break;
default:
break;
break;
}
return (link);
......@@ -310,17 +328,17 @@ static gboolean nmwa_dbus_get_device_link_active (NMWirelessApplet *applet, char
/*
* nmwa_dbus_get_device_supports_carrier_detect
* nmwa_dbus_get_device_driver_support_level
*
* Returns whether or not the device supports carrier detection.
*
*/
static gboolean nmwa_dbus_get_device_supports_carrier_detect (NMWirelessApplet *applet, char *net_path)
static gboolean nmwa_dbus_get_device_driver_support_level (NMWirelessApplet *applet, char *net_path)
{
gboolean supports_carrier_detect = FALSE;
guint32 driver_support_level = FALSE;
switch (nmwa_dbus_call_nm_method (applet->connection, net_path, "getSupportsCarrierDetect",
DBUS_TYPE_BOOLEAN, (void **)(&supports_carrier_detect), NULL))
switch (nmwa_dbus_call_nm_method (applet->connection, net_path, "getDriverSupportLevel",
DBUS_TYPE_UINT32, (void **)(&driver_support_level), NULL))
{
case (RETURN_NO_NM):
applet->applet_state = APPLET_STATE_NO_NM;
......@@ -330,7 +348,31 @@ static gboolean nmwa_dbus_get_device_supports_carrier_detect (NMWirelessApplet *
break;
}
return (supports_carrier_detect);
return (driver_support_level);
}
/*
* nmwa_dbus_get_hw_addr
*
* Return the hardware address of a given device
*
*/
static char * nmwa_dbus_get_hw_addr (NMWirelessApplet *applet, char *dev_path)
{
char *addr = NULL;
switch (nmwa_dbus_call_nm_method (applet->connection, dev_path, "getHWAddress", DBUS_TYPE_STRING, (void **)(&addr), NULL))
{
case (RETURN_NO_NM):
applet->applet_state = APPLET_STATE_NO_NM;
break;
default:
break;
}
return (addr);
}
......@@ -953,6 +995,7 @@ void network_device_unref (NetworkDevice *dev)
g_free (dev->nm_name);
g_free (dev->udi);
g_free (dev->hal_name);
g_free (dev->addr);
g_free (dev);
memset (dev, 0, sizeof (NetworkDevice));
}
......@@ -998,7 +1041,8 @@ NetworkDevice *network_device_copy (NetworkDevice *src)
dev->nm_device = g_strdup (src->nm_device);
dev->type = src->type;
dev->link = src->link;
dev->supports_carrier_detect = src->supports_carrier_detect;
dev->addr = g_strdup (src->addr);
dev->driver_support_level = src->driver_support_level;
dev->nm_name = g_strdup (src->nm_name);
dev->hal_name = g_strdup (src->hal_name);
dev->udi = g_strdup (src->udi);
......@@ -1231,6 +1275,10 @@ static gboolean nmwa_dbus_update_active_device_strength (gpointer user_data)
g_return_val_if_fail (user_data != NULL, FALSE);
applet = (NMWirelessApplet *)user_data;
if (applet->applet_state == APPLET_STATE_NO_NM)
return TRUE;
if (applet->gui_active_device && (applet->gui_active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET))
{
guint8 strength = nmwa_dbus_get_object_strength (applet, applet->gui_active_device->nm_device);
......@@ -1354,6 +1402,73 @@ static void nmwa_dbus_device_update_one_network (NMWirelessApplet *applet, DBusM
}
/*
* nmwa_dbus_schedule_driver_notification
*
* Schedule the driver notification routine to run in the main loop.
*
*/
void nmwa_dbus_schedule_driver_notification (NMWirelessApplet *applet, NetworkDevice *dev)
{
DriverNotifyCBData *cb_data;
g_return_if_fail (applet != NULL);
g_return_if_fail (dev != NULL);
cb_data = g_malloc0 (sizeof (DriverNotifyCBData));
cb_data->applet = applet;
cb_data->dev = dev;
g_idle_add (nmwa_driver_notify, (gpointer)cb_data);
}
/*
* nmwa_dbus_check_drivers
*
* If a device got added, we notify the user if the device's driver
* has any problems (no carrier detect, no wireless scanning, etc).
*
*/
void nmwa_dbus_check_drivers (NMWirelessApplet *applet)
{
GSList *elt;
g_return_if_fail (applet != NULL);
/* For every device that's in the dbus data model but not in
* the gui data model, signal the user.
*/
for (elt = applet->dbus_device_list; elt; elt = g_slist_next (elt))
{
NetworkDevice *dbus_dev = (NetworkDevice *)(elt->data);
GSList *elt2;
gboolean found = FALSE;
for (elt2 = applet->gui_device_list; elt2; elt2 = g_slist_next (elt2))
{
NetworkDevice *gui_dev = (NetworkDevice *)(elt2->data);
if ( !nm_null_safe_strcmp (dbus_dev->nm_device, gui_dev->nm_device)
&& !nm_null_safe_strcmp (dbus_dev->addr, gui_dev->addr)