static gboolean
load_current_modes_finish (MMIfaceModem *_self,
                           GAsyncResult *res,
                           MMModemMode *allowed,
                           MMModemMode *preferred,
                           GError **error)
{
    MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self);
    const gchar *response;
    guint a;

    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
    if (!response)
        return FALSE;

    if (mm_get_uint_from_str (mm_strip_tag (response, "+CFUN:"), &a)) {
        /* No settings to set preferred */
        *preferred = MM_MODEM_MODE_NONE;

        switch (a) {
        case MBM_NETWORK_MODE_OFFLINE:
        case MBM_NETWORK_MODE_LOW_POWER:
            /* Do not update internal mbm_mode */
            *allowed = MM_MODEM_MODE_NONE;
            break;
        case MBM_NETWORK_MODE_2G:
            self->priv->mbm_mode = MBM_NETWORK_MODE_2G;
            *allowed = MM_MODEM_MODE_2G;
            break;
        case MBM_NETWORK_MODE_3G:
            self->priv->mbm_mode = MBM_NETWORK_MODE_3G;
            *allowed = MM_MODEM_MODE_3G;
            break;
        default:
            /* Do not update internal mbm_mode */
            *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
            break;
        }

        return TRUE;
    }

    g_set_error (error,
                 MM_CORE_ERROR,
                 MM_CORE_ERROR_FAILED,
                 "Couldn't parse +CFUN response: '%s'",
                 response);
    return FALSE;
}
Example #2
0
void
mmcli_modem_signal_run_synchronous (GDBusConnection *connection)
{
    GError *error = NULL;

    /* Initialize context */
    ctx = g_new0 (Context, 1);
    ctx->object = mmcli_get_modem_sync (connection,
                                        mmcli_get_common_modem_string (),
                                        &ctx->manager);
    ctx->modem_signal = mm_object_get_modem_signal (ctx->object);

    /* Setup operation timeout */
    if (ctx->modem_signal)
        mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_signal));

    ensure_modem_signal ();

    /* Request to get signal info? */
    if (get_flag) {
        print_signal_info ();
        return;
    }

    /* Request to set rate? */
    if (setup_str) {
        guint rate;
        gboolean result;

        if (!mm_get_uint_from_str (setup_str, &rate)) {
            g_printerr ("error: invalid rate value '%s'", setup_str);
            exit (EXIT_FAILURE);
        }

        g_debug ("Synchronously setting up extended signal quality information retrieval...");
        result = mm_modem_signal_setup_sync (ctx->modem_signal,
                                             rate,
                                             NULL,
                                             &error);
        setup_process_reply (result, error);
        return;
    }


    g_warn_if_reached ();
}
static MMModemPowerState
load_power_state_finish (MMIfaceModem *self,
                         GAsyncResult *res,
                         GError **error)
{
    const gchar *response;
    guint a;

    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
    if (!response)
        return FALSE;

    if (mm_get_uint_from_str (mm_strip_tag (response, "+CFUN:"), &a)) {
        switch (a) {
        case MBM_NETWORK_MODE_OFFLINE:
            return MM_MODEM_POWER_STATE_OFF;

        case MBM_NETWORK_MODE_LOW_POWER:
            return MM_MODEM_POWER_STATE_LOW;

        case MBM_NETWORK_MODE_ANY:
        case MBM_NETWORK_MODE_2G:
        case MBM_NETWORK_MODE_3G:
            return MM_MODEM_POWER_STATE_ON;
        default:
            break;
        }
    }

    g_set_error (error,
                 MM_CORE_ERROR,
                 MM_CORE_ERROR_FAILED,
                 "Couldn't parse +CFUN response: '%s'",
                 response);
    return MM_MODEM_POWER_STATE_UNKNOWN;
}
Example #4
0
static void
get_modem_ready (GObject      *source,
                 GAsyncResult *result)
{
    ctx->object = mmcli_get_modem_finish (result, &ctx->manager);
    ctx->modem_signal = mm_object_get_modem_signal (ctx->object);

    /* Setup operation timeout */
    if (ctx->modem_signal)
        mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_signal));

    ensure_modem_signal ();

    if (get_flag)
        g_assert_not_reached ();

    /* Request to setup? */
    if (setup_str) {
        guint rate;

        if (!mm_get_uint_from_str (setup_str, &rate)) {
            g_printerr ("error: invalid rate value '%s'", setup_str);
            exit (EXIT_FAILURE);
        }

        g_debug ("Asynchronously setting up extended signal quality information retrieval...");
        mm_modem_signal_setup (ctx->modem_signal,
                               rate,
                               ctx->cancellable,
                               (GAsyncReadyCallback)setup_ready,
                               NULL);
        return;
    }

    g_warn_if_reached ();
}
void
mmcli_modem_location_run_synchronous (GDBusConnection *connection)
{
    GError *error = NULL;

    /* Initialize context */
    ctx = g_new0 (Context, 1);
    ctx->object = mmcli_get_modem_sync (connection,
                                        mmcli_get_common_modem_string (),
                                        &ctx->manager);
    ctx->modem_location = mm_object_get_modem_location (ctx->object);

    /* Setup operation timeout */
    if (ctx->modem_location)
        mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_location));

    ensure_modem_location ();

    /* Request to get location status? */
    if (status_flag) {
        g_debug ("Printing location status...");
        print_location_status ();
        return;
    }

    /* Request to setup location gathering? */
    if (enable_3gpp_flag ||
        disable_3gpp_flag ||
        enable_agps_flag ||
        disable_agps_flag ||
        enable_gps_nmea_flag ||
        disable_gps_nmea_flag ||
        enable_gps_raw_flag ||
        disable_gps_raw_flag ||
        enable_cdma_bs_flag ||
        disable_cdma_bs_flag ||
        enable_gps_unmanaged_flag ||
        disable_gps_unmanaged_flag ||
        set_enable_signal_flag ||
        set_disable_signal_flag) {
        gboolean result;

        g_debug ("Synchronously setting up location gathering...");
        result = mm_modem_location_setup_sync (ctx->modem_location,
                                               build_sources_from_flags (),
                                               build_signals_location_from_flags (),
                                               NULL,
                                               &error);
        setup_process_reply (result, error);
        return;
    }

    /* Request to get location from the modem? */
    if (get_3gpp_flag ||
        get_gps_nmea_flag ||
        get_gps_raw_flag ||
        get_cdma_bs_flag) {
        MMLocation3gpp *location_3gpp = NULL;
        MMLocationGpsNmea *location_gps_nmea = NULL;
        MMLocationGpsRaw *location_gps_raw = NULL;
        MMLocationCdmaBs *location_cdma_bs = NULL;

        g_debug ("Synchronously getting location from the modem...");
        mm_modem_location_get_full_sync (ctx->modem_location,
                                         get_3gpp_flag ? &location_3gpp : NULL,
                                         get_gps_nmea_flag ? &location_gps_nmea : NULL,
                                         get_gps_raw_flag ? &location_gps_raw : NULL,
                                         get_cdma_bs_flag ? &location_cdma_bs : NULL,
                                         NULL,
                                         &error);
        get_location_process_reply (location_3gpp, location_gps_nmea, location_gps_raw, location_cdma_bs, error);
        return;
    }

    /* Request to set SUPL server? */
    if (set_supl_server_str) {
        gboolean result;

        g_debug ("Synchronously setting SUPL server...");
        result = mm_modem_location_set_supl_server_sync (ctx->modem_location,
                                                         set_supl_server_str,
                                                         NULL,
                                                         &error);
        set_supl_server_process_reply (result, error);
        return;
    }

    /* Request to set GPS refresh rate? */
    if (set_gps_refresh_rate_str) {
        gboolean result;
        guint rate;

        if (!mm_get_uint_from_str (set_gps_refresh_rate_str, &rate)) {
            g_printerr ("error: couldn't set GPS refresh rate: invalid rate given: '%s'\n",
                        set_gps_refresh_rate_str);
            exit (EXIT_FAILURE);
        }

        g_debug ("Synchronously setting GPS refresh rate...");
        result = mm_modem_location_set_gps_refresh_rate_sync (ctx->modem_location,
                                                              rate,
                                                              NULL,
                                                              &error);
        set_gps_refresh_rate_process_reply (result, error);
        return;
    }

    g_warn_if_reached ();
}
static void
get_modem_ready (GObject      *source,
                 GAsyncResult *result,
                 gpointer      none)
{
    ctx->object = mmcli_get_modem_finish (result, &ctx->manager);
    ctx->modem_location = mm_object_get_modem_location (ctx->object);

    /* Setup operation timeout */
    if (ctx->modem_location)
        mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_location));

    ensure_modem_location ();

    if (status_flag)
        g_assert_not_reached ();

    /* Request to setup location gathering? */
    if (enable_3gpp_flag ||
        disable_3gpp_flag ||
        enable_agps_flag ||
        disable_agps_flag ||
        enable_gps_nmea_flag ||
        disable_gps_nmea_flag ||
        enable_gps_raw_flag ||
        disable_gps_raw_flag ||
        enable_cdma_bs_flag ||
        disable_cdma_bs_flag ||
        enable_gps_unmanaged_flag ||
        disable_gps_unmanaged_flag ||
        set_enable_signal_flag ||
        set_disable_signal_flag) {
        g_debug ("Asynchronously setting up location gathering...");
        mm_modem_location_setup (ctx->modem_location,
                                 build_sources_from_flags (),
                                 build_signals_location_from_flags (),
                                 ctx->cancellable,
                                 (GAsyncReadyCallback)setup_ready,
                                 NULL);
        return;
    }

    /* Request to get location from the modem? */
    if (get_3gpp_flag ||
        get_gps_nmea_flag ||
        get_gps_raw_flag ||
        get_cdma_bs_flag) {
        g_debug ("Asynchronously getting location from the modem...");
        mm_modem_location_get_full (ctx->modem_location,
                                    ctx->cancellable,
                                    (GAsyncReadyCallback)get_location_ready,
                                    NULL);
        return;
    }

    /* Request to set SUPL server? */
    if (set_supl_server_str) {
        g_debug ("Asynchronously setting SUPL server...");
        mm_modem_location_set_supl_server (ctx->modem_location,
                                           set_supl_server_str,
                                           ctx->cancellable,
                                           (GAsyncReadyCallback)set_supl_server_ready,
                                           NULL);
        return;
    }

    /* Request to set GPS refresh rate? */
    if (set_gps_refresh_rate_str) {
        guint rate;

        if (!mm_get_uint_from_str (set_gps_refresh_rate_str, &rate)) {
            g_printerr ("error: couldn't set GPS refresh rate: invalid rate given: '%s'\n",
                        set_gps_refresh_rate_str);
            exit (EXIT_FAILURE);
        }
        g_debug ("Asynchronously setting GPS refresh rate...");
        mm_modem_location_set_gps_refresh_rate (ctx->modem_location,
                                                rate,
                                                ctx->cancellable,
                                                (GAsyncReadyCallback)set_gps_refresh_rate_ready,
                                                NULL);
        return;
    }

    g_warn_if_reached ();
}
const MMHuaweiSyscfgCombination *
mm_huawei_parse_syscfg_response (const gchar *response,
                                 const GArray *supported_mode_combinations,
                                 GError **error)
{
    gchar **split;
    guint mode;
    guint acqorder;
    guint i;

    if (!response || !g_str_has_prefix (response, "^SYSCFG:")) {
        g_set_error (error,
                     MM_CORE_ERROR,
                     MM_CORE_ERROR_FAILED,
                     "Missing ^SYSCFG prefix");
        return NULL;
    }

    /* Format:
     *
     * ^SYSCFG: <mode>,<acqorder>,<band>,<roam>,<srvdomain>
     */

    response = mm_strip_tag (response, "^SYSCFG:");
    split = g_strsplit (response, ",", -1);

    /* We expect 5 string chunks */
    if (g_strv_length (split) < 5 ||
        !mm_get_uint_from_str (split[0], &mode) ||
        !mm_get_uint_from_str (split[1], &acqorder)) {
        /* Dump error to upper layer */
        g_set_error (error,
                     MM_CORE_ERROR,
                     MM_CORE_ERROR_FAILED,
                     "Unexpected ^SYSCFG response: '%s'",
                     response);
        g_strfreev (split);
        return NULL;
    }

    /* Fix invalid modes with non-sensical acquisition orders */
    if (mode == 14 && acqorder != 0)  /* WCDMA only but acqorder != "Automatic" */
        acqorder = 0;
    else if (mode == 13 && acqorder != 0)  /* GSM only but acqorder != "Automatic" */
        acqorder = 0;

    /* Look for current modes among the supported ones */
    for (i = 0; i < supported_mode_combinations->len; i++) {
        const MMHuaweiSyscfgCombination *combination;

        combination = &g_array_index (supported_mode_combinations,
                                      MMHuaweiSyscfgCombination,
                                      i);
        if (mode == combination->mode && acqorder == combination->acqorder) {
            g_strfreev (split);
            return combination;
        }
    }

    g_set_error (error,
                 MM_CORE_ERROR,
                 MM_CORE_ERROR_FAILED,
                 "No SYSCFG combination found matching the current one (%d,%d)",
                 mode,
                 acqorder);
    g_strfreev (split);
    return NULL;
}
static GArray *
parse_syscfg_modes (const gchar *modes_str,
                    const gchar *acqorder_str,
                    GError **error)
{
    GArray *out;
    gchar **split;
    guint i;
    gint min_acqorder = 0;
    gint max_acqorder = 0;

    /* Start parsing acquisition order */
    if (!sscanf (acqorder_str, "%d-%d", &min_acqorder, &max_acqorder))
        mm_dbg ("Error parsing ^SYSCFG acquisition order range (%s)", acqorder_str);

    /* Just in case, we default to supporting only auto */
    if (max_acqorder < min_acqorder) {
        min_acqorder = 0;
        max_acqorder = 0;
    }

    /* Now parse modes */
    split = g_strsplit (modes_str, ",", -1);
    out = g_array_sized_new (FALSE,
                             FALSE,
                             sizeof (MMHuaweiSyscfgCombination),
                             g_strv_length (split));
    for (i = 0; split[i]; i++) {
        guint val;
        guint allowed = MM_MODEM_MODE_NONE;
        GError *inner_error = NULL;
        MMHuaweiSyscfgCombination combination;

        if (!mm_get_uint_from_str (mm_strip_quotes (split[i]), &val)) {
            mm_dbg ("Error parsing ^SYSCFG mode value: %s", split[i]);
            continue;
        }

        if (!mode_from_syscfg (val, &allowed, &inner_error)) {
            if (inner_error) {
                mm_dbg ("Unhandled ^SYSCFG: %s", inner_error->message);
                g_error_free (inner_error);
            }
            continue;
        }

        switch (allowed) {
        case MM_MODEM_MODE_2G:
        case MM_MODEM_MODE_3G:
            /* single mode */
            combination.allowed = allowed;
            combination.preferred = MM_MODEM_MODE_NONE;
            combination.mode = val;
            combination.acqorder = 0;
            g_array_append_val (out, combination);
            break;
        case (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G):
            /* 2G and 3G; auto */
            combination.allowed = allowed;
            combination.mode = val;
            if (min_acqorder == 0) {
                combination.preferred = MM_MODEM_MODE_NONE;
                combination.acqorder = 0;
                g_array_append_val (out, combination);
            }
            /* 2G and 3G; 2G preferred */
            if (min_acqorder <= 1 && max_acqorder >= 1) {
                combination.preferred = MM_MODEM_MODE_2G;
                combination.acqorder = 1;
                g_array_append_val (out, combination);
            }
            /* 2G and 3G; 3G preferred */
            if (min_acqorder <= 2 && max_acqorder >= 2) {
                combination.preferred = MM_MODEM_MODE_3G;
                combination.acqorder = 2;
                g_array_append_val (out, combination);
            }
            break;
        default:
            g_assert_not_reached ();
        }
    }

    g_strfreev (split);

    /* If we didn't build a valid array of combinations, return an error */
    if (out->len == 0) {
        g_set_error (error,
                     MM_CORE_ERROR,
                     MM_CORE_ERROR_FAILED,
                     "Cannot parse list of allowed mode combinations: '%s,%s'",
                     modes_str,
                     acqorder_str);
        g_array_unref (out);
        return NULL;
    }

    return out;
}
GArray *
mm_huawei_parse_prefmode_test (const gchar *response,
                               GError **error)
{
    gchar **split;
    guint i;
    MMModemMode all = MM_MODEM_MODE_NONE;
    GArray *out;

    response = mm_strip_tag (response, "^PREFMODE:");
    split = g_strsplit_set (response, " (,)\r\n", -1);
    if (!split) {
        g_set_error (error,
                     MM_CORE_ERROR,
                     MM_CORE_ERROR_FAILED,
                     "Unexpected ^PREFMODE format output");
        return NULL;
    }

    out = g_array_sized_new (FALSE,
                             FALSE,
                             sizeof (MMHuaweiPrefmodeCombination),
                             3);
    for (i = 0; split[i]; i++) {
        guint val;
        MMModemMode preferred = MM_MODEM_MODE_NONE;
        GError *inner_error = NULL;
        MMHuaweiPrefmodeCombination combination;

        if (split[i][0] == '\0')
            continue;

        if (!mm_get_uint_from_str (split[i], &val)) {
            mm_dbg ("Error parsing ^PREFMODE value: %s", split[i]);
            continue;
        }

        if (!mode_from_prefmode (val, &preferred, &inner_error)) {
            mm_dbg ("Unhandled ^PREFMODE: %s", inner_error->message);
            g_error_free (inner_error);
            continue;
        }

        combination.prefmode = val;
        combination.allowed = MM_MODEM_MODE_NONE; /* reset it later */
        combination.preferred = preferred;

        all |= preferred;

        g_array_append_val (out, combination);
    }
    g_strfreev (split);

    /* No value */
    if (out->len == 0) {
        g_array_unref (out);
        g_set_error (error,
                     MM_CORE_ERROR,
                     MM_CORE_ERROR_FAILED,
                     "^PREFMODE response contains no valid values");
        return NULL;
    }

    /* Single value listed; PREFERRED=NONE... */
    if (out->len == 1) {
        MMHuaweiPrefmodeCombination *combination;

        combination = &g_array_index (out, MMHuaweiPrefmodeCombination, 0);
        combination->allowed = all;
        combination->preferred = MM_MODEM_MODE_NONE;
    } else {
        /* Multiple values, reset ALLOWED */
        for (i = 0; i < out->len; i++) {
            MMHuaweiPrefmodeCombination *combination;

            combination = &g_array_index (out, MMHuaweiPrefmodeCombination, i);
            combination->allowed = all;
            if (combination->preferred == all)
                combination->preferred = MM_MODEM_MODE_NONE;
        }
    }

    return out;
}
gboolean
mm_mbm_parse_cfun_test (const gchar *response,
                        guint32 *supported_mask,
                        GError **error)
{
    gchar **groups;
    guint32 mask = 0;

    g_assert (supported_mask);

    if (!response || !g_str_has_prefix (response, CFUN_TAG)) {
        g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
                             "Missing " CFUN_TAG " prefix");
        return FALSE;
    }

    /*
     * AT+CFUN=?
     * +CFUN: (0,1,4-6),(0,1)
     * OK
     */

    /* Strip tag from response */
    response = mm_strip_tag (response, CFUN_TAG);

    /* Split response in (groups) */
    groups = mm_split_string_groups (response);

    /* First group is the one listing supported modes */
    if (groups && groups[0]) {
        gchar **supported_modes;

        supported_modes = g_strsplit_set (groups[0], ", ", -1);
        if (supported_modes) {
            guint i;

            for (i = 0; supported_modes[i]; i++) {
                gchar *separator;
                guint mode;

                if (!supported_modes[i][0])
                    continue;

                /* Check if this is a range that's being given to us */
                separator = strchr (supported_modes[i], '-');
                if (separator) {
                    gchar *first_str;
                    gchar *last_str;
                    guint first;
                    guint last;

                    *separator = '\0';
                    first_str = supported_modes[i];
                    last_str = separator + 1;

                    if (!mm_get_uint_from_str (first_str, &first))
                        g_warning ("Couldn't match range start: '%s'", first_str);
                    else if (!mm_get_uint_from_str (last_str, &last))
                        g_warning ("Couldn't match range stop: '%s'", last_str);
                    else if (first >= last)
                        g_warning ("Couldn't match range: wrong first '%s' and last '%s' items", first_str, last_str);
                    else {
                        for (mode = first; mode <= last; mode++)
                            add_supported_mode (&mask, mode);
                    }
                } else {
                    if (!mm_get_uint_from_str (supported_modes[i], &mode))
                        g_warning ("Couldn't match mode: '%s'", supported_modes[i]);
                    else
                        add_supported_mode (&mask, mode);
                }
            }

            g_strfreev (supported_modes);
        }
    }
    g_strfreev (groups);

    if (mask)
        *supported_mask = mask;
    return !!mask;
}