static void modem_load_supported_modes (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result; MMModemMode mode; /* Nokia phones don't seem to like AT+WS46?, they just report 2G even if * 3G is supported, so we'll just assume they actually do 3G. */ mode = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); /* Then, if the modem has LTE caps, it does 4G */ if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) mode |= MM_MODEM_MODE_4G; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, modem_load_supported_modes); g_simple_async_result_set_op_res_gpointer (result, GUINT_TO_POINTER (mode), NULL); g_simple_async_result_complete_in_idle (result); g_object_unref (result); }
static void set_allowed_modes (MMIfaceModem *self, MMModemMode allowed, MMModemMode preferred, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result; gchar *command; gint cm_mode = -1; gint pref_acq = -1; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, set_allowed_modes); if (allowed == MM_MODEM_MODE_2G) { cm_mode = 1; pref_acq = 0; } else if (allowed == MM_MODEM_MODE_3G) { cm_mode = 2; pref_acq = 0; } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G) && !mm_iface_modem_is_3gpp_lte (self)) { /* LTE models do not support 2G|3G mode */ cm_mode = 0; if (preferred == MM_MODEM_MODE_2G) pref_acq = 1; else if (preferred == MM_MODEM_MODE_3G) pref_acq = 2; else /* none preferred, so AUTO */ pref_acq = 0; } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) { cm_mode = 0; pref_acq = 0; } else if (allowed == MM_MODEM_MODE_4G) { cm_mode = 6; pref_acq = 0; } if (cm_mode < 0 || pref_acq < 0) { gchar *allowed_str; gchar *preferred_str; allowed_str = mm_modem_mode_build_string_from_mask (allowed); preferred_str = mm_modem_mode_build_string_from_mask (preferred); g_simple_async_result_set_error (result, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Requested mode (allowed: '%s', preferred: '%s') not " "supported by the modem.", allowed_str, preferred_str); g_free (allowed_str); g_free (preferred_str); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } command = g_strdup_printf ("AT+ZSNT=%d,0,%d", cm_mode, pref_acq); mm_base_modem_at_command ( MM_BASE_MODEM (self), command, 3, FALSE, (GAsyncReadyCallback)allowed_mode_update_ready, result); g_free (command); }
static void set_allowed_modes (MMIfaceModem *self, MMModemMode allowed, MMModemMode preferred, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result; MMAtSerialPort *primary; gint idx = -1; gchar *command; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, load_allowed_modes); if (!mm_iface_modem_is_3gpp (self)) { /* Cannot do this in CDMA modems */ g_simple_async_result_set_error (result, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot set allowed modes in CDMA modems"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } /* Sierra secondary ports don't have full AT command interpreters */ primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); if (!primary || mm_port_get_connected (MM_PORT (primary))) { g_simple_async_result_set_error ( result, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, "Cannot set allowed modes while connected"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } if (allowed == MM_MODEM_MODE_3G) idx = 1; else if (allowed == MM_MODEM_MODE_2G) idx = 2; else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { /* in Sierra LTE devices, modes 3 and 4 are automatic, including LTE, no preference */ if (mm_iface_modem_is_3gpp_lte (self)) { if (preferred == MM_MODEM_MODE_NONE) idx = 5; /* GSM and UMTS Only */ } else if (preferred == MM_MODEM_MODE_3G) idx = 3; else if (preferred == MM_MODEM_MODE_2G) idx = 4; else if (preferred == MM_MODEM_MODE_NONE) idx = 0; } else if (allowed == MM_MODEM_MODE_4G) idx = 6; else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) idx = 7; else if (allowed == MM_MODEM_MODE_ANY) idx = 0; if (idx < 0) { gchar *allowed_str; gchar *preferred_str; allowed_str = mm_modem_mode_build_string_from_mask (allowed); preferred_str = mm_modem_mode_build_string_from_mask (preferred); g_simple_async_result_set_error (result, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Requested mode (allowed: '%s', preferred: '%s') not " "supported by the modem.", allowed_str, preferred_str); g_free (allowed_str); g_free (preferred_str); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } command = g_strdup_printf ("!SELRAT=%d", idx); mm_base_modem_at_command_full (MM_BASE_MODEM (self), primary, command, 3, FALSE, FALSE, /* raw */ NULL, /* cancellable */ (GAsyncReadyCallback)selrat_set_ready, result); g_free (command); }
static gboolean load_allowed_modes_finish (MMIfaceModem *self, GAsyncResult *res, MMModemMode *allowed, MMModemMode *preferred, GError **error) { const gchar *response; GMatchInfo *match_info = NULL; GRegex *r; gint cm_mode = -1; gint pref_acq = -1; gboolean result; response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); if (!response) return FALSE; r = g_regex_new ("\\+ZSNT:\\s*(\\d),(\\d),(\\d)", G_REGEX_UNGREEDY, 0, error); g_assert (r != NULL); result = FALSE; if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, error)) goto done; if (!mm_get_int_from_match_info (match_info, 1, &cm_mode) || cm_mode < 0 || (cm_mode > 2 && cm_mode != 6) || !mm_get_int_from_match_info (match_info, 3, &pref_acq) || pref_acq < 0 || pref_acq > 2) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to parse the allowed mode response: '%s'", response); goto done; } /* Correctly parsed! */ result = TRUE; if (cm_mode == 0) { /* Both 2G, 3G and LTE allowed. For LTE modems, no 2G/3G preference supported. */ if (pref_acq == 0 || mm_iface_modem_is_3gpp_lte (self)) { /* Any allowed */ *allowed = MM_MODEM_MODE_ANY; *preferred = MM_MODEM_MODE_NONE; } else if (pref_acq == 1) { *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); *preferred = MM_MODEM_MODE_2G; } else if (pref_acq == 2) { *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); *preferred = MM_MODEM_MODE_3G; } else g_assert_not_reached (); } else if (cm_mode == 1) { /* GSM only */ *allowed = MM_MODEM_MODE_2G; *preferred = MM_MODEM_MODE_NONE; } else if (cm_mode == 2) { /* WCDMA only */ *allowed = MM_MODEM_MODE_3G; *preferred = MM_MODEM_MODE_NONE; } else if (cm_mode == 6) { /* LTE only */ *allowed = MM_MODEM_MODE_4G; *preferred = MM_MODEM_MODE_NONE; } else g_assert_not_reached (); done: if (match_info) g_match_info_free (match_info); if (r) g_regex_unref (r); return result; }
static void selrat_query_ready (MMBaseModem *self, GAsyncResult *res, GSimpleAsyncResult *simple) { LoadAllowedModesResult result; const gchar *response; GError *error = NULL; GRegex *r = NULL; GMatchInfo *match_info = NULL; response = mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error); if (!response) { g_simple_async_result_take_error (simple, error); g_simple_async_result_complete (simple); g_object_unref (simple); return; } /* Example response: !SELRAT: 03, UMTS 3G Preferred */ r = g_regex_new ("!SELRAT:\\s*(\\d+).*$", 0, 0, NULL); g_assert (r != NULL); if (g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &error)) { guint mode; if (mm_get_uint_from_match_info (match_info, 1, &mode) && mode >= 0 && mode <= 7) { switch (mode) { case 0: result.allowed = MM_MODEM_MODE_ANY; result.preferred = MM_MODEM_MODE_NONE; break; case 1: result.allowed = MM_MODEM_MODE_3G; result.preferred = MM_MODEM_MODE_NONE; break; case 2: result.allowed = MM_MODEM_MODE_2G; result.preferred = MM_MODEM_MODE_NONE; break; case 3: /* in Sierra LTE devices, mode 3 is automatic, including LTE, no preference */ if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) { result.allowed = MM_MODEM_MODE_ANY; result.preferred = MM_MODEM_MODE_NONE; } else { result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); result.preferred = MM_MODEM_MODE_3G; } break; case 4: /* in Sierra LTE devices, mode 4 is automatic, including LTE, no preference */ if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) { result.allowed = MM_MODEM_MODE_ANY; result.preferred = MM_MODEM_MODE_NONE; } else { result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); result.preferred = MM_MODEM_MODE_2G; } break; case 5: result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); result.preferred = MM_MODEM_MODE_NONE; break; case 6: result.allowed = MM_MODEM_MODE_4G; result.preferred = MM_MODEM_MODE_NONE; break; case 7: result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); result.preferred = MM_MODEM_MODE_NONE; break; default: g_assert_not_reached (); break; } } else error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to parse the allowed mode response: '%s'", response); } if (error) g_simple_async_result_take_error (simple, error); else g_simple_async_result_set_op_res_gpointer (simple, &result, NULL); g_simple_async_result_complete (simple); g_object_unref (simple); }