diff options
Diffstat (limited to 'src/mm-generic-gsm.c')
-rw-r--r-- | src/mm-generic-gsm.c | 260 |
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; } |