cinterion: update default setting for new SMS indications

The setup in Cinterion modems goes as follows:
  AT+CNMI=<mode>[, <mt>[, <bm>[, <ds>[, <bfr>]]]]

For each field, several setups are available, so we could use a default value,
as we were doing until now (+CNMI=2,1,2,2,1).

BUT, not every Cinterion modem allows the same set of settings. For example, the
new PHS8 only allows '0' for the <ds> value:
  AT+CNMI=?
  +CNMI: (0,1,2),(0,1),(0,2),(0),(1)

So, instead of hardcoding the setup, try to find the best suitable one for each
modem. We'll parse the +CNMI=? test response to know which values are supported
during the messaging support check, which is run once during initialization.
This commit is contained in:
Aleksander Morgado
2014-06-25 15:39:45 +02:00
parent 58d2806f4c
commit 9637c1ed38

View File

@@ -58,6 +58,13 @@ struct _MMBroadbandModemCinterionPrivate {
/* Cached supported bands in Cinterion format */
guint supported_bands;
/* Cached supported modes for SMS setup */
GArray *cnmi_supported_mode;
GArray *cnmi_supported_mt;
GArray *cnmi_supported_bm;
GArray *cnmi_supported_ds;
GArray *cnmi_supported_bfr;
};
/* Setup relationship between the band bitmask in the modem and the bitmask
@@ -120,24 +127,210 @@ messaging_enable_unsolicited_events_finish (MMIfaceModemMessaging *self,
GAsyncResult *res,
GError **error)
{
return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
static void
messaging_enable_unsolicited_events (MMIfaceModemMessaging *self,
cnmi_test_ready (MMBaseModem *self,
GAsyncResult *res,
GSimpleAsyncResult *simple)
{
GError *error = NULL;
mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (error)
g_simple_async_result_take_error (simple, error);
else
g_simple_async_result_set_op_res_gboolean (simple, TRUE);
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
static gboolean
value_supported (const GArray *array,
const guint value)
{
guint i;
if (!array)
return FALSE;
for (i = 0; i < array->len; i++) {
if (g_array_index (array, guint, i) == value)
return TRUE;
}
return FALSE;
}
static void
messaging_enable_unsolicited_events (MMIfaceModemMessaging *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
/* AT+CNMI=<mode>,[<mt>[,<bm>[,<ds>[,<bfr>]]]]
* but <bfr> should be either not set, or equal to 1;
* and <ds> can be only either 0 or 2 (EGS5)
*/
MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
GString *cmd;
GError *error = NULL;
GSimpleAsyncResult *simple;
simple = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
messaging_enable_unsolicited_events);
/* AT+CNMI=<mode>,[<mt>[,<bm>[,<ds>[,<bfr>]]]] */
cmd = g_string_new ("+CNMI=");
/* Mode 2 or 1 */
if (!error) {
if (value_supported (self->priv->cnmi_supported_mode, 2))
g_string_append_printf (cmd, "%u,", 2);
else if (value_supported (self->priv->cnmi_supported_mode, 1))
g_string_append_printf (cmd, "%u,", 1);
else
error = g_error_new (MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"SMS settings don't accept [2,1] <mode>");
}
/* mt 2 or 1 */
if (!error) {
if (value_supported (self->priv->cnmi_supported_mt, 2))
g_string_append_printf (cmd, "%u,", 2);
else if (value_supported (self->priv->cnmi_supported_mt, 1))
g_string_append_printf (cmd, "%u,", 1);
else
error = g_error_new (MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"SMS settings don't accept [2,1] <mt>");
}
/* bm 2 or 0 */
if (!error) {
if (value_supported (self->priv->cnmi_supported_bm, 2))
g_string_append_printf (cmd, "%u,", 2);
else if (value_supported (self->priv->cnmi_supported_bm, 0))
g_string_append_printf (cmd, "%u,", 0);
else
error = g_error_new (MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"SMS settings don't accept [2,0] <bm>");
}
/* ds 2, 1 or 0 */
if (!error) {
if (value_supported (self->priv->cnmi_supported_ds, 2))
g_string_append_printf (cmd, "%u,", 2);
if (value_supported (self->priv->cnmi_supported_ds, 1))
g_string_append_printf (cmd, "%u,", 1);
else if (value_supported (self->priv->cnmi_supported_ds, 0))
g_string_append_printf (cmd, "%u,", 0);
else
error = g_error_new (MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"SMS settings don't accept [2,1,0] <ds>");
}
/* bfr 1 */
if (!error) {
if (value_supported (self->priv->cnmi_supported_bfr, 1))
g_string_append_printf (cmd, "%u", 1);
/* otherwise, skip setting it */
}
/* Early error report */
if (error) {
g_simple_async_result_take_error (simple, error);
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
g_string_free (cmd, TRUE);
return;
}
mm_base_modem_at_command (MM_BASE_MODEM (self),
"+CNMI=2,1,2,2,1",
cmd->str,
3,
FALSE,
(GAsyncReadyCallback)cnmi_test_ready,
simple);
g_string_free (cmd, TRUE);
}
/*****************************************************************************/
/* Check if Messaging supported (Messaging interface) */
static gboolean
messaging_check_support_finish (MMIfaceModemMessaging *self,
GAsyncResult *res,
GError **error)
{
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
static void
cnmi_format_check_ready (MMBroadbandModemCinterion *self,
GAsyncResult *res,
GSimpleAsyncResult *simple)
{
GError *error = NULL;
const gchar *response;
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (error) {
g_simple_async_result_take_error (simple, error);
g_simple_async_result_complete (simple);
g_object_unref (simple);
return;
}
/* Parse */
if (!mm_cinterion_parse_cnmi_test (response,
&self->priv->cnmi_supported_mode,
&self->priv->cnmi_supported_mt,
&self->priv->cnmi_supported_bm,
&self->priv->cnmi_supported_ds,
&self->priv->cnmi_supported_bfr,
&error)) {
mm_warn ("error reading SMS setup: %s", error->message);
g_error_free (error);
}
/* CNMI command is supported; assume we have full messaging capabilities */
g_simple_async_result_set_op_res_gboolean (simple, TRUE);
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
static void
messaging_check_support (MMIfaceModemMessaging *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *result;
result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data);
user_data,
messaging_check_support);
/* We assume that CDMA-only modems don't have messaging capabilities */
if (mm_iface_modem_is_cdma_only (MM_IFACE_MODEM (self))) {
g_simple_async_result_set_error (
result,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"CDMA-only modems don't have messaging capabilities");
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
return;
}
/* Check CNMI support */
mm_base_modem_at_command (MM_BASE_MODEM (self),
"+CNMI=?",
3,
TRUE,
(GAsyncReadyCallback)cnmi_format_check_ready,
result);
}
/*****************************************************************************/
@@ -1500,6 +1693,17 @@ finalize (GObject *object)
g_free (self->priv->sleep_mode_cmd);
g_free (self->priv->manual_operator_id);
if (self->priv->cnmi_supported_mode)
g_array_unref (self->priv->cnmi_supported_mode);
if (self->priv->cnmi_supported_mt)
g_array_unref (self->priv->cnmi_supported_mt);
if (self->priv->cnmi_supported_bm)
g_array_unref (self->priv->cnmi_supported_bm);
if (self->priv->cnmi_supported_ds)
g_array_unref (self->priv->cnmi_supported_ds);
if (self->priv->cnmi_supported_bfr)
g_array_unref (self->priv->cnmi_supported_bfr);
G_OBJECT_CLASS (mm_broadband_modem_cinterion_parent_class)->finalize (object);
}
@@ -1544,6 +1748,8 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
static void
iface_modem_messaging_init (MMIfaceModemMessaging *iface)
{
iface->check_support = messaging_check_support;
iface->check_support_finish = messaging_check_support_finish;
iface->enable_unsolicited_events = messaging_enable_unsolicited_events;
iface->enable_unsolicited_events_finish = messaging_enable_unsolicited_events_finish;
}