static void
dump_device (NMDevice *device)
{
	const char *str;
	NMDeviceState state;

	str = nm_device_get_iface (device);
	g_print ("Interface: %s\n", str);

	str = nm_device_get_udi (device);
	g_print ("Udi: %s\n", str);

	str = nm_device_get_driver (device);
	g_print ("Driver: %s\n", str);

	str = nm_device_get_vendor (device);
	g_print ("Vendor: %s\n", str);

	str = nm_device_get_product (device);
	g_print ("Product: %s\n", str);

	state = nm_device_get_state (device);
	g_print ("State: %d\n", state);

	if (state == NM_DEVICE_STATE_ACTIVATED)
		dump_ip4_config (nm_device_get_ip4_config (device));

	if (NM_IS_DEVICE_ETHERNET (device))
		dump_wired (NM_DEVICE_ETHERNET (device));
	else if (NM_IS_DEVICE_WIFI (device))
		dump_wireless (NM_DEVICE_WIFI (device));

	dump_dhcp4_config (nm_device_get_dhcp4_config (device));
}
static void
show_active_connection_device (gpointer data, gpointer user_data)
{
	NMDevice *device = NM_DEVICE (data);

	g_print ("           %s\n", nm_device_get_udi (device));
}
static void
get_property (GObject *object,
              guint prop_id,
              GValue *value,
              GParamSpec *pspec)
{
	NMDevice *device = NM_DEVICE (object);

	switch (prop_id) {
	case PROP_UDI:
		g_value_set_string (value, nm_device_get_udi (device));
		break;
	case PROP_INTERFACE:
		g_value_set_string (value, nm_device_get_iface (device));
		break;
	case PROP_DRIVER:
		g_value_set_string (value, nm_device_get_driver (device));
		break;
	case PROP_CAPABILITIES:
		g_value_set_uint (value, nm_device_get_capabilities (device));
		break;
	case PROP_MANAGED:
		g_value_set_boolean (value, nm_device_get_managed (device));
		break;
	case PROP_IP4_CONFIG:
		g_value_set_object (value, nm_device_get_ip4_config (device));
		break;
	case PROP_DHCP4_CONFIG:
		g_value_set_object (value, nm_device_get_dhcp4_config (device));
		break;
	case PROP_IP6_CONFIG:
		g_value_set_object (value, nm_device_get_ip6_config (device));
		break;
	case PROP_STATE:
		g_value_set_uint (value, nm_device_get_state (device));
		break;
	case PROP_PRODUCT:
		g_value_set_string (value, nm_device_get_product (device));
		break;
	case PROP_VENDOR:
		g_value_set_string (value, nm_device_get_vendor (device));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
show_generic_info (NMDevice * device)
{
	const char *ifname, *uid, *driver;
	gboolean managed;
	NMDeviceState state;
	NMIP4Config * ip4;
	NMIP6Config * ip6;

	g_return_if_fail (NM_IS_DEVICE (device));

	ifname = nm_device_get_iface (device);
	managed = nm_device_get_managed (device);

	if (managed) {
		state = nm_device_get_state (device);
		ip4 = nm_device_get_ip4_config (device);
		ip6 = nm_device_get_ip6_config (device);
		driver = nm_device_get_driver (device);
		uid = nm_device_get_udi (device);

		//TODO: show active connection name
		g_print("%-9s State:%s  Connection:%s\n", ifname, device_state_to_string(state), "Not implemented");

		print_ip4_info (ip4);

		print_ip6_info (ip6);

		if (driver || uid) {
			g_print("%-9s ", "");
			if (driver)
				g_print("Driver:%s  ", driver);
			if (uid)
				g_print("UID:%s", uid);
			g_print ("\n");
		}

	}
	else {
		g_print("%-9s Device is not managed by NetworkManager\n", ifname);
	}
}
static void
active_connections_changed (NMClient *client, GParamSpec *pspec, gpointer user_data)
{
	const GPtrArray *connections;
	int i, j;

	g_print ("Active connections changed:\n");
	connections = nm_client_get_active_connections (client);
	for (i = 0; connections && (i < connections->len); i++) {
		NMActiveConnection *connection;
		const GPtrArray *devices;

		connection = g_ptr_array_index (connections, i);
		g_print ("    %s\n", nm_object_get_path (NM_OBJECT (connection)));
		devices = nm_active_connection_get_devices (connection);
		for (j = 0; devices && j < devices->len; j++)
			g_print ("           %s\n", nm_device_get_udi (g_ptr_array_index (devices, j)));
		if (NM_IS_VPN_CONNECTION (connection))
			g_print ("           VPN base connection: %s\n", nm_active_connection_get_specific_object (connection));
	}
}
static void
cdma_device_added (NMDevice *device, NMApplet *applet)
{
	NMDeviceModem *modem = NM_DEVICE_MODEM (device);
	CdmaDeviceInfo *info;
	DBusGConnection *bus;
	const char *udi;
	GError *error = NULL;

	udi = nm_device_get_udi (device);
	if (!udi)
		return;

	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
	if (!bus) {
		g_warning ("%s: failed to connect to D-Bus: (%d) %s", __func__, error->code, error->message);
		g_clear_error (&error);
		return;
	}

	info = g_malloc0 (sizeof (CdmaDeviceInfo));
	info->applet = applet;
	info->device = device;
	info->bus = bus;
	info->quality_valid = FALSE;

	info->props_proxy = dbus_g_proxy_new_for_name (bus,
	                                               "org.freedesktop.ModemManager",
	                                               udi,
	                                               "org.freedesktop.DBus.Properties");
	if (!info->props_proxy) {
		g_message ("%s: failed to create D-Bus properties proxy.", __func__);
		cdma_device_info_free (info);
		return;
	}

	info->cdma_proxy = dbus_g_proxy_new_for_name (bus,
	                                              "org.freedesktop.ModemManager",
	                                              udi,
	                                              "org.freedesktop.ModemManager.Modem.Cdma");
	if (!info->cdma_proxy) {
		g_message ("%s: failed to create CDMA proxy.", __func__);
		cdma_device_info_free (info);
		return;
	}

	g_object_set_data_full (G_OBJECT (modem), "devinfo", info, cdma_device_info_free);

	/* Registration state change signal */
	dbus_g_object_register_marshaller (_nma_marshal_VOID__UINT_UINT,
	                                   G_TYPE_NONE,
	                                   G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
	dbus_g_proxy_add_signal (info->cdma_proxy, "RegistrationStateChanged",
	                         G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
	dbus_g_proxy_connect_signal (info->cdma_proxy, "RegistrationStateChanged",
	                             G_CALLBACK (reg_state_changed_cb), info, NULL);

	/* Signal quality change signal */
	dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__UINT,
	                                   G_TYPE_NONE, G_TYPE_UINT, G_TYPE_INVALID);
	dbus_g_proxy_add_signal (info->cdma_proxy, "SignalQuality", G_TYPE_UINT, G_TYPE_INVALID);
	dbus_g_proxy_connect_signal (info->cdma_proxy, "SignalQuality",
	                             G_CALLBACK (signal_quality_changed_cb), info, NULL);

	/* Modem property change signal */
	dbus_g_object_register_marshaller (_nma_marshal_VOID__STRING_BOXED,
	                                   G_TYPE_NONE, G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT,
	                                   G_TYPE_INVALID);
	dbus_g_proxy_add_signal (info->props_proxy, "MmPropertiesChanged",
	                         G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
	dbus_g_proxy_connect_signal (info->props_proxy, "MmPropertiesChanged",
	                             G_CALLBACK (modem_properties_changed),
	                             info, NULL);

	/* Ask whether the device is enabled */
	dbus_g_proxy_begin_call (info->props_proxy, "Get",
	                         enabled_reply, info, NULL,
	                         G_TYPE_STRING, MM_OLD_DBUS_INTERFACE_MODEM,
	                         G_TYPE_STRING, "Enabled",
	                         G_TYPE_INVALID);
}
static NMActStageReturn
real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
{
	NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
	NMActRequest *req;
	NMDBusManager *dbus_mgr;
	DBusGConnection *g_connection;
	gboolean dun = FALSE;

	req = nm_device_get_act_request (device);
	g_assert (req);

	priv->bt_type = get_connection_bt_type (nm_act_request_get_connection (req));
	if (priv->bt_type == NM_BT_CAPABILITY_NONE) {
		// FIXME: set a reason code
		return NM_ACT_STAGE_RETURN_FAILURE;
	}

	dbus_mgr = nm_dbus_manager_get ();
	g_connection = nm_dbus_manager_get_connection (dbus_mgr);
	g_object_unref (dbus_mgr);

	if (priv->bt_type == NM_BT_CAPABILITY_DUN)
		dun = TRUE;
	else if (priv->bt_type == NM_BT_CAPABILITY_NAP)
		dun = FALSE;
	else
		g_assert_not_reached ();

	priv->dev_proxy = dbus_g_proxy_new_for_name (g_connection,
	                                               BLUEZ_SERVICE,
	                                               nm_device_get_udi (device),
	                                               BLUEZ_DEVICE_INTERFACE);
	if (!priv->dev_proxy) {
		// FIXME: set a reason code
		return NM_ACT_STAGE_RETURN_FAILURE;
	}

	/* Watch for BT device property changes */
	dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED,
	                                   G_TYPE_NONE,
	                                   G_TYPE_STRING, G_TYPE_VALUE,
	                                   G_TYPE_INVALID);
	dbus_g_proxy_add_signal (priv->dev_proxy, "PropertyChanged",
	                         G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
	dbus_g_proxy_connect_signal (priv->dev_proxy, "PropertyChanged",
	                             G_CALLBACK (bluez_property_changed), device, NULL);

	priv->type_proxy = dbus_g_proxy_new_for_name (g_connection,
	                                              BLUEZ_SERVICE,
	                                              nm_device_get_udi (device),
	                                              dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE);
	if (!priv->type_proxy) {
		// FIXME: set a reason code
		return NM_ACT_STAGE_RETURN_FAILURE;
	}

	nm_log_dbg (LOGD_BT, "(%s): requesting connection to the device",
	            nm_device_get_iface (device));

	/* Connect to the BT device */
	dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect",
	                                      bluez_connect_cb,
	                                      device,
	                                      NULL,
	                                      20000,
	                                      G_TYPE_STRING, dun ? BLUETOOTH_DUN_UUID : BLUETOOTH_NAP_UUID,
	                                      G_TYPE_INVALID);

	if (priv->timeout_id)
		g_source_remove (priv->timeout_id);
	priv->timeout_id = g_timeout_add_seconds (30, bt_connect_timeout, device);

	return NM_ACT_STAGE_RETURN_POSTPONE;
}