aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-generic-cdma.c130
-rw-r--r--src/mm-modem-helpers.c233
-rw-r--r--src/mm-modem-helpers.h4
3 files changed, 342 insertions, 25 deletions
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c
index 728d8766..b708882b 100644
--- a/src/mm-generic-cdma.c
+++ b/src/mm-generic-cdma.c
@@ -391,8 +391,14 @@ spservice_done (MMAtSerialPort *port,
GError *error,
gpointer user_data)
{
- if (!error)
+ if (!error) {
MM_GENERIC_CDMA_GET_PRIVATE (user_data)->has_spservice = TRUE;
+
+ /* +SPSERVICE provides a better indicator of registration status than
+ * +CSS, which some devices implement inconsistently.
+ */
+ MM_GENERIC_CDMA_GET_PRIVATE (user_data)->reg_try_css = FALSE;
+ }
}
static void
@@ -1165,22 +1171,26 @@ static void
set_callback_1x_state_helper (MMCallbackInfo *info,
MMModemCdmaRegistrationState new_state)
{
- MMGenericCdma *self = MM_GENERIC_CDMA (info->modem);
- MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
+ if (info->modem) {
+ MMGenericCdma *self = MM_GENERIC_CDMA (info->modem);
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
- mm_generic_cdma_set_1x_registration_state (self, new_state);
- mm_generic_cdma_query_reg_state_set_callback_1x_state (info, priv->cdma_1x_reg_state);
+ mm_generic_cdma_set_1x_registration_state (self, new_state);
+ mm_generic_cdma_query_reg_state_set_callback_1x_state (info, priv->cdma_1x_reg_state);
+ }
}
static void
set_callback_evdo_state_helper (MMCallbackInfo *info,
MMModemCdmaRegistrationState new_state)
{
- MMGenericCdma *self = MM_GENERIC_CDMA (info->modem);
- MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
+ if (info->modem) {
+ MMGenericCdma *self = MM_GENERIC_CDMA (info->modem);
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
- mm_generic_cdma_set_evdo_registration_state (self, new_state);
- mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, priv->evdo_reg_state);
+ mm_generic_cdma_set_evdo_registration_state (self, new_state);
+ mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, priv->evdo_reg_state);
+ }
}
static void
@@ -1203,22 +1213,87 @@ reg_state_query_done (MMModemCdma *cdma,
}
static void
-query_subclass_registration_state (MMGenericCdma *self, MMCallbackInfo *info)
+reg_query_speri_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+ MMModemCdmaRegistrationState cdma_state;
+ MMModemCdmaRegistrationState evdo_state;
+
+ cdma_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "tmp-cdma-state"));
+ evdo_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "tmp-evdo-state"));
+
+ if (!error) {
+ gboolean roam = FALSE;
+
+ if (mm_cdma_parse_speri_response (response->str, &roam, NULL)) {
+ cdma_state = roam ? MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING
+ : MM_MODEM_CDMA_REGISTRATION_STATE_HOME;
+ evdo_state = roam ? MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING
+ : MM_MODEM_CDMA_REGISTRATION_STATE_HOME;
+ }
+ }
+
+ set_callback_1x_state_helper (info, cdma_state);
+ set_callback_evdo_state_helper (info, evdo_state);
+ mm_callback_info_schedule (info);
+}
+
+static void
+reg_query_spservice_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+ MMModemCdmaRegistrationState cdma_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
+ MMModemCdmaRegistrationState evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
+
+ if (error)
+ info->error = g_error_copy (error);
+ else if (mm_cdma_parse_spservice_response (response->str,
+ &cdma_state,
+ &evdo_state)) {
+ if (MM_GENERIC_CDMA_GET_PRIVATE (info->modem)->has_speri) {
+ /* Get roaming status to override generic registration state */
+ mm_callback_info_set_data (info, "tmp-cdma-state", GUINT_TO_POINTER (cdma_state), NULL);
+ mm_callback_info_set_data (info, "tmp-evdo-state", GUINT_TO_POINTER (evdo_state), NULL);
+ mm_at_serial_port_queue_command (port, "$SPERI?", 3, reg_query_speri_done, info);
+ return;
+ }
+ }
+
+ set_callback_1x_state_helper (info, cdma_state);
+ set_callback_evdo_state_helper (info, evdo_state);
+ mm_callback_info_schedule (info);
+}
+
+static void
+real_query_registration_state (MMGenericCdma *self,
+ MMModemCdmaRegistrationStateFn callback,
+ gpointer user_data)
{
- /* Let subclasses figure out roaming and detailed registration state */
- if (MM_GENERIC_CDMA_GET_CLASS (self)->query_registration_state) {
- MM_GENERIC_CDMA_GET_CLASS (self)->query_registration_state (self,
- reg_state_query_done,
- info);
+ MMCallbackInfo *info;
+ MMAtSerialPort *port;
+
+ info = mm_generic_cdma_query_reg_state_callback_info_new (self, callback, user_data);
+
+ port = mm_generic_cdma_get_best_at_port (self, &info->error);
+ if (!port) {
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ if (MM_GENERIC_CDMA_GET_PRIVATE (self)->has_spservice) {
+ /* Try Sprint-specific commands */
+ mm_at_serial_port_queue_command (port, "+SPSERVICE?", 3, reg_query_spservice_done, info);
} else {
- /* Or if the subclass doesn't implement more specific checking,
- * assume we're registered.
- */
- reg_state_query_done (MM_MODEM_CDMA (self),
- MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED,
- MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED,
- NULL,
- info);
+ /* Assume we're registered if we passed CAD and CSS checking */
+ set_callback_1x_state_helper (info, MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED);
+ set_callback_evdo_state_helper (info, MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED);
+ mm_callback_info_schedule (info);
}
}
@@ -1248,7 +1323,9 @@ reg_state_css_response (MMModemCdma *cdma,
return;
}
- query_subclass_registration_state (MM_GENERIC_CDMA (info->modem), info);
+ MM_GENERIC_CDMA_GET_CLASS (cdma)->query_registration_state (MM_GENERIC_CDMA (info->modem),
+ reg_state_query_done,
+ info);
}
static void
@@ -1299,7 +1376,9 @@ get_analog_digital_done (MMAtSerialPort *port,
/* Subclass knows that AT+CSS? will respond incorrectly to EVDO
* state, so skip AT+CSS? query.
*/
- query_subclass_registration_state (MM_GENERIC_CDMA (info->modem), info);
+ MM_GENERIC_CDMA_GET_CLASS (info->modem)->query_registration_state (MM_GENERIC_CDMA (info->modem),
+ reg_state_query_done,
+ info);
}
return;
} else {
@@ -1765,6 +1844,7 @@ mm_generic_cdma_class_init (MMGenericCdmaClass *klass)
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->constructor = constructor;
+ klass->query_registration_state = real_query_registration_state;
/* Properties */
g_object_class_override_property (object_class,
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 0a2bb623..1f7a7888 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -18,6 +18,7 @@
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
+#include <errno.h>
#include "mm-errors.h"
#include "mm-modem-helpers.h"
@@ -469,6 +470,238 @@ mm_cdma_parse_spservice_response (const char *reply,
/*************************************************************************/
+typedef struct {
+ int num;
+ gboolean roam_ind;
+ const char *banner;
+} EriItem;
+
+/* NOTE: these may be Sprint-specific for now... */
+static const EriItem eris[] = {
+ { 0, TRUE, "Digital or Analog Roaming" },
+ { 1, FALSE, "Home" },
+ { 2, TRUE, "Digital or Analog Roaming" },
+ { 3, TRUE, "Out of neighborhood" },
+ { 4, TRUE, "Out of building" },
+ { 5, TRUE, "Preferred system" },
+ { 6, TRUE, "Available System" },
+ { 7, TRUE, "Alliance Partner" },
+ { 8, TRUE, "Premium Partner" },
+ { 9, TRUE, "Full Service Functionality" },
+ { 10, TRUE, "Partial Service Functionality" },
+ { 64, TRUE, "Preferred system" },
+ { 65, TRUE, "Available System" },
+ { 66, TRUE, "Alliance Partner" },
+ { 67, TRUE, "Premium Partner" },
+ { 68, TRUE, "Full Service Functionality" },
+ { 69, TRUE, "Partial Service Functionality" },
+ { 70, TRUE, "Analog A" },
+ { 71, TRUE, "Analog B" },
+ { 72, TRUE, "CDMA 800 A" },
+ { 73, TRUE, "CDMA 800 B" },
+ { 74, TRUE, "International Roaming" },
+ { 75, TRUE, "Extended Network" },
+ { 76, FALSE, "Campus" },
+ { 77, FALSE, "In Building" },
+ { 78, TRUE, "Regional" },
+ { 79, TRUE, "Community" },
+ { 80, TRUE, "Business" },
+ { 81, TRUE, "Zone 1" },
+ { 82, TRUE, "Zone 2" },
+ { 83, TRUE, "National" },
+ { 84, TRUE, "Local" },
+ { 85, TRUE, "City" },
+ { 86, TRUE, "Government" },
+ { 87, TRUE, "USA" },
+ { 88, TRUE, "State" },
+ { 89, TRUE, "Resort" },
+ { 90, TRUE, "Headquarters" },
+ { 91, TRUE, "Personal" },
+ { 92, FALSE, "Home" },
+ { 93, TRUE, "Residential" },
+ { 94, TRUE, "University" },
+ { 95, TRUE, "College" },
+ { 96, TRUE, "Hotel Guest" },
+ { 97, TRUE, "Rental" },
+ { 98, FALSE, "Corporate" },
+ { 99, FALSE, "Home Provider" },
+ { 100, FALSE, "Campus" },
+ { 101, FALSE, "In Building" },
+ { 102, TRUE, "Regional" },
+ { 103, TRUE, "Community" },
+ { 104, TRUE, "Business" },
+ { 105, TRUE, "Zone 1" },
+ { 106, TRUE, "Zone 2" },
+ { 107, TRUE, "National" },
+ { 108, TRUE, "Local" },
+ { 109, TRUE, "City" },
+ { 110, TRUE, "Government" },
+ { 111, TRUE, "USA" },
+ { 112, TRUE, "State" },
+ { 113, TRUE, "Resort" },
+ { 114, TRUE, "Headquarters" },
+ { 115, TRUE, "Personal" },
+ { 116, FALSE, "Home" },
+ { 117, TRUE, "Residential" },
+ { 118, TRUE, "University" },
+ { 119, TRUE, "College" },
+ { 120, TRUE, "Hotel Guest" },
+ { 121, TRUE, "Rental" },
+ { 122, FALSE, "Corporate" },
+ { 123, FALSE, "Home Provider" },
+ { 124, TRUE, "International" },
+ { 125, TRUE, "International" },
+ { 126, TRUE, "International" },
+ { 127, FALSE, "Premium Service" },
+ { 128, FALSE, "Enhanced Service" },
+ { 129, FALSE, "Enhanced Digital" },
+ { 130, FALSE, "Enhanced Roaming" },
+ { 131, FALSE, "Alliance Service" },
+ { 132, FALSE, "Alliance Network" },
+ { 133, FALSE, "Data Roaming" }, /* Sprint: Vision Roaming */
+ { 134, FALSE, "Extended Service" },
+ { 135, FALSE, "Expanded Services" },
+ { 136, FALSE, "Expanded Network" },
+ { 137, TRUE, "Premium Service" },
+ { 138, TRUE, "Enhanced Service" },
+ { 139, TRUE, "Enhanced Digital" },
+ { 140, TRUE, "Enhanced Roaming" },
+ { 141, TRUE, "Alliance Service" },
+ { 142, TRUE, "Alliance Network" },
+ { 143, TRUE, "Data Roaming" }, /* Sprint: Vision Roaming */
+ { 144, TRUE, "Extended Service" },
+ { 145, TRUE, "Expanded Services" },
+ { 146, TRUE, "Expanded Network" },
+ { 147, TRUE, "Premium Service" },
+ { 148, TRUE, "Enhanced Service" },
+ { 149, TRUE, "Enhanced Digital" },
+ { 150, TRUE, "Enhanced Roaming" },
+ { 151, TRUE, "Alliance Service" },
+ { 152, TRUE, "Alliance Network" },
+ { 153, TRUE, "Data Roaming" }, /* Sprint: Vision Roaming */
+ { 154, TRUE, "Extended Service" },
+ { 155, TRUE, "Expanded Services" },
+ { 156, TRUE, "Expanded Network" },
+ { 157, TRUE, "Premium International" },
+ { 158, TRUE, "Premium International" },
+ { 159, TRUE, "Premium International" },
+ { 160, TRUE, NULL },
+ { 161, TRUE, NULL },
+ { 162, FALSE, NULL },
+ { 163, FALSE, NULL },
+ { 164, FALSE, "Extended Voice/Data Network" },
+ { 165, FALSE, "Extended Voice/Data Network" },
+ { 166, TRUE, "Extended Voice/Data Network" },
+ { 167, FALSE, "Extended Broadband" },
+ { 168, FALSE, "Extended Broadband" },
+ { 169, TRUE, "Extended Broadband" },
+ { 170, FALSE, "Extended Data" },
+ { 171, FALSE, "Extended Data" },
+ { 172, TRUE, "Extended Data" },
+ { 173, FALSE, "Extended Data Network" },
+ { 174, FALSE, "Extended Data Network" },
+ { 175, TRUE, "Extended Data Network" },
+ { 176, FALSE, "Extended Network" },
+ { 177, FALSE, "Extended Network" },
+ { 178, TRUE, "Extended Network" },
+ { 179, FALSE, "Extended Service" },
+ { 180, TRUE, "Extended Service" },
+ { 181, FALSE, "Extended Voice" },
+ { 182, FALSE, "Extended Voice" },
+ { 183, TRUE, "Extended Voice" },
+ { 184, FALSE, "Extended Voice/Data" },
+ { 185, FALSE, "Extended Voice/Data" },
+ { 186, TRUE, "Extended Voice/Data" },
+ { 187, FALSE, "Extended Voice Network" },
+ { 188, FALSE, "Extended Voice Network" },
+ { 189, TRUE, "Extended Voice Network" },
+ { 190, FALSE, "Extended Voice/Data" },
+ { 191, FALSE, "Extended Voice/Data" },
+ { 192, TRUE, "Extended Voice/Data" },
+ { 193, TRUE, "International" },
+ { 194, FALSE, "International Services" },
+ { 195, FALSE, "International Voice" },
+ { 196, FALSE, "International Voice/Data" },
+ { 197, FALSE, "International Voice/Data" },
+ { 198, TRUE, "International Voice/Data" },
+ { 199, FALSE, "Extended Voice/Data Network" },
+ { 200, TRUE, "Extended Voice/Data Network" },
+ { 201, TRUE, "Extended Voice/Data Network" },
+ { 202, FALSE, "Extended Broadband" },
+ { 203, TRUE, "Extended Broadband" },
+ { 204, TRUE, "Extended Broadband" },
+ { 205, FALSE, "Extended Data" },
+ { 206, TRUE, "Extended Data" },
+ { 207, TRUE, "Extended Data" },
+ { 208, FALSE, "Extended Data Network" },
+ { 209, TRUE, "Extended Data Network" },
+ { 210, TRUE, "Extended Data Network" },
+ { 211, FALSE, "Extended Network" },
+ { 212, TRUE, "Extended Network" },
+ { 213, FALSE, "Extended Service" },
+ { 214, TRUE, "Extended Service" },
+ { 215, TRUE, "Extended Service" },
+ { 216, FALSE, "Extended Voice" },
+ { 217, TRUE, "Extended Voice" },
+ { 218, TRUE, "Extended Voice" },
+ { 219, FALSE, "Extended Voice/Data" },
+ { 220, TRUE, "Extended Voice/Data" },
+ { 221, TRUE, "Extended Voice/Data" },
+ { 222, FALSE, "Extended Voice Network" },
+ { 223, FALSE, "Extended Voice Network" },
+ { 224, TRUE, "Extended Voice Network" },
+ { 225, FALSE, "Extended Voice/Data" },
+ { 226, TRUE, "Extended Voice/Data" },
+ { 227, TRUE, "Extended Voice/Data" },
+ { 228, TRUE, "International" },
+ { 229, TRUE, "International" },
+ { 230, TRUE, "International Services" },
+ { 231, TRUE, "International Voice" },
+ { 232, FALSE, "International Voice/Data" },
+ { 233, TRUE, "International Voice/Data" },
+ { 234, TRUE, "International Voice/Data" },
+ { 235, TRUE, "Premium International" },
+ { 236, TRUE, NULL },
+ { 237, TRUE, NULL },
+ { 238, FALSE, NULL },
+ { 239, FALSE, NULL },
+ { -1, FALSE, NULL },
+};
+
+gboolean
+mm_cdma_parse_speri_response (const char *reply,
+ gboolean *out_roaming,
+ const char **out_desc)
+{
+ const char *p;
+ long int ind;
+ const EriItem *iter = &eris[0];
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (reply != NULL, FALSE);
+ g_return_val_if_fail (out_roaming != NULL, FALSE);
+
+ p = mm_strip_tag (reply, "$SPERI:");
+ errno = 0;
+ ind = strtol (p, NULL, 10);
+ if (errno == 0) {
+ while (iter->num != -1) {
+ if (iter->num == ind) {
+ *out_roaming = iter->roam_ind;
+ if (out_desc)
+ *out_desc = iter->banner;
+ found = TRUE;
+ break;
+ }
+ iter++;
+ }
+ }
+
+ return found;
+}
+
+/*************************************************************************/
+
const char *
mm_strip_tag (const char *str, const char *cmd)
{
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 3e398e59..0ef16074 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -47,5 +47,9 @@ gboolean mm_cdma_parse_spservice_response (const char *reply,
MMModemCdmaRegistrationState *out_cdma_1x_state,
MMModemCdmaRegistrationState *out_evdo_state);
+gboolean mm_cdma_parse_speri_response (const char *reply,
+ gboolean *out_roaming,
+ const char **out_desc);
+
#endif /* MM_MODEM_HELPERS_H */