Implement registration information retrieving for GSM modems.
This commit is contained in:
@@ -116,6 +116,29 @@
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="GetRegistrationInfo">
|
||||
<tp:docstring>
|
||||
Get the registration status and the current operator (if registered).
|
||||
</tp:docstring>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_gsm_modem_get_reg_info"/>
|
||||
<arg name="status" type="u" direction="out" tp:type="MM_GSM_MODEM_REG_STATUS">
|
||||
<tp:docstring>
|
||||
The current network mode.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg name="operator_code" type="s" direction="out">
|
||||
<tp:docstring>
|
||||
The current operator code.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg name="operator_name" type="s" direction="out">
|
||||
<tp:docstring>
|
||||
The current operator name.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<signal name="SignalQuality">
|
||||
<tp:docstring>
|
||||
The signal quality changed.
|
||||
@@ -239,5 +262,38 @@
|
||||
</tp:enumvalue>
|
||||
</tp:enum>
|
||||
|
||||
<tp:enum name="MM_GSM_MODEM_REG_STATUS" type="u">
|
||||
<tp:enumvalue suffix="IDLE" value="0">
|
||||
<tp:docstring>
|
||||
Not registered, not searching for new operator to register.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="HOME" value="1">
|
||||
<tp:docstring>
|
||||
Registered on home network.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="SEARCHING" value="2">
|
||||
<tp:docstring>
|
||||
Not registered, searching for new operator to register with.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="DENIED" value="3">
|
||||
<tp:docstring>
|
||||
Registration denied.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="UNKNOWN" value="4">
|
||||
<tp:docstring>
|
||||
Unknown registration status.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="ROAMING" value="5">
|
||||
<tp:docstring>
|
||||
Registered on a roaming network.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
</tp:enum>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
|
@@ -248,43 +248,102 @@ register_manual (MMGsmModem *modem, const char *network_id, MMCallbackInfo *info
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
automatic_registration_again (gpointer data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) data;
|
||||
|
||||
register_auto (MM_GSM_MODEM (mm_callback_info_get_data (info, "modem")), info);
|
||||
|
||||
mm_callback_info_set_data (info, "modem", NULL, NULL);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
register_auto_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
get_reg_status_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_IDLE;
|
||||
break;
|
||||
case 1:
|
||||
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_HOME;
|
||||
break;
|
||||
case 2:
|
||||
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_SEARCHING;
|
||||
break;
|
||||
case 3:
|
||||
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_DENIED;
|
||||
break;
|
||||
case 4:
|
||||
info->uint_result = (guint32) MM_GSM_MODEM_REG_STATUS_ROAMING;
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
|
||||
"Reading registration status timed out");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
|
||||
"Reading registration status failed");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
get_registration_status (MMGsmModem *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 (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Reading registration status failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
automatic_registration_again (gpointer data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) data;
|
||||
|
||||
register_auto (MM_GSM_MODEM (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_GSM_MODEM_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 1:
|
||||
case MM_GSM_MODEM_REG_STATUS_HOME:
|
||||
g_message ("Registered on Home network");
|
||||
break;
|
||||
case 2:
|
||||
mm_callback_info_set_data (info, "modem", g_object_ref (serial), g_object_unref);
|
||||
MM_GENERIC_GSM_GET_PRIVATE (serial)->pending_id = g_timeout_add (1000, automatic_registration_again, info);
|
||||
case MM_GSM_MODEM_REG_STATUS_SEARCHING:
|
||||
MM_GENERIC_GSM_GET_PRIVATE (modem)->pending_id = g_timeout_add (1000, automatic_registration_again, info);
|
||||
return;
|
||||
break;
|
||||
case 3:
|
||||
case MM_GSM_MODEM_REG_STATUS_DENIED:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s",
|
||||
"Automatic registration failed: registration denied");
|
||||
break;
|
||||
case 4:
|
||||
case MM_GSM_MODEM_REG_STATUS_ROAMING:
|
||||
g_message ("Registered on Roaming network");
|
||||
break;
|
||||
case -1:
|
||||
@@ -295,24 +354,14 @@ register_auto_done (MMSerial *serial,
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
register_auto (MMGsmModem *modem, 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;
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CREG?"))
|
||||
id = mm_serial_wait_for_reply (MM_SERIAL (modem), 60, responses, terminators,
|
||||
register_auto_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Automatic registration failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
get_registration_status (modem, register_auto_done, info);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -331,6 +380,132 @@ do_register (MMGsmModem *modem,
|
||||
register_auto (modem, info);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
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,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (MM_MODEM (self), reg_info_callback_wrapper, 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);
|
||||
}
|
||||
|
||||
static void
|
||||
connect_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
@@ -623,6 +798,7 @@ gsm_modem_init (MMGsmModem *gsm_modem_class)
|
||||
{
|
||||
gsm_modem_class->set_pin = set_pin;
|
||||
gsm_modem_class->do_register = do_register;
|
||||
gsm_modem_class->get_registration_info = get_registration_info;
|
||||
gsm_modem_class->set_apn = set_apn;
|
||||
gsm_modem_class->scan = scan;
|
||||
gsm_modem_class->get_signal_quality = get_signal_quality;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
static void impl_gsm_modem_set_pin (MMGsmModem *modem, const char *pin, DBusGMethodInvocation *context);
|
||||
static void impl_gsm_modem_register (MMGsmModem *modem, const char *network_id, DBusGMethodInvocation *context);
|
||||
static void impl_gsm_modem_get_reg_info (MMGsmModem *modem, DBusGMethodInvocation *context);
|
||||
static void impl_gsm_modem_scan (MMGsmModem *modem, DBusGMethodInvocation *context);
|
||||
static void impl_gsm_modem_set_apn (MMGsmModem *modem, const char *apn, DBusGMethodInvocation *context);
|
||||
static void impl_gsm_modem_get_signal_quality (MMGsmModem *modem, DBusGMethodInvocation *context);
|
||||
@@ -131,6 +132,65 @@ impl_gsm_modem_register (MMGsmModem *modem,
|
||||
mm_gsm_modem_register (modem, id, async_call_done, context);
|
||||
}
|
||||
|
||||
static void
|
||||
reg_not_supported (MMModem *modem, GError *error, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
MMGsmModemRegInfoFn callback = (MMGsmModemRegInfoFn) mm_callback_info_get_data (info, "reg-info-callback");
|
||||
|
||||
callback (MM_GSM_MODEM (modem), 0, NULL, NULL, error, mm_callback_info_get_data (info, "reg-info-data"));
|
||||
}
|
||||
|
||||
void
|
||||
mm_gsm_modem_get_reg_info (MMGsmModem *self,
|
||||
MMGsmModemRegInfoFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_GSM_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_GSM_MODEM_GET_INTERFACE (self)->get_registration_info)
|
||||
MM_GSM_MODEM_GET_INTERFACE (self)->get_registration_info (self, callback, user_data);
|
||||
else {
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (MM_MODEM (self), reg_not_supported, user_data);
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
|
||||
"%s", "Operation not supported");
|
||||
|
||||
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);
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_reg_info_done (MMGsmModem *modem,
|
||||
NMGsmModemRegStatus status,
|
||||
const char *oper_code,
|
||||
const char *oper_name,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
|
||||
|
||||
if (error)
|
||||
dbus_g_method_return_error (context, error);
|
||||
else {
|
||||
dbus_g_method_return (context, status,
|
||||
oper_code ? oper_code : "",
|
||||
oper_name ? oper_name : "");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
impl_gsm_modem_get_reg_info (MMGsmModem *modem, DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_gsm_modem_get_reg_info (modem, get_reg_info_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_gsm_modem_scan (MMGsmModem *self,
|
||||
MMGsmModemScanFn callback,
|
||||
|
@@ -39,6 +39,15 @@ typedef enum {
|
||||
MM_GSM_MODEM_BAND_LAST = MM_GSM_MODEM_BAND_U17IX
|
||||
} MMGsmModemBand;
|
||||
|
||||
typedef enum {
|
||||
MM_GSM_MODEM_REG_STATUS_IDLE = 0,
|
||||
MM_GSM_MODEM_REG_STATUS_HOME = 1,
|
||||
MM_GSM_MODEM_REG_STATUS_SEARCHING = 2,
|
||||
MM_GSM_MODEM_REG_STATUS_DENIED = 3,
|
||||
MM_GSM_MODEM_REG_STATUS_UNKNOWN = 4,
|
||||
MM_GSM_MODEM_REG_STATUS_ROAMING = 5
|
||||
} NMGsmModemRegStatus;
|
||||
|
||||
typedef struct _MMGsmModem MMGsmModem;
|
||||
|
||||
typedef void (*MMGsmModemScanFn) (MMGsmModem *modem,
|
||||
@@ -46,6 +55,13 @@ typedef void (*MMGsmModemScanFn) (MMGsmModem *modem,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*MMGsmModemRegInfoFn) (MMGsmModem *modem,
|
||||
NMGsmModemRegStatus status,
|
||||
const char *oper_code,
|
||||
const char *oper_name,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
struct _MMGsmModem {
|
||||
GTypeInterface g_iface;
|
||||
|
||||
@@ -61,6 +77,10 @@ struct _MMGsmModem {
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*get_registration_info) (MMGsmModem *self,
|
||||
MMGsmModemRegInfoFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*scan) (MMGsmModem *self,
|
||||
MMGsmModemScanFn callback,
|
||||
gpointer user_data);
|
||||
@@ -112,6 +132,10 @@ void mm_gsm_modem_register (MMGsmModem *self,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_gsm_modem_get_reg_info (MMGsmModem *self,
|
||||
MMGsmModemRegInfoFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_gsm_modem_scan (MMGsmModem *self,
|
||||
MMGsmModemScanFn callback,
|
||||
gpointer user_data);
|
||||
|
Reference in New Issue
Block a user