Re: [MM][PATCH v2] altair-lte: initial altair lte plugin



Hey Ori,

---
 plugins/Makefile.am                             |   12 +
 plugins/altair/mm-broadband-bearer-altair-lte.c |  383 ++++++++
 plugins/altair/mm-broadband-bearer-altair-lte.h |   60 ++
 plugins/altair/mm-broadband-modem-altair-lte.c  | 1096 +++++++++++++++++++++++
 plugins/altair/mm-broadband-modem-altair-lte.h  |   51 ++
 plugins/altair/mm-plugin-altair-lte.c           |   84 ++
 plugins/altair/mm-plugin-altair-lte.h           |   48 +
 src/77-mm-usb-device-blacklist.rules            |    3 +
 8 files changed, 1737 insertions(+)
 create mode 100644 plugins/altair/mm-broadband-bearer-altair-lte.c
 create mode 100644 plugins/altair/mm-broadband-bearer-altair-lte.h
 create mode 100644 plugins/altair/mm-broadband-modem-altair-lte.c
 create mode 100644 plugins/altair/mm-broadband-modem-altair-lte.h
 create mode 100644 plugins/altair/mm-plugin-altair-lte.c
 create mode 100644 plugins/altair/mm-plugin-altair-lte.h
 mode change 100644 => 100755 src/77-mm-usb-device-blacklist.rules


Some more comments below. Also, as requested in another email, please
attach a debug log of MM handling this modem, for reference.


diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 3693a4b..9621de9 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -53,6 +53,7 @@ pkglib_LTLIBRARIES = \
      libmm-plugin-motorola.la \
      libmm-plugin-novatel.la \
      libmm-plugin-novatel-lte.la \
+     libmm-plugin-altair-lte.la \
      libmm-plugin-samsung.la \
      libmm-plugin-option.la \
      libmm-plugin-hso.la \
@@ -315,6 +316,17 @@ libmm_plugin_novatel_la_SOURCES = \
 libmm_plugin_novatel_la_CPPFLAGS = $(PLUGIN_COMMON_COMPILER_FLAGS)
 libmm_plugin_novatel_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS)
 
+# Altair LTE modem
+libmm_plugin_altair_lte_la_SOURCES = \
+     altair/mm-plugin-altair-lte.c \
+     altair/mm-plugin-altair-lte.h \
+     altair/mm-broadband-modem-altair-lte.c \
+     altair/mm-broadband-modem-altair-lte.h \
+     altair/mm-broadband-bearer-altair-lte.c \
+     altair/mm-broadband-bearer-altair-lte.h
+libmm_plugin_altair_lte_la_CPPFLAGS = $(PLUGIN_COMMON_COMPILER_FLAGS)
+libmm_plugin_altair_lte_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS)
+
 # VIA modem
 libmm_plugin_via_la_SOURCES = \
      via/mm-plugin-via.c \
diff --git a/plugins/altair/mm-broadband-bearer-altair-lte.c 
b/plugins/altair/mm-broadband-bearer-altair-lte.c
new file mode 100644
index 0000000..6303a8c
--- /dev/null
+++ b/plugins/altair/mm-broadband-bearer-altair-lte.c
@@ -0,0 +1,383 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 - 2012 Red Hat, Inc.
+ * Copyright (C) 2013 Altair Semiconductor
+ *
+ * Author: Ori Inbar <ori inbar altair-semi com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <ModemManager.h>
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
+#include "mm-base-modem-at.h"
+#include "mm-broadband-bearer-altair-lte.h"
+#include "mm-log.h"
+#include "mm-modem-helpers.h"
+
+#define CONNECTION_CHECK_TIMEOUT_SEC 5
+#define STATCM_TAG "%STATCM:"
+
+G_DEFINE_TYPE (MMBroadbandBearerAltairLte, mm_broadband_bearer_altair_lte, MM_TYPE_BROADBAND_BEARER);
+
+/*****************************************************************************/
+/* 3GPP Connect sequence */
+
+typedef struct {
+    MMBroadbandBearerAltairLte *self;
+    MMBaseModem *modem;
+    MMAtSerialPort *primary;
+    MMPort *data;
+    GCancellable *cancellable;
+    GSimpleAsyncResult *result;
+} DetailedConnectContext;
+
+static DetailedConnectContext *
+detailed_connect_context_new (MMBroadbandBearer *self,
+                              MMBroadbandModem *modem,
+                              MMAtSerialPort *primary,
+                              MMPort *data,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+    DetailedConnectContext *ctx;
+
+    ctx = g_new0 (DetailedConnectContext, 1);
+    ctx->self = g_object_ref (self);
+    ctx->modem = MM_BASE_MODEM (g_object_ref (modem));
+    ctx->primary = g_object_ref (primary);
+    ctx->data = data;
+    /* NOTE:
+     * We don't currently support cancelling AT commands, so we'll just check
+     * whether the operation is to be cancelled at each step. */
+    ctx->cancellable = g_object_ref (cancellable);
+    ctx->result = g_simple_async_result_new (G_OBJECT (self),
+                                             callback,
+                                             user_data,
+                                             detailed_connect_context_new);
+    return ctx;
+}
+
+static void
+detailed_connect_context_complete_and_free (DetailedConnectContext *ctx)
+{
+    g_simple_async_result_complete_in_idle (ctx->result);
+    g_object_unref (ctx->result);
+    g_object_unref (ctx->cancellable);
+    if (ctx->data)
+        g_object_unref (ctx->data);
+    g_object_unref (ctx->primary);
+    g_object_unref (ctx->modem);
+    g_object_unref (ctx->self);
+    g_free (ctx);
+}
+
+static MMBearerConnectResult *
+connect_3gpp_finish (MMBroadbandBearer *self,
+                     GAsyncResult *res,
+                     GError **error)
+{
+    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+        return NULL;
+
+    return mm_bearer_connect_result_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT 
(res)));
+}
+
+static void
+connect_3gpp_connect_ready (MMBaseModem *modem,
+                            GAsyncResult *res,
+                            DetailedConnectContext *ctx)
+{
+    const gchar *result;
+    GError *error = NULL;
+    MMBearerIpConfig *config;
+
+    result = mm_base_modem_at_command_finish (MM_BASE_MODEM (modem),
+                                              res,
+                                              &error);
+    if (!result) {
+        mm_warn ("connect failed: %s", error->message);
+        g_simple_async_result_take_error (ctx->result, error);
+        detailed_connect_context_complete_and_free (ctx);
+        return;
+    }
+
+    mm_dbg("Connected");

Whitespace before the parenthesis.

+
+    config = mm_bearer_ip_config_new ();
+
+    mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP);
+
+    /* Set operation result */
+    g_simple_async_result_set_op_res_gpointer (
+        ctx->result,
+        mm_bearer_connect_result_new (ctx->data,
+                                      config,
+                                      config),
+        (GDestroyNotify)mm_bearer_connect_result_unref);
+
+    g_object_unref (config);
+
+    detailed_connect_context_complete_and_free (ctx);

Explicit return and whitelines afterwards not needed.

