diff options
-rw-r--r-- | src/mm-broadband-modem.c | 288 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 155 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.h | 8 |
3 files changed, 186 insertions, 265 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 515e3c1f..3c9cfcb2 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -113,6 +113,7 @@ struct _MMBroadbandModemPrivate { MMModemState modem_state; /* Implementation helpers */ MMModemCharset modem_current_charset; + gboolean modem_cind_support_checked; gboolean modem_cind_supported; guint modem_cind_indicator_signal_quality; guint modem_cind_min_signal_quality; @@ -1490,17 +1491,87 @@ modem_load_signal_quality (MMIfaceModem *self, } /*****************************************************************************/ -/* Setting up indicators (3GPP interface) */ +/* Setup/Cleanup unsolicited events (3GPP interface) */ static gboolean -modem_3gpp_setup_indicators_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) { return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } static void +ciev_received (MMAtSerialPort *port, + GMatchInfo *info, + MMBroadbandModem *self) +{ + gint ind = 0; + gchar *item; + + item = g_match_info_fetch (info, 1); + if (item) + ind = atoi (item); + + /* Handle signal quality change indication */ + if (ind == self->priv->modem_cind_indicator_signal_quality || + g_str_equal (item, "signal")) { + gchar *value; + + value = g_match_info_fetch (info, 2); + if (value) { + gint quality = 0; + + quality = atoi (value); + + mm_iface_modem_update_signal_quality ( + MM_IFACE_MODEM (self), + normalize_ciev_cind_signal_quality (quality, + self->priv->modem_cind_min_signal_quality, + self->priv->modem_cind_max_signal_quality)); + g_free (value); + } + } + + g_free (item); + + /* FIXME: handle roaming and service indicators. + * ... wait, arent these already handle by unsolicited CREG responses? */ +} + +static void +set_unsolicited_events_handlers (MMBroadbandModem *self, + gboolean enable) +{ + MMAtSerialPort *ports[2]; + GRegex *ciev_regex; + guint i; + + ciev_regex = mm_3gpp_ciev_regex_get (); + ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); + ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); + + /* Enable unsolicited events in given port */ + for (i = 0; i < 2; i++) { + if (!ports[i]) + continue; + + /* Set/unset unsolicited CIEV event handler */ + mm_dbg ("(%s) %s 3GPP unsolicited events handlers", + mm_port_get_device (MM_PORT (ports[i])), + enable ? "Setting" : "Removing"); + mm_at_serial_port_add_unsolicited_msg_handler ( + ports[i], + ciev_regex, + enable ? (MMAtSerialUnsolicitedMsgFn) ciev_received : NULL, + enable ? self : NULL, + NULL); + } + + g_regex_unref (ciev_regex); +} + +static void cind_format_check_ready (MMBroadbandModem *self, GAsyncResult *res, GSimpleAsyncResult *simple) @@ -1513,8 +1584,10 @@ cind_format_check_ready (MMBroadbandModem *self, result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (error || !(indicators = mm_3gpp_parse_cind_test_response (result, &error))) { - /* quit with error */ - g_simple_async_result_take_error (simple, error); + /* unsupported indications */ + mm_dbg ("Marking indications as unsupported: '%s'", error->message); + g_free (error); + g_simple_async_result_set_op_res_gboolean (simple, TRUE); g_simple_async_result_complete (simple); g_object_unref (simple); return; @@ -1559,140 +1632,71 @@ cind_format_check_ready (MMBroadbandModem *self, g_hash_table_destroy (indicators); + /* Now, keep on setting up the ports */ + set_unsolicited_events_handlers (self, TRUE); + g_simple_async_result_set_op_res_gboolean (simple, TRUE); g_simple_async_result_complete (simple); g_object_unref (simple); } static void -modem_3gpp_setup_indicators (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) +modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *_self, + GAsyncReadyCallback callback, + gpointer user_data) { + MMBroadbandModem *self = MM_BROADBAND_MODEM (_self); GSimpleAsyncResult *result; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - modem_3gpp_setup_indicators); + modem_3gpp_setup_unsolicited_events); /* Load supported indicators */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CIND=?", - 3, - TRUE, - (GAsyncReadyCallback)cind_format_check_ready, - result); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); -} - -static void -ciev_received (MMAtSerialPort *port, - GMatchInfo *info, - MMBroadbandModem *self) -{ - gint ind = 0; - gchar *item; - - item = g_match_info_fetch (info, 1); - if (item) - ind = atoi (item); - - /* Handle signal quality change indication */ - if (ind == self->priv->modem_cind_indicator_signal_quality || - g_str_equal (item, "signal")) { - gchar *value; - - value = g_match_info_fetch (info, 2); - if (value) { - gint quality = 0; - - quality = atoi (value); - - mm_iface_modem_update_signal_quality ( - MM_IFACE_MODEM (self), - normalize_ciev_cind_signal_quality (quality, - self->priv->modem_cind_min_signal_quality, - self->priv->modem_cind_max_signal_quality)); - g_free (value); - } + if (!self->priv->modem_cind_support_checked) { + mm_dbg ("Checking indicator support..."); + self->priv->modem_cind_support_checked = TRUE; + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CIND=?", + 3, + TRUE, + (GAsyncReadyCallback)cind_format_check_ready, + result); + return; } - g_free (item); + /* If supported, go on */ + if (self->priv->modem_cind_supported) + set_unsolicited_events_handlers (self, TRUE); - /* FIXME: handle roaming and service indicators. - * ... wait, arent these already handle by unsolicited CREG responses? */ + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); } static void -set_unsolicited_events_handlers (MMIfaceModem3gpp *self, - gboolean enable, - GAsyncReadyCallback callback, - gpointer user_data) +modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *_self, + GAsyncReadyCallback callback, + gpointer user_data) { + MMBroadbandModem *self = MM_BROADBAND_MODEM (_self); GSimpleAsyncResult *result; - MMAtSerialPort *ports[2]; - GRegex *ciev_regex; - guint i; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - set_unsolicited_events_handlers); - - ciev_regex = mm_3gpp_ciev_regex_get (); - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - /* Enable unsolicited events in given port */ - for (i = 0; i < 2; i++) { - if (!ports[i]) - continue; + modem_3gpp_cleanup_unsolicited_events); - /* Set/unset unsolicited CIEV event handler */ - mm_dbg ("(%s) %s 3GPP unsolicited events handlers", - mm_port_get_device (MM_PORT (ports[i])), - enable ? "Setting" : "Removing"); - mm_at_serial_port_add_unsolicited_msg_handler ( - ports[i], - ciev_regex, - enable ? (MMAtSerialUnsolicitedMsgFn) ciev_received : NULL, - enable ? self : NULL, - NULL); - } + /* If supported, go on */ + if (self->priv->modem_cind_support_checked && self->priv->modem_cind_supported) + set_unsolicited_events_handlers (self, FALSE); - g_regex_unref (ciev_regex); g_simple_async_result_set_op_res_gboolean (result, TRUE); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - set_unsolicited_events_handlers (self, TRUE, callback, user_data); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - set_unsolicited_events_handlers (self, FALSE, callback, user_data); -} - /*****************************************************************************/ /* Enabling/disabling unsolicited events (3GPP interface) */ @@ -1780,38 +1784,64 @@ run_unsolicited_events_setup (UnsolicitedEventsContext *ctx) } static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, +modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *_self, GAsyncReadyCallback callback, gpointer user_data) { - UnsolicitedEventsContext *ctx; + MMBroadbandModem *self = MM_BROADBAND_MODEM (_self); + GSimpleAsyncResult *result; - ctx = g_new0 (UnsolicitedEventsContext, 1); - ctx->self = g_object_ref (self); - ctx->enable = TRUE; - ctx->command = g_strdup ("+CMER=3,0,0,1"); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_enable_unsolicited_events); - run_unsolicited_events_setup (ctx); + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + modem_3gpp_enable_unsolicited_events); + + /* If supported, go on */ + if (self->priv->modem_cind_support_checked && self->priv->modem_cind_supported) { + UnsolicitedEventsContext *ctx; + + ctx = g_new0 (UnsolicitedEventsContext, 1); + ctx->self = g_object_ref (self); + ctx->enable = TRUE; + ctx->command = g_strdup ("+CMER=3,0,0,1"); + ctx->result = result; + run_unsolicited_events_setup (ctx); + return; + } + + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); } static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, +modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *_self, GAsyncReadyCallback callback, gpointer user_data) { - UnsolicitedEventsContext *ctx; + MMBroadbandModem *self = MM_BROADBAND_MODEM (_self); + GSimpleAsyncResult *result; - ctx = g_new0 (UnsolicitedEventsContext, 1); - ctx->self = g_object_ref (self); - ctx->command = g_strdup ("+CMER=0"); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_disable_unsolicited_events); - run_unsolicited_events_setup (ctx); + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + modem_3gpp_disable_unsolicited_events); + + /* If supported, go on */ + if (self->priv->modem_cind_support_checked && self->priv->modem_cind_supported) { + UnsolicitedEventsContext *ctx; + + ctx = g_new0 (UnsolicitedEventsContext, 1); + ctx->self = g_object_ref (self); + ctx->command = g_strdup ("+CMER=0"); + ctx->result = result; + run_unsolicited_events_setup (ctx); + return; + } + + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); } /*****************************************************************************/ @@ -7878,8 +7908,6 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface) iface->load_enabled_facility_locks_finish = modem_3gpp_load_enabled_facility_locks_finish; /* Enabling steps */ - iface->setup_indicators = modem_3gpp_setup_indicators; - iface->setup_indicators_finish = modem_3gpp_setup_indicators_finish; iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events; iface->setup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish; iface->enable_unsolicited_events = modem_3gpp_enable_unsolicited_events; diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c index de92f328..8d6c6ce0 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -30,13 +30,9 @@ #define SUBSYSTEM_3GPP "3gpp" -#define INDICATORS_CHECKED_TAG "3gpp-indicators-checked-tag" -#define UNSOLICITED_EVENTS_SUPPORTED_TAG "3gpp-unsolicited-events-supported-tag" #define REGISTRATION_STATE_CONTEXT_TAG "3gpp-registration-state-context-tag" #define REGISTRATION_CHECK_CONTEXT_TAG "3gpp-registration-check-context-tag" -static GQuark indicators_checked_quark; -static GQuark unsolicited_events_supported_quark; static GQuark registration_state_context_quark; static GQuark registration_check_context_quark; @@ -1113,41 +1109,25 @@ interface_disabling_step (DisablingContext *ctx) ctx->step++; case DISABLING_STEP_CLEANUP_UNSOLICITED_EVENTS: - if (G_UNLIKELY (!unsolicited_events_supported_quark)) - unsolicited_events_supported_quark = (g_quark_from_static_string ( - UNSOLICITED_EVENTS_SUPPORTED_TAG)); - - /* Only try to disable if supported */ - if (GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (ctx->self), - unsolicited_events_supported_quark))) { - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events ( - ctx->self, - (GAsyncReadyCallback)cleanup_unsolicited_events_ready, - ctx); - return; - } + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events ( + ctx->self, + (GAsyncReadyCallback)cleanup_unsolicited_events_ready, + ctx); + return; } /* Fall down to next step */ ctx->step++; case DISABLING_STEP_DISABLE_UNSOLICITED_EVENTS: - if (G_UNLIKELY (!unsolicited_events_supported_quark)) - unsolicited_events_supported_quark = (g_quark_from_static_string ( - UNSOLICITED_EVENTS_SUPPORTED_TAG)); - - /* Only try to disable if supported */ - if (GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (ctx->self), - unsolicited_events_supported_quark))) { - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_events && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_events_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_events ( - ctx->self, - (GAsyncReadyCallback)disable_unsolicited_events_ready, - ctx); - return; - } + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_events_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_events ( + ctx->self, + (GAsyncReadyCallback)disable_unsolicited_events_ready, + ctx); + return; } /* Fall down to next step */ ctx->step++; @@ -1179,7 +1159,6 @@ static void interface_enabling_step (EnablingContext *ctx); typedef enum { ENABLING_STEP_FIRST, - ENABLING_STEP_SETUP_INDICATORS, ENABLING_STEP_SETUP_UNSOLICITED_EVENTS, ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS, ENABLING_STEP_SETUP_UNSOLICITED_REGISTRATION, @@ -1276,36 +1255,6 @@ mm_iface_modem_3gpp_enable_finish (MMIfaceModem3gpp *self, } static void -setup_indicators_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - EnablingContext *ctx) -{ - GError *error = NULL; - - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->setup_indicators_finish (self, res, &error); - if (error) { - /* This error shouldn't be treated as critical */ - mm_dbg ("Indicator control setup failed: '%s'", error->message); - g_error_free (error); - - /* If we get an error setting up indicators, don't even bother trying to - * enable unsolicited events. */ - ctx->step = ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS + 1; - interface_enabling_step (ctx); - return; - } - - /* Indicators setup, so assume we support unsolicited events */ - g_object_set_qdata (G_OBJECT (self), - unsolicited_events_supported_quark, - GUINT_TO_POINTER (TRUE)); - - /* Go on to next step */ - ctx->step++; - interface_enabling_step (ctx); -} - -static void enable_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, EnablingContext *ctx) @@ -1317,11 +1266,6 @@ enable_unsolicited_events_ready (MMIfaceModem3gpp *self, /* This error shouldn't be treated as critical */ mm_dbg ("Enabling unsolicited events failed: '%s'", error->message); g_error_free (error); - - /* Reset support flag */ - g_object_set_qdata (G_OBJECT (self), - unsolicited_events_supported_quark, - GUINT_TO_POINTER (FALSE)); } /* Go on to next step */ @@ -1342,11 +1286,6 @@ setup_unsolicited_events_ready (MMIfaceModem3gpp *self, mm_dbg ("Setting up unsolicited events failed: '%s'", error->message); g_error_free (error); - /* Reset support flag */ - g_object_set_qdata (G_OBJECT (self), - unsolicited_events_supported_quark, - GUINT_TO_POINTER (FALSE)); - /* If we get an error setting up unsolicited events, don't even bother trying to * enable them. */ ctx->step = ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS + 1; @@ -1448,67 +1387,29 @@ interface_enabling_step (EnablingContext *ctx) switch (ctx->step) { case ENABLING_STEP_FIRST: - /* Setup quarks if we didn't do it before */ - if (G_UNLIKELY (!indicators_checked_quark)) - indicators_checked_quark = (g_quark_from_static_string ( - INDICATORS_CHECKED_TAG)); - if (G_UNLIKELY (!unsolicited_events_supported_quark)) - unsolicited_events_supported_quark = (g_quark_from_static_string ( - UNSOLICITED_EVENTS_SUPPORTED_TAG)); - /* Fall down to next step */ - ctx->step++; - - case ENABLING_STEP_SETUP_INDICATORS: - if (!GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (ctx->self), - indicators_checked_quark))) { - /* Set the checked flag so that we don't run it again */ - g_object_set_qdata (G_OBJECT (ctx->self), - indicators_checked_quark, - GUINT_TO_POINTER (TRUE)); - /* Initially, assume we don't support unsolicited events */ - g_object_set_qdata (G_OBJECT (ctx->self), - unsolicited_events_supported_quark, - GUINT_TO_POINTER (FALSE)); - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_indicators && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_indicators_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_indicators ( - ctx->self, - (GAsyncReadyCallback)setup_indicators_ready, - ctx); - return; - } - } /* Fall down to next step */ ctx->step++; case ENABLING_STEP_SETUP_UNSOLICITED_EVENTS: - /* Only try to setup unsolicited events if they are supported */ - if (GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (ctx->self), - unsolicited_events_supported_quark))) { - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_events && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_events_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_events ( - ctx->self, - (GAsyncReadyCallback)setup_unsolicited_events_ready, - ctx); - return; - } + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_events_finish) { + MM_IFACE_MODEM_3GPP_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: - /* Only try to enable unsolicited events if they are supported */ - if (GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (ctx->self), - unsolicited_events_supported_quark))) { - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_events && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_events_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_events ( - ctx->self, - (GAsyncReadyCallback)enable_unsolicited_events_ready, - ctx); - return; - } + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_events_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_events ( + ctx->self, + (GAsyncReadyCallback)enable_unsolicited_events_ready, + ctx); + return; } /* Fall down to next step */ ctx->step++; diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h index 779b82e1..12dc8bda 100644 --- a/src/mm-iface-modem-3gpp.h +++ b/src/mm-iface-modem-3gpp.h @@ -66,14 +66,6 @@ struct _MMIfaceModem3gpp { GAsyncResult *res, GError **error); - /* Asynchronous setup of indicators */ - void (*setup_indicators) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*setup_indicators_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - /* Asynchronous setting up unsolicited events */ void (*setup_unsolicited_events) (MMIfaceModem3gpp *self, GAsyncReadyCallback callback, |