diff options
author | Dan Williams <dcbw@redhat.com> | 2012-03-01 17:22:56 -0600 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2012-03-01 17:23:46 -0600 |
commit | 5f6c65e7c1f23d3aa9f14580e5eb82c9ff4b8505 (patch) | |
tree | 8e6b9d314799e58c84cc7341da1da949358fb642 | |
parent | bc118aa1602b309101f1151805a2d8cdf0f916eb (diff) |
gsm: retry sending SMS in PDU mode if text fails and PDU is supported
In the future we'll just default to PDU mode.
-rw-r--r-- | src/mm-generic-gsm.c | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 0a0a2a1a..426d3db4 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -139,6 +139,7 @@ typedef struct { */ GHashTable *sms_parts; gboolean sms_pdu_mode; + gboolean sms_pdu_supported; guint sms_fetch_pending; @@ -1787,14 +1788,18 @@ sms_set_format_cb (MMAtSerialPort *port, GError *error, gpointer user_data) { + MMGenericGsm *self = MM_GENERIC_GSM (user_data); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + if (error) { mm_warn ("(%s): failed to set SMS mode, assuming text mode", mm_port_get_device (MM_PORT (port))); - MM_GENERIC_GSM_GET_PRIVATE (user_data)->sms_pdu_mode = FALSE; + priv->sms_pdu_mode = FALSE; + priv->sms_pdu_supported = FALSE; } else { mm_info ("(%s): using %s mode for SMS", mm_port_get_device (MM_PORT (port)), - MM_GENERIC_GSM_GET_PRIVATE (user_data)->sms_pdu_mode ? "PDU" : "text"); + priv->sms_pdu_mode ? "PDU" : "text"); } } @@ -1857,6 +1862,10 @@ sms_get_format_cb (MMAtSerialPort *port, mm_at_serial_port_queue_command (priv->primary, "AT+CMGF=0", 3, sms_set_format_cb, self); } else mm_at_serial_port_queue_command (priv->primary, "AT+CMGF=1", 3, sms_set_format_cb, self); + + /* Save whether PDU mode is supported so we can fall back to it if text fails */ + if (min == 0) + priv->sms_pdu_supported = TRUE; } g_match_info_free (match_info); @@ -4844,19 +4853,41 @@ sms_send_done (MMAtSerialPort *port, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - const char *p; + const char *p, *pdu; unsigned long num; GArray *indexes = NULL; guint32 idx = 0; + guint cmgs_pdu_size; + char *command; /* If the modem has already been removed, return without * scheduling callback */ if (mm_callback_info_check_modem_removed (info)) return; - if (error) + if (error) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + + /* If there was an error sending in text mode the retry with the PDU; + * text mode is pretty dumb on most devices and often fails. Later we'll + * just use text mode exclusively. + */ + pdu = mm_callback_info_get_data (info, "pdu"); + if (priv->sms_pdu_mode == FALSE && priv->sms_pdu_supported && pdu) { + cmgs_pdu_size = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "cmgs-pdu-size")); + g_assert (cmgs_pdu_size); + command = g_strdup_printf ("+CMGS=%d\r%s\x1a", cmgs_pdu_size, pdu); + mm_at_serial_port_queue_command (port, command, 10, sms_send_done, info); + g_free (command); + + /* Clear the PDU data so we don't keep getting here */ + mm_callback_info_set_data (info, "pdu", NULL, NULL); + return; + } + + /* Otherwise it's a hard error */ info->error = g_error_copy (error); - else { + } else { /* If the response happens to have a ">" in it from the interactive * handling of the CMGS command, skip it. */ @@ -4893,6 +4924,9 @@ sms_send (MMModemGsmSms *modem, MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); char *command; MMAtSerialPort *port; + guint8 *pdu; + guint pdulen = 0, msgstart = 0; + char *hex; info = mm_callback_info_new_full (MM_MODEM (modem), sms_send_invoke, @@ -4905,31 +4939,29 @@ sms_send (MMModemGsmSms *modem, return; } - if (priv->sms_pdu_mode) { - guint8 *pdu; - guint pdulen = 0, msgstart = 0; - char *hex; - - pdu = sms_create_submit_pdu (number, text, smsc, validity, class, &pdulen, &msgstart, &info->error); - if (!pdu) { - mm_callback_info_schedule (info); - return; - } + /* Always create a PDU since we might need it for fallback from text mode */ + pdu = sms_create_submit_pdu (number, text, smsc, validity, class, &pdulen, &msgstart, &info->error); + if (!pdu) { + mm_callback_info_schedule (info); + return; + } - hex = utils_bin2hexstr (pdu, pdulen); - g_free (pdu); - if (hex == NULL) { - g_set_error_literal (&info->error, - MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Not enough memory to send SMS PDU"); - mm_callback_info_schedule (info); - return; - } + hex = utils_bin2hexstr (pdu, pdulen); + g_free (pdu); + if (hex == NULL) { + g_set_error_literal (&info->error, + MM_MODEM_ERROR, + MM_MODEM_ERROR_GENERAL, + "Not enough memory to send SMS PDU"); + mm_callback_info_schedule (info); + return; + } + mm_callback_info_set_data (info, "pdu", hex, g_free); + mm_callback_info_set_data (info, "cmgs-pdu-size", GUINT_TO_POINTER (pdulen - msgstart), NULL); + if (priv->sms_pdu_mode) { /* CMGS length is the size of the PDU without SMSC information */ command = g_strdup_printf ("+CMGS=%d\r%s\x1a", pdulen - msgstart, hex); - g_free (hex); } else command = g_strdup_printf ("+CMGS=\"%s\"\r%s\x1a", number, text); |