[MM][PATCH] altair-lte: add support for 3GPP Vendor PCO info
ori inbar
ori.inbar.altair.semi.com at gmail.com
Mon Jul 1 22:28:11 PDT 2013
From: ori inbar <ori.inbar at altair-semi.com>
Change-Id: I5cd665247a035c1da6f892ead083ab8c8af3551a
---
plugins/altair/mm-broadband-modem-altair-lte.c | 179 +++++++++++++++++++++++--
1 file changed, 169 insertions(+), 10 deletions(-)
mode change 100644 => 100755 plugins/altair/mm-broadband-modem-altair-lte.c
diff --git a/plugins/altair/mm-broadband-modem-altair-lte.c b/plugins/altair/mm-broadband-modem-altair-lte.c
old mode 100644
new mode 100755
index a2ae2ba..c1b16f3
--- a/plugins/altair/mm-broadband-modem-altair-lte.c
+++ b/plugins/altair/mm-broadband-modem-altair-lte.c
@@ -51,6 +51,7 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemAltairLte, mm_broadband_modem_altair_lte
struct _MMBroadbandModemAltairLtePrivate {
/* Regex for bearer related notifications */
GRegex *statcm_regex;
+ GRegex *pcoinfo_regex;
};
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
@@ -553,6 +554,19 @@ altair_statcm_changed (MMAtSerialPort *port,
}
static void
+altair_pcoinfo_changed (MMAtSerialPort *port,
+ GMatchInfo *match_info,
+ MMBroadbandModemAltairLte *self)
+{
+ gint cid = 0;
+ mm_get_int_from_match_info (match_info, 1, &cid);
+
+ mm_dbg ("altair_pcoinfo_changed for cid %d", cid);
+
+ mm_iface_modem_3gpp_reload_current_vendor_pco_info (MM_IFACE_MODEM_3GPP (self), NULL, NULL);
+}
+
+static void
set_3gpp_unsolicited_events_handlers (MMBroadbandModemAltairLte *self,
gboolean enable)
{
@@ -574,6 +588,14 @@ set_3gpp_unsolicited_events_handlers (MMBroadbandModemAltairLte *self,
enable ? (MMAtSerialUnsolicitedMsgFn)altair_statcm_changed : NULL,
enable ? self : NULL,
NULL);
+
+ /* Vendor PCO info change */
+ mm_at_serial_port_add_unsolicited_msg_handler (
+ ports[i],
+ self->priv->pcoinfo_regex,
+ enable ? (MMAtSerialUnsolicitedMsgFn)altair_pcoinfo_changed : NULL,
+ enable ? self : NULL,
+ NULL);
}
}
@@ -687,6 +709,12 @@ own_enable_unsolicited_events_ready (MMBaseModem *self,
g_object_unref (simple);
}
+static const MMBaseModemAtCommand unsolicited_enable_sequence[] = {
+ { "%STATCM=1", 5, FALSE, NULL },
+ { "%PCOINFO=1", 3, FALSE, NULL },
+ { NULL }
+};
+
static void
parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self,
GAsyncResult *res,
@@ -702,13 +730,12 @@ parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self,
}
/* Our own enable now */
- mm_base_modem_at_command_full (
+ mm_base_modem_at_sequence_full (
MM_BASE_MODEM (self),
mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
- "%STATCM=1",
- 6,
- FALSE, /* allow_cached */
- FALSE, /* raw */
+ unsolicited_enable_sequence,
+ NULL, /* response_processor_context */
+ NULL, /* response_processor_context_free */
NULL, /* cancellable */
(GAsyncReadyCallback)own_enable_unsolicited_events_ready,
simple);
@@ -781,6 +808,12 @@ own_disable_unsolicited_events_ready (MMBaseModem *self,
simple);
}
+static const MMBaseModemAtCommand unsolicited_disable_sequence[] = {
+ { "%STATCM=0", 5, FALSE, NULL },
+ { "%PCOINFO=0", 5, FALSE, NULL },
+ { NULL }
+};
+
static void
modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,
@@ -794,13 +827,12 @@ modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self,
modem_3gpp_disable_unsolicited_events);
/* Our own disable first */
- mm_base_modem_at_command_full (
+ mm_base_modem_at_sequence_full (
MM_BASE_MODEM (self),
mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
- "%STATCM=0",
- 5,
- FALSE, /* allow_cached */
- FALSE, /* raw */
+ unsolicited_disable_sequence,
+ NULL, /* response_processor_context */
+ NULL, /* response_processor_context_free */
NULL, /* cancellable */
(GAsyncReadyCallback)own_disable_unsolicited_events_ready,
result);
@@ -893,6 +925,128 @@ modem_3gpp_load_operator_name (MMIfaceModem3gpp *self,
callback,
user_data);
}
+/*****************************************************************************/
+/* Vendor PCO Info loading (3GPP interface) */
+
+static gchar *
+mm_broadband_modem_altair_lte_parse_vendor_pco_info (const gchar *reply)
+{
+ GError *inner_error = NULL;
+ GRegex *r;
+ GMatchInfo *match_info;
+ guint cid;
+ gchar *result = NULL;
+
+ if (!reply[0])
+ /* No APNs configured, all done */
+ return NULL;
+
+ r = g_regex_new ("\\%PCOINFO:\\s*(\\d+)\\s*,(\\d+)\\s*(,([^,\\)]*),([0-9A-Fa-f]*))?",
+ G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
+ 0, &inner_error);
+ if (r) {
+ g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, &inner_error);
+
+ while (!inner_error && g_match_info_matches (match_info)) {
+ gchar *pco_id;
+
+ if (!mm_get_uint_from_match_info (match_info, 2, &cid)) {
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't parse CID from reply: '%s'",
+ reply);
+ break;
+ }
+
+ pco_id = mm_get_string_unquoted_from_match_info (match_info, 4);
+
+ /* If this is the first PCO info we're getting, use it. Otherwise only use CID 3
+ PCO info, since this is the internet bearer. */
+ if (pco_id && (!result || cid == 3)) {
+ gchar *pco_payload;
+
+ pco_payload = mm_get_string_unquoted_from_match_info (match_info, 5);
+ if (!pco_payload) {
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't parse PCO payload from reply: '%s'",
+ reply);
+ g_free (pco_id);
+ break;
+ }
+
+ if (result) {
+ g_free (result);
+ result = NULL;
+ }
+
+ result = g_strdup_printf ("%s%s", pco_id, pco_payload);
+
+ mm_dbg ("Vendor PCO info for CID %d: '%s'", cid, result);
+
+ g_free (pco_id);
+ g_free (pco_payload);
+ } else {
+ if (pco_id)
+ mm_dbg ("Vendor PCO info for CID %d is disregarded since we already have one", cid);
+ else
+ mm_dbg ("Vendor PCO info for CID %d is disregarded since it has no PCO data", cid);
+ }
+
+ g_match_info_next (match_info, &inner_error);
+ }
+
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+ }
+
+ if (inner_error) {
+ mm_dbg ("Error parsing %%PCOINFO response: '%s'", inner_error->message);
+ g_error_free (inner_error);
+ if (result) {
+ g_free (result);
+ result = NULL;
+ }
+ }
+
+ return result;
+}
+
+static gchar *
+modem_3gpp_load_vendor_pco_info_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ const gchar *result;
+ gchar *vendor_pco_info;
+
+ result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
+ if (!result)
+ return NULL;
+
+ vendor_pco_info = mm_broadband_modem_altair_lte_parse_vendor_pco_info (result);
+ if (vendor_pco_info)
+ mm_dbg ("loaded Vendor PCO Info: %s", vendor_pco_info);
+ else
+ mm_dbg ("loaded empty Vendor PCO Info");
+
+ return vendor_pco_info;
+}
+
+static void
+modem_3gpp_load_vendor_pco_info (MMIfaceModem3gpp *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ mm_dbg ("Loading Vendor PCO Info...");
+
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "%PCOINFO?",
+ 6,
+ FALSE,
+ callback,
+ user_data);
+}
/*****************************************************************************/
/* Generic ports open/close context */
@@ -955,6 +1109,9 @@ mm_broadband_modem_altair_lte_init (MMBroadbandModemAltairLte *self)
self->priv->statcm_regex = g_regex_new ("\\r\\n\\%STATCM:\\s*(\\d*),?(\\d*)\\r+\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+
+ self->priv->pcoinfo_regex = g_regex_new ("\\r\\n\\%PCOINFO:\\s*(\\d*),([^,\\s]*),([^,\\s]*)\\r+\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
}
static void
@@ -1028,6 +1185,8 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
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_vendor_pco_info = modem_3gpp_load_vendor_pco_info;
+ iface->load_vendor_pco_info_finish = modem_3gpp_load_vendor_pco_info_finish;
}
--
1.7.12.4
More information about the ModemManager-devel
mailing list