Grab the registration information right after a successful registration.

The registration information is stored now because in the generic case, it
is not possible to issue AT commands when the device is connected.
This commit is contained in:
Tambet Ingo
2008-08-22 14:50:02 +03:00
parent 91ac2260b7
commit 36b1ba72d4
4 changed files with 181 additions and 130 deletions

View File

@@ -14,6 +14,9 @@ static gpointer mm_generic_gsm_parent_class = NULL;
typedef struct {
char *driver;
char *oper_code;
char *oper_name;
MMGsmModemRegStatus reg_status;
guint32 cid;
guint32 pending_id;
} MMGenericGsmPrivate;
@@ -40,6 +43,33 @@ mm_generic_gsm_get_cid (MMGenericGsm *modem)
return MM_GENERIC_GSM_GET_PRIVATE (modem)->cid;
}
void
mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
MMGsmModemRegStatus status)
{
g_return_if_fail (MM_IS_GENERIC_GSM (modem));
MM_GENERIC_GSM_GET_PRIVATE (modem)->reg_status = status;
}
void
mm_generic_gsm_set_operator (MMGenericGsm *modem,
const char *code,
const char *name)
{
MMGenericGsmPrivate *priv;
g_return_if_fail (MM_IS_GENERIC_GSM (modem));
priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
g_free (priv->oper_code);
g_free (priv->oper_name);
priv->oper_code = g_strdup (code);
priv->oper_name = g_strdup (name);
}
/*****************************************************************************/
static void
@@ -206,44 +236,85 @@ set_pin (MMGsmModem *modem,
}
}
static char *
parse_operator (const char *reply)
{
char *operator = NULL;
if (reply && !strncmp (reply, "+COPS: ", 7)) {
/* Got valid reply */
GRegex *r;
GMatchInfo *match_info;
reply += 7;
r = g_regex_new ("(\\d),(\\d),\"(.+)\"", G_REGEX_UNGREEDY, 0, NULL);
if (!r)
return NULL;
g_regex_match (r, reply, 0, &match_info);
if (g_match_info_matches (match_info))
operator = g_match_info_fetch (match_info, 3);
g_match_info_free (match_info);
g_regex_unref (r);
}
return operator;
}
static void
register_manual_done (MMSerial *serial,
int reply_index,
gpointer user_data)
get_reg_name_done (MMSerial *serial, const char *reply, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *oper;
switch (reply_index) {
case 0:
/* success */
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;
}
oper = parse_operator (reply);
if (!oper)
g_warning ("Could not parse operator");
mm_generic_gsm_set_operator (MM_GENERIC_GSM (serial),
(char *) mm_callback_info_get_data (info, "reg-info-oper-code"),
oper);
g_free (oper);
mm_callback_info_schedule (info);
}
static void
register_manual (MMGsmModem *modem, const char *network_id, MMCallbackInfo *info)
get_reg_code_done (MMSerial *serial, const char *reply, gpointer user_data)
{
char *command;
char *responses[] = { "OK", "ERROR", "ERR", NULL };
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *oper;
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);
oper = parse_operator (reply);
if (oper) {
char *terminators = "\r\n";
g_free (command);
mm_callback_info_set_data (info, "reg-info-oper-code", oper, g_free);
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);
}
if (!id) {
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Manual registration failed.");
g_warning ("Could not read operator");
mm_callback_info_schedule (info);
}
}
static void
read_operator (MMGenericGsm *modem,
MMCallbackInfo *info)
{
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);
}
}
@@ -272,15 +343,19 @@ get_reg_status_done (MMSerial *serial,
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_ROAMING;
break;
case -1:
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_UNKNOWN;
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
"Reading registration status timed out");
break;
default:
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_UNKNOWN;
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
"Reading registration status failed");
break;
}
mm_generic_gsm_set_reg_status (MM_GENERIC_GSM (serial), info->uint_result);
mm_callback_info_schedule (info);
}
@@ -304,6 +379,64 @@ get_registration_status (MMGsmModem *modem, MMModemUIntFn callback, gpointer use
}
}
static void
register_manual_get_status_done (MMModem *modem,
guint32 result,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
if (result == MM_GSM_MODEM_REG_STATUS_HOME || result == MM_GSM_MODEM_REG_STATUS_ROAMING)
read_operator (MM_GENERIC_GSM (modem), info);
else
mm_callback_info_schedule (info);
}
static void
register_manual_done (MMSerial *serial,
int reply_index,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
switch (reply_index) {
case 0:
/* success */
get_registration_status (MM_GSM_MODEM (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)
mm_callback_info_schedule (info);
}
static void
register_manual (MMGsmModem *modem, 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)
{
@@ -355,7 +488,11 @@ register_auto_done (MMModem *modem,
}
out:
mm_callback_info_schedule (info);
if (info->error)
mm_callback_info_schedule (info);
else
read_operator (MM_GENERIC_GSM (modem), info);
}
static void
@@ -381,116 +518,22 @@ do_register (MMGsmModem *modem,
}
static char *
parse_operator (const char *reply)
{
char *operator = NULL;
if (reply && !strncmp (reply, "+COPS: ", 7)) {
/* Got valid reply */
GRegex *r;
GMatchInfo *match_info;
reply += 7;
r = g_regex_new ("(\\d),(\\d),\"(.+)\"", G_REGEX_UNGREEDY, 0, NULL);
if (!r)
return NULL;
g_regex_match (r, reply, 0, &match_info);
if (g_match_info_matches (match_info))
operator = g_match_info_fetch (match_info, 3);
g_match_info_free (match_info);
g_regex_unref (r);
}
return operator;
}
static void
reg_info_callback_wrapper (MMModem *modem,
GError *error,
gpointer user_data)
get_registration_info_done (MMModem *modem, GError *error, gpointer user_data)
{
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMGsmModemRegInfoFn reg_info_fn;
reg_info_fn = (MMGsmModemRegInfoFn) mm_callback_info_get_data (info, "reg-info-callback");
reg_info_fn (MM_GSM_MODEM (modem),
GPOINTER_TO_UINT (mm_callback_info_get_data (info, "reg-info-status")),
(char *) mm_callback_info_get_data (info, "reg-info-oper-code"),
(char *) mm_callback_info_get_data (info, "reg-info-oper-name"),
error,
priv->reg_status,
priv->oper_code,
priv->oper_name,
NULL,
mm_callback_info_get_data (info, "reg-info-data"));
}
static void
get_reg_name_done (MMSerial *serial, const char *reply, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *oper;
oper = parse_operator (reply);
if (oper)
mm_callback_info_set_data (info, "reg-info-oper-name", oper, g_free);
else
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not parse operator");
mm_callback_info_schedule (info);
}
static void
get_reg_code_done (MMSerial *serial, const char *reply, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *oper;
oper = parse_operator (reply);
if (oper) {
char *terminators = "\r\n";
guint id = 0;
mm_callback_info_set_data (info, "reg-info-oper-code", oper, g_free);
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);
if (!id)
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading operator name failed.");
} else
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not parse operator");
if (info->error)
mm_callback_info_schedule (info);
}
static void
get_reg_info_status_done (MMModem *modem,
guint32 result,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *terminators = "\r\n";
guint id = 0;
if (!error) {
mm_callback_info_set_data (info, "reg-info-status", GUINT_TO_POINTER (result), NULL);
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) {
if (error)
info->error = g_error_copy (error);
else
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
"Reading operator code failed.");
mm_callback_info_schedule (info);
}
}
static void
get_registration_info (MMGsmModem *self,
MMGsmModemRegInfoFn callback,
@@ -498,12 +541,12 @@ get_registration_info (MMGsmModem *self,
{
MMCallbackInfo *info;
info = mm_callback_info_new (MM_MODEM (self), reg_info_callback_wrapper, NULL);
info = mm_callback_info_new (MM_MODEM (self), get_registration_info_done, NULL);
info->user_data = info;
mm_callback_info_set_data (info, "reg-info-callback", callback, NULL);
mm_callback_info_set_data (info, "reg-info-data", user_data, NULL);
get_registration_status (self, get_reg_info_status_done, info);
mm_callback_info_schedule (info);
}
static void
@@ -858,6 +901,8 @@ finalize (GObject *object)
}
g_free (priv->driver);
g_free (priv->oper_code);
g_free (priv->oper_name);
G_OBJECT_CLASS (mm_generic_gsm_parent_class)->finalize (object);
}

