aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-generic-gsm.c112
-rw-r--r--src/mm-modem-helpers.c80
-rw-r--r--src/mm-modem-helpers.h12
-rw-r--r--src/tests/test-modem-helpers.c2
4 files changed, 115 insertions, 91 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index b7de209b..7f28dd5c 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -97,9 +97,9 @@ typedef struct {
gboolean manual_reg;
gboolean cmer_enabled;
- gint roam_ind;
- gint signal_ind;
- gint service_ind;
+ guint roam_ind;
+ guint signal_ind;
+ guint service_ind;
guint signal_quality_id;
time_t signal_emit_timestamp;
@@ -1260,7 +1260,7 @@ cind_cb (MMAtSerialPort *port,
self = MM_GENERIC_GSM (user_data);
priv = MM_GENERIC_GSM_GET_PRIVATE (self);
- indicators = mm_parse_cind_response (response->str, NULL);
+ indicators = mm_parse_cind_test_response (response->str, NULL);
if (indicators) {
CindResponse *r;
@@ -3296,95 +3296,48 @@ mm_generic_gsm_update_signal_quality (MMGenericGsm *self, guint32 quality)
#define CIND_TAG "+CIND:"
static void
-cind_signal_cb (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
+get_cind_signal_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- const char *p = response->str;
- GRegex *r = NULL;
- GMatchInfo *match_info;
- int i = 1, quality = -1;
+ MMGenericGsmPrivate *priv;
+ GByteArray *indicators;
+ guint quality;
info->error = mm_modem_check_removed (info->modem, error);
- if (info->error)
- goto done;
-
- if (!g_str_has_prefix (p, CIND_TAG)) {
- info->error = g_error_new_literal (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Could not parse the +CIND response");
- goto done;
- }
-
- p += strlen (CIND_TAG);
- while (isspace (*p))
- p++;
-
- r = g_regex_new ("(\\d+)[^0-9]+", G_REGEX_UNGREEDY, 0, NULL);
- if (!r) {
- info->error = g_error_new_literal (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Internal failure attempting to parse +CIND response");
- goto done;
- }
-
- if (!g_regex_match_full (r, p, strlen (p), 0, 0, &match_info, NULL)) {
- info->error = g_error_new_literal (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Failure parsing the +CIND response");
- goto done;
- }
-
- while (g_match_info_matches (match_info)) {
- if (MM_GENERIC_GSM_GET_PRIVATE (info->modem)->signal_ind == i++) {
- char *str = g_match_info_fetch (match_info, 1);
+ if (!info->error) {
+ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
- if (str) {
- quality = atoi (str);
- mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (info->modem), quality * 20);
- g_free (str);
- break;
+ indicators = mm_parse_cind_query_response (response->str, &info->error);
+ if (indicators) {
+ if (indicators->len >= priv->signal_ind) {
+ quality = g_array_index (indicators, guint8, priv->signal_ind);
+ quality = CLAMP (quality, 0, 5) * 20;
+ mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (info->modem), quality);
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
}
+ g_byte_array_free (indicators, TRUE);
}
- g_match_info_next (match_info, NULL);
}
- g_match_info_free (match_info);
-
-done:
- if (r)
- g_regex_unref (r);
mm_callback_info_schedule (info);
}
static void
-get_signal_quality_done (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
+get_csq_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *reply = response->str;
gboolean parsed = FALSE;
info->error = mm_modem_check_removed (info->modem, error);
- if (info->error) {
- if (info->modem) {
- MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
-
- /* Modem won't do unsolicited reporting via +CMER/+CIEV, but still
- * supports +CIND.
- */
- if (!priv->cmer_enabled && (priv->signal_ind >= 0)) {
- g_clear_error (&info->error);
- mm_at_serial_port_queue_command (port, "+CIND?", 3, cind_signal_cb, info);
- return;
- }
- }
+ if (info->error)
goto done;
- }
if (!strncmp (reply, "+CSQ: ", 6)) {
/* Got valid reply */
@@ -3429,9 +3382,13 @@ get_signal_quality (MMModemGsmNetwork *modem,
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), NULL);
- if (port)
- mm_at_serial_port_queue_command (port, "+CSQ", 3, get_signal_quality_done, info);
- else {
+ if (port) {
+ /* Prefer +CIND if the modem supports it, fall back to +CSQ otherwise */
+ if (priv->signal_ind)
+ mm_at_serial_port_queue_command (port, "+CIND?", 3, get_cind_signal_done, info);
+ else
+ mm_at_serial_port_queue_command (port, "+CSQ", 3, get_csq_done, info);
+ } else {
/* Use cached signal quality */
mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->signal_quality), NULL);
mm_callback_info_schedule (info);
@@ -4694,9 +4651,6 @@ mm_generic_gsm_init (MMGenericGsm *self)
priv->act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
priv->reg_regex = mm_gsm_creg_regex_get (TRUE);
priv->roam_allowed = TRUE;
- priv->signal_ind = -1;
- priv->roam_ind = -1;
- priv->service_ind = -1;
mm_properties_changed_signal_register_property (G_OBJECT (self),
MM_MODEM_GSM_NETWORK_ALLOWED_MODE,
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index cca503e0..25998b1f 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -888,13 +888,13 @@ mm_create_device_identifier (guint vid,
struct CindResponse {
char *desc;
- gint idx;
+ guint idx;
gint min;
gint max;
};
static CindResponse *
-cind_response_new (const char *desc, gint idx, gint min, gint max)
+cind_response_new (const char *desc, guint idx, gint min, gint max)
{
CindResponse *r;
char *p;
@@ -936,10 +936,10 @@ cind_response_get_desc (CindResponse *r)
return r->desc;
}
-gint
+guint
cind_response_get_index (CindResponse *r)
{
- g_return_val_if_fail (r != NULL, -1);
+ g_return_val_if_fail (r != NULL, 0);
return r->idx;
}
@@ -963,12 +963,12 @@ cind_response_get_max (CindResponse *r)
#define CIND_TAG "+CIND:"
GHashTable *
-mm_parse_cind_response (const char *reply, GError **error)
+mm_parse_cind_test_response (const char *reply, GError **error)
{
GHashTable *hash;
GRegex *r;
GMatchInfo *match_info;
- gint idx = 1;
+ guint idx = 1;
g_return_val_if_fail (reply != NULL, NULL);
@@ -1019,3 +1019,71 @@ mm_parse_cind_response (const char *reply, GError **error)
return hash;
}
+GByteArray *
+mm_parse_cind_query_response(const char *reply, GError **error)
+{
+ GByteArray *array = NULL;
+ const char *p = reply;
+ GRegex *r = NULL;
+ GMatchInfo *match_info;
+ guint8 t = 0;
+
+ g_return_val_if_fail (reply != NULL, NULL);
+
+ if (!g_str_has_prefix (p, CIND_TAG)) {
+ g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse the +CIND response");
+ return NULL;
+ }
+
+ p += strlen (CIND_TAG);
+ while (isspace (*p))
+ p++;
+
+ r = g_regex_new ("(\\d+)[^0-9]+", G_REGEX_UNGREEDY, 0, NULL);
+ if (!r) {
+ g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Internal failure attempting to parse +CIND response");
+ return NULL;
+ }
+
+ if (!g_regex_match_full (r, p, strlen (p), 0, 0, &match_info, NULL)) {
+ g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Failure parsing the +CIND response");
+ goto done;
+ }
+
+ array = g_byte_array_sized_new (g_match_info_get_match_count (match_info));
+
+ /* Add a zero element so callers can use 1-based indexes returned by
+ * cind_response_get_index().
+ */
+ g_byte_array_append (array, &t, 1);
+
+ while (g_match_info_matches (match_info)) {
+ char *str;
+ gulong val;
+
+ str = g_match_info_fetch (match_info, 1);
+
+ errno = 0;
+ val = strtoul (str, NULL, 10);
+
+ t = 0;
+ if ((errno == 0) && (val < 255))
+ t = (guint8) val;
+ /* FIXME: indicate errors somehow? */
+ g_byte_array_append (array, &t, 1);
+
+ g_free (str);
+ g_match_info_next (match_info, NULL);
+ }
+ g_match_info_free (match_info);
+
+done:
+ if (r)
+ g_regex_unref (r);
+
+ return array;
+}
+
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index ed3ada0f..eda6e5d7 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -70,11 +70,13 @@ char *mm_create_device_identifier (guint vid,
gboolean debug);
typedef struct CindResponse CindResponse;
-GHashTable *mm_parse_cind_response (const char *reply, GError **error);
-const char *cind_response_get_desc (CindResponse *r);
-gint cind_response_get_index (CindResponse *r);
-gint cind_response_get_min (CindResponse *r);
-gint cind_response_get_max (CindResponse *r);
+GHashTable *mm_parse_cind_test_response (const char *reply, GError **error);
+const char *cind_response_get_desc (CindResponse *r);
+guint cind_response_get_index (CindResponse *r);
+gint cind_response_get_min (CindResponse *r);
+gint cind_response_get_max (CindResponse *r);
+
+GByteArray *mm_parse_cind_query_response(const char *reply, GError **error);
#endif /* MM_MODEM_HELPERS_H */
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index 5627416a..f0cbe61c 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -1095,7 +1095,7 @@ test_cind_results (const char *desc,
g_print ("\nTesting %s +CIND response...\n", desc);
- results = mm_parse_cind_response (reply, &error);
+ results = mm_parse_cind_test_response (reply, &error);
g_assert (results);
g_assert (error == NULL);