diff options
author | Michael Biebl <biebl@debian.org> | 2011-08-07 01:47:27 +0200 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2014-02-05 08:38:27 +0100 |
commit | 95e75c9fd39d5c16c79add762ca578e0360509d6 (patch) | |
tree | 2f09dec06f41503d32a3deade89123ba3ce267c2 /src/mm-generic-cdma.c | |
parent | 59ed3390b9a798ff8bf9133cbc28c4539ad99f42 (diff) | |
parent | a09050a7f63a262bf90dcb1c7a41f9cfd205db43 (diff) |
Imported Debian patch 0.5-1debian/0.5-1
Diffstat (limited to 'src/mm-generic-cdma.c')
-rw-r--r-- | src/mm-generic-cdma.c | 167 |
1 files changed, 160 insertions, 7 deletions
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c index 378555b..11987a2 100644 --- a/src/mm-generic-cdma.c +++ b/src/mm-generic-cdma.c @@ -34,6 +34,15 @@ #define MM_GENERIC_CDMA_PREV_STATE_TAG "prev-state" +typedef enum { + RM_PROTO_ASYNC = 0, + RM_PROTO_RELAY = 1, + RM_PROTO_NETWORK_PPP = 2, + RM_PROTO_NETWORK_SLIP = 3, + RM_PROTO_STU_III = 4 +} RmProtocol; + + static void simple_reg_callback (MMModemCdma *modem, MMModemCdmaRegistrationState cdma_1x_reg_state, MMModemCdmaRegistrationState evdo_reg_state, @@ -67,6 +76,10 @@ typedef struct { gboolean has_spservice; gboolean has_speri; + /* Original and current Rm interface protocol */ + RmProtocol orig_crm; + RmProtocol cur_crm; + guint poll_id; char *meid; @@ -563,6 +576,29 @@ speri_done (MMAtSerialPort *port, } static void +crm_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + const char *p; + unsigned long num; + + if (error) + return; + + p = mm_strip_tag (response->str, "+CRM:"); + if (p) { + errno = 0; + num = strtoul (p, NULL, 10); + if (num >= 0 && num <= 4 && (errno == 0)) { + MM_GENERIC_CDMA_GET_PRIVATE (user_data)->orig_crm = (guint32) num; + MM_GENERIC_CDMA_GET_PRIVATE (user_data)->cur_crm = (guint32) num; + } + } +} + +static void enable_all_done (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = user_data; @@ -599,6 +635,9 @@ enable_all_done (MMModem *modem, GError *error, gpointer user_data) /* Check for support of Sprint-specific phone commands */ mm_at_serial_port_queue_command (priv->primary, "+SPSERVICE?", 3, spservice_done, self); mm_at_serial_port_queue_command (priv->primary, "$SPERI?", 3, speri_done, self); + + /* Grab default CRM */ + mm_at_serial_port_queue_command (priv->primary, "+CRM?", 3, crm_done, self); } out: @@ -1661,11 +1700,17 @@ real_query_registration_state (MMGenericCdma *self, /* Try Sprint-specific commands */ mm_at_serial_port_queue_command (port, "+SPSERVICE?", 3, reg_query_spservice_done, info); } else { - /* Assume we're registered on the 1x network if we passed +CAD, +CSS, - * and QCDM Call Manager checking. + /* Assume we're at least registered on the 1x network if we passed + * +CAD, +CSS, and QCDM Call Manager checking. But don't override a + * more specific registration state passed from a caller. + */ + if (cur_cdma_state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) + mm_generic_cdma_query_reg_state_set_callback_1x_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED); + + /* Don't touch EVDO state; it's already either UNKNOWN, or been set + * by generic checking earlier. */ - mm_generic_cdma_query_reg_state_set_callback_1x_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED); - mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN); + mm_callback_info_schedule (info); } } @@ -1960,12 +2005,63 @@ get_registration_state (MMModemCdma *modem, } /*****************************************************************************/ + +static void +set_rm_proto_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + + if (mm_callback_info_check_modem_removed (info) == FALSE) { + if (error) + info->error = g_error_copy (error); + + mm_callback_info_schedule (info); + } +} + +static void +mm_generic_cdma_set_rm_protocol (MMGenericCdma *self, + RmProtocol proto, + MMModemFn callback, + gpointer user_data) +{ + MMCallbackInfo *info; + MMAtSerialPort *port; + char *cmd; + + info = mm_callback_info_new (MM_MODEM (self), callback, user_data); + + port = mm_generic_cdma_get_best_at_port (self, &info->error); + if (!port) { + mm_callback_info_schedule (info); + return; + } + g_clear_error (&info->error); + + if (proto < RM_PROTO_ASYNC || proto > RM_PROTO_STU_III) { + g_set_error (&info->error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Invalid Rm interface protocol %d", + proto); + mm_callback_info_schedule (info); + return; + } + + cmd = g_strdup_printf ("+CRM=%d", proto); + mm_at_serial_port_queue_command (port, cmd, 3, set_rm_proto_done, info); + g_free (cmd); +} + +/*****************************************************************************/ /* MMModemSimple interface */ typedef enum { SIMPLE_STATE_BEGIN = 0, SIMPLE_STATE_ENABLE, SIMPLE_STATE_REGISTER, + SIMPLE_STATE_PRE_CONNECT, SIMPLE_STATE_CONNECT, SIMPLE_STATE_DONE } SimpleState; @@ -1991,6 +2087,32 @@ simple_get_string_property (MMCallbackInfo *info, const char *name, GError **err } static gboolean +simple_get_uint_property (MMCallbackInfo *info, + const char *name, + guint32 *out_val, + GError **error) +{ + GHashTable *properties = (GHashTable *) mm_callback_info_get_data (info, "simple-connect-properties"); + GValue *value; + + g_return_val_if_fail (out_val != NULL, FALSE); + + value = (GValue *) g_hash_table_lookup (properties, name); + if (value) { + if (G_VALUE_HOLDS_UINT (value)) { + *out_val = g_value_get_uint (value); + return TRUE; + } + + g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Invalid property type for '%s': %s (uint expected)", + name, G_VALUE_TYPE_NAME (value)); + } + + return FALSE; +} + +static gboolean simple_reg_retry (gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; @@ -2083,10 +2205,11 @@ static void simple_state_machine (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem); + MMGenericCdma *self; + MMGenericCdmaPrivate *priv; SimpleState state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "simple-connect-state")); const char *str; - guint id; + guint id, rm_protocol = 0; /* Do nothing if modem removed */ if (!modem || mm_callback_info_check_modem_removed (info)) @@ -2097,12 +2220,17 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data) goto out; } + self = MM_GENERIC_CDMA (info->modem); + priv = MM_GENERIC_CDMA_GET_PRIVATE (self); + switch (state) { case SIMPLE_STATE_BEGIN: + /* Enable state */ state = set_simple_state (info, SIMPLE_STATE_ENABLE); mm_modem_enable (modem, simple_state_machine, info); break; case SIMPLE_STATE_ENABLE: + /* Register state */ state = set_simple_state (info, SIMPLE_STATE_REGISTER); mm_modem_cdma_get_registration_state (MM_MODEM_CDMA (modem), simple_reg_callback, @@ -2114,14 +2242,34 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data) priv->reg_state_changed_id = id; break; case SIMPLE_STATE_REGISTER: + /* Pre Connect state */ registration_cleanup (MM_GENERIC_CDMA (modem), 0, 0); - state = set_simple_state (info, SIMPLE_STATE_CONNECT); + state = set_simple_state (info, SIMPLE_STATE_PRE_CONNECT); mm_modem_set_state (modem, MM_MODEM_STATE_REGISTERED, MM_MODEM_STATE_REASON_NONE); + /* Change the Rm interface protocol due to manager request if needed */ + if (simple_get_uint_property (info, "rm-protocol", &rm_protocol, &info->error)) { + mm_generic_cdma_set_rm_protocol (self, rm_protocol, simple_state_machine, info); + break; + } + + /* Or if the Rm protocol isn't the default, and there was no request + * to change it, do that now. + */ + if (priv->cur_crm != priv->orig_crm) { + mm_generic_cdma_set_rm_protocol (self, priv->orig_crm, simple_state_machine, info); + break; + } + + /* Fall through */ + case SIMPLE_STATE_PRE_CONNECT: + /* Connect state */ + state = set_simple_state (info, SIMPLE_STATE_CONNECT); str = simple_get_string_property (info, "number", &info->error); mm_modem_connect (modem, str, simple_state_machine, info); break; case SIMPLE_STATE_CONNECT: + /* All done! */ state = set_simple_state (info, SIMPLE_STATE_DONE); break; case SIMPLE_STATE_DONE: @@ -2306,10 +2454,15 @@ modem_simple_init (MMModemSimple *class) static void mm_generic_cdma_init (MMGenericCdma *self) { + MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self); + g_signal_connect (self, "notify::" MM_MODEM_VALID, G_CALLBACK (modem_valid_changed), NULL); g_signal_connect (self, "notify::" MM_MODEM_STATE, G_CALLBACK (modem_state_changed), NULL); + + /* Default to Network Layer Rm interface/PPP */ + priv->orig_crm = priv->cur_crm = RM_PROTO_NETWORK_PPP; } static void |