diff options
-rw-r--r-- | src/mm-broadband-modem.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 9227f746..6f06b8f3 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -36,6 +36,7 @@ #include "mm-iface-modem-3gpp-profile-manager.h" #include "mm-iface-modem-3gpp-ussd.h" #include "mm-iface-modem-cdma.h" +#include "mm-iface-modem-cell-broadcast.h" #include "mm-iface-modem-simple.h" #include "mm-iface-modem-location.h" #include "mm-iface-modem-messaging.h" @@ -47,6 +48,8 @@ #include "mm-iface-modem-oma.h" #include "mm-broadband-bearer.h" #include "mm-bearer-list.h" +#include "mm-cbm-list.h" +#include "mm-cbm-part.h" #include "mm-sms-list.h" #include "mm-sms-part-3gpp.h" #include "mm-call-list.h" @@ -66,6 +69,7 @@ static void iface_modem_3gpp_init (MMIfaceModem3gppInterface static void iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManagerInterface *iface); static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssdInterface *iface); static void iface_modem_cdma_init (MMIfaceModemCdmaInterface *iface); +static void iface_modem_cell_broadcast_init (MMIfaceModemCellBroadcastInterface *iface); static void iface_modem_simple_init (MMIfaceModemSimpleInterface *iface); static void iface_modem_location_init (MMIfaceModemLocationInterface *iface); static void iface_modem_messaging_init (MMIfaceModemMessagingInterface *iface); @@ -82,6 +86,7 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModem, mm_broadband_modem, MM_TYPE_BASE_MODEM G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP_PROFILE_MANAGER, iface_modem_3gpp_profile_manager_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP_USSD, iface_modem_3gpp_ussd_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CELL_BROADCAST, iface_modem_cell_broadcast_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIMPLE, iface_modem_simple_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init) @@ -99,6 +104,7 @@ enum { PROP_MODEM_3GPP_PROFILE_MANAGER_DBUS_SKELETON, PROP_MODEM_3GPP_USSD_DBUS_SKELETON, PROP_MODEM_CDMA_DBUS_SKELETON, + PROP_MODEM_CELL_BROADCAST_DBUS_SKELETON, PROP_MODEM_SIMPLE_DBUS_SKELETON, PROP_MODEM_LOCATION_DBUS_SKELETON, PROP_MODEM_MESSAGING_DBUS_SKELETON, @@ -124,6 +130,7 @@ enum { PROP_MODEM_CDMA_EVDO_REGISTRATION_STATE, PROP_MODEM_CDMA_CDMA1X_NETWORK_SUPPORTED, PROP_MODEM_CDMA_EVDO_NETWORK_SUPPORTED, + PROP_MODEM_CELL_BROADCAST_CBM_LIST, PROP_MODEM_MESSAGING_SMS_LIST, PROP_MODEM_MESSAGING_SMS_PDU_MODE, PROP_MODEM_MESSAGING_SMS_DEFAULT_STORAGE, @@ -288,6 +295,11 @@ struct _MMBroadbandModemPrivate { /* Properties */ GObject *modem_sar_dbus_skeleton; + /*<--- Modem CellBroadcast interface --->*/ + /* Properties */ + GObject *modem_cell_broadcast_dbus_skeleton; + MMCbmList *modem_cell_broadcast_cbm_list; + gboolean modem_firmware_ignore_carrier; }; @@ -10405,6 +10417,157 @@ modem_cdma_register_in_network (MMIfaceModemCdma *_self, } /*****************************************************************************/ + +static gboolean +modem_cell_broadcast_setup_cleanup_unsolicited_events_finish (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +cbc_cbm_received (MMPortSerialAt *port, + GMatchInfo *info, + MMBroadbandModem *self) +{ + GError *error = NULL; + MMCbmPart *part; + guint length; + gchar *pdu; + + mm_obj_dbg (self, "got new cell broadcast message indication"); + + if (!mm_get_uint_from_match_info (info, 1, &length)) + return; + + pdu = g_match_info_fetch (info, 2); + if (!pdu) + return; + + part = mm_cbm_part_new_from_pdu (pdu, self, &error); + if (part) { + mm_obj_dbg (self, "correctly parsed PDU"); + mm_iface_modem_cell_broadcast_take_part (MM_IFACE_MODEM_CELL_BROADCAST (self), + part, + MM_CBM_STATE_RECEIVED); + } else { + /* Don't treat the error as critical */ + mm_obj_dbg (self, "error parsing PDU: %s", error->message); + g_error_free (error); + } +} + +static void +set_cell_broadcast_unsolicited_events_handlers (MMIfaceModemCellBroadcast *self, + gboolean enable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMPortSerialAt *ports[2]; + g_autoptr(GRegex) cbm_regex = NULL; + guint i; + GTask *task; + + cbm_regex = mm_3gpp_cbm_regex_get (); + ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); + ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); + + /* Add cell broadcast unsolicited events handler for port primary and secondary */ + for (i = 0; i < 2; i++) { + if (!ports[i]) + continue; + + /* Set/unset unsolicited CBM event handler */ + mm_obj_dbg (self, "%s cell broadcast unsolicited events handlers in %s", + enable ? "setting" : "removing", + mm_port_get_device (MM_PORT (ports[i]))); + mm_port_serial_at_add_unsolicited_msg_handler ( + ports[i], + cbm_regex, + enable ? (MMPortSerialAtUnsolicitedMsgFn) cbc_cbm_received : NULL, + enable ? self : NULL, + NULL); + } + + task = g_task_new (self, NULL, callback, user_data); + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +modem_cell_broadcast_setup_unsolicited_events (MMIfaceModemCellBroadcast *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + set_cell_broadcast_unsolicited_events_handlers (self, TRUE, callback, user_data); +} + +static void +modem_cell_broadcast_cleanup_unsolicited_events (MMIfaceModemCellBroadcast *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + set_cell_broadcast_unsolicited_events_handlers (self, FALSE, callback, user_data); +} + +/*****************************************************************************/ +/* Create CBM (CellBroadcast interface) */ + +static MMBaseCbm * +modem_cell_broadcast_create_cbm (MMIfaceModemCellBroadcast *self) +{ + return mm_base_cbm_new (MM_BASE_MODEM (self)); +} + +/*********************************************************/ +/* Check CellBroadcast support (CellBroadcast interface) */ + +static gboolean +modem_cell_broadcast_check_support_finish (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +cscb_format_check_ready (MMBroadbandModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +modem_cell_broadcast_check_support (MMIfaceModemCellBroadcast *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + + /* Check cell broadcast support */ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CSCB=?", + 3, + TRUE, + (GAsyncReadyCallback)cscb_format_check_ready, + task); +} + +/*****************************************************************************/ /* Load location capabilities (Location interface) */ static MMModemLocationSource @@ -12084,6 +12247,7 @@ typedef enum { ENABLING_STEP_IFACE_LOCATION, ENABLING_STEP_IFACE_MESSAGING, ENABLING_STEP_IFACE_TIME, + ENABLING_STEP_IFACE_CELL_BROADCAST, ENABLING_STEP_IFACE_SIGNAL, ENABLING_STEP_IFACE_OMA, ENABLING_STEP_IFACE_VOICE, @@ -12195,6 +12359,7 @@ INTERFACE_ENABLE_READY_FN (iface_modem_3gpp, MM_IFACE_MODEM_3GPP INTERFACE_ENABLE_READY_FN (iface_modem_3gpp_profile_manager, MM_IFACE_MODEM_3GPP_PROFILE_MANAGER, FALSE) INTERFACE_ENABLE_READY_FN (iface_modem_3gpp_ussd, MM_IFACE_MODEM_3GPP_USSD, FALSE) INTERFACE_ENABLE_READY_FN (iface_modem_cdma, MM_IFACE_MODEM_CDMA, TRUE) +INTERFACE_ENABLE_READY_FN (iface_modem_cell_broadcast, MM_IFACE_MODEM_CELL_BROADCAST, FALSE) INTERFACE_ENABLE_READY_FN (iface_modem_location, MM_IFACE_MODEM_LOCATION, FALSE) INTERFACE_ENABLE_READY_FN (iface_modem_messaging, MM_IFACE_MODEM_MESSAGING, FALSE) INTERFACE_ENABLE_READY_FN (iface_modem_voice, MM_IFACE_MODEM_VOICE, FALSE) @@ -12389,6 +12554,19 @@ enabling_step (GTask *task) ctx->step++; /* fall through */ + case ENABLING_STEP_IFACE_CELL_BROADCAST: + if (self->priv->modem_cell_broadcast_dbus_skeleton) { + mm_obj_dbg (self, "modem has cell broadcast capabilities, enabling the cell broadcast interface..."); + /* Enabling the Modem CellBroadcast interface */ + mm_iface_modem_cell_broadcast_enable (MM_IFACE_MODEM_CELL_BROADCAST (self), + g_task_get_cancellable (task), + (GAsyncReadyCallback)iface_modem_cell_broadcast_enable_ready, + task); + return; + } + ctx->step++; + /* fall through */ + case ENABLING_STEP_IFACE_SIGNAL: if (self->priv->modem_signal_dbus_skeleton) { mm_obj_dbg (self, "modem has extended signal reporting capabilities, enabling the Signal interface..."); @@ -12742,6 +12920,7 @@ typedef enum { INITIALIZE_STEP_IFACE_SIGNAL, INITIALIZE_STEP_IFACE_OMA, INITIALIZE_STEP_IFACE_SAR, + INITIALIZE_STEP_IFACE_CELL_BROADCAST, INITIALIZE_STEP_FALLBACK_LIMITED, INITIALIZE_STEP_IFACE_LOCATION, INITIALIZE_STEP_IFACE_VOICE, @@ -12923,6 +13102,7 @@ INTERFACE_INIT_READY_FN (iface_modem_signal, MM_IFACE_MODEM_SIGNAL INTERFACE_INIT_READY_FN (iface_modem_oma, MM_IFACE_MODEM_OMA, FALSE) INTERFACE_INIT_READY_FN (iface_modem_firmware, MM_IFACE_MODEM_FIRMWARE, FALSE) INTERFACE_INIT_READY_FN (iface_modem_sar, MM_IFACE_MODEM_SAR, FALSE) +INTERFACE_INIT_READY_FN (iface_modem_cell_broadcast, MM_IFACE_MODEM_CELL_BROADCAST, FALSE) static void initialize_step (GTask *task) @@ -13075,6 +13255,14 @@ initialize_step (GTask *task) task); return; + case INITIALIZE_STEP_IFACE_CELL_BROADCAST: + /* Initialize the CellBroadcast interface */ + mm_iface_modem_cell_broadcast_initialize (MM_IFACE_MODEM_CELL_BROADCAST (ctx->self), + g_task_get_cancellable (task), + (GAsyncReadyCallback)iface_modem_cell_broadcast_initialize_ready, + task); + return; + case INITIALIZE_STEP_FALLBACK_LIMITED: /* All the initialization steps after this one will be run both on * successful and locked/failed initializations. */ @@ -13393,6 +13581,10 @@ set_property (GObject *object, g_clear_object (&self->priv->modem_cdma_dbus_skeleton); self->priv->modem_cdma_dbus_skeleton = g_value_dup_object (value); break; + case PROP_MODEM_CELL_BROADCAST_DBUS_SKELETON: + g_clear_object (&self->priv->modem_cell_broadcast_dbus_skeleton); + self->priv->modem_cell_broadcast_dbus_skeleton = g_value_dup_object (value); + break; case PROP_MODEM_SIMPLE_DBUS_SKELETON: g_clear_object (&self->priv->modem_simple_dbus_skeleton); self->priv->modem_simple_dbus_skeleton = g_value_dup_object (value); @@ -13491,6 +13683,10 @@ set_property (GObject *object, case PROP_MODEM_MESSAGING_SMS_DEFAULT_STORAGE: self->priv->modem_messaging_sms_default_storage = g_value_get_enum (value); break; + case PROP_MODEM_CELL_BROADCAST_CBM_LIST: + g_clear_object (&self->priv->modem_cell_broadcast_cbm_list); + self->priv->modem_cell_broadcast_cbm_list = g_value_dup_object (value); + break; case PROP_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS: self->priv->modem_location_allow_gps_unmanaged_always = g_value_get_boolean (value); break; @@ -13559,6 +13755,9 @@ get_property (GObject *object, case PROP_MODEM_CDMA_DBUS_SKELETON: g_value_set_object (value, self->priv->modem_cdma_dbus_skeleton); break; + case PROP_MODEM_CELL_BROADCAST_DBUS_SKELETON: + g_value_set_object (value, self->priv->modem_cell_broadcast_dbus_skeleton); + break; case PROP_MODEM_SIMPLE_DBUS_SKELETON: g_value_set_object (value, self->priv->modem_simple_dbus_skeleton); break; @@ -13643,6 +13842,9 @@ get_property (GObject *object, case PROP_MODEM_MESSAGING_SMS_DEFAULT_STORAGE: g_value_set_enum (value, self->priv->modem_messaging_sms_default_storage); break; + case PROP_MODEM_CELL_BROADCAST_CBM_LIST: + g_value_set_object (value, self->priv->modem_cell_broadcast_cbm_list); + break; case PROP_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS: g_value_set_boolean (value, self->priv->modem_location_allow_gps_unmanaged_always); break; @@ -13773,6 +13975,11 @@ dispose (GObject *object) g_clear_object (&self->priv->modem_cdma_dbus_skeleton); } + if (self->priv->modem_cell_broadcast_dbus_skeleton) { + mm_iface_modem_cell_broadcast_shutdown (MM_IFACE_MODEM_CELL_BROADCAST (object)); + g_clear_object (&self->priv->modem_cell_broadcast_dbus_skeleton); + } + if (self->priv->modem_location_dbus_skeleton) { mm_iface_modem_location_shutdown (MM_IFACE_MODEM_LOCATION (object)); g_clear_object (&self->priv->modem_location_dbus_skeleton); @@ -13820,6 +14027,7 @@ dispose (GObject *object) g_clear_object (&self->priv->modem_messaging_sms_list); g_clear_object (&self->priv->modem_voice_call_list); g_clear_object (&self->priv->modem_simple_status); + g_clear_object (&self->priv->modem_cell_broadcast_cbm_list); G_OBJECT_CLASS (mm_broadband_modem_parent_class)->dispose (object); } @@ -14018,6 +14226,18 @@ iface_modem_cdma_init (MMIfaceModemCdmaInterface *iface) } static void +iface_modem_cell_broadcast_init (MMIfaceModemCellBroadcastInterface *iface) +{ + iface->check_support = modem_cell_broadcast_check_support; + iface->check_support_finish = modem_cell_broadcast_check_support_finish; + iface->setup_unsolicited_events = modem_cell_broadcast_setup_unsolicited_events; + iface->setup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish; + iface->cleanup_unsolicited_events = modem_cell_broadcast_cleanup_unsolicited_events; + iface->cleanup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish; + iface->create_cbm = modem_cell_broadcast_create_cbm; +} + +static void iface_modem_simple_init (MMIfaceModemSimpleInterface *iface) { } @@ -14189,6 +14409,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass) MM_IFACE_MODEM_CDMA_DBUS_SKELETON); g_object_class_override_property (object_class, + PROP_MODEM_CELL_BROADCAST_DBUS_SKELETON, + MM_IFACE_MODEM_CELL_BROADCAST_DBUS_SKELETON); + + g_object_class_override_property (object_class, PROP_MODEM_SIMPLE_DBUS_SKELETON, MM_IFACE_MODEM_SIMPLE_DBUS_SKELETON); @@ -14301,6 +14525,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass) MM_IFACE_MODEM_MESSAGING_SMS_DEFAULT_STORAGE); g_object_class_override_property (object_class, + PROP_MODEM_CELL_BROADCAST_CBM_LIST, + MM_IFACE_MODEM_CELL_BROADCAST_CBM_LIST); + + g_object_class_override_property (object_class, PROP_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS, MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS); |