+    return;
+
+
+}
+
+static void
+connect_3gpp_apnsettings_ready (MMBaseModem *modem,
+                               GAsyncResult *res,
+                               DetailedConnectContext *ctx)
+{
+    const gchar *result;
+    GError *error = NULL;
+
+    result = mm_base_modem_at_command_finish (MM_BASE_MODEM (modem),
+                                              res,
+                                              &error);
+    if (!result) {
+        mm_warn ("setting APN failed: %s", error->message);
+        g_simple_async_result_take_error (ctx->result, error);
+        detailed_connect_context_complete_and_free (ctx);
+        return;
+    }
+
+    mm_dbg ("APN set - connecting bearer");
+    mm_base_modem_at_command (
+        ctx->modem,
+        "%DPDNACT=1",
+        10, /* timeout */
+        FALSE, /* allow_cached */
+        (GAsyncReadyCallback)connect_3gpp_connect_ready, /* callback */
+        ctx); /* user_data */
+}
+
+static void
+connect_3gpp (MMBroadbandBearer *bearer,
+              MMBroadbandModem *modem,
+              MMAtSerialPort *primary,
+              MMAtSerialPort *secondary,
+              GCancellable *cancellable,
+              GAsyncReadyCallback callback,
+              gpointer user_data)
+{
+    DetailedConnectContext *ctx;
+    gchar *command, *apn;
+    MMBearerProperties *config;
+
+    ctx = detailed_connect_context_new (
+        bearer,
+        modem,
+        primary,
+        /* Get a 'net' data port */
+        mm_base_modem_get_best_data_port (MM_BASE_MODEM (modem),
+                                          MM_PORT_TYPE_NET),
+        cancellable,
+        callback,
+        user_data);
+
+    if (!ctx->data) {
+        g_simple_async_result_set_error (
+            ctx->result,
+            MM_CORE_ERROR,
+            MM_CORE_ERROR_CONNECTED,
+            "Couldn't connect: no available net port available");
+        detailed_connect_context_complete_and_free (ctx);
+        return;
+    }
+
+    config = mm_bearer_peek_config (MM_BEARER (bearer));
+    apn = mm_at_serial_port_quote_string (mm_bearer_properties_get_apn (config));
+    command = g_strdup_printf ("%%APNN=%s",apn);
+    g_free (apn);
+    mm_base_modem_at_command (
+        ctx->modem,
+        command,
+        6, /* timeout */
+        FALSE, /* allow_cached */
+        (GAsyncReadyCallback)connect_3gpp_apnsettings_ready,
+        ctx); /* user_data */
+    g_free (command);
+}
+
+/*****************************************************************************/
+/* 3GPP Disconnect sequence */
+
+typedef struct {
+    MMBroadbandBearer *self;
+    MMBaseModem *modem;
+    MMAtSerialPort *primary;
+    MMAtSerialPort *secondary;
+    MMPort *data;
+    GSimpleAsyncResult *result;
+} DetailedDisconnectContext;
+
+static DetailedDisconnectContext *
+detailed_disconnect_context_new (MMBroadbandBearer *self,
+                                 MMBroadbandModem *modem,
+                                 MMAtSerialPort *primary,
+                                 MMAtSerialPort *secondary,
+                                 MMPort *data,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+    DetailedDisconnectContext *ctx;
+
+    ctx = g_new0 (DetailedDisconnectContext, 1);
+    ctx->self = g_object_ref (self);
+    ctx->modem = MM_BASE_MODEM (g_object_ref (modem));
+    ctx->primary = g_object_ref (primary);
+    ctx->secondary = (secondary ? g_object_ref (secondary) : NULL);
+    ctx->data = g_object_ref (data);
+    ctx->result = g_simple_async_result_new (G_OBJECT (self),
+                                             callback,
+                                             user_data,
+                                             detailed_disconnect_context_new);
+    return ctx;
+}
+
+static gboolean
+disconnect_3gpp_finish (MMBroadbandBearer *self,
+                        GAsyncResult *res,
+                        GError **error)
+{
+    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+detailed_disconnect_context_complete_and_free (DetailedDisconnectContext *ctx)
+{
+    g_simple_async_result_complete_in_idle (ctx->result);
+    g_object_unref (ctx->result);
+    g_object_unref (ctx->data);
+    if (ctx->secondary)
+        g_object_unref (ctx->secondary);
+    g_object_unref (ctx->primary);
+    g_object_unref (ctx->modem);
+    g_object_unref (ctx->self);
+    g_free (ctx);
+}
+
+static void
+disconnect_3gpp_check_status (MMBaseModem *modem,
+                              GAsyncResult *res,
+                              DetailedDisconnectContext *ctx)
+{
+
+    const gchar *result;
+    GError *error = NULL;
+
+    result = mm_base_modem_at_command_finish (MM_BASE_MODEM (modem),
+                                              res,
+                                              &error);
+    if (!result) {
+        mm_warn ("Disconnect failed: %s", error->message);
+        g_simple_async_result_take_error (ctx->result, error);
+    }
+    else
+        g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+
+    detailed_disconnect_context_complete_and_free (ctx);

Explicit return not needed here.

+    return;
+}
+
+static void
+disconnect_3gpp (MMBroadbandBearer *self,
+                 MMBroadbandModem *modem,
+                 MMAtSerialPort *primary,
+                 MMAtSerialPort *secondary,
+                 MMPort *data,
+                 guint cid,
+                 GAsyncReadyCallback callback,
+                 gpointer user_data)
+{
+    DetailedDisconnectContext *ctx;
+
+    ctx = detailed_disconnect_context_new (self, modem, primary, secondary,
+                                           data, callback, user_data);
+
+    mm_base_modem_at_command (
+        ctx->modem,
+        "%DPDNACT=0",
+        10, /* timeout */
+        FALSE, /* allow_cached */
+        (GAsyncReadyCallback)disconnect_3gpp_check_status,
+        ctx); /* user_data */
+}
+
+/*****************************************************************************/
+
+MMBearer *
+mm_broadband_bearer_altair_lte_new_finish (GAsyncResult *res,
+                                           GError **error)
+{
+    GObject *bearer;
+    GObject *source;
+
+    source = g_async_result_get_source_object (res);
+    bearer = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error);
+    g_object_unref (source);
+
+    if (!bearer)
+        return NULL;
+
+    /* Only export valid bearers */
+    mm_bearer_export (MM_BEARER (bearer));
+
+    return MM_BEARER (bearer);
+}
+
+void
+mm_broadband_bearer_altair_lte_new (MMBroadbandModemAltairLte *modem,
+                                    MMBearerProperties *config,
+                                    GCancellable *cancellable,
+                                    GAsyncReadyCallback callback,
+                                    gpointer user_data)
+{
+    g_async_initable_new_async (
+        MM_TYPE_BROADBAND_BEARER_ALTAIR_LTE,
+        G_PRIORITY_DEFAULT,
+        cancellable,
+        callback,
+        user_data,
+        MM_BEARER_MODEM, modem,
+        MM_BEARER_CONFIG, config,
+        NULL);
+}
+
+static void
+mm_broadband_bearer_altair_lte_init (MMBroadbandBearerAltairLte *self)
+{
+
+}
+
+static void
+mm_broadband_bearer_altair_lte_class_init (MMBroadbandBearerAltairLteClass *klass)
+{
+    MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass);
+
+    broadband_bearer_class->connect_3gpp = connect_3gpp;
+    broadband_bearer_class->connect_3gpp_finish = connect_3gpp_finish;
+    broadband_bearer_class->disconnect_3gpp = disconnect_3gpp;
+    broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish;
+}
diff --git a/plugins/altair/mm-broadband-bearer-altair-lte.h 
b/plugins/altair/mm-broadband-bearer-altair-lte.h
new file mode 100644
index 0000000..891c0f9
--- /dev/null
+++ b/plugins/altair/mm-broadband-bearer-altair-lte.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2013 Altair Semiconductor
+ *
+ * Author: Ori Inbar <ori inbar altair-semi com>
+ */
+
+#ifndef MM_BROADBAND_BEARER_ALTAIR_LTE_H
+#define MM_BROADBAND_BEARER_ALTAIR_LTE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
+#include "mm-broadband-bearer.h"
+#include "mm-broadband-modem-altair-lte.h"
+
+#define MM_TYPE_BROADBAND_BEARER_ALTAIR_LTE            (mm_broadband_bearer_altair_lte_get_type ())
+#define MM_BROADBAND_BEARER_ALTAIR_LTE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
MM_TYPE_BROADBAND_BEARER_ALTAIR_LTE, MMBroadbandBearerAltairLte))
+#define MM_BROADBAND_BEARER_ALTAIR_LTE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
MM_TYPE_BROADBAND_BEARER_ALTAIR_LTE, MMBroadbandBearerAltairLteClass))
+#define MM_IS_BROADBAND_BEARER_ALTAIR_LTE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
MM_TYPE_BROADBAND_BEARER_ALTAIR_LTE))
+#define MM_IS_BROADBAND_BEARER_ALTAIR_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
MM_TYPE_BROADBAND_BEARER_ALTAIR_LTE))
+#define MM_BROADBAND_BEARER_ALTAIR_LTE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
MM_TYPE_BROADBAND_BEARER_ALTAIR_LTE, MMBroadbandBearerAltairLteClass))
+
+typedef struct _MMBroadbandBearerAltairLte MMBroadbandBearerAltairLte;
+typedef struct _MMBroadbandBearerAltairLteClass MMBroadbandBearerAltairLteClass;
+
+struct _MMBroadbandBearerAltairLte {
+    MMBroadbandBearer parent;
+};
+
+struct _MMBroadbandBearerAltairLteClass {
+    MMBroadbandBearerClass parent;
+};
+
+GType mm_broadband_bearer_altair_lte_get_type (void);
+
+/* Default 3GPP bearer creation implementation */
+void mm_broadband_bearer_altair_lte_new (MMBroadbandModemAltairLte *modem,
+                                          MMBearerProperties *properties,
+                                          GCancellable *cancellable,
+                                          GAsyncReadyCallback callback,
+                                          gpointer user_data);
+MMBearer *mm_broadband_bearer_altair_lte_new_finish (GAsyncResult *res,
+                                                      GError **error);
+
+
+#endif /* MM_BROADBAND_BEARER_ALTAIR_LTE_H */
diff --git a/plugins/altair/mm-broadband-modem-altair-lte.c b/plugins/altair/mm-broadband-modem-altair-lte.c
new file mode 100644
index 0000000..4eb1489
--- /dev/null
+++ b/plugins/altair/mm-broadband-modem-altair-lte.c
@@ -0,0 +1,1096 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2013 Altair Semiconductor
+ *
+ * Author: Ori Inbar <ori inbar altair-semi com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "ModemManager.h"
+#include "mm-base-modem-at.h"
+#include "mm-broadband-bearer-altair-lte.h"
+#include "mm-broadband-modem-altair-lte.h"
+#include "mm-errors-types.h"
+#include "mm-iface-modem.h"
+#include "mm-iface-modem-3gpp.h"
+#include "mm-iface-modem-3gpp-ussd.h"
+#include "mm-iface-modem-messaging.h"
+#include "mm-log.h"
+#include "mm-modem-helpers.h"
+#include "mm-serial-parsers.h"
+#include "mm-bearer-list.h"
+
+static void iface_modem_init (MMIfaceModem *iface);
+static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
+static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface);
+static void iface_modem_messaging_init (MMIfaceModemMessaging *iface);
+
+G_DEFINE_TYPE_EXTENDED (MMBroadbandModemAltairLte, mm_broadband_modem_altair_lte, MM_TYPE_BROADBAND_MODEM, 
0,
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP_USSD, iface_modem_3gpp_ussd_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init));
+
+struct _MMBroadbandModemAltairLtePrivate {
+    /* Regex for bearer related notifications */
+    GRegex *statcm_regex;
+};
+
+static MMIfaceModem3gpp *iface_modem_3gpp_parent;
+
+
+/*****************************************************************************/
+/* Modem power down (Modem interface) */
+
+static gboolean
+modem_power_down_finish (MMIfaceModem *self,
+                         GAsyncResult *res,
+                         GError **error)
+{
+    return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
+}
+
+static void
+modem_power_down (MMIfaceModem *self,
+                  GAsyncReadyCallback callback,
+                  gpointer user_data)
+{
+    mm_base_modem_at_command (MM_BASE_MODEM (self),
+                              "+CFUN=4",
+                              6,
+                              FALSE,
+                              callback,
+                              user_data);
+}
+
+/*****************************************************************************/
+/* Create Bearer (Modem interface) */
+
+static MMBearer *
+modem_create_bearer_finish (MMIfaceModem *self,
+                            GAsyncResult *res,
+                            GError **error)
+{
+    MMBearer *bearer;
+
+    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+        return NULL;
+
+    bearer = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+    return g_object_ref (bearer);
+}
+
+static void
+broadband_bearer_new_ready (GObject *source,
+                            GAsyncResult *res,
+                            GSimpleAsyncResult *simple)
+{
+    MMBearer *bearer = NULL;
+    GError *error = NULL;
+
+    bearer = mm_broadband_bearer_altair_lte_new_finish (res, &error);
+    if (!bearer)
+        g_simple_async_result_take_error (simple, error);
+    else
+        g_simple_async_result_set_op_res_gpointer (simple,
+                                                   bearer,
+                                                   (GDestroyNotify)g_object_unref);
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+}
+
+static void
+modem_create_bearer (MMIfaceModem *self,
+                     MMBearerProperties *properties,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    /* Set a new ref to the bearer object as result */
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        modem_create_bearer);
+
+    /* We just create a MMBroadbandBearer */
+    mm_broadband_bearer_altair_lte_new (MM_BROADBAND_MODEM_ALTAIR_LTE (self),
+                                        properties,
+                                        NULL, /* cancellable */
+                                        (GAsyncReadyCallback)broadband_bearer_new_ready,
+                                        result);
+}
+
+/*****************************************************************************/
+/* Load current capabilities (Modem interface) */
+
+static MMModemCapability
+load_current_capabilities_finish (MMIfaceModem *self,
+                                  GAsyncResult *res,
+                                  GError **error)
+{
+    MMModemCapability caps;
+    gchar *caps_str;
+
+    /* This modem is LTE only.*/
+    caps = MM_MODEM_CAPABILITY_LTE;
+    caps_str = mm_modem_capability_build_string_from_mask (caps);
+    mm_dbg ("Loaded current capabilities: %s", caps_str);
+    g_free (caps_str);
+    return caps;
+}
+
+static void
+load_current_capabilities (MMIfaceModem *self,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    mm_dbg ("Loading (Altair LTE) current capabilities...");
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        load_current_capabilities);
+    g_simple_async_result_complete_in_idle (result);
+    g_object_unref (result);
+}
+
+/*****************************************************************************/
+/* supported/current Bands helpers*/
+
+static GArray *
+parse_bands_response(const gchar *response)

