aboutsummaryrefslogtreecommitdiff
path: root/src/mm-broadband-modem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-broadband-modem.c')
-rw-r--r--src/mm-broadband-modem.c288
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;