aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-08-06 01:32:03 -0500
committerDan Williams <dcbw@redhat.com>2010-08-06 01:32:03 -0500
commited9e056987a0d786178571aa859964badc043453 (patch)
tree7d89a529a9030c1b2b8a049fd49697b05271964c /src
parenta96e53368dfabf20f1bc3b8aecba2a64d60e198b (diff)
cdma: determine EVDO registration even when in 1X mode
Sometimes the primary mode will be 1X (and thus the Call Manager will report 1X system mode) but the HDR subsystem will be registered and idle. Figure that out and report that EVDO is registered too in that case, since the modem will just flip over to EVDO when the data call starts.
Diffstat (limited to 'src')
-rw-r--r--src/mm-generic-cdma.c149
1 files changed, 109 insertions, 40 deletions
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c
index df602bd5..b08c5eba 100644
--- a/src/mm-generic-cdma.c
+++ b/src/mm-generic-cdma.c
@@ -1667,58 +1667,79 @@ error:
}
static void
-reg_cmstate_cb (MMQcdmSerialPort *port,
- GByteArray *response,
- GError *error,
- gpointer user_data)
+reg_hdrstate_cb (MMQcdmSerialPort *port,
+ GByteArray *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = user_data;
- MMAtSerialPort *at_port;
- QCDMResult *result;
- guint32 opmode = 0, sysmode = 0;
+ QCDMResult *result = NULL;
+ guint32 sysmode;
MMModemCdmaRegistrationState cdma_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
MMModemCdmaRegistrationState evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
+ MMAtSerialPort *at_port;
+ gboolean evdo_registered = FALSE;
if (error)
goto error;
- /* Parse the response */
- result = qcdm_cmd_cm_subsys_state_info_result ((const char *) response->data, response->len, &info->error);
- if (!result)
- goto error;
+ sysmode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "sysmode"));
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, &opmode);
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, &sysmode);
- qcdm_result_unref (result);
+ /* Get HDR subsystem state to determine EVDO registration when in 1X mode */
+ result = qcdm_cmd_hdr_subsys_state_info_result ((const char *) response->data,
+ response->len,
+ &info->error);
+ if (result) {
+ guint8 session_state = QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_CLOSED;
+ guint8 almp_state = QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INACTIVE;
+ guint8 hybrid_mode = 0;
- if (opmode == QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE) {
- switch (sysmode) {
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_CDMA:
- cdma_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED;
- break;
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_HDR:
- evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED;
- break;
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_AMPS:
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_NO_SERVICE:
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA:
- default:
- break;
- }
+ if ( qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, &session_state)
+ && qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, &almp_state)
+ && qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, &hybrid_mode)) {
- if (cdma_state || evdo_state) {
- /* Device is registered to something; see if the subclass has a
- * better idea of whether we're roaming or not and what the
- * access technology is.
+ /* EVDO state is registered if the HDR subsystem is registered, and
+ * we're in hybrid mode, and the Call Manager system mode is
+ * CDMA.
*/
- if (MM_GENERIC_CDMA_GET_CLASS (info->modem)->query_registration_state) {
- MM_GENERIC_CDMA_GET_CLASS (info->modem)->query_registration_state (MM_GENERIC_CDMA (info->modem),
- cdma_state,
- evdo_state,
- subclass_reg_query_done,
- info);
- return;
- }
+ if ( hybrid_mode
+ && session_state == QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_OPEN
+ && ( almp_state == QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_IDLE
+ || almp_state == QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_CONNECTED))
+ evdo_registered = TRUE;
+ }
+
+ qcdm_result_unref (result);
+ }
+
+ switch (sysmode) {
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_CDMA:
+ cdma_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED;
+ if (evdo_registered)
+ evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED;
+ break;
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_HDR:
+ evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED;
+ break;
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_AMPS:
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_NO_SERVICE:
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA:
+ default:
+ break;
+ }
+
+ if (cdma_state || evdo_state) {
+ /* Device is registered to something; see if the subclass has a
+ * better idea of whether we're roaming or not and what the
+ * access technology is.
+ */
+ if (MM_GENERIC_CDMA_GET_CLASS (info->modem)->query_registration_state) {
+ MM_GENERIC_CDMA_GET_CLASS (info->modem)->query_registration_state (MM_GENERIC_CDMA (info->modem),
+ cdma_state,
+ evdo_state,
+ subclass_reg_query_done,
+ info);
+ return;
}
}
@@ -1737,6 +1758,54 @@ error:
}
static void
+reg_cmstate_cb (MMQcdmSerialPort *port,
+ GByteArray *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+ MMAtSerialPort *at_port = NULL;
+ QCDMResult *result = NULL;
+ guint32 opmode = 0, sysmode = 0;
+
+ /* Parse the response */
+ if (!error)
+ result = qcdm_cmd_cm_subsys_state_info_result ((const char *) response->data, response->len, &info->error);
+
+ if (!result) {
+ /* If there was some error, fall back to use +CAD like we did before QCDM */
+ if (info->modem)
+ at_port = mm_generic_cdma_get_best_at_port (MM_GENERIC_CDMA (info->modem), &info->error);
+ if (at_port)
+ mm_at_serial_port_queue_command (at_port, "+CAD?", 3, get_analog_digital_done, info);
+ else
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, &opmode);
+ qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, &sysmode);
+ qcdm_result_unref (result);
+
+ if (opmode == QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE) {
+ GByteArray *hdrstate;
+
+ mm_callback_info_set_data (info, "sysmode", GUINT_TO_POINTER (sysmode), NULL);
+
+ /* Get HDR subsystem state */
+ hdrstate = g_byte_array_sized_new (25);
+ hdrstate->len = qcdm_cmd_hdr_subsys_state_info_new ((char *) hdrstate->data, 25, NULL);
+ g_assert (hdrstate->len);
+ mm_qcdm_serial_port_queue_command (port, hdrstate, 3, reg_hdrstate_cb, info);
+ } else {
+ /* No service */
+ set_callback_1x_state_helper (info, MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
+ set_callback_evdo_state_helper (info, MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
+ mm_callback_info_schedule (info);
+ }
+}
+
+static void
get_registration_state (MMModemCdma *modem,
MMModemCdmaRegistrationStateFn callback,
gpointer user_data)