diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2013-08-14 16:14:37 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-09-09 10:19:20 +0200 |
commit | e6a7c85661d33493a8de7f19c6c7ff8773b83e8c (patch) | |
tree | f59cdd1631b12c4b9c83f3c16571bc23506ab556 /src | |
parent | df47f1ac8f696c2712efc8c76bd9551d88c3d837 (diff) |
broadband-modem-qmi: handle OMA indications
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 271 | ||||
-rw-r--r-- | src/mm-modem-helpers-qmi.c | 80 | ||||
-rw-r--r-- | src/mm-modem-helpers-qmi.h | 9 |
3 files changed, 359 insertions, 1 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 760dfea0..08ab45ef 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -111,6 +111,11 @@ struct _MMBroadbandModemQmiPrivate { MMModemLocationSource enabled_sources; guint location_event_report_indication_id; + /* Oma helpers */ + gboolean oma_unsolicited_events_enabled; + gboolean oma_unsolicited_events_setup; + guint oma_event_report_indication_id; + /* Firmware helpers */ GList *firmware_list; MMFirmwareProperties *current_firmware; @@ -8032,6 +8037,261 @@ oma_check_support (MMIfaceModemOma *self, } /*****************************************************************************/ +/* Setup/Cleanup unsolicited event handlers (OMA interface) */ + +static void +oma_event_report_indication_cb (QmiClientNas *client, + QmiIndicationOmaEventReportOutput *output, + MMBroadbandModemQmi *self) +{ + QmiOmaSessionState qmi_session_state; + QmiOmaSessionType network_initiated_alert_session_type; + guint16 network_initiated_alert_session_id; + + /* Update session state? */ + if (qmi_indication_oma_event_report_output_get_session_state ( + output, + &qmi_session_state, + NULL)) { + QmiOmaSessionFailedReason qmi_oma_session_failed_reason = QMI_OMA_SESSION_FAILED_REASON_UNKNOWN; + + if (qmi_session_state == QMI_OMA_SESSION_STATE_FAILED) + qmi_indication_oma_event_report_output_get_session_fail_reason ( + output, + &qmi_oma_session_failed_reason, + NULL); + + mm_iface_modem_oma_update_session_state ( + MM_IFACE_MODEM_OMA (self), + mm_oma_session_state_from_qmi_oma_session_state (qmi_session_state), + mm_oma_session_state_failed_reason_from_qmi_oma_session_failed_reason (qmi_oma_session_failed_reason)); + } + + /* New network initiated session? */ + if (qmi_indication_oma_event_report_output_get_network_initiated_alert ( + output, + &network_initiated_alert_session_type, + &network_initiated_alert_session_id, + NULL)) { + mm_iface_modem_oma_add_pending_network_initiated_session ( + MM_IFACE_MODEM_OMA (self), + mm_oma_session_type_from_qmi_oma_session_type (network_initiated_alert_session_type), + (guint)network_initiated_alert_session_id); + } +} + +static gboolean +common_oma_setup_cleanup_unsolicited_events_finish (MMIfaceModemOma *_self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +common_setup_cleanup_oma_unsolicited_events (MMBroadbandModemQmi *self, + gboolean enable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + QmiClient *client = NULL; + + if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), + QMI_SERVICE_OMA, &client, + callback, user_data)) + return; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + common_setup_cleanup_oma_unsolicited_events); + + if (enable == self->priv->oma_unsolicited_events_setup) { + mm_dbg ("OMA unsolicited events already %s; skipping", + enable ? "setup" : "cleanup"); + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + return; + } + + /* Store new state */ + self->priv->oma_unsolicited_events_setup = enable; + + /* Connect/Disconnect "Event Report" indications */ + if (enable) { + g_assert (self->priv->oma_event_report_indication_id == 0); + self->priv->oma_event_report_indication_id = + g_signal_connect (client, + "event-report", + G_CALLBACK (oma_event_report_indication_cb), + self); + } else { + g_assert (self->priv->oma_event_report_indication_id != 0); + g_signal_handler_disconnect (client, self->priv->oma_event_report_indication_id); + self->priv->oma_event_report_indication_id = 0; + } + + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +oma_cleanup_unsolicited_events (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_setup_cleanup_oma_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + FALSE, + callback, + user_data); +} + +static void +oma_setup_unsolicited_events (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_setup_cleanup_oma_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + TRUE, + callback, + user_data); +} + +/*****************************************************************************/ +/* Enable/Disable unsolicited events (OMA interface) */ + +typedef struct { + MMBroadbandModemQmi *self; + GSimpleAsyncResult *result; + QmiClientOma *client; + gboolean enable; +} EnableOmaUnsolicitedEventsContext; + +static void +enable_oma_unsolicited_events_context_complete_and_free (EnableOmaUnsolicitedEventsContext *ctx) +{ + g_simple_async_result_complete (ctx->result); + g_object_unref (ctx->result); + g_object_unref (ctx->client); + g_object_unref (ctx->self); + g_slice_free (EnableOmaUnsolicitedEventsContext, ctx); +} + +static gboolean +common_oma_enable_disable_unsolicited_events_finish (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +ser_oma_indicator_ready (QmiClientOma *client, + GAsyncResult *res, + EnableOmaUnsolicitedEventsContext *ctx) +{ + QmiMessageOmaSetEventReportOutput *output = NULL; + GError *error = NULL; + + output = qmi_client_oma_set_event_report_finish (client, res, &error); + if (!output) { + mm_dbg ("QMI operation failed: '%s'", error->message); + g_error_free (error); + } else if (!qmi_message_oma_set_event_report_output_get_result (output, &error)) { + mm_dbg ("Couldn't set event report: '%s'", error->message); + g_error_free (error); + } + + if (output) + qmi_message_oma_set_event_report_output_unref (output); + + /* Just ignore errors for now */ + ctx->self->priv->oma_unsolicited_events_enabled = ctx->enable; + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + enable_oma_unsolicited_events_context_complete_and_free (ctx); +} + +static void +common_enable_disable_oma_unsolicited_events (MMBroadbandModemQmi *self, + gboolean enable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EnableOmaUnsolicitedEventsContext *ctx; + GSimpleAsyncResult *result; + QmiClient *client = NULL; + QmiMessageOmaSetEventReportInput *input; + + if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), + QMI_SERVICE_OMA, &client, + callback, user_data)) + return; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + common_enable_disable_oma_unsolicited_events); + + if (enable == self->priv->oma_unsolicited_events_enabled) { + mm_dbg ("OMA unsolicited events already %s; skipping", + enable ? "enabled" : "disabled"); + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + return; + } + + ctx = g_slice_new0 (EnableOmaUnsolicitedEventsContext); + ctx->self = g_object_ref (self); + ctx->client = g_object_ref (client); + ctx->enable = enable; + ctx->result = result; + + input = qmi_message_oma_set_event_report_input_new (); + qmi_message_oma_set_event_report_input_set_session_state_reporting ( + input, + ctx->enable, + NULL); + qmi_message_oma_set_event_report_input_set_network_initiated_alert_reporting ( + input, + ctx->enable, + NULL); + qmi_client_oma_set_event_report ( + ctx->client, + input, + 5, + NULL, + (GAsyncReadyCallback)ser_oma_indicator_ready, + ctx); + qmi_message_oma_set_event_report_input_unref (input); +} + +static void +oma_disable_unsolicited_events (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_enable_disable_oma_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + FALSE, + callback, + user_data); +} + +static void +oma_enable_unsolicited_events (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_enable_disable_oma_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + TRUE, + callback, + user_data); +} + +/*****************************************************************************/ /* Check firmware support (Firmware interface) */ typedef struct { @@ -9366,7 +9626,8 @@ initialization_started (MMBroadbandModem *self, ctx->services[1] = QMI_SERVICE_NAS; ctx->services[2] = QMI_SERVICE_WMS; ctx->services[3] = QMI_SERVICE_PDS; - ctx->services[4] = QMI_SERVICE_UNKNOWN; + ctx->services[4] = QMI_SERVICE_OMA; + ctx->services[5] = QMI_SERVICE_UNKNOWN; /* Now open our QMI port */ mm_qmi_port_open (ctx->qmi, @@ -9650,6 +9911,14 @@ iface_modem_oma_init (MMIfaceModemOma *iface) { iface->check_support = oma_check_support; iface->check_support_finish = oma_check_support_finish; + iface->setup_unsolicited_events = oma_setup_unsolicited_events; + iface->setup_unsolicited_events_finish = common_oma_setup_cleanup_unsolicited_events_finish; + iface->cleanup_unsolicited_events = oma_cleanup_unsolicited_events; + iface->cleanup_unsolicited_events_finish = common_oma_setup_cleanup_unsolicited_events_finish; + iface->enable_unsolicited_events = oma_enable_unsolicited_events; + iface->enable_unsolicited_events_finish = common_oma_enable_disable_unsolicited_events_finish; + iface->disable_unsolicited_events = oma_disable_unsolicited_events; + iface->disable_unsolicited_events_finish = common_oma_enable_disable_unsolicited_events_finish; } static void diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c index 61d8b271..ece937ef 100644 --- a/src/mm-modem-helpers-qmi.c +++ b/src/mm-modem-helpers-qmi.c @@ -1271,3 +1271,83 @@ mm_modem_capability_from_qmi_capabilities_context (MMQmiCapabilitiesContext *ctx return tmp; } + +/*****************************************************************************/ + +MMOmaSessionType +mm_oma_session_type_from_qmi_oma_session_type (QmiOmaSessionType qmi_session_type) +{ + switch (qmi_session_type) { + case QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_DEVICE_CONFIGURE: + return MM_OMA_SESSION_TYPE_CLIENT_INITIATED_DEVICE_CONFIGURE; + case QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_PRL_UPDATE: + return MM_OMA_SESSION_TYPE_CLIENT_INITIATED_PRL_UPDATE; + case QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_HANDS_FREE_ACTIVATION: + return MM_OMA_SESSION_TYPE_CLIENT_INITIATED_HANDS_FREE_ACTIVATION; + case QMI_OMA_SESSION_TYPE_DEVICE_INITIATED_HANDS_FREE_ACTIVATION: + return MM_OMA_SESSION_TYPE_DEVICE_INITIATED_HANDS_FREE_ACTIVATION; + case QMI_OMA_SESSION_TYPE_NETWORK_INITIATED_PRL_UPDATE: + return MM_OMA_SESSION_TYPE_NETWORK_INITIATED_PRL_UPDATE; + case QMI_OMA_SESSION_TYPE_NETWORK_INITIATED_DEVICE_CONFIGURE: + return MM_OMA_SESSION_TYPE_NETWORK_INITIATED_DEVICE_CONFIGURE; + case QMI_OMA_SESSION_TYPE_DEVICE_INITIATED_PRL_UPDATE: + return MM_OMA_SESSION_TYPE_DEVICE_INITIATED_PRL_UPDATE; + default: + return MM_OMA_SESSION_TYPE_UNKNOWN; + } +} + +MMOmaSessionState +mm_oma_session_state_from_qmi_oma_session_state (QmiOmaSessionState qmi_session_state) +{ + /* Note: MM_OMA_SESSION_STATE_STARTED is not a state received from the modem */ + + switch (qmi_session_state) { + case QMI_OMA_SESSION_STATE_COMPLETE_INFORMATION_UPDATED: + case QMI_OMA_SESSION_STATE_COMPLETE_UPDATED_INFORMATION_UNAVAILABLE: + return MM_OMA_SESSION_STATE_COMPLETED; + case QMI_OMA_SESSION_STATE_FAILED: + return MM_OMA_SESSION_STATE_FAILED; + case QMI_OMA_SESSION_STATE_RETRYING: + return MM_OMA_SESSION_STATE_RETRYING; + case QMI_OMA_SESSION_STATE_CONNECTING: + return MM_OMA_SESSION_STATE_CONNECTING; + case QMI_OMA_SESSION_STATE_CONNECTED: + return MM_OMA_SESSION_STATE_CONNECTED; + case QMI_OMA_SESSION_STATE_AUTHENTICATED: + return MM_OMA_SESSION_STATE_AUTHENTICATED; + case QMI_OMA_SESSION_STATE_MDN_DOWNLOADED: + return MM_OMA_SESSION_STATE_MDN_DOWNLOADED; + case QMI_OMA_SESSION_STATE_MSID_DOWNLOADED: + return MM_OMA_SESSION_STATE_MSID_DOWNLOADED; + case QMI_OMA_SESSION_STATE_PRL_DOWNLOADED: + return MM_OMA_SESSION_STATE_PRL_DOWNLOADED; + case QMI_OMA_SESSION_STATE_MIP_PROFILE_DOWNLOADED: + return MM_OMA_SESSION_STATE_MIP_PROFILE_DOWNLOADED; + default: + return MM_OMA_SESSION_STATE_UNKNOWN; + } +} + +/*****************************************************************************/ + +MMOmaSessionStateFailedReason +mm_oma_session_state_failed_reason_from_qmi_oma_session_failed_reason (QmiOmaSessionFailedReason qmi_session_failed_reason) +{ + switch (qmi_session_failed_reason) { + case QMI_OMA_SESSION_FAILED_REASON_UNKNOWN: + return MM_OMA_SESSION_STATE_FAILED_REASON_UNKNOWN; + case QMI_OMA_SESSION_FAILED_REASON_NETWORK_UNAVAILABLE: + return MM_OMA_SESSION_STATE_FAILED_REASON_NETWORK_UNAVAILABLE; + case QMI_OMA_SESSION_FAILED_REASON_SERVER_UNAVAILABLE: + return MM_OMA_SESSION_STATE_FAILED_REASON_SERVER_UNAVAILABLE; + case QMI_OMA_SESSION_FAILED_REASON_AUTHENTICATION_FAILED: + return MM_OMA_SESSION_STATE_FAILED_REASON_AUTHENTICATION_FAILED; + case QMI_OMA_SESSION_FAILED_REASON_MAX_RETRY_EXCEEDED: + return MM_OMA_SESSION_STATE_FAILED_REASON_MAX_RETRY_EXCEEDED; + case QMI_OMA_SESSION_FAILED_REASON_SESSION_CANCELLED: + return MM_OMA_SESSION_STATE_FAILED_REASON_SESSION_CANCELLED; + default: + return MM_OMA_SESSION_STATE_FAILED_REASON_UNKNOWN; + } +} diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h index 63b05311..ff2196cd 100644 --- a/src/mm-modem-helpers-qmi.h +++ b/src/mm-modem-helpers-qmi.h @@ -95,6 +95,15 @@ MMSmsState mm_sms_state_from_qmi_message_tag (QmiWmsMessageTagType tag); QmiWdsAuthentication mm_bearer_allowed_auth_to_qmi_authentication (MMBearerAllowedAuth auth); /*****************************************************************************/ +/* QMI/OMA to MM translations */ + +MMOmaSessionType mm_oma_session_type_from_qmi_oma_session_type (QmiOmaSessionType qmi_session_type); + +MMOmaSessionState mm_oma_session_state_from_qmi_oma_session_state (QmiOmaSessionState qmi_session_state); + +MMOmaSessionStateFailedReason mm_oma_session_state_failed_reason_from_qmi_oma_session_failed_reason (QmiOmaSessionFailedReason qmi_session_failed_reason); + +/*****************************************************************************/ /* Utility to gather current capabilities from various sources */ typedef struct { |