diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2013-02-22 19:39:06 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-02-22 21:49:19 +0100 |
commit | 9976625f94335295843ff38440d9e48a6e899d3a (patch) | |
tree | 34de9b6efcc9cb3be12e820f2a3f5145c448855f | |
parent | b1bb8e30b4fd835649b5790895fcd519f1809141 (diff) |
broadband-modem: USSD response may come even before finishing our request
MBM devices seem to include the '+CUSD: 0' indication before even returning OK to our '+CUSD=1'
(ttyACM0): --> 'AT+CUSD=1,"*111#",15<CR>'
(ttyACM0): <-- '<CR><LF>+CUSD: 0,"reply here"<CR><LF>'
(ttyACM0): <-- '<CR><LF>OK<CR><LF>'
-rw-r--r-- | src/mm-broadband-modem.c | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index a3f5ba47..d1411e95 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -4100,7 +4100,7 @@ modem_3gpp_ussd_send_context_complete_and_free (Modem3gppUssdSendContext *ctx) } g_object_unref (ctx->self); g_free (ctx->command); - g_free (ctx); + g_slice_free (Modem3gppUssdSendContext, ctx); } static const gchar * @@ -4119,20 +4119,36 @@ modem_3gpp_ussd_send_finish (MMIfaceModem3gppUssd *self, static void modem_3gpp_ussd_context_step (Modem3gppUssdSendContext *ctx); +static void cusd_process_string (MMBroadbandModem *self, + const gchar *str); + static void ussd_send_command_ready (MMBroadbandModem *self, GAsyncResult *res, Modem3gppUssdSendContext *ctx) { GError *error = NULL; + const gchar *reply; - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + g_assert (ctx->result == NULL); + + reply = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (error) { /* Some immediate error happened when sending the USSD request */ mm_dbg ("Error sending USSD request: '%s'", error->message); g_error_free (error); - modem_3gpp_ussd_context_step (ctx); + if (self->priv->pending_ussd_action) { + /* Recover result */ + ctx->result = self->priv->pending_ussd_action; + self->priv->pending_ussd_action = NULL; + modem_3gpp_ussd_context_step (ctx); + return; + } + + /* So the USSD action was completed already... */ + mm_dbg ("USSD action already completed via URCs"); + modem_3gpp_ussd_send_context_complete_and_free (ctx); return; } @@ -4147,13 +4163,13 @@ ussd_send_command_ready (MMBroadbandModem *self, ctx->self->priv->use_unencoded_ussd = FALSE; } - /* Cache the action, as it will be completed via URCs. - * There shouldn't be any previous action pending. */ - g_warn_if_fail (self->priv->pending_ussd_action == NULL); - self->priv->pending_ussd_action = ctx->result; + if (!self->priv->pending_ussd_action) + mm_dbg ("USSD operation finished already via URCs"); + else if (reply && reply[0]) { + reply = mm_strip_tag (reply, "+CUSD:"); + cusd_process_string (ctx->self, reply); + } - /* Reset result so that it doesn't get completed */ - ctx->result = NULL; modem_3gpp_ussd_send_context_complete_and_free (ctx); } @@ -4184,6 +4200,12 @@ modem_3gpp_ussd_context_send_encoded (Modem3gppUssdSendContext *ctx) at_command = g_strdup_printf ("+CUSD=1,\"%s\",%d", encoded, scheme); g_free (encoded); + /* Cache the action, as it may be completed via URCs. + * There shouldn't be any previous action pending. */ + g_warn_if_fail (ctx->self->priv->pending_ussd_action == NULL); + ctx->self->priv->pending_ussd_action = ctx->result; + ctx->result = NULL; + mm_base_modem_at_command (MM_BASE_MODEM (ctx->self), at_command, 10, @@ -4204,6 +4226,13 @@ modem_3gpp_ussd_context_send_unencoded (Modem3gppUssdSendContext *ctx) at_command = g_strdup_printf ("+CUSD=1,\"%s\",%d", ctx->command, MM_MODEM_GSM_USSD_SCHEME_7BIT); + + /* Cache the action, as it may be completed via URCs. + * There shouldn't be any previous action pending. */ + g_warn_if_fail (ctx->self->priv->pending_ussd_action == NULL); + ctx->self->priv->pending_ussd_action = ctx->result; + ctx->result = NULL; + mm_base_modem_at_command (MM_BASE_MODEM (ctx->self), at_command, 10, @@ -4254,16 +4283,16 @@ modem_3gpp_ussd_send (MMIfaceModem3gppUssd *self, { Modem3gppUssdSendContext *ctx; - ctx = g_new0 (Modem3gppUssdSendContext, 1); + ctx = g_slice_new0 (Modem3gppUssdSendContext); /* We're going to steal the string result in finish() so we must have a * callback specified. */ g_assert (callback != NULL); + ctx->self = g_object_ref (self); + ctx->command = g_strdup (command); ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, modem_3gpp_ussd_send); - ctx->self = g_object_ref (self); - ctx->command = g_strdup (command); modem_3gpp_ussd_context_step (ctx); @@ -4384,14 +4413,11 @@ decode_ussd_response (MMBroadbandModem *self, } static void -cusd_received (MMAtSerialPort *port, - GMatchInfo *info, - MMBroadbandModem *self) +cusd_process_string (MMBroadbandModem *self, + const gchar *str) { - gchar *str; MMModem3gppUssdSessionState ussd_state = MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE; - str = g_match_info_fetch (info, 1); if (!str || !isdigit (*str)) { if (self->priv->pending_ussd_action) g_simple_async_result_set_error (self->priv->pending_ussd_action, @@ -4502,7 +4528,18 @@ cusd_received (MMAtSerialPort *port, g_object_unref (self->priv->pending_ussd_action); self->priv->pending_ussd_action = NULL; } +} +static void +cusd_received (MMAtSerialPort *port, + GMatchInfo *info, + MMBroadbandModem *self) +{ + gchar *str; + + mm_dbg ("Unsolicited USSD URC received"); + str = g_match_info_fetch (info, 1); + cusd_process_string (self, str); g_free (str); } |