aboutsummaryrefslogtreecommitdiff
path: root/src/mm-generic-cdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-generic-cdma.c')
-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)