From 84e68cd4cdad03766513cc689519be6dad2f75f6 Mon Sep 17 00:00:00 2001 From: ori inbar Date: Wed, 3 Apr 2013 12:47:30 -0500 Subject: altair-lte: initial altair lte plugin --- plugins/Makefile.am | 12 + plugins/altair/mm-broadband-bearer-altair-lte.c | 377 +++++++++ plugins/altair/mm-broadband-bearer-altair-lte.h | 61 ++ plugins/altair/mm-broadband-modem-altair-lte.c | 973 ++++++++++++++++++++++++ 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, 1609 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 diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 2d52359e..b3ff3065 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 \ @@ -317,6 +318,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 00000000..85432b9b --- /dev/null +++ b/plugins/altair/mm-broadband-bearer-altair-lte.c @@ -0,0 +1,377 @@ +/* -*- 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 + */ + +#include + +#include +#include +#include +#include +#include + +#include +#define _LIBMM_INSIDE_MM +#include + +#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"); + + 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); +} + +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); +} + +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 00000000..4b8f1036 --- /dev/null +++ b/plugins/altair/mm-broadband-bearer-altair-lte.h @@ -0,0 +1,61 @@ +/* -*- 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 + */ + +#ifndef MM_BROADBAND_BEARER_ALTAIR_LTE_H +#define MM_BROADBAND_BEARER_ALTAIR_LTE_H + +#include +#include + +#define _LIBMM_INSIDE_MM +#include + +#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 00000000..bdcc0b18 --- /dev/null +++ b/plugins/altair/mm-broadband-modem-altair-lte.c @@ -0,0 +1,973 @@ +/* -*- 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 + */ + +#include + +#include +#include +#include +#include +#include + +#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) +{ + guint32 bandval; + MMModemBand band; + gchar **split; + guint i, num_of_bands; + GArray *bands; + + split = g_strsplit_set (response, ",", -1); + if (!split) + return NULL; + + 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: ,[...]" + */ + response = mm_strip_tag (response, BANDCAP_TAG); + + bands = parse_bands_response (response); + 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); + + 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: ,[...]" + */ + 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); + + /* 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); +} + +/*****************************************************************************/ +/* 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); + return; + } + + /* 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); +} + +/*****************************************************************************/ +/* 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, + 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_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->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; +} 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 00000000..50c9f3e6 --- /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 + */ + +#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 00000000..1e1ecef0 --- /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 + */ + +#include +#include + +#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 00000000..385a5cc2 --- /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 + */ + +#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 29730760..30355b1b --- 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" -- cgit v1.2.3