Merge request !1321 from 'cbm/channels-mmcli'
CellBroadcast: Add libmm-glib and mmcli support for setting channels https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1321 Closes #934
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (C) 2024 Guido Günther <agx@sigxcpu.org>
|
||||
* Copyright (C) 2024-2025 Guido Günther <agx@sigxcpu.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -49,8 +49,13 @@ static Context *ctx;
|
||||
static gboolean status_flag;
|
||||
static gboolean list_flag;
|
||||
static gchar *delete_str;
|
||||
static gchar *channels_str;
|
||||
|
||||
static GOptionEntry entries[] = {
|
||||
{ "cell-broadcast-status", 0, 0, G_OPTION_ARG_NONE, &status_flag,
|
||||
"Show cell broadcast status",
|
||||
NULL
|
||||
},
|
||||
{ "cell-broadcast-list-cbm", 0, 0, G_OPTION_ARG_NONE, &list_flag,
|
||||
"List cell broadcast messages available in a given modem",
|
||||
NULL
|
||||
@@ -59,6 +64,10 @@ static GOptionEntry entries[] = {
|
||||
"Delete a cell broadcast message from a given modem",
|
||||
"[PATH|INDEX]"
|
||||
},
|
||||
{ "cell-broadcast-set-channels", 0, 0, G_OPTION_ARG_STRING, &channels_str,
|
||||
"Set the channel list",
|
||||
"[FIRST_CHANNEL-LAST_CHANNEL,FIRST_CHANNEL-LAST_CHANNEL...]"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -86,8 +95,10 @@ mmcli_modem_cell_broadcast_options_enabled (void)
|
||||
if (checked)
|
||||
return !!n_actions;
|
||||
|
||||
n_actions = (list_flag +
|
||||
!!delete_str);
|
||||
n_actions = (status_flag +
|
||||
list_flag +
|
||||
!!delete_str +
|
||||
!!channels_str);
|
||||
|
||||
if (n_actions > 1) {
|
||||
g_printerr ("error: too many Cell Broadcast actions requested\n");
|
||||
@@ -155,6 +166,21 @@ output_cbm_info (MMCbm *cbm)
|
||||
g_free (extra);
|
||||
}
|
||||
|
||||
static void
|
||||
print_cell_broadcast_status (void)
|
||||
{
|
||||
g_autofree MMCellBroadcastChannels *channels = NULL;
|
||||
guint channels_len = 0;
|
||||
gchar *str = NULL;
|
||||
|
||||
mm_modem_cell_broadcast_get_channels (ctx->modem_cell_broadcast, &channels, &channels_len);
|
||||
if (channels)
|
||||
str = mm_common_build_channels_string (channels, channels_len);
|
||||
|
||||
mmcli_output_string_take (MMC_F_CELL_BROADCAST_CHANNELS, str);
|
||||
mmcli_output_dump ();
|
||||
}
|
||||
|
||||
static void
|
||||
list_process_reply (GList *result,
|
||||
const GError *error)
|
||||
@@ -237,6 +263,50 @@ get_cbm_to_delete_ready (GDBusConnection *connection,
|
||||
g_object_unref (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
set_channels_process_reply (gboolean result,
|
||||
const GError *error)
|
||||
{
|
||||
if (!result) {
|
||||
g_printerr ("error: couldn't set channels: '%s'\n",
|
||||
error ? error->message : "unknown error");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_print ("successfully set channels in the modem\n");
|
||||
}
|
||||
|
||||
static void
|
||||
set_channels_ready (MMModemCellBroadcast *cell_broadcast,
|
||||
GAsyncResult *result,
|
||||
gpointer nothing)
|
||||
{
|
||||
gboolean operation_result;
|
||||
GError *error = NULL;
|
||||
|
||||
operation_result = mm_modem_cell_broadcast_set_channels_finish (cell_broadcast, result, &error);
|
||||
set_channels_process_reply (operation_result, error);
|
||||
|
||||
mmcli_async_operation_done ();
|
||||
}
|
||||
|
||||
static void
|
||||
parse_channels (MMCellBroadcastChannels **channels,
|
||||
guint *n_channels)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
mm_common_get_cell_broadcast_channels_from_string (channels_str,
|
||||
channels,
|
||||
n_channels,
|
||||
&error);
|
||||
if (error) {
|
||||
g_printerr ("error: couldn't parse list of channels: '%s'\n",
|
||||
error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_modem_ready (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -274,6 +344,21 @@ get_modem_ready (GObject *source,
|
||||
return;
|
||||
}
|
||||
|
||||
if (channels_str) {
|
||||
g_autofree MMCellBroadcastChannels *channels = NULL;
|
||||
guint n_channels;
|
||||
|
||||
parse_channels (&channels, &n_channels);
|
||||
g_debug ("Asynchronously setting channels...");
|
||||
mm_modem_cell_broadcast_set_channels (ctx->modem_cell_broadcast,
|
||||
channels,
|
||||
n_channels,
|
||||
ctx->cancellable,
|
||||
(GAsyncReadyCallback)set_channels_ready,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
||||
@@ -313,6 +398,13 @@ mmcli_modem_cell_broadcast_run_synchronous (GDBusConnection *connection)
|
||||
|
||||
ensure_modem_cell_broadcast ();
|
||||
|
||||
/* Request to get cell broadcst status? */
|
||||
if (status_flag) {
|
||||
g_debug ("Printing cell broadcast status...");
|
||||
print_cell_broadcast_status ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Request to list the CBM? */
|
||||
if (list_flag) {
|
||||
GList *result;
|
||||
@@ -351,5 +443,22 @@ mmcli_modem_cell_broadcast_run_synchronous (GDBusConnection *connection)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set channels */
|
||||
if (channels_str) {
|
||||
gboolean result;
|
||||
g_autofree MMCellBroadcastChannels *channels = NULL;
|
||||
guint n_channels;
|
||||
|
||||
parse_channels (&channels, &n_channels);
|
||||
g_debug ("Synchronously setting channels...");
|
||||
result = mm_modem_cell_broadcast_set_channels_sync (ctx->modem_cell_broadcast,
|
||||
channels,
|
||||
n_channels,
|
||||
NULL,
|
||||
&error);
|
||||
set_channels_process_reply (result, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ static SectionInfo section_infos[] = {
|
||||
[MMC_S_MODEM_3GPP_USSD] = { "3GPP USSD" },
|
||||
[MMC_S_MODEM_3GPP_PROFILE_MANAGER] = { "3GPP profile manager" },
|
||||
[MMC_S_MODEM_CDMA] = { "CDMA" },
|
||||
[MMC_S_MODEM_CELL_BROADCAST] = { "Cell Broadcast" },
|
||||
[MMC_S_MODEM_SIM] = { "SIM" },
|
||||
[MMC_S_MODEM_BEARER] = { "Bearer" },
|
||||
[MMC_S_MODEM_TIME] = { "Time" },
|
||||
@@ -167,6 +168,7 @@ static FieldInfo field_infos[] = {
|
||||
[MMC_F_CDMA_REGISTRATION_CDMA1X] = { "modem.cdma.cdma1x-registration-state", "registration cdma1x", MMC_S_MODEM_CDMA, },
|
||||
[MMC_F_CDMA_REGISTRATION_EVDO] = { "modem.cdma.evdo-registration-state", "registration evdo", MMC_S_MODEM_CDMA, },
|
||||
[MMC_F_CDMA_ACTIVATION] = { "modem.cdma.activation-state", "activation", MMC_S_MODEM_CDMA, },
|
||||
[MMC_F_CELL_BROADCAST_CHANNELS] = { "modem.cellbroadcast.channels", "channels", MMC_S_MODEM_CELL_BROADCAST, },
|
||||
[MMC_F_SIM_PATH] = { "modem.generic.sim", "primary sim path", MMC_S_MODEM_SIM, },
|
||||
[MMC_F_SIM_PRIMARY_SLOT] = { "modem.generic.primary-sim-slot", NULL, MMC_S_MODEM_SIM, },
|
||||
[MMC_F_SIM_SLOT_PATHS] = { "modem.generic.sim-slots", "sim slot paths", MMC_S_MODEM_SIM, },
|
||||
|
||||
@@ -46,6 +46,7 @@ typedef enum {
|
||||
MMC_S_MODEM_3GPP_USSD,
|
||||
MMC_S_MODEM_3GPP_PROFILE_MANAGER,
|
||||
MMC_S_MODEM_CDMA,
|
||||
MMC_S_MODEM_CELL_BROADCAST,
|
||||
MMC_S_MODEM_SIM,
|
||||
MMC_S_MODEM_BEARER,
|
||||
MMC_S_MODEM_TIME,
|
||||
@@ -173,6 +174,8 @@ typedef enum {
|
||||
MMC_F_CDMA_REGISTRATION_CDMA1X,
|
||||
MMC_F_CDMA_REGISTRATION_EVDO,
|
||||
MMC_F_CDMA_ACTIVATION,
|
||||
/* CellBroadcast section */
|
||||
MMC_F_CELL_BROADCAST_CHANNELS,
|
||||
/* SIM section */
|
||||
MMC_F_SIM_PATH,
|
||||
MMC_F_SIM_PRIMARY_SLOT,
|
||||
|
||||
@@ -740,6 +740,24 @@ Use \fBSECONDS\fR for the timeout when performing operations with this
|
||||
command. This option is useful when executing long running operations, like
|
||||
\fB\-\-3gpp\-scan\fR.
|
||||
|
||||
.SH CELL BROADCAST OPTIONS
|
||||
|
||||
All cell broadcast options must be used with \fB\-\-modem\fR or \fB\-m\fR.
|
||||
|
||||
.TP
|
||||
.B \-\-cell\-broadcast\-status
|
||||
Show the status of the cell broadcast support.
|
||||
.TP
|
||||
.B \-\-cell\-broadcast\-list\-cbm
|
||||
List cell broadcast messages available on a given modem.
|
||||
.TP
|
||||
.B \-\-cell\-broadcast\-delete\-cbm=[PATH|INDEX]
|
||||
Delete cell broadcast message at the given path or index
|
||||
.TP
|
||||
.B \-\-cell\-broadcast\-set\-channels=[CHANNELS]
|
||||
Set the list of channels on which cell broadcasts are received (e.g. \fB5370,5371-5372\fR)
|
||||
.RS 9
|
||||
|
||||
.SH EXAMPLES
|
||||
.SS Send the PIN to the SIM card
|
||||
|
||||
@@ -988,6 +1006,16 @@ XTRA assistance data is usually valid for several days.
|
||||
successfully setup location gathering
|
||||
.Ed
|
||||
|
||||
.SS Setting the Cell Broadcast channel list
|
||||
|
||||
The channel list can be set as a comma separated list of channels or channel intervals:
|
||||
|
||||
.Bd -literal -compact
|
||||
$ sudo mmcli -m 0 \\
|
||||
--cell-broadcast-set-channels=5370,5371,5373-5000
|
||||
successfully set channels in the modem
|
||||
.Ed
|
||||
|
||||
.SS Key-Value output
|
||||
|
||||
Writing shell scripts that use mmcli to perform operations with the
|
||||
|
||||
@@ -174,6 +174,36 @@ mm_common_build_mode_combinations_string (const MMModemModeCombination *modes,
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
gchar *
|
||||
mm_common_build_channels_string (const MMCellBroadcastChannels *channels,
|
||||
guint n_channels)
|
||||
{
|
||||
gboolean first = TRUE;
|
||||
GString *str;
|
||||
guint i;
|
||||
|
||||
if (!channels || !n_channels)
|
||||
return g_strdup ("none");
|
||||
|
||||
str = g_string_new ("");
|
||||
for (i = 0; i < n_channels; i++) {
|
||||
if (channels[i].start == channels[i].end) {
|
||||
g_string_append_printf (str, "%s%u",
|
||||
first ? "" : ",",
|
||||
channels[i].start);
|
||||
} else {
|
||||
g_string_append_printf (str, "%s%u-%u",
|
||||
first ? "" : ",",
|
||||
channels[i].start, channels[i].end);
|
||||
}
|
||||
|
||||
if (first)
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* String to enums/flags parsers */
|
||||
|
||||
@@ -738,6 +768,90 @@ mm_common_get_profile_source_from_string (const gchar *str,
|
||||
error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_common_get_cell_broadcast_channels_from_string (const gchar *str,
|
||||
MMCellBroadcastChannels **channels,
|
||||
guint *n_channels,
|
||||
GError **error)
|
||||
{
|
||||
GError *inner_error = NULL;
|
||||
GArray *array;
|
||||
g_auto(GStrv) channel_strings = NULL;
|
||||
|
||||
array = g_array_new (FALSE, FALSE, sizeof (MMCellBroadcastChannels));
|
||||
|
||||
channel_strings = g_strsplit (str, ",", -1);
|
||||
|
||||
if (channel_strings) {
|
||||
guint i;
|
||||
|
||||
for (i = 0; channel_strings[i]; i++) {
|
||||
char *startptr, *endptr;
|
||||
gint64 start;
|
||||
|
||||
startptr = channel_strings[i];
|
||||
start = g_ascii_strtoll (startptr, &endptr, 10);
|
||||
if (startptr == endptr || start > G_MAXUINT16 || start < 0) {
|
||||
inner_error = g_error_new (MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_INVALID_ARGS,
|
||||
"Couldn't parse '%s' as MMCellBroadcastChannel start value",
|
||||
channel_strings[i]);
|
||||
break;
|
||||
}
|
||||
if (*endptr == '\0') {
|
||||
MMCellBroadcastChannels ch;
|
||||
|
||||
ch.start = start;
|
||||
ch.end = start;
|
||||
g_array_append_val (array, ch);
|
||||
} else if (*endptr == '-') {
|
||||
gint64 end;
|
||||
|
||||
startptr = endptr + 1;
|
||||
end = g_ascii_strtoll (startptr, &endptr, 10);
|
||||
if (startptr == endptr || end > G_MAXUINT16 || end < 0) {
|
||||
inner_error = g_error_new (MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_INVALID_ARGS,
|
||||
"Couldn't parse '%s' as MMCellBroadcastChannel end value",
|
||||
channel_strings[i]);
|
||||
break;
|
||||
}
|
||||
if (*endptr == '\0') {
|
||||
MMCellBroadcastChannels ch;
|
||||
|
||||
ch.start = start;
|
||||
ch.end = end;
|
||||
g_array_append_val (array, ch);
|
||||
} else {
|
||||
inner_error = g_error_new (MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_INVALID_ARGS,
|
||||
"Couldn't parse '%s' as MMCellBroadcastChannel end value",
|
||||
channel_strings[i]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
inner_error = g_error_new (MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_INVALID_ARGS,
|
||||
"Couldn't parse '%s' as MMCellBroadcastChannel value",
|
||||
channel_strings[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inner_error) {
|
||||
g_propagate_error (error, inner_error);
|
||||
g_array_free (array, TRUE);
|
||||
*n_channels = 0;
|
||||
*channels = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*n_channels = array->len;
|
||||
*channels = (MMCellBroadcastChannels *)g_array_free (array, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* MMModemPortInfo array management */
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ gchar *mm_common_build_sms_storages_string (const MMSmsStorage *s
|
||||
guint n_storages);
|
||||
gchar *mm_common_build_mode_combinations_string (const MMModemModeCombination *modes,
|
||||
guint n_modes);
|
||||
gchar *mm_common_build_channels_string (const MMCellBroadcastChannels *channels,
|
||||
guint n_channels);
|
||||
|
||||
/******************************************************************************/
|
||||
/* String to enums/flags parsers */
|
||||
@@ -102,6 +104,10 @@ MMBearerAccessTypePreference mm_common_get_access_type_preference_from_string
|
||||
GError **error);
|
||||
MMBearerProfileSource mm_common_get_profile_source_from_string (const gchar *str,
|
||||
GError **error);
|
||||
gboolean mm_common_get_cell_broadcast_channels_from_string (const gchar *str,
|
||||
MMCellBroadcastChannels **channels,
|
||||
guint *n_channels,
|
||||
GError **error);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2024 Guido Günther <agx@sigxcpu.org>
|
||||
* Copyright (C) 2024-2025 Guido Günther <agx@sigxcpu.org>
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
@@ -43,6 +43,8 @@ G_DEFINE_TYPE (MMModemCellBroadcast, mm_modem_cell_broadcast, MM_GDBUS_TYPE_MODE
|
||||
struct _MMModemCellBroadcastPrivate {
|
||||
/* Common mutex to sync access */
|
||||
GMutex mutex;
|
||||
|
||||
PROPERTY_ARRAY_DECLARE (channels)
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -91,6 +93,11 @@ mm_modem_cell_broadcast_dup_path (MMModemCellBroadcast *self)
|
||||
RETURN_NON_EMPTY_STRING (value);
|
||||
}
|
||||
|
||||
PROPERTY_ARRAY_DEFINE (channels,
|
||||
ModemCellBroadcast, modem_cell_broadcast, MODEM_CELL_BROADCAST,
|
||||
MMCellBroadcastChannels,
|
||||
mm_common_cell_broadcast_channels_variant_to_garray)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
@@ -406,11 +413,117 @@ mm_modem_cell_broadcast_delete_sync (MMModemCellBroadcast *self,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* mm_modem_cell_broadcast_set_channels_finish
|
||||
* @self: A #MMModemCellBroadcast.
|
||||
* @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to
|
||||
* mm_modem_cell_broadcast_set_channels()
|
||||
* @error: Return location for error or %NULL.
|
||||
*
|
||||
* Finishes an operation started with mm_modem_cell_broadcast_set_channels().
|
||||
*
|
||||
* Returns: %TRUE if set default storage is success, %FALSE if @error is set.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
gboolean
|
||||
mm_modem_cell_broadcast_set_channels_finish (MMModemCellBroadcast *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_MODEM_CELL_BROADCAST (self), FALSE);
|
||||
|
||||
return mm_gdbus_modem_cell_broadcast_call_set_channels_finish (MM_GDBUS_MODEM_CELL_BROADCAST (self),
|
||||
res,
|
||||
error);
|
||||
}
|
||||
|
||||
/**
|
||||
* mm_modem_cell_broadcast_set_channels
|
||||
* @self: A #MMModemCellBroadcast.
|
||||
* @channels: The #MMCellbroadcastChannels to set
|
||||
* @n_channels: The number of elements in `channels`
|
||||
* @cancellable: (allow-none): A #GCancellable or %NULL.
|
||||
* @callback: A #GAsyncReadyCallback to call when the request is satisfied or
|
||||
* %NULL
|
||||
* @user_data: User data to pass to @callback.
|
||||
*
|
||||
* Asynchronously set the #MMCellbroadcastChannel s in the modem.
|
||||
*
|
||||
* When the operation is finished, @callback will be invoked in the
|
||||
* <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
|
||||
* of the thread you are calling this method from. You can then call
|
||||
* mm_modem_cell_broadcast_set_channels_finish() to get the result of the operation.
|
||||
*
|
||||
* See mm_modem_cell_broadcast_set_channels_sync() for the synchronous, blocking version
|
||||
* of this method.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
void
|
||||
mm_modem_cell_broadcast_set_channels (MMModemCellBroadcast *self,
|
||||
const MMCellBroadcastChannels *channels,
|
||||
guint n_channels,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GVariant *channels_variant;
|
||||
|
||||
g_return_if_fail (MM_IS_MODEM_CELL_BROADCAST (self));
|
||||
|
||||
channels_variant = mm_common_cell_broadcast_channels_array_to_variant (channels, n_channels);
|
||||
mm_gdbus_modem_cell_broadcast_call_set_channels (MM_GDBUS_MODEM_CELL_BROADCAST (self),
|
||||
channels_variant,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mm_modem_cell_broadcast_set_channels_sync
|
||||
* @self: A #MMModemCellBroadcast.
|
||||
* @channels: The #MMCellbroadcastChannels to set
|
||||
* @n_channels: The number of elements in `channels`
|
||||
* @cancellable: (allow-none): A #GCancellable or %NULL.
|
||||
* @error: Return location for error or %NULL.
|
||||
*
|
||||
* Asynchronously set the #MMCellbroadcastChannel s in the modem.
|
||||
*
|
||||
* The calling thread is blocked until a reply is received. See
|
||||
* mm_modem_cell_broadcast_set_channels() for the asynchronous version of this method.
|
||||
*
|
||||
* Returns: %TRUE if the operation was successful, %FALSE if @error is set.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
gboolean
|
||||
mm_modem_cell_broadcast_set_channels_sync (MMModemCellBroadcast *self,
|
||||
const MMCellBroadcastChannels *channels,
|
||||
guint n_channels,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GVariant *channels_variant;
|
||||
|
||||
g_return_val_if_fail (MM_IS_MODEM_CELL_BROADCAST (self), FALSE);
|
||||
|
||||
channels_variant = mm_common_cell_broadcast_channels_array_to_variant (channels, n_channels);
|
||||
return mm_gdbus_modem_cell_broadcast_call_set_channels_sync (MM_GDBUS_MODEM_CELL_BROADCAST (self),
|
||||
channels_variant,
|
||||
cancellable,
|
||||
error);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
mm_modem_cell_broadcast_init (MMModemCellBroadcast *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_MODEM_CELL_BROADCAST, MMModemCellBroadcastPrivate);
|
||||
g_mutex_init (&self->priv->mutex);
|
||||
|
||||
PROPERTY_INITIALIZE (channels, "channels")
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -420,6 +533,8 @@ finalize (GObject *object)
|
||||
|
||||
g_mutex_clear (&self->priv->mutex);
|
||||
|
||||
PROPERTY_ARRAY_FINALIZE (channels)
|
||||
|
||||
G_OBJECT_CLASS (mm_modem_cell_broadcast_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,13 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMModemCellBroadcast, g_object_unref)
|
||||
const gchar *mm_modem_cell_broadcast_get_path (MMModemCellBroadcast *self);
|
||||
gchar *mm_modem_cell_broadcast_dup_path (MMModemCellBroadcast *self);
|
||||
|
||||
gboolean mm_modem_cell_broadcast_get_channels (MMModemCellBroadcast *self,
|
||||
MMCellBroadcastChannels **channels,
|
||||
guint *n_storages);
|
||||
gboolean mm_modem_cell_broadcast_peek_channels (MMModemCellBroadcast *self,
|
||||
const MMCellBroadcastChannels **channels,
|
||||
guint *n_storages);
|
||||
|
||||
void mm_modem_cell_broadcast_list (MMModemCellBroadcast *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
@@ -92,6 +99,23 @@ gboolean mm_modem_cell_broadcast_delete_sync (MMModemCellBroadcast *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean mm_modem_cell_broadcast_set_channels_finish (MMModemCellBroadcast *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
void mm_modem_cell_broadcast_set_channels (MMModemCellBroadcast *self,
|
||||
const MMCellBroadcastChannels *channels,
|
||||
guint n_channels,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean mm_modem_cell_broadcast_set_channels_sync (MMModemCellBroadcast *self,
|
||||
const MMCellBroadcastChannels *channels,
|
||||
guint n_channels,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _MM_MODEM_CELL_BROADCAST_H_ */
|
||||
|
||||
@@ -761,6 +761,28 @@ sms_storages_to_string (void)
|
||||
g_clear_pointer (&sms_storages_str, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
cell_broadcast_channels_to_string (void)
|
||||
{
|
||||
gchar *channels_str = NULL;
|
||||
MMCellBroadcastChannels channels[] = {
|
||||
{ .start = 4383, .end = 4383 },
|
||||
{ .start = 4380, .end = 4382 }
|
||||
};
|
||||
|
||||
channels_str = mm_common_build_channels_string (NULL, 0);
|
||||
g_assert_cmpstr (channels_str, ==, "none");
|
||||
g_clear_pointer (&channels_str, g_free);
|
||||
|
||||
channels_str = mm_common_build_channels_string (channels, 1);
|
||||
g_assert_cmpstr (channels_str, ==, "4383");
|
||||
g_clear_pointer (&channels_str, g_free);
|
||||
|
||||
channels_str = mm_common_build_channels_string (channels, 2);
|
||||
g_assert_cmpstr (channels_str, ==, "4383,4380-4382");
|
||||
g_clear_pointer (&channels_str, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
capabilities_from_string (void)
|
||||
{
|
||||
@@ -1012,7 +1034,7 @@ call_direction_from_string (void)
|
||||
|
||||
call_direction = mm_common_get_call_direction_from_string ("incoming", &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (call_direction == MM_CALL_DIRECTION_INCOMING);
|
||||
g_assert (call_direction == MM_CALL_DIRECTION_INCOMING);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1256,7 +1278,7 @@ access_type_preference_from_string (void)
|
||||
|
||||
access_type_preference = mm_common_get_access_type_preference_from_string ("3gpp-preferred", &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (access_type_preference == MM_BEARER_ACCESS_TYPE_PREFERENCE_3GPP_PREFERRED);
|
||||
g_assert (access_type_preference == MM_BEARER_ACCESS_TYPE_PREFERENCE_3GPP_PREFERRED);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1275,6 +1297,68 @@ profile_source_from_string (void)
|
||||
g_assert (profile_source == MM_BEARER_PROFILE_SOURCE_MODEM);
|
||||
}
|
||||
|
||||
static void
|
||||
cell_broadcast_channels_from_string (void)
|
||||
{
|
||||
MMCellBroadcastChannels *channels = NULL;
|
||||
guint n_channels = 0;
|
||||
gboolean ret = FALSE;
|
||||
GError *error = NULL;
|
||||
|
||||
ret = mm_common_get_cell_broadcast_channels_from_string ("not found", &channels, &n_channels, &error);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_assert_false (ret);
|
||||
g_assert_cmpuint (n_channels, ==, 0);
|
||||
g_assert_null (channels);
|
||||
g_clear_error (&error);
|
||||
|
||||
ret = mm_common_get_cell_broadcast_channels_from_string ("4370", &channels, &n_channels, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (ret);
|
||||
g_assert_cmpuint (n_channels, ==, 1);
|
||||
g_assert_cmpuint (channels[0].start, ==, 4370);
|
||||
g_assert_cmpuint (channels[0].end, ==, 4370);
|
||||
g_clear_pointer(&channels, g_free);
|
||||
|
||||
ret = mm_common_get_cell_broadcast_channels_from_string ("4370,4371-abc", &channels, &n_channels, &error);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_assert_false (ret);
|
||||
g_assert_cmpuint (n_channels, ==, 0);
|
||||
g_assert_null (channels);
|
||||
g_clear_error (&error);
|
||||
|
||||
ret = mm_common_get_cell_broadcast_channels_from_string ("4370,,4371-5000", &channels, &n_channels, &error);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_assert_false (ret);
|
||||
g_assert_cmpuint (n_channels, ==, 0);
|
||||
g_assert_null (channels);
|
||||
g_clear_error (&error);
|
||||
|
||||
ret = mm_common_get_cell_broadcast_channels_from_string ("4370,,-5000", &channels, &n_channels, &error);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_assert_false (ret);
|
||||
g_assert_cmpuint (n_channels, ==, 0);
|
||||
g_assert_null (channels);
|
||||
g_clear_error (&error);
|
||||
|
||||
ret = mm_common_get_cell_broadcast_channels_from_string ("65537", &channels, &n_channels, &error);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_assert_false (ret);
|
||||
g_assert_cmpuint (n_channels, ==, 0);
|
||||
g_assert_null (channels);
|
||||
g_clear_error (&error);
|
||||
|
||||
ret = mm_common_get_cell_broadcast_channels_from_string ("4370,4371-5000", &channels, &n_channels, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (ret);
|
||||
g_assert_cmpuint (n_channels, ==, 2);
|
||||
g_assert_cmpuint (channels[0].start, ==, 4370);
|
||||
g_assert_cmpuint (channels[0].end, ==, 4370);
|
||||
g_assert_cmpuint (channels[1].start, ==, 4371);
|
||||
g_assert_cmpuint (channels[1].end, ==, 5000);
|
||||
g_clear_pointer(&channels, g_free);
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
int main (int argc, char **argv)
|
||||
@@ -1328,6 +1412,7 @@ int main (int argc, char **argv)
|
||||
g_test_add_func ("/MM/Common/StrConvTo/mode-combinations", mode_combinations_to_string);
|
||||
g_test_add_func ("/MM/Common/StrConvTo/ports", ports_to_string);
|
||||
g_test_add_func ("/MM/Common/StrConvTo/sms-storages", sms_storages_to_string);
|
||||
g_test_add_func ("/MM/Common/StrConvTo/cb-channels", cell_broadcast_channels_to_string);
|
||||
|
||||
g_test_add_func ("/MM/Common/StrConvFrom/capabilities", capabilities_from_string);
|
||||
g_test_add_func ("/MM/Common/StrConvFrom/modes", modes_from_string);
|
||||
@@ -1354,6 +1439,7 @@ int main (int argc, char **argv)
|
||||
g_test_add_func ("/MM/Common/StrConvFrom/3gpp_drx_cycle", _3gpp_drx_cycle_from_string);
|
||||
g_test_add_func ("/MM/Common/StrConvFrom/access_type", access_type_preference_from_string);
|
||||
g_test_add_func ("/MM/Common/StrConvFrom/profile_source", profile_source_from_string);
|
||||
g_test_add_func ("/MM/Common/StrConvFrom/cb_channels", cell_broadcast_channels_from_string);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user