Whitespace before parenthesis.

+{
+    guint32 bandval;
+    MMModemBand band;
+    gchar **split;
+    guint i,num_of_bands;
+    GArray *bands;
+
+    split = g_strsplit_set (response, ",", -1);
+    if (!split)
+        return NULL;
+
+    for (num_of_bands = 0; split[num_of_bands]; num_of_bands++);


Better just:
num_of_bands = g_strv_length (split);


+
+    bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), num_of_bands);
+
+    for (i = 0; split[i]; i++) {
+        bandval = (guint32)strtoul (split[i], NULL, 10);
+        band = MM_MODEM_BAND_EUTRAN_I - 1 + bandval;
+        g_array_append_val(bands, band);
+    }
+
+    g_strfreev (split);
+
+    return bands;
+}
+/*****************************************************************************/
+/* Load supported bands (Modem interface) */
+
+static GArray *
+load_supported_bands_finish (MMIfaceModem *self,
+                           GAsyncResult *res,
+                           GError **error)
+{
+    /* Never fails */
+    return (GArray *) g_array_ref (g_simple_async_result_get_op_res_gpointer (
+                                   G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+#define BANDCAP_TAG "%BANDCAP:  "
+
+static void
+load_supported_bands_done (MMIfaceModem *self,
+                         GAsyncResult *res,
+                         GSimpleAsyncResult *operation_result)
+{
+    GArray *bands;
+    const gchar *response;
+    GError *error = NULL;
+
+    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+    if (!response) {
+        mm_dbg ("Couldn't query supported bands: '%s'", error->message);
+        g_simple_async_result_take_error (operation_result, error);
+        g_simple_async_result_complete_in_idle (operation_result);
+        g_object_unref (operation_result);
+        return;
+    }
+
+    /*
+     * Response is "%BANDCAP: <band>,[<band>...]"
+     */
+    response = mm_strip_tag (response, BANDCAP_TAG);
+
+    bands = parse_bands_response(response);

Whitespace before parenthesis.

+    if (!bands) {
+        mm_dbg ("Failed to parse supported bands response");
+        g_simple_async_result_set_error (
+            operation_result,
+            MM_CORE_ERROR,
+            MM_CORE_ERROR_FAILED,
+            "Failed to parse supported bands response");
+        g_simple_async_result_complete_in_idle (operation_result);
+        g_object_unref (operation_result);
+        return;
+    }
+
+    g_simple_async_result_set_op_res_gpointer (operation_result,
+                                               bands,
+                                               (GDestroyNotify)g_array_unref);
+    g_simple_async_result_complete_in_idle (operation_result);
+    g_object_unref (operation_result);
+}
+
+static void
+load_supported_bands (MMIfaceModem *self,
+                      GAsyncReadyCallback callback,
+                      gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        load_supported_bands);

Good! Querying supported bands is much better than hardcoding them.

+
+    mm_base_modem_at_command (
+        MM_BASE_MODEM (self),
+        "%BANDCAP=",
+        3,
+        FALSE,
+        (GAsyncReadyCallback)load_supported_bands_done,
+        result);
+}
+/*****************************************************************************/
+/* Load current bands (Modem interface) */
+
+static GArray *
+load_current_bands_finish (MMIfaceModem *self,
+                           GAsyncResult *res,
+                           GError **error)
+{
+    /* Never fails */
+    return (GArray *) g_array_ref (g_simple_async_result_get_op_res_gpointer (
+                                   G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+#define CFGBANDS_TAG "Bands:  "
+
+static void
+load_current_bands_done (MMIfaceModem *self,
+                         GAsyncResult *res,
+                         GSimpleAsyncResult *operation_result)
+{
+    GArray *bands;
+    const gchar *response;
+    GError *error = NULL;
+
+    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+    if (!response) {
+        mm_dbg ("Couldn't query current bands: '%s'", error->message);
+        g_simple_async_result_take_error (operation_result, error);
+        g_simple_async_result_complete_in_idle (operation_result);
+        g_object_unref (operation_result);
+        return;
+    }
+
+    /*
+     * Response is "Bands: <band>,[<band>...]"
+     */
+    response = mm_strip_tag (response, CFGBANDS_TAG);
+
+    bands = parse_bands_response(response);
+    if (!bands) {
+        mm_dbg ("Failed to parse current bands response");
+        g_simple_async_result_set_error (
+            operation_result,
+            MM_CORE_ERROR,
+            MM_CORE_ERROR_FAILED,
+            "Failed to parse current bands response");
+        g_simple_async_result_complete_in_idle (operation_result);
+        g_object_unref (operation_result);
+        return;
+    }
+
+    g_simple_async_result_set_op_res_gpointer (operation_result,
+                                               bands,
+                                               (GDestroyNotify)g_array_unref);
+    g_simple_async_result_complete_in_idle (operation_result);
+    g_object_unref (operation_result);
+}
+
+static void
+load_current_bands (MMIfaceModem *self,
+                      GAsyncReadyCallback callback,
+                      gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        load_current_bands);
+
+    mm_base_modem_at_command (
+        MM_BASE_MODEM (self),
+        "%GETCFG=\"BAND\"",
+        3,
+        FALSE,
+        (GAsyncReadyCallback)load_current_bands_done,
+        result);
+}
+
+/*****************************************************************************/
+/* Reset (Modem interface) */
+
+static gboolean
+reset_finish (MMIfaceModem *self,
+              GAsyncResult *res,
+              GError **error)
+{
+    return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
+}
+
+static void
+reset (MMIfaceModem *self,
+       GAsyncReadyCallback callback,
+       gpointer user_data)
+{
+    mm_base_modem_at_command (MM_BASE_MODEM (self),
+                              "ATZ",
+                              3,
+                              FALSE,
+                              callback,
+                              user_data);
+}
+
+/*****************************************************************************/
+/* Register in network (3GPP interface) */
+
+static void
+modem_3gpp_register_in_network (MMIfaceModem3gpp *self,
+                                const gchar *operator_id,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
+{
+    if (operator_id) {
+        /* Currently only VZW is supported */
+        g_simple_async_report_error_in_idle (G_OBJECT (self),
+                                             callback,
+                                             user_data,
+                                             MM_CORE_ERROR,
+                                             MM_CORE_ERROR_UNSUPPORTED,
+                                             "Setting a specific operator Id is not supported");
+        return;
+    }
+
+    mm_base_modem_at_command_full (MM_BASE_MODEM (self),
+                                   mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL),
+                                   "%CMATT=1",
+                                   3,
+                                   FALSE,
+                                   FALSE, /* raw */
+                                   cancellable,
+                                   callback,
+                                   user_data);
+}
+
+static gboolean
+modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self,
+                                       GAsyncResult *res,
+                                       GError **error)
+{
+    return !!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, error);
+}
+
+/*****************************************************************************/
+/* Setup/Cleanup unsolicited events (3GPP interface) */
+
+typedef enum {
+    MM_STATCM_ALTAIR_LTE_DEREGISTERED = 0,
+    MM_STATCM_ALTAIR_LTE_REGISTERED = 1,
+    MM_STATCM_ALTAIR_PDN_CONNECTED = 3,
+    MM_STATCM_ALTAIR_PDN_DISCONNECTED = 4,
+} MMStatcmAltair;
+
+static void
+bearer_list_report_diconnect_status_foreach (MMBearer *bearer,
+                                             gpointer *user_data)
+{
+    mm_bearer_report_disconnection (bearer);
+}
+
+static void
+altair_statcm_changed (MMAtSerialPort *port,
+                       GMatchInfo *match_info,
+                       MMBroadbandModemAltairLte *self)
+{
+    gint pdn_event = 0;
+    MMBearerList *list = NULL;
+
+    mm_get_int_from_match_info (match_info, 1, &pdn_event);
+
+    mm_dbg ("altair_statcm_changed %d",pdn_event);

Whitespace after comma.

+
+    /* Currently we only care about bearer disconnection */
+
+    if (pdn_event == MM_STATCM_ALTAIR_PDN_DISCONNECTED) {
+        /* If empty bearer list, nothing else to do */
+        g_object_get (self,
+                      MM_IFACE_MODEM_BEARER_LIST, &list,
+                      NULL);
+        if (!list)
+            return;
+
+        mm_bearer_list_foreach (list,
+                                (MMBearerListForeachFunc)bearer_list_report_diconnect_status_foreach,
+                                NULL);
+
+        g_object_unref (list);
+    }
+
+}
+
+static void
+set_3gpp_unsolicited_events_handlers (MMBroadbandModemAltairLte *self,
+                                      gboolean enable)
+{
+    MMAtSerialPort *ports[2];
+    guint i;
+
+    ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
+    ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
+
+    /* Enable/disable unsolicited events in given port */
+    for (i = 0; i < 2; i++) {
+        if (!ports[i])
+            continue;
+
+        /* bearer mode related */
+        mm_at_serial_port_add_unsolicited_msg_handler (
+            ports[i],
+            self->priv->statcm_regex,
+            enable ? (MMAtSerialUnsolicitedMsgFn)altair_statcm_changed : NULL,
+            enable ? self : NULL,
+            NULL);
+    }
+}
+
+static gboolean
+modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self,
+                                                    GAsyncResult *res,
+                                                    GError **error)
+{
+    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+parent_3gpp_setup_unsolicited_events_ready (MMIfaceModem3gpp *self,
+                                            GAsyncResult *res,
+                                            GSimpleAsyncResult *simple)
+{
+    GError *error = NULL;
+
+    if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error))
+        g_simple_async_result_take_error (simple, error);
+    else {
+        /* Our own setup now */
+        set_3gpp_unsolicited_events_handlers (MM_BROADBAND_MODEM_ALTAIR_LTE (self), TRUE);
+        g_simple_async_result_set_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res), TRUE);
+    }
+
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+}
+
+static void
+modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        modem_3gpp_setup_unsolicited_events);
+
+    /* Chain up parent's setup */
+    iface_modem_3gpp_parent->setup_unsolicited_events (
+        self,
+        (GAsyncReadyCallback)parent_3gpp_setup_unsolicited_events_ready,
+        result);
+}
+
+static void
+parent_3gpp_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self,
+                                              GAsyncResult *res,
+                                              GSimpleAsyncResult *simple)
+{
+    GError *error = NULL;
+
+    if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error))
+        g_simple_async_result_take_error (simple, error);
+    else
+        g_simple_async_result_set_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res), TRUE);
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+}
+
+static void
+modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self,
+                                       GAsyncReadyCallback callback,
+                                       gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        modem_3gpp_cleanup_unsolicited_events);
+
+    /* Our own cleanup first */
+    set_3gpp_unsolicited_events_handlers (MM_BROADBAND_MODEM_ALTAIR_LTE (self), FALSE);
+
+    /* And now chain up parent's cleanup */
+    iface_modem_3gpp_parent->cleanup_unsolicited_events (
+        self,
+        (GAsyncReadyCallback)parent_3gpp_cleanup_unsolicited_events_ready,
+        result);
+}

