Merge commit 'cros/upstream~1' into 'cros/master'.
This cl fixes issues seen with autoconnect after suspend.
Contains the following commit:
b0c21263 broadband-modem: Disconnect bearers during disable (Pavan Holla)
BUG=b:170144157
TEST=powerd_dbus_suspend; press any key; check that cellular reconnects
Change-Id: I82a89c1892e71acadf1d75c74fd3058c410787b6
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..af1732f
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+ejcaruso@chromium.org
+pholla@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 e741ae9..8abea6a 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
@@ -247,5 +247,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/generic/mm-plugin-generic.c b/plugins/generic/mm-plugin-generic.c
index c2e3a07..428819b 100644
--- a/plugins/generic/mm-plugin-generic.c
+++ b/plugins/generic/mm-plugin-generic.c
@@ -58,6 +58,13 @@
GError **error)
{
#if defined WITH_QMI
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove the ifdefs and upstream
+ return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid,
+ drivers,
+ mm_plugin_get_name (self),
+ vendor,
+ product));
+#endif
if (mm_port_probe_list_has_qmi_port (probes)) {
mm_obj_dbg (self, "QMI-powered generic modem found...");
return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid,
diff --git a/plugins/novatel/mm-broadband-modem-novatel-lte.c b/plugins/novatel/mm-broadband-modem-novatel-lte.c
index df33138..3748ac9 100644
--- a/plugins/novatel/mm-broadband-modem-novatel-lte.c
+++ b/plugins/novatel/mm-broadband-modem-novatel-lte.c
@@ -635,6 +635,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,
@@ -649,6 +692,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);
}
@@ -695,4 +743,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-base-manager.c b/src/mm-base-manager.c
index 653adb5..a8de7dc 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -1319,6 +1319,73 @@
/*****************************************************************************/
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+static void
+create_virtual_device (const gchar *id,
+ const gchar *plugin_name,
+ const gchar *const *ports,
+ MMBaseManager *self)
+{
+ MMPlugin *plugin;
+ MMDevice *device;
+ gchar *physdev_uid;
+ GError *error = NULL;
+
+ mm_obj_info (self, "Creating virtual device '%s'", id);
+
+ /* Create device and keep it listed in the Manager */
+ physdev_uid = g_strdup_printf ("/virtual/%s", id);
+ device = mm_device_new (physdev_uid, TRUE, TRUE, self->priv->object_manager);
+ g_hash_table_insert (self->priv->devices, physdev_uid, device);
+
+ /* Grab virtual ports */
+ mm_device_virtual_grab_ports (device, (const gchar **)ports);
+
+ /* Set plugin to use */
+ plugin = mm_plugin_manager_peek_plugin (self->priv->plugin_manager, plugin_name);
+ if (!plugin) {
+ error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_NOT_FOUND,
+ "Requested plugin '%s' not found",
+ plugin_name);
+ mm_obj_warn (self, "Couldn't set plugin for virtual device '%s': %s",
+ mm_device_get_uid (device),
+ error->message);
+ goto out;
+ }
+ mm_device_set_plugin (device, G_OBJECT (plugin));
+
+ /* Create modem */
+ if (!mm_device_create_modem (device, &error)) {
+ mm_obj_warn (self, "Couldn't create modem for virtual device '%s': %s",
+ mm_device_get_uid (device),
+ error->message);
+ goto out;
+ }
+
+ mm_obj_info (self, "Modem for virtual device '%s' successfully created",
+ mm_device_get_uid (device));
+
+out:
+
+ if (error) {
+ mm_device_remove_modem (device);
+ g_hash_table_remove (self->priv->devices, mm_device_get_uid (device));
+ g_error_free (error);
+ }
+}
+
+static gboolean
+create_fake_modem (MMBaseManager *self)
+{
+ const gchar *ports[] = { "qmi0", "rmnet_data0", NULL };
+
+ create_virtual_device ("fake", "generic", ports, self);
+
+ return FALSE;
+}
+#endif
+
MMBaseManager *
mm_base_manager_new (GDBusConnection *connection,
const gchar *plugin_dir,
@@ -1520,6 +1587,9 @@
error))
return FALSE;
}
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ g_timeout_add_seconds (3, (GSourceFunc)create_fake_modem, MM_BASE_MANAGER (initable));
+#endif
/* All good */
return TRUE;
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index a11f15a..941d655 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -292,6 +292,22 @@
MM_PORT_TYPE, MM_PORT_TYPE_NET,
NULL));
}
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ else if (g_str_has_prefix (subsys, "virtual") &&
+ g_str_has_prefix (name, "rmnet_data0")) {
+ mm_obj_info (self, "@@ %s: virtual net port = %s", __FUNCTION__, name);
+ port = MM_PORT (g_object_new (MM_TYPE_PORT,
+ MM_PORT_DEVICE, name,
+ MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET,
+ MM_PORT_TYPE, MM_PORT_TYPE_NET,
+ NULL));
+ }
+ else if (g_str_has_prefix (subsys, "virtual") &&
+ g_str_has_prefix (name, "qmi")) {
+ mm_obj_info (self, "@@ %s: virtual qmi port = %s", __FUNCTION__, name);
+ port = MM_PORT (mm_port_qmi_new (name));
+ }
+#endif
/* cdc-wdm ports... */
else if (g_str_has_prefix (subsys, "usb") &&
g_str_has_prefix (name, "cdc-wdm")) {
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index 45185c6..0157d38 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -411,12 +411,18 @@
CONNECT_STEP_WDS_CLIENT_IPV4,
CONNECT_STEP_IP_FAMILY_IPV4,
CONNECT_STEP_ENABLE_INDICATIONS_IPV4,
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ CONNECT_STEP_BIND_MUX_DATA_PORT_IPV4,
+#endif
CONNECT_STEP_START_NETWORK_IPV4,
CONNECT_STEP_GET_CURRENT_SETTINGS_IPV4,
CONNECT_STEP_IPV6,
CONNECT_STEP_WDS_CLIENT_IPV6,
CONNECT_STEP_IP_FAMILY_IPV6,
CONNECT_STEP_ENABLE_INDICATIONS_IPV6,
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ CONNECT_STEP_BIND_MUX_DATA_PORT_IPV6,
+#endif
CONNECT_STEP_START_NETWORK_IPV6,
CONNECT_STEP_GET_CURRENT_SETTINGS_IPV6,
CONNECT_STEP_LAST
@@ -551,6 +557,53 @@
static void connect_context_step (GTask *task);
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+static void bind_mux_data_port_ready (QmiClientWds *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBearerQmi *self;
+ ConnectContext *ctx;
+ GError *error = NULL;
+ QmiMessageWdsBindMuxDataPortOutput *output;
+
+ self = g_task_get_task_data (task);
+ ctx = g_task_get_task_data (task);
+ g_assert (ctx->running_ipv4 || ctx->running_ipv6);
+ g_assert (!(ctx->running_ipv4 && ctx->running_ipv6));
+
+ output = qmi_client_wds_bind_mux_data_port_finish (client, res, &error);
+ if (!output ||
+ !qmi_message_wds_bind_mux_data_port_output_get_result (output, &error)) {
+ mm_obj_info (self, "error: couldn't bind mux data port: %s\n", error->message);
+
+ if (ctx->running_ipv4)
+ ctx->error_ipv4 = error;
+ else
+ ctx->error_ipv6 = error;
+
+ ctx->step = CONNECT_STEP_LAST;
+ } else
+ ctx->step++;
+
+ if (output)
+ qmi_message_wds_bind_mux_data_port_output_unref (output);
+
+ connect_context_step (task);
+}
+
+static QmiMessageWdsBindMuxDataPortInput *
+build_bind_mux_data_port_input (void)
+{
+ QmiMessageWdsBindMuxDataPortInput *input;
+
+ input = qmi_message_wds_bind_mux_data_port_input_new ();
+ qmi_message_wds_bind_mux_data_port_input_set_endpoint_info (input, 0x4, 0x1, NULL);
+ qmi_message_wds_bind_mux_data_port_input_set_mux_id (input, 0x1, NULL);
+ return input;
+}
+#endif
+
static void
start_network_ready (QmiClientWds *client,
GAsyncResult *res,
@@ -1344,10 +1397,14 @@
* to request. If the LLP is raw-ip, we force Static IP, because not
* all DHCP clients support the raw-ip interfaces; otherwise default
* to DHCP as always. */
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ ctx->ip_method = MM_BEARER_IP_METHOD_STATIC;
+#else
if (mm_port_qmi_llp_is_raw_ip (ctx->qmi))
ctx->ip_method = MM_BEARER_IP_METHOD_STATIC;
else
ctx->ip_method = MM_BEARER_IP_METHOD_DHCP;
+#endif
mm_obj_dbg (self, "defaulting to use %s IP method", mm_bearer_ip_method_get_string (ctx->ip_method));
ctx->step++;
@@ -1424,6 +1481,24 @@
task);
return;
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ case CONNECT_STEP_BIND_MUX_DATA_PORT_IPV4: {
+ QmiMessageWdsBindMuxDataPortInput *input;
+
+ mm_obj_dbg (ctx->self, "Binding mux data port for IPv4...");
+
+ input = build_bind_mux_data_port_input ();
+ qmi_client_wds_bind_mux_data_port (ctx->client_ipv4,
+ input,
+ 10,
+ g_task_get_cancellable (task),
+ (GAsyncReadyCallback) bind_mux_data_port_ready,
+ task);
+ qmi_message_wds_bind_mux_data_port_input_unref (input);
+ return;
+ }
+#endif
+
case CONNECT_STEP_START_NETWORK_IPV4: {
QmiMessageWdsStartNetworkInput *input;
@@ -1515,6 +1590,24 @@
task);
return;
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ case CONNECT_STEP_BIND_MUX_DATA_PORT_IPV6: {
+ QmiMessageWdsBindMuxDataPortInput *input;
+
+ mm_obj_dbg (self, "Binding mux data port for IPv6...");
+
+ input = build_bind_mux_data_port_input ();
+ qmi_client_wds_bind_mux_data_port (ctx->client_ipv6,
+ input,
+ 10,
+ g_task_get_cancellable (task),
+ (GAsyncReadyCallback) bind_mux_data_port_ready,
+ task);
+ qmi_message_wds_bind_mux_data_port_input_unref (input);
+ return;
+ }
+#endif
+
case CONNECT_STEP_START_NETWORK_IPV6: {
QmiMessageWdsStartNetworkInput *input;
@@ -1653,7 +1746,13 @@
}
/* Each data port has a single QMI port associated */
+
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ qmi = mm_base_modem_get_port_qmi (modem);
+#else
qmi = mm_base_modem_get_port_qmi_for_data (modem, data, &error);
+#endif
+
if (!qmi) {
g_task_report_error (
self,
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index e0a3457..6c681d0 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 {
@@ -3163,6 +3164,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);
@@ -3218,6 +3243,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;
@@ -3480,7 +3509,7 @@
if (!device)
return;
- mm_obj_dbg (self, "supported notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s)",
+ mm_obj_dbg (self, "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",
@@ -3489,7 +3518,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 */
@@ -3558,6 +3588,7 @@
self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY;
self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_CONNECT;
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)
@@ -3576,6 +3607,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)
@@ -3654,7 +3686,7 @@
if (!peek_device (self, &device, callback, user_data))
return;
- mm_obj_dbg (self, "enabled notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s)",
+ mm_obj_dbg (self, "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",
@@ -3663,7 +3695,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);
@@ -3672,11 +3705,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)
@@ -3687,6 +3721,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++;
}
@@ -3932,6 +3968,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)
@@ -3950,6 +3987,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)
@@ -4340,6 +4378,86 @@
}
/*****************************************************************************/
+/* Load profiles (3GPP interface) */
+
+static gboolean
+modem_3gpp_load_profiles_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GList **out_list,
+ GError **error)
+{
+ GTask *task;
+
+ task = G_TASK (res);
+ if (!g_task_propagate_boolean (task, error))
+ return FALSE;
+
+ if (out_list)
+ *out_list = mm_3gpp_profile_list_copy (g_task_get_task_data (task));
+ return TRUE;
+}
+
+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_set_task_data (task, profiles, (GDestroyNotify)mm_3gpp_profile_list_free);
+ g_task_return_boolean (task, TRUE);
+ } 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_obj_dbg (self, "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
@@ -5589,6 +5707,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 9a1a1e6..e2d0f46 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -2446,6 +2446,223 @@
}
/*****************************************************************************/
+/* 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 gboolean
+modem_3gpp_load_profiles_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GList **out_list,
+ GError **error)
+{
+ GTask *task;
+
+ task = G_TASK (res);
+ if (!g_task_propagate_boolean (task, error))
+ return FALSE;
+
+ if (out_list)
+ *out_list = mm_3gpp_profile_list_copy (g_task_get_task_data (task));
+ return TRUE;
+}
+
+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_set_task_data (task,
+ mm_3gpp_profile_list_from_qmi_profile_settings (ctx->profiles),
+ (GDestroyNotify) mm_3gpp_profile_list_free);
+ g_task_return_boolean (task, TRUE);
+ 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
@@ -9440,6 +9657,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 662052f..f9963e4 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -1759,6 +1759,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);
@@ -1973,6 +2029,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;
@@ -2127,6 +2184,34 @@
}
static void
+load_profiles_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ gboolean success;
+ GList *profiles = NULL;
+ EnablingContext *ctx;
+ GError *error = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ success = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_profiles_finish (self, res, &profiles, &error);
+ if (!success) {
+ mm_obj_dbg (self, "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;
@@ -2226,6 +2311,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);
@@ -2570,6 +2667,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 2bff383..0a2659c 100644
--- a/src/mm-iface-modem-3gpp.h
+++ b/src/mm-iface-modem-3gpp.h
@@ -234,6 +234,15 @@
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);
+ gboolean (* load_profiles_finish) (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GList **out_list,
+ GError **error);
};
GType mm_iface_modem_3gpp_get_type (void);
@@ -292,6 +301,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 0d5ff5f..5784d3a 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 f9d509f..c70b9a4 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 e9291a7..975d429 100644
--- a/src/mm-modem-helpers-qmi.c
+++ b/src/mm-modem-helpers-qmi.c
@@ -1472,6 +1472,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 baa993e..804aa47 100644
--- a/src/mm-modem-helpers-qmi.h
+++ b/src/mm-modem-helpers-qmi.h
@@ -114,6 +114,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 d080e01..8b9e3fa 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -1768,6 +1768,41 @@
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 MM3gppProfile *
+mm_3gpp_profile_copy (MM3gppProfile *profile)
+{
+ MM3gppProfile *copy;
+
+ copy = g_slice_new0 (MM3gppProfile);
+ copy->profile_id = profile->profile_id;
+ copy->apn = g_strdup (profile->apn);
+ copy->username = g_strdup (profile->username);
+ copy->password = g_strdup (profile->password);
+ copy->auth_type = profile->auth_type;
+ return copy;
+}
+
+GList *
+mm_3gpp_profile_list_copy (GList *list)
+{
+ return g_list_copy_deep (list, (GCopyFunc)mm_3gpp_profile_copy, NULL);
+}
+
/*************************************************************************/
static void
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index c1a1b2c..819c90a 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -202,6 +202,16 @@
gboolean *out_cid_reused,
gboolean *out_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);
+GList *mm_3gpp_profile_list_copy (GList *profiles);
+
/* AT+CGACT? (active PDP context query) response parser */
typedef struct {
guint cid;
diff --git a/src/mm-plugin.c b/src/mm-plugin.c
index 77bd652..bb57a50 100644
--- a/src/mm-plugin.c
+++ b/src/mm-plugin.c
@@ -50,7 +50,7 @@
G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init))
/* Virtual port corresponding to the embedded modem */
-static const gchar *virtual_port[] = {"smd0", NULL};
+static const gchar *virtual_port[] = {"smd0", "rmnet_data0", "qmi0", NULL};
#define HAS_POST_PROBING_FILTERS(self) \
(self->priv->vendor_strings || \
@@ -1061,7 +1061,11 @@
g_clear_error (&inner_error);
} else if (!mm_base_modem_grab_port (modem,
kernel_device,
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ MM_PORT_TYPE_QMI,
+#else
MM_PORT_TYPE_AT,
+#endif
MM_PORT_SERIAL_AT_FLAG_NONE,
&inner_error)) {
mm_obj_warn (self, "could not grab virtual port %s: %s",
diff --git a/src/mm-port-qmi.c b/src/mm-port-qmi.c
index 571bb93..c0a3fc7 100644
--- a/src/mm-port-qmi.c
+++ b/src/mm-port-qmi.c
@@ -228,6 +228,10 @@
PORT_OPEN_STEP_FIRST,
PORT_OPEN_STEP_CHECK_OPENING,
PORT_OPEN_STEP_CHECK_ALREADY_OPEN,
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ PORT_OPEN_STEP_OPEN_QRTR_NODE,
+ PORT_OPEN_STEP_WAIT_FOR_SERVICES,
+#endif
PORT_OPEN_STEP_DEVICE_NEW,
PORT_OPEN_STEP_OPEN_WITHOUT_DATA_FORMAT,
PORT_OPEN_STEP_GET_KERNEL_DATA_FORMAT,
@@ -241,6 +245,9 @@
} PortOpenStep;
typedef struct {
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ QrtrNode *node;
+#endif
QmiDevice *device;
QmiClient *wda;
GError *error;
@@ -261,6 +268,9 @@
3, NULL, NULL, NULL);
g_clear_object (&ctx->wda);
g_clear_object (&ctx->device);
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ g_clear_object (&ctx->node);
+#endif
g_slice_free (PortOpenContext, ctx);
}
@@ -443,6 +453,45 @@
port_open_step (task);
}
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+static void
+qrtr_node_services_ready (QrtrNode *node,
+ GAsyncResult *res,
+ GTask *task)
+{
+ PortOpenContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+ if (!qrtr_node_wait_for_services_finish (node, res, &ctx->error)) {
+ /* Error creating the device */
+ ctx->step = PORT_OPEN_STEP_LAST;
+ } else {
+ /* Go on to next step */
+ ctx->step++;
+ }
+ port_open_step (task);
+}
+
+static void
+qrtr_node_ready (GObject *unused,
+ GAsyncResult *res,
+ GTask *task)
+{
+ PortOpenContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+
+ ctx->node = qrtr_node_for_id_finish (res, &ctx->error);
+ if (!ctx->node)
+ /* Error creating the node */
+ ctx->step = PORT_OPEN_STEP_LAST;
+ else
+ /* Go on to next step */
+ ctx->step++;
+ port_open_step (task);
+}
+#endif
+
static void
port_open_step (GTask *task)
{
@@ -480,7 +529,57 @@
ctx->step++;
/* Fall through */
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ case PORT_OPEN_STEP_OPEN_QRTR_NODE:
+ self->priv->in_progress = TRUE;
+
+ mm_obj_info (self, "Fetching QRTR node 0...");
+ qrtr_node_for_id (0,
+ 20,
+ g_task_get_cancellable (task),
+ (GAsyncReadyCallback) qrtr_node_ready,
+ task);
+ return;
+
+ case PORT_OPEN_STEP_WAIT_FOR_SERVICES: {
+ GArray *services;
+ QmiService required_services[] = {
+ QMI_SERVICE_DMS,
+ QMI_SERVICE_WDA,
+ QMI_SERVICE_WDS,
+ QMI_SERVICE_NAS,
+ QMI_SERVICE_UIM,
+ QMI_SERVICE_PDC,
+ QMI_SERVICE_WMS
+ };
+
+ services = g_array_sized_new (FALSE,
+ FALSE,
+ sizeof (QmiService),
+ G_N_ELEMENTS (required_services));
+ g_array_append_vals (services,
+ required_services,
+ G_N_ELEMENTS (required_services));
+
+ mm_obj_info (self,"Waiting for services...");
+ qrtr_node_wait_for_services (ctx->node,
+ services,
+ 0,
+ NULL,
+ (GAsyncReadyCallback) qrtr_node_services_ready,
+ task);
+ return;
+ }
+#endif
+
case PORT_OPEN_STEP_DEVICE_NEW: {
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove hacks before merging to upstream
+ mm_obj_info (self, "Creating QMI device from QRTR node...");
+ qmi_device_new_from_node (ctx->node,
+ g_task_get_cancellable (task),
+ (GAsyncReadyCallback) qmi_device_new_ready,
+ task);
+#else
GFile *file;
gchar *fullpath;
@@ -500,6 +599,7 @@
g_free (fullpath);
g_object_unref (file);
+#endif
return;
}
@@ -668,7 +768,11 @@
ctx = g_slice_new0 (PortOpenContext);
ctx->step = PORT_OPEN_STEP_FIRST;
+#if QMI_QRTR_SUPPORTED //TODO(crbug.com/1103840): Remove before merging to upstream
+ ctx->set_data_format = FALSE;
+#else
ctx->set_data_format = set_data_format;
+#endif
ctx->kernel_data_format = QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN;
ctx->llp = QMI_WDA_LINK_LAYER_PROTOCOL_UNKNOWN;