diff options
Diffstat (limited to 'src/mm-broadband-modem.c')
-rw-r--r-- | src/mm-broadband-modem.c | 288 |
1 files changed, 158 insertions, 130 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; |