예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
static void
icera_disconnect_done (MMModem *modem,
                       GError *error,
                       gpointer user_data)
{
    mm_info ("Modem signaled disconnection from the network");
}
예제 #4
0
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. */
}
예제 #5
0
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;
}
예제 #6
0
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);
}
예제 #7
0
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. */
}
예제 #8
0
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);
    }
}
예제 #9
0
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);
}
예제 #10
0
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 ();
}
예제 #12
0
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;
}
예제 #13
0
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);
}
예제 #14
0
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);
}
예제 #15
0
static void
found_plugin (MMPlugin *plugin)
{
    mm_info ("Loaded plugin '%s'", mm_plugin_get_name (plugin));
}
예제 #16
0
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;
}
예제 #17
0
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 ();
}