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.c737
1 files changed, 279 insertions, 458 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index f7b7a178..88589ef7 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -6,8 +6,9 @@
#include "mm-generic-gsm.h"
#include "mm-modem-gsm-card.h"
#include "mm-modem-gsm-network.h"
-#include "mm-modem-error.h"
+#include "mm-errors.h"
#include "mm-callback-info.h"
+#include "mm-serial-parsers.h"
static gpointer mm_generic_gsm_parent_class = NULL;
@@ -22,7 +23,8 @@ typedef struct {
guint32 pending_id;
} MMGenericGsmPrivate;
-static void register_auto (MMModemGsmNetwork *modem, MMCallbackInfo *info);
+static void get_registration_status (MMSerial *serial, MMCallbackInfo *info);
+static void real_register (MMSerial *serial, const char *network_id, MMCallbackInfo *info);
MMModem *
mm_generic_gsm_new (const char *serial_device, const char *driver)
@@ -74,89 +76,23 @@ mm_generic_gsm_set_operator (MMGenericGsm *modem,
/*****************************************************************************/
static void
-check_pin_done (MMSerial *serial,
- int reply_index,
- gpointer user_data)
-{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- switch (reply_index) {
- case 0:
- /* success */
- break;
- case 1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_PIN_NEEDED, "%s", "PIN needed");
- break;
- case 2:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_PUK_NEEDED, "%s", "PUK needed");
- break;
- case -1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking timed out.");
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking failed.");
- break;
- }
-
- mm_callback_info_schedule (info);
-}
-
-static void
-check_pin (MMSerial *serial, gpointer user_data)
-{
- char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL };
- char *terminators[] = { "OK", "ERROR", "ERR", NULL };
- guint id = 0;
-
- if (mm_serial_send_command_string (serial, "AT+CPIN?"))
- id = mm_serial_wait_for_reply (serial, 3, responses, terminators, check_pin_done, user_data);
-
- if (!id) {
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking failed.");
- mm_callback_info_schedule (info);
- }
-}
-
-static void
init_done (MMSerial *serial,
- int reply_index,
+ GString *response,
+ GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- switch (reply_index) {
- case 0:
- /* success */
- check_pin (serial, user_data);
- break;
- case -1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Modem initialization timed out.");
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Modem initialization failed");
- }
+ if (error)
+ info->error = g_error_copy (error);
- if (info->error)
- mm_callback_info_schedule (info);
+ mm_callback_info_schedule (info);
}
static void
flash_done (MMSerial *serial, gpointer user_data)
{
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
- guint id = 0;
-
- if (mm_serial_send_command_string (serial, "ATZ E0"))
- id = mm_serial_wait_for_reply (serial, 10, responses, responses, init_done, user_data);
-
- if (!id) {
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Turning modem echo off failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (serial, "Z E0 V1 X4 &C1 +CMEE=1", 3, init_done, user_data);
}
static void
@@ -175,29 +111,25 @@ enable (MMModem *modem,
return;
}
- if (mm_serial_open (MM_SERIAL (modem))) {
- guint id;
-
- id = mm_serial_flash (MM_SERIAL (modem), 100, flash_done, info);
- if (!id)
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Could not communicate with serial device.");
- } else
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not open serial device.");
+ if (mm_serial_open (MM_SERIAL (modem), &info->error))
+ mm_serial_flash (MM_SERIAL (modem), 100, flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
}
static void
-get_string_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_string_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- if (reply)
- mm_callback_info_set_result (info, g_strdup (reply), g_free);
+ if (error)
+ info->error = g_error_copy (error);
else
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading information failed.");
+ mm_callback_info_set_result (info, g_strdup (response->str), g_free);
mm_callback_info_schedule (info);
}
@@ -208,18 +140,9 @@ get_imei (MMModemGsmCard *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- const char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CGSN"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 3, terminators, get_string_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading IMEI failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "+CGSN", 3, get_string_done, info);
}
static void
@@ -228,21 +151,11 @@ get_imsi (MMModemGsmCard *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- const char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CIMI"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 3, terminators, get_string_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading IMSI failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "+CIMI", 3, get_string_done, info);
}
-
static void
card_info_wrapper (MMModem *modem,
GError *error,
@@ -263,52 +176,47 @@ card_info_wrapper (MMModem *modem,
}
static void
-get_version_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_version_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- if (reply)
- mm_callback_info_set_data (info, "card-info-version", g_strdup (reply), g_free);
- else
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading version failed.");
-
+ if (!error)
+ mm_callback_info_set_data (info, "card-info-version", g_strdup (response->str), g_free);
+ else if (!info->error)
+ info->error = g_error_copy (error);
+
mm_callback_info_schedule (info);
}
static void
-get_model_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_model_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *terminators = "\r\n";
- guint id = 0;
-
- if (reply && mm_serial_send_command_string (serial, "AT+CGMR"))
- id = mm_serial_get_reply (serial, 5, terminators, get_version_done, info);
- if (id)
- mm_callback_info_set_data (info, "card-info-model", g_strdup (reply), g_free);
- else {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading model failed.");
- mm_callback_info_schedule (info);
- }
+ if (!error)
+ mm_callback_info_set_data (info, "card-info-model", g_strdup (response->str), g_free);
+ else if (!info->error)
+ info->error = g_error_copy (error);
}
static void
-get_manufacturer_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_manufacturer_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *terminators = "\r\n";
- guint id = 0;
- if (reply && mm_serial_send_command_string (serial, "AT+CGMM"))
- id = mm_serial_get_reply (serial, 5, terminators, get_model_done, info);
-
- if (id)
- mm_callback_info_set_data (info, "card-info-manufacturer", g_strdup (reply), g_free);
- else {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading manufacturer failed.");
- mm_callback_info_schedule (info);
- }
+ if (!error)
+ mm_callback_info_set_data (info, "card-info-manufacturer", g_strdup (response->str), g_free);
+ else
+ info->error = g_error_copy (error);
}
static void
@@ -317,43 +225,27 @@ get_card_info (MMModemGsmCard *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_new (MM_MODEM (modem), card_info_wrapper, NULL);
info->user_data = info;
mm_callback_info_set_data (info, "card-info-callback", callback, NULL);
mm_callback_info_set_data (info, "card-info-data", user_data, NULL);
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CGMI"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 5, terminators, get_manufacturer_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading card information failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "+CGMI", 3, get_manufacturer_done, info);
+ mm_serial_queue_command (MM_SERIAL (modem), "+CGMM", 3, get_model_done, info);
+ mm_serial_queue_command (MM_SERIAL (modem), "+CGMR", 3, get_version_done, info);
}
static void
send_pin_done (MMSerial *serial,
- int reply_index,
+ GString *response,
+ GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- switch (reply_index) {
- case 0:
- /* success */
- break;
- case -1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Did not receive response for secret");
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_INVALID_SECRET, "%s", "Invalid secret");
- break;
- }
-
+ if (error)
+ info->error = g_error_copy (error);
mm_callback_info_schedule (info);
}
@@ -365,21 +257,11 @@ send_pin (MMModemGsmCard *modem,
{
MMCallbackInfo *info;
char *command;
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
- guint id = 0;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
-
- command = g_strdup_printf ("AT+CPIN=\"%s\"", pin);
- if (mm_serial_send_command_string (MM_SERIAL (modem), command))
- id = mm_serial_wait_for_reply (MM_SERIAL (modem), 3, responses, responses, send_pin_done, info);
-
+ command = g_strdup_printf ("+CPIN=\"%s\"", pin);
+ mm_serial_queue_command (MM_SERIAL (modem), command, 3, send_pin_done, info);
g_free (command);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking failed.");
- mm_callback_info_schedule (info);
- }
}
static char *
@@ -409,244 +291,206 @@ parse_operator (const char *reply)
}
static void
-get_reg_name_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_reg_code_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *oper;
+ const char *reply = response->str;
- oper = parse_operator (reply);
- if (!oper)
- g_warning ("Could not parse operator");
+ if (!error) {
+ char *oper;
- mm_generic_gsm_set_operator (MM_GENERIC_GSM (serial),
- (char *) mm_callback_info_get_data (info, "reg-info-oper-code"),
- oper);
- g_free (oper);
+ oper = parse_operator (reply);
+ if (oper) {
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (serial);
- mm_callback_info_schedule (info);
+ g_free (priv->oper_code);
+ priv->oper_name = oper;
+ }
+ }
}
static void
-get_reg_code_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_reg_name_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *oper;
- guint id = 0;
+ const char *reply = response->str;
- oper = parse_operator (reply);
- if (oper) {
- char *terminators = "\r\n";
+ if (!error) {
+ char *oper;
- mm_callback_info_set_data (info, "reg-info-oper-code", oper, g_free);
+ oper = parse_operator (reply);
+ if (oper) {
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (serial);
- if (mm_serial_send_command_string (serial, "AT+COPS=3,0;+COPS?"))
- id = mm_serial_get_reply (MM_SERIAL (serial), 5, terminators, get_reg_name_done, info);
+ g_free (priv->oper_name);
+ priv->oper_name = oper;
+ }
}
+}
- if (!id) {
- g_warning ("Could not read operator");
+static gboolean
+reg_status_again (gpointer data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) data;
+ guint32 counter;
+
+ counter = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "reg-status-counter"));
+ if (counter > 60) {
+ /* That's 60 seconds */
+ info->error = g_error_new_literal (MM_MOBILE_ERROR,
+ MM_MOBILE_ERROR_NETWORK_TIMEOUT,
+ "Registration timed out");
mm_callback_info_schedule (info);
+ } else {
+ mm_callback_info_set_data (info, "reg-status-counter",
+ GUINT_TO_POINTER (++counter), NULL);
+ get_registration_status (MM_SERIAL (info->modem), info);
}
+
+ return TRUE;
}
static void
-read_operator (MMGenericGsm *modem,
- MMCallbackInfo *info)
+reg_status_remove (gpointer data)
{
- char *terminators = "\r\n";
- guint id = 0;
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+COPS=3,2;+COPS?"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 5, terminators, get_reg_code_done, info);
-
- if (!id) {
- g_warning ("Reading operator code failed.");
- mm_callback_info_schedule (info);
- }
+ g_source_remove (GPOINTER_TO_UINT (data));
}
static void
get_reg_status_done (MMSerial *serial,
- int reply_index,
+ GString *response,
+ GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- MMModemGsmNetworkRegStatus status;
+ const char *reply = response->str;
+ guint32 id;
+ gboolean done = FALSE;
- switch (reply_index) {
- case 0:
- status = MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE;
- break;
- case 1:
- status = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
- break;
- case 2:
- status = MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING;
- break;
- case 3:
- status = MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED;
- break;
- case 4:
- status = MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING;
- break;
- case -1:
- status = MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN;
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
- "Reading registration status timed out");
- break;
- default:
- status = MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN;
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
- "Reading registration status failed");
- break;
+ if (error) {
+ info->error = g_error_copy (error);
+ goto out;
}
- mm_generic_gsm_set_reg_status (MM_GENERIC_GSM (serial), status);
- mm_callback_info_set_result (info, GUINT_TO_POINTER (status), NULL);
-
- mm_callback_info_schedule (info);
-}
-
-static void
-get_registration_status (MMModemGsmNetwork *modem, MMModemUIntFn callback, gpointer user_data)
-{
- MMCallbackInfo *info;
- char *responses[] = { "+CREG: 0,0", "+CREG: 0,1", "+CREG: 0,2", "+CREG: 0,3", "+CREG: 0,5", NULL };
- char *terminators[] = { "OK", "ERROR", "ERR", NULL };
- guint id = 0;
-
- info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CREG?"))
- id = mm_serial_wait_for_reply (MM_SERIAL (modem), 60, responses, terminators,
- get_reg_status_done, info);
+ if (g_str_has_prefix (reply, "+CREG: ")) {
+ /* Got valid reply */
+ int n, stat;
+
+ if (sscanf (reply + 7, "%d,%d", &n, &stat)) {
+ MMModemGsmNetworkRegStatus status;
+
+ switch (stat) {
+ case 0:
+ status = MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE;
+ break;
+ case 1:
+ status = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
+ break;
+ case 2:
+ status = MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING;
+ break;
+ case 3:
+ status = MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED;
+ break;
+ case 4:
+ status = MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN;
+ break;
+ case 5:
+ status = MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING;
+ break;
+ default:
+ status = MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN;
+ break;
+ }
+
+ mm_generic_gsm_set_reg_status (MM_GENERIC_GSM (serial), status);
+
+ switch (status) {
+ case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
+ case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
+ /* Done */
+ mm_serial_queue_command (serial, "+COPS=3,2;+COPS?", 3, get_reg_code_done, NULL);
+ mm_serial_queue_command (serial, "+COPS=3,0;+COPS?", 3, get_reg_name_done, NULL);
+ done = TRUE;
+ break;
+ case MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE:
+ /* Huh? Stupid card, we already told it to register, tell again */
+ real_register (serial,
+ (char *) mm_callback_info_get_data (info, "reg-network-id"),
+ info);
+ break;
+ case MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING:
+ /* Wait more until the timeout expires. */
+ id = GPOINTER_TO_INT (mm_callback_info_get_data (info, "reg-status-timeout"));
+ if (!id) {
+ id = g_timeout_add (1000, reg_status_again, info);
+ mm_callback_info_set_data (info, "reg-status-timeout", GUINT_TO_POINTER (id),
+ reg_status_remove);
+ }
+ break;
+ case MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED:
+ info->error = g_error_new_literal (MM_MOBILE_ERROR,
+ MM_MOBILE_ERROR_NETWORK_NOT_ALLOWED,
+ "Network no allowed");
+ break;
+ case MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN:
+ default:
+ info->error = g_error_new_literal (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "Unknown network status");
+ break;
+ }
+ }
+ } else
+ info->error = g_error_new_literal (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "Could not parse the response");
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading registration status failed.");
+ out:
+ if (done || info->error)
mm_callback_info_schedule (info);
- }
}
static void
-register_manual_get_status_done (MMModem *modem,
- guint32 result,
- GError *error,
- gpointer user_data)
+get_registration_status (MMSerial *serial, MMCallbackInfo *info)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- if (result == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME || result == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)
- read_operator (MM_GENERIC_GSM (modem), info);
- else
- mm_callback_info_schedule (info);
+ g_debug ("Queueing +CREG");
+ mm_serial_queue_command (serial, "+CREG?", 3, get_reg_status_done, info);
}
static void
-register_manual_done (MMSerial *serial,
- int reply_index,
- gpointer user_data)
+register_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- switch (reply_index) {
- case 0:
- /* success */
- get_registration_status (MM_MODEM_GSM_NETWORK (serial), register_manual_get_status_done, info);
- break;
- case -1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Manual registration timed out");
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Manual registration failed");
- break;
- }
-
- if (info->error)
+ if (error) {
+ info->error = g_error_copy (error);
mm_callback_info_schedule (info);
+ } else
+ get_registration_status (serial, info);
}
static void
-register_manual (MMModemGsmNetwork *modem, const char *network_id, MMCallbackInfo *info)
+real_register (MMSerial *serial,
+ const char *network_id,
+ MMCallbackInfo *info)
{
char *command;
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
- guint id = 0;
-
- command = g_strdup_printf ("AT+COPS=1,2,\"%s\"", network_id);
- if (mm_serial_send_command_string (MM_SERIAL (modem), command))
- id = mm_serial_wait_for_reply (MM_SERIAL (modem), 30, responses, responses,
- register_manual_done, info);
-
- g_free (command);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Manual registration failed.");
- mm_callback_info_schedule (info);
- }
-}
-
-static gboolean
-automatic_registration_again (gpointer data)
-{
- MMCallbackInfo *info = (MMCallbackInfo *) data;
-
- register_auto (MM_MODEM_GSM_NETWORK (info->modem), info);
-
- return FALSE;
-}
-static void
-register_auto_done (MMModem *modem,
- guint result,
- GError *error,
- gpointer user_data)
-{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- if (error) {
- info->error = g_error_copy (error);
- goto out;
- }
-
- switch (result) {
- case MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Automatic registration failed: not registered and not searching.");
- break;
- case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
- g_message ("Registered on Home network");
- break;
- case MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING:
- MM_GENERIC_GSM_GET_PRIVATE (modem)->pending_id = g_timeout_add (1000, automatic_registration_again, info);
- return;
- break;
- case MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
- "Automatic registration failed: registration denied");
- break;
- case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
- g_message ("Registered on Roaming network");
- break;
- case -1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Automatic registration timed out");
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Automatic registration failed");
- break;
- }
-
- out:
-
- if (info->error)
- mm_callback_info_schedule (info);
+ if (network_id)
+ command = g_strdup_printf ("+COPS=1,2,\"%s\"", network_id);
else
- read_operator (MM_GENERIC_GSM (modem), info);
-}
+ command = g_strdup ("+COPS=0,,");
-static void
-register_auto (MMModemGsmNetwork *modem, MMCallbackInfo *info)
-{
- get_registration_status (modem, register_auto_done, info);
+ mm_serial_queue_command (serial, command, 60, register_done, info);
+ g_free (command);
}
static void
@@ -658,14 +502,11 @@ do_register (MMModemGsmNetwork *modem,
MMCallbackInfo *info;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
+ mm_callback_info_set_data (info, "reg-network-id", g_strdup (network_id), g_free);
- if (network_id)
- register_manual (modem, network_id, info);
- else
- register_auto (modem, info);
+ real_register (MM_SERIAL (modem), network_id, info);
}
-
static void
get_registration_info_done (MMModem *modem, GError *error, gpointer user_data)
{
@@ -698,37 +539,39 @@ get_registration_info (MMModemGsmNetwork *self,
}
static void
-connect_done (MMSerial *serial,
- int reply_index,
- gpointer user_data)
+connect_report_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- switch (reply_index) {
- case 0:
- /* success */
- break;
- case 1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: Busy");
- break;
- case 2:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: No dial tone");
- break;
- case 3:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: No carrier");
- break;
- case -1:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing timed out");
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing failed");
- break;
+ if (!error && g_str_has_prefix (response->str, "+CEER: ")) {
+ g_free (info->error->message);
+ info->error->message = g_strdup (response->str + 7); /* skip the "+CEER: " */
}
-
+
mm_callback_info_schedule (info);
}
static void
+connect_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (error) {
+ info->error = g_error_copy (error);
+ /* Try to get more information why it failed */
+ mm_serial_queue_command (serial, "+CEER", 3, connect_report_done, info);
+ } else
+ /* Done */
+ mm_callback_info_schedule (info);
+}
+
+static void
connect (MMModem *modem,
const char *number,
MMModemFn callback,
@@ -736,8 +579,6 @@ connect (MMModem *modem,
{
MMCallbackInfo *info;
char *command;
- char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
- guint id = 0;
guint32 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (modem));
info = mm_callback_info_new (modem, callback, user_data);
@@ -745,7 +586,7 @@ connect (MMModem *modem,
if (cid > 0) {
GString *str;
- str = g_string_new ("ATD");
+ str = g_string_new ("D");
if (g_str_has_suffix (number, "#"))
str = g_string_append_len (str, number, strlen (number) - 1);
else
@@ -754,17 +595,16 @@ connect (MMModem *modem,
g_string_append_printf (str, "***%d#", cid);
command = g_string_free (str, FALSE);
} else
- command = g_strconcat ("ATDT", number, NULL);
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), command))
- id = mm_serial_wait_for_reply (MM_SERIAL (modem), 60, responses, responses, connect_done, info);
+ command = g_strconcat ("DT", number, NULL);
+ mm_serial_queue_command (MM_SERIAL (modem), command, 60, connect_done, info);
g_free (command);
+}
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing failed.");
- mm_callback_info_schedule (info);
- }
+static void
+disconnect_flash_done (MMSerial *serial, gpointer user_data)
+{
+ mm_callback_info_schedule ((MMCallbackInfo *) user_data);
}
static void
@@ -775,8 +615,7 @@ disconnect (MMModem *modem,
MMCallbackInfo *info;
info = mm_callback_info_new (modem, callback, user_data);
- mm_serial_close (MM_SERIAL (modem));
- mm_callback_info_schedule (info);
+ mm_serial_flash (MM_SERIAL (modem), 1000, disconnect_flash_done, info);
}
static void
@@ -806,15 +645,19 @@ destroy_scan_data (gpointer data)
}
static void
-scan_done (MMSerial *serial, const char *reply, gpointer user_data)
+scan_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- GPtrArray *results;
+ char *reply = response->str;
- results = g_ptr_array_new ();
-
- if (reply && !strncmp (reply, "+COPS: ", 7)) {
+ if (error)
+ info->error = g_error_copy (error);
+ else if (!strncmp (reply, "+COPS: ", 7)) {
/* Got valid reply */
+ GPtrArray *results;
GRegex *r;
GMatchInfo *match_info;
GError *err = NULL;
@@ -830,6 +673,8 @@ scan_done (MMSerial *serial, const char *reply, gpointer user_data)
goto out;
}
+ results = g_ptr_array_new ();
+
g_regex_match (r, reply, 0, &match_info);
while (g_match_info_matches (match_info)) {
GHashTable *hash;
@@ -844,12 +689,10 @@ scan_done (MMSerial *serial, const char *reply, gpointer user_data)
g_match_info_next (match_info, NULL);
}
+ mm_callback_info_set_data (info, "scan-results", results, destroy_scan_data);
g_match_info_free (match_info);
g_regex_unref (r);
- } else
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not parse scan results");
-
- mm_callback_info_set_data (info, "scan-results", results, destroy_scan_data);
+ }
out:
mm_callback_info_schedule (info);
@@ -861,39 +704,27 @@ scan (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_new (MM_MODEM (modem), scan_callback_wrapper, NULL);
info->user_data = info;
mm_callback_info_set_data (info, "scan-callback", callback, NULL);
mm_callback_info_set_data (info, "scan-data", user_data, NULL);
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+COPS=?"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 60, terminators, scan_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Scanning failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "+COPS=?", 60, scan_done, info);
}
static void
set_apn_done (MMSerial *serial,
- int reply_index,
+ GString *response,
+ GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- switch (reply_index) {
- case 0:
- /* success */
+ if (error)
+ info->error = g_error_copy (error);
+ else
MM_GENERIC_GSM_GET_PRIVATE (serial)->cid = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "CID"));
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting APN failed");
- break;
- }
mm_callback_info_schedule (info);
}
@@ -906,32 +737,28 @@ set_apn (MMModemGsmNetwork *modem,
{
MMCallbackInfo *info;
char *command;
- char *responses[] = { "OK", "ERROR", NULL };
guint cid = 1;
- guint id = 0;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
mm_callback_info_set_data (info, "CID", GUINT_TO_POINTER (cid), NULL);
- command = g_strdup_printf ("AT+CGDCONT=%d, \"IP\", \"%s\"", cid, apn);
- if (mm_serial_send_command_string (MM_SERIAL (modem), command))
- id = mm_serial_wait_for_reply (MM_SERIAL (modem), 3, responses, responses, set_apn_done, info);
-
+ command = g_strdup_printf ("+CGDCONT=%d, \"IP\", \"%s\"", cid, apn);
+ mm_serial_queue_command (MM_SERIAL (modem), command, 3, set_apn_done, info);
g_free (command);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting APN failed.");
- mm_callback_info_schedule (info);
- }
}
static void
-get_signal_quality_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_signal_quality_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- guint32 result = 0;
+ char *reply = response->str;
- if (reply && !strncmp (reply, "+CSQ: ", 6)) {
+ if (error)
+ info->error = g_error_copy (error);
+ else if (!strncmp (reply, "+CSQ: ", 6)) {
/* Got valid reply */
int quality;
int ber;
@@ -942,15 +769,14 @@ get_signal_quality_done (MMSerial *serial, const char *reply, gpointer user_data
/* 99 means unknown */
if (quality != 99)
/* Normalize the quality */
- result = quality * 100 / 31;
+ quality = quality * 100 / 31;
+
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
} else
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"%s", "Could not parse signal quality results");
- } else
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Could not parse signal quality results");
+ }
- mm_callback_info_set_result (info, GUINT_TO_POINTER (result), NULL);
mm_callback_info_schedule (info);
}
@@ -960,18 +786,9 @@ get_signal_quality (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CSQ"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, get_signal_quality_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Getting signal quality failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "+CSQ", 3, get_signal_quality_done, info);
}
/*****************************************************************************/
@@ -1006,6 +823,10 @@ modem_gsm_network_init (MMModemGsmNetwork *class)
static void
mm_generic_gsm_init (MMGenericGsm *self)
{
+ mm_serial_set_response_parser (MM_SERIAL (self),
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
}
static void