ports: add port initialization sequences instead of iface-modem's modem_init()

Instead of a custom modem_init() step in the 'Modem' interface, just add a
sequence of port initialization commands in each port.

While enabling for the first time a non-hotplugged modem, we will issue the
port initialization commands only after having run the enabling_modem_init()
step (i.e. after ATZ usually).
This commit is contained in:
Aleksander Morgado
2013-02-18 13:37:35 +01:00
parent be37f41f06
commit 1746949277
7 changed files with 138 additions and 269 deletions

View File

@@ -43,37 +43,6 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemIridium, mm_broadband_modem_iridium, MM_
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init));
/*****************************************************************************/
/* Initializing the modem (Modem interface) */
static const MMBaseModemAtCommand modem_init_sequence[] = {
/* Init command */
{ "E0 V1", 3, FALSE, NULL },
{ "+CMEE=1", 3, FALSE, NULL },
{ NULL }
};
static gboolean
modem_init_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return !!mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, error);
}
static void
modem_init (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
mm_base_modem_at_sequence (MM_BASE_MODEM (self),
modem_init_sequence,
NULL, /* response_processor_context */
NULL, /* response_processor_context_free */
callback,
user_data);
}
/*****************************************************************************/
/* Operator Code and Name loading (3GPP interface) */
@@ -338,6 +307,16 @@ create_bearer (MMIfaceModem *self,
/*****************************************************************************/
static const gchar *primary_init_sequence[] = {
/* Disable echo */
"E0",
/* Get word responses */
"V1",
/* Extended numeric codes */
"+CMEE=1",
NULL
};
static void
setup_ports (MMBroadbandModem *self)
{
@@ -354,6 +333,7 @@ setup_ports (MMBroadbandModem *self)
g_object_set (G_OBJECT (primary),
MM_SERIAL_PORT_BAUD, 9600,
MM_AT_SERIAL_PORT_INIT_SEQUENCE, primary_init_sequence,
NULL);
}
@@ -387,10 +367,6 @@ mm_broadband_modem_iridium_init (MMBroadbandModemIridium *self)
static void
iface_modem_init (MMIfaceModem *iface)
{
/* Initialization */
iface->modem_init = modem_init;
iface->modem_init_finish = modem_init_finish;
/* Create Iridium-specific SIM and bearer*/
iface->create_sim = create_sim;
iface->create_sim_finish = create_sim_finish;

View File

@@ -304,35 +304,6 @@ set_allowed_modes (MMIfaceModem *_self,
g_free (command);
}
/*****************************************************************************/
/* Initializing the modem (Modem interface) */
static gboolean
modem_init_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
/* Ignore errors */
mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, NULL);
return TRUE;
}
static void
modem_init (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
mm_base_modem_at_command_full (MM_BASE_MODEM (self),
mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
"E0 V1 X4 &C1 +CMEE=1",
3,
FALSE,
FALSE,
NULL, /* cancellable */
callback,
user_data);
}
/*****************************************************************************/
/* Initializing the modem (during first enabling) */
@@ -1128,8 +1099,6 @@ iface_modem_init (MMIfaceModem *iface)
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
iface->set_allowed_modes_finish = set_allowed_modes_finish;
iface->modem_init = modem_init;
iface->modem_init_finish = modem_init_finish;
iface->reset = reset;
iface->reset_finish = reset_finish;
iface->factory_reset = factory_reset;

View File

