diff options
-rw-r--r-- | cli/mmcli-modem-cell-broadcast.c | 115 | ||||
-rw-r--r-- | cli/mmcli-output.c | 2 | ||||
-rw-r--r-- | cli/mmcli-output.h | 3 | ||||
-rw-r--r-- | docs/man/mmcli.1 | 28 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.c | 114 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.h | 6 | ||||
-rw-r--r-- | libmm-glib/mm-modem-cell-broadcast.c | 117 | ||||
-rw-r--r-- | libmm-glib/mm-modem-cell-broadcast.h | 24 | ||||
-rw-r--r-- | libmm-glib/tests/test-common-helpers.c | 90 |
9 files changed, 493 insertions, 6 deletions
diff --git a/cli/mmcli-modem-cell-broadcast.c b/cli/mmcli-modem-cell-broadcast.c index 8121e8a5..2e6c975f 100644 --- a/cli/mmcli-modem-cell-broadcast.c +++ b/cli/mmcli-modem-cell-broadcast.c @@ -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"); @@ -156,6 +167,21 @@ output_cbm_info (MMCbm *cbm) } 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) { @@ -238,6 +264,50 @@ get_cbm_to_delete_ready (GDBusConnection *connection, } 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, gpointer none) @@ -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 (); } diff --git a/cli/mmcli-output.c b/cli/mmcli-output.c index 1884e906..440d6059 100644 --- a/cli/mmcli-output.c +++ b/cli/mmcli-output.c @@ -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, }, diff --git a/cli/mmcli-output.h b/cli/mmcli-output.h index 8dde1412..a9f050d8 100644 --- a/cli/mmcli-output.h +++ b/cli/mmcli-output.h @@ -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, diff --git a/docs/man/mmcli.1 b/docs/man/mmcli.1 index 99a8fd4f..d15cb799 100644 --- a/docs/man/mmcli.1 +++ b/docs/man/mmcli.1 @@ -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 diff --git a/libmm-glib/mm-common-helpers.c b/libmm-glib/mm-common-helpers.c index e249a2fc..12796429 100644 --- a/libmm-glib/mm-common-helpers.c +++ b/libmm-glib/mm-common-helpers.c @@ -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 */ diff --git a/libmm-glib/mm-common-helpers.h b/libmm-glib/mm-common-helpers.h index bea220e0..d3b2a0fb 100644 --- a/libmm-glib/mm-common-helpers.h +++ b/libmm-glib/mm-common-helpers.h @@ -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); /******************************************************************************/ diff --git a/libmm-glib/mm-modem-cell-broadcast.c b/libmm-glib/mm-modem-cell-broadcast.c index fe7fd829..60495f84 100644 --- a/libmm-glib/mm-modem-cell-broadcast.c +++ b/libmm-glib/mm-modem-cell-broadcast.c @@ -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); } diff --git a/libmm-glib/mm-modem-cell-broadcast.h b/libmm-glib/mm-modem-cell-broadcast.h index a1049caf..9d9cafa3 100644 --- a/libmm-glib/mm-modem-cell-broadcast.h +++ b/libmm-glib/mm-modem-cell-broadcast.h @@ -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_ */ diff --git a/libmm-glib/tests/test-common-helpers.c b/libmm-glib/tests/test-common-helpers.c index b8923ab3..a84314ba 100644 --- a/libmm-glib/tests/test-common-helpers.c +++ b/libmm-glib/tests/test-common-helpers.c @@ -762,6 +762,28 @@ sms_storages_to_string (void) } 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) { MMModemCapability capability = MM_MODEM_CAPABILITY_ANY; @@ -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 (); } |