[MM][PATCH] altair-lte: add support for 3GPP Vendor PCO info
Dan Williams
dcbw at redhat.com
Tue Jul 9 07:24:48 PDT 2013
On Tue, 2013-07-02 at 00:28 -0500, ori inbar wrote:
> 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. */
I'll assume CID here means the PDP context CID from CGDCONT. In that
case, why is CID 3 special? Yes, by default for VZW CID 3 is
"vzwinternet" but relying on a specific PDP context layout is quite
fragile. Does the POC info show up regardless of whether there's an
active bearer?
Dan
> + 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;
>
> }
>
More information about the ModemManager-devel
mailing list