static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingConnection *s_con; NMSettingBluetooth *s_bt; const char *ctype; const GByteArray *mac; const char *hw_str; struct ether_addr *hw_mac; NMBluetoothCapabilities dev_caps; NMBluetoothCapabilities bt_type; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); ctype = nm_setting_connection_get_connection_type (s_con); if (strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME) != 0) { g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION, "The connection was not a Bluetooth connection."); return FALSE; } s_bt = nm_connection_get_setting_bluetooth (connection); if (!s_bt) { g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION, "The connection was not a valid Bluetooth connection."); return FALSE; } /* Check BT address */ hw_str = nm_device_bt_get_hw_address (NM_DEVICE_BT (device)); if (hw_str) { hw_mac = ether_aton (hw_str); if (!hw_mac) { g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC, "Invalid device MAC address."); return FALSE; } mac = nm_setting_bluetooth_get_bdaddr (s_bt); if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) { g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MAC_MISMATCH, "The MACs of the device and the connection didn't match."); return FALSE; } } dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device)); bt_type = get_connection_bt_type (connection); if (!(bt_type & dev_caps)) { g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS, "The device missed BT capabilities required by the connection."); return FALSE; } return TRUE; }
static void real_connection_secrets_updated (NMDevice *device, NMConnection *connection, GSList *updated_settings, RequestSecretsCaller caller) { NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMActRequest *req; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device))); req = nm_device_get_act_request (device); g_assert (req); if (!nm_modem_connection_secrets_updated (priv->modem, req, connection, updated_settings, caller)) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); return; } /* PPP handles stuff itself... */ if (caller == SECRETS_CALLER_PPP) return; /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */ g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); if (!modem_stage1 (self, priv->modem, &reason)) nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason); }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceBt *device = NM_DEVICE_BT (object); _nm_object_ensure_inited (NM_OBJECT (object)); switch (prop_id) { case PROP_HW_ADDRESS: g_value_set_string (value, nm_device_bt_get_hw_address (device)); break; case PROP_NAME: g_value_set_string (value, nm_device_bt_get_name (device)); break; case PROP_BT_CAPABILITIES: g_value_set_uint (value, nm_device_bt_get_capabilities (device)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void ppp_stats (NMModem *modem, guint32 in_bytes, guint32 out_bytes, gpointer user_data) { g_signal_emit (NM_DEVICE_BT (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes); }
static void bluez_property_changed (DBusGProxy *proxy, const char *property, GValue *value, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); gboolean connected; NMDeviceState state; const char *prop_str = "(unknown)"; if (G_VALUE_HOLDS_STRING (value)) prop_str = g_value_get_string (value); else if (G_VALUE_HOLDS_BOOLEAN (value)) prop_str = g_value_get_boolean (value) ? "true" : "false"; nm_log_dbg (LOGD_BT, "(%s): bluez property '%s' changed to '%s'", nm_device_get_iface (device), property, prop_str); if (strcmp (property, "Connected")) return; state = nm_device_get_state (device); connected = g_value_get_boolean (value); if (connected) { if (state == NM_DEVICE_STATE_CONFIG) { nm_log_dbg (LOGD_BT, "(%s): connected to the device", nm_device_get_iface (device)); priv->connected = TRUE; check_connect_continue (self); } } else { gboolean fail = FALSE; /* Bluez says we're disconnected from the device. Suck. */ if (nm_device_is_activating (device)) { nm_log_info (LOGD_BT, "Activation (%s/bluetooth): bluetooth link disconnected.", nm_device_get_iface (device)); fail = TRUE; } else if (state == NM_DEVICE_STATE_ACTIVATED) { nm_log_info (LOGD_BT, "(%s): bluetooth link disconnected.", nm_device_get_iface (device)); fail = TRUE; } if (fail) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CARRIER); priv->connected = FALSE; } } }
static void show_bt_specific_info (NMDevice * dev) { NMDeviceBt * device = NM_DEVICE_BT (dev); //TODO: implement device = device; g_print("%-9s Bluetooth specific info not yet implemented\n", ""); }
static const char * bt_get_hw_address (NMDeviceItem *item) { NMDeviceBt *device; device = NM_DEVICE_BT (nm_device_item_get_device (NM_DEVICE_ITEM (item))); return nm_device_bt_get_hw_address (device); }
static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingBluetooth *s_bt; const char *hw_addr, *setting_addr; NMBluetoothCapabilities dev_caps; NMBluetoothCapabilities bt_type; if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->connection_compatible (device, connection, error)) return FALSE; if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The connection was not a Bluetooth connection.")); return FALSE; } /* Check BT address */ hw_addr = nm_device_bt_get_hw_address (NM_DEVICE_BT (device)); if (hw_addr) { if (!nm_utils_hwaddr_valid (hw_addr, ETH_ALEN)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, _("Invalid device Bluetooth address.")); return FALSE; } s_bt = nm_connection_get_setting_bluetooth (connection); setting_addr = nm_setting_bluetooth_get_bdaddr (s_bt); if (setting_addr && !nm_utils_hwaddr_matches (setting_addr, -1, hw_addr, -1)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The Bluetooth addresses of the device and the connection didn't match.")); return FALSE; } } dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device)); bt_type = get_connection_bt_type (connection); if (!(bt_type & dev_caps)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The device is lacking Bluetooth capabilities required by the connection.")); return FALSE; } return TRUE; }
static void constructed (GObject *object) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object); priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE_BLUETOOTH); register_properties (NM_DEVICE_BT (object)); }
static gboolean modem_find_timeout (gpointer user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); NM_DEVICE_BT_GET_PRIVATE (self)->timeout_id = 0; nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND); return FALSE; }
static gboolean is_available (NMDevice *dev) { NMDeviceBt *self = NM_DEVICE_BT (dev); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); /* PAN doesn't need ModemManager, so devices that support it are always available */ if (priv->capabilities & NM_BT_CAPABILITY_NAP) return TRUE; /* DUN requires ModemManager */ return priv->mm_running; }
static gboolean bt_connect_timeout (gpointer user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); nm_log_dbg (LOGD_BT, "(%s): initial connection timed out", nm_device_get_iface (NM_DEVICE (self))); NM_DEVICE_BT_GET_PRIVATE (self)->timeout_id = 0; nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); return FALSE; }
static void constructed (GObject *object) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object); priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), NM_DBUS_SERVICE, nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_DEVICE_BLUETOOTH); register_properties (NM_DEVICE_BT (object)); }
static void bt_add_menu_item (NMDevice *device, guint32 n_devices, NMConnection *active, GtkWidget *menu, NMApplet *applet) { const char *text; GtkWidget *item; GSList *connections, *all; all = applet_get_all_connections (applet); connections = nm_device_filter_connections (device, all); g_slist_free (all); text = nm_device_bt_get_name (NM_DEVICE_BT (device)); if (!text) { text = utils_get_device_description (device); if (!text) text = nm_device_get_iface (device); g_assert (text); } 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); if (g_slist_length (connections)) add_connection_items (device, connections, active, ADD_ACTIVE, menu, applet); /* Notify user of unmanaged or unavailable device */ item = nma_menu_device_get_menu_item (device, applet, NULL); if (item) { gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } if (!nma_menu_device_check_unusable (device)) { /* Add menu items for existing bluetooth connections for this device */ if (g_slist_length (connections)) { applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1); add_connection_items (device, connections, active, ADD_INACTIVE, menu, applet); } } g_slist_free (connections); }
static void bluez_connect_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, void *user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); GError *error = NULL; char *device; if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_STRING, &device, G_TYPE_INVALID) == FALSE) { nm_log_warn (LOGD_BT, "Error connecting with bluez: %s", error && error->message ? error->message : "(unknown)"); g_clear_error (&error); nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); return; } if (!device || !strlen (device)) { nm_log_warn (LOGD_BT, "Invalid network device returned by bluez"); nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); } if (priv->bt_type == NM_BT_CAPABILITY_DUN) { g_free (priv->rfcomm_iface); priv->rfcomm_iface = device; } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { nm_device_set_ip_iface (NM_DEVICE (self), device); g_free (device); } nm_log_dbg (LOGD_BT, "(%s): connect request successful", nm_device_get_iface (NM_DEVICE (self))); /* Stage 3 gets scheduled when Bluez says we're connected */ priv->have_iface = TRUE; check_connect_continue (self); }
static void bt_added (NMItemProvider *provider, NMSettingsConnectionInterface *connection) { NMDeviceProvider *device_provider = NM_DEVICE_PROVIDER (provider); NMDevice *device; if (!nm_device_provider_ready (device_provider)) return; device = nm_device_provider_get_device (device_provider); if (utils_connection_valid_for_device (NM_CONNECTION (connection), device, NULL)) { NMListItem *item; item = nm_bt_item_new (nm_item_provider_get_client (provider), NM_DEVICE_BT (device), connection); nm_item_provider_item_added (provider, item); } }
static void modem_auth_result (NMModem *modem, GError *error, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; if (error) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); } else { /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */ g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); if (!modem_stage1 (NM_DEVICE_BT (device), priv->modem, &reason)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); } }
static void modem_need_auth (NMModem *modem, const char *setting_name, gboolean retry, RequestSecretsCaller caller, const char *hint1, const char *hint2, gpointer user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); NMActRequest *req; req = nm_device_get_act_request (NM_DEVICE (self)); g_assert (req); nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); nm_act_request_get_secrets (req, setting_name, retry, caller, hint1, hint2); }
static gboolean nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); if (NM_IS_DEVICE_ETHERNET (device)) return check_ethernet_compatible (NM_DEVICE_ETHERNET (device), connection, error); else if (NM_IS_DEVICE_WIFI (device)) return check_wifi_compatible (NM_DEVICE_WIFI (device), connection, error); else if (NM_IS_DEVICE_BT (device)) return check_bt_compatible (NM_DEVICE_BT (device), connection, error); // else if (NM_IS_DEVICE_OLPC_MESH (device)) // return check_olpc_mesh_compatible (NM_DEVICE_OLPC_MESH (device), connection, error); g_set_error (error, 0, 0, "unhandled device type '%s'", G_OBJECT_TYPE_NAME (device)); return FALSE; }
static void bt_add_menu_item (NMDevice *device, gboolean multiple__devices, const GPtrArray *connections, NMConnection *active, GtkWidget *menu, NMApplet *applet) { const char *text; GtkWidget *item; text = nm_device_bt_get_name (NM_DEVICE_BT (device)); if (!text) text = nm_device_get_description (device); 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); if (connections->len) applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_ACTIVE, menu, applet); /* Notify user of unmanaged or unavailable device */ item = nma_menu_device_get_menu_item (device, applet, NULL); if (item) { gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } if (!nma_menu_device_check_unusable (device)) { /* Add menu items for existing bluetooth connections for this device */ if (connections->len) { applet_menu_item_add_complex_separator_helper (menu, applet, _("Available")); applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_INACTIVE, menu, applet); } } }
static const char * get_hw_address (NMDevice *device) { return nm_device_bt_get_hw_address (NM_DEVICE_BT (device)); }