@@ -102,45 +102,6 @@ modem_load_supported_modes (MMIfaceModem *self,
g_object_unref (result);
}
/*****************************************************************************/
/* Modem initialization (Modem interface) */
static gboolean
modem_init_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return !mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, error);
}
static const MMBaseModemAtCommand modem_init_sequence[] = {
/* Also, when initializing a Nokia phone, first enable the echo,
* and then disable it, so that we get it properly disabled.
*/
{ "E1 E0 V1", 3, FALSE, NULL },
/* Setup errors */
{ "+CMEE=1", 3, FALSE, NULL },
/* Additional OPTIONAL initialization */
{ "X4 &C1", 3, FALSE, NULL },
{ NULL }
};
static void
modem_init (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
mm_base_modem_at_sequence (MM_BASE_MODEM (self),
modem_init_sequence,
NULL, /* response_processor_context */
NULL, /* response_processor_context_free */
callback,
user_data);
}
/*****************************************************************************/
/* Initializing the modem (during first enabling) */
@@ -235,6 +196,39 @@ enabling_modem_init (MMBroadbandModem *self,
retry_atz (ctx);
}
/*****************************************************************************/
/* Setup ports (Broadband modem class) */
static const gchar *primary_init_sequence[] = {
/* When initializing a Nokia port, first enable the echo,
* and then disable it, so that we get it properly disabled. */
"E1 E0",
/* Get word responses */
"V1",
/* Extended numeric codes */
"+CMEE=1",
/* Report all call status */
"X4",
/* Assert DCD when carrier detected */
"&C1",
NULL
};
static void
setup_ports (MMBroadbandModem *self)
{
MMAtSerialPort *primary;
/* Call parent's setup ports first always */
MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_nokia_parent_class)->setup_ports (self);
primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
g_object_set (primary,
MM_AT_SERIAL_PORT_INIT_SEQUENCE, primary_init_sequence,
NULL);
}
/*****************************************************************************/
MMBroadbandModemNokia *
@@ -269,10 +263,6 @@ iface_modem_messaging_init (MMIfaceModemMessaging *iface)
static void
iface_modem_init (MMIfaceModem *iface)
{
/* Setup custom modem init */
iface->modem_init = modem_init;
iface->modem_init_finish = modem_init_finish;
/* Create Nokia-specific SIM*/
iface->create_sim = create_sim;
iface->create_sim_finish = create_sim_finish;
@@ -302,6 +292,7 @@ mm_broadband_modem_nokia_class_init (MMBroadbandModemNokiaClass *klass)
{
MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass);
broadband_modem_class->setup_ports = setup_ports;
broadband_modem_class->enabling_modem_init = enabling_modem_init;
broadband_modem_class->enabling_modem_init_finish = enabling_modem_init_finish;
}

View File

@@ -7474,8 +7474,6 @@ iface_modem_init (MMIfaceModem *iface)
iface->load_power_state_finish = load_power_state_finish;
/* Enabling/disabling */
iface->modem_init = NULL;
iface->modem_init_finish = NULL;
iface->modem_power_up = modem_power_up;
iface->modem_power_up_finish = modem_power_up_down_finish;
iface->modem_after_power_up = NULL;

View File