View File

@@ -3,7 +3,7 @@
#ifndef MM_GENERIC_GSM_H
#define MM_GENERIC_GSM_H
#include "mm-modem.h"
#include "mm-gsm-modem.h"
#include "mm-serial.h"
#define MM_TYPE_GENERIC_GSM (mm_generic_gsm_get_type ())
@@ -27,5 +27,11 @@ MMModem *mm_generic_gsm_new (const char *serial_device,
const char *driver);
guint32 mm_generic_gsm_get_cid (MMGenericGsm *modem);
void mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
MMGsmModemRegStatus status);
void mm_generic_gsm_set_operator (MMGenericGsm *modem,
const char *code,
const char *name);
#endif /* MM_GENERIC_GSM_H */

View File

@@ -168,7 +168,7 @@ mm_gsm_modem_get_reg_info (MMGsmModem *self,
static void
get_reg_info_done (MMGsmModem *modem,
NMGsmModemRegStatus status,
MMGsmModemRegStatus status,
const char *oper_code,
const char *oper_name,
GError *error,

View File

@@ -46,7 +46,7 @@ typedef enum {
MM_GSM_MODEM_REG_STATUS_DENIED = 3,
MM_GSM_MODEM_REG_STATUS_UNKNOWN = 4,
MM_GSM_MODEM_REG_STATUS_ROAMING = 5
} NMGsmModemRegStatus;
} MMGsmModemRegStatus;
typedef struct _MMGsmModem MMGsmModem;
@@ -56,7 +56,7 @@ typedef void (*MMGsmModemScanFn) (MMGsmModem *modem,
gpointer user_data);
typedef void (*MMGsmModemRegInfoFn) (MMGsmModem *modem,
NMGsmModemRegStatus status,
MMGsmModemRegStatus status,
const char *oper_code,
const char *oper_name,
GError *error,