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>'
This commit is contained in:
@@ -4100,7 +4100,7 @@ modem_3gpp_ussd_send_context_complete_and_free (Modem3gppUssdSendContext *ctx)
|
|||||||
}
|
}
|
||||||
g_object_unref (ctx->self);
|
g_object_unref (ctx->self);
|
||||||
g_free (ctx->command);
|
g_free (ctx->command);
|
||||||
g_free (ctx);
|
g_slice_free (Modem3gppUssdSendContext, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar *
|
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 modem_3gpp_ussd_context_step (Modem3gppUssdSendContext *ctx);
|
||||||
|
|
||||||
|
static void cusd_process_string (MMBroadbandModem *self,
|
||||||
|
const gchar *str);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ussd_send_command_ready (MMBroadbandModem *self,
|
ussd_send_command_ready (MMBroadbandModem *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
Modem3gppUssdSendContext *ctx)
|
Modem3gppUssdSendContext *ctx)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
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) {
|
if (error) {
|
||||||
/* Some immediate error happened when sending the USSD request */
|
/* Some immediate error happened when sending the USSD request */
|
||||||
mm_dbg ("Error sending USSD request: '%s'", error->message);
|
mm_dbg ("Error sending USSD request: '%s'", error->message);
|
||||||
g_error_free (error);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4147,13 +4163,13 @@ ussd_send_command_ready (MMBroadbandModem *self,
|
|||||||
ctx->self->priv->use_unencoded_ussd = FALSE;
|
ctx->self->priv->use_unencoded_ussd = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cache the action, as it will be completed via URCs.
|
if (!self->priv->pending_ussd_action)
|
||||||
* There shouldn't be any previous action pending. */
|
mm_dbg ("USSD operation finished already via URCs");
|
||||||
g_warn_if_fail (self->priv->pending_ussd_action == NULL);
|
else if (reply && reply[0]) {
|
||||||
self->priv->pending_ussd_action = ctx->result;
|
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);
|
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);
|
at_command = g_strdup_printf ("+CUSD=1,\"%s\",%d", encoded, scheme);
|
||||||
g_free (encoded);
|
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),
|
mm_base_modem_at_command (MM_BASE_MODEM (ctx->self),
|
||||||
at_command,
|
at_command,
|
||||||
10,
|
10,
|
||||||
@@ -4204,6 +4226,13 @@ modem_3gpp_ussd_context_send_unencoded (Modem3gppUssdSendContext *ctx)
|
|||||||
at_command = g_strdup_printf ("+CUSD=1,\"%s\",%d",
|
at_command = g_strdup_printf ("+CUSD=1,\"%s\",%d",
|
||||||
ctx->command,
|
ctx->command,
|
||||||
MM_MODEM_GSM_USSD_SCHEME_7BIT);
|
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),
|
mm_base_modem_at_command (MM_BASE_MODEM (ctx->self),
|
||||||
at_command,
|
at_command,
|
||||||
10,
|
10,
|
||||||
@@ -4254,16 +4283,16 @@ modem_3gpp_ussd_send (MMIfaceModem3gppUssd *self,
|
|||||||
{
|
{
|
||||||
Modem3gppUssdSendContext *ctx;
|
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
|
/* We're going to steal the string result in finish() so we must have a
|
||||||
* callback specified. */
|
* callback specified. */
|
||||||
g_assert (callback != NULL);
|
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),
|
ctx->result = g_simple_async_result_new (G_OBJECT (self),
|
||||||
callback,
|
callback,
|
||||||
user_data,
|
user_data,
|
||||||
modem_3gpp_ussd_send);
|
modem_3gpp_ussd_send);
|
||||||
ctx->self = g_object_ref (self);
|
|
||||||
ctx->command = g_strdup (command);
|
|
||||||
|
|
||||||
modem_3gpp_ussd_context_step (ctx);
|
modem_3gpp_ussd_context_step (ctx);
|
||||||
|
|
||||||
@@ -4384,14 +4413,11 @@ decode_ussd_response (MMBroadbandModem *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cusd_received (MMAtSerialPort *port,
|
cusd_process_string (MMBroadbandModem *self,
|
||||||
GMatchInfo *info,
|
const gchar *str)
|
||||||
MMBroadbandModem *self)
|
|
||||||
{
|
{
|
||||||
gchar *str;
|
|
||||||
MMModem3gppUssdSessionState ussd_state = MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE;
|
MMModem3gppUssdSessionState ussd_state = MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE;
|
||||||
|
|
||||||
str = g_match_info_fetch (info, 1);
|
|
||||||
if (!str || !isdigit (*str)) {
|
if (!str || !isdigit (*str)) {
|
||||||
if (self->priv->pending_ussd_action)
|
if (self->priv->pending_ussd_action)
|
||||||
g_simple_async_result_set_error (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);
|
g_object_unref (self->priv->pending_ussd_action);
|
||||||
self->priv->pending_ussd_action = NULL;
|
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);
|
g_free (str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user