static gint
sort_nsps (gconstpointer a, gconstpointer b)
{
	const char *name_a = NULL, *name_b = NULL;

	if (a)
		name_a = nm_wimax_nsp_get_name (NM_WIMAX_NSP (a));
	if (b)
		name_b = nm_wimax_nsp_get_name (NM_WIMAX_NSP (b));

	return g_strcmp0 (name_a, name_b);
}
static NMActStageReturn
real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
	NMActRequest *req;
	GSList *iter;
	const char *path;

	clear_link_timeout (NM_DEVICE_WIMAX (device));

	req = nm_device_get_act_request (device);
	if (!req)
		goto err;

	path = nm_act_request_get_specific_object (req);
	if (!path)
		goto err;

	for (iter = priv->nsp_list; iter; iter = iter->next) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);

		if (!strcmp (path, nm_wimax_nsp_get_dbus_path (nsp))) {
			set_current_nsp (NM_DEVICE_WIMAX (device), nsp);
			return NM_ACT_STAGE_RETURN_SUCCESS;
		}
	}

 err:
	*reason = NM_DEVICE_STATE_REASON_NONE;
	return NM_ACT_STAGE_RETURN_FAILURE;
}
Ejemplo n.º 3
0
static void
get_property (GObject *object,
              guint prop_id,
              GValue *value,
              GParamSpec *pspec)
{
	NMWimaxNsp *nsp = NM_WIMAX_NSP (object);

	_nm_object_ensure_inited (NM_OBJECT (object));

	switch (prop_id) {
	case PROP_NAME:
		g_value_set_string (value, nm_wimax_nsp_get_name (nsp));
		break;
	case PROP_SIGNAL_QUALITY:
		g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (nsp));
		break;
	case PROP_NETWORK_TYPE:
		g_value_set_uint (value, nm_wimax_nsp_get_network_type (nsp));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
Ejemplo n.º 4
0
static void
clean_up_nsps (NMDeviceWimax *self, gboolean notify)
{
	NMDeviceWimaxPrivate *priv;

	g_return_if_fail (NM_IS_DEVICE_WIMAX (self));

	priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);

	if (priv->active_nsp) {
		g_object_unref (priv->active_nsp);
		priv->active_nsp = NULL;
	}

	if (priv->nsps) {
		while (priv->nsps->len) {
			NMWimaxNsp *nsp = NM_WIMAX_NSP (g_ptr_array_index (priv->nsps, 0));

			if (notify)
				g_signal_emit (self, signals[NSP_REMOVED], 0, nsp);
			g_ptr_array_remove (priv->nsps, nsp);
			g_object_unref (nsp);
		}
		g_ptr_array_free (priv->nsps, TRUE);
		priv->nsps = NULL;
	}
}
Ejemplo n.º 5
0
NMWimaxNsp *
nm_wimax_nsp_new (const char *name)
{
	g_return_val_if_fail (name != NULL, NULL);

	return NM_WIMAX_NSP (g_object_new (NM_TYPE_WIMAX_NSP,
									   NM_WIMAX_NSP_NAME, name,
									   NULL));
}
Ejemplo n.º 6
0
static void
constructed (GObject *object)
{
	NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object);

	G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructed (object);

	priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_WIMAX_NSP);
	register_properties (NM_WIMAX_NSP (object));
}
Ejemplo n.º 7
0
static gboolean
impl_device_get_nsp_list (NMDeviceWimax *self, GPtrArray **nsps, GError **error)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	GSList *iter;

	*nsps = g_ptr_array_sized_new (4);
	for (iter = priv->nsp_list; iter; iter = iter->next)
		g_ptr_array_add (*nsps, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data))));

	return TRUE;
}
Ejemplo n.º 8
0
static void
remove_outdated_nsps (NMDeviceWimax *self,
					  WIMAX_API_NSP_INFO_EX *nsp_list,
					  guint32 list_size)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	GSList *iter;
	GSList *to_remove = NULL;

	for (iter = priv->nsp_list; iter; iter = iter->next) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
		gboolean found = FALSE;
		int i;

		for (i = 0; i < list_size; i++) {
			WIMAX_API_NSP_INFO_EX *info = &nsp_list[i];

			if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), (char *) info->NSPName)) {
				found = TRUE;
				break;
			}
		}

		if (!found)
			to_remove = g_slist_prepend (to_remove, nsp);
	}

	for (iter = to_remove; iter; iter = iter->next) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);

		emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE);
		priv->nsp_list = g_slist_remove (priv->nsp_list, nsp);
		g_object_unref (nsp);
	}

	if (g_slist_length(to_remove) > 0)
	    nm_device_recheck_available_connections (NM_DEVICE (self));

	g_slist_free (to_remove);
}
static NMWimaxNsp *
get_nsp_by_name (NMDeviceWimax *self, const char *name)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	GSList *iter;

	for (iter = priv->nsp_list; iter; iter = iter->next) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);

		if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), name))
			return nsp;
	}

	return NULL;
}
static void
remove_all_nsps (NMDeviceWimax *self)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);

	while (g_slist_length (priv->nsp_list)) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data);

		priv->nsp_list = g_slist_remove (priv->nsp_list, nsp);
		g_signal_emit (self, signals[NSP_REMOVED], 0, nsp);
		g_object_unref (nsp);
	}

	g_slist_free (priv->nsp_list);
	priv->nsp_list = NULL;
}
Ejemplo n.º 11
0
static NMActStageReturn
act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
	NMActRequest *req;
	GSList *iter;
	const char *path;
	NMWimaxNsp *nsp = NULL;

	clear_link_timeout (NM_DEVICE_WIMAX (device));

	*reason = NM_DEVICE_STATE_REASON_NONE;

	req = nm_device_get_act_request (device);
	if (!req)
		return NM_ACT_STAGE_RETURN_FAILURE;

	path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req));
	if (!path)
		return NM_ACT_STAGE_RETURN_FAILURE;

	/* Find the NSP in the scan list */
	for (iter = priv->nsp_list; iter; iter = iter->next) {
		NMWimaxNsp *candidate = NM_WIMAX_NSP (iter->data);

		if (!strcmp (path, nm_wimax_nsp_get_dbus_path (candidate))) {
			nsp = candidate;
			break;
		}
	}

	/* Couldn't find the NSP for some reason */
	if (nsp == NULL)
		return NM_ACT_STAGE_RETURN_FAILURE;

	set_current_nsp (NM_DEVICE_WIMAX (device), nsp);

	priv->prepare_done = TRUE;

	/* If the device is scanning, it won't connect, so we have to wait until
	 * it's not scanning to proceed to stage 2.
	 */
	if (priv->status == WIMAX_API_DEVICE_STATUS_Scanning)
		return NM_ACT_STAGE_RETURN_POSTPONE;

	return NM_ACT_STAGE_RETURN_SUCCESS;
}
Ejemplo n.º 12
0
static NMWimaxNsp *
get_nsp_by_path (NMDeviceWimax *self, const char *path)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	GSList *iter;

	g_return_val_if_fail (path, NULL);

	for (iter = priv->nsp_list; iter; iter = iter->next) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);

		if (!strcmp (nm_wimax_nsp_get_dbus_path (nsp), path))
			return nsp;
	}

	return NULL;
}
Ejemplo n.º 13
0
static void
remove_all_nsps (NMDeviceWimax *self)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);

	set_current_nsp (self, NULL);

	while (priv->nsp_list) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data);

		priv->nsp_list = g_slist_remove (priv->nsp_list, nsp);
		emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE);
		g_object_unref (nsp);
	}

	nm_device_recheck_available_connections (NM_DEVICE (self));
}
static NMConnection *
real_get_best_auto_connection (NMDevice *device,
                               GSList *connections,
                               char **specific_object)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
	GSList *iter;

	for (iter = connections; iter; iter = g_slist_next (iter)) {
		NMConnection *connection = NM_CONNECTION (iter->data);
		NMSettingConnection *s_con;
		NMSettingWimax *s_wimax;
		const char *connection_type;
		const GByteArray *mac;

		s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
		g_assert (s_con);

		if (!nm_setting_connection_get_autoconnect (s_con))
			continue;

		connection_type = nm_setting_connection_get_connection_type (s_con);
		if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME))
			continue;

		s_wimax = (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
		if (!s_wimax)
			continue;

		mac = nm_setting_wimax_get_mac_address (s_wimax);
		if (mac && memcmp (mac->data, priv->hw_addr.ether_addr_octet, ETH_ALEN))
			continue;

		for (iter = priv->nsp_list; iter; iter = iter->next) {
			NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);

			if (nm_wimax_nsp_check_compatible (nsp, connection)) {
				*specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp);
				return connection;
			}
		}
	}

	return NULL;
}
Ejemplo n.º 15
0
static void
get_property (GObject *object, guint prop_id,
			  GValue *value, GParamSpec *pspec)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (object);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	GPtrArray *array;
	GSList *iter;

	switch (prop_id) {
	case PROP_NSPS:
		array = g_ptr_array_sized_new (4);
		for (iter = priv->nsp_list; iter; iter = g_slist_next (iter))
			g_ptr_array_add (array, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data))));
		g_value_take_boxed (value, array);
		break;
	case PROP_ACTIVE_NSP:
		if (priv->current_nsp)
			g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp));
		else
			g_value_set_boxed (value, "/");
		break;
	case PROP_CENTER_FREQ:
		g_value_set_uint (value, priv->center_freq);
		break;
	case PROP_RSSI:
		g_value_set_int (value, priv->rssi);
		break;
	case PROP_CINR:
		g_value_set_int (value, priv->cinr);
		break;
	case PROP_TX_POWER:
		g_value_set_int (value, priv->tx_power);
		break;
	case PROP_BSID:
		g_value_set_string (value, priv->bsid);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
