static void device_support_check_ready (MMPluginManager *plugin_manager, GAsyncResult *res, FindDeviceSupportContext *ctx) { GError *error = NULL; MMPlugin *plugin; /* Receive plugin result from the plugin manager */ plugin = mm_plugin_manager_device_support_check_finish (plugin_manager, res, &error); if (!plugin) { mm_info ("Couldn't check support for device at '%s': %s", mm_device_get_path (ctx->device), error->message); g_error_free (error); find_device_support_context_free (ctx); return; } /* Set the plugin as the one expected in the device */ mm_device_set_plugin (ctx->device, G_OBJECT (plugin)); g_object_unref (plugin); if (!mm_device_create_modem (ctx->device, ctx->self->priv->object_manager, &error)) { mm_warn ("Couldn't create modem for device at '%s': %s", mm_device_get_path (ctx->device), error->message); g_error_free (error); find_device_support_context_free (ctx); return; } /* Modem now created */ mm_info ("Modem for device at '%s' successfully created", mm_device_get_path (ctx->device)); find_device_support_context_free (ctx); }
static gboolean handle_set_profile (MmGdbusTest *skeleton, GDBusMethodInvocation *invocation, const gchar *id, const gchar *plugin_name, const gchar *const *ports, MMBaseManager *self) { MMPlugin *plugin; MMDevice *device; gchar *physdev; GError *error = NULL; mm_info ("Test profile set to: '%s'", id); /* Create device and keep it listed in the Manager */ physdev = g_strdup_printf ("/virtual/%s", id); device = mm_device_virtual_new (physdev, TRUE); g_hash_table_insert (self->priv->devices, physdev, device); /* Grab virtual ports */ mm_device_virtual_grab_ports (device, (const gchar **)ports); /* Set plugin to use */ plugin = mm_plugin_manager_peek_plugin (self->priv->plugin_manager, plugin_name); if (!plugin) { error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, "Requested plugin '%s' not found", plugin_name); mm_warn ("Couldn't set plugin for virtual device at '%s': %s", mm_device_get_path (device), error->message); goto out; } mm_device_set_plugin (device, G_OBJECT (plugin)); /* Create modem */ if (!mm_device_create_modem (device, self->priv->object_manager, &error)) { mm_warn ("Couldn't create modem for virtual device at '%s': %s", mm_device_get_path (device), error->message); goto out; } mm_info ("Modem for virtual device at '%s' successfully created", mm_device_get_path (device)); out: if (error) { mm_device_remove_modem (device); g_hash_table_remove (self->priv->devices, mm_device_get_path (device)); g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); } else mm_gdbus_test_complete_set_profile (skeleton, invocation); return TRUE; }
static void icera_disconnect_done (MMModem *modem, GError *error, gpointer user_data) { mm_info ("Modem signaled disconnection from the network"); }
static void device_removed (MMBaseManager *self, GUdevDevice *udev_device) { MMDevice *device; const gchar *subsys; const gchar *name; g_return_if_fail (udev_device != NULL); subsys = g_udev_device_get_subsystem (udev_device); name = g_udev_device_get_name (udev_device); if (!g_str_has_prefix (subsys, "usb") || (name && g_str_has_prefix (name, "cdc-wdm"))) { /* Handle tty/net/wdm port removal */ device = find_device_by_port (self, udev_device); if (device) { mm_info ("(%s/%s): released by modem %s", subsys, name, g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device))); mm_device_release_port (device, udev_device); /* If port probe list gets empty, remove the device object iself */ if (!mm_device_peek_port_probe_list (device)) { mm_dbg ("Removing empty device '%s'", mm_device_get_path (device)); if (mm_plugin_manager_device_support_check_cancel (self->priv->plugin_manager, device)) mm_dbg ("Device support check has been cancelled"); mm_device_remove_modem (device); g_hash_table_remove (self->priv->devices, mm_device_get_path (device)); } } return; } /* This case is designed to handle the case where, at least with kernel 2.6.31, unplugging * an in-use ttyACMx device results in udev generating remove events for the usb, but the * ttyACMx device (subsystem tty) is not removed, since it was in-use. So if we have not * found a modem for the port (above), we're going to look here to see if we have a modem * associated with the newly removed device. If so, we'll remove the modem, since the * device has been removed. That way, if the device is reinserted later, we'll go through * the process of exporting it. */ device = find_device_by_udev_device (self, udev_device); if (device) { mm_dbg ("Removing device '%s'", mm_device_get_path (device)); mm_device_remove_modem (device); g_hash_table_remove (self->priv->devices, mm_device_get_path (device)); return; } /* Maybe a plugin is checking whether or not the port is supported. * TODO: Cancel every possible supports check in this port. */ }
static gboolean quit_cb (gpointer user_data) { mm_info ("Caught signal, shutting down..."); if (manager) g_object_set (manager, MM_BASE_MANAGER_CONNECTION, NULL, NULL); if (loop) g_idle_add ((GSourceFunc) g_main_loop_quit, loop); else _exit (0); return FALSE; }
static void find_device_support_ready (MMPluginManager *plugin_manager, GAsyncResult *result, FindDeviceSupportContext *ctx) { GError *error = NULL; if (!mm_plugin_manager_find_device_support_finish (plugin_manager, result, &error)) { mm_info ("Couldn't find support for device at '%s': %s", mm_device_get_path (ctx->device), error->message); g_error_free (error); } else if (!mm_device_create_modem (ctx->device, ctx->self->priv->object_manager, &error)) { mm_warn ("Couldn't create modem for device at '%s': %s", mm_device_get_path (ctx->device), error->message); g_error_free (error); } else { mm_info ("Modem for device at '%s' successfully created", mm_device_get_path (ctx->device)); } find_device_support_context_free (ctx); }
static void device_removed (MMManager *manager, GUdevDevice *device) { MMBaseModem *modem; const char *subsys, *name; g_return_if_fail (device != NULL); subsys = g_udev_device_get_subsystem (device); name = g_udev_device_get_name (device); /* Ensure cached port probe infos get removed when the port is gone */ mm_port_probe_cache_remove (device); if (strcmp (subsys, "usb") != 0) { /* find_modem_for_port handles tty and net removal */ modem = find_modem_for_port (manager, subsys, name); if (modem) { mm_info ("(%s/%s): released by modem %s", subsys, name, mm_base_modem_get_device (modem)); mm_base_modem_release_port (modem, subsys, name); return; } } else { /* This case is designed to handle the case where, at least with kernel 2.6.31, unplugging * an in-use ttyACMx device results in udev generating remove events for the usb, but the * ttyACMx device (subsystem tty) is not removed, since it was in-use. So if we have not * found a modem for the port (above), we're going to look here to see if we have a modem * associated with the newly removed device. If so, we'll remove the modem, since the * device has been removed. That way, if the device is reinserted later, we'll go through * the process of exporting it. */ const char *sysfs_path = g_udev_device_get_sysfs_path (device); modem = find_modem_for_device (manager, sysfs_path); if (modem) { mm_dbg ("Removing modem claimed by removed device %s", sysfs_path); remove_modem (manager, modem); return; } } /* Maybe a plugin is checking whether or not the port is supported. * TODO: Cancel every possible supports check in this port. */ }
static void grab_port (MMManager *manager, MMPlugin *plugin, GUdevDevice *device, GUdevDevice *physical_device) { GError *error = NULL; MMBaseModem *modem; MMBaseModem *existing; existing = g_hash_table_lookup (manager->priv->modems, g_udev_device_get_sysfs_path (physical_device)); /* While grabbing the first port, modem will get created */ modem = mm_plugin_grab_port (plugin, g_udev_device_get_subsystem (device), g_udev_device_get_name (device), existing, &error); if (!modem) { mm_warn ("plugin '%s' claimed to support %s/%s but couldn't: (%d) %s", mm_plugin_get_name (plugin), g_udev_device_get_subsystem (device), g_udev_device_get_name (device), error ? error->code : -1, (error && error->message) ? error->message : "(unknown)"); g_clear_error (&error); if (existing) check_export_modem (manager, existing); return; } mm_info ("(%s): modem %s claimed port %s", mm_plugin_get_name (plugin), mm_base_modem_get_device (modem), g_udev_device_get_name (device)); if (existing) { g_assert (existing == modem); check_export_modem (manager, modem); } else { /* If the modem was just created, store it */ add_modem (manager, modem, plugin); } }
static void set_logging_auth_ready (MMAuthProvider *authp, GAsyncResult *res, SetLoggingContext *ctx) { GError *error = NULL; if (!mm_auth_provider_authorize_finish (authp, res, &error)) g_dbus_method_invocation_take_error (ctx->invocation, error); else if (!mm_log_set_level(ctx->level, &error)) g_dbus_method_invocation_take_error (ctx->invocation, error); else { mm_info ("logging: level '%s'", ctx->level); mm_gdbus_org_freedesktop_modem_manager1_complete_set_logging ( MM_GDBUS_ORG_FREEDESKTOP_MODEM_MANAGER1 (ctx->self), ctx->invocation); } set_logging_context_free (ctx); }
int main (int argc, char *argv[]) { GMainLoop *inner; GError *err = NULL; guint name_id; g_type_init (); /* Setup application context */ mm_context_init (argc, argv); if (!mm_log_setup (mm_context_get_log_level (), mm_context_get_log_file (), mm_context_get_timestamps (), mm_context_get_relative_timestamps (), mm_context_get_debug (), &err)) { g_warning ("Failed to set up logging: %s", err->message); g_error_free (err); exit (1); } g_unix_signal_add (SIGTERM, quit_cb, NULL); g_unix_signal_add (SIGINT, quit_cb, NULL); mm_info ("ModemManager (version " MM_DIST_VERSION ") starting in %s bus...", mm_context_get_test_session () ? "session" : "system"); /* Acquire name, don't allow replacement */ name_id = g_bus_own_name (mm_context_get_test_session () ? G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM, MM_DBUS_SERVICE, G_BUS_NAME_OWNER_FLAGS_NONE, bus_acquired_cb, name_acquired_cb, name_lost_cb, NULL, NULL); /* Go into the main loop */ loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); /* Clear the global variable, so that subsequent requests to * exit succeed. */ inner = loop; loop = NULL; if (manager) { GTimer *timer; mm_base_manager_shutdown (manager); /* Wait for all modems to be disabled and removed, but don't wait * forever: if disabling the modems takes longer than 20s, just * shutdown anyway. */ timer = g_timer_new (); while (mm_base_manager_num_modems (manager) && g_timer_elapsed (timer, NULL) < (gdouble)MAX_SHUTDOWN_TIME_SECS) { GMainContext *ctx = g_main_loop_get_context (inner); g_main_context_iteration (ctx, FALSE); g_usleep (50); } if (mm_base_manager_num_modems (manager)) mm_warn ("Disabling modems took too long, " "shutting down with '%u' modems around", mm_base_manager_num_modems (manager)); g_object_unref (manager); g_timer_destroy (timer); } g_main_loop_unref (inner); g_bus_unown_name (name_id); mm_info ("ModemManager is shut down"); mm_log_shutdown (); return 0; }
static void interface_enabling_step (EnablingContext *ctx) { /* Don't run new steps if we're cancelled */ if (enabling_context_complete_and_free_if_cancelled (ctx)) return; switch (ctx->step) { case ENABLING_STEP_FIRST: { MMSmsList *list; list = mm_sms_list_new (MM_BASE_MODEM (ctx->self)); g_object_set (ctx->self, MM_IFACE_MODEM_MESSAGING_SMS_LIST, list, NULL); /* Connect to list's signals */ g_signal_connect (list, MM_SMS_ADDED, G_CALLBACK (sms_added), ctx->skeleton); g_signal_connect (list, MM_SMS_DELETED, G_CALLBACK (sms_deleted), ctx->skeleton); g_object_unref (list); /* Fall down to next step */ ctx->step++; } case ENABLING_STEP_SETUP_SMS_FORMAT: /* Allow setting SMS format to use */ if (MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->setup_sms_format && MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->setup_sms_format_finish) { MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->setup_sms_format ( ctx->self, (GAsyncReadyCallback)setup_sms_format_ready, ctx); return; } /* Fall down to next step */ ctx->step++; case ENABLING_STEP_STORAGE_DEFAULTS: /* Set storage defaults */ if (MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->set_default_storage && MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->set_default_storage_finish) { MMSmsStorage default_storage; default_storage = get_best_initial_default_sms_storage (ctx->self); /* Already bound to the 'default-storage' property in the skeleton */ g_object_set (ctx->self, MM_IFACE_MODEM_MESSAGING_SMS_DEFAULT_STORAGE, default_storage, NULL); if (default_storage != MM_SMS_STORAGE_UNKNOWN) { MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->set_default_storage ( ctx->self, default_storage, (GAsyncReadyCallback)set_default_storage_ready, ctx); return; } mm_info ("Cannot set default storage, none of the suggested ones supported"); } /* Fall down to next step */ ctx->step++; case ENABLING_STEP_LOAD_INITIAL_SMS_PARTS: /* Allow loading the initial list of SMS parts */ if (MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->load_initial_sms_parts && MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->load_initial_sms_parts_finish) { load_initial_sms_parts_from_storages (ctx); return; } /* Fall down to next step */ ctx->step++; case ENABLING_STEP_SETUP_UNSOLICITED_EVENTS: /* Allow setting up unsolicited events */ if (MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->setup_unsolicited_events && MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->setup_unsolicited_events_finish) { MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->setup_unsolicited_events ( ctx->self, (GAsyncReadyCallback)setup_unsolicited_events_ready, ctx); return; } /* Fall down to next step */ ctx->step++; case ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS: /* Allow setting up unsolicited events */ if (MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->enable_unsolicited_events && MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->enable_unsolicited_events_finish) { MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->enable_unsolicited_events ( ctx->self, (GAsyncReadyCallback)enable_unsolicited_events_ready, ctx); return; } /* Fall down to next step */ ctx->step++; case ENABLING_STEP_LAST: /* We are done without errors! */ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); enabling_context_complete_and_free (ctx); return; } g_assert_not_reached (); }
MMQmiPort * mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self, MMPort *data, GError **error) { MMQmiPort *found; GUdevClient *client; GUdevDevice *data_device; GUdevDevice *data_device_parent; GList *l; if (mm_port_get_subsys (data) != MM_PORT_SUBSYS_NET) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot look for QMI port associated to a non-net data port"); return NULL; } /* don't listen for uevents */ client = g_udev_client_new (NULL); /* Get udev device for the data port */ data_device = (g_udev_client_query_by_subsystem_and_name ( client, "net", mm_port_get_device (data))); if (!data_device) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't find udev device for port 'net/%s'", mm_port_get_device (data)); g_object_unref (client); return NULL; } /* Get parent of the data device */ data_device_parent = g_udev_device_get_parent (data_device); if (!data_device_parent) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't get udev device parent for port 'net/%s'", mm_port_get_device (data)); g_object_unref (data_device); g_object_unref (client); return NULL; } /* Now walk the list of QMI ports looking for a match */ found = NULL; for (l = self->priv->qmi; l && !found; l = g_list_next (l)) { GUdevDevice *qmi_device; GUdevDevice *qmi_device_parent; /* Get udev device for the QMI port */ qmi_device = (g_udev_client_query_by_subsystem_and_name ( client, "usb", mm_port_get_device (MM_PORT (l->data)))); if (!qmi_device) { qmi_device = (g_udev_client_query_by_subsystem_and_name ( client, "usbmisc", mm_port_get_device (MM_PORT (l->data)))); if (!qmi_device) { mm_warn ("Couldn't get udev device for QMI port '%s'", mm_port_get_device (MM_PORT (l->data))); continue; } } /* Get parent of the QMI device */ qmi_device_parent = g_udev_device_get_parent (qmi_device); g_object_unref (qmi_device); if (!data_device_parent) { mm_warn ("Couldn't get udev device parent for QMI port '%s'", mm_port_get_device (MM_PORT (l->data))); continue; } if (g_str_equal (g_udev_device_get_sysfs_path (data_device_parent), g_udev_device_get_sysfs_path (qmi_device_parent))) found = MM_QMI_PORT (l->data); g_object_unref (qmi_device_parent); } g_object_unref (data_device_parent); g_object_unref (data_device); g_object_unref (client); if (!found) { /* For the case where we have only 1 data port and 1 QMI port and they * don't match with the previous rules (e.g. in some Huawei modems), * just return the found one */ if (g_list_length (self->priv->data) == 1 && g_list_length (self->priv->qmi) == 1 && self->priv->data->data == data) { mm_info ("Assuming QMI port '%s' is associated to net/%s", mm_port_get_device (MM_PORT (self->priv->qmi->data)), mm_port_get_device (data)); found = MM_QMI_PORT (self->priv->qmi->data); } else { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, "Couldn't find associated QMI port for 'net/%s'", mm_port_get_device (data)); return NULL; } } return found; }
static void get_current_settings_ready (QmiClientWds *client, GAsyncResult *res, ConnectContext *ctx) { GError *error = NULL; QmiMessageWdsGetCurrentSettingsOutput *output; g_assert (ctx->running_ipv4 || ctx->running_ipv6); g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); output = qmi_client_wds_get_current_settings_finish (client, res, &error); if (!output || !qmi_message_wds_get_current_settings_output_get_result (output, &error)) { /* Never treat this as a hard connection error; not all devices support * "WDS Get Current Settings" */ mm_info ("error: couldn't get current settings: %s", error->message); g_error_free (error); } else { gboolean success; guint32 addr, mtu, i; GArray *array; guint8 prefix; if (ctx->running_ipv4) { mm_dbg ("QMI IPv4 Settings:"); /* IPv4 address */ success = qmi_message_wds_get_current_settings_output_get_ipv4_address (output, &addr, &error); print_address4 (success, "Address", addr, error); g_clear_error (&error); /* IPv4 gateway address */ success = qmi_message_wds_get_current_settings_output_get_ipv4_gateway_address (output, &addr, &error); print_address4 (success, "Gateway", addr, error); g_clear_error (&error); /* IPv4 subnet mask */ success = qmi_message_wds_get_current_settings_output_get_ipv4_gateway_subnet_mask (output, &addr, &error); print_address4 (success, "Netmask", addr, error); g_clear_error (&error); /* IPv4 DNS #1 */ success = qmi_message_wds_get_current_settings_output_get_primary_ipv4_dns_address (output, &addr, &error); print_address4 (success, " DNS #1", addr, error); g_clear_error (&error); /* IPv4 DNS #2 */ success = qmi_message_wds_get_current_settings_output_get_secondary_ipv4_dns_address (output, &addr, &error); print_address4 (success, " DNS #2", addr, error); g_clear_error (&error); } else { mm_dbg ("QMI IPv6 Settings:"); /* IPv6 address */ success = qmi_message_wds_get_current_settings_output_get_ipv6_address (output, &array, &prefix, &error); print_address6 (success, "Address", array, prefix, error); g_clear_error (&error); /* IPv6 gateway address */ success = qmi_message_wds_get_current_settings_output_get_ipv6_gateway_address (output, &array, &prefix, &error); print_address6 (success, "Gateway", array, prefix, error); g_clear_error (&error); /* IPv6 DNS #1 */ success = qmi_message_wds_get_current_settings_output_get_ipv6_primary_dns_address (output, &array, &error); print_address6 (success, " DNS #1", array, 0, error); g_clear_error (&error); /* IPv6 DNS #2 */ success = qmi_message_wds_get_current_settings_output_get_ipv6_secondary_dns_address (output, &array, &error); print_address6 (success, " DNS #2", array, 0, error); g_clear_error (&error); } /* Domain names */ if (qmi_message_wds_get_current_settings_output_get_domain_name_list (output, &array, &error)) { GString *s = g_string_sized_new (array ? (array->len * 20) : 1); for (i = 0; array && (i < array->len); i++) { if (s->len) g_string_append (s, ", "); g_string_append (s, g_array_index (array, const char *, i)); } mm_dbg (" Domains: %s", s->str); g_string_free (s, TRUE); } else { mm_dbg (" Domains: failed (%s)", error ? error->message : "unknown"); g_clear_error (&error); } if (qmi_message_wds_get_current_settings_output_get_mtu (output, &mtu, &error)) mm_dbg (" MTU: %d", mtu); else { mm_dbg (" MTU: failed (%s)", error ? error->message : "unknown"); g_clear_error (&error); } } if (output) qmi_message_wds_get_current_settings_output_unref (output); /* Keep on */ ctx->step++; connect_context_step (ctx); }
static void start_network_ready (QmiClientWds *client, GAsyncResult *res, ConnectContext *ctx) { GError *error = NULL; QmiMessageWdsStartNetworkOutput *output; g_assert (ctx->running_ipv4 || ctx->running_ipv6); g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); output = qmi_client_wds_start_network_finish (client, res, &error); if (output && !qmi_message_wds_start_network_output_get_result (output, &error)) { /* No-effect errors should be ignored. The modem will keep the * connection active as long as there is a WDS client which requested * to start the network. If ModemManager crashed while a connection was * active, we would be leaving an unreleased WDS client around and the * modem would just keep connected. */ if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_NO_EFFECT)) { g_error_free (error); error = NULL; if (ctx->running_ipv4) ctx->packet_data_handle_ipv4 = GLOBAL_PACKET_DATA_HANDLE; else ctx->packet_data_handle_ipv6 = GLOBAL_PACKET_DATA_HANDLE; /* Fall down to a successful connection */ } else { mm_info ("error: couldn't start network: %s", error->message); if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_CALL_FAILED)) { QmiWdsCallEndReason cer; QmiWdsVerboseCallEndReasonType verbose_cer_type; gint16 verbose_cer_reason; if (qmi_message_wds_start_network_output_get_call_end_reason ( output, &cer, NULL)) mm_info ("call end reason (%u): '%s'", cer, qmi_wds_call_end_reason_get_string (cer)); if (qmi_message_wds_start_network_output_get_verbose_call_end_reason ( output, &verbose_cer_type, &verbose_cer_reason, NULL)) mm_info ("verbose call end reason (%u,%d): [%s] %s", verbose_cer_type, verbose_cer_reason, qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type), qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason)); } } } if (error) { if (ctx->running_ipv4) ctx->error_ipv4 = error; else ctx->error_ipv6 = error; } else { if (ctx->running_ipv4) qmi_message_wds_start_network_output_get_packet_data_handle (output, &ctx->packet_data_handle_ipv4, NULL); else qmi_message_wds_start_network_output_get_packet_data_handle (output, &ctx->packet_data_handle_ipv6, NULL); } if (output) qmi_message_wds_start_network_output_unref (output); /* Keep on */ ctx->step++; connect_context_step (ctx); }
static void found_plugin (MMPlugin *plugin) { mm_info ("Loaded plugin '%s'", mm_plugin_get_name (plugin)); }
static gboolean load_plugins (MMPluginManager *self, GError **error) { GDir *dir = NULL; const gchar *fname; MMPlugin *generic_plugin = NULL; gchar *plugindir_display = NULL; if (!g_module_supported ()) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "GModules are not supported on your platform!"); goto out; } /* Get printable UTF-8 string of the path */ plugindir_display = g_filename_display_name (PLUGINDIR); mm_dbg ("Looking for plugins in '%s'", plugindir_display); dir = g_dir_open (PLUGINDIR, 0, NULL); if (!dir) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS, "Plugin directory '%s' not found", plugindir_display); goto out; } while ((fname = g_dir_read_name (dir)) != NULL) { gchar *path; MMPlugin *plugin; if (!g_str_has_suffix (fname, G_MODULE_SUFFIX)) continue; path = g_module_build_path (PLUGINDIR, fname); plugin = load_plugin (path); g_free (path); if (plugin) { if (g_str_equal (mm_plugin_get_name (plugin), MM_PLUGIN_GENERIC_NAME)) generic_plugin = plugin; else self->priv->plugins = g_slist_append (self->priv->plugins, plugin); } } /* Sort last plugins that request it */ self->priv->plugins = g_slist_sort (self->priv->plugins, (GCompareFunc)compare_plugins); /* Make sure the generic plugin is last */ if (generic_plugin) self->priv->plugins = g_slist_append (self->priv->plugins, generic_plugin); /* Treat as error if we don't find any plugin */ if (!self->priv->plugins) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS, "No plugins found in plugin directory '%s'", plugindir_display); goto out; } /* Now report about all the found plugins, in the same order they will be * used while checking support */ g_slist_foreach (self->priv->plugins, (GFunc)found_plugin, NULL); mm_info ("Successfully loaded %u plugins", g_slist_length (self->priv->plugins)); out: if (dir) g_dir_close (dir); g_free (plugindir_display); return !!self->priv->plugins; }
void mm_port_probe_run (MMPortProbe *self, MMPortProbeFlag flags, guint64 at_send_delay, const MMPortProbeAtCommand *at_custom_init, GAsyncReadyCallback callback, gpointer user_data) { PortProbeRunTask *task; guint32 i; gchar *probe_list_str; g_return_if_fail (MM_IS_PORT_PROBE (self)); g_return_if_fail (flags != MM_PORT_PROBE_NONE); g_return_if_fail (callback != NULL); /* Shouldn't schedule more than one probing at a time */ g_assert (self->priv->task == NULL); task = g_new0 (PortProbeRunTask, 1); task->at_send_delay = at_send_delay; task->flags = MM_PORT_PROBE_NONE; task->at_custom_init = at_custom_init; task->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, mm_port_probe_run); /* Check if we already have the requested probing results. * We will fix here the 'task->flags' so that we only request probing * for the missing things. */ for (i = MM_PORT_PROBE_AT; i <= MM_PORT_PROBE_QCDM; i = (i << 1)) { if ((flags & i) && !(self->priv->flags & i)) { task->flags += i; } } /* Store as current task. We need to keep it internally, as it will be * freed during _finish() when the operation is completed. */ self->priv->task = task; /* All requested probings already available? If so, we're done */ if (!task->flags) { port_probe_run_task_complete (task, TRUE, NULL); return; } /* Setup internal cancellable */ task->cancellable = g_cancellable_new (); probe_list_str = mm_port_probe_flag_build_string_from_mask (task->flags); mm_info ("(%s) launching port probing: '%s'", self->priv->name, probe_list_str); g_free (probe_list_str); /* If any AT probing is needed, start by opening as AT port */ if (task->flags & MM_PORT_PROBE_AT || task->flags & MM_PORT_PROBE_AT_VENDOR || task->flags & MM_PORT_PROBE_AT_PRODUCT) { task->at_probing_cancellable = g_cancellable_new (); task->source_id = g_idle_add ((GSourceFunc)serial_open_at, self); return; } /* Otherwise, start by opening as QCDM port */ if (task->flags & MM_PORT_PROBE_QCDM) { task->source_id = g_idle_add ((GSourceFunc)serial_probe_qcdm, self); return; } /* Shouldn't happen */ g_assert_not_reached (); }