aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-02-07 16:03:20 +0100
committerAleksander Morgado <aleksander@lanedo.com>2012-03-15 14:15:00 +0100
commit23a615605996415cfdbc8d80831959e5f2679278 (patch)
tree1d7d92818b25882fe44b5f9f1d009e87e42c533d
parentffedaf2ec3ca45d348abf9faf0ef353f81fac782 (diff)
broadband-modem: allow listing SMS parts in Text mode
-rw-r--r--src/mm-broadband-modem.c170
1 files changed, 159 insertions, 11 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 8bcb69f3..cfd5e06b 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -3573,9 +3573,8 @@ cmgf_format_check_ready (MMBroadbandModem *self,
g_error_free (error);
}
- /* FIXME: we currently default to using PDU modem always, until we provide
- * full support for text mode. */
- self->priv->sms_use_pdu_mode = TRUE;
+ /* If text mode is supported, default to use it for now; othewise try PDU mode */
+ self->priv->sms_use_pdu_mode = !sms_text_supported;
self->priv->sms_supported_modes_checked = TRUE;
@@ -3671,7 +3670,7 @@ sms_part_ready (MMBroadbandModem *self,
return;
}
- part = mm_sms_part_new (ctx->idx, pdu, &error);
+ part = mm_sms_part_new_from_pdu (ctx->idx, pdu, &error);
if (part) {
mm_dbg ("Correctly parsed PDU (%d)", ctx->idx);
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
@@ -3797,10 +3796,154 @@ modem_messaging_load_initial_sms_parts_finish (MMIfaceModemMessaging *self,
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
+static gboolean
+get_match_uint (GMatchInfo *m,
+ guint match_index,
+ guint *out_val)
+{
+ gchar *s;
+ gulong num;
+
+ g_return_val_if_fail (out_val != NULL, FALSE);
+
+ s = g_match_info_fetch (m, match_index);
+ g_return_val_if_fail (s != NULL, FALSE);
+
+ errno = 0;
+ num = strtoul (s, NULL, 10);
+ g_free (s);
+
+ if (num <= 1000 && errno == 0) {
+ *out_val = (guint) num;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gchar *
+get_match_string_unquoted (GMatchInfo *m,
+ guint match_index)
+{
+ gchar *s, *p, *q, *ret = NULL;
+
+ q = s = g_match_info_fetch (m, match_index);
+ g_return_val_if_fail (s != NULL, FALSE);
+
+ /* remove quotes */
+ if (*q == '"')
+ q++;
+ p = strchr (q, '"');
+ if (p)
+ *p = '\0';
+ if (*q)
+ ret = g_strdup (q);
+ g_free (s);
+ return ret;
+}
+
static void
-sms_part_list_ready (MMBroadbandModem *self,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
+sms_text_part_list_ready (MMBroadbandModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GRegex *r;
+ GMatchInfo *match_info = NULL;
+ const gchar *response;
+ GError *error = NULL;
+
+ response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+ if (error) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* +CMGL: <index>,<stat>,<oa/da>,[alpha],<scts><CR><LF><data><CR><LF> */
+ r = g_regex_new ("\\+CMGL:\\s*(\\d+)\\s*,\\s*([^,]*),\\s*([^,]*),\\s*([^,]*),\\s*([^\\r\\n]*)\\r\\n(.*)\\r\\n",
+ 0, 0, NULL);
+ g_assert (r);
+
+ if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) {
+ g_simple_async_result_set_error (simple,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Couldn't parse SMS list response");
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_regex_unref (r);
+ return;
+ }
+
+ while (g_match_info_matches (match_info)) {
+ MMSmsPart *part;
+ guint matches, idx;
+ gchar *number = NULL, *timestamp, *text, *ucs2_text;
+ gsize ucs2_len = 0;
+ GByteArray *raw;
+
+ matches = g_match_info_get_match_count (match_info);
+ if (matches != 7) {
+ mm_dbg ("Failed to match entire CMGL response (count %d)", matches);
+ goto next;
+ }
+
+ if (!get_match_uint (match_info, 1, &idx)) {
+ mm_dbg ("Failed to convert message index");
+ goto next;
+ }
+
+ /* <stat is ignored for now> */
+
+ number = get_match_string_unquoted (match_info, 3);
+ if (!number) {
+ mm_dbg ("Failed to get message sender number");
+ goto next;
+ }
+
+ timestamp = get_match_string_unquoted (match_info, 5);
+
+ text = g_match_info_fetch (match_info, 6);
+ /* FIXME: Text is going to be in the character set we've set with +CSCS */
+
+ /* The raw SMS data can only be GSM, UCS2, or unknown (8-bit), so we
+ * need to convert to UCS2 here.
+ */
+ ucs2_text = g_convert (text, -1, "UCS-2BE//TRANSLIT", "UTF-8", NULL, &ucs2_len, NULL);
+ g_assert (ucs2_text);
+ raw = g_byte_array_sized_new (ucs2_len);
+ g_byte_array_append (raw, (const guint8 *) ucs2_text, ucs2_len);
+ g_free (ucs2_text);
+
+ /* all take() methods pass ownership of the value as well */
+ part = mm_sms_part_new (idx);
+ mm_sms_part_take_number (part, number);
+ mm_sms_part_take_timestamp (part, timestamp);
+ mm_sms_part_take_text (part, text);
+ mm_sms_part_take_data (part, raw);
+ mm_sms_part_set_data_coding_scheme (part, 2); /* DCS = UCS2 */
+ mm_sms_part_set_class (part, 0);
+
+ mm_dbg ("Correctly parsed SMS list entry (%d)", idx);
+ mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
+ part,
+ FALSE);
+next:
+ g_match_info_next (match_info, NULL);
+ }
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+
+ /* We consider all done */
+ g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+sms_pdu_part_list_ready (MMBroadbandModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
{
const gchar *response;
GError *error = NULL;
@@ -3840,7 +3983,7 @@ sms_part_list_ready (MMBroadbandModem *self,
/* Will try to keep on the loop */
response += offset;
- part = mm_sms_part_new (idx, pdu, &error);
+ part = mm_sms_part_new_from_pdu (idx, pdu, &error);
if (part) {
mm_dbg ("Correctly parsed PDU (%d)", idx);
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
@@ -3871,13 +4014,18 @@ modem_messaging_load_initial_sms_parts (MMIfaceModemMessaging *self,
user_data,
modem_messaging_load_initial_sms_parts);
- /* Get SMS parts from ALL types (4) */
+ /* Get SMS parts from ALL types.
+ * Different command to be used if we are on Text or PDU mode */
mm_base_modem_at_command (MM_BASE_MODEM (self),
- "+CMGL=4",
+ (MM_BROADBAND_MODEM (self)->priv->sms_use_pdu_mode ?
+ "+CMGL=4" :
+ "+CMGL=\"ALL\""),
10,
FALSE,
NULL, /* cancellable */
- (GAsyncReadyCallback)sms_part_list_ready,
+ (GAsyncReadyCallback) (MM_BROADBAND_MODEM (self)->priv->sms_use_pdu_mode ?
+ sms_pdu_part_list_ready :
+ sms_text_part_list_ready),
result);
}