Ejemplo n.º 16
0
static gboolean
can_auto_connect (NMDevice *device,
                  NMConnection *connection,
                  char **specific_object)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
	GSList *iter;

	if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->can_auto_connect (device, connection, specific_object))
		return FALSE;

	for (iter = priv->nsp_list; iter; iter = iter->next) {
		NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);

		if (nm_wimax_nsp_check_compatible (nsp, connection)) {
			*specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp);
			return TRUE;
		}
	}

	return FALSE;
}
Ejemplo n.º 17
0
static gboolean
check_connection_available (NMDevice *device,
                            NMConnection *connection,
                            const char *specific_object)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
	const GSList *ns_iter = NULL;
	NMWimaxNsp *nsp;

	if (specific_object) {
		nsp = get_nsp_by_path (NM_DEVICE_WIMAX (device), specific_object);
		return nsp ? nm_wimax_nsp_check_compatible (nsp, connection) : FALSE;
	}

	/* Ensure the connection applies to an NSP in the scan list */
	for (ns_iter = priv->nsp_list; ns_iter; ns_iter = ns_iter->next) {
		if (nm_wimax_nsp_check_compatible (NM_WIMAX_NSP (ns_iter->data), connection))
			return TRUE;
	}

	return FALSE;
}
Ejemplo n.º 18
0
static void
detail_nsp (gpointer data, gpointer user_data)
{
	NMWimaxNsp *nsp = NM_WIMAX_NSP (data);
	const char *active_name = (const char *) user_data;
	const char *name;
	char *label;
	char *data_str;
	gboolean active = FALSE;

	name = nm_wimax_nsp_get_name (nsp);

	if (active_name)
		active = g_strcmp0 (active_name, name) == 0;

	label = g_strdup_printf ("  %s%s", active ? "*" : "", name);
	data_str = g_strdup_printf ("%d%% (%s)",
				    nm_wimax_nsp_get_signal_quality (nsp),
				    wimax_network_type_to_str (nm_wimax_nsp_get_network_type (nsp)));

	print_string (label, data_str);
	g_free (label);
	g_free (data_str);
}
Ejemplo n.º 19
0
static gboolean
real_complete_connection (NMDevice *device,
                          NMConnection *connection,
                          const char *specific_object,
                          const GSList *existing_connections,
                          GError **error)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (device);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	NMSettingWimax *s_wimax;
	const GByteArray *setting_mac;
	char *format;
	const char *nsp_name = NULL;
	NMWimaxNsp *nsp = NULL;
	GSList *iter;

	s_wimax = nm_connection_get_setting_wimax (connection);

	if (!specific_object) {
		/* If not given a specific object, we need at minimum an NSP name */
		if (!s_wimax) {
			g_set_error_literal (error,
			                     NM_WIMAX_ERROR,
			                     NM_WIMAX_ERROR_CONNECTION_INVALID,
			                     "A 'wimax' setting is required if no NSP path was given.");
			return FALSE;
		}

		nsp_name = nm_setting_wimax_get_network_name (s_wimax);
		if (!nsp_name || !strlen (nsp_name)) {
			g_set_error_literal (error,
			                     NM_WIMAX_ERROR,
			                     NM_WIMAX_ERROR_CONNECTION_INVALID,
			                     "A 'wimax' setting with a valid network name is required if no NSP path was given.");
			return FALSE;
		}

		/* Find a compatible NSP in the list */
		nsp = get_nsp_by_name (self, nsp_name);

		/* If we still don't have an NSP, then the WiMAX settings needs to be
		 * fully specified by the client.  Might not be able to find the NSP
		 * if the scan didn't find the NSP yet.
		 */
		if (!nsp) {
			if (!nm_setting_verify (NM_SETTING (s_wimax), NULL, error))
				return FALSE;
		}
	} else {
		/* Find a compatible NSP in the list */
		for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) {
			if (!strcmp (specific_object, nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))) {
				nsp = NM_WIMAX_NSP (iter->data);
				break;
			}
		}

		if (!nsp) {
			g_set_error (error,
			             NM_WIMAX_ERROR,
			             NM_WIMAX_ERROR_NSP_NOT_FOUND,
			             "The NSP %s was not in the scan list.",
			             specific_object);
			return FALSE;
		}

		nsp_name = nm_wimax_nsp_get_name (nsp);
	}

	/* Add a WiMAX setting if one doesn't exist */
	if (!s_wimax) {
		s_wimax = (NMSettingWimax *) nm_setting_wimax_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_wimax));
	}

	g_assert (nsp_name);
	format = g_strdup_printf ("%s %%d", nsp_name);
	nm_utils_complete_generic (connection,
	                           NM_SETTING_WIMAX_SETTING_NAME,
	                           existing_connections,
	                           format,
	                           nsp_name,
	                           TRUE);
	g_free (format);
	g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_NETWORK_NAME, nsp_name, NULL);

	setting_mac = nm_setting_wimax_get_mac_address (s_wimax);
	if (setting_mac) {
		/* Make sure the setting MAC (if any) matches the device's permanent MAC */
		if (memcmp (setting_mac->data, &priv->hw_addr.ether_addr_octet, ETH_ALEN)) {
			g_set_error (error,
				         NM_SETTING_WIMAX_ERROR,
				         NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY,
				         NM_SETTING_WIMAX_MAC_ADDRESS);
			return FALSE;
		}
	} else {
		GByteArray *mac;
		const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };

		/* Lock the connection to this device by default */
		if (memcmp (&priv->hw_addr.ether_addr_octet, null_mac, ETH_ALEN)) {
			mac = g_byte_array_sized_new (ETH_ALEN);
			g_byte_array_append (mac, priv->hw_addr.ether_addr_octet, ETH_ALEN);
			g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_MAC_ADDRESS, mac, NULL);
			g_byte_array_free (mac, TRUE);
		}
	}

	return TRUE;
}
Ejemplo n.º 20
0
static gboolean
complete_connection (NMDevice *device,
                     NMConnection *connection,
                     const char *specific_object,
                     const GSList *existing_connections,
                     GError **error)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (device);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	NMSettingWimax *s_wimax;
	const char *setting_mac;
	const char *hw_address;
	const char *nsp_name = NULL;
	NMWimaxNsp *nsp = NULL;
	GSList *iter;

	s_wimax = nm_connection_get_setting_wimax (connection);

	if (!specific_object) {
		/* If not given a specific object, we need at minimum an NSP name */
		if (!s_wimax) {
			g_set_error_literal (error,
			                     NM_DEVICE_ERROR,
			                     NM_DEVICE_ERROR_INVALID_CONNECTION,
			                     "A 'wimax' setting is required if no NSP path was given.");
			return FALSE;
		}

		nsp_name = nm_setting_wimax_get_network_name (s_wimax);
		if (!nsp_name || !strlen (nsp_name)) {
			g_set_error_literal (error,
			                     NM_DEVICE_ERROR,
			                     NM_DEVICE_ERROR_INVALID_CONNECTION,
			                     "A 'wimax' setting with a valid network name is required if no NSP path was given.");
			return FALSE;
		}

		/* Find a compatible NSP in the list */
		nsp = get_nsp_by_name (self, nsp_name);

		/* If we still don't have an NSP, then the WiMAX settings needs to be
		 * fully specified by the client.  Might not be able to find the NSP
		 * if the scan didn't find the NSP yet.
		 */
		if (!nsp) {
			if (!nm_setting_verify (NM_SETTING (s_wimax), NULL, error))
				return FALSE;
		}
	} else {
		/* Find a compatible NSP in the list */
		for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) {
			if (!strcmp (specific_object, nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))) {
				nsp = NM_WIMAX_NSP (iter->data);
				break;
			}
		}

		if (!nsp) {
			g_set_error (error,
			             NM_DEVICE_ERROR,
			             NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND,
			             "The NSP %s was not in the scan list.",
			             specific_object);
			return FALSE;
		}

		nsp_name = nm_wimax_nsp_get_name (nsp);
	}

	/* Add a WiMAX setting if one doesn't exist */
	if (!s_wimax) {
		s_wimax = (NMSettingWimax *) nm_setting_wimax_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_wimax));
	}

	g_assert (nsp_name);
	nm_utils_complete_generic (connection,
	                           NM_SETTING_WIMAX_SETTING_NAME,
	                           existing_connections,
	                           nsp_name,
	                           nsp_name,
	                           NULL,
	                           TRUE);
	g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_NETWORK_NAME, nsp_name, NULL);

	setting_mac = nm_setting_wimax_get_mac_address (s_wimax);
	hw_address = nm_device_get_hw_address (device);
	if (setting_mac) {
		/* Make sure the setting MAC (if any) matches the device's permanent MAC */
		if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) {
			g_set_error_literal (error,
			                     NM_CONNECTION_ERROR,
			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
			                     _("connection does not match device"));
			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_MAC_ADDRESS);
			return FALSE;
		}
	} else {
		/* Lock the connection to this device by default */
		if (!nm_utils_hwaddr_matches (hw_address, -1, NULL, ETH_ALEN))
			g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_MAC_ADDRESS, hw_address, NULL);
	}

	return TRUE;
}
static void
wimax_add_menu_item (NMDevice *device,
                     guint32 n_devices,
                     NMConnection *active,
                     GtkWidget *menu,
                     NMApplet *applet)
{
	NMDeviceWimax *wimax = NM_DEVICE_WIMAX (device);
	char *text;
	GtkWidget *item;
	GSList *connections, *all, *iter, *sorted = NULL;
	const GPtrArray *nsps;
	NMWimaxNsp *active_nsp = NULL;
	gboolean wimax_enabled, wimax_hw_enabled;
	int i;

	nsps = nm_device_wimax_get_nsps (wimax);

	if (n_devices > 1) {
		const char *desc;

		desc = nma_utils_get_device_description (device);
		text = g_strdup_printf (_("WiMAX Mobile Broadband (%s)"), desc);
	} else {
		text = g_strdup (_("WiMAX Mobile Broadband"));
	}

	item = applet_menu_item_create_device_item_helper (device, applet, text);
	gtk_widget_set_sensitive (item, FALSE);
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	gtk_widget_show (item);
	g_free (text);

	/* Add the active NSP if we're connected to something and the device is available */
	if (!nma_menu_device_check_unusable (device)) {
		active_nsp = nm_device_wimax_get_active_nsp (wimax);
		if (active_nsp) {
			item = new_nsp_menu_item (wimax, active, TRUE, active_nsp, applet);
			if (item) {
				gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
				gtk_widget_show (item);
			}
		}
	}

	/* Notify user of unmanaged or unavailable device */
	wimax_enabled = nm_client_wimax_get_enabled (applet->nm_client);
	wimax_hw_enabled = nm_client_wimax_hardware_get_enabled (applet->nm_client);
	item = nma_menu_device_get_menu_item (device, applet,
	                                      wimax_hw_enabled ?
	                                          (wimax_enabled ? NULL : _("WiMAX is disabled")) :
	                                          _("WiMAX is disabled by hardware switch"));
	if (item) {
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
		gtk_widget_show (item);
	}

	/* If disabled or rfkilled or whatever, nothing left to do */
	if (nma_menu_device_check_unusable (device))
		return;

	/* Create a sorted list of NSPs */
	for (i = 0; nsps && (i < nsps->len); i++) {
		NMWimaxNsp *nsp = g_ptr_array_index (nsps, i);

		if (nsp != active_nsp)
			sorted = g_slist_insert_sorted (sorted, nsp, sort_nsps);
	}

	if (g_slist_length (sorted)) {
		applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);

		all = applet_get_all_connections (applet);
		connections = nm_device_filter_connections (device, all);
		g_slist_free (all);

		/* And add menu items for each NSP */
		for (iter = sorted; iter; iter = g_slist_next (iter)) {
			NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
			NMConnection *connection = NULL;

			connection = get_connection_for_nsp (connections, nsp);
			item = new_nsp_menu_item (wimax, connection, FALSE, nsp, applet);
			if (item) {
				gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
				gtk_widget_show (item);
			}
		}

		g_slist_free (connections);
	}

	g_slist_free (sorted);
}