diff options
Diffstat (limited to 'src/mm-generic-cdma.c')
-rw-r--r-- | src/mm-generic-cdma.c | 149 |
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) |