diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-08-24 12:01:01 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-08-24 12:32:29 +0200 |
commit | ba4e209745676a08f7c886d7cd0ba13202e336d5 (patch) | |
tree | cdcb533e86bffc3e97e383b3a2dc4078453d6649 /src | |
parent | 4fe7c7d637644de6b24e7d71a45aad3647086e19 (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.c | 19 | ||||
-rw-r--r-- | src/mm-sms.c | 118 |
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, |