diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-01-09 13:30:00 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-15 14:14:48 +0100 |
commit | d1cfdd974cefb6ec87d6bc2889320ac8373dd4be (patch) | |
tree | 07ffb52cfd9c44cd8a00ff5caedf988a7d1374b8 /src | |
parent | 070c27701305dfa5c549f072d09785a12d6f03f5 (diff) |
bearer-cdma: when specific RM protocol given to be used, ensure it is supported
If the requested RM protocol is not supported, the CDMA Bearer creation will
fail.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-bearer-cdma.c | 69 | ||||
-rw-r--r-- | src/mm-modem-helpers.c | 81 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 8 |
3 files changed, 158 insertions, 0 deletions
diff --git a/src/mm-bearer-cdma.c b/src/mm-bearer-cdma.c index e4d34617..ee6fabee 100644 --- a/src/mm-bearer-cdma.c +++ b/src/mm-bearer-cdma.c @@ -113,6 +113,7 @@ static void interface_initialization_step (InitAsyncContext *ctx); typedef enum { INITIALIZATION_STEP_FIRST, + INITIALIZATION_STEP_RM_PROTOCOL, INITIALIZATION_STEP_LAST } InitializationStep; @@ -174,6 +175,55 @@ initable_init_finish (GAsyncInitable *initable, } static void +crm_range_ready (MMBaseModem *modem, + GAsyncResult *res, + InitAsyncContext *ctx) +{ + GError *error = NULL; + const gchar *response; + + response = mm_base_modem_at_command_finish (modem, res, &error); + if (error) { + /* We should possibly take this error as fatal. If we were told to use a + * specific Rm protocol, we must be able to check if it is supported. */ + g_simple_async_result_take_error (ctx->result, error); + } else { + MMModemCdmaRmProtocol min = MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN; + MMModemCdmaRmProtocol max = MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN; + + if (mm_cdma_parse_crm_range_response (response, + &min, &max, + &error)) { + GEnumClass *enum_class; + GEnumValue *value; + + /* Check if value within the range */ + if (ctx->self->priv->rm_protocol >= min && + ctx->self->priv->rm_protocol <= max) { + /* Fine, go on with next step */ + ctx->step++; + interface_initialization_step (ctx); + } + + enum_class = G_ENUM_CLASS (g_type_class_ref (MM_TYPE_MODEM_CDMA_RM_PROTOCOL)); + value = g_enum_get_value (enum_class, ctx->self->priv->rm_protocol); + g_assert (error == NULL); + error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Requested RM protocol '%s' is not supported", + value->value_nick); + g_type_class_unref (enum_class); + } + + /* Failed, set as fatal as well */ + g_simple_async_result_take_error (ctx->result, error); + } + + g_simple_async_result_complete (ctx->result); + init_async_context_free (ctx, TRUE); +} + +static void interface_initialization_step (InitAsyncContext *ctx) { switch (ctx->step) { @@ -181,6 +231,25 @@ interface_initialization_step (InitAsyncContext *ctx) /* Fall down to next step */ ctx->step++; + case INITIALIZATION_STEP_RM_PROTOCOL: + /* If a specific RM protocol is given, we need to check whether it is + * supported. */ + if (ctx->self->priv->rm_protocol != MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN) { + mm_base_modem_at_command_in_port ( + ctx->modem, + ctx->port, + "+CRM=?", + 3, + TRUE, /* getting range, so reply can be cached */ + NULL, /* cancellable */ + (GAsyncReadyCallback)crm_range_ready, + ctx); + return; + } + + /* Fall down to next step */ + ctx->step++; + case INITIALIZATION_STEP_LAST: /* We are done without errors! */ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index ded11b03..2262a4b3 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -1595,6 +1595,87 @@ mm_cdma_convert_sid (const gchar *sid) return (gint) tmp_sid; } +MMModemCdmaRmProtocol +mm_cdma_get_rm_protocol_from_index (guint index, + GError **error) +{ + guint protocol; + + /* just adding 1 from the index value should give us the enum */ + protocol = index + 1 ; + if (protocol > MM_MODEM_CDMA_RM_PROTOCOL_STU_III) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Unexpected RM protocol index (%u)", + index); + protocol = MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN; + } + + return (MMModemCdmaRmProtocol)protocol; +} + +gboolean +mm_cdma_parse_crm_range_response (const gchar *reply, + MMModemCdmaRmProtocol *min, + MMModemCdmaRmProtocol *max, + GError **error) +{ + gboolean result = FALSE; + GRegex *r; + + + /* Expected reply format is: + * ---> AT+CRM=? + * <--- +CRM: (0-2) + */ + + r = g_regex_new ("\\+CRM:\\s*\\((\\d+)-(\\d+)\\)", + G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, + 0, error); + if (r) { + GMatchInfo *match_info = NULL; + + if (g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, error)) { + gchar *aux; + guint min_val = 0; + guint max_val = 0; + + aux = g_match_info_fetch (match_info, 1); + min_val = (guint) atoi (aux); + g_free (aux); + + aux = g_match_info_fetch (match_info, 2); + max_val = (guint) atoi (aux); + g_free (aux); + + if (min_val == 0 || + max_val == 0 || + min_val >= max_val) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't parse CRM range: " + "Unexpected range of RM protocols (%u,%u)", + min_val, + max_val); + } else { + *min = mm_cdma_get_rm_protocol_from_index (min_val, error); + if (*min != MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN) { + *max = mm_cdma_get_rm_protocol_from_index (max_val, error); + if (*max != MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN) + result = TRUE; + } + } + } + + g_match_info_free (match_info); + g_regex_unref (r); + } + + return result; +} + guint mm_count_bits_set (gulong number) { diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index e0ae8b67..a5a13f8b 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -77,6 +77,14 @@ gboolean mm_cdma_parse_eri (const char *reply, guint32 *out_ind, const char **out_desc); +MMModemCdmaRmProtocol mm_cdma_get_rm_protocol_from_index (guint index, + GError **error); + +gboolean mm_cdma_parse_crm_range_response (const gchar *reply, + MMModemCdmaRmProtocol *min, + MMModemCdmaRmProtocol *max, + GError **error); + gboolean mm_gsm_parse_cscs_support_response (const char *reply, MMModemCharset *out_charsets); |