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.
This commit is contained in:
Dan Williams
2010-08-06 01:32:03 -05:00
parent a96e53368d
commit ed9e056987
+109 -40
View File
@@ -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)) {
/* 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 ( 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;
}
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;
}
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;
}
}
@@ -1736,6 +1757,54 @@ error:
mm_callback_info_schedule (info);
}
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,