broadband-modem: Add Cell Broadcast implementation
The CBMs are read via unsolicted events for which we register an event handler. We don't enable unsolicted events explicitly as this already happens via the `+CNMI=*,*,2,*,*` whens setting up unsolicted events in `modem_messaging_enable_unsolicited_events` (ETSI TS 127 005).
This commit is contained in:
committed by
Aleksander Morgado
parent
62f7b76e8e
commit
60357247eb
@@ -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;
|
||||
};
|
||||
|
||||
@@ -10404,6 +10416,157 @@ modem_cdma_register_in_network (MMIfaceModemCdma *_self,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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) */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -14017,6 +14225,18 @@ iface_modem_cdma_init (MMIfaceModemCdmaInterface *iface)
|
||||
iface->register_in_network_finish = modem_cdma_register_in_network_finish;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -14188,6 +14408,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
|
||||
PROP_MODEM_CDMA_DBUS_SKELETON,
|
||||
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);
|
||||
@@ -14300,6 +14524,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
|
||||
PROP_MODEM_MESSAGING_SMS_DEFAULT_STORAGE,
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user