Whiteline here between sections.

+/*****************************************************************************/
+/* Enabling unsolicited events (3GPP interface) */
+
+static gboolean
+modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self,
+                                             GAsyncResult *res,
+                                             GError **error)
+{
+    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+own_enable_unsolicited_events_ready (MMBaseModem *self,
+                                     GAsyncResult *res,
+                                     GSimpleAsyncResult *simple)
+{
+    GError *error = NULL;
+
+    mm_base_modem_at_sequence_full_finish (self, res, NULL, &error);
+    if (error)
+        g_simple_async_result_take_error (simple, error);
+    else
+        g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+}
+
+static void
+parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self,
+                                        GAsyncResult *res,
+                                        GSimpleAsyncResult *simple)
+{
+    GError *error = NULL;
+
+    if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) {
+        g_simple_async_result_take_error (simple, error);
+        g_simple_async_result_complete (simple);
+        g_object_unref (simple);
+    }
+
+    /* Our own enable now */
+    mm_base_modem_at_command_full (
+        MM_BASE_MODEM (self),
+        mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
+        "%STATCM=1",
+        6,
+        FALSE, /* allow_cached */
+        FALSE, /* raw */
+        NULL, /* cancellable */
+        (GAsyncReadyCallback)own_enable_unsolicited_events_ready,
+        simple);
+}
+
+static void
+modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self,
+                                      GAsyncReadyCallback callback,
+                                      gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        modem_3gpp_enable_unsolicited_events);
+
+    /* Chain up parent's enable */
+    iface_modem_3gpp_parent->enable_unsolicited_events (
+        self,
+        (GAsyncReadyCallback)parent_enable_unsolicited_events_ready,
+        result);
+}
+
+/*****************************************************************************/
+/* Disabling unsolicited events (3GPP interface) */
+
+static gboolean
+modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self,
+                                              GAsyncResult *res,
+                                              GError **error)
+{
+    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self,
+                                         GAsyncResult *res,
+                                         GSimpleAsyncResult *simple)
+{
+    GError *error = NULL;
+
+    if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error))
+        g_simple_async_result_take_error (simple, error);
+    else
+        g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+}
+
+static void
+own_disable_unsolicited_events_ready (MMBaseModem *self,
+                                      GAsyncResult *res,
+                                      GSimpleAsyncResult *simple)
+{
+    GError *error = NULL;
+
+    mm_base_modem_at_command_full_finish (self, res, &error);
+    if (error) {
+        g_simple_async_result_take_error (simple, error);
+        g_simple_async_result_complete (simple);
+        g_object_unref (simple);
+        return;
+    }
+
+    /* Next, chain up parent's disable */
+    iface_modem_3gpp_parent->disable_unsolicited_events (
+        MM_IFACE_MODEM_3GPP (self),
+        (GAsyncReadyCallback)parent_disable_unsolicited_events_ready,
+        simple);
+}
+
+static void
+modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self,
+                                       GAsyncReadyCallback callback,
+                                       gpointer user_data)
+{
+    GSimpleAsyncResult *result;
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                                        callback,
+                                        user_data,
+                                        modem_3gpp_disable_unsolicited_events);
+
+    /* Our own disable first */
+    mm_base_modem_at_command_full (
+        MM_BASE_MODEM (self),
+        mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
+        "%STATCM=0",
+        5,
+        FALSE, /* allow_cached */
+        FALSE, /* raw */
+        NULL, /* cancellable */
+        (GAsyncReadyCallback)own_disable_unsolicited_events_ready,
+        result);
+}
+
+/*****************************************************************************/
+/* Facility locks status loading (3GPP interface) */
+
+typedef struct {
+    MMBroadbandModem *self;
+    GSimpleAsyncResult *result;
+    guint current;
+    MMModem3gppFacility facilities;
+    MMModem3gppFacility locks;
+} LoadEnabledFacilityLocksContext;
+
+static void get_next_facility_lock_status (LoadEnabledFacilityLocksContext *ctx);
+
+static void
+load_enabled_facility_locks_context_complete_and_free (LoadEnabledFacilityLocksContext *ctx)
+{
+    g_simple_async_result_complete (ctx->result);
+    g_object_unref (ctx->result);
+    g_object_unref (ctx->self);
+    g_free (ctx);
+}
+
+static MMModem3gppFacility
+modem_3gpp_load_enabled_facility_locks_finish (MMIfaceModem3gpp *self,
+                                               GAsyncResult *res,
+                                               GError **error)
+{
+    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+        return MM_MODEM_3GPP_FACILITY_NONE;
+
+    return ((MMModem3gppFacility) GPOINTER_TO_UINT (
+                g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))));
+}
+
+static void
+clck_single_query_ready (MMBaseModem *self,
+                         GAsyncResult *res,
+                         LoadEnabledFacilityLocksContext *ctx)
+{
+    const gchar *response;
+    gboolean enabled = FALSE;
+
+    response = mm_base_modem_at_command_finish (self, res, NULL);
+    if (response &&
+        mm_3gpp_parse_clck_write_response (response, &enabled) &&
+        enabled) {
+        ctx->locks |= (1 << ctx->current);
+    } else {
+        /* On errors, we'll just assume disabled */
+        ctx->locks &= ~(1 << ctx->current);
+    }
+
+    /* And go on with the next one */
+    ctx->current++;
+    get_next_facility_lock_status (ctx);
+}
+
+static void
+get_next_facility_lock_status (LoadEnabledFacilityLocksContext *ctx)
+{
+    guint i;
+
+    for (i = ctx->current; i < sizeof (MMModem3gppFacility) * 8; i++) {
+        guint32 facility = 1 << i;
+
+        /* Found the next one to query! */
+        if (ctx->facilities & facility) {
+            gchar *cmd;
+
+            /* Keep the current one */
+            ctx->current = i;
+
+            /* Query current */
+            cmd = g_strdup_printf ("+CLCK=\"%s\",2",
+                                   mm_3gpp_facility_to_acronym (facility));
+            mm_base_modem_at_command (MM_BASE_MODEM (ctx->self),
+                                      cmd,
+                                      3,
+                                      FALSE,
+                                      (GAsyncReadyCallback)clck_single_query_ready,
+                                      ctx);
+            g_free (cmd);
+            return;
+        }
+    }
+
+    /* No more facilities to query, all done */
+    g_simple_async_result_set_op_res_gpointer (ctx->result,
+                                               GUINT_TO_POINTER (ctx->locks),
+                                               NULL);
+    load_enabled_facility_locks_context_complete_and_free (ctx);
+}
+
+static void
+modem_3gpp_load_enabled_facility_locks (MMIfaceModem3gpp *self,
+                                        GAsyncReadyCallback callback,
+                                        gpointer user_data)
+{
+    LoadEnabledFacilityLocksContext *ctx;
+
+    ctx = g_new (LoadEnabledFacilityLocksContext, 1);
+    ctx->self = g_object_ref (self);
+    ctx->result = g_simple_async_result_new (G_OBJECT (self),
+                                             callback,
+                                             user_data,
+                                             modem_3gpp_load_enabled_facility_locks);
+    ctx->facilities = MM_MODEM_3GPP_FACILITY_SIM;

What's the problem with the generic method doing "AT+CLCK=?"? Why not
ask for which are the supported facilities and then query each of them
(which is what the generic method is doing)?

If you only really need to report about the SIM lock, you better
simplify the logic of this method, you don't need to have a
ctx->facilities and then query each enabled facility in the flags mask,
as there will only be one. So just a single AT+CLCK="xx",2 will be needed.

If the problem is that you don't want certain facilities to be checked,
you can set the new "MM_IFACE_MODEM_3GPP_IGNORED_FACILITY_LOCKS" to
contain a mask of flags with the facilities to ignore. See commits
d9cf4fe91 and e33fc37e.

+    ctx->locks = MM_MODEM_3GPP_FACILITY_NONE;
+    ctx->current = 0;
+
+    /* Go on... */
+    get_next_facility_lock_status (ctx);
+}
+
+/*****************************************************************************/
+/* Operator Code loading (3GPP interface) */
+
+static gchar *
+modem_3gpp_load_operator_code_finish (MMIfaceModem3gpp *self,
+                                      GAsyncResult *res,
+                                      GError **error)
+{
+    const gchar *result;
+    gchar *operator_code;
+
+    result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
+    if (!result)
+        return NULL;
+
+    operator_code = mm_3gpp_parse_operator (result, MM_MODEM_CHARSET_UNKNOWN);
+    if (operator_code)
+        mm_dbg ("loaded Operator Code: %s", operator_code);
+
+    return operator_code;
+}
+
+static void
+modem_3gpp_load_operator_code (MMIfaceModem3gpp *self,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+    mm_dbg ("loading Operator Code...");
+
+    mm_base_modem_at_command (MM_BASE_MODEM (self),
+                              "+COPS=3,2",
+                              6,
+                              FALSE,
+                              NULL,
+                              NULL);
+
+    mm_base_modem_at_command (MM_BASE_MODEM (self),
+                              "+COPS?",
+                              6,
+                              FALSE,
+                              callback,
+                              user_data);
+}
+
+/*****************************************************************************/
+/* Operator Name loading (3GPP interface) */
+
+static gchar *
+modem_3gpp_load_operator_name_finish (MMIfaceModem3gpp *self,
+                                      GAsyncResult *res,
+                                      GError **error)
+{
+    const gchar *result;
+    gchar *operator_name;
+
+    result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
+    if (!result)
+        return NULL;
+
+    operator_name = mm_3gpp_parse_operator (result, MM_MODEM_CHARSET_UNKNOWN);
+    if (operator_name)
+        mm_dbg ("loaded Operator Name: %s", operator_name);
+
+    return operator_name;
+}
+
+static void
+modem_3gpp_load_operator_name (MMIfaceModem3gpp *self,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+    mm_dbg ("Loading Operator Name...");
+
+    mm_base_modem_at_command (MM_BASE_MODEM (self),
+                              "+COPS=3,0",
+                              6,
+                              FALSE,
+                              NULL,
+                              NULL);
+
+    mm_base_modem_at_command (MM_BASE_MODEM (self),
+                              "+COPS?",
+                              6,
+                              FALSE,
+                              callback,
+                              user_data);
+}
+
+/*****************************************************************************/
+/* Generic ports open/close context */
+
+static const gchar *primary_init_sequence[] = {
+    /* Extended numeric codes */
+    "+CMEE=1",
+    NULL
+};
+
+
+static void
+setup_ports (MMBroadbandModem *self)
+{
+    MMAtSerialPort *primary;
+    /* Call parent's setup ports first always */
+    MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_altair_lte_parent_class)->setup_ports (self);
+
+    primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
+
+    g_object_set (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
+                  MM_AT_SERIAL_PORT_SEND_LF, TRUE,
+                  NULL);
+
+    g_object_set (primary,
+                  MM_AT_SERIAL_PORT_INIT_SEQUENCE, primary_init_sequence,
+                  NULL);
+
+}
+
+/*****************************************************************************/
+
+MMBroadbandModemAltairLte *
+mm_broadband_modem_altair_lte_new (const gchar *device,
+                                    const gchar **drivers,
+                                    const gchar *plugin,
+                                    guint16 vendor_id,
+                                    guint16 product_id)
+{
+    return g_object_new (MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE,
+                         MM_BASE_MODEM_DEVICE, device,
+                         MM_BASE_MODEM_DRIVERS, drivers,
+                         MM_BASE_MODEM_PLUGIN, plugin,
+                         MM_BASE_MODEM_VENDOR_ID, vendor_id,
+                         MM_BASE_MODEM_PRODUCT_ID, product_id,
+                         /* Since this is an LTE-only modem - don't bother query
+                          * anything else */
+                         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);
+}
+
+static void
+mm_broadband_modem_altair_lte_init (MMBroadbandModemAltairLte *self)
+{
+
+    /* Initialize private data */
+    self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
+                                              MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE,
+                                              MMBroadbandModemAltairLtePrivate);
+
+    self->priv->statcm_regex = g_regex_new ("\\r\\n\\%STATCM:\\s*(\\d*),?(\\d*)\\r+\\n",
+                                            G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+}
+
+static void
+iface_modem_init (MMIfaceModem *iface)
+{
+    /* the modem is powered up at startup - no need to waste
+     * on power query and power up commands */
+    iface->load_power_state = NULL;
+    iface->load_power_state_finish = NULL;
+    iface->modem_power_up = NULL;
+    iface->modem_power_up_finish = NULL;
+

This is not right. If you do provide power_down, you need to provide
power_up. Users can request low-power mode themselves via DBus, so we
also need to allow them to power-up the modem back. If the module is
*always* powered up when enabled, you can skip load_power_state, but
modem_power_up really needs to be implemented.


+    iface->modem_power_down = modem_power_down;
+    iface->modem_power_down_finish = modem_power_down_finish;
+    iface->create_bearer = modem_create_bearer;
+    iface->create_bearer_finish = modem_create_bearer_finish;
+    iface->load_current_capabilities = load_current_capabilities;
+    iface->load_current_capabilities_finish = load_current_capabilities_finish;
+    iface->load_supported_bands = load_supported_bands;
+    iface->load_supported_bands_finish = load_supported_bands_finish;
+    iface->load_current_bands = load_current_bands;
+    iface->load_current_bands_finish = load_current_bands_finish;
+
+    iface->load_access_technologies = NULL;
+    iface->load_access_technologies_finish = NULL;
+
+    iface->reset = reset;
+    iface->reset_finish = reset_finish;
+
+    iface->load_supported_charsets = NULL;
+    iface->load_supported_charsets_finish = NULL;
+    iface->setup_charset = NULL;
+    iface->setup_charset_finish = NULL;
+    iface->setup_flow_control = NULL;
+    iface->setup_flow_control_finish = NULL;
+
+}
+
+static void
+iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface)
+{
+    /* we don't have USSD support */
+    iface->check_support = NULL;
+    iface->check_support_finish = NULL;
+}
+
+static void
+iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
+{
+
+    iface_modem_3gpp_parent = g_type_interface_peek_parent (iface);
+
+    iface->load_enabled_facility_locks = modem_3gpp_load_enabled_facility_locks;
+    iface->load_enabled_facility_locks_finish = modem_3gpp_load_enabled_facility_locks_finish;
+
+
+    iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events;
+    iface->setup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish;
+    iface->cleanup_unsolicited_events = modem_3gpp_cleanup_unsolicited_events;
+    iface->cleanup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish;
+    iface->enable_unsolicited_events = modem_3gpp_enable_unsolicited_events;
+    iface->enable_unsolicited_events_finish = modem_3gpp_enable_unsolicited_events_finish;
+    iface->disable_unsolicited_events = modem_3gpp_disable_unsolicited_events;
+    iface->disable_unsolicited_events_finish = modem_3gpp_disable_unsolicited_events_finish;
+
+    iface->register_in_network = modem_3gpp_register_in_network;
+    iface->register_in_network_finish = modem_3gpp_register_in_network_finish;
+
+    /* Scanning is not currently supported */
+    iface->scan_networks = NULL;
+    iface->scan_networks_finish = NULL;
+
+    /* Additional actions */
+    iface->load_operator_code = modem_3gpp_load_operator_code;
+    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;
+
+}
+
+static void
+iface_modem_messaging_init (MMIfaceModemMessaging *iface)
+{
+    /* Currently no messaging is implemented - so skip checking*/
+    iface->check_support = NULL;
+    iface->check_support_finish = NULL;
+}
+
+static void
+mm_broadband_modem_altair_lte_class_init (MMBroadbandModemAltairLteClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass);
+
+    g_type_class_add_private (object_class, sizeof (MMBroadbandModemAltairLtePrivate));
+
+    broadband_modem_class->setup_ports = setup_ports;
+
+    /* no need to send any special commands to initialize */
+    broadband_modem_class->initialization_started = NULL;
+    broadband_modem_class->initialization_started_finish = NULL;
+    broadband_modem_class->initialization_stopped = NULL;

