aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-08-24 12:01:01 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-08-24 12:32:29 +0200
commitba4e209745676a08f7c886d7cd0ba13202e336d5 (patch)
treecdcb533e86bffc3e97e383b3a2dc4078453d6649 /src
parent4fe7c7d637644de6b24e7d71a45aad3647086e19 (diff)
sms: fix sending SMS messages on some modems
This is the port to git master of the following commit: commit 65f13f41cfd00cd38f118121a58b83713501f45f Author: Dan Williams <dcbw@redhat.com> Date: Tue Jul 17 16:00:31 2012 -0500 gsm: fix sending SMS messages on some modems and use PDU by default It turns out we really do have to wait for the modem to return the ">" prompt before sending the message data, otherwise a number of modems will complain about the data and fail the message. Fix that by sending the first bit of the CMGS, waiting for the ">", and then sending the rest. This also switches all modems over to PDU mode by default if they support it, since it's more compatible and most recent modems don't even bother to support text mode anyway.
Diffstat (limited to 'src')
-rw-r--r--src/mm-serial-parsers.c19
-rw-r--r--src/mm-sms.c118
2 files changed, 105 insertions, 32 deletions
diff --git a/src/mm-serial-parsers.c b/src/mm-serial-parsers.c
index 041615db..53b22a81 100644
--- a/src/mm-serial-parsers.c
+++ b/src/mm-serial-parsers.c
@@ -83,6 +83,7 @@ typedef struct {
/* Regular expressions for successful replies */
GRegex *regex_ok;
GRegex *regex_connect;
+ GRegex *regex_sms;
GRegex *regex_custom_successful;
/* Regular expressions for error replies */
GRegex *regex_cme_error;
@@ -105,6 +106,7 @@ mm_serial_parser_v1_new (void)
parser->regex_ok = g_regex_new ("\\r\\nOK(\\r\\n)+$", flags, 0, NULL);
parser->regex_connect = g_regex_new ("\\r\\nCONNECT.*\\r\\n", flags, 0, NULL);
+ parser->regex_sms = g_regex_new ("\\r\\n>\\s*$", flags, 0, NULL);
parser->regex_cme_error = g_regex_new ("\\r\\n\\+CME ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
parser->regex_cms_error = g_regex_new ("\\r\\n\\+CMS ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
parser->regex_cme_error_str = g_regex_new ("\\r\\n\\+CME ERROR:\\s*([^\\n\\r]+)\\r\\n$", flags, 0, NULL);
@@ -173,10 +175,18 @@ mm_serial_parser_v1_parse (gpointer data,
0, 0, NULL, NULL);
if (found)
remove_matches (parser->regex_ok, response);
- else
- found = g_regex_match_full (parser->regex_connect,
- response->str, response->len,
- 0, 0, NULL, NULL);
+ }
+
+ if (!found) {
+ found = g_regex_match_full (parser->regex_connect,
+ response->str, response->len,
+ 0, 0, NULL, NULL);
+ }
+
+ if (!found) {
+ found = g_regex_match_full (parser->regex_sms,
+ response->str, response->len,
+ 0, 0, NULL, NULL);
}
if (found) {
@@ -328,6 +338,7 @@ mm_serial_parser_v1_destroy (gpointer data)
g_regex_unref (parser->regex_ok);
g_regex_unref (parser->regex_connect);
+ g_regex_unref (parser->regex_sms);
g_regex_unref (parser->regex_cme_error);
g_regex_unref (parser->regex_cms_error);
g_regex_unref (parser->regex_cme_error_str);
diff --git a/src/mm-sms.c b/src/mm-sms.c
index b68ee768..33856b5b 100644
--- a/src/mm-sms.c
+++ b/src/mm-sms.c
@@ -404,20 +404,23 @@ mm_sms_has_part_index (MMSms *self,
/*****************************************************************************/
-static gchar *
+static gboolean
sms_get_store_or_send_command (MMSmsPart *part,
gboolean text_or_pdu, /* TRUE for PDU */
gboolean store_or_send, /* TRUE for send */
+ gchar **out_cmd,
+ gchar **out_msg_data,
GError **error)
{
- gchar *cmd;
+ g_assert (out_cmd != NULL);
+ g_assert (out_msg_data != NULL);
if (!text_or_pdu) {
/* Text mode */
- cmd = g_strdup_printf ("+CMG%c=\"%s\"\r%s\x1a",
- store_or_send ? 'S' : 'W',
- mm_sms_part_get_number (part),
- mm_sms_part_get_text (part));
+ *out_cmd = g_strdup_printf ("+CMG%c=\"%s\"",
+ store_or_send ? 'S' : 'W',
+ mm_sms_part_get_number (part));
+ *out_msg_data = g_strdup_printf ("%s\x1a", mm_sms_part_get_text (part));
} else {
guint8 *pdu;
guint pdulen = 0;
@@ -428,7 +431,8 @@ sms_get_store_or_send_command (MMSmsPart *part,
pdu = mm_sms_part_get_submit_pdu (part, &pdulen, &msgstart, error);
if (!pdu)
- return NULL;
+ /* 'error' should already be set */
+ return FALSE;
/* Convert PDU to hex */
hex = utils_bin2hexstr (pdu, pdulen);
@@ -439,18 +443,18 @@ sms_get_store_or_send_command (MMSmsPart *part,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Not enough memory to send SMS PDU");
- return NULL;
+ return FALSE;
}
/* CMGW/S length is the size of the PDU without SMSC information */
- cmd = g_strdup_printf ("+CMG%c=%d\r%s\x1a",
- store_or_send ? 'S' : 'W',
- pdulen - msgstart,
- hex);
+ *out_cmd = g_strdup_printf ("+CMG%c=%d",
+ store_or_send ? 'S' : 'W',
+ pdulen - msgstart);
+ *out_msg_data = g_strdup_printf ("%s\x1a", hex);
g_free (hex);
}
- return cmd;
+ return TRUE;
}
/*****************************************************************************/
@@ -459,6 +463,7 @@ sms_get_store_or_send_command (MMSmsPart *part,
typedef struct {
MMSms *self;
MMBaseModem *modem;
+ char *msg_data;
GSimpleAsyncResult *result;
} SmsStoreContext;
@@ -469,6 +474,7 @@ sms_store_context_complete_and_free (SmsStoreContext *ctx)
g_object_unref (ctx->result);
g_object_unref (ctx->modem);
g_object_unref (ctx->self);
+ g_free (ctx->msg_data);
g_free (ctx);
}
@@ -481,9 +487,9 @@ sms_store_finish (MMSms *self,
}
static void
-store_ready (MMBaseModem *modem,
- GAsyncResult *res,
- SmsStoreContext *ctx)
+store_msg_data_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ SmsStoreContext *ctx)
{
const gchar *response;
GError *error = NULL;
@@ -518,6 +524,30 @@ store_ready (MMBaseModem *modem,
}
static void
+store_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ SmsStoreContext *ctx)
+{
+ const gchar *response;
+ GError *error = NULL;
+
+ response = mm_base_modem_at_command_finish (MM_BASE_MODEM (modem), res, &error);
+ if (error) {
+ g_simple_async_result_take_error (ctx->result, error);
+ sms_store_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* Send the actual message data */
+ mm_base_modem_at_command_raw (ctx->modem,
+ ctx->msg_data,
+ 10,
+ FALSE,
+ (GAsyncReadyCallback) store_msg_data_ready,
+ ctx);
+}
+
+static void
sms_store (MMSms *self,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -554,16 +584,20 @@ sms_store (MMSms *self,
MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &use_pdu_mode,
NULL);
- cmd = sms_get_store_or_send_command ((MMSmsPart *)ctx->self->priv->parts->data,
- use_pdu_mode,
- FALSE,
- &error);
- if (!cmd) {
+ if (!sms_get_store_or_send_command ((MMSmsPart *)ctx->self->priv->parts->data,
+ use_pdu_mode,
+ FALSE,
+ &cmd,
+ &ctx->msg_data,
+ &error)) {
g_simple_async_result_take_error (ctx->result, error);
sms_store_context_complete_and_free (ctx);
return;
}
+ g_assert (cmd != NULL);
+ g_assert (ctx->msg_data != NULL);
+
mm_base_modem_at_command (ctx->modem,
cmd,
10,
@@ -579,6 +613,7 @@ sms_store (MMSms *self,
typedef struct {
MMSms *self;
MMBaseModem *modem;
+ char *msg_data;
GSimpleAsyncResult *result;
} SmsSendContext;
@@ -601,6 +636,24 @@ sms_send_finish (MMSms *self,
}
static void
+send_generic_msg_data_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ SmsSendContext *ctx)
+{
+ GError *error = NULL;
+
+ mm_base_modem_at_command_finish (MM_BASE_MODEM (modem), res, &error);
+ if (error) {
+ g_simple_async_result_take_error (ctx->result, error);
+ sms_send_context_complete_and_free (ctx);
+ return;
+ }
+
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ sms_send_context_complete_and_free (ctx);
+}
+
+static void
send_generic_ready (MMBaseModem *modem,
GAsyncResult *res,
SmsSendContext *ctx)
@@ -614,8 +667,13 @@ send_generic_ready (MMBaseModem *modem,
return;
}
- g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
- sms_send_context_complete_and_free (ctx);
+ /* Send the actual message data */
+ mm_base_modem_at_command_raw (ctx->modem,
+ ctx->msg_data,
+ 10,
+ FALSE,
+ (GAsyncReadyCallback)send_generic_msg_data_ready,
+ ctx);
}
static void
@@ -630,16 +688,20 @@ sms_send_generic (SmsSendContext *ctx)
MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &use_pdu_mode,
NULL);
- cmd = sms_get_store_or_send_command ((MMSmsPart *)ctx->self->priv->parts->data,
- use_pdu_mode,
- FALSE,
- &error);
- if (!cmd) {
+ if (!sms_get_store_or_send_command ((MMSmsPart *)ctx->self->priv->parts->data,
+ use_pdu_mode,
+ TRUE,
+ &cmd,
+ &ctx->msg_data,
+ &error)) {
g_simple_async_result_take_error (ctx->result, error);
sms_send_context_complete_and_free (ctx);
return;
}
+ g_assert (cmd != NULL);
+ g_assert (ctx->msg_data != NULL);
+
mm_base_modem_at_command (ctx->modem,
cmd,
10,