@@ -2913,102 +2913,6 @@ modem_command (MMIfaceModem *self,
user_data);
}
/*****************************************************************************/
/* Initializing the modem (Modem interface) */
static gboolean
modem_init_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
static void
modem_init_sequence_ready (MMBaseModem *self,
GAsyncResult *res,
GSimpleAsyncResult *simple)
{
GError *error = NULL;
mm_base_modem_at_sequence_full_finish (MM_BASE_MODEM (self), res, NULL, &error);
if (error)
g_simple_async_result_take_error (simple, error);
else {
MMAtSerialPort *secondary;
/* Disable echo in secondary port as well, if any */
secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
if (secondary)
/* No need to wait for the reply */
mm_base_modem_at_command_full (MM_BASE_MODEM (self),
secondary,
"E0",
3,
FALSE,
FALSE, /* raw */
NULL, /* cancellable */
NULL,
NULL);
g_simple_async_result_set_op_res_gboolean (simple, TRUE);
}
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
static const MMBaseModemAtCommand modem_init_sequence[] = {
/* Ensure echo is off after the init command */
{ "E0 V1", 3, FALSE, NULL },
/* Some phones (like Blackberries) don't support +CMEE=1, so make it
* optional. It completely violates 3GPP TS 27.007 (9.1) but what can we do...
*/
{ "+CMEE=1", 3, FALSE, NULL },
/* Additional OPTIONAL initialization */
{ "X4 &C1", 3, FALSE, NULL },
{ NULL }
};
static void
modem_init (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMAtSerialPort *primary;
GSimpleAsyncResult *result;
result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
modem_init);
primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
if (!primary) {
g_simple_async_result_set_error (
result,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Need primary AT port to run modem init sequence");
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
return;
}
mm_base_modem_at_sequence_full (MM_BASE_MODEM (self),
primary,
modem_init_sequence,
NULL, /* response_processor_context */
NULL, /* response_processor_context_free */
NULL, /* cancellable */
(GAsyncReadyCallback)modem_init_sequence_ready,
result);
}
/*****************************************************************************/
/* IMEI loading (3GPP interface) */
@@ -7185,6 +7089,26 @@ enable_location_gathering (MMIfaceModemLocation *self,
/*****************************************************************************/
static const gchar *primary_init_sequence[] = {
/* Ensure echo is off */
"E0",
/* Get word responses */
"V1",
/* Extended numeric codes */
"+CMEE=1",
/* Report all call status */
"X4",
/* Assert DCD when carrier detected */
"&C1",
NULL
};
static const gchar *secondary_init_sequence[] = {
/* Ensure echo is off */
"E0",
NULL
};
static void
setup_ports (MMBroadbandModem *self)
{
@@ -7196,6 +7120,16 @@ setup_ports (MMBroadbandModem *self)
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
if (ports[0])
g_object_set (ports[0],
MM_AT_SERIAL_PORT_INIT_SEQUENCE, primary_init_sequence,
NULL);
if (ports[1])
g_object_set (ports[1],
MM_AT_SERIAL_PORT_INIT_SEQUENCE, secondary_init_sequence,
NULL);
/* Cleanup all unsolicited message handlers in all AT ports */
/* Set up CREG unsolicited message handlers, with NULL callbacks */
@@ -7466,6 +7400,7 @@ typedef struct {
MMBroadbandModem *self;
GSimpleAsyncResult *result;
PortsContext *ports;
gboolean modem_init_required;
} EnablingStartedContext;
static void
@@ -7475,7 +7410,7 @@ enabling_started_context_complete_and_free (EnablingStartedContext *ctx)
ports_context_unref (ctx->ports);
g_object_unref (ctx->result);
g_object_unref (ctx->self);
g_free (ctx);
g_slice_free (EnablingStartedContext, ctx);
}
static gboolean
@@ -7489,6 +7424,18 @@ enabling_started_finish (MMBroadbandModem *self,
static gboolean
enabling_after_modem_init_timeout (EnablingStartedContext *ctx)
{
/* Reset init sequence enabled flags and run them explicitly */
g_object_set (ctx->ports->primary,
MM_AT_SERIAL_PORT_INIT_SEQUENCE_ENABLED, TRUE,
NULL);
mm_at_serial_port_run_init_sequence (ctx->ports->primary);
if (ctx->ports->secondary) {
g_object_set (ctx->ports->secondary,
MM_AT_SERIAL_PORT_INIT_SEQUENCE_ENABLED, TRUE,
NULL);
mm_at_serial_port_run_init_sequence (ctx->ports->secondary);
}
/* Store enabled ports context and complete */
ctx->self->priv->enabled_ports_ctx = ports_context_ref (ctx->ports);
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
@@ -7529,18 +7476,8 @@ enabling_flash_done (MMSerialPort *port,
return;
}
/* Skip modem initialization if the device was hotplugged OR if we already
* did it (i.e. don't reinitialize if the modem got disabled and enabled
* again) */
if (ctx->self->priv->modem_init_run)
mm_dbg ("Skipping modem initialization: not first enabling");
else if (mm_base_modem_get_hotplugged (MM_BASE_MODEM (ctx->self))) {
ctx->self->priv->modem_init_run = TRUE;
mm_dbg ("Skipping modem initialization: device hotplugged");
} else if (!MM_BROADBAND_MODEM_GET_CLASS (ctx->self)->enabling_modem_init ||
!MM_BROADBAND_MODEM_GET_CLASS (ctx->self)->enabling_modem_init_finish)
mm_dbg ("Skipping modem initialization: not required");
else {
if (ctx->modem_init_required) {
mm_dbg ("Running modem initialization sequence...");
MM_BROADBAND_MODEM_GET_CLASS (ctx->self)->enabling_modem_init (ctx->self,
(GAsyncReadyCallback)enabling_modem_init_ready,
@@ -7557,6 +7494,7 @@ enabling_flash_done (MMSerialPort *port,
static gboolean
open_ports_enabling (MMBroadbandModem *self,
PortsContext *ctx,
gboolean modem_init_required,
GError **error)
{
/* Open primary */
@@ -7569,6 +7507,13 @@ open_ports_enabling (MMBroadbandModem *self,
return FALSE;
}
/* If we'll need to run modem initialization, disable port init sequence */
if (modem_init_required)
g_object_set (ctx->primary,
MM_AT_SERIAL_PORT_INIT_SEQUENCE_ENABLED, FALSE,
NULL);
if (!mm_serial_port_open (MM_SERIAL_PORT (ctx->primary), error)) {
g_prefix_error (error, "Couldn't open primary port: ");
return FALSE;
@@ -7579,6 +7524,11 @@ open_ports_enabling (MMBroadbandModem *self,
/* Open secondary (optional) */
ctx->secondary = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self));
if (ctx->secondary) {
/* If we'll need to run modem initialization, disable port init sequence */
if (modem_init_required)
g_object_set (ctx->secondary,
MM_AT_SERIAL_PORT_INIT_SEQUENCE_ENABLED, FALSE,
NULL);
if (!mm_serial_port_open (MM_SERIAL_PORT (ctx->secondary), error)) {
g_prefix_error (error, "Couldn't open secondary port: ");
return FALSE;
@@ -7607,7 +7557,7 @@ enabling_started (MMBroadbandModem *self,
GError *error = NULL;
EnablingStartedContext *ctx;
ctx = g_new0 (EnablingStartedContext, 1);
ctx = g_slice_new0 (EnablingStartedContext);
ctx->self = g_object_ref (self);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
@@ -7616,8 +7566,22 @@ enabling_started (MMBroadbandModem *self,
ctx->ports = g_new0 (PortsContext, 1);
ctx->ports->ref_count = 1;
/* Skip modem initialization if the device was hotplugged OR if we already
* did it (i.e. don't reinitialize if the modem got disabled and enabled
* again) */
if (ctx->self->priv->modem_init_run)
mm_dbg ("Skipping modem initialization: not first enabling");
else if (mm_base_modem_get_hotplugged (MM_BASE_MODEM (ctx->self))) {
ctx->self->priv->modem_init_run = TRUE;
mm_dbg ("Skipping modem initialization: device hotplugged");
} else if (!MM_BROADBAND_MODEM_GET_CLASS (ctx->self)->enabling_modem_init ||
!MM_BROADBAND_MODEM_GET_CLASS (ctx->self)->enabling_modem_init_finish)
mm_dbg ("Skipping modem initialization: not required");
else
ctx->modem_init_required = TRUE;
/* Enabling */
if (!open_ports_enabling (self, ctx->ports, &error)) {
if (!open_ports_enabling (self, ctx->ports, ctx->modem_init_required, &error)) {
g_prefix_error (&error, "Couldn't open ports during modem enabling: ");
g_simple_async_result_take_error (ctx->result, error);
enabling_started_context_complete_and_free (ctx);
@@ -9170,8 +9134,6 @@ iface_modem_init (MMIfaceModem *iface)
iface->load_power_state_finish = load_power_state_finish;
/* Enabling steps */
iface->modem_init = modem_init;
iface->modem_init_finish = modem_init_finish;
iface->modem_power_up = modem_power_up;
iface->modem_power_up_finish = modem_power_up_finish;
iface->setup_flow_control = modem_setup_flow_control;

View File

@@ -3004,7 +3004,6 @@ static void interface_enabling_step (EnablingContext *ctx);
typedef enum {
ENABLING_STEP_FIRST,
ENABLING_STEP_MODEM_INIT,
ENABLING_STEP_SET_POWER_STATE,
ENABLING_STEP_FLOW_CONTROL,
ENABLING_STEP_SUPPORTED_CHARSETS,
@@ -3058,29 +3057,6 @@ mm_iface_modem_enable_finish (MMIfaceModem *self,
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
#undef VOID_REPLY_READY_FN
#define VOID_REPLY_READY_FN(NAME) \
static void \
NAME##_ready (MMIfaceModem *self, \
GAsyncResult *res, \
EnablingContext *ctx) \
{ \
GError *error = NULL; \
\
MM_IFACE_MODEM_GET_INTERFACE (self)->NAME##_finish (self, res, &error); \
if (error) { \
g_simple_async_result_take_error (ctx->result, error); \
enabling_context_complete_and_free (ctx); \
return; \
} \
\
/* Go on to next step */ \
ctx->step++; \
interface_enabling_step (ctx); \
}
VOID_REPLY_READY_FN (modem_init);
static void
enabling_set_power_state_ready (MMIfaceModem *self,
GAsyncResult *res,
@@ -3099,7 +3075,24 @@ enabling_set_power_state_ready (MMIfaceModem *self,
interface_enabling_step (ctx);
}
VOID_REPLY_READY_FN (setup_flow_control);
static void
setup_flow_control_ready (MMIfaceModem *self,
GAsyncResult *res,
EnablingContext *ctx)
{
GError *error = NULL;
MM_IFACE_MODEM_GET_INTERFACE (self)->setup_flow_control_finish (self, res, &error);
if (error) {
g_simple_async_result_take_error (ctx->result, error);
enabling_context_complete_and_free (ctx);
return;
}
/* Go on to next step */
ctx->step++;
interface_enabling_step (ctx);
}
static void
load_supported_charsets_ready (MMIfaceModem *self,
@@ -3232,18 +3225,6 @@ interface_enabling_step (EnablingContext *ctx)
/* Fall down to next step */
ctx->step++;
case ENABLING_STEP_MODEM_INIT:
if (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_init &&
MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_init_finish) {
MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_init (
ctx->self,
(GAsyncReadyCallback)modem_init_ready,
ctx);
return;
}
/* Fall down to next step */
ctx->step++;
case ENABLING_STEP_SET_POWER_STATE:
mm_iface_modem_set_power_state (ctx->self,
MM_MODEM_POWER_STATE_ON,

View File

@@ -228,14 +228,6 @@ struct _MMIfaceModem {
GAsyncResult *res,
GError **error);
/* Asynchronous modem initialization operation */
void (*modem_init) (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*modem_init_finish) (MMIfaceModem *self,
GAsyncResult *res,
GError **error);
/* Asynchronous method to wait for the SIM to be ready after having
* unlocked it. */
void (*modem_after_sim_unlock) (MMIfaceModem *self,