aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-12-18 19:44:48 -0800
committerDan Williams <dcbw@redhat.com>2009-12-18 19:44:48 -0800
commitdb7214c202b7ed9d9cf12f49ff70ceba020f6f33 (patch)
tree9cedc58d64a240b3001c2a2fe27aeeff5c0bdee0
parent8d42094608e68eccbcf5838d87fd59aa605a18be (diff)
sierra: fix CDMA registration detection in some cases
It turns out that "Modem is [NOT] registered" is not a good indicator of whether the card has service or not; instead some of the AT!STATUS response is needed to really determine registration state or not.
-rw-r--r--plugins/mm-modem-sierra-cdma.c72
1 files changed, 59 insertions, 13 deletions
diff --git a/plugins/mm-modem-sierra-cdma.c b/plugins/mm-modem-sierra-cdma.c
index 83cfba30..eec2a83c 100644
--- a/plugins/mm-modem-sierra-cdma.c
+++ b/plugins/mm-modem-sierra-cdma.c
@@ -35,6 +35,7 @@ G_DEFINE_TYPE (MMModemSierraCdma, mm_modem_sierra_cdma, MM_TYPE_GENERIC_CDMA)
typedef enum {
SYS_MODE_UNKNOWN,
+ SYS_MODE_NO_SERVICE,
SYS_MODE_CDMA_1X,
SYS_MODE_EVDO_REV0,
SYS_MODE_EVDO_REVA
@@ -75,6 +76,7 @@ mm_modem_sierra_cdma_new (const char *device,
#define SYS_MODE_EVDO_TAG "HDR"
#define SYS_MODE_1X_TAG "1x"
#define EVDO_REV_TAG "HDR Revision:"
+#define SID_TAG "SID:"
static gboolean
get_roam_value (const char *reply, const char *tag, gboolean *roaming)
@@ -99,6 +101,14 @@ get_roam_value (const char *reply, const char *tag, gboolean *roaming)
return FALSE;
}
+static gboolean
+sys_mode_has_service (SysMode mode)
+{
+ return ( mode == SYS_MODE_CDMA_1X
+ || mode == SYS_MODE_EVDO_REV0
+ || mode == SYS_MODE_EVDO_REVA);
+}
+
static void
status_done (MMSerialPort *port,
GString *response,
@@ -109,6 +119,7 @@ status_done (MMSerialPort *port,
MMModemSierraCdmaPrivate *priv = MM_MODEM_SIERRA_CDMA_GET_PRIVATE (info->modem);
char **lines, **iter;
gboolean registered = FALSE;
+ gboolean have_sid = FALSE;
SysMode evdo_mode = SYS_MODE_UNKNOWN;
SysMode sys_mode = SYS_MODE_UNKNOWN;
gboolean cdma_1x_set = FALSE, evdo_set = FALSE;
@@ -129,10 +140,10 @@ status_done (MMSerialPort *port,
* while of course 1x parts only report 1x status. Some modems also do not
* report the Roaming information (MP 555 GPS).
*
+ * AT!STATUS responses:
*
* Unregistered MC5725:
* -----------------------
- * at!status
* Current band: PCS CDMA
* Current channel: 350
* SID: 0 NID: 0 1xRoam: 0 HDRRoam: 0
@@ -140,8 +151,6 @@ status_done (MMSerialPort *port,
* Pilot NOT acquired
* Modem has NOT registered
*
- * OK
- *
* Registered MC5725:
* -----------------------
* Current band: Cellular Sleep
@@ -151,6 +160,31 @@ status_done (MMSerialPort *port,
* Pilot acquired
* Modem has registered
* HDR Revision: A
+ *
+ * Unregistered AC580:
+ * -----------------------
+ * Current band: PCS CDMA
+ * Current channel: 350
+ * SID: 0 NID: 0 Roaming: 0
+ * Temp: 39 State: 100 Scan Mode: 0
+ * Pilot NOT acquired
+ * Modem has NOT registered
+ *
+ * Registered AC580:
+ * -----------------------
+ * Current band: Cellular Sleep
+ * Current channel: 548
+ * SID: 26 NID: 1 Roaming: 1
+ * Temp: 39 State: 200 Scan Mode: 0
+ * Pilot Acquired
+ * Modem has registered
+ */
+
+ /* We have to handle the two formats slightly differently; for newer formats
+ * with "Sys Mode", we consider the modem registered if the Sys Mode is not
+ * "NO SRV". The explicit registration status is just icing on the cake.
+ * For older formats (no "Sys Mode") we treat the modem as registered if
+ * the SID is non-zero.
*/
for (iter = lines; iter && *iter; iter++) {
@@ -194,7 +228,7 @@ status_done (MMSerialPort *port,
while (*p && isspace (*p))
p++;
if (!strncmp (p, SYS_MODE_NO_SERVICE_TAG, strlen (SYS_MODE_NO_SERVICE_TAG)))
- sys_mode = SYS_MODE_UNKNOWN;
+ sys_mode = SYS_MODE_NO_SERVICE;
else if (!strncmp (p, SYS_MODE_EVDO_TAG, strlen (SYS_MODE_EVDO_TAG)))
sys_mode = SYS_MODE_EVDO_REV0;
else if (!strncmp (p, SYS_MODE_1X_TAG, strlen (SYS_MODE_1X_TAG)))
@@ -212,19 +246,27 @@ status_done (MMSerialPort *port,
else if (*p == '0')
evdo_mode = SYS_MODE_EVDO_REV0;
}
+
+ /* SID */
+ p = strstr (*iter, SID_TAG);
+ if (p) {
+ p += strlen (SID_TAG);
+ while (*p && isspace (*p))
+ p++;
+ if (isdigit (*p) && (*p != '0'))
+ have_sid = TRUE;
+ }
}
- if (!registered) {
- mm_generic_cdma_query_reg_state_set_callback_1x_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
- mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
- } else {
- /* Update current system mode */
- if (sys_mode == SYS_MODE_EVDO_REV0 || sys_mode == SYS_MODE_EVDO_REVA) {
- /* Prefer the explicit EVDO mode from EVDO_REV_TAG */
+ /* Update current system mode */
+ if (sys_mode == SYS_MODE_EVDO_REV0 || sys_mode == SYS_MODE_EVDO_REVA) {
+ /* Prefer the explicit EVDO mode from EVDO_REV_TAG */
+ if (evdo_mode != SYS_MODE_UNKNOWN)
sys_mode = evdo_mode;
- }
- priv->sys_mode = sys_mode;
+ }
+ priv->sys_mode = sys_mode;
+ if (registered || have_sid || sys_mode_has_service (sys_mode)) {
/* As a backup, if for some reason the registration states didn't get
* figured out by parsing the status info, set some generic registration
* states here.
@@ -235,6 +277,10 @@ status_done (MMSerialPort *port,
/* Ensure EVDO registration mode is set if we're at least in EVDO mode */
if (!evdo_set && (sys_mode == SYS_MODE_EVDO_REV0 || sys_mode == SYS_MODE_EVDO_REVA))
mm_generic_cdma_query_reg_state_set_callback_1x_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED);
+ } else {
+ /* Not registered */
+ mm_generic_cdma_query_reg_state_set_callback_1x_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
+ mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
}
done: