[MM][PATCH] modem: add support for 3GPP Vendor PCO info
ori inbar
ori.inbar.altair.semi.com at gmail.com
Mon Jul 1 22:27:12 PDT 2013
From: ori inbar <ori.inbar at altair-semi.com>
Change-Id: I139802238868e9743390906c1cfc77fef9179599
---
...g.freedesktop.ModemManager1.Modem.Modem3gpp.xml | 17 +++
libmm-glib/mm-simple-status.c | 26 +++-
libmm-glib/mm-simple-status.h | 1 +
src/mm-broadband-bearer.c | 10 ++
src/mm-iface-modem-3gpp.c | 145 +++++++++++++++++++--
src/mm-iface-modem-3gpp.h | 18 +++
6 files changed, 206 insertions(+), 11 deletions(-)
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
index 83e1499..14b5e02 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
@@ -136,5 +136,22 @@
-->
<property name="EnabledFacilityLocks" type="u" access="read" />
+ <!--
+ VendorPcoInfo
+
+ Vendor-specific protocol configuration option (PCO) info received from the LTE
+ mobile network to which the mobile is currently registered (see 3GPP TS 24.008
+ Section 10.5.6.3).
+
+ Returned in the format <literal>"PCOIdPCOPayload"</literal>, where
+ <literal>PCOId</literal> is the 4-digit hex-encoded string of PCO ID and
+ <literal>PCOPayload</literal> is the hex-encoded string of the PCO payload data,
+ e.g. <literal>"FF003114800"</literal>.
+
+ If the <literal>PCOId</literal> and <literal>PCOPayload</literal> are not known
+ or the mobile is not registered to a mobile network, this property will
+ be a zero-length (blank) string.
+ -->
+ <property name="VendorPcoInfo" type="s" access="read" />
</interface>
</node>
diff --git a/libmm-glib/mm-simple-status.c b/libmm-glib/mm-simple-status.c
index 10dfee3..0560a34 100644
--- a/libmm-glib/mm-simple-status.c
+++ b/libmm-glib/mm-simple-status.c
@@ -44,6 +44,7 @@ enum {
PROP_3GPP_REGISTRATION_STATE,
PROP_3GPP_OPERATOR_CODE,
PROP_3GPP_OPERATOR_NAME,
+ PROP_3GPP_VENDOR_PCO_INFO,
PROP_CDMA_CDMA1X_REGISTRATION_STATE,
PROP_CDMA_EVDO_REGISTRATION_STATE,
PROP_CDMA_SID,
@@ -72,6 +73,8 @@ struct _MMSimpleStatusPrivate {
gchar *modem_3gpp_operator_code;
/* 3GPP operator name, given only when registered, signature 's' */
gchar *modem_3gpp_operator_name;
+ /* 3GPP LTE vendor PCO info, given only when registered, signature 's' */
+ gchar *modem_3gpp_vendor_pco_info;
/* <--- From the Modem CDMA interface ---> */
/* CDMA/CDMA1x registration state, signature 'u' */
@@ -350,6 +353,11 @@ mm_simple_status_get_dictionary (MMSimpleStatus *self)
"{sv}",
MM_SIMPLE_PROPERTY_3GPP_OPERATOR_NAME,
g_variant_new_string (self->priv->modem_3gpp_operator_name));
+ if (self->priv->modem_3gpp_vendor_pco_info)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ MM_SIMPLE_PROPERTY_3GPP_VENDOR_PCO_INFO,
+ g_variant_new_string (self->priv->modem_3gpp_vendor_pco_info));
if (self->priv->modem_cdma_cdma1x_registration_state != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
g_variant_builder_add (&builder,
@@ -423,7 +431,8 @@ mm_simple_status_new_from_dictionary (GVariant *dictionary,
key, g_variant_get_uint32 (value),
NULL);
} else if (g_str_equal (key, MM_SIMPLE_PROPERTY_3GPP_OPERATOR_CODE) ||
- g_str_equal (key, MM_SIMPLE_PROPERTY_3GPP_OPERATOR_NAME)) {
+ g_str_equal (key, MM_SIMPLE_PROPERTY_3GPP_OPERATOR_NAME) ||
+ g_str_equal (key, MM_SIMPLE_PROPERTY_3GPP_VENDOR_PCO_INFO)) {
/* string properties */
g_object_set (properties,
key, g_variant_get_string (value, NULL),
@@ -501,6 +510,10 @@ set_property (GObject *object,
g_free (self->priv->modem_3gpp_operator_code);
self->priv->modem_3gpp_operator_code = g_value_dup_string (value);
break;
+ case PROP_3GPP_VENDOR_PCO_INFO:
+ g_free (self->priv->modem_3gpp_vendor_pco_info);
+ self->priv->modem_3gpp_vendor_pco_info = g_value_dup_string (value);
+ break;
case PROP_3GPP_OPERATOR_NAME:
g_free (self->priv->modem_3gpp_operator_name);
self->priv->modem_3gpp_operator_name = g_value_dup_string (value);
@@ -553,6 +566,9 @@ get_property (GObject *object,
case PROP_3GPP_OPERATOR_NAME:
g_value_set_string (value, self->priv->modem_3gpp_operator_name);
break;
+ case PROP_3GPP_VENDOR_PCO_INFO:
+ g_value_set_string (value, self->priv->modem_3gpp_vendor_pco_info);
+ break;
case PROP_CDMA_CDMA1X_REGISTRATION_STATE:
g_value_set_enum (value, self->priv->modem_cdma_cdma1x_registration_state);
break;
@@ -678,6 +694,14 @@ mm_simple_status_class_init (MMSimpleStatusClass *klass)
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_3GPP_OPERATOR_NAME, properties[PROP_3GPP_OPERATOR_NAME]);
+ properties[PROP_3GPP_VENDOR_PCO_INFO] =
+ g_param_spec_string (MM_SIMPLE_PROPERTY_3GPP_VENDOR_PCO_INFO,
+ "3GPP LTE vendor PCO info",
+ "Hex-encoded string of the current vendor PCO info",
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_3GPP_VENDOR_PCO_INFO, properties[PROP_3GPP_VENDOR_PCO_INFO]);
+
properties[PROP_CDMA_CDMA1X_REGISTRATION_STATE] =
g_param_spec_enum (MM_SIMPLE_PROPERTY_CDMA_CDMA1X_REGISTRATION_STATE,
"CDMA1x registration state",
diff --git a/libmm-glib/mm-simple-status.h b/libmm-glib/mm-simple-status.h
index 8292fdb..be4f7f6 100644
--- a/libmm-glib/mm-simple-status.h
+++ b/libmm-glib/mm-simple-status.h
@@ -88,6 +88,7 @@ guint mm_simple_status_get_cdma_nid
#define MM_SIMPLE_PROPERTY_3GPP_REGISTRATION_STATE "m3gpp-registration-state"
#define MM_SIMPLE_PROPERTY_3GPP_OPERATOR_CODE "m3gpp-operator-code"
#define MM_SIMPLE_PROPERTY_3GPP_OPERATOR_NAME "m3gpp-operator-name"
+#define MM_SIMPLE_PROPERTY_3GPP_VENDOR_PCO_INFO "m3gpp-vendor-pco-info"
#define MM_SIMPLE_PROPERTY_CDMA_CDMA1X_REGISTRATION_STATE "cdma-cdma1x-registration-state"
#define MM_SIMPLE_PROPERTY_CDMA_EVDO_REGISTRATION_STATE "cdma-evdo-registration-state"
diff --git a/src/mm-broadband-bearer.c b/src/mm-broadband-bearer.c
index f8f449d..90fd33f 100644
--- a/src/mm-broadband-bearer.c
+++ b/src/mm-broadband-bearer.c
@@ -1100,6 +1100,7 @@ connect_3gpp_ready (MMBroadbandBearer *self,
ConnectContext *ctx)
{
MMBearerConnectResult *result;
+ MMBaseModem *modem = NULL;
GError *error = NULL;
result = MM_BROADBAND_BEARER_GET_CLASS (self)->connect_3gpp_finish (self, res, &error);
@@ -1109,6 +1110,15 @@ connect_3gpp_ready (MMBroadbandBearer *self,
return;
}
+ /* Get the owner modem object */
+ g_object_get (self,
+ MM_BEARER_MODEM, &modem,
+ NULL);
+ g_assert (modem != NULL);
+
+ /* In case of 3GPP LTE, there is a need to refresh the vendor PCO info at this stage. */
+ mm_iface_modem_3gpp_reload_current_vendor_pco_info (MM_IFACE_MODEM_3GPP (modem), NULL, NULL);
+
/* take result */
connect_succeeded (ctx, CONNECTION_TYPE_3GPP, result);
}
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 53399d5..7fdce03 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -64,6 +64,10 @@ mm_iface_modem_3gpp_bind_simple_status (MMIfaceModem3gpp *self,
status, MM_SIMPLE_PROPERTY_3GPP_OPERATOR_NAME,
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+ g_object_bind_property (skeleton, "vendor-pco-info",
+ status, MM_SIMPLE_PROPERTY_3GPP_VENDOR_PCO_INFO,
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
g_object_unref (skeleton);
}
@@ -75,7 +79,7 @@ typedef struct {
MMModem3gppRegistrationState eps;
gboolean manual_registration;
GCancellable *pending_registration_cancellable;
- gboolean reloading_operator;
+ gboolean reloading_registration_info;
} RegistrationStateContext;
static void
@@ -951,6 +955,114 @@ mm_iface_modem_3gpp_clear_current_operator (MMIfaceModem3gpp *self)
/*****************************************************************************/
+typedef struct {
+ MMIfaceModem3gpp *self;
+ MmGdbusModem3gpp *skeleton;
+ GSimpleAsyncResult *result;
+} ReloadCurrentVendorPcoInfoContext;
+
+static void
+reload_current_vendor_pco_info_context_complete_and_free (ReloadCurrentVendorPcoInfoContext *ctx)
+{
+ g_simple_async_result_complete_in_idle (ctx->result);
+ g_object_unref (ctx->result);
+ if (ctx->skeleton)
+ g_object_unref (ctx->skeleton);
+ g_object_unref (ctx->self);
+ g_slice_free (ReloadCurrentVendorPcoInfoContext, ctx);
+}
+
+gboolean
+mm_iface_modem_3gpp_reload_current_vendor_pco_info_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+load_vendor_pco_info_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ ReloadCurrentVendorPcoInfoContext *ctx)
+{
+ GError *error = NULL;
+ gchar *str;
+
+ str = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_vendor_pco_info_finish (self, res, &error);
+ if (error) {
+ mm_warn ("Couldn't load Vendor PCO Info: '%s'", error->message);
+ g_error_free (error);
+ }
+
+ if (ctx->skeleton)
+ mm_gdbus_modem3gpp_set_vendor_pco_info (ctx->skeleton, str);
+
+ g_free (str);
+
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ reload_current_vendor_pco_info_context_complete_and_free (ctx);
+}
+
+void
+mm_iface_modem_3gpp_reload_current_vendor_pco_info (MMIfaceModem3gpp *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ReloadCurrentVendorPcoInfoContext *ctx;
+
+ ctx = g_slice_new0 (ReloadCurrentVendorPcoInfoContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ mm_iface_modem_3gpp_reload_current_vendor_pco_info);
+
+ g_object_get (self,
+ MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &ctx->skeleton,
+ NULL);
+
+ if (!ctx->skeleton) {
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't get interface skeleton");
+ reload_current_vendor_pco_info_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (!MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_vendor_pco_info ||
+ !MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_vendor_pco_info_finish) {
+
+ mm_gdbus_modem3gpp_set_vendor_pco_info (ctx->skeleton, NULL);
+
+ g_simple_async_result_set_op_res_gboolean(ctx->result, TRUE);
+ reload_current_vendor_pco_info_context_complete_and_free(ctx);
+ return;
+ }
+
+ /* Launch vendor PCO info update */
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->load_vendor_pco_info (
+ ctx->self,
+ (GAsyncReadyCallback)load_vendor_pco_info_ready,
+ ctx);
+}
+
+void
+mm_iface_modem_3gpp_clear_current_vendor_pco_info (MMIfaceModem3gpp *self)
+{
+ MmGdbusModem3gpp *skeleton = NULL;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton,
+ NULL);
+ if (!skeleton)
+ return;
+
+ mm_gdbus_modem3gpp_set_vendor_pco_info (skeleton, NULL);
+}
+/*****************************************************************************/
+
+
void
mm_iface_modem_3gpp_update_access_technologies (MMIfaceModem3gpp *self,
MMModemAccessTechnology access_tech)
@@ -969,7 +1081,7 @@ mm_iface_modem_3gpp_update_access_technologies (MMIfaceModem3gpp *self,
* but only if something valid to report */
if (state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
- ctx->reloading_operator) {
+ ctx->reloading_registration_info) {
if (access_tech != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN)
mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self),
access_tech,
@@ -1034,7 +1146,19 @@ update_registration_reload_current_operator_ready (MMIfaceModem3gpp *self,
MM_MODEM_STATE_CHANGE_REASON_UNKNOWN);
ctx = get_registration_state_context (self);
- ctx->reloading_operator = FALSE;
+ ctx->reloading_registration_info = FALSE;
+}
+
+static void
+update_registration_reload_current_vendor_pco_info_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ mm_iface_modem_3gpp_reload_current_operator (
+ self,
+ (GAsyncReadyCallback)update_registration_reload_current_operator_ready,
+ user_data);
+
}
static void
@@ -1044,6 +1168,7 @@ update_non_registered_state (MMIfaceModem3gpp *self,
{
/* Not registered neither in home nor roaming network */
mm_iface_modem_3gpp_clear_current_operator (self);
+ mm_iface_modem_3gpp_clear_current_vendor_pco_info(self);
/* The property in the interface is bound to the property
* in the skeleton, so just updating here is enough */
@@ -1081,20 +1206,20 @@ update_registration_state (MMIfaceModem3gpp *self,
if (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
- /* If already reloading operator, skip it */
- if (ctx->reloading_operator)
+ /* If already reloading registration info, skip it */
+ if (ctx->reloading_registration_info)
return;
mm_info ("Modem %s: 3GPP Registration state changed (%s -> registering)",
g_dbus_object_get_object_path (G_DBUS_OBJECT (self)),
mm_modem_3gpp_registration_state_get_string (old_state));
- /* Reload current operator. ONLY update the state to REGISTERED after
- * having loaded operator code/name */
- ctx->reloading_operator = TRUE;
- mm_iface_modem_3gpp_reload_current_operator (
+ /* Reload current registration info - vendor PCO info and operator.
+ * ONLY update the state to REGISTERED after having loaded operator code/name */
+ ctx->reloading_registration_info = TRUE;
+ mm_iface_modem_3gpp_reload_current_vendor_pco_info (
self,
- (GAsyncReadyCallback)update_registration_reload_current_operator_ready,
+ (GAsyncReadyCallback)update_registration_reload_current_vendor_pco_info_ready,
GUINT_TO_POINTER (new_state));
return;
}
diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h
index f4014c4..79342e6 100644
--- a/src/mm-iface-modem-3gpp.h
+++ b/src/mm-iface-modem-3gpp.h
@@ -34,6 +34,7 @@
#define MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED "iface-modem-3gpp-ps-network-supported"
#define MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED "iface-modem-3gpp-eps-network-supported"
#define MM_IFACE_MODEM_3GPP_IGNORED_FACILITY_LOCKS "iface-modem-3gpp-ignored-facility-locks"
+#define MM_IFACE_MODEM_3GPP_VENDOR_PCO_INFO "iface-modem-3gpp-vendor-pco-info"
#define MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK \
(MM_MODEM_ACCESS_TECHNOLOGY_GSM | \
@@ -176,6 +177,14 @@ struct _MMIfaceModem3gpp {
GAsyncResult *res,
GError **error);
+ /* Loading of the Vendor PCO Info property */
+ void (*load_vendor_pco_info) (MMIfaceModem3gpp *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gchar * (*load_vendor_pco_info_finish) (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
+
/* Scan current networks, expect a GList of MMModem3gppNetworkInfo */
void (* scan_networks) (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,
@@ -249,6 +258,15 @@ gboolean mm_iface_modem_3gpp_reload_current_operator_finish (MMIfaceModem3gpp *s
GError **error);
void mm_iface_modem_3gpp_clear_current_operator (MMIfaceModem3gpp *self);
+/* Request to reload vendor PCO info */
+void mm_iface_modem_3gpp_reload_current_vendor_pco_info (MMIfaceModem3gpp *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_iface_modem_3gpp_reload_current_vendor_pco_info_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
+void mm_iface_modem_3gpp_clear_current_vendor_pco_info (MMIfaceModem3gpp *self);
+
/* Allow registering in the network */
gboolean mm_iface_modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
--
1.7.12.4
More information about the ModemManager-devel
mailing list