broadband-modem: implement CDMA registration method

Will wait up to 60s to be registered in the CDMA network.
This commit is contained in:
Aleksander Morgado
2012-03-15 14:14:49 +01:00
parent 0b8ad70250
commit 787a651f19
+167
View File
@@ -111,6 +111,7 @@ struct _MMBroadbandModemPrivate {
MMModemCdmaRegistrationState modem_cdma_evdo_registration_state;
gboolean modem_cdma_cdma1x_network_supported;
gboolean modem_cdma_evdo_network_supported;
GCancellable *modem_cdma_pending_registration_cancellable;
/* Implementation helpers */
gboolean checked_sprint_support;
gboolean has_spservice;
@@ -3788,6 +3789,170 @@ modem_cdma_setup_registration_checks (MMIfaceModemCdma *self,
ctx);
}
/*****************************************************************************/
/* Register in network (CDMA interface) */
/* Maximum time to wait for a successful registration when polling
* periodically */
#define MAX_CDMA_REGISTRATION_CHECK_WAIT_TIME 60
typedef struct {
MMBroadbandModem *self;
GSimpleAsyncResult *result;
GCancellable *cancellable;
GTimer *timer;
} RegisterInCdmaNetworkContext;
static void
register_in_cdma_network_context_complete_and_free (RegisterInCdmaNetworkContext *ctx)
{
/* If our cancellable reference is still around, clear it */
if (ctx->self->priv->modem_cdma_pending_registration_cancellable ==
ctx->cancellable) {
g_clear_object (&ctx->self->priv->modem_cdma_pending_registration_cancellable);
}
if (ctx->timer)
g_timer_destroy (ctx->timer);
g_simple_async_result_complete (ctx->result);
g_object_unref (ctx->result);
g_object_unref (ctx->cancellable);
g_object_unref (ctx->self);
g_free (ctx);
}
static gboolean
modem_cdma_register_in_network_finish (MMIfaceModemCdma *self,
GAsyncResult *res,
GError **error)
{
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
#undef REG_IS_IDLE
#define REG_IS_IDLE(state) \
(state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)
#undef REG_IS_DONE
#define REG_IS_DONE(state) \
(state == MM_MODEM_CDMA_REGISTRATION_STATE_HOME || \
state == MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING || \
state == MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED)
static void run_all_cdma_registration_checks_ready (MMBroadbandModem *self,
GAsyncResult *res,
RegisterInCdmaNetworkContext *ctx);
static gboolean
run_all_cdma_registration_checks_again (RegisterInCdmaNetworkContext *ctx)
{
/* Get fresh registration state */
mm_iface_modem_cdma_run_all_registration_checks (
MM_IFACE_MODEM_CDMA (ctx->self),
(GAsyncReadyCallback)run_all_cdma_registration_checks_ready,
ctx);
return FALSE;
}
static void
run_all_cdma_registration_checks_ready (MMBroadbandModem *self,
GAsyncResult *res,
RegisterInCdmaNetworkContext *ctx)
{
GError *error = NULL;
mm_iface_modem_cdma_run_all_registration_checks_finish (MM_IFACE_MODEM_CDMA (self),
res,
&error);
if (error) {
mm_dbg ("CDMA registration check failed: '%s'", error->message);
mm_iface_modem_cdma_update_cdma1x_registration_state (
MM_IFACE_MODEM_CDMA (self),
MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN,
MM_MODEM_CDMA_SID_UNKNOWN,
MM_MODEM_CDMA_NID_UNKNOWN);
mm_iface_modem_cdma_update_evdo_registration_state (
MM_IFACE_MODEM_CDMA (self),
MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
g_simple_async_result_take_error (ctx->result, error);
register_in_cdma_network_context_complete_and_free (ctx);
return;
}
/* If we got registered in at least one CDMA network, end registration checks */
if (REG_IS_DONE (self->priv->modem_cdma_cdma1x_registration_state) ||
REG_IS_DONE (self->priv->modem_cdma_evdo_registration_state)) {
mm_dbg ("Modem is currently registered in a CDMA network "
"(CDMA1x: '%s', EV-DO: '%s')",
REG_IS_DONE (self->priv->modem_cdma_cdma1x_registration_state) ? "yes" : "no",
REG_IS_DONE (self->priv->modem_cdma_evdo_registration_state) ? "yes" : "no");
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
register_in_cdma_network_context_complete_and_free (ctx);
return;
}
/* Don't spend too much time waiting to get registered */
if (g_timer_elapsed (ctx->timer, NULL) > MAX_CDMA_REGISTRATION_CHECK_WAIT_TIME) {
mm_dbg ("CDMA registration check timed out");
mm_iface_modem_cdma_update_cdma1x_registration_state (
MM_IFACE_MODEM_CDMA (self),
MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN,
MM_MODEM_CDMA_SID_UNKNOWN,
MM_MODEM_CDMA_NID_UNKNOWN);
mm_iface_modem_cdma_update_evdo_registration_state (
MM_IFACE_MODEM_CDMA (self),
MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
g_simple_async_result_take_error (
ctx->result,
mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT));
register_in_cdma_network_context_complete_and_free (ctx);
return;
}
/* Check again in a few seconds. */
mm_dbg ("Modem not yet registered in a CDMA network... will recheck soon");
g_timeout_add_seconds (3,
(GSourceFunc)run_all_cdma_registration_checks_again,
ctx);
}
static void
modem_cdma_register_in_network (MMIfaceModemCdma *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMBroadbandModem *broadband = MM_BROADBAND_MODEM (self);
RegisterInCdmaNetworkContext *ctx;
/* (Try to) cancel previous registration request */
if (broadband->priv->modem_cdma_pending_registration_cancellable) {
g_cancellable_cancel (broadband->priv->modem_cdma_pending_registration_cancellable);
g_clear_object (&broadband->priv->modem_cdma_pending_registration_cancellable);
}
ctx = g_new0 (RegisterInCdmaNetworkContext, 1);
ctx->self = g_object_ref (self);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
modem_cdma_register_in_network);
ctx->cancellable = g_cancellable_new ();
/* Keep an accessible reference to the cancellable, so that we can cancel
* previous request when needed */
broadband->priv->modem_cdma_pending_registration_cancellable =
g_object_ref (ctx->cancellable);
/* Get fresh registration state */
ctx->timer = g_timer_new ();
mm_iface_modem_cdma_run_all_registration_checks (
MM_IFACE_MODEM_CDMA (self),
(GAsyncReadyCallback)run_all_cdma_registration_checks_ready,
ctx);
}
/*****************************************************************************/
typedef enum {
@@ -4730,6 +4895,8 @@ iface_modem_cdma_init (MMIfaceModemCdma *iface)
iface->get_detailed_registration_state_finish = modem_cdma_get_detailed_registration_state_finish;
/* Additional actions */
iface->register_in_network = modem_cdma_register_in_network;
iface->register_in_network_finish = modem_cdma_register_in_network_finish;
iface->bearer_new = mm_bearer_cdma_new;
iface->bearer_new_finish = mm_bearer_cdma_new_finish;
}