iface-modem-3gpp-ussd: allow error reporting in encode/decode

This commit is contained in:
Aleksander Morgado
2012-03-15 14:14:57 +01:00
parent 7210e6caf1
commit 2bf40184e0
3 changed files with 129 additions and 81 deletions
+115 -73
View File
@@ -2819,7 +2819,8 @@ modem_3gpp_setup_ps_registration (MMIfaceModem3gpp *self,
static gchar *
modem_3gpp_ussd_encode (MMIfaceModem3gppUssd *self,
const gchar *command,
guint *scheme)
guint *scheme,
GError **error)
{
MMBroadbandModem *broadband = MM_BROADBAND_MODEM (self);
GByteArray *ussd_command;
@@ -2844,7 +2845,8 @@ modem_3gpp_ussd_encode (MMIfaceModem3gppUssd *self,
static gchar *
modem_3gpp_ussd_decode (MMIfaceModem3gppUssd *self,
const gchar *reply)
const gchar *reply,
GError **error)
{
MMBroadbandModem *broadband = MM_BROADBAND_MODEM (self);
@@ -2865,7 +2867,8 @@ modem_3gpp_ussd_setup_cleanup_unsolicited_result_codes_finish (MMIfaceModem3gppU
static gchar *
decode_ussd_response (MMBroadbandModem *self,
const gchar *reply)
const gchar *reply,
GError **error)
{
gchar **items, **iter, *p;
gchar *str = NULL;
@@ -2874,8 +2877,14 @@ decode_ussd_response (MMBroadbandModem *self,
/* Look for the first ',' */
p = strchr (reply, ',');
if (!p)
if (!p) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Cannot decode USSD response (%s): missing field separator",
reply);
return NULL;
}
items = g_strsplit_set (p + 1, " ,", -1);
for (iter = items; iter && *iter; iter++) {
@@ -2890,8 +2899,14 @@ decode_ussd_response (MMBroadbandModem *self,
}
}
if (!str)
if (!str) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Cannot decode USSD response (%s): not enough fields",
reply);
return NULL;
}
/* Strip quotes */
if (str[0] == '"')
@@ -2900,7 +2915,7 @@ decode_ussd_response (MMBroadbandModem *self,
if (p)
*p = '\0';
decoded = mm_iface_modem_3gpp_ussd_decode (MM_IFACE_MODEM_3GPP_USSD (self), str);
decoded = mm_iface_modem_3gpp_ussd_decode (MM_IFACE_MODEM_3GPP_USSD (self), str, error);
g_strfreev (items);
return decoded;
}
@@ -2910,82 +2925,109 @@ cusd_received (MMAtSerialPort *port,
GMatchInfo *info,
MMBroadbandModem *self)
{
gint status;
gchar *str;
MMModem3gppUssdSessionState ussd_state = MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE;
str = g_match_info_fetch (info, 1);
if (!str || !isdigit (*str)) {
mm_warn ("Received invalid USSD response: '%s'", str ? str : "(none)");
g_free (str);
return;
}
status = g_ascii_digit_value (*str);
switch (status) {
case 0: /* no further action required */ {
gchar *converted;
converted = decode_ussd_response (self, str);
if (self->priv->pending_ussd_action) {
/* Response to the user's request */
g_simple_async_result_set_op_res_gpointer (self->priv->pending_ussd_action,
converted,
g_free);
} else {
/* Network-initiated USSD-Notify */
mm_iface_modem_3gpp_ussd_update_network_notification (
MM_IFACE_MODEM_3GPP_USSD (self),
converted);
g_free (converted);
}
break;
}
case 1: /* further action required */ {
gchar *converted;
ussd_state = MM_MODEM_3GPP_USSD_SESSION_STATE_USER_RESPONSE;
converted = decode_ussd_response (self, str);
if (self->priv->pending_ussd_action) {
g_simple_async_result_set_op_res_gpointer (self->priv->pending_ussd_action,
converted,
g_free);
} else {
/* Network-initiated USSD-Request */
mm_iface_modem_3gpp_ussd_update_network_request (
MM_IFACE_MODEM_3GPP_USSD (self),
converted);
g_free (converted);
}
break;
}
case 2:
if (self->priv->pending_ussd_action)
g_simple_async_result_set_error (self->priv->pending_ussd_action,
MM_CORE_ERROR,
MM_CORE_ERROR_CANCELLED,
"USSD terminated by network.");
break;
case 4:
if (self->priv->pending_ussd_action)
g_simple_async_result_set_error (self->priv->pending_ussd_action,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Operation not supported.");
break;
default:
if (self->priv->pending_ussd_action)
g_simple_async_result_set_error (self->priv->pending_ussd_action,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Unhandled USSD reply: %s (%d)",
str,
status);
break;
"Invalid USSD response received: '%s'",
str ? str : "(none)");
else
mm_warn ("Received invalid USSD network-initiated request: '%s'",
str ? str : "(none)");
} else {
gint status;
status = g_ascii_digit_value (*str);
switch (status) {
case 0: /* no further action required */ {
gchar *converted;
GError *error = NULL;
converted = decode_ussd_response (self, str, &error);
if (self->priv->pending_ussd_action) {
/* Response to the user's request */
if (error)
g_simple_async_result_take_error (self->priv->pending_ussd_action, error);
else
g_simple_async_result_set_op_res_gpointer (self->priv->pending_ussd_action,
converted,
g_free);
} else {
if (error) {
mm_warn ("Invalid network initiated USSD notification: %s",
error->message);
g_error_free (error);
} else {
/* Network-initiated USSD-Notify */
mm_iface_modem_3gpp_ussd_update_network_notification (
MM_IFACE_MODEM_3GPP_USSD (self),
converted);
g_free (converted);
}
}
break;
}
case 1: /* further action required */ {
gchar *converted;
GError *error = NULL;
ussd_state = MM_MODEM_3GPP_USSD_SESSION_STATE_USER_RESPONSE;
converted = decode_ussd_response (self, str, &error);
if (self->priv->pending_ussd_action) {
if (error)
g_simple_async_result_take_error (self->priv->pending_ussd_action, error);
else
g_simple_async_result_set_op_res_gpointer (self->priv->pending_ussd_action,
converted,
g_free);
} else {
if (error) {
mm_warn ("Invalid network initiated USSD request: %s",
error->message);
g_error_free (error);
} else {
/* Network-initiated USSD-Request */
mm_iface_modem_3gpp_ussd_update_network_request (
MM_IFACE_MODEM_3GPP_USSD (self),
converted);
g_free (converted);
}
}
break;
}
case 2:
if (self->priv->pending_ussd_action)
g_simple_async_result_set_error (self->priv->pending_ussd_action,
MM_CORE_ERROR,
MM_CORE_ERROR_CANCELLED,
"USSD terminated by network.");
break;
case 4:
if (self->priv->pending_ussd_action)
g_simple_async_result_set_error (self->priv->pending_ussd_action,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Operation not supported.");
break;
default:
if (self->priv->pending_ussd_action)
g_simple_async_result_set_error (self->priv->pending_ussd_action,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Unhandled USSD reply: %s (%d)",
str,
status);
break;
}
}
mm_iface_modem_3gpp_ussd_update_state (MM_IFACE_MODEM_3GPP_USSD (self),
+6 -4
View File
@@ -236,16 +236,18 @@ handle_initiate (MmGdbusModem3gppUssd *skeleton,
gchar *
mm_iface_modem_3gpp_ussd_encode (MMIfaceModem3gppUssd *self,
const gchar *command,
guint *scheme)
guint *scheme,
GError **error)
{
return MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->encode (self, command, scheme);
return MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->encode (self, command, scheme, error);
}
gchar *
mm_iface_modem_3gpp_ussd_decode (MMIfaceModem3gppUssd *self,
const gchar *reply)
const gchar *reply,
GError **error)
{
return MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->decode (self, reply);
return MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->decode (self, reply, error);
}
/*****************************************************************************/
+8 -4
View File
@@ -82,9 +82,11 @@ struct _MMIfaceModem3gppUssd {
/* Encode/Decode */
gchar * (*encode) (MMIfaceModem3gppUssd *self,
const gchar *command,
guint *scheme);
guint *scheme,
GError **error);
gchar * (*decode) (MMIfaceModem3gppUssd *self,
const gchar *reply);
const gchar *reply,
GError **error);
/* Send command */
void (* send) (MMIfaceModem3gppUssd *self,
@@ -142,9 +144,11 @@ void mm_iface_modem_3gpp_ussd_update_network_request (MMIfaceModem3gppUssd
/* Encode/Decode USSD */
gchar *mm_iface_modem_3gpp_ussd_encode (MMIfaceModem3gppUssd *self,
const gchar *command,
guint *scheme);
guint *scheme,
GError **error);
gchar *mm_iface_modem_3gpp_ussd_decode (MMIfaceModem3gppUssd *self,
const gchar *reply);
const gchar *reply,
GError **error);
/* Shutdown USSD interface */
void mm_iface_modem_3gpp_ussd_shutdown (MMIfaceModem3gppUssd *self);