aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/mmcli-modem-3gpp.c78
-rw-r--r--data/org.freedesktop.ModemManager1.conf.polkit4
-rw-r--r--docs/reference/libmm-glib/libmm-glib-sections.txt6
-rw-r--r--introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml14
-rw-r--r--libmm-glib/mm-modem-3gpp.c95
-rw-r--r--libmm-glib/mm-modem-3gpp.h15
-rw-r--r--src/mm-broadband-modem-mbim.c87
-rw-r--r--src/mm-iface-modem-3gpp.c96
-rw-r--r--src/mm-iface-modem-3gpp.h10
9 files changed, 404 insertions, 1 deletions
diff --git a/cli/mmcli-modem-3gpp.c b/cli/mmcli-modem-3gpp.c
index 957ad928..17734326 100644
--- a/cli/mmcli-modem-3gpp.c
+++ b/cli/mmcli-modem-3gpp.c
@@ -54,6 +54,7 @@ static gchar *set_initial_eps_bearer_settings_str;
static gchar *disable_facility_lock_str;
static gchar *set_packet_service_state_str;
static gchar *set_nr5g_registration_settings_str;
+static gchar *set_carrier_lock_str;
static GOptionEntry entries[] = {
{ "3gpp-scan", 0, 0, G_OPTION_ARG_NONE, &scan_flag,
@@ -88,6 +89,10 @@ static GOptionEntry entries[] = {
"Set 5GNR registration settings",
"[\"key=value,...\"]"
},
+ { "3gpp-set-carrier-lock", 0, 0, G_OPTION_ARG_STRING, &set_carrier_lock_str,
+ "Carrier Lock",
+ "[(Data)]"
+ },
{ NULL }
};
@@ -122,7 +127,8 @@ mmcli_modem_3gpp_options_enabled (void)
!!set_initial_eps_bearer_settings_str +
!!disable_facility_lock_str +
!!set_packet_service_state_str +
- !!set_nr5g_registration_settings_str);
+ !!set_nr5g_registration_settings_str +
+ !!set_carrier_lock_str);
if (n_actions > 1) {
g_printerr ("error: too many 3GPP actions requested\n");
@@ -421,6 +427,32 @@ set_nr5g_registration_settings_ready (MMModem3gpp *modem_3gpp,
}
static void
+set_carrier_lock_process_reply (gboolean result,
+ const GError *error)
+{
+ if (!result) {
+ g_printerr ("error: couldn't send carrier lock information: '%s'\n",
+ error ? error->message : "unknown error");
+ exit (EXIT_FAILURE);
+ }
+
+ g_print ("successfully sent carrier lock information to modem\n");
+}
+
+static void
+set_carrier_lock_ready (MMModem3gpp *modem_3gpp,
+ GAsyncResult *result)
+{
+ gboolean operation_result;
+ g_autoptr(GError) error = NULL;
+
+ operation_result = mm_modem_3gpp_set_carrier_lock_finish (modem_3gpp, result, &error);
+ set_carrier_lock_process_reply (operation_result, error);
+
+ mmcli_async_operation_done ();
+}
+
+static void
get_modem_ready (GObject *source,
GAsyncResult *result)
{
@@ -455,6 +487,28 @@ get_modem_ready (GObject *source,
return;
}
+ /* Request to set carrier Lock */
+ if (set_carrier_lock_str) {
+ gsize data_size = 0;
+ g_autofree guint8 *data = NULL;
+ GError *error = NULL;
+
+ data = mm_utils_hexstr2bin (set_carrier_lock_str, -1, &data_size, &error);
+ if (!data) {
+ g_printerr ("Failed to read data from the input: %s\n", error->message);
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+ mm_modem_3gpp_set_carrier_lock (ctx->modem_3gpp,
+ data,
+ (guint32)data_size,
+ ctx->cancellable,
+ (GAsyncReadyCallback)set_carrier_lock_ready,
+ NULL);
+ return;
+ }
+
ensure_modem_enabled ();
/* Request to scan networks? */
@@ -617,6 +671,28 @@ mmcli_modem_3gpp_run_synchronous (GDBusConnection *connection)
return;
}
+ /* Request to set carrier Lock */
+ if (set_carrier_lock_str) {
+ gsize data_size = 0;
+ g_autofree guint8 *data = NULL;
+ gboolean result;
+
+ data = mm_utils_hexstr2bin (set_carrier_lock_str, -1, &data_size, &error);
+ if (!data) {
+ g_printerr ("Failed to read data from the input: %s\n", error->message);
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+ result = mm_modem_3gpp_set_carrier_lock_sync (ctx->modem_3gpp,
+ data,
+ (guint32)data_size,
+ NULL,
+ &error);
+ set_carrier_lock_process_reply (result, error);
+ return;
+ }
+
ensure_modem_enabled ();
/* Request to register the modem? */
diff --git a/data/org.freedesktop.ModemManager1.conf.polkit b/data/org.freedesktop.ModemManager1.conf.polkit
index ab0e9e5c..5d66fb9f 100644
--- a/data/org.freedesktop.ModemManager1.conf.polkit
+++ b/data/org.freedesktop.ModemManager1.conf.polkit
@@ -128,6 +128,10 @@
send_interface="org.freedesktop.ModemManager1.Modem.Modem3gpp"
send_member="DisableFacilityLock"/>
+ <allow send_destination="org.freedesktop.ModemManager1"
+ send_interface="org.freedesktop.ModemManager1.Modem.Modem3gpp"
+ send_member="SetCarrierLock"/>
+
<!-- org.freedesktop.ModemManager1.Modem.ModemCdma.xml -->
<!-- Protected by the Device.Control policy rule -->
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index 1054d8b4..ed2373cf 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -576,6 +576,9 @@ mm_modem_3gpp_set_packet_service_state_sync
mm_modem_3gpp_set_nr5g_registration_settings
mm_modem_3gpp_set_nr5g_registration_settings_finish
mm_modem_3gpp_set_nr5g_registration_settings_sync
+mm_modem_3gpp_set_carrier_lock
+mm_modem_3gpp_set_carrier_lock_finish
+mm_modem_3gpp_set_carrier_lock_sync
<SUBSECTION Standard>
MMModem3gppClass
MMModem3gppPrivate
@@ -2417,6 +2420,9 @@ mm_gdbus_modem3gpp_call_register_sync
mm_gdbus_modem3gpp_call_scan
mm_gdbus_modem3gpp_call_scan_finish
mm_gdbus_modem3gpp_call_scan_sync
+mm_gdbus_modem3gpp_call_set_carrier_lock
+mm_gdbus_modem3gpp_call_set_carrier_lock_finish
+mm_gdbus_modem3gpp_call_set_carrier_lock_sync
mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation
mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation_finish
mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation_sync
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
index ed8c99df..f7719676 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
@@ -230,6 +230,20 @@
</method>
<!--
+ SetCarrierLock:
+ @data: The list of carrier network information to be sent to be configured.
+
+ Command to send the list of carrier network information to the modem.
+
+ Since: 1.22
+ -->
+ <method name="SetCarrierLock">
+ <arg name="data" type="ay" direction="in">
+ <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>
+ </arg>
+ </method>
+
+ <!--
SetPacketServiceState:
@state: a <link linkend="MMModem3gppPacketServiceState">MMModem3gppPacketServiceState</link>.
diff --git a/libmm-glib/mm-modem-3gpp.c b/libmm-glib/mm-modem-3gpp.c
index 0d3944e8..cb228108 100644
--- a/libmm-glib/mm-modem-3gpp.c
+++ b/libmm-glib/mm-modem-3gpp.c
@@ -1510,6 +1510,101 @@ mm_modem_3gpp_set_nr5g_registration_settings_sync (MMModem3gpp *
/*****************************************************************************/
+/**
+ * mm_modem_3gpp_set_carrier_lock_finish:
+ * @self: A #MMModem3gpp.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to mm_gdbus_modem3gpp_call_set_carrier_lock().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with mm_modem_3gpp_set_carrier_lock().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ * Since: 1.22
+ */
+gboolean
+mm_modem_3gpp_set_carrier_lock_finish (MMModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (MM_IS_MODEM_3GPP (self), FALSE);
+
+ return mm_gdbus_modem3gpp_call_set_carrier_lock_finish (MM_GDBUS_MODEM3GPP (self), res, error);
+}
+
+/**
+ * mm_modem_3gpp_set_carrier_lock:
+ * @self: A #MMModem3gpp.
+ * @data: (array length=data_size): Carrier lock information.
+ * @data_size: size of @data.
+ * @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 sends the carrier lock information to 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_location_inject_assistance_data_finish() to get the result of the
+ * operation.
+ *
+ * See mm_modem_3gpp_set_carrier_lock_sync() for the synchronous,
+ * blocking version of this method.
+ *
+ * Since: 1.22
+ */
+void
+mm_modem_3gpp_set_carrier_lock (MMModem3gpp *self,
+ const guint8 *data,
+ gsize data_size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM_3GPP (self));
+
+ mm_gdbus_modem3gpp_call_set_carrier_lock (MM_GDBUS_MODEM3GPP (self),
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, data, data_size, sizeof (guint8)),
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * mm_modem_3gpp_set_carrier_lock_sync:
+ * @self: A #MMModem3gpp.
+ * @data: (array length=data_size): Carrier lock information.
+ * @data_size: size of @data.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously sends the carrier lock information to the modem..
+ *
+ * The calling thread is blocked until a reply is received. See
+ * mm_modem_3gpp_set_carrier_lock() for the asynchronous version of this method.
+ *
+ * Returns: %TRUE if the carrier network info is successfully send, %FALSE if @error is set.
+ *
+ * Since: 1.22
+ */
+gboolean
+mm_modem_3gpp_set_carrier_lock_sync (MMModem3gpp *self,
+ const guint8 *data,
+ gsize data_size,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (MM_IS_MODEM_3GPP (self), FALSE);
+
+ return mm_gdbus_modem3gpp_call_set_carrier_lock_sync (MM_GDBUS_MODEM3GPP (self),
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, data, data_size, sizeof (guint8)),
+ cancellable,
+ error);
+}
+
+/*****************************************************************************/
+
static void
mm_modem_3gpp_init (MMModem3gpp *self)
{
diff --git a/libmm-glib/mm-modem-3gpp.h b/libmm-glib/mm-modem-3gpp.h
index da65ae49..8f137676 100644
--- a/libmm-glib/mm-modem-3gpp.h
+++ b/libmm-glib/mm-modem-3gpp.h
@@ -219,6 +219,21 @@ gboolean mm_modem_3gpp_set_nr5g_registration_settings_sync (MMModem3gpp
GCancellable *cancellable,
GError **error);
+gboolean mm_modem_3gpp_set_carrier_lock_finish (MMModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
+void mm_modem_3gpp_set_carrier_lock (MMModem3gpp *self,
+ const guint8 *data,
+ gsize data_size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_modem_3gpp_set_carrier_lock_sync (MMModem3gpp *self,
+ const guint8 *data,
+ gsize data_size,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
#endif /* _MM_MODEM_3GPP_H_ */
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 6abeb541..48a235a9 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -145,6 +145,7 @@ struct _MMBroadbandModemMbimPrivate {
gboolean is_intel_reset_supported;
gboolean is_slot_info_status_supported;
gboolean is_ms_sar_supported;
+ gboolean is_google_carrier_lock_supported;
/* Process unsolicited notifications */
guint notification_id;
@@ -3386,6 +3387,16 @@ query_device_services_ready (MbimDevice *device,
continue;
}
+ if (service == MBIM_SERVICE_GOOGLE) {
+ for (j = 0; j < device_services[i]->cids_count; j++) {
+ if (device_services[i]->cids[j] == MBIM_CID_GOOGLE_CARRIER_LOCK) {
+ mm_obj_dbg (self, "Google carrier lock is supported");
+ self->priv->is_google_carrier_lock_supported = TRUE;
+ }
+ }
+ continue;
+ }
+
/* no optional features to check in remaining services */
}
mbim_device_service_element_array_free (device_services);
@@ -5121,6 +5132,14 @@ basic_connect_notification_subscriber_ready_status (MMBroadbandModemMbim *self,
active_sim_event = TRUE;
}
+ if ((self->priv->enabled_cache.last_ready_state != MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED &&
+ ready_state == MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED) ||
+ (self->priv->enabled_cache.last_ready_state == MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED &&
+ ready_state != MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED)) {
+ mm_obj_dbg (self, "Lock state change detected");
+ active_sim_event = TRUE;
+ }
+
self->priv->enabled_cache.last_ready_state = ready_state;
if (active_sim_event) {
@@ -9618,6 +9637,71 @@ set_packet_service_state (MMIfaceModem3gpp *self,
task);
}
+/*****************************************************************************/
+/* Set carrier lock */
+
+static gboolean
+modem_set_carrier_lock_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+set_carrier_lock_ready (MbimDevice *device,
+ GAsyncResult *res,
+ GTask *task)
+{
+ g_autoptr(MbimMessage) response = NULL;
+ GError *error = NULL;
+
+ response = mbim_device_command_finish (device, res, &error);
+ if (response &&
+ mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
+ g_task_return_boolean (task, TRUE);
+ } else if (g_error_matches (error, MBIM_STATUS_ERROR, MBIM_STATUS_ERROR_OPERATION_NOT_ALLOWED)) {
+ g_clear_error (&error);
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "operation not allowed");
+ } else
+ g_task_return_error (task, error);
+
+ g_object_unref (task);
+}
+
+static void
+modem_set_carrier_lock (MMIfaceModem3gpp *_self,
+ const guint8 *data,
+ gsize data_size,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
+ MbimDevice *device;
+ g_autoptr(MbimMessage) message = NULL;
+ GTask *task;
+
+ if (!peek_device (self, &device, callback, user_data))
+ return;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (!self->priv->is_google_carrier_lock_supported) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "Google carrier lock is not supported");
+ g_object_unref (task);
+ return;
+ }
+
+ mm_obj_dbg (self, "Sending carrier lock request...");
+ message = mbim_message_google_carrier_lock_set_new (data_size, data, NULL);
+ mbim_device_command (device,
+ message,
+ 10,
+ NULL,
+ (GAsyncReadyCallback)set_carrier_lock_ready,
+ task);
+}
/*****************************************************************************/
@@ -9853,6 +9937,9 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
iface->disable_facility_lock_finish = modem_3gpp_disable_facility_lock_finish;
iface->set_packet_service_state = set_packet_service_state;
iface->set_packet_service_state_finish = set_packet_service_state_finish;
+ /* carrier lock */
+ iface->set_carrier_lock = modem_set_carrier_lock;
+ iface->set_carrier_lock_finish = modem_set_carrier_lock_finish;
}
static void
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 5d501042..9fd376fd 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -3360,6 +3360,98 @@ load_imei_ready (MMIfaceModem3gpp *self,
interface_initialization_step (task);
}
+/*****************************************************************************/
+
+typedef struct {
+ MmGdbusModem3gpp *skeleton;
+ GDBusMethodInvocation *invocation;
+ MMIfaceModem3gpp *self;
+ GVariant *data;
+} HandleSetCarrierLockContext;
+
+static void
+handle_set_carrier_lock_context_free (HandleSetCarrierLockContext *ctx)
+{
+ g_object_unref (ctx->skeleton);
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->self);
+ g_variant_unref (ctx->data);
+ g_free (ctx);
+}
+
+static void
+handle_set_carrier_lock_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ HandleSetCarrierLockContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_carrier_lock_finish (self, res, &error))
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ else
+ mm_gdbus_modem3gpp_complete_set_carrier_lock (ctx->skeleton, ctx->invocation);
+ handle_set_carrier_lock_context_free (ctx);
+}
+
+static void
+handle_set_carrier_lock_auth_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ HandleSetCarrierLockContext *ctx)
+{
+ GError *error = NULL;
+ const guint8 *data;
+ gsize data_size;
+
+ if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_set_carrier_lock_context_free (ctx);
+ return;
+ }
+
+ /* If carrier lock is not implemented, report an error */
+ if (!MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_carrier_lock ||
+ !MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_carrier_lock_finish) {
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot send set carrier lock request to modem: "
+ "operation not supported");
+ handle_set_carrier_lock_context_free (ctx);
+ return;
+ }
+ data = (const guint8 *) g_variant_get_fixed_array (ctx->data, &data_size, sizeof (guint8));
+
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_carrier_lock (ctx->self,
+ data,
+ data_size,
+ (GAsyncReadyCallback)handle_set_carrier_lock_ready,
+ ctx);
+}
+
+static gboolean
+handle_set_carrier_lock (MmGdbusModem3gpp *skeleton,
+ GDBusMethodInvocation *invocation,
+ GVariant *data,
+ MMIfaceModem3gpp *self)
+{
+ HandleSetCarrierLockContext *ctx;
+
+ ctx = g_new0 (HandleSetCarrierLockContext, 1);
+ ctx->skeleton = g_object_ref (skeleton);
+ ctx->invocation = g_object_ref (invocation);
+ ctx->self = g_object_ref (self);
+ ctx->data = g_variant_ref (data);
+
+ mm_base_modem_authorize (MM_BASE_MODEM (self),
+ invocation,
+ MM_AUTHORIZATION_DEVICE_CONTROL,
+ (GAsyncReadyCallback)handle_set_carrier_lock_auth_ready,
+ ctx);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
static void
interface_initialization_step (GTask *task)
{
@@ -3498,6 +3590,10 @@ interface_initialization_step (GTask *task)
"handle-disable-facility-lock",
G_CALLBACK (handle_disable_facility_lock),
self);
+ g_signal_connect (ctx->skeleton,
+ "handle-set-carrier-lock",
+ G_CALLBACK (handle_set_carrier_lock),
+ self);
/* Finally, export the new interface */
mm_gdbus_object_skeleton_set_modem3gpp (MM_GDBUS_OBJECT_SKELETON (self),
diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h
index 424e33eb..e2ae5ee8 100644
--- a/src/mm-iface-modem-3gpp.h
+++ b/src/mm-iface-modem-3gpp.h
@@ -273,6 +273,16 @@ struct _MMIfaceModem3gpp {
gboolean (* set_nr5g_registration_settings_finish) (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error);
+
+ /* Set carrier lock */
+ void (* set_carrier_lock) (MMIfaceModem3gpp *self,
+ const guint8 *data,
+ gsize data_size,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*set_carrier_lock_finish) (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
};
GType mm_iface_modem_3gpp_get_type (void);