diff options
author | Ujjwal Pande <ujjwalpande@google.com> | 2023-05-25 21:42:01 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksandermj@chromium.org> | 2023-06-08 20:16:12 +0000 |
commit | e3a1206c57db685065dfd0eb4efae5083dd5cef5 (patch) | |
tree | bc0cb37666e9d7b798f0bf9f53c5558b340fa53f | |
parent | 97c32d6e51ebabb14085a7166db6d7c81d62e98e (diff) |
api: new carrier lock support
Adding support for carrier lock for MBIM modems using google simlock
mechanism.
-rw-r--r-- | cli/mmcli-modem-3gpp.c | 78 | ||||
-rw-r--r-- | data/org.freedesktop.ModemManager1.conf.polkit | 4 | ||||
-rw-r--r-- | docs/reference/libmm-glib/libmm-glib-sections.txt | 6 | ||||
-rw-r--r-- | introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml | 14 | ||||
-rw-r--r-- | libmm-glib/mm-modem-3gpp.c | 95 | ||||
-rw-r--r-- | libmm-glib/mm-modem-3gpp.h | 15 | ||||
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 87 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 96 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.h | 10 |
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); |