[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