aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-broadband-modem.c228
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);