Wait, but you *do* need the parent implementation of these methods, so
don't set them to NULL.


+}
diff --git a/plugins/altair/mm-broadband-modem-altair-lte.h b/plugins/altair/mm-broadband-modem-altair-lte.h
new file mode 100644
index 0000000..50c9f3e
--- /dev/null
+++ b/plugins/altair/mm-broadband-modem-altair-lte.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2013 Altair Semiconductor
+ *
+ * Author: Ori Inbar <ori inbar altair-semi com>
+ */
+
+#ifndef MM_BROADBAND_MODEM_ALTAIR_LTE_H
+#define MM_BROADBAND_MODEM_ALTAIR_LTE_H
+
+#include "mm-broadband-modem.h"
+
+#define MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE            (mm_broadband_modem_altair_lte_get_type ())
+#define MM_BROADBAND_MODEM_ALTAIR_LTE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE, MMBroadbandModemAltairLte))
+#define MM_BROADBAND_MODEM_ALTAIR_LTE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE, MMBroadbandModemAltairLteClass))
+#define MM_IS_BROADBAND_MODEM_ALTAIR_LTE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE))
+#define MM_IS_BROADBAND_MODEM_ALTAIR_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE))
+#define MM_BROADBAND_MODEM_ALTAIR_LTE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE, MMBroadbandModemAltairLteClass))
+
+typedef struct _MMBroadbandModemAltairLte MMBroadbandModemAltairLte;
+typedef struct _MMBroadbandModemAltairLteClass MMBroadbandModemAltairLteClass;
+typedef struct _MMBroadbandModemAltairLtePrivate MMBroadbandModemAltairLtePrivate;
+
+struct _MMBroadbandModemAltairLte {
+    MMBroadbandModem parent;
+    MMBroadbandModemAltairLtePrivate *priv;
+};
+
+struct _MMBroadbandModemAltairLteClass{
+    MMBroadbandModemClass parent;
+};
+
+GType mm_broadband_modem_altair_lte_get_type (void);
+
+MMBroadbandModemAltairLte *mm_broadband_modem_altair_lte_new (const gchar *device,
+                                                              const gchar **drivers,
+                                                              const gchar *plugin,
+                                                              guint16 vendor_id,
+                                                              guint16 product_id);
+
+#endif /* MM_BROADBAND_MODEM_ALTAIR_LTE_H */
diff --git a/plugins/altair/mm-plugin-altair-lte.c b/plugins/altair/mm-plugin-altair-lte.c
new file mode 100644
index 0000000..6f27825
--- /dev/null
+++ b/plugins/altair/mm-plugin-altair-lte.c
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2013 Altair Semiconductor
+ *
+ * Author: Ori Inbar <ori inbar altair-semi com>
+ */
+
+#include <string.h>
+#include <gmodule.h>
+
+#include "mm-plugin-altair-lte.h"
+#include "mm-private-boxed-types.h"
+#include "mm-broadband-modem-altair-lte.h"
+#include "mm-log.h"
+
+G_DEFINE_TYPE (MMPluginAltairLte, mm_plugin_altair_lte, MM_TYPE_PLUGIN)
+
+int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
+int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
+
+static MMBaseModem *
+create_modem (MMPlugin *self,
+              const gchar *sysfs_path,
+              const gchar **drivers,
+              guint16 vendor,
+              guint16 product,
+              GList *probes,
+              GError **error)
+{
+    return MM_BASE_MODEM (mm_broadband_modem_altair_lte_new (sysfs_path,
+                                                              drivers,
+                                                              mm_plugin_get_name (self),
+                                                              vendor,
+                                                              product));
+}
+
+/*****************************************************************************/
+G_MODULE_EXPORT MMPlugin *
+mm_plugin_create (void)
+{
+    static const gchar *subsystems[] = { "tty", "net", NULL };
+    static const mm_uint16_pair products[] = {
+        { 0x216f, 0x0047 }, /* Altair NPe */
+        { 0, 0 }
+    };
+
+    return MM_PLUGIN (
+        g_object_new (MM_TYPE_PLUGIN_ALTAIR_LTE,
+                      MM_PLUGIN_NAME,                "Altair LTE",
+                      MM_PLUGIN_ALLOWED_SUBSYSTEMS,  subsystems,
+                      MM_PLUGIN_ALLOWED_PRODUCT_IDS, products,
+                      MM_PLUGIN_ALLOWED_SINGLE_AT,   TRUE,
+                      MM_PLUGIN_SEND_LF,             TRUE,
+                      NULL));
+}
+
+static void
+mm_plugin_altair_lte_init (MMPluginAltairLte *self)
+{
+}
+
+static void
+mm_plugin_altair_lte_class_init (MMPluginAltairLteClass *klass)
+{
+    MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass);
+
+    plugin_class->create_modem = create_modem;
+}
diff --git a/plugins/altair/mm-plugin-altair-lte.h b/plugins/altair/mm-plugin-altair-lte.h
new file mode 100644
index 0000000..385a5cc
--- /dev/null
+++ b/plugins/altair/mm-plugin-altair-lte.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2013 Altair Semiconductor
+ *
+ * Author: Ori Inbar <ori inbar altair-semi com>
+ */
+
+#ifndef MM_PLUGIN_ALTAIR_LTE_H
+#define MM_PLUGIN_ALTAIR_LTE_H
+
+#include "mm-plugin.h"
+
+#define MM_TYPE_PLUGIN_ALTAIR_LTE            (mm_plugin_altair_lte_get_type ())
+#define MM_PLUGIN_ALTAIR_LTE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
MM_TYPE_PLUGIN_ALTAIR_LTE, MMPluginAltairLte))
+#define MM_PLUGIN_ALTAIR_LTE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
MM_TYPE_PLUGIN_ALTAIR_LTE, MMPluginAltairLteClass))
+#define MM_IS_PLUGIN_ALTAIR_LTE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
MM_TYPE_PLUGIN_ALTAIR_LTE))
+#define MM_IS_PLUGIN_ALTAIR_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
MM_TYPE_PLUGIN_ALTAIR_LTE))
+#define MM_PLUGIN_ALTAIR_LTE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
MM_TYPE_PLUGIN_ALTAIR_LTE, MMPluginAltairLteClass))
+
+typedef struct {
+    MMPlugin parent;
+} MMPluginAltairLte;
+
+typedef struct {
+    MMPluginClass parent;
+} MMPluginAltairLteClass;
+
+GType mm_plugin_altair_lte_get_type (void);
+
+G_MODULE_EXPORT MMPlugin *mm_plugin_create (void);
+
+#endif /* MM_PLUGIN_ALTAIR_LTE_H */
diff --git a/src/77-mm-usb-device-blacklist.rules b/src/77-mm-usb-device-blacklist.rules
old mode 100644
new mode 100755
index 2973076..30355b1
--- a/src/77-mm-usb-device-blacklist.rules
+++ b/src/77-mm-usb-device-blacklist.rules
@@ -84,4 +84,7 @@ ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"
 ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9207", ENV{ID_MM_DEVICE_IGNORE}="1"
 ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9208", ENV{ID_MM_DEVICE_IGNORE}="1"
 
+# Altair U-Boot device
+ATTRS{idVendor}=="0216", ATTRS{idProduct}=="0051" ENV{ID_MM_DEVICE_IGNORE}="1"
+
 LABEL="mm_usb_device_blacklist_end"



-- 
Aleksander


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]