Merge remote-tracking branch 'cros/upstream' into 'cros/master'
Contains the following commits:
fd052c8e base-sim: don't allow sending PIN/PUK if not required (Aleksander Morgado)
9f192be6 iface-modem: allow loading current required lock info (Aleksander Morgado)
634bb1ca base-sim: avoid using 'self' to refer to the modem (Aleksander Morgado)
b6add181 iface-modem-simple: don't abort connection attempt if SIM-PUK2 locked (Aleksander Morgado)
94025aad base-sim: refactor common PIN/PUK unlock operations (Aleksander Morgado)
[...287 other commits...]
c523d5bd bearer-qmi: plug memleaks when connection attempt fails early (Aleksander Morgado)
260d34be bearer-qmi: plug memleaks during network disconnection (Aleksander Morgado)
7297b3fc mbim: release all allocated CIDs during shutdown (Amol Lad)
913f0d63 ci: require autoconf-archive (Aleksander Morgado)
8f4b5b52 sierra: add port hints for EM7565 modem (Amol Lad)
Cq-Depend: chromium:2063833
Change-Id: I62b8d9392c3da4f72da5076ceab272e75168d19f
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..6f7554b
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+akhouderchah@chromium.org
+ejcaruso@chromium.org
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
new file mode 100644
index 0000000..51d8dd6
--- /dev/null
+++ b/PRESUBMIT.cfg
@@ -0,0 +1,9 @@
+# This sample config file disables all of the ChromiumOS source style checks.
+# Comment out the disable-flags for any checks you want to leave enabled.
+
+[Hook Overrides]
+stray_whitespace_check: false
+long_line_check: false
+cros_license_check: false
+tab_check: false
+
diff --git a/README.chromium b/README.chromium
new file mode 100644
index 0000000..10c881e
--- /dev/null
+++ b/README.chromium
@@ -0,0 +1,20 @@
+DESCRIPTION="Broadband modem support daemon (new API)"
+HOMEPAGE="http://projects.gnome.org/NetworkManager/"
+UPSTREAM_REPO="git://anongit.freedesktop.org/ModemManager/ModemManager"
+LOCAL_GIT_REPO="https://chromium.googlesource.com/chromiumos/third_party/modemmanager-next.git"
+UPSTREAM_BUGSDB="https://bugzilla.gnome.org/enter_bug.cgi?product=NetworkManager"
+LOCAL_BUGSDB="http://crosbug.com"
+LICENSE="GPLv2"
+LICENSE_FILE="COPYING"
+
+Description:
+
+ModemManager provides a DBus interface to control broadband modem
+devices. The intended user is a network manager program, such as
+NetworkManager, flimflam, or shill.
+
+This repository mirrors the 0.6-api branch of the upstream repository
+while it is under active development as a branch.
+
+Local changes should be minimal, but support for particular modems may
+make it here before they make it upstream.
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
index b9e9b19..ea05feb 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
@@ -228,5 +228,28 @@
-->
<property name="InitialEpsBearerSettings" type="a{sv}" access="read" />
+ <!--
+ Profiles:
+
+ Profiles or contexts provisioned on the modem.
+
+ A list of dictionaries whose entries are:
+ <variablelist>
+ <varlistentry><term><literal>"profile-id"</literal></term>
+ <listitem><para>Unique identifier for this profile (signature <literal>"u"</literal>).</para></listitem></varlistentry>
+ <varlistentry><term><literal>"apn"</literal></term>
+ <listitem><para>Access Point Name, given as a string value (signature <literal>"s"</literal>).</para></listitem></varlistentry>
+ <varlistentry><term><literal>"auth-type"</literal></term>
+ <listitem><para>The authentication method to use, given as a <link linkend="MMBearerAllowedAuth">MMBearerAllowedAuth</link> value (signature <literal>"u"</literal>). Optional.</para></listitem></varlistentry>
+ <varlistentry><term><literal>"user"</literal></term>
+ <listitem><para>User name (if any) required by the network, given as a string value (signature <literal>"s"</literal>). Optional.</para></listitem></varlistentry>
+ <varlistentry><term><literal>"password"</literal></term>
+ <listitem><para>Password (if any) required by the network, given as a string value (signature <literal>"s"</literal>). Optional.</para></listitem></varlistentry>
+ </variablelist>
+
+ This is a read-only property.
+ -->
+ <property name="Profiles" type="aa{sv}" access="read" />
+
</interface>
</node>
diff --git a/plugins/novatel/mm-broadband-modem-novatel-lte.c b/plugins/novatel/mm-broadband-modem-novatel-lte.c
index 6b5d049..17c557b 100644
--- a/plugins/novatel/mm-broadband-modem-novatel-lte.c
+++ b/plugins/novatel/mm-broadband-modem-novatel-lte.c
@@ -166,6 +166,43 @@
}
/*****************************************************************************/
+/* Load current capabilities (Modem interface) */
+
+static MMModemCapability
+load_current_capabilities_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ MMModemCapability caps;
+ gchar *caps_str;
+
+ /* Constrain the modem capabilities to LTE only.
+ * TODO(benchan): Remove this constraint. */
+ caps = MM_MODEM_CAPABILITY_LTE;
+ caps_str = mm_modem_capability_build_string_from_mask (caps);
+ mm_dbg ("loaded current capabilities: %s", caps_str);
+ g_free (caps_str);
+ return caps;
+}
+
+static void
+load_current_capabilities (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ mm_dbg ("loading (Novatel LTE) current capabilities...");
+
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_current_capabilities);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+}
+
+/*****************************************************************************/
/* Load own numbers (Modem interface) */
static GStrv
@@ -629,6 +666,49 @@
}
/*****************************************************************************/
+/* Initializing the modem (during first enabling) */
+
+static const MMBaseModemAtCommand modem_init_sequence[] = {
+ /* Init command. ITU rec v.250 (6.1.1) says:
+ * The DTE should not include additional commands on the same command line
+ * after the Z command because such commands may be ignored.
+ * So run ATZ alone.
+ */
+ { "Z", 6, FALSE, mm_base_modem_response_processor_no_result_continue },
+
+ /* Temporarily force the modem into LTE only mode to prevent it from falling
+ * back to 3G.
+ * TODO(benchan): Remove this constraint
+ */
+ { "$NWPREFMODE=30", 6, FALSE, mm_base_modem_response_processor_continue_on_error },
+
+ { NULL }
+};
+
+static gboolean
+enabling_modem_init_finish (MMBroadbandModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, error);
+}
+
+static void
+enabling_modem_init (MMBroadbandModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ mm_base_modem_at_sequence_full (MM_BASE_MODEM (self),
+ mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
+ modem_init_sequence,
+ NULL, /* response_processor_context */
+ NULL, /* response_processor_context_free */
+ NULL, /* cancellable */
+ callback,
+ user_data);
+}
+
+/*****************************************************************************/
MMBroadbandModemNovatelLte *
mm_broadband_modem_novatel_lte_new (const gchar *device,
@@ -643,6 +723,11 @@
MM_BASE_MODEM_PLUGIN, plugin,
MM_BASE_MODEM_VENDOR_ID, vendor_id,
MM_BASE_MODEM_PRODUCT_ID, product_id,
+ /* Temporarily allows only EPS network registration status */
+ /* TODO(benchan): Remove this constraint */
+ MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, FALSE,
+ MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, FALSE,
+ MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, TRUE,
NULL);
}
@@ -662,6 +747,8 @@
iface->create_sim_finish = modem_create_sim_finish;
iface->modem_after_sim_unlock = modem_after_sim_unlock;
iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish;
+ iface->load_current_capabilities = load_current_capabilities;
+ iface->load_current_capabilities_finish = load_current_capabilities_finish;
iface->load_own_numbers = load_own_numbers;
iface->load_own_numbers_finish = load_own_numbers_finish;
iface->load_supported_bands = load_supported_bands;
@@ -689,4 +776,8 @@
static void
mm_broadband_modem_novatel_lte_class_init (MMBroadbandModemNovatelLteClass *klass)
{
+ MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass);
+
+ broadband_modem_class->enabling_modem_init = enabling_modem_init;
+ broadband_modem_class->enabling_modem_init_finish = enabling_modem_init_finish;
}
diff --git a/plugins/tests/test-fixture.c b/plugins/tests/test-fixture.c
index 29eb8d5..ac2d3e6 100644
--- a/plugins/tests/test-fixture.c
+++ b/plugins/tests/test-fixture.c
@@ -142,7 +142,7 @@
break;
/* Blocking wait */
- g_assert_cmpuint (wait_time, <=, 20);
+ g_assert_cmpuint (wait_time, <=, 120);
wait_time++;
sleep (1);
}
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index a6b6ec5..ba129dc 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -84,6 +84,7 @@
PROCESS_NOTIFICATION_FLAG_PCO = 1 << 6,
PROCESS_NOTIFICATION_FLAG_USSD = 1 << 7,
PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS = 1 << 8,
+ PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS = 1 << 9,
} ProcessNotificationFlag;
struct _MMBroadbandModemMbimPrivate {
@@ -3134,6 +3135,30 @@
update_access_technologies (self);
}
+static void
+basic_connect_notification_provisioned_contexts (MMBroadbandModemMbim *self,
+ MbimMessage *notification)
+{
+ MbimProvisionedContextElement **provisioned_contexts;
+ guint32 n_provisioned_contexts;
+ GList *profiles;
+
+ if (!mbim_message_provisioned_contexts_notification_parse (
+ notification,
+ &n_provisioned_contexts,
+ &provisioned_contexts,
+ NULL)) {
+ return;
+ }
+
+ profiles = mm_3gpp_profile_list_from_mbim_provisioned_contexts (
+ (const MbimProvisionedContextElement *const *)provisioned_contexts,
+ n_provisioned_contexts);
+ mbim_provisioned_context_element_array_free (provisioned_contexts);
+
+ mm_iface_modem_3gpp_update_profiles (MM_IFACE_MODEM_3GPP (self), profiles);
+}
+
static void add_sms_part (MMBroadbandModemMbim *self,
const MbimSmsPduReadRecord *pdu);
@@ -3189,6 +3214,10 @@
if (self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE)
basic_connect_notification_packet_service (self, notification);
break;
+ case MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS:
+ if (self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS)
+ basic_connect_notification_provisioned_contexts (self, notification);
+ break;
default:
/* Ignore */
break;
@@ -3451,7 +3480,7 @@
if (!device)
return;
- mm_dbg ("Supported notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s)",
+ mm_dbg ("Supported notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s), provisioned contexts (%s)",
self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY ? "yes" : "no",
self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES ? "yes" : "no",
self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_SMS_READ ? "yes" : "no",
@@ -3460,7 +3489,8 @@
self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE ? "yes" : "no",
self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PCO ? "yes" : "no",
self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_USSD ? "yes" : "no",
- self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no");
+ self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no",
+ self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS ? "yes" : "no");
if (setup) {
/* Don't re-enable it if already there */
@@ -3536,6 +3566,7 @@
if (is_sim_hot_swap_configured)
self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE;
+ self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS;
if (self->priv->is_pco_supported)
self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_PCO;
if (self->priv->is_lte_attach_status_supported)
@@ -3554,6 +3585,7 @@
self->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_CONNECT;
self->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
self->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE;
+ self->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS;
if (self->priv->is_pco_supported)
self->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_PCO;
if (self->priv->is_lte_attach_status_supported)
@@ -3632,7 +3664,7 @@
if (!peek_device (self, &device, callback, user_data))
return;
- mm_dbg ("Enabled notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s)",
+ mm_dbg ("Enabled notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s), provisioned contexts (%s)",
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY ? "yes" : "no",
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES ? "yes" : "no",
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SMS_READ ? "yes" : "no",
@@ -3641,7 +3673,8 @@
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE ? "yes" : "no",
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PCO ? "yes" : "no",
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_USSD ? "yes" : "no",
- self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no");
+ self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no",
+ self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS ? "yes" : "no");
entries = g_new0 (MbimEventEntry *, 5);
@@ -3650,11 +3683,12 @@
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES ||
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_CONNECT ||
self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO ||
- self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE) {
+ self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE ||
+ self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS) {
entries[n_entries] = g_new (MbimEventEntry, 1);
memcpy (&(entries[n_entries]->device_service_id), MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid));
entries[n_entries]->cids_count = 0;
- entries[n_entries]->cids = g_new0 (guint32, 5);
+ entries[n_entries]->cids = g_new0 (guint32, 6);
if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY)
entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_SIGNAL_STATE;
if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES)
@@ -3665,6 +3699,8 @@
entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS;
if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE)
entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_PACKET_SERVICE;
+ if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS)
+ entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS;
n_entries++;
}
@@ -3853,6 +3889,7 @@
if (is_sim_hot_swap_configured)
self->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
self->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE;
+ self->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS;
if (self->priv->is_pco_supported)
self->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_PCO;
if (self->priv->is_lte_attach_status_supported)
@@ -3871,6 +3908,7 @@
self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_CONNECT;
self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE;
+ self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS;
if (self->priv->is_pco_supported)
self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_PCO;
if (self->priv->is_lte_attach_status_supported)
@@ -4260,6 +4298,76 @@
}
/*****************************************************************************/
+/* Load profiles (3GPP interface) */
+
+static GList *
+modem_3gpp_load_profiles_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+provisioned_contexts_ready (MbimDevice *device,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MbimMessage *response;
+ MbimProvisionedContextElement **provisioned_contexts;
+ guint32 n_provisioned_contexts;
+ 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) &&
+ mbim_message_provisioned_contexts_response_parse (response,
+ &n_provisioned_contexts,
+ &provisioned_contexts,
+ &error)) {
+ GList *profiles;
+
+ profiles = mm_3gpp_profile_list_from_mbim_provisioned_contexts (
+ (const MbimProvisionedContextElement *const *)provisioned_contexts,
+ n_provisioned_contexts);
+ mbim_provisioned_context_element_array_free (provisioned_contexts);
+
+ g_task_return_pointer (task, profiles, (GDestroyNotify)mm_3gpp_profile_list_free);
+ } else
+ g_task_return_error (task, error);
+
+ g_object_unref (task);
+
+ if (response)
+ mbim_message_unref (response);
+}
+
+static void
+modem_3gpp_load_profiles (MMIfaceModem3gpp *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MbimDevice *device;
+ MbimMessage *message;
+ GTask *task;
+
+ if (!peek_device (self, &device, callback, user_data))
+ return;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ mm_dbg ("loading provisioned contexts...");
+ message = mbim_message_provisioned_contexts_query_new (NULL);
+ mbim_device_command (device,
+ message,
+ 300,
+ NULL,
+ (GAsyncReadyCallback)provisioned_contexts_ready,
+ task);
+ mbim_message_unref (message);
+}
+
+/*****************************************************************************/
/* Check support (Signal interface) */
static gboolean
@@ -5505,6 +5613,8 @@
iface->register_in_network_finish = modem_3gpp_register_in_network_finish;
iface->scan_networks = modem_3gpp_scan_networks;
iface->scan_networks_finish = modem_3gpp_scan_networks_finish;
+ iface->load_profiles = modem_3gpp_load_profiles;
+ iface->load_profiles_finish = modem_3gpp_load_profiles_finish;
}
static void
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 7c6f4eb..b6ffb7d 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -2547,6 +2547,213 @@
}
/*****************************************************************************/
+/* Load profiles (3GPP interface) */
+
+typedef struct {
+ QmiClientWds *client;
+ guint i;
+ GArray *profile_ids;
+ GList *profiles;
+} GetProfileListContext;
+
+static void
+get_profile_list_context_free (GetProfileListContext *ctx)
+{
+ g_object_unref (ctx->client);
+ g_array_unref (ctx->profile_ids);
+ g_list_free_full (ctx->profiles, (GDestroyNotify) qmi_message_wds_get_profile_settings_output_unref);
+ g_slice_free (GetProfileListContext, ctx);
+}
+
+static GList *
+modem_3gpp_load_profiles_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void get_next_profile_settings (GTask *task);
+
+static void
+get_profile_settings_ready (QmiClientWds *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GetProfileListContext *ctx;
+ QmiMessageWdsGetProfileSettingsOutput *output;
+ GError *error = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ output = qmi_client_wds_get_profile_settings_finish (client, res, &error);
+ if (!output) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ if (!qmi_message_wds_get_profile_settings_output_get_result (output, &error)) {
+ QmiWdsDsProfileError ds_profile_error;
+
+ if (g_error_matches (error,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL) &&
+ qmi_message_wds_get_profile_settings_output_get_extended_error_code (
+ output,
+ &ds_profile_error,
+ NULL)) {
+ g_task_return_new_error (task,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL,
+ "DS profile error: %s\n",
+ qmi_wds_ds_profile_error_get_string (ds_profile_error));
+ g_error_free (error);
+ } else {
+ g_task_return_error (task, error);
+ }
+
+ qmi_message_wds_get_profile_settings_output_unref (output);
+ g_object_unref (task);
+ return;
+ }
+
+ ctx->profiles = g_list_prepend (ctx->profiles, output);
+ ctx->i++;
+ get_next_profile_settings (task);
+}
+
+static void
+get_next_profile_settings (GTask *task)
+{
+ QmiMessageWdsGetProfileListOutputProfileListProfile *profile;
+ QmiMessageWdsGetProfileSettingsInput *input;
+ GetProfileListContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+
+ if (ctx->i == ctx->profile_ids->len) {
+ g_task_return_pointer (task,
+ mm_3gpp_profile_list_from_qmi_profile_settings (ctx->profiles),
+ (GDestroyNotify) mm_3gpp_profile_list_free);
+ g_object_unref (task);
+ return;
+ }
+
+ profile = &g_array_index (ctx->profile_ids, QmiMessageWdsGetProfileListOutputProfileListProfile, ctx->i);
+
+ input = qmi_message_wds_get_profile_settings_input_new ();
+ qmi_message_wds_get_profile_settings_input_set_profile_id (
+ input,
+ profile->profile_type,
+ profile->profile_index,
+ NULL);
+ qmi_client_wds_get_profile_settings (ctx->client,
+ input,
+ 3,
+ NULL,
+ (GAsyncReadyCallback)get_profile_settings_ready,
+ task);
+ qmi_message_wds_get_profile_settings_input_unref (input);
+}
+
+static void
+get_profile_list_ready (QmiClientWds *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+ QmiMessageWdsGetProfileListOutput *output;
+ GetProfileListContext *ctx;
+ GArray *profile_ids = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ output = qmi_client_wds_get_profile_list_finish (client, res, &error);
+ if (!output) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ if (!qmi_message_wds_get_profile_list_output_get_result (output, &error)) {
+ QmiWdsDsProfileError ds_profile_error;
+
+ if (g_error_matches (error,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL) &&
+ qmi_message_wds_get_profile_list_output_get_extended_error_code (
+ output,
+ &ds_profile_error,
+ NULL)) {
+ g_task_return_new_error (task,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL,
+ "DS profile error: %s\n",
+ qmi_wds_ds_profile_error_get_string (ds_profile_error));
+ g_error_free (error);
+ } else {
+ g_task_return_error (task, error);
+ }
+
+ qmi_message_wds_get_profile_list_output_unref (output);
+ g_object_unref (task);
+ return;
+ }
+
+ qmi_message_wds_get_profile_list_output_get_profile_list (output, &profile_ids, NULL);
+
+ if (!profile_ids || !profile_ids->len) {
+ /* No profiles to get details for. */
+ g_task_return_pointer (task, NULL, NULL);
+ g_object_unref (task);
+ return;
+ }
+
+ ctx->profile_ids = profile_ids;
+
+ get_next_profile_settings (task);
+}
+
+static void
+modem_3gpp_load_profiles (MMIfaceModem3gpp *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+ GTask *task;
+ QmiClient *client;
+ GetProfileListContext *ctx;
+ QmiMessageWdsGetProfileListInput *input;
+ GError *error = NULL;
+
+ task = g_task_new (self, NULL, callback, user_data);
+ client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
+ QMI_SERVICE_WDS,
+ MM_PORT_QMI_FLAG_DEFAULT,
+ &error);
+ if (!client) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ }
+
+ ctx = g_slice_new0 (GetProfileListContext);
+ ctx->client = g_object_ref (QMI_CLIENT_WDS (client));
+ g_task_set_task_data (task, ctx, (GDestroyNotify) get_profile_list_context_free);
+
+ input = qmi_message_wds_get_profile_list_input_new ();
+ qmi_message_wds_get_profile_list_input_set_profile_type (input, QMI_WDS_PROFILE_TYPE_3GPP, NULL);
+
+ qmi_client_wds_get_profile_list (ctx->client,
+ input,
+ 10,
+ NULL,
+ (GAsyncReadyCallback) get_profile_list_ready,
+ NULL);
+ qmi_message_wds_get_profile_list_input_unref (input);
+}
+
+/*****************************************************************************/
/* Registration checks (3GPP interface) */
static gboolean
@@ -8848,6 +9055,8 @@
iface->load_operator_code_finish = modem_3gpp_load_operator_code_finish;
iface->load_operator_name = modem_3gpp_load_operator_name;
iface->load_operator_name_finish = modem_3gpp_load_operator_name_finish;
+ iface->load_profiles = modem_3gpp_load_profiles;
+ iface->load_profiles_finish = modem_3gpp_load_profiles_finish;
}
static void
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 3e04f95..0d07b89 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -1728,6 +1728,62 @@
/*****************************************************************************/
+static GVariant *
+profiles_build_result (const GList *profiles)
+{
+ const GList *l;
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ for (l = profiles; l; l = g_list_next (l)) {
+ const MM3gppProfile *profile = l->data;
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ g_variant_builder_add (&builder, "{sv}",
+ "profile-id", g_variant_new_uint32 (profile->profile_id));
+ if (profile->apn) {
+ g_variant_builder_add (&builder, "{sv}",
+ "apn", g_variant_new_string (profile->apn));
+ } else {
+ g_variant_builder_add (&builder, "{sv}", "apn", g_variant_new_string (""));
+ }
+ g_variant_builder_add (&builder, "{sv}",
+ "auth-type", g_variant_new_uint32 (profile->auth_type));
+ if (profile->username)
+ g_variant_builder_add (&builder, "{sv}",
+ "username", g_variant_new_string (profile->username));
+ if (profile->password)
+ g_variant_builder_add (&builder, "{sv}",
+ "password", g_variant_new_string (profile->password));
+ g_variant_builder_close (&builder);
+ }
+
+ return g_variant_ref_sink (g_variant_builder_end (&builder));
+}
+
+void
+mm_iface_modem_3gpp_update_profiles (MMIfaceModem3gpp *self,
+ const GList *profiles)
+{
+ MmGdbusModem3gpp *skeleton = NULL;
+ GVariant *variant;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton,
+ NULL);
+ if (!skeleton)
+ return;
+
+ variant = profiles_build_result (profiles);
+ mm_gdbus_modem3gpp_set_profiles (skeleton, variant);
+ g_variant_unref (variant);
+ g_object_unref (skeleton);
+}
+
+/*****************************************************************************/
+
typedef struct _DisablingContext DisablingContext;
static void interface_disabling_step (GTask *task);
@@ -1942,6 +1998,7 @@
ENABLING_STEP_SETUP_UNSOLICITED_REGISTRATION_EVENTS,
ENABLING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS,
ENABLING_STEP_INITIAL_EPS_BEARER,
+ ENABLING_STEP_LOAD_PROFILES,
ENABLING_STEP_LAST
} EnablingStep;
@@ -2096,6 +2153,33 @@
}
static void
+load_profiles_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GList *profiles;
+ EnablingContext *ctx;
+ GError *error = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ profiles = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_profiles_finish (self, res, &error);
+ if (error) {
+ mm_dbg ("couldn't load initial profiles: '%s'", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ mm_iface_modem_3gpp_update_profiles (self, profiles);
+ mm_3gpp_profile_list_free (profiles);
+
+out:
+ /* Go on to next step */
+ ctx->step++;
+ interface_enabling_step (task);
+}
+
+static void
interface_enabling_step (GTask *task)
{
MMIfaceModem3gpp *self;
@@ -2195,6 +2279,18 @@
ctx->step++;
} /* fall through */
+ case ENABLING_STEP_LOAD_PROFILES:
+ if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_profiles &&
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_profiles_finish) {
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_profiles (
+ self,
+ (GAsyncReadyCallback)load_profiles_ready,
+ task);
+ return;
+ }
+ /* Fall down to next step */
+ ctx->step++;
+
case ENABLING_STEP_LAST:
/* We are done without errors! */
g_task_return_boolean (task, TRUE);
@@ -2539,6 +2635,7 @@
mm_gdbus_modem3gpp_set_subscription_state (skeleton, MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN);
mm_gdbus_modem3gpp_set_pco (skeleton, NULL);
mm_gdbus_modem3gpp_set_initial_eps_bearer (skeleton, NULL);
+ mm_gdbus_modem3gpp_set_profiles (skeleton, NULL);
/* Bind our RegistrationState property */
g_object_bind_property (self, MM_IFACE_MODEM_3GPP_REGISTRATION_STATE,
diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h
index 91976fd..9cb1f4d 100644
--- a/src/mm-iface-modem-3gpp.h
+++ b/src/mm-iface-modem-3gpp.h
@@ -231,6 +231,14 @@
gboolean (* set_initial_eps_bearer_settings_finish) (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error);
+
+ /* Get profiles or provisioned contexts from the modem as a list of MM3gppProfile */
+ void (* load_profiles) (MMIfaceModem3gpp *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ GList * (* load_profiles_finish) (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
};
GType mm_iface_modem_3gpp_get_type (void);
@@ -286,6 +294,8 @@
const GList *pco_list);
void mm_iface_modem_3gpp_update_initial_eps_bearer (MMIfaceModem3gpp *self,
MMBearerProperties *properties);
+void mm_iface_modem_3gpp_update_profiles (MMIfaceModem3gpp *self,
+ const GList *profiles);
/* Run all registration checks */
void mm_iface_modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self,
diff --git a/src/mm-modem-helpers-mbim.c b/src/mm-modem-helpers-mbim.c
index eb68467..e1adcca 100644
--- a/src/mm-modem-helpers-mbim.c
+++ b/src/mm-modem-helpers-mbim.c
@@ -198,6 +198,33 @@
/*****************************************************************************/
+GList *
+mm_3gpp_profile_list_from_mbim_provisioned_contexts (
+ const MbimProvisionedContextElement *const *contexts,
+ guint n_contexts)
+{
+ GList *profiles = NULL;
+ guint i;
+
+ for (i = 0; i < n_contexts; i++) {
+ MM3gppProfile *profile;
+
+ profile = g_slice_new0 (MM3gppProfile);
+ profile->profile_id = contexts[i]->context_id;
+ profile->apn = g_strdup (contexts[i]->access_string);
+ profile->username = g_strdup (contexts[i]->user_name);
+ profile->password = g_strdup (contexts[i]->password);
+ profile->auth_type =
+ mm_bearer_allowed_auth_from_mbim_auth_protocol (contexts[i]->auth_protocol);
+
+ profiles = g_list_prepend (profiles, profile);
+ }
+
+ return profiles;
+}
+
+/*****************************************************************************/
+
GError *
mm_mobile_equipment_error_from_mbim_nw_error (MbimNwError nw_error)
{
diff --git a/src/mm-modem-helpers-mbim.h b/src/mm-modem-helpers-mbim.h
index a648cac..090b764 100644
--- a/src/mm-modem-helpers-mbim.h
+++ b/src/mm-modem-helpers-mbim.h
@@ -37,6 +37,9 @@
GList *mm_3gpp_network_info_list_from_mbim_providers (const MbimProvider *const *providers, guint n_providers);
+GList *mm_3gpp_profile_list_from_mbim_provisioned_contexts (const MbimProvisionedContextElement *const *contexts,
+ guint n_contexts);
+
GError *mm_mobile_equipment_error_from_mbim_nw_error (MbimNwError nw_error);
MMBearerAllowedAuth mm_bearer_allowed_auth_from_mbim_auth_protocol (MbimAuthProtocol auth_protocol);
diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c
index baf6f3d..e4a3c58 100644
--- a/src/mm-modem-helpers-qmi.c
+++ b/src/mm-modem-helpers-qmi.c
@@ -1438,6 +1438,54 @@
return out;
}
+MMBearerAllowedAuth
+mm_bearer_allowed_auth_from_qmi_authentication (QmiWdsAuthentication auth)
+{
+ MMBearerAllowedAuth out;
+
+ out = MM_BEARER_ALLOWED_AUTH_NONE;
+ if (auth & QMI_WDS_AUTHENTICATION_PAP)
+ out |= MM_BEARER_ALLOWED_AUTH_PAP;
+ if (auth & QMI_WDS_AUTHENTICATION_CHAP)
+ out |= MM_BEARER_ALLOWED_AUTH_CHAP;
+
+ return out;
+}
+
+/*****************************************************************************/
+
+GList *
+mm_3gpp_profile_list_from_qmi_profile_settings (GList *profiles)
+{
+ GList *mm_profiles = NULL;
+ GList *iter;
+
+ for (iter = profiles; iter; iter = g_list_next (iter)) {
+ QmiMessageWdsGetProfileSettingsOutput *wds_profile;
+ MM3gppProfile *mm_profile;
+ const gchar *str;
+ guint8 context_number;
+ QmiWdsAuthentication auth;
+
+ wds_profile = iter->data;
+ mm_profile = g_slice_new0 (MM3gppProfile);
+ if (qmi_message_wds_get_profile_settings_output_get_apn_name (wds_profile, &str, NULL))
+ mm_profile->apn = g_strdup(str);
+ if (qmi_message_wds_get_profile_settings_output_get_pdp_context_number (wds_profile, &context_number, NULL))
+ mm_profile->profile_id = context_number;
+ if (qmi_message_wds_get_profile_settings_output_get_username (wds_profile, &str, NULL))
+ mm_profile->username = g_strdup(str);
+ if (qmi_message_wds_get_profile_settings_output_get_password (wds_profile, &str, NULL))
+ mm_profile->password = g_strdup(str);
+ if (qmi_message_wds_get_profile_settings_output_get_authentication (wds_profile, &auth, NULL))
+ mm_profile->auth_type = mm_bearer_allowed_auth_from_qmi_authentication (auth);
+
+ mm_profiles = g_list_prepend (mm_profiles, mm_profile);
+ }
+
+ return mm_profiles;
+}
+
/*****************************************************************************/
/**
diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h
index 5c0200e..29b61af 100644
--- a/src/mm-modem-helpers-qmi.h
+++ b/src/mm-modem-helpers-qmi.h
@@ -107,6 +107,10 @@
/* QMI/WDS to MM translations */
QmiWdsAuthentication mm_bearer_allowed_auth_to_qmi_authentication (MMBearerAllowedAuth auth);
+MMBearerAllowedAuth mm_bearer_allowed_auth_from_qmi_authentication (QmiWdsAuthentication auth);
+
+/* Input is a GList of QmiMessageWdsGetProfileSettingsOutput. */
+GList *mm_3gpp_profile_list_from_qmi_profile_settings (GList *profile_list);
/*****************************************************************************/
/* QMI/OMA to MM translations */
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 15fba35..7761d01 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -1846,6 +1846,21 @@
return list;
}
+static void
+mm_3gpp_profile_free (MM3gppProfile *profile)
+{
+ g_free (profile->apn);
+ g_free (profile->username);
+ g_free (profile->password);
+ g_slice_free (MM3gppProfile, profile);
+}
+
+void
+mm_3gpp_profile_list_free (GList *list)
+{
+ g_list_free_full (list, (GDestroyNotify) mm_3gpp_profile_free);
+}
+
/*************************************************************************/
static void
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 9c1be81..2ad24fa 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -201,6 +201,15 @@
gboolean *cid_reused,
gboolean *cid_overwritten);
+typedef struct {
+ guint profile_id;
+ gchar *apn;
+ gchar *username;
+ gchar *password;
+ MMBearerAllowedAuth auth_type;
+} MM3gppProfile;
+void mm_3gpp_profile_list_free (GList *profiles);
+
/* AT+CGACT? (active PDP context query) response parser */
typedef struct {
guint cid;