core: new `Initializing' state in the global modem state machine

We need to define a state to be used while the modem is being initialized, so
that we forbid any operation on the modem on already exported interfaces, while
there are interfaces pending to get exported.

This Initializing state will also cover the state between having the SIM
unlocked (which launches re-initialization) and being completely initialized.
This commit is contained in:
Aleksander Morgado
2012-03-16 14:53:24 +01:00
parent 6de2e3f72c
commit d27e40ae9a
6 changed files with 140 additions and 47 deletions
+12 -10
View File
@@ -93,6 +93,7 @@ typedef enum { /*< underscore_name=mm_modem_lock >*/
/** /**
* MMModemState: * MMModemState:
* @MM_MODEM_STATE_UNKNOWN: State unknown or not reportable. * @MM_MODEM_STATE_UNKNOWN: State unknown or not reportable.
* @MM_MODEM_STATE_INITIALIZING: The modem is currently being initialized.
* @MM_MODEM_STATE_LOCKED: The modem needs to be unlocked. * @MM_MODEM_STATE_LOCKED: The modem needs to be unlocked.
* @MM_MODEM_STATE_DISABLED: The modem is not enabled and is powered down. * @MM_MODEM_STATE_DISABLED: The modem is not enabled and is powered down.
* @MM_MODEM_STATE_DISABLING: The modem is currently transitioning to the @MM_MODEM_STATE_DISABLED state. * @MM_MODEM_STATE_DISABLING: The modem is currently transitioning to the @MM_MODEM_STATE_DISABLED state.
@@ -108,16 +109,17 @@ typedef enum { /*< underscore_name=mm_modem_lock >*/
*/ */
typedef enum { /*< underscore_name=mm_modem_state >*/ typedef enum { /*< underscore_name=mm_modem_state >*/
MM_MODEM_STATE_UNKNOWN = 0, MM_MODEM_STATE_UNKNOWN = 0,
MM_MODEM_STATE_LOCKED = 1, MM_MODEM_STATE_INITIALIZING = 1,
MM_MODEM_STATE_DISABLED = 2, MM_MODEM_STATE_LOCKED = 2,
MM_MODEM_STATE_DISABLING = 3, MM_MODEM_STATE_DISABLED = 3,
MM_MODEM_STATE_ENABLING = 4, MM_MODEM_STATE_DISABLING = 4,
MM_MODEM_STATE_ENABLED = 5, MM_MODEM_STATE_ENABLING = 5,
MM_MODEM_STATE_SEARCHING = 6, MM_MODEM_STATE_ENABLED = 6,
MM_MODEM_STATE_REGISTERED = 7, MM_MODEM_STATE_SEARCHING = 7,
MM_MODEM_STATE_DISCONNECTING = 8, MM_MODEM_STATE_REGISTERED = 8,
MM_MODEM_STATE_CONNECTING = 9, MM_MODEM_STATE_DISCONNECTING = 9,
MM_MODEM_STATE_CONNECTED = 10 MM_MODEM_STATE_CONNECTING = 10,
MM_MODEM_STATE_CONNECTED = 11
} MMModemState; } MMModemState;
/** /**
+62 -10
View File
@@ -6066,6 +6066,7 @@ disable (MMBaseModem *self,
g_assert_not_reached (); g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_INITIALIZING:
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_LOCKED:
case MM_MODEM_STATE_DISABLED: case MM_MODEM_STATE_DISABLED:
/* Just return success, don't relaunch enabling */ /* Just return success, don't relaunch enabling */
@@ -6338,6 +6339,14 @@ enable (MMBaseModem *self,
g_assert_not_reached (); g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_INITIALIZING:
g_simple_async_result_set_error (result,
MM_CORE_ERROR,
MM_CORE_ERROR_WRONG_STATE,
"Cannot enable modem: "
"device not fully initialized yet");
break;
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_LOCKED:
g_simple_async_result_set_error (result, g_simple_async_result_set_error (result,
MM_CORE_ERROR, MM_CORE_ERROR,
@@ -6663,6 +6672,12 @@ initialize_step (InitializeContext *ctx)
case INITIALIZE_STEP_LAST: case INITIALIZE_STEP_LAST:
/* All initialized without errors! */ /* All initialized without errors! */
/* Set as disabled (a.k.a. initialized) */
mm_iface_modem_update_state (MM_IFACE_MODEM (ctx->self),
MM_MODEM_STATE_DISABLED,
MM_MODEM_STATE_CHANGE_REASON_UNKNOWN);
g_simple_async_result_set_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (ctx->result), TRUE); g_simple_async_result_set_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (ctx->result), TRUE);
initialize_context_complete_and_free (ctx); initialize_context_complete_and_free (ctx);
return; return;
@@ -6677,18 +6692,55 @@ initialize (MMBaseModem *self,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
InitializeContext *ctx; GSimpleAsyncResult *result;
ctx = g_new0 (InitializeContext, 1); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, initialize);
ctx->self = g_object_ref (self);
ctx->cancellable = g_object_ref (cancellable);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
initialize);
ctx->step = INITIALIZE_STEP_FIRST;
initialize_step (ctx); /* Check state before launching modem initialization */
switch (MM_BROADBAND_MODEM (self)->priv->modem_state) {
case MM_MODEM_STATE_UNKNOWN:
case MM_MODEM_STATE_LOCKED: {
InitializeContext *ctx;
ctx = g_new0 (InitializeContext, 1);
ctx->self = g_object_ref (self);
ctx->cancellable = g_object_ref (cancellable);
ctx->result = result;
ctx->step = INITIALIZE_STEP_FIRST;
/* Set as being initialized, even if we were locked before */
mm_iface_modem_update_state (MM_IFACE_MODEM (self),
MM_MODEM_STATE_INITIALIZING,
MM_MODEM_STATE_CHANGE_REASON_UNKNOWN);
initialize_step (ctx);
return;
}
case MM_MODEM_STATE_INITIALIZING:
g_simple_async_result_set_error (result,
MM_CORE_ERROR,
MM_CORE_ERROR_WRONG_STATE,
"Cannot initialize modem: "
"already being initialized");
break;
case MM_MODEM_STATE_DISABLED:
case MM_MODEM_STATE_DISABLING:
case MM_MODEM_STATE_ENABLING:
case MM_MODEM_STATE_ENABLED:
case MM_MODEM_STATE_SEARCHING:
case MM_MODEM_STATE_REGISTERED:
case MM_MODEM_STATE_DISCONNECTING:
case MM_MODEM_STATE_CONNECTING:
case MM_MODEM_STATE_CONNECTED:
/* Just return success, don't relaunch initialization */
g_simple_async_result_set_op_res_gboolean (result, TRUE);
break;
}
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
} }
/*****************************************************************************/ /*****************************************************************************/
+20 -4
View File
@@ -173,11 +173,19 @@ handle_register_auth_ready (MMBaseModem *self,
g_assert_not_reached (); g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_INITIALIZING:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_WRONG_STATE, MM_CORE_ERROR_WRONG_STATE,
"Cannot register modem: device locked"); "Cannot register modem: "
"device not fully initialized yet");
handle_register_context_free (ctx);
return;
case MM_MODEM_STATE_LOCKED:
/* We should never have such request in LOCKED state
* (interface wasn't exported yet) */
g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_ENABLED: case MM_MODEM_STATE_ENABLED:
@@ -358,11 +366,19 @@ handle_scan_auth_ready (MMBaseModem *self,
g_assert_not_reached (); g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_INITIALIZING:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_WRONG_STATE, MM_CORE_ERROR_WRONG_STATE,
"Cannot scan networks: device locked"); "Cannot scan networks: "
"device not fully initialized yet");
handle_scan_context_free (ctx);
return;
case MM_MODEM_STATE_LOCKED:
/* We should never have such request in LOCKED state
* (interface wasn't exported yet) */
g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_DISABLED: case MM_MODEM_STATE_DISABLED:
+18 -4
View File
@@ -135,12 +135,19 @@ handle_activate_auth_ready (MMBaseModem *self,
g_assert_not_reached (); g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_INITIALIZING:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_WRONG_STATE, MM_CORE_ERROR_WRONG_STATE,
"Cannot perform OTA activation: " "Cannot perform OTA activation: "
"device locked"); "device not fully initialized yet");
handle_activate_context_free (ctx);
return;
case MM_MODEM_STATE_LOCKED:
/* We should never have such request in LOCKED state
* (interface wasn't exported yet) */
g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_ENABLED: case MM_MODEM_STATE_ENABLED:
@@ -278,12 +285,19 @@ handle_activate_manual_auth_ready (MMBaseModem *self,
g_assert_not_reached (); g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_INITIALIZING:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_WRONG_STATE, MM_CORE_ERROR_WRONG_STATE,
"Cannot perform manual activation: " "Cannot perform manual activation: "
"device locked"); "device not fully initialized yet");
handle_activate_manual_context_free (ctx);
return;
case MM_MODEM_STATE_LOCKED:
/* We should never have such request in LOCKED state
* (interface wasn't exported yet) */
g_assert_not_reached ();
break; break;
case MM_MODEM_STATE_ENABLED: case MM_MODEM_STATE_ENABLED:
+19 -15
View File
@@ -985,10 +985,11 @@ mm_iface_modem_update_state (MMIfaceModem *self,
NULL); NULL);
/* Signal status change */ /* Signal status change */
mm_gdbus_modem_emit_state_changed (skeleton, if (skeleton)
old_state, mm_gdbus_modem_emit_state_changed (skeleton,
new_state, old_state,
reason); new_state,
reason);
/* If we go to registered state (from unregistered), setup signal /* If we go to registered state (from unregistered), setup signal
* quality and access technologies periodic retrieval */ * quality and access technologies periodic retrieval */
@@ -1287,6 +1288,7 @@ handle_reset_auth_ready (MMBaseModem *self,
switch (modem_state) { switch (modem_state) {
case MM_MODEM_STATE_UNKNOWN: case MM_MODEM_STATE_UNKNOWN:
case MM_MODEM_STATE_INITIALIZING:
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_LOCKED:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
@@ -1399,6 +1401,7 @@ handle_factory_reset_auth_ready (MMBaseModem *self,
switch (modem_state) { switch (modem_state) {
case MM_MODEM_STATE_UNKNOWN: case MM_MODEM_STATE_UNKNOWN:
case MM_MODEM_STATE_INITIALIZING:
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_LOCKED:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
@@ -1662,6 +1665,7 @@ handle_set_bands_auth_ready (MMBaseModem *self,
switch (modem_state) { switch (modem_state) {
case MM_MODEM_STATE_UNKNOWN: case MM_MODEM_STATE_UNKNOWN:
case MM_MODEM_STATE_INITIALIZING:
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_LOCKED:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
@@ -1905,6 +1909,7 @@ handle_set_allowed_modes_auth_ready (MMBaseModem *self,
switch (modem_state) { switch (modem_state) {
case MM_MODEM_STATE_UNKNOWN: case MM_MODEM_STATE_UNKNOWN:
case MM_MODEM_STATE_INITIALIZING:
case MM_MODEM_STATE_LOCKED: case MM_MODEM_STATE_LOCKED:
g_dbus_method_invocation_return_error (ctx->invocation, g_dbus_method_invocation_return_error (ctx->invocation,
MM_CORE_ERROR, MM_CORE_ERROR,
@@ -2000,10 +2005,13 @@ static void
reinitialize_ready (MMBaseModem *self, reinitialize_ready (MMBaseModem *self,
GAsyncResult *res) GAsyncResult *res)
{ {
mm_base_modem_initialize_finish (self, res, NULL); GError *error = NULL;
mm_iface_modem_update_state (MM_IFACE_MODEM (self),
MM_MODEM_STATE_DISABLED, mm_base_modem_initialize_finish (self, res, &error);
MM_MODEM_STATE_CHANGE_REASON_UNKNOWN); if (error) {
mm_warn ("Modem reinitialization failed: '%s'", error->message);
g_error_free (error);
}
} }
static gboolean static gboolean
@@ -2030,23 +2038,19 @@ set_lock_status (MMIfaceModem *self,
if (lock == MM_MODEM_LOCK_NONE || if (lock == MM_MODEM_LOCK_NONE ||
lock == MM_MODEM_LOCK_SIM_PIN2 || lock == MM_MODEM_LOCK_SIM_PIN2 ||
lock == MM_MODEM_LOCK_SIM_PUK2) { lock == MM_MODEM_LOCK_SIM_PUK2) {
/* Notify transition from UNKNOWN/LOCKED to DISABLED */ /* Notify transition from INITIALIZING/LOCKED to DISABLED */
if (old_lock != MM_MODEM_LOCK_NONE && if (old_lock != MM_MODEM_LOCK_NONE &&
old_lock != MM_MODEM_LOCK_SIM_PIN2 && old_lock != MM_MODEM_LOCK_SIM_PIN2 &&
old_lock != MM_MODEM_LOCK_SIM_PUK2) { old_lock != MM_MODEM_LOCK_SIM_PUK2) {
/* Only restart initialization if going from LOCKED to DISABLED. /* Only restart initialization if leaving LOCKED.
* If this is the case, we do NOT update the state yet, we wait * If this is the case, we do NOT update the state yet, we wait
* to be completely re-initialized to do so. */ * to be completely re-initialized to do so. */
if (old_lock != MM_MODEM_LOCK_UNKNOWN) if (old_lock != MM_MODEM_LOCK_UNKNOWN)
g_idle_add ((GSourceFunc)restart_initialize_idle, self); g_idle_add ((GSourceFunc)restart_initialize_idle, self);
else
mm_iface_modem_update_state (self,
MM_MODEM_STATE_DISABLED,
MM_MODEM_STATE_CHANGE_REASON_UNKNOWN);
} }
} else { } else {
if (old_lock == MM_MODEM_LOCK_UNKNOWN) { if (old_lock == MM_MODEM_LOCK_UNKNOWN) {
/* Notify transition from UNKNOWN to LOCKED */ /* Notify transition from INITIALIZING to LOCKED */
mm_iface_modem_update_state (self, mm_iface_modem_update_state (self,
MM_MODEM_STATE_LOCKED, MM_MODEM_STATE_LOCKED,
MM_MODEM_STATE_CHANGE_REASON_UNKNOWN); MM_MODEM_STATE_CHANGE_REASON_UNKNOWN);
+9 -4
View File
@@ -489,11 +489,15 @@ typedef struct {
MMSim *self; MMSim *self;
GSimpleAsyncResult *result; GSimpleAsyncResult *result;
GError *save_error; GError *save_error;
gulong wait_for_unlock_id;
} SendPinPukContext; } SendPinPukContext;
static void static void
send_pin_puk_context_complete_and_free (SendPinPukContext *ctx) send_pin_puk_context_complete_and_free (SendPinPukContext *ctx)
{ {
if (ctx->wait_for_unlock_id)
g_signal_handler_disconnect (ctx->self->priv->modem,
ctx->wait_for_unlock_id);
if (ctx->save_error) if (ctx->save_error)
g_error_free (ctx->save_error); g_error_free (ctx->save_error);
g_simple_async_result_complete (ctx->result); g_simple_async_result_complete (ctx->result);
@@ -568,16 +572,17 @@ unlock_check_ready (MMIfaceModem *modem,
g_simple_async_result_take_error (ctx->result, ctx->save_error); g_simple_async_result_take_error (ctx->result, ctx->save_error);
ctx->save_error = NULL; ctx->save_error = NULL;
g_clear_error (&error); g_clear_error (&error);
} } else if (error)
else if (error)
g_simple_async_result_take_error (ctx->result, error); g_simple_async_result_take_error (ctx->result, error);
else else
g_simple_async_result_take_error (ctx->result, g_simple_async_result_take_error (ctx->result,
error_for_unlock_check (lock)); error_for_unlock_check (lock));
} else send_pin_puk_context_complete_and_free (ctx);
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); }
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
send_pin_puk_context_complete_and_free (ctx); send_pin_puk_context_complete_and_free (ctx);
return;
} }
static void static void