aboutsummaryrefslogtreecommitdiff
path: root/src/mm-generic-gsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-generic-gsm.c')
-rw-r--r--src/mm-generic-gsm.c260
1 files changed, 181 insertions, 79 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 7f28dd5c..98713b0d 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -33,7 +33,7 @@
#include "mm-qcdm-serial-port.h"
#include "mm-serial-parsers.h"
#include "mm-modem-helpers.h"
-#include "mm-options.h"
+#include "mm-log.h"
#include "mm-properties-changed-signal.h"
#include "mm-utils.h"
#include "mm-modem-location.h"
@@ -471,10 +471,8 @@ get_iccid_done (MMModem *modem,
g_free (priv->simid);
priv->simid = g_strdup (g_checksum_get_string (sum));
- if (mm_options_debug ()) {
- g_debug ("SIM ID source '%s'", response);
- g_debug ("SIM ID '%s'", priv->simid);
- }
+ mm_dbg ("SIM ID source '%s'", response);
+ mm_dbg ("SIM ID '%s'", priv->simid);
g_object_notify (G_OBJECT (modem), MM_MODEM_GSM_CARD_SIM_IDENTIFIER);
@@ -990,6 +988,57 @@ periodic_poll_cb (gpointer user_data)
return TRUE; /* continue running */
}
+#define CREG_NUM_TAG "creg-num"
+#define CGREG_NUM_TAG "cgreg-num"
+
+static void
+initial_unsolicited_reg_check_done (MMCallbackInfo *info)
+{
+ MMGenericGsmPrivate *priv;
+ guint creg_num, cgreg_num;
+
+ if (!info->modem || info->error)
+ goto done;
+
+ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+ if (!priv->secondary)
+ goto done;
+
+ /* Enable unsolicited registration responses on secondary ports too,
+ * to ensure that we get the response even if the modem is connected
+ * on the primary port. We enable responses on both ports because we
+ * cannot trust modems to reliably send the responses on the port we
+ * enable them on.
+ */
+
+ creg_num = GPOINTER_TO_UINT (mm_callback_info_get_data (info, CREG_NUM_TAG));
+ switch (creg_num) {
+ case 1:
+ mm_at_serial_port_queue_command (priv->secondary, "+CREG=1", 3, NULL, NULL);
+ break;
+ case 2:
+ mm_at_serial_port_queue_command (priv->secondary, "+CREG=2", 3, NULL, NULL);
+ break;
+ default:
+ break;
+ }
+
+ cgreg_num = GPOINTER_TO_UINT (mm_callback_info_get_data (info, CGREG_NUM_TAG));
+ switch (cgreg_num) {
+ case 1:
+ mm_at_serial_port_queue_command (priv->secondary, "+CGREG=1", 3, NULL, NULL);
+ break;
+ case 2:
+ mm_at_serial_port_queue_command (priv->secondary, "+CGREG=2", 3, NULL, NULL);
+ break;
+ default:
+ break;
+ }
+
+done:
+ mm_callback_info_schedule (info);
+}
+
static void
cgreg1_done (MMAtSerialPort *port,
GString *response,
@@ -1007,11 +1056,14 @@ cgreg1_done (MMAtSerialPort *port,
/* The modem doesn't like unsolicited CGREG, so we'll need to poll */
priv->cgreg_poll = TRUE;
- }
+ } else
+ mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (1), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem);
}
- mm_callback_info_schedule (info);
+
+ initial_unsolicited_reg_check_done (info);
}
static void
@@ -1032,11 +1084,13 @@ cgreg2_done (MMAtSerialPort *port,
} else {
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
+ mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (2), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem);
/* All done */
- mm_callback_info_schedule (info);
+ initial_unsolicited_reg_check_done (info);
}
} else {
/* Modem got removed */
@@ -1061,7 +1115,9 @@ creg1_done (MMAtSerialPort *port,
/* The modem doesn't like unsolicited CREG, so we'll need to poll */
priv->creg_poll = TRUE;
- }
+ } else
+ mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (1), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem);
@@ -1090,6 +1146,8 @@ creg2_done (MMAtSerialPort *port,
} else {
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
+ mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (2), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem);
@@ -1240,8 +1298,15 @@ cmer_cb (MMAtSerialPort *port,
GError *error,
gpointer user_data)
{
- if (!error)
- MM_GENERIC_GSM_GET_PRIVATE (user_data)->cmer_enabled = TRUE;
+ if (!error) {
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
+
+ priv->cmer_enabled = TRUE;
+
+ /* Enable CMER on the secondary port if we can too */
+ if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
+ mm_at_serial_port_queue_command (priv->secondary, "+CMER=3,0,0,1", 3, NULL, NULL);
+ }
}
static void
@@ -1306,12 +1371,9 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self,
*/
if (priv->secondary) {
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &error)) {
- if (mm_options_debug ()) {
- g_warning ("%s: error opening secondary port: (%d) %s",
- __func__,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- }
+ mm_dbg ("error opening secondary port: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
}
}
@@ -1524,11 +1586,16 @@ disable_flash_done (MMSerialPort *port,
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
/* Disable unsolicited messages */
- mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "AT+CREG=0", 3, NULL, NULL);
- mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "AT+CGREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "+CREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "+CGREG=0", 3, NULL, NULL);
if (priv->cmer_enabled) {
mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "+CMER=0", 3, NULL, NULL);
+
+ /* And on the secondary port */
+ if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
+ mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, NULL, NULL);
+
priv->cmer_enabled = FALSE;
}
@@ -1541,6 +1608,15 @@ disable_flash_done (MMSerialPort *port,
}
static void
+secondary_unsolicited_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ mm_serial_port_close_force (MM_SERIAL_PORT (port));
+}
+
+static void
disable (MMModem *modem,
MMModemFn callback,
gpointer user_data)
@@ -1575,9 +1651,12 @@ disable (MMModem *modem,
update_lac_ci (self, 0, 0, 1);
_internal_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
- /* Close the secondary port if its open */
- if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
- mm_serial_port_close_force (MM_SERIAL_PORT (priv->secondary));
+ /* Clean up the secondary port if it's open */
+ if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) {
+ mm_at_serial_port_queue_command (priv->secondary, "+CREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (priv->secondary, "+CGREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, secondary_unsolicited_done, NULL);
+ }
info = mm_callback_info_new (modem, callback, user_data);
@@ -2237,7 +2316,7 @@ roam_disconnect_done (MMModem *modem,
GError *error,
gpointer user_data)
{
- g_message ("Disconnected because roaming is not allowed");
+ mm_info ("Disconnected because roaming is not allowed");
}
static void
@@ -2268,9 +2347,9 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *self,
if (priv->reg_status[rs_type - 1] == status)
return;
- g_debug ("%s registration state changed: %d",
- (rs_type == MM_GENERIC_GSM_REG_TYPE_CS) ? "CS" : "PS",
- status);
+ mm_dbg ("%s registration state changed: %d",
+ (rs_type == MM_GENERIC_GSM_REG_TYPE_CS) ? "CS" : "PS",
+ status);
priv->reg_status[rs_type - 1] = status;
port = mm_generic_gsm_get_best_at_port (self, NULL);
@@ -2389,11 +2468,8 @@ reg_state_changed (MMAtSerialPort *port,
GError *error = NULL;
if (!mm_gsm_parse_creg_response (match_info, &state, &lac, &cell_id, &act, &cgreg, &error)) {
- if (mm_options_debug ()) {
- g_warning ("%s: error parsing unsolicited registration: %s",
- __func__,
- error && error->message ? error->message : "(unknown)");
- }
+ mm_warn ("error parsing unsolicited registration: %s",
+ error && error->message ? error->message : "(unknown)");
return;
}
@@ -3830,10 +3906,10 @@ ussd_update_state (MMGenericGsm *self, MMModemGsmUssdState new_state)
}
static void
-ussd_initiate_done (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
+ussd_send_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMGenericGsmPrivate *priv;
@@ -3860,10 +3936,7 @@ ussd_initiate_done (MMAtSerialPort *port,
case 0: /* no further action required */
ussd_state = MM_MODEM_GSM_USSD_STATE_IDLE;
break;
- case 1: /* Not an error but not yet implemented */
- info->error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Further action required.");
+ case 1: /* further action required */
ussd_state = MM_MODEM_GSM_USSD_STATE_USER_RESPONSE;
break;
case 2:
@@ -3894,10 +3967,8 @@ ussd_initiate_done (MMAtSerialPort *port,
if (reply) {
/* look for the reply data coding scheme */
- if (mm_options_debug ()) {
- if ((start = strrchr (end, ',')) != NULL)
- g_debug ("USSD data coding scheme %d", atoi (start + 1));
- }
+ if ((start = strrchr (end, ',')) != NULL)
+ mm_dbg ("USSD data coding scheme %d", atoi (start + 1));
converted = mm_modem_charset_hex_to_utf8 (reply, priv->cur_charset);
mm_callback_info_set_result (info, converted, g_free);
@@ -3919,10 +3990,10 @@ done:
}
static void
-ussd_initiate (MMModemGsmUssd *modem,
- const char *command,
- MMModemStringFn callback,
- gpointer user_data)
+ussd_send (MMModemGsmUssd *modem,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data)
{
MMCallbackInfo *info;
char *atc_command;
@@ -3947,13 +4018,57 @@ ussd_initiate (MMModemGsmUssd *modem,
atc_command = g_strdup_printf ("+CUSD=1,\"%s\",15", hex);
g_free (hex);
- mm_at_serial_port_queue_command (port, atc_command, 10, ussd_initiate_done, info);
+ mm_at_serial_port_queue_command (port, atc_command, 10, ussd_send_done, info);
g_free (atc_command);
ussd_update_state (MM_GENERIC_GSM (modem), MM_MODEM_GSM_USSD_STATE_ACTIVE);
}
static void
+ussd_initiate (MMModemGsmUssd *modem,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
+
+ if (priv->ussd_state != MM_MODEM_GSM_USSD_STATE_IDLE) {
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "USSD session already active.");
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ ussd_send (modem, command, callback, user_data);
+ return;
+}
+
+static void
+ussd_respond (MMModemGsmUssd *modem,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
+
+ if (priv->ussd_state != MM_MODEM_GSM_USSD_STATE_USER_RESPONSE) {
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "No active USSD session, cannot respond.");
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ ussd_send (modem, command, callback, user_data);
+ return;
+}
+
+static void
ussd_cancel_done (MMAtSerialPort *port,
GString *response,
GError *error,
@@ -4123,6 +4238,7 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data)
gboolean done = FALSE;
MMModemGsmAllowedMode allowed_mode;
gboolean home_only = FALSE;
+ char *data_device;
info->error = mm_modem_check_removed (modem, error);
if (info->error)
@@ -4130,16 +4246,9 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data)
priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
- if (mm_options_debug ()) {
- GTimeVal tv;
- char *data_device;
-
- g_object_get (G_OBJECT (modem), MM_MODEM_DATA_DEVICE, &data_device, NULL);
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s): simple connect state %d",
- tv.tv_sec, tv.tv_usec, data_device, state);
- g_free (data_device);
- }
+ g_object_get (G_OBJECT (modem), MM_MODEM_DATA_DEVICE, &data_device, NULL);
+ mm_dbg ("(%s): simple connect state %d", data_device, state);
+ g_free (data_device);
switch (state) {
case SIMPLE_STATE_CHECK_PIN:
@@ -4238,29 +4347,21 @@ simple_connect (MMModemSimple *simple,
gpointer user_data)
{
MMCallbackInfo *info;
+ GHashTableIter iter;
+ gpointer key, value;
+ char *data_device;
- /* If debugging, list all the simple connect properties */
- if (mm_options_debug ()) {
- GHashTableIter iter;
- gpointer key, value;
- GTimeVal tv;
- char *data_device;
-
- g_object_get (G_OBJECT (simple), MM_MODEM_DATA_DEVICE, &data_device, NULL);
- g_get_current_time (&tv);
-
- g_hash_table_iter_init (&iter, properties);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- char *val_str;
-
- val_str = g_strdup_value_contents ((GValue *) value);
- g_debug ("<%ld.%ld> (%s): %s => %s",
- tv.tv_sec, tv.tv_usec,
- data_device, (const char *) key, val_str);
- g_free (val_str);
- }
- g_free (data_device);
+ /* List simple connect properties when debugging */
+ g_object_get (G_OBJECT (simple), MM_MODEM_DATA_DEVICE, &data_device, NULL);
+ g_hash_table_iter_init (&iter, properties);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ char *val_str;
+
+ val_str = g_strdup_value_contents ((GValue *) value);
+ mm_dbg ("(%s): %s => %s", data_device, (const char *) key, val_str);
+ g_free (val_str);
}
+ g_free (data_device);
info = mm_callback_info_new (MM_MODEM (simple), callback, user_data);
mm_callback_info_set_data (info, "simple-connect-properties",
@@ -4633,6 +4734,7 @@ static void
modem_gsm_ussd_init (MMModemGsmUssd *class)
{
class->initiate = ussd_initiate;
+ class->respond = ussd_respond;
class->cancel = ussd_cancel;
}